--- /dev/null
+#ifndef MSP_LIEAL_MATMIX_H_
+#define MSP_LIEAL_MATMIX_H_
+
+#include "vector.h"
+
+namespace Msp {
+namespace LinAl {
+
+/**
+A general mathematical matrix.
+*/
+template<typename T, unsigned M, unsigned N>
+class Matrix
+{
+private:
+ T data[M*N];
+
+public:
+ Matrix();
+ Matrix(const T *);
+ template<typename U>
+ Matrix(const Matrix<U, M, N> &);
+ static Matrix from_columns(const Vector<T, M> *);
+ static Matrix from_rows(const Vector<T, N> *);
+
+ T &operator()(unsigned, unsigned);
+ const T &operator()(unsigned, unsigned) const;
+
+ Matrix &operator*=(T);
+ Matrix &operator/=(T);
+ Matrix &operator+=(const Matrix &);
+ Matrix &operator-=(const Matrix &);
+
+ Matrix<T, N, M> transpose() const;
+};
+
+template<typename T, unsigned M, unsigned N>
+inline T &Matrix<T, M, N>::operator()(unsigned i, unsigned j)
+{
+ return data[i+M*j];
+}
+
+template<typename T, unsigned M, unsigned N>
+inline const T &Matrix<T, M, N>::operator()(unsigned i, unsigned j) const
+{
+ return data[i+M*j];
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> &Matrix<T, M, N>::operator*=(T s)
+{
+ for(unsigned i=0; i<M*N; ++i)
+ data[i] *= s;
+ return *this;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator*(const Matrix<T, M, N> &m, T s)
+{
+ Matrix<T, M, N> r(m);
+ return r *= s;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator*(T s, const Matrix<T, M, N> &m)
+{
+ return m*s;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> &Matrix<T, M, N>::operator/=(T s)
+{
+ for(unsigned i=0; i<M*N; ++i)
+ data[i] /= s;
+ return *this;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator/(const Matrix<T, M, N> &m, T s)
+{
+ Matrix<T, M, N> r(m);
+ return r /= s;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> &Matrix<T, M, N>::operator+=(const Matrix<T, M, N> &m)
+{
+ for(unsigned i=0; i<M*N; ++i)
+ data[i] += m.data[i];
+ return *this;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator+(const Matrix<T, M, N> &m1, const Matrix<T, M, N> &m2)
+{
+ Matrix<T, M, N> r(m1);
+ return r += m2;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> &Matrix<T, M, N>::operator-=(const Matrix<T, M, N> &m)
+{
+ for(unsigned i=0; i<M*N; ++i)
+ data[i] -= m.data[i];
+ return *this;
+}
+
+template<typename T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator-(const Matrix<T, M, N> &m1, const Matrix<T, M, N> &m2)
+{
+ Matrix<T, M, N> r(m1);
+ return r -= m2;
+}
+
+template<typename T, unsigned M, unsigned P, unsigned N>
+Matrix<T, M, N> operator*(const Matrix<T, M, P> &m1, const Matrix<T, P, N> &m2)
+{
+ Matrix<T, M, N> r;
+ for(unsigned i=0; i<M; ++i)
+ for(unsigned j=0; j<N; ++j)
+ for(unsigned k=0; k<P; ++k)
+ r.at(i, j) += m1(i, k)*m2(k, j);
+ return r;
+}
+
+template<typename T, unsigned M, unsigned N>
+Vector<T, M> operator*(const Matrix<T, M, N> &m, const Vector<T, N> &v)
+{
+ Vector<T, M> r;
+ for(unsigned i=0; i<M; ++i)
+ for(unsigned j=0; j<N; ++j)
+ r[i] += m(i, j)*v[j];
+ return r;
+}
+
+template<typename T, unsigned M, unsigned N>
+Vector<T, N> operator*(const Vector<T, M> &v, const Matrix<T, M, N> &m)
+{
+ Vector<T, N> r;
+ for(unsigned j=0; j<N; ++j)
+ for(unsigned i=0; i<M; ++i)
+ r[j] += v[i]*m.at(i, j);
+ return r;
+}
+
+} // namespace LinAl
+} // namespace Msp
+
+#endif