12 #include <type_traits> 15 #include "mu/typetraits.h" 16 #include "mu/utility.h" 35 template <std::
size_t N, std::
size_t M,
typename T>
37 static_assert(N != 0,
"first matrix dimension (rows) cannot be zero");
38 static_assert(M != 0,
"second matrix dimension (columns) cannot be zero");
39 static_assert(std::is_arithmetic<T>::value,
40 "Matrix type T must be an arithmetic type");
44 using value_type =
typename std::array<Vector<M, T>, N>::value_type;
45 using size_type =
typename std::array<Vector<M, T>, N>::size_type;
47 using iterator =
typename std::array<Vector<M, T>, N>::iterator;
48 using const_iterator =
typename std::array<Vector<M, T>, N>::const_iterator;
56 constexpr
Matrix() =
default;
69 template <
typename... TArgs,
71 sizeof...(TArgs) == N &&
72 (mu::conjunction<std::is_same<
73 T, std::remove_reference_t<TArgs>>::value...>::value),
76 Matrix(TArgs
const(&&... rows)[M]) : data_{mu::to_array(rows)...} {}
92 template <std::
size_t Nn, std::
size_t Mm,
class U>
95 static_assert(N == Nn,
"Matrix dimension mismatch (rows)");
96 static_assert(M == Mm,
"Matrix dimension mismatch (columns)");
123 template <
typename U = T>
126 std::transform(a.begin(), a.end(),
begin(),
142 template <
typename U = T,
143 std::enable_if_t<std::is_arithmetic<U>::value,
int> = 0>
145 Matrix(
const std::array<std::array<U, M>, N> &a) {
146 std::transform(a.begin(), a.end(),
begin(),
163 template <
typename U = T,
164 std::enable_if_t<std::is_arithmetic<U>::value,
int> = 0>
272 constexpr std::array<size_type, 2>
size() const noexcept {
273 return std::array<size_type, 2>{N, M};
283 constexpr size_type
n_rows() const noexcept {
return N; }
292 constexpr size_type
n_cols() const noexcept {
return M; }
301 iterator
begin() noexcept {
return data_.begin(); }
310 const_iterator
begin() const noexcept {
return data_.begin(); }
319 iterator
end() noexcept {
return data_.end(); }
328 const_iterator
end() const noexcept {
return data_.end(); }
342 assert(idx >= 0 && idx < N);
358 assert(idx >= 0 && idx < M);
360 for (std::size_t i = 0; i < N; i++) {
361 ret[i] = data_[i][idx];
375 for (
const auto &
row : data_) {
376 ret = mu::min(ret, mu::min(
row));
390 for (
const auto &
row : data_) {
391 ret = mu::max(ret, mu::max(
row));
405 for (
const auto &
row : data_) {
422 template <
typename U = T>
424 return U(
sum()) / (N * M);
443 constexpr std::size_t s = N < M ? N : M;
445 for (std::size_t i = 0; i < s; i++) {
446 ret[i] = data_[i][i];
461 static_assert(N == M,
462 "Matrix dimensions must match to calculate the determinant");
463 std::vector<std::vector<T>> vv;
464 for (std::size_t i = 0; i < N; i++) {
465 vv.push_back(std::vector<T>());
466 for (
const auto &item : data_[i]) {
467 vv[i].push_back(item);
484 "Matrix dimensions must match to transpose this object. For Matrices " 485 "with unequal dimensions, i.e. N != M, the \"transposed()\" method can " 488 for (std::size_t i = 0; i < N; i++) {
489 for (std::size_t j = 0; j < M; j++) {
490 data_[j][i] = copy[i][j];
504 for (std::size_t i = 0; i < N; i++) {
505 for (std::size_t j = 0; j < M; j++) {
506 ret[j][i] = data_[i][j];
547 template <
typename U =
void, std::
size_t N2, std::
size_t M2,
typename T2>
553 "Matrix dimension mismatch. Second dimension of first matrix must be " 554 "equal to the first dimension of the second matrix");
555 using U_ = std::conditional_t<!std::is_same<T, T2>::value, U, T>;
556 static_assert(!std::is_same<U_, void>::value,
557 "Matrix types are different. please specify the return " 558 "type. e.g. \"mat1.dot<float>(mat2);\"");
560 for (std::size_t i = 0; i < N; i++) {
561 for (std::size_t j = 0; j < M2; j++) {
563 for (std::size_t k = 0; k < M; k++) {
564 sum += (data_[i][k] * rhs[k][j]);
603 template <
typename U =
void, std::
size_t N2,
typename T2>
608 "Matrix-Vector dimension mismatch. Second dimension of the matrix " 609 "must be equal to the vector size");
610 using U_ = std::conditional_t<!std::is_same<T, T2>::value, U, T>;
612 !std::is_same<U_, void>::value,
613 "Matrix and Vector types are different. please specify the return " 614 "type. e.g. \"mat.dot<float>(vec);\"");
616 for (std::size_t i = 0; i < N; i++) {
618 for (std::size_t k = 0; k < M; k++) {
619 sum += (data_[i][k] * rhs[k]);
636 template <
class U = T>
640 for (
const auto &
row : data_) {
641 for (
const auto &item :
row) {
642 sum += mu::pow(item - m, 2);
645 return U(mu::sqrt(
sum / (N * M)));
663 template <std::
size_t Nn, std::
size_t Mm,
class U>
664 friend std::ostream &operator<<(std::ostream &os, const Matrix<Nn, Mm, U> &m);
676 template <
typename U = T>
678 for (std::size_t i = 0; i < N; i++) {
680 if (data_[i] != rhs[i]) {
693 template <
typename U = T>
707 template <
typename U = T>
709 for (std::size_t i = 0; i < N; i++) {
724 template <
typename U = T>
726 for (std::size_t i = 0; i < N; i++) {
741 template <
typename U = T>
743 for (std::size_t i = 0; i < N; i++) {
758 template <
typename U = T>
760 for (std::size_t i = 0; i < N; i++) {
780 template <
class TScalar>
781 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
784 for (
auto &
row : data_) {
798 template <
class TScalar>
799 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
802 for (
auto &
row : data_) {
816 template <
class TScalar>
817 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
820 for (
auto &
row : data_) {
836 template <
class TScalar>
837 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
841 for (
auto &
row : data_) {
850 std::array<Vector<M, T>, N> data_;
855 template <std::
size_t Nn, std::
size_t Mm,
class U>
856 std::ostream &operator<<(std::ostream &os, const Matrix<Nn, Mm, U> &m) {
858 for (std::size_t i = 0; i < Nn; i++) {
883 template <std::
size_t N, std::
size_t M,
class T,
class U = T>
900 template <std::
size_t N, std::
size_t M,
class T,
class U = T>
917 template <std::
size_t N, std::
size_t M,
class T,
class U = T>
934 template <std::
size_t N, std::
size_t M,
class T,
class U = T>
954 template <std::
size_t N, std::
size_t M,
class T,
class TScalar>
955 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
973 template <std::
size_t N, std::
size_t M,
class T,
class TScalar>
974 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
990 template <std::
size_t N, std::
size_t M,
class T,
class TScalar>
991 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
1009 template <std::
size_t N, std::
size_t M,
class T,
class TScalar>
1010 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
1028 template <std::
size_t N, std::
size_t M,
class T,
class TScalar>
1029 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
1045 template <std::
size_t N, std::
size_t M,
class T,
class TScalar>
1046 typename std::enable_if_t<std::is_arithmetic<TScalar>::value,
1054 template <std::
size_t N, std::
size_t M,
class T>
1059 template <std::
size_t N, std::
size_t M,
class T>
1064 template <std::
size_t N, std::
size_t M,
class T>
1069 template <
class U =
void, std::
size_t N, std::
size_t M,
typename T>
1070 inline std::conditional_t<std::is_same<U, void>::value, T, U>
mean(
1073 .template mean<std::conditional_t<std::is_same<U, void>::value, T, U>>();
1076 template <std::
size_t N, std::
size_t M,
typename T>
1077 std::conditional_t <
1092 template <std::
size_t N,
typename T>
1095 for (std::size_t i = 0; i < N; i++) {
1101 template <std::
size_t N, std::
size_t M,
typename T>
1106 template <std::
size_t N, std::
size_t M,
typename T>
1112 template <std::
size_t N, std::
size_t M,
typename T>
1117 template <
typename U = void, std::size_t N1, std::size_t M1,
typename T1,
1118 std::size_t N2, std::size_t M2,
typename T2>
1122 return lhs.template dot<U>(rhs);
1125 template <
typename U = void, std::size_t N, std::size_t M,
typename T,
1126 std::size_t N2,
typename T2>
1129 return lhs.template dot<U>(rhs);
1132 template <std::
size_t S,
typename T =
int>
1135 for (std::size_t i = 0; i < S; i++) {
1141 template <std::
size_t N, std::
size_t M,
typename T =
int>
1146 template <std::
size_t N, std::
size_t M,
typename T =
int>
1163 template <std::
size_t N,
typename T>
1171 template <
typename T>
1179 template <
typename T>
1183 #endif // MU_MATRIX_H_ Matrix< N, M, T > operator-(const Matrix< N, M, T > &lhs, const Matrix< N, M, U > &rhs)
minus operator
Definition: matrix.h:901
std::enable_if_t< std::is_arithmetic< TScalar >::value, Matrix< N, M, T > & > operator*=(const TScalar &scalar)
multiply a scalar with this matrix
Definition: matrix.h:819
Matrix< N, M, T > & operator/=(const Matrix< N, M, U > &rhs)
divison equal operator
Definition: matrix.h:759
Vector< M, T > row(const size_type &idx) const
get a matrix row as a vector
Definition: matrix.h:340
U mean() const
mean of all the elements of the matrix
Definition: matrix.h:423
Matrix< N, M, T > operator/(const Matrix< N, M, T > &lhs, const Matrix< N, M, U > &rhs)
division operator
Definition: matrix.h:935
Matrix(TArgs const(&&... rows)[M])
Construct a new Matrix object from a number of NxM values.
Definition: matrix.h:76
constexpr size_type n_cols() const noexcept
returns the number of columns
Definition: matrix.h:292
constexpr size_type n_rows() const noexcept
returns the number of rows
Definition: matrix.h:283
auto diag() const
returns the diagonal of the matrix as a vector
Definition: matrix.h:442
Vector< M, T > & operator[](size_type idx) noexcept
access a row within the matrix
Definition: matrix.h:224
std::enable_if_t< std::is_arithmetic< TScalar >::value, Matrix< N, M, T > & > operator+=(const TScalar &scalar)
add a scalar to this matrix
Definition: matrix.h:783
Matrix< N, M, T > operator*(const Matrix< N, M, T > &lhs, const Matrix< N, M, U > &rhs)
multiplication operator
Definition: matrix.h:918
Vector< N, T > col(const size_type &idx) const
get a matrix column as a vector
Definition: matrix.h:356
std::conditional_t< std::is_same< U, void >::value, Vector< N, T >, Vector< N, U > > dot(const Vector< N2, T2 > &rhs) const
dot product of a matrix and a vector
Definition: matrix.h:605
Matrix< N, M, T > & operator*=(const Matrix< N, M, U > &rhs)
multiplication equal operator
Definition: matrix.h:742
A generic vector.
Definition: vector.h:48
U std() const
calculates the standard deviation
Definition: matrix.h:637
iterator end() noexcept
returns a iterator starting at one after the last row
Definition: matrix.h:319
void transpose()
transposes this Matrix object
Definition: matrix.h:481
constexpr Matrix()=default
Construct a new Matrix object.
T det() const
calculates the determinant of the matrix
Definition: matrix.h:460
Matrix(const std::array< Vector< M, T >, N > &a)
Construct a new Matrix object from an std::array of Vectors.
Definition: matrix.h:109
iterator begin() noexcept
returns an iterator starting at the first row
Definition: matrix.h:301
bool operator==(const Matrix< N, M, U > &rhs) const
equality operator
Definition: matrix.h:677
Matrix(const std::array< std::array< U, M >, N > &a)
Construct a new Matrix object from an std::array of std::arrays. possibly of a different type...
Definition: matrix.h:145
bool operator!=(const Matrix< N, M, U > &rhs) const
unequality operator
Definition: matrix.h:694
Vector< M, T > & at(size_type idx)
access a row within the matrix
Definition: matrix.h:249
Matrix< N, M, T > operator+(const Matrix< N, M, T > &lhs, const Matrix< N, M, U > &rhs)
plus operator
Definition: matrix.h:884
const_iterator end() const noexcept
returns a const iterator starting at one after the last row
Definition: matrix.h:328
T min() const
get the min value of the matrix
Definition: matrix.h:373
const Vector< M, T > & at(size_type idx) const
const access a row within the matrix
Definition: matrix.h:260
const_iterator begin() const noexcept
returns a const iterator starting at the first row
Definition: matrix.h:310
Matrix(const U &value)
Construct a new Matrix object from a single value possibly of a different type.
Definition: matrix.h:166
Matrix(const std::array< Vector< M, U >, N > &a)
Construct a new Matrix object from an std::array of Vectors of a different type.
Definition: matrix.h:125
Definition: literals.h:11
Matrix(const Matrix< Nn, Mm, U > &m)
Construct a new Matrix from an existing Matrix of a different type.
Definition: matrix.h:94
A generic matrix.
Definition: matrix.h:36
const Vector< M, T > & operator[](size_type idx) const noexcept
const access a row within the matrix
Definition: matrix.h:236
std::enable_if_t< std::is_arithmetic< TScalar >::value, Matrix< N, M, T > & > operator/=(const TScalar &scalar)
divide every element of this matrix by a scalar
Definition: matrix.h:839
~Matrix()=default
Destroy the Matrix object.
Matrix< N, M, T > & operator-=(const Matrix< N, M, U > &rhs)
minus equal operator
Definition: matrix.h:725
std::enable_if_t< std::is_arithmetic< TScalar >::value, Matrix< N, M, T > & > operator-=(const TScalar &scalar)
subtract a scalar from every element of this matrix
Definition: matrix.h:801
Matrix & operator=(const Matrix &other)=default
Copy assignment operator.
constexpr std::array< size_type, 2 > size() const noexcept
returns the matrix dimensions as an array of size 2
Definition: matrix.h:272
Matrix< M, N, T > transposed() const
creates and returns a transposed Matrix object
Definition: matrix.h:502
std::conditional_t< std::is_same< U, void >::value, Matrix< N, M2, T >, Matrix< N, M2, U > > dot(const Matrix< N2, M2, T2 > &rhs) const
dot product of two matrices
Definition: matrix.h:550
Matrix< N, M, T > & operator+=(const Matrix< N, M, U > &rhs)
plus equal operator
Definition: matrix.h:708
T max() const
get the max value of the matrix
Definition: matrix.h:388
T sum() const
sum up all the elements of the matrix
Definition: matrix.h:403