eigensystems.h

00001 #ifndef Eigensystems_H
00002 #define Eigensystems_H
00003 
00004 #include  <math.h>
00005 #include "util.h"
00006 
00007 #define ROTATE( a, i, j, k, l) g=a[i][j]; h=a[k][l];a[i][j]=g-s*(h+g*tau); a[k][l]=h+s*(g-h*tau);
00008 
00009 void jacobi( TMatrix a, int n, Value_Type d[], TMatrix v, int *nrot )
00010 /* Computes all eigenvalues and eigenvectors of a real symmetric matrix a[1..n][1..n].
00011    On output, elements of a above the diagonal are destroyed. d[1..n] returns the 
00012    eigenvalues of a. v[1..n][1..n] is a matrix whose columns contain, on output, 
00013    the normalized eigenvectors of a.  nrot returns the number of Jacobi rotations that were 
00014    required.
00015 
00016   Ref. Press et al., "Numerical Recipes in C", 1988. Pages 467-469. */
00017 {
00018         int j, iq, ip, i;
00019         Value_Type tresh, theta, tau, t, sm, s, h, g, c, *b, *z;
00020 
00021         b = create_vector(1, n );
00022         z = create_vector(1, n);
00023         for (ip=1; ip<=n; ip++) {
00024                 for (iq=1; iq<=n; iq++) v[ip][iq] = 0.0;
00025                 v[ip][ip] = 1.0;
00026         };
00027         for (ip=1; ip<=n; ip++) {
00028                 b[ip] = d[ip] = a[ip][ip];
00029                 z[ip] = 0.0;
00030         };
00031 //      *nrot = 0;
00032         for (i=1; i<= 50; i++) {
00033                 sm = 0.0;
00034                 for (ip=1; ip<=n-1; ip++) {
00035                         for (iq=ip+1; iq<=n; iq++)
00036                                 sm += fabs( a[ip][iq] );
00037                 };
00038                 if ( sm == 0.0 ) {
00039                         free_vector( z, 1, n );
00040                         free_vector( b, 1, n );
00041                         return;
00042                 };
00043                 if ( i < 4 )
00044                         tresh = 0.2*sm/(n*n);
00045                 else
00046                         tresh = 0.0;
00047                 for (ip=1; ip<=n-1; ip++) {
00048                         for (iq=ip+1; iq<=n; iq++) {
00049                                 g = 100.0*fabs( a[ip][iq]);
00050                                 if ( i > 4 && (Value_Type)(fabs(d[ip])+g) == (Value_Type)fabs(d[ip]) && (Value_Type)(fabs(d[iq])+g) == (Value_Type)fabs(d[iq]))
00051                                         a[ip][iq] = 0.0;
00052                                 else if (fabs(a[ip][iq]) > tresh) {
00053                                         h = d[iq]-d[ip];
00054                                         if ((Value_Type)(fabs(h)+g) == (Value_Type)fabs(h))
00055                                                 t = (a[ip][iq])/h;
00056                                         else {
00057                                                 theta = 0.5*h/(a[ip][iq]);
00058                                                 t = 1.0/(fabs(theta)+sqrt( 1.0+theta*theta));
00059                                                 if (theta < 0.0) t = -t;
00060                                         }
00061                                         c = 1.0/sqrt(1+t*t);
00062                                         s = t*c;
00063                                         tau = s/(1.0 + c);
00064                                         h = t*a[ip][iq];
00065                                         z[ip] -= h;
00066                                         z[iq] += h;
00067                                         d[ip] -= h;
00068                                         d[iq] += h;
00069                                         a[ip][iq] = 0.0;
00070                                         for ( j=1; j<ip-1; j++) {
00071                                                 ROTATE( a, j, ip, j, iq );
00072                                         }
00073                                         for (j=ip+1; j<= iq-1; j++) {
00074                                                 ROTATE( a, ip, j, j, iq );
00075                                         }
00076                                         for (j=iq+1; j<=n; j++) {
00077                                                 ROTATE( a, ip, j, iq, j);
00078                                         }
00079                                         for (j=1; j<=n; j++ ) {
00080                                                 ROTATE(v, j, ip, j, iq );
00081                                         }
00082                                         //++(*nrot);
00083                                 }
00084 
00085                         };
00086                 };
00087                 for (ip=1; ip<=n; ip++)  {
00088                         b[ip] += z[ip];
00089                         d[ip] = b[ip];
00090                         z[ip] = 0.0;
00091                 }
00092         };
00093 };
00094 
00095 
00096 
00097 void eigsrt( Value_Type d[], TMatrix v, int n )
00098 /* Given the eigenvalues d[1..n] and eigenvectors v[1..n][1..n] as output from
00099    jacobi, this routine sorts the eigenvalues into descendenting order, and 
00100    rearranges the columns of v correspondingly. */
00101 {
00102         int k, j, i;
00103         Value_Type p;
00104 
00105         for (i=1; i<n; i++) {
00106                 p = d[k=i];
00107                 for (j=i+1; j<=n; j++ )
00108                         if ( d[j] >= p) p = d[k=j];
00109                         if (k != i ) {
00110                                 d[k] = d[i];
00111                                 d[i] = p;
00112                                 for (j=1; j<=n; j++) {
00113                                         p = v[j][i];
00114                                         v[j][i] = v[j][k];
00115                                         v[j][k] = p;
00116                                 };
00117                         };
00118         };
00119 };
00120 
00121 #endif

Generated on Tue Aug 7 16:03:33 2007 for SOMCode by  doxygen 1.5.3