#ifndef P02_MATRIX_H #define P02_MATRIX_H #include #include #include #include #include #include #define NORM_INF INT_MAX using std::size_t; template class Matrix { using self_t = Matrix; std::unique_ptr values; size_t _rows, _cols; public: explicit Matrix(size_t n); Matrix(std::initializer_list> values); Matrix(size_t n, size_t m); Matrix(const self_t& m); T& operator()(size_t n, size_t m); T operator()(size_t n, size_t m) const; self_t operator*(const self_t& rhs) const; self_t operator+(const self_t& rhs) const; self_t operator*(T rhs) const; self_t operator+(T rhs) const; self_t operator-() const; self_t operator-(const self_t& rhs) const; self_t& operator=(self_t&& rhs) noexcept; size_t rows() const; size_t cols() const; template friend std::ostream &operator<<(std::ostream &os, const Matrix &matrix); static self_t diag(size_t n, T value, int offset = 0); static self_t hvec(std::initializer_list values); static self_t vvec(std::initializer_list values); // static self_t diag(std::initializer_list values, size_t offset = 0); }; template Matrix::Matrix(size_t n, size_t m) : _rows(n), _cols(m), values(new T[m*n]) { for(size_t i = 0; i < m*n; i++) { this->values.get()[i] = T(); } } template Matrix::Matrix(size_t n) : Matrix(n, n) { } template Matrix::Matrix(const Matrix &m) : Matrix(m._rows, m._cols) { std::copy(m.values.get(), m.values.get() + m._cols*m._rows, values.get()); } template T &Matrix::operator()(size_t n, size_t m) { return values.get()[n*this->_cols + m]; } template T Matrix::operator()(size_t n, size_t m) const { return values.get()[n*this->_cols + m]; } template Matrix Matrix::operator+(const Matrix &rhs) const { assert(this->_cols == rhs._cols && this->_rows == rhs._rows); self_t result(this->_rows, this->_cols); for (size_t i = 0; i < _rows; i++) for (size_t j = 0; j < _cols; j++) result(i, j) = (*this)(i, j) + rhs(i, j); return result; } template Matrix Matrix::operator*(const Matrix &rhs) const { assert(_cols == rhs._rows); self_t result(_rows, rhs._cols); for (size_t i = 0; i < _rows; i++) { for (size_t j = 0; j < rhs._cols; j++) { T accumulator = 0; for(size_t k = 0; k < _cols; k++) accumulator += (*this)(i, k) * rhs(k, j); result(i, j) = std::move(accumulator); } } return result; } template Matrix Matrix::operator-() const { self_t result(*this); return result * -1; } template Matrix Matrix::operator-(const Matrix& rhs) const { self_t result(*this); for (size_t i = 0; i < _rows; i++) for (size_t j = 0; j < _cols; j++) result(i, j) -= rhs(i, j); return result; } template Matrix Matrix::operator*(const T rhs) const { self_t result(*this); for (size_t i = 0; i < _rows; i++) for (size_t j = 0; j < _cols; j++) result(i, j) *= rhs(i, j); return result; } template Matrix Matrix::operator+(const T rhs) const { self_t result(*this); for (size_t i = 0; i < _rows; i++) for (size_t j = 0; j < _cols; j++) result(i, j) += rhs(i, j); return result; } template std::ostream &operator<<(std::ostream &os, const Matrix &matrix) { os << "[ "; for (size_t i = 0; i < matrix._rows; i++) { for (size_t j = 0; j < matrix._cols; j++) { os << matrix(i, j) << " "; } os << (i == matrix._rows - 1 ? "]\n" : "\n "); } return os; } template Matrix Matrix::diag(size_t n, T value, int offset) { self_t result(n); if (offset >= 0) { for(size_t i = 0; i < n - offset; i++) { result(i,i+offset) = value; } } else { for(size_t i = 0; i < n + offset; i++) { result(i-offset, i) = value; } } return result; } template Matrix::Matrix(std::initializer_list> values) : Matrix(values.size(), values.begin()->size()) { size_t i = 0; for (auto h : values) { if (i > _rows) break; size_t j = 0; for (auto x : h) { if (j > _cols) break; (*this)(i, j) = x; j++; } i++; } } template Matrix& Matrix::operator=(Matrix &&rhs) noexcept { this->_cols = rhs._cols; this->_rows = rhs._rows; std::swap(values, rhs.values); return *this; } template inline size_t Matrix::rows() const { return this->_rows; } template inline size_t Matrix::cols() const { return this->_cols; } template Matrix Matrix::hvec(std::initializer_list values) { Matrix result(1, values.size()); size_t i = 0; for(auto val : values) { result(0, i++) = val; } return result; } template Matrix Matrix::vvec(std::initializer_list values) { Matrix result(values.size(), 1); size_t i = 0; for(auto val : values) { result(i++, 0) = val; } return result; } template double norm(const Matrix& matrix, unsigned norm = 2) { // needed? // assert(matrix.cols() == 1 || matrix.rows() == 1); double accumulator = 0.; for (size_t i = 0; i < matrix.cols(); ++i) { for (size_t j = 0; j < matrix.rows(); ++j) { accumulator += std::pow(matrix(j, i), norm); } } return std::pow(accumulator, 1. / norm); } #endif //P02_MATRIX_H