Annotation of rpl/lapack/lapack/dstemr.f, revision 1.1
1.1 ! bertrand 1: SUBROUTINE DSTEMR( JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
! 2: $ M, W, Z, LDZ, NZC, ISUPPZ, TRYRAC, WORK, LWORK,
! 3: $ IWORK, LIWORK, INFO )
! 4: IMPLICIT NONE
! 5: *
! 6: * -- LAPACK computational 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 JOBZ, RANGE
! 13: LOGICAL TRYRAC
! 14: INTEGER IL, INFO, IU, LDZ, NZC, LIWORK, LWORK, M, N
! 15: DOUBLE PRECISION VL, VU
! 16: * ..
! 17: * .. Array Arguments ..
! 18: INTEGER ISUPPZ( * ), IWORK( * )
! 19: DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )
! 20: DOUBLE PRECISION Z( LDZ, * )
! 21: * ..
! 22: *
! 23: * Purpose
! 24: * =======
! 25: *
! 26: * DSTEMR computes selected eigenvalues and, optionally, eigenvectors
! 27: * of a real symmetric tridiagonal matrix T. Any such unreduced matrix has
! 28: * a well defined set of pairwise different real eigenvalues, the corresponding
! 29: * real eigenvectors are pairwise orthogonal.
! 30: *
! 31: * The spectrum may be computed either completely or partially by specifying
! 32: * either an interval (VL,VU] or a range of indices IL:IU for the desired
! 33: * eigenvalues.
! 34: *
! 35: * Depending on the number of desired eigenvalues, these are computed either
! 36: * by bisection or the dqds algorithm. Numerically orthogonal eigenvectors are
! 37: * computed by the use of various suitable L D L^T factorizations near clusters
! 38: * of close eigenvalues (referred to as RRRs, Relatively Robust
! 39: * Representations). An informal sketch of the algorithm follows.
! 40: *
! 41: * For each unreduced block (submatrix) of T,
! 42: * (a) Compute T - sigma I = L D L^T, so that L and D
! 43: * define all the wanted eigenvalues to high relative accuracy.
! 44: * This means that small relative changes in the entries of D and L
! 45: * cause only small relative changes in the eigenvalues and
! 46: * eigenvectors. The standard (unfactored) representation of the
! 47: * tridiagonal matrix T does not have this property in general.
! 48: * (b) Compute the eigenvalues to suitable accuracy.
! 49: * If the eigenvectors are desired, the algorithm attains full
! 50: * accuracy of the computed eigenvalues only right before
! 51: * the corresponding vectors have to be computed, see steps c) and d).
! 52: * (c) For each cluster of close eigenvalues, select a new
! 53: * shift close to the cluster, find a new factorization, and refine
! 54: * the shifted eigenvalues to suitable accuracy.
! 55: * (d) For each eigenvalue with a large enough relative separation compute
! 56: * the corresponding eigenvector by forming a rank revealing twisted
! 57: * factorization. Go back to (c) for any clusters that remain.
! 58: *
! 59: * For more details, see:
! 60: * - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations
! 61: * to compute orthogonal eigenvectors of symmetric tridiagonal matrices,"
! 62: * Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004.
! 63: * - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and
! 64: * Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25,
! 65: * 2004. Also LAPACK Working Note 154.
! 66: * - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric
! 67: * tridiagonal eigenvalue/eigenvector problem",
! 68: * Computer Science Division Technical Report No. UCB/CSD-97-971,
! 69: * UC Berkeley, May 1997.
! 70: *
! 71: * Further Details
! 72: * 1.DSTEMR works only on machines which follow IEEE-754
! 73: * floating-point standard in their handling of infinities and NaNs.
! 74: * This permits the use of efficient inner loops avoiding a check for
! 75: * zero divisors.
! 76: *
! 77: * Arguments
! 78: * =========
! 79: *
! 80: * JOBZ (input) CHARACTER*1
! 81: * = 'N': Compute eigenvalues only;
! 82: * = 'V': Compute eigenvalues and eigenvectors.
! 83: *
! 84: * RANGE (input) CHARACTER*1
! 85: * = 'A': all eigenvalues will be found.
! 86: * = 'V': all eigenvalues in the half-open interval (VL,VU]
! 87: * will be found.
! 88: * = 'I': the IL-th through IU-th eigenvalues will be found.
! 89: *
! 90: * N (input) INTEGER
! 91: * The order of the matrix. N >= 0.
! 92: *
! 93: * D (input/output) DOUBLE PRECISION array, dimension (N)
! 94: * On entry, the N diagonal elements of the tridiagonal matrix
! 95: * T. On exit, D is overwritten.
! 96: *
! 97: * E (input/output) DOUBLE PRECISION array, dimension (N)
! 98: * On entry, the (N-1) subdiagonal elements of the tridiagonal
! 99: * matrix T in elements 1 to N-1 of E. E(N) need not be set on
! 100: * input, but is used internally as workspace.
! 101: * On exit, E is overwritten.
! 102: *
! 103: * VL (input) DOUBLE PRECISION
! 104: * VU (input) DOUBLE PRECISION
! 105: * If RANGE='V', the lower and upper bounds of the interval to
! 106: * be searched for eigenvalues. VL < VU.
! 107: * Not referenced if RANGE = 'A' or 'I'.
! 108: *
! 109: * IL (input) INTEGER
! 110: * IU (input) INTEGER
! 111: * If RANGE='I', the indices (in ascending order) of the
! 112: * smallest and largest eigenvalues to be returned.
! 113: * 1 <= IL <= IU <= N, if N > 0.
! 114: * Not referenced if RANGE = 'A' or 'V'.
! 115: *
! 116: * M (output) INTEGER
! 117: * The total number of eigenvalues found. 0 <= M <= N.
! 118: * If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
! 119: *
! 120: * W (output) DOUBLE PRECISION array, dimension (N)
! 121: * The first M elements contain the selected eigenvalues in
! 122: * ascending order.
! 123: *
! 124: * Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) )
! 125: * If JOBZ = 'V', and if INFO = 0, then the first M columns of Z
! 126: * contain the orthonormal eigenvectors of the matrix T
! 127: * corresponding to the selected eigenvalues, with the i-th
! 128: * column of Z holding the eigenvector associated with W(i).
! 129: * If JOBZ = 'N', then Z is not referenced.
! 130: * Note: the user must ensure that at least max(1,M) columns are
! 131: * supplied in the array Z; if RANGE = 'V', the exact value of M
! 132: * is not known in advance and can be computed with a workspace
! 133: * query by setting NZC = -1, see below.
! 134: *
! 135: * LDZ (input) INTEGER
! 136: * The leading dimension of the array Z. LDZ >= 1, and if
! 137: * JOBZ = 'V', then LDZ >= max(1,N).
! 138: *
! 139: * NZC (input) INTEGER
! 140: * The number of eigenvectors to be held in the array Z.
! 141: * If RANGE = 'A', then NZC >= max(1,N).
! 142: * If RANGE = 'V', then NZC >= the number of eigenvalues in (VL,VU].
! 143: * If RANGE = 'I', then NZC >= IU-IL+1.
! 144: * If NZC = -1, then a workspace query is assumed; the
! 145: * routine calculates the number of columns of the array Z that
! 146: * are needed to hold the eigenvectors.
! 147: * This value is returned as the first entry of the Z array, and
! 148: * no error message related to NZC is issued by XERBLA.
! 149: *
! 150: * ISUPPZ (output) INTEGER ARRAY, dimension ( 2*max(1,M) )
! 151: * The support of the eigenvectors in Z, i.e., the indices
! 152: * indicating the nonzero elements in Z. The i-th computed eigenvector
! 153: * is nonzero only in elements ISUPPZ( 2*i-1 ) through
! 154: * ISUPPZ( 2*i ). This is relevant in the case when the matrix
! 155: * is split. ISUPPZ is only accessed when JOBZ is 'V' and N > 0.
! 156: *
! 157: * TRYRAC (input/output) LOGICAL
! 158: * If TRYRAC.EQ..TRUE., indicates that the code should check whether
! 159: * the tridiagonal matrix defines its eigenvalues to high relative
! 160: * accuracy. If so, the code uses relative-accuracy preserving
! 161: * algorithms that might be (a bit) slower depending on the matrix.
! 162: * If the matrix does not define its eigenvalues to high relative
! 163: * accuracy, the code can uses possibly faster algorithms.
! 164: * If TRYRAC.EQ..FALSE., the code is not required to guarantee
! 165: * relatively accurate eigenvalues and can use the fastest possible
! 166: * techniques.
! 167: * On exit, a .TRUE. TRYRAC will be set to .FALSE. if the matrix
! 168: * does not define its eigenvalues to high relative accuracy.
! 169: *
! 170: * WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)
! 171: * On exit, if INFO = 0, WORK(1) returns the optimal
! 172: * (and minimal) LWORK.
! 173: *
! 174: * LWORK (input) INTEGER
! 175: * The dimension of the array WORK. LWORK >= max(1,18*N)
! 176: * if JOBZ = 'V', and LWORK >= max(1,12*N) if JOBZ = 'N'.
! 177: * If LWORK = -1, then a workspace query is assumed; the routine
! 178: * only calculates the optimal size of the WORK array, returns
! 179: * this value as the first entry of the WORK array, and no error
! 180: * message related to LWORK is issued by XERBLA.
! 181: *
! 182: * IWORK (workspace/output) INTEGER array, dimension (LIWORK)
! 183: * On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
! 184: *
! 185: * LIWORK (input) INTEGER
! 186: * The dimension of the array IWORK. LIWORK >= max(1,10*N)
! 187: * if the eigenvectors are desired, and LIWORK >= max(1,8*N)
! 188: * if only the eigenvalues are to be computed.
! 189: * If LIWORK = -1, then a workspace query is assumed; the
! 190: * routine only calculates the optimal size of the IWORK array,
! 191: * returns this value as the first entry of the IWORK array, and
! 192: * no error message related to LIWORK is issued by XERBLA.
! 193: *
! 194: * INFO (output) INTEGER
! 195: * On exit, INFO
! 196: * = 0: successful exit
! 197: * < 0: if INFO = -i, the i-th argument had an illegal value
! 198: * > 0: if INFO = 1X, internal error in DLARRE,
! 199: * if INFO = 2X, internal error in DLARRV.
! 200: * Here, the digit X = ABS( IINFO ) < 10, where IINFO is
! 201: * the nonzero error code returned by DLARRE or
! 202: * DLARRV, respectively.
! 203: *
! 204: *
! 205: * Further Details
! 206: * ===============
! 207: *
! 208: * Based on contributions by
! 209: * Beresford Parlett, University of California, Berkeley, USA
! 210: * Jim Demmel, University of California, Berkeley, USA
! 211: * Inderjit Dhillon, University of Texas, Austin, USA
! 212: * Osni Marques, LBNL/NERSC, USA
! 213: * Christof Voemel, University of California, Berkeley, USA
! 214: *
! 215: * =====================================================================
! 216: *
! 217: * .. Parameters ..
! 218: DOUBLE PRECISION ZERO, ONE, FOUR, MINRGP
! 219: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0,
! 220: $ FOUR = 4.0D0,
! 221: $ MINRGP = 1.0D-3 )
! 222: * ..
! 223: * .. Local Scalars ..
! 224: LOGICAL ALLEIG, INDEIG, LQUERY, VALEIG, WANTZ, ZQUERY
! 225: INTEGER I, IBEGIN, IEND, IFIRST, IIL, IINDBL, IINDW,
! 226: $ IINDWK, IINFO, IINSPL, IIU, ILAST, IN, INDD,
! 227: $ INDE2, INDERR, INDGP, INDGRS, INDWRK, ITMP,
! 228: $ ITMP2, J, JBLK, JJ, LIWMIN, LWMIN, NSPLIT,
! 229: $ NZCMIN, OFFSET, WBEGIN, WEND
! 230: DOUBLE PRECISION BIGNUM, CS, EPS, PIVMIN, R1, R2, RMAX, RMIN,
! 231: $ RTOL1, RTOL2, SAFMIN, SCALE, SMLNUM, SN,
! 232: $ THRESH, TMP, TNRM, WL, WU
! 233: * ..
! 234: * ..
! 235: * .. External Functions ..
! 236: LOGICAL LSAME
! 237: DOUBLE PRECISION DLAMCH, DLANST
! 238: EXTERNAL LSAME, DLAMCH, DLANST
! 239: * ..
! 240: * .. External Subroutines ..
! 241: EXTERNAL DCOPY, DLAE2, DLAEV2, DLARRC, DLARRE, DLARRJ,
! 242: $ DLARRR, DLARRV, DLASRT, DSCAL, DSWAP, XERBLA
! 243: * ..
! 244: * .. Intrinsic Functions ..
! 245: INTRINSIC MAX, MIN, SQRT
! 246:
! 247:
! 248: * ..
! 249: * .. Executable Statements ..
! 250: *
! 251: * Test the input parameters.
! 252: *
! 253: WANTZ = LSAME( JOBZ, 'V' )
! 254: ALLEIG = LSAME( RANGE, 'A' )
! 255: VALEIG = LSAME( RANGE, 'V' )
! 256: INDEIG = LSAME( RANGE, 'I' )
! 257: *
! 258: LQUERY = ( ( LWORK.EQ.-1 ).OR.( LIWORK.EQ.-1 ) )
! 259: ZQUERY = ( NZC.EQ.-1 )
! 260:
! 261: * DSTEMR needs WORK of size 6*N, IWORK of size 3*N.
! 262: * In addition, DLARRE needs WORK of size 6*N, IWORK of size 5*N.
! 263: * Furthermore, DLARRV needs WORK of size 12*N, IWORK of size 7*N.
! 264: IF( WANTZ ) THEN
! 265: LWMIN = 18*N
! 266: LIWMIN = 10*N
! 267: ELSE
! 268: * need less workspace if only the eigenvalues are wanted
! 269: LWMIN = 12*N
! 270: LIWMIN = 8*N
! 271: ENDIF
! 272:
! 273: WL = ZERO
! 274: WU = ZERO
! 275: IIL = 0
! 276: IIU = 0
! 277:
! 278: IF( VALEIG ) THEN
! 279: * We do not reference VL, VU in the cases RANGE = 'I','A'
! 280: * The interval (WL, WU] contains all the wanted eigenvalues.
! 281: * It is either given by the user or computed in DLARRE.
! 282: WL = VL
! 283: WU = VU
! 284: ELSEIF( INDEIG ) THEN
! 285: * We do not reference IL, IU in the cases RANGE = 'V','A'
! 286: IIL = IL
! 287: IIU = IU
! 288: ENDIF
! 289: *
! 290: INFO = 0
! 291: IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
! 292: INFO = -1
! 293: ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THEN
! 294: INFO = -2
! 295: ELSE IF( N.LT.0 ) THEN
! 296: INFO = -3
! 297: ELSE IF( VALEIG .AND. N.GT.0 .AND. WU.LE.WL ) THEN
! 298: INFO = -7
! 299: ELSE IF( INDEIG .AND. ( IIL.LT.1 .OR. IIL.GT.N ) ) THEN
! 300: INFO = -8
! 301: ELSE IF( INDEIG .AND. ( IIU.LT.IIL .OR. IIU.GT.N ) ) THEN
! 302: INFO = -9
! 303: ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN
! 304: INFO = -13
! 305: ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
! 306: INFO = -17
! 307: ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
! 308: INFO = -19
! 309: END IF
! 310: *
! 311: * Get machine constants.
! 312: *
! 313: SAFMIN = DLAMCH( 'Safe minimum' )
! 314: EPS = DLAMCH( 'Precision' )
! 315: SMLNUM = SAFMIN / EPS
! 316: BIGNUM = ONE / SMLNUM
! 317: RMIN = SQRT( SMLNUM )
! 318: RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )
! 319: *
! 320: IF( INFO.EQ.0 ) THEN
! 321: WORK( 1 ) = LWMIN
! 322: IWORK( 1 ) = LIWMIN
! 323: *
! 324: IF( WANTZ .AND. ALLEIG ) THEN
! 325: NZCMIN = N
! 326: ELSE IF( WANTZ .AND. VALEIG ) THEN
! 327: CALL DLARRC( 'T', N, VL, VU, D, E, SAFMIN,
! 328: $ NZCMIN, ITMP, ITMP2, INFO )
! 329: ELSE IF( WANTZ .AND. INDEIG ) THEN
! 330: NZCMIN = IIU-IIL+1
! 331: ELSE
! 332: * WANTZ .EQ. FALSE.
! 333: NZCMIN = 0
! 334: ENDIF
! 335: IF( ZQUERY .AND. INFO.EQ.0 ) THEN
! 336: Z( 1,1 ) = NZCMIN
! 337: ELSE IF( NZC.LT.NZCMIN .AND. .NOT.ZQUERY ) THEN
! 338: INFO = -14
! 339: END IF
! 340: END IF
! 341:
! 342: IF( INFO.NE.0 ) THEN
! 343: *
! 344: CALL XERBLA( 'DSTEMR', -INFO )
! 345: *
! 346: RETURN
! 347: ELSE IF( LQUERY .OR. ZQUERY ) THEN
! 348: RETURN
! 349: END IF
! 350: *
! 351: * Handle N = 0, 1, and 2 cases immediately
! 352: *
! 353: M = 0
! 354: IF( N.EQ.0 )
! 355: $ RETURN
! 356: *
! 357: IF( N.EQ.1 ) THEN
! 358: IF( ALLEIG .OR. INDEIG ) THEN
! 359: M = 1
! 360: W( 1 ) = D( 1 )
! 361: ELSE
! 362: IF( WL.LT.D( 1 ) .AND. WU.GE.D( 1 ) ) THEN
! 363: M = 1
! 364: W( 1 ) = D( 1 )
! 365: END IF
! 366: END IF
! 367: IF( WANTZ.AND.(.NOT.ZQUERY) ) THEN
! 368: Z( 1, 1 ) = ONE
! 369: ISUPPZ(1) = 1
! 370: ISUPPZ(2) = 1
! 371: END IF
! 372: RETURN
! 373: END IF
! 374: *
! 375: IF( N.EQ.2 ) THEN
! 376: IF( .NOT.WANTZ ) THEN
! 377: CALL DLAE2( D(1), E(1), D(2), R1, R2 )
! 378: ELSE IF( WANTZ.AND.(.NOT.ZQUERY) ) THEN
! 379: CALL DLAEV2( D(1), E(1), D(2), R1, R2, CS, SN )
! 380: END IF
! 381: IF( ALLEIG.OR.
! 382: $ (VALEIG.AND.(R2.GT.WL).AND.
! 383: $ (R2.LE.WU)).OR.
! 384: $ (INDEIG.AND.(IIL.EQ.1)) ) THEN
! 385: M = M+1
! 386: W( M ) = R2
! 387: IF( WANTZ.AND.(.NOT.ZQUERY) ) THEN
! 388: Z( 1, M ) = -SN
! 389: Z( 2, M ) = CS
! 390: * Note: At most one of SN and CS can be zero.
! 391: IF (SN.NE.ZERO) THEN
! 392: IF (CS.NE.ZERO) THEN
! 393: ISUPPZ(2*M-1) = 1
! 394: ISUPPZ(2*M-1) = 2
! 395: ELSE
! 396: ISUPPZ(2*M-1) = 1
! 397: ISUPPZ(2*M-1) = 1
! 398: END IF
! 399: ELSE
! 400: ISUPPZ(2*M-1) = 2
! 401: ISUPPZ(2*M) = 2
! 402: END IF
! 403: ENDIF
! 404: ENDIF
! 405: IF( ALLEIG.OR.
! 406: $ (VALEIG.AND.(R1.GT.WL).AND.
! 407: $ (R1.LE.WU)).OR.
! 408: $ (INDEIG.AND.(IIU.EQ.2)) ) THEN
! 409: M = M+1
! 410: W( M ) = R1
! 411: IF( WANTZ.AND.(.NOT.ZQUERY) ) THEN
! 412: Z( 1, M ) = CS
! 413: Z( 2, M ) = SN
! 414: * Note: At most one of SN and CS can be zero.
! 415: IF (SN.NE.ZERO) THEN
! 416: IF (CS.NE.ZERO) THEN
! 417: ISUPPZ(2*M-1) = 1
! 418: ISUPPZ(2*M-1) = 2
! 419: ELSE
! 420: ISUPPZ(2*M-1) = 1
! 421: ISUPPZ(2*M-1) = 1
! 422: END IF
! 423: ELSE
! 424: ISUPPZ(2*M-1) = 2
! 425: ISUPPZ(2*M) = 2
! 426: END IF
! 427: ENDIF
! 428: ENDIF
! 429: RETURN
! 430: END IF
! 431:
! 432: * Continue with general N
! 433:
! 434: INDGRS = 1
! 435: INDERR = 2*N + 1
! 436: INDGP = 3*N + 1
! 437: INDD = 4*N + 1
! 438: INDE2 = 5*N + 1
! 439: INDWRK = 6*N + 1
! 440: *
! 441: IINSPL = 1
! 442: IINDBL = N + 1
! 443: IINDW = 2*N + 1
! 444: IINDWK = 3*N + 1
! 445: *
! 446: * Scale matrix to allowable range, if necessary.
! 447: * The allowable range is related to the PIVMIN parameter; see the
! 448: * comments in DLARRD. The preference for scaling small values
! 449: * up is heuristic; we expect users' matrices not to be close to the
! 450: * RMAX threshold.
! 451: *
! 452: SCALE = ONE
! 453: TNRM = DLANST( 'M', N, D, E )
! 454: IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THEN
! 455: SCALE = RMIN / TNRM
! 456: ELSE IF( TNRM.GT.RMAX ) THEN
! 457: SCALE = RMAX / TNRM
! 458: END IF
! 459: IF( SCALE.NE.ONE ) THEN
! 460: CALL DSCAL( N, SCALE, D, 1 )
! 461: CALL DSCAL( N-1, SCALE, E, 1 )
! 462: TNRM = TNRM*SCALE
! 463: IF( VALEIG ) THEN
! 464: * If eigenvalues in interval have to be found,
! 465: * scale (WL, WU] accordingly
! 466: WL = WL*SCALE
! 467: WU = WU*SCALE
! 468: ENDIF
! 469: END IF
! 470: *
! 471: * Compute the desired eigenvalues of the tridiagonal after splitting
! 472: * into smaller subblocks if the corresponding off-diagonal elements
! 473: * are small
! 474: * THRESH is the splitting parameter for DLARRE
! 475: * A negative THRESH forces the old splitting criterion based on the
! 476: * size of the off-diagonal. A positive THRESH switches to splitting
! 477: * which preserves relative accuracy.
! 478: *
! 479: IF( TRYRAC ) THEN
! 480: * Test whether the matrix warrants the more expensive relative approach.
! 481: CALL DLARRR( N, D, E, IINFO )
! 482: ELSE
! 483: * The user does not care about relative accurately eigenvalues
! 484: IINFO = -1
! 485: ENDIF
! 486: * Set the splitting criterion
! 487: IF (IINFO.EQ.0) THEN
! 488: THRESH = EPS
! 489: ELSE
! 490: THRESH = -EPS
! 491: * relative accuracy is desired but T does not guarantee it
! 492: TRYRAC = .FALSE.
! 493: ENDIF
! 494: *
! 495: IF( TRYRAC ) THEN
! 496: * Copy original diagonal, needed to guarantee relative accuracy
! 497: CALL DCOPY(N,D,1,WORK(INDD),1)
! 498: ENDIF
! 499: * Store the squares of the offdiagonal values of T
! 500: DO 5 J = 1, N-1
! 501: WORK( INDE2+J-1 ) = E(J)**2
! 502: 5 CONTINUE
! 503:
! 504: * Set the tolerance parameters for bisection
! 505: IF( .NOT.WANTZ ) THEN
! 506: * DLARRE computes the eigenvalues to full precision.
! 507: RTOL1 = FOUR * EPS
! 508: RTOL2 = FOUR * EPS
! 509: ELSE
! 510: * DLARRE computes the eigenvalues to less than full precision.
! 511: * DLARRV will refine the eigenvalue approximations, and we can
! 512: * need less accurate initial bisection in DLARRE.
! 513: * Note: these settings do only affect the subset case and DLARRE
! 514: RTOL1 = SQRT(EPS)
! 515: RTOL2 = MAX( SQRT(EPS)*5.0D-3, FOUR * EPS )
! 516: ENDIF
! 517: CALL DLARRE( RANGE, N, WL, WU, IIL, IIU, D, E,
! 518: $ WORK(INDE2), RTOL1, RTOL2, THRESH, NSPLIT,
! 519: $ IWORK( IINSPL ), M, W, WORK( INDERR ),
! 520: $ WORK( INDGP ), IWORK( IINDBL ),
! 521: $ IWORK( IINDW ), WORK( INDGRS ), PIVMIN,
! 522: $ WORK( INDWRK ), IWORK( IINDWK ), IINFO )
! 523: IF( IINFO.NE.0 ) THEN
! 524: INFO = 10 + ABS( IINFO )
! 525: RETURN
! 526: END IF
! 527: * Note that if RANGE .NE. 'V', DLARRE computes bounds on the desired
! 528: * part of the spectrum. All desired eigenvalues are contained in
! 529: * (WL,WU]
! 530:
! 531:
! 532: IF( WANTZ ) THEN
! 533: *
! 534: * Compute the desired eigenvectors corresponding to the computed
! 535: * eigenvalues
! 536: *
! 537: CALL DLARRV( N, WL, WU, D, E,
! 538: $ PIVMIN, IWORK( IINSPL ), M,
! 539: $ 1, M, MINRGP, RTOL1, RTOL2,
! 540: $ W, WORK( INDERR ), WORK( INDGP ), IWORK( IINDBL ),
! 541: $ IWORK( IINDW ), WORK( INDGRS ), Z, LDZ,
! 542: $ ISUPPZ, WORK( INDWRK ), IWORK( IINDWK ), IINFO )
! 543: IF( IINFO.NE.0 ) THEN
! 544: INFO = 20 + ABS( IINFO )
! 545: RETURN
! 546: END IF
! 547: ELSE
! 548: * DLARRE computes eigenvalues of the (shifted) root representation
! 549: * DLARRV returns the eigenvalues of the unshifted matrix.
! 550: * However, if the eigenvectors are not desired by the user, we need
! 551: * to apply the corresponding shifts from DLARRE to obtain the
! 552: * eigenvalues of the original matrix.
! 553: DO 20 J = 1, M
! 554: ITMP = IWORK( IINDBL+J-1 )
! 555: W( J ) = W( J ) + E( IWORK( IINSPL+ITMP-1 ) )
! 556: 20 CONTINUE
! 557: END IF
! 558: *
! 559:
! 560: IF ( TRYRAC ) THEN
! 561: * Refine computed eigenvalues so that they are relatively accurate
! 562: * with respect to the original matrix T.
! 563: IBEGIN = 1
! 564: WBEGIN = 1
! 565: DO 39 JBLK = 1, IWORK( IINDBL+M-1 )
! 566: IEND = IWORK( IINSPL+JBLK-1 )
! 567: IN = IEND - IBEGIN + 1
! 568: WEND = WBEGIN - 1
! 569: * check if any eigenvalues have to be refined in this block
! 570: 36 CONTINUE
! 571: IF( WEND.LT.M ) THEN
! 572: IF( IWORK( IINDBL+WEND ).EQ.JBLK ) THEN
! 573: WEND = WEND + 1
! 574: GO TO 36
! 575: END IF
! 576: END IF
! 577: IF( WEND.LT.WBEGIN ) THEN
! 578: IBEGIN = IEND + 1
! 579: GO TO 39
! 580: END IF
! 581:
! 582: OFFSET = IWORK(IINDW+WBEGIN-1)-1
! 583: IFIRST = IWORK(IINDW+WBEGIN-1)
! 584: ILAST = IWORK(IINDW+WEND-1)
! 585: RTOL2 = FOUR * EPS
! 586: CALL DLARRJ( IN,
! 587: $ WORK(INDD+IBEGIN-1), WORK(INDE2+IBEGIN-1),
! 588: $ IFIRST, ILAST, RTOL2, OFFSET, W(WBEGIN),
! 589: $ WORK( INDERR+WBEGIN-1 ),
! 590: $ WORK( INDWRK ), IWORK( IINDWK ), PIVMIN,
! 591: $ TNRM, IINFO )
! 592: IBEGIN = IEND + 1
! 593: WBEGIN = WEND + 1
! 594: 39 CONTINUE
! 595: ENDIF
! 596: *
! 597: * If matrix was scaled, then rescale eigenvalues appropriately.
! 598: *
! 599: IF( SCALE.NE.ONE ) THEN
! 600: CALL DSCAL( M, ONE / SCALE, W, 1 )
! 601: END IF
! 602: *
! 603: * If eigenvalues are not in increasing order, then sort them,
! 604: * possibly along with eigenvectors.
! 605: *
! 606: IF( NSPLIT.GT.1 ) THEN
! 607: IF( .NOT. WANTZ ) THEN
! 608: CALL DLASRT( 'I', M, W, IINFO )
! 609: IF( IINFO.NE.0 ) THEN
! 610: INFO = 3
! 611: RETURN
! 612: END IF
! 613: ELSE
! 614: DO 60 J = 1, M - 1
! 615: I = 0
! 616: TMP = W( J )
! 617: DO 50 JJ = J + 1, M
! 618: IF( W( JJ ).LT.TMP ) THEN
! 619: I = JJ
! 620: TMP = W( JJ )
! 621: END IF
! 622: 50 CONTINUE
! 623: IF( I.NE.0 ) THEN
! 624: W( I ) = W( J )
! 625: W( J ) = TMP
! 626: IF( WANTZ ) THEN
! 627: CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )
! 628: ITMP = ISUPPZ( 2*I-1 )
! 629: ISUPPZ( 2*I-1 ) = ISUPPZ( 2*J-1 )
! 630: ISUPPZ( 2*J-1 ) = ITMP
! 631: ITMP = ISUPPZ( 2*I )
! 632: ISUPPZ( 2*I ) = ISUPPZ( 2*J )
! 633: ISUPPZ( 2*J ) = ITMP
! 634: END IF
! 635: END IF
! 636: 60 CONTINUE
! 637: END IF
! 638: ENDIF
! 639: *
! 640: *
! 641: WORK( 1 ) = LWMIN
! 642: IWORK( 1 ) = LIWMIN
! 643: RETURN
! 644: *
! 645: * End of DSTEMR
! 646: *
! 647: END
CVSweb interface <joel.bertrand@systella.fr>