5 #ifndef BPP_NUMERIC_MATRIX_EIGENVALUE_H 6 #define BPP_NUMERIC_MATRIX_EIGENVALUE_H 9 #define TOST(i) static_cast<size_t>(i) 19 #include "../NumTools.h" 128 for (
size_t j = 0; j <
n_; j++)
130 d_[j] =
V_(n_ - 1, j);
135 for (
size_t i = n_ - 1; i > 0; i--)
141 for (
size_t k = 0; k < i; ++k)
143 scale = scale + NumTools::abs<Real>(d_[k]);
148 for (
size_t j = 0; j < i; ++j)
150 d_[j] =
V_(i - 1, j);
159 for (
size_t k = 0; k < i; ++k)
173 for (
size_t j = 0; j < i; ++j)
180 for (
size_t j = 0; j < i; ++j)
184 g = e_[j] +
V_(j, j) * f;
185 for (
size_t k = j + 1; k <= i - 1; k++)
187 g +=
V_(k, j) * d_[k];
188 e_[k] +=
V_(k, j) * f;
193 for (
size_t j = 0; j < i; ++j)
198 Real hh = f / (h + h);
199 for (
size_t j = 0; j < i; ++j)
203 for (
size_t j = 0; j < i; ++j)
207 for (
size_t k = j; k <= i - 1; ++k)
209 V_(k, j) -= (f * e_[k] + g * d_[k]);
211 d_[j] =
V_(i - 1, j);
220 for (
size_t i = 0; i < n_ - 1; i++)
222 V_(n_ - 1, i) =
V_(i, i);
227 for (
size_t k = 0; k <= i; k++)
229 d_[k] =
V_(k, i + 1) / h;
231 for (
size_t j = 0; j <= i; j++)
234 for (
size_t k = 0; k <= i; k++)
236 g +=
V_(k, i + 1) *
V_(k, j);
238 for (
size_t k = 0; k <= i; k++)
240 V_(k, j) -= g * d_[k];
244 for (
size_t k = 0; k <= i; k++)
249 for (
size_t j = 0; j <
n_; j++)
251 d_[j] =
V_(n_ - 1, j);
254 V_(n_ - 1, n_ - 1) = 1.0;
268 for (
size_t i = 1; i <
n_; i++)
276 Real eps = std::pow(2.0, -52.0);
277 for (
size_t l = 0; l <
n_; ++l)
281 tst1 = std::max(tst1, NumTools::abs<Real>(d_[l]) + NumTools::abs<Real>(e_[l]));
287 if (NumTools::abs<Real>(e_[m]) <= eps * tst1)
307 Real p = (d_[l + 1] - g) / (2.0 * e_[l]);
308 Real r = hypot(p, 1.0);
313 d_[l] = e_[l] / (p + r);
314 d_[l + 1] = e_[l] * (p + r);
315 Real dl1 = d_[l + 1];
317 for (
size_t i = l + 2; i <
n_; ++i)
329 Real el1 = e_[l + 1];
333 for (
size_t ii = m; ii > l; --ii)
345 p = c * d_[i] - s * g;
346 d_[i + 1] = h + s * (c * g + s * d_[i]);
350 for (
size_t k = 0; k <
n_; k++)
353 V_(k, i + 1) = s *
V_(k, i) + c * h;
354 V_(k, i) = c *
V_(k, i) - s * h;
357 p = -s * s2 * c3 * el1 * e_[l] / dl1;
363 while (NumTools::abs<Real>(e_[l]) > eps * tst1);
371 for (
size_t i = 0; n_ > 0 && i < n_ - 1; i++)
375 for (
size_t j = i + 1; j <
n_; j++)
387 for (
size_t j = 0; j <
n_; j++)
409 size_t high = n_ - 1;
411 for (
size_t m = low + 1; m <= high - 1; ++m)
416 for (
size_t i = m; i <= high; ++i)
418 scale = scale + NumTools::abs<Real>(
H_(i, m - 1));
425 for (
size_t i = high; i >= m; --i)
427 ort_[i] =
H_(i, m - 1) / scale;
428 h += ort_[i] * ort_[i];
436 ort_[m] = ort_[m] - g;
441 for (
size_t j = m; j <
n_; ++j)
444 for (
size_t i = high; i >= m; --i)
446 f += ort_[i] *
H_(i, j);
449 for (
size_t i = m; i <= high; ++i)
451 H_(i, j) -= f * ort_[i];
455 for (
size_t i = 0; i <= high; ++i)
458 for (
size_t j = high; j >= m; --j)
460 f += ort_[j] *
H_(i, j);
463 for (
size_t j = m; j <= high; ++j)
465 H_(i, j) -= f * ort_[j];
468 ort_[m] = scale * ort_[m];
469 H_(m, m - 1) = scale * g;
475 for (
size_t i = 0; i <
n_; i++)
477 for (
size_t j = 0; j <
n_; j++)
479 V_(i, j) = (i == j ? 1.0 : 0.0);
483 for (
size_t m = high - 1; m >= low + 1; --m)
485 if (
H_(m, m - 1) != 0.0)
487 for (
size_t i = m + 1; i <= high; ++i)
489 ort_[i] =
H_(i, m - 1);
491 for (
size_t j = m; j <= high; ++j)
494 for (
size_t i = m; i <= high; i++)
496 g += ort_[i] *
V_(i, j);
499 g = (g / ort_[m]) /
H_(m, m - 1);
500 for (
size_t i = m; i <= high; ++i)
502 V_(i, j) += g * ort_[i];
513 void cdiv(Real xr, Real xi, Real yr, Real yi)
516 if (NumTools::abs<Real>(yr) > NumTools::abs<Real>(yi))
520 cdivr = (xr + r * xi) / d;
521 cdivi = (xi - r * xr) / d;
527 cdivr = (r * xr + xi) / d;
528 cdivi = (r * xi - xr) / d;
544 int nn =
static_cast<int>(this->
n_);
548 Real eps = std::pow(2.0, -52.0);
550 Real p = 0, q = 0, r = 0, s = 0, z = 0, t, w, x, y;
555 for (
int i = 0; i < nn; i++)
557 if ((i < low) || (i > high))
562 for (
int j = std::max(i - 1, 0); j < nn; j++)
564 norm = norm + NumTools::abs<Real>(
H_(
TOST(i),
TOST(j)));
578 s = NumTools::abs<Real>(
H_(
TOST(l - 1),
TOST(l - 1))) + NumTools::abs<Real>(
H_(
TOST(l),
TOST(l)));
583 if (NumTools::abs<Real>(
H_(
TOST(l),
TOST(l - 1))) < eps * s)
608 z = sqrt(NumTools::abs<Real>(q));
625 d_[
TOST(n - 1)] = x + z;
629 d_[
TOST(n)] = x - w / z;
631 e_[
TOST(n - 1)] = 0.0;
634 s = NumTools::abs<Real>(x) + NumTools::abs<Real>(z);
637 r = sqrt(p * p + q * q);
643 for (
int j = n - 1; j < nn; j++)
652 for (
int i = 0; i <= n; i++)
661 for (
int i = low; i <= high; i++)
672 d_[
TOST(n - 1)] = x + p;
700 for (
int i = low; i <= n; i++)
704 s = NumTools::abs<Real>(
H_(
TOST(n),
TOST(n - 1))) + NumTools::abs<Real>(
H_(
TOST(n - 1),
TOST(n - 2)));
721 s = x - w / ((y - x) / 2.0 + s);
722 for (
int i = low; i <= n; i++)
744 s = NumTools::abs<Real>(p) + NumTools::abs<Real>(q) + NumTools::abs<Real>(r);
752 if (NumTools::abs<Real>(
H_(
TOST(m),
TOST(m - 1))) * (NumTools::abs<Real>(q) + NumTools::abs<Real>(r)) <
753 eps * (NumTools::abs<Real>(p) * (NumTools::abs<Real>(
H_(
TOST(m - 1),
TOST(m - 1))) + NumTools::abs<Real>(z) +
754 NumTools::abs<Real>(
H_(
TOST(m + 1),
TOST(m + 1))))))
761 for (
int i = m + 2; i <= n; i++)
772 for (
int k = m; k <= n - 1; k++)
774 int notlast = (k != n - 1);
779 r = (notlast ?
H_(
TOST(k + 2),
TOST(k - 1)) : 0.0);
780 x = NumTools::abs<Real>(p) + NumTools::abs<Real>(q) + NumTools::abs<Real>(r);
792 s = sqrt(p * p + q * q + r * r);
816 for (
int j = k; j < nn; j++)
830 for (
int i = 0; i <= std::min(n, k + 3); i++)
844 for (
int i = low; i <= high; i++)
867 for (n = nn - 1; n >= 0; n--)
878 for (
int i = n - 1; i >= 0; i--)
882 for (
int j = l; j <= n; j++)
886 if (e_[
TOST(i)] < 0.0)
894 if (e_[
TOST(i)] == 0.0)
912 t = (x * s - z * r) / q;
914 if (NumTools::abs<Real>(x) > NumTools::abs<Real>(z))
926 t = NumTools::abs<Real>(
H_(
TOST(i),
TOST(n)));
927 if ((eps * t) * t > 1)
929 for (
int j = i; j <= n; j++)
945 if (NumTools::abs<Real>(
H_(
TOST(n),
TOST(n - 1))) > NumTools::abs<Real>(
H_(
TOST(n - 1),
TOST(n))))
958 for (
int i = n - 2; i >= 0; i--)
963 for (
int j = l; j <= n; j++)
970 if (e_[
TOST(i)] < 0.0)
979 if (e_[
TOST(i)] == 0)
981 cdiv(-ra, -sa, w, q);
991 vr = (d_[
TOST(i)] - p) * (d_[
TOST(i)] - p) + e_[
TOST(i)] * e_[
TOST(i)] - q * q;
992 vi = (d_[
TOST(i)] - p) * 2.0 * q;
993 if ((vr == 0.0) && (vi == 0.0))
995 vr = eps * norm * (NumTools::abs<Real>(w) + NumTools::abs<Real>(q) +
996 NumTools::abs<Real>(x) + NumTools::abs<Real>(y) + NumTools::abs<Real>(z));
998 cdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi);
1001 if (NumTools::abs<Real>(x) > (NumTools::abs<Real>(z) + NumTools::abs<Real>(q)))
1015 t = std::max(NumTools::abs<Real>(
H_(
TOST(i),
TOST(n - 1))), NumTools::abs<Real>(
H_(
TOST(i),
TOST(n))));
1016 if ((eps * t) * t > 1)
1018 for (
int j = i; j <= n; j++)
1031 for (
int i = 0; i < nn; i++)
1033 if (i < low || i > high)
1035 for (
int j = i; j < nn; j++)
1044 for (
int j = nn - 1; j >= low; j--)
1046 for (
int i = low; i <= high; i++)
1049 for (
int k = low; k <= std::min(j, high); k++)
1068 n_(A.getNumberOfColumns()),
1080 for (
size_t j = 0; (j <
n_) && issymmetric_; j++)
1082 for (
size_t i = 0; (i <
n_) && issymmetric_; i++)
1084 issymmetric_ = (A(i, j) == A(j, i));
1090 for (
size_t i = 0; i <
n_; i++)
1092 for (
size_t j = 0; j <
n_; j++)
1109 for (
size_t j = 0; j <
n_; j++)
1111 for (
size_t i = 0; i <
n_; i++)
1182 for (
size_t i = 0; i <
n_; i++)
1184 for (
size_t j = 0; j <
n_; j++)
1191 D_(i, i + 1) = e_[i];
1195 D_(i, i - 1) = e_[i];
1202 #endif // BPP_NUMERIC_MATRIX_EIGENVALUE_H The matrix template interface.
std::vector< Real > ort_
Working storage for nonsymmetric algorithm.
RowMatrix< Real > V_
Array for internal storage of eigenvectors.
const RowMatrix< Real > & getD() const
Computes the block diagonal eigenvalue matrix.
const RowMatrix< Real > & getV() const
Return the eigenvector matrix.
void orthes()
Nonsymmetric reduction to Hessenberg form.
void resize(size_t nRows, size_t nCols)
Resize the matrix.
Computes eigenvalues and eigenvectors of a real (non-complex) matrix.
const std::vector< Real > & getImagEigenValues() const
Return the imaginary parts of the eigenvalues in parameter e.
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
void tql2()
Symmetric tridiagonal QL algorithm.
const std::vector< Real > & getRealEigenValues() const
Return the real parts of the eigenvalues.
EigenValue(const Matrix< Real > &A)
Check for symmetry, then construct the eigenvalue decomposition.
bool issymmetric_
Tell if the matrix is symmetric.
RowMatrix< Real > D_
Matrix for internal storage of eigen values in a matrix form.
std::string toString(T t)
General template method to convert to a string.
void tred2()
Symmetric Householder reduction to tridiagonal form.
size_t n_
Row and column dimension (square matrix).
void cdiv(Real xr, Real xi, Real yr, Real yi)
RowMatrix< Real > H_
Matrix for internal storage of nonsymmetric Hessenberg form.