/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/common/quadrature/diagonalization.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/common/quadrature/diagonalization.hh Source File
DiFfRG
diagonalization.hh
Go to the documentation of this file.
1#pragma once
2
3// DiFfRG
5
6// C++ standard library
7#include <cmath>
8#include <limits>
9
10namespace DiFfRG
11{
30 template <typename T>
31 void diagonalize_tridiagonal_symmetric_matrix(std::vector<T> &d, std::vector<T> &e, std::vector<T> &z)
32 {
33 const int n = d.size();
34 if (n == 1) return;
35 if ((int)e.size() != n) throw std::runtime_error("The size of e must be d.size() for the purpose of this routine.");
36 if ((int)z.size() != n) throw std::runtime_error("The size of z must be d.size().");
37 T b = 0;
38 T c = 0;
39 T f = 0;
40 T g = 0;
41 int i = 0;
42 int ii = 0;
43 int itn = 30;
44 int j = 0;
45 int k = 0;
46 int l = 0;
47 int m = 0;
48 int mml = 0;
49 T p = 0;
50 T prec = 0;
51 T r = 0;
52 T s = 0;
53
54 prec = std::numeric_limits<T>::epsilon();
55
56 using std::fabs, DiFfRG::sign;
57
58 e[n - 1] = 0.0;
59
60 for (l = 1; l <= n; ++l) {
61 j = 0;
62 for (;;) {
63 for (m = l; m <= n; ++m) {
64 if (m == n) break;
65 if (fabs(e[m - 1]) <= prec * (fabs(d[m - 1]) + fabs(d[m]))) break;
66 }
67
68 p = d[l - 1];
69 if (m == l) break;
70
71 if (itn <= j) {
72 std::cerr << "\n";
73 std::cerr << "IMTQLX - Fatal error!\n";
74 std::cerr << " Iteration limit exceeded\n";
75 throw std::runtime_error("IMTQLX - Fatal error!");
76 }
77
78 j = j + 1;
79 g = (d[l] - p) / (2.0 * e[l - 1]);
80 r = sqrt(g * g + 1.0);
81 g = d[m - 1] - p + e[l - 1] / (g + fabs(r) * sign(g));
82 s = 1.0;
83 c = 1.0;
84 p = 0.0;
85 mml = m - l;
86
87 for (ii = 1; ii <= mml; ++ii) {
88 i = m - ii;
89 f = s * e[i - 1];
90 b = c * e[i - 1];
91
92 if (fabs(g) <= fabs(f)) {
93 c = g / f;
94 r = sqrt(c * c + 1.0);
95 e[i] = f * r;
96 s = 1.0 / r;
97 c = c * s;
98 } else {
99 s = f / g;
100 r = sqrt(s * s + 1.0);
101 e[i] = g * r;
102 c = 1.0 / r;
103 s = s * c;
104 }
105 g = d[i] - p;
106 r = (d[i - 1] - g) * s + 2.0 * c * b;
107 p = s * r;
108 d[i] = g + p;
109 g = c * r - b;
110 f = z[i];
111 z[i] = s * z[i - 1] + c * f;
112 z[i - 1] = c * z[i - 1] - s * f;
113 }
114 d[l - 1] = d[l - 1] - p;
115 e[l - 1] = g;
116 e[m - 1] = 0.0;
117 }
118 }
119
120 // Sorting.
121 for (ii = 2; ii <= m; ++ii) {
122 i = ii - 1;
123 k = i;
124 p = d[i - 1];
125
126 for (j = ii; j <= n; ++j) {
127 if (d[j - 1] < p) {
128 k = j;
129 p = d[j - 1];
130 }
131 }
132
133 if (k != i) {
134 d[k - 1] = d[i - 1];
135 d[i - 1] = p;
136 p = z[i - 1];
137 z[i - 1] = z[k - 1];
138 z[k - 1] = p;
139 }
140 }
141 }
142} // namespace DiFfRG
Definition complex_math.hh:10
constexpr KOKKOS_INLINE_FUNCTION auto sign(const NumberType x)
A compile-time evaluatable sign function.
Definition math.hh:149
void diagonalize_tridiagonal_symmetric_matrix(std::vector< T > &d, std::vector< T > &e, std::vector< T > &z)
Diagonalizes a symmetric tridiagonal matrix.
Definition diagonalization.hh:31