From b7e237c6ea4b1fce8201309a0adb27ed7114fb05 Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Thu, 3 Jul 2014 06:43:28 +0000
Subject: [PATCH] math: move matrix code out of vector.h into a new matrix.h
 header.

---
 src/Makefile.am             |   2 +-
 src/lol/base/types.h        |   4 +
 src/lol/math/all.h          |   1 +
 src/lol/math/matrix.h       | 427 ++++++++++++++++++++++++++++++++++++
 src/lol/math/vector.h       | 424 +----------------------------------
 src/lolcore.vcxproj         |   1 +
 src/lolcore.vcxproj.filters |   3 +
 7 files changed, 445 insertions(+), 417 deletions(-)
 create mode 100644 src/lol/math/matrix.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 749e1904..a6fda3e6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,7 +43,7 @@ liblolcore_headers = \
     lol/math/all.h \
     lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \
     lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \
-    lol/math/array3d.h lol/math/constants.h \
+    lol/math/array3d.h lol/math/constants.h lol/math/matrix.h \
     \
     lol/algorithm/all.h \
     lol/algorithm/sort.h lol/algorithm/portal.h lol/algorithm/aabb_tree.h \
diff --git a/src/lol/base/types.h b/src/lol/base/types.h
index 0180bc5d..5c24fc43 100644
--- a/src/lol/base/types.h
+++ b/src/lol/base/types.h
@@ -28,6 +28,10 @@ typedef Real<16> real;
 /* The “half” type used for 16-bit floating point numbers. */
 class half;
 
+/* Forward declaration of vec and matrix */
+template<int N, typename T, int MASK> struct vec;
+template<int COLS, int ROWS, typename T> struct matrix;
+
 } /* namespace lol */
 
 #endif // __LOL_BASE_TYPES_H__
diff --git a/src/lol/math/all.h b/src/lol/math/all.h
index 24cfe955..446901a9 100644
--- a/src/lol/math/all.h
+++ b/src/lol/math/all.h
@@ -16,6 +16,7 @@
 #include <lol/math/half.h>
 #include <lol/math/real.h>
 #include <lol/math/vector.h>
+#include <lol/math/matrix.h>
 #include <lol/math/array2d.h>
 #include <lol/math/array3d.h>
 #include <lol/math/geometry.h>
diff --git a/src/lol/math/matrix.h b/src/lol/math/matrix.h
new file mode 100644
index 00000000..863e37e7
--- /dev/null
+++ b/src/lol/math/matrix.h
@@ -0,0 +1,427 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the Do What The Fuck You Want To
+//   Public License, Version 2, as published by Sam Hocevar. See
+//   http://www.wtfpl.net/ for more details.
+//
+
+//
+// The matrix classes
+// ------------------
+//
+
+#if !defined __LOL_MATH_MATRIX_H__
+#define __LOL_MATH_MATRIX_H__
+
+#include <stdint.h>
+#include <ostream>
+
+#include <lol/math/vector.h>
+
+namespace lol
+{
+
+#if !LOL_FEATURE_CXX11_CONSTEXPR
+#   define constexpr /* */
+#endif
+
+/* The generic "matrix" type, which is a fixed-size matrix */
+template<int COLS, int ROWS, typename T>
+struct matrix
+{
+    typedef matrix<COLS,ROWS,T> type;
+
+    inline matrix() {}
+
+    explicit inline matrix(T const &val)
+    {
+        T const zero = T(0);
+        for (int i = 0; i < COLS; ++i)
+            for (int j = 0; j < ROWS; ++j)
+                m_data[i][j] = i == j ? val : zero;
+    }
+
+    inline vec<ROWS,T>& operator[](size_t n) { return m_data[n]; }
+    inline vec<ROWS,T> const& operator[](size_t n) const { return m_data[n]; }
+
+private:
+    vec<ROWS,T> m_data[COLS];
+};
+
+/*
+ * 2×2-element matrices
+ */
+
+template <typename T>
+struct matrix<2, 2, T>
+{
+    typedef matrix<2,2,T> type;
+
+    inline matrix() {}
+    inline matrix(vec<2,T> V0, vec<2,T> V1)
+      : v0(V0), v1(V1) {}
+
+    explicit inline matrix(T const &val)
+      : v0(val, (T)0),
+        v1((T)0, val) {}
+
+    explicit inline matrix(matrix<4,4,T> const &mat)
+      : v0(mat[0].xy),
+        v1(mat[1].xy) {}
+
+    inline vec<2,T>& operator[](size_t n) { return (&v0)[n]; }
+    inline vec<2,T> const& operator[](size_t n) const { return (&v0)[n]; }
+
+    /* Helpers for transformation matrices */
+    static matrix<2,2,T> rotate(T degrees);
+    static inline matrix<2,2,T> rotate(matrix<2,2,T> mat, T degrees)
+    {
+        return rotate(degrees) * mat;
+    }
+
+    void printf() const;
+    String tostring() const;
+
+    template<class U>
+    friend std::ostream &operator<<(std::ostream &stream,
+                                    matrix<2,2,U> const &m);
+
+    vec<2,T> v0, v1;
+
+    static const matrix<2,2,T> identity;
+};
+
+/*
+ * 3×3-element matrices
+ */
+
+template <typename T>
+struct matrix<3,3,T>
+{
+    typedef matrix<3,3,T> type;
+
+    inline matrix() {}
+    inline matrix(vec<3,T> V0, vec<3,T> V1, vec<3,T> V2)
+      : v0(V0), v1(V1), v2(V2) {}
+
+    explicit inline matrix(T const &val)
+      : v0(val, (T)0, (T)0),
+        v1((T)0, val, (T)0),
+        v2((T)0, (T)0, val) {}
+
+    explicit inline matrix(matrix<2,2,T> mat)
+      : v0(mat[0], (T)0),
+        v1(mat[1], (T)0),
+        v2((T)0, (T)0, (T)0) {}
+
+    explicit inline matrix(matrix<2,2,T> mat, T const &val)
+      : v0(vec<3,T>(mat[0], (T)0)),
+        v1(vec<3,T>(mat[1], (T)0)),
+        v2((T)0, (T)0, val) {}
+
+    explicit inline matrix(matrix<4,4,T> const &mat)
+      : v0(mat[0].xyz),
+        v1(mat[1].xyz),
+        v2(mat[2].xyz) {}
+
+    explicit matrix(Quat<T> const &q);
+
+    inline vec<3,T>& operator[](size_t n) { return (&v0)[n]; }
+    inline vec<3,T> const& operator[](size_t n) const { return (&v0)[n]; }
+
+    /* Helpers for transformation matrices */
+    static matrix<3,3,T> scale(T x);
+    static matrix<3,3,T> scale(T x, T y, T z);
+    static matrix<3,3,T> scale(vec<3,T> v);
+    static matrix<3,3,T> rotate(T degrees, T x, T y, T z);
+    static matrix<3,3,T> rotate(T degrees, vec<3,T> v);
+
+    static matrix<3,3,T> fromeuler_xyz(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_xzy(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_yxz(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_yzx(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_zxy(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_zyx(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_xyz(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_xzy(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_yxz(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_yzx(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_zxy(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_zyx(T phi, T theta, T psi);
+
+    static matrix<3,3,T> fromeuler_xyx(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_xzx(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_yxy(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_yzy(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_zxz(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_zyz(vec<3,T> const &v);
+    static matrix<3,3,T> fromeuler_xyx(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_xzx(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_yxy(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_yzy(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_zxz(T phi, T theta, T psi);
+    static matrix<3,3,T> fromeuler_zyz(T phi, T theta, T psi);
+
+    static inline matrix<3,3,T> rotate(matrix<3,3,T> mat, T degrees, vec<3,T> v)
+    {
+        return rotate(degrees, v) * mat;
+    }
+
+    void printf() const;
+    String tostring() const;
+
+    template<class U>
+    friend std::ostream &operator<<(std::ostream &stream,
+                                    matrix<3,3,U> const &m);
+
+    vec<3,T> v0, v1, v2;
+
+    static const matrix<3,3,T> identity;
+};
+
+/*
+ * 4×4-element matrices
+ */
+
+template <typename T>
+struct matrix<4, 4, T>
+{
+    typedef matrix<4,4,T> type;
+
+    inline matrix() {}
+    inline matrix(vec<4,T> V0, vec<4,T> V1, vec<4,T> V2, vec<4,T> V3)
+      : v0(V0), v1(V1), v2(V2), v3(V3) {}
+
+    explicit inline matrix(T const &val)
+      : v0(val, (T)0, (T)0, (T)0),
+        v1((T)0, val, (T)0, (T)0),
+        v2((T)0, (T)0, val, (T)0),
+        v3((T)0, (T)0, (T)0, val) {}
+
+    explicit inline matrix(matrix<2,2,T> mat)
+      : v0(mat[0], (T)0, (T)0),
+        v1(mat[1], (T)0, (T)0),
+        v2((T)0, (T)0, (T)0, (T)0),
+        v3((T)0, (T)0, (T)0, (T)0) {}
+
+    explicit inline matrix(matrix<2,2,T> mat, T const &val1, T const &val2)
+      : v0(mat[0], (T)0, (T)0),
+        v1(mat[1], (T)0, (T)0),
+        v2((T)0, (T)0, val1, (T)0),
+        v3((T)0, (T)0, (T)0, val2) {}
+
+    explicit inline matrix(matrix<3,3,T> mat)
+      : v0(mat[0], (T)0),
+        v1(mat[1], (T)0),
+        v2(mat[2], (T)0),
+        v3((T)0, (T)0, (T)0, (T)0) {}
+
+    explicit inline matrix(matrix<3,3,T> mat, T const &val)
+      : v0(mat[0], (T)0),
+        v1(mat[1], (T)0),
+        v2(mat[2], (T)0),
+        v3((T)0, (T)0, (T)0, val) {}
+
+    explicit matrix(Quat<T> const &q);
+
+    inline vec<4,T>& operator[](size_t n) { return (&v0)[n]; }
+    inline vec<4,T> const& operator[](size_t n) const { return (&v0)[n]; }
+
+    /* Helpers for transformation matrices */
+    static matrix<4,4,T> translate(T x, T y, T z);
+    static matrix<4,4,T> translate(vec<3,T> v);
+
+    static inline matrix<4,4,T> scale(T x)
+    {
+        return matrix<4,4,T>(matrix<3,3,T>::scale(x), (T)1);
+    }
+
+    static inline matrix<4,4,T> scale(T x, T y, T z)
+    {
+        return matrix<4,4,T>(matrix<3,3,T>::scale(x, y, z), (T)1);
+    }
+
+    static inline matrix<4,4,T> scale(vec<3,T> v)
+    {
+        return matrix<4,4,T>(matrix<3,3,T>::scale(v), (T)1);
+    }
+
+    static inline matrix<4,4,T> translate(matrix<4,4,T> const &mat, vec<3,T> v)
+    {
+        return translate(v) * mat;
+    }
+
+    static inline matrix<4,4,T> rotate(T degrees, T x, T y, T z)
+    {
+        return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, x, y, z), (T)1);
+    }
+
+    static inline matrix<4,4,T> rotate(T degrees, vec<3,T> v)
+    {
+        return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, v), (T)1);
+    }
+
+    static inline matrix<4,4,T> rotate(matrix<4,4,T> &mat, T degrees, vec<3,T> v)
+    {
+        return rotate(degrees, v) * mat;
+    }
+
+    static matrix<4,4,T> fromeuler_xyz(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_xzy(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_yxz(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_yzx(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_zxy(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_zyx(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_xyz(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_xzy(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_yxz(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_yzx(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_zxy(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_zyx(T phi, T theta, T psi);
+
+    static matrix<4,4,T> fromeuler_xyx(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_xzx(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_yxy(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_yzy(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_zxz(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_zyz(vec<3,T> const &v);
+    static matrix<4,4,T> fromeuler_xyx(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_xzx(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_yxy(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_yzy(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_zxz(T phi, T theta, T psi);
+    static matrix<4,4,T> fromeuler_zyz(T phi, T theta, T psi);
+
+    /* Helpers for view matrices */
+    static matrix<4,4,T> lookat(vec<3,T> eye, vec<3,T> center, vec<3,T> up);
+
+    /* Helpers for projection matrices */
+    static matrix<4,4,T> ortho(T left, T right, T bottom, T top, T near, T far);
+    static matrix<4,4,T> ortho(T width, T height, T near, T far);
+    static matrix<4,4,T> frustum(T left, T right, T bottom, T top, T near, T far);
+    static matrix<4,4,T> perspective(T fov_y, T width, T height, T near, T far);
+    static matrix<4,4,T> shifted_perspective(T fov_y, T screen_size, T screen_ratio_yx, T near, T far);
+
+    void printf() const;
+    String tostring() const;
+
+    template<class U>
+    friend std::ostream &operator<<(std::ostream &stream,
+                                    matrix<4,4,U> const &m);
+
+    vec<4,T> v0, v1, v2, v3;
+
+    static const matrix<4,4,T> identity;
+};
+
+template<typename T> T determinant(matrix<2,2,T> const &);
+template<typename T> T determinant(matrix<3,3,T> const &);
+template<typename T> T determinant(matrix<4,4,T> const &);
+
+template<typename T> matrix<2,2,T> transpose(matrix<2,2,T> const &);
+template<typename T> matrix<3,3,T> transpose(matrix<3,3,T> const &);
+template<typename T> matrix<4,4,T> transpose(matrix<4,4,T> const &);
+
+template<typename T> matrix<2,2,T> inverse(matrix<2,2,T> const &);
+template<typename T> matrix<3,3,T> inverse(matrix<3,3,T> const &);
+template<typename T> matrix<4,4,T> inverse(matrix<4,4,T> const &);
+
+/*
+ * Addition/subtraction/unary
+ */
+
+template<int COLS, int ROWS, typename T>
+static inline matrix<COLS, ROWS, T> &operator +=(matrix<COLS, ROWS, T> &a,
+                                                 matrix<COLS, ROWS, T> const &b)
+{
+    for (int i = 0; i < COLS; ++i)
+        a[i] += b[i];
+    return a;
+}
+
+template<int COLS, int ROWS, typename T>
+static inline matrix<COLS, ROWS, T> operator +(matrix<COLS, ROWS, T> const &a,
+                                               matrix<COLS, ROWS, T> const &b)
+{
+    matrix<COLS, ROWS, T> ret = a;
+    return ret += b;
+}
+
+template<int COLS, int ROWS, typename T>
+static inline matrix<COLS, ROWS, T> operator +(matrix<COLS, ROWS, T> const &m)
+{
+    return m;
+}
+
+template<int COLS, int ROWS, typename T>
+static inline matrix<COLS, ROWS, T> &operator -=(matrix<COLS, ROWS, T> &a,
+                                                 matrix<COLS, ROWS, T> const &b)
+{
+    for (int i = 0; i < COLS; ++i)
+        a[i] -= b[i];
+    return a;
+}
+
+template<int COLS, int ROWS, typename T>
+static inline matrix<COLS, ROWS, T> operator -(matrix<COLS, ROWS, T> const &a,
+                                               matrix<COLS, ROWS, T> const &b)
+{
+    matrix<COLS, ROWS, T> ret = a;
+    return ret -= b;
+}
+
+template<int COLS, int ROWS, typename T>
+static inline matrix<COLS, ROWS, T> operator -(matrix<COLS, ROWS, T> const &m)
+{
+    matrix<COLS, ROWS, T> ret;
+    for (int i = 0; i < COLS; ++i)
+        ret[i] = -m[i];
+    return ret;
+}
+
+/*
+ * Matrix-vector multiplication
+ */
+
+template<int COLS, int ROWS, int MASK, typename T>
+static inline vec<ROWS, T> operator *(matrix<COLS, ROWS, T> const &m,
+                                      vec<COLS, T, MASK> const &v)
+{
+    vec<ROWS, T> ret(T(0));
+    for (int i = 0; i < COLS; ++i)
+        ret += m[i] * v[i];
+    return ret;
+}
+
+/*
+ * Matrix-matrix multiplication
+ */
+
+template<int COLS, int N, int ROWS, typename T>
+static inline matrix<COLS, ROWS, T> operator *(matrix<N, ROWS, T> const &a,
+                                               matrix<COLS, N, T> const &b)
+{
+    matrix<COLS, ROWS, T> ret;
+    for (int i = 0; i < COLS; ++i)
+        ret[i] = a * b[i];
+    return ret;
+}
+
+template<int N, typename T>
+static inline matrix<N, N, T> &operator *=(matrix<N, N, T> &a,
+                                           matrix<N, N, T> const &b)
+{
+    return a = a * b;
+}
+
+#if !LOL_FEATURE_CXX11_CONSTEXPR
+#undef constexpr
+#endif
+
+} /* namespace lol */
+
+#endif // __LOL_MATH_MATRIX_H__
+
diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h
index 8aa6eb49..cc799578 100644
--- a/src/lol/math/vector.h
+++ b/src/lol/math/vector.h
@@ -52,6 +52,8 @@ namespace lol
 template<int N, typename T, int MASK = -1>
 struct vec
 {
+    typedef vec<N,T> type;
+
     inline vec<N, T, MASK>& operator =(vec<N, T> that);
 
 #if LOL_FEATURE_CXX11_RELAXED_UNIONS
@@ -78,16 +80,13 @@ struct vec
 template<int N, typename T>
 struct vec<N, T, -1>
 {
-private:
-    T m_data[N];
-};
+    typedef vec<N,T> type;
+
+    inline T& operator[](size_t n) { return m_data[n]; }
+    inline T const& operator[](size_t n) const { return m_data[n]; }
 
-/* The generic "matrix" type, which is a fixed-size matrix */
-template<int COLS, int ROWS, typename T>
-struct matrix
-{
 private:
-    T m_data[COLS][ROWS];
+    T m_data[N];
 };
 
 /* The generic complex and quaternion types. */
@@ -99,7 +98,6 @@ template<typename T> struct Quat;
  */
 
 #define COMMA ,
-
 #define LOL_VECTOR_TYPEDEFS(tleft, tright, suffix) \
     typedef tleft half tright f16##suffix; \
     typedef tleft float tright suffix; \
@@ -134,6 +132,7 @@ LOL_VECTOR_TYPEDEFS(Cmplx<, >, cmplx)
 LOL_VECTOR_TYPEDEFS(Quat<, >, quat)
 
 #undef LOL_VECTOR_TYPEDEFS
+#undef COMMA
 
 /*
  * HLSL/Cg-compliant type names.
@@ -1612,413 +1611,6 @@ inline vec<N, T, MASK>& vec<N, T, MASK>::operator =(vec<N,T> that)
 }
 #endif
 
-/*
- * 2×2-element matrices
- */
-
-template <typename T>
-struct matrix<2, 2, T>
-{
-    typedef matrix<2,2,T> type;
-
-    inline matrix() {}
-    inline matrix(vec<2,T> V0, vec<2,T> V1)
-      : v0(V0), v1(V1) {}
-
-    explicit inline matrix(T val)
-      : v0(val, (T)0),
-        v1((T)0, val) {}
-
-    explicit inline matrix(matrix<4,4,T> const &mat)
-      : v0(mat[0].xy),
-        v1(mat[1].xy) {}
-
-    inline vec<2,T>& operator[](size_t n) { return (&v0)[n]; }
-    inline vec<2,T> const& operator[](size_t n) const { return (&v0)[n]; }
-
-    /* Helpers for transformation matrices */
-    static matrix<2,2,T> rotate(T degrees);
-    static inline matrix<2,2,T> rotate(matrix<2,2,T> mat, T degrees)
-    {
-        return rotate(degrees) * mat;
-    }
-
-    void printf() const;
-    String tostring() const;
-
-    template<class U>
-    friend std::ostream &operator<<(std::ostream &stream,
-                                    matrix<2,2,U> const &m);
-
-    inline matrix<2,2,T> operator +(matrix<2,2,T> const m) const
-    {
-        return matrix<2,2,T>(v0 + m[0], v1 + m[1]);
-    }
-
-    inline matrix<2,2,T> operator +=(matrix<2,2,T> const m)
-    {
-        return *this = *this + m;
-    }
-
-    inline matrix<2,2,T> operator -(matrix<2,2,T> const m) const
-    {
-        return matrix<2,2,T>(v0 - m[0], v1 - m[1]);
-    }
-
-    inline matrix<2,2,T> operator -=(matrix<2,2,T> const m)
-    {
-        return *this = *this - m;
-    }
-
-    inline matrix<2,2,T> operator *(matrix<2,2,T> const m) const
-    {
-        return matrix<2,2,T>(*this * m[0], *this * m[1]);
-    }
-
-    inline matrix<2,2,T> operator *=(matrix<2,2,T> const m)
-    {
-        return *this = *this * m;
-    }
-
-    inline vec<2,T> operator *(vec<2,T> const m) const
-    {
-        vec<2,T> ret;
-        for (int j = 0; j < 2; j++)
-        {
-            T tmp = 0;
-            for (int k = 0; k < 2; k++)
-                tmp += (*this)[k][j] * m[k];
-            ret[j] = tmp;
-        }
-        return ret;
-    }
-
-    vec<2,T> v0, v1;
-
-    static const matrix<2,2,T> identity;
-};
-
-/*
- * 3×3-element matrices
- */
-
-template <typename T>
-struct matrix<3,3,T>
-{
-    typedef matrix<3,3,T> type;
-
-    inline matrix() {}
-    inline matrix(vec<3,T> V0, vec<3,T> V1, vec<3,T> V2)
-      : v0(V0), v1(V1), v2(V2) {}
-
-    explicit inline matrix(T val)
-      : v0(val, (T)0, (T)0),
-        v1((T)0, val, (T)0),
-        v2((T)0, (T)0, val) {}
-
-    explicit inline matrix(matrix<2,2,T> mat)
-      : v0(mat[0], (T)0),
-        v1(mat[1], (T)0),
-        v2((T)0, (T)0, (T)0) {}
-
-    explicit inline matrix(matrix<2,2,T> mat, T val)
-      : v0(vec<3,T>(mat[0], (T)0)),
-        v1(vec<3,T>(mat[1], (T)0)),
-        v2((T)0, (T)0, val) {}
-
-    explicit inline matrix(matrix<4,4,T> const &mat)
-      : v0(mat[0].xyz),
-        v1(mat[1].xyz),
-        v2(mat[2].xyz) {}
-
-    explicit matrix(Quat<T> const &q);
-
-    inline vec<3,T>& operator[](size_t n) { return (&v0)[n]; }
-    inline vec<3,T> const& operator[](size_t n) const { return (&v0)[n]; }
-
-    /* Helpers for transformation matrices */
-    static matrix<3,3,T> scale(T x);
-    static matrix<3,3,T> scale(T x, T y, T z);
-    static matrix<3,3,T> scale(vec<3,T> v);
-    static matrix<3,3,T> rotate(T degrees, T x, T y, T z);
-    static matrix<3,3,T> rotate(T degrees, vec<3,T> v);
-
-    static matrix<3,3,T> fromeuler_xyz(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_xzy(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_yxz(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_yzx(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_zxy(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_zyx(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_xyz(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_xzy(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_yxz(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_yzx(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_zxy(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_zyx(T phi, T theta, T psi);
-
-    static matrix<3,3,T> fromeuler_xyx(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_xzx(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_yxy(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_yzy(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_zxz(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_zyz(vec<3,T> const &v);
-    static matrix<3,3,T> fromeuler_xyx(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_xzx(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_yxy(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_yzy(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_zxz(T phi, T theta, T psi);
-    static matrix<3,3,T> fromeuler_zyz(T phi, T theta, T psi);
-
-    static inline matrix<3,3,T> rotate(matrix<3,3,T> mat, T degrees, vec<3,T> v)
-    {
-        return rotate(degrees, v) * mat;
-    }
-
-    void printf() const;
-    String tostring() const;
-
-    template<class U>
-    friend std::ostream &operator<<(std::ostream &stream,
-                                    matrix<3,3,U> const &m);
-
-    inline matrix<3,3,T> operator +(matrix<3,3,T> const m) const
-    {
-        return matrix<3,3,T>(v0 + m[0], v1 + m[1], v2 + m[2]);
-    }
-
-    inline matrix<3,3,T> operator +=(matrix<3,3,T> const m)
-    {
-        return *this = *this + m;
-    }
-
-    inline matrix<3,3,T> operator -(matrix<3,3,T> const m) const
-    {
-        return matrix<3,3,T>(v0 - m[0], v1 - m[1], v2 - m[2]);
-    }
-
-    inline matrix<3,3,T> operator -=(matrix<3,3,T> const m)
-    {
-        return *this = *this - m;
-    }
-
-    inline matrix<3,3,T> operator *(matrix<3,3,T> const m) const
-    {
-        return matrix<3,3,T>(*this * m[0], *this * m[1], *this * m[2]);
-    }
-
-    inline matrix<3,3,T> operator *=(matrix<3,3,T> const m)
-    {
-        return *this = *this * m;
-    }
-
-    inline vec<3,T> operator *(vec<3,T> const m) const
-    {
-        vec<3,T> ret;
-        for (int j = 0; j < 3; j++)
-        {
-            T tmp = 0;
-            for (int k = 0; k < 3; k++)
-                tmp += (*this)[k][j] * m[k];
-            ret[j] = tmp;
-        }
-        return ret;
-    }
-
-    vec<3,T> v0, v1, v2;
-
-    static const matrix<3,3,T> identity;
-};
-
-/*
- * 4×4-element matrices
- */
-
-template <typename T>
-struct matrix<4, 4, T>
-{
-    typedef matrix<4,4,T> type;
-
-    inline matrix() {}
-    inline matrix(vec<4,T> V0, vec<4,T> V1, vec<4,T> V2, vec<4,T> V3)
-      : v0(V0), v1(V1), v2(V2), v3(V3) {}
-
-    explicit inline matrix(T val)
-      : v0(val, (T)0, (T)0, (T)0),
-        v1((T)0, val, (T)0, (T)0),
-        v2((T)0, (T)0, val, (T)0),
-        v3((T)0, (T)0, (T)0, val) {}
-
-    explicit inline matrix(matrix<2,2,T> mat)
-      : v0(mat[0], (T)0, (T)0),
-        v1(mat[1], (T)0, (T)0),
-        v2((T)0, (T)0, (T)0, (T)0),
-        v3((T)0, (T)0, (T)0, (T)0) {}
-
-    explicit inline matrix(matrix<2,2,T> mat, T val1, T val2)
-      : v0(mat[0], (T)0, (T)0),
-        v1(mat[1], (T)0, (T)0),
-        v2((T)0, (T)0, val1, (T)0),
-        v3((T)0, (T)0, (T)0, val2) {}
-
-    explicit inline matrix(matrix<3,3,T> mat)
-      : v0(mat[0], (T)0),
-        v1(mat[1], (T)0),
-        v2(mat[2], (T)0),
-        v3((T)0, (T)0, (T)0, (T)0) {}
-
-    explicit inline matrix(matrix<3,3,T> mat, T val)
-      : v0(mat[0], (T)0),
-        v1(mat[1], (T)0),
-        v2(mat[2], (T)0),
-        v3((T)0, (T)0, (T)0, val) {}
-
-    explicit matrix(Quat<T> const &q);
-
-    inline vec<4,T>& operator[](size_t n) { return (&v0)[n]; }
-    inline vec<4,T> const& operator[](size_t n) const { return (&v0)[n]; }
-
-    /* Helpers for transformation matrices */
-    static matrix<4,4,T> translate(T x, T y, T z);
-    static matrix<4,4,T> translate(vec<3,T> v);
-
-    static inline matrix<4,4,T> scale(T x)
-    {
-        return matrix<4,4,T>(matrix<3,3,T>::scale(x), (T)1);
-    }
-
-    static inline matrix<4,4,T> scale(T x, T y, T z)
-    {
-        return matrix<4,4,T>(matrix<3,3,T>::scale(x, y, z), (T)1);
-    }
-
-    static inline matrix<4,4,T> scale(vec<3,T> v)
-    {
-        return matrix<4,4,T>(matrix<3,3,T>::scale(v), (T)1);
-    }
-
-    static inline matrix<4,4,T> translate(matrix<4,4,T> const &mat, vec<3,T> v)
-    {
-        return translate(v) * mat;
-    }
-
-    static inline matrix<4,4,T> rotate(T degrees, T x, T y, T z)
-    {
-        return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, x, y, z), (T)1);
-    }
-
-    static inline matrix<4,4,T> rotate(T degrees, vec<3,T> v)
-    {
-        return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, v), (T)1);
-    }
-
-    static inline matrix<4,4,T> rotate(matrix<4,4,T> &mat, T degrees, vec<3,T> v)
-    {
-        return rotate(degrees, v) * mat;
-    }
-
-    static matrix<4,4,T> fromeuler_xyz(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_xzy(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_yxz(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_yzx(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_zxy(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_zyx(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_xyz(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_xzy(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_yxz(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_yzx(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_zxy(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_zyx(T phi, T theta, T psi);
-
-    static matrix<4,4,T> fromeuler_xyx(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_xzx(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_yxy(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_yzy(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_zxz(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_zyz(vec<3,T> const &v);
-    static matrix<4,4,T> fromeuler_xyx(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_xzx(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_yxy(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_yzy(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_zxz(T phi, T theta, T psi);
-    static matrix<4,4,T> fromeuler_zyz(T phi, T theta, T psi);
-
-    /* Helpers for view matrices */
-    static matrix<4,4,T> lookat(vec<3,T> eye, vec<3,T> center, vec<3,T> up);
-
-    /* Helpers for projection matrices */
-    static matrix<4,4,T> ortho(T left, T right, T bottom, T top, T near, T far);
-    static matrix<4,4,T> ortho(T width, T height, T near, T far);
-    static matrix<4,4,T> frustum(T left, T right, T bottom, T top, T near, T far);
-    static matrix<4,4,T> perspective(T fov_y, T width, T height, T near, T far);
-    static matrix<4,4,T> shifted_perspective(T fov_y, T screen_size, T screen_ratio_yx, T near, T far);
-
-    void printf() const;
-    String tostring() const;
-
-    template<class U>
-    friend std::ostream &operator<<(std::ostream &stream,
-                                    matrix<4,4,U> const &m);
-
-    inline matrix<4,4,T> operator +(matrix<4,4,T> const &m) const
-    {
-        return matrix<4,4,T>(v0 + m[0], v1 + m[1], v2 + m[2], v3 + m[3]);
-    }
-
-    inline matrix<4,4,T> operator +=(matrix<4,4,T> const &m)
-    {
-        return *this = *this + m;
-    }
-
-    inline matrix<4,4,T> operator -(matrix<4,4,T> const &m) const
-    {
-        return matrix<4,4,T>(v0 - m[0], v1 - m[1], v2 - m[2], v3 - m[3]);
-    }
-
-    inline matrix<4,4,T> operator -=(matrix<4,4,T> const &m)
-    {
-        return *this = *this - m;
-    }
-
-    inline matrix<4,4,T> operator *(matrix<4,4,T> const &m) const
-    {
-        return matrix<4,4,T>(*this * m[0], *this * m[1], *this * m[2], *this * m[3]);
-    }
-
-    inline matrix<4,4,T> operator *=(matrix<4,4,T> const &m)
-    {
-        return *this = *this * m;
-    }
-
-    inline vec<4,T> operator *(vec<4,T> const &m) const
-    {
-        vec<4,T> ret;
-        for (int j = 0; j < 4; j++)
-        {
-            T tmp = 0;
-            for (int k = 0; k < 4; k++)
-                tmp += (*this)[k][j] * m[k];
-            ret[j] = tmp;
-        }
-        return ret;
-    }
-
-    vec<4,T> v0, v1, v2, v3;
-
-    static const matrix<4,4,T> identity;
-};
-
-template<typename T> T determinant(matrix<2,2,T> const &);
-template<typename T> T determinant(matrix<3,3,T> const &);
-template<typename T> T determinant(matrix<4,4,T> const &);
-
-template<typename T> matrix<2,2,T> transpose(matrix<2,2,T> const &);
-template<typename T> matrix<3,3,T> transpose(matrix<3,3,T> const &);
-template<typename T> matrix<4,4,T> transpose(matrix<4,4,T> const &);
-
-template<typename T> matrix<2,2,T> inverse(matrix<2,2,T> const &);
-template<typename T> matrix<3,3,T> inverse(matrix<3,3,T> const &);
-template<typename T> matrix<4,4,T> inverse(matrix<4,4,T> const &);
-
 #if !LOL_FEATURE_CXX11_CONSTEXPR
 #undef constexpr
 #endif
diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj
index da0ea4e6..dd1e4100 100644
--- a/src/lolcore.vcxproj
+++ b/src/lolcore.vcxproj
@@ -326,6 +326,7 @@
     <ClInclude Include="lol\math\geometry.h" />
     <ClInclude Include="lol\math\half.h" />
     <ClInclude Include="lol\math\interp.h" />
+    <ClInclude Include="lol\math\matrix.h" />
     <ClInclude Include="lol\math\rand.h" />
     <ClInclude Include="lol\math\real.h" />
     <ClInclude Include="lol\math\remez.h" />
diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters
index 988ca612..6849a1c8 100644
--- a/src/lolcore.vcxproj.filters
+++ b/src/lolcore.vcxproj.filters
@@ -438,6 +438,9 @@
     <ClInclude Include="lol\math\all.h">
       <Filter>lol\math</Filter>
     </ClInclude>
+    <ClInclude Include="lol\math\matrix.h">
+      <Filter>lol\math</Filter>
+    </ClInclude>
     <ClInclude Include="lol\math\rand.h">
       <Filter>lol\math</Filter>
     </ClInclude>