LAPACK 3.3.0
|
00001 SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E, 00002 $ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK, 00003 $ INFO ) 00004 * 00005 * -- LAPACK routine (version 3.2) -- 00006 * -- LAPACK is a software package provided by Univ. of Tennessee, -- 00007 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 00008 * November 2006 00009 * 8-18-00: Increase FUDGE factor for T3E (eca) 00010 * 00011 * .. Scalar Arguments .. 00012 CHARACTER ORDER, RANGE 00013 INTEGER IL, INFO, IU, M, N, NSPLIT 00014 DOUBLE PRECISION ABSTOL, VL, VU 00015 * .. 00016 * .. Array Arguments .. 00017 INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * ) 00018 DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ) 00019 * .. 00020 * 00021 * Purpose 00022 * ======= 00023 * 00024 * DSTEBZ computes the eigenvalues of a symmetric tridiagonal 00025 * matrix T. The user may ask for all eigenvalues, all eigenvalues 00026 * in the half-open interval (VL, VU], or the IL-th through IU-th 00027 * eigenvalues. 00028 * 00029 * To avoid overflow, the matrix must be scaled so that its 00030 * largest element is no greater than overflow**(1/2) * 00031 * underflow**(1/4) in absolute value, and for greatest 00032 * accuracy, it should not be much smaller than that. 00033 * 00034 * See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal 00035 * Matrix", Report CS41, Computer Science Dept., Stanford 00036 * University, July 21, 1966. 00037 * 00038 * Arguments 00039 * ========= 00040 * 00041 * RANGE (input) CHARACTER*1 00042 * = 'A': ("All") all eigenvalues will be found. 00043 * = 'V': ("Value") all eigenvalues in the half-open interval 00044 * (VL, VU] will be found. 00045 * = 'I': ("Index") the IL-th through IU-th eigenvalues (of the 00046 * entire matrix) will be found. 00047 * 00048 * ORDER (input) CHARACTER*1 00049 * = 'B': ("By Block") the eigenvalues will be grouped by 00050 * split-off block (see IBLOCK, ISPLIT) and 00051 * ordered from smallest to largest within 00052 * the block. 00053 * = 'E': ("Entire matrix") 00054 * the eigenvalues for the entire matrix 00055 * will be ordered from smallest to 00056 * largest. 00057 * 00058 * N (input) INTEGER 00059 * The order of the tridiagonal matrix T. N >= 0. 00060 * 00061 * VL (input) DOUBLE PRECISION 00062 * VU (input) DOUBLE PRECISION 00063 * If RANGE='V', the lower and upper bounds of the interval to 00064 * be searched for eigenvalues. Eigenvalues less than or equal 00065 * to VL, or greater than VU, will not be returned. VL < VU. 00066 * Not referenced if RANGE = 'A' or 'I'. 00067 * 00068 * IL (input) INTEGER 00069 * IU (input) INTEGER 00070 * If RANGE='I', the indices (in ascending order) of the 00071 * smallest and largest eigenvalues to be returned. 00072 * 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. 00073 * Not referenced if RANGE = 'A' or 'V'. 00074 * 00075 * ABSTOL (input) DOUBLE PRECISION 00076 * The absolute tolerance for the eigenvalues. An eigenvalue 00077 * (or cluster) is considered to be located if it has been 00078 * determined to lie in an interval whose width is ABSTOL or 00079 * less. If ABSTOL is less than or equal to zero, then ULP*|T| 00080 * will be used, where |T| means the 1-norm of T. 00081 * 00082 * Eigenvalues will be computed most accurately when ABSTOL is 00083 * set to twice the underflow threshold 2*DLAMCH('S'), not zero. 00084 * 00085 * D (input) DOUBLE PRECISION array, dimension (N) 00086 * The n diagonal elements of the tridiagonal matrix T. 00087 * 00088 * E (input) DOUBLE PRECISION array, dimension (N-1) 00089 * The (n-1) off-diagonal elements of the tridiagonal matrix T. 00090 * 00091 * M (output) INTEGER 00092 * The actual number of eigenvalues found. 0 <= M <= N. 00093 * (See also the description of INFO=2,3.) 00094 * 00095 * NSPLIT (output) INTEGER 00096 * The number of diagonal blocks in the matrix T. 00097 * 1 <= NSPLIT <= N. 00098 * 00099 * W (output) DOUBLE PRECISION array, dimension (N) 00100 * On exit, the first M elements of W will contain the 00101 * eigenvalues. (DSTEBZ may use the remaining N-M elements as 00102 * workspace.) 00103 * 00104 * IBLOCK (output) INTEGER array, dimension (N) 00105 * At each row/column j where E(j) is zero or small, the 00106 * matrix T is considered to split into a block diagonal 00107 * matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which 00108 * block (from 1 to the number of blocks) the eigenvalue W(i) 00109 * belongs. (DSTEBZ may use the remaining N-M elements as 00110 * workspace.) 00111 * 00112 * ISPLIT (output) INTEGER array, dimension (N) 00113 * The splitting points, at which T breaks up into submatrices. 00114 * The first submatrix consists of rows/columns 1 to ISPLIT(1), 00115 * the second of rows/columns ISPLIT(1)+1 through ISPLIT(2), 00116 * etc., and the NSPLIT-th consists of rows/columns 00117 * ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N. 00118 * (Only the first NSPLIT elements will actually be used, but 00119 * since the user cannot know a priori what value NSPLIT will 00120 * have, N words must be reserved for ISPLIT.) 00121 * 00122 * WORK (workspace) DOUBLE PRECISION array, dimension (4*N) 00123 * 00124 * IWORK (workspace) INTEGER array, dimension (3*N) 00125 * 00126 * INFO (output) INTEGER 00127 * = 0: successful exit 00128 * < 0: if INFO = -i, the i-th argument had an illegal value 00129 * > 0: some or all of the eigenvalues failed to converge or 00130 * were not computed: 00131 * =1 or 3: Bisection failed to converge for some 00132 * eigenvalues; these eigenvalues are flagged by a 00133 * negative block number. The effect is that the 00134 * eigenvalues may not be as accurate as the 00135 * absolute and relative tolerances. This is 00136 * generally caused by unexpectedly inaccurate 00137 * arithmetic. 00138 * =2 or 3: RANGE='I' only: Not all of the eigenvalues 00139 * IL:IU were found. 00140 * Effect: M < IU+1-IL 00141 * Cause: non-monotonic arithmetic, causing the 00142 * Sturm sequence to be non-monotonic. 00143 * Cure: recalculate, using RANGE='A', and pick 00144 * out eigenvalues IL:IU. In some cases, 00145 * increasing the PARAMETER "FUDGE" may 00146 * make things work. 00147 * = 4: RANGE='I', and the Gershgorin interval 00148 * initially used was too small. No eigenvalues 00149 * were computed. 00150 * Probable cause: your machine has sloppy 00151 * floating-point arithmetic. 00152 * Cure: Increase the PARAMETER "FUDGE", 00153 * recompile, and try again. 00154 * 00155 * Internal Parameters 00156 * =================== 00157 * 00158 * RELFAC DOUBLE PRECISION, default = 2.0e0 00159 * The relative tolerance. An interval (a,b] lies within 00160 * "relative tolerance" if b-a < RELFAC*ulp*max(|a|,|b|), 00161 * where "ulp" is the machine precision (distance from 1 to 00162 * the next larger floating point number.) 00163 * 00164 * FUDGE DOUBLE PRECISION, default = 2 00165 * A "fudge factor" to widen the Gershgorin intervals. Ideally, 00166 * a value of 1 should work, but on machines with sloppy 00167 * arithmetic, this needs to be larger. The default for 00168 * publicly released versions should be large enough to handle 00169 * the worst machine around. Note that this has no effect 00170 * on accuracy of the solution. 00171 * 00172 * ===================================================================== 00173 * 00174 * .. Parameters .. 00175 DOUBLE PRECISION ZERO, ONE, TWO, HALF 00176 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, 00177 $ HALF = 1.0D0 / TWO ) 00178 DOUBLE PRECISION FUDGE, RELFAC 00179 PARAMETER ( FUDGE = 2.1D0, RELFAC = 2.0D0 ) 00180 * .. 00181 * .. Local Scalars .. 00182 LOGICAL NCNVRG, TOOFEW 00183 INTEGER IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO, 00184 $ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX, 00185 $ ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL, 00186 $ NWU 00187 DOUBLE PRECISION ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN, 00188 $ TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL 00189 * .. 00190 * .. Local Arrays .. 00191 INTEGER IDUMMA( 1 ) 00192 * .. 00193 * .. External Functions .. 00194 LOGICAL LSAME 00195 INTEGER ILAENV 00196 DOUBLE PRECISION DLAMCH 00197 EXTERNAL LSAME, ILAENV, DLAMCH 00198 * .. 00199 * .. External Subroutines .. 00200 EXTERNAL DLAEBZ, XERBLA 00201 * .. 00202 * .. Intrinsic Functions .. 00203 INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT 00204 * .. 00205 * .. Executable Statements .. 00206 * 00207 INFO = 0 00208 * 00209 * Decode RANGE 00210 * 00211 IF( LSAME( RANGE, 'A' ) ) THEN 00212 IRANGE = 1 00213 ELSE IF( LSAME( RANGE, 'V' ) ) THEN 00214 IRANGE = 2 00215 ELSE IF( LSAME( RANGE, 'I' ) ) THEN 00216 IRANGE = 3 00217 ELSE 00218 IRANGE = 0 00219 END IF 00220 * 00221 * Decode ORDER 00222 * 00223 IF( LSAME( ORDER, 'B' ) ) THEN 00224 IORDER = 2 00225 ELSE IF( LSAME( ORDER, 'E' ) ) THEN 00226 IORDER = 1 00227 ELSE 00228 IORDER = 0 00229 END IF 00230 * 00231 * Check for Errors 00232 * 00233 IF( IRANGE.LE.0 ) THEN 00234 INFO = -1 00235 ELSE IF( IORDER.LE.0 ) THEN 00236 INFO = -2 00237 ELSE IF( N.LT.0 ) THEN 00238 INFO = -3 00239 ELSE IF( IRANGE.EQ.2 ) THEN 00240 IF( VL.GE.VU ) 00241 $ INFO = -5 00242 ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) ) 00243 $ THEN 00244 INFO = -6 00245 ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) 00246 $ THEN 00247 INFO = -7 00248 END IF 00249 * 00250 IF( INFO.NE.0 ) THEN 00251 CALL XERBLA( 'DSTEBZ', -INFO ) 00252 RETURN 00253 END IF 00254 * 00255 * Initialize error flags 00256 * 00257 INFO = 0 00258 NCNVRG = .FALSE. 00259 TOOFEW = .FALSE. 00260 * 00261 * Quick return if possible 00262 * 00263 M = 0 00264 IF( N.EQ.0 ) 00265 $ RETURN 00266 * 00267 * Simplifications: 00268 * 00269 IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N ) 00270 $ IRANGE = 1 00271 * 00272 * Get machine constants 00273 * NB is the minimum vector length for vector bisection, or 0 00274 * if only scalar is to be done. 00275 * 00276 SAFEMN = DLAMCH( 'S' ) 00277 ULP = DLAMCH( 'P' ) 00278 RTOLI = ULP*RELFAC 00279 NB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 ) 00280 IF( NB.LE.1 ) 00281 $ NB = 0 00282 * 00283 * Special Case when N=1 00284 * 00285 IF( N.EQ.1 ) THEN 00286 NSPLIT = 1 00287 ISPLIT( 1 ) = 1 00288 IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THEN 00289 M = 0 00290 ELSE 00291 W( 1 ) = D( 1 ) 00292 IBLOCK( 1 ) = 1 00293 M = 1 00294 END IF 00295 RETURN 00296 END IF 00297 * 00298 * Compute Splitting Points 00299 * 00300 NSPLIT = 1 00301 WORK( N ) = ZERO 00302 PIVMIN = ONE 00303 * 00304 *DIR$ NOVECTOR 00305 DO 10 J = 2, N 00306 TMP1 = E( J-1 )**2 00307 IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN 00308 ISPLIT( NSPLIT ) = J - 1 00309 NSPLIT = NSPLIT + 1 00310 WORK( J-1 ) = ZERO 00311 ELSE 00312 WORK( J-1 ) = TMP1 00313 PIVMIN = MAX( PIVMIN, TMP1 ) 00314 END IF 00315 10 CONTINUE 00316 ISPLIT( NSPLIT ) = N 00317 PIVMIN = PIVMIN*SAFEMN 00318 * 00319 * Compute Interval and ATOLI 00320 * 00321 IF( IRANGE.EQ.3 ) THEN 00322 * 00323 * RANGE='I': Compute the interval containing eigenvalues 00324 * IL through IU. 00325 * 00326 * Compute Gershgorin interval for entire (split) matrix 00327 * and use it as the initial interval 00328 * 00329 GU = D( 1 ) 00330 GL = D( 1 ) 00331 TMP1 = ZERO 00332 * 00333 DO 20 J = 1, N - 1 00334 TMP2 = SQRT( WORK( J ) ) 00335 GU = MAX( GU, D( J )+TMP1+TMP2 ) 00336 GL = MIN( GL, D( J )-TMP1-TMP2 ) 00337 TMP1 = TMP2 00338 20 CONTINUE 00339 * 00340 GU = MAX( GU, D( N )+TMP1 ) 00341 GL = MIN( GL, D( N )-TMP1 ) 00342 TNORM = MAX( ABS( GL ), ABS( GU ) ) 00343 GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN 00344 GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN 00345 * 00346 * Compute Iteration parameters 00347 * 00348 ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) / 00349 $ LOG( TWO ) ) + 2 00350 IF( ABSTOL.LE.ZERO ) THEN 00351 ATOLI = ULP*TNORM 00352 ELSE 00353 ATOLI = ABSTOL 00354 END IF 00355 * 00356 WORK( N+1 ) = GL 00357 WORK( N+2 ) = GL 00358 WORK( N+3 ) = GU 00359 WORK( N+4 ) = GU 00360 WORK( N+5 ) = GL 00361 WORK( N+6 ) = GU 00362 IWORK( 1 ) = -1 00363 IWORK( 2 ) = -1 00364 IWORK( 3 ) = N + 1 00365 IWORK( 4 ) = N + 1 00366 IWORK( 5 ) = IL - 1 00367 IWORK( 6 ) = IU 00368 * 00369 CALL DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E, 00370 $ WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT, 00371 $ IWORK, W, IBLOCK, IINFO ) 00372 * 00373 IF( IWORK( 6 ).EQ.IU ) THEN 00374 WL = WORK( N+1 ) 00375 WLU = WORK( N+3 ) 00376 NWL = IWORK( 1 ) 00377 WU = WORK( N+4 ) 00378 WUL = WORK( N+2 ) 00379 NWU = IWORK( 4 ) 00380 ELSE 00381 WL = WORK( N+2 ) 00382 WLU = WORK( N+4 ) 00383 NWL = IWORK( 2 ) 00384 WU = WORK( N+3 ) 00385 WUL = WORK( N+1 ) 00386 NWU = IWORK( 3 ) 00387 END IF 00388 * 00389 IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THEN 00390 INFO = 4 00391 RETURN 00392 END IF 00393 ELSE 00394 * 00395 * RANGE='A' or 'V' -- Set ATOLI 00396 * 00397 TNORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ), 00398 $ ABS( D( N ) )+ABS( E( N-1 ) ) ) 00399 * 00400 DO 30 J = 2, N - 1 00401 TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+ 00402 $ ABS( E( J ) ) ) 00403 30 CONTINUE 00404 * 00405 IF( ABSTOL.LE.ZERO ) THEN 00406 ATOLI = ULP*TNORM 00407 ELSE 00408 ATOLI = ABSTOL 00409 END IF 00410 * 00411 IF( IRANGE.EQ.2 ) THEN 00412 WL = VL 00413 WU = VU 00414 ELSE 00415 WL = ZERO 00416 WU = ZERO 00417 END IF 00418 END IF 00419 * 00420 * Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU. 00421 * NWL accumulates the number of eigenvalues .le. WL, 00422 * NWU accumulates the number of eigenvalues .le. WU 00423 * 00424 M = 0 00425 IEND = 0 00426 INFO = 0 00427 NWL = 0 00428 NWU = 0 00429 * 00430 DO 70 JB = 1, NSPLIT 00431 IOFF = IEND 00432 IBEGIN = IOFF + 1 00433 IEND = ISPLIT( JB ) 00434 IN = IEND - IOFF 00435 * 00436 IF( IN.EQ.1 ) THEN 00437 * 00438 * Special Case -- IN=1 00439 * 00440 IF( IRANGE.EQ.1 .OR. WL.GE.D( IBEGIN )-PIVMIN ) 00441 $ NWL = NWL + 1 00442 IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN ) 00443 $ NWU = NWU + 1 00444 IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE. 00445 $ D( IBEGIN )-PIVMIN ) ) THEN 00446 M = M + 1 00447 W( M ) = D( IBEGIN ) 00448 IBLOCK( M ) = JB 00449 END IF 00450 ELSE 00451 * 00452 * General Case -- IN > 1 00453 * 00454 * Compute Gershgorin Interval 00455 * and use it as the initial interval 00456 * 00457 GU = D( IBEGIN ) 00458 GL = D( IBEGIN ) 00459 TMP1 = ZERO 00460 * 00461 DO 40 J = IBEGIN, IEND - 1 00462 TMP2 = ABS( E( J ) ) 00463 GU = MAX( GU, D( J )+TMP1+TMP2 ) 00464 GL = MIN( GL, D( J )-TMP1-TMP2 ) 00465 TMP1 = TMP2 00466 40 CONTINUE 00467 * 00468 GU = MAX( GU, D( IEND )+TMP1 ) 00469 GL = MIN( GL, D( IEND )-TMP1 ) 00470 BNORM = MAX( ABS( GL ), ABS( GU ) ) 00471 GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN 00472 GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN 00473 * 00474 * Compute ATOLI for the current submatrix 00475 * 00476 IF( ABSTOL.LE.ZERO ) THEN 00477 ATOLI = ULP*MAX( ABS( GL ), ABS( GU ) ) 00478 ELSE 00479 ATOLI = ABSTOL 00480 END IF 00481 * 00482 IF( IRANGE.GT.1 ) THEN 00483 IF( GU.LT.WL ) THEN 00484 NWL = NWL + IN 00485 NWU = NWU + IN 00486 GO TO 70 00487 END IF 00488 GL = MAX( GL, WL ) 00489 GU = MIN( GU, WU ) 00490 IF( GL.GE.GU ) 00491 $ GO TO 70 00492 END IF 00493 * 00494 * Set Up Initial Interval 00495 * 00496 WORK( N+1 ) = GL 00497 WORK( N+IN+1 ) = GU 00498 CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN, 00499 $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ), 00500 $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM, 00501 $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO ) 00502 * 00503 NWL = NWL + IWORK( 1 ) 00504 NWU = NWU + IWORK( IN+1 ) 00505 IWOFF = M - IWORK( 1 ) 00506 * 00507 * Compute Eigenvalues 00508 * 00509 ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) / 00510 $ LOG( TWO ) ) + 2 00511 CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN, 00512 $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ), 00513 $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT, 00514 $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO ) 00515 * 00516 * Copy Eigenvalues Into W and IBLOCK 00517 * Use -JB for block number for unconverged eigenvalues. 00518 * 00519 DO 60 J = 1, IOUT 00520 TMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) ) 00521 * 00522 * Flag non-convergence. 00523 * 00524 IF( J.GT.IOUT-IINFO ) THEN 00525 NCNVRG = .TRUE. 00526 IB = -JB 00527 ELSE 00528 IB = JB 00529 END IF 00530 DO 50 JE = IWORK( J ) + 1 + IWOFF, 00531 $ IWORK( J+IN ) + IWOFF 00532 W( JE ) = TMP1 00533 IBLOCK( JE ) = IB 00534 50 CONTINUE 00535 60 CONTINUE 00536 * 00537 M = M + IM 00538 END IF 00539 70 CONTINUE 00540 * 00541 * If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU 00542 * If NWL+1 < IL or NWU > IU, discard extra eigenvalues. 00543 * 00544 IF( IRANGE.EQ.3 ) THEN 00545 IM = 0 00546 IDISCL = IL - 1 - NWL 00547 IDISCU = NWU - IU 00548 * 00549 IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN 00550 DO 80 JE = 1, M 00551 IF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THEN 00552 IDISCL = IDISCL - 1 00553 ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THEN 00554 IDISCU = IDISCU - 1 00555 ELSE 00556 IM = IM + 1 00557 W( IM ) = W( JE ) 00558 IBLOCK( IM ) = IBLOCK( JE ) 00559 END IF 00560 80 CONTINUE 00561 M = IM 00562 END IF 00563 IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN 00564 * 00565 * Code to deal with effects of bad arithmetic: 00566 * Some low eigenvalues to be discarded are not in (WL,WLU], 00567 * or high eigenvalues to be discarded are not in (WUL,WU] 00568 * so just kill off the smallest IDISCL/largest IDISCU 00569 * eigenvalues, by simply finding the smallest/largest 00570 * eigenvalue(s). 00571 * 00572 * (If N(w) is monotone non-decreasing, this should never 00573 * happen.) 00574 * 00575 IF( IDISCL.GT.0 ) THEN 00576 WKILL = WU 00577 DO 100 JDISC = 1, IDISCL 00578 IW = 0 00579 DO 90 JE = 1, M 00580 IF( IBLOCK( JE ).NE.0 .AND. 00581 $ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THEN 00582 IW = JE 00583 WKILL = W( JE ) 00584 END IF 00585 90 CONTINUE 00586 IBLOCK( IW ) = 0 00587 100 CONTINUE 00588 END IF 00589 IF( IDISCU.GT.0 ) THEN 00590 * 00591 WKILL = WL 00592 DO 120 JDISC = 1, IDISCU 00593 IW = 0 00594 DO 110 JE = 1, M 00595 IF( IBLOCK( JE ).NE.0 .AND. 00596 $ ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THEN 00597 IW = JE 00598 WKILL = W( JE ) 00599 END IF 00600 110 CONTINUE 00601 IBLOCK( IW ) = 0 00602 120 CONTINUE 00603 END IF 00604 IM = 0 00605 DO 130 JE = 1, M 00606 IF( IBLOCK( JE ).NE.0 ) THEN 00607 IM = IM + 1 00608 W( IM ) = W( JE ) 00609 IBLOCK( IM ) = IBLOCK( JE ) 00610 END IF 00611 130 CONTINUE 00612 M = IM 00613 END IF 00614 IF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THEN 00615 TOOFEW = .TRUE. 00616 END IF 00617 END IF 00618 * 00619 * If ORDER='B', do nothing -- the eigenvalues are already sorted 00620 * by block. 00621 * If ORDER='E', sort the eigenvalues from smallest to largest 00622 * 00623 IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THEN 00624 DO 150 JE = 1, M - 1 00625 IE = 0 00626 TMP1 = W( JE ) 00627 DO 140 J = JE + 1, M 00628 IF( W( J ).LT.TMP1 ) THEN 00629 IE = J 00630 TMP1 = W( J ) 00631 END IF 00632 140 CONTINUE 00633 * 00634 IF( IE.NE.0 ) THEN 00635 ITMP1 = IBLOCK( IE ) 00636 W( IE ) = W( JE ) 00637 IBLOCK( IE ) = IBLOCK( JE ) 00638 W( JE ) = TMP1 00639 IBLOCK( JE ) = ITMP1 00640 END IF 00641 150 CONTINUE 00642 END IF 00643 * 00644 INFO = 0 00645 IF( NCNVRG ) 00646 $ INFO = INFO + 1 00647 IF( TOOFEW ) 00648 $ INFO = INFO + 2 00649 RETURN 00650 * 00651 * End of DSTEBZ 00652 * 00653 END