1 #ifndef GENESIS_UTILS_MATH_MATRIX_H_
2 #define GENESIS_UTILS_MATH_MATRIX_H_
54 template<
typename T >
58 if( data.
rows() == 0 || data.
cols() == 0 ) {
60 std::numeric_limits<double>::quiet_NaN(),
61 std::numeric_limits<double>::quiet_NaN()
67 std::numeric_limits<double>::infinity(),
68 - std::numeric_limits<double>::infinity()
73 for(
auto const& e : data ) {
74 if( std::isfinite( e ) || ! ignore_non_finite_values ) {
75 ret.
min = std::min( ret.min, e );
76 ret.max = std::max( ret.max, e );
84 std::numeric_limits<double>::quiet_NaN(),
85 std::numeric_limits<double>::quiet_NaN()
98 template<
typename T >
101 auto ret = std::vector<MinMaxPair<T>>( data.
cols(), {
102 std::numeric_limits<double>::quiet_NaN(),
103 std::numeric_limits<double>::quiet_NaN()
107 if( data.
rows() == 0 ) {
112 for(
size_t c = 0; c < data.
cols(); ++c ) {
113 ret[ c ].min = std::numeric_limits<double>::infinity();
114 ret[ c ].max = - std::numeric_limits<double>::infinity();
117 for(
size_t r = 0; r < data.
rows(); ++r ) {
120 auto const& e = data( r, c );
121 if( std::isfinite( e ) || ! ignore_non_finite_values ) {
122 ret[ c ].min = std::min( ret[ c ].min, data( r, c ) );
123 ret[ c ].max = std::max( ret[ c ].max, data( r, c ) );
130 ret[ c ].min = std::numeric_limits<double>::quiet_NaN();
131 ret[ c ].max = std::numeric_limits<double>::quiet_NaN();
144 template<
typename T >
147 auto ret = std::vector<MinMaxPair<T>>( data.
rows(), {
148 std::numeric_limits<double>::quiet_NaN(),
149 std::numeric_limits<double>::quiet_NaN()
153 if( data.
cols() == 0 ) {
157 for(
size_t r = 0; r < data.
rows(); ++r ) {
159 ret[ r ].min = std::numeric_limits<double>::infinity();
160 ret[ r ].max = - std::numeric_limits<double>::infinity();
164 for(
size_t c = 0; c < data.
cols(); ++c ) {
165 auto const& e = data( r, c );
166 if( std::isfinite( e ) || ! ignore_non_finite_values ) {
167 ret[ r ].min = std::min( ret[ r ].min, data( r, c ) );
168 ret[ r ].max = std::max( ret[ r ].max, data( r, c ) );
175 ret[ r ].min = std::numeric_limits<double>::quiet_NaN();
176 ret[ r ].max = std::numeric_limits<double>::quiet_NaN();
189 template<
typename T >
194 for(
auto const& e : data ) {
195 if( std::isfinite( e ) || ! ignore_non_finite_values ) {
208 template<
typename T >
212 auto row_sums = std::vector<T>( data.
rows(), T{} );
213 for(
size_t i = 0; i < data.
rows(); ++i ) {
214 for(
size_t j = 0; j < data.
cols(); ++j ) {
215 auto const& e = data( i, j );
216 if( std::isfinite( e ) || ! ignore_non_finite_values ) {
230 template<
typename T >
234 auto col_sums = std::vector<T>( data.
cols(), T{} );
235 for(
size_t i = 0; i < data.
rows(); ++i ) {
236 for(
size_t j = 0; j < data.
cols(); ++j ) {
237 auto const& e = data( i, j );
238 if( std::isfinite( e ) || ! ignore_non_finite_values ) {
262 std::vector<MinMaxPair<double>>
normalize_cols( Matrix<double>& data );
276 std::vector<MinMaxPair<double>>
normalize_rows( Matrix<double>& data );
296 Matrix<double>& data,
297 bool scale_means =
true,
298 bool scale_std =
true
319 Matrix<double>& data,
320 bool scale_means =
true,
321 bool scale_std =
true
339 Matrix<double>& data,
340 double epsilon = 1e-5
383 template<
typename T >
387 throw std::runtime_error(
"Symmetric sort only works on square matrices." );
392 auto si =
sort_indices( row_sums.begin(), row_sums.end() );
394 for(
size_t i = 0; i < data.
rows(); ++i ) {
395 for(
size_t j = 0; j < data.
cols(); ++j ) {
396 result( i, j ) = data( si[i], si[j] );
414 template<
typename T >
418 throw std::runtime_error(
"Symmetric sort only works on square matrices." );
423 auto si =
sort_indices( col_sums.begin(), col_sums.end() );
425 for(
size_t i = 0; i < data.
rows(); ++i ) {
426 for(
size_t j = 0; j < data.
cols(); ++j ) {
427 result( i, j ) = data( si[i], si[j] );
442 template<
typename T >
446 throw std::runtime_error(
"Symmetric sort only works on square matrices." );
451 auto find_max = [](
Matrix<T> const& mat,
size_t start ){
452 size_t max_r = start;
453 size_t max_c = start;
454 for(
size_t r = start; r < mat.
rows(); ++r ) {
455 for(
size_t c = start; c < mat.
cols(); ++c ) {
456 if( mat(r, c) > mat( max_r, max_c ) ) {
462 return std::make_pair( max_r, max_c );
468 for(
size_t i = 0; i < mat.
rows(); ++i ) {
469 auto const max_pair = find_max( mat, i );
470 matrix_swap_rows( mat, i, max_pair.first );
471 matrix_swap_cols( mat, i, max_pair.second );
485 template<
typename T =
double,
typename A =
double,
typename B =
double >
489 throw std::runtime_error(
"Cannot add matrices with different dimensions." );
493 for(
size_t r = 0; r < a.
rows(); ++r ) {
494 for(
size_t c = 0; c < a.
cols(); ++c ) {
495 result( r, c ) = a( r, c ) + b( r, c );
504 template<
typename T =
double,
typename A =
double,
typename B =
double >
508 for(
size_t r = 0; r < matrix.
rows(); ++r ) {
509 for(
size_t c = 0; c < matrix.
cols(); ++c ) {
510 result( r, c ) = matrix( r, c ) + scalar;
521 template<
typename T =
double,
typename A =
double,
typename B =
double >
525 throw std::runtime_error(
"Cannot add matrices with different dimensions." );
529 for(
size_t r = 0; r < a.
rows(); ++r ) {
530 for(
size_t c = 0; c < a.
cols(); ++c ) {
531 result( r, c ) = a( r, c ) - b( r, c );
547 template<
typename T =
double,
typename A =
double,
typename B =
double >
551 throw std::runtime_error(
"Cannot multiply matrices if a.cols() != b.rows()." );
558 for(
size_t r = 0; r < a.
rows(); ++r ) {
559 for(
size_t c = 0; c < b.
cols(); ++c ) {
560 result( r, c ) = 0.0;
561 for(
size_t j = 0; j < a.
cols(); ++j ) {
562 result( r, c ) += a( r, j ) * b( j, c );
577 template<
typename T =
double,
typename A =
double,
typename B =
double >
580 if( a.size() != b.
rows() ) {
581 throw std::runtime_error(
"Cannot multiply vector with matrix if a.size() != b.rows()." );
584 auto result = std::vector<T>( b.
cols(), 0.0 );
585 for(
size_t c = 0; c < b.
cols(); ++c ) {
586 for(
size_t j = 0; j < a.size(); ++j ) {
587 result[ c ] += a[ j ] * b( j, c );
601 template<
typename T =
double,
typename A =
double,
typename B =
double >
604 if( a.
cols() != b.size() ) {
605 throw std::runtime_error(
"Cannot multiply matrix with vector if a.cols() != b.size()." );
608 auto result = std::vector<T>( a.
rows(), 0.0 );
609 for(
size_t r = 0; r < a.
rows(); ++r ) {
610 for(
size_t j = 0; j < a.
cols(); ++j ) {
611 result[ r ] += a( r, j ) * b[ j ];
621 template<
typename T =
double,
typename A =
double,
typename B =
double >
625 for(
size_t r = 0; r < matrix.
rows(); ++r ) {
626 for(
size_t c = 0; c < matrix.
cols(); ++c ) {
627 result( r, c ) = matrix( r, c ) * scalar;
636 #endif // include guard