matrix.h
#ifndef __SW_MATRIX_H__ #define __SW_MATRIX_H__ /* #include <iostream> //#include <iomanip> #include <vector> */ // uncomment to disable assert() // #define NDEBUG #include <cassert> namespace SW { template <typename T> class Matrix { private: std::vector<std::vector<T> > data; mutable unsigned rows; mutable unsigned cols; public: Matrix(); Matrix(unsigned _rows, unsigned _cols); Matrix(unsigned _rows, unsigned _cols, const T& _initial); //Matrix(T&&... elements); /* template<typename ...E> //Matrix(T element, E&&... elements); Matrix(E&&... elements); //Matrix(unsigned _rows, unsigned _cols, T element, E&&... elements); */ /** * Constructs a Matrix whose elements are initialized with the provided values * * @param element the first value * * @param elements all subsequent values * * <pre>Matrix<int, 3, 3> matrix(1, 2, 3, 1, 2, 3, 1, 2 ,3);</pre> * */ //template<typename ...E> //Matrix(unsigned _rows, unsigned _cols, T element, E&&... elements); Matrix(const Matrix<T>& rhs); virtual ~Matrix(); //~Matrix(); /* template<typename T, std::size_t X, std::size_t Y> bool operator==(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept; template<typename T, std::size_t X, std::size_t Y> bool operator!=(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept; template<typename T, std::size_t X, std::size_t Y> std::ostream& operator<<(std::ostream& stream, const Matrix<T, X, Y>& matrix); template<typename T, std::size_t X, std::size_t Y> std::istream& operator>>(std::istream& stream, Matrix<T, X, Y>& matrix); */ /// Privileged free-functions /* friend std::ostream& operator<<<>(std::ostream&, const Matrix<T, Rows, Columns>&); friend std::istream& operator>><>(std::istream&, const Matrix<T, Rows, Columns>&); friend bool operator!=<>(const Matrix<T>& lhs, const Matrix<T>&); friend bool operator==<>(const Matrix<T>& lhs, const Matrix<T>& rhs); */ //Matrix<T>& operator==<>(const Matrix<T>& lhs, const Matrix<T>& rhs); //bool operator==(const Matrix<T>& lhs, const Matrix<T>& rhs); //Matrix<T>& operator==(Matrix<T>& rhs); //bool operator==(Matrix<T>& rhs); // Operator overloading, for "standard" mathematical matrix operations. Matrix<T>& operator=(const Matrix<T>& rhs); // Operator overloading, for comparitive operations. bool operator==(const Matrix<T>& rhs) const; bool operator!=(const Matrix<T>& rhs) const; bool operator<(const Matrix<T>& rhs) const; bool operator<=(const Matrix<T>& rhs) const; bool operator>(const Matrix<T>& rhs) const; bool operator>=(const Matrix<T>& rhs) const; // Arithmetic operators. Matrix<T> operator - () const; // negate operator Matrix<T> operator ++ (); // prefix increment operator Matrix<T> operator ++ (int); // postfix increment operator Matrix<T> operator -- (); // prefix decrement operator Matrix<T> operator -- (int); // postfix decrement operator // Matrix mathematical operations. Matrix<T> operator+(const Matrix<T>& rhs); Matrix<T>& operator+=(const Matrix<T>& rhs); Matrix<T> operator-(const Matrix<T>& rhs); Matrix<T>& operator-=(const Matrix<T>& rhs); Matrix<T> operator*(const Matrix<T>& rhs); Matrix<T>& operator*=(const Matrix<T>& rhs); Matrix<T> operator%(const Matrix<T>& rhs); Matrix<T>& operator%=(const Matrix<T>& rhs); Matrix<T> operator^(const Matrix<T>& rhs); Matrix<T>& operator^=(const Matrix<T>& rhs); //Matrix operator ^ (const Matrix<T>& rhs, const int power); //Matrix<T> operator^(const int power); Matrix<T>& operator^=(const int power); Matrix<T> abs(); void print(); Matrix<T> sqrt(); //sequence_generator Matrix<T> transpose(); // Matrix/scalar operations. Matrix<T> operator+(const T& rhs); Matrix<T> operator-(const T& rhs); Matrix<T> operator*(const T& rhs); Matrix<T> operator/(const T& rhs); // Matrix/vector operations. std::vector<T> operator*(const std::vector<T>& rhs); std::vector<T> diag_vec(); // Access the individual elements. T& operator()(const unsigned& row, const unsigned& col); const T& operator()(const unsigned& row, const unsigned& col) const; // Access the row and column sizes. unsigned get_rows() const; unsigned get_cols() const; // vector operations Matrix<T> get_row(unsigned r) const; Matrix<T> get_col(unsigned c) const; Matrix<T>& set_col(unsigned c, const Matrix<T>& C); Matrix<T>& set_row(unsigned r, const Matrix<T>& R); Matrix<T> delete_row(unsigned r) const; Matrix<T> delete_col(unsigned c) const; bool swap_rows(unsigned i, unsigned j); /**/ // I/O stream functions. template<typename T> friend std::ostream & operator<<(std::ostream &, const Matrix<T>&); template<typename T> friend std::istream& operator>>(std::istream&, const Matrix<T>&); }; /* template<class T> ostream& operator<<(ostream& o, const Matrix<T>& M) { o << endl; for (int i = 0; i<M.rows; i++) { o << "[ "; for (int j = 0; j<M.cols; j++) o << M(i, j) << " "; o << "]" << endl; } o << endl; return o; } */ // Basic Constructor. template<typename T> Matrix<T>::Matrix() { rows = 0; cols = 0; } // Parameter Constructor. template<typename T> Matrix<T>::Matrix(unsigned _rows, unsigned _cols) { data.resize(_rows); for (unsigned i = 0; i<data.size(); i++) { data[i].resize(_cols, 0); } rows = _rows; cols = _cols; } // Parameter Constructor. template<typename T> Matrix<T>::Matrix(unsigned _rows, unsigned _cols, const T& _initial) { data.resize(_rows); for (unsigned i = 0; i<data.size(); i++) { data[i].resize(_cols, _initial); } rows = _rows; cols = _cols; } //template<typename T, unsigned _rows, unsigned cols> //template<typename ...E> //Matrix<T, Rows, Columns>::Matrix(T first, E&&... elements) noexcept : values{ { first, std::forward<T>(static_cast<T>(elements))... } } /* template<typename T> template<typename ...E> //Matrix<T>::Matrix(T first, E&&... elements) noexcept : values{ { first, std::forward<T>(static_cast<T>(elements))... } } //Matrix<T>::Matrix(T first, E&&... elements) : data{ { first, std::forward<T>(static_cast<T>(elements))... } } Matrix<T>::Matrix(E&&... elements) : data{ { std::forward<T>(static_cast<T>(elements))... } } { data.push_back() } */ /* template<typename T> template<typename ...E> //Matrix<T>::Matrix(unsigned _rows, unsigned _cols, T first, E&&... elements) : mat{ { first, std::forward<T>(static_cast<T>(elements))... } } //Matrix<T>::Matrix(unsigned _rows, unsigned _cols, T first, E&&... elements) : mat{ { first, std::forward<T>(static_cast<T>(elements))... } } Matrix<T>::Matrix(unsigned _rows, unsigned _cols, T first, E&&... elements) : mat{ { first, std::forward<T>(static_cast<T>(elements))... } } { data.resize(_rows); for (unsigned i = 0; i<data.size(); i++) { data[i].resize(_cols, 0); } rows = _rows; cols = _cols; } */ /* Matrix<T>::Matrix(T&&... elements) { std::forward<T>(static_cast<T>(elements))...; } */ // Copy Constructor. template<typename T> Matrix<T>::Matrix(const Matrix<T>& rhs) { data = rhs.data; rows = rhs.get_rows(); cols = rhs.get_cols(); } // (Virtual) Destructor. template<typename T> Matrix<T>::~Matrix() { } // Assignment Operator. template<typename T> Matrix<T>& Matrix<T>::operator=(const Matrix<T>& rhs) { if (&rhs == this) return *this; unsigned new_rows = rhs.get_rows(); unsigned new_cols = rhs.get_cols(); data.resize(new_rows); for (unsigned i = 0; i<data.size(); i++) { data[i].resize(new_cols); } for (unsigned i = 0; i<new_rows; i++) { for (unsigned j = 0; j<new_cols; j++) { data[i][j] = rhs(i, j); } } rows = new_rows; cols = new_cols; return *this; } // Comparison Operator ==. template<typename T> bool Matrix<T>::operator==(const Matrix<T>& rhs) const { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); if (get_rows() != rows) return false; if (get_cols() != cols) return false; for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { if (this->data[i][j] != rhs(i, j)) return false; } } return true; } // Comparison Operator !=. template<typename T> bool Matrix<T>::operator!=(const Matrix<T>& rhs) const { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); if (get_rows() != rows) return true; if (get_cols() != cols) return true; for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { if (this->data[i][j] == rhs(i, j)) return false; } } return false; } // Comparison Operator <. template<typename T> bool Matrix<T>::operator<(const Matrix<T>& rhs) const { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); if (get_rows() != rows) return false; if (get_cols() != cols) return false; for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { if (this->data[i][j] >= rhs(i, j)) return false; } } return true; } // Comparison Operator <=. template<typename T> bool Matrix<T>::operator<=(const Matrix<T>& rhs) const { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); if (get_rows() != rows) return false; if (get_cols() != cols) return false; for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { if (this->data[i][j] > rhs(i, j)) return false; } } return true; } // Comparison Operator <. template<typename T> bool Matrix<T>::operator>(const Matrix<T>& rhs) const { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); if (get_rows() != rows) return false; if (get_cols() != cols) return false; for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { if (this->data[i][j] <= rhs(i, j)) return false; } } return true; } // Comparison Operator >=. template<typename T> bool Matrix<T>::operator>=(const Matrix<T>& rhs) const { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); if (get_rows() != rows) return false; if (get_cols() != cols) return false; for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { if (this->data[i][j] < rhs(i, j)) return false; } } return true; } // Unary - operator template<typename T> Matrix<T> Matrix<T>::operator -() const { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = -this->data[i][j]; } } return result; } // Prefix increment operator template<typename T> Matrix<T> Matrix<T>::operator ++ () { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] + 1; } } return *this = result; } // Postfix increment operator template<typename T> Matrix<T> Matrix<T>::operator ++ (int) { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] + 1; } } return result; } // Prefix decrement operator template<typename T> Matrix<T> Matrix<T>::operator -- () { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] - 1; } } return *this = result; } // Postfix decrement operator template<typename T> Matrix<T> Matrix<T>::operator -- (int) { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] - 1; } } return result; } // Addition of two matrices. template<typename T> Matrix<T> Matrix<T>::operator+(const Matrix<T>& rhs) { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] + rhs(i, j); } } return result; } // Cumulative addition of this matrix and another. template<typename T> Matrix<T>& Matrix<T>::operator+=(const Matrix<T>& rhs) { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { this->data[i][j] += rhs(i, j); } } return *this; } // Subtraction of this matrix and another. template<typename T> Matrix<T> Matrix<T>::operator-(const Matrix<T>& rhs) { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] - rhs(i, j); } } return result; } // Cumulative subtraction of this matrix and another. template<typename T> Matrix<T>& Matrix<T>::operator-=(const Matrix<T>& rhs) { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { this->data[i][j] -= rhs(i, j); } } return *this; } // Left multiplication of this matrix and another. template<typename T> Matrix<T> Matrix<T>::operator*(const Matrix<T>& rhs) { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { for (unsigned k = 0; k<rows; k++) { result(i, j) += this->data[i][k] * rhs(k, j); } } } return result; } // Cumulative left multiplication of this matrix and another. template<typename T> Matrix<T>& Matrix<T>::operator*=(const Matrix<T>& rhs) { Matrix result = (*this) * rhs; (*this) = result; return *this; } //************************************************************************************************ // Left mod of this matrix and another. template<typename T> Matrix<T> Matrix<T>::operator%(const Matrix<T>& rhs) { unsigned rows = rhs.get_rows(); unsigned cols = rhs.get_cols(); Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { for (unsigned k = 0; k<rows; k++) { result(i, j) += this->data[i][k] % rhs(k, j); } } } return result; } // Cumulative left mod of this matrix and another. template<typename T> Matrix<T>& Matrix<T>::operator%=(const Matrix<T>& rhs) { Matrix result = (*this) % rhs; (*this) = result; return *this; } // Left raise of this matrix and another. template<typename T> Matrix<T> Matrix<T>::operator^(const Matrix<T>& rhs) { // unsigned rows = rhs.get_rows(); // unsigned cols = rhs.get_cols(); Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { for (unsigned k = 0; k<rows; k++) { result(i, j) += this->data[i][k] ^ rhs(k, j); } } } return result; } // Cumulative left raise of this matrix and another. template<typename T> Matrix<T>& Matrix<T>::operator^=(const Matrix<T>& rhs) { Matrix result = (*this) % rhs; (*this) = result; return *this; } /* template<typename T> //Matrix<T> Matrix<T>::operator^(const Matrix<T>& rhs, const int power) Matrix<T> Matrix<T>::operator^(const int power) { std::cout << "Z" << std::endl; //unsigned rows = rhs.get_rows(); //unsigned cols = rhs.get_cols(); Matrix result(rows, cols, 0.0); //result = rhs; for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { T temp = this->data[i][j]; std::cout << "T=" << std::endl; //T temp = 2; //T temp = rhs[i][j]; // not <= below \/ because first time counts as 2 for (int k = 2; k<=power; k++) //result(i, j) += this->data[i][j] * this->data[i][j]; result(i, j) = result(i, j) * temp; } } return result; } */ // Left raise of this matrix and another. template<typename T> Matrix<T>& Matrix<T>::operator^=(const int power) { Matrix result = (*this); unsigned rows = result.get_rows(); unsigned cols = result.get_cols(); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { T temp = this->data[i][j]; // not <= below \/ because first time counts as 2 for (int k = 2; k <= power; k++) result(i, j) = result(i, j) * temp; } } //(*this) = result; *this = result; return *this; } //********************************************************************************************* // Converts all values to their absolute value within the matrix. template<typename T> Matrix<T> Matrix<T>::abs() { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = std::math::abs(this->data[i][j]); } } return result; } template<typename T> void Matrix<T>::print() { for (unsigned int i = 0; i < rows; i++) { for (unsigned int j = 0; j<cols; j++) { std::cout << data[i][j] << ", "; } std::cout << std::endl; } std::cout << std::endl; } // Concerts all values to their square roots within the matrix. template<typename T> Matrix<T> Matrix<T>::sqrt() { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = std::math::sqrt(this->data[j][i]); } } return result; } // Calculate a transpose of this matrix. template<typename T> Matrix<T> Matrix<T>::transpose() { Matrix result(cols, rows, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[j][i]; } } return result; } // Matrix/scalar addition. template<typename T> Matrix<T> Matrix<T>::operator+(const T& rhs) { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] + rhs; } } return result; } // Matrix/scalar subtraction. template<typename T> Matrix<T> Matrix<T>::operator-(const T& rhs) { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] - rhs; } } return result; } // Matrix/scalar multiplication. template<typename T> Matrix<T> Matrix<T>::operator*(const T& rhs) { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] * rhs; } } return result; } // Matrix/scalar division. template<typename T> Matrix<T> Matrix<T>::operator/(const T& rhs) { Matrix result(rows, cols, 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result(i, j) = this->data[i][j] / rhs; } } return result; } // Multiply a matrix with a vector. template<typename T> std::vector<T> Matrix<T>::operator*(const std::vector<T>& rhs) { std::vector<T> result(rhs.size(), 0.0); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { result[i] = this->data[i][j] * rhs[j]; } } return result; } // Obtain a vector of the diagonal elements. template<typename T> std::vector<T> Matrix<T>::diag_vec() { std::vector<T> result(rows, 0.0); for (unsigned i = 0; i<rows; i++) { result[i] = this->data[i][i]; } return result; } // Access the individual elements. template<typename T> T& Matrix<T>::operator()(const unsigned& row, const unsigned& col) { assert(row >= 0); assert(col >= 0); assert(row < rows); assert(col < cols); return this->data[row][col]; } // Access the individual elements (const). template<typename T> const T& Matrix<T>::operator()(const unsigned& row, const unsigned& col) const { assert(row >= 0); assert(col >= 0); assert(row < rows); assert(col < cols); return this->data[row][col]; } // Get the number of rows of the matrix. template<typename T> unsigned Matrix<T>::get_rows() const { return this->rows; } // Get the number of columns of the matrix. template<typename T> unsigned Matrix<T>::get_cols() const { return this->cols; } // Returns a row. template<typename T> Matrix<T> Matrix<T>::get_row(unsigned r) const { Matrix<T> result(1, cols, 0.0); for (unsigned i = 0; i<cols; i++) { result[i] = this->data[r][i]; } return result; } template<typename T> Matrix<T> Matrix<T>::get_col(unsigned c) const { Matrix<T> result(rows, 1, 0.0); for (unsigned i = 0; i<rows; i++) { result[i] = this->data[i][c]; } return result; } template<typename T> Matrix<T>& Matrix<T>::set_col(unsigned c, const Matrix<T>& C) { } template<typename T> Matrix<T>& Matrix<T>::set_row(unsigned r, const Matrix<T>& R) { } template<typename T> Matrix<T> Matrix<T>::delete_row(unsigned r) const { } template<typename T> Matrix<T> Matrix<T>::delete_col(unsigned c) const { } // swap_rows() uses a row's worth of memory for better run-time performance // if you want pairwise swap, just write it yourself template<typename T> bool Matrix<T>::swap_rows(unsigned i, unsigned j) { if (i == j) return; /* Matrix<T,1> temp = (*this)[i]; (*this)[i] = (*this)[j]; (*this)[j] = temp; */ unsigned max = (*this)[i].size(); for (unsigned ii = 0; ii<max; ++ii) std::swap((*this)(i, ii), (*this)(j, ii)); return true; } template<typename T> std::ostream & operator << (std::ostream &s, const Matrix<T>& m) { unsigned rows = m.get_rows(); unsigned cols = m.get_cols(); for (unsigned i = 0; i<rows; i++) { for (unsigned j = 0; j<cols; j++) { s << m(i, j); if ((i*j) < (((rows - 1)*(cols - 1)) - 1)) s << ", "; } s << std::endl; } return s; } template<typename T> std::istream & operator >> (std::istream &s, Matrix<T>& m) { /* std::string temp(10000, ' '); s >> temp; v = Verylong(temp); */ return s; } } // end namespace SW. #endif