1: *> \brief <b> ZGEES computes the eigenvalues, the Schur form, and, optionally, the matrix of Schur vectors for GE 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 ZGEES + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgees.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgees.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgees.f">
15: *> [TXT]</a>
16: *> \endhtmlonly
17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE ZGEES( JOBVS, SORT, SELECT, N, A, LDA, SDIM, W, VS,
22: * LDVS, WORK, LWORK, RWORK, BWORK, INFO )
23: *
24: * .. Scalar Arguments ..
25: * CHARACTER JOBVS, SORT
26: * INTEGER INFO, LDA, LDVS, LWORK, N, SDIM
27: * ..
28: * .. Array Arguments ..
29: * LOGICAL BWORK( * )
30: * DOUBLE PRECISION RWORK( * )
31: * COMPLEX*16 A( LDA, * ), VS( LDVS, * ), W( * ), WORK( * )
32: * ..
33: * .. Function Arguments ..
34: * LOGICAL SELECT
35: * EXTERNAL SELECT
36: * ..
37: *
38: *
39: *> \par Purpose:
40: * =============
41: *>
42: *> \verbatim
43: *>
44: *> ZGEES computes for an N-by-N complex nonsymmetric matrix A, the
45: *> eigenvalues, the Schur form T, and, optionally, the matrix of Schur
46: *> vectors Z. This gives the Schur factorization A = Z*T*(Z**H).
47: *>
48: *> Optionally, it also orders the eigenvalues on the diagonal of the
49: *> Schur form so that selected eigenvalues are at the top left.
50: *> The leading columns of Z then form an orthonormal basis for the
51: *> invariant subspace corresponding to the selected eigenvalues.
52: *>
53: *> A complex matrix is in Schur form if it is upper triangular.
54: *> \endverbatim
55: *
56: * Arguments:
57: * ==========
58: *
59: *> \param[in] JOBVS
60: *> \verbatim
61: *> JOBVS is CHARACTER*1
62: *> = 'N': Schur vectors are not computed;
63: *> = 'V': Schur vectors are computed.
64: *> \endverbatim
65: *>
66: *> \param[in] SORT
67: *> \verbatim
68: *> SORT is CHARACTER*1
69: *> Specifies whether or not to order the eigenvalues on the
70: *> diagonal of the Schur form.
71: *> = 'N': Eigenvalues are not ordered:
72: *> = 'S': Eigenvalues are ordered (see SELECT).
73: *> \endverbatim
74: *>
75: *> \param[in] SELECT
76: *> \verbatim
77: *> SELECT is procedure) LOGICAL FUNCTION of one COMPLEX*16 argument
78: *> SELECT must be declared EXTERNAL in the calling subroutine.
79: *> If SORT = 'S', SELECT is used to select eigenvalues to order
80: *> to the top left of the Schur form.
81: *> IF SORT = 'N', SELECT is not referenced.
82: *> The eigenvalue W(j) is selected if SELECT(W(j)) is true.
83: *> \endverbatim
84: *>
85: *> \param[in] N
86: *> \verbatim
87: *> N is INTEGER
88: *> The order of the matrix A. N >= 0.
89: *> \endverbatim
90: *>
91: *> \param[in,out] A
92: *> \verbatim
93: *> A is COMPLEX*16 array, dimension (LDA,N)
94: *> On entry, the N-by-N matrix A.
95: *> On exit, A has been overwritten by its Schur form T.
96: *> \endverbatim
97: *>
98: *> \param[in] LDA
99: *> \verbatim
100: *> LDA is INTEGER
101: *> The leading dimension of the array A. LDA >= max(1,N).
102: *> \endverbatim
103: *>
104: *> \param[out] SDIM
105: *> \verbatim
106: *> SDIM is INTEGER
107: *> If SORT = 'N', SDIM = 0.
108: *> If SORT = 'S', SDIM = number of eigenvalues for which
109: *> SELECT is true.
110: *> \endverbatim
111: *>
112: *> \param[out] W
113: *> \verbatim
114: *> W is COMPLEX*16 array, dimension (N)
115: *> W contains the computed eigenvalues, in the same order that
116: *> they appear on the diagonal of the output Schur form T.
117: *> \endverbatim
118: *>
119: *> \param[out] VS
120: *> \verbatim
121: *> VS is COMPLEX*16 array, dimension (LDVS,N)
122: *> If JOBVS = 'V', VS contains the unitary matrix Z of Schur
123: *> vectors.
124: *> If JOBVS = 'N', VS is not referenced.
125: *> \endverbatim
126: *>
127: *> \param[in] LDVS
128: *> \verbatim
129: *> LDVS is INTEGER
130: *> The leading dimension of the array VS. LDVS >= 1; if
131: *> JOBVS = 'V', LDVS >= N.
132: *> \endverbatim
133: *>
134: *> \param[out] WORK
135: *> \verbatim
136: *> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
137: *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
138: *> \endverbatim
139: *>
140: *> \param[in] LWORK
141: *> \verbatim
142: *> LWORK is INTEGER
143: *> The dimension of the array WORK. LWORK >= max(1,2*N).
144: *> For good performance, LWORK must generally be larger.
145: *>
146: *> If LWORK = -1, then a workspace query is assumed; the routine
147: *> only calculates the optimal size of the WORK array, returns
148: *> this value as the first entry of the WORK array, and no error
149: *> message related to LWORK is issued by XERBLA.
150: *> \endverbatim
151: *>
152: *> \param[out] RWORK
153: *> \verbatim
154: *> RWORK is DOUBLE PRECISION array, dimension (N)
155: *> \endverbatim
156: *>
157: *> \param[out] BWORK
158: *> \verbatim
159: *> BWORK is LOGICAL array, dimension (N)
160: *> Not referenced if SORT = 'N'.
161: *> \endverbatim
162: *>
163: *> \param[out] INFO
164: *> \verbatim
165: *> INFO is INTEGER
166: *> = 0: successful exit
167: *> < 0: if INFO = -i, the i-th argument had an illegal value.
168: *> > 0: if INFO = i, and i is
169: *> <= N: the QR algorithm failed to compute all the
170: *> eigenvalues; elements 1:ILO-1 and i+1:N of W
171: *> contain those eigenvalues which have converged;
172: *> if JOBVS = 'V', VS contains the matrix which
173: *> reduces A to its partially converged Schur form.
174: *> = N+1: the eigenvalues could not be reordered because
175: *> some eigenvalues were too close to separate (the
176: *> problem is very ill-conditioned);
177: *> = N+2: after reordering, roundoff changed values of
178: *> some complex eigenvalues so that leading
179: *> eigenvalues in the Schur form no longer satisfy
180: *> SELECT = .TRUE.. This could also be caused by
181: *> underflow due to scaling.
182: *> \endverbatim
183: *
184: * Authors:
185: * ========
186: *
187: *> \author Univ. of Tennessee
188: *> \author Univ. of California Berkeley
189: *> \author Univ. of Colorado Denver
190: *> \author NAG Ltd.
191: *
192: *> \date November 2011
193: *
194: *> \ingroup complex16GEeigen
195: *
196: * =====================================================================
197: SUBROUTINE ZGEES( JOBVS, SORT, SELECT, N, A, LDA, SDIM, W, VS,
198: $ LDVS, WORK, LWORK, RWORK, BWORK, INFO )
199: *
200: * -- LAPACK driver routine (version 3.4.0) --
201: * -- LAPACK is a software package provided by Univ. of Tennessee, --
202: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
203: * November 2011
204: *
205: * .. Scalar Arguments ..
206: CHARACTER JOBVS, SORT
207: INTEGER INFO, LDA, LDVS, LWORK, N, SDIM
208: * ..
209: * .. Array Arguments ..
210: LOGICAL BWORK( * )
211: DOUBLE PRECISION RWORK( * )
212: COMPLEX*16 A( LDA, * ), VS( LDVS, * ), W( * ), WORK( * )
213: * ..
214: * .. Function Arguments ..
215: LOGICAL SELECT
216: EXTERNAL SELECT
217: * ..
218: *
219: * =====================================================================
220: *
221: * .. Parameters ..
222: DOUBLE PRECISION ZERO, ONE
223: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
224: * ..
225: * .. Local Scalars ..
226: LOGICAL LQUERY, SCALEA, WANTST, WANTVS
227: INTEGER HSWORK, I, IBAL, ICOND, IERR, IEVAL, IHI, ILO,
228: $ ITAU, IWRK, MAXWRK, MINWRK
229: DOUBLE PRECISION ANRM, BIGNUM, CSCALE, EPS, S, SEP, SMLNUM
230: * ..
231: * .. Local Arrays ..
232: DOUBLE PRECISION DUM( 1 )
233: * ..
234: * .. External Subroutines ..
235: EXTERNAL DLABAD, XERBLA, ZCOPY, ZGEBAK, ZGEBAL, ZGEHRD,
236: $ ZHSEQR, ZLACPY, ZLASCL, ZTRSEN, ZUNGHR
237: * ..
238: * .. External Functions ..
239: LOGICAL LSAME
240: INTEGER ILAENV
241: DOUBLE PRECISION DLAMCH, ZLANGE
242: EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE
243: * ..
244: * .. Intrinsic Functions ..
245: INTRINSIC MAX, SQRT
246: * ..
247: * .. Executable Statements ..
248: *
249: * Test the input arguments
250: *
251: INFO = 0
252: LQUERY = ( LWORK.EQ.-1 )
253: WANTVS = LSAME( JOBVS, 'V' )
254: WANTST = LSAME( SORT, 'S' )
255: IF( ( .NOT.WANTVS ) .AND. ( .NOT.LSAME( JOBVS, 'N' ) ) ) THEN
256: INFO = -1
257: ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN
258: INFO = -2
259: ELSE IF( N.LT.0 ) THEN
260: INFO = -4
261: ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
262: INFO = -6
263: ELSE IF( LDVS.LT.1 .OR. ( WANTVS .AND. LDVS.LT.N ) ) THEN
264: INFO = -10
265: END IF
266: *
267: * Compute workspace
268: * (Note: Comments in the code beginning "Workspace:" describe the
269: * minimal amount of workspace needed at that point in the code,
270: * as well as the preferred amount for good performance.
271: * CWorkspace refers to complex workspace, and RWorkspace to real
272: * workspace. NB refers to the optimal block size for the
273: * immediately following subroutine, as returned by ILAENV.
274: * HSWORK refers to the workspace preferred by ZHSEQR, as
275: * calculated below. HSWORK is computed assuming ILO=1 and IHI=N,
276: * the worst case.)
277: *
278: IF( INFO.EQ.0 ) THEN
279: IF( N.EQ.0 ) THEN
280: MINWRK = 1
281: MAXWRK = 1
282: ELSE
283: MAXWRK = N + N*ILAENV( 1, 'ZGEHRD', ' ', N, 1, N, 0 )
284: MINWRK = 2*N
285: *
286: CALL ZHSEQR( 'S', JOBVS, N, 1, N, A, LDA, W, VS, LDVS,
287: $ WORK, -1, IEVAL )
288: HSWORK = WORK( 1 )
289: *
290: IF( .NOT.WANTVS ) THEN
291: MAXWRK = MAX( MAXWRK, HSWORK )
292: ELSE
293: MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'ZUNGHR',
294: $ ' ', N, 1, N, -1 ) )
295: MAXWRK = MAX( MAXWRK, HSWORK )
296: END IF
297: END IF
298: WORK( 1 ) = MAXWRK
299: *
300: IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
301: INFO = -12
302: END IF
303: END IF
304: *
305: IF( INFO.NE.0 ) THEN
306: CALL XERBLA( 'ZGEES ', -INFO )
307: RETURN
308: ELSE IF( LQUERY ) THEN
309: RETURN
310: END IF
311: *
312: * Quick return if possible
313: *
314: IF( N.EQ.0 ) THEN
315: SDIM = 0
316: RETURN
317: END IF
318: *
319: * Get machine constants
320: *
321: EPS = DLAMCH( 'P' )
322: SMLNUM = DLAMCH( 'S' )
323: BIGNUM = ONE / SMLNUM
324: CALL DLABAD( SMLNUM, BIGNUM )
325: SMLNUM = SQRT( SMLNUM ) / EPS
326: BIGNUM = ONE / SMLNUM
327: *
328: * Scale A if max element outside range [SMLNUM,BIGNUM]
329: *
330: ANRM = ZLANGE( 'M', N, N, A, LDA, DUM )
331: SCALEA = .FALSE.
332: IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
333: SCALEA = .TRUE.
334: CSCALE = SMLNUM
335: ELSE IF( ANRM.GT.BIGNUM ) THEN
336: SCALEA = .TRUE.
337: CSCALE = BIGNUM
338: END IF
339: IF( SCALEA )
340: $ CALL ZLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
341: *
342: * Permute the matrix to make it more nearly triangular
343: * (CWorkspace: none)
344: * (RWorkspace: need N)
345: *
346: IBAL = 1
347: CALL ZGEBAL( 'P', N, A, LDA, ILO, IHI, RWORK( IBAL ), IERR )
348: *
349: * Reduce to upper Hessenberg form
350: * (CWorkspace: need 2*N, prefer N+N*NB)
351: * (RWorkspace: none)
352: *
353: ITAU = 1
354: IWRK = N + ITAU
355: CALL ZGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
356: $ LWORK-IWRK+1, IERR )
357: *
358: IF( WANTVS ) THEN
359: *
360: * Copy Householder vectors to VS
361: *
362: CALL ZLACPY( 'L', N, N, A, LDA, VS, LDVS )
363: *
364: * Generate unitary matrix in VS
365: * (CWorkspace: need 2*N-1, prefer N+(N-1)*NB)
366: * (RWorkspace: none)
367: *
368: CALL ZUNGHR( N, ILO, IHI, VS, LDVS, WORK( ITAU ), WORK( IWRK ),
369: $ LWORK-IWRK+1, IERR )
370: END IF
371: *
372: SDIM = 0
373: *
374: * Perform QR iteration, accumulating Schur vectors in VS if desired
375: * (CWorkspace: need 1, prefer HSWORK (see comments) )
376: * (RWorkspace: none)
377: *
378: IWRK = ITAU
379: CALL ZHSEQR( 'S', JOBVS, N, ILO, IHI, A, LDA, W, VS, LDVS,
380: $ WORK( IWRK ), LWORK-IWRK+1, IEVAL )
381: IF( IEVAL.GT.0 )
382: $ INFO = IEVAL
383: *
384: * Sort eigenvalues if desired
385: *
386: IF( WANTST .AND. INFO.EQ.0 ) THEN
387: IF( SCALEA )
388: $ CALL ZLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, W, N, IERR )
389: DO 10 I = 1, N
390: BWORK( I ) = SELECT( W( I ) )
391: 10 CONTINUE
392: *
393: * Reorder eigenvalues and transform Schur vectors
394: * (CWorkspace: none)
395: * (RWorkspace: none)
396: *
397: CALL ZTRSEN( 'N', JOBVS, BWORK, N, A, LDA, VS, LDVS, W, SDIM,
398: $ S, SEP, WORK( IWRK ), LWORK-IWRK+1, ICOND )
399: END IF
400: *
401: IF( WANTVS ) THEN
402: *
403: * Undo balancing
404: * (CWorkspace: none)
405: * (RWorkspace: need N)
406: *
407: CALL ZGEBAK( 'P', 'R', N, ILO, IHI, RWORK( IBAL ), N, VS, LDVS,
408: $ IERR )
409: END IF
410: *
411: IF( SCALEA ) THEN
412: *
413: * Undo scaling for the Schur form of A
414: *
415: CALL ZLASCL( 'U', 0, 0, CSCALE, ANRM, N, N, A, LDA, IERR )
416: CALL ZCOPY( N, A, LDA+1, W, 1 )
417: END IF
418: *
419: WORK( 1 ) = MAXWRK
420: RETURN
421: *
422: * End of ZGEES
423: *
424: END
CVSweb interface <joel.bertrand@systella.fr>