sstebz.c
Go to the documentation of this file.
00001 /* sstebz.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__1 = 1;
00019 static integer c_n1 = -1;
00020 static integer c__3 = 3;
00021 static integer c__2 = 2;
00022 static integer c__0 = 0;
00023 
00024 /* Subroutine */ int sstebz_(char *range, char *order, integer *n, real *vl, 
00025         real *vu, integer *il, integer *iu, real *abstol, real *d__, real *e, 
00026         integer *m, integer *nsplit, real *w, integer *iblock, integer *
00027         isplit, real *work, integer *iwork, integer *info)
00028 {
00029     /* System generated locals */
00030     integer i__1, i__2, i__3;
00031     real r__1, r__2, r__3, r__4, r__5;
00032 
00033     /* Builtin functions */
00034     double sqrt(doublereal), log(doublereal);
00035 
00036     /* Local variables */
00037     integer j, ib, jb, ie, je, nb;
00038     real gl;
00039     integer im, in;
00040     real gu;
00041     integer iw;
00042     real wl, wu;
00043     integer nwl;
00044     real ulp, wlu, wul;
00045     integer nwu;
00046     real tmp1, tmp2;
00047     integer iend, ioff, iout, itmp1, jdisc;
00048     extern logical lsame_(char *, char *);
00049     integer iinfo;
00050     real atoli;
00051     integer iwoff;
00052     real bnorm;
00053     integer itmax;
00054     real wkill, rtoli, tnorm;
00055     integer ibegin, irange, idiscl;
00056     extern doublereal slamch_(char *);
00057     real safemn;
00058     integer idumma[1];
00059     extern /* Subroutine */ int xerbla_(char *, integer *);
00060     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
00061             integer *, integer *);
00062     integer idiscu;
00063     extern /* Subroutine */ int slaebz_(integer *, integer *, integer *, 
00064             integer *, integer *, integer *, real *, real *, real *, real *, 
00065             real *, real *, integer *, real *, real *, integer *, integer *, 
00066             real *, integer *, integer *);
00067     integer iorder;
00068     logical ncnvrg;
00069     real pivmin;
00070     logical toofew;
00071 
00072 
00073 /*  -- LAPACK routine (version 3.2) -- */
00074 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00075 /*     November 2006 */
00076 /*     8-18-00:  Increase FUDGE factor for T3E (eca) */
00077 
00078 /*     .. Scalar Arguments .. */
00079 /*     .. */
00080 /*     .. Array Arguments .. */
00081 /*     .. */
00082 
00083 /*  Purpose */
00084 /*  ======= */
00085 
00086 /*  SSTEBZ computes the eigenvalues of a symmetric tridiagonal */
00087 /*  matrix T.  The user may ask for all eigenvalues, all eigenvalues */
00088 /*  in the half-open interval (VL, VU], or the IL-th through IU-th */
00089 /*  eigenvalues. */
00090 
00091 /*  To avoid overflow, the matrix must be scaled so that its */
00092 /*  largest element is no greater than overflow**(1/2) * */
00093 /*  underflow**(1/4) in absolute value, and for greatest */
00094 /*  accuracy, it should not be much smaller than that. */
00095 
00096 /*  See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal */
00097 /*  Matrix", Report CS41, Computer Science Dept., Stanford */
00098 /*  University, July 21, 1966. */
00099 
00100 /*  Arguments */
00101 /*  ========= */
00102 
00103 /*  RANGE   (input) CHARACTER*1 */
00104 /*          = 'A': ("All")   all eigenvalues will be found. */
00105 /*          = 'V': ("Value") all eigenvalues in the half-open interval */
00106 /*                           (VL, VU] will be found. */
00107 /*          = 'I': ("Index") the IL-th through IU-th eigenvalues (of the */
00108 /*                           entire matrix) will be found. */
00109 
00110 /*  ORDER   (input) CHARACTER*1 */
00111 /*          = 'B': ("By Block") the eigenvalues will be grouped by */
00112 /*                              split-off block (see IBLOCK, ISPLIT) and */
00113 /*                              ordered from smallest to largest within */
00114 /*                              the block. */
00115 /*          = 'E': ("Entire matrix") */
00116 /*                              the eigenvalues for the entire matrix */
00117 /*                              will be ordered from smallest to */
00118 /*                              largest. */
00119 
00120 /*  N       (input) INTEGER */
00121 /*          The order of the tridiagonal matrix T.  N >= 0. */
00122 
00123 /*  VL      (input) REAL */
00124 /*  VU      (input) REAL */
00125 /*          If RANGE='V', the lower and upper bounds of the interval to */
00126 /*          be searched for eigenvalues.  Eigenvalues less than or equal */
00127 /*          to VL, or greater than VU, will not be returned.  VL < VU. */
00128 /*          Not referenced if RANGE = 'A' or 'I'. */
00129 
00130 /*  IL      (input) INTEGER */
00131 /*  IU      (input) INTEGER */
00132 /*          If RANGE='I', the indices (in ascending order) of the */
00133 /*          smallest and largest eigenvalues to be returned. */
00134 /*          1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. */
00135 /*          Not referenced if RANGE = 'A' or 'V'. */
00136 
00137 /*  ABSTOL  (input) REAL */
00138 /*          The absolute tolerance for the eigenvalues.  An eigenvalue */
00139 /*          (or cluster) is considered to be located if it has been */
00140 /*          determined to lie in an interval whose width is ABSTOL or */
00141 /*          less.  If ABSTOL is less than or equal to zero, then ULP*|T| */
00142 /*          will be used, where |T| means the 1-norm of T. */
00143 
00144 /*          Eigenvalues will be computed most accurately when ABSTOL is */
00145 /*          set to twice the underflow threshold 2*SLAMCH('S'), not zero. */
00146 
00147 /*  D       (input) REAL array, dimension (N) */
00148 /*          The n diagonal elements of the tridiagonal matrix T. */
00149 
00150 /*  E       (input) REAL array, dimension (N-1) */
00151 /*          The (n-1) off-diagonal elements of the tridiagonal matrix T. */
00152 
00153 /*  M       (output) INTEGER */
00154 /*          The actual number of eigenvalues found. 0 <= M <= N. */
00155 /*          (See also the description of INFO=2,3.) */
00156 
00157 /*  NSPLIT  (output) INTEGER */
00158 /*          The number of diagonal blocks in the matrix T. */
00159 /*          1 <= NSPLIT <= N. */
00160 
00161 /*  W       (output) REAL array, dimension (N) */
00162 /*          On exit, the first M elements of W will contain the */
00163 /*          eigenvalues.  (SSTEBZ may use the remaining N-M elements as */
00164 /*          workspace.) */
00165 
00166 /*  IBLOCK  (output) INTEGER array, dimension (N) */
00167 /*          At each row/column j where E(j) is zero or small, the */
00168 /*          matrix T is considered to split into a block diagonal */
00169 /*          matrix.  On exit, if INFO = 0, IBLOCK(i) specifies to which */
00170 /*          block (from 1 to the number of blocks) the eigenvalue W(i) */
00171 /*          belongs.  (SSTEBZ may use the remaining N-M elements as */
00172 /*          workspace.) */
00173 
00174 /*  ISPLIT  (output) INTEGER array, dimension (N) */
00175 /*          The splitting points, at which T breaks up into submatrices. */
00176 /*          The first submatrix consists of rows/columns 1 to ISPLIT(1), */
00177 /*          the second of rows/columns ISPLIT(1)+1 through ISPLIT(2), */
00178 /*          etc., and the NSPLIT-th consists of rows/columns */
00179 /*          ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N. */
00180 /*          (Only the first NSPLIT elements will actually be used, but */
00181 /*          since the user cannot know a priori what value NSPLIT will */
00182 /*          have, N words must be reserved for ISPLIT.) */
00183 
00184 /*  WORK    (workspace) REAL array, dimension (4*N) */
00185 
00186 /*  IWORK   (workspace) INTEGER array, dimension (3*N) */
00187 
00188 /*  INFO    (output) INTEGER */
00189 /*          = 0:  successful exit */
00190 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00191 /*          > 0:  some or all of the eigenvalues failed to converge or */
00192 /*                were not computed: */
00193 /*                =1 or 3: Bisection failed to converge for some */
00194 /*                        eigenvalues; these eigenvalues are flagged by a */
00195 /*                        negative block number.  The effect is that the */
00196 /*                        eigenvalues may not be as accurate as the */
00197 /*                        absolute and relative tolerances.  This is */
00198 /*                        generally caused by unexpectedly inaccurate */
00199 /*                        arithmetic. */
00200 /*                =2 or 3: RANGE='I' only: Not all of the eigenvalues */
00201 /*                        IL:IU were found. */
00202 /*                        Effect: M < IU+1-IL */
00203 /*                        Cause:  non-monotonic arithmetic, causing the */
00204 /*                                Sturm sequence to be non-monotonic. */
00205 /*                        Cure:   recalculate, using RANGE='A', and pick */
00206 /*                                out eigenvalues IL:IU.  In some cases, */
00207 /*                                increasing the PARAMETER "FUDGE" may */
00208 /*                                make things work. */
00209 /*                = 4:    RANGE='I', and the Gershgorin interval */
00210 /*                        initially used was too small.  No eigenvalues */
00211 /*                        were computed. */
00212 /*                        Probable cause: your machine has sloppy */
00213 /*                                        floating-point arithmetic. */
00214 /*                        Cure: Increase the PARAMETER "FUDGE", */
00215 /*                              recompile, and try again. */
00216 
00217 /*  Internal Parameters */
00218 /*  =================== */
00219 
00220 /*  RELFAC  REAL, default = 2.0e0 */
00221 /*          The relative tolerance.  An interval (a,b] lies within */
00222 /*          "relative tolerance" if  b-a < RELFAC*ulp*max(|a|,|b|), */
00223 /*          where "ulp" is the machine precision (distance from 1 to */
00224 /*          the next larger floating point number.) */
00225 
00226 /*  FUDGE   REAL, default = 2 */
00227 /*          A "fudge factor" to widen the Gershgorin intervals.  Ideally, */
00228 /*          a value of 1 should work, but on machines with sloppy */
00229 /*          arithmetic, this needs to be larger.  The default for */
00230 /*          publicly released versions should be large enough to handle */
00231 /*          the worst machine around.  Note that this has no effect */
00232 /*          on accuracy of the solution. */
00233 
00234 /*  ===================================================================== */
00235 
00236 /*     .. Parameters .. */
00237 /*     .. */
00238 /*     .. Local Scalars .. */
00239 /*     .. */
00240 /*     .. Local Arrays .. */
00241 /*     .. */
00242 /*     .. External Functions .. */
00243 /*     .. */
00244 /*     .. External Subroutines .. */
00245 /*     .. */
00246 /*     .. Intrinsic Functions .. */
00247 /*     .. */
00248 /*     .. Executable Statements .. */
00249 
00250     /* Parameter adjustments */
00251     --iwork;
00252     --work;
00253     --isplit;
00254     --iblock;
00255     --w;
00256     --e;
00257     --d__;
00258 
00259     /* Function Body */
00260     *info = 0;
00261 
00262 /*     Decode RANGE */
00263 
00264     if (lsame_(range, "A")) {
00265         irange = 1;
00266     } else if (lsame_(range, "V")) {
00267         irange = 2;
00268     } else if (lsame_(range, "I")) {
00269         irange = 3;
00270     } else {
00271         irange = 0;
00272     }
00273 
00274 /*     Decode ORDER */
00275 
00276     if (lsame_(order, "B")) {
00277         iorder = 2;
00278     } else if (lsame_(order, "E")) {
00279         iorder = 1;
00280     } else {
00281         iorder = 0;
00282     }
00283 
00284 /*     Check for Errors */
00285 
00286     if (irange <= 0) {
00287         *info = -1;
00288     } else if (iorder <= 0) {
00289         *info = -2;
00290     } else if (*n < 0) {
00291         *info = -3;
00292     } else if (irange == 2) {
00293         if (*vl >= *vu) {
00294             *info = -5;
00295         }
00296     } else if (irange == 3 && (*il < 1 || *il > max(1,*n))) {
00297         *info = -6;
00298     } else if (irange == 3 && (*iu < min(*n,*il) || *iu > *n)) {
00299         *info = -7;
00300     }
00301 
00302     if (*info != 0) {
00303         i__1 = -(*info);
00304         xerbla_("SSTEBZ", &i__1);
00305         return 0;
00306     }
00307 
00308 /*     Initialize error flags */
00309 
00310     *info = 0;
00311     ncnvrg = FALSE_;
00312     toofew = FALSE_;
00313 
00314 /*     Quick return if possible */
00315 
00316     *m = 0;
00317     if (*n == 0) {
00318         return 0;
00319     }
00320 
00321 /*     Simplifications: */
00322 
00323     if (irange == 3 && *il == 1 && *iu == *n) {
00324         irange = 1;
00325     }
00326 
00327 /*     Get machine constants */
00328 /*     NB is the minimum vector length for vector bisection, or 0 */
00329 /*     if only scalar is to be done. */
00330 
00331     safemn = slamch_("S");
00332     ulp = slamch_("P");
00333     rtoli = ulp * 2.f;
00334     nb = ilaenv_(&c__1, "SSTEBZ", " ", n, &c_n1, &c_n1, &c_n1);
00335     if (nb <= 1) {
00336         nb = 0;
00337     }
00338 
00339 /*     Special Case when N=1 */
00340 
00341     if (*n == 1) {
00342         *nsplit = 1;
00343         isplit[1] = 1;
00344         if (irange == 2 && (*vl >= d__[1] || *vu < d__[1])) {
00345             *m = 0;
00346         } else {
00347             w[1] = d__[1];
00348             iblock[1] = 1;
00349             *m = 1;
00350         }
00351         return 0;
00352     }
00353 
00354 /*     Compute Splitting Points */
00355 
00356     *nsplit = 1;
00357     work[*n] = 0.f;
00358     pivmin = 1.f;
00359 
00360 /* DIR$ NOVECTOR */
00361     i__1 = *n;
00362     for (j = 2; j <= i__1; ++j) {
00363 /* Computing 2nd power */
00364         r__1 = e[j - 1];
00365         tmp1 = r__1 * r__1;
00366 /* Computing 2nd power */
00367         r__2 = ulp;
00368         if ((r__1 = d__[j] * d__[j - 1], dabs(r__1)) * (r__2 * r__2) + safemn 
00369                 > tmp1) {
00370             isplit[*nsplit] = j - 1;
00371             ++(*nsplit);
00372             work[j - 1] = 0.f;
00373         } else {
00374             work[j - 1] = tmp1;
00375             pivmin = dmax(pivmin,tmp1);
00376         }
00377 /* L10: */
00378     }
00379     isplit[*nsplit] = *n;
00380     pivmin *= safemn;
00381 
00382 /*     Compute Interval and ATOLI */
00383 
00384     if (irange == 3) {
00385 
00386 /*        RANGE='I': Compute the interval containing eigenvalues */
00387 /*                   IL through IU. */
00388 
00389 /*        Compute Gershgorin interval for entire (split) matrix */
00390 /*        and use it as the initial interval */
00391 
00392         gu = d__[1];
00393         gl = d__[1];
00394         tmp1 = 0.f;
00395 
00396         i__1 = *n - 1;
00397         for (j = 1; j <= i__1; ++j) {
00398             tmp2 = sqrt(work[j]);
00399 /* Computing MAX */
00400             r__1 = gu, r__2 = d__[j] + tmp1 + tmp2;
00401             gu = dmax(r__1,r__2);
00402 /* Computing MIN */
00403             r__1 = gl, r__2 = d__[j] - tmp1 - tmp2;
00404             gl = dmin(r__1,r__2);
00405             tmp1 = tmp2;
00406 /* L20: */
00407         }
00408 
00409 /* Computing MAX */
00410         r__1 = gu, r__2 = d__[*n] + tmp1;
00411         gu = dmax(r__1,r__2);
00412 /* Computing MIN */
00413         r__1 = gl, r__2 = d__[*n] - tmp1;
00414         gl = dmin(r__1,r__2);
00415 /* Computing MAX */
00416         r__1 = dabs(gl), r__2 = dabs(gu);
00417         tnorm = dmax(r__1,r__2);
00418         gl = gl - tnorm * 2.1f * ulp * *n - pivmin * 4.2000000000000002f;
00419         gu = gu + tnorm * 2.1f * ulp * *n + pivmin * 2.1f;
00420 
00421 /*        Compute Iteration parameters */
00422 
00423         itmax = (integer) ((log(tnorm + pivmin) - log(pivmin)) / log(2.f)) + 
00424                 2;
00425         if (*abstol <= 0.f) {
00426             atoli = ulp * tnorm;
00427         } else {
00428             atoli = *abstol;
00429         }
00430 
00431         work[*n + 1] = gl;
00432         work[*n + 2] = gl;
00433         work[*n + 3] = gu;
00434         work[*n + 4] = gu;
00435         work[*n + 5] = gl;
00436         work[*n + 6] = gu;
00437         iwork[1] = -1;
00438         iwork[2] = -1;
00439         iwork[3] = *n + 1;
00440         iwork[4] = *n + 1;
00441         iwork[5] = *il - 1;
00442         iwork[6] = *iu;
00443 
00444         slaebz_(&c__3, &itmax, n, &c__2, &c__2, &nb, &atoli, &rtoli, &pivmin, 
00445                 &d__[1], &e[1], &work[1], &iwork[5], &work[*n + 1], &work[*n 
00446                 + 5], &iout, &iwork[1], &w[1], &iblock[1], &iinfo);
00447 
00448         if (iwork[6] == *iu) {
00449             wl = work[*n + 1];
00450             wlu = work[*n + 3];
00451             nwl = iwork[1];
00452             wu = work[*n + 4];
00453             wul = work[*n + 2];
00454             nwu = iwork[4];
00455         } else {
00456             wl = work[*n + 2];
00457             wlu = work[*n + 4];
00458             nwl = iwork[2];
00459             wu = work[*n + 3];
00460             wul = work[*n + 1];
00461             nwu = iwork[3];
00462         }
00463 
00464         if (nwl < 0 || nwl >= *n || nwu < 1 || nwu > *n) {
00465             *info = 4;
00466             return 0;
00467         }
00468     } else {
00469 
00470 /*        RANGE='A' or 'V' -- Set ATOLI */
00471 
00472 /* Computing MAX */
00473         r__3 = dabs(d__[1]) + dabs(e[1]), r__4 = (r__1 = d__[*n], dabs(r__1)) 
00474                 + (r__2 = e[*n - 1], dabs(r__2));
00475         tnorm = dmax(r__3,r__4);
00476 
00477         i__1 = *n - 1;
00478         for (j = 2; j <= i__1; ++j) {
00479 /* Computing MAX */
00480             r__4 = tnorm, r__5 = (r__1 = d__[j], dabs(r__1)) + (r__2 = e[j - 
00481                     1], dabs(r__2)) + (r__3 = e[j], dabs(r__3));
00482             tnorm = dmax(r__4,r__5);
00483 /* L30: */
00484         }
00485 
00486         if (*abstol <= 0.f) {
00487             atoli = ulp * tnorm;
00488         } else {
00489             atoli = *abstol;
00490         }
00491 
00492         if (irange == 2) {
00493             wl = *vl;
00494             wu = *vu;
00495         } else {
00496             wl = 0.f;
00497             wu = 0.f;
00498         }
00499     }
00500 
00501 /*     Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU. */
00502 /*     NWL accumulates the number of eigenvalues .le. WL, */
00503 /*     NWU accumulates the number of eigenvalues .le. WU */
00504 
00505     *m = 0;
00506     iend = 0;
00507     *info = 0;
00508     nwl = 0;
00509     nwu = 0;
00510 
00511     i__1 = *nsplit;
00512     for (jb = 1; jb <= i__1; ++jb) {
00513         ioff = iend;
00514         ibegin = ioff + 1;
00515         iend = isplit[jb];
00516         in = iend - ioff;
00517 
00518         if (in == 1) {
00519 
00520 /*           Special Case -- IN=1 */
00521 
00522             if (irange == 1 || wl >= d__[ibegin] - pivmin) {
00523                 ++nwl;
00524             }
00525             if (irange == 1 || wu >= d__[ibegin] - pivmin) {
00526                 ++nwu;
00527             }
00528             if (irange == 1 || wl < d__[ibegin] - pivmin && wu >= d__[ibegin] 
00529                     - pivmin) {
00530                 ++(*m);
00531                 w[*m] = d__[ibegin];
00532                 iblock[*m] = jb;
00533             }
00534         } else {
00535 
00536 /*           General Case -- IN > 1 */
00537 
00538 /*           Compute Gershgorin Interval */
00539 /*           and use it as the initial interval */
00540 
00541             gu = d__[ibegin];
00542             gl = d__[ibegin];
00543             tmp1 = 0.f;
00544 
00545             i__2 = iend - 1;
00546             for (j = ibegin; j <= i__2; ++j) {
00547                 tmp2 = (r__1 = e[j], dabs(r__1));
00548 /* Computing MAX */
00549                 r__1 = gu, r__2 = d__[j] + tmp1 + tmp2;
00550                 gu = dmax(r__1,r__2);
00551 /* Computing MIN */
00552                 r__1 = gl, r__2 = d__[j] - tmp1 - tmp2;
00553                 gl = dmin(r__1,r__2);
00554                 tmp1 = tmp2;
00555 /* L40: */
00556             }
00557 
00558 /* Computing MAX */
00559             r__1 = gu, r__2 = d__[iend] + tmp1;
00560             gu = dmax(r__1,r__2);
00561 /* Computing MIN */
00562             r__1 = gl, r__2 = d__[iend] - tmp1;
00563             gl = dmin(r__1,r__2);
00564 /* Computing MAX */
00565             r__1 = dabs(gl), r__2 = dabs(gu);
00566             bnorm = dmax(r__1,r__2);
00567             gl = gl - bnorm * 2.1f * ulp * in - pivmin * 2.1f;
00568             gu = gu + bnorm * 2.1f * ulp * in + pivmin * 2.1f;
00569 
00570 /*           Compute ATOLI for the current submatrix */
00571 
00572             if (*abstol <= 0.f) {
00573 /* Computing MAX */
00574                 r__1 = dabs(gl), r__2 = dabs(gu);
00575                 atoli = ulp * dmax(r__1,r__2);
00576             } else {
00577                 atoli = *abstol;
00578             }
00579 
00580             if (irange > 1) {
00581                 if (gu < wl) {
00582                     nwl += in;
00583                     nwu += in;
00584                     goto L70;
00585                 }
00586                 gl = dmax(gl,wl);
00587                 gu = dmin(gu,wu);
00588                 if (gl >= gu) {
00589                     goto L70;
00590                 }
00591             }
00592 
00593 /*           Set Up Initial Interval */
00594 
00595             work[*n + 1] = gl;
00596             work[*n + in + 1] = gu;
00597             slaebz_(&c__1, &c__0, &in, &in, &c__1, &nb, &atoli, &rtoli, &
00598                     pivmin, &d__[ibegin], &e[ibegin], &work[ibegin], idumma, &
00599                     work[*n + 1], &work[*n + (in << 1) + 1], &im, &iwork[1], &
00600                     w[*m + 1], &iblock[*m + 1], &iinfo);
00601 
00602             nwl += iwork[1];
00603             nwu += iwork[in + 1];
00604             iwoff = *m - iwork[1];
00605 
00606 /*           Compute Eigenvalues */
00607 
00608             itmax = (integer) ((log(gu - gl + pivmin) - log(pivmin)) / log(
00609                     2.f)) + 2;
00610             slaebz_(&c__2, &itmax, &in, &in, &c__1, &nb, &atoli, &rtoli, &
00611                     pivmin, &d__[ibegin], &e[ibegin], &work[ibegin], idumma, &
00612                     work[*n + 1], &work[*n + (in << 1) + 1], &iout, &iwork[1], 
00613                      &w[*m + 1], &iblock[*m + 1], &iinfo);
00614 
00615 /*           Copy Eigenvalues Into W and IBLOCK */
00616 /*           Use -JB for block number for unconverged eigenvalues. */
00617 
00618             i__2 = iout;
00619             for (j = 1; j <= i__2; ++j) {
00620                 tmp1 = (work[j + *n] + work[j + in + *n]) * .5f;
00621 
00622 /*              Flag non-convergence. */
00623 
00624                 if (j > iout - iinfo) {
00625                     ncnvrg = TRUE_;
00626                     ib = -jb;
00627                 } else {
00628                     ib = jb;
00629                 }
00630                 i__3 = iwork[j + in] + iwoff;
00631                 for (je = iwork[j] + 1 + iwoff; je <= i__3; ++je) {
00632                     w[je] = tmp1;
00633                     iblock[je] = ib;
00634 /* L50: */
00635                 }
00636 /* L60: */
00637             }
00638 
00639             *m += im;
00640         }
00641 L70:
00642         ;
00643     }
00644 
00645 /*     If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU */
00646 /*     If NWL+1 < IL or NWU > IU, discard extra eigenvalues. */
00647 
00648     if (irange == 3) {
00649         im = 0;
00650         idiscl = *il - 1 - nwl;
00651         idiscu = nwu - *iu;
00652 
00653         if (idiscl > 0 || idiscu > 0) {
00654             i__1 = *m;
00655             for (je = 1; je <= i__1; ++je) {
00656                 if (w[je] <= wlu && idiscl > 0) {
00657                     --idiscl;
00658                 } else if (w[je] >= wul && idiscu > 0) {
00659                     --idiscu;
00660                 } else {
00661                     ++im;
00662                     w[im] = w[je];
00663                     iblock[im] = iblock[je];
00664                 }
00665 /* L80: */
00666             }
00667             *m = im;
00668         }
00669         if (idiscl > 0 || idiscu > 0) {
00670 
00671 /*           Code to deal with effects of bad arithmetic: */
00672 /*           Some low eigenvalues to be discarded are not in (WL,WLU], */
00673 /*           or high eigenvalues to be discarded are not in (WUL,WU] */
00674 /*           so just kill off the smallest IDISCL/largest IDISCU */
00675 /*           eigenvalues, by simply finding the smallest/largest */
00676 /*           eigenvalue(s). */
00677 
00678 /*           (If N(w) is monotone non-decreasing, this should never */
00679 /*               happen.) */
00680 
00681             if (idiscl > 0) {
00682                 wkill = wu;
00683                 i__1 = idiscl;
00684                 for (jdisc = 1; jdisc <= i__1; ++jdisc) {
00685                     iw = 0;
00686                     i__2 = *m;
00687                     for (je = 1; je <= i__2; ++je) {
00688                         if (iblock[je] != 0 && (w[je] < wkill || iw == 0)) {
00689                             iw = je;
00690                             wkill = w[je];
00691                         }
00692 /* L90: */
00693                     }
00694                     iblock[iw] = 0;
00695 /* L100: */
00696                 }
00697             }
00698             if (idiscu > 0) {
00699 
00700                 wkill = wl;
00701                 i__1 = idiscu;
00702                 for (jdisc = 1; jdisc <= i__1; ++jdisc) {
00703                     iw = 0;
00704                     i__2 = *m;
00705                     for (je = 1; je <= i__2; ++je) {
00706                         if (iblock[je] != 0 && (w[je] > wkill || iw == 0)) {
00707                             iw = je;
00708                             wkill = w[je];
00709                         }
00710 /* L110: */
00711                     }
00712                     iblock[iw] = 0;
00713 /* L120: */
00714                 }
00715             }
00716             im = 0;
00717             i__1 = *m;
00718             for (je = 1; je <= i__1; ++je) {
00719                 if (iblock[je] != 0) {
00720                     ++im;
00721                     w[im] = w[je];
00722                     iblock[im] = iblock[je];
00723                 }
00724 /* L130: */
00725             }
00726             *m = im;
00727         }
00728         if (idiscl < 0 || idiscu < 0) {
00729             toofew = TRUE_;
00730         }
00731     }
00732 
00733 /*     If ORDER='B', do nothing -- the eigenvalues are already sorted */
00734 /*        by block. */
00735 /*     If ORDER='E', sort the eigenvalues from smallest to largest */
00736 
00737     if (iorder == 1 && *nsplit > 1) {
00738         i__1 = *m - 1;
00739         for (je = 1; je <= i__1; ++je) {
00740             ie = 0;
00741             tmp1 = w[je];
00742             i__2 = *m;
00743             for (j = je + 1; j <= i__2; ++j) {
00744                 if (w[j] < tmp1) {
00745                     ie = j;
00746                     tmp1 = w[j];
00747                 }
00748 /* L140: */
00749             }
00750 
00751             if (ie != 0) {
00752                 itmp1 = iblock[ie];
00753                 w[ie] = w[je];
00754                 iblock[ie] = iblock[je];
00755                 w[je] = tmp1;
00756                 iblock[je] = itmp1;
00757             }
00758 /* L150: */
00759         }
00760     }
00761 
00762     *info = 0;
00763     if (ncnvrg) {
00764         ++(*info);
00765     }
00766     if (toofew) {
00767         *info += 2;
00768     }
00769     return 0;
00770 
00771 /*     End of SSTEBZ */
00772 
00773 } /* sstebz_ */


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