00001 /* dlarrv.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_b5 = 0.; 00019 static integer c__1 = 1; 00020 static integer c__2 = 2; 00021 00022 /* Subroutine */ int dlarrv_(integer *n, doublereal *vl, doublereal *vu, 00023 doublereal *d__, doublereal *l, doublereal *pivmin, integer *isplit, 00024 integer *m, integer *dol, integer *dou, doublereal *minrgp, 00025 doublereal *rtol1, doublereal *rtol2, doublereal *w, doublereal *werr, 00026 doublereal *wgap, integer *iblock, integer *indexw, doublereal *gers, 00027 doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 00028 integer *iwork, integer *info) 00029 { 00030 /* System generated locals */ 00031 integer z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5; 00032 doublereal d__1, d__2; 00033 logical L__1; 00034 00035 /* Builtin functions */ 00036 double log(doublereal); 00037 00038 /* Local variables */ 00039 integer minwsize, i__, j, k, p, q, miniwsize, ii; 00040 doublereal gl; 00041 integer im, in; 00042 doublereal gu, gap, eps, tau, tol, tmp; 00043 integer zto; 00044 doublereal ztz; 00045 integer iend, jblk; 00046 doublereal lgap; 00047 integer done; 00048 doublereal rgap, left; 00049 integer wend, iter; 00050 doublereal bstw; 00051 integer itmp1; 00052 extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, 00053 integer *); 00054 integer indld; 00055 doublereal fudge; 00056 integer idone; 00057 doublereal sigma; 00058 integer iinfo, iindr; 00059 doublereal resid; 00060 logical eskip; 00061 doublereal right; 00062 extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 00063 doublereal *, integer *); 00064 integer nclus, zfrom; 00065 doublereal rqtol; 00066 integer iindc1, iindc2; 00067 extern /* Subroutine */ int dlar1v_(integer *, integer *, integer *, 00068 doublereal *, doublereal *, doublereal *, doublereal *, 00069 doublereal *, doublereal *, doublereal *, doublereal *, logical *, 00070 integer *, doublereal *, doublereal *, integer *, integer *, 00071 doublereal *, doublereal *, doublereal *, doublereal *); 00072 logical stp2ii; 00073 doublereal lambda; 00074 extern doublereal dlamch_(char *); 00075 integer ibegin, indeig; 00076 logical needbs; 00077 integer indlld; 00078 doublereal sgndef, mingma; 00079 extern /* Subroutine */ int dlarrb_(integer *, doublereal *, doublereal *, 00080 integer *, integer *, doublereal *, doublereal *, integer *, 00081 doublereal *, doublereal *, doublereal *, doublereal *, integer *, 00082 doublereal *, doublereal *, integer *, integer *); 00083 integer oldien, oldncl, wbegin; 00084 doublereal spdiam; 00085 integer negcnt; 00086 extern /* Subroutine */ int dlarrf_(integer *, doublereal *, doublereal *, 00087 doublereal *, integer *, integer *, doublereal *, doublereal *, 00088 doublereal *, doublereal *, doublereal *, doublereal *, 00089 doublereal *, doublereal *, doublereal *, doublereal *, 00090 doublereal *, integer *); 00091 integer oldcls; 00092 doublereal savgap; 00093 integer ndepth; 00094 doublereal ssigma; 00095 extern /* Subroutine */ int dlaset_(char *, integer *, integer *, 00096 doublereal *, doublereal *, doublereal *, integer *); 00097 logical usedbs; 00098 integer iindwk, offset; 00099 doublereal gaptol; 00100 integer newcls, oldfst, indwrk, windex, oldlst; 00101 logical usedrq; 00102 integer newfst, newftt, parity, windmn, windpl, isupmn, newlst, zusedl; 00103 doublereal bstres; 00104 integer newsiz, zusedu, zusedw; 00105 doublereal nrminv, rqcorr; 00106 logical tryrqc; 00107 integer isupmx; 00108 00109 00110 /* -- LAPACK auxiliary routine (version 3.2) -- */ 00111 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00112 /* November 2006 */ 00113 00114 /* .. Scalar Arguments .. */ 00115 /* .. */ 00116 /* .. Array Arguments .. */ 00117 /* .. */ 00118 00119 /* Purpose */ 00120 /* ======= */ 00121 00122 /* DLARRV computes the eigenvectors of the tridiagonal matrix */ 00123 /* T = L D L^T given L, D and APPROXIMATIONS to the eigenvalues of L D L^T. */ 00124 /* The input eigenvalues should have been computed by DLARRE. */ 00125 00126 /* Arguments */ 00127 /* ========= */ 00128 00129 /* N (input) INTEGER */ 00130 /* The order of the matrix. N >= 0. */ 00131 00132 /* VL (input) DOUBLE PRECISION */ 00133 /* VU (input) DOUBLE PRECISION */ 00134 /* Lower and upper bounds of the interval that contains the desired */ 00135 /* eigenvalues. VL < VU. Needed to compute gaps on the left or right */ 00136 /* end of the extremal eigenvalues in the desired RANGE. */ 00137 00138 /* D (input/output) DOUBLE PRECISION array, dimension (N) */ 00139 /* On entry, the N diagonal elements of the diagonal matrix D. */ 00140 /* On exit, D may be overwritten. */ 00141 00142 /* L (input/output) DOUBLE PRECISION array, dimension (N) */ 00143 /* On entry, the (N-1) subdiagonal elements of the unit */ 00144 /* bidiagonal matrix L are in elements 1 to N-1 of L */ 00145 /* (if the matrix is not splitted.) At the end of each block */ 00146 /* is stored the corresponding shift as given by DLARRE. */ 00147 /* On exit, L is overwritten. */ 00148 00149 /* PIVMIN (in) DOUBLE PRECISION */ 00150 /* The minimum pivot allowed in the Sturm sequence. */ 00151 00152 /* ISPLIT (input) INTEGER array, dimension (N) */ 00153 /* The splitting points, at which T breaks up into blocks. */ 00154 /* The first block consists of rows/columns 1 to */ 00155 /* ISPLIT( 1 ), the second of rows/columns ISPLIT( 1 )+1 */ 00156 /* through ISPLIT( 2 ), etc. */ 00157 00158 /* M (input) INTEGER */ 00159 /* The total number of input eigenvalues. 0 <= M <= N. */ 00160 00161 /* DOL (input) INTEGER */ 00162 /* DOU (input) INTEGER */ 00163 /* If the user wants to compute only selected eigenvectors from all */ 00164 /* the eigenvalues supplied, he can specify an index range DOL:DOU. */ 00165 /* Or else the setting DOL=1, DOU=M should be applied. */ 00166 /* Note that DOL and DOU refer to the order in which the eigenvalues */ 00167 /* are stored in W. */ 00168 /* If the user wants to compute only selected eigenpairs, then */ 00169 /* the columns DOL-1 to DOU+1 of the eigenvector space Z contain the */ 00170 /* computed eigenvectors. All other columns of Z are set to zero. */ 00171 00172 /* MINRGP (input) DOUBLE PRECISION */ 00173 00174 /* RTOL1 (input) DOUBLE PRECISION */ 00175 /* RTOL2 (input) DOUBLE PRECISION */ 00176 /* Parameters for bisection. */ 00177 /* An interval [LEFT,RIGHT] has converged if */ 00178 /* RIGHT-LEFT.LT.MAX( RTOL1*GAP, RTOL2*MAX(|LEFT|,|RIGHT|) ) */ 00179 00180 /* W (input/output) DOUBLE PRECISION array, dimension (N) */ 00181 /* The first M elements of W contain the APPROXIMATE eigenvalues for */ 00182 /* which eigenvectors are to be computed. The eigenvalues */ 00183 /* should be grouped by split-off block and ordered from */ 00184 /* smallest to largest within the block ( The output array */ 00185 /* W from DLARRE is expected here ). Furthermore, they are with */ 00186 /* respect to the shift of the corresponding root representation */ 00187 /* for their block. On exit, W holds the eigenvalues of the */ 00188 /* UNshifted matrix. */ 00189 00190 /* WERR (input/output) DOUBLE PRECISION array, dimension (N) */ 00191 /* The first M elements contain the semiwidth of the uncertainty */ 00192 /* interval of the corresponding eigenvalue in W */ 00193 00194 /* WGAP (input/output) DOUBLE PRECISION array, dimension (N) */ 00195 /* The separation from the right neighbor eigenvalue in W. */ 00196 00197 /* IBLOCK (input) INTEGER array, dimension (N) */ 00198 /* The indices of the blocks (submatrices) associated with the */ 00199 /* corresponding eigenvalues in W; IBLOCK(i)=1 if eigenvalue */ 00200 /* W(i) belongs to the first block from the top, =2 if W(i) */ 00201 /* belongs to the second block, etc. */ 00202 00203 /* INDEXW (input) INTEGER array, dimension (N) */ 00204 /* The indices of the eigenvalues within each block (submatrix); */ 00205 /* for example, INDEXW(i)= 10 and IBLOCK(i)=2 imply that the */ 00206 /* i-th eigenvalue W(i) is the 10-th eigenvalue in the second block. */ 00207 00208 /* GERS (input) DOUBLE PRECISION array, dimension (2*N) */ 00209 /* The N Gerschgorin intervals (the i-th Gerschgorin interval */ 00210 /* is (GERS(2*i-1), GERS(2*i)). The Gerschgorin intervals should */ 00211 /* be computed from the original UNshifted matrix. */ 00212 00213 /* Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) ) */ 00214 /* If INFO = 0, the first M columns of Z contain the */ 00215 /* orthonormal eigenvectors of the matrix T */ 00216 /* corresponding to the input eigenvalues, with the i-th */ 00217 /* column of Z holding the eigenvector associated with W(i). */ 00218 /* Note: the user must ensure that at least max(1,M) columns are */ 00219 /* supplied in the array Z. */ 00220 00221 /* LDZ (input) INTEGER */ 00222 /* The leading dimension of the array Z. LDZ >= 1, and if */ 00223 /* JOBZ = 'V', LDZ >= max(1,N). */ 00224 00225 /* ISUPPZ (output) INTEGER array, dimension ( 2*max(1,M) ) */ 00226 /* The support of the eigenvectors in Z, i.e., the indices */ 00227 /* indicating the nonzero elements in Z. The I-th eigenvector */ 00228 /* is nonzero only in elements ISUPPZ( 2*I-1 ) through */ 00229 /* ISUPPZ( 2*I ). */ 00230 00231 /* WORK (workspace) DOUBLE PRECISION array, dimension (12*N) */ 00232 00233 /* IWORK (workspace) INTEGER array, dimension (7*N) */ 00234 00235 /* INFO (output) INTEGER */ 00236 /* = 0: successful exit */ 00237 00238 /* > 0: A problem occured in DLARRV. */ 00239 /* < 0: One of the called subroutines signaled an internal problem. */ 00240 /* Needs inspection of the corresponding parameter IINFO */ 00241 /* for further information. */ 00242 00243 /* =-1: Problem in DLARRB when refining a child's eigenvalues. */ 00244 /* =-2: Problem in DLARRF when computing the RRR of a child. */ 00245 /* When a child is inside a tight cluster, it can be difficult */ 00246 /* to find an RRR. A partial remedy from the user's point of */ 00247 /* view is to make the parameter MINRGP smaller and recompile. */ 00248 /* However, as the orthogonality of the computed vectors is */ 00249 /* proportional to 1/MINRGP, the user should be aware that */ 00250 /* he might be trading in precision when he decreases MINRGP. */ 00251 /* =-3: Problem in DLARRB when refining a single eigenvalue */ 00252 /* after the Rayleigh correction was rejected. */ 00253 /* = 5: The Rayleigh Quotient Iteration failed to converge to */ 00254 /* full accuracy in MAXITR steps. */ 00255 00256 /* Further Details */ 00257 /* =============== */ 00258 00259 /* Based on contributions by */ 00260 /* Beresford Parlett, University of California, Berkeley, USA */ 00261 /* Jim Demmel, University of California, Berkeley, USA */ 00262 /* Inderjit Dhillon, University of Texas, Austin, USA */ 00263 /* Osni Marques, LBNL/NERSC, USA */ 00264 /* Christof Voemel, University of California, Berkeley, USA */ 00265 00266 /* ===================================================================== */ 00267 00268 /* .. Parameters .. */ 00269 /* .. */ 00270 /* .. Local Scalars .. */ 00271 /* .. */ 00272 /* .. External Functions .. */ 00273 /* .. */ 00274 /* .. External Subroutines .. */ 00275 /* .. */ 00276 /* .. Intrinsic Functions .. */ 00277 /* .. */ 00278 /* .. Executable Statements .. */ 00279 /* .. */ 00280 /* The first N entries of WORK are reserved for the eigenvalues */ 00281 /* Parameter adjustments */ 00282 --d__; 00283 --l; 00284 --isplit; 00285 --w; 00286 --werr; 00287 --wgap; 00288 --iblock; 00289 --indexw; 00290 --gers; 00291 z_dim1 = *ldz; 00292 z_offset = 1 + z_dim1; 00293 z__ -= z_offset; 00294 --isuppz; 00295 --work; 00296 --iwork; 00297 00298 /* Function Body */ 00299 indld = *n + 1; 00300 indlld = (*n << 1) + 1; 00301 indwrk = *n * 3 + 1; 00302 minwsize = *n * 12; 00303 i__1 = minwsize; 00304 for (i__ = 1; i__ <= i__1; ++i__) { 00305 work[i__] = 0.; 00306 /* L5: */ 00307 } 00308 /* IWORK(IINDR+1:IINDR+N) hold the twist indices R for the */ 00309 /* factorization used to compute the FP vector */ 00310 iindr = 0; 00311 /* IWORK(IINDC1+1:IINC2+N) are used to store the clusters of the current */ 00312 /* layer and the one above. */ 00313 iindc1 = *n; 00314 iindc2 = *n << 1; 00315 iindwk = *n * 3 + 1; 00316 miniwsize = *n * 7; 00317 i__1 = miniwsize; 00318 for (i__ = 1; i__ <= i__1; ++i__) { 00319 iwork[i__] = 0; 00320 /* L10: */ 00321 } 00322 zusedl = 1; 00323 if (*dol > 1) { 00324 /* Set lower bound for use of Z */ 00325 zusedl = *dol - 1; 00326 } 00327 zusedu = *m; 00328 if (*dou < *m) { 00329 /* Set lower bound for use of Z */ 00330 zusedu = *dou + 1; 00331 } 00332 /* The width of the part of Z that is used */ 00333 zusedw = zusedu - zusedl + 1; 00334 dlaset_("Full", n, &zusedw, &c_b5, &c_b5, &z__[zusedl * z_dim1 + 1], ldz); 00335 eps = dlamch_("Precision"); 00336 rqtol = eps * 2.; 00337 00338 /* Set expert flags for standard code. */ 00339 tryrqc = TRUE_; 00340 if (*dol == 1 && *dou == *m) { 00341 } else { 00342 /* Only selected eigenpairs are computed. Since the other evalues */ 00343 /* are not refined by RQ iteration, bisection has to compute to full */ 00344 /* accuracy. */ 00345 *rtol1 = eps * 4.; 00346 *rtol2 = eps * 4.; 00347 } 00348 /* The entries WBEGIN:WEND in W, WERR, WGAP correspond to the */ 00349 /* desired eigenvalues. The support of the nonzero eigenvector */ 00350 /* entries is contained in the interval IBEGIN:IEND. */ 00351 /* Remark that if k eigenpairs are desired, then the eigenvectors */ 00352 /* are stored in k contiguous columns of Z. */ 00353 /* DONE is the number of eigenvectors already computed */ 00354 done = 0; 00355 ibegin = 1; 00356 wbegin = 1; 00357 i__1 = iblock[*m]; 00358 for (jblk = 1; jblk <= i__1; ++jblk) { 00359 iend = isplit[jblk]; 00360 sigma = l[iend]; 00361 /* Find the eigenvectors of the submatrix indexed IBEGIN */ 00362 /* through IEND. */ 00363 wend = wbegin - 1; 00364 L15: 00365 if (wend < *m) { 00366 if (iblock[wend + 1] == jblk) { 00367 ++wend; 00368 goto L15; 00369 } 00370 } 00371 if (wend < wbegin) { 00372 ibegin = iend + 1; 00373 goto L170; 00374 } else if (wend < *dol || wbegin > *dou) { 00375 ibegin = iend + 1; 00376 wbegin = wend + 1; 00377 goto L170; 00378 } 00379 /* Find local spectral diameter of the block */ 00380 gl = gers[(ibegin << 1) - 1]; 00381 gu = gers[ibegin * 2]; 00382 i__2 = iend; 00383 for (i__ = ibegin + 1; i__ <= i__2; ++i__) { 00384 /* Computing MIN */ 00385 d__1 = gers[(i__ << 1) - 1]; 00386 gl = min(d__1,gl); 00387 /* Computing MAX */ 00388 d__1 = gers[i__ * 2]; 00389 gu = max(d__1,gu); 00390 /* L20: */ 00391 } 00392 spdiam = gu - gl; 00393 /* OLDIEN is the last index of the previous block */ 00394 oldien = ibegin - 1; 00395 /* Calculate the size of the current block */ 00396 in = iend - ibegin + 1; 00397 /* The number of eigenvalues in the current block */ 00398 im = wend - wbegin + 1; 00399 /* This is for a 1x1 block */ 00400 if (ibegin == iend) { 00401 ++done; 00402 z__[ibegin + wbegin * z_dim1] = 1.; 00403 isuppz[(wbegin << 1) - 1] = ibegin; 00404 isuppz[wbegin * 2] = ibegin; 00405 w[wbegin] += sigma; 00406 work[wbegin] = w[wbegin]; 00407 ibegin = iend + 1; 00408 ++wbegin; 00409 goto L170; 00410 } 00411 /* The desired (shifted) eigenvalues are stored in W(WBEGIN:WEND) */ 00412 /* Note that these can be approximations, in this case, the corresp. */ 00413 /* entries of WERR give the size of the uncertainty interval. */ 00414 /* The eigenvalue approximations will be refined when necessary as */ 00415 /* high relative accuracy is required for the computation of the */ 00416 /* corresponding eigenvectors. */ 00417 dcopy_(&im, &w[wbegin], &c__1, &work[wbegin], &c__1); 00418 /* We store in W the eigenvalue approximations w.r.t. the original */ 00419 /* matrix T. */ 00420 i__2 = im; 00421 for (i__ = 1; i__ <= i__2; ++i__) { 00422 w[wbegin + i__ - 1] += sigma; 00423 /* L30: */ 00424 } 00425 /* NDEPTH is the current depth of the representation tree */ 00426 ndepth = 0; 00427 /* PARITY is either 1 or 0 */ 00428 parity = 1; 00429 /* NCLUS is the number of clusters for the next level of the */ 00430 /* representation tree, we start with NCLUS = 1 for the root */ 00431 nclus = 1; 00432 iwork[iindc1 + 1] = 1; 00433 iwork[iindc1 + 2] = im; 00434 /* IDONE is the number of eigenvectors already computed in the current */ 00435 /* block */ 00436 idone = 0; 00437 /* loop while( IDONE.LT.IM ) */ 00438 /* generate the representation tree for the current block and */ 00439 /* compute the eigenvectors */ 00440 L40: 00441 if (idone < im) { 00442 /* This is a crude protection against infinitely deep trees */ 00443 if (ndepth > *m) { 00444 *info = -2; 00445 return 0; 00446 } 00447 /* breadth first processing of the current level of the representation */ 00448 /* tree: OLDNCL = number of clusters on current level */ 00449 oldncl = nclus; 00450 /* reset NCLUS to count the number of child clusters */ 00451 nclus = 0; 00452 00453 parity = 1 - parity; 00454 if (parity == 0) { 00455 oldcls = iindc1; 00456 newcls = iindc2; 00457 } else { 00458 oldcls = iindc2; 00459 newcls = iindc1; 00460 } 00461 /* Process the clusters on the current level */ 00462 i__2 = oldncl; 00463 for (i__ = 1; i__ <= i__2; ++i__) { 00464 j = oldcls + (i__ << 1); 00465 /* OLDFST, OLDLST = first, last index of current cluster. */ 00466 /* cluster indices start with 1 and are relative */ 00467 /* to WBEGIN when accessing W, WGAP, WERR, Z */ 00468 oldfst = iwork[j - 1]; 00469 oldlst = iwork[j]; 00470 if (ndepth > 0) { 00471 /* Retrieve relatively robust representation (RRR) of cluster */ 00472 /* that has been computed at the previous level */ 00473 /* The RRR is stored in Z and overwritten once the eigenvectors */ 00474 /* have been computed or when the cluster is refined */ 00475 if (*dol == 1 && *dou == *m) { 00476 /* Get representation from location of the leftmost evalue */ 00477 /* of the cluster */ 00478 j = wbegin + oldfst - 1; 00479 } else { 00480 if (wbegin + oldfst - 1 < *dol) { 00481 /* Get representation from the left end of Z array */ 00482 j = *dol - 1; 00483 } else if (wbegin + oldfst - 1 > *dou) { 00484 /* Get representation from the right end of Z array */ 00485 j = *dou; 00486 } else { 00487 j = wbegin + oldfst - 1; 00488 } 00489 } 00490 dcopy_(&in, &z__[ibegin + j * z_dim1], &c__1, &d__[ibegin] 00491 , &c__1); 00492 i__3 = in - 1; 00493 dcopy_(&i__3, &z__[ibegin + (j + 1) * z_dim1], &c__1, &l[ 00494 ibegin], &c__1); 00495 sigma = z__[iend + (j + 1) * z_dim1]; 00496 /* Set the corresponding entries in Z to zero */ 00497 dlaset_("Full", &in, &c__2, &c_b5, &c_b5, &z__[ibegin + j 00498 * z_dim1], ldz); 00499 } 00500 /* Compute DL and DLL of current RRR */ 00501 i__3 = iend - 1; 00502 for (j = ibegin; j <= i__3; ++j) { 00503 tmp = d__[j] * l[j]; 00504 work[indld - 1 + j] = tmp; 00505 work[indlld - 1 + j] = tmp * l[j]; 00506 /* L50: */ 00507 } 00508 if (ndepth > 0) { 00509 /* P and Q are index of the first and last eigenvalue to compute */ 00510 /* within the current block */ 00511 p = indexw[wbegin - 1 + oldfst]; 00512 q = indexw[wbegin - 1 + oldlst]; 00513 /* Offset for the arrays WORK, WGAP and WERR, i.e., th P-OFFSET */ 00514 /* thru' Q-OFFSET elements of these arrays are to be used. */ 00515 /* OFFSET = P-OLDFST */ 00516 offset = indexw[wbegin] - 1; 00517 /* perform limited bisection (if necessary) to get approximate */ 00518 /* eigenvalues to the precision needed. */ 00519 dlarrb_(&in, &d__[ibegin], &work[indlld + ibegin - 1], &p, 00520 &q, rtol1, rtol2, &offset, &work[wbegin], &wgap[ 00521 wbegin], &werr[wbegin], &work[indwrk], &iwork[ 00522 iindwk], pivmin, &spdiam, &in, &iinfo); 00523 if (iinfo != 0) { 00524 *info = -1; 00525 return 0; 00526 } 00527 /* We also recompute the extremal gaps. W holds all eigenvalues */ 00528 /* of the unshifted matrix and must be used for computation */ 00529 /* of WGAP, the entries of WORK might stem from RRRs with */ 00530 /* different shifts. The gaps from WBEGIN-1+OLDFST to */ 00531 /* WBEGIN-1+OLDLST are correctly computed in DLARRB. */ 00532 /* However, we only allow the gaps to become greater since */ 00533 /* this is what should happen when we decrease WERR */ 00534 if (oldfst > 1) { 00535 /* Computing MAX */ 00536 d__1 = wgap[wbegin + oldfst - 2], d__2 = w[wbegin + 00537 oldfst - 1] - werr[wbegin + oldfst - 1] - w[ 00538 wbegin + oldfst - 2] - werr[wbegin + oldfst - 00539 2]; 00540 wgap[wbegin + oldfst - 2] = max(d__1,d__2); 00541 } 00542 if (wbegin + oldlst - 1 < wend) { 00543 /* Computing MAX */ 00544 d__1 = wgap[wbegin + oldlst - 1], d__2 = w[wbegin + 00545 oldlst] - werr[wbegin + oldlst] - w[wbegin + 00546 oldlst - 1] - werr[wbegin + oldlst - 1]; 00547 wgap[wbegin + oldlst - 1] = max(d__1,d__2); 00548 } 00549 /* Each time the eigenvalues in WORK get refined, we store */ 00550 /* the newly found approximation with all shifts applied in W */ 00551 i__3 = oldlst; 00552 for (j = oldfst; j <= i__3; ++j) { 00553 w[wbegin + j - 1] = work[wbegin + j - 1] + sigma; 00554 /* L53: */ 00555 } 00556 } 00557 /* Process the current node. */ 00558 newfst = oldfst; 00559 i__3 = oldlst; 00560 for (j = oldfst; j <= i__3; ++j) { 00561 if (j == oldlst) { 00562 /* we are at the right end of the cluster, this is also the */ 00563 /* boundary of the child cluster */ 00564 newlst = j; 00565 } else if (wgap[wbegin + j - 1] >= *minrgp * (d__1 = work[ 00566 wbegin + j - 1], abs(d__1))) { 00567 /* the right relative gap is big enough, the child cluster */ 00568 /* (NEWFST,..,NEWLST) is well separated from the following */ 00569 newlst = j; 00570 } else { 00571 /* inside a child cluster, the relative gap is not */ 00572 /* big enough. */ 00573 goto L140; 00574 } 00575 /* Compute size of child cluster found */ 00576 newsiz = newlst - newfst + 1; 00577 /* NEWFTT is the place in Z where the new RRR or the computed */ 00578 /* eigenvector is to be stored */ 00579 if (*dol == 1 && *dou == *m) { 00580 /* Store representation at location of the leftmost evalue */ 00581 /* of the cluster */ 00582 newftt = wbegin + newfst - 1; 00583 } else { 00584 if (wbegin + newfst - 1 < *dol) { 00585 /* Store representation at the left end of Z array */ 00586 newftt = *dol - 1; 00587 } else if (wbegin + newfst - 1 > *dou) { 00588 /* Store representation at the right end of Z array */ 00589 newftt = *dou; 00590 } else { 00591 newftt = wbegin + newfst - 1; 00592 } 00593 } 00594 if (newsiz > 1) { 00595 00596 /* Current child is not a singleton but a cluster. */ 00597 /* Compute and store new representation of child. */ 00598 00599 00600 /* Compute left and right cluster gap. */ 00601 00602 /* LGAP and RGAP are not computed from WORK because */ 00603 /* the eigenvalue approximations may stem from RRRs */ 00604 /* different shifts. However, W hold all eigenvalues */ 00605 /* of the unshifted matrix. Still, the entries in WGAP */ 00606 /* have to be computed from WORK since the entries */ 00607 /* in W might be of the same order so that gaps are not */ 00608 /* exhibited correctly for very close eigenvalues. */ 00609 if (newfst == 1) { 00610 /* Computing MAX */ 00611 d__1 = 0., d__2 = w[wbegin] - werr[wbegin] - *vl; 00612 lgap = max(d__1,d__2); 00613 } else { 00614 lgap = wgap[wbegin + newfst - 2]; 00615 } 00616 rgap = wgap[wbegin + newlst - 1]; 00617 00618 /* Compute left- and rightmost eigenvalue of child */ 00619 /* to high precision in order to shift as close */ 00620 /* as possible and obtain as large relative gaps */ 00621 /* as possible */ 00622 00623 for (k = 1; k <= 2; ++k) { 00624 if (k == 1) { 00625 p = indexw[wbegin - 1 + newfst]; 00626 } else { 00627 p = indexw[wbegin - 1 + newlst]; 00628 } 00629 offset = indexw[wbegin] - 1; 00630 dlarrb_(&in, &d__[ibegin], &work[indlld + ibegin 00631 - 1], &p, &p, &rqtol, &rqtol, &offset, & 00632 work[wbegin], &wgap[wbegin], &werr[wbegin] 00633 , &work[indwrk], &iwork[iindwk], pivmin, & 00634 spdiam, &in, &iinfo); 00635 /* L55: */ 00636 } 00637 00638 if (wbegin + newlst - 1 < *dol || wbegin + newfst - 1 00639 > *dou) { 00640 /* if the cluster contains no desired eigenvalues */ 00641 /* skip the computation of that branch of the rep. tree */ 00642 00643 /* We could skip before the refinement of the extremal */ 00644 /* eigenvalues of the child, but then the representation */ 00645 /* tree could be different from the one when nothing is */ 00646 /* skipped. For this reason we skip at this place. */ 00647 idone = idone + newlst - newfst + 1; 00648 goto L139; 00649 } 00650 00651 /* Compute RRR of child cluster. */ 00652 /* Note that the new RRR is stored in Z */ 00653 00654 /* DLARRF needs LWORK = 2*N */ 00655 dlarrf_(&in, &d__[ibegin], &l[ibegin], &work[indld + 00656 ibegin - 1], &newfst, &newlst, &work[wbegin], 00657 &wgap[wbegin], &werr[wbegin], &spdiam, &lgap, 00658 &rgap, pivmin, &tau, &z__[ibegin + newftt * 00659 z_dim1], &z__[ibegin + (newftt + 1) * z_dim1], 00660 &work[indwrk], &iinfo); 00661 if (iinfo == 0) { 00662 /* a new RRR for the cluster was found by DLARRF */ 00663 /* update shift and store it */ 00664 ssigma = sigma + tau; 00665 z__[iend + (newftt + 1) * z_dim1] = ssigma; 00666 /* WORK() are the midpoints and WERR() the semi-width */ 00667 /* Note that the entries in W are unchanged. */ 00668 i__4 = newlst; 00669 for (k = newfst; k <= i__4; ++k) { 00670 fudge = eps * 3. * (d__1 = work[wbegin + k - 00671 1], abs(d__1)); 00672 work[wbegin + k - 1] -= tau; 00673 fudge += eps * 4. * (d__1 = work[wbegin + k - 00674 1], abs(d__1)); 00675 /* Fudge errors */ 00676 werr[wbegin + k - 1] += fudge; 00677 /* Gaps are not fudged. Provided that WERR is small */ 00678 /* when eigenvalues are close, a zero gap indicates */ 00679 /* that a new representation is needed for resolving */ 00680 /* the cluster. A fudge could lead to a wrong decision */ 00681 /* of judging eigenvalues 'separated' which in */ 00682 /* reality are not. This could have a negative impact */ 00683 /* on the orthogonality of the computed eigenvectors. */ 00684 /* L116: */ 00685 } 00686 ++nclus; 00687 k = newcls + (nclus << 1); 00688 iwork[k - 1] = newfst; 00689 iwork[k] = newlst; 00690 } else { 00691 *info = -2; 00692 return 0; 00693 } 00694 } else { 00695 00696 /* Compute eigenvector of singleton */ 00697 00698 iter = 0; 00699 00700 tol = log((doublereal) in) * 4. * eps; 00701 00702 k = newfst; 00703 windex = wbegin + k - 1; 00704 /* Computing MAX */ 00705 i__4 = windex - 1; 00706 windmn = max(i__4,1); 00707 /* Computing MIN */ 00708 i__4 = windex + 1; 00709 windpl = min(i__4,*m); 00710 lambda = work[windex]; 00711 ++done; 00712 /* Check if eigenvector computation is to be skipped */ 00713 if (windex < *dol || windex > *dou) { 00714 eskip = TRUE_; 00715 goto L125; 00716 } else { 00717 eskip = FALSE_; 00718 } 00719 left = work[windex] - werr[windex]; 00720 right = work[windex] + werr[windex]; 00721 indeig = indexw[windex]; 00722 /* Note that since we compute the eigenpairs for a child, */ 00723 /* all eigenvalue approximations are w.r.t the same shift. */ 00724 /* In this case, the entries in WORK should be used for */ 00725 /* computing the gaps since they exhibit even very small */ 00726 /* differences in the eigenvalues, as opposed to the */ 00727 /* entries in W which might "look" the same. */ 00728 if (k == 1) { 00729 /* In the case RANGE='I' and with not much initial */ 00730 /* accuracy in LAMBDA and VL, the formula */ 00731 /* LGAP = MAX( ZERO, (SIGMA - VL) + LAMBDA ) */ 00732 /* can lead to an overestimation of the left gap and */ 00733 /* thus to inadequately early RQI 'convergence'. */ 00734 /* Prevent this by forcing a small left gap. */ 00735 /* Computing MAX */ 00736 d__1 = abs(left), d__2 = abs(right); 00737 lgap = eps * max(d__1,d__2); 00738 } else { 00739 lgap = wgap[windmn]; 00740 } 00741 if (k == im) { 00742 /* In the case RANGE='I' and with not much initial */ 00743 /* accuracy in LAMBDA and VU, the formula */ 00744 /* can lead to an overestimation of the right gap and */ 00745 /* thus to inadequately early RQI 'convergence'. */ 00746 /* Prevent this by forcing a small right gap. */ 00747 /* Computing MAX */ 00748 d__1 = abs(left), d__2 = abs(right); 00749 rgap = eps * max(d__1,d__2); 00750 } else { 00751 rgap = wgap[windex]; 00752 } 00753 gap = min(lgap,rgap); 00754 if (k == 1 || k == im) { 00755 /* The eigenvector support can become wrong */ 00756 /* because significant entries could be cut off due to a */ 00757 /* large GAPTOL parameter in LAR1V. Prevent this. */ 00758 gaptol = 0.; 00759 } else { 00760 gaptol = gap * eps; 00761 } 00762 isupmn = in; 00763 isupmx = 1; 00764 /* Update WGAP so that it holds the minimum gap */ 00765 /* to the left or the right. This is crucial in the */ 00766 /* case where bisection is used to ensure that the */ 00767 /* eigenvalue is refined up to the required precision. */ 00768 /* The correct value is restored afterwards. */ 00769 savgap = wgap[windex]; 00770 wgap[windex] = gap; 00771 /* We want to use the Rayleigh Quotient Correction */ 00772 /* as often as possible since it converges quadratically */ 00773 /* when we are close enough to the desired eigenvalue. */ 00774 /* However, the Rayleigh Quotient can have the wrong sign */ 00775 /* and lead us away from the desired eigenvalue. In this */ 00776 /* case, the best we can do is to use bisection. */ 00777 usedbs = FALSE_; 00778 usedrq = FALSE_; 00779 /* Bisection is initially turned off unless it is forced */ 00780 needbs = ! tryrqc; 00781 L120: 00782 /* Check if bisection should be used to refine eigenvalue */ 00783 if (needbs) { 00784 /* Take the bisection as new iterate */ 00785 usedbs = TRUE_; 00786 itmp1 = iwork[iindr + windex]; 00787 offset = indexw[wbegin] - 1; 00788 d__1 = eps * 2.; 00789 dlarrb_(&in, &d__[ibegin], &work[indlld + ibegin 00790 - 1], &indeig, &indeig, &c_b5, &d__1, & 00791 offset, &work[wbegin], &wgap[wbegin], & 00792 werr[wbegin], &work[indwrk], &iwork[ 00793 iindwk], pivmin, &spdiam, &itmp1, &iinfo); 00794 if (iinfo != 0) { 00795 *info = -3; 00796 return 0; 00797 } 00798 lambda = work[windex]; 00799 /* Reset twist index from inaccurate LAMBDA to */ 00800 /* force computation of true MINGMA */ 00801 iwork[iindr + windex] = 0; 00802 } 00803 /* Given LAMBDA, compute the eigenvector. */ 00804 L__1 = ! usedbs; 00805 dlar1v_(&in, &c__1, &in, &lambda, &d__[ibegin], &l[ 00806 ibegin], &work[indld + ibegin - 1], &work[ 00807 indlld + ibegin - 1], pivmin, &gaptol, &z__[ 00808 ibegin + windex * z_dim1], &L__1, &negcnt, & 00809 ztz, &mingma, &iwork[iindr + windex], &isuppz[ 00810 (windex << 1) - 1], &nrminv, &resid, &rqcorr, 00811 &work[indwrk]); 00812 if (iter == 0) { 00813 bstres = resid; 00814 bstw = lambda; 00815 } else if (resid < bstres) { 00816 bstres = resid; 00817 bstw = lambda; 00818 } 00819 /* Computing MIN */ 00820 i__4 = isupmn, i__5 = isuppz[(windex << 1) - 1]; 00821 isupmn = min(i__4,i__5); 00822 /* Computing MAX */ 00823 i__4 = isupmx, i__5 = isuppz[windex * 2]; 00824 isupmx = max(i__4,i__5); 00825 ++iter; 00826 /* sin alpha <= |resid|/gap */ 00827 /* Note that both the residual and the gap are */ 00828 /* proportional to the matrix, so ||T|| doesn't play */ 00829 /* a role in the quotient */ 00830 00831 /* Convergence test for Rayleigh-Quotient iteration */ 00832 /* (omitted when Bisection has been used) */ 00833 00834 if (resid > tol * gap && abs(rqcorr) > rqtol * abs( 00835 lambda) && ! usedbs) { 00836 /* We need to check that the RQCORR update doesn't */ 00837 /* move the eigenvalue away from the desired one and */ 00838 /* towards a neighbor. -> protection with bisection */ 00839 if (indeig <= negcnt) { 00840 /* The wanted eigenvalue lies to the left */ 00841 sgndef = -1.; 00842 } else { 00843 /* The wanted eigenvalue lies to the right */ 00844 sgndef = 1.; 00845 } 00846 /* We only use the RQCORR if it improves the */ 00847 /* the iterate reasonably. */ 00848 if (rqcorr * sgndef >= 0. && lambda + rqcorr <= 00849 right && lambda + rqcorr >= left) { 00850 usedrq = TRUE_; 00851 /* Store new midpoint of bisection interval in WORK */ 00852 if (sgndef == 1.) { 00853 /* The current LAMBDA is on the left of the true */ 00854 /* eigenvalue */ 00855 left = lambda; 00856 /* We prefer to assume that the error estimate */ 00857 /* is correct. We could make the interval not */ 00858 /* as a bracket but to be modified if the RQCORR */ 00859 /* chooses to. In this case, the RIGHT side should */ 00860 /* be modified as follows: */ 00861 /* RIGHT = MAX(RIGHT, LAMBDA + RQCORR) */ 00862 } else { 00863 /* The current LAMBDA is on the right of the true */ 00864 /* eigenvalue */ 00865 right = lambda; 00866 /* See comment about assuming the error estimate is */ 00867 /* correct above. */ 00868 /* LEFT = MIN(LEFT, LAMBDA + RQCORR) */ 00869 } 00870 work[windex] = (right + left) * .5; 00871 /* Take RQCORR since it has the correct sign and */ 00872 /* improves the iterate reasonably */ 00873 lambda += rqcorr; 00874 /* Update width of error interval */ 00875 werr[windex] = (right - left) * .5; 00876 } else { 00877 needbs = TRUE_; 00878 } 00879 if (right - left < rqtol * abs(lambda)) { 00880 /* The eigenvalue is computed to bisection accuracy */ 00881 /* compute eigenvector and stop */ 00882 usedbs = TRUE_; 00883 goto L120; 00884 } else if (iter < 10) { 00885 goto L120; 00886 } else if (iter == 10) { 00887 needbs = TRUE_; 00888 goto L120; 00889 } else { 00890 *info = 5; 00891 return 0; 00892 } 00893 } else { 00894 stp2ii = FALSE_; 00895 if (usedrq && usedbs && bstres <= resid) { 00896 lambda = bstw; 00897 stp2ii = TRUE_; 00898 } 00899 if (stp2ii) { 00900 /* improve error angle by second step */ 00901 L__1 = ! usedbs; 00902 dlar1v_(&in, &c__1, &in, &lambda, &d__[ibegin] 00903 , &l[ibegin], &work[indld + ibegin - 00904 1], &work[indlld + ibegin - 1], 00905 pivmin, &gaptol, &z__[ibegin + windex 00906 * z_dim1], &L__1, &negcnt, &ztz, & 00907 mingma, &iwork[iindr + windex], & 00908 isuppz[(windex << 1) - 1], &nrminv, & 00909 resid, &rqcorr, &work[indwrk]); 00910 } 00911 work[windex] = lambda; 00912 } 00913 00914 /* Compute FP-vector support w.r.t. whole matrix */ 00915 00916 isuppz[(windex << 1) - 1] += oldien; 00917 isuppz[windex * 2] += oldien; 00918 zfrom = isuppz[(windex << 1) - 1]; 00919 zto = isuppz[windex * 2]; 00920 isupmn += oldien; 00921 isupmx += oldien; 00922 /* Ensure vector is ok if support in the RQI has changed */ 00923 if (isupmn < zfrom) { 00924 i__4 = zfrom - 1; 00925 for (ii = isupmn; ii <= i__4; ++ii) { 00926 z__[ii + windex * z_dim1] = 0.; 00927 /* L122: */ 00928 } 00929 } 00930 if (isupmx > zto) { 00931 i__4 = isupmx; 00932 for (ii = zto + 1; ii <= i__4; ++ii) { 00933 z__[ii + windex * z_dim1] = 0.; 00934 /* L123: */ 00935 } 00936 } 00937 i__4 = zto - zfrom + 1; 00938 dscal_(&i__4, &nrminv, &z__[zfrom + windex * z_dim1], 00939 &c__1); 00940 L125: 00941 /* Update W */ 00942 w[windex] = lambda + sigma; 00943 /* Recompute the gaps on the left and right */ 00944 /* But only allow them to become larger and not */ 00945 /* smaller (which can only happen through "bad" */ 00946 /* cancellation and doesn't reflect the theory */ 00947 /* where the initial gaps are underestimated due */ 00948 /* to WERR being too crude.) */ 00949 if (! eskip) { 00950 if (k > 1) { 00951 /* Computing MAX */ 00952 d__1 = wgap[windmn], d__2 = w[windex] - werr[ 00953 windex] - w[windmn] - werr[windmn]; 00954 wgap[windmn] = max(d__1,d__2); 00955 } 00956 if (windex < wend) { 00957 /* Computing MAX */ 00958 d__1 = savgap, d__2 = w[windpl] - werr[windpl] 00959 - w[windex] - werr[windex]; 00960 wgap[windex] = max(d__1,d__2); 00961 } 00962 } 00963 ++idone; 00964 } 00965 /* here ends the code for the current child */ 00966 00967 L139: 00968 /* Proceed to any remaining child nodes */ 00969 newfst = j + 1; 00970 L140: 00971 ; 00972 } 00973 /* L150: */ 00974 } 00975 ++ndepth; 00976 goto L40; 00977 } 00978 ibegin = iend + 1; 00979 wbegin = wend + 1; 00980 L170: 00981 ; 00982 } 00983 00984 return 0; 00985 00986 /* End of DLARRV */ 00987 00988 } /* dlarrv_ */