Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Tools/Math/LA_Eigenvalues.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 #include <math.h>
00003 #include "LA_Eigenvalues.h"
00004 //------------------------------------------------------------------------------
00005 namespace LA
00006 {
00007 //------------------------------------------------------------------------------
00008 Eigenvalues::Eigenvalues(const Matrix& A)
00009 {
00010   int i, j;
00011   
00012   n = A.columns();
00013 
00014   V.create(n, n);
00015   d.create(n);
00016   e.create(n);
00017 
00018   issymmetric = 1;
00019   for (j = 0; (j < n) && issymmetric; j++)
00020   {
00021     for (i = 0; (i < n) && issymmetric; i++)
00022     {
00023       issymmetric = (A[i][j] == A[j][i]);
00024     }
00025   }
00026 
00027   if (issymmetric)
00028   {
00029     for (i = 0; i < n; i++)
00030     {
00031       for (j = 0; j < n; j++)
00032       {
00033         V[i][j] = A[i][j];
00034       }
00035     }
00036    
00037     // Tridiagonalize.
00038     tred2();
00039    
00040     // Diagonalize.
00041     tql2();
00042   }
00043   else
00044   {
00045     H.create(n, n);
00046     ort.create(n);
00047 
00048     for (j = 0; j < n; j++)
00049     {
00050       for (i = 0; i < n; i++)
00051       {
00052         H[i][j] = A[i][j];
00053       }
00054     }
00055    
00056     // Reduce to Hessenberg form.
00057     orthes();
00058    
00059     // Reduce Hessenberg to real Schur form.
00060     hqr2();
00061   }
00062 }
00063 //------------------------------------------------------------------------------
00064 const Matrix& Eigenvalues::getV() const
00065 {
00066   return V;
00067 }
00068 //------------------------------------------------------------------------------
00069 const Vector& Eigenvalues::getRealEigenvalues() const
00070 {
00071   return d;
00072 }
00073 //------------------------------------------------------------------------------
00074 const Vector& Eigenvalues::getImagEigenvalues() const
00075 {
00076   return e;
00077 }
00078 //------------------------------------------------------------------------------
00079 Matrix Eigenvalues::getD() const
00080 {
00081   Matrix D(n, n);
00082   for (int i = 0; i < n; i++)
00083   {
00084     for (int j = 0; j < n; j++)
00085     {
00086       D[i][j] = 0.0;
00087     }
00088     D[i][i] = d[i];
00089     if (e[i] > 0)
00090     {
00091       D[i][i+1] = e[i];
00092     }
00093     else if (e[i] < 0)
00094     {
00095       D[i][i-1] = e[i];
00096     }
00097   }
00098   return D;
00099 }
00100 //------------------------------------------------------------------------------
00101 void Eigenvalues::tred2()
00102 {
00103   //  This is derived from the Algol procedures tred2 by
00104   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
00105   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
00106   //  Fortran subroutine in EISPACK.
00107 
00108   int i, j, k;
00109   
00110   for (j = 0; j < n; j++)
00111   {
00112     d[j] = V[n-1][j];
00113   }
00114 
00115   // Householder reduction to tridiagonal form.
00116    
00117   for (i = n-1; i > 0; i--)
00118   {
00119     // Scale to avoid under/overflow.
00120     double scale = 0.0;
00121     double h = 0.0;
00122     for (k = 0; k < i; k++)
00123     {
00124       scale = scale + fabs(d[k]);
00125     }
00126     if (scale == 0.0)
00127     {
00128       e[i] = d[i-1];
00129       for (j = 0; j < i; j++)
00130       {
00131         d[j] = V[i-1][j];
00132         V[i][j] = 0.0;
00133         V[j][i] = 0.0;
00134       }
00135     }
00136     else
00137     {
00138       // Generate Householder vector.
00139       for (k = 0; k < i; k++)
00140       {
00141         d[k] /= scale;
00142         h += d[k] * d[k];
00143       }
00144       double f = d[i-1];
00145       double g = sqrt(h);
00146       if (f > 0)
00147       {
00148         g = -g;
00149       }
00150       e[i] = scale * g;
00151       h = h - f * g;
00152       d[i-1] = f - g;
00153       for (j = 0; j < i; j++)
00154       {
00155         e[j] = 0.0;
00156       }
00157 
00158       // Apply similarity transformation to remaining columns.
00159       for (j = 0; j < i; j++)
00160       {
00161         f = d[j];
00162         V[j][i] = f;
00163         g = e[j] + V[j][j] * f;
00164         for (k = j+1; k <= i-1; k++)
00165         {
00166           g += V[k][j] * d[k];
00167           e[k] += V[k][j] * f;
00168         }
00169         e[j] = g;
00170       }
00171       f = 0.0;
00172       for (j = 0; j < i; j++)
00173       {
00174         e[j] /= h;
00175         f += e[j] * d[j];
00176       }
00177       double hh = f / (h + h);
00178       for (j = 0; j < i; j++)
00179       {
00180         e[j] -= hh * d[j];
00181       }
00182       for (j = 0; j < i; j++)
00183       {
00184         f = d[j];
00185         g = e[j];
00186         for (k = j; k <= i-1; k++)
00187         {
00188           V[k][j] -= (f * e[k] + g * d[k]);
00189         }
00190         d[j] = V[i-1][j];
00191         V[i][j] = 0.0;
00192       }
00193     }
00194     d[i] = h;
00195   }
00196    
00197   // Accumulate transformations.
00198   for (i = 0; i < n-1; i++)
00199   {
00200     V[n-1][i] = V[i][i];
00201     V[i][i] = 1.0;
00202     double h = d[i+1];
00203     if (h != 0.0)
00204     {
00205       for (k = 0; k <= i; k++)
00206       {
00207         d[k] = V[k][i+1] / h;
00208       }
00209       for (j = 0; j <= i; j++)
00210       {
00211         double g = 0.0;
00212         for (k = 0; k <= i; k++)
00213         {
00214           g += V[k][i+1] * V[k][j];
00215         }
00216         for (k = 0; k <= i; k++)
00217         {
00218           V[k][j] -= g * d[k];
00219         }
00220       }
00221     }
00222     for (k = 0; k <= i; k++)
00223     {
00224       V[k][i+1] = 0.0;
00225     }
00226   }
00227   for (j = 0; j < n; j++)
00228   {
00229     d[j] = V[n-1][j];
00230     V[n-1][j] = 0.0;
00231   }
00232   V[n-1][n-1] = 1.0;
00233   e[0] = 0.0;
00234 }
00235 //------------------------------------------------------------------------------
00236 void Eigenvalues::tql2()
00237 {
00238   //  This is derived from the Algol procedures tql2, by
00239   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
00240   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
00241   //  Fortran subroutine in EISPACK.
00242 
00243   int i, j, k, l;
00244 
00245   for (i = 1; i < n; i++)
00246   {
00247     e[i-1] = e[i];
00248   }
00249   e[n-1] = 0.0;
00250    
00251   double f = 0.0;
00252   double tst1 = 0.0;
00253   double eps = pow(2.0,-52.0);
00254   for (l = 0; l < n; l++)
00255   {
00256     // Find small subdiagonal element
00257     double tst2 = fabs(d[l]) + fabs(e[l]);
00258     tst1 = (tst1 > tst2)? tst1: tst2;
00259     int m = l;
00260 
00261     // Original while-loop from Java code
00262     while (m < n)
00263     {
00264       if (fabs(e[m]) <= eps*tst1)
00265       {
00266         break;
00267       }
00268       m++;
00269     }
00270    
00271     // If m == l, d[l] is an eigenvalue,
00272     // otherwise, iterate.
00273     if (m > l)
00274     {
00275       int iter = 0;
00276       do
00277       {
00278         iter = iter + 1;  // (Could check iteration count here.)
00279    
00280         // Compute implicit shift
00281         double g = d[l];
00282         double p = (d[l+1] - g) / (2.0 * e[l]);
00283 #ifdef _WIN32
00284         double r = _hypot(p,1.0);
00285 #else
00286         double r = hypot(p,1.0);
00287 #endif
00288         if (p < 0)
00289         {
00290           r = -r;
00291         }
00292         d[l] = e[l] / (p + r);
00293         d[l+1] = e[l] * (p + r);
00294         double dl1 = d[l+1];
00295         double h = g - d[l];
00296         for (i = l+2; i < n; i++)
00297         {
00298           d[i] -= h;
00299         }
00300         f = f + h;
00301    
00302         // Implicit QL transformation.
00303         p = d[m];
00304         double c = 1.0;
00305         double c2 = c;
00306         double c3 = c;
00307         double el1 = e[l+1];
00308         double s = 0.0;
00309         double s2 = 0.0;
00310         for (i = m-1; i >= l; i--)
00311         {
00312           c3 = c2;
00313           c2 = c;
00314           s2 = s;
00315           g = c * e[i];
00316           h = c * p;
00317 #ifdef _WIN32
00318           r = _hypot(p,e[i]);
00319 #else
00320           r = hypot(p,e[i]);
00321 #endif
00322           e[i+1] = s * r;
00323           s = e[i] / r;
00324           c = p / r;
00325           p = c * d[i] - s * g;
00326           d[i+1] = h + s * (c * g + s * d[i]);
00327    
00328           // Accumulate transformation.
00329           for (k = 0; k < n; k++)
00330           {
00331             h = V[k][i+1];
00332             V[k][i+1] = s * V[k][i] + c * h;
00333             V[k][i] = c * V[k][i] - s * h;
00334           }
00335         }
00336         p = -s * s2 * c3 * el1 * e[l] / dl1;
00337         e[l] = s * p;
00338         d[l] = c * p;
00339    
00340         // Check for convergence.
00341       }
00342       while (fabs(e[l]) > eps*tst1);
00343     }
00344     d[l] = d[l] + f;
00345     e[l] = 0.0;
00346   }
00347      
00348   // Sort eigenvalues and corresponding vectors.
00349   for (i = 0; i < n-1; i++)
00350   {
00351     k = i;
00352     double p = d[i];
00353     for (j = i+1; j < n; j++)
00354     {
00355       if (d[j] < p)
00356       {
00357         k = j;
00358         p = d[j];
00359       }
00360     }
00361     if (k != i)
00362     {
00363       d[k] = d[i];
00364       d[i] = p;
00365       for (j = 0; j < n; j++)
00366       {
00367         p = V[j][i];
00368         V[j][i] = V[j][k];
00369         V[j][k] = p;
00370       }
00371     }
00372   }
00373 }
00374 //------------------------------------------------------------------------------
00375 void Eigenvalues::orthes()
00376 {
00377   //  This is derived from the Algol procedures orthes and ortran,
00378   //  by Martin and Wilkinson, Handbook for Auto. Comp.,
00379   //  Vol.ii-Linear Algebra, and the corresponding
00380   //  Fortran subroutines in EISPACK.
00381    
00382   int low = 0;
00383   int high = n-1;
00384 
00385   int i, j, m;
00386    
00387   for (m = low+1; m <= high-1; m++)
00388   {
00389     // Scale column.
00390     double scale = 0.0;
00391     for (i = m; i <= high; i++)
00392     {
00393       scale = scale + fabs(H[i][m-1]);
00394     }
00395     if (scale != 0.0)
00396     {
00397       // Compute Householder transformation.
00398       double h = 0.0;
00399       for (i = high; i >= m; i--)
00400       {
00401         ort[i] = H[i][m-1]/scale;
00402         h += ort[i] * ort[i];
00403       }
00404       double g = sqrt(h);
00405       if (ort[m] > 0)
00406       {
00407         g = -g;
00408       }
00409       h = h - ort[m] * g;
00410       ort[m] = ort[m] - g;
00411    
00412       // Apply Householder similarity transformation
00413       // H = (I-u*u'/h)*H*(I-u*u')/h)
00414    
00415       for (j = m; j < n; j++)
00416       {
00417         double f = 0.0;
00418         for (i = high; i >= m; i--)
00419         {
00420           f += ort[i]*H[i][j];
00421         }
00422         f = f/h;
00423         for (i = m; i <= high; i++)
00424         {
00425           H[i][j] -= f*ort[i];
00426         }
00427       }
00428    
00429       for (i = 0; i <= high; i++)
00430       {
00431         double f = 0.0;
00432         for (j = high; j >= m; j--)
00433         {
00434           f += ort[j]*H[i][j];
00435         }
00436         f = f/h;
00437         for (j = m; j <= high; j++)
00438         {
00439           H[i][j] -= f*ort[j];
00440         }
00441       }
00442       ort[m] = scale*ort[m];
00443       H[m][m-1] = scale*g;
00444     }
00445   }
00446    
00447   // Accumulate transformations (Algol's ortran).
00448   for (i = 0; i < n; i++)
00449   {
00450     for (j = 0; j < n; j++)
00451     {
00452       V[i][j] = (i == j ? 1.0 : 0.0);
00453     }
00454   }
00455 
00456   for (m = high-1; m >= low+1; m--)
00457   {
00458     if (H[m][m-1] != 0.0)
00459     {
00460       for (i = m+1; i <= high; i++)
00461       {
00462         ort[i] = H[i][m-1];
00463       }
00464       for (j = m; j <= high; j++)
00465       {
00466         double g = 0.0;
00467         for (i = m; i <= high; i++)
00468         {
00469           g += ort[i] * V[i][j];
00470         }
00471         // Double division avoids possible underflow
00472         g = (g / ort[m]) / H[m][m-1];
00473         for (i = m; i <= high; i++)
00474         {
00475           V[i][j] += g * ort[i];
00476         }
00477       }
00478     }
00479   }
00480 }
00481 //------------------------------------------------------------------------------
00482 void Eigenvalues::cdiv(double xr, double xi, double yr, double yi)
00483 {
00484   double r, d;
00485   if (fabs(yr) > fabs(yi))
00486   {
00487     r = yi/yr;
00488     d = yr + r*yi;
00489     cdivr = (xr + r*xi)/d;
00490     cdivi = (xi - r*xr)/d;
00491   }
00492   else
00493   {
00494     r = yr/yi;
00495     d = yi + r*yr;
00496     cdivr = (r*xr + xi)/d;
00497     cdivi = (r*xi - xr)/d;
00498   }
00499 }
00500 //------------------------------------------------------------------------------
00501 void Eigenvalues::hqr2()
00502 {
00503   //  This is derived from the Algol procedure hqr2,
00504   //  by Martin and Wilkinson, Handbook for Auto. Comp.,
00505   //  Vol.ii-Linear Algebra, and the corresponding
00506   //  Fortran subroutine in EISPACK.
00507 
00508   int i, j, k;
00509    
00510   // Initialize
00511   int nn = this->n;
00512   int n = nn-1;
00513   int low = 0;
00514   int high = nn-1;
00515   double eps = pow(2.0,-52.0);
00516   double exshift = 0.0;
00517   double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
00518    
00519   // Store roots isolated by balanc and compute matrix norm
00520   double norm = 0.0;
00521   for (i = 0; i < nn; i++)
00522   {
00523     if ((i < low) || (i > high))
00524     {
00525       d[i] = H[i][i];
00526       e[i] = 0.0;
00527     }
00528     for (j = ((i-1)>0)?i-1:0; j < nn; j++)
00529     {
00530       norm = norm + fabs(H[i][j]);
00531     }
00532   }
00533    
00534   // Outer loop over eigenvalue index
00535   int iter = 0;
00536   while (n >= low)
00537   {
00538     // Look for single small sub-diagonal element
00539     int l = n;
00540     while (l > low)
00541     {
00542       s = fabs(H[l-1][l-1]) + fabs(H[l][l]);
00543       if (s == 0.0)
00544       {
00545         s = norm;
00546       }
00547       if (fabs(H[l][l-1]) < eps * s)
00548       {
00549         break;
00550       }
00551       l--;
00552     }
00553        
00554     // Check for convergence
00555     // One root found
00556     if (l == n)
00557     {
00558       H[n][n] = H[n][n] + exshift;
00559       d[n] = H[n][n];
00560       e[n] = 0.0;
00561       n--;
00562       iter = 0;
00563    
00564       // Two roots found
00565     }
00566     else if (l == n-1)
00567     {
00568       w = H[n][n-1] * H[n-1][n];
00569       p = (H[n-1][n-1] - H[n][n]) / 2.0;
00570       q = p * p + w;
00571       z = sqrt(fabs(q));
00572       H[n][n] = H[n][n] + exshift;
00573       H[n-1][n-1] = H[n-1][n-1] + exshift;
00574       x = H[n][n];
00575   
00576       // Real pair
00577       if (q >= 0)
00578       {
00579         if (p >= 0)
00580         {
00581           z = p + z;
00582         }
00583         else
00584         {
00585           z = p - z;
00586         }
00587         d[n-1] = x + z;
00588         d[n] = d[n-1];
00589         if (z != 0.0)
00590         {
00591           d[n] = x - w / z;
00592         }
00593         e[n-1] = 0.0;
00594         e[n] = 0.0;
00595         x = H[n][n-1];
00596         s = fabs(x) + fabs(z);
00597         p = x / s;
00598         q = z / s;
00599         r = sqrt(p * p+q * q);
00600         p = p / r;
00601         q = q / r;
00602   
00603         // Row modification
00604         for (j = n-1; j < nn; j++)
00605         {
00606           z = H[n-1][j];
00607           H[n-1][j] = q * z + p * H[n][j];
00608           H[n][j] = q * H[n][j] - p * z;
00609         }
00610    
00611         // Column modification
00612         for (i = 0; i <= n; i++)
00613         {
00614           z = H[i][n-1];
00615           H[i][n-1] = q * z + p * H[i][n];
00616           H[i][n] = q * H[i][n] - p * z;
00617         }
00618    
00619         // Accumulate transformations
00620         for (i = low; i <= high; i++)
00621         {
00622           z = V[i][n-1];
00623           V[i][n-1] = q * z + p * V[i][n];
00624           V[i][n] = q * V[i][n] - p * z;
00625         }
00626    
00627         // Complex pair
00628       }
00629       else
00630       {
00631         d[n-1] = x + p;
00632         d[n] = x + p;
00633         e[n-1] = z;
00634         e[n] = -z;
00635       }
00636       n = n - 2;
00637       iter = 0;
00638    
00639       // No convergence yet
00640     }
00641     else
00642     {
00643       // Form shift
00644       x = H[n][n];
00645       y = 0.0;
00646       w = 0.0;
00647       if (l < n)
00648       {
00649         y = H[n-1][n-1];
00650         w = H[n][n-1] * H[n-1][n];
00651       }
00652    
00653       // Wilkinson's original ad hoc shift
00654       if (iter == 10)
00655       {
00656         exshift += x;
00657         for (i = low; i <= n; i++)
00658         {
00659           H[i][i] -= x;
00660         }
00661         s = fabs(H[n][n-1]) + fabs(H[n-1][n-2]);
00662         x = y = 0.75 * s;
00663         w = -0.4375 * s * s;
00664       }
00665 
00666       // MATLAB's new ad hoc shift
00667       if (iter == 30)
00668       {
00669         s = (y - x) / 2.0;
00670         s = s * s + w;
00671         if (s > 0)
00672         {
00673           s = sqrt(s);
00674           if (y < x)
00675           {
00676             s = -s;
00677           }
00678           s = x - w / ((y - x) / 2.0 + s);
00679           for (i = low; i <= n; i++)
00680           {
00681             H[i][i] -= s;
00682           }
00683           exshift += s;
00684           x = y = w = 0.964;
00685         }
00686       }
00687       iter = iter + 1;   // (Could check iteration count here.)
00688    
00689       // Look for two consecutive small sub-diagonal elements
00690       int m = n-2;
00691       while (m >= l)
00692       {
00693         z = H[m][m];
00694         r = x - z;
00695         s = y - z;
00696         p = (r * s - w) / H[m+1][m] + H[m][m+1];
00697         q = H[m+1][m+1] - z - r - s;
00698         r = H[m+2][m+1];
00699         s = fabs(p) + fabs(q) + fabs(r);
00700         p = p / s;
00701         q = q / s;
00702         r = r / s;
00703         if (m == l)
00704         {
00705           break;
00706         }
00707         if (fabs(H[m][m-1]) * (fabs(q) + fabs(r)) <
00708             eps * (fabs(p) * (fabs(H[m-1][m-1]) + fabs(z) +
00709               fabs(H[m+1][m+1]))))
00710         {
00711           break;
00712         }
00713         m--;
00714       }
00715    
00716       for (i = m+2; i <= n; i++)
00717       {
00718         H[i][i-2] = 0.0;
00719         if (i > m+2)
00720         {
00721           H[i][i-3] = 0.0;
00722         }
00723       }
00724    
00725       // Double QR step involving rows l:n and columns m:n
00726       for (k = m; k <= n-1; k++)
00727       {
00728         int notlast = (k != n-1);
00729         if (k != m)
00730         {
00731           p = H[k][k-1];
00732           q = H[k+1][k-1];
00733           r = (notlast ? H[k+2][k-1] : 0.0);
00734           x = fabs(p) + fabs(q) + fabs(r);
00735           if (x != 0.0)
00736           {
00737             p = p / x;
00738             q = q / x;
00739             r = r / x;
00740           }
00741         }
00742         if (x == 0.0)
00743         {
00744           break;
00745         }
00746         s = sqrt(p * p + q * q + r * r);
00747         if (p < 0)
00748         {
00749           s = -s;
00750         }
00751         if (s != 0)
00752         {
00753           if (k != m)
00754           {
00755             H[k][k-1] = -s * x;
00756           }
00757           else if (l != m)
00758           {
00759             H[k][k-1] = -H[k][k-1];
00760           }
00761           p = p + s;
00762           x = p / s;
00763           y = q / s;
00764           z = r / s;
00765           q = q / p;
00766           r = r / p;
00767   
00768           // Row modification
00769           for (j = k; j < nn; j++)
00770           {
00771             p = H[k][j] + q * H[k+1][j];
00772             if (notlast)
00773             {
00774               p = p + r * H[k+2][j];
00775               H[k+2][j] = H[k+2][j] - p * z;
00776             }
00777             H[k][j] = H[k][j] - p * x;
00778             H[k+1][j] = H[k+1][j] - p * y;
00779           }
00780    
00781           // Column modification
00782           int limit = (n<(k+3))?n:k+3;
00783           for (i = 0; i <= limit; i++)
00784           {
00785             p = x * H[i][k] + y * H[i][k+1];
00786             if (notlast)
00787             {
00788               p = p + z * H[i][k+2];
00789               H[i][k+2] = H[i][k+2] - p * r;
00790             }
00791             H[i][k] = H[i][k] - p;
00792             H[i][k+1] = H[i][k+1] - p * q;
00793           }
00794    
00795           // Accumulate transformations
00796           for (i = low; i <= high; i++)
00797           {
00798             p = x * V[i][k] + y * V[i][k+1];
00799             if (notlast)
00800             {
00801               p = p + z * V[i][k+2];
00802               V[i][k+2] = V[i][k+2] - p * r;
00803             }
00804             V[i][k] = V[i][k] - p;
00805             V[i][k+1] = V[i][k+1] - p * q;
00806           }
00807         }  // (s != 0)
00808       }  // k loop
00809     }  // check convergence
00810   }  // while (n >= low)
00811       
00812   // Backsubstitute to find vectors of upper triangular form
00813   if (norm == 0.0)
00814   {
00815     return;
00816   }
00817    
00818   for (n = nn-1; n >= 0; n--)
00819   {
00820     p = d[n];
00821     q = e[n];
00822    
00823     // Real vector
00824     if (q == 0)
00825     {
00826       int l = n;
00827       H[n][n] = 1.0;
00828       for (i = n-1; i >= 0; i--)
00829       {
00830         w = H[i][i] - p;
00831         r = 0.0;
00832         for (j = l; j <= n; j++)
00833         {
00834           r = r + H[i][j] * H[j][n];
00835         }
00836         if (e[i] < 0.0)
00837         {
00838           z = w;
00839           s = r;
00840         }
00841         else
00842         {
00843           l = i;
00844           if (e[i] == 0.0)
00845           {
00846             if (w != 0.0)
00847             {
00848               H[i][n] = -r / w;
00849             }
00850             else
00851             {
00852               H[i][n] = -r / (eps * norm);
00853             }
00854    
00855             // Solve real equations
00856           }
00857           else
00858           {
00859             x = H[i][i+1];
00860             y = H[i+1][i];
00861             q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
00862             t = (x * s - z * r) / q;
00863             H[i][n] = t;
00864             if (fabs(x) > fabs(z))
00865             {
00866               H[i+1][n] = (-r - w * t) / x;
00867             }
00868             else
00869             {
00870               H[i+1][n] = (-s - y * t) / z;
00871             }
00872           }
00873    
00874           // Overflow control
00875           t = fabs(H[i][n]);
00876           if ((eps * t) * t > 1)
00877           {
00878             for (j = i; j <= n; j++)
00879             {
00880               H[j][n] = H[j][n] / t;
00881             }
00882           }
00883         }
00884       }
00885    
00886       // Complex vector
00887     }
00888     else if (q < 0)
00889     {
00890       int l = n-1;
00891 
00892       // Last vector component imaginary so matrix is triangular
00893       if (fabs(H[n][n-1]) > fabs(H[n-1][n]))
00894       {
00895         H[n-1][n-1] = q / H[n][n-1];
00896         H[n-1][n] = -(H[n][n] - p) / H[n][n-1];
00897       }
00898       else
00899       {
00900         cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);
00901         H[n-1][n-1] = cdivr;
00902         H[n-1][n] = cdivi;
00903       }
00904       H[n][n-1] = 0.0;
00905       H[n][n] = 1.0;
00906       for (i = n-2; i >= 0; i--)
00907       {
00908         double ra,sa,vr,vi;
00909         ra = 0.0;
00910         sa = 0.0;
00911         for (j = l; j <= n; j++)
00912         {
00913           ra = ra + H[i][j] * H[j][n-1];
00914           sa = sa + H[i][j] * H[j][n];
00915         }
00916         w = H[i][i] - p;
00917    
00918         if (e[i] < 0.0)
00919         {
00920           z = w;
00921           r = ra;
00922           s = sa;
00923         }
00924         else
00925         {
00926           l = i;
00927           if (e[i] == 0)
00928           {
00929             cdiv(-ra,-sa,w,q);
00930             H[i][n-1] = cdivr;
00931             H[i][n] = cdivi;
00932           }
00933           else
00934           {
00935             // Solve complex equations
00936             x = H[i][i+1];
00937             y = H[i+1][i];
00938             vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
00939             vi = (d[i] - p) * 2.0 * q;
00940             if ((vr == 0.0) && (vi == 0.0))
00941             {
00942               vr = eps * norm * (fabs(w) + fabs(q) +
00943                         fabs(x) + fabs(y) + fabs(z));
00944             }
00945             cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
00946             H[i][n-1] = cdivr;
00947             H[i][n] = cdivi;
00948             if (fabs(x) > (fabs(z) + fabs(q)))
00949             {
00950               H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;
00951               H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;
00952             }
00953             else
00954             {
00955               cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);
00956               H[i+1][n-1] = cdivr;
00957               H[i+1][n] = cdivi;
00958             }
00959           }
00960    
00961           // Overflow control
00962           double t1 = fabs(H[i][n-1]);
00963           double t2 = fabs(H[i][n]);
00964           t = (t1>t2)?t1:t2;
00965           if ((eps * t) * t > 1)
00966           {
00967             for (j = i; j <= n; j++)
00968             {
00969               H[j][n-1] = H[j][n-1] / t;
00970               H[j][n] = H[j][n] / t;
00971             }
00972           }
00973         }
00974       }
00975     }
00976   }
00977    
00978   // Vectors of isolated roots
00979   for (i = 0; i < nn; i++)
00980   {
00981     if (i < low || i > high)
00982     {
00983       for (j = i; j < nn; j++)
00984       {
00985         V[i][j] = H[i][j];
00986       }
00987     }
00988   }
00989    
00990   // Back transformation to get eigenvectors of original matrix
00991   for (j = nn-1; j >= low; j--)
00992   {
00993     for (i = low; i <= high; i++)
00994     {
00995       z = 0.0;
00996       int limit = (j<high)?j:high;
00997       for (k = low; k <= limit; k++)
00998       {
00999         z = z + V[i][k] * H[k][j];
01000       }
01001       V[i][j] = z;
01002     }
01003   }
01004 }
01005 //------------------------------------------------------------------------------
01006 }
01007 //------------------------------------------------------------------------------

Generated on Mon Mar 20 22:00:06 2006 for GT2005 by doxygen 1.3.6