CEDRIC  Revision_backup-2009-02
Eigenvalue.h
Go to the documentation of this file.
1 #ifndef REDUKT_EIGENVALUE_H
2 #define REDUKT_EIGENVALUE_H
3 
4 #include <algorithm> // for min(), max() below
5 using std::min;
6 using std::max;
7 
8 #include <cmath> // for abs() below
9 using std::abs;
10 
11 #include <boost/numeric/ublas/matrix.hpp> // replacement for TNT::Array2D
12 #include <boost/numeric/ublas/vector.hpp> // replacement for TNT::Array1D
13 #include <boost/numeric/ublas/operation.hpp>
14 
59 template <class ValueType>
61 {
62 public:
63  typedef boost::numeric::ublas::matrix<ValueType> Matrix;
64  typedef boost::numeric::ublas::vector<ValueType> Vector;
65 
66 public:
67 
70  static bool isSymmetric( const Matrix& A )
71  {
72  bool symmetric = true;
73  for( unsigned int j = 0; (j < A.size1()) && symmetric; ++j )
74  for( unsigned int i = 0; (i < A.size2()) && symmetric; ++i )
75  symmetric = ( A(i,j) == A(j,i) );
76  //{
77  // ValueType err = A(i,j) - A(j,i);
78  // symmetric = ( err <= eps );
79  //}
80 
81  return symmetric;
82  }
83 
87  Eigenvalue( const Matrix& A )
88  {
89  n = A.size2();
90  V = Matrix(n,n);
91  d = Vector(n);
92  e = Vector(n);
93 
94  if( isSymmetric( A ) )
95  {
96  for (int i = 0; i < n; i++)
97  for (int j = 0; j < n; j++)
98  V(i,j) = A(i,j);
99 
100  // Tridiagonalize.
101  tred2();
102 
103  // Diagonalize.
104  tql2();
105 
106  }
107  else // not symmetric case
108  {
109  H = Matrix(n,n);
110  ort = Vector(n);
111 
112  for (int j = 0; j < n; j++)
113  for (int i = 0; i < n; i++)
114  H(i,j) = A(i,j);
115 
116  // Reduce to Hessenberg form.
117  orthes();
118 
119  // Reduce Hessenberg to real Schur form.
120  hqr2();
121  }
122 
123  // results are ordered from smallest to largest eigenvalue
124  // reverse this order to deliver a convenient result
125  for( int i=0; i < n/2; ++i )
126  {
127  int j = n - i - 1;
128 
129  // reorder eigenvector matrix V
130  // swap column i and j <<<<< ====== TODO: This piece of code relies uneccesarilly on boost matrix proxies! ======
131  Vector v = boost::numeric::ublas::column(V,i);
132  boost::numeric::ublas::column(V,i) = boost::numeric::ublas::column(V,j);
133  boost::numeric::ublas::column(V,j) = v;
134 
135  // reorder eigenvalues
136  ValueType tmp;
137  tmp = d[i];
138  d[i] = d[j];
139  d[j] = tmp;
140  tmp = e[i];
141  e[i] = e[j];
142  e[j] = tmp;
143  }
144  }
145 
146 
150  const Matrix& getV() const
151  {
152  return V;
153  }
154 
158  const Vector& getRealEigenvalues() const
159  {
160  return d;
161  }
162 
166  const Vector& getImagEigenvalues() const
167  {
168  return e;
169  }
170 
171 
204  void getD( Matrix& D )
205  {
206  D = Matrix(n,n);
207  for (int i = 0; i < n; i++)
208  {
209  for (int j = 0; j < n; j++)
210  D(i,j) = 0.0;
211 
212  D(i,i) = d[i];
213 
214  if (e[i] > 0)
215  {
216  D(i,i+1) = e[i];
217  }
218  else
219  if (e[i] < 0)
220  {
221  D(i,i-1) = e[i];
222  }
223  }
224  }
225 
226 
227 private:
229  int n;
230 
232  Vector d; /* real part */
233  Vector e; /* img part */
234 
236  Matrix V;
237 
241  Matrix H;
242 
243 
247  Vector ort;
248 
249 
250  // Symmetric Householder reduction to tridiagonal form.
251 
252  void tred2() {
253 
254  // This is derived from the Algol procedures tred2 by
255  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
256  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
257  // Fortran subroutine in EISPACK.
258 
259  for (int j = 0; j < n; j++) {
260  d[j] = V(n-1,j);
261  }
262 
263  // Householder reduction to tridiagonal form.
264 
265  for (int i = n-1; i > 0; i--) {
266 
267  // Scale to avoid under/overflow.
268 
269  ValueType scale = 0.0;
270  ValueType h = 0.0;
271  for (int k = 0; k < i; k++) {
272  scale = scale + abs(d[k]);
273  }
274  if (scale == 0.0) {
275  e[i] = d[i-1];
276  for (int j = 0; j < i; j++) {
277  d[j] = V(i-1,j);
278  V(i,j) = 0.0;
279  V(j,i) = 0.0;
280  }
281  } else {
282 
283  // Generate Householder vector.
284 
285  for (int k = 0; k < i; k++) {
286  d[k] /= scale;
287  h += d[k] * d[k];
288  }
289  ValueType f = d[i-1];
290  ValueType g = sqrt(h);
291  if (f > 0) {
292  g = -g;
293  }
294  e[i] = scale * g;
295  h = h - f * g;
296  d[i-1] = f - g;
297  for (int j = 0; j < i; j++) {
298  e[j] = 0.0;
299  }
300 
301  // Apply similarity transformation to remaining columns.
302 
303  for (int j = 0; j < i; j++) {
304  f = d[j];
305  V(j,i) = f;
306  g = e[j] + V(j,j) * f;
307  for (int k = j+1; k <= i-1; k++) {
308  g += V(k,j) * d[k];
309  e[k] += V(k,j) * f;
310  }
311  e[j] = g;
312  }
313  f = 0.0;
314  for (int j = 0; j < i; j++) {
315  e[j] /= h;
316  f += e[j] * d[j];
317  }
318  ValueType hh = f / (h + h);
319  for (int j = 0; j < i; j++) {
320  e[j] -= hh * d[j];
321  }
322  for (int j = 0; j < i; j++) {
323  f = d[j];
324  g = e[j];
325  for (int k = j; k <= i-1; k++) {
326  V(k,j) -= (f * e[k] + g * d[k]);
327  }
328  d[j] = V(i-1,j);
329  V(i,j) = 0.0;
330  }
331  }
332  d[i] = h;
333  }
334 
335  // Accumulate transformations.
336 
337  for (int i = 0; i < n-1; i++) {
338  V(n-1,i) = V(i,i);
339  V(i,i) = 1.0;
340  ValueType h = d[i+1];
341  if (h != 0.0) {
342  for (int k = 0; k <= i; k++) {
343  d[k] = V(k,i+1) / h;
344  }
345  for (int j = 0; j <= i; j++) {
346  ValueType g = 0.0;
347  for (int k = 0; k <= i; k++) {
348  g += V(k,i+1) * V(k,j);
349  }
350  for (int k = 0; k <= i; k++) {
351  V(k,j) -= g * d[k];
352  }
353  }
354  }
355  for (int k = 0; k <= i; k++) {
356  V(k,i+1) = 0.0;
357  }
358  }
359  for (int j = 0; j < n; j++) {
360  d[j] = V(n-1,j);
361  V(n-1,j) = 0.0;
362  }
363  V(n-1,n-1) = 1.0;
364  e[0] = 0.0;
365  }
366 
367  // Symmetric tridiagonal QL algorithm.
368 
369  void tql2 () {
370 
371  // This is derived from the Algol procedures tql2, by
372  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
373  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
374  // Fortran subroutine in EISPACK.
375 
376  for (int i = 1; i < n; i++) {
377  e[i-1] = e[i];
378  }
379  e[n-1] = 0.0;
380 
381  ValueType f = 0.0;
382  ValueType tst1 = 0.0;
383  ValueType eps = pow(2.0,-52.0);
384  for (int l = 0; l < n; l++) {
385 
386  // Find small subdiagonal element
387 
388  tst1 = max(tst1,abs(d[l]) + abs(e[l]));
389  int m = l;
390 
391  // Original while-loop from Java code
392  while (m < n) {
393  if (abs(e[m]) <= eps*tst1) {
394  break;
395  }
396  m++;
397  }
398 
399 
400  // If m == l, d[l] is an eigenvalue,
401  // otherwise, iterate.
402 
403  if (m > l) {
404  int iter = 0;
405  do {
406  iter = iter + 1; // (Could check iteration count here.)
407 
408  // Compute implicit shift
409 
410  ValueType g = d[l];
411  ValueType p = (d[l+1] - g) / (2.0 * e[l]);
412  ValueType r = hypot(p,1.0);
413  if (p < 0) {
414  r = -r;
415  }
416  d[l] = e[l] / (p + r);
417  d[l+1] = e[l] * (p + r);
418  ValueType dl1 = d[l+1];
419  ValueType h = g - d[l];
420  for (int i = l+2; i < n; i++) {
421  d[i] -= h;
422  }
423  f = f + h;
424 
425  // Implicit QL transformation.
426 
427  p = d[m];
428  ValueType c = 1.0;
429  ValueType c2 = c;
430  ValueType c3 = c;
431  ValueType el1 = e[l+1];
432  ValueType s = 0.0;
433  ValueType s2 = 0.0;
434  for (int i = m-1; i >= l; i--) {
435  c3 = c2;
436  c2 = c;
437  s2 = s;
438  g = c * e[i];
439  h = c * p;
440  r = hypot(p,e[i]);
441  e[i+1] = s * r;
442  s = e[i] / r;
443  c = p / r;
444  p = c * d[i] - s * g;
445  d[i+1] = h + s * (c * g + s * d[i]);
446 
447  // Accumulate transformation.
448 
449  for (int k = 0; k < n; k++) {
450  h = V(k,i+1);
451  V(k,i+1) = s * V(k,i) + c * h;
452  V(k,i) = c * V(k,i) - s * h;
453  }
454  }
455  p = -s * s2 * c3 * el1 * e[l] / dl1;
456  e[l] = s * p;
457  d[l] = c * p;
458 
459  // Check for convergence.
460 
461  } while (abs(e[l]) > eps*tst1);
462  }
463  d[l] = d[l] + f;
464  e[l] = 0.0;
465  }
466 
467  // Sort eigenvalues and corresponding vectors.
468 
469  for (int i = 0; i < n-1; i++) {
470  int k = i;
471  ValueType p = d[i];
472  for (int j = i+1; j < n; j++) {
473  if (d[j] < p) {
474  k = j;
475  p = d[j];
476  }
477  }
478  if (k != i) {
479  d[k] = d[i];
480  d[i] = p;
481  for (int j = 0; j < n; j++) {
482  p = V(j,i);
483  V(j,i) = V(j,k);
484  V(j,k) = p;
485  }
486  }
487  }
488  }
489 
490  // Nonsymmetric reduction to Hessenberg form.
491 
492  void orthes () {
493 
494  // This is derived from the Algol procedures orthes and ortran,
495  // by Martin and Wilkinson, Handbook for Auto. Comp.,
496  // Vol.ii-Linear Algebra, and the corresponding
497  // Fortran subroutines in EISPACK.
498 
499  int low = 0;
500  int high = n-1;
501 
502  for (int m = low+1; m <= high-1; m++) {
503 
504  // Scale column.
505 
506  ValueType scale = 0.0;
507  for (int i = m; i <= high; i++) {
508  scale = scale + abs(H(i,m-1));
509  }
510  if (scale != 0.0) {
511 
512  // Compute Householder transformation.
513 
514  ValueType h = 0.0;
515  for (int i = high; i >= m; i--) {
516  ort[i] = H(i,m-1)/scale;
517  h += ort[i] * ort[i];
518  }
519  ValueType g = sqrt(h);
520  if (ort[m] > 0) {
521  g = -g;
522  }
523  h = h - ort[m] * g;
524  ort[m] = ort[m] - g;
525 
526  // Apply Householder similarity transformation
527  // H = (I-u*u'/h)*H*(I-u*u')/h)
528 
529  for (int j = m; j < n; j++) {
530  ValueType f = 0.0;
531  for (int i = high; i >= m; i--) {
532  f += ort[i]*H(i,j);
533  }
534  f = f/h;
535  for (int i = m; i <= high; i++) {
536  H(i,j) -= f*ort[i];
537  }
538  }
539 
540  for (int i = 0; i <= high; i++) {
541  ValueType f = 0.0;
542  for (int j = high; j >= m; j--) {
543  f += ort[j]*H(i,j);
544  }
545  f = f/h;
546  for (int j = m; j <= high; j++) {
547  H(i,j) -= f*ort[j];
548  }
549  }
550  ort[m] = scale*ort[m];
551  H(m,m-1) = scale*g;
552  }
553  }
554 
555  // Accumulate transformations (Algol's ortran).
556 
557  for (int i = 0; i < n; i++) {
558  for (int j = 0; j < n; j++) {
559  V(i,j) = (i == j ? 1.0 : 0.0);
560  }
561  }
562 
563  for (int m = high-1; m >= low+1; m--) {
564  if (H(m,m-1) != 0.0) {
565  for (int i = m+1; i <= high; i++) {
566  ort[i] = H(i,m-1);
567  }
568  for (int j = m; j <= high; j++) {
569  ValueType g = 0.0;
570  for (int i = m; i <= high; i++) {
571  g += ort[i] * V(i,j);
572  }
573  // Double division avoids possible underflow
574  g = (g / ort[m]) / H(m,m-1);
575  for (int i = m; i <= high; i++) {
576  V(i,j) += g * ort[i];
577  }
578  }
579  }
580  }
581  }
582 
583 
584  // Complex scalar division.
585 
586  ValueType cdivr, cdivi;
587  void cdiv(ValueType xr, ValueType xi, ValueType yr, ValueType yi) {
588  ValueType r,d;
589  if (abs(yr) > abs(yi)) {
590  r = yi/yr;
591  d = yr + r*yi;
592  cdivr = (xr + r*xi)/d;
593  cdivi = (xi - r*xr)/d;
594  } else {
595  r = yr/yi;
596  d = yi + r*yr;
597  cdivr = (r*xr + xi)/d;
598  cdivi = (r*xi - xr)/d;
599  }
600  }
601 
602 
603  // Nonsymmetric reduction from Hessenberg to real Schur form.
604 
605  void hqr2 () {
606 
607  // This is derived from the Algol procedure hqr2,
608  // by Martin and Wilkinson, Handbook for Auto. Comp.,
609  // Vol.ii-Linear Algebra, and the corresponding
610  // Fortran subroutine in EISPACK.
611 
612  // Initialize
613 
614  int nn = this->n;
615  int n = nn-1;
616  int low = 0;
617  int high = nn-1;
618  ValueType eps = pow(2.0,-52.0);
619  ValueType exshift = 0.0;
620  ValueType p=0,q=0,r=0,s=0,z=0,t,w,x,y;
621 
622  // Store roots isolated by balanc and compute matrix norm
623 
624  ValueType norm = 0.0;
625  for (int i = 0; i < nn; i++) {
626  if ((i < low) || (i > high)) {
627  d[i] = H(i,i);
628  e[i] = 0.0;
629  }
630  for (int j = max(i-1,0); j < nn; j++) {
631  norm = norm + abs(H(i,j));
632  }
633  }
634 
635  // Outer loop over eigenvalue index
636 
637  int iter = 0;
638  while (n >= low) {
639 
640  // Look for single small sub-diagonal element
641 
642  int l = n;
643  while (l > low) {
644  s = abs(H(l-1,l-1)) + abs(H(l,l));
645  if (s == 0.0) {
646  s = norm;
647  }
648  if (abs(H(l,l-1)) < eps * s) {
649  break;
650  }
651  l--;
652  }
653 
654  // Check for convergence
655  // One root found
656 
657  if (l == n) {
658  H(n,n) = H(n,n) + exshift;
659  d[n] = H(n,n);
660  e[n] = 0.0;
661  n--;
662  iter = 0;
663 
664  // Two roots found
665 
666  } else if (l == n-1) {
667  w = H(n,n-1) * H(n-1,n);
668  p = (H(n-1,n-1) - H(n,n)) / 2.0;
669  q = p * p + w;
670  z = sqrt(abs(q));
671  H(n,n) = H(n,n) + exshift;
672  H(n-1,n-1) = H(n-1,n-1) + exshift;
673  x = H(n,n);
674 
675  // ValueType pair
676 
677  if (q >= 0) {
678  if (p >= 0) {
679  z = p + z;
680  } else {
681  z = p - z;
682  }
683  d[n-1] = x + z;
684  d[n] = d[n-1];
685  if (z != 0.0) {
686  d[n] = x - w / z;
687  }
688  e[n-1] = 0.0;
689  e[n] = 0.0;
690  x = H(n,n-1);
691  s = abs(x) + abs(z);
692  p = x / s;
693  q = z / s;
694  r = sqrt(p * p+q * q);
695  p = p / r;
696  q = q / r;
697 
698  // Row modification
699 
700  for (int j = n-1; j < nn; j++) {
701  z = H(n-1,j);
702  H(n-1,j) = q * z + p * H(n,j);
703  H(n,j) = q * H(n,j) - p * z;
704  }
705 
706  // Column modification
707 
708  for (int i = 0; i <= n; i++) {
709  z = H(i,n-1);
710  H(i,n-1) = q * z + p * H(i,n);
711  H(i,n) = q * H(i,n) - p * z;
712  }
713 
714  // Accumulate transformations
715 
716  for (int i = low; i <= high; i++) {
717  z = V(i,n-1);
718  V(i,n-1) = q * z + p * V(i,n);
719  V(i,n) = q * V(i,n) - p * z;
720  }
721 
722  // Complex pair
723 
724  } else {
725  d[n-1] = x + p;
726  d[n] = x + p;
727  e[n-1] = z;
728  e[n] = -z;
729  }
730  n = n - 2;
731  iter = 0;
732 
733  // No convergence yet
734 
735  } else {
736 
737  // Form shift
738 
739  x = H(n,n);
740  y = 0.0;
741  w = 0.0;
742  if (l < n) {
743  y = H(n-1,n-1);
744  w = H(n,n-1) * H(n-1,n);
745  }
746 
747  // Wilkinson's original ad hoc shift
748 
749  if (iter == 10) {
750  exshift += x;
751  for (int i = low; i <= n; i++) {
752  H(i,i) -= x;
753  }
754  s = abs(H(n,n-1)) + abs(H(n-1,n-2));
755  x = y = 0.75 * s;
756  w = -0.4375 * s * s;
757  }
758 
759  // MATLAB's new ad hoc shift
760 
761  if (iter == 30) {
762  s = (y - x) / 2.0;
763  s = s * s + w;
764  if (s > 0) {
765  s = sqrt(s);
766  if (y < x) {
767  s = -s;
768  }
769  s = x - w / ((y - x) / 2.0 + s);
770  for (int i = low; i <= n; i++) {
771  H(i,i) -= s;
772  }
773  exshift += s;
774  x = y = w = 0.964;
775  }
776  }
777 
778  iter = iter + 1; // (Could check iteration count here.)
779 
780  // Look for two consecutive small sub-diagonal elements
781 
782  int m = n-2;
783  while (m >= l) {
784  z = H(m,m);
785  r = x - z;
786  s = y - z;
787  p = (r * s - w) / H(m+1,m) + H(m,m+1);
788  q = H(m+1,m+1) - z - r - s;
789  r = H(m+2,m+1);
790  s = abs(p) + abs(q) + abs(r);
791  p = p / s;
792  q = q / s;
793  r = r / s;
794  if (m == l) {
795  break;
796  }
797  if (abs(H(m,m-1)) * (abs(q) + abs(r)) <
798  eps * (abs(p) * (abs(H(m-1,m-1)) + abs(z) +
799  abs(H(m+1,m+1))))) {
800  break;
801  }
802  m--;
803  }
804 
805  for (int i = m+2; i <= n; i++) {
806  H(i,i-2) = 0.0;
807  if (i > m+2) {
808  H(i,i-3) = 0.0;
809  }
810  }
811 
812  // Double QR step involving rows l:n and columns m:n
813 
814  for (int k = m; k <= n-1; k++) {
815  int notlast = (k != n-1);
816  if (k != m) {
817  p = H(k,k-1);
818  q = H(k+1,k-1);
819  r = (notlast ? H(k+2,k-1) : 0.0);
820  x = abs(p) + abs(q) + abs(r);
821  if (x != 0.0) {
822  p = p / x;
823  q = q / x;
824  r = r / x;
825  }
826  }
827  if (x == 0.0) {
828  break;
829  }
830  s = sqrt(p * p + q * q + r * r);
831  if (p < 0) {
832  s = -s;
833  }
834  if (s != 0) {
835  if (k != m) {
836  H(k,k-1) = -s * x;
837  } else if (l != m) {
838  H(k,k-1) = -H(k,k-1);
839  }
840  p = p + s;
841  x = p / s;
842  y = q / s;
843  z = r / s;
844  q = q / p;
845  r = r / p;
846 
847  // Row modification
848 
849  for (int j = k; j < nn; j++) {
850  p = H(k,j) + q * H(k+1,j);
851  if (notlast) {
852  p = p + r * H(k+2,j);
853  H(k+2,j) = H(k+2,j) - p * z;
854  }
855  H(k,j) = H(k,j) - p * x;
856  H(k+1,j) = H(k+1,j) - p * y;
857  }
858 
859  // Column modification
860 
861  for (int i = 0; i <= min(n,k+3); i++) {
862  p = x * H(i,k) + y * H(i,k+1);
863  if (notlast) {
864  p = p + z * H(i,k+2);
865  H(i,k+2) = H(i,k+2) - p * r;
866  }
867  H(i,k) = H(i,k) - p;
868  H(i,k+1) = H(i,k+1) - p * q;
869  }
870 
871  // Accumulate transformations
872 
873  for (int i = low; i <= high; i++) {
874  p = x * V(i,k) + y * V(i,k+1);
875  if (notlast) {
876  p = p + z * V(i,k+2);
877  V(i,k+2) = V(i,k+2) - p * r;
878  }
879  V(i,k) = V(i,k) - p;
880  V(i,k+1) = V(i,k+1) - p * q;
881  }
882  } // (s != 0)
883  } // k loop
884  } // check convergence
885  } // while (n >= low)
886 
887  // Backsubstitute to find vectors of upper triangular form
888 
889  if (norm == 0.0) {
890  return;
891  }
892 
893  for (n = nn-1; n >= 0; n--) {
894  p = d[n];
895  q = e[n];
896 
897  // ValueType vector
898 
899  if (q == 0) {
900  int l = n;
901  H(n,n) = 1.0;
902  for (int i = n-1; i >= 0; i--) {
903  w = H(i,i) - p;
904  r = 0.0;
905  for (int j = l; j <= n; j++) {
906  r = r + H(i,j) * H(j,n);
907  }
908  if (e[i] < 0.0) {
909  z = w;
910  s = r;
911  } else {
912  l = i;
913  if (e[i] == 0.0) {
914  if (w != 0.0) {
915  H(i,n) = -r / w;
916  } else {
917  H(i,n) = -r / (eps * norm);
918  }
919 
920  // Solve real equations
921 
922  } else {
923  x = H(i,i+1);
924  y = H(i+1,i);
925  q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
926  t = (x * s - z * r) / q;
927  H(i,n) = t;
928  if (abs(x) > abs(z)) {
929  H(i+1,n) = (-r - w * t) / x;
930  } else {
931  H(i+1,n) = (-s - y * t) / z;
932  }
933  }
934 
935  // Overflow control
936 
937  t = abs(H(i,n));
938  if ((eps * t) * t > 1) {
939  for (int j = i; j <= n; j++) {
940  H(j,n) = H(j,n) / t;
941  }
942  }
943  }
944  }
945 
946  // Complex vector
947 
948  } else if (q < 0) {
949  int l = n-1;
950 
951  // Last vector component imaginary so matrix is triangular
952 
953  if (abs(H(n,n-1)) > abs(H(n-1,n))) {
954  H(n-1,n-1) = q / H(n,n-1);
955  H(n-1,n) = -(H(n,n) - p) / H(n,n-1);
956  } else {
957  cdiv(0.0,-H(n-1,n),H(n-1,n-1)-p,q);
958  H(n-1,n-1) = cdivr;
959  H(n-1,n) = cdivi;
960  }
961  H(n,n-1) = 0.0;
962  H(n,n) = 1.0;
963  for (int i = n-2; i >= 0; i--) {
964  ValueType ra,sa,vr,vi;
965  ra = 0.0;
966  sa = 0.0;
967  for (int j = l; j <= n; j++) {
968  ra = ra + H(i,j) * H(j,n-1);
969  sa = sa + H(i,j) * H(j,n);
970  }
971  w = H(i,i) - p;
972 
973  if (e[i] < 0.0) {
974  z = w;
975  r = ra;
976  s = sa;
977  } else {
978  l = i;
979  if (e[i] == 0) {
980  cdiv(-ra,-sa,w,q);
981  H(i,n-1) = cdivr;
982  H(i,n) = cdivi;
983  } else {
984 
985  // Solve complex equations
986 
987  x = H(i,i+1);
988  y = H(i+1,i);
989  vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
990  vi = (d[i] - p) * 2.0 * q;
991  if ((vr == 0.0) && (vi == 0.0)) {
992  vr = eps * norm * (abs(w) + abs(q) +
993  abs(x) + abs(y) + abs(z));
994  }
995  cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
996  H(i,n-1) = cdivr;
997  H(i,n) = cdivi;
998  if (abs(x) > (abs(z) + abs(q))) {
999  H(i+1,n-1) = (-ra - w * H(i,n-1) + q * H(i,n)) / x;
1000  H(i+1,n) = (-sa - w * H(i,n) - q * H(i,n-1)) / x;
1001  } else {
1002  cdiv(-r-y*H(i,n-1),-s-y*H(i,n),z,q);
1003  H(i+1,n-1) = cdivr;
1004  H(i+1,n) = cdivi;
1005  }
1006  }
1007 
1008  // Overflow control
1009 
1010  t = max(abs(H(i,n-1)),abs(H(i,n)));
1011  if ((eps * t) * t > 1) {
1012  for (int j = i; j <= n; j++) {
1013  H(j,n-1) = H(j,n-1) / t;
1014  H(j,n) = H(j,n) / t;
1015  }
1016  }
1017  }
1018  }
1019  }
1020  }
1021 
1022  // Vectors of isolated roots
1023 
1024  for (int i = 0; i < nn; i++) {
1025  if (i < low || i > high) {
1026  for (int j = i; j < nn; j++) {
1027  V(i,j) = H(i,j);
1028  }
1029  }
1030  }
1031 
1032  // Back transformation to get eigenvectors of original matrix
1033 
1034  for (int j = nn-1; j >= low; j--) {
1035  for (int i = low; i <= high; i++) {
1036  z = 0.0;
1037  for (int k = low; k <= min(j,high); k++) {
1038  z = z + V(i,k) * H(k,j);
1039  }
1040  V(i,j) = z;
1041  }
1042  }
1043  }
1044 
1045 };
1046 
1047 
1048 #endif // REDUKT_EIGENVALUE_H
boost::numeric::ublas::vector< ValueType > Vector
Definition: Eigenvalue.h:64
const Matrix & getV() const
Definition: Eigenvalue.h:150
Definition: Eigenvalue.h:60
boost::numeric::ublas::matrix< ValueType > Matrix
Definition: Eigenvalue.h:63
Eigenvalue(const Matrix &A)
Definition: Eigenvalue.h:87
static bool isSymmetric(const Matrix &A)
Definition: Eigenvalue.h:70
const Vector & getRealEigenvalues() const
Definition: Eigenvalue.h:158
const Vector & getImagEigenvalues() const
Definition: Eigenvalue.h:166
void getD(Matrix &D)
Definition: Eigenvalue.h:204