@ -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,13 +201,21 @@ 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 ) ;
@ -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 getD eterminant( ) ;
Matrix < T , M > get SVD( ) ;
T d eterminant( ) ;
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 . _ row s; j + + )
for ( typename Matrix < T , M > : : size_type j = 0 ; j < src . _ column s; 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 > : : getD eterminant( )
T Matrix < T , M > : : d eterminant( )
{
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 - > do MultiplyRowWith( val , i ) ;
MultiplyRowWith( * this , val , i ) ;
for ( int j = i + 1 ; j < sideLength ; j + + )
{
val = - ( ( * this ) [ j ] [ i ] ) ;
this - > do MultiplyAndAddToRow( 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 > : : get SVD( )
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 = Identity Matrix< T , M > ( S . rows ( ) ) ;
V = Identity Matrix< 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 . do MultiplyAndAddToRow( val , i , j ) ;
U . do MultiplyAndAddToRow( - 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 */