/* ---------------------------------------------------------------------------- * matrix.hpp * * Copyright (c) 2017 Yann Herklotz Grave -- MIT License * See file LICENSE for more details * ---------------------------------------------------------------------------- */ #ifndef YAGE_MATH_MATRIX_HPP #define YAGE_MATH_MATRIX_HPP #include #include #include #include #include #include namespace yage { template class Matrix; // includes implementation details that should not be accessible to the user namespace detail { // Row class // // Used to implement the double square bracket operator and be able // to return the value by reference of the array. template class Row { private: Matrix *parent_; int index_; public: Row(Matrix *parent, int index) : parent_(parent), index_(index) {} Type& operator[](int col) { // the index is the y-position of the element in the matrix return parent_->data_[index_*Cols+col]; } const Type& operator[](int col) const { return parent_->data_[index_*Cols+col]; } }; } // detail // Matrix class // // Implements the base Matrix class that is inherited by other classes to make them more // specific. template class Matrix { // friended with the row class so that it can access protected member data friend class detail::Row; protected: std::vector data_; public: Matrix() : data_(Rows*Cols) {} int rowSize() const { return Rows; } int colSize() const { return Cols; } // returns the row in a row matrix Matrix<1, Cols, Type> getRow(int row) const { Matrix<1, Cols, Type> rowMatrix; for(int i=0; i getCol(int col) const { Matrix colMatrix; for(int i=0; i::iterator begin() { return data_.begin(); } // iterator support for end typename std::vector::iterator end() { return data_.end(); } // prints out the matrix, but can also be implemented by other classes to print data // differently virtual std::string toString() const { std::stringstream ss; ss<<'['; for(int i=0; i operator[](int row) { return detail::Row(this, row); } detail::Row operator[](int row) const { // TODO got to fix this return detail::Row((Matrix*)this, row); } Matrix& operator=(const Matrix &other) { if(this!=&other) { data_=other.data_; } return *this; } Matrix& operator+=(const Matrix &rhs) { std::vector out; out.reserve(data_.size()); std::transform(data_.begin(), data_.end(), rhs.data_.begin(), std::back_inserter(out), [] (Type a, Type b) { return a+b; }); data_=std::move(out); return *this; } Matrix& operator-=(const Matrix &rhs) { std::vector out; out.reserve(data_.size()); std::transform(data_.begin(), data_.end(), rhs.begin(), std::back_inserter(out), [] (Type a, Type b) { return a-b; }); data_=std::move(out); return *this; } }; template Matrix operator+(Matrix lhs, const Matrix &rhs) { lhs+=rhs; return lhs; } template Matrix operator-(Matrix lhs, const Matrix &rhs) { lhs-=rhs; return lhs; } template Matrix operator+(Matrix lhs, const T &rhs) { for(auto &data : lhs) { data+=rhs; } return lhs; } template Matrix operator+(const T &lhs, Matrix rhs) { for(auto &data : rhs) { data+=lhs; } return rhs; } template Matrix operator-(Matrix lhs, const T &rhs) { for(auto &data : lhs) { data-=rhs; } return lhs; } template Matrix operator-(const T &lhs, Matrix rhs) { for(auto &data : rhs) { data=lhs-data; } return rhs; } template Matrix operator*(Matrix lhs, const T &rhs) { for(auto &data : lhs) { data*=rhs; } return lhs; } template Matrix operator*(const T &lhs, Matrix rhs) { for(auto &data : rhs) { data*=lhs; } return rhs; } template Matrix operator/(Matrix lhs, const T &rhs) { for(auto &data : lhs) { data/=rhs; } return lhs; } template bool operator==(const Matrix &lhs, const Matrix &rhs) { for(int i=0; i std::ostream& operator<<(std::ostream &os, const Matrix &mat) { return os< class Vector : public Matrix { public: Vector() : Matrix() {} explicit Vector(const Matrix &other) : Matrix(other) {} Type& operator[](int col) { return this->data_[col]; } const Type& operator[](int col) const { return this->data_[col]; } virtual std::string toString() const { std::stringstream ss; ss<<"["; for(std::size_t i=0; idata_.size()-1; ++i) { ss<data_[i]<<" "; } ss<data_[this->data_.size()-1]<<"]"; return ss.str(); } }; template class Vector2 : public Vector<2, Type> { public: Vector2() : Vector<2, Type>() {} Vector2(Type x, Type y) { this->data_[0]=x; this->data_[1]=y; } Vector2(const Matrix<2, 1, Type> &other) : Vector<2, Type>(other) {} Type& x() { return this->data_[0]; } const Type& x() const { return this->data_[0]; } Type& y() { return this->data_[1]; } const Type& y() const { return this->data_[1]; } }; typedef Vector2 Vector2d; namespace matrix { template Matrix transpose(const Matrix &m) { Matrix trans; for(int i=0; i T dot(const Matrix &m1, const Matrix &m2) { T sum=0; for(int i=0; i Matrix multiply(const Matrix &m1, const Matrix &m2) { if(N!=P) { throw std::runtime_error("Matrices don't have the right dimensions for multiplication"); } Matrix res; for(int i=0; i