Annotation of rpl/lapack/lapack/dlarrd.f, revision 1.1
1.1 ! bertrand 1: SUBROUTINE DLARRD( RANGE, ORDER, N, VL, VU, IL, IU, GERS,
! 2: $ RELTOL, D, E, E2, PIVMIN, NSPLIT, ISPLIT,
! 3: $ M, W, WERR, WL, WU, IBLOCK, INDEXW,
! 4: $ WORK, IWORK, INFO )
! 5: *
! 6: * -- LAPACK auxiliary routine (version 3.2.1) --
! 7: * -- LAPACK is a software package provided by Univ. of Tennessee, --
! 8: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! 9: * -- April 2009 --
! 10: *
! 11: * .. Scalar Arguments ..
! 12: CHARACTER ORDER, RANGE
! 13: INTEGER IL, INFO, IU, M, N, NSPLIT
! 14: DOUBLE PRECISION PIVMIN, RELTOL, VL, VU, WL, WU
! 15: * ..
! 16: * .. Array Arguments ..
! 17: INTEGER IBLOCK( * ), INDEXW( * ),
! 18: $ ISPLIT( * ), IWORK( * )
! 19: DOUBLE PRECISION D( * ), E( * ), E2( * ),
! 20: $ GERS( * ), W( * ), WERR( * ), WORK( * )
! 21: * ..
! 22: *
! 23: * Purpose
! 24: * =======
! 25: *
! 26: * DLARRD computes the eigenvalues of a symmetric tridiagonal
! 27: * matrix T to suitable accuracy. This is an auxiliary code to be
! 28: * called from DSTEMR.
! 29: * The user may ask for all eigenvalues, all eigenvalues
! 30: * in the half-open interval (VL, VU], or the IL-th through IU-th
! 31: * eigenvalues.
! 32: *
! 33: * To avoid overflow, the matrix must be scaled so that its
! 34: * largest element is no greater than overflow**(1/2) *
! 35: * underflow**(1/4) in absolute value, and for greatest
! 36: * accuracy, it should not be much smaller than that.
! 37: *
! 38: * See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal
! 39: * Matrix", Report CS41, Computer Science Dept., Stanford
! 40: * University, July 21, 1966.
! 41: *
! 42: * Arguments
! 43: * =========
! 44: *
! 45: * RANGE (input) CHARACTER
! 46: * = 'A': ("All") all eigenvalues will be found.
! 47: * = 'V': ("Value") all eigenvalues in the half-open interval
! 48: * (VL, VU] will be found.
! 49: * = 'I': ("Index") the IL-th through IU-th eigenvalues (of the
! 50: * entire matrix) will be found.
! 51: *
! 52: * ORDER (input) CHARACTER
! 53: * = 'B': ("By Block") the eigenvalues will be grouped by
! 54: * split-off block (see IBLOCK, ISPLIT) and
! 55: * ordered from smallest to largest within
! 56: * the block.
! 57: * = 'E': ("Entire matrix")
! 58: * the eigenvalues for the entire matrix
! 59: * will be ordered from smallest to
! 60: * largest.
! 61: *
! 62: * N (input) INTEGER
! 63: * The order of the tridiagonal matrix T. N >= 0.
! 64: *
! 65: * VL (input) DOUBLE PRECISION
! 66: * VU (input) DOUBLE PRECISION
! 67: * If RANGE='V', the lower and upper bounds of the interval to
! 68: * be searched for eigenvalues. Eigenvalues less than or equal
! 69: * to VL, or greater than VU, will not be returned. VL < VU.
! 70: * Not referenced if RANGE = 'A' or 'I'.
! 71: *
! 72: * IL (input) INTEGER
! 73: * IU (input) INTEGER
! 74: * If RANGE='I', the indices (in ascending order) of the
! 75: * smallest and largest eigenvalues to be returned.
! 76: * 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
! 77: * Not referenced if RANGE = 'A' or 'V'.
! 78: *
! 79: * GERS (input) DOUBLE PRECISION array, dimension (2*N)
! 80: * The N Gerschgorin intervals (the i-th Gerschgorin interval
! 81: * is (GERS(2*i-1), GERS(2*i)).
! 82: *
! 83: * RELTOL (input) DOUBLE PRECISION
! 84: * The minimum relative width of an interval. When an interval
! 85: * is narrower than RELTOL times the larger (in
! 86: * magnitude) endpoint, then it is considered to be
! 87: * sufficiently small, i.e., converged. Note: this should
! 88: * always be at least radix*machine epsilon.
! 89: *
! 90: * D (input) DOUBLE PRECISION array, dimension (N)
! 91: * The n diagonal elements of the tridiagonal matrix T.
! 92: *
! 93: * E (input) DOUBLE PRECISION array, dimension (N-1)
! 94: * The (n-1) off-diagonal elements of the tridiagonal matrix T.
! 95: *
! 96: * E2 (input) DOUBLE PRECISION array, dimension (N-1)
! 97: * The (n-1) squared off-diagonal elements of the tridiagonal matrix T.
! 98: *
! 99: * PIVMIN (input) DOUBLE PRECISION
! 100: * The minimum pivot allowed in the Sturm sequence for T.
! 101: *
! 102: * NSPLIT (input) INTEGER
! 103: * The number of diagonal blocks in the matrix T.
! 104: * 1 <= NSPLIT <= N.
! 105: *
! 106: * ISPLIT (input) INTEGER array, dimension (N)
! 107: * The splitting points, at which T breaks up into submatrices.
! 108: * The first submatrix consists of rows/columns 1 to ISPLIT(1),
! 109: * the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
! 110: * etc., and the NSPLIT-th consists of rows/columns
! 111: * ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
! 112: * (Only the first NSPLIT elements will actually be used, but
! 113: * since the user cannot know a priori what value NSPLIT will
! 114: * have, N words must be reserved for ISPLIT.)
! 115: *
! 116: * M (output) INTEGER
! 117: * The actual number of eigenvalues found. 0 <= M <= N.
! 118: * (See also the description of INFO=2,3.)
! 119: *
! 120: * W (output) DOUBLE PRECISION array, dimension (N)
! 121: * On exit, the first M elements of W will contain the
! 122: * eigenvalue approximations. DLARRD computes an interval
! 123: * I_j = (a_j, b_j] that includes eigenvalue j. The eigenvalue
! 124: * approximation is given as the interval midpoint
! 125: * W(j)= ( a_j + b_j)/2. The corresponding error is bounded by
! 126: * WERR(j) = abs( a_j - b_j)/2
! 127: *
! 128: * WERR (output) DOUBLE PRECISION array, dimension (N)
! 129: * The error bound on the corresponding eigenvalue approximation
! 130: * in W.
! 131: *
! 132: * WL (output) DOUBLE PRECISION
! 133: * WU (output) DOUBLE PRECISION
! 134: * The interval (WL, WU] contains all the wanted eigenvalues.
! 135: * If RANGE='V', then WL=VL and WU=VU.
! 136: * If RANGE='A', then WL and WU are the global Gerschgorin bounds
! 137: * on the spectrum.
! 138: * If RANGE='I', then WL and WU are computed by DLAEBZ from the
! 139: * index range specified.
! 140: *
! 141: * IBLOCK (output) INTEGER array, dimension (N)
! 142: * At each row/column j where E(j) is zero or small, the
! 143: * matrix T is considered to split into a block diagonal
! 144: * matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which
! 145: * block (from 1 to the number of blocks) the eigenvalue W(i)
! 146: * belongs. (DLARRD may use the remaining N-M elements as
! 147: * workspace.)
! 148: *
! 149: * INDEXW (output) INTEGER array, dimension (N)
! 150: * The indices of the eigenvalues within each block (submatrix);
! 151: * for example, INDEXW(i)= j and IBLOCK(i)=k imply that the
! 152: * i-th eigenvalue W(i) is the j-th eigenvalue in block k.
! 153: *
! 154: * WORK (workspace) DOUBLE PRECISION array, dimension (4*N)
! 155: *
! 156: * IWORK (workspace) INTEGER array, dimension (3*N)
! 157: *
! 158: * INFO (output) INTEGER
! 159: * = 0: successful exit
! 160: * < 0: if INFO = -i, the i-th argument had an illegal value
! 161: * > 0: some or all of the eigenvalues failed to converge or
! 162: * were not computed:
! 163: * =1 or 3: Bisection failed to converge for some
! 164: * eigenvalues; these eigenvalues are flagged by a
! 165: * negative block number. The effect is that the
! 166: * eigenvalues may not be as accurate as the
! 167: * absolute and relative tolerances. This is
! 168: * generally caused by unexpectedly inaccurate
! 169: * arithmetic.
! 170: * =2 or 3: RANGE='I' only: Not all of the eigenvalues
! 171: * IL:IU were found.
! 172: * Effect: M < IU+1-IL
! 173: * Cause: non-monotonic arithmetic, causing the
! 174: * Sturm sequence to be non-monotonic.
! 175: * Cure: recalculate, using RANGE='A', and pick
! 176: * out eigenvalues IL:IU. In some cases,
! 177: * increasing the PARAMETER "FUDGE" may
! 178: * make things work.
! 179: * = 4: RANGE='I', and the Gershgorin interval
! 180: * initially used was too small. No eigenvalues
! 181: * were computed.
! 182: * Probable cause: your machine has sloppy
! 183: * floating-point arithmetic.
! 184: * Cure: Increase the PARAMETER "FUDGE",
! 185: * recompile, and try again.
! 186: *
! 187: * Internal Parameters
! 188: * ===================
! 189: *
! 190: * FUDGE DOUBLE PRECISION, default = 2
! 191: * A "fudge factor" to widen the Gershgorin intervals. Ideally,
! 192: * a value of 1 should work, but on machines with sloppy
! 193: * arithmetic, this needs to be larger. The default for
! 194: * publicly released versions should be large enough to handle
! 195: * the worst machine around. Note that this has no effect
! 196: * on accuracy of the solution.
! 197: *
! 198: * Based on contributions by
! 199: * W. Kahan, University of California, Berkeley, USA
! 200: * Beresford Parlett, University of California, Berkeley, USA
! 201: * Jim Demmel, University of California, Berkeley, USA
! 202: * Inderjit Dhillon, University of Texas, Austin, USA
! 203: * Osni Marques, LBNL/NERSC, USA
! 204: * Christof Voemel, University of California, Berkeley, USA
! 205: *
! 206: * =====================================================================
! 207: *
! 208: * .. Parameters ..
! 209: DOUBLE PRECISION ZERO, ONE, TWO, HALF, FUDGE
! 210: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0,
! 211: $ TWO = 2.0D0, HALF = ONE/TWO,
! 212: $ FUDGE = TWO )
! 213: INTEGER ALLRNG, VALRNG, INDRNG
! 214: PARAMETER ( ALLRNG = 1, VALRNG = 2, INDRNG = 3 )
! 215: * ..
! 216: * .. Local Scalars ..
! 217: LOGICAL NCNVRG, TOOFEW
! 218: INTEGER I, IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,
! 219: $ IM, IN, IOFF, IOUT, IRANGE, ITMAX, ITMP1,
! 220: $ ITMP2, IW, IWOFF, J, JBLK, JDISC, JE, JEE, NB,
! 221: $ NWL, NWU
! 222: DOUBLE PRECISION ATOLI, EPS, GL, GU, RTOLI, TMP1, TMP2,
! 223: $ TNORM, UFLOW, WKILL, WLU, WUL
! 224:
! 225: * ..
! 226: * .. Local Arrays ..
! 227: INTEGER IDUMMA( 1 )
! 228: * ..
! 229: * .. External Functions ..
! 230: LOGICAL LSAME
! 231: INTEGER ILAENV
! 232: DOUBLE PRECISION DLAMCH
! 233: EXTERNAL LSAME, ILAENV, DLAMCH
! 234: * ..
! 235: * .. External Subroutines ..
! 236: EXTERNAL DLAEBZ
! 237: * ..
! 238: * .. Intrinsic Functions ..
! 239: INTRINSIC ABS, INT, LOG, MAX, MIN
! 240: * ..
! 241: * .. Executable Statements ..
! 242: *
! 243: INFO = 0
! 244: *
! 245: * Decode RANGE
! 246: *
! 247: IF( LSAME( RANGE, 'A' ) ) THEN
! 248: IRANGE = ALLRNG
! 249: ELSE IF( LSAME( RANGE, 'V' ) ) THEN
! 250: IRANGE = VALRNG
! 251: ELSE IF( LSAME( RANGE, 'I' ) ) THEN
! 252: IRANGE = INDRNG
! 253: ELSE
! 254: IRANGE = 0
! 255: END IF
! 256: *
! 257: * Check for Errors
! 258: *
! 259: IF( IRANGE.LE.0 ) THEN
! 260: INFO = -1
! 261: ELSE IF( .NOT.(LSAME(ORDER,'B').OR.LSAME(ORDER,'E')) ) THEN
! 262: INFO = -2
! 263: ELSE IF( N.LT.0 ) THEN
! 264: INFO = -3
! 265: ELSE IF( IRANGE.EQ.VALRNG ) THEN
! 266: IF( VL.GE.VU )
! 267: $ INFO = -5
! 268: ELSE IF( IRANGE.EQ.INDRNG .AND.
! 269: $ ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) ) THEN
! 270: INFO = -6
! 271: ELSE IF( IRANGE.EQ.INDRNG .AND.
! 272: $ ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THEN
! 273: INFO = -7
! 274: END IF
! 275: *
! 276: IF( INFO.NE.0 ) THEN
! 277: RETURN
! 278: END IF
! 279:
! 280: * Initialize error flags
! 281: INFO = 0
! 282: NCNVRG = .FALSE.
! 283: TOOFEW = .FALSE.
! 284:
! 285: * Quick return if possible
! 286: M = 0
! 287: IF( N.EQ.0 ) RETURN
! 288:
! 289: * Simplification:
! 290: IF( IRANGE.EQ.INDRNG .AND. IL.EQ.1 .AND. IU.EQ.N ) IRANGE = 1
! 291:
! 292: * Get machine constants
! 293: EPS = DLAMCH( 'P' )
! 294: UFLOW = DLAMCH( 'U' )
! 295:
! 296:
! 297: * Special Case when N=1
! 298: * Treat case of 1x1 matrix for quick return
! 299: IF( N.EQ.1 ) THEN
! 300: IF( (IRANGE.EQ.ALLRNG).OR.
! 301: $ ((IRANGE.EQ.VALRNG).AND.(D(1).GT.VL).AND.(D(1).LE.VU)).OR.
! 302: $ ((IRANGE.EQ.INDRNG).AND.(IL.EQ.1).AND.(IU.EQ.1)) ) THEN
! 303: M = 1
! 304: W(1) = D(1)
! 305: * The computation error of the eigenvalue is zero
! 306: WERR(1) = ZERO
! 307: IBLOCK( 1 ) = 1
! 308: INDEXW( 1 ) = 1
! 309: ENDIF
! 310: RETURN
! 311: END IF
! 312:
! 313: * NB is the minimum vector length for vector bisection, or 0
! 314: * if only scalar is to be done.
! 315: NB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 )
! 316: IF( NB.LE.1 ) NB = 0
! 317:
! 318: * Find global spectral radius
! 319: GL = D(1)
! 320: GU = D(1)
! 321: DO 5 I = 1,N
! 322: GL = MIN( GL, GERS( 2*I - 1))
! 323: GU = MAX( GU, GERS(2*I) )
! 324: 5 CONTINUE
! 325: * Compute global Gerschgorin bounds and spectral diameter
! 326: TNORM = MAX( ABS( GL ), ABS( GU ) )
! 327: GL = GL - FUDGE*TNORM*EPS*N - FUDGE*TWO*PIVMIN
! 328: GU = GU + FUDGE*TNORM*EPS*N + FUDGE*TWO*PIVMIN
! 329: * [JAN/28/2009] remove the line below since SPDIAM variable not use
! 330: * SPDIAM = GU - GL
! 331: * Input arguments for DLAEBZ:
! 332: * The relative tolerance. An interval (a,b] lies within
! 333: * "relative tolerance" if b-a < RELTOL*max(|a|,|b|),
! 334: RTOLI = RELTOL
! 335: * Set the absolute tolerance for interval convergence to zero to force
! 336: * interval convergence based on relative size of the interval.
! 337: * This is dangerous because intervals might not converge when RELTOL is
! 338: * small. But at least a very small number should be selected so that for
! 339: * strongly graded matrices, the code can get relatively accurate
! 340: * eigenvalues.
! 341: ATOLI = FUDGE*TWO*UFLOW + FUDGE*TWO*PIVMIN
! 342:
! 343: IF( IRANGE.EQ.INDRNG ) THEN
! 344:
! 345: * RANGE='I': Compute an interval containing eigenvalues
! 346: * IL through IU. The initial interval [GL,GU] from the global
! 347: * Gerschgorin bounds GL and GU is refined by DLAEBZ.
! 348: ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) /
! 349: $ LOG( TWO ) ) + 2
! 350: WORK( N+1 ) = GL
! 351: WORK( N+2 ) = GL
! 352: WORK( N+3 ) = GU
! 353: WORK( N+4 ) = GU
! 354: WORK( N+5 ) = GL
! 355: WORK( N+6 ) = GU
! 356: IWORK( 1 ) = -1
! 357: IWORK( 2 ) = -1
! 358: IWORK( 3 ) = N + 1
! 359: IWORK( 4 ) = N + 1
! 360: IWORK( 5 ) = IL - 1
! 361: IWORK( 6 ) = IU
! 362: *
! 363: CALL DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN,
! 364: $ D, E, E2, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,
! 365: $ IWORK, W, IBLOCK, IINFO )
! 366: IF( IINFO .NE. 0 ) THEN
! 367: INFO = IINFO
! 368: RETURN
! 369: END IF
! 370: * On exit, output intervals may not be ordered by ascending negcount
! 371: IF( IWORK( 6 ).EQ.IU ) THEN
! 372: WL = WORK( N+1 )
! 373: WLU = WORK( N+3 )
! 374: NWL = IWORK( 1 )
! 375: WU = WORK( N+4 )
! 376: WUL = WORK( N+2 )
! 377: NWU = IWORK( 4 )
! 378: ELSE
! 379: WL = WORK( N+2 )
! 380: WLU = WORK( N+4 )
! 381: NWL = IWORK( 2 )
! 382: WU = WORK( N+3 )
! 383: WUL = WORK( N+1 )
! 384: NWU = IWORK( 3 )
! 385: END IF
! 386: * On exit, the interval [WL, WLU] contains a value with negcount NWL,
! 387: * and [WUL, WU] contains a value with negcount NWU.
! 388: IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THEN
! 389: INFO = 4
! 390: RETURN
! 391: END IF
! 392:
! 393: ELSEIF( IRANGE.EQ.VALRNG ) THEN
! 394: WL = VL
! 395: WU = VU
! 396:
! 397: ELSEIF( IRANGE.EQ.ALLRNG ) THEN
! 398: WL = GL
! 399: WU = GU
! 400: ENDIF
! 401:
! 402:
! 403:
! 404: * Find Eigenvalues -- Loop Over blocks and recompute NWL and NWU.
! 405: * NWL accumulates the number of eigenvalues .le. WL,
! 406: * NWU accumulates the number of eigenvalues .le. WU
! 407: M = 0
! 408: IEND = 0
! 409: INFO = 0
! 410: NWL = 0
! 411: NWU = 0
! 412: *
! 413: DO 70 JBLK = 1, NSPLIT
! 414: IOFF = IEND
! 415: IBEGIN = IOFF + 1
! 416: IEND = ISPLIT( JBLK )
! 417: IN = IEND - IOFF
! 418: *
! 419: IF( IN.EQ.1 ) THEN
! 420: * 1x1 block
! 421: IF( WL.GE.D( IBEGIN )-PIVMIN )
! 422: $ NWL = NWL + 1
! 423: IF( WU.GE.D( IBEGIN )-PIVMIN )
! 424: $ NWU = NWU + 1
! 425: IF( IRANGE.EQ.ALLRNG .OR.
! 426: $ ( WL.LT.D( IBEGIN )-PIVMIN
! 427: $ .AND. WU.GE. D( IBEGIN )-PIVMIN ) ) THEN
! 428: M = M + 1
! 429: W( M ) = D( IBEGIN )
! 430: WERR(M) = ZERO
! 431: * The gap for a single block doesn't matter for the later
! 432: * algorithm and is assigned an arbitrary large value
! 433: IBLOCK( M ) = JBLK
! 434: INDEXW( M ) = 1
! 435: END IF
! 436:
! 437: * Disabled 2x2 case because of a failure on the following matrix
! 438: * RANGE = 'I', IL = IU = 4
! 439: * Original Tridiagonal, d = [
! 440: * -0.150102010615740E+00
! 441: * -0.849897989384260E+00
! 442: * -0.128208148052635E-15
! 443: * 0.128257718286320E-15
! 444: * ];
! 445: * e = [
! 446: * -0.357171383266986E+00
! 447: * -0.180411241501588E-15
! 448: * -0.175152352710251E-15
! 449: * ];
! 450: *
! 451: * ELSE IF( IN.EQ.2 ) THEN
! 452: ** 2x2 block
! 453: * DISC = SQRT( (HALF*(D(IBEGIN)-D(IEND)))**2 + E(IBEGIN)**2 )
! 454: * TMP1 = HALF*(D(IBEGIN)+D(IEND))
! 455: * L1 = TMP1 - DISC
! 456: * IF( WL.GE. L1-PIVMIN )
! 457: * $ NWL = NWL + 1
! 458: * IF( WU.GE. L1-PIVMIN )
! 459: * $ NWU = NWU + 1
! 460: * IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L1-PIVMIN .AND. WU.GE.
! 461: * $ L1-PIVMIN ) ) THEN
! 462: * M = M + 1
! 463: * W( M ) = L1
! 464: ** The uncertainty of eigenvalues of a 2x2 matrix is very small
! 465: * WERR( M ) = EPS * ABS( W( M ) ) * TWO
! 466: * IBLOCK( M ) = JBLK
! 467: * INDEXW( M ) = 1
! 468: * ENDIF
! 469: * L2 = TMP1 + DISC
! 470: * IF( WL.GE. L2-PIVMIN )
! 471: * $ NWL = NWL + 1
! 472: * IF( WU.GE. L2-PIVMIN )
! 473: * $ NWU = NWU + 1
! 474: * IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L2-PIVMIN .AND. WU.GE.
! 475: * $ L2-PIVMIN ) ) THEN
! 476: * M = M + 1
! 477: * W( M ) = L2
! 478: ** The uncertainty of eigenvalues of a 2x2 matrix is very small
! 479: * WERR( M ) = EPS * ABS( W( M ) ) * TWO
! 480: * IBLOCK( M ) = JBLK
! 481: * INDEXW( M ) = 2
! 482: * ENDIF
! 483: ELSE
! 484: * General Case - block of size IN >= 2
! 485: * Compute local Gerschgorin interval and use it as the initial
! 486: * interval for DLAEBZ
! 487: GU = D( IBEGIN )
! 488: GL = D( IBEGIN )
! 489: TMP1 = ZERO
! 490:
! 491: DO 40 J = IBEGIN, IEND
! 492: GL = MIN( GL, GERS( 2*J - 1))
! 493: GU = MAX( GU, GERS(2*J) )
! 494: 40 CONTINUE
! 495: * [JAN/28/2009]
! 496: * change SPDIAM by TNORM in lines 2 and 3 thereafter
! 497: * line 1: remove computation of SPDIAM (not useful anymore)
! 498: * SPDIAM = GU - GL
! 499: * GL = GL - FUDGE*SPDIAM*EPS*IN - FUDGE*PIVMIN
! 500: * GU = GU + FUDGE*SPDIAM*EPS*IN + FUDGE*PIVMIN
! 501: GL = GL - FUDGE*TNORM*EPS*IN - FUDGE*PIVMIN
! 502: GU = GU + FUDGE*TNORM*EPS*IN + FUDGE*PIVMIN
! 503: *
! 504: IF( IRANGE.GT.1 ) THEN
! 505: IF( GU.LT.WL ) THEN
! 506: * the local block contains none of the wanted eigenvalues
! 507: NWL = NWL + IN
! 508: NWU = NWU + IN
! 509: GO TO 70
! 510: END IF
! 511: * refine search interval if possible, only range (WL,WU] matters
! 512: GL = MAX( GL, WL )
! 513: GU = MIN( GU, WU )
! 514: IF( GL.GE.GU )
! 515: $ GO TO 70
! 516: END IF
! 517:
! 518: * Find negcount of initial interval boundaries GL and GU
! 519: WORK( N+1 ) = GL
! 520: WORK( N+IN+1 ) = GU
! 521: CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
! 522: $ D( IBEGIN ), E( IBEGIN ), E2( IBEGIN ),
! 523: $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,
! 524: $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
! 525: IF( IINFO .NE. 0 ) THEN
! 526: INFO = IINFO
! 527: RETURN
! 528: END IF
! 529: *
! 530: NWL = NWL + IWORK( 1 )
! 531: NWU = NWU + IWORK( IN+1 )
! 532: IWOFF = M - IWORK( 1 )
! 533:
! 534: * Compute Eigenvalues
! 535: ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) /
! 536: $ LOG( TWO ) ) + 2
! 537: CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
! 538: $ D( IBEGIN ), E( IBEGIN ), E2( IBEGIN ),
! 539: $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,
! 540: $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
! 541: IF( IINFO .NE. 0 ) THEN
! 542: INFO = IINFO
! 543: RETURN
! 544: END IF
! 545: *
! 546: * Copy eigenvalues into W and IBLOCK
! 547: * Use -JBLK for block number for unconverged eigenvalues.
! 548: * Loop over the number of output intervals from DLAEBZ
! 549: DO 60 J = 1, IOUT
! 550: * eigenvalue approximation is middle point of interval
! 551: TMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) )
! 552: * semi length of error interval
! 553: TMP2 = HALF*ABS( WORK( J+N )-WORK( J+IN+N ) )
! 554: IF( J.GT.IOUT-IINFO ) THEN
! 555: * Flag non-convergence.
! 556: NCNVRG = .TRUE.
! 557: IB = -JBLK
! 558: ELSE
! 559: IB = JBLK
! 560: END IF
! 561: DO 50 JE = IWORK( J ) + 1 + IWOFF,
! 562: $ IWORK( J+IN ) + IWOFF
! 563: W( JE ) = TMP1
! 564: WERR( JE ) = TMP2
! 565: INDEXW( JE ) = JE - IWOFF
! 566: IBLOCK( JE ) = IB
! 567: 50 CONTINUE
! 568: 60 CONTINUE
! 569: *
! 570: M = M + IM
! 571: END IF
! 572: 70 CONTINUE
! 573:
! 574: * If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
! 575: * If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
! 576: IF( IRANGE.EQ.INDRNG ) THEN
! 577: IDISCL = IL - 1 - NWL
! 578: IDISCU = NWU - IU
! 579: *
! 580: IF( IDISCL.GT.0 ) THEN
! 581: IM = 0
! 582: DO 80 JE = 1, M
! 583: * Remove some of the smallest eigenvalues from the left so that
! 584: * at the end IDISCL =0. Move all eigenvalues up to the left.
! 585: IF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THEN
! 586: IDISCL = IDISCL - 1
! 587: ELSE
! 588: IM = IM + 1
! 589: W( IM ) = W( JE )
! 590: WERR( IM ) = WERR( JE )
! 591: INDEXW( IM ) = INDEXW( JE )
! 592: IBLOCK( IM ) = IBLOCK( JE )
! 593: END IF
! 594: 80 CONTINUE
! 595: M = IM
! 596: END IF
! 597: IF( IDISCU.GT.0 ) THEN
! 598: * Remove some of the largest eigenvalues from the right so that
! 599: * at the end IDISCU =0. Move all eigenvalues up to the left.
! 600: IM=M+1
! 601: DO 81 JE = M, 1, -1
! 602: IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THEN
! 603: IDISCU = IDISCU - 1
! 604: ELSE
! 605: IM = IM - 1
! 606: W( IM ) = W( JE )
! 607: WERR( IM ) = WERR( JE )
! 608: INDEXW( IM ) = INDEXW( JE )
! 609: IBLOCK( IM ) = IBLOCK( JE )
! 610: END IF
! 611: 81 CONTINUE
! 612: JEE = 0
! 613: DO 82 JE = IM, M
! 614: JEE = JEE + 1
! 615: W( JEE ) = W( JE )
! 616: WERR( JEE ) = WERR( JE )
! 617: INDEXW( JEE ) = INDEXW( JE )
! 618: IBLOCK( JEE ) = IBLOCK( JE )
! 619: 82 CONTINUE
! 620: M = M-IM+1
! 621: END IF
! 622:
! 623: IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
! 624: * Code to deal with effects of bad arithmetic. (If N(w) is
! 625: * monotone non-decreasing, this should never happen.)
! 626: * Some low eigenvalues to be discarded are not in (WL,WLU],
! 627: * or high eigenvalues to be discarded are not in (WUL,WU]
! 628: * so just kill off the smallest IDISCL/largest IDISCU
! 629: * eigenvalues, by marking the corresponding IBLOCK = 0
! 630: IF( IDISCL.GT.0 ) THEN
! 631: WKILL = WU
! 632: DO 100 JDISC = 1, IDISCL
! 633: IW = 0
! 634: DO 90 JE = 1, M
! 635: IF( IBLOCK( JE ).NE.0 .AND.
! 636: $ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THEN
! 637: IW = JE
! 638: WKILL = W( JE )
! 639: END IF
! 640: 90 CONTINUE
! 641: IBLOCK( IW ) = 0
! 642: 100 CONTINUE
! 643: END IF
! 644: IF( IDISCU.GT.0 ) THEN
! 645: WKILL = WL
! 646: DO 120 JDISC = 1, IDISCU
! 647: IW = 0
! 648: DO 110 JE = 1, M
! 649: IF( IBLOCK( JE ).NE.0 .AND.
! 650: $ ( W( JE ).GE.WKILL .OR. IW.EQ.0 ) ) THEN
! 651: IW = JE
! 652: WKILL = W( JE )
! 653: END IF
! 654: 110 CONTINUE
! 655: IBLOCK( IW ) = 0
! 656: 120 CONTINUE
! 657: END IF
! 658: * Now erase all eigenvalues with IBLOCK set to zero
! 659: IM = 0
! 660: DO 130 JE = 1, M
! 661: IF( IBLOCK( JE ).NE.0 ) THEN
! 662: IM = IM + 1
! 663: W( IM ) = W( JE )
! 664: WERR( IM ) = WERR( JE )
! 665: INDEXW( IM ) = INDEXW( JE )
! 666: IBLOCK( IM ) = IBLOCK( JE )
! 667: END IF
! 668: 130 CONTINUE
! 669: M = IM
! 670: END IF
! 671: IF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THEN
! 672: TOOFEW = .TRUE.
! 673: END IF
! 674: END IF
! 675: *
! 676: IF(( IRANGE.EQ.ALLRNG .AND. M.NE.N ).OR.
! 677: $ ( IRANGE.EQ.INDRNG .AND. M.NE.IU-IL+1 ) ) THEN
! 678: TOOFEW = .TRUE.
! 679: END IF
! 680:
! 681: * If ORDER='B', do nothing the eigenvalues are already sorted by
! 682: * block.
! 683: * If ORDER='E', sort the eigenvalues from smallest to largest
! 684:
! 685: IF( LSAME(ORDER,'E') .AND. NSPLIT.GT.1 ) THEN
! 686: DO 150 JE = 1, M - 1
! 687: IE = 0
! 688: TMP1 = W( JE )
! 689: DO 140 J = JE + 1, M
! 690: IF( W( J ).LT.TMP1 ) THEN
! 691: IE = J
! 692: TMP1 = W( J )
! 693: END IF
! 694: 140 CONTINUE
! 695: IF( IE.NE.0 ) THEN
! 696: TMP2 = WERR( IE )
! 697: ITMP1 = IBLOCK( IE )
! 698: ITMP2 = INDEXW( IE )
! 699: W( IE ) = W( JE )
! 700: WERR( IE ) = WERR( JE )
! 701: IBLOCK( IE ) = IBLOCK( JE )
! 702: INDEXW( IE ) = INDEXW( JE )
! 703: W( JE ) = TMP1
! 704: WERR( JE ) = TMP2
! 705: IBLOCK( JE ) = ITMP1
! 706: INDEXW( JE ) = ITMP2
! 707: END IF
! 708: 150 CONTINUE
! 709: END IF
! 710: *
! 711: INFO = 0
! 712: IF( NCNVRG )
! 713: $ INFO = INFO + 1
! 714: IF( TOOFEW )
! 715: $ INFO = INFO + 2
! 716: RETURN
! 717: *
! 718: * End of DLARRD
! 719: *
! 720: END
CVSweb interface <joel.bertrand@systella.fr>