00001 /* cstemr.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 real c_b18 = .003f; 00020 00021 /* Subroutine */ int cstemr_(char *jobz, char *range, integer *n, real *d__, 00022 real *e, real *vl, real *vu, integer *il, integer *iu, integer *m, 00023 real *w, complex *z__, integer *ldz, integer *nzc, integer *isuppz, 00024 logical *tryrac, real *work, integer *lwork, integer *iwork, integer * 00025 liwork, integer *info) 00026 { 00027 /* System generated locals */ 00028 integer z_dim1, z_offset, i__1, i__2; 00029 real r__1, r__2; 00030 00031 /* Builtin functions */ 00032 double sqrt(doublereal); 00033 00034 /* Local variables */ 00035 integer i__, j; 00036 real r1, r2; 00037 integer jj; 00038 real cs; 00039 integer in; 00040 real sn, wl, wu; 00041 integer iil, iiu; 00042 real eps, tmp; 00043 integer indd, iend, jblk, wend; 00044 real rmin, rmax; 00045 integer itmp; 00046 real tnrm; 00047 integer inde2; 00048 extern /* Subroutine */ int slae2_(real *, real *, real *, real *, real *) 00049 ; 00050 integer itmp2; 00051 real rtol1, rtol2, scale; 00052 integer indgp; 00053 extern logical lsame_(char *, char *); 00054 integer iinfo; 00055 extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *); 00056 integer iindw, ilast; 00057 extern /* Subroutine */ int cswap_(integer *, complex *, integer *, 00058 complex *, integer *); 00059 integer lwmin; 00060 extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, 00061 integer *); 00062 logical wantz; 00063 extern /* Subroutine */ int slaev2_(real *, real *, real *, real *, real * 00064 , real *, real *); 00065 logical alleig; 00066 integer ibegin; 00067 logical indeig; 00068 integer iindbl; 00069 logical valeig; 00070 extern doublereal slamch_(char *); 00071 integer wbegin; 00072 real safmin; 00073 extern /* Subroutine */ int xerbla_(char *, integer *); 00074 real bignum; 00075 integer inderr, iindwk, indgrs, offset; 00076 extern /* Subroutine */ int slarrc_(char *, integer *, real *, real *, 00077 real *, real *, real *, integer *, integer *, integer *, integer * 00078 ), clarrv_(integer *, real *, real *, real *, real *, 00079 real *, integer *, integer *, integer *, integer *, real *, real * 00080 , real *, real *, real *, real *, integer *, integer *, real *, 00081 complex *, integer *, integer *, real *, integer *, integer *), 00082 slarre_(char *, integer *, real *, real *, integer *, integer *, 00083 real *, real *, real *, real *, real *, real *, integer *, 00084 integer *, integer *, real *, real *, real *, integer *, integer * 00085 , real *, real *, real *, integer *, integer *); 00086 integer iinspl, indwrk, ifirst, liwmin, nzcmin; 00087 real pivmin, thresh; 00088 extern doublereal slanst_(char *, integer *, real *, real *); 00089 extern /* Subroutine */ int slarrj_(integer *, real *, real *, integer *, 00090 integer *, real *, integer *, real *, real *, real *, integer *, 00091 real *, real *, integer *); 00092 integer nsplit; 00093 extern /* Subroutine */ int slarrr_(integer *, real *, real *, integer *); 00094 real smlnum; 00095 extern /* Subroutine */ int slasrt_(char *, integer *, real *, integer *); 00096 logical lquery, zquery; 00097 00098 00099 /* -- LAPACK computational routine (version 3.2) -- */ 00100 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00101 /* November 2006 */ 00102 00103 /* .. Scalar Arguments .. */ 00104 /* .. */ 00105 /* .. Array Arguments .. */ 00106 /* .. */ 00107 00108 /* Purpose */ 00109 /* ======= */ 00110 00111 /* CSTEMR computes selected eigenvalues and, optionally, eigenvectors */ 00112 /* of a real symmetric tridiagonal matrix T. Any such unreduced matrix has */ 00113 /* a well defined set of pairwise different real eigenvalues, the corresponding */ 00114 /* real eigenvectors are pairwise orthogonal. */ 00115 00116 /* The spectrum may be computed either completely or partially by specifying */ 00117 /* either an interval (VL,VU] or a range of indices IL:IU for the desired */ 00118 /* eigenvalues. */ 00119 00120 /* Depending on the number of desired eigenvalues, these are computed either */ 00121 /* by bisection or the dqds algorithm. Numerically orthogonal eigenvectors are */ 00122 /* computed by the use of various suitable L D L^T factorizations near clusters */ 00123 /* of close eigenvalues (referred to as RRRs, Relatively Robust */ 00124 /* Representations). An informal sketch of the algorithm follows. */ 00125 00126 /* For each unreduced block (submatrix) of T, */ 00127 /* (a) Compute T - sigma I = L D L^T, so that L and D */ 00128 /* define all the wanted eigenvalues to high relative accuracy. */ 00129 /* This means that small relative changes in the entries of D and L */ 00130 /* cause only small relative changes in the eigenvalues and */ 00131 /* eigenvectors. The standard (unfactored) representation of the */ 00132 /* tridiagonal matrix T does not have this property in general. */ 00133 /* (b) Compute the eigenvalues to suitable accuracy. */ 00134 /* If the eigenvectors are desired, the algorithm attains full */ 00135 /* accuracy of the computed eigenvalues only right before */ 00136 /* the corresponding vectors have to be computed, see steps c) and d). */ 00137 /* (c) For each cluster of close eigenvalues, select a new */ 00138 /* shift close to the cluster, find a new factorization, and refine */ 00139 /* the shifted eigenvalues to suitable accuracy. */ 00140 /* (d) For each eigenvalue with a large enough relative separation compute */ 00141 /* the corresponding eigenvector by forming a rank revealing twisted */ 00142 /* factorization. Go back to (c) for any clusters that remain. */ 00143 00144 /* For more details, see: */ 00145 /* - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations */ 00146 /* to compute orthogonal eigenvectors of symmetric tridiagonal matrices," */ 00147 /* Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. */ 00148 /* - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and */ 00149 /* Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, */ 00150 /* 2004. Also LAPACK Working Note 154. */ 00151 /* - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric */ 00152 /* tridiagonal eigenvalue/eigenvector problem", */ 00153 /* Computer Science Division Technical Report No. UCB/CSD-97-971, */ 00154 /* UC Berkeley, May 1997. */ 00155 00156 /* Notes: */ 00157 /* 1.CSTEMR works only on machines which follow IEEE-754 */ 00158 /* floating-point standard in their handling of infinities and NaNs. */ 00159 /* This permits the use of efficient inner loops avoiding a check for */ 00160 /* zero divisors. */ 00161 00162 /* 2. LAPACK routines can be used to reduce a complex Hermitean matrix to */ 00163 /* real symmetric tridiagonal form. */ 00164 00165 /* (Any complex Hermitean tridiagonal matrix has real values on its diagonal */ 00166 /* and potentially complex numbers on its off-diagonals. By applying a */ 00167 /* similarity transform with an appropriate diagonal matrix */ 00168 /* diag(1,e^{i \phy_1}, ... , e^{i \phy_{n-1}}), the complex Hermitean */ 00169 /* matrix can be transformed into a real symmetric matrix and complex */ 00170 /* arithmetic can be entirely avoided.) */ 00171 00172 /* While the eigenvectors of the real symmetric tridiagonal matrix are real, */ 00173 /* the eigenvectors of original complex Hermitean matrix have complex entries */ 00174 /* in general. */ 00175 /* Since LAPACK drivers overwrite the matrix data with the eigenvectors, */ 00176 /* CSTEMR accepts complex workspace to facilitate interoperability */ 00177 /* with CUNMTR or CUPMTR. */ 00178 00179 /* Arguments */ 00180 /* ========= */ 00181 00182 /* JOBZ (input) CHARACTER*1 */ 00183 /* = 'N': Compute eigenvalues only; */ 00184 /* = 'V': Compute eigenvalues and eigenvectors. */ 00185 00186 /* RANGE (input) CHARACTER*1 */ 00187 /* = 'A': all eigenvalues will be found. */ 00188 /* = 'V': all eigenvalues in the half-open interval (VL,VU] */ 00189 /* will be found. */ 00190 /* = 'I': the IL-th through IU-th eigenvalues will be found. */ 00191 00192 /* N (input) INTEGER */ 00193 /* The order of the matrix. N >= 0. */ 00194 00195 /* D (input/output) REAL array, dimension (N) */ 00196 /* On entry, the N diagonal elements of the tridiagonal matrix */ 00197 /* T. On exit, D is overwritten. */ 00198 00199 /* E (input/output) REAL array, dimension (N) */ 00200 /* On entry, the (N-1) subdiagonal elements of the tridiagonal */ 00201 /* matrix T in elements 1 to N-1 of E. E(N) need not be set on */ 00202 /* input, but is used internally as workspace. */ 00203 /* On exit, E is overwritten. */ 00204 00205 /* VL (input) REAL */ 00206 /* VU (input) REAL */ 00207 /* If RANGE='V', the lower and upper bounds of the interval to */ 00208 /* be searched for eigenvalues. VL < VU. */ 00209 /* Not referenced if RANGE = 'A' or 'I'. */ 00210 00211 /* IL (input) INTEGER */ 00212 /* IU (input) INTEGER */ 00213 /* If RANGE='I', the indices (in ascending order) of the */ 00214 /* smallest and largest eigenvalues to be returned. */ 00215 /* 1 <= IL <= IU <= N, if N > 0. */ 00216 /* Not referenced if RANGE = 'A' or 'V'. */ 00217 00218 /* M (output) INTEGER */ 00219 /* The total number of eigenvalues found. 0 <= M <= N. */ 00220 /* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. */ 00221 00222 /* W (output) REAL array, dimension (N) */ 00223 /* The first M elements contain the selected eigenvalues in */ 00224 /* ascending order. */ 00225 00226 /* Z (output) COMPLEX array, dimension (LDZ, max(1,M) ) */ 00227 /* If JOBZ = 'V', and if INFO = 0, then the first M columns of Z */ 00228 /* contain the orthonormal eigenvectors of the matrix T */ 00229 /* corresponding to the selected eigenvalues, with the i-th */ 00230 /* column of Z holding the eigenvector associated with W(i). */ 00231 /* If JOBZ = 'N', then Z is not referenced. */ 00232 /* Note: the user must ensure that at least max(1,M) columns are */ 00233 /* supplied in the array Z; if RANGE = 'V', the exact value of M */ 00234 /* is not known in advance and can be computed with a workspace */ 00235 /* query by setting NZC = -1, see below. */ 00236 00237 /* LDZ (input) INTEGER */ 00238 /* The leading dimension of the array Z. LDZ >= 1, and if */ 00239 /* JOBZ = 'V', then LDZ >= max(1,N). */ 00240 00241 /* NZC (input) INTEGER */ 00242 /* The number of eigenvectors to be held in the array Z. */ 00243 /* If RANGE = 'A', then NZC >= max(1,N). */ 00244 /* If RANGE = 'V', then NZC >= the number of eigenvalues in (VL,VU]. */ 00245 /* If RANGE = 'I', then NZC >= IU-IL+1. */ 00246 /* If NZC = -1, then a workspace query is assumed; the */ 00247 /* routine calculates the number of columns of the array Z that */ 00248 /* are needed to hold the eigenvectors. */ 00249 /* This value is returned as the first entry of the Z array, and */ 00250 /* no error message related to NZC is issued by XERBLA. */ 00251 00252 /* ISUPPZ (output) INTEGER ARRAY, dimension ( 2*max(1,M) ) */ 00253 /* The support of the eigenvectors in Z, i.e., the indices */ 00254 /* indicating the nonzero elements in Z. The i-th computed eigenvector */ 00255 /* is nonzero only in elements ISUPPZ( 2*i-1 ) through */ 00256 /* ISUPPZ( 2*i ). This is relevant in the case when the matrix */ 00257 /* is split. ISUPPZ is only accessed when JOBZ is 'V' and N > 0. */ 00258 00259 /* TRYRAC (input/output) LOGICAL */ 00260 /* If TRYRAC.EQ..TRUE., indicates that the code should check whether */ 00261 /* the tridiagonal matrix defines its eigenvalues to high relative */ 00262 /* accuracy. If so, the code uses relative-accuracy preserving */ 00263 /* algorithms that might be (a bit) slower depending on the matrix. */ 00264 /* If the matrix does not define its eigenvalues to high relative */ 00265 /* accuracy, the code can uses possibly faster algorithms. */ 00266 /* If TRYRAC.EQ..FALSE., the code is not required to guarantee */ 00267 /* relatively accurate eigenvalues and can use the fastest possible */ 00268 /* techniques. */ 00269 /* On exit, a .TRUE. TRYRAC will be set to .FALSE. if the matrix */ 00270 /* does not define its eigenvalues to high relative accuracy. */ 00271 00272 /* WORK (workspace/output) REAL array, dimension (LWORK) */ 00273 /* On exit, if INFO = 0, WORK(1) returns the optimal */ 00274 /* (and minimal) LWORK. */ 00275 00276 /* LWORK (input) INTEGER */ 00277 /* The dimension of the array WORK. LWORK >= max(1,18*N) */ 00278 /* if JOBZ = 'V', and LWORK >= max(1,12*N) if JOBZ = 'N'. */ 00279 /* If LWORK = -1, then a workspace query is assumed; the routine */ 00280 /* only calculates the optimal size of the WORK array, returns */ 00281 /* this value as the first entry of the WORK array, and no error */ 00282 /* message related to LWORK is issued by XERBLA. */ 00283 00284 /* IWORK (workspace/output) INTEGER array, dimension (LIWORK) */ 00285 /* On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. */ 00286 00287 /* LIWORK (input) INTEGER */ 00288 /* The dimension of the array IWORK. LIWORK >= max(1,10*N) */ 00289 /* if the eigenvectors are desired, and LIWORK >= max(1,8*N) */ 00290 /* if only the eigenvalues are to be computed. */ 00291 /* If LIWORK = -1, then a workspace query is assumed; the */ 00292 /* routine only calculates the optimal size of the IWORK array, */ 00293 /* returns this value as the first entry of the IWORK array, and */ 00294 /* no error message related to LIWORK is issued by XERBLA. */ 00295 00296 /* INFO (output) INTEGER */ 00297 /* On exit, INFO */ 00298 /* = 0: successful exit */ 00299 /* < 0: if INFO = -i, the i-th argument had an illegal value */ 00300 /* > 0: if INFO = 1X, internal error in SLARRE, */ 00301 /* if INFO = 2X, internal error in CLARRV. */ 00302 /* Here, the digit X = ABS( IINFO ) < 10, where IINFO is */ 00303 /* the nonzero error code returned by SLARRE or */ 00304 /* CLARRV, respectively. */ 00305 00306 00307 /* Further Details */ 00308 /* =============== */ 00309 00310 /* Based on contributions by */ 00311 /* Beresford Parlett, University of California, Berkeley, USA */ 00312 /* Jim Demmel, University of California, Berkeley, USA */ 00313 /* Inderjit Dhillon, University of Texas, Austin, USA */ 00314 /* Osni Marques, LBNL/NERSC, USA */ 00315 /* Christof Voemel, University of California, Berkeley, USA */ 00316 00317 /* ===================================================================== */ 00318 00319 /* .. Parameters .. */ 00320 /* .. */ 00321 /* .. Local Scalars .. */ 00322 /* .. */ 00323 /* .. */ 00324 /* .. External Functions .. */ 00325 /* .. */ 00326 /* .. External Subroutines .. */ 00327 /* .. */ 00328 /* .. Intrinsic Functions .. */ 00329 /* .. */ 00330 /* .. Executable Statements .. */ 00331 00332 /* Test the input parameters. */ 00333 00334 /* Parameter adjustments */ 00335 --d__; 00336 --e; 00337 --w; 00338 z_dim1 = *ldz; 00339 z_offset = 1 + z_dim1; 00340 z__ -= z_offset; 00341 --isuppz; 00342 --work; 00343 --iwork; 00344 00345 /* Function Body */ 00346 wantz = lsame_(jobz, "V"); 00347 alleig = lsame_(range, "A"); 00348 valeig = lsame_(range, "V"); 00349 indeig = lsame_(range, "I"); 00350 00351 lquery = *lwork == -1 || *liwork == -1; 00352 zquery = *nzc == -1; 00353 /* SSTEMR needs WORK of size 6*N, IWORK of size 3*N. */ 00354 /* In addition, SLARRE needs WORK of size 6*N, IWORK of size 5*N. */ 00355 /* Furthermore, CLARRV needs WORK of size 12*N, IWORK of size 7*N. */ 00356 if (wantz) { 00357 lwmin = *n * 18; 00358 liwmin = *n * 10; 00359 } else { 00360 /* need less workspace if only the eigenvalues are wanted */ 00361 lwmin = *n * 12; 00362 liwmin = *n << 3; 00363 } 00364 wl = 0.f; 00365 wu = 0.f; 00366 iil = 0; 00367 iiu = 0; 00368 if (valeig) { 00369 /* We do not reference VL, VU in the cases RANGE = 'I','A' */ 00370 /* The interval (WL, WU] contains all the wanted eigenvalues. */ 00371 /* It is either given by the user or computed in SLARRE. */ 00372 wl = *vl; 00373 wu = *vu; 00374 } else if (indeig) { 00375 /* We do not reference IL, IU in the cases RANGE = 'V','A' */ 00376 iil = *il; 00377 iiu = *iu; 00378 } 00379 00380 *info = 0; 00381 if (! (wantz || lsame_(jobz, "N"))) { 00382 *info = -1; 00383 } else if (! (alleig || valeig || indeig)) { 00384 *info = -2; 00385 } else if (*n < 0) { 00386 *info = -3; 00387 } else if (valeig && *n > 0 && wu <= wl) { 00388 *info = -7; 00389 } else if (indeig && (iil < 1 || iil > *n)) { 00390 *info = -8; 00391 } else if (indeig && (iiu < iil || iiu > *n)) { 00392 *info = -9; 00393 } else if (*ldz < 1 || wantz && *ldz < *n) { 00394 *info = -13; 00395 } else if (*lwork < lwmin && ! lquery) { 00396 *info = -17; 00397 } else if (*liwork < liwmin && ! lquery) { 00398 *info = -19; 00399 } 00400 00401 /* Get machine constants. */ 00402 00403 safmin = slamch_("Safe minimum"); 00404 eps = slamch_("Precision"); 00405 smlnum = safmin / eps; 00406 bignum = 1.f / smlnum; 00407 rmin = sqrt(smlnum); 00408 /* Computing MIN */ 00409 r__1 = sqrt(bignum), r__2 = 1.f / sqrt(sqrt(safmin)); 00410 rmax = dmin(r__1,r__2); 00411 00412 if (*info == 0) { 00413 work[1] = (real) lwmin; 00414 iwork[1] = liwmin; 00415 00416 if (wantz && alleig) { 00417 nzcmin = *n; 00418 } else if (wantz && valeig) { 00419 slarrc_("T", n, vl, vu, &d__[1], &e[1], &safmin, &nzcmin, &itmp, & 00420 itmp2, info); 00421 } else if (wantz && indeig) { 00422 nzcmin = iiu - iil + 1; 00423 } else { 00424 /* WANTZ .EQ. FALSE. */ 00425 nzcmin = 0; 00426 } 00427 if (zquery && *info == 0) { 00428 i__1 = z_dim1 + 1; 00429 z__[i__1].r = (real) nzcmin, z__[i__1].i = 0.f; 00430 } else if (*nzc < nzcmin && ! zquery) { 00431 *info = -14; 00432 } 00433 } 00434 if (*info != 0) { 00435 00436 i__1 = -(*info); 00437 xerbla_("CSTEMR", &i__1); 00438 00439 return 0; 00440 } else if (lquery || zquery) { 00441 return 0; 00442 } 00443 00444 /* Handle N = 0, 1, and 2 cases immediately */ 00445 00446 *m = 0; 00447 if (*n == 0) { 00448 return 0; 00449 } 00450 00451 if (*n == 1) { 00452 if (alleig || indeig) { 00453 *m = 1; 00454 w[1] = d__[1]; 00455 } else { 00456 if (wl < d__[1] && wu >= d__[1]) { 00457 *m = 1; 00458 w[1] = d__[1]; 00459 } 00460 } 00461 if (wantz && ! zquery) { 00462 i__1 = z_dim1 + 1; 00463 z__[i__1].r = 1.f, z__[i__1].i = 0.f; 00464 isuppz[1] = 1; 00465 isuppz[2] = 1; 00466 } 00467 return 0; 00468 } 00469 00470 if (*n == 2) { 00471 if (! wantz) { 00472 slae2_(&d__[1], &e[1], &d__[2], &r1, &r2); 00473 } else if (wantz && ! zquery) { 00474 slaev2_(&d__[1], &e[1], &d__[2], &r1, &r2, &cs, &sn); 00475 } 00476 if (alleig || valeig && r2 > wl && r2 <= wu || indeig && iil == 1) { 00477 ++(*m); 00478 w[*m] = r2; 00479 if (wantz && ! zquery) { 00480 i__1 = *m * z_dim1 + 1; 00481 r__1 = -sn; 00482 z__[i__1].r = r__1, z__[i__1].i = 0.f; 00483 i__1 = *m * z_dim1 + 2; 00484 z__[i__1].r = cs, z__[i__1].i = 0.f; 00485 /* Note: At most one of SN and CS can be zero. */ 00486 if (sn != 0.f) { 00487 if (cs != 0.f) { 00488 isuppz[(*m << 1) - 1] = 1; 00489 isuppz[(*m << 1) - 1] = 2; 00490 } else { 00491 isuppz[(*m << 1) - 1] = 1; 00492 isuppz[(*m << 1) - 1] = 1; 00493 } 00494 } else { 00495 isuppz[(*m << 1) - 1] = 2; 00496 isuppz[*m * 2] = 2; 00497 } 00498 } 00499 } 00500 if (alleig || valeig && r1 > wl && r1 <= wu || indeig && iiu == 2) { 00501 ++(*m); 00502 w[*m] = r1; 00503 if (wantz && ! zquery) { 00504 i__1 = *m * z_dim1 + 1; 00505 z__[i__1].r = cs, z__[i__1].i = 0.f; 00506 i__1 = *m * z_dim1 + 2; 00507 z__[i__1].r = sn, z__[i__1].i = 0.f; 00508 /* Note: At most one of SN and CS can be zero. */ 00509 if (sn != 0.f) { 00510 if (cs != 0.f) { 00511 isuppz[(*m << 1) - 1] = 1; 00512 isuppz[(*m << 1) - 1] = 2; 00513 } else { 00514 isuppz[(*m << 1) - 1] = 1; 00515 isuppz[(*m << 1) - 1] = 1; 00516 } 00517 } else { 00518 isuppz[(*m << 1) - 1] = 2; 00519 isuppz[*m * 2] = 2; 00520 } 00521 } 00522 } 00523 return 0; 00524 } 00525 /* Continue with general N */ 00526 indgrs = 1; 00527 inderr = (*n << 1) + 1; 00528 indgp = *n * 3 + 1; 00529 indd = (*n << 2) + 1; 00530 inde2 = *n * 5 + 1; 00531 indwrk = *n * 6 + 1; 00532 00533 iinspl = 1; 00534 iindbl = *n + 1; 00535 iindw = (*n << 1) + 1; 00536 iindwk = *n * 3 + 1; 00537 00538 /* Scale matrix to allowable range, if necessary. */ 00539 /* The allowable range is related to the PIVMIN parameter; see the */ 00540 /* comments in SLARRD. The preference for scaling small values */ 00541 /* up is heuristic; we expect users' matrices not to be close to the */ 00542 /* RMAX threshold. */ 00543 00544 scale = 1.f; 00545 tnrm = slanst_("M", n, &d__[1], &e[1]); 00546 if (tnrm > 0.f && tnrm < rmin) { 00547 scale = rmin / tnrm; 00548 } else if (tnrm > rmax) { 00549 scale = rmax / tnrm; 00550 } 00551 if (scale != 1.f) { 00552 sscal_(n, &scale, &d__[1], &c__1); 00553 i__1 = *n - 1; 00554 sscal_(&i__1, &scale, &e[1], &c__1); 00555 tnrm *= scale; 00556 if (valeig) { 00557 /* If eigenvalues in interval have to be found, */ 00558 /* scale (WL, WU] accordingly */ 00559 wl *= scale; 00560 wu *= scale; 00561 } 00562 } 00563 00564 /* Compute the desired eigenvalues of the tridiagonal after splitting */ 00565 /* into smaller subblocks if the corresponding off-diagonal elements */ 00566 /* are small */ 00567 /* THRESH is the splitting parameter for SLARRE */ 00568 /* A negative THRESH forces the old splitting criterion based on the */ 00569 /* size of the off-diagonal. A positive THRESH switches to splitting */ 00570 /* which preserves relative accuracy. */ 00571 00572 if (*tryrac) { 00573 /* Test whether the matrix warrants the more expensive relative approach. */ 00574 slarrr_(n, &d__[1], &e[1], &iinfo); 00575 } else { 00576 /* The user does not care about relative accurately eigenvalues */ 00577 iinfo = -1; 00578 } 00579 /* Set the splitting criterion */ 00580 if (iinfo == 0) { 00581 thresh = eps; 00582 } else { 00583 thresh = -eps; 00584 /* relative accuracy is desired but T does not guarantee it */ 00585 *tryrac = FALSE_; 00586 } 00587 00588 if (*tryrac) { 00589 /* Copy original diagonal, needed to guarantee relative accuracy */ 00590 scopy_(n, &d__[1], &c__1, &work[indd], &c__1); 00591 } 00592 /* Store the squares of the offdiagonal values of T */ 00593 i__1 = *n - 1; 00594 for (j = 1; j <= i__1; ++j) { 00595 /* Computing 2nd power */ 00596 r__1 = e[j]; 00597 work[inde2 + j - 1] = r__1 * r__1; 00598 /* L5: */ 00599 } 00600 /* Set the tolerance parameters for bisection */ 00601 if (! wantz) { 00602 /* SLARRE computes the eigenvalues to full precision. */ 00603 rtol1 = eps * 4.f; 00604 rtol2 = eps * 4.f; 00605 } else { 00606 /* SLARRE computes the eigenvalues to less than full precision. */ 00607 /* CLARRV will refine the eigenvalue approximations, and we only */ 00608 /* need less accurate initial bisection in SLARRE. */ 00609 /* Note: these settings do only affect the subset case and SLARRE */ 00610 /* Computing MAX */ 00611 r__1 = sqrt(eps) * .05f, r__2 = eps * 4.f; 00612 rtol1 = dmax(r__1,r__2); 00613 /* Computing MAX */ 00614 r__1 = sqrt(eps) * .005f, r__2 = eps * 4.f; 00615 rtol2 = dmax(r__1,r__2); 00616 } 00617 slarre_(range, n, &wl, &wu, &iil, &iiu, &d__[1], &e[1], &work[inde2], & 00618 rtol1, &rtol2, &thresh, &nsplit, &iwork[iinspl], m, &w[1], &work[ 00619 inderr], &work[indgp], &iwork[iindbl], &iwork[iindw], &work[ 00620 indgrs], &pivmin, &work[indwrk], &iwork[iindwk], &iinfo); 00621 if (iinfo != 0) { 00622 *info = abs(iinfo) + 10; 00623 return 0; 00624 } 00625 /* Note that if RANGE .NE. 'V', SLARRE computes bounds on the desired */ 00626 /* part of the spectrum. All desired eigenvalues are contained in */ 00627 /* (WL,WU] */ 00628 if (wantz) { 00629 00630 /* Compute the desired eigenvectors corresponding to the computed */ 00631 /* eigenvalues */ 00632 00633 clarrv_(n, &wl, &wu, &d__[1], &e[1], &pivmin, &iwork[iinspl], m, & 00634 c__1, m, &c_b18, &rtol1, &rtol2, &w[1], &work[inderr], &work[ 00635 indgp], &iwork[iindbl], &iwork[iindw], &work[indgrs], &z__[ 00636 z_offset], ldz, &isuppz[1], &work[indwrk], &iwork[iindwk], & 00637 iinfo); 00638 if (iinfo != 0) { 00639 *info = abs(iinfo) + 20; 00640 return 0; 00641 } 00642 } else { 00643 /* SLARRE computes eigenvalues of the (shifted) root representation */ 00644 /* CLARRV returns the eigenvalues of the unshifted matrix. */ 00645 /* However, if the eigenvectors are not desired by the user, we need */ 00646 /* to apply the corresponding shifts from SLARRE to obtain the */ 00647 /* eigenvalues of the original matrix. */ 00648 i__1 = *m; 00649 for (j = 1; j <= i__1; ++j) { 00650 itmp = iwork[iindbl + j - 1]; 00651 w[j] += e[iwork[iinspl + itmp - 1]]; 00652 /* L20: */ 00653 } 00654 } 00655 00656 if (*tryrac) { 00657 /* Refine computed eigenvalues so that they are relatively accurate */ 00658 /* with respect to the original matrix T. */ 00659 ibegin = 1; 00660 wbegin = 1; 00661 i__1 = iwork[iindbl + *m - 1]; 00662 for (jblk = 1; jblk <= i__1; ++jblk) { 00663 iend = iwork[iinspl + jblk - 1]; 00664 in = iend - ibegin + 1; 00665 wend = wbegin - 1; 00666 /* check if any eigenvalues have to be refined in this block */ 00667 L36: 00668 if (wend < *m) { 00669 if (iwork[iindbl + wend] == jblk) { 00670 ++wend; 00671 goto L36; 00672 } 00673 } 00674 if (wend < wbegin) { 00675 ibegin = iend + 1; 00676 goto L39; 00677 } 00678 offset = iwork[iindw + wbegin - 1] - 1; 00679 ifirst = iwork[iindw + wbegin - 1]; 00680 ilast = iwork[iindw + wend - 1]; 00681 rtol2 = eps * 4.f; 00682 slarrj_(&in, &work[indd + ibegin - 1], &work[inde2 + ibegin - 1], 00683 &ifirst, &ilast, &rtol2, &offset, &w[wbegin], &work[ 00684 inderr + wbegin - 1], &work[indwrk], &iwork[iindwk], & 00685 pivmin, &tnrm, &iinfo); 00686 ibegin = iend + 1; 00687 wbegin = wend + 1; 00688 L39: 00689 ; 00690 } 00691 } 00692 00693 /* If matrix was scaled, then rescale eigenvalues appropriately. */ 00694 00695 if (scale != 1.f) { 00696 r__1 = 1.f / scale; 00697 sscal_(m, &r__1, &w[1], &c__1); 00698 } 00699 00700 /* If eigenvalues are not in increasing order, then sort them, */ 00701 /* possibly along with eigenvectors. */ 00702 00703 if (nsplit > 1) { 00704 if (! wantz) { 00705 slasrt_("I", m, &w[1], &iinfo); 00706 if (iinfo != 0) { 00707 *info = 3; 00708 return 0; 00709 } 00710 } else { 00711 i__1 = *m - 1; 00712 for (j = 1; j <= i__1; ++j) { 00713 i__ = 0; 00714 tmp = w[j]; 00715 i__2 = *m; 00716 for (jj = j + 1; jj <= i__2; ++jj) { 00717 if (w[jj] < tmp) { 00718 i__ = jj; 00719 tmp = w[jj]; 00720 } 00721 /* L50: */ 00722 } 00723 if (i__ != 0) { 00724 w[i__] = w[j]; 00725 w[j] = tmp; 00726 if (wantz) { 00727 cswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[j * 00728 z_dim1 + 1], &c__1); 00729 itmp = isuppz[(i__ << 1) - 1]; 00730 isuppz[(i__ << 1) - 1] = isuppz[(j << 1) - 1]; 00731 isuppz[(j << 1) - 1] = itmp; 00732 itmp = isuppz[i__ * 2]; 00733 isuppz[i__ * 2] = isuppz[j * 2]; 00734 isuppz[j * 2] = itmp; 00735 } 00736 } 00737 /* L60: */ 00738 } 00739 } 00740 } 00741 00742 00743 work[1] = (real) lwmin; 00744 iwork[1] = liwmin; 00745 return 0; 00746 00747 /* End of CSTEMR */ 00748 00749 } /* cstemr_ */