+template<typename T, unsigned S>
+SquareMatrix<T, S>::SquareMatrix(const T *d):
+ Matrix<T, S, S>(d)
+{ }
+
+template<typename T, unsigned S>
+template<typename U>
+SquareMatrix<T, S>::SquareMatrix(const Matrix<U, S, S> &m):
+ Matrix<T, S, S>(m)
+{ }
+
+template<typename T, unsigned S>
+inline SquareMatrix<T, S> SquareMatrix<T, S>::identity()
+{
+ SquareMatrix<T, S> m;
+ for(unsigned i=0; i<S; ++i)
+ m(i, i) = T(1);
+ return m;
+}
+
+template<typename T, unsigned S>
+SquareMatrix<T, S> &SquareMatrix<T, S>::operator*=(const SquareMatrix<T, S> &m)
+{
+ Matrix<T, S, S>::operator*=(m);
+ return *this;
+}
+
+template<typename T, unsigned S>
+SquareMatrix<T, S> &SquareMatrix<T, S>::invert()
+{
+ SquareMatrix<T, S> r = identity();
+ for(unsigned i=0; i<S; ++i)
+ {
+ if(this->element(i, i)==T(0))
+ {
+ unsigned pivot = i;
+ for(unsigned j=i+1; j<S; ++j)
+ if(abs(this->element(j, i))>abs(this->element(pivot, i)))
+ pivot = j;
+
+ if(pivot==i)
+ throw not_invertible();
+
+ this->exchange_rows(i, pivot);
+ r.exchange_rows(i, pivot);
+ }
+
+ for(unsigned j=i+1; j<S; ++j)
+ {
+ T a = -this->element(j, i)/this->element(i, i);
+ this->add_row(i, j, a);
+ r.add_row(i, j, a);
+ }
+
+ T a = T(1)/this->element(i, i);
+ this->multiply_row(i, a);
+ r.multiply_row(i, a);
+ }
+
+ for(unsigned i=S; i-->0; )
+ for(unsigned j=i; j-->0; )
+ r.add_row(i, j, -this->element(j, i));
+
+ return *this = r;
+}
+
+template<typename T, unsigned S>
+inline SquareMatrix<T, S> invert(const SquareMatrix<T, S> &m)
+{
+ SquareMatrix<T, S> r = m;
+ return r.invert();
+}
+