14template <
int n,
typename Mtype>
18 for (
int i = 0; i < n - 1; i++) {
19 for (
int j = i + 1; j < n; j++) {
28 return ::sqrt(abs_mpq);
42template <
typename Dtype>
55 auto t0 = c * v.
e(0) + s * v.
e(1);
62 auto t0 = v.
e(0) * c -
::conj(s) * v.
e(1);
63 v.
e(1) = v.
e(0) * s + v.
e(1) * c;
68 template <
typename Mtype>
69 void mult_by_Givens_left(
Mtype &M,
int p,
int q)
const {
71 for (
int i = 0; i < M.
columns(); i++) {
75 a = this->mult_vector_left(a);
82 template <
typename Mtype>
83 void mult_by_Givens_right(
Mtype &M,
int p,
int q)
const {
85 for (
int i = 0; i < M.
rows(); i++) {
89 a = this->mult_row_right(a);
137template <
typename Dtype>
138GivensMatrix<Dtype> diagonalize_2x2(
const double mpp,
const double mqq,
const Dtype mpq) {
140 GivensMatrix<Dtype> res;
144 double a = (mqq - mpp);
147 double t = 2.0 / (
abs(a) +
sqrt(a * a + 4 * mpq2));
150 res.c = 1.0 /
sqrt(mpq2 * t * t + 1.0);
151 res.s = mpq * (t * res.c);
198template <
int n,
int m,
typename T,
typename Mtype>
199template <
typename Et,
typename Mt,
typename MT>
202 enum hila::sort sorted)
const {
204 static_assert(!hila::contains_complex<T>::value || hila::contains_complex<Mt>::value,
205 "Eigenvector matrix must be complex with complex original matrix");
207 static_assert(n == m,
"Eigensystem can be solved only for square matrices");
210 typename std::conditional<hila::contains_complex<T>::value,
Complex<double>,
double>::type;
214 constexpr double eps = 2.22e-16;
228 for (rot = 0; rot < 100 * n * n; rot++) {
232 double abs_mpq = hila::linalg::find_largest_offdiag(M, p, q);
236 if (abs_mpq <= eps *
sqrt(
::abs(eigenvalues.
e(p)) *
::abs(eigenvalues.
e(q)))) {
241 auto P = hila::linalg::diagonalize_2x2(eigenvalues.
e(p), eigenvalues.
e(q), M.
e(p, q));
243 P.dagger().mult_by_Givens_left(M, p, q);
244 P.mult_by_Givens_right(M, p, q);
246 eigenvalues.
e(p) =
::real(M.
e(p, p));
247 eigenvalues.
e(q) =
::real(M.
e(q, q));
262 P.mult_by_Givens_right(V, p, q);
266 if (sorted == hila::sort::unsorted) {
275 E = eigenvalues.
sort(perm, sorted);
305template <
int n,
int m,
typename T,
typename Mtype>
309 this->eigen_hermitean(res.eigenvalues, res.eigenvectors, sorted);
342template <
int n,
int m,
typename T,
typename Mtype>
343template <
typename Et,
typename Mt,
typename MT>
347 enum hila::sort sorted)
const {
349 static_assert(!hila::contains_complex<T>::value || hila::contains_complex<Mt>::value,
350 "SVD: diagonalizing matrix must be complex with complex original matrix");
352 static_assert(n == m,
"SVD can be solved only for square matrices");
355 typename std::conditional<hila::contains_complex<T>::value,
Complex<double>,
double>::type;
359 constexpr double eps = 2.22e-16;
373 for (rot = 0; rot < 100 *
sqr(n); rot++) {
377 double abs_pq = hila::linalg::find_largest_offdiag(B, p, q);
383 auto P = hila::linalg::diagonalize_2x2(
::real(B.
e(p, p)),
::real(B.
e(q, q)), B.
e(p, q));
386 P.mult_by_Givens_right(M, p, q);
387 P.mult_by_Givens_right(V, p, q);
392 for (
int i = 0; i < n; i++) {
394 B.
e(p, i) = col.dot(M.
column(i));
399 for (
int i = 0; i < n; i++) {
401 B.
e(q, i) = col.dot(M.
column(i));
411 for (
int i = 0; i < n; i++) {
417 if (sorted == hila::sort::unsorted) {
427 _S = S.
sort(perm, sorted);
466template <
int n,
int m,
typename T,
typename Mtype>
467template <
typename Et,
typename Mt,
typename MT>
471 enum hila::sort sorted)
const {
473 static_assert(!hila::contains_complex<T>::value || hila::contains_complex<Mt>::value,
474 "SVD: diagonalizing matrix must be complex with complex original matrix");
476 static_assert(n == m,
"SVD can be solved only for square matrices");
479 typename std::conditional<hila::contains_complex<T>::value,
Complex<double>,
double>::type;
483 constexpr double eps = 2.22e-16;
496 for (rot = 0; cont && rot < 100 *
sqr(n);) {
499 for (
int p = 0; p < n - 1; p++) {
502 for (
int q = p + 1; q < n; q++) {
512 double Bqq = colq.squarenorm();
514 Dtype Bpq = colp.
dot(colq);
519 if (
::abs(Bpq) > eps *
sqrt(Bpp * Bqq)) {
523 auto P = hila::linalg::diagonalize_2x2(Bpp, Bqq, Bpq);
526 P.mult_by_Givens_right(M, p, q);
527 P.mult_by_Givens_right(V, p, q);
535 for (
int i = 0; i < n; i++) {
541 if (sorted == hila::sort::unsorted) {
551 _S = S.
sort(perm, sorted);
575template <
int n,
int m,
typename T,
typename Mtype>
579 this->svd(res.U, res.singularvalues, res.V, sorted);
583template <
int n,
int m,
typename T,
typename Mtype>
587 this->svd_pivot(res.U, res.singularvalues, res.V, sorted);
597 typename Mtype, std::enable_if_t<Mtype::is_matrix(),
int> = 0,
599Rtype Minor(
const Mtype &bigger,
int row,
int col) {
605 for (
int i = 0; i < n; i++)
608 for (
int j = 0; j < m; j++) {
610 result.e(ri, ci) = bigger.
e(i, j);
635template <
int n,
int m,
typename T,
typename Mtype>
638 static_assert(n == m,
"determinants defined only for square matrices");
640 if constexpr (n == 1) {
643 if constexpr (n == 2) {
644 return this->e(0, 0) * this->e(1, 1) - this->e(1, 0) * this->e(0, 1);
646 if constexpr (n == 3) {
647 return this->e(0, 0) * (this->e(1, 1) * this->e(2, 2) - this->e(2, 1) * this->e(1, 2)) -
648 this->e(0, 1) * (this->e(1, 0) * this->e(2, 2) - this->e(1, 2) * this->e(2, 0)) +
649 this->e(0, 2) * (this->e(1, 0) * this->e(2, 1) - this->e(1, 1) * this->e(2, 0));
652 if constexpr (n > 3) {
654 hila::arithmetic_type<T> parity = 1, opposite = -1;
655 for (
int i = 0; i < n; i++) {
656 Matrix<n - 1, m - 1, T> minor = hila::linalg::Minor(*
this, 0, i);
657 result += parity * minor.det_laplace() * (*this).e(0, i);
675template <
int n,
int m,
typename T,
typename Mtype>
678 static_assert(n == m,
"Determinant is defined only for square matrix");
683 hila::arithmetic_type<T> d = 1, big, tmp;
687 for (
int i = 0; i < n; i++) {
689 for (
int j = 0; j < n; j++) {
699 vv[i] = 1.0 /
sqrt(big);
703 for (
int j = 0; j < n; j++) {
706 for (
int i = 0; i < j; i++) {
707 for (
int k = 0; k < i; k++) {
708 a.
e(i, j) -= a.
e(i, k) * a.
e(k, j);
714 for (
int i = j; i < n; i++) {
715 auto csum = a.
e(i, j);
716 for (
int k = 0; k < j; k++) {
717 csum -= a.
e(i, k) * a.
e(k, j);
720 auto dum = vv[i] *
::abs(csum);
728 for (
int k = 0; k < n; k++) {
729 hila::swap(a.
e(imax, k), a.
e(j, k));
736 if (
::abs(a.
e(j, j)) == 0.0)
741 auto dum = 1 / a.
e(j, j);
742 for (
int i = j + 1; i < n; i++) {
750 for (
int j = 0; j < n; j++) {
763template <
int n,
int m,
typename T,
typename Mtype>
765 static_assert(n == m,
"Determinant only for square matrix");
767 return this->det_laplace();
769 return this->det_lu();
777template <
int n,
int m,
typename T,
typename Mtype>
782template <
int n,
int m,
typename T,
typename Mtype>
787template <
int n,
int m,
typename T,
typename Mtype>
810template <
int N,
typename T,
typename C,
811 std::enable_if_t<hila::is_complex_or_arithmetic<C>::value,
int> = 0>
815 auto tmul = c / (1 + c * trace(B));
817 return B - tmul * B.asVector() * B.asVector().transpose();
Array< n, m, T > conj(const Array< n, m, T > &arg)
Return conjugate Array.
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Array< n, m, T > sqrt(Array< n, m, T > a)
Square root.
Array< n, m, hila::arithmetic_type< T > > real(const Array< n, m, T > &arg)
Return real part of Array.
Define type DiagonalMatrix<n,T>
T e(const int i) const
Element access - e(i) gives diagonal element i.
DiagonalMatrix< n, T > sort(Vector< N, int > &permutation, hila::sort order=hila::sort::ascending) const
implement sort as casting to matrix
The main matrix type template Matrix_t. This is a base class type for "useful" types which are deriv...
void set_column(int c, const Vector< n, S > &v)
get column of a matrix
Vector< n, T > column(int c) const
Returns column vector as value at index c.
static constexpr int rows()
Define constant methods rows(), columns() - may be useful in template code.
static constexpr int columns()
Returns column length.
T det() const
determinant function - if matrix size is < 5, use Laplace, otherwise LU
Rtype dagger() const
Hermitian conjugate of matrix.
int eigen_hermitean(DiagonalMatrix< n, Et > &eigenvalues, Matrix_t< n, n, Mt, MT > &eigenvectors, enum hila::sort sorted=hila::sort::unsorted) const
Calculate eigenvalues and -vectors of an hermitean (or symmetric) matrix.
int svd_pivot(Matrix_t< n, n, Mt, MT > &_U, DiagonalMatrix< n, Et > &_D, Matrix_t< n, n, Mt, MT > &_V, enum hila::sort sorted=hila::sort::unsorted) const
Singular value decomposition: divide matrix A = U S V*, where U,V unitary and S diagonal matrix of re...
T e(const int i, const int j) const
Standard array indexing operation for matrices and vectors.
T det_laplace() const
Determinant of matrix, using Laplace method.
int svd(Matrix_t< n, n, Mt, MT > &_U, DiagonalMatrix< n, Et > &_D, Matrix_t< n, n, Mt, MT > &_V, enum hila::sort sorted=hila::sort::unsorted) const
Singular value decomposition: divide matrix A = U S V*, where U,V unitary and S diagonal matrix of re...
Mtype permute_columns(const Vector< m, int > &permutation) const
permute columns of Matrix
R dot(const Matrix< p, q, S > &rhs) const
Dot product.
T det_lu() const
following calculate the determinant of a square matrix det() is the generic interface,...
DiagonalMatrix< n, T > diagonal()
Return diagonal of square matrix.
hila::arithmetic_type< T > squarenorm() const
Calculate square norm - sum of squared elements.
Matrix class which defines matrix operations.
Complex< T > dagger(const Complex< T > &val)
Return dagger of Complex number.
T abs(const Complex< T > &a)
Return absolute value of Complex number.
constexpr T sqr(const T &arg)
Define convenience function sqr(), returning square of argument.
Definition of Matrix types.
auto invert_diagonal_plus_constant_matrix(const DiagonalMatrix< N, T > &D, const C c)
Implement hila::swap for gauge fields.
type to store the return value of eigen_hermitean(): {E, U} where E is nxn DiagonalMatrix containing ...
type to store the return combo of svd: {U, D, V} where U and V are nxn unitary / orthogonal,...