DiFfRG
Loading...
Searching...
No Matches
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 <cstdlib>
9#include <cstring>
10#include <ctime>
11#include <iostream>
12#include <limits>
13
14namespace DiFfRG
15{
34 template <typename T>
35 void diagonalize_tridiagonal_symmetric_matrix(std::vector<T> &d, std::vector<T> &e, std::vector<T> &z)
36 {
37 const int n = d.size();
38 if (n == 1) return;
39 if ((int)e.size() != n) throw std::runtime_error("The size of e must be d.size() for the purpose of this routine.");
40 if ((int)z.size() != n) throw std::runtime_error("The size of z must be d.size().");
41 T b;
42 T c;
43 T f;
44 T g;
45 int i;
46 int ii;
47 int itn = 30;
48 int j;
49 int k;
50 int l;
51 int m;
52 int mml;
53 T p;
54 T prec;
55 T r;
56 T s;
57
58 prec = std::numeric_limits<T>::epsilon();
59
60 using std::fabs, DiFfRG::sign;
61
62 e[n - 1] = 0.0;
63
64 for (l = 1; l <= n; ++l) {
65 j = 0;
66 for (;;) {
67 for (m = l; m <= n; ++m) {
68 if (m == n) break;
69 if (fabs(e[m - 1]) <= prec * (fabs(d[m - 1]) + fabs(d[m]))) break;
70 }
71
72 p = d[l - 1];
73 if (m == l) break;
74
75 if (itn <= j) {
76 std::cerr << "\n";
77 std::cerr << "IMTQLX - Fatal error!\n";
78 std::cerr << " Iteration limit exceeded\n";
79 throw std::runtime_error("IMTQLX - Fatal error!");
80 }
81
82 j = j + 1;
83 g = (d[l] - p) / (2.0 * e[l - 1]);
84 r = sqrt(g * g + 1.0);
85 g = d[m - 1] - p + e[l - 1] / (g + fabs(r) * sign(g));
86 s = 1.0;
87 c = 1.0;
88 p = 0.0;
89 mml = m - l;
90
91 for (ii = 1; ii <= mml; ++ii) {
92 i = m - ii;
93 f = s * e[i - 1];
94 b = c * e[i - 1];
95
96 if (fabs(g) <= fabs(f)) {
97 c = g / f;
98 r = sqrt(c * c + 1.0);
99 e[i] = f * r;
100 s = 1.0 / r;
101 c = c * s;
102 } else {
103 s = f / g;
104 r = sqrt(s * s + 1.0);
105 e[i] = g * r;
106 c = 1.0 / r;
107 s = s * c;
108 }
109 g = d[i] - p;
110 r = (d[i - 1] - g) * s + 2.0 * c * b;
111 p = s * r;
112 d[i] = g + p;
113 g = c * r - b;
114 f = z[i];
115 z[i] = s * z[i - 1] + c * f;
116 z[i - 1] = c * z[i - 1] - s * f;
117 }
118 d[l - 1] = d[l - 1] - p;
119 e[l - 1] = g;
120 e[m - 1] = 0.0;
121 }
122 }
123
124 // Sorting.
125 for (ii = 2; ii <= m; ++ii) {
126 i = ii - 1;
127 k = i;
128 p = d[i - 1];
129
130 for (j = ii; j <= n; ++j) {
131 if (d[j - 1] < p) {
132 k = j;
133 p = d[j - 1];
134 }
135 }
136
137 if (k != i) {
138 d[k - 1] = d[i - 1];
139 d[i - 1] = p;
140 p = z[i - 1];
141 z[i - 1] = z[k - 1];
142 z[k - 1] = p;
143 }
144 }
145 }
146} // namespace DiFfRG
Definition complex_math.hh:14
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:35
constexpr __forceinline__ __host__ __device__ auto sign(const NumberType x)
A compile-time evaluatable sign function.
Definition math.hh:141