1 #ifndef CLASSIC_FComplexEigen_HH
2 #define CLASSIC_FComplexEigen_HH
73 int &low,
int &high,
double scale[N]);
75 void balbak(
int low,
int high,
const double scale[N]);
78 int j,
int m,
int low,
int high);
80 int hqr(
FMatrix<complex<double>, N, N> &,
int low,
int high);
82 int hqr2(
FMatrix<complex<double>, N, N> &,
int low,
int high,
83 complex<double> ort[N]);
86 int high, complex<double> ort[N]);
104 inline double abssum(complex<double> a) {
118 lambda(rhs.lambda), vectors(rhs.vectors)
125 lambda(), vectors() {
126 for(
int i = 0; i < N; ++i)
vectors(i, i) = 1.0;
131 balance(copy, low, upp, scale);
133 complex<double> ort[N];
134 orthes(copy, low, upp, ort);
137 if(
hqr2(copy, low, upp, ort) != 0) {
139 "Unable to find all eigenvalues.");
144 if(
hqr(copy, low, upp) != 0) {
146 "Unable to find all eigenvalues.");
172 int &upp,
double scale[N])
211 for(
int j = upp; ; j--) {
212 for(
int i = 0; i <= upp; i++) {
213 if(i != j && copy[j][i] != 0.0)
goto next_row;
217 exchange(copy, j, upp, low, upp);
218 scale[upp] = double(j);
227 for(
int j = low; ; j++) {
228 for(
int i = low; i <= upp; i++) {
229 if(i != j && copy[i][j] != 0.0)
goto next_column;
233 exchange(copy, j, low, low, upp);
234 scale[low] = double(j);
243 for(
int i = low; i <= upp; i++) scale[i] = 1.0;
246 const double radix = 16.;
247 const double b2 = radix * radix;
254 for(
int i = low; i <= upp; i++) {
258 for(
int j = low; j <= upp; j++) {
260 c = c + abssum(copy[j][i]);
261 r = r + abssum(copy[i][j]);
266 if(c != 0.0 && r != 0.0) {
267 double g = r / radix;
284 if((c + r) / f < s * .95) {
288 for(
int j = low; j <= N; j++) copy[i][j] *= g;
289 for(
int j = 1; j <= upp; j++) copy[j][i] *= f;
324 for(
int i = low; i <= upp; i++) {
326 for(
int j = 0; j < N; j++) vectors[i][j] *= s;
332 for(
int i = low; i-- > 0;) {
333 int k = int(scale[i]);
334 if(k != i) vectors.swapRows(k, i);
337 for(
int i = upp + 1; i < N; i++) {
338 int k = int(scale[i]);
339 if(k != i) vectors.swapRows(k, i);
348 (
FMatrix<complex<double>, N, N> ©,
int j,
int m,
int low,
int upp) {
350 for(
int i = 0; i <= upp; i++) swap(copy[i][j], copy[i][m]);
351 for(
int i = low; i <= N; i++) swap(copy[j][i], copy[m][i]);
391 complex<double> s, x, y, z;
394 for(
int i = low + 1; i <= upp; i++) {
395 if(
imag(h[i][i-1]) != 0.0) {
397 y = h[i][i-1] / norm;
398 h[i][i-1] = complex<double>(norm, 0.0);
399 for(
int j = i; j <= upp; j++) h[i][j] =
conj(y) * h[i][j];
400 int ll = (upp <= i) ? upp : (i + 1);
401 for(
int j = low; j <= ll; j++) h[j][i] = y * h[j][i];
406 for(
int i = 0; i < N; i++) {
407 if(i < low || i < upp) lambda[i] = h[i][i];
411 complex<double> t = 0.0;
414 for(
int en = upp + 1; en-- > low;) {
420 for(l = en; l > low; l--) {
422 tst1 = abssum(h[l-1][l-1]) + abssum(h[l][l]);
424 if(tst2 == tst1)
break;
431 if(itn == 0)
return (en + 1);
433 if(its != 10 && its != 20) {
435 x = h[en-1][en] *
real(h[en][en-1]);
438 y = (h[en-1][en-1] - s) / 2.0;
452 for(
int i = low; i <= en; i++) h[i][i] -= s;
458 for(
int i = l + 1; i <= en; i++) {
459 double sr =
real(h[i][i-1]);
460 double norm = hypot(
std::abs(h[i-1][i-1]), sr);
461 lambda[i-1] = x = h[i-1][i-1] / norm;
463 double fi = sr / norm;
464 h[i][i-1] = complex<double>(0.0, fi);
466 for(
int j = i; j <= en; j++) {
469 h[i-1][j] =
conj(x) * y + fi * z;
470 h[i][j] = x * z - fi * y;
474 double si =
imag(h[en][en]);
478 s = h[en][en] / norm;
483 for(
int j = l + 1; j <= en; j++) {
484 double fi =
imag(h[j][j-1]);
487 for(
int i = l; i < j; i++) {
490 h[i][j-1] = x * y + fi * z;
491 h[i][j] =
conj(x) * z - fi * y;
494 double yr =
real(h[j][j-1]);
496 h[j][j-1] =
real(x) * yr + fi *
real(z);
497 h[j][j] =
conj(x) * z - fi * yr;
501 for(
int i = l; i <= en; i++) h[i][en] *= s;
506 lambda[en] = h[en][en] + t;
516 int upp, complex<double> ort[N])
562 complex<double> s, x, y, z;
566 for(
int i = upp - 1; i > low; i--) {
567 if(ort[i] != 0.0 && h[i][i-1] != 0.0) {
569 double norm =
real(h[i][i-1]) *
real(ort[i]) +
572 for(
int k = i + 1; k <= upp; k++) ort[k] = h[k][i-1];
574 for(
int j = i; j <= upp; j++) {
576 for(
int k = i; k <= upp; k++) s +=
conj(ort[k]) * vectors[k][j];
578 for(
int k = i; k <= upp; k++) vectors[k][j] += s * ort[k];
584 for(
int i = low + 1; i <= upp; i++) {
585 if(
imag(h[i][i-1]) != 0.0) {
587 y = h[i][i-1] / norm;
589 for(
int j = i; j < N; j++) h[i][j] =
conj(y) * h[i][j];
590 int ll = (upp <= i) ? upp : (i + 1);
591 for(
int j = 0; j <= ll; j++) h[j][i] = y * h[j][i];
592 for(
int j = low; j <= upp; j++) vectors[j][i] = y * vectors[j][i];
597 for(
int i = 0; i < N; i++) {
598 if(i < low || i > upp) lambda[i] = h[i][i];
601 complex<double> t = 0.0;
605 for(
int en = upp + 1; en-- > low;) {
611 for(l = en; l > low; l--) {
613 tst1 = abssum(h[l-1][l-1]) + abssum(h[l][l]);
615 if(tst2 == tst1)
break;
621 if(itn == 0)
return (en + 1);
623 if(its != 10 && its != 20) {
626 x = h[en-1][en] *
real(h[en][en-1]);
629 y = (h[en-1][en-1] - s) / 2.0;
643 for(
int i = low; i <= en; i++) h[i][i] -= s;
649 for(
int i = l + 1; i <= en; i++) {
650 double sr =
real(h[i][i-1]);
651 double norm = hypot(
std::abs(h[i-1][i-1]), sr);
652 lambda[i-1] = x = h[i-1][i-1] / norm;
654 double fi = sr / norm;
655 h[i][i-1] = complex<double>(0.0, fi);
657 for(
int j = i; j < N; j++) {
660 h[i-1][j] =
conj(x) * y + fi * z;
661 h[i][j] = x * z - fi * y;
665 double si =
imag(h[en][en]);
669 s = h[en][en] / norm;
671 for(
int j = en + 1; j < N; j++) h[en][j] *=
conj(s);
675 for(
int j = l + 1; j <= en; j++) {
677 double fi =
imag(h[j][j-1]);
679 for(
int i = 0; i < j; i++) {
682 h[i][j-1] = x * y + fi * z;
683 h[i][j] =
conj(x) * z - fi * y;
686 double yr =
real(h[j][j-1]);
688 h[j][j-1] =
real(x) * yr + fi *
real(z);
689 h[j][j] =
conj(x) * z - fi * yr;
691 for(
int i = low; i <= upp; i++) {
694 vectors[i][j-1] = x * y + fi * z;
695 vectors[i][j] =
conj(x) * z - fi * y;
700 for(
int i = 0; i <= en; i++) h[i][en] *= s;
701 for(
int i = low; i <= upp; i++) vectors[i][en] *= s;
707 lambda[en] = h[en][en];
714 for(
int i = 0; i < N; i++) {
715 for(
int j = i; j < N; j++) {
716 double temp = abssum(h[i][j]);
717 if(temp > norm) norm = temp;
721 if(N == 1 || norm == 0.0)
return 0;
723 for(
int en = N - 1; en > 0; en--) {
727 for(
int i = en; i-- > 0;) {
729 for(
int j = i + 1; j <= en; j++) z += h[i][j] * h[j][en];
739 }
while(tst2 > norm);
747 double temp = abssum(h[i][en]);
751 double tst2 = tst1 + 1.0 / tst1;
754 for(
int j = i; j <= en; j++) h[j][en] /= temp;
761 for(
int i = 0; i < N; i++) {
762 if(i < low || i > upp) {
763 for(
int j = i; j <= N; j++) vectors[i][j] = h[i][j];
768 for(
int j = N; j-- > low;) {
769 int m = (j < upp) ? j : upp;
771 for(
int i = low; i <= upp; i++) {
773 for(
int k = low; k <= m; k++) z += vectors[i][k] * h[k][j];
784 int upp, complex<double> ort[N])
809 for(
int m = low + 1; m < upp; m++) {
815 for(
int i = m; i <= upp; i++) scale += abssum(copy[i][m-1]);
818 for(
int i = upp + 1; i-- > m;) {
819 ort[i] = copy[i][m-1] / scale;
832 copy[m][m-1] = scale;
836 for(
int j = m; j < N; j++) {
837 complex<double> f = 0.0;
838 for(
int i = upp + 1; i-- > m;) f +=
conj(ort[i]) * copy[i][j];
840 for(
int i = m; i <= upp; i++) copy[i][j] -= f * ort[i];
844 for(
int i = 0; i <= upp; i++) {
845 complex<double> f = 0.0;
846 for(
int j = upp + 1; j-- > m;) f += ort[j] * copy[i][j];
848 for(
int j = m; j <= upp; j++) copy[i][j] -= f *
conj(ort[j]);
852 copy[m][m-1] = - g * copy[m][m-1];
857 #endif // CLASSIC_FComplexEigen_HH
int hqr2(FMatrix< complex< double >, N, N > &, int low, int high, complex< double > ort[N])
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
static void orthes(FMatrix< complex< double >, N, N > &, int low, int high, complex< double > ort[N])
MMatrix< m_complex > complex(MMatrix< double > real)
A templated representation for matrices.
int hqr(FMatrix< complex< double >, N, N > &, int low, int high)
A templated representation for vectors.
FMatrix< complex< double >, N, N > vectors
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
void balbak(int low, int high, const double scale[N])
m_complex conj(const m_complex &c)
constexpr double c
The velocity of light in m/s.
static void balance(FMatrix< complex< double >, N, N > &, int &low, int &high, double scale[N])
const FVector< complex< double >, N > & eigenValues() const
Get eigenvalues.
Eigenvalue error exception.
Tps< T > sqrt(const Tps< T > &x)
Square root.
Eigenvalues and eigenvectors for a complex general matrix.
const FMatrix< complex< double >, N, N > & eigenVectors() const
Get eigenvectors.
static void exchange(FMatrix< complex< double >, N, N > &, int j, int m, int low, int high)
void operator=(const FComplexEigen &)
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.
FVector< complex< double >, N > lambda