cmtkEigenSystemSymmetricMatrix3x3.txx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //  Copyright 2004-2009 SRI International
00005 //
00006 //  This file is part of the Computational Morphometry Toolkit.
00007 //
00008 //  http://www.nitrc.org/projects/cmtk/
00009 //
00010 //  The Computational Morphometry Toolkit is free software: you can
00011 //  redistribute it and/or modify it under the terms of the GNU General Public
00012 //  License as published by the Free Software Foundation, either version 3 of
00013 //  the License, or (at your option) any later version.
00014 //
00015 //  The Computational Morphometry Toolkit is distributed in the hope that it
00016 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00017 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 //  GNU General Public License for more details.
00019 //
00020 //  You should have received a copy of the GNU General Public License along
00021 //  with the Computational Morphometry Toolkit.  If not, see
00022 //  <http://www.gnu.org/licenses/>.
00023 //
00024 //  $Revision: 1317 $
00025 //
00026 //  $LastChangedDate: 2010-03-10 14:08:16 -0800 (Wed, 10 Mar 2010) $
00027 //
00028 //  $LastChangedBy: torstenrohlfing $
00029 //
00030 */
00031 
00032 namespace
00033 cmtk
00034 {
00035 
00038 
00039 template<class TFloat>
00040 EigenSystemSymmetricMatrix3x3<TFloat>
00041 ::EigenSystemSymmetricMatrix3x3( const Matrix3x3<TFloat>& matrix, const bool sortAbsolute )
00042 {
00043   TFloat e[3];
00044   for (int i = 0; i < 3; i++) 
00045     {
00046     for (int j = 0; j < 3; j++) 
00047       {
00048       this->m_Eigenvectors[i][j] = matrix[i][j];
00049       }
00050     }
00051   tred2( this->m_Eigenvectors, this->m_Eigenvalues, e);
00052   tql2( this->m_Eigenvectors, this->m_Eigenvalues, e, sortAbsolute );
00053 }
00054 
00055 template<class TFloat>
00056 TFloat
00057 EigenSystemSymmetricMatrix3x3<TFloat>
00058 ::hypot2( const TFloat& x, const TFloat& y) 
00059 {
00060   return sqrt(x*x+y*y);
00061 }
00062 
00063 template<class TFloat>
00064 void 
00065 EigenSystemSymmetricMatrix3x3<TFloat>
00066 ::tred2( TFloat V[3][3], TFloat d[3], TFloat e[3] ) 
00067 {
00068 //  This is derived from the Algol procedures tred2 by
00069 //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
00070 //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
00071 //  Fortran subroutine in EISPACK.
00072   
00073   for (int j = 0; j < 3; j++) 
00074     {
00075     d[j] = V[2][j];
00076     }
00077   
00078   // Householder reduction to tridiagonal form.
00079   
00080   for (int i = 2; i > 0; i--) 
00081     {    
00082     // Scale to avoid under/overflow.
00083     
00084     TFloat scale = 0.0;
00085     TFloat h = 0.0;
00086     for (int k = 0; k < i; k++) 
00087       {
00088       scale = scale + fabs(d[k]);
00089       }
00090     if (scale == 0.0) 
00091       {
00092       e[i] = d[i-1];
00093       for (int j = 0; j < i; j++) 
00094         {
00095         d[j] = V[i-1][j];
00096         V[i][j] = 0.0;
00097         V[j][i] = 0.0;
00098         }
00099       } 
00100     else 
00101       {
00102       // Generate Householder vector.
00103       
00104       for (int k = 0; k < i; k++) 
00105         {
00106         d[k] /= scale;
00107         h += d[k] * d[k];
00108         }
00109       TFloat f = d[i-1];
00110       TFloat g = sqrt(h);
00111       if (f > 0) 
00112         {
00113         g = -g;
00114         }
00115       e[i] = scale * g;
00116       h = h - f * g;
00117       d[i-1] = f - g;
00118       for (int j = 0; j < i; j++) 
00119         {
00120         e[j] = 0.0;
00121         }
00122       
00123       // Apply similarity transformation to remaining columns.
00124 
00125       for (int j = 0; j < i; j++) 
00126         {
00127         f = d[j];
00128         V[j][i] = f;
00129         g = e[j] + V[j][j] * f;
00130         for (int k = j+1; k <= i-1; k++) 
00131           {
00132           g += V[k][j] * d[k];
00133           e[k] += V[k][j] * f;
00134           }
00135         e[j] = g;
00136         }
00137       f = 0.0;
00138       for (int j = 0; j < i; j++) 
00139         {
00140         e[j] /= h;
00141         f += e[j] * d[j];
00142         }
00143       TFloat hh = f / (h + h);
00144       for (int j = 0; j < i; j++) 
00145         {
00146         e[j] -= hh * d[j];
00147         }
00148       for (int j = 0; j < i; j++) 
00149         {
00150         f = d[j];
00151         g = e[j];
00152         for (int k = j; k <= i-1; k++) 
00153           {
00154           V[k][j] -= (f * e[k] + g * d[k]);
00155           }
00156         d[j] = V[i-1][j];
00157         V[i][j] = 0.0;
00158         }
00159       }
00160     d[i] = h;
00161     }
00162   
00163   // Accumulate transformations.
00164   
00165   for (int i = 0; i < 2; i++) 
00166     {
00167     V[2][i] = V[i][i];
00168     V[i][i] = 1.0;
00169     TFloat h = d[i+1];
00170     if (h != 0.0)
00171       {
00172       for (int k = 0; k <= i; k++) 
00173         {
00174         d[k] = V[k][i+1] / h;
00175         }
00176       for (int j = 0; j <= i; j++) 
00177         {
00178         TFloat g = 0.0;
00179         for (int k = 0; k <= i; k++) 
00180           {
00181           g += V[k][i+1] * V[k][j];
00182           }
00183         for (int k = 0; k <= i; k++) 
00184           {
00185           V[k][j] -= g * d[k];
00186           }
00187         }
00188       }
00189     for (int k = 0; k <= i; k++) 
00190       {
00191       V[k][i+1] = 0.0;
00192       }
00193     }
00194   for (int j = 0; j < 3; j++) 
00195     {
00196     d[j] = V[2][j];
00197     V[2][j] = 0.0;
00198     }
00199   V[2][2] = 1.0;
00200   e[0] = 0.0;
00201 } 
00202 
00203 template<class TFloat>
00204 void 
00205 EigenSystemSymmetricMatrix3x3<TFloat>
00206 ::tql2(TFloat V[3][3], TFloat d[3], TFloat e[3], const bool sortAbsolute) 
00207 {
00208 //  This is derived from the Algol procedures tql2, by
00209 //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
00210 //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
00211 //  Fortran subroutine in EISPACK.
00212   
00213   for (int i = 1; i < 3; i++) 
00214     {
00215     e[i-1] = e[i];
00216     }
00217   e[2] = 0.0;
00218   
00219   TFloat f = 0.0;
00220   TFloat tst1 = 0.0;
00221   TFloat eps = pow(2.0,-52.0);
00222   for (int l = 0; l < 3; l++) 
00223     {
00224     // Find small subdiagonal element
00225     
00226     tst1 = ( tst1 > fabs( d[l]) + fabs(e[l]) ) ? tst1 : fabs( d[l]) + fabs(e[l]) ;
00227     int m = l;
00228     while (m < 3) 
00229       {
00230       if (fabs(e[m]) <= eps*tst1) 
00231         {
00232         break;
00233         }
00234       m++;
00235       }
00236     
00237     // If m == l, d[l] is an eigenvalue,
00238     // otherwise, iterate.
00239     
00240     if (m > l) 
00241       {
00242       int iter = 0;
00243       do 
00244         {
00245         iter = iter + 1;  // (Could check iteration count here.)
00246         
00247         // Compute implicit shift
00248         
00249         TFloat g = d[l];
00250         TFloat p = (d[l+1] - g) / (2.0 * e[l]);
00251         TFloat r = hypot2(p,1.0);
00252         if (p < 0) 
00253           {
00254           r = -r;
00255           }
00256         d[l] = e[l] / (p + r);
00257         d[l+1] = e[l] * (p + r);
00258         TFloat dl1 = d[l+1];
00259         TFloat h = g - d[l];
00260         for (int i = l+2; i < 3; i++) 
00261           {
00262           d[i] -= h;
00263           }
00264         f = f + h;
00265         
00266         // Implicit QL transformation.
00267         
00268         p = d[m];
00269         TFloat c = 1.0;
00270         TFloat c2 = c;
00271         TFloat c3 = c;
00272         TFloat el1 = e[l+1];
00273         TFloat s = 0.0;
00274         TFloat s2 = 0.0;
00275         for (int i = m-1; i >= l; i--) 
00276           {
00277           c3 = c2;
00278           c2 = c;
00279           s2 = s;
00280           g = c * e[i];
00281           h = c * p;
00282           r = hypot2(p,e[i]);
00283           e[i+1] = s * r;
00284           s = e[i] / r;
00285           c = p / r;
00286           p = c * d[i] - s * g;
00287           d[i+1] = h + s * (c * g + s * d[i]);
00288           
00289           // Accumulate transformation.
00290           
00291           for (int k = 0; k < 3; k++) 
00292             {
00293             h = V[k][i+1];
00294             V[k][i+1] = s * V[k][i] + c * h;
00295             V[k][i] = c * V[k][i] - s * h;
00296             }
00297           }
00298         p = -s * s2 * c3 * el1 * e[l] / dl1;
00299         e[l] = s * p;
00300         d[l] = c * p;
00301         
00302         // Check for convergence.
00303         
00304         } 
00305       while (fabs(e[l]) > eps*tst1);
00306       }
00307     d[l] = d[l] + f;
00308     e[l] = 0.0;
00309     }
00310   
00311   // Sort eigenvalues and corresponding vectors.
00312   
00313   for (int i = 0; i < 2; i++) 
00314     {
00315     int k = i;
00316     TFloat p = d[i];
00317     for (int j = i+1; j < 3; j++) 
00318       {
00319       const bool swap = sortAbsolute ? (fabs(d[j]) < fabs(p)) : (d[j] < p);
00320       if ( swap ) 
00321         {
00322         k = j;
00323         p = d[j];
00324         }
00325       }
00326     if (k != i) 
00327       {
00328       d[k] = d[i];
00329       d[i] = p;
00330       for (int j = 0; j < 3; j++) 
00331         {
00332         p = V[j][i];
00333         V[j][i] = V[j][k];
00334         V[j][k] = p;
00335         }
00336       }
00337     }
00338 }
00339 
00340 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines