Main Page   Data Structures   File List   Data Fields   Globals  

eigen.c

Go to the documentation of this file.
00001 #include        "sadie.h"
00002 
00003 /*-Copyright Information------------------------------------------------------*/
00004 /* Copyright (c) 1988 by the University of Arizona Digital Image Analysis Lab */
00005 /*----------------------------------------------------------------------------*/
00006 /*-General Information--------------------------------------------------------*/
00007 /*                                                                            */
00008 /*   This low-level function computes the eigenvalues and eigenvectors of a   */
00009 /*   symmetric matrix.                                                        */
00010 /*                                                                            */
00011 /*----------------------------------------------------------------------------*/
00012 /*-Background Information-----------------------------------------------------*/
00013 /*                                                                            */
00014 /*   Davis, J.C.:                                                             */
00015 /*   "Statistics and Data Analysis in Geology."                               */
00016 /*   J. Wiley & Sons, New York, 1986                                          */
00017 /*                                                                            */
00018 /*----------------------------------------------------------------------------*/
00019 /*-Interface Information------------------------------------------------------*/
00020 void EIGEN (
00021 double *mat,    /*  I   Pointer to the symmetric input matrix[size][size].    */
00022 short  size,    /*  I   Size of the matrix.                                   */
00023 double *eig     /*  O   Pointer to the eigenvector matrix[size][size].        */
00024 /*----------------------------------------------------------------------------*/
00025 ) { register short i, j, k, found;
00026     char   msg[SLEN];
00027     double norm, thr, al, am, ao, sine, sinsq, cosine, cossq, at, bt, xt, temp;
00028 
00029     if (TIMES) TIMING(T_EIGEN);
00030 
00031     /* set eig to identity matrix */
00032     for (norm=0.0,i=0; i<size; i++) {
00033         for (j=0; j<size; j++) {
00034             if (i == j) {
00035                 eig[i*size+j] = 1.0;
00036             } else {
00037                 eig[i*size+j] = 0.0;
00038                 norm += mat[i*size+j]*mat[i*size+j];
00039             }
00040         }
00041     }
00042 
00043     /* iterate */
00044     thr  =         sqrt(norm);
00045     norm = 1.0E-09*sqrt(norm)/(double)size;
00046     do {
00047         thr /= (double)size;
00048         do {
00049 
00050             /* scan down columns for off-diagonal elements greater than or equal to threshold */
00051             for (found=FALSE,i=1; i<size; i++) {
00052                 for (j=0; j<i; j++) {
00053                     if (thr <= fabs(mat[j*size+i])) {
00054 
00055                         /* compute sines and cosines */
00056                         found = TRUE;
00057                         al = -mat[j*size+i];
00058                         am = (mat[j*size+j]-mat[i*size+i])/2.0;
00059                         ao = am < 0.0  ?  -al/sqrt(al*al+am*am) : al/sqrt(al*al+am*am);
00060                         sine   = ao/sqrt(2.0*(1.0+sqrt(1.0-ao*ao)));
00061                         sinsq  = sine*sine;
00062                         cosine = sqrt(1.0-sinsq);
00063                         cossq  = cosine*cosine;
00064 
00065                         /* rotate columns i and j */
00066                         for (k=0; k<size; k++) {
00067                             if (k != i  &&  k != j) {
00068                                 at = mat[k*size+j];
00069                                 mat[k*size+j] = at*cosine - mat[k*size+i]*sine;
00070                                 mat[k*size+i] = at*sine + mat[k*size+i]*cosine;
00071                             }
00072                             bt = eig[k*size+j];
00073                             eig[k*size+j] = bt*cosine - eig[k*size+i]*sine;
00074                             eig[k*size+i] = bt*sine + eig[k*size+i]*cosine;
00075                         }
00076                         at = mat[j*size+j];
00077                         bt = mat[i*size+i];
00078                         xt = 2.0*mat[j*size+i]*sine*cosine;
00079                         mat[j*size+j] = at*cossq + bt*sinsq - xt;
00080                         mat[i*size+i] = at*sinsq + bt*cossq + xt;
00081                         mat[i*size+j] = mat[j*size+i] = (at-bt)*sine*cosine + mat[j*size+i]*(cossq-sinsq);
00082                         for (k=0; k<size; k++) {
00083                             mat[j*size+k] = mat[k*size+j];
00084                             mat[i*size+k] = mat[k*size+i];
00085                         }
00086                     }
00087                 }
00088             }
00089         } while (found);
00090     } while (thr > norm);
00091 
00092     /* sort eigenvalues and eigenvectors */
00093     for (i=1; i<size; i++) {
00094         for (j=i; j>0; j--) {
00095             if (mat[(j-1)*size+j-1] < mat[j*size+j]) {
00096                 temp = mat[(j-1)*size+j-1];
00097                 mat[(j-1)*size+j-1] = mat[j*size+j];
00098                 mat[j*size+j] = temp;
00099                 for (k=0; k<size; k++) {
00100                     temp = eig[k*size+j-1];
00101                     eig[k*size+j-1] = eig[k*size+j];
00102                     eig[k*size+j] = temp;
00103                 }
00104             }
00105         }
00106     }
00107 
00108     /* output eigenvalues and eigenvectors */
00109     MESSAGE('I',"");
00110     MESSAGE('I'," Eigenvalues        Eigenvectors");
00111     for (i=0; i<size; i++) {
00112         sprintf(msg," %d   %11.4e     ",i+1,mat[i*size+i]);
00113         for (j=0; j<size; j+=1) {
00114             sprintf(msg+strlen(msg),"%12.4e",eig[j*size+i]);
00115         }
00116         MESSAGE('I',msg);
00117     }
00118 
00119     the_end:
00120     if (TIMES) TIMING(T_EXIT);
00121 }

Generated on Wed Apr 9 08:56:05 2003 for TREES by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002