#pragma once #include #include #include template class MatrixView; template class Matrix { public: Matrix(size_t nrow, size_t ncol) : _nrow{nrow}, _ncol{ncol} { _elem.reserve(nrow * ncol); }; size_t nrow() const { return _nrow; }; size_t ncol() const { return _ncol; }; size_t size() const { return _nrow * _ncol; }; T& operator()(int i) { return _elem[index(i)]; }; const T& operator()(int i) const { return _elem[index(i)]; }; T& operator()(int i, int j) { return _elem[index(i, j)]; }; const T& operator()(int i, int j) const { return _elem[index(i, j)]; }; private: size_t _nrow; size_t _ncol; std::vector _elem; size_t index(int i) const { int nelem = static_cast(_nrow * _ncol); while (i < 0) { i += nelem; } while (i >= nelem) { i -= nelem; } return i; }; size_t index(int i, int j) const { int nrow = static_cast(_nrow); int ncol = static_cast(_ncol); while (i < 0) { i += nrow; } while (i >= nrow) { i -= nrow; } while (j < 0) { j += ncol; } while (j >= ncol) { j -= ncol; } return static_cast(i + j * _nrow); }; }; template std::ostream& operator<<(std::ostream& out, const Matrix& mat) { for (size_t i = 0; i < mat.nrow(); ++i) { for (size_t j = 0; j < mat.ncol(); ++j) { out << mat(i, j) << ' '; } out << '\n'; } return out; } template class MatrixView { public: MatrixView(Matrix& matrix, size_t index, size_t stride, size_t nelem) : _matrix(matrix), _index{index}, _stride{stride}, _nelem{nelem} { }; const size_t size() const { return _nelem; }; T& operator()(int i) { return _matrix(_index + i * _stride); }; const T& operator()(int i) const { return _matrix(_index + i * _stride); }; protected: Matrix& _matrix; size_t _index; size_t _stride; size_t _nelem; }; template std::ostream& operator<<(std::ostream& out, const MatrixView& view) { for (size_t i = 0; i < view.size(); ++i) { out << view(i) << ' '; } return out; } template class Row : public MatrixView { public: Row(Matrix& matrix, size_t index) : MatrixView(matrix, index * matrix.ncol(), 1, matrix.nrow()) { }; }; template class Col : public MatrixView { public: Col(Matrix& matrix, size_t index) : MatrixView(matrix, index, matrix.nrow(), matrix.ncol()) { }; }; template class Diag : public MatrixView { public: Diag(Matrix& matrix) : MatrixView(matrix, 0, matrix.nrow() + 1, matrix.nrow() < matrix.ncol() ? matrix.nrow() : matrix.ncol()) { }; };