浏览代码

Convert to GoogleTest

Sam Jaffe 7 年之前
父节点
当前提交
df992c6728

+ 0 - 160
vector.t.h

@@ -1,160 +0,0 @@
-#include <cxxtest/TestSuite.h>
-
-#include "vector.hpp"
-
-class vector_TestSuite : public CxxTest::TestSuite {
-public:
-  using vec2i = math::vector::vector<int, 2>;
-  using vec3  = math::vector::vector<double, 3>;
-  using vec3i = math::vector::vector<int, 3>;
-  using vec4i = math::vector::vector<int, 4>;
-  
-  void test_vector_badsize_throws() const {
-    TS_ASSERT_THROWS((vec2i{1}), std::logic_error);
-    TS_ASSERT_THROWS((vec2i{1,1,1}), std::logic_error);
-  }
-  
-  void test_vector_equals() const {
-    TS_ASSERT_EQUALS(iota3i(), (vec3i{1, 2, 3}));
-  }
-  
-  void test_vector_notequals() const {
-    TS_ASSERT_DIFFERS(iota3i(), (vec3i{0, 2, 3}));
-  }
-  
-  void test_vector_elems() const {
-    math::vector::vector<int, 3> viota = iota3i();
-    TS_ASSERT_EQUALS(viota[0], 1);
-    TS_ASSERT_EQUALS(viota[1], 2);
-    TS_ASSERT_EQUALS(viota[2], 3);
-  }
-  
-  void test_vector_oob() const {
-    TS_ASSERT_THROWS((iota<int, 3>()).at(3), std::out_of_range);
-  }
-  
-  void test_default_zero() const {
-    TS_ASSERT_EQUALS(vec3i(), (vec3i{0,0,0}));
-  }
-  
-  void test_extends_with_zero() const {
-    TS_ASSERT_EQUALS(vec4i(iota3i()), (vec4i{1,2,3,0}));
-  }
-  
-  void test_vec2_cross() const {
-    TS_ASSERT_EQUALS((vec2i{1,1}.cross(vec2i{-1,1})), (vec3i{0,0,2}));
-  }
-  
-  void test_vec3_cross() const {
-    TS_ASSERT_EQUALS((vec3i{1,1,2}.cross(vec3i{-1,1,1})), (vec3i{-1,-3,2}));
-  }
-  
-  void test_vector_addition_vector() const {
-    TS_ASSERT_EQUALS((vec2i{1,0} + vec2i{0,1}), (vec2i{1,1}))
-  }
-  
-  void test_vector_subtraction_vector() const {
-    TS_ASSERT_EQUALS((vec2i{1,0} - vec2i{0,1}), (vec2i{1,-1}))
-  }
-  
-  void test_vector_multiplication_vector() const {
-    TS_ASSERT_EQUALS((vec2i{1,0}*(vec2i{2,1})), (vec2i{2,0}))
-  }
-  
-  void test_vector_divides_vector() const {
-    TS_ASSERT_EQUALS((vec2i{6,4}/(vec2i{2,1})), (vec2i{3,4}))
-  }
-  
-  void test_divide_by_zero_fails() const {
-    TS_ASSERT_THROWS(vec3{} / 0, std::domain_error);
-    TS_ASSERT_THROWS((vec3{1.0, 1.0, 1.0}/(vec3{1.0, 0.5, 0.0})), std::domain_error);
-  }
-  
-  //  void test_vector_addition_value() const {
-  //    TS_ASSERT_EQUALS((vec2i{1,0} + 1), (vec2i{2,1}))
-  //  }
-  //
-  //  void test_vector_subtraction_value() const {
-  //    TS_ASSERT_EQUALS((vec2i{1,0} - 1), (vec2i{0,-1}))
-  //  }
-  
-  void test_vector_multiplication_value() const {
-    TS_ASSERT_EQUALS((vec2i{1,0} * 3), (vec2i{3,0}))
-  }
-  
-  void test_vector_divides_value() const {
-    TS_ASSERT_EQUALS((vec2i{6,4} / 2), (vec2i{3,2}))
-  }
-  
-  //  void test_value_addition_vector() const {
-  //    TS_ASSERT_EQUALS(1+iota2i(), (vec2i{2,3}));
-  //  }
-  //
-  //  void test_value_subtraction_vector() const {
-  //    TS_ASSERT_EQUALS(4-iota2i(), (vec2i{3,2}));
-  //  }
-  
-  void test_value_multiplication_vector() const {
-    TS_ASSERT_EQUALS(2*iota2i(), (vec2i{2,4}));
-  }
-  
-  //  void test_value_divides_vector() const {
-  //    TS_ASSERT_EQUALS(4/iota2i(), (vec2i{4,2}));
-  //  }
-  
-  void test_length_of_vector() const {
-    //    TS_ASSERT_EQUALS(iota3i().lengthSquared(), 14);
-    TS_ASSERT_DELTA(iota3i().magnitude(), std::sqrt(14), 0.00001);
-  }
-  
-  void test_distance_of_vector() const {
-    //    TS_ASSERT_EQUALS((iota3i().distanceSquared(vec3i{3, 1, -1})), 21);
-    TS_ASSERT_DELTA((iota3i() - vec3i{3, 1, -1}).magnitude(), std::sqrt(21), 0.00001);
-  }
-  
-  void test_projection_of_vector() const {
-    TS_ASSERT_DELTA((iota3i().projection(vec3i{3, 1, -1})).magnitude(), std::sqrt(4.0/11.0), 0.00001);
-  }
-  
-  void test_dot_product() const {
-    TS_ASSERT_EQUALS((iota3i().dot(vec3i{3, 0, -1})), 0);
-  }
-  
-  void test_unit_vector() const {
-    double sq = std::sqrt(14);
-    vec3 epsilon{0.00001, math::vector::fill};
-    TS_ASSERT_DELTA(iota3i().unit(), (vec3{1/sq, 2/sq, 3/sq}), epsilon);
-  }
-  
-  void test_type_shift() const {
-    TS_ASSERT_EQUALS((vec3i(vec3{1.0, 2.3, 3.9})), iota3i());
-  }
-  
-  void test_swap() const {
-    using std::swap;
-    vec2i a{1, 2}; const vec2i ac = a;
-    vec2i b{5, 7}; const vec2i bc = b;
-    swap(a, b);
-    TS_ASSERT_EQUALS(a, bc);
-    TS_ASSERT_EQUALS(b, ac);
-  }
-  
-  void test_negate_vector() const {
-    TS_ASSERT_EQUALS(-iota3i(), (vec3i{-1,-2,-3}));
-  }
-  
-  void test_absolute_value() const {
-    TS_ASSERT_EQUALS(iota3i(), abs(-iota3i()));
-  }
-  
-private:
-  
-  template <typename T, size_t N> math::vector::vector<T, N> iota() const {
-    math::vector::vector<T, N> rval;
-    for (size_t i = 0; i < N; ++i) rval[i] = static_cast<T>(i+1);
-    return rval;
-  }
-  
-  vec2i iota2i() const { return iota<int, 2>(); }
-  vec3i iota3i() const { return iota<int, 3>(); }
-};

+ 404 - 8
vector.xcodeproj/project.pbxproj

@@ -7,9 +7,58 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		0E5DFDFB1BB4D5070063976E /* vector_tc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0E5DFDDA1BB4D3360063976E /* vector_tc.cpp */; };
+		CD0C599220C31D0000454F82 /* vector.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CDFFC7A81D62296200E9528B /* vector.hpp */; };
+		CD0C599C20C31D1900454F82 /* libvector.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD0C598E20C31CF600454F82 /* libvector.dylib */; };
+		CD0C59A420C31D2B00454F82 /* GoogleMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD0C598220C31CC300454F82 /* GoogleMock.framework */; };
+		CD0C59A520C31D3B00454F82 /* vector_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD0C598920C31CD300454F82 /* vector_test.cpp */; };
+		CD0C59B020C31E6600454F82 /* vector_dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD0C59AF20C31E6600454F82 /* vector_dummy.cpp */; };
 /* End PBXBuildFile section */
 
+/* Begin PBXContainerItemProxy section */
+		CD0C598120C31CC300454F82 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05818F861A685AEA0072A469;
+			remoteInfo = GoogleMock;
+		};
+		CD0C598320C31CC300454F82 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05E96ABD1A68600C00204102;
+			remoteInfo = gmock;
+		};
+		CD0C598520C31CC300454F82 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05E96B1F1A68634900204102;
+			remoteInfo = gtest;
+		};
+		CD0C598720C31CC300454F82 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05818F901A685AEA0072A469;
+			remoteInfo = GoogleMockTests;
+		};
+		CD0C599D20C31D1900454F82 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0E5DFDD11BB4D3360063976E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = CD0C598D20C31CF600454F82;
+			remoteInfo = vector;
+		};
+		CD0C59A220C31D2600454F82 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = 05818F851A685AEA0072A469;
+			remoteInfo = GoogleMock;
+		};
+/* End PBXContainerItemProxy section */
+
 /* Begin PBXCopyFilesBuildPhase section */
 		0E5DFDF11BB4D5040063976E /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
@@ -23,9 +72,13 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
-		0E5DFDDA1BB4D3360063976E /* vector_tc.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = vector_tc.cpp; sourceTree = "<group>"; };
-		0E5DFDDB1BB4D3360063976E /* vector.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vector.t.h; sourceTree = "<group>"; };
 		0E5DFDF31BB4D5040063976E /* vector_tc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vector_tc; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleMock.xcodeproj; path = "../../../gmock-xcode-master/GoogleMock.xcodeproj"; sourceTree = "<group>"; };
+		CD0C598920C31CD300454F82 /* vector_test.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = vector_test.cpp; sourceTree = "<group>"; };
+		CD0C598E20C31CF600454F82 /* libvector.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libvector.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD0C599720C31D1900454F82 /* vector_test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = vector_test.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD0C599B20C31D1900454F82 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = vector_test/Info.plist; sourceTree = "<group>"; };
+		CD0C59AF20C31E6600454F82 /* vector_dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vector_dummy.cpp; sourceTree = "<group>"; };
 		CDFFC7A81D62296200E9528B /* vector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -37,12 +90,29 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		CD0C598B20C31CF600454F82 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CD0C599420C31D1900454F82 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD0C59A420C31D2B00454F82 /* GoogleMock.framework in Frameworks */,
+				CD0C599C20C31D1900454F82 /* libvector.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
 		0E5DFDD01BB4D3360063976E = {
 			isa = PBXGroup;
 			children = (
+				CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */,
 				CD78202D1E44F40F001D22E5 /* src */,
 				CD78202E1E44F414001D22E5 /* test */,
 				0E5DFDF41BB4D5040063976E /* Products */,
@@ -53,6 +123,19 @@
 			isa = PBXGroup;
 			children = (
 				0E5DFDF31BB4D5040063976E /* vector_tc */,
+				CD0C598E20C31CF600454F82 /* libvector.dylib */,
+				CD0C599720C31D1900454F82 /* vector_test.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CD0C597B20C31CC300454F82 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CD0C598220C31CC300454F82 /* GoogleMock.framework */,
+				CD0C598420C31CC300454F82 /* gmock.framework */,
+				CD0C598620C31CC300454F82 /* gtest.framework */,
+				CD0C598820C31CC300454F82 /* GoogleMockTests.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -61,6 +144,7 @@
 			isa = PBXGroup;
 			children = (
 				CDFFC7A81D62296200E9528B /* vector.hpp */,
+				CD0C59AF20C31E6600454F82 /* vector_dummy.cpp */,
 			);
 			name = src;
 			sourceTree = "<group>";
@@ -68,14 +152,25 @@
 		CD78202E1E44F414001D22E5 /* test */ = {
 			isa = PBXGroup;
 			children = (
-				0E5DFDDB1BB4D3360063976E /* vector.t.h */,
-				0E5DFDDA1BB4D3360063976E /* vector_tc.cpp */,
+				CD0C598920C31CD300454F82 /* vector_test.cpp */,
+				CD0C599B20C31D1900454F82 /* Info.plist */,
 			);
 			name = test;
 			sourceTree = "<group>";
 		};
 /* End PBXGroup section */
 
+/* Begin PBXHeadersBuildPhase section */
+		CD0C598C20C31CF600454F82 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD0C599220C31D0000454F82 /* vector.hpp in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
 /* Begin PBXNativeTarget section */
 		0E5DFDF21BB4D5040063976E /* vector_tc */ = {
 			isa = PBXNativeTarget;
@@ -95,6 +190,42 @@
 			productReference = 0E5DFDF31BB4D5040063976E /* vector_tc */;
 			productType = "com.apple.product-type.tool";
 		};
+		CD0C598D20C31CF600454F82 /* vector */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CD0C598F20C31CF700454F82 /* Build configuration list for PBXNativeTarget "vector" */;
+			buildPhases = (
+				CD0C598A20C31CF600454F82 /* Sources */,
+				CD0C598B20C31CF600454F82 /* Frameworks */,
+				CD0C598C20C31CF600454F82 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = vector;
+			productName = vector;
+			productReference = CD0C598E20C31CF600454F82 /* libvector.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		CD0C599620C31D1900454F82 /* vector_test */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CD0C599F20C31D1900454F82 /* Build configuration list for PBXNativeTarget "vector_test" */;
+			buildPhases = (
+				CD0C599320C31D1900454F82 /* Sources */,
+				CD0C599420C31D1900454F82 /* Frameworks */,
+				CD0C599520C31D1900454F82 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				CD0C59A320C31D2600454F82 /* PBXTargetDependency */,
+				CD0C599E20C31D1900454F82 /* PBXTargetDependency */,
+			);
+			name = vector_test;
+			productName = vector_test;
+			productReference = CD0C599720C31D1900454F82 /* vector_test.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
@@ -106,6 +237,12 @@
 					0E5DFDF21BB4D5040063976E = {
 						CreatedOnToolsVersion = 7.0;
 					};
+					CD0C598D20C31CF600454F82 = {
+						CreatedOnToolsVersion = 7.2.1;
+					};
+					CD0C599620C31D1900454F82 = {
+						CreatedOnToolsVersion = 7.2.1;
+					};
 				};
 			};
 			buildConfigurationList = 0E5DFDD41BB4D3360063976E /* Build configuration list for PBXProject "vector" */;
@@ -118,13 +255,62 @@
 			mainGroup = 0E5DFDD01BB4D3360063976E;
 			productRefGroup = 0E5DFDF41BB4D5040063976E /* Products */;
 			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = CD0C597B20C31CC300454F82 /* Products */;
+					ProjectRef = CD0C597A20C31CC300454F82 /* GoogleMock.xcodeproj */;
+				},
+			);
 			projectRoot = "";
 			targets = (
 				0E5DFDF21BB4D5040063976E /* vector_tc */,
+				CD0C598D20C31CF600454F82 /* vector */,
+				CD0C599620C31D1900454F82 /* vector_test */,
 			);
 		};
 /* End PBXProject section */
 
+/* Begin PBXReferenceProxy section */
+		CD0C598220C31CC300454F82 /* GoogleMock.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = GoogleMock.framework;
+			remoteRef = CD0C598120C31CC300454F82 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CD0C598420C31CC300454F82 /* gmock.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = gmock.framework;
+			remoteRef = CD0C598320C31CC300454F82 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CD0C598620C31CC300454F82 /* gtest.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = gtest.framework;
+			remoteRef = CD0C598520C31CC300454F82 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CD0C598820C31CC300454F82 /* GoogleMockTests.xctest */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.cfbundle;
+			path = GoogleMockTests.xctest;
+			remoteRef = CD0C598720C31CC300454F82 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+		CD0C599520C31D1900454F82 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
 /* Begin PBXShellScriptBuildPhase section */
 		CD35DCF11D6130E700BE3686 /* Run Script */ = {
 			isa = PBXShellScriptBuildPhase;
@@ -149,12 +335,40 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				0E5DFDFB1BB4D5070063976E /* vector_tc.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CD0C598A20C31CF600454F82 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD0C59B020C31E6600454F82 /* vector_dummy.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CD0C599320C31D1900454F82 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD0C59A520C31D3B00454F82 /* vector_test.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXSourcesBuildPhase section */
 
+/* Begin PBXTargetDependency section */
+		CD0C599E20C31D1900454F82 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = CD0C598D20C31CF600454F82 /* vector */;
+			targetProxy = CD0C599D20C31D1900454F82 /* PBXContainerItemProxy */;
+		};
+		CD0C59A320C31D2600454F82 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = GoogleMock;
+			targetProxy = CD0C59A220C31D2600454F82 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
 /* Begin XCBuildConfiguration section */
 		0E5DFDD21BB4D3360063976E /* Debug */ = {
 			isa = XCBuildConfiguration;
@@ -165,6 +379,8 @@
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
+				USER_HEADER_SEARCH_PATHS = ../../paradigm/declarative;
+				WARNING_CFLAGS = "-Wno-gnu-zero-variadic-macro-arguments";
 			};
 			name = Debug;
 		};
@@ -175,6 +391,8 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				SDKROOT = macosx;
+				USER_HEADER_SEARCH_PATHS = ../../paradigm/declarative;
+				WARNING_CFLAGS = "-Wno-gnu-zero-variadic-macro-arguments";
 			};
 			name = Release;
 		};
@@ -216,7 +434,6 @@
 				MTL_ENABLE_DEBUG_INFO = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				USER_HEADER_SEARCH_PATHS = "../../**";
 			};
 			name = Debug;
 		};
@@ -253,7 +470,168 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				USER_HEADER_SEARCH_PATHS = "../../**";
+			};
+			name = Release;
+		};
+		CD0C599020C31CF700454F82 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				EXECUTABLE_PREFIX = lib;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		CD0C599120C31CF700454F82 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				EXECUTABLE_PREFIX = lib;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		CD0C59A020C31D1900454F82 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COMBINE_HIDPI_IMAGES = YES;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				INFOPLIST_FILE = vector_test/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = "leumasjaffe.vector-test";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		CD0C59A120C31D1900454F82 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COMBINE_HIDPI_IMAGES = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				INFOPLIST_FILE = vector_test/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				PRODUCT_BUNDLE_IDENTIFIER = "leumasjaffe.vector-test";
+				PRODUCT_NAME = "$(TARGET_NAME)";
 			};
 			name = Release;
 		};
@@ -278,6 +656,24 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		CD0C598F20C31CF700454F82 /* Build configuration list for PBXNativeTarget "vector" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD0C599020C31CF700454F82 /* Debug */,
+				CD0C599120C31CF700454F82 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CD0C599F20C31D1900454F82 /* Build configuration list for PBXNativeTarget "vector_test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD0C59A020C31D1900454F82 /* Debug */,
+				CD0C59A120C31D1900454F82 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 0E5DFDD11BB4D3360063976E /* Project object */;

+ 21 - 1
vector.xcodeproj/xcuserdata/samjaffe.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -4,10 +4,20 @@
 <dict>
 	<key>SchemeUserState</key>
 	<dict>
+		<key>vector.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>39</integer>
+		</dict>
 		<key>vector_tc.xcscheme</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>0</integer>
+			<integer>1</integer>
+		</dict>
+		<key>vector_test.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>40</integer>
 		</dict>
 	</dict>
 	<key>SuppressBuildableAutocreation</key>
@@ -22,6 +32,16 @@
 			<key>primary</key>
 			<true/>
 		</dict>
+		<key>CD0C598D20C31CF600454F82</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>CD0C599620C31D1900454F82</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
 	</dict>
 </dict>
 </plist>

+ 15 - 0
vector_dummy.cpp

@@ -0,0 +1,15 @@
+//
+//  vector_dummy.cpp
+//  vector
+//
+//  Created by Sam Jaffe on 6/2/18.
+//
+
+#include "vector.hpp"
+
+namespace math { namespace vector {
+  template class vector<int, 2>;
+  template class vector<double, 3>;
+  template class vector<int, 3>;
+  template class vector<int, 4>;
+} }

+ 153 - 0
vector_test.cpp

@@ -0,0 +1,153 @@
+//
+//  vector_test.cpp
+//  vector
+//
+//  Created by Sam Jaffe on 6/2/18.
+//
+
+#include <gmock/gmock.h>
+
+#include "vector.hpp"
+
+template <typename T, size_t N>
+math::vector::vector<T, N> iota() {
+  math::vector::vector<T, N> rval;
+  for (size_t i = 0; i < N; ++i) rval[i] = static_cast<T>(i+1);
+  return rval;
+}
+
+using vec2i = math::vector::vector<int, 2>;
+using vec3  = math::vector::vector<double, 3>;
+using vec3i = math::vector::vector<int, 3>;
+using vec4i = math::vector::vector<int, 4>;
+
+vec2i iota2i() { return iota<int, 2>(); }
+vec3i iota3i() { return iota<int, 3>(); }
+
+TEST(Vector, IncompatibleSizeThrows) {
+  EXPECT_THROW((vec2i{1}), std::logic_error);
+  EXPECT_THROW((vec2i{1,1,1}), std::logic_error);
+}
+
+TEST(Vector, Equality) {
+  EXPECT_THAT((iota3i()), (vec3i{1, 2, 3}));
+  EXPECT_THAT((iota3i()), ::testing::Not(vec3i{0, 2, 3}));
+}
+
+TEST(Vector, DefaultConstructorIsAllZero) {
+  EXPECT_THAT(vec3i(), (vec3i{0,0,0}));
+}
+
+TEST(Vector, ExtensionConstructorAppendsZeros) {
+  EXPECT_THAT(vec4i(iota3i()), (vec4i{1,2,3,0}));
+}
+
+TEST(Vector, CanAccessVectorElements) {
+  math::vector::vector<int, 3> viota = iota3i();
+  EXPECT_THAT(viota[0], 1);
+  EXPECT_THAT(viota[1], 2);
+  EXPECT_THAT(viota[2], 3);
+}
+
+TEST(Vector, AccessingOutOfRangeThrows) {
+  EXPECT_THROW(iota3i().at(3), std::out_of_range);
+}
+
+TEST(Vector, CrossProduct2DHasOnlyZElement) {
+  EXPECT_THAT((vec2i{1,1}.cross(vec2i{-1,1})), (vec3i{0,0,2}));
+}
+
+TEST(Vector, CrossProduct3DHasAllElements) {
+  EXPECT_THAT((vec3i{1,1,2}.cross(vec3i{-1,1,1})), (vec3i{-1,-3,2}));
+}
+
+TEST(Vector, AdditionIsPiecewise) {
+  EXPECT_THAT((vec2i{1,0} + vec2i{0,1}), (vec2i{1,1}));
+}
+
+TEST(Vector, SubtractionIsPiecewise) {
+  EXPECT_THAT((vec2i{1,0} - vec2i{0,1}), (vec2i{1,-1}));
+}
+
+TEST(Vector, MultiplicationIsPiecewise) {
+  EXPECT_THAT((vec2i{1,0}*(vec2i{2,1})), (vec2i{2,0}));
+}
+
+TEST(Vector, DivisionIsPiecewise) {
+  EXPECT_THAT((vec2i{6,4}/(vec2i{2,1})), (vec2i{3,4}));
+}
+
+TEST(Vector, DivisionByZeroThrowsException) {
+  EXPECT_THROW(vec3{} / 0, std::domain_error);
+  EXPECT_THROW((vec3{1.0, 1.0, 1.0}/(vec3{1.0, 0.5, 0.0})), std::domain_error);
+}
+
+//  TEST(Vector, AdditionWithValueType) {
+//    EXPECT_THAT((vec2i{1,0} + 1), (vec2i{2,1}))
+//    EXPECT_THAT(1+iota2i(), (vec2i{2,3}));
+//  }
+//
+//  TEST(Vector, SubtractionWithValueType) {
+//    EXPECT_THAT(4-iota2i(), (vec2i{3,2}));
+//    EXPECT_THAT((vec2i{1,0} - 1), (vec2i{0,-1}))
+//  }
+
+TEST(Vector, MultiplicationWithValueType) {
+  EXPECT_THAT((vec2i{1,0} * 3), (vec2i{3,0}));
+  EXPECT_THAT(2*iota2i(), (vec2i{2,4}));
+}
+
+TEST(Vector, DivisionWithValueType) {
+  EXPECT_THAT((vec2i{6,4} / 2), (vec2i{3,2}));
+//  EXPECT_THAT(4/iota2i(), (vec2i{4,2}));
+}
+
+TEST(Vector, Length) {
+  //    EXPECT_THAT(iota3i().lengthSquared(), 14);
+  EXPECT_THAT(iota3i().magnitude(),
+              ::testing::DoubleNear(std::sqrt(14), 0.00001));
+}
+
+TEST(Vector, Distance) {
+  //    EXPECT_THAT((iota3i().distanceSquared(vec3i{3, 1, -1})), 21);
+  EXPECT_THAT((iota3i() - vec3i{3, 1, -1}).magnitude(),
+              ::testing::DoubleNear(std::sqrt(21), 0.00001));
+}
+
+TEST(Vector, Projection) {
+  EXPECT_THAT((iota3i().projection(vec3i{3, 1, -1})).magnitude(),
+              ::testing::DoubleNear(std::sqrt(4.0/11.0), 0.00001));
+}
+
+TEST(Vector, DotProductIsSumOfElementProducts) {
+  EXPECT_THAT((iota3i().dot(vec3i{3, 0, -1})), 0);
+}
+
+TEST(Vector, UnitFunctionCreatesNewVectorOverMagnitude) {
+  double sq = std::sqrt(14);
+  auto unit = iota3i().unit();
+  EXPECT_THAT(unit[0], ::testing::DoubleNear(1/sq, 0.00001));
+  EXPECT_THAT(unit[1], ::testing::DoubleNear(2/sq, 0.00001));
+  EXPECT_THAT(unit[2], ::testing::DoubleNear(3/sq, 0.00001));
+}
+
+TEST(Vector, CanCastEntireVectorThroughConstructor) {
+  EXPECT_THAT((vec3i(vec3{1.0, 2.3, 3.9})), iota3i());
+}
+
+TEST(Vector, SwapExchangesAllValues) {
+  using std::swap;
+  vec2i a{1, 2}; const vec2i ac = a;
+  vec2i b{5, 7}; const vec2i bc = b;
+  swap(a, b);
+  EXPECT_THAT(a, bc);
+  EXPECT_THAT(b, ac);
+}
+
+TEST(Vector, UnaryNegateOperatorNegatesAllElements) {
+  EXPECT_THAT(-iota3i(), (vec3i{-1,-2,-3}));
+}
+
+TEST(Vector, AbsoluteValueOfVectorAbsAllElements) {
+  EXPECT_THAT(iota3i(), abs(-iota3i()));
+}

+ 24 - 0
vector_test/Info.plist

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>