Annotation of rpl/lapack/lapack/dstevx.f, revision 1.5
1.1 bertrand 1: SUBROUTINE DSTEVX( JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL,
2: $ M, W, Z, LDZ, WORK, IWORK, IFAIL, INFO )
3: *
4: * -- LAPACK driver routine (version 3.2) --
5: * -- LAPACK is a software package provided by Univ. of Tennessee, --
6: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
7: * November 2006
8: *
9: * .. Scalar Arguments ..
10: CHARACTER JOBZ, RANGE
11: INTEGER IL, INFO, IU, LDZ, M, N
12: DOUBLE PRECISION ABSTOL, VL, VU
13: * ..
14: * .. Array Arguments ..
15: INTEGER IFAIL( * ), IWORK( * )
16: DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )
17: * ..
18: *
19: * Purpose
20: * =======
21: *
22: * DSTEVX computes selected eigenvalues and, optionally, eigenvectors
23: * of a real symmetric tridiagonal matrix A. Eigenvalues and
24: * eigenvectors can be selected by specifying either a range of values
25: * or a range of indices for the desired eigenvalues.
26: *
27: * Arguments
28: * =========
29: *
30: * JOBZ (input) CHARACTER*1
31: * = 'N': Compute eigenvalues only;
32: * = 'V': Compute eigenvalues and eigenvectors.
33: *
34: * RANGE (input) CHARACTER*1
35: * = 'A': all eigenvalues will be found.
36: * = 'V': all eigenvalues in the half-open interval (VL,VU]
37: * will be found.
38: * = 'I': the IL-th through IU-th eigenvalues will be found.
39: *
40: * N (input) INTEGER
41: * The order of the matrix. N >= 0.
42: *
43: * D (input/output) DOUBLE PRECISION array, dimension (N)
44: * On entry, the n diagonal elements of the tridiagonal matrix
45: * A.
46: * On exit, D may be multiplied by a constant factor chosen
47: * to avoid over/underflow in computing the eigenvalues.
48: *
49: * E (input/output) DOUBLE PRECISION array, dimension (max(1,N-1))
50: * On entry, the (n-1) subdiagonal elements of the tridiagonal
51: * matrix A in elements 1 to N-1 of E.
52: * On exit, E may be multiplied by a constant factor chosen
53: * to avoid over/underflow in computing the eigenvalues.
54: *
55: * VL (input) DOUBLE PRECISION
56: * VU (input) DOUBLE PRECISION
57: * If RANGE='V', the lower and upper bounds of the interval to
58: * be searched for eigenvalues. VL < VU.
59: * Not referenced if RANGE = 'A' or 'I'.
60: *
61: * IL (input) INTEGER
62: * IU (input) INTEGER
63: * If RANGE='I', the indices (in ascending order) of the
64: * smallest and largest eigenvalues to be returned.
65: * 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
66: * Not referenced if RANGE = 'A' or 'V'.
67: *
68: * ABSTOL (input) DOUBLE PRECISION
69: * The absolute error tolerance for the eigenvalues.
70: * An approximate eigenvalue is accepted as converged
71: * when it is determined to lie in an interval [a,b]
72: * of width less than or equal to
73: *
74: * ABSTOL + EPS * max( |a|,|b| ) ,
75: *
76: * where EPS is the machine precision. If ABSTOL is less
77: * than or equal to zero, then EPS*|T| will be used in
78: * its place, where |T| is the 1-norm of the tridiagonal
79: * matrix.
80: *
81: * Eigenvalues will be computed most accurately when ABSTOL is
82: * set to twice the underflow threshold 2*DLAMCH('S'), not zero.
83: * If this routine returns with INFO>0, indicating that some
84: * eigenvectors did not converge, try setting ABSTOL to
85: * 2*DLAMCH('S').
86: *
87: * See "Computing Small Singular Values of Bidiagonal Matrices
88: * with Guaranteed High Relative Accuracy," by Demmel and
89: * Kahan, LAPACK Working Note #3.
90: *
91: * M (output) INTEGER
92: * The total number of eigenvalues found. 0 <= M <= N.
93: * If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
94: *
95: * W (output) DOUBLE PRECISION array, dimension (N)
96: * The first M elements contain the selected eigenvalues in
97: * ascending order.
98: *
99: * Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) )
100: * If JOBZ = 'V', then if INFO = 0, the first M columns of Z
101: * contain the orthonormal eigenvectors of the matrix A
102: * corresponding to the selected eigenvalues, with the i-th
103: * column of Z holding the eigenvector associated with W(i).
104: * If an eigenvector fails to converge (INFO > 0), then that
105: * column of Z contains the latest approximation to the
106: * eigenvector, and the index of the eigenvector is returned
107: * in IFAIL. If JOBZ = 'N', then Z is not referenced.
108: * Note: the user must ensure that at least max(1,M) columns are
109: * supplied in the array Z; if RANGE = 'V', the exact value of M
110: * is not known in advance and an upper bound must be used.
111: *
112: * LDZ (input) INTEGER
113: * The leading dimension of the array Z. LDZ >= 1, and if
114: * JOBZ = 'V', LDZ >= max(1,N).
115: *
116: * WORK (workspace) DOUBLE PRECISION array, dimension (5*N)
117: *
118: * IWORK (workspace) INTEGER array, dimension (5*N)
119: *
120: * IFAIL (output) INTEGER array, dimension (N)
121: * If JOBZ = 'V', then if INFO = 0, the first M elements of
122: * IFAIL are zero. If INFO > 0, then IFAIL contains the
123: * indices of the eigenvectors that failed to converge.
124: * If JOBZ = 'N', then IFAIL is not referenced.
125: *
126: * INFO (output) INTEGER
127: * = 0: successful exit
128: * < 0: if INFO = -i, the i-th argument had an illegal value
129: * > 0: if INFO = i, then i eigenvectors failed to converge.
130: * Their indices are stored in array IFAIL.
131: *
132: * =====================================================================
133: *
134: * .. Parameters ..
135: DOUBLE PRECISION ZERO, ONE
136: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
137: * ..
138: * .. Local Scalars ..
139: LOGICAL ALLEIG, INDEIG, TEST, VALEIG, WANTZ
140: CHARACTER ORDER
141: INTEGER I, IMAX, INDIBL, INDISP, INDIWO, INDWRK,
142: $ ISCALE, ITMP1, J, JJ, NSPLIT
143: DOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM,
144: $ TMP1, TNRM, VLL, VUU
145: * ..
146: * .. External Functions ..
147: LOGICAL LSAME
148: DOUBLE PRECISION DLAMCH, DLANST
149: EXTERNAL LSAME, DLAMCH, DLANST
150: * ..
151: * .. External Subroutines ..
152: EXTERNAL DCOPY, DSCAL, DSTEBZ, DSTEIN, DSTEQR, DSTERF,
153: $ DSWAP, XERBLA
154: * ..
155: * .. Intrinsic Functions ..
156: INTRINSIC MAX, MIN, SQRT
157: * ..
158: * .. Executable Statements ..
159: *
160: * Test the input parameters.
161: *
162: WANTZ = LSAME( JOBZ, 'V' )
163: ALLEIG = LSAME( RANGE, 'A' )
164: VALEIG = LSAME( RANGE, 'V' )
165: INDEIG = LSAME( RANGE, 'I' )
166: *
167: INFO = 0
168: IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
169: INFO = -1
170: ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THEN
171: INFO = -2
172: ELSE IF( N.LT.0 ) THEN
173: INFO = -3
174: ELSE
175: IF( VALEIG ) THEN
176: IF( N.GT.0 .AND. VU.LE.VL )
177: $ INFO = -7
178: ELSE IF( INDEIG ) THEN
179: IF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THEN
180: INFO = -8
181: ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THEN
182: INFO = -9
183: END IF
184: END IF
185: END IF
186: IF( INFO.EQ.0 ) THEN
187: IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) )
188: $ INFO = -14
189: END IF
190: *
191: IF( INFO.NE.0 ) THEN
192: CALL XERBLA( 'DSTEVX', -INFO )
193: RETURN
194: END IF
195: *
196: * Quick return if possible
197: *
198: M = 0
199: IF( N.EQ.0 )
200: $ RETURN
201: *
202: IF( N.EQ.1 ) THEN
203: IF( ALLEIG .OR. INDEIG ) THEN
204: M = 1
205: W( 1 ) = D( 1 )
206: ELSE
207: IF( VL.LT.D( 1 ) .AND. VU.GE.D( 1 ) ) THEN
208: M = 1
209: W( 1 ) = D( 1 )
210: END IF
211: END IF
212: IF( WANTZ )
213: $ Z( 1, 1 ) = ONE
214: RETURN
215: END IF
216: *
217: * Get machine constants.
218: *
219: SAFMIN = DLAMCH( 'Safe minimum' )
220: EPS = DLAMCH( 'Precision' )
221: SMLNUM = SAFMIN / EPS
222: BIGNUM = ONE / SMLNUM
223: RMIN = SQRT( SMLNUM )
224: RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )
225: *
226: * Scale matrix to allowable range, if necessary.
227: *
228: ISCALE = 0
229: IF( VALEIG ) THEN
230: VLL = VL
231: VUU = VU
232: ELSE
233: VLL = ZERO
234: VUU = ZERO
235: END IF
236: TNRM = DLANST( 'M', N, D, E )
237: IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THEN
238: ISCALE = 1
239: SIGMA = RMIN / TNRM
240: ELSE IF( TNRM.GT.RMAX ) THEN
241: ISCALE = 1
242: SIGMA = RMAX / TNRM
243: END IF
244: IF( ISCALE.EQ.1 ) THEN
245: CALL DSCAL( N, SIGMA, D, 1 )
246: CALL DSCAL( N-1, SIGMA, E( 1 ), 1 )
247: IF( VALEIG ) THEN
248: VLL = VL*SIGMA
249: VUU = VU*SIGMA
250: END IF
251: END IF
252: *
253: * If all eigenvalues are desired and ABSTOL is less than zero, then
254: * call DSTERF or SSTEQR. If this fails for some eigenvalue, then
255: * try DSTEBZ.
256: *
257: TEST = .FALSE.
258: IF( INDEIG ) THEN
259: IF( IL.EQ.1 .AND. IU.EQ.N ) THEN
260: TEST = .TRUE.
261: END IF
262: END IF
263: IF( ( ALLEIG .OR. TEST ) .AND. ( ABSTOL.LE.ZERO ) ) THEN
264: CALL DCOPY( N, D, 1, W, 1 )
265: CALL DCOPY( N-1, E( 1 ), 1, WORK( 1 ), 1 )
266: INDWRK = N + 1
267: IF( .NOT.WANTZ ) THEN
268: CALL DSTERF( N, W, WORK, INFO )
269: ELSE
270: CALL DSTEQR( 'I', N, W, WORK, Z, LDZ, WORK( INDWRK ), INFO )
271: IF( INFO.EQ.0 ) THEN
272: DO 10 I = 1, N
273: IFAIL( I ) = 0
274: 10 CONTINUE
275: END IF
276: END IF
277: IF( INFO.EQ.0 ) THEN
278: M = N
279: GO TO 20
280: END IF
281: INFO = 0
282: END IF
283: *
284: * Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.
285: *
286: IF( WANTZ ) THEN
287: ORDER = 'B'
288: ELSE
289: ORDER = 'E'
290: END IF
291: INDWRK = 1
292: INDIBL = 1
293: INDISP = INDIBL + N
294: INDIWO = INDISP + N
295: CALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTOL, D, E, M,
296: $ NSPLIT, W, IWORK( INDIBL ), IWORK( INDISP ),
297: $ WORK( INDWRK ), IWORK( INDIWO ), INFO )
298: *
299: IF( WANTZ ) THEN
300: CALL DSTEIN( N, D, E, M, W, IWORK( INDIBL ), IWORK( INDISP ),
301: $ Z, LDZ, WORK( INDWRK ), IWORK( INDIWO ), IFAIL,
302: $ INFO )
303: END IF
304: *
305: * If matrix was scaled, then rescale eigenvalues appropriately.
306: *
307: 20 CONTINUE
308: IF( ISCALE.EQ.1 ) THEN
309: IF( INFO.EQ.0 ) THEN
310: IMAX = M
311: ELSE
312: IMAX = INFO - 1
313: END IF
314: CALL DSCAL( IMAX, ONE / SIGMA, W, 1 )
315: END IF
316: *
317: * If eigenvalues are not in order, then sort them, along with
318: * eigenvectors.
319: *
320: IF( WANTZ ) THEN
321: DO 40 J = 1, M - 1
322: I = 0
323: TMP1 = W( J )
324: DO 30 JJ = J + 1, M
325: IF( W( JJ ).LT.TMP1 ) THEN
326: I = JJ
327: TMP1 = W( JJ )
328: END IF
329: 30 CONTINUE
330: *
331: IF( I.NE.0 ) THEN
332: ITMP1 = IWORK( INDIBL+I-1 )
333: W( I ) = W( J )
334: IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )
335: W( J ) = TMP1
336: IWORK( INDIBL+J-1 ) = ITMP1
337: CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )
338: IF( INFO.NE.0 ) THEN
339: ITMP1 = IFAIL( I )
340: IFAIL( I ) = IFAIL( J )
341: IFAIL( J ) = ITMP1
342: END IF
343: END IF
344: 40 CONTINUE
345: END IF
346: *
347: RETURN
348: *
349: * End of DSTEVX
350: *
351: END
CVSweb interface <joel.bertrand@systella.fr>