Blender V2.61 - r43446

EIGENVALUE_HELPER.cpp

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