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
00021 EIGEN (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   )
00026 {
00027   register short i, j, k, found;
00028   char msg[SLEN];
00029   double norm, thr, al, am, ao, sine, sinsq, cosine, cossq, at, bt, xt, temp;
00030 
00031   if (TIMES)
00032     TIMING (T_EIGEN);
00033 
00034   /* set eig to identity matrix */
00035   for (norm = 0.0, i = 0; i < size; i++)
00036     {
00037       for (j = 0; j < size; j++)
00038         {
00039           if (i == j)
00040             {
00041               eig[i * size + j] = 1.0;
00042             }
00043           else
00044             {
00045               eig[i * size + j] = 0.0;
00046               norm += mat[i * size + j] * mat[i * size + j];
00047             }
00048         }
00049     }
00050 
00051   /* iterate */
00052   thr = sqrt (norm);
00053   norm = 1.0E-09 * sqrt (norm) / (double) size;
00054   do
00055     {
00056       thr /= (double) size;
00057       do
00058         {
00059 
00060           /* scan down columns for off-diagonal elements greater than or equal to threshold */
00061           for (found = FALSE, i = 1; i < size; i++)
00062             {
00063               for (j = 0; j < i; j++)
00064                 {
00065                   if (thr <= fabs (mat[j * size + i]))
00066                     {
00067 
00068                       /* compute sines and cosines */
00069                       found = TRUE;
00070                       al = -mat[j * size + i];
00071                       am = (mat[j * size + j] - mat[i * size + i]) / 2.0;
00072                       ao =
00073                         am <
00074                         0.0 ? -al / sqrt (al * al +
00075                                           am * am) : al / sqrt (al * al +
00076                                                                 am * am);
00077                       sine = ao / sqrt (2.0 * (1.0 + sqrt (1.0 - ao * ao)));
00078                       sinsq = sine * sine;
00079                       cosine = sqrt (1.0 - sinsq);
00080                       cossq = cosine * cosine;
00081 
00082                       /* rotate columns i and j */
00083                       for (k = 0; k < size; k++)
00084                         {
00085                           if (k != i && k != j)
00086                             {
00087                               at = mat[k * size + j];
00088                               mat[k * size + j] =
00089                                 at * cosine - mat[k * size + i] * sine;
00090                               mat[k * size + i] =
00091                                 at * sine + mat[k * size + i] * cosine;
00092                             }
00093                           bt = eig[k * size + j];
00094                           eig[k * size + j] =
00095                             bt * cosine - eig[k * size + i] * sine;
00096                           eig[k * size + i] =
00097                             bt * sine + eig[k * size + i] * cosine;
00098                         }
00099                       at = mat[j * size + j];
00100                       bt = mat[i * size + i];
00101                       xt = 2.0 * mat[j * size + i] * sine * cosine;
00102                       mat[j * size + j] = at * cossq + bt * sinsq - xt;
00103                       mat[i * size + i] = at * sinsq + bt * cossq + xt;
00104                       mat[i * size + j] = mat[j * size + i] =
00105                         (at - bt) * sine * cosine + mat[j * size +
00106                                                         i] * (cossq - sinsq);
00107                       for (k = 0; k < size; k++)
00108                         {
00109                           mat[j * size + k] = mat[k * size + j];
00110                           mat[i * size + k] = mat[k * size + i];
00111                         }
00112                     }
00113                 }
00114             }
00115         }
00116       while (found);
00117     }
00118   while (thr > norm);
00119 
00120   /* sort eigenvalues and eigenvectors */
00121   for (i = 1; i < size; i++)
00122     {
00123       for (j = i; j > 0; j--)
00124         {
00125           if (mat[(j - 1) * size + j - 1] < mat[j * size + j])
00126             {
00127               temp = mat[(j - 1) * size + j - 1];
00128               mat[(j - 1) * size + j - 1] = mat[j * size + j];
00129               mat[j * size + j] = temp;
00130               for (k = 0; k < size; k++)
00131                 {
00132                   temp = eig[k * size + j - 1];
00133                   eig[k * size + j - 1] = eig[k * size + j];
00134                   eig[k * size + j] = temp;
00135                 }
00136             }
00137         }
00138     }
00139 
00140   /* output eigenvalues and eigenvectors */
00141   MESSAGE ('I', "");
00142   MESSAGE ('I', " Eigenvalues        Eigenvectors");
00143   for (i = 0; i < size; i++)
00144     {
00145       sprintf (msg, " %d   %11.4e     ", i + 1, mat[i * size + i]);
00146       for (j = 0; j < size; j += 1)
00147         {
00148           sprintf (msg + strlen (msg), "%12.4e", eig[j * size + i]);
00149         }
00150       MESSAGE ('I', msg);
00151     }
00152 
00153 the_end:
00154   if (TIMES)
00155     TIMING (T_EXIT);
00156 }

Generated on Sun May 18 15:36:09 2003 for tclSadie by doxygen1.3