--- /dev/null
+#include <limits>
+#include <msp/linal/vector.h>
+#include <msp/test/test.h>
+
+using namespace std;
+using namespace Msp;
+
+class VectorTests: public Test::RegisteredTest<VectorTests>
+{
+private:
+ typedef LinAl::Vector<int, 2> Vector2i;
+ typedef LinAl::Vector<int, 3> Vector3i;
+ typedef LinAl::Vector<float, 3> Vector3f;
+
+public:
+ VectorTests();
+
+ static const char *get_name() { return "Vector"; }
+
+private:
+ void component_aliases();
+ void composition();
+ void slice();
+ void addition();
+ void inner_prod();
+ void cross_prod();
+ void norm();
+ void unit_vec();
+};
+
+VectorTests::VectorTests()
+{
+ add(&VectorTests::component_aliases, "Component aliases");
+ add(&VectorTests::composition, "Compose");
+ add(&VectorTests::slice, "Slice");
+ add(&VectorTests::addition, "Addition");
+ add(&VectorTests::inner_prod, "Inner product");
+ add(&VectorTests::cross_prod, "Cross product");
+ add(&VectorTests::norm, "Norm");
+ add(&VectorTests::unit_vec, "Normalize");
+}
+
+void VectorTests::component_aliases()
+{
+ Vector3i v;
+ v.x = 1;
+ v[1] = 2;
+ v.z = 3;
+ EXPECT_EQUAL(v.x, v[0]);
+ EXPECT_EQUAL(v.y, v[1]);
+ EXPECT_EQUAL(v.z, v[2]);
+}
+
+void VectorTests::composition()
+{
+ Vector2i v(1, 2);
+ EXPECT_EQUAL(compose(3, v), Vector3i(3, 1, 2));
+ EXPECT_EQUAL(compose(v, 3), Vector3i(1, 2, 3));
+}
+
+void VectorTests::slice()
+{
+ Vector3i v(1, 2, 3);
+ EXPECT_EQUAL(v.slice<2>(0), Vector2i(1, 2));
+ EXPECT_EQUAL(v.slice<2>(1), Vector2i(2, 3));
+ EXPECT_EQUAL(v.slice<3>(0), v);
+}
+
+void VectorTests::addition()
+{
+ Vector3i v(1, 2, 3);
+ Vector3i w(4, 3, 5);
+ EXPECT_EQUAL(v+w, Vector3i(5, 5, 8));
+ EXPECT_EQUAL(v+w, w+v);
+}
+
+void VectorTests::inner_prod()
+{
+ Vector3i v(1, 2, 3);
+ Vector3i w(-2, 5, 1);
+ Vector3i u(-13, -7, 9);
+ EXPECT_EQUAL(inner_product(v, w), 11);
+ EXPECT_EQUAL(inner_product(v, u), 0);
+ EXPECT_EQUAL(inner_product(w, u), 0);
+}
+
+void VectorTests::cross_prod()
+{
+ Vector3i x(1, 0, 0);
+ Vector3i y(0, 1, 0);
+ Vector3i z(0, 0, 1);
+ EXPECT_EQUAL(cross(x, y), z);
+ EXPECT_EQUAL(cross(y, x), -z);
+ EXPECT_EQUAL(cross(y, z), x);
+ EXPECT_EQUAL(cross(z, y), -x);
+ EXPECT_EQUAL(cross(z, x), y);
+ EXPECT_EQUAL(cross(x, z), -y);
+}
+
+void VectorTests::norm()
+{
+ Vector3f v(2.0f, 6.0f, 9.0f);
+ Vector3f w(-3.0f, -4.0f, 12.0f);
+ EXPECT_EQUAL(v.norm(), 11.0f);
+ EXPECT_EQUAL(w.norm(), 13.0f);
+}
+
+template<typename T, unsigned N>
+bool is_unit(const LinAl::Vector<T, N> &v)
+{
+ static const T limit = numeric_limits<T>::epsilon()*4;
+ return abs(v.norm()-T(1))<=limit;
+}
+
+void VectorTests::unit_vec()
+{
+ Vector3f v(2.0f, 6.0f, 9.0f);
+ Vector3f w(-3.0f, -4.0f, 12.0f);
+ EXPECT(is_unit(normalize(v)));
+ EXPECT(is_unit(normalize(w)));
+}