32 #ifndef __VMML__MATRIX__HPP__
33 #define __VMML__MATRIX__HPP__
35 #include <vmmlib/vmmlib_config.hpp>
37 #include <vmmlib/matrix_functors.hpp>
38 #include <vmmlib/vector.hpp>
39 #include <vmmlib/math.hpp>
40 #include <vmmlib/exception.hpp>
41 #include <vmmlib/enable_if.hpp>
57 template<
size_t M,
size_t N,
typename T =
float >
63 typedef const T* const_iterator;
64 typedef std::reverse_iterator< iterator > reverse_iterator;
65 typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
67 static const size_t ROWS = M;
68 static const size_t COLS = N;
73 template<
size_t P,
size_t Q,
typename U >
77 inline T& operator()(
size_t row_index,
size_t col_index );
78 inline const T& operator()(
size_t row_index,
size_t col_index )
const;
80 inline T& at(
size_t row_index,
size_t col_index );
81 inline const T& at(
size_t row_index,
size_t col_index )
const;
86 const_iterator begin()
const;
87 const_iterator end()
const;
89 reverse_iterator rbegin();
90 reverse_iterator rend();
91 const_reverse_iterator rbegin()
const;
92 const_reverse_iterator rend()
const;
94 #ifndef VMMLIB_NO_CONVERSION_OPERATORS
97 operator const T*()
const;
100 bool operator==(
const matrix& other )
const;
101 bool operator!=(
const matrix& other )
const;
105 bool equals(
const matrix& other, T tolerance )
const;
108 template<
typename compare_t >
109 bool equals(
const matrix& other, compare_t& cmp )
const;
111 void multiply_piecewise(
const matrix& other );
118 template<
size_t U,
size_t V >
127 template<
size_t O,
size_t P,
typename TT >
128 typename enable_if< M == N && O == P && M == O, TT >::type*
131 inline matrix operator+(
const matrix& other )
const;
132 inline matrix operator-(
const matrix& other )
const;
134 void operator+=(
const matrix& other );
135 void operator-=(
const matrix& other );
137 void operator+=( T scalar );
138 void operator-=( T scalar );
140 template<
size_t O,
size_t P,
size_t Q,
size_t R >
141 typename enable_if< M == O + Q && N == P + R >::type*
147 matrix operator*( T scalar );
148 void operator*=( T scalar );
150 matrix operator/( T scalar );
151 void operator/=( T scalar );
171 template<
size_t uM,
size_t vM >
172 typename enable_if< uM == 3 && vM == 3 && M == N && M == 4 >::type*
177 template<
size_t O,
size_t P >
179 get_sub_matrix(
size_t row_offset,
size_t col_offset,
180 typename enable_if< O <= M && P <= N >::type* = 0 )
const;
182 template<
size_t O,
size_t P >
185 size_t row_offset = 0,
size_t col_offset = 0 )
const;
187 template<
size_t O,
size_t P >
190 size_t row_offset = 0,
size_t col_offset = 0 );
203 template<
size_t P,
size_t Q,
typename U >
205 void operator=(
const T old_fashioned_matrix[ M ][ N ] );
210 void operator=(
const T* data_array );
211 void operator=(
const std::vector< T >& data );
214 void operator=( T fill_value );
215 void fill( T fill_value );
219 template<
typename input_iterator_t >
220 void set( input_iterator_t begin_, input_iterator_t end_,
221 bool row_major_layout =
true );
227 void set_random(
int seed = -1 );
234 double frobenius_norm()
const;
235 double p_norm(
double p )
const;
237 template<
typename TT >
240 void read_csv_file(
const std::string& dir_,
const std::string& filename_ );
241 void write_csv_file(
const std::string& dir_,
const std::string& filename_ )
const;
242 void write_to_raw(
const std::string& dir_,
const std::string& filename_ )
const;
243 void read_from_raw(
const std::string& dir_,
const std::string& filename_ ) ;
245 template<
typename TT >
246 void quantize_to(
matrix< M, N, TT >& quantized_,
const T& min_value,
const T& max_value )
const;
247 template<
typename TT >
249 template<
typename TT >
250 void dequantize(
matrix< M, N, TT >& quantized_,
const TT& min_value,
const TT& max_value )
const;
253 double sum_elements()
const;
259 typename enable_if< R == M && R == N >::type*
267 template<
size_t O,
size_t P >
272 T get_abs_min()
const;
273 T get_abs_max()
const;
277 size_t nnz(
const T& threshold_ )
const;
278 void threshold(
const T& threshold_value_ );
281 void get_column(
size_t column_index,
vector< M, T>& column )
const;
297 size_t get_number_of_rows()
const;
298 size_t get_number_of_columns()
const;
305 template<
size_t O,
size_t P,
typename TT >
307 T tolerance = std::numeric_limits<T>::epsilon(),
310 template<
size_t O,
size_t P >
314 template<
size_t O,
size_t P >
320 template<
size_t O,
size_t P >
331 template<
typename TT >
333 typename enable_if< M == N && M == 4, TT >::type* = 0 );
335 template<
typename TT >
337 typename enable_if< M == N && M == 4, TT >::type* = 0 );
339 template<
typename TT >
341 typename enable_if< M == N && M == 4, TT >::type* = 0 );
343 template<
typename TT >
345 typename enable_if< M == N && M == 4, TT >::type* = 0 );
347 template<
typename TT >
349 typename enable_if< M == N && M == 4, TT >::type* = 0 );
351 template<
typename TT >
353 typename enable_if< M == N && M == 4, TT >::type* = 0 );
355 template<
typename TT >
357 typename enable_if< M == N && M == 4, TT >::type* = 0 );
359 template<
typename TT >
361 typename enable_if< M == N && M == 4, TT >::type* = 0 );
363 template<
typename TT >
365 typename enable_if< M == N && M == 4, TT >::type* = 0 );
367 template<
typename TT >
369 typename enable_if< M == N && M == 4, TT >::type* = 0 );
371 template<
typename TT >
373 typename enable_if< M == N && M == 4, TT >::type* = 0 );
375 template<
typename TT >
377 typename enable_if< M == N && M == 4, TT >::type* = 0 );
379 template<
typename TT >
381 typename enable_if< M == N && M == 4, TT >::type* = 0 );
383 template<
typename TT >
385 typename enable_if< M == N && M == 4, TT >::type* = 0 );
387 template<
typename TT >
389 typename enable_if< M == N && M == 4, TT >::type* = 0 );
391 template<
typename TT >
394 vector< N-1, T > get_translation()
const;
397 template<
typename init_functor_t >
398 static const matrix get_initialized_matrix();
411 row_accessor( T* array_ ) : array( array_ ) {}
413 operator[](
size_t col_index )
415 #ifdef VMMLIB_SAFE_ACCESSORS
416 if ( col_index >= N )
417 VMMLIB_ERROR(
"column index out of bounds", VMMLIB_HERE );
419 return array[ col_index * M ];
423 operator[](
size_t col_index )
const
425 #ifdef VMMLIB_SAFE_ACCESSORS
426 if ( col_index >= N )
427 VMMLIB_ERROR(
"column index out of bounds", VMMLIB_HERE );
429 return array[ col_index * M ];
433 private: row_accessor() {}
437 inline row_accessor operator[](
size_t row_index )
439 #ifdef VMMLIB_SAFE_ACCESSORS
441 VMMLIB_ERROR(
"row index out of bounds", VMMLIB_HERE );
443 return row_accessor( array + row_index );
447 inline row_accessor operator[](
int row_index )
449 return ( *
this )[ size_t ( row_index ) ];
452 friend std::ostream& operator << ( std::ostream& os,
455 #ifdef EQFABRIC_API_H
456 const std::ios::fmtflags flags = os.flags();
457 const int prec = os.precision();
459 os.setf( std::ios::right, std::ios::adjustfield );
462 for(
size_t row_index = 0; row_index < M; ++row_index )
465 for(
size_t col_index = 0; col_index < N; ++col_index )
467 os << std::setw(10) << matrix.at( row_index, col_index ) <<
" ";
469 os <<
"|" << std::endl;
471 os.precision( prec );
474 for(
size_t row_index = 0; row_index < M; ++row_index )
477 for(
size_t col_index = 0; col_index < N; ++col_index )
479 if(
sizeof(T) ==
sizeof(
unsigned char)) {
480 os << int(matrix.at( row_index, col_index ));
482 os << matrix.at( row_index, col_index );
484 if (col_index + 1 < N )
487 os <<
")" << std::endl;
495 VMMLIB_ALIGN( T array[ M * N ] );
504 #ifndef VMMLIB_NO_TYPEDEFS
515 template<
size_t M,
size_t N,
typename T >
517 const T tolerance = std::numeric_limits< T >::epsilon())
519 return m0.equals( m1, tolerance );
523 template<
size_t M,
size_t N,
typename T >
524 inline void multiply(
const matrix< M, N, T >& left,
525 const matrix< M, N, T >& right,
526 matrix< M, N, T >& result )
528 result.multiply( left, right );
533 template<
size_t M,
size_t N,
typename T >
534 template<
size_t U,
size_t V >
535 void matrix< M, N, T>::convolve(
const matrix< U, V, T >& kernel)
537 matrix< M, N, T> temp;
539 for(
size_t y_ = 0; y_ < N; ++y_)
541 for(
size_t x_ = 0; x_ < M; ++x_)
545 for(
size_t j = 0; j < V; ++j)
547 int srcy = y_ - V/2 + j;
550 if(srcy < 0) srcy = 0;
551 if(srcy >=
int(N)) srcy = N-1;
553 for(
size_t i = 0; i < U; ++i)
555 int srcx = x_ - U/2 + i;
558 if(srcx < 0) srcx = 0;
559 if(srcx >=
int(M)) srcx = M-1;
561 sum += kernel.at(j,i) * at(srcy,srcx);
564 temp.at(y_,x_) = sum;
573 template<
size_t M,
size_t N,
size_t P,
typename T >
575 multiply(
const matrix< M, P, T >& left,
const matrix< P, N, T >& right,
576 matrix< M, N, T >& result )
578 result.multiply( left, right );
582 template<
size_t M,
size_t N,
typename T >
583 inline typename enable_if< M == N >::type* identity( matrix< M, N, T >& m )
585 m =
static_cast< T
>( 0.0 );
586 for(
size_t index = 0; index < M; ++index )
587 m( index, index ) =
static_cast< T
>( 1.0 );
593 template<
typename T >
594 inline T compute_determinant(
const matrix< 1, 1, T >& matrix_ )
596 return matrix_.array[ 0 ];
601 template<
typename T >
602 inline T compute_determinant(
const matrix< 2, 2, T >& matrix_ )
604 const T& a = matrix_( 0, 0 );
605 const T& b = matrix_( 0, 1 );
606 const T& c = matrix_( 1, 0 );
607 const T& d = matrix_( 1, 1 );
608 return a * d - b * c;
613 template<
typename T >
614 inline T compute_determinant(
const matrix< 3, 3, T >& m_ )
617 m_( 0,0 ) * ( m_( 1,1 ) * m_( 2,2 ) - m_( 1,2 ) * m_( 2,1 ) )
618 + m_( 0,1 ) * ( m_( 1,2 ) * m_( 2,0 ) - m_( 1,0 ) * m_( 2,2 ) )
619 + m_( 0,2 ) * ( m_( 1,0 ) * m_( 2,1 ) - m_( 1,1 ) * m_( 2,0 ) );
623 template<
typename T >
624 inline T compute_determinant(
const matrix< 4, 4, T >& m )
644 m03 * m12 * m21 * m30
645 - m02 * m13 * m21 * m30
646 - m03 * m11 * m22 * m30
647 + m01 * m13 * m22 * m30
648 + m02 * m11 * m23 * m30
649 - m01 * m12 * m23 * m30
650 - m03 * m12 * m20 * m31
651 + m02 * m13 * m20 * m31
652 + m03 * m10 * m22 * m31
653 - m00 * m13 * m22 * m31
654 - m02 * m10 * m23 * m31
655 + m00 * m12 * m23 * m31
656 + m03 * m11 * m20 * m32
657 - m01 * m13 * m20 * m32
658 - m03 * m10 * m21 * m32
659 + m00 * m13 * m21 * m32
660 + m01 * m10 * m23 * m32
661 - m00 * m11 * m23 * m32
662 - m02 * m11 * m20 * m33
663 + m01 * m12 * m20 * m33
664 + m02 * m10 * m21 * m33
665 - m00 * m12 * m21 * m33
666 - m01 * m10 * m22 * m33
667 + m00 * m11 * m22 * m33;
672 template<
typename T >
673 bool compute_inverse(
const matrix< 2, 2, T >& m_, matrix< 2, 2, T >& inverse_,
674 T tolerance_ = std::numeric_limits<T>::epsilon())
676 const T det_ = compute_determinant( m_ );
677 if( fabs( det_ ) < tolerance_ )
680 const T detinv =
static_cast< T
>( 1.0 ) / det_;
682 m_.get_adjugate( inverse_ );
689 template<
typename T >
690 bool compute_inverse(
const matrix< 3, 3, T >& m_, matrix< 3, 3, T >& inverse_,
691 T tolerance_ = std::numeric_limits<T>::epsilon() )
695 inverse_.at( 0, 0 ) = m_.at( 1, 1 ) * m_.at( 2, 2 ) - m_.at( 1, 2 ) * m_.at( 2, 1 );
696 inverse_.at( 0, 1 ) = m_.at( 0, 2 ) * m_.at( 2, 1 ) - m_.at( 0, 1 ) * m_.at( 2, 2 );
697 inverse_.at( 0, 2 ) = m_.at( 0, 1 ) * m_.at( 1, 2 ) - m_.at( 0, 2 ) * m_.at( 1, 1 );
698 inverse_.at( 1, 0 ) = m_.at( 1, 2 ) * m_.at( 2, 0 ) - m_.at( 1, 0 ) * m_.at( 2, 2 );
699 inverse_.at( 1, 1 ) = m_.at( 0, 0 ) * m_.at( 2, 2 ) - m_.at( 0, 2 ) * m_.at( 2, 0 );
700 inverse_.at( 1, 2 ) = m_.at( 0, 2 ) * m_.at( 1, 0 ) - m_.at( 0, 0 ) * m_.at( 1, 2 );
701 inverse_.at( 2, 0 ) = m_.at( 1, 0 ) * m_.at( 2, 1 ) - m_.at( 1, 1 ) * m_.at( 2, 0 );
702 inverse_.at( 2, 1 ) = m_.at( 0, 1 ) * m_.at( 2, 0 ) - m_.at( 0, 0 ) * m_.at( 2, 1 );
703 inverse_.at( 2, 2 ) = m_.at( 0, 0 ) * m_.at( 1, 1 ) - m_.at( 0, 1 ) * m_.at( 1, 0 );
705 const T determinant =
706 m_.at( 0, 0 ) * inverse_.at( 0, 0 )
707 + m_.at( 0, 1 ) * inverse_.at( 1, 0 )
708 + m_.at( 0, 2 ) * inverse_.at( 2, 0 );
710 if ( fabs( determinant ) <= tolerance_ )
713 const T detinv =
static_cast< T
>( 1.0 ) / determinant;
715 inverse_.at( 0, 0 ) *= detinv;
716 inverse_.at( 0, 1 ) *= detinv;
717 inverse_.at( 0, 2 ) *= detinv;
718 inverse_.at( 1, 0 ) *= detinv;
719 inverse_.at( 1, 1 ) *= detinv;
720 inverse_.at( 1, 2 ) *= detinv;
721 inverse_.at( 2, 0 ) *= detinv;
722 inverse_.at( 2, 1 ) *= detinv;
723 inverse_.at( 2, 2 ) *= detinv;
729 template<
typename T >
730 bool compute_inverse(
const matrix< 4, 4, T >& m_,
731 matrix< 4, 4, T >& inv_,
732 T tolerance_ = std::numeric_limits<T>::epsilon() )
734 const T* array = m_.array;
738 const T t1[6] = { array[ 2] * array[ 7] - array[ 6] * array[ 3],
739 array[ 2] * array[11] - array[10] * array[ 3],
740 array[ 2] * array[15] - array[14] * array[ 3],
741 array[ 6] * array[11] - array[10] * array[ 7],
742 array[ 6] * array[15] - array[14] * array[ 7],
743 array[10] * array[15] - array[14] * array[11] };
746 inv_.array[0] = array[ 5] * t1[5] - array[ 9] * t1[4] + array[13] * t1[3];
747 inv_.array[1] = array[ 9] * t1[2] - array[13] * t1[1] - array[ 1] * t1[5];
748 inv_.array[2] = array[13] * t1[0] - array[ 5] * t1[2] + array[ 1] * t1[4];
749 inv_.array[3] = array[ 5] * t1[1] - array[ 1] * t1[3] - array[ 9] * t1[0];
750 inv_.array[4] = array[ 8] * t1[4] - array[ 4] * t1[5] - array[12] * t1[3];
751 inv_.array[5] = array[ 0] * t1[5] - array[ 8] * t1[2] + array[12] * t1[1];
752 inv_.array[6] = array[ 4] * t1[2] - array[12] * t1[0] - array[ 0] * t1[4];
753 inv_.array[7] = array[ 0] * t1[3] - array[ 4] * t1[1] + array[ 8] * t1[0];
756 const T t2[6] = { array[ 0] * array[ 5] - array[ 4] * array[ 1],
757 array[ 0] * array[ 9] - array[ 8] * array[ 1],
758 array[ 0] * array[13] - array[12] * array[ 1],
759 array[ 4] * array[ 9] - array[ 8] * array[ 5],
760 array[ 4] * array[13] - array[12] * array[ 5],
761 array[ 8] * array[13] - array[12] * array[ 9] };
764 inv_.array[8] = array[ 7] * t2[5] - array[11] * t2[4] + array[15] * t2[3];
765 inv_.array[9] = array[11] * t2[2] - array[15] * t2[1] - array[ 3] * t2[5];
766 inv_.array[10] = array[15] * t2[0] - array[ 7] * t2[2] + array[ 3] * t2[4];
767 inv_.array[11] = array[ 7] * t2[1] - array[ 3] * t2[3] - array[11] * t2[0];
768 inv_.array[12] = array[10] * t2[4] - array[ 6] * t2[5] - array[14] * t2[3];
769 inv_.array[13] = array[ 2] * t2[5] - array[10] * t2[2] + array[14] * t2[1];
770 inv_.array[14] = array[ 6] * t2[2] - array[14] * t2[0] - array[ 2] * t2[4];
771 inv_.array[15] = array[ 2] * t2[3] - array[ 6] * t2[1] + array[10] * t2[0];
774 const T determinant = array[0] * inv_.array[0] + array[4] * inv_.array[1] +
775 array[8] * inv_.array[2] + array[12] * inv_.array[3];
777 if( fabs( determinant ) <= tolerance_ )
781 const T detinv =
static_cast< T
>( 1.0 ) / determinant;
783 for(
size_t i = 0; i != 16; ++i )
784 inv_.array[i] *= detinv;
792 template<
size_t M,
size_t N,
typename T >
793 inline matrix< N, M, T >
794 transpose(
const matrix< M, N, T >& matrix_ )
796 matrix< N, M, T > transpose_;
797 matrix_.transpose_to( transpose_ );
802 template<
size_t M,
size_t N,
typename T >
803 bool is_positive_definite(
const matrix< M, N, T >& matrix_,
804 const T limit = -1e12,
805 typename enable_if< M == N && M <= 3 >::type* = 0 )
807 if ( matrix_.at( 0, 0 ) < limit )
814 matrix_.get_sub_matrix( m, 0, 0 );
815 if ( compute_determinant( m ) < limit )
822 matrix_.get_sub_matrix( m, 0, 0 );
823 if ( compute_determinant( m ) < limit )
831 template<
size_t M,
size_t N,
typename T >
832 matrix< M, N, T >::matrix()
836 for(
size_t i = 0; i < M; ++i )
837 at( i, i ) =
static_cast< T
>( 1.0 );
840 template<
size_t M,
size_t N,
typename T >
841 template<
size_t P,
size_t Q,
typename U >
842 matrix< M, N, T >::matrix(
const matrix< P, Q, U >& source_ )
848 template<
size_t M,
size_t N,
typename T >
849 inline T& matrix< M, N, T >::at(
size_t row_index,
size_t col_index )
851 #ifdef VMMLIB_SAFE_ACCESSORS
852 if ( row_index >= M || col_index >= N )
853 VMMLIB_ERROR(
"at( row, col ) - index out of bounds", VMMLIB_HERE );
855 return array[ col_index * M + row_index ];
860 template<
size_t M,
size_t N,
typename T >
862 matrix< M, N, T >::at(
size_t row_index,
size_t col_index )
const
864 #ifdef VMMLIB_SAFE_ACCESSORS
865 if ( row_index >= M || col_index >= N )
866 VMMLIB_ERROR(
"at( row, col ) - index out of bounds", VMMLIB_HERE );
868 return array[ col_index * M + row_index ];
872 template<
size_t M,
size_t N,
typename T >
874 matrix< M, N, T >::operator()(
size_t row_index,
size_t col_index )
876 return at( row_index, col_index );
881 template<
size_t M,
size_t N,
typename T >
883 matrix< M, N, T >::operator()(
size_t row_index,
size_t col_index )
const
885 return at( row_index, col_index );
888 #ifndef VMMLIB_NO_CONVERSION_OPERATORS
890 template<
size_t M,
size_t N,
typename T >
899 template<
size_t M,
size_t N,
typename T >
901 operator
const T*()
const
909 template<
size_t M,
size_t N,
typename T >
912 operator==(
const matrix< M, N, T >& other )
const
915 for(
size_t i = 0; is_ok && i < M * N; ++i )
917 is_ok = array[ i ] == other.array[ i ];
925 template<
size_t M,
size_t N,
typename T >
928 operator!=(
const matrix< M, N, T >& other )
const
930 return ! operator==( other );
935 template<
size_t M,
size_t N,
typename T >
938 equals(
const matrix< M, N, T >& other, T tolerance )
const
941 for(
size_t row_index = 0; is_ok && row_index < M; row_index++)
943 for(
size_t col_index = 0; is_ok && col_index < N; col_index++)
945 is_ok = fabs( at( row_index, col_index ) - other( row_index, col_index ) ) < tolerance;
953 template<
size_t M,
size_t N,
typename T >
954 template<
typename compare_t >
955 bool matrix< M, N, T >::equals(
const matrix< M, N, T >& other_matrix,
956 compare_t& cmp )
const
959 for(
size_t row = 0; is_ok && row < M; ++row )
961 for(
size_t col = 0; is_ok && col < N; ++col)
963 is_ok = cmp( at( row, col ), other_matrix.at( row, col ) );
969 #if (( __GNUC__ > 4 ) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) )
970 # pragma GCC diagnostic ignored "-Warray-bounds" // gcc 4.4.7 bug WAR
972 template<
size_t M,
size_t N,
typename T >
973 const matrix< M, N, T >&
974 matrix< M, N, T >::operator=(
const matrix< M, N, T >& source_ )
976 memcpy( array, source_.array, M * N *
sizeof( T ));
979 #if (( __GNUC__ > 4 ) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) )
980 # pragma GCC diagnostic warning "-Warray-bounds"
983 template<
size_t M,
size_t N,
typename T >
984 template<
size_t P,
size_t Q,
typename U >
985 void matrix< M, N, T >::operator=(
const matrix< P, Q, U >& source_ )
987 const size_t minL = P < M ? P : M;
988 const size_t minC = Q < N ? Q : N;
990 if( minL < M || minC < N )
993 for (
size_t i = 0 ; i < minL ; i++ )
994 for (
size_t j = 0 ; j < minC ; j++ )
995 at( i,j ) =
static_cast< T
>( source_( i, j ));
999 template<
size_t M,
size_t N,
typename T >
1000 void matrix< M, N, T >::operator=(
const T old_fashioned_matrix[ M ][ N ] )
1002 for(
size_t row = 0; row < M; row++)
1004 for(
size_t col = 0; col < N; col++)
1006 at( row, col ) = old_fashioned_matrix[ row ][ col ];
1016 template<
size_t M,
size_t N,
typename T >
1018 matrix< M, N, T >::operator=(
const T* data_array )
1020 set( data_array, data_array + M * N,
true );
1025 template<
size_t M,
size_t N,
typename T >
1027 matrix< M, N, T >::operator=(
const std::vector< T >& data )
1029 if ( data.size() < M * N )
1030 VMMLIB_ERROR(
"index out of bounds.", VMMLIB_HERE );
1032 set( data.begin(), data.end(), true );
1036 template<
size_t M,
size_t N,
typename T >
1038 matrix< M, N, T >::multiply_piecewise(
const matrix& other )
1040 for(
size_t row_index = 0; row_index < M; row_index++)
1042 for(
size_t col_index = 0; col_index < N; col_index++ )
1044 T& value = at( row_index, col_index );
1045 value *= other.at( row_index, col_index );
1051 template<
size_t M,
size_t N,
typename T >
1052 template<
size_t P >
1054 matrix< M, N, T >::multiply(
1055 const matrix< M, P, T >& left,
1056 const matrix< P, N, T >& right
1059 for(
size_t row_index = 0; row_index < M; row_index++)
1061 for(
size_t col_index = 0; col_index < N; col_index++)
1063 T& component = at( row_index, col_index );
1064 component =
static_cast< T
>( 0.0 );
1065 for(
size_t p = 0; p < P; p++)
1067 component += left.at( row_index, p ) * right.at( p, col_index );
1075 template<
size_t M,
size_t N,
typename T >
1076 template<
size_t P >
1078 matrix< M, N, T >::operator*(
const matrix< N, P, T >& other )
const
1080 matrix< M, P, T > result;
1081 result.multiply( *
this, other );
1087 template<
size_t M,
size_t N,
typename T >
1088 template<
size_t O,
size_t P,
typename TT >
1089 typename enable_if< M == N && O == P && M == O, TT >::type*
1090 matrix< M, N, T >::operator*=(
const matrix< O, P, TT >& right )
1092 matrix< M, N, T > copy( *
this );
1093 multiply( copy, right );
1097 template<
size_t M,
size_t N,
typename T >
1099 matrix< M, N, T >::operator/( T scalar )
1101 matrix< M, N, T > result;
1103 for(
size_t row_index = 0; row_index < M; ++row_index )
1105 for(
size_t col_index = 0; col_index < N; ++col_index )
1107 result.at( row_index, col_index ) = at( row_index, col_index ) / scalar;
1115 template<
size_t M,
size_t N,
typename T >
1117 matrix< M, N, T >::operator/=( T scalar )
1119 for(
size_t row_index = 0; row_index < M; ++row_index )
1121 for(
size_t col_index = 0; col_index < N; ++col_index )
1123 at( row_index, col_index ) /= scalar;
1132 template<
size_t M,
size_t N,
typename T >
1134 matrix< M, N, T >::operator*( T scalar )
1136 matrix< M, N, T > result;
1138 for(
size_t row_index = 0; row_index < M; ++row_index )
1140 for(
size_t col_index = 0; col_index < N; ++col_index )
1142 result.at( row_index, col_index ) = at( row_index, col_index ) * scalar;
1150 template<
size_t M,
size_t N,
typename T >
1152 matrix< M, N, T >::operator*=( T scalar )
1154 for(
size_t row_index = 0; row_index < M; ++row_index )
1156 for(
size_t col_index = 0; col_index < N; ++col_index )
1158 at( row_index, col_index ) *= scalar;
1165 template<
size_t M,
size_t N,
typename T >
1166 vector< M, T > matrix< M, N, T >::operator*(
const vector< N, T >& vec )
const
1168 vector< M, T > result;
1171 for(
size_t i = 0; i < M; ++i )
1174 for(
size_t j = 0; j < N; ++j )
1175 tmp += at( i, j ) * vec.at( j );
1176 result.at( i ) = tmp;
1185 template<
size_t M,
size_t N,
typename T >
1186 template<
size_t O > vector< O, T >
1187 matrix< M, N, T >::operator*(
const vector< O, T >& vector_ )
const
1189 vector< O, T > result;
1191 for(
size_t row_index = 0; row_index < M; ++row_index )
1194 for(
size_t col_index = 0; col_index < N-1; ++col_index )
1196 tmp += vector_( col_index ) * at( row_index, col_index );
1198 if ( row_index < N - 1 )
1199 result( row_index ) = tmp + at( row_index, N-1 );
1202 tmp += at( row_index, N - 1 );
1203 for(
size_t col_index = 0; col_index < N - 1; ++col_index )
1205 result( col_index ) /= tmp;
1214 template<
size_t M,
size_t N,
typename T >
1215 inline matrix< M, N, T >
1216 matrix< M, N, T >::operator-()
const
1223 template<
size_t M,
size_t N,
typename T >
1225 matrix< M, N, T >::negate()
const
1227 matrix< M, N, T > result;
1234 template<
size_t M,
size_t N,
typename T >
1236 matrix< M, N, T >::tensor(
const vector< M, T >& u,
const vector< N, T >& v )
1238 for (
size_t col_index = 0; col_index < N; ++col_index )
1239 for (
size_t row_index = 0; row_index < M; ++row_index )
1240 at( row_index, col_index ) = u.array[ col_index ] *
1241 v.array[ row_index ];
1246 template<
size_t M,
size_t N,
typename T >
1247 template<
size_t uM,
size_t vM >
1248 typename enable_if< uM == 3 && vM == 3 && M == N && M == 4 >::type*
1249 matrix< M, N, T >::tensor(
const vector< uM, T >& u,
const vector< vM, T >& v )
1251 for (
size_t col_index = 0; col_index < 3; ++col_index )
1253 for (
size_t row_index = 0; row_index < 3; ++row_index )
1254 at( row_index, col_index ) = u.array[ col_index ] *
1255 v.array[ row_index ];
1257 at( 3, col_index ) = u.array[ col_index ];
1260 for (
size_t row_index = 0; row_index < 3; ++row_index )
1261 at( row_index, 3 ) = v.array[ row_index ];
1270 template<
size_t M,
size_t N,
typename T >
1273 transpose_to( matrix< N, M, T >& tM )
const
1275 for(
size_t row = 0; row < M; ++row )
1277 for(
size_t col = 0; col < N; ++col )
1279 tM.at( col, row ) = at( row, col );
1284 template<
size_t M,
size_t N,
typename T >
1287 symmetric_covariance( matrix< M, M, T >& cov_m_ )
const
1290 for(
size_t row = 0; row < M; ++row )
1292 for(
size_t col = row; col < M; ++col )
1294 for (
size_t k = 0; k < N; ++k )
1296 tmp += (at( row, k ) * at( col, k ));
1299 cov_m_.at( row, col ) = tmp;
1300 cov_m_.at( col, row ) = tmp;
1308 template<
size_t M,
size_t N,
typename T >
1309 vector< M, T > matrix< M, N, T >::get_column(
size_t index )
const
1311 vector< M, T > column;
1312 get_column( index, column );
1318 template<
size_t M,
size_t N,
typename T >
1319 void matrix< M, N, T >::get_column(
size_t index, vector< M, T >& column )
const
1321 #ifdef VMMLIB_SAFE_ACCESSORS
1323 VMMLIB_ERROR(
"get_column() - index out of bounds.", VMMLIB_HERE );
1326 memcpy( &column.array[0], &array[ M * index ], M *
sizeof( T ) );
1331 template<
size_t M,
size_t N,
typename T >
1332 void matrix< M, N, T >::set_column(
size_t index,
const vector< M, T >& column )
1334 #ifdef VMMLIB_SAFE_ACCESSORS
1337 VMMLIB_ERROR(
"set_column() - index out of bounds.", VMMLIB_HERE );
1341 memcpy( array + M * index, column.array, M *
sizeof( T ) );
1344 template<
size_t M,
size_t N,
typename T >
1345 void matrix< M, N, T >::get_column(
size_t index, matrix< M, 1, T >& column )
1348 #ifdef VMMLIB_SAFE_ACCESSORS
1350 VMMLIB_ERROR(
"get_column() - index out of bounds.", VMMLIB_HERE );
1353 memcpy( column.array, array + M * index, M *
sizeof( T ) );
1356 template<
size_t M,
size_t N,
typename T >
1357 void matrix< M, N, T >::set_column(
size_t index,
1358 const matrix< M, 1, T >& column )
1360 #ifdef VMMLIB_SAFE_ACCESSORS
1362 VMMLIB_ERROR(
"set_column() - index out of bounds.", VMMLIB_HERE );
1365 memcpy( &array[ M * index ], column.array, M *
sizeof( T ) );
1368 template<
size_t M,
size_t N,
typename T >
1369 vector< N, T > matrix< M, N, T >::get_row(
size_t index )
const
1372 get_row( index, row );
1376 template<
size_t M,
size_t N,
typename T >
1377 void matrix< M, N, T >::get_row(
size_t row_index, vector< N, T >& row )
const
1379 #ifdef VMMLIB_SAFE_ACCESSORS
1380 if ( row_index >= M )
1381 VMMLIB_ERROR(
"get_row() - index out of bounds.", VMMLIB_HERE );
1384 for(
size_t col_index = 0; col_index < N; ++col_index )
1386 row.at( col_index ) = at( row_index, col_index );
1390 template<
size_t M,
size_t N,
typename T >
1391 void matrix< M, N, T >::set_row(
size_t row_index,
const vector< N, T >& row )
1393 #ifdef VMMLIB_SAFE_ACCESSORS
1394 if ( row_index >= M )
1395 VMMLIB_ERROR(
"set_row() - index out of bounds.", VMMLIB_HERE );
1398 for(
size_t col_index = 0; col_index < N; ++col_index )
1400 at( row_index, col_index ) = row.at( col_index );
1404 template<
size_t M,
size_t N,
typename T >
1405 void matrix< M, N, T >::get_row(
size_t row_index, matrix< 1, N, T >& row )
1408 #ifdef VMMLIB_SAFE_ACCESSORS
1409 if ( row_index >= M )
1410 VMMLIB_ERROR(
"get_row() - index out of bounds.", VMMLIB_HERE );
1413 for(
size_t col_index = 0; col_index < N; ++col_index )
1415 row.at( 0, col_index ) = at( row_index, col_index );
1419 template<
size_t M,
size_t N,
typename T >
1420 void matrix< M, N, T >::set_row(
size_t row_index,
1421 const matrix< 1, N, T >& row )
1423 #ifdef VMMLIB_SAFE_ACCESSORS
1424 if ( row_index >= M )
1425 VMMLIB_ERROR(
"set_row() - index out of bounds.", VMMLIB_HERE );
1428 for(
size_t col_index = 0; col_index < N; ++col_index )
1430 at( row_index, col_index ) = row.at( 0, col_index );
1434 template<
size_t M,
size_t N,
typename T >
1437 get_number_of_rows()
const
1444 template<
size_t M,
size_t N,
typename T >
1447 get_number_of_columns()
const
1454 template<
size_t M,
size_t N,
typename T >
1459 for(
size_t row_index = 0; row_index < M; ++row_index )
1461 for(
size_t col_index = 0; col_index < N; ++col_index )
1463 at( row_index, col_index ) = fillValue;
1469 template<
size_t M,
size_t N,
typename T >
1471 matrix< M, N, T >::x()
1478 template<
size_t M,
size_t N,
typename T >
1480 matrix< M, N, T >::y()
1487 template<
size_t M,
size_t N,
typename T >
1489 matrix< M, N, T >::z()
1494 template<
size_t M,
size_t N,
typename T >
1495 template<
typename input_iterator_t >
1496 void matrix< M, N, T >::set( input_iterator_t begin_,
1497 input_iterator_t end_,
bool row_major_layout )
1499 input_iterator_t it( begin_ );
1500 if( row_major_layout )
1502 for(
size_t row = 0; row < M; ++row )
1504 for(
size_t col = 0; col < N; ++col, ++it )
1508 at( row, col ) =
static_cast< T
>( *it );
1514 std::copy( it, it + ( M * N ), begin() );
1520 template<
size_t M,
size_t N,
typename T >
1521 void matrix< M, N, T >::zero()
1523 fill( static_cast< T >( 0.0 ) );
1526 template<
size_t M,
size_t N,
typename T >
1527 void matrix< M, N, T >::operator=( T value_ )
1529 std::fill( begin(), end(), value_ );
1534 template<
size_t M,
size_t N,
typename T >
1535 inline matrix< M, N, T >
1536 matrix< M, N, T >::operator+(
const matrix< M, N, T >& other )
const
1538 matrix< M, N, T > result( *
this );
1545 template<
size_t M,
size_t N,
typename T >
1546 void matrix< M, N, T >::operator+=(
const matrix< M, N, T >& other )
1548 iterator it = begin(), it_end = end();
1549 const_iterator other_it = other.begin();
1550 for( ; it != it_end; ++it, ++other_it )
1557 template<
size_t M,
size_t N,
typename T >
1558 void matrix< M, N, T >::operator+=( T scalar )
1560 iterator it = begin(), it_end = end();
1561 for( ; it != it_end; ++it )
1567 template<
size_t M,
size_t N,
typename T >
1568 inline matrix< M, N, T >
1570 operator-(
const matrix< M, N, T >& other )
const
1572 matrix< M, N, T > result( *
this );
1579 template<
size_t M,
size_t N,
typename T >
1582 operator-=(
const matrix< M, N, T >& other )
1584 iterator it = begin(), it_end = end();
1585 const_iterator other_it = other.begin();
1586 for( ; it != it_end; ++it, ++other_it )
1592 template<
size_t M,
size_t N,
typename T >
1594 matrix< M, N, T >::operator-=( T scalar )
1596 iterator it = begin(), it_end = end();
1597 for( ; it != it_end; ++it )
1604 template<
size_t M,
size_t N,
typename T >
1605 template<
size_t O,
size_t P,
size_t Q,
size_t R >
1606 typename enable_if< M == O + Q && N == P + R >::type*
1607 matrix< M, N, T >::direct_sum(
const matrix< O, P, T >& upper_left,
1608 const matrix< Q, R, T >& lower_right )
1610 (*this) =
static_cast< T
>( 0.0 );
1612 for(
size_t row = 0; row < O; ++row )
1614 for(
size_t col = 0; col < P; ++col )
1616 at( row, col ) = upper_left( row, col );
1620 for(
size_t row = 0; row < Q; ++row )
1622 for(
size_t col = 0; col < R; ++col )
1624 at( O + row, P + col ) = lower_right( row, col );
1633 template<
size_t M,
size_t N,
typename T >
1634 template<
size_t O,
size_t P >
1636 matrix< M, N, T >::get_sub_matrix(
size_t row_offset,
size_t col_offset,
1637 typename enable_if< O <= M && P <= N >::type* )
const
1639 matrix< O, P, T > result;
1640 get_sub_matrix( result, row_offset, col_offset );
1646 template<
size_t M,
size_t N,
typename T >
1647 template<
size_t O,
size_t P >
1648 typename enable_if< O <= M && P <= N >::type*
1650 get_sub_matrix( matrix< O, P, T >& result,
1651 size_t row_offset,
size_t col_offset )
const
1653 #ifdef VMMLIB_SAFE_ACCESSORS
1654 if ( O + row_offset > M || P + col_offset > N )
1655 VMMLIB_ERROR(
"index out of bounds.", VMMLIB_HERE );
1658 for(
size_t row = 0; row < O; ++row )
1660 for(
size_t col = 0; col < P; ++col )
1662 result.at( row, col )
1663 = at( row_offset + row, col_offset + col );
1671 template<
size_t M,
size_t N,
typename T >
1672 template<
size_t O,
size_t P >
1673 typename enable_if< O <= M && P <= N >::type*
1675 set_sub_matrix(
const matrix< O, P, T >& sub_matrix,
1676 size_t row_offset,
size_t col_offset )
1678 for(
size_t row = 0; row < O; ++row )
1680 for(
size_t col = 0; col < P; ++col )
1682 at( row_offset + row, col_offset + col )
1683 = sub_matrix.at( row, col );
1691 template<
size_t M,
size_t N,
typename T >
1693 matrix< M, N, T >::det()
const
1695 return compute_determinant( *
this );
1700 template<
size_t M,
size_t N,
typename T >
1701 template<
size_t O,
size_t P,
typename TT >
1702 inline bool matrix< M, N, T >::inverse( matrix< O, P, TT >& inverse_,
1703 T tolerance,
typename
1704 enable_if< M == N && O == P && O == M && M >= 2 && M <= 4, TT >::type* )
1707 return compute_inverse( *
this, inverse_, tolerance );
1712 template<
size_t M,
size_t N,
typename T >
1713 template<
size_t O,
size_t P >
1714 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
1716 get_adjugate( matrix< O, P, T >& adjugate )
const
1718 get_cofactors( adjugate );
1719 adjugate = transpose( adjugate );
1725 template<
size_t M,
size_t N,
typename T >
1726 template<
size_t O,
size_t P >
1727 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
1729 get_cofactors( matrix< O, P, T >& cofactors )
const
1731 matrix< M-1, N-1, T > minor_;
1733 const size_t _negate = 1u;
1734 for(
size_t row_index = 0; row_index < M; ++row_index )
1736 for(
size_t col_index = 0; col_index < N; ++col_index )
1738 if ( ( row_index + col_index ) & _negate )
1739 cofactors( row_index, col_index ) = -get_minor( minor_, row_index, col_index );
1741 cofactors( row_index, col_index ) = get_minor( minor_, row_index, col_index );
1749 template<
size_t M,
size_t N,
typename T >
1750 template<
size_t O,
size_t P >
1753 get_minor( matrix< O, P, T >& minor_,
size_t row_to_cut,
size_t col_to_cut,
1754 typename enable_if< O == M-1 && P == N-1 && M == N && M >= 2 >::type* )
const
1756 size_t row_offset = 0;
1757 size_t col_offset = 0;
1758 for(
size_t row_index = 0; row_index < M; ++row_index )
1760 if ( row_index == row_to_cut )
1764 for(
size_t col_index = 0; col_index < M; ++col_index )
1766 if ( col_index == col_to_cut )
1769 minor_.at( row_index + row_offset, col_index + col_offset )
1770 = at( row_index, col_index );
1775 return compute_determinant( minor_ );
1778 template<
size_t M,
size_t N,
typename T >
1779 template<
typename TT >
1780 matrix< M, N, T >& matrix< M, N, T >::rotate(
1781 const TT angle_,
const vector< M-1, T >& axis,
1782 typename enable_if< M == N && M == 4, TT >::type* )
1784 const T angle =
static_cast< T
>( angle_ );
1786 const T sine = std::sin( angle );
1787 const T cosine = std::cos( angle );
1794 const T _zero = 0.0;
1798 array[0] = cosine + ( one - cosine ) * std::pow( axis.array[0], two );
1799 array[1] = ( one - cosine ) * axis.array[0] * axis.array[1] + sine * axis.array[2];
1800 array[2] = ( one - cosine ) * axis.array[0] * axis.array[2] - sine * axis.array[1];
1803 array[4] = ( one - cosine ) * axis.array[0] * axis.array[1] - sine * axis.array[2];
1804 array[5] = cosine + ( one - cosine ) * std::pow( axis.array[1], two );
1805 array[6] = ( one - cosine ) * axis.array[1] * axis.array[2] + sine * axis.array[0];
1808 array[8] = ( one - cosine ) * axis.array[0] * axis.array[2] + sine * axis.array[1];
1809 array[9] = ( one - cosine ) * axis.array[1] * axis.array[2] - sine * axis.array[0];
1810 array[10] = cosine + ( one - cosine ) * std::pow( axis.array[2], two );
1821 template<
size_t M,
size_t N,
typename T >
1822 template<
typename TT >
1823 matrix< M, N, T >& matrix< M, N, T >::rotate_x(
const TT angle_,
1824 typename enable_if< M == N && M == 4, TT >::type* )
1826 const T angle =
static_cast< T
>( angle_ );
1828 const T sine = std::sin( angle );
1829 const T cosine = std::cos( angle );
1833 tmp = array[ 4 ] * cosine + array[ 8 ] * sine;
1834 array[ 8 ] = - array[ 4 ] * sine + array[ 8 ] * cosine;
1837 tmp = array[ 5 ] * cosine + array[ 9 ] * sine;
1838 array[ 9 ] = - array[ 5 ] * sine + array[ 9 ] * cosine;
1841 tmp = array[ 6 ] * cosine + array[ 10 ] * sine;
1842 array[ 10 ] = - array[ 6 ] * sine + array[ 10 ] * cosine;
1845 tmp = array[ 7 ] * cosine + array[ 11 ] * sine;
1846 array[ 11 ] = - array[ 7 ] * sine + array[ 11 ] * cosine;
1852 template<
size_t M,
size_t N,
typename T >
1853 template<
typename TT >
1854 matrix< M, N, T >& matrix< M, N, T >::rotate_y(
const TT angle_,
1855 typename enable_if< M == N && M == 4, TT >::type* )
1857 const T angle =
static_cast< T
>( angle_ );
1859 const T sine = std::sin( angle );
1860 const T cosine = std::cos( angle );
1864 tmp = array[ 0 ] * cosine - array[ 8 ] * sine;
1865 array[ 8 ] = array[ 0 ] * sine + array[ 8 ] * cosine;
1868 tmp = array[ 1 ] * cosine - array[ 9 ] * sine;
1869 array[ 9 ] = array[ 1 ] * sine + array[ 9 ] * cosine;
1872 tmp = array[ 2 ] * cosine - array[ 10 ] * sine;
1873 array[ 10 ] = array[ 2 ] * sine + array[ 10 ] * cosine;
1876 tmp = array[ 3 ] * cosine - array[ 11 ] * sine;
1877 array[ 11 ] = array[ 3 ] * sine + array[ 11 ] * cosine;
1883 template<
size_t M,
size_t N,
typename T >
1884 template<
typename TT >
1885 matrix< M, N, T >& matrix< M, N, T >::rotate_z(
const TT angle_,
1886 typename enable_if< M == N && M == 4, TT >::type* )
1888 const T angle =
static_cast< T
>( angle_ );
1890 const T sine = std::sin( angle );
1891 const T cosine = std::cos( angle );
1895 tmp = array[ 0 ] * cosine + array[ 4 ] * sine;
1896 array[ 4 ] = - array[ 0 ] * sine + array[ 4 ] * cosine;
1899 tmp = array[ 1 ] * cosine + array[ 5 ] * sine;
1900 array[ 5 ] = - array[ 1 ] * sine + array[ 5 ] * cosine;
1903 tmp = array[ 2 ] * cosine + array[ 6 ] * sine;
1904 array[ 6 ] = - array[ 2 ] * sine + array[ 6 ] * cosine;
1907 tmp = array[ 3 ] * cosine + array[ 7 ] * sine;
1908 array[ 7 ] = - array[ 3 ] * sine + array[ 7 ] * cosine;
1914 template<
size_t M,
size_t N,
typename T >
1915 template<
typename TT >
1916 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_x(
const TT angle_,
1917 typename enable_if< M == N && M == 4, TT >::type* )
1919 const T angle =
static_cast< T
>( angle_ );
1921 const T sine = std::sin( angle );
1922 const T cosine = std::cos( angle );
1927 array[ 1 ] = array[ 1 ] * cosine + array[ 2 ] * sine;
1928 array[ 2 ] = tmp * -sine + array[ 2 ] * cosine;
1931 array[ 5 ] = array[ 5 ] * cosine + array[ 6 ] * sine;
1932 array[ 6 ] = tmp * -sine + array[ 6 ] * cosine;
1935 array[ 9 ] = array[ 9 ] * cosine + array[ 10 ] * sine;
1936 array[ 10 ] = tmp * -sine + array[ 10 ] * cosine;
1939 array[ 13 ] = array[ 13 ] * cosine + array[ 14 ] * sine;
1940 array[ 14 ] = tmp * -sine + array[ 14 ] * cosine;
1945 template<
size_t M,
size_t N,
typename T >
1946 template<
typename TT >
1947 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_y(
const TT angle_,
1948 typename enable_if< M == N && M == 4, TT >::type* )
1950 const T angle =
static_cast< T
>( angle_ );
1952 const T sine = std::sin( angle );
1953 const T cosine = std::cos( angle );
1958 array[ 0 ] = array[ 0 ] * cosine - array[ 2 ] * sine;
1959 array[ 2 ] = tmp * sine + array[ 2 ] * cosine;
1962 array[ 4 ] = array[ 4 ] * cosine - array[ 6 ] * sine;
1963 array[ 6 ] = tmp * sine + array[ 6 ] * cosine;
1966 array[ 8 ] = array[ 8 ] * cosine - array[ 10 ] * sine;
1967 array[ 10 ] = tmp * sine + array[ 10 ] * cosine;
1970 array[ 12 ] = array[ 12 ] * cosine - array[ 14 ] * sine;
1971 array[ 14 ] = tmp * sine + array[ 14 ] * cosine;
1976 template<
size_t M,
size_t N,
typename T >
1977 template<
typename TT >
1978 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_z(
const TT angle_,
1979 typename enable_if< M == N && M == 4, TT >::type* )
1981 const T angle =
static_cast< T
>( angle_ );
1983 const T sine = std::sin( angle );
1984 const T cosine = std::cos( angle );
1989 array[ 0 ] = array[ 0 ] * cosine + array[ 1 ] * sine;
1990 array[ 1 ] = tmp * -sine + array[ 1 ] * cosine;
1993 array[ 4 ] = array[ 4 ] * cosine + array[ 5 ] * sine;
1994 array[ 5 ] = tmp * -sine + array[ 5 ] * cosine;
1997 array[ 8 ] = array[ 8 ] * cosine + array[ 9 ] * sine;
1998 array[ 9 ] = tmp * -sine + array[ 9 ] * cosine;
2001 array[ 12 ] = array[ 12 ] * cosine + array[ 13 ] * sine;
2002 array[ 13 ] = tmp * -sine + array[ 13 ] * cosine;
2007 template<
size_t M,
size_t N,
typename T >
2008 template<
typename TT >
2009 matrix< M, N, T >& matrix< M, N, T >::scale(
const TT _scale[3],
2010 typename enable_if< M == N && M == 4, TT >::type* )
2012 const T scale0 =
static_cast< T
>( _scale[ 0 ] );
2013 const T scale1 =
static_cast< T
>( _scale[ 1 ] );
2014 const T scale2 =
static_cast< T
>( _scale[ 2 ] );
2026 array[10] *= scale2;
2027 array[11] *= scale2;
2032 template<
size_t M,
size_t N,
typename T >
2033 template<
typename TT >
2034 matrix< M, N, T >& matrix< M, N, T >::scale(
const TT x_,
const T y_,
const T z_,
2035 typename enable_if< M == N && M == 4, TT >::type* )
2037 const T _x =
static_cast< T
>( x_ );
2055 template<
size_t M,
size_t N,
typename T >
2056 template<
typename TT >
2057 inline matrix< M, N, T >& matrix< M, N, T >::scale(
2058 const vector< 3, TT >& scale_,
2059 typename enable_if< M == N && M == 4, TT >::type* )
2061 return scale( scale_.array );
2066 template<
size_t M,
size_t N,
typename T >
2067 template<
typename TT >
2068 matrix< M, N, T >& matrix< M, N, T >::scale_translation(
const TT scale_[3],
2069 typename enable_if< M == N && M == 4, TT >::type* )
2071 array[12] *=
static_cast< T
>( scale_[0] );
2072 array[13] *=
static_cast< T
>( scale_[1] );
2073 array[14] *=
static_cast< T
>( scale_[2] );
2077 template<
size_t M,
size_t N,
typename T >
2078 template<
typename TT >
2079 inline matrix< M, N, T >& matrix< M, N, T >::scale_translation(
2080 const vector< 3, TT >& scale_,
2081 typename enable_if< M == N && M == 4, TT >::type* )
2083 return scale_translation( scale_.array );
2086 template<
size_t M,
size_t N,
typename T >
2087 template<
typename TT >
2088 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
2089 const TT x_,
const TT y_,
const TT z_,
2090 typename enable_if< M == N && M == 4, TT >::type* )
2092 array[12] =
static_cast< T
>( x_ );
2093 array[13] =
static_cast< T
>( y_ );
2094 array[14] =
static_cast< T
>( z_ );
2098 template<
size_t M,
size_t N,
typename T >
2099 template<
typename TT >
2100 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
const TT trans[3],
2101 typename enable_if< M == N && M == 4, TT >::type* )
2103 array[12] =
static_cast< T
>( trans[ 0 ] );
2104 array[13] =
static_cast< T
>( trans[ 1 ] );
2105 array[14] =
static_cast< T
>( trans[ 2 ] );
2109 template<
size_t M,
size_t N,
typename T >
2110 template<
typename TT >
2111 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
2112 const vector< 3, TT >& translation_,
2113 typename enable_if< M == N && M == 4, TT >::type* )
2115 return set_translation( translation_.array );
2118 template<
size_t M,
size_t N,
typename T >
template<
typename TT >
inline
2119 void matrix< M, N, T >::get_translation( vector< N-1, TT >& translation_ )
2122 for(
size_t i = 0; i < N-1; ++i )
2123 translation_.array[ i ] = array[ i + M * (N - 1) ];
2127 template<
size_t M,
size_t N,
typename T >
2128 inline vector< N-1, T > matrix< M, N, T >::get_translation()
const
2130 vector< N-1, T > result;
2131 get_translation( result );
2137 template<
size_t M,
size_t N,
typename T >
2147 template<
size_t M,
size_t N,
typename T >
2148 typename matrix< M, N, T >::iterator
2157 template<
size_t M,
size_t N,
typename T >
2158 typename matrix< M, N, T >::iterator
2162 return array + size();
2167 template<
size_t M,
size_t N,
typename T >
2168 typename matrix< M, N, T >::const_iterator
2177 template<
size_t M,
size_t N,
typename T >
2178 typename matrix< M, N, T >::const_iterator
2182 return array + size();
2187 template<
size_t M,
size_t N,
typename T >
2188 typename matrix< M, N, T >::reverse_iterator
2192 return array + size() - 1;
2197 template<
size_t M,
size_t N,
typename T >
2198 typename matrix< M, N, T >::reverse_iterator
2207 template<
size_t M,
size_t N,
typename T >
2208 typename matrix< M, N, T >::const_reverse_iterator
2212 return array + size() - 1;
2217 template<
size_t M,
size_t N,
typename T >
2218 typename matrix< M, N, T >::const_reverse_iterator
2227 template<
size_t M,
size_t N,
typename T >
2228 template<
typename init_functor_t >
2229 const matrix< M, N, T >
2230 matrix< M, N, T >::get_initialized_matrix()
2232 matrix< M, N, T > matrix_;
2233 init_functor_t()( matrix_ );
2240 template<
size_t M,
size_t N,
typename T >
2241 const matrix< M, N, T >
2242 matrix< M, N, T >::IDENTITY(
2243 matrix< M, N, T >::get_initialized_matrix<
2244 set_to_identity_functor< matrix< M, N, T > > >( ));
2247 template<
size_t M,
size_t N,
typename T >
2248 const matrix< M, N, T >
2249 matrix< M, N, T >::ZERO(
2251 get_initialized_matrix< set_to_zero_functor< matrix< M, N, T > > >()
2256 template<
size_t M,
size_t N,
typename T >
2258 matrix< M, N, T >::frobenius_norm( )
const
2262 const_iterator it = begin(), it_end = end();
2263 for( ; it != it_end; ++it )
2268 return std::sqrt(norm);
2271 template<
size_t M,
size_t N,
typename T >
2273 matrix< M, N, T >::p_norm(
double p )
const
2277 const_iterator it = begin(), it_end = end();
2278 for( ; it != it_end; ++it )
2280 norm += std::pow(*it, p);
2283 return std::pow(norm,1./p);
2287 template<
size_t M,
size_t N,
typename T >
2288 template<
size_t O >
2290 matrix< M, N, T >::khatri_rao_product(
const matrix< O, N, T >& right_, matrix< M*O, N, T >& prod_ )
const
2293 for (
size_t col = 0; col < N; ++col )
2295 for (
size_t m = 0; m < M; ++m )
2297 for (
size_t o = 0; o < O; ++o )
2299 prod_.at(O*m + o, col) = at( m, col ) * right_.at( o, col );
2305 template<
size_t M,
size_t N,
typename T >
2306 template<
size_t O,
size_t P >
2308 matrix< M, N, T >::kronecker_product(
const matrix< O, P, T >& right_, matrix< M*O, N*P, T >& result_ )
const
2311 for (
size_t m = 0; m < M; ++m )
2313 for (
size_t n = 0; n < N; ++n )
2315 for (
size_t o = 0; o < O; ++o )
2317 for (
size_t p = 0; p < P; ++p )
2319 result_.at(O*m + o, P*n + p) = at( m, n ) * right_.at( o, p );
2327 template<
size_t M,
size_t N,
typename T >
2328 template<
typename TT >
2330 matrix< M, N, T >::cast_from(
const matrix< M, N, TT >& other )
2333 typedef typename matrix_tt_type::const_iterator tt_const_iterator;
2335 iterator it = begin(), it_end = end();
2336 tt_const_iterator other_it = other.begin();
2337 for( ; it != it_end; ++it, ++other_it )
2339 *it =
static_cast< T
>( *other_it );
2344 template<
size_t M,
size_t N,
typename T >
2346 matrix< M, N, T >::get_min()
const
2348 T min_value =
static_cast<T
>(std::numeric_limits<T>::max());
2350 const_iterator it = begin(),
2352 for( ; it != it_end; ++it)
2354 if ( *it < min_value ) {
2361 template<
size_t M,
size_t N,
typename T >
2363 matrix< M, N, T >::get_max()
const
2365 T max_value =
static_cast<T
>(0);
2367 const_iterator it = begin(),
2369 for( ; it != it_end; ++it)
2371 if ( *it > max_value ) {
2379 template<
size_t M,
size_t N,
typename T >
2381 matrix< M, N, T >::get_abs_min()
const
2383 T min_value =
static_cast<T
>(std::numeric_limits<T>::max());
2385 const_iterator it = begin(),
2387 for( ; it != it_end; ++it)
2389 if ( fabs(*it) < fabs(min_value) ) {
2390 min_value = fabs(*it);
2396 template<
size_t M,
size_t N,
typename T >
2398 matrix< M, N, T >::get_abs_max()
const
2400 T max_value =
static_cast<T
>(0);
2402 const_iterator it = begin(),
2404 for( ; it != it_end; ++it)
2406 if ( fabs(*it) > fabs(max_value) ) {
2407 max_value = fabs(*it);
2415 template<
size_t M,
size_t N,
typename T >
2417 matrix< M, N, T >::nnz()
const
2421 const_iterator it = begin(),
2423 for( ; it != it_end; ++it)
2433 template<
size_t M,
size_t N,
typename T >
2435 matrix< M, N, T >::nnz(
const T& threshold_ )
const
2439 const_iterator it = begin(),
2441 for( ; it != it_end; ++it)
2443 if ( fabs(*it) > threshold_ ) {
2451 template<
size_t M,
size_t N,
typename T >
2453 matrix< M, N, T >::threshold(
const T& threshold_value_ )
2455 iterator it = begin(),
2457 for( ; it != it_end; ++it)
2459 if ( fabs(*it) <= threshold_value_ ) {
2460 *it =
static_cast<T
> (0);
2466 template<
size_t M,
size_t N,
typename T >
2467 template<
typename TT >
2469 matrix< M, N, T >::quantize_to( matrix< M, N, TT >& quantized_,
const T& min_value,
const T& max_value )
const
2471 long max_tt_range = long(std::numeric_limits< TT >::max());
2472 long min_tt_range = long(std::numeric_limits< TT >::min());
2473 long tt_range = (max_tt_range - min_tt_range);
2475 T t_range = max_value - min_value;
2477 typedef matrix< M, N, TT > m_tt_type ;
2478 typedef typename m_tt_type::iterator tt_iterator;
2479 tt_iterator it_quant = quantized_.begin();
2480 const_iterator it = begin(), it_end = end();
2482 for( ; it != it_end; ++it, ++it_quant )
2484 if (std::numeric_limits<TT>::is_signed ) {
2485 *it_quant = TT( std::min( std::max( min_tt_range,
long(( *it * tt_range / t_range ) + 0.5)), max_tt_range ));
2487 *it_quant = TT( std::min( std::max( min_tt_range,
long(((*it - min_value) * tt_range / t_range) + 0.5)), max_tt_range ));
2493 template<
size_t M,
size_t N,
typename T >
2494 template<
typename TT >
2496 matrix< M, N, T >::quantize( matrix< M, N, TT >& quantized_, T& min_value, T& max_value )
const
2498 min_value = get_min();
2499 max_value = get_max();
2500 quantize_to( quantized_, min_value, max_value );
2505 template<
size_t M,
size_t N,
typename T >
2506 template<
typename TT >
2508 matrix< M, N, T >::dequantize( matrix< M, N, TT >& dequantized_,
const TT& min_value,
const TT& max_value )
const
2510 long max_t_range = long(std::numeric_limits< T >::max());
2511 long min_t_range = long(std::numeric_limits< T >::min());
2512 long t_range = (max_t_range - min_t_range);
2514 TT tt_range = max_value - min_value;
2516 typedef matrix< M, N, TT > m_tt_type ;
2517 typedef typename m_tt_type::iterator tt_iterator;
2518 tt_iterator it_dequant = dequantized_.begin();
2519 const_iterator it = begin(), it_end = end();
2520 for( ; it != it_end; ++it, ++it_dequant )
2522 if (std::numeric_limits<T>::is_signed ) {
2523 *it_dequant = std::min( std::max( min_value, TT((TT(*it) / t_range) * tt_range)), max_value );
2525 *it_dequant = std::min( std::max( min_value, TT((((TT(*it) / t_range)) * tt_range ) + min_value)), max_value );
2530 template<
size_t M,
size_t N,
typename T >
2532 matrix< M, N, T >::columnwise_sum( vector< N, T>& summed_columns_ )
const
2535 for (
size_t n = 0; n < N; ++n )
2538 for (
size_t m = 0; m < M; ++m )
2540 value += at( m, n );
2542 summed_columns_.at( n ) = value;
2546 template<
size_t M,
size_t N,
typename T >
2548 matrix< M, N, T >::sum_elements( )
const
2552 const_iterator it = begin(), it_end = end();
2553 for( ; it != it_end; ++it )
2561 template<
size_t M,
size_t N,
typename T >
2563 typename enable_if< R == M && R == N>::type*
2564 matrix< M, N, T >::diag(
const vector< R, T >& diag_values_ )
2567 for(
size_t r = 0; r < R; ++r )
2569 at(r, r) =
static_cast< T
>( diag_values_.at(r) );
2575 template<
size_t M,
size_t N,
typename T >
2577 matrix< M, N, T >::set_dct()
2579 const double num_rows = M;
2580 double fill_value = 0.0f;
2581 for(
size_t row = 0; row < M; ++row )
2584 const double weight = ( row == 0.0 ) ? std::sqrt(1/num_rows) :
2585 std::sqrt(2/num_rows);
2586 for(
size_t col = 0; col < N; ++col )
2588 fill_value = (2 * col + 1) * row * M_PI / (2*M);
2589 fill_value = std::cos( fill_value );
2590 fill_value *= weight;
2591 at( row, col ) =
static_cast< T
>( fill_value ) ;
2597 template<
size_t M,
size_t N,
typename T >
2599 matrix< M, N, T >::set_random(
int seed )
2604 double fillValue = 0.0f;
2605 for(
size_t row = 0; row < M; ++row )
2607 for(
size_t col = 0; col < N; ++col )
2610 fillValue /= RAND_MAX;
2611 at( row, col ) = -1.0 + 2.0 *
static_cast< double >( fillValue ) ;
2616 template<
size_t M,
size_t N,
typename T >
2618 matrix< M, N, T >::write_to_raw(
const std::string& dir_,
const std::string& filename_ )
const
2620 int dir_length = dir_.size() -1;
2621 int last_separator = dir_.find_last_of(
"/");
2622 std::string path = dir_;
2623 if (last_separator < dir_length ) {
2626 path.append( filename_ );
2628 if( filename_.find(
"raw", filename_.size() -3) == std::string::npos )
2631 path.append(
"raw" );
2633 std::string path_raw = path;
2635 std::ofstream outfile;
2636 outfile.open( path_raw.c_str() );
2637 if( outfile.is_open() ) {
2638 size_t len_slice =
sizeof(T) * M*N;
2639 outfile.write( (
char*)&(*
this), len_slice );
2642 std::cout <<
"no file open" << std::endl;
2646 template<
size_t M,
size_t N,
typename T >
2648 matrix< M, N, T >::read_from_raw(
const std::string& dir_,
const std::string& filename_ )
2650 int dir_length = dir_.size() -1;
2651 int last_separator = dir_.find_last_of(
"/");
2652 std::string path = dir_;
2653 if (last_separator < dir_length ) {
2656 path.append( filename_ );
2658 size_t max_file_len = 2147483648u -
sizeof(T) ;
2659 size_t len_data =
sizeof(T) * size();
2660 char* data =
new char[ len_data ];
2661 std::ifstream infile;
2662 infile.open( path.c_str(), std::ios::in);
2664 if( infile.is_open())
2666 iterator it = begin(),
2669 while ( len_data > 0 )
2671 size_t len_read = (len_data % max_file_len ) > 0 ?
2672 len_data % max_file_len : len_data;
2673 len_data -= len_read;
2674 infile.read( data, len_read );
2676 T* T_ptr = (T*)&(data[0]);
2677 for( ; (it != it_end) && (len_read > 0); ++it, len_read -=
sizeof(T) )
2679 *it = *T_ptr; ++T_ptr;
2686 std::cout <<
"no file open" << std::endl;
2694 template<
size_t M,
size_t N,
typename T >
2696 matrix< M, N, T >::write_csv_file(
const std::string& dir_,
const std::string& filename_ )
const
2698 int dir_length = dir_.size() -1;
2699 int last_separator = dir_.find_last_of(
"/");
2700 std::string path = dir_;
2701 if (last_separator < dir_length ) {
2704 path.append( filename_ );
2706 int suffix_pos = filename_.find(
"csv", filename_.size() -3);
2707 if( suffix_pos == (-1)) {
2709 path.append(
"csv" );
2712 std::ofstream outfile;
2713 outfile.open( path.c_str() );
2714 if( outfile.is_open() ) {
2715 outfile << *
this << std::endl;
2718 std::cout <<
"no file open" << std::endl;
2723 template<
size_t M,
size_t N,
typename T >
2725 matrix< M, N, T >::read_csv_file(
const std::string& dir_,
const std::string& filename_ )
2727 int dir_length = dir_.size() -1;
2728 int last_separator = dir_.find_last_of(
"/");
2729 std::string path = dir_;
2730 if (last_separator < dir_length ) {
2733 path.append( filename_ );
2735 int suffix_pos = filename_.find(
"csv", filename_.size() -3);
2736 if( suffix_pos == (-1)) {
2738 path.append(
"csv" );
2741 std::ifstream infile;
2742 infile.open( path.c_str(), std::ios::in);
2743 if( infile.is_open() ) {
2748 std::cout <<
"no file open" << std::endl;
2754 template<
size_t M,
size_t N,
typename T >
2756 matrix< M, N, T >::sum_rows( matrix< M/2, N, T>& other )
const
2758 typedef vector< N, T > row_type;
2760 row_type* row0 =
new row_type;
2761 row_type* row1 =
new row_type;
2765 for (
size_t row = 0; row < M; ++row )
2767 get_row( row++, *row0 );
2770 get_row( row, *row1 );
2772 other.set_row( row/2 , *row0 );
2780 template<
size_t M,
size_t N,
typename T >
2782 matrix< M, N, T >::sum_columns( matrix< M, N/2, T>& other )
const
2784 typedef vector< M, T > col_type;
2786 col_type* col0 =
new col_type;
2787 col_type* col1 =
new col_type;
2791 for (
size_t col = 0; col< N; ++col )
2793 get_column( col++, *col0 );
2796 get_column( col, *col1 );
2798 other.set_column( col/2, *col0 );