32 #ifndef __VMML__MATRIX__HPP__
33 #define __VMML__MATRIX__HPP__
35 #include <vmmlib/enable_if.hpp>
36 #include <vmmlib/math.hpp>
37 #include <vmmlib/matrix_functors.hpp>
38 #include <vmmlib/types.hpp>
54 template<
size_t M,
size_t N,
typename T >
class matrix
59 typedef const T* const_iterator;
60 typedef std::reverse_iterator< iterator > reverse_iterator;
61 typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
63 static const size_t ROWS = M;
64 static const size_t COLS = N;
76 matrix(
const T* begin,
const T* end );
78 template<
size_t P,
size_t Q,
typename U >
87 typename enable_if< M == O+1 && N == O+1 && O == 3 >::type* = 0 );
96 typename enable_if< M == O+1 && N == O+1 && O == 3 >::type* = 0 );
99 inline T& operator()(
size_t row_index,
size_t col_index );
100 inline const T& operator()(
size_t row_index,
size_t col_index )
const;
102 inline T& at(
size_t row_index,
size_t col_index );
103 inline const T& at(
size_t row_index,
size_t col_index )
const;
108 const_iterator begin()
const;
109 const_iterator end()
const;
111 reverse_iterator rbegin();
112 reverse_iterator rend();
113 const_reverse_iterator rbegin()
const;
114 const_reverse_iterator rend()
const;
116 #ifndef VMMLIB_NO_CONVERSION_OPERATORS
119 operator const T*()
const;
122 bool operator==(
const matrix& other )
const;
123 bool operator!=(
const matrix& other )
const;
127 bool equals(
const matrix& other,
128 T tolerance = std::numeric_limits< T >::epsilon( ))
const;
130 void multiply_piecewise(
const matrix& other );
137 template<
size_t U,
size_t V >
146 template<
size_t O,
size_t P,
typename TT >
147 typename enable_if< M == N && O == P && M == O, TT >::type*
150 inline matrix operator+(
const matrix& other )
const;
151 inline matrix operator-(
const matrix& other )
const;
153 void operator+=(
const matrix& other );
154 void operator-=(
const matrix& other );
156 void operator+=( T scalar );
157 void operator-=( T scalar );
159 template<
size_t O,
size_t P,
size_t Q,
size_t R >
160 typename enable_if< M == O + Q && N == P + R >::type*
166 matrix operator*( T scalar );
167 void operator*=( T scalar );
169 matrix operator/( T scalar );
170 void operator/=( T scalar );
190 template<
size_t uM,
size_t vM >
191 typename enable_if< uM == 3 && vM == 3 && M == N && M == 4 >::type*
196 template<
size_t O,
size_t P >
198 get_sub_matrix(
size_t row_offset,
size_t col_offset,
199 typename enable_if< O <= M && P <= N >::type* = 0 )
const;
201 template<
size_t O,
size_t P >
204 size_t row_offset = 0,
size_t col_offset = 0 )
const;
206 template<
size_t O,
size_t P >
209 size_t row_offset = 0,
size_t col_offset = 0 );
222 template<
size_t P,
size_t Q,
typename U >
224 void operator=(
const T old_fashioned_matrix[ M ][ N ] );
229 void operator=(
const T* data_array );
230 void operator=(
const std::vector< T >& data );
233 void operator=( T fill_value );
234 void fill( T fill_value );
238 template<
typename input_iterator_t >
239 void set( input_iterator_t begin_, input_iterator_t end_,
240 bool row_major_layout =
true );
246 void set_random(
int seed = -1 );
253 double frobenius_norm()
const;
254 double p_norm(
double p )
const;
256 template<
typename TT >
259 void read_csv_file(
const std::string& dir_,
const std::string& filename_ );
260 void write_csv_file(
const std::string& dir_,
const std::string& filename_ )
const;
261 void write_to_raw(
const std::string& dir_,
const std::string& filename_ )
const;
262 void read_from_raw(
const std::string& dir_,
const std::string& filename_ ) ;
264 template<
typename TT >
265 void quantize_to(
matrix< M, N, TT >& quantized_,
const T& min_value,
const T& max_value )
const;
266 template<
typename TT >
268 template<
typename TT >
269 void dequantize(
matrix< M, N, TT >& quantized_,
const TT& min_value,
const TT& max_value )
const;
272 double sum_elements()
const;
278 typename enable_if< R == M && R == N >::type*
286 template<
size_t O,
size_t P >
291 T get_abs_min()
const;
292 T get_abs_max()
const;
296 size_t nnz(
const T& threshold_ )
const;
297 void threshold(
const T& threshold_value_ );
300 void get_column(
size_t column_index,
vector< M, T>& column )
const;
316 size_t get_number_of_rows()
const;
317 size_t get_number_of_columns()
const;
324 template<
size_t O,
size_t P,
typename TT >
326 T tolerance = std::numeric_limits<T>::epsilon(),
329 template<
size_t O,
size_t P >
333 template<
size_t O,
size_t P >
334 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
339 template<
size_t O,
size_t P >
350 template<
typename TT >
352 typename enable_if< M == N && M == 4, TT >::type* = 0 );
354 template<
typename TT >
356 typename enable_if< M == N && M == 4, TT >::type* = 0 );
358 template<
typename TT >
360 typename enable_if< M == N && M == 4, TT >::type* = 0 );
362 template<
typename TT >
364 typename enable_if< M == N && M == 4, TT >::type* = 0 );
366 template<
typename TT >
368 typename enable_if< M == N && M == 4, TT >::type* = 0 );
370 template<
typename TT >
372 typename enable_if< M == N && M == 4, TT >::type* = 0 );
374 template<
typename TT >
376 typename enable_if< M == N && M == 4, TT >::type* = 0 );
378 template<
typename TT >
380 typename enable_if< M == N && M == 4, TT >::type* = 0 );
382 template<
typename TT >
384 typename enable_if< M == N && M == 4, TT >::type* = 0 );
386 template<
typename TT >
388 typename enable_if< M == N && M == 4, TT >::type* = 0 );
390 template<
typename TT >
392 typename enable_if< M == N && M == 4, TT >::type* = 0 );
394 template<
typename TT >
396 typename enable_if< M == N && M == 4, TT >::type* = 0 );
398 template<
typename TT >
400 typename enable_if< M == N && M == 4, TT >::type* = 0 );
402 template<
typename TT >
404 typename enable_if< M == N && M == 4, TT >::type* = 0 );
406 template<
typename TT >
408 typename enable_if< M == N && M == 4, TT >::type* = 0 );
410 template<
typename TT >
413 vector< N-1, T > get_translation()
const;
422 typename enable_if< M == O+1 && N == O+1 && O == 3 >::type* = 0 )
const;
425 template<
typename init_functor_t >
426 static const matrix get_initialized_matrix();
439 row_accessor( T* array_ ) : array( array_ ) {}
440 T& operator[](
const size_t col_index )
442 if ( col_index >= N )
443 throw std::runtime_error(
"column index out of bounds" );
444 return array[ col_index * M ];
447 const T& operator[](
const size_t col_index )
const
449 if ( col_index >= N )
450 throw std::runtime_error(
"column index out of bounds" );
451 return array[ col_index * M ];
460 inline row_accessor operator[](
const size_t row_index )
463 throw std::runtime_error(
"row index out of bounds" );
464 return row_accessor( array + row_index );
468 inline row_accessor operator[](
int row_index )
470 return ( *
this )[ size_t ( row_index ) ];
473 friend std::ostream& operator << ( std::ostream& os,
476 const std::ios::fmtflags flags = os.flags();
477 const int prec = os.precision();
479 os.setf( std::ios::right, std::ios::adjustfield );
482 for(
size_t row_index = 0; row_index < M; ++row_index )
485 for(
size_t col_index = 0; col_index < N; ++col_index )
487 os << std::setw(10) << matrix.at( row_index, col_index ) <<
" ";
489 os <<
"|" << std::endl;
491 os.precision( prec );
506 #include <vmmlib/quaternion.hpp>
507 #include <vmmlib/vector.hpp>
514 template<
size_t M,
size_t N,
typename T >
515 inline void multiply(
const matrix< M, N, T >& left,
516 const matrix< M, N, T >& right,
517 matrix< M, N, T >& result )
519 result.multiply( left, right );
524 template<
size_t M,
size_t N,
typename T >
525 template<
size_t U,
size_t V >
526 void matrix< M, N, T>::convolve(
const matrix< U, V, T >& kernel)
528 matrix< M, N, T> temp;
530 for(
size_t y_ = 0; y_ < N; ++y_)
532 for(
size_t x_ = 0; x_ < M; ++x_)
536 for(
size_t j = 0; j < V; ++j)
538 int srcy = y_ - V/2 + j;
541 if(srcy < 0) srcy = 0;
542 if(srcy >=
int(N)) srcy = N-1;
544 for(
size_t i = 0; i < U; ++i)
546 int srcx = x_ - U/2 + i;
549 if(srcx < 0) srcx = 0;
550 if(srcx >=
int(M)) srcx = M-1;
552 sum += kernel.at(j,i) * at(srcy,srcx);
555 temp.at(y_,x_) = sum;
564 template<
size_t M,
size_t N,
size_t P,
typename T >
566 multiply(
const matrix< M, P, T >& left,
const matrix< P, N, T >& right,
567 matrix< M, N, T >& result )
569 result.multiply( left, right );
573 template<
size_t M,
size_t N,
typename T >
574 inline typename enable_if< M == N >::type* identity( matrix< M, N, T >& m )
576 m =
static_cast< T
>( 0.0 );
577 for(
size_t index = 0; index < M; ++index )
578 m( index, index ) =
static_cast< T
>( 1.0 );
584 template<
typename T >
585 inline T compute_determinant(
const matrix< 1, 1, T >& matrix_ )
587 return matrix_.array[ 0 ];
592 template<
typename T >
593 inline T compute_determinant(
const matrix< 2, 2, T >& matrix_ )
595 const T& a = matrix_( 0, 0 );
596 const T& b = matrix_( 0, 1 );
597 const T& c = matrix_( 1, 0 );
598 const T& d = matrix_( 1, 1 );
599 return a * d - b * c;
604 template<
typename T >
605 inline T compute_determinant(
const matrix< 3, 3, T >& m_ )
608 m_( 0,0 ) * ( m_( 1,1 ) * m_( 2,2 ) - m_( 1,2 ) * m_( 2,1 ) )
609 + m_( 0,1 ) * ( m_( 1,2 ) * m_( 2,0 ) - m_( 1,0 ) * m_( 2,2 ) )
610 + m_( 0,2 ) * ( m_( 1,0 ) * m_( 2,1 ) - m_( 1,1 ) * m_( 2,0 ) );
614 template<
typename T >
615 inline T compute_determinant(
const matrix< 4, 4, T >& m )
635 m03 * m12 * m21 * m30
636 - m02 * m13 * m21 * m30
637 - m03 * m11 * m22 * m30
638 + m01 * m13 * m22 * m30
639 + m02 * m11 * m23 * m30
640 - m01 * m12 * m23 * m30
641 - m03 * m12 * m20 * m31
642 + m02 * m13 * m20 * m31
643 + m03 * m10 * m22 * m31
644 - m00 * m13 * m22 * m31
645 - m02 * m10 * m23 * m31
646 + m00 * m12 * m23 * m31
647 + m03 * m11 * m20 * m32
648 - m01 * m13 * m20 * m32
649 - m03 * m10 * m21 * m32
650 + m00 * m13 * m21 * m32
651 + m01 * m10 * m23 * m32
652 - m00 * m11 * m23 * m32
653 - m02 * m11 * m20 * m33
654 + m01 * m12 * m20 * m33
655 + m02 * m10 * m21 * m33
656 - m00 * m12 * m21 * m33
657 - m01 * m10 * m22 * m33
658 + m00 * m11 * m22 * m33;
663 template<
typename T >
664 bool compute_inverse(
const matrix< 2, 2, T >& m_, matrix< 2, 2, T >& inverse_,
665 T tolerance_ = std::numeric_limits<T>::epsilon())
667 const T det_ = compute_determinant( m_ );
668 if( fabs( det_ ) < tolerance_ )
671 const T detinv =
static_cast< T
>( 1.0 ) / det_;
673 m_.get_adjugate( inverse_ );
680 template<
typename T >
681 bool compute_inverse(
const matrix< 3, 3, T >& m_, matrix< 3, 3, T >& inverse_,
682 T tolerance_ = std::numeric_limits<T>::epsilon() )
686 inverse_.at( 0, 0 ) = m_.at( 1, 1 ) * m_.at( 2, 2 ) - m_.at( 1, 2 ) * m_.at( 2, 1 );
687 inverse_.at( 0, 1 ) = m_.at( 0, 2 ) * m_.at( 2, 1 ) - m_.at( 0, 1 ) * m_.at( 2, 2 );
688 inverse_.at( 0, 2 ) = m_.at( 0, 1 ) * m_.at( 1, 2 ) - m_.at( 0, 2 ) * m_.at( 1, 1 );
689 inverse_.at( 1, 0 ) = m_.at( 1, 2 ) * m_.at( 2, 0 ) - m_.at( 1, 0 ) * m_.at( 2, 2 );
690 inverse_.at( 1, 1 ) = m_.at( 0, 0 ) * m_.at( 2, 2 ) - m_.at( 0, 2 ) * m_.at( 2, 0 );
691 inverse_.at( 1, 2 ) = m_.at( 0, 2 ) * m_.at( 1, 0 ) - m_.at( 0, 0 ) * m_.at( 1, 2 );
692 inverse_.at( 2, 0 ) = m_.at( 1, 0 ) * m_.at( 2, 1 ) - m_.at( 1, 1 ) * m_.at( 2, 0 );
693 inverse_.at( 2, 1 ) = m_.at( 0, 1 ) * m_.at( 2, 0 ) - m_.at( 0, 0 ) * m_.at( 2, 1 );
694 inverse_.at( 2, 2 ) = m_.at( 0, 0 ) * m_.at( 1, 1 ) - m_.at( 0, 1 ) * m_.at( 1, 0 );
696 const T determinant =
697 m_.at( 0, 0 ) * inverse_.at( 0, 0 )
698 + m_.at( 0, 1 ) * inverse_.at( 1, 0 )
699 + m_.at( 0, 2 ) * inverse_.at( 2, 0 );
701 if ( fabs( determinant ) <= tolerance_ )
704 const T detinv =
static_cast< T
>( 1.0 ) / determinant;
706 inverse_.at( 0, 0 ) *= detinv;
707 inverse_.at( 0, 1 ) *= detinv;
708 inverse_.at( 0, 2 ) *= detinv;
709 inverse_.at( 1, 0 ) *= detinv;
710 inverse_.at( 1, 1 ) *= detinv;
711 inverse_.at( 1, 2 ) *= detinv;
712 inverse_.at( 2, 0 ) *= detinv;
713 inverse_.at( 2, 1 ) *= detinv;
714 inverse_.at( 2, 2 ) *= detinv;
720 template<
typename T >
721 bool compute_inverse(
const matrix< 4, 4, T >& m_,
722 matrix< 4, 4, T >& inv_,
723 T tolerance_ = std::numeric_limits<T>::epsilon() )
725 const T* array = m_.array;
729 const T t1[6] = { array[ 2] * array[ 7] - array[ 6] * array[ 3],
730 array[ 2] * array[11] - array[10] * array[ 3],
731 array[ 2] * array[15] - array[14] * array[ 3],
732 array[ 6] * array[11] - array[10] * array[ 7],
733 array[ 6] * array[15] - array[14] * array[ 7],
734 array[10] * array[15] - array[14] * array[11] };
737 inv_.array[0] = array[ 5] * t1[5] - array[ 9] * t1[4] + array[13] * t1[3];
738 inv_.array[1] = array[ 9] * t1[2] - array[13] * t1[1] - array[ 1] * t1[5];
739 inv_.array[2] = array[13] * t1[0] - array[ 5] * t1[2] + array[ 1] * t1[4];
740 inv_.array[3] = array[ 5] * t1[1] - array[ 1] * t1[3] - array[ 9] * t1[0];
741 inv_.array[4] = array[ 8] * t1[4] - array[ 4] * t1[5] - array[12] * t1[3];
742 inv_.array[5] = array[ 0] * t1[5] - array[ 8] * t1[2] + array[12] * t1[1];
743 inv_.array[6] = array[ 4] * t1[2] - array[12] * t1[0] - array[ 0] * t1[4];
744 inv_.array[7] = array[ 0] * t1[3] - array[ 4] * t1[1] + array[ 8] * t1[0];
747 const T t2[6] = { array[ 0] * array[ 5] - array[ 4] * array[ 1],
748 array[ 0] * array[ 9] - array[ 8] * array[ 1],
749 array[ 0] * array[13] - array[12] * array[ 1],
750 array[ 4] * array[ 9] - array[ 8] * array[ 5],
751 array[ 4] * array[13] - array[12] * array[ 5],
752 array[ 8] * array[13] - array[12] * array[ 9] };
755 inv_.array[8] = array[ 7] * t2[5] - array[11] * t2[4] + array[15] * t2[3];
756 inv_.array[9] = array[11] * t2[2] - array[15] * t2[1] - array[ 3] * t2[5];
757 inv_.array[10] = array[15] * t2[0] - array[ 7] * t2[2] + array[ 3] * t2[4];
758 inv_.array[11] = array[ 7] * t2[1] - array[ 3] * t2[3] - array[11] * t2[0];
759 inv_.array[12] = array[10] * t2[4] - array[ 6] * t2[5] - array[14] * t2[3];
760 inv_.array[13] = array[ 2] * t2[5] - array[10] * t2[2] + array[14] * t2[1];
761 inv_.array[14] = array[ 6] * t2[2] - array[14] * t2[0] - array[ 2] * t2[4];
762 inv_.array[15] = array[ 2] * t2[3] - array[ 6] * t2[1] + array[10] * t2[0];
765 const T determinant = array[0] * inv_.array[0] + array[4] * inv_.array[1] +
766 array[8] * inv_.array[2] + array[12] * inv_.array[3];
768 if( fabs( determinant ) <= tolerance_ )
772 const T detinv =
static_cast< T
>( 1.0 ) / determinant;
774 for(
size_t i = 0; i != 16; ++i )
775 inv_.array[i] *= detinv;
783 template<
size_t M,
size_t N,
typename T >
784 inline matrix< N, M, T >
785 transpose(
const matrix< M, N, T >& matrix_ )
787 matrix< N, M, T > transpose_;
788 matrix_.transpose_to( transpose_ );
793 template<
size_t M,
size_t N,
typename T >
794 bool is_positive_definite(
const matrix< M, N, T >& matrix_,
795 const T limit = -1e12,
796 typename enable_if< M == N && M <= 3 >::type* = 0 )
798 if ( matrix_.at( 0, 0 ) < limit )
805 matrix_.get_sub_matrix( m, 0, 0 );
806 if ( compute_determinant( m ) < limit )
813 matrix_.get_sub_matrix( m, 0, 0 );
814 if ( compute_determinant( m ) < limit )
822 template<
size_t M,
size_t N,
typename T >
827 for(
size_t i = 0; i < M; ++i )
828 at( i, i ) =
static_cast< T
>( 1.0 );
831 template<
size_t M,
size_t N,
typename T >
835 const T* to = std::min( end_, begin_ + M*N );
836 ::memcpy( array, begin_, (to - begin_) *
sizeof( T ));
839 template<
size_t M,
size_t N,
typename T >
840 template<
size_t P,
size_t Q,
typename U >
846 template<
size_t M,
size_t N,
typename T >
template<
size_t O >
849 typename enable_if< M == O+1 && N == O+1 && O == 3 >::type* )
851 rotation.get_rotation_matrix( *
this );
852 set_translation( translation );
859 template<
size_t M,
size_t N,
typename T >
864 typename enable_if< M == O+1 && N == O+1 && O == 3 >::type* )
881 at( 0, 3 ) = -vmml::dot( s, eye );
882 at( 1, 3 ) = -vmml::dot( u, eye );
883 at( 2, 3 ) = vmml::dot( f, eye );
886 template<
size_t M,
size_t N,
typename T >
889 #ifdef VMMLIB_SAFE_ACCESSORS
890 if ( row_index >= M || col_index >= N )
891 throw std::runtime_error(
"at( row, col ) - index out of bounds" );
893 return array[ col_index * M + row_index ];
898 template<
size_t M,
size_t N,
typename T >
900 matrix< M, N, T >::at(
size_t row_index,
size_t col_index )
const
902 #ifdef VMMLIB_SAFE_ACCESSORS
903 if ( row_index >= M || col_index >= N )
904 throw std::runtime_error(
"at( row, col ) - index out of bounds" );
906 return array[ col_index * M + row_index ];
910 template<
size_t M,
size_t N,
typename T >
912 matrix< M, N, T >::operator()(
size_t row_index,
size_t col_index )
914 return at( row_index, col_index );
919 template<
size_t M,
size_t N,
typename T >
921 matrix< M, N, T >::operator()(
size_t row_index,
size_t col_index )
const
923 return at( row_index, col_index );
926 #ifndef VMMLIB_NO_CONVERSION_OPERATORS
928 template<
size_t M,
size_t N,
typename T >
937 template<
size_t M,
size_t N,
typename T >
939 operator
const T*()
const
947 template<
size_t M,
size_t N,
typename T >
950 operator==(
const matrix< M, N, T >& other )
const
953 for(
size_t i = 0; is_ok && i < M * N; ++i )
955 is_ok = array[ i ] == other.array[ i ];
963 template<
size_t M,
size_t N,
typename T >
966 operator!=(
const matrix< M, N, T >& other )
const
968 return ! operator==( other );
973 template<
size_t M,
size_t N,
typename T >
974 bool matrix< M, N, T >::equals(
const matrix< M, N, T >& other,
975 const T tolerance )
const
977 for(
size_t row_index = 0; row_index < M; row_index++)
978 for(
size_t col_index = 0; col_index < N; col_index++)
979 if( std::abs( at( row_index, col_index ) -
980 other( row_index, col_index )) > tolerance )
987 template<
size_t M,
size_t N,
typename T >
988 const matrix< M, N, T >&
989 matrix< M, N, T >::operator=(
const matrix< M, N, T >& source_ )
991 memcpy( array, source_.array, M * N *
sizeof( T ));
995 template<
size_t M,
size_t N,
typename T >
996 template<
size_t P,
size_t Q,
typename U >
997 void matrix< M, N, T >::operator=(
const matrix< P, Q, U >& source_ )
999 const size_t minL = P < M ? P : M;
1000 const size_t minC = Q < N ? Q : N;
1002 if( minL < M || minC < N )
1005 for (
size_t i = 0 ; i < minL ; i++ )
1006 for (
size_t j = 0 ; j < minC ; j++ )
1007 at( i,j ) =
static_cast< T
>( source_( i, j ));
1011 template<
size_t M,
size_t N,
typename T >
1012 void matrix< M, N, T >::operator=(
const T old_fashioned_matrix[ M ][ N ] )
1014 for(
size_t row = 0; row < M; row++)
1016 for(
size_t col = 0; col < N; col++)
1018 at( row, col ) = old_fashioned_matrix[ row ][ col ];
1028 template<
size_t M,
size_t N,
typename T >
1030 matrix< M, N, T >::operator=(
const T* data_array )
1032 set( data_array, data_array + M * N,
true );
1037 template<
size_t M,
size_t N,
typename T >
1039 matrix< M, N, T >::operator=(
const std::vector< T >& data )
1041 if ( data.size() < M * N )
1042 throw std::runtime_error(
"index out of bounds." );
1044 set( data.begin(), data.end(), true );
1048 template<
size_t M,
size_t N,
typename T >
1050 matrix< M, N, T >::multiply_piecewise(
const matrix& other )
1052 for(
size_t row_index = 0; row_index < M; row_index++)
1054 for(
size_t col_index = 0; col_index < N; col_index++ )
1056 T& value = at( row_index, col_index );
1057 value *= other.at( row_index, col_index );
1063 template<
size_t M,
size_t N,
typename T >
1064 template<
size_t P >
1066 matrix< M, N, T >::multiply(
1067 const matrix< M, P, T >& left,
1068 const matrix< P, N, T >& right
1071 for(
size_t row_index = 0; row_index < M; row_index++)
1073 for(
size_t col_index = 0; col_index < N; col_index++)
1075 T& component = at( row_index, col_index );
1076 component =
static_cast< T
>( 0.0 );
1077 for(
size_t p = 0; p < P; p++)
1079 component += left.at( row_index, p ) * right.at( p, col_index );
1087 template<
size_t M,
size_t N,
typename T >
1088 template<
size_t P >
1090 matrix< M, N, T >::operator*(
const matrix< N, P, T >& other )
const
1092 matrix< M, P, T > result;
1093 result.multiply( *
this, other );
1099 template<
size_t M,
size_t N,
typename T >
1100 template<
size_t O,
size_t P,
typename TT >
1101 typename enable_if< M == N && O == P && M == O, TT >::type*
1102 matrix< M, N, T >::operator*=(
const matrix< O, P, TT >& right )
1104 matrix< M, N, T > copy( *
this );
1105 multiply( copy, right );
1109 template<
size_t M,
size_t N,
typename T >
1111 matrix< M, N, T >::operator/( T scalar )
1113 matrix< M, N, T > result;
1115 for(
size_t row_index = 0; row_index < M; ++row_index )
1117 for(
size_t col_index = 0; col_index < N; ++col_index )
1119 result.at( row_index, col_index ) = at( row_index, col_index ) / scalar;
1127 template<
size_t M,
size_t N,
typename T >
1129 matrix< M, N, T >::operator/=( T scalar )
1131 for(
size_t row_index = 0; row_index < M; ++row_index )
1133 for(
size_t col_index = 0; col_index < N; ++col_index )
1135 at( row_index, col_index ) /= scalar;
1144 template<
size_t M,
size_t N,
typename T >
1146 matrix< M, N, T >::operator*( T scalar )
1148 matrix< M, N, T > result;
1150 for(
size_t row_index = 0; row_index < M; ++row_index )
1152 for(
size_t col_index = 0; col_index < N; ++col_index )
1154 result.at( row_index, col_index ) = at( row_index, col_index ) * scalar;
1162 template<
size_t M,
size_t N,
typename T >
1164 matrix< M, N, T >::operator*=( T scalar )
1166 for(
size_t row_index = 0; row_index < M; ++row_index )
1168 for(
size_t col_index = 0; col_index < N; ++col_index )
1170 at( row_index, col_index ) *= scalar;
1177 template<
size_t M,
size_t N,
typename T >
1178 vector< M, T > matrix< M, N, T >::operator*(
const vector< N, T >& vec )
const
1180 vector< M, T > result;
1183 for(
size_t i = 0; i < M; ++i )
1186 for(
size_t j = 0; j < N; ++j )
1187 tmp += at( i, j ) * vec.at( j );
1188 result.at( i ) = tmp;
1197 template<
size_t M,
size_t N,
typename T >
1198 template<
size_t O > vector< O, T >
1199 matrix< M, N, T >::operator*(
const vector< O, T >& vector_ )
const
1201 vector< O, T > result;
1203 for(
size_t row_index = 0; row_index < M; ++row_index )
1206 for(
size_t col_index = 0; col_index < N-1; ++col_index )
1208 tmp += vector_( col_index ) * at( row_index, col_index );
1210 if ( row_index < N - 1 )
1211 result( row_index ) = tmp + at( row_index, N-1 );
1214 tmp += at( row_index, N - 1 );
1215 for(
size_t col_index = 0; col_index < N - 1; ++col_index )
1217 result( col_index ) /= tmp;
1226 template<
size_t M,
size_t N,
typename T >
1227 inline matrix< M, N, T >
1228 matrix< M, N, T >::operator-()
const
1235 template<
size_t M,
size_t N,
typename T >
1237 matrix< M, N, T >::negate()
const
1239 matrix< M, N, T > result;
1246 template<
size_t M,
size_t N,
typename T >
1248 matrix< M, N, T >::tensor(
const vector< M, T >& u,
const vector< N, T >& v )
1250 for (
size_t col_index = 0; col_index < N; ++col_index )
1251 for (
size_t row_index = 0; row_index < M; ++row_index )
1252 at( row_index, col_index ) = u.array[ col_index ] *
1253 v.array[ row_index ];
1258 template<
size_t M,
size_t N,
typename T >
1259 template<
size_t uM,
size_t vM >
1260 typename enable_if< uM == 3 && vM == 3 && M == N && M == 4 >::type*
1261 matrix< M, N, T >::tensor(
const vector< uM, T >& u,
const vector< vM, T >& v )
1263 for (
size_t col_index = 0; col_index < 3; ++col_index )
1265 for (
size_t row_index = 0; row_index < 3; ++row_index )
1266 at( row_index, col_index ) = u.array[ col_index ] *
1267 v.array[ row_index ];
1269 at( 3, col_index ) = u.array[ col_index ];
1272 for (
size_t row_index = 0; row_index < 3; ++row_index )
1273 at( row_index, 3 ) = v.array[ row_index ];
1282 template<
size_t M,
size_t N,
typename T >
1285 transpose_to( matrix< N, M, T >& tM )
const
1287 for(
size_t row = 0; row < M; ++row )
1289 for(
size_t col = 0; col < N; ++col )
1291 tM.at( col, row ) = at( row, col );
1296 template<
size_t M,
size_t N,
typename T >
1299 symmetric_covariance( matrix< M, M, T >& cov_m_ )
const
1302 for(
size_t row = 0; row < M; ++row )
1304 for(
size_t col = row; col < M; ++col )
1306 for (
size_t k = 0; k < N; ++k )
1308 tmp += (at( row, k ) * at( col, k ));
1311 cov_m_.at( row, col ) = tmp;
1312 cov_m_.at( col, row ) = tmp;
1320 template<
size_t M,
size_t N,
typename T >
1321 vector< M, T > matrix< M, N, T >::get_column(
size_t index )
const
1323 vector< M, T > column;
1324 get_column( index, column );
1330 template<
size_t M,
size_t N,
typename T >
1331 void matrix< M, N, T >::get_column(
size_t index, vector< M, T >& column )
const
1334 throw std::runtime_error(
"get_column() - index out of bounds." );
1335 memcpy( &column.array[0], &array[ M * index ], M *
sizeof( T ) );
1340 template<
size_t M,
size_t N,
typename T >
1341 void matrix< M, N, T >::set_column(
size_t index,
const vector< M, T >& column )
1344 throw std::runtime_error(
"set_column() - index out of bounds." );
1345 memcpy( array + M * index, column.array, M *
sizeof( T ) );
1348 template<
size_t M,
size_t N,
typename T >
1349 void matrix< M, N, T >::get_column(
size_t index, matrix< M, 1, T >& column )
1353 throw std::runtime_error(
"get_column() - index out of bounds." );
1354 memcpy( column.array, array + M * index, M *
sizeof( T ) );
1357 template<
size_t M,
size_t N,
typename T >
1358 void matrix< M, N, T >::set_column(
size_t index,
1359 const matrix< M, 1, T >& column )
1362 throw std::runtime_error(
"set_column() - index out of bounds." );
1363 memcpy( &array[ M * index ], column.array, M *
sizeof( T ) );
1366 template<
size_t M,
size_t N,
typename T >
1367 vector< N, T > matrix< M, N, T >::get_row(
size_t index )
const
1370 get_row( index, row );
1374 template<
size_t M,
size_t N,
typename T >
1375 void matrix< M, N, T >::get_row(
size_t row_index, vector< N, T >& row )
const
1377 if ( row_index >= M )
1378 throw std::runtime_error(
"get_row() - index out of bounds." );
1380 for(
size_t col_index = 0; col_index < N; ++col_index )
1381 row.at( col_index ) = at( row_index, col_index );
1384 template<
size_t M,
size_t N,
typename T >
1385 void matrix< M, N, T >::set_row(
size_t row_index,
const vector< N, T >& row )
1387 if ( row_index >= M )
1388 throw std::runtime_error(
"set_row() - index out of bounds." );
1390 for(
size_t col_index = 0; col_index < N; ++col_index )
1391 at( row_index, col_index ) = row.at( col_index );
1394 template<
size_t M,
size_t N,
typename T >
1395 void matrix< M, N, T >::get_row(
size_t row_index, matrix< 1, N, T >& row )
1398 if ( row_index >= M )
1399 throw std::runtime_error(
"get_row() - index out of bounds." );
1401 for(
size_t col_index = 0; col_index < N; ++col_index )
1402 row.at( 0, col_index ) = at( row_index, col_index );
1405 template<
size_t M,
size_t N,
typename T >
1406 void matrix< M, N, T >::set_row(
size_t row_index,
1407 const matrix< 1, N, T >& row )
1409 if ( row_index >= M )
1410 throw std::runtime_error(
"set_row() - index out of bounds." );
1412 for(
size_t col_index = 0; col_index < N; ++col_index )
1413 at( row_index, col_index ) = row.at( 0, col_index );
1416 template<
size_t M,
size_t N,
typename T >
1417 size_t matrix< M, N, T >::get_number_of_rows()
const
1422 template<
size_t M,
size_t N,
typename T >
1423 size_t matrix< M, N, T >::get_number_of_columns()
const
1428 template<
size_t M,
size_t N,
typename T >
1433 for(
size_t row_index = 0; row_index < M; ++row_index )
1435 for(
size_t col_index = 0; col_index < N; ++col_index )
1437 at( row_index, col_index ) = fillValue;
1443 template<
size_t M,
size_t N,
typename T >
1445 matrix< M, N, T >::x()
1452 template<
size_t M,
size_t N,
typename T >
1454 matrix< M, N, T >::y()
1461 template<
size_t M,
size_t N,
typename T >
1463 matrix< M, N, T >::z()
1468 template<
size_t M,
size_t N,
typename T >
1469 template<
typename input_iterator_t >
1470 void matrix< M, N, T >::set( input_iterator_t begin_,
1471 input_iterator_t end_,
bool row_major_layout )
1473 input_iterator_t it( begin_ );
1474 if( row_major_layout )
1476 for(
size_t row = 0; row < M; ++row )
1478 for(
size_t col = 0; col < N; ++col, ++it )
1482 at( row, col ) =
static_cast< T
>( *it );
1488 std::copy( it, it + ( M * N ), begin() );
1494 template<
size_t M,
size_t N,
typename T >
1495 void matrix< M, N, T >::zero()
1497 fill( static_cast< T >( 0.0 ) );
1500 template<
size_t M,
size_t N,
typename T >
1501 void matrix< M, N, T >::operator=( T value_ )
1503 std::fill( begin(), end(), value_ );
1508 template<
size_t M,
size_t N,
typename T >
1509 inline matrix< M, N, T >
1510 matrix< M, N, T >::operator+(
const matrix< M, N, T >& other )
const
1512 matrix< M, N, T > result( *
this );
1519 template<
size_t M,
size_t N,
typename T >
1520 void matrix< M, N, T >::operator+=(
const matrix< M, N, T >& other )
1522 iterator it = begin(), it_end = end();
1523 const_iterator other_it = other.begin();
1524 for( ; it != it_end; ++it, ++other_it )
1531 template<
size_t M,
size_t N,
typename T >
1532 void matrix< M, N, T >::operator+=( T scalar )
1534 iterator it = begin(), it_end = end();
1535 for( ; it != it_end; ++it )
1541 template<
size_t M,
size_t N,
typename T >
1542 inline matrix< M, N, T >
1544 operator-(
const matrix< M, N, T >& other )
const
1546 matrix< M, N, T > result( *
this );
1553 template<
size_t M,
size_t N,
typename T >
1556 operator-=(
const matrix< M, N, T >& other )
1558 iterator it = begin(), it_end = end();
1559 const_iterator other_it = other.begin();
1560 for( ; it != it_end; ++it, ++other_it )
1566 template<
size_t M,
size_t N,
typename T >
1568 matrix< M, N, T >::operator-=( T scalar )
1570 iterator it = begin(), it_end = end();
1571 for( ; it != it_end; ++it )
1578 template<
size_t M,
size_t N,
typename T >
1579 template<
size_t O,
size_t P,
size_t Q,
size_t R >
1580 typename enable_if< M == O + Q && N == P + R >::type*
1581 matrix< M, N, T >::direct_sum(
const matrix< O, P, T >& upper_left,
1582 const matrix< Q, R, T >& lower_right )
1584 (*this) =
static_cast< T
>( 0.0 );
1586 for(
size_t row = 0; row < O; ++row )
1588 for(
size_t col = 0; col < P; ++col )
1590 at( row, col ) = upper_left( row, col );
1594 for(
size_t row = 0; row < Q; ++row )
1596 for(
size_t col = 0; col < R; ++col )
1598 at( O + row, P + col ) = lower_right( row, col );
1607 template<
size_t M,
size_t N,
typename T >
1608 template<
size_t O,
size_t P >
1610 matrix< M, N, T >::get_sub_matrix(
size_t row_offset,
size_t col_offset,
1611 typename enable_if< O <= M && P <= N >::type* )
const
1613 matrix< O, P, T > result;
1614 get_sub_matrix( result, row_offset, col_offset );
1620 template<
size_t M,
size_t N,
typename T >
1621 template<
size_t O,
size_t P >
1622 typename enable_if< O <= M && P <= N >::type*
1624 get_sub_matrix( matrix< O, P, T >& result,
1625 size_t row_offset,
size_t col_offset )
const
1627 #ifdef VMMLIB_SAFE_ACCESSORS
1628 if ( O + row_offset > M || P + col_offset > N )
1629 throw std::runtime_error(
"index out of bounds." );
1632 for(
size_t row = 0; row < O; ++row )
1634 for(
size_t col = 0; col < P; ++col )
1636 result.at( row, col )
1637 = at( row_offset + row, col_offset + col );
1645 template<
size_t M,
size_t N,
typename T >
1646 template<
size_t O,
size_t P >
1647 typename enable_if< O <= M && P <= N >::type*
1649 set_sub_matrix(
const matrix< O, P, T >& sub_matrix,
1650 size_t row_offset,
size_t col_offset )
1652 for(
size_t row = 0; row < O; ++row )
1654 for(
size_t col = 0; col < P; ++col )
1656 at( row_offset + row, col_offset + col )
1657 = sub_matrix.at( row, col );
1665 template<
size_t M,
size_t N,
typename T >
1667 matrix< M, N, T >::det()
const
1669 return compute_determinant( *
this );
1674 template<
size_t M,
size_t N,
typename T >
1675 template<
size_t O,
size_t P,
typename TT >
1676 inline bool matrix< M, N, T >::inverse( matrix< O, P, TT >& inverse_,
1677 T tolerance,
typename
1678 enable_if< M == N && O == P && O == M && M >= 2 && M <= 4, TT >::type* )
1681 return compute_inverse( *
this, inverse_, tolerance );
1686 template<
size_t M,
size_t N,
typename T >
1687 template<
size_t O,
size_t P >
1688 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
1690 get_adjugate( matrix< O, P, T >& adjugate )
const
1692 get_cofactors( adjugate );
1693 adjugate = transpose( adjugate );
1699 template<
size_t M,
size_t N,
typename T >
1700 template<
size_t O,
size_t P >
1701 typename enable_if< O == P && M == N && O == M && M >= 2 >::type*
1703 get_cofactors( matrix< O, P, T >& cofactors )
const
1705 matrix< M-1, N-1, T > minor_;
1707 const size_t _negate = 1u;
1708 for(
size_t row_index = 0; row_index < M; ++row_index )
1710 for(
size_t col_index = 0; col_index < N; ++col_index )
1712 if ( ( row_index + col_index ) & _negate )
1713 cofactors( row_index, col_index ) = -get_minor( minor_, row_index, col_index );
1715 cofactors( row_index, col_index ) = get_minor( minor_, row_index, col_index );
1723 template<
size_t M,
size_t N,
typename T >
1724 template<
size_t O,
size_t P >
1727 get_minor( matrix< O, P, T >& minor_,
size_t row_to_cut,
size_t col_to_cut,
1728 typename enable_if< O == M-1 && P == N-1 && M == N && M >= 2 >::type* )
const
1730 size_t row_offset = 0;
1731 size_t col_offset = 0;
1732 for(
size_t row_index = 0; row_index < M; ++row_index )
1734 if ( row_index == row_to_cut )
1738 for(
size_t col_index = 0; col_index < M; ++col_index )
1740 if ( col_index == col_to_cut )
1743 minor_.at( row_index + row_offset, col_index + col_offset )
1744 = at( row_index, col_index );
1749 return compute_determinant( minor_ );
1752 template<
size_t M,
size_t N,
typename T >
1753 template<
typename TT >
1754 matrix< M, N, T >& matrix< M, N, T >::rotate(
1755 const TT angle_,
const vector< M-1, T >& axis,
1756 typename enable_if< M == N && M == 4, TT >::type* )
1758 const T angle =
static_cast< T
>( angle_ );
1760 const T sine = std::sin( angle );
1761 const T cosine = std::cos( angle );
1768 const T _zero = 0.0;
1772 array[0] = cosine + ( one - cosine ) * std::pow( axis.array[0], two );
1773 array[1] = ( one - cosine ) * axis.array[0] * axis.array[1] + sine * axis.array[2];
1774 array[2] = ( one - cosine ) * axis.array[0] * axis.array[2] - sine * axis.array[1];
1777 array[4] = ( one - cosine ) * axis.array[0] * axis.array[1] - sine * axis.array[2];
1778 array[5] = cosine + ( one - cosine ) * std::pow( axis.array[1], two );
1779 array[6] = ( one - cosine ) * axis.array[1] * axis.array[2] + sine * axis.array[0];
1782 array[8] = ( one - cosine ) * axis.array[0] * axis.array[2] + sine * axis.array[1];
1783 array[9] = ( one - cosine ) * axis.array[1] * axis.array[2] - sine * axis.array[0];
1784 array[10] = cosine + ( one - cosine ) * std::pow( axis.array[2], two );
1795 template<
size_t M,
size_t N,
typename T >
1796 template<
typename TT >
1797 matrix< M, N, T >& matrix< M, N, T >::rotate_x(
const TT angle_,
1798 typename enable_if< M == N && M == 4, TT >::type* )
1800 const T angle =
static_cast< T
>( angle_ );
1802 const T sine = std::sin( angle );
1803 const T cosine = std::cos( angle );
1807 tmp = array[ 4 ] * cosine + array[ 8 ] * sine;
1808 array[ 8 ] = - array[ 4 ] * sine + array[ 8 ] * cosine;
1811 tmp = array[ 5 ] * cosine + array[ 9 ] * sine;
1812 array[ 9 ] = - array[ 5 ] * sine + array[ 9 ] * cosine;
1815 tmp = array[ 6 ] * cosine + array[ 10 ] * sine;
1816 array[ 10 ] = - array[ 6 ] * sine + array[ 10 ] * cosine;
1819 tmp = array[ 7 ] * cosine + array[ 11 ] * sine;
1820 array[ 11 ] = - array[ 7 ] * sine + array[ 11 ] * cosine;
1826 template<
size_t M,
size_t N,
typename T >
1827 template<
typename TT >
1828 matrix< M, N, T >& matrix< M, N, T >::rotate_y(
const TT angle_,
1829 typename enable_if< M == N && M == 4, TT >::type* )
1831 const T angle =
static_cast< T
>( angle_ );
1833 const T sine = std::sin( angle );
1834 const T cosine = std::cos( angle );
1838 tmp = array[ 0 ] * cosine - array[ 8 ] * sine;
1839 array[ 8 ] = array[ 0 ] * sine + array[ 8 ] * cosine;
1842 tmp = array[ 1 ] * cosine - array[ 9 ] * sine;
1843 array[ 9 ] = array[ 1 ] * sine + array[ 9 ] * cosine;
1846 tmp = array[ 2 ] * cosine - array[ 10 ] * sine;
1847 array[ 10 ] = array[ 2 ] * sine + array[ 10 ] * cosine;
1850 tmp = array[ 3 ] * cosine - array[ 11 ] * sine;
1851 array[ 11 ] = array[ 3 ] * sine + array[ 11 ] * cosine;
1857 template<
size_t M,
size_t N,
typename T >
1858 template<
typename TT >
1859 matrix< M, N, T >& matrix< M, N, T >::rotate_z(
const TT angle_,
1860 typename enable_if< M == N && M == 4, TT >::type* )
1862 const T angle =
static_cast< T
>( angle_ );
1864 const T sine = std::sin( angle );
1865 const T cosine = std::cos( angle );
1869 tmp = array[ 0 ] * cosine + array[ 4 ] * sine;
1870 array[ 4 ] = - array[ 0 ] * sine + array[ 4 ] * cosine;
1873 tmp = array[ 1 ] * cosine + array[ 5 ] * sine;
1874 array[ 5 ] = - array[ 1 ] * sine + array[ 5 ] * cosine;
1877 tmp = array[ 2 ] * cosine + array[ 6 ] * sine;
1878 array[ 6 ] = - array[ 2 ] * sine + array[ 6 ] * cosine;
1881 tmp = array[ 3 ] * cosine + array[ 7 ] * sine;
1882 array[ 7 ] = - array[ 3 ] * sine + array[ 7 ] * cosine;
1888 template<
size_t M,
size_t N,
typename T >
1889 template<
typename TT >
1890 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_x(
const TT angle_,
1891 typename enable_if< M == N && M == 4, TT >::type* )
1893 const T angle =
static_cast< T
>( angle_ );
1895 const T sine = std::sin( angle );
1896 const T cosine = std::cos( angle );
1901 array[ 1 ] = array[ 1 ] * cosine + array[ 2 ] * sine;
1902 array[ 2 ] = tmp * -sine + array[ 2 ] * cosine;
1905 array[ 5 ] = array[ 5 ] * cosine + array[ 6 ] * sine;
1906 array[ 6 ] = tmp * -sine + array[ 6 ] * cosine;
1909 array[ 9 ] = array[ 9 ] * cosine + array[ 10 ] * sine;
1910 array[ 10 ] = tmp * -sine + array[ 10 ] * cosine;
1913 array[ 13 ] = array[ 13 ] * cosine + array[ 14 ] * sine;
1914 array[ 14 ] = tmp * -sine + array[ 14 ] * cosine;
1919 template<
size_t M,
size_t N,
typename T >
1920 template<
typename TT >
1921 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_y(
const TT angle_,
1922 typename enable_if< M == N && M == 4, TT >::type* )
1924 const T angle =
static_cast< T
>( angle_ );
1926 const T sine = std::sin( angle );
1927 const T cosine = std::cos( angle );
1932 array[ 0 ] = array[ 0 ] * cosine - array[ 2 ] * sine;
1933 array[ 2 ] = tmp * sine + array[ 2 ] * cosine;
1936 array[ 4 ] = array[ 4 ] * cosine - array[ 6 ] * sine;
1937 array[ 6 ] = tmp * sine + array[ 6 ] * cosine;
1940 array[ 8 ] = array[ 8 ] * cosine - array[ 10 ] * sine;
1941 array[ 10 ] = tmp * sine + array[ 10 ] * cosine;
1944 array[ 12 ] = array[ 12 ] * cosine - array[ 14 ] * sine;
1945 array[ 14 ] = tmp * sine + array[ 14 ] * cosine;
1950 template<
size_t M,
size_t N,
typename T >
1951 template<
typename TT >
1952 matrix< M, N, T >& matrix< M, N, T >::pre_rotate_z(
const TT angle_,
1953 typename enable_if< M == N && M == 4, TT >::type* )
1955 const T angle =
static_cast< T
>( angle_ );
1957 const T sine = std::sin( angle );
1958 const T cosine = std::cos( angle );
1963 array[ 0 ] = array[ 0 ] * cosine + array[ 1 ] * sine;
1964 array[ 1 ] = tmp * -sine + array[ 1 ] * cosine;
1967 array[ 4 ] = array[ 4 ] * cosine + array[ 5 ] * sine;
1968 array[ 5 ] = tmp * -sine + array[ 5 ] * cosine;
1971 array[ 8 ] = array[ 8 ] * cosine + array[ 9 ] * sine;
1972 array[ 9 ] = tmp * -sine + array[ 9 ] * cosine;
1975 array[ 12 ] = array[ 12 ] * cosine + array[ 13 ] * sine;
1976 array[ 13 ] = tmp * -sine + array[ 13 ] * cosine;
1981 template<
size_t M,
size_t N,
typename T >
1982 template<
typename TT >
1983 matrix< M, N, T >& matrix< M, N, T >::scale(
const TT _scale[3],
1984 typename enable_if< M == N && M == 4, TT >::type* )
1986 const T scale0 =
static_cast< T
>( _scale[ 0 ] );
1987 const T scale1 =
static_cast< T
>( _scale[ 1 ] );
1988 const T scale2 =
static_cast< T
>( _scale[ 2 ] );
2000 array[10] *= scale2;
2001 array[11] *= scale2;
2006 template<
size_t M,
size_t N,
typename T >
2007 template<
typename TT >
2008 matrix< M, N, T >& matrix< M, N, T >::scale(
const TT x_,
const T y_,
const T z_,
2009 typename enable_if< M == N && M == 4, TT >::type* )
2011 const T _x =
static_cast< T
>( x_ );
2029 template<
size_t M,
size_t N,
typename T >
2030 template<
typename TT >
2031 inline matrix< M, N, T >& matrix< M, N, T >::scale(
2032 const vector< 3, TT >& scale_,
2033 typename enable_if< M == N && M == 4, TT >::type* )
2035 return scale( scale_.array );
2040 template<
size_t M,
size_t N,
typename T >
2041 template<
typename TT >
2042 matrix< M, N, T >& matrix< M, N, T >::scale_translation(
const TT scale_[3],
2043 typename enable_if< M == N && M == 4, TT >::type* )
2045 array[12] *=
static_cast< T
>( scale_[0] );
2046 array[13] *=
static_cast< T
>( scale_[1] );
2047 array[14] *=
static_cast< T
>( scale_[2] );
2051 template<
size_t M,
size_t N,
typename T >
2052 template<
typename TT >
2053 inline matrix< M, N, T >& matrix< M, N, T >::scale_translation(
2054 const vector< 3, TT >& scale_,
2055 typename enable_if< M == N && M == 4, TT >::type* )
2057 return scale_translation( scale_.array );
2060 template<
size_t M,
size_t N,
typename T >
2061 template<
typename TT >
2062 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
2063 const TT x_,
const TT y_,
const TT z_,
2064 typename enable_if< M == N && M == 4, TT >::type* )
2066 array[12] =
static_cast< T
>( x_ );
2067 array[13] =
static_cast< T
>( y_ );
2068 array[14] =
static_cast< T
>( z_ );
2072 template<
size_t M,
size_t N,
typename T >
2073 template<
typename TT >
2074 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
const TT trans[3],
2075 typename enable_if< M == N && M == 4, TT >::type* )
2077 array[12] =
static_cast< T
>( trans[ 0 ] );
2078 array[13] =
static_cast< T
>( trans[ 1 ] );
2079 array[14] =
static_cast< T
>( trans[ 2 ] );
2083 template<
size_t M,
size_t N,
typename T >
2084 template<
typename TT >
2085 inline matrix< M, N, T >& matrix< M, N, T >::set_translation(
2086 const vector< 3, TT >& translation_,
2087 typename enable_if< M == N && M == 4, TT >::type* )
2089 return set_translation( translation_.array );
2092 template<
size_t M,
size_t N,
typename T >
template<
typename TT >
inline
2093 void matrix< M, N, T >::get_translation( vector< N-1, TT >& translation_ )
2096 for(
size_t i = 0; i < N-1; ++i )
2097 translation_.array[ i ] = array[ i + M * (N - 1) ];
2101 template<
size_t M,
size_t N,
typename T >
2102 inline vector< N-1, T > matrix< M, N, T >::get_translation()
const
2104 vector< N-1, T > result;
2105 get_translation( result );
2109 template<
size_t M,
size_t N,
typename T >
2110 template<
size_t O >
2111 void matrix< M, N, T >::getLookAt( vector< O, T >& eye, vector< O, T >& lookAt,
2113 typename enable_if< M == O+1 && N == O+1 && O == 3 >::type* )
const
2115 matrix< 4, 4, T > inv;
2118 const matrix< 3, 3, T > rotation( transpose( matrix< 3, 3, T >( *
this )));
2120 eye = inv * vector< 3, T >::ZERO;
2121 up = rotation * vector< 3, T >::UP;
2122 lookAt = rotation * vector< 3, T >::FORWARD;
2124 lookAt = eye + lookAt;
2127 template<
size_t M,
size_t N,
typename T >
2137 template<
size_t M,
size_t N,
typename T >
2138 typename matrix< M, N, T >::iterator
2147 template<
size_t M,
size_t N,
typename T >
2148 typename matrix< M, N, T >::iterator
2152 return array + size();
2157 template<
size_t M,
size_t N,
typename T >
2158 typename matrix< M, N, T >::const_iterator
2167 template<
size_t M,
size_t N,
typename T >
2168 typename matrix< M, N, T >::const_iterator
2172 return array + size();
2177 template<
size_t M,
size_t N,
typename T >
2178 typename matrix< M, N, T >::reverse_iterator
2182 return array + size() - 1;
2187 template<
size_t M,
size_t N,
typename T >
2188 typename matrix< M, N, T >::reverse_iterator
2197 template<
size_t M,
size_t N,
typename T >
2198 typename matrix< M, N, T >::const_reverse_iterator
2202 return array + size() - 1;
2207 template<
size_t M,
size_t N,
typename T >
2208 typename matrix< M, N, T >::const_reverse_iterator
2217 template<
size_t M,
size_t N,
typename T >
template<
typename init_functor_t >
2218 const matrix< M, N, T > matrix< M, N, T >::get_initialized_matrix()
2220 matrix< M, N, T > matrix_;
2221 init_functor_t()( matrix_ );
2228 template<
size_t M,
size_t N,
typename T >
2229 const matrix< M, N, T >
2230 matrix< M, N, T >::IDENTITY(
2231 matrix< M, N, T >::get_initialized_matrix<
2232 set_to_identity_functor< matrix< M, N, T > > >( ));
2235 template<
size_t M,
size_t N,
typename T >
2236 const matrix< M, N, T >
2237 matrix< M, N, T >::ZERO(
2239 get_initialized_matrix< set_to_zero_functor< matrix< M, N, T > > >()
2244 template<
size_t M,
size_t N,
typename T >
2246 matrix< M, N, T >::frobenius_norm( )
const
2250 const_iterator it = begin(), it_end = end();
2251 for( ; it != it_end; ++it )
2256 return std::sqrt(norm);
2259 template<
size_t M,
size_t N,
typename T >
2261 matrix< M, N, T >::p_norm(
double p )
const
2265 const_iterator it = begin(), it_end = end();
2266 for( ; it != it_end; ++it )
2268 norm += std::pow(*it, p);
2271 return std::pow(norm,1./p);
2275 template<
size_t M,
size_t N,
typename T >
2276 template<
size_t O >
2278 matrix< M, N, T >::khatri_rao_product(
const matrix< O, N, T >& right_, matrix< M*O, N, T >& prod_ )
const
2281 for (
size_t col = 0; col < N; ++col )
2283 for (
size_t m = 0; m < M; ++m )
2285 for (
size_t o = 0; o < O; ++o )
2287 prod_.at(O*m + o, col) = at( m, col ) * right_.at( o, col );
2293 template<
size_t M,
size_t N,
typename T >
2294 template<
size_t O,
size_t P >
2296 matrix< M, N, T >::kronecker_product(
const matrix< O, P, T >& right_, matrix< M*O, N*P, T >& result_ )
const
2299 for (
size_t m = 0; m < M; ++m )
2301 for (
size_t n = 0; n < N; ++n )
2303 for (
size_t o = 0; o < O; ++o )
2305 for (
size_t p = 0; p < P; ++p )
2307 result_.at(O*m + o, P*n + p) = at( m, n ) * right_.at( o, p );
2315 template<
size_t M,
size_t N,
typename T >
2316 template<
typename TT >
2318 matrix< M, N, T >::cast_from(
const matrix< M, N, TT >& other )
2321 typedef typename matrix_tt_type::const_iterator tt_const_iterator;
2323 iterator it = begin(), it_end = end();
2324 tt_const_iterator other_it = other.begin();
2325 for( ; it != it_end; ++it, ++other_it )
2327 *it =
static_cast< T
>( *other_it );
2332 template<
size_t M,
size_t N,
typename T >
2334 matrix< M, N, T >::get_min()
const
2336 T min_value =
static_cast<T
>(std::numeric_limits<T>::max());
2338 const_iterator it = begin(),
2340 for( ; it != it_end; ++it)
2342 if ( *it < min_value ) {
2349 template<
size_t M,
size_t N,
typename T >
2351 matrix< M, N, T >::get_max()
const
2353 T max_value =
static_cast<T
>(0);
2355 const_iterator it = begin(),
2357 for( ; it != it_end; ++it)
2359 if ( *it > max_value ) {
2367 template<
size_t M,
size_t N,
typename T >
2369 matrix< M, N, T >::get_abs_min()
const
2371 T min_value =
static_cast<T
>(std::numeric_limits<T>::max());
2373 const_iterator it = begin(),
2375 for( ; it != it_end; ++it)
2377 if ( fabs(*it) < fabs(min_value) ) {
2378 min_value = fabs(*it);
2384 template<
size_t M,
size_t N,
typename T >
2386 matrix< M, N, T >::get_abs_max()
const
2388 T max_value =
static_cast<T
>(0);
2390 const_iterator it = begin(),
2392 for( ; it != it_end; ++it)
2394 if ( fabs(*it) > fabs(max_value) ) {
2395 max_value = fabs(*it);
2403 template<
size_t M,
size_t N,
typename T >
2405 matrix< M, N, T >::nnz()
const
2409 const_iterator it = begin(),
2411 for( ; it != it_end; ++it)
2421 template<
size_t M,
size_t N,
typename T >
2423 matrix< M, N, T >::nnz(
const T& threshold_ )
const
2427 const_iterator it = begin(),
2429 for( ; it != it_end; ++it)
2431 if ( fabs(*it) > threshold_ ) {
2439 template<
size_t M,
size_t N,
typename T >
2441 matrix< M, N, T >::threshold(
const T& threshold_value_ )
2443 iterator it = begin(),
2445 for( ; it != it_end; ++it)
2447 if ( fabs(*it) <= threshold_value_ ) {
2448 *it =
static_cast<T
> (0);
2454 template<
size_t M,
size_t N,
typename T >
2455 template<
typename TT >
2457 matrix< M, N, T >::quantize_to( matrix< M, N, TT >& quantized_,
const T& min_value,
const T& max_value )
const
2459 long max_tt_range = long(std::numeric_limits< TT >::max());
2460 long min_tt_range = long(std::numeric_limits< TT >::min());
2461 long tt_range = (max_tt_range - min_tt_range);
2463 T t_range = max_value - min_value;
2465 typedef matrix< M, N, TT > m_tt_type ;
2466 typedef typename m_tt_type::iterator tt_iterator;
2467 tt_iterator it_quant = quantized_.begin();
2468 const_iterator it = begin(), it_end = end();
2470 for( ; it != it_end; ++it, ++it_quant )
2472 if (std::numeric_limits<TT>::is_signed ) {
2473 *it_quant = TT( std::min( std::max( min_tt_range,
long(( *it * tt_range / t_range ) + 0.5)), max_tt_range ));
2475 *it_quant = TT( std::min( std::max( min_tt_range,
long(((*it - min_value) * tt_range / t_range) + 0.5)), max_tt_range ));
2481 template<
size_t M,
size_t N,
typename T >
2482 template<
typename TT >
2484 matrix< M, N, T >::quantize( matrix< M, N, TT >& quantized_, T& min_value, T& max_value )
const
2486 min_value = get_min();
2487 max_value = get_max();
2488 quantize_to( quantized_, min_value, max_value );
2493 template<
size_t M,
size_t N,
typename T >
2494 template<
typename TT >
2496 matrix< M, N, T >::dequantize( matrix< M, N, TT >& dequantized_,
const TT& min_value,
const TT& max_value )
const
2498 long max_t_range = long(std::numeric_limits< T >::max());
2499 long min_t_range = long(std::numeric_limits< T >::min());
2500 long t_range = (max_t_range - min_t_range);
2502 TT tt_range = max_value - min_value;
2504 typedef matrix< M, N, TT > m_tt_type ;
2505 typedef typename m_tt_type::iterator tt_iterator;
2506 tt_iterator it_dequant = dequantized_.begin();
2507 const_iterator it = begin(), it_end = end();
2508 for( ; it != it_end; ++it, ++it_dequant )
2510 if (std::numeric_limits<T>::is_signed ) {
2511 *it_dequant = std::min( std::max( min_value, TT((TT(*it) / t_range) * tt_range)), max_value );
2513 *it_dequant = std::min( std::max( min_value, TT((((TT(*it) / t_range)) * tt_range ) + min_value)), max_value );
2518 template<
size_t M,
size_t N,
typename T >
2520 matrix< M, N, T >::columnwise_sum( vector< N, T>& summed_columns_ )
const
2523 for (
size_t n = 0; n < N; ++n )
2526 for (
size_t m = 0; m < M; ++m )
2528 value += at( m, n );
2530 summed_columns_.at( n ) = value;
2534 template<
size_t M,
size_t N,
typename T >
2536 matrix< M, N, T >::sum_elements( )
const
2540 const_iterator it = begin(), it_end = end();
2541 for( ; it != it_end; ++it )
2549 template<
size_t M,
size_t N,
typename T >
2551 typename enable_if< R == M && R == N>::type*
2552 matrix< M, N, T >::diag(
const vector< R, T >& diag_values_ )
2555 for(
size_t r = 0; r < R; ++r )
2557 at(r, r) =
static_cast< T
>( diag_values_.at(r) );
2563 template<
size_t M,
size_t N,
typename T >
2565 matrix< M, N, T >::set_dct()
2567 const double num_rows = M;
2568 double fill_value = 0.0f;
2569 for(
size_t row = 0; row < M; ++row )
2572 const double weight = ( row == 0.0 ) ? std::sqrt(1/num_rows) :
2573 std::sqrt(2/num_rows);
2574 for(
size_t col = 0; col < N; ++col )
2576 fill_value = (2 * col + 1) * row * M_PI / (2*M);
2577 fill_value = std::cos( fill_value );
2578 fill_value *= weight;
2579 at( row, col ) =
static_cast< T
>( fill_value ) ;
2585 template<
size_t M,
size_t N,
typename T >
2587 matrix< M, N, T >::set_random(
int seed )
2592 double fillValue = 0.0f;
2593 for(
size_t row = 0; row < M; ++row )
2595 for(
size_t col = 0; col < N; ++col )
2598 fillValue /= RAND_MAX;
2599 at( row, col ) = -1.0 + 2.0 *
static_cast< double >( fillValue ) ;
2604 template<
size_t M,
size_t N,
typename T >
2606 matrix< M, N, T >::write_to_raw(
const std::string& dir_,
const std::string& filename_ )
const
2608 int dir_length = dir_.size() -1;
2609 int last_separator = dir_.find_last_of(
"/");
2610 std::string path = dir_;
2611 if (last_separator < dir_length ) {
2614 path.append( filename_ );
2616 if( filename_.find(
"raw", filename_.size() -3) == std::string::npos )
2619 path.append(
"raw" );
2621 std::string path_raw = path;
2623 std::ofstream outfile;
2624 outfile.open( path_raw.c_str() );
2625 if( outfile.is_open() ) {
2626 size_t len_slice =
sizeof(T) * M*N;
2627 outfile.write( (
char*)&(*
this), len_slice );
2630 std::cout <<
"no file open" << std::endl;
2634 template<
size_t M,
size_t N,
typename T >
2636 matrix< M, N, T >::read_from_raw(
const std::string& dir_,
const std::string& filename_ )
2638 int dir_length = dir_.size() -1;
2639 int last_separator = dir_.find_last_of(
"/");
2640 std::string path = dir_;
2641 if (last_separator < dir_length ) {
2644 path.append( filename_ );
2646 size_t max_file_len = 2147483648u -
sizeof(T) ;
2647 size_t len_data =
sizeof(T) * size();
2648 char* data =
new char[ len_data ];
2649 std::ifstream infile;
2650 infile.open( path.c_str(), std::ios::in);
2652 if( infile.is_open())
2654 iterator it = begin(),
2657 while ( len_data > 0 )
2659 size_t len_read = (len_data % max_file_len ) > 0 ?
2660 len_data % max_file_len : len_data;
2661 len_data -= len_read;
2662 infile.read( data, len_read );
2664 T* T_ptr = (T*)&(data[0]);
2665 for( ; (it != it_end) && (len_read > 0); ++it, len_read -=
sizeof(T) )
2667 *it = *T_ptr; ++T_ptr;
2674 std::cout <<
"no file open" << std::endl;
2682 template<
size_t M,
size_t N,
typename T >
2684 matrix< M, N, T >::write_csv_file(
const std::string& dir_,
const std::string& filename_ )
const
2686 int dir_length = dir_.size() -1;
2687 int last_separator = dir_.find_last_of(
"/");
2688 std::string path = dir_;
2689 if (last_separator < dir_length ) {
2692 path.append( filename_ );
2694 int suffix_pos = filename_.find(
"csv", filename_.size() -3);
2695 if( suffix_pos == (-1)) {
2697 path.append(
"csv" );
2700 std::ofstream outfile;
2701 outfile.open( path.c_str() );
2702 if( outfile.is_open() ) {
2703 outfile << *
this << std::endl;
2706 std::cout <<
"no file open" << std::endl;
2711 template<
size_t M,
size_t N,
typename T >
2713 matrix< M, N, T >::read_csv_file(
const std::string& dir_,
const std::string& filename_ )
2715 int dir_length = dir_.size() -1;
2716 int last_separator = dir_.find_last_of(
"/");
2717 std::string path = dir_;
2718 if (last_separator < dir_length ) {
2721 path.append( filename_ );
2723 int suffix_pos = filename_.find(
"csv", filename_.size() -3);
2724 if( suffix_pos == (-1)) {
2726 path.append(
"csv" );
2729 std::ifstream infile;
2730 infile.open( path.c_str(), std::ios::in);
2731 if( infile.is_open() ) {
2736 std::cout <<
"no file open" << std::endl;
2742 template<
size_t M,
size_t N,
typename T >
2744 matrix< M, N, T >::sum_rows( matrix< M/2, N, T>& other )
const
2746 typedef vector< N, T > row_type;
2748 row_type* row0 =
new row_type;
2749 row_type* row1 =
new row_type;
2753 for (
size_t row = 0; row < M; ++row )
2755 get_row( row++, *row0 );
2758 get_row( row, *row1 );
2760 other.set_row( row/2 , *row0 );
2768 template<
size_t M,
size_t N,
typename T >
2770 matrix< M, N, T >::sum_columns( matrix< M, N/2, T>& other )
const
2772 typedef vector< M, T > col_type;
2774 col_type* col0 =
new col_type;
2775 col_type* col1 =
new col_type;
2779 for (
size_t col = 0; col< N; ++col )
2781 get_column( col++, *col0 );
2784 get_column( col, *col1 );
2786 other.set_column( col/2, *col0 );
matrix()
Construct a zero-initialized 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