Annotation of rpl/lapack/lapack/dsterf.f, revision 1.1
1.1 ! bertrand 1: SUBROUTINE DSTERF( N, D, E, INFO )
! 2: *
! 3: * -- LAPACK routine (version 3.2) --
! 4: * -- LAPACK is a software package provided by Univ. of Tennessee, --
! 5: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! 6: * November 2006
! 7: *
! 8: * .. Scalar Arguments ..
! 9: INTEGER INFO, N
! 10: * ..
! 11: * .. Array Arguments ..
! 12: DOUBLE PRECISION D( * ), E( * )
! 13: * ..
! 14: *
! 15: * Purpose
! 16: * =======
! 17: *
! 18: * DSTERF computes all eigenvalues of a symmetric tridiagonal matrix
! 19: * using the Pal-Walker-Kahan variant of the QL or QR algorithm.
! 20: *
! 21: * Arguments
! 22: * =========
! 23: *
! 24: * N (input) INTEGER
! 25: * The order of the matrix. N >= 0.
! 26: *
! 27: * D (input/output) DOUBLE PRECISION array, dimension (N)
! 28: * On entry, the n diagonal elements of the tridiagonal matrix.
! 29: * On exit, if INFO = 0, the eigenvalues in ascending order.
! 30: *
! 31: * E (input/output) DOUBLE PRECISION array, dimension (N-1)
! 32: * On entry, the (n-1) subdiagonal elements of the tridiagonal
! 33: * matrix.
! 34: * On exit, E has been destroyed.
! 35: *
! 36: * INFO (output) INTEGER
! 37: * = 0: successful exit
! 38: * < 0: if INFO = -i, the i-th argument had an illegal value
! 39: * > 0: the algorithm failed to find all of the eigenvalues in
! 40: * a total of 30*N iterations; if INFO = i, then i
! 41: * elements of E have not converged to zero.
! 42: *
! 43: * =====================================================================
! 44: *
! 45: * .. Parameters ..
! 46: DOUBLE PRECISION ZERO, ONE, TWO, THREE
! 47: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
! 48: $ THREE = 3.0D0 )
! 49: INTEGER MAXIT
! 50: PARAMETER ( MAXIT = 30 )
! 51: * ..
! 52: * .. Local Scalars ..
! 53: INTEGER I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M,
! 54: $ NMAXIT
! 55: DOUBLE PRECISION ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC,
! 56: $ OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN,
! 57: $ SIGMA, SSFMAX, SSFMIN
! 58: * ..
! 59: * .. External Functions ..
! 60: DOUBLE PRECISION DLAMCH, DLANST, DLAPY2
! 61: EXTERNAL DLAMCH, DLANST, DLAPY2
! 62: * ..
! 63: * .. External Subroutines ..
! 64: EXTERNAL DLAE2, DLASCL, DLASRT, XERBLA
! 65: * ..
! 66: * .. Intrinsic Functions ..
! 67: INTRINSIC ABS, SIGN, SQRT
! 68: * ..
! 69: * .. Executable Statements ..
! 70: *
! 71: * Test the input parameters.
! 72: *
! 73: INFO = 0
! 74: *
! 75: * Quick return if possible
! 76: *
! 77: IF( N.LT.0 ) THEN
! 78: INFO = -1
! 79: CALL XERBLA( 'DSTERF', -INFO )
! 80: RETURN
! 81: END IF
! 82: IF( N.LE.1 )
! 83: $ RETURN
! 84: *
! 85: * Determine the unit roundoff for this environment.
! 86: *
! 87: EPS = DLAMCH( 'E' )
! 88: EPS2 = EPS**2
! 89: SAFMIN = DLAMCH( 'S' )
! 90: SAFMAX = ONE / SAFMIN
! 91: SSFMAX = SQRT( SAFMAX ) / THREE
! 92: SSFMIN = SQRT( SAFMIN ) / EPS2
! 93: *
! 94: * Compute the eigenvalues of the tridiagonal matrix.
! 95: *
! 96: NMAXIT = N*MAXIT
! 97: SIGMA = ZERO
! 98: JTOT = 0
! 99: *
! 100: * Determine where the matrix splits and choose QL or QR iteration
! 101: * for each block, according to whether top or bottom diagonal
! 102: * element is smaller.
! 103: *
! 104: L1 = 1
! 105: *
! 106: 10 CONTINUE
! 107: IF( L1.GT.N )
! 108: $ GO TO 170
! 109: IF( L1.GT.1 )
! 110: $ E( L1-1 ) = ZERO
! 111: DO 20 M = L1, N - 1
! 112: IF( ABS( E( M ) ).LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+
! 113: $ 1 ) ) ) )*EPS ) THEN
! 114: E( M ) = ZERO
! 115: GO TO 30
! 116: END IF
! 117: 20 CONTINUE
! 118: M = N
! 119: *
! 120: 30 CONTINUE
! 121: L = L1
! 122: LSV = L
! 123: LEND = M
! 124: LENDSV = LEND
! 125: L1 = M + 1
! 126: IF( LEND.EQ.L )
! 127: $ GO TO 10
! 128: *
! 129: * Scale submatrix in rows and columns L to LEND
! 130: *
! 131: ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) )
! 132: ISCALE = 0
! 133: IF( ANORM.GT.SSFMAX ) THEN
! 134: ISCALE = 1
! 135: CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,
! 136: $ INFO )
! 137: CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,
! 138: $ INFO )
! 139: ELSE IF( ANORM.LT.SSFMIN ) THEN
! 140: ISCALE = 2
! 141: CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,
! 142: $ INFO )
! 143: CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,
! 144: $ INFO )
! 145: END IF
! 146: *
! 147: DO 40 I = L, LEND - 1
! 148: E( I ) = E( I )**2
! 149: 40 CONTINUE
! 150: *
! 151: * Choose between QL and QR iteration
! 152: *
! 153: IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN
! 154: LEND = LSV
! 155: L = LENDSV
! 156: END IF
! 157: *
! 158: IF( LEND.GE.L ) THEN
! 159: *
! 160: * QL Iteration
! 161: *
! 162: * Look for small subdiagonal element.
! 163: *
! 164: 50 CONTINUE
! 165: IF( L.NE.LEND ) THEN
! 166: DO 60 M = L, LEND - 1
! 167: IF( ABS( E( M ) ).LE.EPS2*ABS( D( M )*D( M+1 ) ) )
! 168: $ GO TO 70
! 169: 60 CONTINUE
! 170: END IF
! 171: M = LEND
! 172: *
! 173: 70 CONTINUE
! 174: IF( M.LT.LEND )
! 175: $ E( M ) = ZERO
! 176: P = D( L )
! 177: IF( M.EQ.L )
! 178: $ GO TO 90
! 179: *
! 180: * If remaining matrix is 2 by 2, use DLAE2 to compute its
! 181: * eigenvalues.
! 182: *
! 183: IF( M.EQ.L+1 ) THEN
! 184: RTE = SQRT( E( L ) )
! 185: CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 )
! 186: D( L ) = RT1
! 187: D( L+1 ) = RT2
! 188: E( L ) = ZERO
! 189: L = L + 2
! 190: IF( L.LE.LEND )
! 191: $ GO TO 50
! 192: GO TO 150
! 193: END IF
! 194: *
! 195: IF( JTOT.EQ.NMAXIT )
! 196: $ GO TO 150
! 197: JTOT = JTOT + 1
! 198: *
! 199: * Form shift.
! 200: *
! 201: RTE = SQRT( E( L ) )
! 202: SIGMA = ( D( L+1 )-P ) / ( TWO*RTE )
! 203: R = DLAPY2( SIGMA, ONE )
! 204: SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )
! 205: *
! 206: C = ONE
! 207: S = ZERO
! 208: GAMMA = D( M ) - SIGMA
! 209: P = GAMMA*GAMMA
! 210: *
! 211: * Inner loop
! 212: *
! 213: DO 80 I = M - 1, L, -1
! 214: BB = E( I )
! 215: R = P + BB
! 216: IF( I.NE.M-1 )
! 217: $ E( I+1 ) = S*R
! 218: OLDC = C
! 219: C = P / R
! 220: S = BB / R
! 221: OLDGAM = GAMMA
! 222: ALPHA = D( I )
! 223: GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM
! 224: D( I+1 ) = OLDGAM + ( ALPHA-GAMMA )
! 225: IF( C.NE.ZERO ) THEN
! 226: P = ( GAMMA*GAMMA ) / C
! 227: ELSE
! 228: P = OLDC*BB
! 229: END IF
! 230: 80 CONTINUE
! 231: *
! 232: E( L ) = S*P
! 233: D( L ) = SIGMA + GAMMA
! 234: GO TO 50
! 235: *
! 236: * Eigenvalue found.
! 237: *
! 238: 90 CONTINUE
! 239: D( L ) = P
! 240: *
! 241: L = L + 1
! 242: IF( L.LE.LEND )
! 243: $ GO TO 50
! 244: GO TO 150
! 245: *
! 246: ELSE
! 247: *
! 248: * QR Iteration
! 249: *
! 250: * Look for small superdiagonal element.
! 251: *
! 252: 100 CONTINUE
! 253: DO 110 M = L, LEND + 1, -1
! 254: IF( ABS( E( M-1 ) ).LE.EPS2*ABS( D( M )*D( M-1 ) ) )
! 255: $ GO TO 120
! 256: 110 CONTINUE
! 257: M = LEND
! 258: *
! 259: 120 CONTINUE
! 260: IF( M.GT.LEND )
! 261: $ E( M-1 ) = ZERO
! 262: P = D( L )
! 263: IF( M.EQ.L )
! 264: $ GO TO 140
! 265: *
! 266: * If remaining matrix is 2 by 2, use DLAE2 to compute its
! 267: * eigenvalues.
! 268: *
! 269: IF( M.EQ.L-1 ) THEN
! 270: RTE = SQRT( E( L-1 ) )
! 271: CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 )
! 272: D( L ) = RT1
! 273: D( L-1 ) = RT2
! 274: E( L-1 ) = ZERO
! 275: L = L - 2
! 276: IF( L.GE.LEND )
! 277: $ GO TO 100
! 278: GO TO 150
! 279: END IF
! 280: *
! 281: IF( JTOT.EQ.NMAXIT )
! 282: $ GO TO 150
! 283: JTOT = JTOT + 1
! 284: *
! 285: * Form shift.
! 286: *
! 287: RTE = SQRT( E( L-1 ) )
! 288: SIGMA = ( D( L-1 )-P ) / ( TWO*RTE )
! 289: R = DLAPY2( SIGMA, ONE )
! 290: SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )
! 291: *
! 292: C = ONE
! 293: S = ZERO
! 294: GAMMA = D( M ) - SIGMA
! 295: P = GAMMA*GAMMA
! 296: *
! 297: * Inner loop
! 298: *
! 299: DO 130 I = M, L - 1
! 300: BB = E( I )
! 301: R = P + BB
! 302: IF( I.NE.M )
! 303: $ E( I-1 ) = S*R
! 304: OLDC = C
! 305: C = P / R
! 306: S = BB / R
! 307: OLDGAM = GAMMA
! 308: ALPHA = D( I+1 )
! 309: GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM
! 310: D( I ) = OLDGAM + ( ALPHA-GAMMA )
! 311: IF( C.NE.ZERO ) THEN
! 312: P = ( GAMMA*GAMMA ) / C
! 313: ELSE
! 314: P = OLDC*BB
! 315: END IF
! 316: 130 CONTINUE
! 317: *
! 318: E( L-1 ) = S*P
! 319: D( L ) = SIGMA + GAMMA
! 320: GO TO 100
! 321: *
! 322: * Eigenvalue found.
! 323: *
! 324: 140 CONTINUE
! 325: D( L ) = P
! 326: *
! 327: L = L - 1
! 328: IF( L.GE.LEND )
! 329: $ GO TO 100
! 330: GO TO 150
! 331: *
! 332: END IF
! 333: *
! 334: * Undo scaling if necessary
! 335: *
! 336: 150 CONTINUE
! 337: IF( ISCALE.EQ.1 )
! 338: $ CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,
! 339: $ D( LSV ), N, INFO )
! 340: IF( ISCALE.EQ.2 )
! 341: $ CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,
! 342: $ D( LSV ), N, INFO )
! 343: *
! 344: * Check for no convergence to an eigenvalue after a total
! 345: * of N*MAXIT iterations.
! 346: *
! 347: IF( JTOT.LT.NMAXIT )
! 348: $ GO TO 10
! 349: DO 160 I = 1, N - 1
! 350: IF( E( I ).NE.ZERO )
! 351: $ INFO = INFO + 1
! 352: 160 CONTINUE
! 353: GO TO 180
! 354: *
! 355: * Sort eigenvalues in increasing order.
! 356: *
! 357: 170 CONTINUE
! 358: CALL DLASRT( 'I', N, D, INFO )
! 359: *
! 360: 180 CONTINUE
! 361: RETURN
! 362: *
! 363: * End of DSTERF
! 364: *
! 365: END
CVSweb interface <joel.bertrand@systella.fr>