41 #ifndef BPP_NUMERIC_MATRIX_EIGENVALUE_H
42 #define BPP_NUMERIC_MATRIX_EIGENVALUE_H
46 #define TOST(i) static_cast<size_t>(i)
56 #include "../NumTools.h"
124 std::vector<Real>
d_;
125 std::vector<Real>
e_;
165 for (
size_t j = 0; j <
n_; j++)
172 for (
size_t i =
n_ - 1; i > 0; i--)
178 for (
size_t k = 0; k < i; ++k)
180 scale = scale + NumTools::abs<Real>(
d_[k]);
185 for (
size_t j = 0; j < i; ++j)
187 d_[j] =
V_(i - 1, j);
196 for (
size_t k = 0; k < i; ++k)
210 for (
size_t j = 0; j < i; ++j)
217 for (
size_t j = 0; j < i; ++j)
221 g =
e_[j] +
V_(j, j) * f;
222 for (
size_t k = j + 1; k <= i - 1; k++)
224 g +=
V_(k, j) *
d_[k];
225 e_[k] +=
V_(k, j) * f;
230 for (
size_t j = 0; j < i; ++j)
235 Real hh = f / (h + h);
236 for (
size_t j = 0; j < i; ++j)
240 for (
size_t j = 0; j < i; ++j)
244 for (
size_t k = j; k <= i - 1; ++k)
246 V_(k, j) -= (f *
e_[k] + g *
d_[k]);
248 d_[j] =
V_(i - 1, j);
257 for (
size_t i = 0; i <
n_ - 1; i++)
264 for (
size_t k = 0; k <= i; k++)
266 d_[k] =
V_(k, i + 1) / h;
268 for (
size_t j = 0; j <= i; j++)
271 for (
size_t k = 0; k <= i; k++)
273 g +=
V_(k, i + 1) *
V_(k, j);
275 for (
size_t k = 0; k <= i; k++)
277 V_(k, j) -= g *
d_[k];
281 for (
size_t k = 0; k <= i; k++)
286 for (
size_t j = 0; j <
n_; j++)
305 for (
size_t i = 1; i <
n_; i++)
313 Real eps = std::pow(2.0, -52.0);
314 for (
size_t l = 0; l <
n_; ++l)
318 tst1 = std::max(tst1, NumTools::abs<Real>(
d_[l]) + NumTools::abs<Real>(
e_[l]));
324 if (NumTools::abs<Real>(
e_[m]) <= eps * tst1)
344 Real p = (
d_[l + 1] - g) / (2.0 *
e_[l]);
345 Real r = hypot(p, 1.0);
350 d_[l] =
e_[l] / (p + r);
351 d_[l + 1] =
e_[l] * (p + r);
352 Real dl1 =
d_[l + 1];
354 for (
size_t i = l + 2; i <
n_; ++i)
366 Real el1 =
e_[l + 1];
370 for (
size_t ii = m; ii > l; --ii)
382 p = c *
d_[i] - s * g;
383 d_[i + 1] = h + s * (c * g + s *
d_[i]);
387 for (
size_t k = 0; k <
n_; k++)
390 V_(k, i + 1) = s *
V_(k, i) + c * h;
391 V_(k, i) = c *
V_(k, i) - s * h;
394 p = -s * s2 * c3 * el1 *
e_[l] / dl1;
400 while (NumTools::abs<Real>(
e_[l]) > eps * tst1);
408 for (
size_t i = 0;
n_ > 0 && i <
n_ - 1; i++)
412 for (
size_t j = i + 1; j <
n_; j++)
424 for (
size_t j = 0; j <
n_; j++)
446 size_t high =
n_ - 1;
448 for (
size_t m = low + 1; m <= high - 1; ++m)
453 for (
size_t i = m; i <= high; ++i)
455 scale = scale + NumTools::abs<Real>(
H_(i, m - 1));
462 for (
size_t i = high; i >= m; --i)
464 ort_[i] =
H_(i, m - 1) / scale;
478 for (
size_t j = m; j <
n_; ++j)
481 for (
size_t i = high; i >= m; --i)
486 for (
size_t i = m; i <= high; ++i)
492 for (
size_t i = 0; i <= high; ++i)
495 for (
size_t j = high; j >= m; --j)
500 for (
size_t j = m; j <= high; ++j)
506 H_(m, m - 1) = scale * g;
512 for (
size_t i = 0; i <
n_; i++)
514 for (
size_t j = 0; j <
n_; j++)
516 V_(i, j) = (i == j ? 1.0 : 0.0);
520 for (
size_t m = high - 1; m >= low + 1; --m)
522 if (
H_(m, m - 1) != 0.0)
524 for (
size_t i = m + 1; i <= high; ++i)
528 for (
size_t j = m; j <= high; ++j)
531 for (
size_t i = m; i <= high; i++)
536 g = (g /
ort_[m]) /
H_(m, m - 1);
537 for (
size_t i = m; i <= high; ++i)
550 void cdiv(Real xr, Real xi, Real yr, Real yi)
553 if (NumTools::abs<Real>(yr) > NumTools::abs<Real>(yi))
557 cdivr = (xr + r * xi) / d;
558 cdivi = (xi - r * xr) / d;
564 cdivr = (r * xr + xi) / d;
565 cdivi = (r * xi - xr) / d;
581 int nn =
static_cast<int>(this->
n_);
585 Real eps = std::pow(2.0, -52.0);
587 Real p = 0, q = 0, r = 0, s = 0, z = 0, t, w, x, y;
592 for (
int i = 0; i < nn; i++)
594 if ((i < low) || (i > high))
599 for (
int j = std::max(i - 1, 0); j < nn; j++)
601 norm = norm + NumTools::abs<Real>(
H_(
TOST(i),
TOST(j)));
615 s = NumTools::abs<Real>(
H_(
TOST(l - 1),
TOST(l - 1))) + NumTools::abs<Real>(
H_(
TOST(l),
TOST(l)));
620 if (NumTools::abs<Real>(
H_(
TOST(l),
TOST(l - 1))) < eps * s)
645 z = sqrt(NumTools::abs<Real>(q));
671 s = NumTools::abs<Real>(x) + NumTools::abs<Real>(z);
674 r = sqrt(p * p + q * q);
680 for (
int j = n - 1; j < nn; j++)
689 for (
int i = 0; i <= n; i++)
698 for (
int i = low; i <= high; i++)
737 for (
int i = low; i <= n; i++)
741 s = NumTools::abs<Real>(
H_(
TOST(n),
TOST(n - 1))) + NumTools::abs<Real>(
H_(
TOST(n - 1),
TOST(n - 2)));
758 s = x - w / ((y - x) / 2.0 + s);
759 for (
int i = low; i <= n; i++)
781 s = NumTools::abs<Real>(p) + NumTools::abs<Real>(q) + NumTools::abs<Real>(r);
789 if (NumTools::abs<Real>(
H_(
TOST(m),
TOST(m - 1))) * (NumTools::abs<Real>(q) + NumTools::abs<Real>(r)) <
790 eps * (NumTools::abs<Real>(p) * (NumTools::abs<Real>(
H_(
TOST(m - 1),
TOST(m - 1))) + NumTools::abs<Real>(z) +
791 NumTools::abs<Real>(
H_(
TOST(m + 1),
TOST(m + 1))))))
798 for (
int i = m + 2; i <= n; i++)
809 for (
int k = m; k <= n - 1; k++)
811 int notlast = (k != n - 1);
816 r = (notlast ?
H_(
TOST(k + 2),
TOST(k - 1)) : 0.0);
817 x = NumTools::abs<Real>(p) + NumTools::abs<Real>(q) + NumTools::abs<Real>(r);
829 s = sqrt(p * p + q * q + r * r);
853 for (
int j = k; j < nn; j++)
867 for (
int i = 0; i <= std::min(n, k + 3); i++)
881 for (
int i = low; i <= high; i++)
904 for (n = nn - 1; n >= 0; n--)
915 for (
int i = n - 1; i >= 0; i--)
919 for (
int j = l; j <= n; j++)
949 t = (x * s - z * r) / q;
951 if (NumTools::abs<Real>(x) > NumTools::abs<Real>(z))
963 t = NumTools::abs<Real>(
H_(
TOST(i),
TOST(n)));
964 if ((eps * t) * t > 1)
966 for (
int j = i; j <= n; j++)
982 if (NumTools::abs<Real>(
H_(
TOST(n),
TOST(n - 1))) > NumTools::abs<Real>(
H_(
TOST(n - 1),
TOST(n))))
995 for (
int i = n - 2; i >= 0; i--)
1000 for (
int j = l; j <= n; j++)
1018 cdiv(-ra, -sa, w, q);
1029 vi = (
d_[
TOST(i)] - p) * 2.0 * q;
1030 if ((vr == 0.0) && (vi == 0.0))
1032 vr = eps * norm * (NumTools::abs<Real>(w) + NumTools::abs<Real>(q) +
1033 NumTools::abs<Real>(x) + NumTools::abs<Real>(y) + NumTools::abs<Real>(z));
1035 cdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi);
1038 if (NumTools::abs<Real>(x) > (NumTools::abs<Real>(z) + NumTools::abs<Real>(q)))
1052 t = std::max(NumTools::abs<Real>(
H_(
TOST(i),
TOST(n - 1))), NumTools::abs<Real>(
H_(
TOST(i),
TOST(n))));
1053 if ((eps * t) * t > 1)
1055 for (
int j = i; j <= n; j++)
1068 for (
int i = 0; i < nn; i++)
1070 if (i < low || i > high)
1072 for (
int j = i; j < nn; j++)
1081 for (
int j = nn - 1; j >= low; j--)
1083 for (
int i = low; i <= high; i++)
1086 for (
int k = low; k <= std::min(j, high); k++)
1105 n_(A.getNumberOfColumns()),
1127 for (
size_t i = 0; i <
n_; i++)
1129 for (
size_t j = 0; j <
n_; j++)
1146 for (
size_t j = 0; j <
n_; j++)
1148 for (
size_t i = 0; i <
n_; i++)
1219 for (
size_t i = 0; i <
n_; i++)
1221 for (
size_t j = 0; j <
n_; j++)
1228 D_(i, i + 1) =
e_[i];
1232 D_(i, i - 1) =
e_[i];
Computes eigenvalues and eigenvectors of a real (non-complex) matrix.
void tql2()
Symmetric tridiagonal QL algorithm.
EigenValue(const Matrix< Real > &A)
Check for symmetry, then construct the eigenvalue decomposition.
size_t n_
Row and column dimension (square matrix).
const RowMatrix< Real > & getV() const
Return the eigenvector matrix.
const RowMatrix< Real > & getD() const
Computes the block diagonal eigenvalue matrix.
std::vector< Real > ort_
Working storage for nonsymmetric algorithm.
bool issymmetric_
Tell if the matrix is symmetric.
const std::vector< Real > & getImagEigenValues() const
Return the imaginary parts of the eigenvalues in parameter e.
RowMatrix< Real > H_
Matrix for internal storage of nonsymmetric Hessenberg form.
RowMatrix< Real > D_
Matrix for internal storage of eigen values in a matrix form.
const std::vector< Real > & getRealEigenValues() const
Return the real parts of the eigenvalues.
void cdiv(Real xr, Real xi, Real yr, Real yi)
RowMatrix< Real > V_
Array for internal storage of eigenvectors.
void tred2()
Symmetric Householder reduction to tridiagonal form.
void orthes()
Nonsymmetric reduction to Hessenberg form.
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
The matrix template interface.
void resize(size_t nRows, size_t nCols)
Resize the matrix.
std::string toString(T t)
General template method to convert to a string.