Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages | Examples

feigen.cpp

Go to the documentation of this file.
00001 //http://perso.orange.fr/jean-pierre.moreau/c_matrices.html
00002 /* ----------------------- MODULE feigen.cpp ------------------------ *
00003  * Reference: "Numerical Algorithms with C By G. Engeln-Mueller and   *
00004  *             F. Uhlig, Springer-Verlag, 1996" [BIBLI 11].           *
00005  * ------------------------------------------------------------------ */
00006 #include <basis.h>
00007 #include <vmblock.h>
00008 
00009 
00010 #define MAXIT 50                      /*  Maximal number of           */
00011                                       /*  iterations per eigenvalue   */
00012 
00013 /*--------------------------------------------------------------------*
00014  * Auxiliary functions for  eigen                                     *
00015  *--------------------------------------------------------------------*/
00016 
00017 
00018 static int balance       /* balance a matrix .........................*/
00019                    (int       n,      /* size of matrix ..............*/
00020                     REAL *    mat[],  /* matrix ......................*/
00021                     REAL      scal[], /* Scaling data ................*/
00022                     int *     low,    /* first relevant row index ....*/
00023                     int *     high,   /* last relevant row index .....*/
00024                     int       basis   /* base of computer numbers ....*/
00025                    )
00026 /*====================================================================*
00027  *                                                                    *
00028  *  balance balances the matrix mat so that the rows with zero entries*
00029  *  off the diagonal are isolated and the remaining columns and rows  *
00030  *  are resized to have one norm close to 1.                          *
00031  *                                                                    *
00032  *====================================================================*
00033  *                                                                    *
00034  *   Input parameters:                                                *
00035  *   ================                                                 *
00036  *      n        int n;  ( n > 0 )                                    *
00037  *               Dimension of mat                                     *
00038  *      mat      REAL   *mat[n];                                      *
00039  *               n x n input matrix                                   *
00040  *      basis    int basis;                                           *
00041  *               Base of number representaion in the given computer   *
00042  *               (see BASIS)                                          *
00043  *                                                                    *
00044  *   Output parameters:                                               *
00045  *   ==================                                               *
00046  *      mat      REAL   *mat[n];                                      *
00047  *               scaled matrix                                        *
00048  *      low      int *low;                                            *
00049  *      high     int *high;                                           *
00050  *               the rows 0 to low-1 and those from high to n-1       *
00051  *               contain isolated eigenvalues (only nonzero entry on  *
00052  *               the diagonal)                                        *
00053  *      scal     REAL   scal[];                                       *
00054  *               the vector scal contains the isolated eigenvalues in *
00055  *               the positions 0 to low-1 and high to n-1, its other  *
00056  *               components contain the scaling factors for           *
00057  *               transforming mat.                                    *
00058  *                                                                    *
00059  *====================================================================*
00060  *                                                                    *
00061  *   Macros:     SWAP, ABS                                            *
00062  *   =======                                                          *
00063  *                                                                    *
00064  *====================================================================*
00065  *                                                                    *
00066  *   Constants used:     TRUE, FALSE                                  *
00067  *   ==============                                                   *
00068  *                                                                    *
00069  *====================================================================*/
00070 {
00071   register int i, j;
00072   int      iter, k, m;
00073   REAL     b2, r, c, f, g, s;
00074 
00075   b2 = (REAL) (basis * basis);
00076   m = 0;
00077   k = n - 1;
00078 
00079   do
00080   {
00081     iter = FALSE;
00082     for (j = k; j >= 0; j--)
00083     {
00084       for (r = ZERO, i = 0; i <= k; i++)
00085         if (i != j)  r += ABS (mat[j][i]);
00086 
00087       if (r == ZERO)
00088       {
00089         scal[k] = (REAL) j;
00090         if (j != k)
00091         {
00092           for (i = 0; i <= k; i++) SWAP (REAL, mat[i][j], mat[i][k])
00093           for (i = m; i < n; i++)  SWAP (REAL, mat[j][i], mat[k][i])
00094         }
00095         k--;
00096         iter = TRUE;
00097       }
00098     }   /* end of j */
00099   }   /* end of do  */
00100   while (iter);
00101 
00102   do
00103   {
00104     iter = FALSE;
00105     for (j = m; j <= k; j++)
00106     {
00107       for (c = ZERO, i = m; i <= k; i++)
00108         if (i != j) c += ABS (mat[i][j]);
00109       if (c == ZERO)
00110       {
00111         scal[m] = (REAL) j;
00112         if ( j != m )
00113         {
00114           for (i = 0; i <= k; i++) SWAP (REAL, mat[i][j], mat[i][m])
00115           for (i = m; i < n; i++)  SWAP (REAL, mat[j][i], mat[m][i])
00116         }
00117         m++;
00118         iter = TRUE;
00119       }
00120     }   /* end of j */
00121   }   /* end of do  */
00122   while (iter);
00123 
00124   *low = m;
00125   *high = k;
00126   for (i = m; i <= k; i++) scal[i] = ONE;
00127 
00128   do
00129   {
00130     iter = FALSE;
00131     for (i = m; i <= k; i++)
00132     {
00133       for (c = r = ZERO, j = m; j <= k; j++)
00134       if (j !=i)
00135       {
00136         c += ABS (mat[j][i]);
00137         r += ABS (mat[i][j]);
00138       }
00139       g = r / basis;
00140       f = ONE;
00141       s = c + r;
00142 
00143       while (c < g)
00144       {
00145         f *= basis;
00146         c *= b2;
00147       }
00148 
00149       g = r * basis;
00150       while (c >= g)
00151       {
00152         f /= basis;
00153         c /= b2;
00154       }
00155 
00156       if ((c + r) / f < (REAL)0.95 * s)
00157       {
00158         g = ONE / f;
00159         scal[i] *= f;
00160         iter = TRUE;
00161         for (j = m; j < n; j++ ) mat[i][j] *= g;
00162         for (j = 0; j <= k; j++ ) mat[j][i] *= f;
00163       }
00164     }
00165   }
00166   while (iter);
00167 
00168   return (0);
00169 }
00170 
00171 
00172 static int balback       /* reverse balancing ........................*/
00173                    (int     n,        /* Dimension of matrix .........*/
00174                     int     low,      /* first nonzero row ...........*/
00175                     int     high,     /* last nonzero row ............*/
00176                     REAL    scal[],   /* Scaling data ................*/
00177                     REAL *  eivec[]   /* Eigenvectors ................*/
00178                    )
00179 /*====================================================================*
00180  *                                                                    *
00181  *  balback reverses the balancing of balance for the eigenvactors.   *
00182  *                                                                    *
00183  *====================================================================*
00184  *                                                                    *
00185  *   Input parameters:                                                *
00186  *   ================                                                 *
00187  *      n        int n;  ( n > 0 )                                    *
00188  *               Dimension of mat                                     *
00189  *      low      int low;                                             *
00190  *      high     int high;   see balance                              *
00191  *      eivec    REAL   *eivec[n];                                    *
00192  *               Matrix of eigenvectors, as computed in  qr2          *
00193  *      scal     REAL   scal[];                                       *
00194  *               Scaling data from  balance                           *
00195  *                                                                    *
00196  *   Output parameter:                                                *
00197  *   ================                                                 *
00198  *      eivec    REAL   *eivec[n];                                    *
00199  *               Non-normalized eigenvectors of the original matrix   *
00200  *                                                                    *
00201  *   Macros :    SWAP()                                               *
00202  *   ========                                                         *
00203  *                                                                    *
00204  *====================================================================*/
00205 {
00206   register int i, j, k;
00207   REAL s;
00208 
00209   for (i = low; i <= high; i++)
00210   {
00211     s = scal[i];
00212     for (j = 0; j < n; j++) eivec[i][j] *= s;
00213   }
00214 
00215   for (i = low - 1; i >= 0; i--)
00216   {
00217     k = (int) scal[i];
00218     if (k != i)
00219       for (j = 0; j < n; j++) SWAP (REAL, eivec[i][j], eivec[k][j])
00220   }
00221 
00222   for (i = high + 1; i < n; i++)
00223   {
00224     k = (int) scal[i];
00225     if (k != i)
00226       for (j = 0; j < n; j++) SWAP (REAL, eivec[i][j], eivec[k][j])
00227   }
00228   return (0);
00229 }
00230 
00231 
00232 
00233 static int elmhes       /* reduce matrix to upper Hessenberg form ....*/
00234                   (int       n,       /* Dimension of matrix .........*/
00235                    int       low,     /* first nonzero row ...........*/
00236                    int       high,    /* last nonzero row ............*/
00237                    REAL *    mat[],   /* input/output matrix .........*/
00238                    int       perm[]   /* Permutation vector ..........*/
00239                   )
00240 /*====================================================================*
00241  *                                                                    *
00242  *  elmhes transforms the matrix mat to upper Hessenberg form.        *
00243  *                                                                    *
00244  *====================================================================*
00245  *                                                                    *
00246  *   Input parameters:                                                *
00247  *   ================                                                 *
00248  *      n        int n;  ( n > 0 )                                    *
00249  *               Dimension of mat                                     *
00250  *      low      int low;                                             *
00251  *      high     int high; see  balance                               *
00252  *      mat      REAL   *mat[n];                                      *
00253  *               n x n matrix                                         *
00254  *                                                                    *
00255  *   Output parameter:                                                *
00256  *   =================                                                *
00257  *      mat      REAL   *mat[n];                                      *
00258  *               upper Hessenberg matrix; additional information on   *
00259  *               the transformation is stored in the lower triangle   *
00260  *      perm     int perm[];                                          *
00261  *               Permutation vector for elmtrans                      *
00262  *                                                                    *
00263  *====================================================================*
00264  *                                                                    *
00265  *   Macros:   SWAP, ABS                                              *
00266  *   =======                                                          *
00267  *                                                                    *
00268  *====================================================================*/
00269 {
00270   register int i, j, m;
00271   REAL   x, y;
00272 
00273   for (m = low + 1; m < high; m++)
00274   {
00275     i = m;
00276     x = ZERO;
00277     for (j = m; j <= high; j++)
00278       if (ABS (mat[j][m-1]) > ABS (x))
00279       {
00280         x = mat[j][m-1];
00281         i = j;
00282       }
00283 
00284     perm[m] = i;
00285     if (i != m)
00286     {
00287       for (j = m - 1; j < n; j++) SWAP (REAL, mat[i][j], mat[m][j])
00288       for (j = 0; j <= high; j++) SWAP (REAL, mat[j][i], mat[j][m])
00289     }
00290 
00291     if (x != ZERO)
00292     {
00293       for (i = m + 1; i <= high; i++)
00294       {
00295         y = mat[i][m-1];
00296         if (y != ZERO)
00297         {
00298           y = mat[i][m-1] = y / x;
00299           for (j = m; j < n; j++) mat[i][j] -= y * mat[m][j];
00300           for (j = 0; j <= high; j++) mat[j][m] += y * mat[j][i];
00301         }
00302       } /* end i */
00303     }
00304   } /* end m */
00305 
00306   return (0);
00307 }
00308 
00309 
00310 static int elmtrans       /* copy to Hessenberg form .................*/
00311                     (int     n,       /* Dimension of matrix .........*/
00312                      int     low,     /* first nonzero row ...........*/
00313                      int     high,    /* last nonzero row ............*/
00314                      REAL *  mat[],   /* input matrix ................*/
00315                      int     perm[],  /* row permutations ............*/
00316                      REAL *  h[]      /* Hessenberg matrix ...........*/
00317                     )
00318 /*====================================================================*
00319  *                                                                    *
00320  *  elmtrans copies the Hessenberg matrix stored in mat to h.         *
00321  *                                                                    *
00322  *====================================================================*
00323  *                                                                    *
00324  *   Input parameters:                                                *
00325  *   ================                                                 *
00326  *      n        int n;  ( n > 0 )                                    *
00327  *               Dimension of  mat and eivec                          *
00328  *      low      int low;                                             *
00329  *      high     int high; see  balance                               *
00330  *      mat      REAL   *mat[n];                                      *
00331  *               n x n input matrix                                   *
00332  *      perm     int *perm;                                           *
00333  *               Permutation data from  elmhes                        *
00334  *                                                                    *
00335  *   Output parameter:                                                *
00336  *   ================                                                 *
00337  *      h        REAL   *h[n];                                        *
00338  *               Hessenberg matrix                                    *
00339  *                                                                    *
00340  *====================================================================*/
00341 {
00342   register int k, i, j;
00343 
00344   for (i = 0; i < n; i++)
00345   {
00346     for (k = 0; k < n; k++) h[i][k] = ZERO;
00347     h[i][i] = ONE;
00348   }
00349 
00350   for (i = high - 1; i > low; i--)
00351   {
00352     j = perm[i];
00353     for (k = i + 1; k <= high; k++) h[k][i] = mat[k][i-1];
00354     if ( i != j )
00355     {
00356       for (k = i; k <= high; k++)
00357       {
00358         h[i][k] = h[j][k];
00359         h[j][k] = ZERO;
00360       }
00361       h[j][i] = ONE;
00362     }
00363   }
00364 
00365   return (0);
00366 }
00367 
00368 
00369 /* ------------------------------------------------------------------ */
00370 
00371 static int orthes     /* reduce orthogonally to upper Hessenberg form */
00372                  (
00373                   int  n,                  /* Dimension of matrix     */
00374                   int  low,                /* [low,low]..[high,high]: */
00375                   int  high,               /* submatrix to be reduced */
00376                   REAL *mat[],             /* input/output matrix     */
00377                   REAL d[]                 /* reduction information   */
00378                  )                         /* error code              */
00379 
00380 /***********************************************************************
00381 * This function reduces matrix mat to upper Hessenberg form by         *
00382 * Householder transformations. All details of the transformations are  *
00383 * stored in the remaining triangle of the Hessenberg matrix and in     *
00384 * vector d.                                                            *
00385 *                                                                      *
00386 * Input parameters:                                                    *
00387 * =================                                                    *
00388 * n        dimension of mat                                            *
00389 * low  \   rows 0 to low-1 and high+1 to n-1 contain isolated          *
00390 * high  >  eigenvalues, i. e. eigenvalues corresponding to             *
00391 *      /   eigenvectors that are multiples of unit vectors             *
00392 * mat      [0..n-1,0..n-1] matrix to be reduced                        *
00393 *                                                                      *
00394 * Output parameters:                                                   *
00395 * ==================                                                   *
00396 * mat      the desired Hessenberg matrix together with the first part  *
00397 *          of the reduction information below the subdiagonal          *
00398 * d        [0..n-1] vector with the remaining reduction information    *
00399 *                                                                      *
00400 * Return value:                                                        *
00401 * =============                                                        *
00402 * Error code. This can only be the value 0 here.                       *
00403 *                                                                      *
00404 * global names used:                                                   *
00405 * ==================                                                   *
00406 * REAL, MACH_EPS, ZERO, SQRT                                           *
00407 *                                                                      *
00408 * -------------------------------------------------------------------- *
00409 * Literature: Numerical Mathematics 12 (1968), pages 359 and 360       *
00410 ***********************************************************************/
00411 
00412 {
00413   int  i, j, m;    /* loop variables                                  */
00414   REAL s,          /* Euclidian norm sigma of the subdiagonal column  */
00415                    /* vector v of mat, that shall be reflected into a */
00416                    /* multiple of the unit vector e1 = (1,0,...,0)    */
00417                    /* (v = (v1,..,v(high-m+1))                        */
00418        x = ZERO,   /* first element of v in the beginning, then       */
00419                    /* summation variable in the actual Householder    */
00420                    /* transformation                                  */
00421        y,          /* sigma^2 in the beginning, then ||u||^2, with    */
00422                    /* u := v +- sigma * e1                            */
00423        eps;        /* tolerance for checking if the transformation is */
00424                    /* valid                                           */
00425 
00426   eps = (REAL)128.0 * MACH_EPS;
00427 
00428   for (m = low + 1; m < high; m++)
00429   {
00430     for (y = ZERO, i = high; i >= m; i--)
00431       x    = mat[i][m - 1],
00432       d[i] = x,
00433       y    = y + x * x;
00434     if (y <= eps)
00435       s = ZERO;
00436     else
00437     {
00438       s = (x >= ZERO) ? -SQRT(y) : SQRT(y);
00439       y    -= x * s;
00440       d[m] =  x - s;
00441 
00442       for (j = m; j < n; j++)               /* multiply mat from the  */
00443       {                                     /* left by  (E-(u*uT)/y)  */
00444         for (x = ZERO, i = high; i >= m; i--)
00445           x += d[i] * mat[i][j];
00446         for (x /= y, i = m; i <= high; i++)
00447           mat[i][j] -= x * d[i];
00448       }
00449 
00450       for (i = 0; i <= high; i++)           /* multiply mat from the  */
00451       {                                     /* right by  (E-(u*uT)/y) */
00452         for (x = ZERO, j = high; j >= m; j--)
00453           x += d[j] * mat[i][j];
00454         for (x /= y, j = m; j <= high; j++)
00455           mat[i][j] -= x * d[j];
00456       }
00457     }
00458 
00459     mat[m][m - 1] = s;
00460   }
00461 
00462   return 0;
00463 
00464 }    /* --------------------------- orthes -------------------------- */
00465 
00466 
00467 /* ------------------------------------------------------------------ */
00468 
00469 static int orttrans       /* compute orthogonal transformation matrix */
00470                    (
00471                     int  n,      /* Dimension of matrix               */
00472                     int  low,    /* [low,low]..[high,high]: submatrix */
00473                     int  high,   /* affected by the reduction         */
00474                     REAL *mat[], /* Hessenberg matrix, reduction inf. */
00475                     REAL d[],    /* remaining reduction information   */
00476                     REAL *v[]    /* transformation matrix             */
00477                    )             /* error code                        */
00478 
00479 /***********************************************************************
00480 * compute the matrix v of accumulated transformations from the         *
00481 * information left by the Householder reduction of matrix mat to upper *
00482 * Hessenberg form below the Hessenberg matrix in mat and in the        *
00483 * vector d. The contents of the latter are destroyed.                  *
00484 *                                                                      *
00485 * Input parameters:                                                    *
00486 * =================                                                    *
00487 * n        dimension of mat                                            *
00488 * low  \   rows 0 to low-1 and high+1 to n-1 contain isolated          *
00489 * high  >  eigenvalues, i. e. eigenvalues corresponding to             *
00490 *      /   eigenvectors that are multiples of unit vectors             *
00491 * mat      [0..n-1,0..n-1] matrix produced by `orthes' giving the      *
00492 *          upper Hessenberg matrix and part of the information on the  *
00493 *          orthogonal reduction                                        *
00494 * d        [0..n-1] vector with the remaining information on the       *
00495 *          orthogonal reduction to upper Hessenberg form               *
00496 *                                                                      *
00497 * Output parameters:                                                   *
00498 * ==================                                                   *
00499 * d        input vector destroyed by this function                     *
00500 * v        [0..n-1,0..n-1] matrix defining the similarity reduction    *
00501 *          to upper Hessenberg form                                    *
00502 *                                                                      *
00503 * Return value:                                                        *
00504 * =============                                                        *
00505 * Error code. This can only be the value 0 here.                       *
00506 *                                                                      *
00507 * global names used:                                                   *
00508 * =================                                                    *
00509 * REAL, ZERO, ONE                                                      *
00510 *                                                                      *
00511 * -------------------------------------------------------------------- *
00512 * Literature: Numerical Mathematics 16 (1970), page 191                *
00513 ***********************************************************************/
00514 
00515 {
00516   int  i, j, m;                        /* loop variables              */
00517   REAL x,                              /* summation variable in the   */
00518                                        /* Householder transformation  */
00519        y;                              /* sigma  respectively         */
00520                                        /* sigma * (v1 +- sigma)       */
00521 
00522   for (i = 0; i < n; i++)              /* form the unit matrix in v   */
00523   {
00524     for (j = 0; j < n; j++)
00525       v[i][j] = ZERO;
00526     v[i][i] = ONE;
00527   }
00528 
00529   for (m = high - 1; m > low; m--)     /* apply the transformations   */
00530   {                                    /* that reduced mat to upper   */
00531     y = mat[m][m - 1];                 /* Hessenberg form also to the */
00532                                        /* unit matrix in v. This      */
00533     if (y != ZERO)                     /* produces the desired        */
00534     {                                  /* transformation matrix in v. */
00535       y *= d[m];
00536       for (i = m + 1; i <= high; i++)
00537         d[i] = mat[i][m - 1];
00538       for (j = m; j <= high; j++)
00539       {
00540         for (x = ZERO, i = m; i <= high; i++)
00541           x += d[i] * v[i][j];
00542         for (x /= y, i = m; i <= high; i++)
00543           v[i][j] += x * d[i];
00544       }
00545     }
00546   }
00547 
00548   return 0;
00549 
00550 }    /* -------------------------- orttrans ------------------------- */
00551 
00552 
00553 static int hqrvec       /* compute eigenvectors ......................*/
00554                   (int     n,           /* Dimension of matrix .......*/
00555                    int     low,         /* first nonzero row .........*/
00556                    int     high,        /* last nonzero row ..........*/
00557                    REAL *  h[],         /* upper Hessenberg matrix ...*/
00558                    REAL    wr[],        /* Real parts of evalues .....*/
00559                    REAL    wi[],        /* Imaginary parts of evalues */
00560                    REAL *  eivec[]      /* Eigenvectors ..............*/
00561                   )
00562 /*====================================================================*
00563  *                                                                    *
00564  *  hqrvec computes the eigenvectors for the eigenvalues found in hqr2*
00565  *                                                                    *
00566  *====================================================================*
00567  *                                                                    *
00568  *   Input parameters:                                                *
00569  *   ================                                                 *
00570  *      n        int n;  ( n > 0 )                                    *
00571  *               Dimension of  mat and eivec, number of eigenvalues.  *
00572  *      low      int low;                                             *
00573  *      high     int high; see  balance                               *
00574  *      h        REAL   *h[n];                                        *
00575  *               upper Hessenberg matrix                              *
00576  *      wr       REAL   wr[n];                                        *
00577  *               Real parts of the n eigenvalues.                     *
00578  *      wi       REAL   wi[n];                                        *
00579  *               Imaginary parts of the n eigenvalues.                *
00580  *                                                                    *
00581  *   Output parameter:                                                *
00582  *   ================                                                 *
00583  *      eivec    REAL   *eivec[n];                                    *
00584  *               Matrix, whose columns are the eigenvectors           *
00585  *                                                                    *
00586  *   Return value :                                                   *
00587  *   =============                                                    *
00588  *      =  0     all ok                                               *
00589  *      =  1     h is the zero matrix.                                *
00590  *                                                                    *
00591  *====================================================================*
00592  *                                                                    *
00593  *   function in use  :                                               *
00594  *   ==================                                               *
00595  *                                                                    *
00596  *      int   comdiv(): complex division                              *
00597  *                                                                    *
00598  *====================================================================*
00599  *                                                                    *
00600  *   Constants used  :    MACH_EPS                                    *
00601  *   =================                                                *
00602  *                                                                    *
00603  *   Macros :   SQR, ABS                                              *
00604  *   ========                                                         *
00605  *                                                                    *
00606  *====================================================================*/
00607 {
00608   int   i, j, k;
00609   int   l, m, en, na;
00610   REAL  p, q, r = ZERO, s = ZERO, t, w, x, y, z = ZERO,
00611         ra, sa, vr, vi, norm;
00612 
00613   for (norm = ZERO, i = 0; i < n; i++)        /* find norm of h       */
00614   {
00615     for (j = i; j < n; j++) norm += ABS(h[i][j]);
00616   }
00617 
00618   if (norm == ZERO) return (1);               /* zero matrix          */
00619 
00620   for (en = n - 1; en >= 0; en--)             /* transform back       */
00621   {
00622     p = wr[en];
00623     q = wi[en];
00624     na = en - 1;
00625     if (q == ZERO)
00626     {
00627       m = en;
00628       h[en][en] = ONE;
00629       for (i = na; i >= 0; i--)
00630       {
00631         w = h[i][i] - p;
00632         r = h[i][en];
00633         for (j = m; j <= na; j++) r += h[i][j] * h[j][en];
00634         if (wi[i] < ZERO)
00635         {
00636           z = w;
00637           s = r;
00638         }
00639         else
00640         {
00641           m = i;
00642           if (wi[i] == ZERO)
00643             h[i][en] = -r / ((w != ZERO) ? (w) : (MACH_EPS * norm));
00644           else
00645           {  /* Solve the linear system:            */
00646              /* | w   x |  | h[i][en]   |   | -r |  */
00647              /* |       |  |            | = |    |  */
00648              /* | y   z |  | h[i+1][en] |   | -s |  */
00649 
00650              x = h[i][i+1];
00651              y = h[i+1][i];
00652              q = SQR (wr[i] - p) + SQR (wi[i]);
00653              h[i][en] = t = (x * s - z * r) / q;
00654              h[i+1][en] = ( (ABS(x) > ABS(z) ) ?
00655                                 (-r -w * t) / x : (-s -y * t) / z);
00656           }
00657         }  /* wi[i] >= 0  */
00658       }  /*  end i     */
00659     }  /* end q = 0  */
00660 
00661     else if (q < ZERO)
00662     {
00663       m = na;
00664       if (ABS(h[en][na]) > ABS(h[na][en]))
00665       {
00666         h[na][na] = - (h[en][en] - p) / h[en][na];
00667         h[na][en] = - q / h[en][na];
00668       }
00669       else
00670        comdiv(-h[na][en], ZERO, h[na][na]-p, q, &h[na][na], &h[na][en]);
00671 
00672       h[en][na] = ONE;
00673       h[en][en] = ZERO;
00674       for (i = na - 1; i >= 0; i--)
00675       {
00676         w = h[i][i] - p;
00677         ra = h[i][en];
00678         sa = ZERO;
00679         for (j = m; j <= na; j++)
00680         {
00681           ra += h[i][j] * h[j][na];
00682           sa += h[i][j] * h[j][en];
00683         }
00684 
00685         if (wi[i] < ZERO)
00686         {
00687           z = w;
00688           r = ra;
00689           s = sa;
00690         }
00691         else
00692         {
00693           m = i;
00694           if (wi[i] == ZERO)
00695             comdiv (-ra, -sa, w, q, &h[i][na], &h[i][en]);
00696           else
00697           {
00698 
00699          /* solve complex linear system:                              */
00700          /* | w+i*q     x | | h[i][na] + i*h[i][en]  |   | -ra+i*sa | */
00701          /* |             | |                        | = |          | */
00702          /* |   y    z+i*q| | h[i+1][na]+i*h[i+1][en]|   | -r+i*s   | */
00703 
00704             x = h[i][i+1];
00705             y = h[i+1][i];
00706             vr = SQR (wr[i] - p) + SQR (wi[i]) - SQR (q);
00707             vi = TWO * q * (wr[i] - p);
00708             if (vr == ZERO && vi == ZERO)
00709               vr = MACH_EPS * norm *
00710                   (ABS (w) + ABS (q) + ABS (x) + ABS (y) + ABS (z));
00711 
00712             comdiv (x * r - z * ra + q * sa, x * s - z * sa -q * ra,
00713                     vr, vi, &h[i][na], &h[i][en]);
00714             if (ABS (x) > ABS (z) + ABS (q))
00715             {
00716               h[i+1][na] = (-ra - w * h[i][na] + q * h[i][en]) / x;
00717               h[i+1][en] = (-sa - w * h[i][en] - q * h[i][na]) / x;
00718             }
00719             else
00720               comdiv (-r - y * h[i][na], -s - y * h[i][en], z, q,
00721                                               &h[i+1][na], &h[i+1][en]);
00722 
00723           }   /* end wi[i] > 0  */
00724         }   /* end wi[i] >= 0  */
00725       }   /* end i            */
00726     }    /*  if q < 0        */
00727   }    /* end  en           */
00728 
00729   for (i = 0; i < n; i++)         /* Eigenvectors for the evalues for */
00730     if (i < low || i > high)      /* rows < low  and rows  > high     */
00731       for (k = i + 1; k < n; k++) eivec[i][k] = h[i][k];
00732 
00733   for (j = n - 1; j >= low; j--)
00734   {
00735     m = (j <= high) ? j : high;
00736     if (wi[j] < ZERO)
00737     {
00738       for (l = j - 1, i = low; i <= high; i++)
00739       {
00740         for (y = z = ZERO, k = low; k <= m; k++)
00741         {
00742           y += eivec[i][k] * h[k][l];
00743           z += eivec[i][k] * h[k][j];
00744         }
00745 
00746         eivec[i][l] = y;
00747         eivec[i][j] = z;
00748       }
00749     }
00750     else
00751       if (wi[j] == ZERO)
00752       {
00753         for (i = low; i <= high; i++)
00754         {
00755           for (z = ZERO, k = low; k <= m; k++)
00756             z += eivec[i][k] * h[k][j];
00757           eivec[i][j] = z;
00758         }
00759       }
00760 
00761   }  /*  end j  */
00762 
00763   return (0);
00764 }
00765 
00766 
00767 static int hqr2         /* compute eigenvalues .......................*/
00768                 (int     vec,         /* switch for computing evectors*/
00769                  int     n,           /* Dimension of matrix .........*/
00770                  int     low,         /* first nonzero row ...........*/
00771                  int     high,        /* last nonzero row ............*/
00772                  REAL *  h[],         /* Hessenberg matrix ...........*/
00773                  REAL    wr[],        /* Real parts of eigenvalues ...*/
00774                  REAL    wi[],        /* Imaginary parts of evalues ..*/
00775                  REAL *  eivec[],     /* Matrix of eigenvectors ......*/
00776                  int     cnt[]        /* Iteration counter ...........*/
00777                 )
00778 /*====================================================================*
00779  *                                                                    *
00780  *  hqr2 computes the eigenvalues and (if vec != 0) the eigenvectors  *
00781  *  of an  n * n upper Hessenberg matrix.                             *
00782  *                                                                    *
00783  *====================================================================*
00784  *                                                                    *
00785  *   Control parameter:                                               *
00786  *   ==================                                               *
00787  *      vec      int vec;                                             *
00788  *       = 0     compute eigenvalues only                             *
00789  *       = 1     compute all eigenvalues and eigenvectors             *
00790  *                                                                    *
00791  *   Input parameters:                                                *
00792  *   ================                                                 *
00793  *      n        int n;  ( n > 0 )                                    *
00794  *               Dimension of  mat and eivec,                         *
00795  *               length of the real parts vector  wr and of the       *
00796  *               imaginary parts vector  wi of the eigenvalues.       *
00797  *      low      int low;                                             *
00798  *      high     int high; see  balance                               *
00799  *      h        REAL   *h[n];                                        *
00800  *               upper  Hessenberg matrix                             *
00801  *                                                                    *
00802  *   Output parameters:                                               *
00803  *   ==================                                               *
00804  *      eivec    REAL   *eivec[n];     ( bei vec = 1 )                *
00805  *               Matrix, which for vec = 1 contains the eigenvectors  *
00806  *               as follows  :                                        *
00807  *               For real eigebvalues the corresponding column        *
00808  *               contains the corresponding eigenvactor, while for    *
00809  *               complex eigenvalues the corresponding column contains*
00810  *               the real part of the eigenvactor with its imaginary  *
00811  *               part is stored in the subsequent column of eivec.    *
00812  *               The eigenvactor for the complex conjugate eigenvactor*
00813  *               is given by the complex conjugate eigenvactor.       *
00814  *      wr       REAL   wr[n];                                        *
00815  *               Real part of the n eigenvalues.                      *
00816  *      wi       REAL   wi[n];                                        *
00817  *               Imaginary parts of the eigenvalues                   *
00818  *      cnt      int cnt[n];                                          *
00819  *               vector of iterations used for each eigenvalue.       *
00820  *               For a complex conjugate eigenvalue pair the second   *
00821  *               entry is negative.                                   *
00822  *                                                                    *
00823  *   Return value :                                                   *
00824  *   =============                                                    *
00825  *      =   0    all ok                                               *
00826  *      = 4xx    Iteration maximum exceeded when computing evalue xx  *
00827  *      =  99    zero  matrix                                         *
00828  *                                                                    *
00829  *====================================================================*
00830  *                                                                    *
00831  *   functions in use  :                                              *
00832  *   ===================                                              *
00833  *                                                                    *
00834  *      int hqrvec(): reverse transform for eigenvectors              *
00835  *                                                                    *
00836  *====================================================================*
00837  *                                                                    *
00838  *   Constants used  :   MACH_EPS, MAXIT                              *
00839  *   =================                                                *
00840  *                                                                    *
00841  *   Macros  :   SWAP, ABS, SQRT                                      *
00842  *   =========                                                        *
00843  *                                                                    *
00844  *====================================================================*/
00845 {
00846   int  i, j;
00847   int  na, en, iter, k, l, m;
00848   REAL p = ZERO, q = ZERO, r = ZERO, s, t, w, x, y, z;
00849 
00850   for (i = 0; i < n; i++)
00851     if (i < low || i > high)
00852     {
00853       wr[i] = h[i][i];
00854       wi[i] = ZERO;
00855       cnt[i] = 0;
00856     }
00857 
00858   en = high;
00859   t = ZERO;
00860 
00861   while (en >= low)
00862   {
00863     iter = 0;
00864     na = en - 1;
00865 
00866     for ( ; ; )
00867     {
00868       for (l = en; l > low; l--)             /* search for small      */
00869         if ( ABS(h[l][l-1]) <=               /* subdiagonal element   */
00870               MACH_EPS * (ABS(h[l-1][l-1]) + ABS(h[l][l])) )  break;
00871 
00872       x = h[en][en];
00873       if (l == en)                            /* found one evalue     */
00874       {
00875         wr[en] = h[en][en] = x + t;
00876         wi[en] = ZERO;
00877         cnt[en] = iter;
00878         en--;
00879         break;
00880       }
00881 
00882       y = h[na][na];
00883       w = h[en][na] * h[na][en];
00884 
00885       if (l == na)                            /* found two evalues    */
00886       {
00887         p = (y - x) * 0.5;
00888         q = p * p + w;
00889         z = SQRT (ABS (q));
00890         x = h[en][en] = x + t;
00891         h[na][na] = y + t;
00892         cnt[en] = -iter;
00893         cnt[na] = iter;
00894         if (q >= ZERO)
00895         {                                     /* real eigenvalues     */
00896           z = (p < ZERO) ? (p - z) : (p + z);
00897           wr[na] = x + z;
00898           wr[en] = s = x - w / z;
00899           wi[na] = wi[en] = ZERO;
00900           x = h[en][na];
00901           r = SQRT (x * x + z * z);
00902 
00903           if (vec)
00904           {
00905             p = x / r;
00906             q = z / r;
00907             for (j = na; j < n; j++)
00908             {
00909               z = h[na][j];
00910               h[na][j] = q * z + p * h[en][j];
00911               h[en][j] = q * h[en][j] - p * z;
00912             }
00913 
00914             for (i = 0; i <= en; i++)
00915             {
00916               z = h[i][na];
00917               h[i][na] = q * z + p * h[i][en];
00918               h[i][en] = q * h[i][en] - p * z;
00919             }
00920 
00921             for (i = low; i <= high; i++)
00922             {
00923               z = eivec[i][na];
00924               eivec[i][na] = q * z + p * eivec[i][en];
00925               eivec[i][en] = q * eivec[i][en] - p * z;
00926             }
00927           }  /* end if (vec) */
00928         }  /* end if (q >= ZERO) */
00929         else                                  /* pair of complex      */
00930         {                                     /* conjugate evalues    */
00931           wr[na] = wr[en] = x + p;
00932           wi[na] =   z;
00933           wi[en] = - z;
00934         }
00935 
00936         en -= 2;
00937         break;
00938       }  /* end if (l == na) */
00939 
00940       if (iter >= MAXIT)
00941       {
00942         cnt[en] = MAXIT + 1;
00943         return (en);                         /* MAXIT Iterations     */
00944       }
00945 
00946       if ( (iter != 0) && (iter % 10 == 0) )
00947       {
00948         t += x;
00949         for (i = low; i <= en; i++) h[i][i] -= x;
00950         s = ABS (h[en][na]) + ABS (h[na][en-2]);
00951         x = y = (REAL)0.75 * s;
00952         w = - (REAL)0.4375 * s * s;
00953       }
00954 
00955       iter ++;
00956 
00957       for (m = en - 2; m >= l; m--)
00958       {
00959         z = h[m][m];
00960         r = x - z;
00961         s = y - z;
00962         p = ( r * s - w ) / h[m+1][m] + h[m][m+1];
00963         q = h[m + 1][m + 1] - z - r - s;
00964         r = h[m + 2][m + 1];
00965         s = ABS (p) + ABS (q) + ABS (r);
00966         p /= s;
00967         q /= s;
00968         r /= s;
00969         if (m == l) break;
00970         if ( ABS (h[m][m-1]) * (ABS (q) + ABS (r)) <=
00971                  MACH_EPS * ABS (p)
00972                  * ( ABS (h[m-1][m-1]) + ABS (z) + ABS (h[m+1][m+1])) )
00973           break;
00974       }
00975 
00976       for (i = m + 2; i <= en; i++) h[i][i-2] = ZERO;
00977       for (i = m + 3; i <= en; i++) h[i][i-3] = ZERO;
00978 
00979       for (k = m; k <= na; k++)
00980       {
00981         if (k != m)             /* double  QR step, for rows l to en  */
00982         {                       /* and columns m to en                */
00983           p = h[k][k-1];
00984           q = h[k+1][k-1];
00985           r = (k != na) ? h[k+2][k-1] : ZERO;
00986           x = ABS (p) + ABS (q) + ABS (r);
00987           if (x == ZERO) continue;                  /*  next k        */
00988           p /= x;
00989           q /= x;
00990           r /= x;
00991         }
00992         s = SQRT (p * p + q * q + r * r);
00993         if (p < ZERO) s = -s;
00994 
00995         if (k != m) h[k][k-1] = -s * x;
00996           else if (l != m)
00997                  h[k][k-1] = -h[k][k-1];
00998         p += s;
00999         x = p / s;
01000         y = q / s;
01001         z = r / s;
01002         q /= p;
01003         r /= p;
01004 
01005         for (j = k; j < n; j++)               /* modify rows          */
01006         {
01007           p = h[k][j] + q * h[k+1][j];
01008           if (k != na)
01009           {
01010             p += r * h[k+2][j];
01011             h[k+2][j] -= p * z;
01012           }
01013           h[k+1][j] -= p * y;
01014           h[k][j]   -= p * x;
01015         }
01016 
01017         j = (k + 3 < en) ? (k + 3) : en;
01018         for (i = 0; i <= j; i++)              /* modify columns       */
01019         {
01020           p = x * h[i][k] + y * h[i][k+1];
01021           if (k != na)
01022           {
01023             p += z * h[i][k+2];
01024             h[i][k+2] -= p * r;
01025           }
01026           h[i][k+1] -= p * q;
01027           h[i][k]   -= p;
01028         }
01029 
01030         if (vec)      /* if eigenvectors are needed ..................*/
01031         {
01032           for (i = low; i <= high; i++)
01033           {
01034             p = x * eivec[i][k] + y * eivec[i][k+1];
01035             if (k != na)
01036             {
01037               p += z * eivec[i][k+2];
01038               eivec[i][k+2] -= p * r;
01039             }
01040             eivec[i][k+1] -= p * q;
01041             eivec[i][k]   -= p;
01042           }
01043         }
01044       }    /* end k          */
01045 
01046     }    /* end for ( ; ;) */
01047 
01048   }    /* while (en >= low)                      All evalues found    */
01049 
01050   if (vec)                                /* transform evectors back  */
01051     if (hqrvec (n, low, high, h, wr, wi, eivec)) return (99);
01052   return (0);
01053 }
01054 
01055 
01056 static int norm_1       /* normalize eigenvectors to have one norm 1 .*/
01057                   (int     n,       /* Dimension of matrix ...........*/
01058                    REAL *  v[],     /* Matrix with eigenvektors ......*/
01059                    REAL    wi[]     /* Imaginary parts of evalues ....*/
01060                   )
01061 /*====================================================================*
01062  *                                                                    *
01063  *  norm_1 normalizes the one norm of the column vectors in v.        *
01064  *  (special attention to complex vectors in v  is given)             *
01065  *                                                                    *
01066  *====================================================================*
01067  *                                                                    *
01068  *   Input parameters:                                                *
01069  *   ================                                                 *
01070  *      n        int n; ( n > 0 )                                     *
01071  *               Dimension of matrix v                                *
01072  *      v        REAL   *v[];                                         *
01073  *               Matrix of eigenvectors                               *
01074  *      wi       REAL   wi[];                                         *
01075  *               Imaginary parts of the eigenvalues                   *
01076  *                                                                    *
01077  *   Output parameter:                                                *
01078  *   ================                                                 *
01079  *      v        REAL   *v[];                                         *
01080  *               Matrix with normalized eigenvectors                  *
01081  *                                                                    *
01082  *   Return value :                                                   *
01083  *   =============                                                    *
01084  *      = 0      all ok                                               *
01085  *      = 1      n < 1                                                *
01086  *                                                                    *
01087  *====================================================================*
01088  *                                                                    *
01089  *   functions used  :                                                *
01090  *   =================                                                *
01091  *      REAL   comabs():  complex absolute value                      *
01092  *      int    comdiv():  complex division                            *
01093  *                                                                    *
01094  *   Macros :   ABS                                                   *
01095  *   ========                                                         *
01096  *                                                                    *
01097  *====================================================================*/
01098 {
01099   int  i, j;
01100   REAL maxi, tr, ti;
01101 
01102   if (n < 1) return (1);
01103 
01104   for (j = 0; j < n; j++)
01105   {
01106     if (wi[j] == ZERO)
01107     {
01108       maxi = v[0][j];
01109       for (i = 1; i < n; i++)
01110         if (ABS (v[i][j]) > ABS (maxi))  maxi = v[i][j];
01111 
01112       if (maxi != ZERO)
01113       {
01114         maxi = ONE / maxi;
01115         for (i = 0; i < n; i++) v[i][j] *= maxi;
01116       }
01117     }
01118     else
01119     {
01120       tr = v[0][j];
01121       ti = v[0][j+1];
01122       for (i = 1; i < n; i++)
01123         if ( comabs (v[i][j], v[i][j+1]) > comabs (tr, ti) )
01124         {
01125           tr = v[i][j];
01126           ti = v[i][j+1];
01127         }
01128 
01129       if (tr != ZERO || ti != ZERO)
01130         for (i = 0; i < n; i++)
01131           comdiv (v[i][j], v[i][j+1], tr, ti, &v[i][j], &v[i][j+1]);
01132 
01133       j++;                                          /* raise j by two */
01134     }
01135   }
01136   return (0);
01137 }
01138 
01139 
01140 int eigen               /* Compute all evalues/evectors of a matrix ..*/
01141           (
01142            int     vec,           /* switch for computing evectors ...*/
01143            int     ortho,         /* orthogonal Hessenberg reduction? */
01144            int     ev_norm,       /* normalize Eigenvectors? .........*/
01145            int     n,             /* size of matrix ..................*/
01146            REAL ** mat,           /* input matrix ....................*/
01147            REAL ** eivec,         /* Eigenvectors ....................*/
01148            REAL  * valre,         /* real parts of eigenvalues .......*/
01149            REAL  * valim,         /* imaginary parts of eigenvalues ..*/
01150            int   * cnt            /* Iteration counter ...............*/
01151           )
01152 /*====================================================================*
01153  *                                                                    *
01154  *  The function  eigen  determines all eigenvalues and (if desired)  *
01155  *  all eigenvectors of a real square  n * n  matrix via the QR method*
01156  *  in the version of  Martin, Parlett, Peters, Reinsch and Wilkinson.*
01157  *                                                                    *
01158  *====================================================================*
01159  *                                                                    *
01160  *   Literature:                                                      *
01161  *   ===========                                                      *
01162  *      1) Peters, Wilkinson: Eigenvectors of real and complex        *
01163  *         matrices by LR and QR triangularisations,                  *
01164  *         Num. Math. 16, p.184-204, (1970); [PETE70]; contribution   *
01165  *         II/15, p. 372 - 395 in [WILK71].                           *
01166  *      2) Martin, Wilkinson: Similarity reductions of a general      *
01167  *         matrix to Hessenberg form, Num. Math. 12, p. 349-368,(1968)*
01168  *         [MART 68]; contribution II,13, p. 339 - 358 in [WILK71].   *
01169  *      3) Parlett, Reinsch: Balancing a matrix for calculations of   *
01170  *         eigenvalues and eigenvectors, Num. Math. 13, p. 293-304,   *
01171  *         (1969); [PARL69]; contribution II/11, p.315 - 326 in       *
01172  *         [WILK71].                                                  *
01173  *                                                                    *
01174  *====================================================================*
01175  *                                                                    *
01176  *   Control parameters:                                              *
01177  *   ===================                                              *
01178  *      vec      int vec;                                             *
01179  *               call for eigen :                                     *
01180  *       = 0     compute eigenvalues only                             *
01181  *       = 1     compute all eigenvalues and eigenvectors             *
01182  *      ortho    flag that shows if transformation of mat to          *
01183  *               Hessenberg form shall be done orthogonally by        *
01184  *               `orthes' (flag set) or elementarily by `elmhes'      *
01185  *               (flag cleared). The Householder matrices used in     *
01186  *               orthogonal transformation have the advantage of      *
01187  *               preserving the symmetry of input matrices.           *
01188  *      ev_norm  flag that shows if Eigenvectors shall be             *
01189  *               normalized (flag set) or not (flag cleared)          *
01190  *                                                                    *
01191  *   Input parameters:                                                *
01192  *   ================                                                 *
01193  *      n        int n;  ( n > 0 )                                    *
01194  *               size of matrix, number of eigenvalues                *
01195  *      mat      REAL   *mat[n];                                      *
01196  *               matrix                                               *
01197  *                                                                    *
01198  *   Output parameters:                                               *
01199  *   ==================                                               *
01200  *      eivec    REAL   *eivec[n];     ( bei vec = 1 )                *
01201  *               matrix, if  vec = 1  this holds the eigenvectors     *
01202  *               thus :                                               *
01203  *               If the jth eigenvalue of the matrix is real then the *
01204  *               jth column is the corresponding real eigenvector;    *
01205  *               if the jth eigenvalue is complex then the jth column *
01206  *               of eivec contains the real part of the eigenvector   *
01207  *               while its imaginary part is in column j+1.           *
01208  *               (the j+1st eigenvector is the complex conjugate      *
01209  *               vector.)                                             *
01210  *      valre    REAL   valre[n];                                     *
01211  *               Real parts of the eigenvalues.                       *
01212  *      valim    REAL   valim[n];                                     *
01213  *               Imaginary parts of the eigenvalues                   *
01214  *      cnt      int cnt[n];                                          *
01215  *               vector containing the number of iterations for each  *
01216  *               eigenvalue. (for a complex conjugate pair the second *
01217  *               entry is negative.)                                  *
01218  *                                                                    *
01219  *   Return value :                                                   *
01220  *   =============                                                    *
01221  *      =   0    all ok                                               *
01222  *      =   1    n < 1 or other invalid input parameter               *
01223  *      =   2    insufficient memory                                  *
01224  *      = 10x    error x from balance()                               *
01225  *      = 20x    error x from elmh()                                  *
01226  *      = 30x    error x from elmtrans()   (for vec = 1 only)         *
01227  *      = 4xx    error xx from hqr2()                                 *
01228  *      = 50x    error x from balback()    (for vec = 1 only)         *
01229  *      = 60x    error x from norm_1()     (for vec = 1 only)         *
01230  *                                                                    *
01231  *====================================================================*
01232  *                                                                    *
01233  *   Functions in use   :                                             *
01234  *   ===================                                              *
01235  *                                                                    *
01236  *   static int balance (): Balancing of an  n x n  matrix            *
01237  *   static int elmh ():    Transformation to upper Hessenberg form   *
01238  *   static int elmtrans(): intialize eigenvectors                    *
01239  *   static int hqr2 ():    compute eigenvalues/eigenvectors          *
01240  *   static int balback (): Reverse balancing to obtain eigenvectors  *
01241  *   static int norm_1 ():  Normalize eigenvectors                    *
01242  *                                                                    *
01243  *   void *vmalloc():       allocate vector or matrix                 *
01244  *   void vmfree():         free list of vectors and matrices         *
01245  *                                                                    *
01246  *====================================================================*
01247  *                                                                    *
01248  *   Constants used   :     NULL, BASIS                               *
01249  *   ===================                                              *
01250  *                                                                    *
01251  *====================================================================*/
01252 {
01253   register int i;
01254   int      low, high, rc;
01255   REAL     *scale,
01256            *d = NULL;
01257   void     *vmblock;
01258 
01259   if (n < 1) return (1);                       /*  n >= 1 ............*/
01260 
01261   if (valre == NULL || valim == NULL || mat == NULL || cnt == NULL)
01262     return (1);
01263 
01264   for (i = 0; i < n; i++)
01265     if (mat[i] == NULL) return (1);
01266 
01267   for (i = 0; i < n; i++) cnt[i] = 0;
01268 
01269   if (n == 1)                                  /*  n = 1 .............*/
01270   {
01271     eivec[0][0] = ONE;
01272     valre[0]    = mat[0][0];
01273     valim[0]    = ZERO;
01274     return (0);
01275   }
01276 
01277   if (vec)
01278   {
01279     if (eivec == NULL) return (1);
01280     for (i = 0; i < n; i++)
01281       if (eivec[i] == NULL) return (1);
01282   }
01283 
01284   vmblock = vminit();
01285   scale = (REAL *)vmalloc(vmblock, VEKTOR, n, 0);
01286   if (! vmcomplete(vmblock))                 /* memory error         */
01287     return 2;
01288 
01289   if (vec && ortho)                          /* with Eigenvectors     */
01290   {                                          /* and orthogonal        */
01291                                              /* Hessenberg reduction? */
01292     d = (REAL *)vmalloc(vmblock, VEKTOR, n, 0);
01293     if (! vmcomplete(vmblock))
01294     {
01295       vmfree(vmblock);
01296       return 1;
01297     }
01298   }
01299 
01300                                             /* balance mat for nearly */
01301   rc = balance (n, mat, scale,              /* equal row and column   */
01302                   &low, &high, BASIS);      /* one norms              */
01303   if (rc)
01304   {
01305     vmfree(vmblock);
01306     return (100 + rc);
01307   }
01308 
01309   if (ortho)
01310     rc = orthes(n, low, high, mat, d);
01311   else
01312     rc = elmhes (n, low, high, mat, cnt);   /*  reduce mat to upper   */
01313   if (rc)                                   /*  Hessenberg form       */
01314   {
01315     vmfree(vmblock);
01316     return (200 + rc);
01317   }
01318 
01319   if (vec)                                  /*  initialize eivec      */
01320   {
01321     if (ortho)
01322       rc = orttrans(n, low, high, mat, d, eivec);
01323     else
01324       rc = elmtrans (n, low, high, mat, cnt, eivec);
01325     if (rc)
01326     {
01327       vmfree(vmblock);
01328       return (300 + rc);
01329     }
01330   }
01331 
01332   rc = hqr2 (vec, n, low, high, mat,        /*  execute Francis QR    */
01333              valre, valim, eivec, cnt);     /*  algorithm to obtain   */
01334   if (rc)                                   /*  eigenvalues           */
01335   {
01336     vmfree(vmblock);
01337     return (400 + rc);
01338   }
01339 
01340   if (vec)
01341   {
01342     rc = balback (n, low, high,             /*  reverse balancing if  */
01343                       scale, eivec);        /*  eigenvaectors are to  */
01344     if (rc)                                 /*  be determined         */
01345     {
01346       vmfree(vmblock);
01347       return (500 + rc);
01348     }
01349     if (ev_norm)
01350       rc = norm_1 (n, eivec, valim);        /* normalize eigenvectors */
01351     if (rc)
01352     {
01353       vmfree(vmblock);
01354       return (600 + rc);
01355     }
01356   }
01357 
01358   vmfree(vmblock);                          /* free buffers           */
01359 
01360 
01361   return (0);
01362 }
01363 
01364 /* ------------------------ END feigen.cpp -------------------------- */

Generated on Wed Sep 5 12:54:21 2007 for DSACSS Operational Code by  doxygen 1.3.9.1