]> git.tdb.fi Git - libs/math.git/blobdiff - source/linal/dynamicmatrix.h
Add dynamically allocated versions of matrix and vector
[libs/math.git] / source / linal / dynamicmatrix.h
diff --git a/source/linal/dynamicmatrix.h b/source/linal/dynamicmatrix.h
new file mode 100644 (file)
index 0000000..3852424
--- /dev/null
@@ -0,0 +1,323 @@
+#ifndef MSP_LINAL_DYNAMICMATRIX_H_
+#define MSP_LINAL_DYNAMICMATRIX_H_
+
+#include <algorithm>
+#include "dynamicvector.h"
+#include "matrixops.h"
+
+namespace Msp {
+namespace LinAl {
+
+/**
+A general mathematical matrix.  Size is specified at runtime.  May be slower
+than a fixed-size matrix.  There are no compile-time diagnostics for mismatched
+matrix sizes.
+*/
+template<typename T>
+class DynamicMatrix
+{
+public:
+       typedef T ElementType;
+
+private:
+       unsigned rows_;
+       unsigned columns_;
+       T *data;
+
+public:
+       DynamicMatrix(unsigned, unsigned);
+       DynamicMatrix(unsigned, unsigned, const T *);
+       DynamicMatrix(const DynamicMatrix &);
+       DynamicMatrix &operator=(const DynamicMatrix &);
+       ~DynamicMatrix();
+
+       unsigned rows() const { return rows_; }
+       unsigned columns() const { return columns_; }
+
+       T &element(unsigned, unsigned);
+       const T &element(unsigned, unsigned) const;
+       T &operator()(unsigned i, unsigned j) { return element(i, j); }
+       const T &operator()(unsigned i, unsigned j) const { return element(i, j); }
+
+       DynamicMatrix &operator*=(T);
+       DynamicMatrix &operator/=(T);
+       DynamicMatrix &operator+=(const DynamicMatrix &);
+       DynamicMatrix &operator-=(const DynamicMatrix &);
+
+       DynamicMatrix &exchange_rows(unsigned, unsigned);
+       DynamicMatrix &multiply_row(unsigned, T);
+       DynamicMatrix &add_row(unsigned, unsigned, T);
+
+       DynamicMatrix &invert();
+};
+
+
+template<typename T>
+inline DynamicMatrix<T>::DynamicMatrix(unsigned r, unsigned c):
+       rows_(r),
+       columns_(c),
+       data(new T[rows_*columns_])
+{
+       std::fill(data, data+rows_*columns_, T());
+}
+
+template<typename T>
+inline DynamicMatrix<T>::DynamicMatrix(unsigned r, unsigned c, const T *d):
+       rows_(r),
+       columns_(c),
+       data(new T[rows_*columns_])
+{
+       std::copy(d, d+rows_*columns_, data);
+}
+
+template<typename T>
+inline DynamicMatrix<T>::DynamicMatrix(const DynamicMatrix &other):
+       rows_(other.rows()),
+       columns_(other.columns()),
+       data(new T[rows_*columns_])
+{
+       std::copy(other.data, other.data+rows_*columns_, data);
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::operator=(const DynamicMatrix &other)
+{
+       if(rows_!=other.rows() || columns_!=other.columns())
+       {
+               delete[] data;
+               rows_ = other.rows();
+               columns_ = other.columns();
+               data = new T[rows_*columns_];
+       }
+
+       std::copy(other.data, other.data+rows_*columns_, data);
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T>::~DynamicMatrix()
+{
+       delete[] data;
+}
+
+template<typename T>
+inline T &DynamicMatrix<T>::element(unsigned i, unsigned j)
+{
+       if(i>=rows_ || j>=columns_)
+               throw std::out_of_range("DynamicMatrix::element");
+
+       return data[i+rows_*j];
+}
+
+template<typename T>
+inline const T &DynamicMatrix<T>::element(unsigned i, unsigned j) const
+{
+       if(i>=rows_ || j>=columns_)
+               throw std::out_of_range("DynamicMatrix::element");
+
+       return data[i+rows_*j];
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::operator*=(T s)
+{
+       for(unsigned i=0; i<rows_*columns_; ++i)
+               data[i] *= s;
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T> operator*(const DynamicMatrix<T> &m, T s)
+{
+       DynamicMatrix<T> r(m);
+       return r *= s;
+}
+
+template<typename T>
+inline DynamicMatrix<T> operator*(T s, const DynamicMatrix<T> &m)
+{
+       return m*s;
+}
+
+template<typename T>
+inline DynamicMatrix<T> operator*(const DynamicMatrix<T> &m1, const DynamicMatrix<T> &m2)
+{
+       if(m1.columns()!=m2.rows())
+               throw size_mismatch("matrix*matrix");
+
+       DynamicMatrix<T> r(m1.rows(), m2.columns());
+       for(unsigned i=0; i<m1.rows(); ++i)
+               for(unsigned j=0; j<m2.columns(); ++j)
+                       for(unsigned k=0; k<m1.columns(); ++k)
+                               r(i, j) += m1(i, k)*m2(k, j);
+
+       return r;
+}
+
+template<typename T>
+inline DynamicVector<T> operator*(const DynamicMatrix<T> &m, const DynamicVector<T> &v)
+{
+       if(m.columns()!=v.size())
+               throw size_mismatch("matrix*vector");
+
+       DynamicVector<T> r(m.rows());
+       for(unsigned i=0; i<m.rows(); ++i)
+               for(unsigned j=0; j<m.columns(); ++j)
+                       r[i] += m(i, j)*v[j];
+
+       return r;
+}
+
+template<typename T>
+inline DynamicVector<T> operator*(const DynamicVector<T> &v, const DynamicMatrix<T> &m)
+{
+       if(v.size()!=m.rows())
+               throw size_mismatch("vector*matrix");
+
+       DynamicVector<T> r(m.columns());
+       for(unsigned j=0; j<m.columns(); ++j)
+               for(unsigned i=0; i<m.rows(); ++i)
+                       r[i] += v[i]*m(i, j);
+
+       return r;
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::operator/=(T s)
+{
+       for(unsigned i=0; i<rows_*columns_; ++i)
+               data[i] /= s;
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T> operator/(const DynamicMatrix<T> &m, T s)
+{
+       DynamicMatrix<T> r(m);
+       return r /= s;
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::operator+=(const DynamicMatrix<T> &m)
+{
+       if(rows_!=m.rows_ || columns_!=m.columns_)
+               throw size_mismatch("matrix+matrix");
+
+       for(unsigned i=0; i<rows_*columns_; ++i)
+               data[i] += m.data[i];
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T> operator+(const DynamicMatrix<T> &m1, const DynamicMatrix<T> &m2)
+{
+       DynamicMatrix<T> r(m1);
+       return r += m2;
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::operator-=(const DynamicMatrix<T> &m)
+{
+       if(rows_!=m.rows_ || columns_!=m.columns_)
+               throw size_mismatch("matrix-matrix");
+
+       for(unsigned i=0; i<rows_*columns_; ++i)
+               data[i] += m.data[i];
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T> operator-(const DynamicMatrix<T> &m1, const DynamicMatrix<T> &m2)
+{
+       DynamicMatrix<T> r(m1);
+       return r += m2;
+}
+
+template<typename T>
+inline bool operator==(const DynamicMatrix<T> &m1, const DynamicMatrix<T> &m2)
+{
+       if(m1.rows()!=m2.rows() || m1.columns()!=m2.columns())
+               throw size_mismatch("matrix==matrix");
+
+       for(unsigned i=0; i<m1.rows(); ++i)
+               for(unsigned j=0; j<m1.columns(); ++j)
+                       if(m1(i, j)!=m2(i, j))
+                               return false;
+
+       return true;
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::exchange_rows(unsigned i, unsigned j)
+{
+       if(i>=rows_ || j>=rows_)
+               throw std::out_of_range("DynamicMatrix::exchange_rows");
+
+       using std::swap;
+       for(unsigned k=0; k<columns_; ++k)
+               swap(element(i, k), element(j, k));
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::multiply_row(unsigned i, T s)
+{
+       if(i>=rows_)
+               throw std::out_of_range("DynamicMatrix::multiply_row");
+
+       for(unsigned k=0; k<columns_; ++k)
+               element(i, k) *= s;
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::add_row(unsigned i, unsigned j, T s)
+{
+       if(i>=rows_ || j>=rows_)
+               throw std::out_of_range("DynamicMatrix::exchange_rows");
+
+       for(unsigned k=0; k<columns_; ++k)
+               element(j, k) += element(i, k)*s;
+
+       return *this;
+}
+
+template<typename T>
+inline DynamicMatrix<T> transpose(const DynamicMatrix<T> &m)
+{
+       DynamicMatrix<T> r(m.columns(), m.rows());
+       for(unsigned i=0; i<m.rows(); ++i)
+               for(unsigned j=0; j<m.columns(); ++j)
+                       r(j, i) = m(i, j);
+       return r;
+}
+
+template<typename T>
+inline DynamicMatrix<T> &DynamicMatrix<T>::invert()
+{
+       if(rows_!=columns_)
+               throw size_mismatch("matrix invert");
+
+       DynamicMatrix<T> r(rows_, columns_);
+       for(unsigned i=0; i<rows_; ++i)
+               r(i, i) = T(1);
+
+       return invert_matrix(*this, r);
+}
+
+template<typename T>
+inline DynamicMatrix<T> invert(const DynamicMatrix<T> &m)
+{
+       DynamicMatrix<T> r = m;
+       return r.invert();
+}
+
+} // namespace LinAl
+} // namespace Msp
+
+#endif