|  |  |  | @@ -55,6 +55,27 @@ std::string to_string(std::complex<T> value) | 
		
	
		
			
				|  |  |  |  |     return sstr.str(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Poly::Matrix<T,M> real(const Poly::Matrix<std::complex<T>,M>& mat) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Poly::Matrix<T,M> result(mat.rows(),mat.columns()); | 
		
	
		
			
				|  |  |  |  |     std::transform(mat.begin(),mat.end(),result.begin(),[](const std::complex<T>& elem) -> T {return elem.real();}); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Poly::Matrix<T,M> imag(const Poly::Matrix<std::complex<T>,M>& mat) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Poly::Matrix<T,M> result(mat.rows(),mat.columns()); | 
		
	
		
			
				|  |  |  |  |     std::transform(mat.begin(),mat.end(),result.begin(),[](const std::complex<T>& elem) -> T {return elem.imag();}); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void swap(Poly::Matrix<T,M>&__a, Poly::Matrix<T,M>&__b) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     std::swap(__a._rows,__b._rows); | 
		
	
		
			
				|  |  |  |  |     std::swap(__a._columns,__b._columns); | 
		
	
		
			
				|  |  |  |  |     std::swap(__a._matEls,__b._matEls); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | namespace Poly | 
		
	
	
		
			
				
					
					|  |  |  | @@ -129,6 +150,8 @@ public: | 
		
	
		
			
				|  |  |  |  |     typedef const T& const_reference; | 
		
	
		
			
				|  |  |  |  |     typedef long size_type; | 
		
	
		
			
				|  |  |  |  |     typedef size_type difference_type; | 
		
	
		
			
				|  |  |  |  |     typedef typename std::vector<T>::iterator iterator; | 
		
	
		
			
				|  |  |  |  |     typedef typename std::vector<T>::const_iterator const_iterator; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | private: | 
		
	
		
			
				|  |  |  |  |     std::vector<T> _matEls; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -140,21 +163,21 @@ private: | 
		
	
		
			
				|  |  |  |  |     inline size_type SizeToReserve(const size_type &rows, const size_type &columns) const; | 
		
	
		
			
				|  |  |  |  |     void invert_manual(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     void _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | public: | 
		
	
		
			
				|  |  |  |  |     void _check_square_matrix() const; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M>(); | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M>(const size_type& rows, const size_type& columns, const T& initialValue = T()); | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M>(const size_type& rows, const size_type& columns, const std::initializer_list<T>& init_list); | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M>(const Matrix<T, M>& src) = default; | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M>(Matrix&&) = default; | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M>(Matrix<T, M>&&) = default; | 
		
	
		
			
				|  |  |  |  |     ~Matrix() = default; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     //copy constructor from real to complex | 
		
	
		
			
				|  |  |  |  |     template <typename U, typename = typename std::enable_if<std::is_same<T, std::complex<U>>::value>::type> | 
		
	
		
			
				|  |  |  |  |         Matrix(const Matrix<U, M> & src); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     ~Matrix() = default; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M> &operator=(const Matrix<T,M>& rhs) = default; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -178,14 +201,22 @@ public: | 
		
	
		
			
				|  |  |  |  |         friend Matrix<_T,_M> operator+(const Matrix<_T,_M>& lhs, const Matrix<_T,_M>& rhs); | 
		
	
		
			
				|  |  |  |  |     template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |         friend Matrix<_T,_M> operator-(const Matrix<_T,_M>& lhs, const Matrix<_T,_M>& rhs); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |         friend Matrix<_T,_M> operator*(const _T& lhs, const Matrix<_T,_M>& rhs); | 
		
	
		
			
				|  |  |  |  |     template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |         friend Matrix<_T,_M> operator*(const Matrix<_T,_M>& lhs, const _T& rhs); | 
		
	
		
			
				|  |  |  |  |     template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |         friend Matrix<_T,_M> operator/(const Matrix<_T,_M>& lhs, const _T& rhs); | 
		
	
		
			
				|  |  |  |  |     template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |         friend void std::swap(Poly::Matrix<_T,_M>&__a, Poly::Matrix<_T,_M>&__b); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |    template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |        friend Matrix<std::complex<_T>,_M> operator*(const Matrix<std::complex<_T>,_M>& lhs, const _T& rhs); | 
		
	
		
			
				|  |  |  |  |    template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |        friend Matrix<std::complex<_T>,_M> operator*(const _T& lhs, const Matrix<std::complex<_T>,_M>& rhs); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |    template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |        friend Matrix<std::complex<_T>,_M> operator*(const std::complex<_T>& lhs, const Matrix<_T,_M>& rhs); | 
		
	
		
			
				|  |  |  |  |    template <typename _T, int _M> | 
		
	
	
		
			
				
					
					|  |  |  | @@ -201,19 +232,24 @@ public: | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     inline T& operator[](const size_type& index); | 
		
	
		
			
				|  |  |  |  |     inline const T& operator[](const size_type& index) const; | 
		
	
		
			
				|  |  |  |  |     inline T& operator()(const size_type& index); | 
		
	
		
			
				|  |  |  |  |     inline const T& operator()(const size_type& index) const; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     inline typename std::vector<T>::iterator begin() noexcept; | 
		
	
		
			
				|  |  |  |  |     inline typename std::vector<T>::const_iterator begin() const noexcept; | 
		
	
		
			
				|  |  |  |  |     inline typename std::vector<T>::iterator end() noexcept; | 
		
	
		
			
				|  |  |  |  |     inline typename std::vector<T>::const_iterator end() const noexcept; | 
		
	
		
			
				|  |  |  |  |     inline iterator begin() noexcept; | 
		
	
		
			
				|  |  |  |  |     inline const_iterator begin() const noexcept; | 
		
	
		
			
				|  |  |  |  |     inline iterator end() noexcept; | 
		
	
		
			
				|  |  |  |  |     inline const_iterator end() const noexcept; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M>& operator+=(const Matrix<T,M>& rhs); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M>& operator-=(const Matrix<T,M>& rhs); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M>& operator*=(const Matrix<T,M>& rhs); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M>& operator/=(const Matrix<T,M>& rhs); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M>& operator*=(const T& rhs); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M>& operator/=(const T& rhs); | 
		
	
		
			
				|  |  |  |  |     void elementWiseProduct_inplace(const Matrix<T,M>& rhs); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> elementWiseProduct(const Matrix<T,M>& rhs); | 
		
	
		
			
				|  |  |  |  |     T trace(); | 
		
	
		
			
				|  |  |  |  |     template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |     friend _T Trace(const Matrix<_T,_M> &rhs); | 
		
	
		
			
				|  |  |  |  |     void zeros(); | 
		
	
		
			
				|  |  |  |  |     void ones(); | 
		
	
		
			
				|  |  |  |  |     void inverse_inplace(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -221,29 +257,36 @@ public: | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> getExp(); | 
		
	
		
			
				|  |  |  |  |     void conjugate_inplace(); | 
		
	
		
			
				|  |  |  |  |     void conjugateTranspose_inplace(); | 
		
	
		
			
				|  |  |  |  |     std::vector<T> vectorize(const VECTORIZATION_MODE& mode = VECMODE_FULL) const; | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> vectorize(const VECTORIZATION_MODE& mode = VECMODE_FULL) const; | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> diagonal() const; | 
		
	
		
			
				|  |  |  |  |     const T& at(size_type row, size_type column) const; | 
		
	
		
			
				|  |  |  |  |     T& at(size_type row, size_type column); | 
		
	
		
			
				|  |  |  |  |     T& operator()(size_type row, size_type column); | 
		
	
		
			
				|  |  |  |  |     const T& operator()(size_type row, size_type column) const; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     T& front(); | 
		
	
		
			
				|  |  |  |  |     const T& front() const; | 
		
	
		
			
				|  |  |  |  |     void resize(size_type rows, size_type columns, const T &initialValue = T()); | 
		
	
		
			
				|  |  |  |  |     const size_type& rows(); | 
		
	
		
			
				|  |  |  |  |     const size_type& columns(); | 
		
	
		
			
				|  |  |  |  |     typename Matrix<T,M>::size_type size(); | 
		
	
		
			
				|  |  |  |  |     const size_type& rows() const; | 
		
	
		
			
				|  |  |  |  |     const size_type& columns() const; | 
		
	
		
			
				|  |  |  |  |     typename Matrix<T,M>::size_type size() const; | 
		
	
		
			
				|  |  |  |  |     void clear(); | 
		
	
		
			
				|  |  |  |  |     void transpose_inplace(); | 
		
	
		
			
				|  |  |  |  |     T getDeterminant(); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> getSVD(); | 
		
	
		
			
				|  |  |  |  |     T determinant(); | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> SVD(); | 
		
	
		
			
				|  |  |  |  |     std::string asString(int precision = 7, char open = '[', char close = ']', char sep = ','); | 
		
	
		
			
				|  |  |  |  |     template <typename _T, int _M> | 
		
	
		
			
				|  |  |  |  |         friend std::ostream& operator<<(std::ostream &os, const Matrix<_T,_M> &src); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     void print(std::ostream &os = std::cout, std::string header = "") const; | 
		
	
		
			
				|  |  |  |  |     void raw_print(std::ostream &os = std::cout, std::string header = "") const; | 
		
	
		
			
				|  |  |  |  |     //converts elements to type _targetType and puts them in a new Matrix | 
		
	
		
			
				|  |  |  |  |     template <typename _targetType> | 
		
	
		
			
				|  |  |  |  |         Matrix<_targetType,M> convertElements(); | 
		
	
		
			
				|  |  |  |  |     template <typename _targetType> | 
		
	
		
			
				|  |  |  |  |         Matrix<_targetType,M> convertElements(std::function<_targetType(T)> conversion_rule); | 
		
	
		
			
				|  |  |  |  |         Matrix<_targetType,M> convertElements(const std::function<_targetType(T)> &conversion_rule); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     //puts all the elements in a new container | 
		
	
		
			
				|  |  |  |  |     template <typename Container> | 
		
	
	
		
			
				
					
					|  |  |  | @@ -261,7 +304,7 @@ Matrix<_targetType, M> Matrix<T,M>::convertElements() | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | template <typename _targetType> | 
		
	
		
			
				|  |  |  |  | Matrix<_targetType, M> Matrix<T,M>::convertElements(std::function<_targetType(T)> conversion_rule) | 
		
	
		
			
				|  |  |  |  | Matrix<_targetType, M> Matrix<T,M>::convertElements(const std::function<_targetType(T)> &conversion_rule) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Matrix<_targetType, M> ret(this->rows(),this->columns()); | 
		
	
		
			
				|  |  |  |  |     std::transform(this->begin(), this->end(), ret.begin(),conversion_rule); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -400,6 +443,18 @@ const typename Matrix<T,M>::size_type& Matrix<T,M>::rows() const | 
		
	
		
			
				|  |  |  |  |     return _rows; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | typename Matrix<T,M>::size_type Matrix<T,M>::size() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->_matEls.size(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | typename Matrix<T,M>::size_type Matrix<T,M>::size() const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->_matEls.size(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::clear() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -430,13 +485,40 @@ bool Matrix<T,M>::operator!=(const Matrix<T,M>& rhs) | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::transpose_inplace() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     *this = Transpose(*this); | 
		
	
		
			
				|  |  |  |  |     if(this->rows() == 1 || this->columns() == 1) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         std::swap(this->_rows,this->_columns); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         for(typename Poly::Matrix<T,M>::size_type i = 0; i < this->rows(); i++) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             for(typename Poly::Matrix<T,M>::size_type j = i+1; j < this->columns(); j++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 std::swap(this->at(j,i),this->at(i,j)); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::conjugateTranspose_inplace() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     *this = ConjugateTranspose(*this); | 
		
	
		
			
				|  |  |  |  |     if(this->rows() == 1 || this->columns() == 1) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         std::swap(this->_rows,this->_columns); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         for(typename Poly::Matrix<T,M>::size_type i = 0; i < this->rows(); i++) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             for(typename Poly::Matrix<T,M>::size_type j = i+1; j < this->columns(); j++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 std::swap(this->at(j,i),this->at(i,j)); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     this->conjugate_inplace(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
	
		
			
				
					
					|  |  |  | @@ -444,7 +526,7 @@ std::ostream& operator<<(std::ostream &os, const Matrix<T,M> &src) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     for (typename Matrix<T,M>::size_type i = 0; i < src._rows; i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         for (typename Matrix<T,M>::size_type j = 0; j < src._rows; j++) | 
		
	
		
			
				|  |  |  |  |         for (typename Matrix<T,M>::size_type j = 0; j < src._columns; j++) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             os << src.at(i,j) << "\t"; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -452,6 +534,30 @@ std::ostream& operator<<(std::ostream &os, const Matrix<T,M> &src) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return os; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<std::complex<T>,M> operator*(const Matrix<std::complex<T>,M>& lhs, const T& rhs) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Matrix<std::complex<T>,M> result = lhs; | 
		
	
		
			
				|  |  |  |  |     for(typename Matrix<T,M>::size_type i = 0; i < static_cast<typename Matrix<T,M>::size_type>(lhs._matEls.size()); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         result._matEls[i] *= rhs; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return result; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<std::complex<T>,M> operator*(const T& lhs, const Matrix<std::complex<T>,M>& rhs) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Matrix<std::complex<T>,M> result = rhs; | 
		
	
		
			
				|  |  |  |  |     for(typename Matrix<T,M>::size_type i = 0; i < static_cast<typename Matrix<T,M>::size_type>(rhs._matEls.size()); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         result._matEls[i] *= lhs; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return result; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T,M> operator*(const Matrix<T,M>& lhs, const Matrix<T,M>& rhs) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -601,6 +707,20 @@ Matrix<T,M>& Matrix<T,M>::operator*=(const Matrix<T,M>& rhs) | 
		
	
		
			
				|  |  |  |  |     return *this; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T,M>& Matrix<T,M>::operator*=(const T& rhs) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     (*this) = (*this) * rhs; | 
		
	
		
			
				|  |  |  |  |     return *this; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T,M>& Matrix<T,M>::operator/=(const T& rhs) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     (*this) = (*this) / rhs; | 
		
	
		
			
				|  |  |  |  |     return *this; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::elementWiseProduct_inplace(const Matrix<T,M> &rhs) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -632,6 +752,18 @@ T Matrix<T,M>::trace() | 
		
	
		
			
				|  |  |  |  |     return result; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | T Trace(const Matrix<T,M> &rhs) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     rhs._check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |     T result = T(0); | 
		
	
		
			
				|  |  |  |  |     for(typename Matrix<T,M>::size_type i = 0; i < rhs.rows(); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         result += rhs.at(i,i); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return result; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::zeros() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -647,11 +779,7 @@ void Matrix<T,M>::ones() | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::inverse_inplace() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     //FIXME: Make size error functions all in one place | 
		
	
		
			
				|  |  |  |  |     if(rows() != columns()) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         throw std::length_error("Matrix inverse is only for square matrices."); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     this->_check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |     if(std::is_same<float,T>::value) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         Xgetri(float,s, tmp_workspace_size) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -737,7 +865,7 @@ void Matrix<T,M>::invert_manual() | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::_check_square_matrix() | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::_check_square_matrix() const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | #ifdef POLYMATH_DEBUG | 
		
	
		
			
				|  |  |  |  |     if(this->columns() != this->rows()) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -829,20 +957,34 @@ void Matrix<T,M>::conjugate_inplace() | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  | Matrix<T, M> Matrix<T,M>::diagonal() const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     std::vector<T> output; | 
		
	
		
			
				|  |  |  |  |     _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M> output(this->columns(),1); | 
		
	
		
			
				|  |  |  |  |     for(long i = 0; i < this->rows(); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         output._matEls[i] = this->at(i,i); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return output; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T, M> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Matrix<T, M> output; | 
		
	
		
			
				|  |  |  |  |     if(M == ColMaj) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if(mode == Poly::VECMODE_FULL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             return _matEls; | 
		
	
		
			
				|  |  |  |  |             Matrix<T, M> output(this->rows()*this->columns(),1); | 
		
	
		
			
				|  |  |  |  |             std::copy(this->begin(),this->end(),output.begin()); | 
		
	
		
			
				|  |  |  |  |             return output; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_UPPER_TRIANGULAR_NO_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin() + this->columns(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin() + this->columns(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             for(int i = 1; i < this->columns(); i++) //Starts with 1 to skip the diagonal | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -854,8 +996,8 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_UPPER_TRIANGULAR_WITH_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin(); | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             for(int i = 0; i < this->columns(); i++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -867,8 +1009,8 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_LOWER_TRIANGULAR_NO_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             it += 1; | 
		
	
		
			
				|  |  |  |  |             for(int i = this->columns() - 1; i > 0 ; i--) //Starts with 1 to skip the diagonal | 
		
	
	
		
			
				
					
					|  |  |  | @@ -881,8 +1023,8 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_LOWER_TRIANGULAR_WITH_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             for(int i = this->columns() - 1; i >= 0 ; i--) //Starts with 1 to skip the diagonal | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -900,13 +1042,15 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if(mode == Poly::VECMODE_FULL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             return _matEls; | 
		
	
		
			
				|  |  |  |  |             Matrix<T, M> output(this->rows()*this->columns(),1); | 
		
	
		
			
				|  |  |  |  |             std::copy(this->begin(),this->end(),output.begin()); | 
		
	
		
			
				|  |  |  |  |             return output; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_LOWER_TRIANGULAR_NO_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin() + this->columns(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin() + this->columns(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             for(int i = 1; i < this->columns(); i++) //Starts with 1 to skip the diagonal | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -918,8 +1062,8 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_LOWER_TRIANGULAR_WITH_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin(); | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             for(int i = 0; i < this->columns(); i++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -931,8 +1075,8 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_UPPER_TRIANGULAR_NO_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()-1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             it += 1; | 
		
	
		
			
				|  |  |  |  |             for(int i = this->columns() - 1; i > 0 ; i--) //Starts with 1 to skip the diagonal | 
		
	
	
		
			
				
					
					|  |  |  | @@ -945,8 +1089,8 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |         else if(mode == Poly::VECMODE_UPPER_TRIANGULAR_WITH_DIAGONAL) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2); | 
		
	
		
			
				|  |  |  |  |             typename std::vector<T>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             output.resize((this->columns()*(this->columns()+1))/2,1); | 
		
	
		
			
				|  |  |  |  |             typename Matrix<T,M>::const_iterator it = _matEls.begin(); //iterator at rows to skip in every step, starts at second column | 
		
	
		
			
				|  |  |  |  |             long size_to_copy = 0; | 
		
	
		
			
				|  |  |  |  |             for(int i = this->columns() - 1; i >= 0 ; i--) //Starts with 1 to skip the diagonal | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -963,6 +1107,18 @@ std::vector<T> Matrix<T, M>::vectorize(const VECTORIZATION_MODE &mode) const | 
		
	
		
			
				|  |  |  |  |     return output; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | T& Matrix<T,M>::operator()(size_type row, size_type column) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->at(row,column); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | const T& Matrix<T,M>::operator()(size_type row, size_type column) const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->at(row,column); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | T &Matrix<T,M>::at(size_type row, size_type column) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1014,40 +1170,47 @@ const T& Matrix<T,M>::operator[](const size_type& index) const | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | typename std::vector<T>::iterator Matrix<T,M>::begin() noexcept | 
		
	
		
			
				|  |  |  |  | T& Matrix<T,M>::operator()(const size_type& index) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return _matEls[index]; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | const T& Matrix<T,M>::operator()(const size_type& index) const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return _matEls[index]; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | typename Matrix<T,M>::iterator Matrix<T,M>::begin() noexcept | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->_matEls.begin(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | typename std::vector<T>::const_iterator Matrix<T,M>::begin() const noexcept | 
		
	
		
			
				|  |  |  |  | typename Matrix<T,M>::const_iterator Matrix<T,M>::begin() const noexcept | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->_matEls.begin(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | typename std::vector<T>::iterator Matrix<T,M>::end() noexcept | 
		
	
		
			
				|  |  |  |  | typename Matrix<T,M>::iterator Matrix<T,M>::end() noexcept | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->_matEls.end(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | typename std::vector<T>::const_iterator Matrix<T,M>::end() const noexcept | 
		
	
		
			
				|  |  |  |  | typename Matrix<T,M>::const_iterator Matrix<T,M>::end() const noexcept | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     return this->_matEls.end(); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | T Matrix<T,M>::getDeterminant() | 
		
	
		
			
				|  |  |  |  | T Matrix<T,M>::determinant() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     this->_check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |     T det = static_cast<T>(1); | 
		
	
		
			
				|  |  |  |  |     T val; | 
		
	
		
			
				|  |  |  |  | #ifdef POLYMATH_DEBUG | 
		
	
		
			
				|  |  |  |  |     if(this->rows() != this->columns()) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         throw std::length_error("Determinant is for square matrices only."); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |     size_type sideLength = this->rows(); | 
		
	
		
			
				|  |  |  |  |     for (size_type i = 0; i < sideLength; i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1056,11 +1219,11 @@ T Matrix<T,M>::getDeterminant() | 
		
	
		
			
				|  |  |  |  | //            cout<<(*this)<<endl; | 
		
	
		
			
				|  |  |  |  |             val = static_cast<T>(1)/((*this)[i][i]); | 
		
	
		
			
				|  |  |  |  |             det *= static_cast<T>(1)/val; | 
		
	
		
			
				|  |  |  |  |             this->doMultiplyRowWith(val,i); | 
		
	
		
			
				|  |  |  |  |             MultiplyRowWith(*this,val,i); | 
		
	
		
			
				|  |  |  |  |             for (int j = i + 1; j < sideLength; j++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 val = -((*this)[j][i]); | 
		
	
		
			
				|  |  |  |  |                 this->doMultiplyAndAddToRow(val,i,j); | 
		
	
		
			
				|  |  |  |  |                 MultiplyAndAddToRow(*this,val,i,j); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1082,28 +1245,25 @@ T Matrix<T,M>::getDeterminant() | 
		
	
		
			
				|  |  |  |  |     return det; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T,M> Matrix<T,M>::getSVD() | 
		
	
		
			
				|  |  |  |  | Matrix<T,M> Matrix<T,M>::SVD() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> U, S, V; | 
		
	
		
			
				|  |  |  |  |     S = (*this); | 
		
	
		
			
				|  |  |  |  |     std::cout<<S.rows()<<"\t"<<S.columns()<<std::endl; | 
		
	
		
			
				|  |  |  |  | //    std::cout<<S.rows()<<"\t"<<S.columns()<<std::endl; | 
		
	
		
			
				|  |  |  |  |     std::vector<T> ret; | 
		
	
		
			
				|  |  |  |  |     U = Matrix<T,M>::identity(S.rows()); | 
		
	
		
			
				|  |  |  |  |     V = Matrix<T,M>::identity(S.columns()); | 
		
	
		
			
				|  |  |  |  |     U = IdentityMatrix<T,M>(S.rows()); | 
		
	
		
			
				|  |  |  |  |     V = IdentityMatrix<T,M>(S.columns()); | 
		
	
		
			
				|  |  |  |  |     T val; | 
		
	
		
			
				|  |  |  |  |     for (size_type i = 0; i < S.rows(); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if(S[i][i] != static_cast<T>(0)) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             std::cout<<"Int S: "<<std::endl<<S<<std::endl<<U<<std::endl<<U*S<<std::endl; | 
		
	
		
			
				|  |  |  |  |             //val = 1.0/((S)[i][i]); | 
		
	
		
			
				|  |  |  |  |             //S.doMultiplyRowWith(val,i); | 
		
	
		
			
				|  |  |  |  |             //sideMat.doMultiplyRowWith(1/val,i); | 
		
	
		
			
				|  |  |  |  | //            std::cout<<"Int S: "<<std::endl<<S<<std::endl<<U<<std::endl<<U*S<<std::endl; | 
		
	
		
			
				|  |  |  |  |             for (size_type j = i + 1; j < S.rows(); j++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 val = -S[j][i]/S[i][i]; | 
		
	
		
			
				|  |  |  |  |                 S.doMultiplyAndAddToRow(val,i,j); | 
		
	
		
			
				|  |  |  |  |                 U.doMultiplyAndAddToRow(-val,i,j); | 
		
	
		
			
				|  |  |  |  |                 MultiplyAndAddToRow(S,val,i,j); | 
		
	
		
			
				|  |  |  |  |                 MultiplyAndAddToRow(U,-val,i,j); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1123,10 +1283,10 @@ Matrix<T,M> Matrix<T,M>::getSVD() | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     std::cout<<"U: "<<std::endl<<U<<std::endl; | 
		
	
		
			
				|  |  |  |  |     std::cout<<"S: "<<std::endl<<S<<std::endl; | 
		
	
		
			
				|  |  |  |  |     std::cout<<"Start Res: "<<std::endl<<*this<<std::endl; | 
		
	
		
			
				|  |  |  |  |     std::cout<<"Res: "<<std::endl<<U*S<<std::endl; | 
		
	
		
			
				|  |  |  |  | //    std::cout<<"U: "<<std::endl<<U<<std::endl; | 
		
	
		
			
				|  |  |  |  | //    std::cout<<"S: "<<std::endl<<S<<std::endl; | 
		
	
		
			
				|  |  |  |  | //    std::cout<<"Start Res: "<<std::endl<<*this<<std::endl; | 
		
	
		
			
				|  |  |  |  | //    std::cout<<"Res: "<<std::endl<<U*S<<std::endl; | 
		
	
		
			
				|  |  |  |  |     ret.push_back(U); | 
		
	
		
			
				|  |  |  |  |     ret.push_back(S); | 
		
	
		
			
				|  |  |  |  |     ret.push_back(V); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1156,6 +1316,22 @@ std::string Matrix<T,M>::asString(int precision, char open, char close, char sep | 
		
	
		
			
				|  |  |  |  |     return out; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::print(std::ostream &os, std::string header) const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     if(!header.empty()) | 
		
	
		
			
				|  |  |  |  |         std::cout<<header<<std::endl; | 
		
	
		
			
				|  |  |  |  |     std::cout << *this << std::endl; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | void Matrix<T,M>::raw_print(std::ostream &os, std::string header) const | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     if(!header.empty()) | 
		
	
		
			
				|  |  |  |  |         std::cout<<header<<std::endl; | 
		
	
		
			
				|  |  |  |  |     std::cout << *this << std::endl; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T,M> IdentityMatrix(const typename Poly::Matrix<T,M>::size_type& size) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1186,28 +1362,16 @@ void ResetMatrix(Matrix<T,M> &matrix, T value) | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T,M> Transpose(const Matrix<T,M> &matrix) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> res(matrix.columns(),matrix.rows()); | 
		
	
		
			
				|  |  |  |  |     for(typename Poly::Matrix<T,M>::size_type i = 0; i < matrix.rows(); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         for(typename Poly::Matrix<T,M>::size_type j = 0; j < matrix.columns(); j++) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             res.at(j,i) = matrix.at(i,j); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> res(matrix); | 
		
	
		
			
				|  |  |  |  |     res.transpose_inplace(); | 
		
	
		
			
				|  |  |  |  |     return res; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Matrix<T,M> ConjugateTranspose(const Matrix<T,M> &matrix) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> res(matrix.columns(),matrix.rows()); | 
		
	
		
			
				|  |  |  |  |     for(typename Poly::Matrix<T,M>::size_type i = 0; i < matrix.rows(); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         for(typename Poly::Matrix<T,M>::size_type j = 0; j < matrix.columns(); j++) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             res.at(j,i) = std::conj(matrix.at(i,j)); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     Matrix<T,M> res(matrix); | 
		
	
		
			
				|  |  |  |  |     res.conjugateTranspose_inplace(); | 
		
	
		
			
				|  |  |  |  |     return res; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1759,6 +1923,7 @@ EigenVecsVals(Poly::Matrix<T,M>& eigenValues, | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         throw std::logic_error("The type requested is not supported."); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1822,16 +1987,11 @@ template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Poly::Matrix<std::complex<T>, M > | 
		
	
		
			
				|  |  |  |  | MatrixExp(const Poly::Matrix<std::complex<T>, M > &input_matrix, const MATRIX_TYPE &type) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | #ifdef POLYMATH_DEBUG | 
		
	
		
			
				|  |  |  |  |     if(input_matrix.columns() != input_matrix.rows()) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         throw std::length_error("Matrix exponential can only be taken for square matrices"); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | #endif | 
		
	
		
			
				|  |  |  |  |     input_matrix._check_square_matrix(); | 
		
	
		
			
				|  |  |  |  |     if(type == Poly::MATRIX_HERMITIAN) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         auto input = input_matrix; | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<std::complex<T>, M> matrix_exp(input_matrix.rows(),input_matrix.columns(),T()); | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<std::complex<T>, M> matrix_exp(input_matrix.rows(),input_matrix.columns()); | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<T, M> eigenVals; | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<std::complex<T>, M> eigenVecs; | 
		
	
		
			
				|  |  |  |  |         EigenVecsVals(eigenVals,eigenVecs,input,type); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1841,12 +2001,48 @@ MatrixExp(const Poly::Matrix<std::complex<T>, M > &input_matrix, const MATRIX_TY | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         return eigenVecs*matrix_exp*Poly::ConjugateTranspose(eigenVecs); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(type == Poly::MATRIX_ANTIHERMITIAN) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         auto input = std::complex<T>(0,1)*input_matrix; //convert the matrix to Hermitian | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<std::complex<T>, M> matrix_exp(input_matrix.rows(),input_matrix.columns()); | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<T, M> eigenVals; | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<std::complex<T>, M> eigenVecs; | 
		
	
		
			
				|  |  |  |  |         EigenVecsVals(eigenVals,eigenVecs,input,Poly::MATRIX_HERMITIAN); | 
		
	
		
			
				|  |  |  |  |         Poly::Matrix<std::complex<T>, M> eigenValsComplex = std::complex<T>(0,-1)*eigenVals; //necessary for anti-hermitian matrices to reverse the multiplication by i in the beginning | 
		
	
		
			
				|  |  |  |  |         for(long i = 0; i < matrix_exp.rows(); i++) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             matrix_exp.at(i,i) = std::exp(eigenValsComplex[i]); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         return eigenVecs*matrix_exp*Poly::ConjugateTranspose(eigenVecs); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         throw std::logic_error("The matrix type requested is not supported."); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T, int M> | 
		
	
		
			
				|  |  |  |  | Poly::Matrix<T, M> | 
		
	
		
			
				|  |  |  |  | KroneckerProduct(const Poly::Matrix<T, M> &mat1, const Poly::Matrix<T, M> &mat2) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     typedef typename Poly::Matrix<T,M>::size_type size_type; | 
		
	
		
			
				|  |  |  |  |     Poly::Matrix<T,M> result(mat1.rows()*mat2.rows(),mat1.columns()*mat2.columns()); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     for(size_type i = 0; i < mat1.rows(); i++) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         for(size_type j = 0; j < mat1.columns(); j++) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             for(size_type k = 0; k < mat2.rows(); k++) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 for(size_type l = 0; l < mat2.columns(); l++) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     result.at(mat2.rows()*i+k,mat2.columns()*j+l) = mat1.at(i,j)*mat2.at(k,l); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return result; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | #endif	/* Matrix_H */ | 
		
	
	
		
			
				
					
					| 
							
							
							
						 |  |  |   |