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


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:43