19#ifndef THEORETICA_ALGEBRA_H
20#define THEORETICA_ALGEBRA_H
39 template<
typename Matrix>
42 using Type = matrix_element_t<Matrix>;
44 for (
unsigned int i = 0; i < m.rows(); ++i)
45 for (
unsigned int j = 0; j < m.cols(); ++j)
57 template<
typename Vector>
60 using Type = vector_element_t<Vector>;
62 for (
unsigned int i = 0; i < v.size(); ++i)
83 enable_vector<Vector> =
true
101 enable_vector<Vector> =
true
106 if (result.size() == 0)
122 enable_matrix<Matrix> =
true
124 inline Matrix
make_error(
unsigned int rows,
unsigned int cols) {
126 result.resize(rows, cols);
141 enable_matrix<Matrix> =
true
147 if (result.rows() == 0 || result.cols() == 0)
164 template<
typename Matrix>
167 using Type = matrix_element_t<Matrix>;
169 for (
unsigned int i = 0; i < m.rows(); ++i)
170 for (
unsigned int j = 0; j < m.cols(); ++j)
171 m(i, j) = (Type) (i == j ? 1 : 0);
180 template<
typename Matrix>
183 using Type = matrix_element_t<Matrix>;
185 for (
unsigned int i = 0; i < m.rows(); ++i)
186 for (
unsigned int j = 0; j < m.cols(); ++j)
196 template<
typename Vector>
199 using Type = vector_element_t<Vector>;
201 for (
unsigned int i = 0; i < v.size(); ++i)
212 template<
typename Matrix1,
typename Matrix2>
213 inline Matrix1&
mat_copy(Matrix1& dest,
const Matrix2& src) {
215 dest.resize(src.rows(), src.cols());
217 if (dest.rows() != src.rows()) {
222 if (dest.cols() != src.cols()) {
227 for (
unsigned int i = 0; i < src.rows(); ++i)
228 for (
unsigned int j = 0; j < src.cols(); ++j)
229 dest(i, j) = src(i, j);
240 template<
typename Vector1,
typename Vector2>
241 inline Vector1&
vec_copy(Vector1& dest,
const Vector2& src) {
243 dest.resize(src.size());
245 if (dest.size() != src.size()) {
250 for (
unsigned int i = 0; i < dest.size(); ++i)
263 template<
typename Matrix>
264 inline Matrix&
mat_swap_rows(Matrix& A,
unsigned int row1,
unsigned int row2) {
266 using Type = matrix_element_t<Matrix>;
268 if (row1 >= A.rows()) {
273 if (row2 >= A.rows()) {
281 for (
unsigned int j = 0; j < A.cols(); ++j) {
283 const Type tmp = A(row1, j);
285 A(row1, j) = A(row2, j);
299 template<
typename Matrix>
300 inline Matrix&
mat_swap_cols(Matrix& A,
unsigned int col1,
unsigned int col2) {
302 using Type = matrix_element_t<Matrix>;
304 if (col1 >= A.cols()) {
309 if (col2 >= A.cols()) {
317 for (
unsigned int i = 0; i < A.cols(); ++i) {
319 const Type tmp = A(i, col1);
321 A(i, col1) = A(i, col2);
335 template<
typename Matrix,
typename Type = matrix_element_t<Matrix>>
338 const unsigned int count =
min(A.rows(), A.cols());
340 for (
unsigned int i = 0; i < count; ++i)
354 template<
typename Type>
366 template<
typename Type>
377 template<
typename Vector>
383 for (
unsigned int i = 1; i < v.size(); ++i)
394 template<
typename Vector>
395 inline auto norm(
const Vector& v) {
404 template<
typename Vector>
411 const auto m =
norm(v);
419 for (
unsigned int i = 0; i < r.size(); ++i)
429 template<
typename Vector>
432 const auto m =
norm(v);
440 for (
unsigned int i = 0; i < v.size(); ++i)
453 template<
typename Vector1,
typename Vector2>
454 inline auto dot(
const Vector1& v,
const Vector2& w) {
456 if(v.size() != w.size()) {
458 return vector_element_t<Vector1>(
nan());
464 for (
unsigned int i = 1; i < v.size(); ++i)
475 template<
typename Vector1,
typename Vector2>
476 inline Vector1
cross(
const Vector1& v1,
const Vector2& v2) {
491 v3[0] = v1[1] * v2[2] - v1[2] * v2[1];
492 v3[1] = v1[2] * v2[0] - v1[0] * v2[2];
493 v3[2] = v1[0] * v2[1] - v1[1] * v2[0];
503 template<
typename Matrix,
typename MatrixT = Matrix>
507 res.resize(m.cols(), m.rows());
509 for (
unsigned int i = 0; i < m.rows(); ++i)
510 for (
unsigned int j = 0; j < m.cols(); ++j)
520 template<
typename Matrix>
523 if(m.rows() != m.cols()) {
528 for (
unsigned int i = 0; i < m.rows(); ++i) {
529 for (
unsigned int j = 0; j < i; ++j) {
531 const auto buff = m(i, j);
547 template<
typename Matrix1,
typename Matrix2>
548 inline Matrix1&
transpose(Matrix1& dest,
const Matrix2& src) {
552 if(src.rows() != dest.cols()) {
557 if(src.cols() != dest.rows()) {
563 for (
unsigned int i = 0; i < src.rows(); ++i)
564 for (
unsigned int j = 0; j < src.cols(); ++j)
565 dest(j, i) = src(i, j);
575 template<
typename Matrix,
typename MatrixT = Matrix>
579 res.resize(m.cols(), m.rows());
581 for (
unsigned int i = 0; i < m.rows(); ++i)
582 for (
unsigned int j = 0; j < m.cols(); ++j)
594 template<
typename Matrix>
597 if(m.rows() != m.cols()) {
602 for (
unsigned int i = 0; i < m.rows(); ++i) {
603 for (
unsigned int j = 0; j < i; ++j) {
605 const auto buff = m(i, j);
622 template<
typename Matrix1,
typename Matrix2>
623 inline Matrix1&
hermitian(Matrix1& dest,
const Matrix2& src) {
627 if(src.rows() != dest.cols()) {
632 if(src.cols() != dest.rows()) {
638 for (
unsigned int i = 0; i < src.rows(); ++i)
639 for (
unsigned int j = 0; j < src.cols(); ++j)
649 template<
typename Matrix>
650 inline auto trace(
const Matrix& m) {
653 const size_t n =
min(m.rows(), m.cols());
655 for (
unsigned int i = 1; i < n; ++i)
667 template<
typename Matrix>
671 const size_t n =
min(m.rows(), m.cols());
673 for (
unsigned int i = 1; i < n; ++i)
684 template<
typename Field,
typename Matrix>
687 for (
unsigned int i = 0; i < m.rows(); ++i)
688 for (
unsigned int j = 0; j < m.cols(); ++j)
701 template<
typename Field,
typename Matrix1,
typename Matrix2>
702 inline Matrix1&
mat_scalmul(Matrix1& dest, Field a,
const Matrix2& src) {
704 if(src.rows() != dest.rows()) {
709 if(src.cols() != dest.cols()) {
714 for (
unsigned int i = 0; i < src.rows(); ++i)
715 for (
unsigned int j = 0; j < src.cols(); ++j)
716 dest(i, j) = a * src(i, j);
726 template<
typename Field,
typename Vector>
729 for (
unsigned int i = 0; i < v.size(); ++i)
742 template<
typename Field,
typename Vector1,
typename Vector2>
743 inline Vector1&
vec_scalmul(Vector1& dest, Field a,
const Vector2& src) {
745 if(src.size() != dest.size()) {
750 for (
unsigned int i = 0; i < src.size(); ++i)
751 dest[i] = a * src[i];
766 template<
typename Matrix,
typename Vector>
769 if(v.size() != A.cols()) {
775 res.resize(A.rows());
778 for (
unsigned int i = 0; i < A.rows(); ++i)
779 for (
unsigned int j = 0; j < A.cols(); ++j)
780 res[i] += A(i, j) * v[j];
798 template<
typename Matrix,
typename Vector>
799 inline Vector
transform(
const Matrix& A,
const Vector& v) {
802 res.resize(A.rows());
804 if(v.size() != A.cols()) {
811 for (
unsigned int i = 0; i < A.rows(); ++i)
812 for (
unsigned int j = 0; j < A.cols(); ++j)
813 res[i] += A(i, j) * v[j];
826 template<
typename Matrix,
typename Vector1,
typename Vector2>
827 inline Vector1&
transform(Vector1& res,
const Matrix& A,
const Vector2& v) {
829 if(v.size() != A.cols()) {
834 if(res.size() != A.rows()) {
841 for (
unsigned int i = 0; i < A.rows(); ++i)
842 for (
unsigned int j = 0; j < A.cols(); ++j)
843 res[i] += A(i, j) * v[j];
857 template<
typename Matrix1,
typename Matrix2>
858 inline Matrix2&
mat_sum(Matrix1& A,
const Matrix2& B) {
860 if(A.rows() != B.rows()) {
865 if(A.cols() != B.cols()) {
870 for (
unsigned int i = 0; i < A.rows(); ++i)
871 for (
unsigned int j = 0; j < A.cols(); ++j)
872 A(i, j) = A(i, j) + B(i, j);
883 template<
typename Matrix1,
typename Matrix2,
typename Matrix3>
884 inline Matrix1&
mat_sum(Matrix1& res,
const Matrix2& A,
const Matrix3& B) {
886 if(A.rows() != B.rows()) {
891 if(A.cols() != B.cols()) {
896 if(res.rows() != A.rows()) {
901 if(res.cols() != A.cols()) {
906 for (
unsigned int i = 0; i < A.rows(); ++i)
907 for (
unsigned int j = 0; j < A.cols(); ++j)
908 res(i, j) = A(i, j) + B(i, j);
919 template<
typename Matrix1,
typename Matrix2>
920 inline Matrix2&
mat_diff(Matrix1& A,
const Matrix2& B) {
922 if(A.rows() != B.rows()) {
927 if(A.cols() != B.cols()) {
932 for (
unsigned int i = 0; i < A.rows(); ++i)
933 for (
unsigned int j = 0; j < A.cols(); ++j)
934 A(i, j) = A(i, j) - B(i, j);
945 template<
typename Matrix1,
typename Matrix2,
typename Matrix3>
946 inline Matrix1&
mat_diff(Matrix1& res,
const Matrix2& A,
const Matrix3& B) {
948 if(A.rows() != B.rows()) {
953 if(A.cols() != B.cols()) {
958 if(res.rows() != A.rows()) {
963 if(res.cols() != A.cols()) {
968 for (
unsigned int i = 0; i < A.rows(); ++i)
969 for (
unsigned int j = 0; j < A.cols(); ++j)
970 res(i, j) = A(i, j) - B(i, j);
982 template<
typename Field1,
typename Matrix1,
typename Field2,
typename Matrix2>
984 Field1 alpha, Matrix1& A, Field2 beta,
const Matrix2& B) {
986 if(A.rows() != B.rows()) {
991 if(A.cols() != B.cols()) {
996 for (
unsigned int i = 0; i < A.rows(); ++i)
997 for (
unsigned int j = 0; j < A.cols(); ++j)
998 A(i, j) = A(i, j) * alpha + B(i, j) * beta;
1013 template<
typename Matrix1,
typename Field1,
typename Matrix2,
1014 typename Field2,
typename Matrix3>
1016 Matrix1& res, Field1 alpha,
const Matrix2& A, Field2 beta,
const Matrix3& B) {
1018 if(A.rows() != B.rows()) {
1023 if(A.cols() != B.cols()) {
1028 if(res.rows() != A.rows()) {
1034 if(res.cols() != A.cols()) {
1039 for (
unsigned int i = 0; i < A.rows(); ++i)
1040 for (
unsigned int j = 0; j < A.cols(); ++j)
1041 res(i, j) = A(i, j) * alpha + B(i, j) * beta;
1053 template<
typename Matrix1,
typename Matrix2,
typename Matrix3 = Matrix1>
1054 inline Matrix3
mat_mul(
const Matrix1& A,
const Matrix2& B) {
1057 R.resize(A.rows(), B.cols());
1059 if(A.cols() != B.rows()) {
1066 for (
unsigned int i = 0; i < A.rows(); ++i)
1067 for (
unsigned int j = 0; j < B.cols(); ++j)
1068 for (
unsigned int k = 0; k < A.cols(); ++k)
1069 R(i, j) += A(i, k) * B(k, j);
1082 template<
typename Matrix1,
typename Matrix2,
typename Matrix3>
1083 inline Matrix1&
mat_mul(Matrix1& R,
const Matrix2& A,
const Matrix3& B) {
1085 if(R.rows() != A.rows()) {
1090 if(R.cols() != B.cols()) {
1095 if(A.cols() != B.rows()) {
1102 for (
unsigned int i = 0; i < A.rows(); ++i)
1103 for (
unsigned int j = 0; j < B.cols(); ++j)
1104 for (
unsigned int k = 0; k < A.cols(); ++k)
1105 R(i, j) += A(i, k) * B(k, j);
1121 template<
typename Matrix1,
typename Matrix2,
typename Matrix3 = Matrix1>
1125 R.resize(A.cols(), B.cols());
1127 if(A.rows() != B.rows()) {
1134 for (
unsigned int i = 0; i < R.rows(); ++i)
1135 for (
unsigned int j = 0; j < R.cols(); ++j)
1136 for (
unsigned int k = 0; k < A.rows(); ++k)
1137 R(i, j) += A(k, i) * B(k, j);
1153 template<
typename Matrix1,
typename Matrix2,
typename Matrix3 = Matrix1>
1157 R.resize(A.rows(), B.rows());
1159 if(A.cols() != B.cols()) {
1166 for (
unsigned int i = 0; i < R.rows(); ++i)
1167 for (
unsigned int j = 0; j < R.cols(); ++j)
1168 for (
unsigned int k = 0; k < A.cols(); ++k)
1169 R(i, j) += A(i, k) * B(j, k);
1181 template<
typename Matrix1,
typename Matrix2>
1185 if(A.rows() != B.rows() || A.cols() != B.cols())
1188 for (
unsigned int i = 0; i < A.rows(); ++i) {
1189 for (
unsigned int j = 0; j < A.cols(); ++j) {
1191 const auto diff =
abs(A(i, j) - B(i, j));
1193 if(diff > tolerance ||
is_nan(diff))
1207 template<
typename Vector1,
typename Vector2>
1208 inline Vector2&
vec_sum(Vector1& v1,
const Vector2& v2) {
1210 if(v1.size() != v2.size()) {
1215 for (
unsigned int i = 0; i < v1.size(); ++i)
1216 v1[i] = v1[i] + v2[i];
1227 template<
typename Vector1,
typename Vector2,
typename Vector3>
1228 inline Vector1&
vec_sum(Vector1& res,
const Vector2& v1,
const Vector3& v2) {
1230 if(v1.size() != v2.size()) {
1235 if(res.size() != v1.size()) {
1240 for (
unsigned int i = 0; i < v1.size(); ++i)
1241 res[i] = v1[i] + v2[i];
1252 template<
typename Vector1,
typename Vector2>
1253 inline Vector2&
vec_diff(Vector1& v1,
const Vector2& v2) {
1255 if(v1.size() != v2.size()) {
1260 for (
unsigned int i = 0; i < v1.size(); ++i)
1261 v1[i] = v1[i] - v2[i];
1272 template<
typename Vector1,
typename Vector2,
typename Vector3>
1273 inline Vector1&
vec_diff(Vector1& res,
const Vector2& v1,
const Vector3& v2) {
1275 if(v1.size() != v2.size()) {
1280 if(res.size() != v1.size()) {
1285 for (
unsigned int i = 0; i < v1.size(); ++i)
1286 res[i] = v1[i] - v2[i];
1297 template<
typename ReturnVector,
typename Vector,
typename Matrix>
1301 res.resize(A.cols());
1303 if(v.size() != A.rows()) {
1308 if(res.size() != A.cols()) {
1315 for (
unsigned int i = 0; i < A.rows(); ++i)
1316 for (
unsigned int j = 0; j < A.cols(); ++j)
1317 res[j] += v[i] * A(i, j);
1329 template<
typename Vector1,
typename Vector2,
typename Matrix>
1330 inline Vector1&
vec_mat_mul(Vector1& res,
const Vector2& v,
const Matrix& A) {
1332 if(v.size() != A.rows()) {
1337 if(res.size() != A.cols()) {
1344 for (
unsigned int i = 0; i < A.rows(); ++i)
1345 for (
unsigned int j = 0; j < A.cols(); ++j)
1346 res[j] += v[i] * A(i, j);
1358 template<
typename Matrix>
1360 return (m.rows() == m.cols());
1369 template<
typename Matrix>
1372 for (
unsigned int i = 0; i < m.rows(); ++i)
1373 for (
unsigned int j = 0; j < m.cols(); ++j)
1374 if(i != j &&
abs(m(i, j)) > tolerance)
1385 template<
typename Matrix>
1391 for (
unsigned int i = 0; i < m.rows(); ++i)
1392 for (
unsigned int j = 0; j < m.cols(); ++j)
1393 if(
abs(m(i, j) - m(j, i)) > tolerance)
1405 template<
typename Matrix>
1411 for (
unsigned int i = 0; i < m.rows(); ++i)
1412 for (
unsigned int j = i + 1; j < m.cols(); ++j)
1413 if (
abs(m(i, j)) > tolerance)
1425 template<
typename Matrix>
1431 for (
unsigned int i = 0; i < m.rows(); ++i)
1432 for (
unsigned int j = 0; j < i; ++j)
1433 if (
abs(m(i, j)) > tolerance)
1449 template<
typename Matrix, enable_matrix<Matrix> = true>
1452 long unsigned int n = 0;
1454 for (
unsigned int i = 0; i < A.rows(); ++i)
1455 for (
unsigned int j = 0; j < A.cols(); ++j)
1456 if (
abs(A(i, j)) > tolerance)
1459 return (
real(n) / A.rows()) / A.cols();
1472 template<
typename Matrix, enable_matrix<Matrix> = true>
1475 return 1.0 -
density(A, tolerance);
1489 template<
typename Matrix1,
typename Matrix2,
typename Matrix3>
1493 unsigned int err = 0;
1496 L.resize(A.rows(), A.cols());
1497 U.resize(A.rows(), A.cols());
1502 if (A.rows() != L.rows())
1505 if (A.cols() != L.cols())
1508 if (A.rows() != U.rows())
1511 if (A.cols() != U.cols())
1520 using Type = matrix_element_t<Matrix1>;
1523 for (
unsigned int i = 0; i < A.rows(); ++i)
1524 L(i, i) = (Type) 1.0;
1527 for(
unsigned int i = 0; i < A.rows(); ++i) {
1529 for(
unsigned int j = 0; j < A.rows(); ++j) {
1533 for(
unsigned int k = 0; k < i; ++k)
1537 for(
unsigned int j = i + 1; j < A.rows(); ++j) {
1541 for(
unsigned int k = 0; k < i; ++k)
1558 template<
typename Matrix>
1566 for(
unsigned int j = 0; j < A.cols(); ++j) {
1568 for(
unsigned int i = j + 1; i < A.rows(); ++i) {
1572 for(
unsigned int k = j + 1; k < A.rows(); ++k)
1587 template<
typename Matrix>
1591 L.resize(A.rows(), A.cols());
1592 using Type = matrix_element_t<Matrix>;
1606 for (
unsigned int i = 0; i < A.cols(); ++i) {
1608 for (
unsigned int j = 0; j <= i; ++j) {
1612 for (
unsigned int k = 1; k < j; ++k)
1617 const Type sqr_diag = A(j, j) -
sum;
1625 L(i, j) =
sqrt(sqr_diag);
1629 L(i, j) = (A(i, j) -
sum) / L(j, j);
1643 template<
typename Matrix>
1646 using Type = matrix_element_t<Matrix>;
1659 for (
unsigned int k = 0; k < A.rows(); ++k) {
1661 A(k, k) =
sqrt(A(k, k));
1663 for (
unsigned int i = k + 1; i < A.rows(); ++i)
1664 A(i, k) = A(i, k) / A(k, k);
1666 for (
unsigned int j = k + 1; j < A.rows(); ++j)
1667 for (
unsigned int i = j; i < A.cols(); ++i)
1672 for (
unsigned int i = 0; i < A.rows(); ++i)
1673 for (
unsigned int j = i + 1; j < A.rows(); ++j)
1674 A(i, j) = Type(0.0);
1689 template<
typename Matrix,
typename Vector>
1694 using Type = matrix_element_t<Matrix>;
1701 if (b.size() != L.rows()) {
1707 for (
unsigned int i = 0; i < L.cols(); ++i) {
1709 Type
sum = Type(0.0);
1711 for (
unsigned int j = 0; j < i; ++j)
1712 sum += L(i, j) * x[j];
1719 x[i] = (b[i] -
sum) / L(i, i);
1731 template<
typename Matrix,
typename Vector>
1736 using Type = matrix_element_t<Matrix>;
1743 if (b.size() != U.rows()) {
1748 if (U.rows() == 1) {
1749 x[0] = b[0] / U(0, 0);
1754 for (
int i = U.rows() - 1; i >= 0; --i) {
1756 Type
sum = Type(0.0);
1758 for (
unsigned int j = i + 1; j < U.cols(); ++j)
1759 sum += U(i, j) * x[j];
1766 x[i] = (b[i] -
sum) / U(i, i);
1780 template<
typename Matrix,
typename Vector>
1803 template<
typename Matrix,
typename Vector>
1811 if (A.rows() != b.size()) {
1816 using Type = matrix_element_t<Matrix>;
1819 for (
unsigned int i = 1; i < A.rows(); ++i) {
1821 Type
sum = Type(0.0);
1823 for (
unsigned int j = 0; j < i; ++j)
1824 sum += A(i, j) * b[j];
1830 for (
int i = A.rows() - 1; i >= 0; --i) {
1832 Type
sum = Type(0.0);
1834 for (
unsigned int j = i + 1; j < A.rows(); ++j)
1835 sum += A(i, j) * b[j];
1837 b[i] = (b[i] -
sum) / A(i, i);
1851 template<
typename Matrix,
typename Vector>
1872 template<
typename Matrix1,
typename Matrix2,
typename Vector>
1873 inline Vector
solve_lu(
const Matrix1& L,
const Matrix2& U,
const Vector& b) {
1887 if (L.rows() != U.rows()) {
1892 if (b.size() != L.rows()) {
1897 using Type1 = matrix_element_t<Matrix1>;
1900 for (
unsigned int i = 1; i < L.rows(); ++i) {
1902 Type1
sum = Type1(0.0);
1904 for (
unsigned int j = 0; j < i; ++j)
1905 sum += L(i, j) * x[j];
1910 using Type2 = matrix_element_t<Matrix2>;
1913 for (
int i = U.rows() - 1; i >= 0; --i) {
1915 Type2
sum = Type2(0.0);
1917 for (
unsigned int j = i + 1; j < U.rows(); ++j)
1918 sum += U(i, j) * x[j];
1925 x[i] = (x[i] -
sum) / U(i, i);
1943 template<
typename Matrix,
typename Vector>
1953 if (L.rows() != b.size()) {
1958 using Type = matrix_element_t<Matrix>;
1961 for (
unsigned int i = 0; i < L.rows(); ++i) {
1963 Type
sum = Type(0.0);
1965 for (
unsigned int j = 0; j < i; ++j)
1966 sum += L(i, j) * x[j];
1968 x[i] = (x[i] -
sum) / L(i, i);
1972 for (
int i = L.rows() - 1; i >= 0; --i) {
1974 Type
sum = Type(0.0);
1976 for (
unsigned int j = i + 1; j < L.rows(); ++j)
1977 sum += L(j, i) * x[j];
1979 x[i] = (x[i] -
sum) / L(i, i);
1992 template<
typename Matrix,
typename Vector>
1993 inline Vector
solve(
const Matrix& A,
const Vector& b) {
2008 template<
typename Matrix1,
typename Matrix2>
2009 inline Matrix1&
inverse(Matrix1& dest,
const Matrix2& src) {
2011 if(src.rows() != src.cols()) {
2016 if(dest.rows() != src.rows()) {
2021 if(dest.cols() != src.cols()) {
2026 using Type = matrix_element_t<Matrix2>;
2030 A.resize(src.rows(), src.cols());
2031 dest.resize(src.rows(), src.cols());
2036 for (
unsigned int i = 0; i < src.rows(); ++i) {
2040 if(A(i, i) == (Type) 0) {
2045 for (
unsigned int j = i + 1; j < src.rows(); ++j) {
2049 if(A(j, i) != (Type) 0) {
2051 for (
unsigned int k = 0; k < src.rows(); ++k) {
2053 dest(i, k) += dest(j, k);
2067 auto inv_pivot = ((Type) 1.0) / A(i, i);
2071 for (
unsigned int j = 0; j < src.rows(); ++j) {
2079 const auto coeff = A(j, i) * inv_pivot;
2081 for (
unsigned int k = 0; k < src.rows(); ++k) {
2082 A(j, k) -= coeff * A(i, k);
2083 dest(j, k) -= coeff * dest(i, k);
2088 for (
unsigned int j = 0; j < src.rows(); ++j) {
2089 A(i, j) *= inv_pivot;
2090 dest(i, j) *= inv_pivot;
2104 template<
typename Matrix,
typename MatrixInv = Matrix>
2107 res.resize(m.rows(), m.cols());
2118 template<
typename Matrix>
2121 if(m.rows() != m.cols()) {
2128 tmp.resize(m.rows(), m.cols());
2144 template<
typename Matrix>
2145 inline auto det(
const Matrix& A) {
2166 template<
typename Matrix,
typename Vector>
2169 const auto p =
dot(x, x);
2174 return vector_element_t<Vector>(
nan());
2192 template<
typename Matrix,
typename Vector>
2194 const Matrix& A,
const Vector& x,
2197 using Type = matrix_element_t<Matrix>;
2204 if (x.size() != A.rows()) {
2218 for (i = 1; i <= max_iter; ++i) {
2225 if (
norm(x_curr - x_prev) <= tolerance ||
2226 norm(x_curr + x_prev) <= tolerance)
2236 return dot(x_curr, A * x_curr);
2253 template<
typename Matrix,
typename Vector1,
typename Vector2 = Vector1>
2255 const Matrix& A,
const Vector1& x, Vector2& v,
2258 using Type = matrix_element_t<Matrix>;
2265 if (x.size() != A.rows()) {
2270 if (v.size() != x.size()) {
2284 for (i = 1; i <= max_iter; ++i) {
2291 if (
norm(x_curr - x_prev) <= tolerance ||
2292 norm(x_curr + x_prev) <= tolerance)
2305 return dot(x_curr, A * x_curr);
2320 template<
typename Matrix,
typename Vector>
2322 const Matrix& A,
const Vector& x,
2326 using Type = matrix_element_t<Matrix>;
2333 if (A.rows() != x.size()) {
2344 Vector x_curr = x_prev;
2350 for (i = 1; i <= max_iter; ++i) {
2358 if (
norm(x_curr - x_prev) <= tolerance ||
2359 norm(x_curr + x_prev) <= tolerance)
2370 return dot(x_curr, A * x_curr);
2387 template<
typename Matrix,
typename Vector1,
typename Vector2>
2389 const Matrix& A,
const Vector1& x, Vector2& v,
2392 using Type = matrix_element_t<Matrix>;
2399 if (A.rows() != x.size()) {
2410 Vector1 x_curr = x_prev;
2416 for (i = 1; i <= max_iter; ++i) {
2424 if (
norm(x_curr - x_prev) <= tolerance ||
2425 norm(x_curr + x_prev) <= tolerance)
2439 return dot(x_curr, A * x_curr);
2459 template<
typename Matrix,
typename Vector,
typename T = matrix_element_t<Matrix>>
2461 const Matrix& A,
const T& lambda,
const Vector& x,
2469 if (A.rows() != x.size()) {
2483 Vector v_curr = v_prev;
2489 for (i = 1; i <= max_iter; ++i) {
2497 if (
norm(v_curr - v_prev) <= tolerance ||
2498 norm(v_curr + v_prev) <= tolerance)
2525 template<
typename Matrix,
typename Vector,
typename T = matrix_element_t<Matrix>>
2527 const Matrix& A,
const T& lambda,
const Vector& x,
2530 using Type = matrix_element_t<Matrix>;
2537 if (A.rows() != x.size()) {
2546 Type lambda_prev = lambda;
2547 Type lambda_curr = lambda;
2554 for (i = 1; i <= max_iter; ++i) {
2558 lambda_prev = lambda_curr;
2572 if (
norm(x_curr - x_prev) <= tolerance ||
2573 norm(x_curr + x_prev) <= tolerance)
2601 template<
typename Matrix,
typename Vector1,
typename Vector2,
2602 typename T = matrix_element_t<Matrix>>
2604 const Matrix& A,
const T& lambda,
const Vector1& x, Vector2& v,
2607 using Type = matrix_element_t<Matrix>;
2614 if (A.rows() != x.size()) {
2623 Type lambda_prev = lambda;
2624 Type lambda_curr = lambda;
2631 for (i = 1; i <= max_iter; ++i) {
2635 lambda_prev = lambda_curr;
2649 if (
norm(x_curr - x_prev) <= tolerance ||
2650 norm(x_curr + x_prev) <= tolerance)
Complex number in algebraic form .
Definition complex.h:26
Complex data types definitions.
Error handling with errno and exceptions.
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compilation op...
Definition error.h:219
Linear algebra routines.
Definition algebra.h:29
bool is_lower_triangular(const Matrix &m, real tolerance=ALGEBRA_ELEMENT_TOL)
Returns whether the matrix is lower triangular.
Definition algebra.h:1406
Vector1 cross(const Vector1 &v1, const Vector2 &v2)
Compute the cross product between two tridimensional vectors.
Definition algebra.h:476
Matrix2 & mat_sum(Matrix1 &A, const Matrix2 &B)
Sum two matrices and store the result in the first matrix.
Definition algebra.h:858
Matrix3 mat_transpose_mul(const Matrix1 &A, const Matrix2 &B)
Multiply the transpose of a matrix by another matrix, equivalent to the operation .
Definition algebra.h:1122
auto eigenpair_power(const Matrix &A, const Vector1 &x, Vector2 &v, real tolerance=ALGEBRA_EIGEN_TOL, unsigned int max_iter=ALGEBRA_EIGEN_ITER)
Find the biggest eigenvalue in module of a square matrix and its corresponding eigenvector (eigenpai...
Definition algebra.h:2254
Matrix & mat_scalmul(Field a, Matrix &m)
Multiply a matrix by a scalar of any compatible type.
Definition algebra.h:685
bool is_square(const Matrix &m)
Returns whether the matrix is square.
Definition algebra.h:1359
Matrix & invert(Matrix &m)
Invert the given matrix and overwrite it.
Definition algebra.h:2119
auto eigenvalue_power(const Matrix &A, const Vector &x, real tolerance=ALGEBRA_EIGEN_TOL, unsigned int max_iter=ALGEBRA_EIGEN_ITER)
Find the biggest eigenvalue in module of a square matrix using the power method (Von Mises iteration...
Definition algebra.h:2193
auto trace(const Matrix &m)
Compute the trace of the given matrix.
Definition algebra.h:650
auto eigenpair_inverse(const Matrix &A, const Vector1 &x, Vector2 &v, real tolerance=ALGEBRA_EIGEN_TOL, unsigned int max_iter=ALGEBRA_EIGEN_ITER)
Find the eigenvalue with the smallest inverse of a square matrix and its corresponding eigenvector,...
Definition algebra.h:2388
Matrix & make_identity(Matrix &m)
Overwrite a matrix with the identity matrix.
Definition algebra.h:165
Matrix2 & mat_diff(Matrix1 &A, const Matrix2 &B)
Subtract two matrices and store the result in the first matrix.
Definition algebra.h:920
Matrix & mat_swap_cols(Matrix &A, unsigned int col1, unsigned int col2)
Swap two columns of a matrix, given the matrix and the two indices of the columns.
Definition algebra.h:300
Vector & make_normalized(Vector &v)
Normalize a given vector overwriting it.
Definition algebra.h:430
Vector1 & vec_copy(Vector1 &dest, const Vector2 &src)
Copy a vector by overwriting another.
Definition algebra.h:241
Vector & solve_lu_inplace(const Matrix &A, Vector &b)
Solve the linear system , finding , where the matrix A has already undergone in-place LU decompositio...
Definition algebra.h:1804
bool is_symmetric(const Matrix &m, real tolerance=ALGEBRA_ELEMENT_TOL)
Returns whether the matrix is symmetric.
Definition algebra.h:1386
Vector solve(const Matrix &A, const Vector &b)
Solve the linear system , finding using the best available algorithm.
Definition algebra.h:1993
ReturnVector vec_mat_mul(const Vector &v, const Matrix &A)
Multiply a vector by a matrix, returning the result.
Definition algebra.h:1298
Vector transform(const Matrix &A, const Vector &v)
Returns the matrix transformation of a vector.
Definition algebra.h:799
bool is_upper_triangular(const Matrix &m, real tolerance=ALGEBRA_ELEMENT_TOL)
Returns whether the matrix is upper triangular.
Definition algebra.h:1426
Vector & apply_transform(const Matrix &A, Vector &v)
Apply a matrix transformation to a vector and store the result in the vector.
Definition algebra.h:767
Vector eigenvector_inverse(const Matrix &A, const T &lambda, const Vector &x, real tolerance=ALGEBRA_EIGEN_TOL, unsigned int max_iter=ALGEBRA_EIGEN_ITER)
Find the eigenvector associated with a given approximated eigenvalue using the inverse power method.
Definition algebra.h:2460
void decompose_lu(const Matrix1 &A, Matrix2 &L, Matrix3 &U)
Decompose a square matrix to two triangular matrices, L and U where L is lower and U is upper,...
Definition algebra.h:1490
Matrix & mat_swap_rows(Matrix &A, unsigned int row1, unsigned int row2)
Swap two rows of a matrix, given the matrix and the two indices of the rows.
Definition algebra.h:264
Vector solve_lu(Matrix A, Vector b)
Solve the linear system , finding .
Definition algebra.h:1852
Vector solve_triangular(const Matrix &T, const Vector &b)
Solve the linear system for triangular .
Definition algebra.h:1781
Matrix & mat_error(Matrix &m)
Overwrite the given matrix with the error matrix with NaN values on the diagonal and zeroes everywher...
Definition algebra.h:40
Matrix decompose_cholesky(const Matrix &A)
Decompose a symmetric positive definite matrix into a triangular matrix so that using Cholesky decom...
Definition algebra.h:1588
auto dot(const Vector1 &v, const Vector2 &w)
Computes the dot product between two vectors, using the Hermitian form if needed.
Definition algebra.h:454
Matrix3 mat_mul(const Matrix1 &A, const Matrix2 &B)
Multiply two matrices and store the result in the first matrix, equivalent to the operation .
Definition algebra.h:1054
Matrix & mat_zeroes(Matrix &m)
Overwrite a matrix with all zeroes.
Definition algebra.h:181
auto pair_inner_product(const Type &v_i, const Type &w_i)
Compute the contribution of the inner product between a pair of elements of two vectors,...
Definition algebra.h:355
auto diagonal_product(const Matrix &m)
Compute the product of the elements of the main diagonal of a generic matrix.
Definition algebra.h:668
auto eigenvalue_rayleigh(const Matrix &A, const T &lambda, const Vector &x, real tolerance=ALGEBRA_EIGEN_TOL, unsigned int max_iter=ALGEBRA_EIGEN_ITER)
Compute an eigenvalue of a square matrix using the Rayleigh quotient iteration method.
Definition algebra.h:2526
auto eigenpair_rayleigh(const Matrix &A, const T &lambda, const Vector1 &x, Vector2 &v, real tolerance=ALGEBRA_EIGEN_TOL, unsigned int max_iter=ALGEBRA_EIGEN_ITER)
Compute an eigenvalue of a square matrix and its corresponding eigenvector (eigenpair) using the Rayl...
Definition algebra.h:2603
auto rayleigh_quotient(const Matrix &A, const Vector &x)
Compute the Rayleigh quotient of a vector with respect to a matrix.
Definition algebra.h:2167
auto sqr_norm(const Vector &v)
Returns the square of the Euclidean/Hermitian norm of the given vector.
Definition algebra.h:378
auto det(const Matrix &A)
Compute the determinant of a square matrix.
Definition algebra.h:2145
Matrix & mat_shift_diagonal(Matrix &A, const Type &sigma)
Shift the diagonal of a matrix by the given amount, overwriting the matrix itself,...
Definition algebra.h:336
Vector solve_triangular_lower(const Matrix &L, const Vector &b)
Solve the linear system for lower triangular .
Definition algebra.h:1690
Matrix & decompose_cholesky_inplace(Matrix &A)
Decompose a symmetric positive definite matrix in-place, overwriting the starting matrix,...
Definition algebra.h:1644
Vector2 & vec_sum(Vector1 &v1, const Vector2 &v2)
Sum two vectors and store the result in the first vector.
Definition algebra.h:1208
Matrix3 mat_mul_transpose(const Matrix1 &A, const Matrix2 &B)
Multiply a matrix by the transpose of another matrix, equivalent to the operation .
Definition algebra.h:1154
Matrix1 & mat_copy(Matrix1 &dest, const Matrix2 &src)
Copy a matrix by overwriting another.
Definition algebra.h:213
Matrix1 & mat_lincomb(Field1 alpha, Matrix1 &A, Field2 beta, const Matrix2 &B)
Compute the linear combination of two matrices and store the result in the first matrix.
Definition algebra.h:983
Vector2 & vec_diff(Vector1 &v1, const Vector2 &v2)
Subtract two vectors and store the result in the first vector.
Definition algebra.h:1253
MatrixT hermitian(const Matrix &m)
Returns the hermitian of the given matrix.
Definition algebra.h:576
Matrix & make_transposed(Matrix &m)
Transpose the given matrix.
Definition algebra.h:521
Vector solve_triangular_upper(const Matrix &U, const Vector &b)
Solve the linear system for upper triangular .
Definition algebra.h:1732
Vector & vec_zeroes(Vector &v)
Overwrite a vector with all zeroes.
Definition algebra.h:197
Vector & vec_error(Vector &v)
Overwrite the given vector with the error vector with NaN values.
Definition algebra.h:58
real density(const Matrix &A, real tolerance=ALGEBRA_ELEMENT_TOL)
Compute the density of a matrix, counting the proportion of non-zero (bigger in module than the given...
Definition algebra.h:1450
Vector solve_cholesky(const Matrix &L, const Vector &b)
Solve a linear system defined by a symmetric positive definite matrix, using the Cholesky decomposit...
Definition algebra.h:1944
Matrix1 & inverse(Matrix1 &dest, const Matrix2 &src)
Invert the given matrix.
Definition algebra.h:2009
auto norm(const Vector &v)
Returns the Euclidean/Hermitian norm of the given vector.
Definition algebra.h:395
bool is_diagonal(const Matrix &m, real tolerance=ALGEBRA_ELEMENT_TOL)
Returns whether the matrix is diagonal.
Definition algebra.h:1370
bool mat_equals(const Matrix1 &A, const Matrix2 &B, real tolerance=ALGEBRA_ELEMENT_TOL)
Checks whether two matrices are equal.
Definition algebra.h:1182
Vector normalize(const Vector &v)
Returns the normalized vector.
Definition algebra.h:405
auto eigenvalue_inverse(const Matrix &A, const Vector &x, real tolerance=ALGEBRA_EIGEN_TOL, unsigned int max_iter=ALGEBRA_EIGEN_ITER)
Find the eigenvalue with the smallest inverse of a square matrix, using the inverse power method wit...
Definition algebra.h:2321
real sparsity(const Matrix &A, real tolerance=ALGEBRA_ELEMENT_TOL)
Compute the sparsity of a matrix, counting the proportion of zero (smaller in module than the given t...
Definition algebra.h:1473
Matrix & decompose_lu_inplace(Matrix &A)
Decompose a square matrix to two triangular matrices, L and U where L is lower and U is upper,...
Definition algebra.h:1559
Matrix & make_hermitian(Matrix &m)
Compute the hermitian of a given matrix and overwrite it.
Definition algebra.h:595
Vector & vec_scalmul(Field a, Vector &v)
Multiply a vector by a scalar of any compatible type.
Definition algebra.h:727
MatrixT transpose(const Matrix &m)
Returns the transpose of the given matrix.
Definition algebra.h:504
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
auto min(const Vector &X)
Finds the minimum value inside a dataset.
Definition dataset.h:347
dual2 sqrt(dual2 x)
Compute the square root of a second order dual number.
Definition dual2_functions.h:54
bool is_nan(const T &x)
Check whether a generic variable is (equivalent to) a NaN number.
Definition error.h:90
dual2 abs(dual2 x)
Compute the absolute value of a second order dual number.
Definition dual2_functions.h:242
double real
A real number, defined as a floating point type.
Definition constants.h:207
constexpr real ALGEBRA_ELEMENT_TOL
Tolerance for the elements of matrices.
Definition constants.h:279
Vector make_error()
Create a vector representing an error state, with all NaN values.
Definition algebra.h:103
auto sum(const Vector &X)
Compute the sum of a vector of real values using pairwise summation to reduce round-off error.
Definition dataset.h:215
dual2 conjugate(dual2 x)
Return the conjugate of a second order dual number.
Definition dual2_functions.h:35
Vector make_error(unsigned int n)
Create a vector representing an error state, with all NaN values and a fixed size.
Definition algebra.h:85
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:74
@ InvalidArgument
Invalid argument.
Definition error.h:32
@ ImpossibleOperation
Mathematically impossible operation.
Definition error.h:30
@ NoConvergence
Algorithm did not converge.
Definition error.h:31
@ DivByZero
Division by zero.
Definition error.h:27
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition constants.h:216
constexpr real ALGEBRA_EIGEN_ITER
Maximum number of iterations for eigensolvers.
Definition constants.h:285
constexpr real ALGEBRA_EIGEN_TOL
Tolerance for eigensolvers.
Definition constants.h:282