/*! @file @id $Id$ */ // 1 2 3 4 5 6 7 8 // 45678901234567890123456789012345678901234567890123456789012345678901234567890 #include #include #include #include template class MatrixBase { //..............................................................constants public: const size_t ROWS; const size_t COLUMNS; const size_t SIZE; const size_t MEM_SIZE; //...............................................................typedefs public: /// @name Auxiliary Classes ///{ /// Return One Row as Vector, internally used for element access /** Only used to access values: @code Matrix m; m[2][2] = 1; @endcode */ class RowVector { public: TYPE& operator[](size_t column) { assert(column<_m.COLUMNS); return _v[column]; } protected: friend class MatrixBase; RowVector() = delete; // forbidden RowVector(const MatrixBase& m, TYPE c[]): _m(m), _v(c) {} const MatrixBase& _m; TYPE *_v; }; /// Same as RowVector, but in a constant environment. class ConstRowVector { public: const TYPE& operator[](size_t column) const { assert(column<_m.COLUMNS); return _v[column]; } protected: friend class MatrixBase; ConstRowVector() = delete; // forbidden ConstRowVector(const MatrixBase& m, const TYPE c[]): _m(m), _v(c) {} const MatrixBase& _m; const TYPE *_v; }; ///} //................................................................methods public: /// @name construction ///{ MatrixBase(size_t rows, size_t columns): ROWS(rows), COLUMNS(columns), SIZE(ROWS*COLUMNS), MEM_SIZE(SIZE*sizeof(TYPE)) { } template MatrixBase(size_t rows, size_t columns, ARGS...t): ROWS(rows), COLUMNS(columns), SIZE(ROWS*COLUMNS), MEM_SIZE(SIZE*sizeof(TYPE)), _c{std::forward(t)...} { } ///} /// @name element access ///{ TYPE& at(size_t row, size_t column) { assert(row(TYPE*)(_c)) if (*--to != *--from) return false; return true; } bool operator!=(const MatrixBase& o) const { return !operator==(o); } MatrixBase& operator+=(const MatrixBase& o) { assert_check(o); TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); while (to>(TYPE*)(_c)) *--to += *--from; return *this; } MatrixBase& operator-=(const MatrixBase& o) { assert_check(o); TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); while (to>(TYPE*)(_c)) *--to -= *--from; return *this; } MatrixBase& operator*=(const TYPE& o) { TYPE *res((TYPE*)(_c)+SIZE); while (res>(TYPE*)(_c)) *--res *= o; return *this; } MatrixBase& operator/=(const TYPE& o) { TYPE *res((TYPE*)(_c)+SIZE); while (res>(TYPE*)(_c)) *--res /= o; return *this; } ///} /// @name special operations ///{ TYPE det() { // rule of sarrus TYPE res(0); assert(ROWS==COLUMNS); // not really necessary // 1) terms to add for (size_t i(0); i class Matrix: public MatrixBase { //...............................................................typedefs private: typedef MatrixBase Parent; //................................................................methods public: /// @name construction ///{ Matrix(): Parent(TROWS, TCOLUMNS) { memset(Parent::_c, 0, Parent::MEM_SIZE); } Matrix(const Matrix& o): Matrix() { memcpy(Parent::_c, o._c, Parent::MEM_SIZE); } template Matrix(ARGS...t): Parent(TROWS, TCOLUMNS, t...) { static_assert(sizeof...(t)==TROWS*TCOLUMNS, "wrong array size"); } ///} /// @name operators ///{ Matrix& operator=(TYPE oc[TROWS][TCOLUMNS]) { memcpy(Parent::_c, oc, Parent::MEM_SIZE); return *this; } Matrix operator-() const { Matrix res; for (TYPE *to((TYPE*)(res._c)+Parent::SIZE); to>(TYPE*)(Parent::_c); --to) *to = -*to; return res; } template Matrix operator*(const Matrix& o) const { Matrix res; for (size_t i(0); iat(i, j) * o(j, k); return res; } ///} /// @name special operations ///{ Matrix t() const { Matrix res; for (size_t row(0); rowat(row, column); return res; } ///} }; //============================================================================== template class Matrix: public MatrixBase { //...............................................................typedefs private: typedef MatrixBase Parent; //................................................................methods public: /// @name construction ///{ Matrix() = delete; Matrix(size_t rows, size_t columns): Parent(rows, columns) { Parent::_c = new TYPE[rows*columns]; memset(Parent::_c, 0, Parent::MEM_SIZE); } Matrix(const Matrix& o): Matrix(o.ROWS, o.Parent::COLUMNS) { memcpy(Parent::_c, o.Parent::_c, Parent::MEM_SIZE); } template Matrix(size_t rows, size_t columns, ARGS...t): Matrix(rows, columns) { assert(sizeof...(t)==Parent::SIZE); copy_args(Parent::_c, t...); } ///} /// @name destruction ///{ virtual ~Matrix() { delete[] Parent::_c; } ///} /// @name operators ///{ Matrix& operator=(const Matrix& o) { if (o.ROWS!=Parent::ROWS&&o.COLUMNS!=Parent::COLUMNS) { delete[] Parent::_c; Parent::ROWS = o.ROWS; Parent::COLUMNS = o.COLUMNS; Parent::SIZE = o.SIZE; Parent::MEM_SIZE = o.MEM_SIZE; Parent::_c = new TYPE[Parent::SIZE]; } return Parent::operator=(o); } Matrix t() const { Matrix res(Parent::COLUMNS, Parent::ROWS); for (size_t row(0); rowat(row, column); return res; } Matrix operator-() const { Matrix res(Parent::COLUMNS, Parent::ROWS); for (TYPE *to((TYPE*)(res._c)+Parent::SIZE); to>(TYPE*)(Parent::_c); --to) *to = -*to; return res; } Matrix operator*(const Matrix& o) const { Matrix res(this->ROWS, o.COLUMNS); assert(this->COLUMNS==o.ROWS); for (size_t i(0); iROWS; ++i) for (size_t k(0); kCOLUMNS; ++j) res(i, k) += this->at(i, j) * o(j, k); return res; } ///} //................................................................methods protected: virtual void assert_check(const Matrix& o) const { assert(o.ROWS==Parent::ROWS); assert(o.COLUMNS==Parent::COLUMNS); } virtual bool check(const Matrix& o) const { return o.ROWS==Parent::ROWS && o.COLUMNS==Parent::COLUMNS; } void copy_args(TYPE*) {} template void copy_args(TYPE* to, TYPE t1, ARGS...t) { *to = t1; copy_args(++to, t...); } }; //============================================================================== template Matrix operator+(const Matrix& a, const Matrix& b) { Matrix res(a); res += b; return res; } template Matrix operator-(const Matrix& a, const Matrix& b) { Matrix res(a); res -= b; return res; } template Matrix operator*(const TYPE& v, const Matrix& m) { Matrix res(m); res *= v; return res; } template Matrix operator*(const Matrix& m, const TYPE& v) { Matrix res(m); res *= v; return res; } template std::ostream& operator<<(std::ostream& s, const Matrix& m) { for (size_t w = 0; w < m.ROWS; ++w) { for (size_t h = 0; h < m.COLUMNS;++h) { s<