dlarre.c
Go to the documentation of this file.
00001 /* dlarre.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__2 = 2;
00020 
00021 /* Subroutine */ int dlarre_(char *range, integer *n, doublereal *vl, 
00022         doublereal *vu, integer *il, integer *iu, doublereal *d__, doublereal 
00023         *e, doublereal *e2, doublereal *rtol1, doublereal *rtol2, doublereal *
00024         spltol, integer *nsplit, integer *isplit, integer *m, doublereal *w, 
00025         doublereal *werr, doublereal *wgap, integer *iblock, integer *indexw, 
00026         doublereal *gers, doublereal *pivmin, doublereal *work, integer *
00027         iwork, integer *info)
00028 {
00029     /* System generated locals */
00030     integer i__1, i__2;
00031     doublereal d__1, d__2, d__3;
00032 
00033     /* Builtin functions */
00034     double sqrt(doublereal), log(doublereal);
00035 
00036     /* Local variables */
00037     integer i__, j;
00038     doublereal s1, s2;
00039     integer mb;
00040     doublereal gl;
00041     integer in, mm;
00042     doublereal gu;
00043     integer cnt;
00044     doublereal eps, tau, tmp, rtl;
00045     integer cnt1, cnt2;
00046     doublereal tmp1, eabs;
00047     integer iend, jblk;
00048     doublereal eold;
00049     integer indl;
00050     doublereal dmax__, emax;
00051     integer wend, idum, indu;
00052     doublereal rtol;
00053     integer iseed[4];
00054     doublereal avgap, sigma;
00055     extern logical lsame_(char *, char *);
00056     integer iinfo;
00057     extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 
00058             doublereal *, integer *);
00059     logical norep;
00060     extern /* Subroutine */ int dlasq2_(integer *, doublereal *, integer *);
00061     extern doublereal dlamch_(char *);
00062     integer ibegin;
00063     logical forceb;
00064     integer irange;
00065     doublereal sgndef;
00066     extern /* Subroutine */ int dlarra_(integer *, doublereal *, doublereal *, 
00067              doublereal *, doublereal *, doublereal *, integer *, integer *, 
00068             integer *), dlarrb_(integer *, doublereal *, doublereal *, 
00069             integer *, integer *, doublereal *, doublereal *, integer *, 
00070             doublereal *, doublereal *, doublereal *, doublereal *, integer *, 
00071              doublereal *, doublereal *, integer *, integer *), dlarrc_(char *
00072 , integer *, doublereal *, doublereal *, doublereal *, doublereal 
00073             *, doublereal *, integer *, integer *, integer *, integer *);
00074     integer wbegin;
00075     extern /* Subroutine */ int dlarrd_(char *, char *, integer *, doublereal 
00076             *, doublereal *, integer *, integer *, doublereal *, doublereal *, 
00077              doublereal *, doublereal *, doublereal *, doublereal *, integer *
00078 , integer *, integer *, doublereal *, doublereal *, doublereal *, 
00079             doublereal *, integer *, integer *, doublereal *, integer *, 
00080             integer *);
00081     doublereal safmin, spdiam;
00082     extern /* Subroutine */ int dlarrk_(integer *, integer *, doublereal *, 
00083             doublereal *, doublereal *, doublereal *, doublereal *, 
00084             doublereal *, doublereal *, doublereal *, integer *);
00085     logical usedqd;
00086     doublereal clwdth, isleft;
00087     extern /* Subroutine */ int dlarnv_(integer *, integer *, integer *, 
00088             doublereal *);
00089     doublereal isrght, bsrtol, dpivot;
00090 
00091 
00092 /*  -- LAPACK auxiliary routine (version 3.2) -- */
00093 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00094 /*     November 2006 */
00095 
00096 /*     .. Scalar Arguments .. */
00097 /*     .. */
00098 /*     .. Array Arguments .. */
00099 /*     .. */
00100 
00101 /*  Purpose */
00102 /*  ======= */
00103 
00104 /*  To find the desired eigenvalues of a given real symmetric */
00105 /*  tridiagonal matrix T, DLARRE sets any "small" off-diagonal */
00106 /*  elements to zero, and for each unreduced block T_i, it finds */
00107 /*  (a) a suitable shift at one end of the block's spectrum, */
00108 /*  (b) the base representation, T_i - sigma_i I = L_i D_i L_i^T, and */
00109 /*  (c) eigenvalues of each L_i D_i L_i^T. */
00110 /*  The representations and eigenvalues found are then used by */
00111 /*  DSTEMR to compute the eigenvectors of T. */
00112 /*  The accuracy varies depending on whether bisection is used to */
00113 /*  find a few eigenvalues or the dqds algorithm (subroutine DLASQ2) to */
00114 /*  conpute all and then discard any unwanted one. */
00115 /*  As an added benefit, DLARRE also outputs the n */
00116 /*  Gerschgorin intervals for the matrices L_i D_i L_i^T. */
00117 
00118 /*  Arguments */
00119 /*  ========= */
00120 
00121 /*  RANGE   (input) CHARACTER */
00122 /*          = 'A': ("All")   all eigenvalues will be found. */
00123 /*          = 'V': ("Value") all eigenvalues in the half-open interval */
00124 /*                           (VL, VU] will be found. */
00125 /*          = 'I': ("Index") the IL-th through IU-th eigenvalues (of the */
00126 /*                           entire matrix) will be found. */
00127 
00128 /*  N       (input) INTEGER */
00129 /*          The order of the matrix. N > 0. */
00130 
00131 /*  VL      (input/output) DOUBLE PRECISION */
00132 /*  VU      (input/output) DOUBLE PRECISION */
00133 /*          If RANGE='V', the lower and upper bounds for the eigenvalues. */
00134 /*          Eigenvalues less than or equal to VL, or greater than VU, */
00135 /*          will not be returned.  VL < VU. */
00136 /*          If RANGE='I' or ='A', DLARRE computes bounds on the desired */
00137 /*          part of the spectrum. */
00138 
00139 /*  IL      (input) INTEGER */
00140 /*  IU      (input) INTEGER */
00141 /*          If RANGE='I', the indices (in ascending order) of the */
00142 /*          smallest and largest eigenvalues to be returned. */
00143 /*          1 <= IL <= IU <= N. */
00144 
00145 /*  D       (input/output) DOUBLE PRECISION array, dimension (N) */
00146 /*          On entry, the N diagonal elements of the tridiagonal */
00147 /*          matrix T. */
00148 /*          On exit, the N diagonal elements of the diagonal */
00149 /*          matrices D_i. */
00150 
00151 /*  E       (input/output) DOUBLE PRECISION array, dimension (N) */
00152 /*          On entry, the first (N-1) entries contain the subdiagonal */
00153 /*          elements of the tridiagonal matrix T; E(N) need not be set. */
00154 /*          On exit, E contains the subdiagonal elements of the unit */
00155 /*          bidiagonal matrices L_i. The entries E( ISPLIT( I ) ), */
00156 /*          1 <= I <= NSPLIT, contain the base points sigma_i on output. */
00157 
00158 /*  E2      (input/output) DOUBLE PRECISION array, dimension (N) */
00159 /*          On entry, the first (N-1) entries contain the SQUARES of the */
00160 /*          subdiagonal elements of the tridiagonal matrix T; */
00161 /*          E2(N) need not be set. */
00162 /*          On exit, the entries E2( ISPLIT( I ) ), */
00163 /*          1 <= I <= NSPLIT, have been set to zero */
00164 
00165 /*  RTOL1   (input) DOUBLE PRECISION */
00166 /*  RTOL2   (input) DOUBLE PRECISION */
00167 /*           Parameters for bisection. */
00168 /*           An interval [LEFT,RIGHT] has converged if */
00169 /*           RIGHT-LEFT.LT.MAX( RTOL1*GAP, RTOL2*MAX(|LEFT|,|RIGHT|) ) */
00170 
00171 /*  SPLTOL (input) DOUBLE PRECISION */
00172 /*          The threshold for splitting. */
00173 
00174 /*  NSPLIT  (output) INTEGER */
00175 /*          The number of blocks T splits into. 1 <= NSPLIT <= N. */
00176 
00177 /*  ISPLIT  (output) INTEGER array, dimension (N) */
00178 /*          The splitting points, at which T breaks up into blocks. */
00179 /*          The first block consists of rows/columns 1 to ISPLIT(1), */
00180 /*          the second of rows/columns ISPLIT(1)+1 through ISPLIT(2), */
00181 /*          etc., and the NSPLIT-th consists of rows/columns */
00182 /*          ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N. */
00183 
00184 /*  M       (output) INTEGER */
00185 /*          The total number of eigenvalues (of all L_i D_i L_i^T) */
00186 /*          found. */
00187 
00188 /*  W       (output) DOUBLE PRECISION array, dimension (N) */
00189 /*          The first M elements contain the eigenvalues. The */
00190 /*          eigenvalues of each of the blocks, L_i D_i L_i^T, are */
00191 /*          sorted in ascending order ( DLARRE may use the */
00192 /*          remaining N-M elements as workspace). */
00193 
00194 /*  WERR    (output) DOUBLE PRECISION array, dimension (N) */
00195 /*          The error bound on the corresponding eigenvalue in W. */
00196 
00197 /*  WGAP    (output) DOUBLE PRECISION array, dimension (N) */
00198 /*          The separation from the right neighbor eigenvalue in W. */
00199 /*          The gap is only with respect to the eigenvalues of the same block */
00200 /*          as each block has its own representation tree. */
00201 /*          Exception: at the right end of a block we store the left gap */
00202 
00203 /*  IBLOCK  (output) INTEGER array, dimension (N) */
00204 /*          The indices of the blocks (submatrices) associated with the */
00205 /*          corresponding eigenvalues in W; IBLOCK(i)=1 if eigenvalue */
00206 /*          W(i) belongs to the first block from the top, =2 if W(i) */
00207 /*          belongs to the second block, etc. */
00208 
00209 /*  INDEXW  (output) INTEGER array, dimension (N) */
00210 /*          The indices of the eigenvalues within each block (submatrix); */
00211 /*          for example, INDEXW(i)= 10 and IBLOCK(i)=2 imply that the */
00212 /*          i-th eigenvalue W(i) is the 10-th eigenvalue in block 2 */
00213 
00214 /*  GERS    (output) DOUBLE PRECISION array, dimension (2*N) */
00215 /*          The N Gerschgorin intervals (the i-th Gerschgorin interval */
00216 /*          is (GERS(2*i-1), GERS(2*i)). */
00217 
00218 /*  PIVMIN  (output) DOUBLE PRECISION */
00219 /*          The minimum pivot in the Sturm sequence for T. */
00220 
00221 /*  WORK    (workspace) DOUBLE PRECISION array, dimension (6*N) */
00222 /*          Workspace. */
00223 
00224 /*  IWORK   (workspace) INTEGER array, dimension (5*N) */
00225 /*          Workspace. */
00226 
00227 /*  INFO    (output) INTEGER */
00228 /*          = 0:  successful exit */
00229 /*          > 0:  A problem occured in DLARRE. */
00230 /*          < 0:  One of the called subroutines signaled an internal problem. */
00231 /*                Needs inspection of the corresponding parameter IINFO */
00232 /*                for further information. */
00233 
00234 /*          =-1:  Problem in DLARRD. */
00235 /*          = 2:  No base representation could be found in MAXTRY iterations. */
00236 /*                Increasing MAXTRY and recompilation might be a remedy. */
00237 /*          =-3:  Problem in DLARRB when computing the refined root */
00238 /*                representation for DLASQ2. */
00239 /*          =-4:  Problem in DLARRB when preforming bisection on the */
00240 /*                desired part of the spectrum. */
00241 /*          =-5:  Problem in DLASQ2. */
00242 /*          =-6:  Problem in DLASQ2. */
00243 
00244 /*  Further Details */
00245 /*  The base representations are required to suffer very little */
00246 /*  element growth and consequently define all their eigenvalues to */
00247 /*  high relative accuracy. */
00248 /*  =============== */
00249 
00250 /*  Based on contributions by */
00251 /*     Beresford Parlett, University of California, Berkeley, USA */
00252 /*     Jim Demmel, University of California, Berkeley, USA */
00253 /*     Inderjit Dhillon, University of Texas, Austin, USA */
00254 /*     Osni Marques, LBNL/NERSC, USA */
00255 /*     Christof Voemel, University of California, Berkeley, USA */
00256 
00257 /*  ===================================================================== */
00258 
00259 /*     .. Parameters .. */
00260 /*     .. */
00261 /*     .. Local Scalars .. */
00262 /*     .. */
00263 /*     .. Local Arrays .. */
00264 /*     .. */
00265 /*     .. External Functions .. */
00266 /*     .. */
00267 /*     .. External Subroutines .. */
00268 /*     .. */
00269 /*     .. Intrinsic Functions .. */
00270 /*     .. */
00271 /*     .. Executable Statements .. */
00272 
00273     /* Parameter adjustments */
00274     --iwork;
00275     --work;
00276     --gers;
00277     --indexw;
00278     --iblock;
00279     --wgap;
00280     --werr;
00281     --w;
00282     --isplit;
00283     --e2;
00284     --e;
00285     --d__;
00286 
00287     /* Function Body */
00288     *info = 0;
00289 
00290 /*     Decode RANGE */
00291 
00292     if (lsame_(range, "A")) {
00293         irange = 1;
00294     } else if (lsame_(range, "V")) {
00295         irange = 3;
00296     } else if (lsame_(range, "I")) {
00297         irange = 2;
00298     }
00299     *m = 0;
00300 /*     Get machine constants */
00301     safmin = dlamch_("S");
00302     eps = dlamch_("P");
00303 /*     Set parameters */
00304     rtl = sqrt(eps);
00305     bsrtol = sqrt(eps);
00306 /*     Treat case of 1x1 matrix for quick return */
00307     if (*n == 1) {
00308         if (irange == 1 || irange == 3 && d__[1] > *vl && d__[1] <= *vu || 
00309                 irange == 2 && *il == 1 && *iu == 1) {
00310             *m = 1;
00311             w[1] = d__[1];
00312 /*           The computation error of the eigenvalue is zero */
00313             werr[1] = 0.;
00314             wgap[1] = 0.;
00315             iblock[1] = 1;
00316             indexw[1] = 1;
00317             gers[1] = d__[1];
00318             gers[2] = d__[1];
00319         }
00320 /*        store the shift for the initial RRR, which is zero in this case */
00321         e[1] = 0.;
00322         return 0;
00323     }
00324 /*     General case: tridiagonal matrix of order > 1 */
00325 
00326 /*     Init WERR, WGAP. Compute Gerschgorin intervals and spectral diameter. */
00327 /*     Compute maximum off-diagonal entry and pivmin. */
00328     gl = d__[1];
00329     gu = d__[1];
00330     eold = 0.;
00331     emax = 0.;
00332     e[*n] = 0.;
00333     i__1 = *n;
00334     for (i__ = 1; i__ <= i__1; ++i__) {
00335         werr[i__] = 0.;
00336         wgap[i__] = 0.;
00337         eabs = (d__1 = e[i__], abs(d__1));
00338         if (eabs >= emax) {
00339             emax = eabs;
00340         }
00341         tmp1 = eabs + eold;
00342         gers[(i__ << 1) - 1] = d__[i__] - tmp1;
00343 /* Computing MIN */
00344         d__1 = gl, d__2 = gers[(i__ << 1) - 1];
00345         gl = min(d__1,d__2);
00346         gers[i__ * 2] = d__[i__] + tmp1;
00347 /* Computing MAX */
00348         d__1 = gu, d__2 = gers[i__ * 2];
00349         gu = max(d__1,d__2);
00350         eold = eabs;
00351 /* L5: */
00352     }
00353 /*     The minimum pivot allowed in the Sturm sequence for T */
00354 /* Computing MAX */
00355 /* Computing 2nd power */
00356     d__3 = emax;
00357     d__1 = 1., d__2 = d__3 * d__3;
00358     *pivmin = safmin * max(d__1,d__2);
00359 /*     Compute spectral diameter. The Gerschgorin bounds give an */
00360 /*     estimate that is wrong by at most a factor of SQRT(2) */
00361     spdiam = gu - gl;
00362 /*     Compute splitting points */
00363     dlarra_(n, &d__[1], &e[1], &e2[1], spltol, &spdiam, nsplit, &isplit[1], &
00364             iinfo);
00365 /*     Can force use of bisection instead of faster DQDS. */
00366 /*     Option left in the code for future multisection work. */
00367     forceb = FALSE_;
00368 /*     Initialize USEDQD, DQDS should be used for ALLRNG unless someone */
00369 /*     explicitly wants bisection. */
00370     usedqd = irange == 1 && ! forceb;
00371     if (irange == 1 && ! forceb) {
00372 /*        Set interval [VL,VU] that contains all eigenvalues */
00373         *vl = gl;
00374         *vu = gu;
00375     } else {
00376 /*        We call DLARRD to find crude approximations to the eigenvalues */
00377 /*        in the desired range. In case IRANGE = INDRNG, we also obtain the */
00378 /*        interval (VL,VU] that contains all the wanted eigenvalues. */
00379 /*        An interval [LEFT,RIGHT] has converged if */
00380 /*        RIGHT-LEFT.LT.RTOL*MAX(ABS(LEFT),ABS(RIGHT)) */
00381 /*        DLARRD needs a WORK of size 4*N, IWORK of size 3*N */
00382         dlarrd_(range, "B", n, vl, vu, il, iu, &gers[1], &bsrtol, &d__[1], &e[
00383                 1], &e2[1], pivmin, nsplit, &isplit[1], &mm, &w[1], &werr[1], 
00384                 vl, vu, &iblock[1], &indexw[1], &work[1], &iwork[1], &iinfo);
00385         if (iinfo != 0) {
00386             *info = -1;
00387             return 0;
00388         }
00389 /*        Make sure that the entries M+1 to N in W, WERR, IBLOCK, INDEXW are 0 */
00390         i__1 = *n;
00391         for (i__ = mm + 1; i__ <= i__1; ++i__) {
00392             w[i__] = 0.;
00393             werr[i__] = 0.;
00394             iblock[i__] = 0;
00395             indexw[i__] = 0;
00396 /* L14: */
00397         }
00398     }
00399 /* ** */
00400 /*     Loop over unreduced blocks */
00401     ibegin = 1;
00402     wbegin = 1;
00403     i__1 = *nsplit;
00404     for (jblk = 1; jblk <= i__1; ++jblk) {
00405         iend = isplit[jblk];
00406         in = iend - ibegin + 1;
00407 /*        1 X 1 block */
00408         if (in == 1) {
00409             if (irange == 1 || irange == 3 && d__[ibegin] > *vl && d__[ibegin]
00410                      <= *vu || irange == 2 && iblock[wbegin] == jblk) {
00411                 ++(*m);
00412                 w[*m] = d__[ibegin];
00413                 werr[*m] = 0.;
00414 /*              The gap for a single block doesn't matter for the later */
00415 /*              algorithm and is assigned an arbitrary large value */
00416                 wgap[*m] = 0.;
00417                 iblock[*m] = jblk;
00418                 indexw[*m] = 1;
00419                 ++wbegin;
00420             }
00421 /*           E( IEND ) holds the shift for the initial RRR */
00422             e[iend] = 0.;
00423             ibegin = iend + 1;
00424             goto L170;
00425         }
00426 
00427 /*        Blocks of size larger than 1x1 */
00428 
00429 /*        E( IEND ) will hold the shift for the initial RRR, for now set it =0 */
00430         e[iend] = 0.;
00431 
00432 /*        Find local outer bounds GL,GU for the block */
00433         gl = d__[ibegin];
00434         gu = d__[ibegin];
00435         i__2 = iend;
00436         for (i__ = ibegin; i__ <= i__2; ++i__) {
00437 /* Computing MIN */
00438             d__1 = gers[(i__ << 1) - 1];
00439             gl = min(d__1,gl);
00440 /* Computing MAX */
00441             d__1 = gers[i__ * 2];
00442             gu = max(d__1,gu);
00443 /* L15: */
00444         }
00445         spdiam = gu - gl;
00446         if (! (irange == 1 && ! forceb)) {
00447 /*           Count the number of eigenvalues in the current block. */
00448             mb = 0;
00449             i__2 = mm;
00450             for (i__ = wbegin; i__ <= i__2; ++i__) {
00451                 if (iblock[i__] == jblk) {
00452                     ++mb;
00453                 } else {
00454                     goto L21;
00455                 }
00456 /* L20: */
00457             }
00458 L21:
00459             if (mb == 0) {
00460 /*              No eigenvalue in the current block lies in the desired range */
00461 /*              E( IEND ) holds the shift for the initial RRR */
00462                 e[iend] = 0.;
00463                 ibegin = iend + 1;
00464                 goto L170;
00465             } else {
00466 /*              Decide whether dqds or bisection is more efficient */
00467                 usedqd = (doublereal) mb > in * .5 && ! forceb;
00468                 wend = wbegin + mb - 1;
00469 /*              Calculate gaps for the current block */
00470 /*              In later stages, when representations for individual */
00471 /*              eigenvalues are different, we use SIGMA = E( IEND ). */
00472                 sigma = 0.;
00473                 i__2 = wend - 1;
00474                 for (i__ = wbegin; i__ <= i__2; ++i__) {
00475 /* Computing MAX */
00476                     d__1 = 0., d__2 = w[i__ + 1] - werr[i__ + 1] - (w[i__] + 
00477                             werr[i__]);
00478                     wgap[i__] = max(d__1,d__2);
00479 /* L30: */
00480                 }
00481 /* Computing MAX */
00482                 d__1 = 0., d__2 = *vu - sigma - (w[wend] + werr[wend]);
00483                 wgap[wend] = max(d__1,d__2);
00484 /*              Find local index of the first and last desired evalue. */
00485                 indl = indexw[wbegin];
00486                 indu = indexw[wend];
00487             }
00488         }
00489         if (irange == 1 && ! forceb || usedqd) {
00490 /*           Case of DQDS */
00491 /*           Find approximations to the extremal eigenvalues of the block */
00492             dlarrk_(&in, &c__1, &gl, &gu, &d__[ibegin], &e2[ibegin], pivmin, &
00493                     rtl, &tmp, &tmp1, &iinfo);
00494             if (iinfo != 0) {
00495                 *info = -1;
00496                 return 0;
00497             }
00498 /* Computing MAX */
00499             d__2 = gl, d__3 = tmp - tmp1 - eps * 100. * (d__1 = tmp - tmp1, 
00500                     abs(d__1));
00501             isleft = max(d__2,d__3);
00502             dlarrk_(&in, &in, &gl, &gu, &d__[ibegin], &e2[ibegin], pivmin, &
00503                     rtl, &tmp, &tmp1, &iinfo);
00504             if (iinfo != 0) {
00505                 *info = -1;
00506                 return 0;
00507             }
00508 /* Computing MIN */
00509             d__2 = gu, d__3 = tmp + tmp1 + eps * 100. * (d__1 = tmp + tmp1, 
00510                     abs(d__1));
00511             isrght = min(d__2,d__3);
00512 /*           Improve the estimate of the spectral diameter */
00513             spdiam = isrght - isleft;
00514         } else {
00515 /*           Case of bisection */
00516 /*           Find approximations to the wanted extremal eigenvalues */
00517 /* Computing MAX */
00518             d__2 = gl, d__3 = w[wbegin] - werr[wbegin] - eps * 100. * (d__1 = 
00519                     w[wbegin] - werr[wbegin], abs(d__1));
00520             isleft = max(d__2,d__3);
00521 /* Computing MIN */
00522             d__2 = gu, d__3 = w[wend] + werr[wend] + eps * 100. * (d__1 = w[
00523                     wend] + werr[wend], abs(d__1));
00524             isrght = min(d__2,d__3);
00525         }
00526 /*        Decide whether the base representation for the current block */
00527 /*        L_JBLK D_JBLK L_JBLK^T = T_JBLK - sigma_JBLK I */
00528 /*        should be on the left or the right end of the current block. */
00529 /*        The strategy is to shift to the end which is "more populated" */
00530 /*        Furthermore, decide whether to use DQDS for the computation of */
00531 /*        the eigenvalue approximations at the end of DLARRE or bisection. */
00532 /*        dqds is chosen if all eigenvalues are desired or the number of */
00533 /*        eigenvalues to be computed is large compared to the blocksize. */
00534         if (irange == 1 && ! forceb) {
00535 /*           If all the eigenvalues have to be computed, we use dqd */
00536             usedqd = TRUE_;
00537 /*           INDL is the local index of the first eigenvalue to compute */
00538             indl = 1;
00539             indu = in;
00540 /*           MB =  number of eigenvalues to compute */
00541             mb = in;
00542             wend = wbegin + mb - 1;
00543 /*           Define 1/4 and 3/4 points of the spectrum */
00544             s1 = isleft + spdiam * .25;
00545             s2 = isrght - spdiam * .25;
00546         } else {
00547 /*           DLARRD has computed IBLOCK and INDEXW for each eigenvalue */
00548 /*           approximation. */
00549 /*           choose sigma */
00550             if (usedqd) {
00551                 s1 = isleft + spdiam * .25;
00552                 s2 = isrght - spdiam * .25;
00553             } else {
00554                 tmp = min(isrght,*vu) - max(isleft,*vl);
00555                 s1 = max(isleft,*vl) + tmp * .25;
00556                 s2 = min(isrght,*vu) - tmp * .25;
00557             }
00558         }
00559 /*        Compute the negcount at the 1/4 and 3/4 points */
00560         if (mb > 1) {
00561             dlarrc_("T", &in, &s1, &s2, &d__[ibegin], &e[ibegin], pivmin, &
00562                     cnt, &cnt1, &cnt2, &iinfo);
00563         }
00564         if (mb == 1) {
00565             sigma = gl;
00566             sgndef = 1.;
00567         } else if (cnt1 - indl >= indu - cnt2) {
00568             if (irange == 1 && ! forceb) {
00569                 sigma = max(isleft,gl);
00570             } else if (usedqd) {
00571 /*              use Gerschgorin bound as shift to get pos def matrix */
00572 /*              for dqds */
00573                 sigma = isleft;
00574             } else {
00575 /*              use approximation of the first desired eigenvalue of the */
00576 /*              block as shift */
00577                 sigma = max(isleft,*vl);
00578             }
00579             sgndef = 1.;
00580         } else {
00581             if (irange == 1 && ! forceb) {
00582                 sigma = min(isrght,gu);
00583             } else if (usedqd) {
00584 /*              use Gerschgorin bound as shift to get neg def matrix */
00585 /*              for dqds */
00586                 sigma = isrght;
00587             } else {
00588 /*              use approximation of the first desired eigenvalue of the */
00589 /*              block as shift */
00590                 sigma = min(isrght,*vu);
00591             }
00592             sgndef = -1.;
00593         }
00594 /*        An initial SIGMA has been chosen that will be used for computing */
00595 /*        T - SIGMA I = L D L^T */
00596 /*        Define the increment TAU of the shift in case the initial shift */
00597 /*        needs to be refined to obtain a factorization with not too much */
00598 /*        element growth. */
00599         if (usedqd) {
00600 /*           The initial SIGMA was to the outer end of the spectrum */
00601 /*           the matrix is definite and we need not retreat. */
00602             tau = spdiam * eps * *n + *pivmin * 2.;
00603         } else {
00604             if (mb > 1) {
00605                 clwdth = w[wend] + werr[wend] - w[wbegin] - werr[wbegin];
00606                 avgap = (d__1 = clwdth / (doublereal) (wend - wbegin), abs(
00607                         d__1));
00608                 if (sgndef == 1.) {
00609 /* Computing MAX */
00610                     d__1 = wgap[wbegin];
00611                     tau = max(d__1,avgap) * .5;
00612 /* Computing MAX */
00613                     d__1 = tau, d__2 = werr[wbegin];
00614                     tau = max(d__1,d__2);
00615                 } else {
00616 /* Computing MAX */
00617                     d__1 = wgap[wend - 1];
00618                     tau = max(d__1,avgap) * .5;
00619 /* Computing MAX */
00620                     d__1 = tau, d__2 = werr[wend];
00621                     tau = max(d__1,d__2);
00622                 }
00623             } else {
00624                 tau = werr[wbegin];
00625             }
00626         }
00627 
00628         for (idum = 1; idum <= 6; ++idum) {
00629 /*           Compute L D L^T factorization of tridiagonal matrix T - sigma I. */
00630 /*           Store D in WORK(1:IN), L in WORK(IN+1:2*IN), and reciprocals of */
00631 /*           pivots in WORK(2*IN+1:3*IN) */
00632             dpivot = d__[ibegin] - sigma;
00633             work[1] = dpivot;
00634             dmax__ = abs(work[1]);
00635             j = ibegin;
00636             i__2 = in - 1;
00637             for (i__ = 1; i__ <= i__2; ++i__) {
00638                 work[(in << 1) + i__] = 1. / work[i__];
00639                 tmp = e[j] * work[(in << 1) + i__];
00640                 work[in + i__] = tmp;
00641                 dpivot = d__[j + 1] - sigma - tmp * e[j];
00642                 work[i__ + 1] = dpivot;
00643 /* Computing MAX */
00644                 d__1 = dmax__, d__2 = abs(dpivot);
00645                 dmax__ = max(d__1,d__2);
00646                 ++j;
00647 /* L70: */
00648             }
00649 /*           check for element growth */
00650             if (dmax__ > spdiam * 64.) {
00651                 norep = TRUE_;
00652             } else {
00653                 norep = FALSE_;
00654             }
00655             if (usedqd && ! norep) {
00656 /*              Ensure the definiteness of the representation */
00657 /*              All entries of D (of L D L^T) must have the same sign */
00658                 i__2 = in;
00659                 for (i__ = 1; i__ <= i__2; ++i__) {
00660                     tmp = sgndef * work[i__];
00661                     if (tmp < 0.) {
00662                         norep = TRUE_;
00663                     }
00664 /* L71: */
00665                 }
00666             }
00667             if (norep) {
00668 /*              Note that in the case of IRANGE=ALLRNG, we use the Gerschgorin */
00669 /*              shift which makes the matrix definite. So we should end up */
00670 /*              here really only in the case of IRANGE = VALRNG or INDRNG. */
00671                 if (idum == 5) {
00672                     if (sgndef == 1.) {
00673 /*                    The fudged Gerschgorin shift should succeed */
00674                         sigma = gl - spdiam * 2. * eps * *n - *pivmin * 4.;
00675                     } else {
00676                         sigma = gu + spdiam * 2. * eps * *n + *pivmin * 4.;
00677                     }
00678                 } else {
00679                     sigma -= sgndef * tau;
00680                     tau *= 2.;
00681                 }
00682             } else {
00683 /*              an initial RRR is found */
00684                 goto L83;
00685             }
00686 /* L80: */
00687         }
00688 /*        if the program reaches this point, no base representation could be */
00689 /*        found in MAXTRY iterations. */
00690         *info = 2;
00691         return 0;
00692 L83:
00693 /*        At this point, we have found an initial base representation */
00694 /*        T - SIGMA I = L D L^T with not too much element growth. */
00695 /*        Store the shift. */
00696         e[iend] = sigma;
00697 /*        Store D and L. */
00698         dcopy_(&in, &work[1], &c__1, &d__[ibegin], &c__1);
00699         i__2 = in - 1;
00700         dcopy_(&i__2, &work[in + 1], &c__1, &e[ibegin], &c__1);
00701         if (mb > 1) {
00702 
00703 /*           Perturb each entry of the base representation by a small */
00704 /*           (but random) relative amount to overcome difficulties with */
00705 /*           glued matrices. */
00706 
00707             for (i__ = 1; i__ <= 4; ++i__) {
00708                 iseed[i__ - 1] = 1;
00709 /* L122: */
00710             }
00711             i__2 = (in << 1) - 1;
00712             dlarnv_(&c__2, iseed, &i__2, &work[1]);
00713             i__2 = in - 1;
00714             for (i__ = 1; i__ <= i__2; ++i__) {
00715                 d__[ibegin + i__ - 1] *= eps * 8. * work[i__] + 1.;
00716                 e[ibegin + i__ - 1] *= eps * 8. * work[in + i__] + 1.;
00717 /* L125: */
00718             }
00719             d__[iend] *= eps * 4. * work[in] + 1.;
00720 
00721         }
00722 
00723 /*        Don't update the Gerschgorin intervals because keeping track */
00724 /*        of the updates would be too much work in DLARRV. */
00725 /*        We update W instead and use it to locate the proper Gerschgorin */
00726 /*        intervals. */
00727 /*        Compute the required eigenvalues of L D L' by bisection or dqds */
00728         if (! usedqd) {
00729 /*           If DLARRD has been used, shift the eigenvalue approximations */
00730 /*           according to their representation. This is necessary for */
00731 /*           a uniform DLARRV since dqds computes eigenvalues of the */
00732 /*           shifted representation. In DLARRV, W will always hold the */
00733 /*           UNshifted eigenvalue approximation. */
00734             i__2 = wend;
00735             for (j = wbegin; j <= i__2; ++j) {
00736                 w[j] -= sigma;
00737                 werr[j] += (d__1 = w[j], abs(d__1)) * eps;
00738 /* L134: */
00739             }
00740 /*           call DLARRB to reduce eigenvalue error of the approximations */
00741 /*           from DLARRD */
00742             i__2 = iend - 1;
00743             for (i__ = ibegin; i__ <= i__2; ++i__) {
00744 /* Computing 2nd power */
00745                 d__1 = e[i__];
00746                 work[i__] = d__[i__] * (d__1 * d__1);
00747 /* L135: */
00748             }
00749 /*           use bisection to find EV from INDL to INDU */
00750             i__2 = indl - 1;
00751             dlarrb_(&in, &d__[ibegin], &work[ibegin], &indl, &indu, rtol1, 
00752                     rtol2, &i__2, &w[wbegin], &wgap[wbegin], &werr[wbegin], &
00753                     work[(*n << 1) + 1], &iwork[1], pivmin, &spdiam, &in, &
00754                     iinfo);
00755             if (iinfo != 0) {
00756                 *info = -4;
00757                 return 0;
00758             }
00759 /*           DLARRB computes all gaps correctly except for the last one */
00760 /*           Record distance to VU/GU */
00761 /* Computing MAX */
00762             d__1 = 0., d__2 = *vu - sigma - (w[wend] + werr[wend]);
00763             wgap[wend] = max(d__1,d__2);
00764             i__2 = indu;
00765             for (i__ = indl; i__ <= i__2; ++i__) {
00766                 ++(*m);
00767                 iblock[*m] = jblk;
00768                 indexw[*m] = i__;
00769 /* L138: */
00770             }
00771         } else {
00772 /*           Call dqds to get all eigs (and then possibly delete unwanted */
00773 /*           eigenvalues). */
00774 /*           Note that dqds finds the eigenvalues of the L D L^T representation */
00775 /*           of T to high relative accuracy. High relative accuracy */
00776 /*           might be lost when the shift of the RRR is subtracted to obtain */
00777 /*           the eigenvalues of T. However, T is not guaranteed to define its */
00778 /*           eigenvalues to high relative accuracy anyway. */
00779 /*           Set RTOL to the order of the tolerance used in DLASQ2 */
00780 /*           This is an ESTIMATED error, the worst case bound is 4*N*EPS */
00781 /*           which is usually too large and requires unnecessary work to be */
00782 /*           done by bisection when computing the eigenvectors */
00783             rtol = log((doublereal) in) * 4. * eps;
00784             j = ibegin;
00785             i__2 = in - 1;
00786             for (i__ = 1; i__ <= i__2; ++i__) {
00787                 work[(i__ << 1) - 1] = (d__1 = d__[j], abs(d__1));
00788                 work[i__ * 2] = e[j] * e[j] * work[(i__ << 1) - 1];
00789                 ++j;
00790 /* L140: */
00791             }
00792             work[(in << 1) - 1] = (d__1 = d__[iend], abs(d__1));
00793             work[in * 2] = 0.;
00794             dlasq2_(&in, &work[1], &iinfo);
00795             if (iinfo != 0) {
00796 /*              If IINFO = -5 then an index is part of a tight cluster */
00797 /*              and should be changed. The index is in IWORK(1) and the */
00798 /*              gap is in WORK(N+1) */
00799                 *info = -5;
00800                 return 0;
00801             } else {
00802 /*              Test that all eigenvalues are positive as expected */
00803                 i__2 = in;
00804                 for (i__ = 1; i__ <= i__2; ++i__) {
00805                     if (work[i__] < 0.) {
00806                         *info = -6;
00807                         return 0;
00808                     }
00809 /* L149: */
00810                 }
00811             }
00812             if (sgndef > 0.) {
00813                 i__2 = indu;
00814                 for (i__ = indl; i__ <= i__2; ++i__) {
00815                     ++(*m);
00816                     w[*m] = work[in - i__ + 1];
00817                     iblock[*m] = jblk;
00818                     indexw[*m] = i__;
00819 /* L150: */
00820                 }
00821             } else {
00822                 i__2 = indu;
00823                 for (i__ = indl; i__ <= i__2; ++i__) {
00824                     ++(*m);
00825                     w[*m] = -work[i__];
00826                     iblock[*m] = jblk;
00827                     indexw[*m] = i__;
00828 /* L160: */
00829                 }
00830             }
00831             i__2 = *m;
00832             for (i__ = *m - mb + 1; i__ <= i__2; ++i__) {
00833 /*              the value of RTOL below should be the tolerance in DLASQ2 */
00834                 werr[i__] = rtol * (d__1 = w[i__], abs(d__1));
00835 /* L165: */
00836             }
00837             i__2 = *m - 1;
00838             for (i__ = *m - mb + 1; i__ <= i__2; ++i__) {
00839 /*              compute the right gap between the intervals */
00840 /* Computing MAX */
00841                 d__1 = 0., d__2 = w[i__ + 1] - werr[i__ + 1] - (w[i__] + werr[
00842                         i__]);
00843                 wgap[i__] = max(d__1,d__2);
00844 /* L166: */
00845             }
00846 /* Computing MAX */
00847             d__1 = 0., d__2 = *vu - sigma - (w[*m] + werr[*m]);
00848             wgap[*m] = max(d__1,d__2);
00849         }
00850 /*        proceed with next block */
00851         ibegin = iend + 1;
00852         wbegin = wend + 1;
00853 L170:
00854         ;
00855     }
00856 
00857     return 0;
00858 
00859 /*     end of DLARRE */
00860 
00861 } /* dlarre_ */


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