1: *> \brief <b> DSPEVD computes the eigenvalues and, optionally, the left and/or right eigenvectors for OTHER matrices</b>
2: *
3: * =========== DOCUMENTATION ===========
4: *
5: * Online html documentation available at
6: * http://www.netlib.org/lapack/explore-html/
7: *
8: *> \htmlonly
9: *> Download DSPEVD + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dspevd.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dspevd.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspevd.f">
15: *> [TXT]</a>
16: *> \endhtmlonly
17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE DSPEVD( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, LWORK,
22: * IWORK, LIWORK, INFO )
23: *
24: * .. Scalar Arguments ..
25: * CHARACTER JOBZ, UPLO
26: * INTEGER INFO, LDZ, LIWORK, LWORK, N
27: * ..
28: * .. Array Arguments ..
29: * INTEGER IWORK( * )
30: * DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( LDZ, * )
31: * ..
32: *
33: *
34: *> \par Purpose:
35: * =============
36: *>
37: *> \verbatim
38: *>
39: *> DSPEVD computes all the eigenvalues and, optionally, eigenvectors
40: *> of a real symmetric matrix A in packed storage. If eigenvectors are
41: *> desired, it uses a divide and conquer algorithm.
42: *>
43: *> The divide and conquer algorithm makes very mild assumptions about
44: *> floating point arithmetic. It will work on machines with a guard
45: *> digit in add/subtract, or on those binary machines without guard
46: *> digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
47: *> Cray-2. It could conceivably fail on hexadecimal or decimal machines
48: *> without guard digits, but we know of none.
49: *> \endverbatim
50: *
51: * Arguments:
52: * ==========
53: *
54: *> \param[in] JOBZ
55: *> \verbatim
56: *> JOBZ is CHARACTER*1
57: *> = 'N': Compute eigenvalues only;
58: *> = 'V': Compute eigenvalues and eigenvectors.
59: *> \endverbatim
60: *>
61: *> \param[in] UPLO
62: *> \verbatim
63: *> UPLO is CHARACTER*1
64: *> = 'U': Upper triangle of A is stored;
65: *> = 'L': Lower triangle of A is stored.
66: *> \endverbatim
67: *>
68: *> \param[in] N
69: *> \verbatim
70: *> N is INTEGER
71: *> The order of the matrix A. N >= 0.
72: *> \endverbatim
73: *>
74: *> \param[in,out] AP
75: *> \verbatim
76: *> AP is DOUBLE PRECISION array, dimension (N*(N+1)/2)
77: *> On entry, the upper or lower triangle of the symmetric matrix
78: *> A, packed columnwise in a linear array. The j-th column of A
79: *> is stored in the array AP as follows:
80: *> if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;
81: *> if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.
82: *>
83: *> On exit, AP is overwritten by values generated during the
84: *> reduction to tridiagonal form. If UPLO = 'U', the diagonal
85: *> and first superdiagonal of the tridiagonal matrix T overwrite
86: *> the corresponding elements of A, and if UPLO = 'L', the
87: *> diagonal and first subdiagonal of T overwrite the
88: *> corresponding elements of A.
89: *> \endverbatim
90: *>
91: *> \param[out] W
92: *> \verbatim
93: *> W is DOUBLE PRECISION array, dimension (N)
94: *> If INFO = 0, the eigenvalues in ascending order.
95: *> \endverbatim
96: *>
97: *> \param[out] Z
98: *> \verbatim
99: *> Z is DOUBLE PRECISION array, dimension (LDZ, N)
100: *> If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal
101: *> eigenvectors of the matrix A, with the i-th column of Z
102: *> holding the eigenvector associated with W(i).
103: *> If JOBZ = 'N', then Z is not referenced.
104: *> \endverbatim
105: *>
106: *> \param[in] LDZ
107: *> \verbatim
108: *> LDZ is INTEGER
109: *> The leading dimension of the array Z. LDZ >= 1, and if
110: *> JOBZ = 'V', LDZ >= max(1,N).
111: *> \endverbatim
112: *>
113: *> \param[out] WORK
114: *> \verbatim
115: *> WORK is DOUBLE PRECISION array,
116: *> dimension (LWORK)
117: *> On exit, if INFO = 0, WORK(1) returns the required LWORK.
118: *> \endverbatim
119: *>
120: *> \param[in] LWORK
121: *> \verbatim
122: *> LWORK is INTEGER
123: *> The dimension of the array WORK.
124: *> If N <= 1, LWORK must be at least 1.
125: *> If JOBZ = 'N' and N > 1, LWORK must be at least 2*N.
126: *> If JOBZ = 'V' and N > 1, LWORK must be at least
127: *> 1 + 6*N + N**2.
128: *>
129: *> If LWORK = -1, then a workspace query is assumed; the routine
130: *> only calculates the required sizes of the WORK and IWORK
131: *> arrays, returns these values as the first entries of the WORK
132: *> and IWORK arrays, and no error message related to LWORK or
133: *> LIWORK is issued by XERBLA.
134: *> \endverbatim
135: *>
136: *> \param[out] IWORK
137: *> \verbatim
138: *> IWORK is INTEGER array, dimension (MAX(1,LIWORK))
139: *> On exit, if INFO = 0, IWORK(1) returns the required LIWORK.
140: *> \endverbatim
141: *>
142: *> \param[in] LIWORK
143: *> \verbatim
144: *> LIWORK is INTEGER
145: *> The dimension of the array IWORK.
146: *> If JOBZ = 'N' or N <= 1, LIWORK must be at least 1.
147: *> If JOBZ = 'V' and N > 1, LIWORK must be at least 3 + 5*N.
148: *>
149: *> If LIWORK = -1, then a workspace query is assumed; the
150: *> routine only calculates the required sizes of the WORK and
151: *> IWORK arrays, returns these values as the first entries of
152: *> the WORK and IWORK arrays, and no error message related to
153: *> LWORK or LIWORK is issued by XERBLA.
154: *> \endverbatim
155: *>
156: *> \param[out] INFO
157: *> \verbatim
158: *> INFO is INTEGER
159: *> = 0: successful exit
160: *> < 0: if INFO = -i, the i-th argument had an illegal value.
161: *> > 0: if INFO = i, the algorithm failed to converge; i
162: *> off-diagonal elements of an intermediate tridiagonal
163: *> form did not converge to zero.
164: *> \endverbatim
165: *
166: * Authors:
167: * ========
168: *
169: *> \author Univ. of Tennessee
170: *> \author Univ. of California Berkeley
171: *> \author Univ. of Colorado Denver
172: *> \author NAG Ltd.
173: *
174: *> \date November 2011
175: *
176: *> \ingroup doubleOTHEReigen
177: *
178: * =====================================================================
179: SUBROUTINE DSPEVD( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, LWORK,
180: $ IWORK, LIWORK, INFO )
181: *
182: * -- LAPACK driver routine (version 3.4.0) --
183: * -- LAPACK is a software package provided by Univ. of Tennessee, --
184: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
185: * November 2011
186: *
187: * .. Scalar Arguments ..
188: CHARACTER JOBZ, UPLO
189: INTEGER INFO, LDZ, LIWORK, LWORK, N
190: * ..
191: * .. Array Arguments ..
192: INTEGER IWORK( * )
193: DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( LDZ, * )
194: * ..
195: *
196: * =====================================================================
197: *
198: * .. Parameters ..
199: DOUBLE PRECISION ZERO, ONE
200: PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
201: * ..
202: * .. Local Scalars ..
203: LOGICAL LQUERY, WANTZ
204: INTEGER IINFO, INDE, INDTAU, INDWRK, ISCALE, LIWMIN,
205: $ LLWORK, LWMIN
206: DOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,
207: $ SMLNUM
208: * ..
209: * .. External Functions ..
210: LOGICAL LSAME
211: DOUBLE PRECISION DLAMCH, DLANSP
212: EXTERNAL LSAME, DLAMCH, DLANSP
213: * ..
214: * .. External Subroutines ..
215: EXTERNAL DOPMTR, DSCAL, DSPTRD, DSTEDC, DSTERF, XERBLA
216: * ..
217: * .. Intrinsic Functions ..
218: INTRINSIC SQRT
219: * ..
220: * .. Executable Statements ..
221: *
222: * Test the input parameters.
223: *
224: WANTZ = LSAME( JOBZ, 'V' )
225: LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )
226: *
227: INFO = 0
228: IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
229: INFO = -1
230: ELSE IF( .NOT.( LSAME( UPLO, 'U' ) .OR. LSAME( UPLO, 'L' ) ) )
231: $ THEN
232: INFO = -2
233: ELSE IF( N.LT.0 ) THEN
234: INFO = -3
235: ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN
236: INFO = -7
237: END IF
238: *
239: IF( INFO.EQ.0 ) THEN
240: IF( N.LE.1 ) THEN
241: LIWMIN = 1
242: LWMIN = 1
243: ELSE
244: IF( WANTZ ) THEN
245: LIWMIN = 3 + 5*N
246: LWMIN = 1 + 6*N + N**2
247: ELSE
248: LIWMIN = 1
249: LWMIN = 2*N
250: END IF
251: END IF
252: IWORK( 1 ) = LIWMIN
253: WORK( 1 ) = LWMIN
254: *
255: IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
256: INFO = -9
257: ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
258: INFO = -11
259: END IF
260: END IF
261: *
262: IF( INFO.NE.0 ) THEN
263: CALL XERBLA( 'DSPEVD', -INFO )
264: RETURN
265: ELSE IF( LQUERY ) THEN
266: RETURN
267: END IF
268: *
269: * Quick return if possible
270: *
271: IF( N.EQ.0 )
272: $ RETURN
273: *
274: IF( N.EQ.1 ) THEN
275: W( 1 ) = AP( 1 )
276: IF( WANTZ )
277: $ Z( 1, 1 ) = ONE
278: RETURN
279: END IF
280: *
281: * Get machine constants.
282: *
283: SAFMIN = DLAMCH( 'Safe minimum' )
284: EPS = DLAMCH( 'Precision' )
285: SMLNUM = SAFMIN / EPS
286: BIGNUM = ONE / SMLNUM
287: RMIN = SQRT( SMLNUM )
288: RMAX = SQRT( BIGNUM )
289: *
290: * Scale matrix to allowable range, if necessary.
291: *
292: ANRM = DLANSP( 'M', UPLO, N, AP, WORK )
293: ISCALE = 0
294: IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THEN
295: ISCALE = 1
296: SIGMA = RMIN / ANRM
297: ELSE IF( ANRM.GT.RMAX ) THEN
298: ISCALE = 1
299: SIGMA = RMAX / ANRM
300: END IF
301: IF( ISCALE.EQ.1 ) THEN
302: CALL DSCAL( ( N*( N+1 ) ) / 2, SIGMA, AP, 1 )
303: END IF
304: *
305: * Call DSPTRD to reduce symmetric packed matrix to tridiagonal form.
306: *
307: INDE = 1
308: INDTAU = INDE + N
309: CALL DSPTRD( UPLO, N, AP, W, WORK( INDE ), WORK( INDTAU ), IINFO )
310: *
311: * For eigenvalues only, call DSTERF. For eigenvectors, first call
312: * DSTEDC to generate the eigenvector matrix, WORK(INDWRK), of the
313: * tridiagonal matrix, then call DOPMTR to multiply it by the
314: * Householder transformations represented in AP.
315: *
316: IF( .NOT.WANTZ ) THEN
317: CALL DSTERF( N, W, WORK( INDE ), INFO )
318: ELSE
319: INDWRK = INDTAU + N
320: LLWORK = LWORK - INDWRK + 1
321: CALL DSTEDC( 'I', N, W, WORK( INDE ), Z, LDZ, WORK( INDWRK ),
322: $ LLWORK, IWORK, LIWORK, INFO )
323: CALL DOPMTR( 'L', UPLO, 'N', N, N, AP, WORK( INDTAU ), Z, LDZ,
324: $ WORK( INDWRK ), IINFO )
325: END IF
326: *
327: * If matrix was scaled, then rescale eigenvalues appropriately.
328: *
329: IF( ISCALE.EQ.1 )
330: $ CALL DSCAL( N, ONE / SIGMA, W, 1 )
331: *
332: WORK( 1 ) = LWMIN
333: IWORK( 1 ) = LIWMIN
334: RETURN
335: *
336: * End of DSPEVD
337: *
338: END
CVSweb interface <joel.bertrand@systella.fr>