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 >
315 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
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 const std::ios::fmtflags flags = os.flags();
456 const int prec = os.precision();
458 os.setf( std::ios::right, std::ios::adjustfield );
461 for(
size_t row_index = 0; row_index < M; ++row_index )
464 for(
size_t col_index = 0; col_index < N; ++col_index )
466 os << std::setw(10) << matrix.at( row_index, col_index ) <<
" ";
468 os <<
"|" << std::endl;
470 os.precision( prec );
485 #ifndef VMMLIB_NO_TYPEDEFS
496 template<
size_t M,
size_t N,
typename T >
498 const T tolerance = std::numeric_limits< T >::epsilon())
500 return m0.equals( m1, tolerance );
504 template<
size_t M,
size_t N,
typename T >
505 inline void multiply(
const matrix< M, N, T >& left,
506 const matrix< M, N, T >& right,
507 matrix< M, N, T >& result )
509 result.multiply( left, right );
514 template<
size_t M,
size_t N,
typename T >
515 template<
size_t U,
size_t V >
516 void matrix< M, N, T>::convolve(
const matrix< U, V, T >& kernel)
518 matrix< M, N, T> temp;
520 for(
size_t y_ = 0; y_ < N; ++y_)
522 for(
size_t x_ = 0; x_ < M; ++x_)
526 for(
size_t j = 0; j < V; ++j)
528 int srcy = y_ - V/2 + j;
531 if(srcy < 0) srcy = 0;
532 if(srcy >=
int(N)) srcy = N-1;
534 for(
size_t i = 0; i < U; ++i)
536 int srcx = x_ - U/2 + i;
539 if(srcx < 0) srcx = 0;
540 if(srcx >=
int(M)) srcx = M-1;
542 sum += kernel.at(j,i) * at(srcy,srcx);
545 temp.at(y_,x_) = sum;
554 template<
size_t M,
size_t N,
size_t P,
typename T >
556 multiply(
const matrix< M, P, T >& left,
const matrix< P, N, T >& right,
557 matrix< M, N, T >& result )
559 result.multiply( left, right );
563 template<
size_t M,
size_t N,
typename T >
564 inline typename enable_if< M == N >::type* identity( matrix< M, N, T >& m )
566 m =
static_cast< T
>( 0.0 );
567 for(
size_t index = 0; index < M; ++index )
568 m( index, index ) =
static_cast< T
>( 1.0 );
574 template<
typename T >
575 inline T compute_determinant(
const matrix< 1, 1, T >& matrix_ )
577 return matrix_.array[ 0 ];
582 template<
typename T >
583 inline T compute_determinant(
const matrix< 2, 2, T >& matrix_ )
585 const T& a = matrix_( 0, 0 );
586 const T& b = matrix_( 0, 1 );
587 const T& c = matrix_( 1, 0 );
588 const T& d = matrix_( 1, 1 );
589 return a * d - b * c;
594 template<
typename T >
595 inline T compute_determinant(
const matrix< 3, 3, T >& m_ )
598 m_( 0,0 ) * ( m_( 1,1 ) * m_( 2,2 ) - m_( 1,2 ) * m_( 2,1 ) )
599 + m_( 0,1 ) * ( m_( 1,2 ) * m_( 2,0 ) - m_( 1,0 ) * m_( 2,2 ) )
600 + m_( 0,2 ) * ( m_( 1,0 ) * m_( 2,1 ) - m_( 1,1 ) * m_( 2,0 ) );
604 template<
typename T >
605 inline T compute_determinant(
const matrix< 4, 4, T >& m )
625 m03 * m12 * m21 * m30
626 - m02 * m13 * m21 * m30
627 - m03 * m11 * m22 * m30
628 + m01 * m13 * m22 * m30
629 + m02 * m11 * m23 * m30
630 - m01 * m12 * m23 * m30
631 - m03 * m12 * m20 * m31
632 + m02 * m13 * m20 * m31
633 + m03 * m10 * m22 * m31
634 - m00 * m13 * m22 * m31
635 - m02 * m10 * m23 * m31
636 + m00 * m12 * m23 * m31
637 + m03 * m11 * m20 * m32
638 - m01 * m13 * m20 * m32
639 - m03 * m10 * m21 * m32
640 + m00 * m13 * m21 * m32
641 + m01 * m10 * m23 * m32
642 - m00 * m11 * m23 * m32
643 - m02 * m11 * m20 * m33
644 + m01 * m12 * m20 * m33
645 + m02 * m10 * m21 * m33
646 - m00 * m12 * m21 * m33
647 - m01 * m10 * m22 * m33
648 + m00 * m11 * m22 * m33;
653 template<
typename T >
654 bool compute_inverse(
const matrix< 2, 2, T >& m_, matrix< 2, 2, T >& inverse_,
655 T tolerance_ = std::numeric_limits<T>::epsilon())
657 const T det_ = compute_determinant( m_ );
658 if( fabs( det_ ) < tolerance_ )
661 const T detinv =
static_cast< T
>( 1.0 ) / det_;
663 m_.get_adjugate( inverse_ );
670 template<
typename T >
671 bool compute_inverse(
const matrix< 3, 3, T >& m_, matrix< 3, 3, T >& inverse_,
672 T tolerance_ = std::numeric_limits<T>::epsilon() )
676 inverse_.at( 0, 0 ) = m_.at( 1, 1 ) * m_.at( 2, 2 ) - m_.at( 1, 2 ) * m_.at( 2, 1 );
677 inverse_.at( 0, 1 ) = m_.at( 0, 2 ) * m_.at( 2, 1 ) - m_.at( 0, 1 ) * m_.at( 2, 2 );
678 inverse_.at( 0, 2 ) = m_.at( 0, 1 ) * m_.at( 1, 2 ) - m_.at( 0, 2 ) * m_.at( 1, 1 );
679 inverse_.at( 1, 0 ) = m_.at( 1, 2 ) * m_.at( 2, 0 ) - m_.at( 1, 0 ) * m_.at( 2, 2 );
680 inverse_.at( 1, 1 ) = m_.at( 0, 0 ) * m_.at( 2, 2 ) - m_.at( 0, 2 ) * m_.at( 2, 0 );
681 inverse_.at( 1, 2 ) = m_.at( 0, 2 ) * m_.at( 1, 0 ) - m_.at( 0, 0 ) * m_.at( 1, 2 );
682 inverse_.at( 2, 0 ) = m_.at( 1, 0 ) * m_.at( 2, 1 ) - m_.at( 1, 1 ) * m_.at( 2, 0 );
683 inverse_.at( 2, 1 ) = m_.at( 0, 1 ) * m_.at( 2, 0 ) - m_.at( 0, 0 ) * m_.at( 2, 1 );
684 inverse_.at( 2, 2 ) = m_.at( 0, 0 ) * m_.at( 1, 1 ) - m_.at( 0, 1 ) * m_.at( 1, 0 );
686 const T determinant =
687 m_.at( 0, 0 ) * inverse_.at( 0, 0 )
688 + m_.at( 0, 1 ) * inverse_.at( 1, 0 )
689 + m_.at( 0, 2 ) * inverse_.at( 2, 0 );
691 if ( fabs( determinant ) <= tolerance_ )
694 const T detinv =
static_cast< T
>( 1.0 ) / determinant;
696 inverse_.at( 0, 0 ) *= detinv;
697 inverse_.at( 0, 1 ) *= detinv;
698 inverse_.at( 0, 2 ) *= detinv;
699 inverse_.at( 1, 0 ) *= detinv;
700 inverse_.at( 1, 1 ) *= detinv;
701 inverse_.at( 1, 2 ) *= detinv;
702 inverse_.at( 2, 0 ) *= detinv;
703 inverse_.at( 2, 1 ) *= detinv;
704 inverse_.at( 2, 2 ) *= detinv;
710 template<
typename T >
711 bool compute_inverse(
const matrix< 4, 4, T >& m_,
712 matrix< 4, 4, T >& inv_,
713 T tolerance_ = std::numeric_limits<T>::epsilon() )
715 const T* array = m_.array;
719 const T t1[6] = { array[ 2] * array[ 7] - array[ 6] * array[ 3],
720 array[ 2] * array[11] - array[10] * array[ 3],
721 array[ 2] * array[15] - array[14] * array[ 3],
722 array[ 6] * array[11] - array[10] * array[ 7],
723 array[ 6] * array[15] - array[14] * array[ 7],
724 array[10] * array[15] - array[14] * array[11] };
727 inv_.array[0] = array[ 5] * t1[5] - array[ 9] * t1[4] + array[13] * t1[3];
728 inv_.array[1] = array[ 9] * t1[2] - array[13] * t1[1] - array[ 1] * t1[5];
729 inv_.array[2] = array[13] * t1[0] - array[ 5] * t1[2] + array[ 1] * t1[4];
730 inv_.array[3] = array[ 5] * t1[1] - array[ 1] * t1[3] - array[ 9] * t1[0];
731 inv_.array[4] = array[ 8] * t1[4] - array[ 4] * t1[5] - array[12] * t1[3];
732 inv_.array[5] = array[ 0] * t1[5] - array[ 8] * t1[2] + array[12] * t1[1];
733 inv_.array[6] = array[ 4] * t1[2] - array[12] * t1[0] - array[ 0] * t1[4];
734 inv_.array[7] = array[ 0] * t1[3] - array[ 4] * t1[1] + array[ 8] * t1[0];
737 const T t2[6] = { array[ 0] * array[ 5] - array[ 4] * array[ 1],
738 array[ 0] * array[ 9] - array[ 8] * array[ 1],
739 array[ 0] * array[13] - array[12] * array[ 1],
740 array[ 4] * array[ 9] - array[ 8] * array[ 5],
741 array[ 4] * array[13] - array[12] * array[ 5],
742 array[ 8] * array[13] - array[12] * array[ 9] };
745 inv_.array[8] = array[ 7] * t2[5] - array[11] * t2[4] + array[15] * t2[3];
746 inv_.array[9] = array[11] * t2[2] - array[15] * t2[1] - array[ 3] * t2[5];
747 inv_.array[10] = array[15] * t2[0] - array[ 7] * t2[2] + array[ 3] * t2[4];
748 inv_.array[11] = array[ 7] * t2[1] - array[ 3] * t2[3] - array[11] * t2[0];
749 inv_.array[12] = array[10] * t2[4] - array[ 6] * t2[5] - array[14] * t2[3];
750 inv_.array[13] = array[ 2] * t2[5] - array[10] * t2[2] + array[14] * t2[1];
751 inv_.array[14] = array[ 6] * t2[2] - array[14] * t2[0] - array[ 2] * t2[4];
752 inv_.array[15] = array[ 2] * t2[3] - array[ 6] * t2[1] + array[10] * t2[0];
755 const T determinant = array[0] * inv_.array[0] + array[4] * inv_.array[1] +
756 array[8] * inv_.array[2] + array[12] * inv_.array[3];
758 if( fabs( determinant ) <= tolerance_ )
762 const T detinv =
static_cast< T
>( 1.0 ) / determinant;
764 for(
size_t i = 0; i != 16; ++i )
765 inv_.array[i] *= detinv;
773 template<
size_t M,
size_t N,
typename T >
774 inline matrix< N, M, T >
775 transpose(
const matrix< M, N, T >& matrix_ )
777 matrix< N, M, T > transpose_;
778 matrix_.transpose_to( transpose_ );
783 template<
size_t M,
size_t N,
typename T >
784 bool is_positive_definite(
const matrix< M, N, T >& matrix_,
785 const T limit = -1e12,
786 typename enable_if< M == N && M <= 3 >::type* = 0 )
788 if ( matrix_.at( 0, 0 ) < limit )
795 matrix_.get_sub_matrix( m, 0, 0 );
796 if ( compute_determinant( m ) < limit )
803 matrix_.get_sub_matrix( m, 0, 0 );
804 if ( compute_determinant( m ) < limit )
812 template<
size_t M,
size_t N,
typename T >
813 matrix< M, N, T >::matrix()
817 for(
size_t i = 0; i < M; ++i )
818 at( i, i ) =
static_cast< T
>( 1.0 );
821 template<
size_t M,
size_t N,
typename T >
822 template<
size_t P,
size_t Q,
typename U >
823 matrix< M, N, T >::matrix(
const matrix< P, Q, U >& source_ )
829 template<
size_t M,
size_t N,
typename T >
830 inline T& matrix< M, N, T >::at(
size_t row_index,
size_t col_index )
832 #ifdef VMMLIB_SAFE_ACCESSORS
833 if ( row_index >= M || col_index >= N )
834 VMMLIB_ERROR(
"at( row, col ) - index out of bounds", VMMLIB_HERE );
836 return array[ col_index * M + row_index ];
841 template<
size_t M,
size_t N,
typename T >
843 matrix< M, N, T >::at(
size_t row_index,
size_t col_index )
const
845 #ifdef VMMLIB_SAFE_ACCESSORS
846 if ( row_index >= M || col_index >= N )
847 VMMLIB_ERROR(
"at( row, col ) - index out of bounds", VMMLIB_HERE );
849 return array[ col_index * M + row_index ];
853 template<
size_t M,
size_t N,
typename T >
855 matrix< M, N, T >::operator()(
size_t row_index,
size_t col_index )
857 return at( row_index, col_index );
862 template<
size_t M,
size_t N,
typename T >
864 matrix< M, N, T >::operator()(
size_t row_index,
size_t col_index )
const
866 return at( row_index, col_index );
869 #ifndef VMMLIB_NO_CONVERSION_OPERATORS
871 template<
size_t M,
size_t N,
typename T >
880 template<
size_t M,
size_t N,
typename T >
882 operator
const T*()
const
890 template<
size_t M,
size_t N,
typename T >
893 operator==(
const matrix< M, N, T >& other )
const
896 for(
size_t i = 0; is_ok && i < M * N; ++i )
898 is_ok = array[ i ] == other.array[ i ];
906 template<
size_t M,
size_t N,
typename T >
909 operator!=(
const matrix< M, N, T >& other )
const
911 return ! operator==( other );
916 template<
size_t M,
size_t N,
typename T >
919 equals(
const matrix< M, N, T >& other, T tolerance )
const
922 for(
size_t row_index = 0; is_ok && row_index < M; row_index++)
924 for(
size_t col_index = 0; is_ok && col_index < N; col_index++)
926 is_ok = fabs( at( row_index, col_index ) - other( row_index, col_index ) ) < tolerance;
934 template<
size_t M,
size_t N,
typename T >
935 template<
typename compare_t >
936 bool matrix< M, N, T >::equals(
const matrix< M, N, T >& other_matrix,
937 compare_t& cmp )
const
940 for(
size_t row = 0; is_ok && row < M; ++row )
942 for(
size_t col = 0; is_ok && col < N; ++col)
944 is_ok = cmp( at( row, col ), other_matrix.at( row, col ) );
950 #if (( __GNUC__ > 4 ) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) )
951 # pragma GCC diagnostic ignored "-Warray-bounds" // gcc 4.4.7 bug WAR
953 template<
size_t M,
size_t N,
typename T >
954 const matrix< M, N, T >&
955 matrix< M, N, T >::operator=(
const matrix< M, N, T >& source_ )
957 memcpy( array, source_.array, M * N *
sizeof( T ));
960 #if (( __GNUC__ > 4 ) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) )
961 # pragma GCC diagnostic warning "-Warray-bounds"
964 template<
size_t M,
size_t N,
typename T >
965 template<
size_t P,
size_t Q,
typename U >
966 void matrix< M, N, T >::operator=(
const matrix< P, Q, U >& source_ )
968 const size_t minL = P < M ? P : M;
969 const size_t minC = Q < N ? Q : N;
971 if( minL < M || minC < N )
974 for (
size_t i = 0 ; i < minL ; i++ )
975 for (
size_t j = 0 ; j < minC ; j++ )
976 at( i,j ) =
static_cast< T
>( source_( i, j ));
980 template<
size_t M,
size_t N,
typename T >
981 void matrix< M, N, T >::operator=(
const T old_fashioned_matrix[ M ][ N ] )
983 for(
size_t row = 0; row < M; row++)
985 for(
size_t col = 0; col < N; col++)
987 at( row, col ) = old_fashioned_matrix[ row ][ col ];
997 template<
size_t M,
size_t N,
typename T >
999 matrix< M, N, T >::operator=(
const T* data_array )
1001 set( data_array, data_array + M * N,
true );
1006 template<
size_t M,
size_t N,
typename T >
1008 matrix< M, N, T >::operator=(
const std::vector< T >& data )
1010 if ( data.size() < M * N )
1011 VMMLIB_ERROR(
"index out of bounds.", VMMLIB_HERE );
1013 set( data.begin(), data.end(), true );
1017 template<
size_t M,
size_t N,
typename T >
1019 matrix< M, N, T >::multiply_piecewise(
const matrix& other )
1021 for(
size_t row_index = 0; row_index < M; row_index++)
1023 for(
size_t col_index = 0; col_index < N; col_index++ )
1025 T& value = at( row_index, col_index );
1026 value *= other.at( row_index, col_index );
1032 template<
size_t M,
size_t N,
typename T >
1033 template<
size_t P >
1035 matrix< M, N, T >::multiply(
1036 const matrix< M, P, T >& left,
1037 const matrix< P, N, T >& right
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& component = at( row_index, col_index );
1045 component =
static_cast< T
>( 0.0 );
1046 for(
size_t p = 0; p < P; p++)
1048 component += left.at( row_index, p ) * right.at( p, col_index );
1056 template<
size_t M,
size_t N,
typename T >
1057 template<
size_t P >
1059 matrix< M, N, T >::operator*(
const matrix< N, P, T >& other )
const
1061 matrix< M, P, T > result;
1062 result.multiply( *
this, other );
1068 template<
size_t M,
size_t N,
typename T >
1069 template<
size_t O,
size_t P,
typename TT >
1070 typename enable_if< M == N && O == P && M == O, TT >::type*
1071 matrix< M, N, T >::operator*=(
const matrix< O, P, TT >& right )
1073 matrix< M, N, T > copy( *
this );
1074 multiply( copy, right );
1078 template<
size_t M,
size_t N,
typename T >
1080 matrix< M, N, T >::operator/( T scalar )
1082 matrix< M, N, T > result;
1084 for(
size_t row_index = 0; row_index < M; ++row_index )
1086 for(
size_t col_index = 0; col_index < N; ++col_index )
1088 result.at( row_index, col_index ) = at( row_index, col_index ) / scalar;
1096 template<
size_t M,
size_t N,
typename T >
1098 matrix< M, N, T >::operator/=( T scalar )
1100 for(
size_t row_index = 0; row_index < M; ++row_index )
1102 for(
size_t col_index = 0; col_index < N; ++col_index )
1104 at( row_index, col_index ) /= scalar;
1113 template<
size_t M,
size_t N,
typename T >
1115 matrix< M, N, T >::operator*( T scalar )
1117 matrix< M, N, T > result;
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 result.at( row_index, col_index ) = at( row_index, col_index ) * scalar;
1131 template<
size_t M,
size_t N,
typename T >
1133 matrix< M, N, T >::operator*=( T scalar )
1135 for(
size_t row_index = 0; row_index < M; ++row_index )
1137 for(
size_t col_index = 0; col_index < N; ++col_index )
1139 at( row_index, col_index ) *= scalar;
1146 template<
size_t M,
size_t N,
typename T >
1147 vector< M, T > matrix< M, N, T >::operator*(
const vector< N, T >& vec )
const
1149 vector< M, T > result;
1152 for(
size_t i = 0; i < M; ++i )
1155 for(
size_t j = 0; j < N; ++j )
1156 tmp += at( i, j ) * vec.at( j );
1157 result.at( i ) = tmp;
1166 template<
size_t M,
size_t N,
typename T >
1167 template<
size_t O > vector< O, T >
1168 matrix< M, N, T >::operator*(
const vector< O, T >& vector_ )
const
1170 vector< O, T > result;
1172 for(
size_t row_index = 0; row_index < M; ++row_index )
1175 for(
size_t col_index = 0; col_index < N-1; ++col_index )
1177 tmp += vector_( col_index ) * at( row_index, col_index );
1179 if ( row_index < N - 1 )
1180 result( row_index ) = tmp + at( row_index, N-1 );
1183 tmp += at( row_index, N - 1 );
1184 for(
size_t col_index = 0; col_index < N - 1; ++col_index )
1186 result( col_index ) /= tmp;
1195 template<
size_t M,
size_t N,
typename T >
1196 inline matrix< M, N, T >
1197 matrix< M, N, T >::operator-()
const
1204 template<
size_t M,
size_t N,
typename T >
1206 matrix< M, N, T >::negate()
const
1208 matrix< M, N, T > result;
1215 template<
size_t M,
size_t N,
typename T >
1217 matrix< M, N, T >::tensor(
const vector< M, T >& u,
const vector< N, T >& v )
1219 for (
size_t col_index = 0; col_index < N; ++col_index )
1220 for (
size_t row_index = 0; row_index < M; ++row_index )
1221 at( row_index, col_index ) = u.array[ col_index ] *
1222 v.array[ row_index ];
1227 template<
size_t M,
size_t N,
typename T >
1228 template<
size_t uM,
size_t vM >
1229 typename enable_if< uM == 3 && vM == 3 && M == N && M == 4 >::type*
1230 matrix< M, N, T >::tensor(
const vector< uM, T >& u,
const vector< vM, T >& v )
1232 for (
size_t col_index = 0; col_index < 3; ++col_index )
1234 for (
size_t row_index = 0; row_index < 3; ++row_index )
1235 at( row_index, col_index ) = u.array[ col_index ] *
1236 v.array[ row_index ];
1238 at( 3, col_index ) = u.array[ col_index ];
1241 for (
size_t row_index = 0; row_index < 3; ++row_index )
1242 at( row_index, 3 ) = v.array[ row_index ];
1251 template<
size_t M,
size_t N,
typename T >
1254 transpose_to( matrix< N, M, T >& tM )
const
1256 for(
size_t row = 0; row < M; ++row )
1258 for(
size_t col = 0; col < N; ++col )
1260 tM.at( col, row ) = at( row, col );
1265 template<
size_t M,
size_t N,
typename T >
1268 symmetric_covariance( matrix< M, M, T >& cov_m_ )
const
1271 for(
size_t row = 0; row < M; ++row )
1273 for(
size_t col = row; col < M; ++col )
1275 for (
size_t k = 0; k < N; ++k )
1277 tmp += (at( row, k ) * at( col, k ));
1280 cov_m_.at( row, col ) = tmp;
1281 cov_m_.at( col, row ) = tmp;
1289 template<
size_t M,
size_t N,
typename T >
1290 vector< M, T > matrix< M, N, T >::get_column(
size_t index )
const
1292 vector< M, T > column;
1293 get_column( index, column );
1299 template<
size_t M,
size_t N,
typename T >
1300 void matrix< M, N, T >::get_column(
size_t index, vector< M, T >& column )
const
1302 #ifdef VMMLIB_SAFE_ACCESSORS
1304 VMMLIB_ERROR(
"get_column() - index out of bounds.", VMMLIB_HERE );
1307 memcpy( &column.array[0], &array[ M * index ], M *
sizeof( T ) );
1312 template<
size_t M,
size_t N,
typename T >
1313 void matrix< M, N, T >::set_column(
size_t index,
const vector< M, T >& column )
1315 #ifdef VMMLIB_SAFE_ACCESSORS
1318 VMMLIB_ERROR(
"set_column() - index out of bounds.", VMMLIB_HERE );
1322 memcpy( array + M * index, column.array, M *
sizeof( T ) );
1325 template<
size_t M,
size_t N,
typename T >
1326 void matrix< M, N, T >::get_column(
size_t index, matrix< M, 1, T >& column )
1329 #ifdef VMMLIB_SAFE_ACCESSORS
1331 VMMLIB_ERROR(
"get_column() - index out of bounds.", VMMLIB_HERE );
1334 memcpy( column.array, array + M * index, M *
sizeof( T ) );
1337 template<
size_t M,
size_t N,
typename T >
1338 void matrix< M, N, T >::set_column(
size_t index,
1339 const matrix< M, 1, T >& column )
1341 #ifdef VMMLIB_SAFE_ACCESSORS
1343 VMMLIB_ERROR(
"set_column() - index out of bounds.", VMMLIB_HERE );
1346 memcpy( &array[ M * index ], column.array, M *
sizeof( T ) );
1349 template<
size_t M,
size_t N,
typename T >
1350 vector< N, T > matrix< M, N, T >::get_row(
size_t index )
const
1353 get_row( index, row );
1357 template<
size_t M,
size_t N,
typename T >
1358 void matrix< M, N, T >::get_row(
size_t row_index, vector< N, T >& row )
const
1360 #ifdef VMMLIB_SAFE_ACCESSORS
1361 if ( row_index >= M )
1362 VMMLIB_ERROR(
"get_row() - index out of bounds.", VMMLIB_HERE );
1365 for(
size_t col_index = 0; col_index < N; ++col_index )
1367 row.at( col_index ) = at( row_index, col_index );
1371 template<
size_t M,
size_t N,
typename T >
1372 void matrix< M, N, T >::set_row(
size_t row_index,
const vector< N, T >& row )
1374 #ifdef VMMLIB_SAFE_ACCESSORS
1375 if ( row_index >= M )
1376 VMMLIB_ERROR(
"set_row() - index out of bounds.", VMMLIB_HERE );
1379 for(
size_t col_index = 0; col_index < N; ++col_index )
1381 at( row_index, col_index ) = row.at( col_index );
1385 template<
size_t M,
size_t N,
typename T >
1386 void matrix< M, N, T >::get_row(
size_t row_index, matrix< 1, N, T >& row )
1389 #ifdef VMMLIB_SAFE_ACCESSORS
1390 if ( row_index >= M )
1391 VMMLIB_ERROR(
"get_row() - index out of bounds.", VMMLIB_HERE );
1394 for(
size_t col_index = 0; col_index < N; ++col_index )
1396 row.at( 0, col_index ) = at( row_index, col_index );
1400 template<
size_t M,
size_t N,
typename T >
1401 void matrix< M, N, T >::set_row(
size_t row_index,
1402 const matrix< 1, N, T >& row )
1404 #ifdef VMMLIB_SAFE_ACCESSORS
1405 if ( row_index >= M )
1406 VMMLIB_ERROR(
"set_row() - index out of bounds.", VMMLIB_HERE );
1409 for(
size_t col_index = 0; col_index < N; ++col_index )
1411 at( row_index, col_index ) = row.at( 0, col_index );
1415 template<
size_t M,
size_t N,
typename T >
1418 get_number_of_rows()
const
1425 template<
size_t M,
size_t N,
typename T >
1428 get_number_of_columns()
const
1435 template<
size_t M,
size_t N,
typename T >
1440 for(
size_t row_index = 0; row_index < M; ++row_index )
1442 for(
size_t col_index = 0; col_index < N; ++col_index )
1444 at( row_index, col_index ) = fillValue;
1450 template<
size_t M,
size_t N,
typename T >
1452 matrix< M, N, T >::x()
1459 template<
size_t M,
size_t N,
typename T >
1461 matrix< M, N, T >::y()
1468 template<
size_t M,
size_t N,
typename T >
1470 matrix< M, N, T >::z()
1475 template<
size_t M,
size_t N,
typename T >
1476 template<
typename input_iterator_t >
1477 void matrix< M, N, T >::set( input_iterator_t begin_,
1478 input_iterator_t end_,
bool row_major_layout )
1480 input_iterator_t it( begin_ );
1481 if( row_major_layout )
1483 for(
size_t row = 0; row < M; ++row )
1485 for(
size_t col = 0; col < N; ++col, ++it )
1489 at( row, col ) =
static_cast< T
>( *it );
1495 std::copy( it, it + ( M * N ), begin() );
1501 template<
size_t M,
size_t N,
typename T >
1502 void matrix< M, N, T >::zero()
1504 fill( static_cast< T >( 0.0 ) );
1507 template<
size_t M,
size_t N,
typename T >
1508 void matrix< M, N, T >::operator=( T value_ )
1510 std::fill( begin(), end(), value_ );
1515 template<
size_t M,
size_t N,
typename T >
1516 inline matrix< M, N, T >
1517 matrix< M, N, T >::operator+(
const matrix< M, N, T >& other )
const
1519 matrix< M, N, T > result( *
this );
1526 template<
size_t M,
size_t N,
typename T >
1527 void matrix< M, N, T >::operator+=(
const matrix< M, N, T >& other )
1529 iterator it = begin(), it_end = end();
1530 const_iterator other_it = other.begin();
1531 for( ; it != it_end; ++it, ++other_it )
1538 template<
size_t M,
size_t N,
typename T >
1539 void matrix< M, N, T >::operator+=( T scalar )
1541 iterator it = begin(), it_end = end();
1542 for( ; it != it_end; ++it )
1548 template<
size_t M,
size_t N,
typename T >
1549 inline matrix< M, N, T >
1551 operator-(
const matrix< M, N, T >& other )
const
1553 matrix< M, N, T > result( *
this );
1560 template<
size_t M,
size_t N,
typename T >
1563 operator-=(
const matrix< M, N, T >& other )
1565 iterator it = begin(), it_end = end();
1566 const_iterator other_it = other.begin();
1567 for( ; it != it_end; ++it, ++other_it )
1573 template<
size_t M,
size_t N,
typename T >
1575 matrix< M, N, T >::operator-=( T scalar )
1577 iterator it = begin(), it_end = end();
1578 for( ; it != it_end; ++it )
1585 template<
size_t M,
size_t N,
typename T >
1586 template<
size_t O,
size_t P,
size_t Q,
size_t R >
1587 typename enable_if< M == O + Q && N == P + R >::type*
1588 matrix< M, N, T >::direct_sum(
const matrix< O, P, T >& upper_left,
1589 const matrix< Q, R, T >& lower_right )
1591 (*this) =
static_cast< T
>( 0.0 );
1593 for(
size_t row = 0; row < O; ++row )
1595 for(
size_t col = 0; col < P; ++col )
1597 at( row, col ) = upper_left( row, col );
1601 for(
size_t row = 0; row < Q; ++row )
1603 for(
size_t col = 0; col < R; ++col )
1605 at( O + row, P + col ) = lower_right( row, col );
1614 template<
size_t M,
size_t N,
typename T >
1615 template<
size_t O,
size_t P >
1617 matrix< M, N, T >::get_sub_matrix(
size_t row_offset,
size_t col_offset,
1618 typename enable_if< O <= M && P <= N >::type* )
const
1620 matrix< O, P, T > result;
1621 get_sub_matrix( result, row_offset, col_offset );
1627 template<
size_t M,
size_t N,
typename T >
1628 template<
size_t O,
size_t P >
1629 typename enable_if< O <= M && P <= N >::type*
1631 get_sub_matrix( matrix< O, P, T >& result,
1632 size_t row_offset,
size_t col_offset )
const
1634 #ifdef VMMLIB_SAFE_ACCESSORS
1635 if ( O + row_offset > M || P + col_offset > N )
1636 VMMLIB_ERROR(
"index out of bounds.", VMMLIB_HERE );
1639 for(
size_t row = 0; row < O; ++row )
1641 for(
size_t col = 0; col < P; ++col )
1643 result.at( row, col )
1644 = at( row_offset + row, col_offset + col );
1652 template<
size_t M,
size_t N,
typename T >
1653 template<
size_t O,
size_t P >
1654 typename enable_if< O <= M && P <= N >::type*
1656 set_sub_matrix(
const matrix< O, P, T >& sub_matrix,
1657 size_t row_offset,
size_t col_offset )
1659 for(
size_t row = 0; row < O; ++row )
1661 for(
size_t col = 0; col < P; ++col )
1663 at( row_offset + row, col_offset + col )
1664 = sub_matrix.at( row, col );
1672 template<
size_t M,
size_t N,
typename T >
1674 matrix< M, N, T >::det()
const
1676 return compute_determinant( *
this );
1681 template<
size_t M,
size_t N,
typename T >
1682 template<
size_t O,
size_t P,
typename TT >
1683 inline bool matrix< M, N, T >::inverse( matrix< O, P, TT >& inverse_,
1684 T tolerance,
typename
1685 enable_if< M == N && O == P && O == M && M >= 2 && M <= 4, TT >::type* )
1688 return compute_inverse( *
this, inverse_, tolerance );
1693 template<
size_t M,
size_t N,
typename T >
1694 template<
size_t O,
size_t P >
1695 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
1697 get_adjugate( matrix< O, P, T >& adjugate )
const
1699 get_cofactors( adjugate );
1700 adjugate = transpose( adjugate );
1706 template<
size_t M,
size_t N,
typename T >
1707 template<
size_t O,
size_t P >
1708 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
1710 get_cofactors( matrix< O, P, T >& cofactors )
const
1712 matrix< M-1, N-1, T > minor_;
1714 const size_t _negate = 1u;
1715 for(
size_t row_index = 0; row_index < M; ++row_index )
1717 for(
size_t col_index = 0; col_index < N; ++col_index )
1719 if ( ( row_index + col_index ) & _negate )
1720 cofactors( row_index, col_index ) = -get_minor( minor_, row_index, col_index );
1722 cofactors( row_index, col_index ) = get_minor( minor_, row_index, col_index );
1730 template<
size_t M,
size_t N,
typename T >
1731 template<
size_t O,
size_t P >
1734 get_minor( matrix< O, P, T >& minor_,
size_t row_to_cut,
size_t col_to_cut,
1735 typename enable_if< O == M-1 && P == N-1 && M == N && M >= 2 >::type* )
const
1737 size_t row_offset = 0;
1738 size_t col_offset = 0;
1739 for(
size_t row_index = 0; row_index < M; ++row_index )
1741 if ( row_index == row_to_cut )
1745 for(
size_t col_index = 0; col_index < M; ++col_index )
1747 if ( col_index == col_to_cut )
1750 minor_.at( row_index + row_offset, col_index + col_offset )
1751 = at( row_index, col_index );
1756 return compute_determinant( minor_ );
1759 template<
size_t M,
size_t N,
typename T >
1760 template<
typename TT >
1761 matrix< M, N, T >& matrix< M, N, T >::rotate(
1762 const TT angle_,
const vector< M-1, T >& axis,
1763 typename enable_if< M == N && M == 4, TT >::type* )
1765 const T angle =
static_cast< T
>( angle_ );
1767 const T sine = std::sin( angle );
1768 const T cosine = std::cos( angle );
1775 const T _zero = 0.0;
1779 array[0] = cosine + ( one - cosine ) * std::pow( axis.array[0], two );
1780 array[1] = ( one - cosine ) * axis.array[0] * axis.array[1] + sine * axis.array[2];
1781 array[2] = ( one - cosine ) * axis.array[0] * axis.array[2] - sine * axis.array[1];
1784 array[4] = ( one - cosine ) * axis.array[0] * axis.array[1] - sine * axis.array[2];
1785 array[5] = cosine + ( one - cosine ) * std::pow( axis.array[1], two );
1786 array[6] = ( one - cosine ) * axis.array[1] * axis.array[2] + sine * axis.array[0];
1789 array[8] = ( one - cosine ) * axis.array[0] * axis.array[2] + sine * axis.array[1];
1790 array[9] = ( one - cosine ) * axis.array[1] * axis.array[2] - sine * axis.array[0];
1791 array[10] = cosine + ( one - cosine ) * std::pow( axis.array[2], two );
1802 template<
size_t M,
size_t N,
typename T >
1803 template<
typename TT >
1804 matrix< M, N, T >& matrix< M, N, T >::rotate_x(
const TT angle_,
1805 typename enable_if< M == N && M == 4, TT >::type* )
1807 const T angle =
static_cast< T
>( angle_ );
1809 const T sine = std::sin( angle );
1810 const T cosine = std::cos( angle );
1814 tmp = array[ 4 ] * cosine + array[ 8 ] * sine;
1815 array[ 8 ] = - array[ 4 ] * sine + array[ 8 ] * cosine;
1818 tmp = array[ 5 ] * cosine + array[ 9 ] * sine;
1819 array[ 9 ] = - array[ 5 ] * sine + array[ 9 ] * cosine;
1822 tmp = array[ 6 ] * cosine + array[ 10 ] * sine;
1823 array[ 10 ] = - array[ 6 ] * sine + array[ 10 ] * cosine;
1826 tmp = array[ 7 ] * cosine + array[ 11 ] * sine;
1827 array[ 11 ] = - array[ 7 ] * sine + array[ 11 ] * cosine;
1833 template<
size_t M,
size_t N,
typename T >
1834 template<
typename TT >
1835 matrix< M, N, T >& matrix< M, N, T >::rotate_y(
const TT angle_,
1836 typename enable_if< M == N && M == 4, TT >::type* )
1838 const T angle =
static_cast< T
>( angle_ );
1840 const T sine = std::sin( angle );
1841 const T cosine = std::cos( angle );
1845 tmp = array[ 0 ] * cosine - array[ 8 ] * sine;
1846 array[ 8 ] = array[ 0 ] * sine + array[ 8 ] * cosine;
1849 tmp = array[ 1 ] * cosine - array[ 9 ] * sine;
1850 array[ 9 ] = array[ 1 ] * sine + array[ 9 ] * cosine;
1853 tmp = array[ 2 ] * cosine - array[ 10 ] * sine;
1854 array[ 10 ] = array[ 2 ] * sine + array[ 10 ] * cosine;
1857 tmp = array[ 3 ] * cosine - array[ 11 ] * sine;
1858 array[ 11 ] = array[ 3 ] * sine + array[ 11 ] * cosine;
1864 template<
size_t M,
size_t N,
typename T >
1865 template<
typename TT >
1866 matrix< M, N, T >& matrix< M, N, T >::rotate_z(
const TT angle_,
1867 typename enable_if< M == N && M == 4, TT >::type* )
1869 const T angle =
static_cast< T
>( angle_ );
1871 const T sine = std::sin( angle );
1872 const T cosine = std::cos( angle );
1876 tmp = array[ 0 ] * cosine + array[ 4 ] * sine;
1877 array[ 4 ] = - array[ 0 ] * sine + array[ 4 ] * cosine;
1880 tmp = array[ 1 ] * cosine + array[ 5 ] * sine;
1881 array[ 5 ] = - array[ 1 ] * sine + array[ 5 ] * cosine;
1884 tmp = array[ 2 ] * cosine + array[ 6 ] * sine;
1885 array[ 6 ] = - array[ 2 ] * sine + array[ 6 ] * cosine;
1888 tmp = array[ 3 ] * cosine + array[ 7 ] * sine;
1889 array[ 7 ] = - array[ 3 ] * sine + array[ 7 ] * cosine;
1895 template<
size_t M,
size_t N,
typename T >
1896 template<
typename TT >
1897 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_x(
const TT angle_,
1898 typename enable_if< M == N && M == 4, TT >::type* )
1900 const T angle =
static_cast< T
>( angle_ );
1902 const T sine = std::sin( angle );
1903 const T cosine = std::cos( angle );
1908 array[ 1 ] = array[ 1 ] * cosine + array[ 2 ] * sine;
1909 array[ 2 ] = tmp * -sine + array[ 2 ] * cosine;
1912 array[ 5 ] = array[ 5 ] * cosine + array[ 6 ] * sine;
1913 array[ 6 ] = tmp * -sine + array[ 6 ] * cosine;
1916 array[ 9 ] = array[ 9 ] * cosine + array[ 10 ] * sine;
1917 array[ 10 ] = tmp * -sine + array[ 10 ] * cosine;
1920 array[ 13 ] = array[ 13 ] * cosine + array[ 14 ] * sine;
1921 array[ 14 ] = tmp * -sine + array[ 14 ] * cosine;
1926 template<
size_t M,
size_t N,
typename T >
1927 template<
typename TT >
1928 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_y(
const TT angle_,
1929 typename enable_if< M == N && M == 4, TT >::type* )
1931 const T angle =
static_cast< T
>( angle_ );
1933 const T sine = std::sin( angle );
1934 const T cosine = std::cos( angle );
1939 array[ 0 ] = array[ 0 ] * cosine - array[ 2 ] * sine;
1940 array[ 2 ] = tmp * sine + array[ 2 ] * cosine;
1943 array[ 4 ] = array[ 4 ] * cosine - array[ 6 ] * sine;
1944 array[ 6 ] = tmp * sine + array[ 6 ] * cosine;
1947 array[ 8 ] = array[ 8 ] * cosine - array[ 10 ] * sine;
1948 array[ 10 ] = tmp * sine + array[ 10 ] * cosine;
1951 array[ 12 ] = array[ 12 ] * cosine - array[ 14 ] * sine;
1952 array[ 14 ] = tmp * sine + array[ 14 ] * cosine;
1957 template<
size_t M,
size_t N,
typename T >
1958 template<
typename TT >
1959 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_z(
const TT angle_,
1960 typename enable_if< M == N && M == 4, TT >::type* )
1962 const T angle =
static_cast< T
>( angle_ );
1964 const T sine = std::sin( angle );
1965 const T cosine = std::cos( angle );
1970 array[ 0 ] = array[ 0 ] * cosine + array[ 1 ] * sine;
1971 array[ 1 ] = tmp * -sine + array[ 1 ] * cosine;
1974 array[ 4 ] = array[ 4 ] * cosine + array[ 5 ] * sine;
1975 array[ 5 ] = tmp * -sine + array[ 5 ] * cosine;
1978 array[ 8 ] = array[ 8 ] * cosine + array[ 9 ] * sine;
1979 array[ 9 ] = tmp * -sine + array[ 9 ] * cosine;
1982 array[ 12 ] = array[ 12 ] * cosine + array[ 13 ] * sine;
1983 array[ 13 ] = tmp * -sine + array[ 13 ] * cosine;
1988 template<
size_t M,
size_t N,
typename T >
1989 template<
typename TT >
1990 matrix< M, N, T >& matrix< M, N, T >::scale(
const TT _scale[3],
1991 typename enable_if< M == N && M == 4, TT >::type* )
1993 const T scale0 =
static_cast< T
>( _scale[ 0 ] );
1994 const T scale1 =
static_cast< T
>( _scale[ 1 ] );
1995 const T scale2 =
static_cast< T
>( _scale[ 2 ] );
2007 array[10] *= scale2;
2008 array[11] *= scale2;
2013 template<
size_t M,
size_t N,
typename T >
2014 template<
typename TT >
2015 matrix< M, N, T >& matrix< M, N, T >::scale(
const TT x_,
const T y_,
const T z_,
2016 typename enable_if< M == N && M == 4, TT >::type* )
2018 const T _x =
static_cast< T
>( x_ );
2036 template<
size_t M,
size_t N,
typename T >
2037 template<
typename TT >
2038 inline matrix< M, N, T >& matrix< M, N, T >::scale(
2039 const vector< 3, TT >& scale_,
2040 typename enable_if< M == N && M == 4, TT >::type* )
2042 return scale( scale_.array );
2047 template<
size_t M,
size_t N,
typename T >
2048 template<
typename TT >
2049 matrix< M, N, T >& matrix< M, N, T >::scale_translation(
const TT scale_[3],
2050 typename enable_if< M == N && M == 4, TT >::type* )
2052 array[12] *=
static_cast< T
>( scale_[0] );
2053 array[13] *=
static_cast< T
>( scale_[1] );
2054 array[14] *=
static_cast< T
>( scale_[2] );
2058 template<
size_t M,
size_t N,
typename T >
2059 template<
typename TT >
2060 inline matrix< M, N, T >& matrix< M, N, T >::scale_translation(
2061 const vector< 3, TT >& scale_,
2062 typename enable_if< M == N && M == 4, TT >::type* )
2064 return scale_translation( scale_.array );
2067 template<
size_t M,
size_t N,
typename T >
2068 template<
typename TT >
2069 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
2070 const TT x_,
const TT y_,
const TT z_,
2071 typename enable_if< M == N && M == 4, TT >::type* )
2073 array[12] =
static_cast< T
>( x_ );
2074 array[13] =
static_cast< T
>( y_ );
2075 array[14] =
static_cast< T
>( z_ );
2079 template<
size_t M,
size_t N,
typename T >
2080 template<
typename TT >
2081 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
const TT trans[3],
2082 typename enable_if< M == N && M == 4, TT >::type* )
2084 array[12] =
static_cast< T
>( trans[ 0 ] );
2085 array[13] =
static_cast< T
>( trans[ 1 ] );
2086 array[14] =
static_cast< T
>( trans[ 2 ] );
2090 template<
size_t M,
size_t N,
typename T >
2091 template<
typename TT >
2092 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
2093 const vector< 3, TT >& translation_,
2094 typename enable_if< M == N && M == 4, TT >::type* )
2096 return set_translation( translation_.array );
2099 template<
size_t M,
size_t N,
typename T >
template<
typename TT >
inline
2100 void matrix< M, N, T >::get_translation( vector< N-1, TT >& translation_ )
2103 for(
size_t i = 0; i < N-1; ++i )
2104 translation_.array[ i ] = array[ i + M * (N - 1) ];
2108 template<
size_t M,
size_t N,
typename T >
2109 inline vector< N-1, T > matrix< M, N, T >::get_translation()
const
2111 vector< N-1, T > result;
2112 get_translation( result );
2118 template<
size_t M,
size_t N,
typename T >
2128 template<
size_t M,
size_t N,
typename T >
2129 typename matrix< M, N, T >::iterator
2138 template<
size_t M,
size_t N,
typename T >
2139 typename matrix< M, N, T >::iterator
2143 return array + size();
2148 template<
size_t M,
size_t N,
typename T >
2149 typename matrix< M, N, T >::const_iterator
2158 template<
size_t M,
size_t N,
typename T >
2159 typename matrix< M, N, T >::const_iterator
2163 return array + size();
2168 template<
size_t M,
size_t N,
typename T >
2169 typename matrix< M, N, T >::reverse_iterator
2173 return array + size() - 1;
2178 template<
size_t M,
size_t N,
typename T >
2179 typename matrix< M, N, T >::reverse_iterator
2188 template<
size_t M,
size_t N,
typename T >
2189 typename matrix< M, N, T >::const_reverse_iterator
2193 return array + size() - 1;
2198 template<
size_t M,
size_t N,
typename T >
2199 typename matrix< M, N, T >::const_reverse_iterator
2208 template<
size_t M,
size_t N,
typename T >
template<
typename init_functor_t >
2209 const matrix< M, N, T > matrix< M, N, T >::get_initialized_matrix()
2211 matrix< M, N, T > matrix_;
2212 init_functor_t()( matrix_ );
2219 template<
size_t M,
size_t N,
typename T >
2220 const matrix< M, N, T >
2221 matrix< M, N, T >::IDENTITY(
2222 matrix< M, N, T >::get_initialized_matrix<
2223 set_to_identity_functor< matrix< M, N, T > > >( ));
2226 template<
size_t M,
size_t N,
typename T >
2227 const matrix< M, N, T >
2228 matrix< M, N, T >::ZERO(
2230 get_initialized_matrix< set_to_zero_functor< matrix< M, N, T > > >()
2235 template<
size_t M,
size_t N,
typename T >
2237 matrix< M, N, T >::frobenius_norm( )
const
2241 const_iterator it = begin(), it_end = end();
2242 for( ; it != it_end; ++it )
2247 return std::sqrt(norm);
2250 template<
size_t M,
size_t N,
typename T >
2252 matrix< M, N, T >::p_norm(
double p )
const
2256 const_iterator it = begin(), it_end = end();
2257 for( ; it != it_end; ++it )
2259 norm += std::pow(*it, p);
2262 return std::pow(norm,1./p);
2266 template<
size_t M,
size_t N,
typename T >
2267 template<
size_t O >
2269 matrix< M, N, T >::khatri_rao_product(
const matrix< O, N, T >& right_, matrix< M*O, N, T >& prod_ )
const
2272 for (
size_t col = 0; col < N; ++col )
2274 for (
size_t m = 0; m < M; ++m )
2276 for (
size_t o = 0; o < O; ++o )
2278 prod_.at(O*m + o, col) = at( m, col ) * right_.at( o, col );
2284 template<
size_t M,
size_t N,
typename T >
2285 template<
size_t O,
size_t P >
2287 matrix< M, N, T >::kronecker_product(
const matrix< O, P, T >& right_, matrix< M*O, N*P, T >& result_ )
const
2290 for (
size_t m = 0; m < M; ++m )
2292 for (
size_t n = 0; n < N; ++n )
2294 for (
size_t o = 0; o < O; ++o )
2296 for (
size_t p = 0; p < P; ++p )
2298 result_.at(O*m + o, P*n + p) = at( m, n ) * right_.at( o, p );
2306 template<
size_t M,
size_t N,
typename T >
2307 template<
typename TT >
2309 matrix< M, N, T >::cast_from(
const matrix< M, N, TT >& other )
2312 typedef typename matrix_tt_type::const_iterator tt_const_iterator;
2314 iterator it = begin(), it_end = end();
2315 tt_const_iterator other_it = other.begin();
2316 for( ; it != it_end; ++it, ++other_it )
2318 *it =
static_cast< T
>( *other_it );
2323 template<
size_t M,
size_t N,
typename T >
2325 matrix< M, N, T >::get_min()
const
2327 T min_value =
static_cast<T
>(std::numeric_limits<T>::max());
2329 const_iterator it = begin(),
2331 for( ; it != it_end; ++it)
2333 if ( *it < min_value ) {
2340 template<
size_t M,
size_t N,
typename T >
2342 matrix< M, N, T >::get_max()
const
2344 T max_value =
static_cast<T
>(0);
2346 const_iterator it = begin(),
2348 for( ; it != it_end; ++it)
2350 if ( *it > max_value ) {
2358 template<
size_t M,
size_t N,
typename T >
2360 matrix< M, N, T >::get_abs_min()
const
2362 T min_value =
static_cast<T
>(std::numeric_limits<T>::max());
2364 const_iterator it = begin(),
2366 for( ; it != it_end; ++it)
2368 if ( fabs(*it) < fabs(min_value) ) {
2369 min_value = fabs(*it);
2375 template<
size_t M,
size_t N,
typename T >
2377 matrix< M, N, T >::get_abs_max()
const
2379 T max_value =
static_cast<T
>(0);
2381 const_iterator it = begin(),
2383 for( ; it != it_end; ++it)
2385 if ( fabs(*it) > fabs(max_value) ) {
2386 max_value = fabs(*it);
2394 template<
size_t M,
size_t N,
typename T >
2396 matrix< M, N, T >::nnz()
const
2400 const_iterator it = begin(),
2402 for( ; it != it_end; ++it)
2412 template<
size_t M,
size_t N,
typename T >
2414 matrix< M, N, T >::nnz(
const T& threshold_ )
const
2418 const_iterator it = begin(),
2420 for( ; it != it_end; ++it)
2422 if ( fabs(*it) > threshold_ ) {
2430 template<
size_t M,
size_t N,
typename T >
2432 matrix< M, N, T >::threshold(
const T& threshold_value_ )
2434 iterator it = begin(),
2436 for( ; it != it_end; ++it)
2438 if ( fabs(*it) <= threshold_value_ ) {
2439 *it =
static_cast<T
> (0);
2445 template<
size_t M,
size_t N,
typename T >
2446 template<
typename TT >
2448 matrix< M, N, T >::quantize_to( matrix< M, N, TT >& quantized_,
const T& min_value,
const T& max_value )
const
2450 long max_tt_range = long(std::numeric_limits< TT >::max());
2451 long min_tt_range = long(std::numeric_limits< TT >::min());
2452 long tt_range = (max_tt_range - min_tt_range);
2454 T t_range = max_value - min_value;
2456 typedef matrix< M, N, TT > m_tt_type ;
2457 typedef typename m_tt_type::iterator tt_iterator;
2458 tt_iterator it_quant = quantized_.begin();
2459 const_iterator it = begin(), it_end = end();
2461 for( ; it != it_end; ++it, ++it_quant )
2463 if (std::numeric_limits<TT>::is_signed ) {
2464 *it_quant = TT( std::min( std::max( min_tt_range,
long(( *it * tt_range / t_range ) + 0.5)), max_tt_range ));
2466 *it_quant = TT( std::min( std::max( min_tt_range,
long(((*it - min_value) * tt_range / t_range) + 0.5)), max_tt_range ));
2472 template<
size_t M,
size_t N,
typename T >
2473 template<
typename TT >
2475 matrix< M, N, T >::quantize( matrix< M, N, TT >& quantized_, T& min_value, T& max_value )
const
2477 min_value = get_min();
2478 max_value = get_max();
2479 quantize_to( quantized_, min_value, max_value );
2484 template<
size_t M,
size_t N,
typename T >
2485 template<
typename TT >
2487 matrix< M, N, T >::dequantize( matrix< M, N, TT >& dequantized_,
const TT& min_value,
const TT& max_value )
const
2489 long max_t_range = long(std::numeric_limits< T >::max());
2490 long min_t_range = long(std::numeric_limits< T >::min());
2491 long t_range = (max_t_range - min_t_range);
2493 TT tt_range = max_value - min_value;
2495 typedef matrix< M, N, TT > m_tt_type ;
2496 typedef typename m_tt_type::iterator tt_iterator;
2497 tt_iterator it_dequant = dequantized_.begin();
2498 const_iterator it = begin(), it_end = end();
2499 for( ; it != it_end; ++it, ++it_dequant )
2501 if (std::numeric_limits<T>::is_signed ) {
2502 *it_dequant = std::min( std::max( min_value, TT((TT(*it) / t_range) * tt_range)), max_value );
2504 *it_dequant = std::min( std::max( min_value, TT((((TT(*it) / t_range)) * tt_range ) + min_value)), max_value );
2509 template<
size_t M,
size_t N,
typename T >
2511 matrix< M, N, T >::columnwise_sum( vector< N, T>& summed_columns_ )
const
2514 for (
size_t n = 0; n < N; ++n )
2517 for (
size_t m = 0; m < M; ++m )
2519 value += at( m, n );
2521 summed_columns_.at( n ) = value;
2525 template<
size_t M,
size_t N,
typename T >
2527 matrix< M, N, T >::sum_elements( )
const
2531 const_iterator it = begin(), it_end = end();
2532 for( ; it != it_end; ++it )
2540 template<
size_t M,
size_t N,
typename T >
2542 typename enable_if< R == M && R == N>::type*
2543 matrix< M, N, T >::diag(
const vector< R, T >& diag_values_ )
2546 for(
size_t r = 0; r < R; ++r )
2548 at(r, r) =
static_cast< T
>( diag_values_.at(r) );
2554 template<
size_t M,
size_t N,
typename T >
2556 matrix< M, N, T >::set_dct()
2558 const double num_rows = M;
2559 double fill_value = 0.0f;
2560 for(
size_t row = 0; row < M; ++row )
2563 const double weight = ( row == 0.0 ) ? std::sqrt(1/num_rows) :
2564 std::sqrt(2/num_rows);
2565 for(
size_t col = 0; col < N; ++col )
2567 fill_value = (2 * col + 1) * row * M_PI / (2*M);
2568 fill_value = std::cos( fill_value );
2569 fill_value *= weight;
2570 at( row, col ) =
static_cast< T
>( fill_value ) ;
2576 template<
size_t M,
size_t N,
typename T >
2578 matrix< M, N, T >::set_random(
int seed )
2583 double fillValue = 0.0f;
2584 for(
size_t row = 0; row < M; ++row )
2586 for(
size_t col = 0; col < N; ++col )
2589 fillValue /= RAND_MAX;
2590 at( row, col ) = -1.0 + 2.0 *
static_cast< double >( fillValue ) ;
2595 template<
size_t M,
size_t N,
typename T >
2597 matrix< M, N, T >::write_to_raw(
const std::string& dir_,
const std::string& filename_ )
const
2599 int dir_length = dir_.size() -1;
2600 int last_separator = dir_.find_last_of(
"/");
2601 std::string path = dir_;
2602 if (last_separator < dir_length ) {
2605 path.append( filename_ );
2607 if( filename_.find(
"raw", filename_.size() -3) == std::string::npos )
2610 path.append(
"raw" );
2612 std::string path_raw = path;
2614 std::ofstream outfile;
2615 outfile.open( path_raw.c_str() );
2616 if( outfile.is_open() ) {
2617 size_t len_slice =
sizeof(T) * M*N;
2618 outfile.write( (
char*)&(*
this), len_slice );
2621 std::cout <<
"no file open" << std::endl;
2625 template<
size_t M,
size_t N,
typename T >
2627 matrix< M, N, T >::read_from_raw(
const std::string& dir_,
const std::string& filename_ )
2629 int dir_length = dir_.size() -1;
2630 int last_separator = dir_.find_last_of(
"/");
2631 std::string path = dir_;
2632 if (last_separator < dir_length ) {
2635 path.append( filename_ );
2637 size_t max_file_len = 2147483648u -
sizeof(T) ;
2638 size_t len_data =
sizeof(T) * size();
2639 char* data =
new char[ len_data ];
2640 std::ifstream infile;
2641 infile.open( path.c_str(), std::ios::in);
2643 if( infile.is_open())
2645 iterator it = begin(),
2648 while ( len_data > 0 )
2650 size_t len_read = (len_data % max_file_len ) > 0 ?
2651 len_data % max_file_len : len_data;
2652 len_data -= len_read;
2653 infile.read( data, len_read );
2655 T* T_ptr = (T*)&(data[0]);
2656 for( ; (it != it_end) && (len_read > 0); ++it, len_read -=
sizeof(T) )
2658 *it = *T_ptr; ++T_ptr;
2665 std::cout <<
"no file open" << std::endl;
2673 template<
size_t M,
size_t N,
typename T >
2675 matrix< M, N, T >::write_csv_file(
const std::string& dir_,
const std::string& filename_ )
const
2677 int dir_length = dir_.size() -1;
2678 int last_separator = dir_.find_last_of(
"/");
2679 std::string path = dir_;
2680 if (last_separator < dir_length ) {
2683 path.append( filename_ );
2685 int suffix_pos = filename_.find(
"csv", filename_.size() -3);
2686 if( suffix_pos == (-1)) {
2688 path.append(
"csv" );
2691 std::ofstream outfile;
2692 outfile.open( path.c_str() );
2693 if( outfile.is_open() ) {
2694 outfile << *
this << std::endl;
2697 std::cout <<
"no file open" << std::endl;
2702 template<
size_t M,
size_t N,
typename T >
2704 matrix< M, N, T >::read_csv_file(
const std::string& dir_,
const std::string& filename_ )
2706 int dir_length = dir_.size() -1;
2707 int last_separator = dir_.find_last_of(
"/");
2708 std::string path = dir_;
2709 if (last_separator < dir_length ) {
2712 path.append( filename_ );
2714 int suffix_pos = filename_.find(
"csv", filename_.size() -3);
2715 if( suffix_pos == (-1)) {
2717 path.append(
"csv" );
2720 std::ifstream infile;
2721 infile.open( path.c_str(), std::ios::in);
2722 if( infile.is_open() ) {
2727 std::cout <<
"no file open" << std::endl;
2733 template<
size_t M,
size_t N,
typename T >
2735 matrix< M, N, T >::sum_rows( matrix< M/2, N, T>& other )
const
2737 typedef vector< N, T > row_type;
2739 row_type* row0 =
new row_type;
2740 row_type* row1 =
new row_type;
2744 for (
size_t row = 0; row < M; ++row )
2746 get_row( row++, *row0 );
2749 get_row( row, *row1 );
2751 other.set_row( row/2 , *row0 );
2759 template<
size_t M,
size_t N,
typename T >
2761 matrix< M, N, T >::sum_columns( matrix< M, N/2, T>& other )
const
2763 typedef vector< M, T > col_type;
2765 col_type* col0 =
new col_type;
2766 col_type* col1 =
new col_type;
2770 for (
size_t col = 0; col< N; ++col )
2772 get_column( col++, *col0 );
2775 get_column( col, *col1 );
2777 other.set_column( col/2, *col0 );
vmml::matrix< 3, 3, double > Matrix3d
A 3x3 double matrix.
vmml::matrix< 4, 4, float > Matrix4f
A 4x4 float matrix.
vmml::matrix< 4, 4, double > Matrix4d
A 4x4 double matrix.
heavily inspired by boost::enable_if http://www.boost.org, file: boost/utility/enable_if.hpp, Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine
vmml::matrix< 3, 3, float > Matrix3f
A 3x3 float matrix.