dsteqr.c
Go to the documentation of this file.
00001 /* dsteqr.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 doublereal c_b9 = 0.;
00019 static doublereal c_b10 = 1.;
00020 static integer c__0 = 0;
00021 static integer c__1 = 1;
00022 static integer c__2 = 2;
00023 
00024 /* Subroutine */ int dsteqr_(char *compz, integer *n, doublereal *d__, 
00025         doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
00026         integer *info)
00027 {
00028     /* System generated locals */
00029     integer z_dim1, z_offset, i__1, i__2;
00030     doublereal d__1, d__2;
00031 
00032     /* Builtin functions */
00033     double sqrt(doublereal), d_sign(doublereal *, doublereal *);
00034 
00035     /* Local variables */
00036     doublereal b, c__, f, g;
00037     integer i__, j, k, l, m;
00038     doublereal p, r__, s;
00039     integer l1, ii, mm, lm1, mm1, nm1;
00040     doublereal rt1, rt2, eps;
00041     integer lsv;
00042     doublereal tst, eps2;
00043     integer lend, jtot;
00044     extern /* Subroutine */ int dlae2_(doublereal *, doublereal *, doublereal 
00045             *, doublereal *, doublereal *);
00046     extern logical lsame_(char *, char *);
00047     extern /* Subroutine */ int dlasr_(char *, char *, char *, integer *, 
00048             integer *, doublereal *, doublereal *, doublereal *, integer *);
00049     doublereal anorm;
00050     extern /* Subroutine */ int dswap_(integer *, doublereal *, integer *, 
00051             doublereal *, integer *), dlaev2_(doublereal *, doublereal *, 
00052             doublereal *, doublereal *, doublereal *, doublereal *, 
00053             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 *), dlaset_(char *, integer *, integer 
00060             *, doublereal *, doublereal *, doublereal *, integer *);
00061     doublereal safmin;
00062     extern /* Subroutine */ int dlartg_(doublereal *, doublereal *, 
00063             doublereal *, doublereal *, doublereal *);
00064     doublereal safmax;
00065     extern /* Subroutine */ int xerbla_(char *, integer *);
00066     extern doublereal dlanst_(char *, integer *, doublereal *, doublereal *);
00067     extern /* Subroutine */ int dlasrt_(char *, integer *, doublereal *, 
00068             integer *);
00069     integer lendsv;
00070     doublereal ssfmin;
00071     integer nmaxit, icompz;
00072     doublereal ssfmax;
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 /*  DSTEQR 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 symmetric matrix can also be found */
00090 /*  if DSYTRD or DSPTRD or DSBTRD has been used to reduce this matrix to */
00091 /*  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 /*                  symmetric matrix.  On entry, Z must contain the */
00100 /*                  orthogonal 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION array, dimension (LDZ, N) */
00119 /*          On entry, if  COMPZ = 'V', then Z contains the orthogonal */
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 symmetric 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) DOUBLE PRECISION 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 orthogonally 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_("DSTEQR", &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             z__[z_dim1 + 1] = 1.;
00202         }
00203         return 0;
00204     }
00205 
00206 /*     Determine the unit roundoff and over/underflow thresholds. */
00207 
00208     eps = dlamch_("E");
00209 /* Computing 2nd power */
00210     d__1 = eps;
00211     eps2 = d__1 * d__1;
00212     safmin = dlamch_("S");
00213     safmax = 1. / safmin;
00214     ssfmax = sqrt(safmax) / 3.;
00215     ssfmin = sqrt(safmin) / eps2;
00216 
00217 /*     Compute the eigenvalues and eigenvectors of the tridiagonal */
00218 /*     matrix. */
00219 
00220     if (icompz == 2) {
00221         dlaset_("Full", n, n, &c_b9, &c_b10, &z__[z_offset], ldz);
00222     }
00223 
00224     nmaxit = *n * 30;
00225     jtot = 0;
00226 
00227 /*     Determine where the matrix splits and choose QL or QR iteration */
00228 /*     for each block, according to whether top or bottom diagonal */
00229 /*     element is smaller. */
00230 
00231     l1 = 1;
00232     nm1 = *n - 1;
00233 
00234 L10:
00235     if (l1 > *n) {
00236         goto L160;
00237     }
00238     if (l1 > 1) {
00239         e[l1 - 1] = 0.;
00240     }
00241     if (l1 <= nm1) {
00242         i__1 = nm1;
00243         for (m = l1; m <= i__1; ++m) {
00244             tst = (d__1 = e[m], abs(d__1));
00245             if (tst == 0.) {
00246                 goto L30;
00247             }
00248             if (tst <= sqrt((d__1 = d__[m], abs(d__1))) * sqrt((d__2 = d__[m 
00249                     + 1], abs(d__2))) * eps) {
00250                 e[m] = 0.;
00251                 goto L30;
00252             }
00253 /* L20: */
00254         }
00255     }
00256     m = *n;
00257 
00258 L30:
00259     l = l1;
00260     lsv = l;
00261     lend = m;
00262     lendsv = lend;
00263     l1 = m + 1;
00264     if (lend == l) {
00265         goto L10;
00266     }
00267 
00268 /*     Scale submatrix in rows and columns L to LEND */
00269 
00270     i__1 = lend - l + 1;
00271     anorm = dlanst_("I", &i__1, &d__[l], &e[l]);
00272     iscale = 0;
00273     if (anorm == 0.) {
00274         goto L10;
00275     }
00276     if (anorm > ssfmax) {
00277         iscale = 1;
00278         i__1 = lend - l + 1;
00279         dlascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &d__[l], n, 
00280                 info);
00281         i__1 = lend - l;
00282         dlascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &e[l], n, 
00283                 info);
00284     } else if (anorm < ssfmin) {
00285         iscale = 2;
00286         i__1 = lend - l + 1;
00287         dlascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &d__[l], n, 
00288                 info);
00289         i__1 = lend - l;
00290         dlascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &e[l], n, 
00291                 info);
00292     }
00293 
00294 /*     Choose between QL and QR iteration */
00295 
00296     if ((d__1 = d__[lend], abs(d__1)) < (d__2 = d__[l], abs(d__2))) {
00297         lend = lsv;
00298         l = lendsv;
00299     }
00300 
00301     if (lend > l) {
00302 
00303 /*        QL Iteration */
00304 
00305 /*        Look for small subdiagonal element. */
00306 
00307 L40:
00308         if (l != lend) {
00309             lendm1 = lend - 1;
00310             i__1 = lendm1;
00311             for (m = l; m <= i__1; ++m) {
00312 /* Computing 2nd power */
00313                 d__2 = (d__1 = e[m], abs(d__1));
00314                 tst = d__2 * d__2;
00315                 if (tst <= eps2 * (d__1 = d__[m], abs(d__1)) * (d__2 = d__[m 
00316                         + 1], abs(d__2)) + safmin) {
00317                     goto L60;
00318                 }
00319 /* L50: */
00320             }
00321         }
00322 
00323         m = lend;
00324 
00325 L60:
00326         if (m < lend) {
00327             e[m] = 0.;
00328         }
00329         p = d__[l];
00330         if (m == l) {
00331             goto L80;
00332         }
00333 
00334 /*        If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 */
00335 /*        to compute its eigensystem. */
00336 
00337         if (m == l + 1) {
00338             if (icompz > 0) {
00339                 dlaev2_(&d__[l], &e[l], &d__[l + 1], &rt1, &rt2, &c__, &s);
00340                 work[l] = c__;
00341                 work[*n - 1 + l] = s;
00342                 dlasr_("R", "V", "B", n, &c__2, &work[l], &work[*n - 1 + l], &
00343                         z__[l * z_dim1 + 1], ldz);
00344             } else {
00345                 dlae2_(&d__[l], &e[l], &d__[l + 1], &rt1, &rt2);
00346             }
00347             d__[l] = rt1;
00348             d__[l + 1] = rt2;
00349             e[l] = 0.;
00350             l += 2;
00351             if (l <= lend) {
00352                 goto L40;
00353             }
00354             goto L140;
00355         }
00356 
00357         if (jtot == nmaxit) {
00358             goto L140;
00359         }
00360         ++jtot;
00361 
00362 /*        Form shift. */
00363 
00364         g = (d__[l + 1] - p) / (e[l] * 2.);
00365         r__ = dlapy2_(&g, &c_b10);
00366         g = d__[m] - p + e[l] / (g + d_sign(&r__, &g));
00367 
00368         s = 1.;
00369         c__ = 1.;
00370         p = 0.;
00371 
00372 /*        Inner loop */
00373 
00374         mm1 = m - 1;
00375         i__1 = l;
00376         for (i__ = mm1; i__ >= i__1; --i__) {
00377             f = s * e[i__];
00378             b = c__ * e[i__];
00379             dlartg_(&g, &f, &c__, &s, &r__);
00380             if (i__ != m - 1) {
00381                 e[i__ + 1] = r__;
00382             }
00383             g = d__[i__ + 1] - p;
00384             r__ = (d__[i__] - g) * s + c__ * 2. * b;
00385             p = s * r__;
00386             d__[i__ + 1] = g + p;
00387             g = c__ * r__ - b;
00388 
00389 /*           If eigenvectors are desired, then save rotations. */
00390 
00391             if (icompz > 0) {
00392                 work[i__] = c__;
00393                 work[*n - 1 + i__] = -s;
00394             }
00395 
00396 /* L70: */
00397         }
00398 
00399 /*        If eigenvectors are desired, then apply saved rotations. */
00400 
00401         if (icompz > 0) {
00402             mm = m - l + 1;
00403             dlasr_("R", "V", "B", n, &mm, &work[l], &work[*n - 1 + l], &z__[l 
00404                     * z_dim1 + 1], ldz);
00405         }
00406 
00407         d__[l] -= p;
00408         e[l] = g;
00409         goto L40;
00410 
00411 /*        Eigenvalue found. */
00412 
00413 L80:
00414         d__[l] = p;
00415 
00416         ++l;
00417         if (l <= lend) {
00418             goto L40;
00419         }
00420         goto L140;
00421 
00422     } else {
00423 
00424 /*        QR Iteration */
00425 
00426 /*        Look for small superdiagonal element. */
00427 
00428 L90:
00429         if (l != lend) {
00430             lendp1 = lend + 1;
00431             i__1 = lendp1;
00432             for (m = l; m >= i__1; --m) {
00433 /* Computing 2nd power */
00434                 d__2 = (d__1 = e[m - 1], abs(d__1));
00435                 tst = d__2 * d__2;
00436                 if (tst <= eps2 * (d__1 = d__[m], abs(d__1)) * (d__2 = d__[m 
00437                         - 1], abs(d__2)) + safmin) {
00438                     goto L110;
00439                 }
00440 /* L100: */
00441             }
00442         }
00443 
00444         m = lend;
00445 
00446 L110:
00447         if (m > lend) {
00448             e[m - 1] = 0.;
00449         }
00450         p = d__[l];
00451         if (m == l) {
00452             goto L130;
00453         }
00454 
00455 /*        If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 */
00456 /*        to compute its eigensystem. */
00457 
00458         if (m == l - 1) {
00459             if (icompz > 0) {
00460                 dlaev2_(&d__[l - 1], &e[l - 1], &d__[l], &rt1, &rt2, &c__, &s)
00461                         ;
00462                 work[m] = c__;
00463                 work[*n - 1 + m] = s;
00464                 dlasr_("R", "V", "F", n, &c__2, &work[m], &work[*n - 1 + m], &
00465                         z__[(l - 1) * z_dim1 + 1], ldz);
00466             } else {
00467                 dlae2_(&d__[l - 1], &e[l - 1], &d__[l], &rt1, &rt2);
00468             }
00469             d__[l - 1] = rt1;
00470             d__[l] = rt2;
00471             e[l - 1] = 0.;
00472             l += -2;
00473             if (l >= lend) {
00474                 goto L90;
00475             }
00476             goto L140;
00477         }
00478 
00479         if (jtot == nmaxit) {
00480             goto L140;
00481         }
00482         ++jtot;
00483 
00484 /*        Form shift. */
00485 
00486         g = (d__[l - 1] - p) / (e[l - 1] * 2.);
00487         r__ = dlapy2_(&g, &c_b10);
00488         g = d__[m] - p + e[l - 1] / (g + d_sign(&r__, &g));
00489 
00490         s = 1.;
00491         c__ = 1.;
00492         p = 0.;
00493 
00494 /*        Inner loop */
00495 
00496         lm1 = l - 1;
00497         i__1 = lm1;
00498         for (i__ = m; i__ <= i__1; ++i__) {
00499             f = s * e[i__];
00500             b = c__ * e[i__];
00501             dlartg_(&g, &f, &c__, &s, &r__);
00502             if (i__ != m) {
00503                 e[i__ - 1] = r__;
00504             }
00505             g = d__[i__] - p;
00506             r__ = (d__[i__ + 1] - g) * s + c__ * 2. * b;
00507             p = s * r__;
00508             d__[i__] = g + p;
00509             g = c__ * r__ - b;
00510 
00511 /*           If eigenvectors are desired, then save rotations. */
00512 
00513             if (icompz > 0) {
00514                 work[i__] = c__;
00515                 work[*n - 1 + i__] = s;
00516             }
00517 
00518 /* L120: */
00519         }
00520 
00521 /*        If eigenvectors are desired, then apply saved rotations. */
00522 
00523         if (icompz > 0) {
00524             mm = l - m + 1;
00525             dlasr_("R", "V", "F", n, &mm, &work[m], &work[*n - 1 + m], &z__[m 
00526                     * z_dim1 + 1], ldz);
00527         }
00528 
00529         d__[l] -= p;
00530         e[lm1] = g;
00531         goto L90;
00532 
00533 /*        Eigenvalue found. */
00534 
00535 L130:
00536         d__[l] = p;
00537 
00538         --l;
00539         if (l >= lend) {
00540             goto L90;
00541         }
00542         goto L140;
00543 
00544     }
00545 
00546 /*     Undo scaling if necessary */
00547 
00548 L140:
00549     if (iscale == 1) {
00550         i__1 = lendsv - lsv + 1;
00551         dlascl_("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &d__[lsv], 
00552                 n, info);
00553         i__1 = lendsv - lsv;
00554         dlascl_("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &e[lsv], n, 
00555                 info);
00556     } else if (iscale == 2) {
00557         i__1 = lendsv - lsv + 1;
00558         dlascl_("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &d__[lsv], 
00559                 n, info);
00560         i__1 = lendsv - lsv;
00561         dlascl_("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &e[lsv], n, 
00562                 info);
00563     }
00564 
00565 /*     Check for no convergence to an eigenvalue after a total */
00566 /*     of N*MAXIT iterations. */
00567 
00568     if (jtot < nmaxit) {
00569         goto L10;
00570     }
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     goto L190;
00579 
00580 /*     Order eigenvalues and eigenvectors. */
00581 
00582 L160:
00583     if (icompz == 0) {
00584 
00585 /*        Use Quick Sort */
00586 
00587         dlasrt_("I", n, &d__[1], info);
00588 
00589     } else {
00590 
00591 /*        Use Selection Sort to minimize swaps of eigenvectors */
00592 
00593         i__1 = *n;
00594         for (ii = 2; ii <= i__1; ++ii) {
00595             i__ = ii - 1;
00596             k = i__;
00597             p = d__[i__];
00598             i__2 = *n;
00599             for (j = ii; j <= i__2; ++j) {
00600                 if (d__[j] < p) {
00601                     k = j;
00602                     p = d__[j];
00603                 }
00604 /* L170: */
00605             }
00606             if (k != i__) {
00607                 d__[k] = d__[i__];
00608                 d__[i__] = p;
00609                 dswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[k * z_dim1 + 1], 
00610                          &c__1);
00611             }
00612 /* L180: */
00613         }
00614     }
00615 
00616 L190:
00617     return 0;
00618 
00619 /*     End of DSTEQR */
00620 
00621 } /* dsteqr_ */


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