csteqr.c
Go to the documentation of this file.
00001 /* csteqr.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static complex c_b1 = {0.f,0.f};
00019 static complex c_b2 = {1.f,0.f};
00020 static integer c__0 = 0;
00021 static integer c__1 = 1;
00022 static integer c__2 = 2;
00023 static real c_b41 = 1.f;
00024 
00025 /* Subroutine */ int csteqr_(char *compz, integer *n, real *d__, real *e, 
00026         complex *z__, integer *ldz, real *work, integer *info)
00027 {
00028     /* System generated locals */
00029     integer z_dim1, z_offset, i__1, i__2;
00030     real r__1, r__2;
00031 
00032     /* Builtin functions */
00033     double sqrt(doublereal), r_sign(real *, real *);
00034 
00035     /* Local variables */
00036     real b, c__, f, g;
00037     integer i__, j, k, l, m;
00038     real p, r__, s;
00039     integer l1, ii, mm, lm1, mm1, nm1;
00040     real rt1, rt2, eps;
00041     integer lsv;
00042     real tst, eps2;
00043     integer lend, jtot;
00044     extern /* Subroutine */ int slae2_(real *, real *, real *, real *, real *)
00045             ;
00046     extern logical lsame_(char *, char *);
00047     extern /* Subroutine */ int clasr_(char *, char *, char *, integer *, 
00048             integer *, real *, real *, complex *, integer *);
00049     real anorm;
00050     extern /* Subroutine */ int cswap_(integer *, complex *, integer *, 
00051             complex *, integer *);
00052     integer lendm1, lendp1;
00053     extern /* Subroutine */ int slaev2_(real *, real *, real *, real *, real *
00054 , real *, real *);
00055     extern doublereal slapy2_(real *, real *);
00056     integer iscale;
00057     extern doublereal slamch_(char *);
00058     extern /* Subroutine */ int claset_(char *, integer *, integer *, complex 
00059             *, complex *, complex *, integer *);
00060     real safmin;
00061     extern /* Subroutine */ int xerbla_(char *, integer *);
00062     real safmax;
00063     extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, 
00064             real *, integer *, integer *, real *, integer *, integer *);
00065     integer lendsv;
00066     extern /* Subroutine */ int slartg_(real *, real *, real *, real *, real *
00067 );
00068     real ssfmin;
00069     integer nmaxit, icompz;
00070     real ssfmax;
00071     extern doublereal slanst_(char *, integer *, real *, real *);
00072     extern /* Subroutine */ int slasrt_(char *, integer *, real *, integer *);
00073 
00074 
00075 /*  -- LAPACK routine (version 3.2) -- */
00076 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00077 /*     November 2006 */
00078 
00079 /*     .. Scalar Arguments .. */
00080 /*     .. */
00081 /*     .. Array Arguments .. */
00082 /*     .. */
00083 
00084 /*  Purpose */
00085 /*  ======= */
00086 
00087 /*  CSTEQR computes all eigenvalues and, optionally, eigenvectors of a */
00088 /*  symmetric tridiagonal matrix using the implicit QL or QR method. */
00089 /*  The eigenvectors of a full or band complex Hermitian matrix can also */
00090 /*  be found if CHETRD or CHPTRD or CHBTRD has been used to reduce this */
00091 /*  matrix to tridiagonal form. */
00092 
00093 /*  Arguments */
00094 /*  ========= */
00095 
00096 /*  COMPZ   (input) CHARACTER*1 */
00097 /*          = 'N':  Compute eigenvalues only. */
00098 /*          = 'V':  Compute eigenvalues and eigenvectors of the original */
00099 /*                  Hermitian matrix.  On entry, Z must contain the */
00100 /*                  unitary matrix used to reduce the original matrix */
00101 /*                  to tridiagonal form. */
00102 /*          = 'I':  Compute eigenvalues and eigenvectors of the */
00103 /*                  tridiagonal matrix.  Z is initialized to the identity */
00104 /*                  matrix. */
00105 
00106 /*  N       (input) INTEGER */
00107 /*          The order of the matrix.  N >= 0. */
00108 
00109 /*  D       (input/output) REAL array, dimension (N) */
00110 /*          On entry, the diagonal elements of the tridiagonal matrix. */
00111 /*          On exit, if INFO = 0, the eigenvalues in ascending order. */
00112 
00113 /*  E       (input/output) REAL array, dimension (N-1) */
00114 /*          On entry, the (n-1) subdiagonal elements of the tridiagonal */
00115 /*          matrix. */
00116 /*          On exit, E has been destroyed. */
00117 
00118 /*  Z       (input/output) COMPLEX array, dimension (LDZ, N) */
00119 /*          On entry, if  COMPZ = 'V', then Z contains the unitary */
00120 /*          matrix used in the reduction to tridiagonal form. */
00121 /*          On exit, if INFO = 0, then if COMPZ = 'V', Z contains the */
00122 /*          orthonormal eigenvectors of the original Hermitian matrix, */
00123 /*          and if COMPZ = 'I', Z contains the orthonormal eigenvectors */
00124 /*          of the symmetric tridiagonal matrix. */
00125 /*          If COMPZ = 'N', then Z is not referenced. */
00126 
00127 /*  LDZ     (input) INTEGER */
00128 /*          The leading dimension of the array Z.  LDZ >= 1, and if */
00129 /*          eigenvectors are desired, then  LDZ >= max(1,N). */
00130 
00131 /*  WORK    (workspace) REAL array, dimension (max(1,2*N-2)) */
00132 /*          If COMPZ = 'N', then WORK is not referenced. */
00133 
00134 /*  INFO    (output) INTEGER */
00135 /*          = 0:  successful exit */
00136 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00137 /*          > 0:  the algorithm has failed to find all the eigenvalues in */
00138 /*                a total of 30*N iterations; if INFO = i, then i */
00139 /*                elements of E have not converged to zero; on exit, D */
00140 /*                and E contain the elements of a symmetric tridiagonal */
00141 /*                matrix which is unitarily similar to the original */
00142 /*                matrix. */
00143 
00144 /*  ===================================================================== */
00145 
00146 /*     .. Parameters .. */
00147 /*     .. */
00148 /*     .. Local Scalars .. */
00149 /*     .. */
00150 /*     .. External Functions .. */
00151 /*     .. */
00152 /*     .. External Subroutines .. */
00153 /*     .. */
00154 /*     .. Intrinsic Functions .. */
00155 /*     .. */
00156 /*     .. Executable Statements .. */
00157 
00158 /*     Test the input parameters. */
00159 
00160     /* Parameter adjustments */
00161     --d__;
00162     --e;
00163     z_dim1 = *ldz;
00164     z_offset = 1 + z_dim1;
00165     z__ -= z_offset;
00166     --work;
00167 
00168     /* Function Body */
00169     *info = 0;
00170 
00171     if (lsame_(compz, "N")) {
00172         icompz = 0;
00173     } else if (lsame_(compz, "V")) {
00174         icompz = 1;
00175     } else if (lsame_(compz, "I")) {
00176         icompz = 2;
00177     } else {
00178         icompz = -1;
00179     }
00180     if (icompz < 0) {
00181         *info = -1;
00182     } else if (*n < 0) {
00183         *info = -2;
00184     } else if (*ldz < 1 || icompz > 0 && *ldz < max(1,*n)) {
00185         *info = -6;
00186     }
00187     if (*info != 0) {
00188         i__1 = -(*info);
00189         xerbla_("CSTEQR", &i__1);
00190         return 0;
00191     }
00192 
00193 /*     Quick return if possible */
00194 
00195     if (*n == 0) {
00196         return 0;
00197     }
00198 
00199     if (*n == 1) {
00200         if (icompz == 2) {
00201             i__1 = z_dim1 + 1;
00202             z__[i__1].r = 1.f, z__[i__1].i = 0.f;
00203         }
00204         return 0;
00205     }
00206 
00207 /*     Determine the unit roundoff and over/underflow thresholds. */
00208 
00209     eps = slamch_("E");
00210 /* Computing 2nd power */
00211     r__1 = eps;
00212     eps2 = r__1 * r__1;
00213     safmin = slamch_("S");
00214     safmax = 1.f / safmin;
00215     ssfmax = sqrt(safmax) / 3.f;
00216     ssfmin = sqrt(safmin) / eps2;
00217 
00218 /*     Compute the eigenvalues and eigenvectors of the tridiagonal */
00219 /*     matrix. */
00220 
00221     if (icompz == 2) {
00222         claset_("Full", n, n, &c_b1, &c_b2, &z__[z_offset], ldz);
00223     }
00224 
00225     nmaxit = *n * 30;
00226     jtot = 0;
00227 
00228 /*     Determine where the matrix splits and choose QL or QR iteration */
00229 /*     for each block, according to whether top or bottom diagonal */
00230 /*     element is smaller. */
00231 
00232     l1 = 1;
00233     nm1 = *n - 1;
00234 
00235 L10:
00236     if (l1 > *n) {
00237         goto L160;
00238     }
00239     if (l1 > 1) {
00240         e[l1 - 1] = 0.f;
00241     }
00242     if (l1 <= nm1) {
00243         i__1 = nm1;
00244         for (m = l1; m <= i__1; ++m) {
00245             tst = (r__1 = e[m], dabs(r__1));
00246             if (tst == 0.f) {
00247                 goto L30;
00248             }
00249             if (tst <= sqrt((r__1 = d__[m], dabs(r__1))) * sqrt((r__2 = d__[m 
00250                     + 1], dabs(r__2))) * eps) {
00251                 e[m] = 0.f;
00252                 goto L30;
00253             }
00254 /* L20: */
00255         }
00256     }
00257     m = *n;
00258 
00259 L30:
00260     l = l1;
00261     lsv = l;
00262     lend = m;
00263     lendsv = lend;
00264     l1 = m + 1;
00265     if (lend == l) {
00266         goto L10;
00267     }
00268 
00269 /*     Scale submatrix in rows and columns L to LEND */
00270 
00271     i__1 = lend - l + 1;
00272     anorm = slanst_("I", &i__1, &d__[l], &e[l]);
00273     iscale = 0;
00274     if (anorm == 0.f) {
00275         goto L10;
00276     }
00277     if (anorm > ssfmax) {
00278         iscale = 1;
00279         i__1 = lend - l + 1;
00280         slascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &d__[l], n, 
00281                 info);
00282         i__1 = lend - l;
00283         slascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &e[l], n, 
00284                 info);
00285     } else if (anorm < ssfmin) {
00286         iscale = 2;
00287         i__1 = lend - l + 1;
00288         slascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &d__[l], n, 
00289                 info);
00290         i__1 = lend - l;
00291         slascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &e[l], n, 
00292                 info);
00293     }
00294 
00295 /*     Choose between QL and QR iteration */
00296 
00297     if ((r__1 = d__[lend], dabs(r__1)) < (r__2 = d__[l], dabs(r__2))) {
00298         lend = lsv;
00299         l = lendsv;
00300     }
00301 
00302     if (lend > l) {
00303 
00304 /*        QL Iteration */
00305 
00306 /*        Look for small subdiagonal element. */
00307 
00308 L40:
00309         if (l != lend) {
00310             lendm1 = lend - 1;
00311             i__1 = lendm1;
00312             for (m = l; m <= i__1; ++m) {
00313 /* Computing 2nd power */
00314                 r__2 = (r__1 = e[m], dabs(r__1));
00315                 tst = r__2 * r__2;
00316                 if (tst <= eps2 * (r__1 = d__[m], dabs(r__1)) * (r__2 = d__[m 
00317                         + 1], dabs(r__2)) + safmin) {
00318                     goto L60;
00319                 }
00320 /* L50: */
00321             }
00322         }
00323 
00324         m = lend;
00325 
00326 L60:
00327         if (m < lend) {
00328             e[m] = 0.f;
00329         }
00330         p = d__[l];
00331         if (m == l) {
00332             goto L80;
00333         }
00334 
00335 /*        If remaining matrix is 2-by-2, use SLAE2 or SLAEV2 */
00336 /*        to compute its eigensystem. */
00337 
00338         if (m == l + 1) {
00339             if (icompz > 0) {
00340                 slaev2_(&d__[l], &e[l], &d__[l + 1], &rt1, &rt2, &c__, &s);
00341                 work[l] = c__;
00342                 work[*n - 1 + l] = s;
00343                 clasr_("R", "V", "B", n, &c__2, &work[l], &work[*n - 1 + l], &
00344                         z__[l * z_dim1 + 1], ldz);
00345             } else {
00346                 slae2_(&d__[l], &e[l], &d__[l + 1], &rt1, &rt2);
00347             }
00348             d__[l] = rt1;
00349             d__[l + 1] = rt2;
00350             e[l] = 0.f;
00351             l += 2;
00352             if (l <= lend) {
00353                 goto L40;
00354             }
00355             goto L140;
00356         }
00357 
00358         if (jtot == nmaxit) {
00359             goto L140;
00360         }
00361         ++jtot;
00362 
00363 /*        Form shift. */
00364 
00365         g = (d__[l + 1] - p) / (e[l] * 2.f);
00366         r__ = slapy2_(&g, &c_b41);
00367         g = d__[m] - p + e[l] / (g + r_sign(&r__, &g));
00368 
00369         s = 1.f;
00370         c__ = 1.f;
00371         p = 0.f;
00372 
00373 /*        Inner loop */
00374 
00375         mm1 = m - 1;
00376         i__1 = l;
00377         for (i__ = mm1; i__ >= i__1; --i__) {
00378             f = s * e[i__];
00379             b = c__ * e[i__];
00380             slartg_(&g, &f, &c__, &s, &r__);
00381             if (i__ != m - 1) {
00382                 e[i__ + 1] = r__;
00383             }
00384             g = d__[i__ + 1] - p;
00385             r__ = (d__[i__] - g) * s + c__ * 2.f * b;
00386             p = s * r__;
00387             d__[i__ + 1] = g + p;
00388             g = c__ * r__ - b;
00389 
00390 /*           If eigenvectors are desired, then save rotations. */
00391 
00392             if (icompz > 0) {
00393                 work[i__] = c__;
00394                 work[*n - 1 + i__] = -s;
00395             }
00396 
00397 /* L70: */
00398         }
00399 
00400 /*        If eigenvectors are desired, then apply saved rotations. */
00401 
00402         if (icompz > 0) {
00403             mm = m - l + 1;
00404             clasr_("R", "V", "B", n, &mm, &work[l], &work[*n - 1 + l], &z__[l 
00405                     * z_dim1 + 1], ldz);
00406         }
00407 
00408         d__[l] -= p;
00409         e[l] = g;
00410         goto L40;
00411 
00412 /*        Eigenvalue found. */
00413 
00414 L80:
00415         d__[l] = p;
00416 
00417         ++l;
00418         if (l <= lend) {
00419             goto L40;
00420         }
00421         goto L140;
00422 
00423     } else {
00424 
00425 /*        QR Iteration */
00426 
00427 /*        Look for small superdiagonal element. */
00428 
00429 L90:
00430         if (l != lend) {
00431             lendp1 = lend + 1;
00432             i__1 = lendp1;
00433             for (m = l; m >= i__1; --m) {
00434 /* Computing 2nd power */
00435                 r__2 = (r__1 = e[m - 1], dabs(r__1));
00436                 tst = r__2 * r__2;
00437                 if (tst <= eps2 * (r__1 = d__[m], dabs(r__1)) * (r__2 = d__[m 
00438                         - 1], dabs(r__2)) + safmin) {
00439                     goto L110;
00440                 }
00441 /* L100: */
00442             }
00443         }
00444 
00445         m = lend;
00446 
00447 L110:
00448         if (m > lend) {
00449             e[m - 1] = 0.f;
00450         }
00451         p = d__[l];
00452         if (m == l) {
00453             goto L130;
00454         }
00455 
00456 /*        If remaining matrix is 2-by-2, use SLAE2 or SLAEV2 */
00457 /*        to compute its eigensystem. */
00458 
00459         if (m == l - 1) {
00460             if (icompz > 0) {
00461                 slaev2_(&d__[l - 1], &e[l - 1], &d__[l], &rt1, &rt2, &c__, &s)
00462                         ;
00463                 work[m] = c__;
00464                 work[*n - 1 + m] = s;
00465                 clasr_("R", "V", "F", n, &c__2, &work[m], &work[*n - 1 + m], &
00466                         z__[(l - 1) * z_dim1 + 1], ldz);
00467             } else {
00468                 slae2_(&d__[l - 1], &e[l - 1], &d__[l], &rt1, &rt2);
00469             }
00470             d__[l - 1] = rt1;
00471             d__[l] = rt2;
00472             e[l - 1] = 0.f;
00473             l += -2;
00474             if (l >= lend) {
00475                 goto L90;
00476             }
00477             goto L140;
00478         }
00479 
00480         if (jtot == nmaxit) {
00481             goto L140;
00482         }
00483         ++jtot;
00484 
00485 /*        Form shift. */
00486 
00487         g = (d__[l - 1] - p) / (e[l - 1] * 2.f);
00488         r__ = slapy2_(&g, &c_b41);
00489         g = d__[m] - p + e[l - 1] / (g + r_sign(&r__, &g));
00490 
00491         s = 1.f;
00492         c__ = 1.f;
00493         p = 0.f;
00494 
00495 /*        Inner loop */
00496 
00497         lm1 = l - 1;
00498         i__1 = lm1;
00499         for (i__ = m; i__ <= i__1; ++i__) {
00500             f = s * e[i__];
00501             b = c__ * e[i__];
00502             slartg_(&g, &f, &c__, &s, &r__);
00503             if (i__ != m) {
00504                 e[i__ - 1] = r__;
00505             }
00506             g = d__[i__] - p;
00507             r__ = (d__[i__ + 1] - g) * s + c__ * 2.f * b;
00508             p = s * r__;
00509             d__[i__] = g + p;
00510             g = c__ * r__ - b;
00511 
00512 /*           If eigenvectors are desired, then save rotations. */
00513 
00514             if (icompz > 0) {
00515                 work[i__] = c__;
00516                 work[*n - 1 + i__] = s;
00517             }
00518 
00519 /* L120: */
00520         }
00521 
00522 /*        If eigenvectors are desired, then apply saved rotations. */
00523 
00524         if (icompz > 0) {
00525             mm = l - m + 1;
00526             clasr_("R", "V", "F", n, &mm, &work[m], &work[*n - 1 + m], &z__[m 
00527                     * z_dim1 + 1], ldz);
00528         }
00529 
00530         d__[l] -= p;
00531         e[lm1] = g;
00532         goto L90;
00533 
00534 /*        Eigenvalue found. */
00535 
00536 L130:
00537         d__[l] = p;
00538 
00539         --l;
00540         if (l >= lend) {
00541             goto L90;
00542         }
00543         goto L140;
00544 
00545     }
00546 
00547 /*     Undo scaling if necessary */
00548 
00549 L140:
00550     if (iscale == 1) {
00551         i__1 = lendsv - lsv + 1;
00552         slascl_("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &d__[lsv], 
00553                 n, info);
00554         i__1 = lendsv - lsv;
00555         slascl_("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &e[lsv], n, 
00556                 info);
00557     } else if (iscale == 2) {
00558         i__1 = lendsv - lsv + 1;
00559         slascl_("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &d__[lsv], 
00560                 n, info);
00561         i__1 = lendsv - lsv;
00562         slascl_("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &e[lsv], n, 
00563                 info);
00564     }
00565 
00566 /*     Check for no convergence to an eigenvalue after a total */
00567 /*     of N*MAXIT iterations. */
00568 
00569     if (jtot == nmaxit) {
00570         i__1 = *n - 1;
00571         for (i__ = 1; i__ <= i__1; ++i__) {
00572             if (e[i__] != 0.f) {
00573                 ++(*info);
00574             }
00575 /* L150: */
00576         }
00577         return 0;
00578     }
00579     goto L10;
00580 
00581 /*     Order eigenvalues and eigenvectors. */
00582 
00583 L160:
00584     if (icompz == 0) {
00585 
00586 /*        Use Quick Sort */
00587 
00588         slasrt_("I", n, &d__[1], info);
00589 
00590     } else {
00591 
00592 /*        Use Selection Sort to minimize swaps of eigenvectors */
00593 
00594         i__1 = *n;
00595         for (ii = 2; ii <= i__1; ++ii) {
00596             i__ = ii - 1;
00597             k = i__;
00598             p = d__[i__];
00599             i__2 = *n;
00600             for (j = ii; j <= i__2; ++j) {
00601                 if (d__[j] < p) {
00602                     k = j;
00603                     p = d__[j];
00604                 }
00605 /* L170: */
00606             }
00607             if (k != i__) {
00608                 d__[k] = d__[i__];
00609                 d__[i__] = p;
00610                 cswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[k * z_dim1 + 1], 
00611                          &c__1);
00612             }
00613 /* L180: */
00614         }
00615     }
00616     return 0;
00617 
00618 /*     End of CSTEQR */
00619 
00620 } /* csteqr_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:34