ssterf.c
Go to the documentation of this file.
00001 /* ssterf.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 integer c__0 = 0;
00019 static integer c__1 = 1;
00020 static real c_b32 = 1.f;
00021 
00022 /* Subroutine */ int ssterf_(integer *n, real *d__, real *e, integer *info)
00023 {
00024     /* System generated locals */
00025     integer i__1;
00026     real r__1, r__2, r__3;
00027 
00028     /* Builtin functions */
00029     double sqrt(doublereal), r_sign(real *, real *);
00030 
00031     /* Local variables */
00032     real c__;
00033     integer i__, l, m;
00034     real p, r__, s;
00035     integer l1;
00036     real bb, rt1, rt2, eps, rte;
00037     integer lsv;
00038     real eps2, oldc;
00039     integer lend, jtot;
00040     extern /* Subroutine */ int slae2_(real *, real *, real *, real *, real *)
00041             ;
00042     real gamma, alpha, sigma, anorm;
00043     extern doublereal slapy2_(real *, real *);
00044     integer iscale;
00045     real oldgam;
00046     extern doublereal slamch_(char *);
00047     real safmin;
00048     extern /* Subroutine */ int xerbla_(char *, integer *);
00049     real safmax;
00050     extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, 
00051             real *, integer *, integer *, real *, integer *, integer *);
00052     integer lendsv;
00053     real ssfmin;
00054     integer nmaxit;
00055     real ssfmax;
00056     extern doublereal slanst_(char *, integer *, real *, real *);
00057     extern /* Subroutine */ int slasrt_(char *, integer *, real *, integer *);
00058 
00059 
00060 /*  -- LAPACK routine (version 3.2) -- */
00061 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00062 /*     November 2006 */
00063 
00064 /*     .. Scalar Arguments .. */
00065 /*     .. */
00066 /*     .. Array Arguments .. */
00067 /*     .. */
00068 
00069 /*  Purpose */
00070 /*  ======= */
00071 
00072 /*  SSTERF computes all eigenvalues of a symmetric tridiagonal matrix */
00073 /*  using the Pal-Walker-Kahan variant of the QL or QR algorithm. */
00074 
00075 /*  Arguments */
00076 /*  ========= */
00077 
00078 /*  N       (input) INTEGER */
00079 /*          The order of the matrix.  N >= 0. */
00080 
00081 /*  D       (input/output) REAL array, dimension (N) */
00082 /*          On entry, the n diagonal elements of the tridiagonal matrix. */
00083 /*          On exit, if INFO = 0, the eigenvalues in ascending order. */
00084 
00085 /*  E       (input/output) REAL array, dimension (N-1) */
00086 /*          On entry, the (n-1) subdiagonal elements of the tridiagonal */
00087 /*          matrix. */
00088 /*          On exit, E has been destroyed. */
00089 
00090 /*  INFO    (output) INTEGER */
00091 /*          = 0:  successful exit */
00092 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00093 /*          > 0:  the algorithm failed to find all of the eigenvalues in */
00094 /*                a total of 30*N iterations; if INFO = i, then i */
00095 /*                elements of E have not converged to zero. */
00096 
00097 /*  ===================================================================== */
00098 
00099 /*     .. Parameters .. */
00100 /*     .. */
00101 /*     .. Local Scalars .. */
00102 /*     .. */
00103 /*     .. External Functions .. */
00104 /*     .. */
00105 /*     .. External Subroutines .. */
00106 /*     .. */
00107 /*     .. Intrinsic Functions .. */
00108 /*     .. */
00109 /*     .. Executable Statements .. */
00110 
00111 /*     Test the input parameters. */
00112 
00113     /* Parameter adjustments */
00114     --e;
00115     --d__;
00116 
00117     /* Function Body */
00118     *info = 0;
00119 
00120 /*     Quick return if possible */
00121 
00122     if (*n < 0) {
00123         *info = -1;
00124         i__1 = -(*info);
00125         xerbla_("SSTERF", &i__1);
00126         return 0;
00127     }
00128     if (*n <= 1) {
00129         return 0;
00130     }
00131 
00132 /*     Determine the unit roundoff for this environment. */
00133 
00134     eps = slamch_("E");
00135 /* Computing 2nd power */
00136     r__1 = eps;
00137     eps2 = r__1 * r__1;
00138     safmin = slamch_("S");
00139     safmax = 1.f / safmin;
00140     ssfmax = sqrt(safmax) / 3.f;
00141     ssfmin = sqrt(safmin) / eps2;
00142 
00143 /*     Compute the eigenvalues of the tridiagonal matrix. */
00144 
00145     nmaxit = *n * 30;
00146     sigma = 0.f;
00147     jtot = 0;
00148 
00149 /*     Determine where the matrix splits and choose QL or QR iteration */
00150 /*     for each block, according to whether top or bottom diagonal */
00151 /*     element is smaller. */
00152 
00153     l1 = 1;
00154 
00155 L10:
00156     if (l1 > *n) {
00157         goto L170;
00158     }
00159     if (l1 > 1) {
00160         e[l1 - 1] = 0.f;
00161     }
00162     i__1 = *n - 1;
00163     for (m = l1; m <= i__1; ++m) {
00164         if ((r__3 = e[m], dabs(r__3)) <= sqrt((r__1 = d__[m], dabs(r__1))) * 
00165                 sqrt((r__2 = d__[m + 1], dabs(r__2))) * eps) {
00166             e[m] = 0.f;
00167             goto L30;
00168         }
00169 /* L20: */
00170     }
00171     m = *n;
00172 
00173 L30:
00174     l = l1;
00175     lsv = l;
00176     lend = m;
00177     lendsv = lend;
00178     l1 = m + 1;
00179     if (lend == l) {
00180         goto L10;
00181     }
00182 
00183 /*     Scale submatrix in rows and columns L to LEND */
00184 
00185     i__1 = lend - l + 1;
00186     anorm = slanst_("I", &i__1, &d__[l], &e[l]);
00187     iscale = 0;
00188     if (anorm > ssfmax) {
00189         iscale = 1;
00190         i__1 = lend - l + 1;
00191         slascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &d__[l], n, 
00192                 info);
00193         i__1 = lend - l;
00194         slascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &e[l], n, 
00195                 info);
00196     } else if (anorm < ssfmin) {
00197         iscale = 2;
00198         i__1 = lend - l + 1;
00199         slascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &d__[l], n, 
00200                 info);
00201         i__1 = lend - l;
00202         slascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &e[l], n, 
00203                 info);
00204     }
00205 
00206     i__1 = lend - 1;
00207     for (i__ = l; i__ <= i__1; ++i__) {
00208 /* Computing 2nd power */
00209         r__1 = e[i__];
00210         e[i__] = r__1 * r__1;
00211 /* L40: */
00212     }
00213 
00214 /*     Choose between QL and QR iteration */
00215 
00216     if ((r__1 = d__[lend], dabs(r__1)) < (r__2 = d__[l], dabs(r__2))) {
00217         lend = lsv;
00218         l = lendsv;
00219     }
00220 
00221     if (lend >= l) {
00222 
00223 /*        QL Iteration */
00224 
00225 /*        Look for small subdiagonal element. */
00226 
00227 L50:
00228         if (l != lend) {
00229             i__1 = lend - 1;
00230             for (m = l; m <= i__1; ++m) {
00231                 if ((r__2 = e[m], dabs(r__2)) <= eps2 * (r__1 = d__[m] * d__[
00232                         m + 1], dabs(r__1))) {
00233                     goto L70;
00234                 }
00235 /* L60: */
00236             }
00237         }
00238         m = lend;
00239 
00240 L70:
00241         if (m < lend) {
00242             e[m] = 0.f;
00243         }
00244         p = d__[l];
00245         if (m == l) {
00246             goto L90;
00247         }
00248 
00249 /*        If remaining matrix is 2 by 2, use SLAE2 to compute its */
00250 /*        eigenvalues. */
00251 
00252         if (m == l + 1) {
00253             rte = sqrt(e[l]);
00254             slae2_(&d__[l], &rte, &d__[l + 1], &rt1, &rt2);
00255             d__[l] = rt1;
00256             d__[l + 1] = rt2;
00257             e[l] = 0.f;
00258             l += 2;
00259             if (l <= lend) {
00260                 goto L50;
00261             }
00262             goto L150;
00263         }
00264 
00265         if (jtot == nmaxit) {
00266             goto L150;
00267         }
00268         ++jtot;
00269 
00270 /*        Form shift. */
00271 
00272         rte = sqrt(e[l]);
00273         sigma = (d__[l + 1] - p) / (rte * 2.f);
00274         r__ = slapy2_(&sigma, &c_b32);
00275         sigma = p - rte / (sigma + r_sign(&r__, &sigma));
00276 
00277         c__ = 1.f;
00278         s = 0.f;
00279         gamma = d__[m] - sigma;
00280         p = gamma * gamma;
00281 
00282 /*        Inner loop */
00283 
00284         i__1 = l;
00285         for (i__ = m - 1; i__ >= i__1; --i__) {
00286             bb = e[i__];
00287             r__ = p + bb;
00288             if (i__ != m - 1) {
00289                 e[i__ + 1] = s * r__;
00290             }
00291             oldc = c__;
00292             c__ = p / r__;
00293             s = bb / r__;
00294             oldgam = gamma;
00295             alpha = d__[i__];
00296             gamma = c__ * (alpha - sigma) - s * oldgam;
00297             d__[i__ + 1] = oldgam + (alpha - gamma);
00298             if (c__ != 0.f) {
00299                 p = gamma * gamma / c__;
00300             } else {
00301                 p = oldc * bb;
00302             }
00303 /* L80: */
00304         }
00305 
00306         e[l] = s * p;
00307         d__[l] = sigma + gamma;
00308         goto L50;
00309 
00310 /*        Eigenvalue found. */
00311 
00312 L90:
00313         d__[l] = p;
00314 
00315         ++l;
00316         if (l <= lend) {
00317             goto L50;
00318         }
00319         goto L150;
00320 
00321     } else {
00322 
00323 /*        QR Iteration */
00324 
00325 /*        Look for small superdiagonal element. */
00326 
00327 L100:
00328         i__1 = lend + 1;
00329         for (m = l; m >= i__1; --m) {
00330             if ((r__2 = e[m - 1], dabs(r__2)) <= eps2 * (r__1 = d__[m] * d__[
00331                     m - 1], dabs(r__1))) {
00332                 goto L120;
00333             }
00334 /* L110: */
00335         }
00336         m = lend;
00337 
00338 L120:
00339         if (m > lend) {
00340             e[m - 1] = 0.f;
00341         }
00342         p = d__[l];
00343         if (m == l) {
00344             goto L140;
00345         }
00346 
00347 /*        If remaining matrix is 2 by 2, use SLAE2 to compute its */
00348 /*        eigenvalues. */
00349 
00350         if (m == l - 1) {
00351             rte = sqrt(e[l - 1]);
00352             slae2_(&d__[l], &rte, &d__[l - 1], &rt1, &rt2);
00353             d__[l] = rt1;
00354             d__[l - 1] = rt2;
00355             e[l - 1] = 0.f;
00356             l += -2;
00357             if (l >= lend) {
00358                 goto L100;
00359             }
00360             goto L150;
00361         }
00362 
00363         if (jtot == nmaxit) {
00364             goto L150;
00365         }
00366         ++jtot;
00367 
00368 /*        Form shift. */
00369 
00370         rte = sqrt(e[l - 1]);
00371         sigma = (d__[l - 1] - p) / (rte * 2.f);
00372         r__ = slapy2_(&sigma, &c_b32);
00373         sigma = p - rte / (sigma + r_sign(&r__, &sigma));
00374 
00375         c__ = 1.f;
00376         s = 0.f;
00377         gamma = d__[m] - sigma;
00378         p = gamma * gamma;
00379 
00380 /*        Inner loop */
00381 
00382         i__1 = l - 1;
00383         for (i__ = m; i__ <= i__1; ++i__) {
00384             bb = e[i__];
00385             r__ = p + bb;
00386             if (i__ != m) {
00387                 e[i__ - 1] = s * r__;
00388             }
00389             oldc = c__;
00390             c__ = p / r__;
00391             s = bb / r__;
00392             oldgam = gamma;
00393             alpha = d__[i__ + 1];
00394             gamma = c__ * (alpha - sigma) - s * oldgam;
00395             d__[i__] = oldgam + (alpha - gamma);
00396             if (c__ != 0.f) {
00397                 p = gamma * gamma / c__;
00398             } else {
00399                 p = oldc * bb;
00400             }
00401 /* L130: */
00402         }
00403 
00404         e[l - 1] = s * p;
00405         d__[l] = sigma + gamma;
00406         goto L100;
00407 
00408 /*        Eigenvalue found. */
00409 
00410 L140:
00411         d__[l] = p;
00412 
00413         --l;
00414         if (l >= lend) {
00415             goto L100;
00416         }
00417         goto L150;
00418 
00419     }
00420 
00421 /*     Undo scaling if necessary */
00422 
00423 L150:
00424     if (iscale == 1) {
00425         i__1 = lendsv - lsv + 1;
00426         slascl_("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &d__[lsv], 
00427                 n, info);
00428     }
00429     if (iscale == 2) {
00430         i__1 = lendsv - lsv + 1;
00431         slascl_("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &d__[lsv], 
00432                 n, info);
00433     }
00434 
00435 /*     Check for no convergence to an eigenvalue after a total */
00436 /*     of N*MAXIT iterations. */
00437 
00438     if (jtot < nmaxit) {
00439         goto L10;
00440     }
00441     i__1 = *n - 1;
00442     for (i__ = 1; i__ <= i__1; ++i__) {
00443         if (e[i__] != 0.f) {
00444             ++(*info);
00445         }
00446 /* L160: */
00447     }
00448     goto L180;
00449 
00450 /*     Sort eigenvalues in increasing order. */
00451 
00452 L170:
00453     slasrt_("I", n, &d__[1], info);
00454 
00455 L180:
00456     return 0;
00457 
00458 /*     End of SSTERF */
00459 
00460 } /* ssterf_ */


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