3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download ZTREVC3 + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ztrevc3.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ztrevc3.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrevc3.f">
21 * SUBROUTINE ZTREVC3( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,
22 * $ LDVR, MM, M, WORK, LWORK, RWORK, LRWORK, INFO)
24 * .. Scalar Arguments ..
25 * CHARACTER HOWMNY, SIDE
26 * INTEGER INFO, LDT, LDVL, LDVR, LWORK, M, MM, N
28 * .. Array Arguments ..
30 * DOUBLE PRECISION RWORK( * )
31 * COMPLEX*16 T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ),
41 *> ZTREVC3 computes some or all of the right and/or left eigenvectors of
42 *> a complex upper triangular matrix T.
43 *> Matrices of this type are produced by the Schur factorization of
44 *> a complex general matrix: A = Q*T*Q**H, as computed by ZHSEQR.
46 *> The right eigenvector x and the left eigenvector y of T corresponding
47 *> to an eigenvalue w are defined by:
49 *> T*x = w*x, (y**H)*T = w*(y**H)
51 *> where y**H denotes the conjugate transpose of the vector y.
52 *> The eigenvalues are not input to this routine, but are read directly
53 *> from the diagonal of T.
55 *> This routine returns the matrices X and/or Y of right and left
56 *> eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an
57 *> input matrix. If Q is the unitary factor that reduces a matrix A to
58 *> Schur form T, then Q*X and Q*Y are the matrices of right and left
61 *> This uses a Level 3 BLAS version of the back transformation.
69 *> SIDE is CHARACTER*1
70 *> = 'R': compute right eigenvectors only;
71 *> = 'L': compute left eigenvectors only;
72 *> = 'B': compute both right and left eigenvectors.
77 *> HOWMNY is CHARACTER*1
78 *> = 'A': compute all right and/or left eigenvectors;
79 *> = 'B': compute all right and/or left eigenvectors,
80 *> backtransformed using the matrices supplied in
82 *> = 'S': compute selected right and/or left eigenvectors,
83 *> as indicated by the logical array SELECT.
88 *> SELECT is LOGICAL array, dimension (N)
89 *> If HOWMNY = 'S', SELECT specifies the eigenvectors to be
91 *> The eigenvector corresponding to the j-th eigenvalue is
92 *> computed if SELECT(j) = .TRUE..
93 *> Not referenced if HOWMNY = 'A' or 'B'.
99 *> The order of the matrix T. N >= 0.
104 *> T is COMPLEX*16 array, dimension (LDT,N)
105 *> The upper triangular matrix T. T is modified, but restored
112 *> The leading dimension of the array T. LDT >= max(1,N).
117 *> VL is COMPLEX*16 array, dimension (LDVL,MM)
118 *> On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must
119 *> contain an N-by-N matrix Q (usually the unitary matrix Q of
120 *> Schur vectors returned by ZHSEQR).
121 *> On exit, if SIDE = 'L' or 'B', VL contains:
122 *> if HOWMNY = 'A', the matrix Y of left eigenvectors of T;
123 *> if HOWMNY = 'B', the matrix Q*Y;
124 *> if HOWMNY = 'S', the left eigenvectors of T specified by
125 *> SELECT, stored consecutively in the columns
126 *> of VL, in the same order as their
128 *> Not referenced if SIDE = 'R'.
134 *> The leading dimension of the array VL.
135 *> LDVL >= 1, and if SIDE = 'L' or 'B', LDVL >= N.
140 *> VR is COMPLEX*16 array, dimension (LDVR,MM)
141 *> On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must
142 *> contain an N-by-N matrix Q (usually the unitary matrix Q of
143 *> Schur vectors returned by ZHSEQR).
144 *> On exit, if SIDE = 'R' or 'B', VR contains:
145 *> if HOWMNY = 'A', the matrix X of right eigenvectors of T;
146 *> if HOWMNY = 'B', the matrix Q*X;
147 *> if HOWMNY = 'S', the right eigenvectors of T specified by
148 *> SELECT, stored consecutively in the columns
149 *> of VR, in the same order as their
151 *> Not referenced if SIDE = 'L'.
157 *> The leading dimension of the array VR.
158 *> LDVR >= 1, and if SIDE = 'R' or 'B', LDVR >= N.
164 *> The number of columns in the arrays VL and/or VR. MM >= M.
170 *> The number of columns in the arrays VL and/or VR actually
171 *> used to store the eigenvectors.
172 *> If HOWMNY = 'A' or 'B', M is set to N.
173 *> Each selected eigenvector occupies one column.
178 *> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
184 *> The dimension of array WORK. LWORK >= max(1,2*N).
185 *> For optimum performance, LWORK >= N + 2*N*NB, where NB is
186 *> the optimal blocksize.
188 *> If LWORK = -1, then a workspace query is assumed; the routine
189 *> only calculates the optimal size of the WORK array, returns
190 *> this value as the first entry of the WORK array, and no error
191 *> message related to LWORK is issued by XERBLA.
196 *> RWORK is DOUBLE PRECISION array, dimension (LRWORK)
202 *> The dimension of array RWORK. LRWORK >= max(1,N).
204 *> If LRWORK = -1, then a workspace query is assumed; the routine
205 *> only calculates the optimal size of the RWORK array, returns
206 *> this value as the first entry of the RWORK array, and no error
207 *> message related to LRWORK is issued by XERBLA.
213 *> = 0: successful exit
214 *> < 0: if INFO = -i, the i-th argument had an illegal value
220 *> \author Univ. of Tennessee
221 *> \author Univ. of California Berkeley
222 *> \author Univ. of Colorado Denver
225 *> \date November 2011
227 * @precisions fortran z -> c
229 *> \ingroup complex16OTHERcomputational
231 *> \par Further Details:
232 * =====================
236 *> The algorithm used in this program is basically backward (forward)
237 *> substitution, with scaling to make the the code robust against
238 *> possible overflow.
240 *> Each eigenvector is normalized so that the element of largest
241 *> magnitude has magnitude 1; here the magnitude of a complex number
242 *> (x,y) is taken to be |x| + |y|.
245 * =====================================================================
246 SUBROUTINE ZTREVC3( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,
247 $ LDVR, MM, M, WORK, LWORK, RWORK, LRWORK, INFO)
250 * -- LAPACK computational routine (version 3.4.0) --
251 * -- LAPACK is a software package provided by Univ. of Tennessee, --
252 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
255 * .. Scalar Arguments ..
256 CHARACTER HOWMNY, SIDE
257 INTEGER INFO, LDT, LDVL, LDVR, LWORK, LRWORK, M, MM, N
259 * .. Array Arguments ..
261 DOUBLE PRECISION RWORK( * )
262 COMPLEX*16 T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ),
266 * =====================================================================
269 DOUBLE PRECISION ZERO, ONE
270 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
271 COMPLEX*16 CZERO, CONE
272 PARAMETER ( CZERO = ( 0.0D+0, 0.0D+0 ),
273 $ CONE = ( 1.0D+0, 0.0D+0 ) )
275 PARAMETER ( NBMIN = 8, NBMAX = 128 )
277 * .. Local Scalars ..
278 LOGICAL ALLV, BOTHV, LEFTV, LQUERY, OVER, RIGHTV, SOMEV
279 INTEGER I, II, IS, J, K, KI, IV, MAXWRK, NB
280 DOUBLE PRECISION OVFL, REMAX, SCALE, SMIN, SMLNUM, ULP, UNFL
283 * .. External Functions ..
285 INTEGER ILAENV, IZAMAX
286 DOUBLE PRECISION DLAMCH, DZASUM
287 EXTERNAL LSAME, ILAENV, IZAMAX, DLAMCH, DZASUM
289 * .. External Subroutines ..
290 EXTERNAL XERBLA, ZCOPY, ZDSCAL, ZGEMV, ZLATRS
292 * .. Intrinsic Functions ..
293 INTRINSIC ABS, DBLE, DCMPLX, CONJG, AIMAG, MAX
295 * .. Statement Functions ..
296 DOUBLE PRECISION CABS1
298 * .. Statement Function definitions ..
299 CABS1( CDUM ) = ABS( DBLE( CDUM ) ) + ABS( AIMAG( CDUM ) )
301 * .. Executable Statements ..
303 * Decode and test the input parameters
305 BOTHV = LSAME( SIDE, 'B' )
306 RIGHTV = LSAME( SIDE, 'R' ) .OR. BOTHV
307 LEFTV = LSAME( SIDE, 'L' ) .OR. BOTHV
309 ALLV = LSAME( HOWMNY, 'A' )
310 OVER = LSAME( HOWMNY, 'B' )
311 SOMEV = LSAME( HOWMNY, 'S' )
313 * Set M to the number of columns required to store the selected
327 NB = ILAENV( 1, 'ZTREVC', SIDE // HOWMNY, N, -1, -1, -1 )
331 LQUERY = ( LWORK.EQ.-1 .OR. LRWORK.EQ.-1 )
332 IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THEN
334 ELSE IF( .NOT.ALLV .AND. .NOT.OVER .AND. .NOT.SOMEV ) THEN
336 ELSE IF( N.LT.0 ) THEN
338 ELSE IF( LDT.LT.MAX( 1, N ) ) THEN
340 ELSE IF( LDVL.LT.1 .OR. ( LEFTV .AND. LDVL.LT.N ) ) THEN
342 ELSE IF( LDVR.LT.1 .OR. ( RIGHTV .AND. LDVR.LT.N ) ) THEN
344 ELSE IF( MM.LT.M ) THEN
346 ELSE IF( LWORK.LT.MAX( 1, 2*N ) .AND. .NOT.LQUERY ) THEN
348 ELSE IF ( LRWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN
352 CALL XERBLA( 'ZTREVC3', -INFO )
354 ELSE IF( LQUERY ) THEN
358 * Quick return if possible.
363 * Use blocked version of back-transformation if sufficient workspace.
364 * Zero-out the workspace to avoid potential NaN propagation.
366 IF( OVER .AND. LWORK .GE. N + 2*N*NBMIN ) THEN
367 NB = (LWORK - N) / (2*N)
368 NB = MIN( NB, NBMAX )
369 CALL ZLASET( 'F', N, 1+2*NB, CZERO, CZERO, WORK, N )
374 * Set the constants to control overflow.
376 UNFL = DLAMCH( 'Safe minimum' )
378 CALL DLABAD( UNFL, OVFL )
379 ULP = DLAMCH( 'Precision' )
380 SMLNUM = UNFL*( N / ULP )
382 * Store the diagonal elements of T in working array WORK.
385 WORK( I ) = T( I, I )
388 * Compute 1-norm of each column of strictly upper triangular
389 * part of T to control overflow in triangular solver.
393 RWORK( J ) = DZASUM( J-1, T( 1, J ), 1 )
398 * ============================================================
399 * Compute right eigenvectors.
401 * IV is index of column in current block.
402 * Non-blocked version always uses IV=NB=1;
403 * blocked version starts with IV=NB, goes down to 1.
404 * (Note the "0-th" column is used to store the original diagonal.)
409 IF( .NOT.SELECT( KI ) )
412 SMIN = MAX( ULP*( CABS1( T( KI, KI ) ) ), SMLNUM )
414 * --------------------------------------------------------
415 * Complex right eigenvector
417 WORK( KI + IV*N ) = CONE
419 * Form right-hand side.
422 WORK( K + IV*N ) = -T( K, KI )
425 * Solve upper triangular system:
426 * [ T(1:KI-1,1:KI-1) - T(KI,KI) ]*X = SCALE*WORK.
429 T( K, K ) = T( K, K ) - T( KI, KI )
430 IF( CABS1( T( K, K ) ).LT.SMIN )
435 CALL ZLATRS( 'Upper', 'No transpose', 'Non-unit', 'Y',
436 $ KI-1, T, LDT, WORK( 1 + IV*N ), SCALE,
438 WORK( KI + IV*N ) = SCALE
441 * Copy the vector x or Q*x to VR and normalize.
444 * ------------------------------
445 * no back-transform: copy x to VR and normalize.
446 CALL ZCOPY( KI, WORK( 1 + IV*N ), 1, VR( 1, IS ), 1 )
448 II = IZAMAX( KI, VR( 1, IS ), 1 )
449 REMAX = ONE / CABS1( VR( II, IS ) )
450 CALL ZDSCAL( KI, REMAX, VR( 1, IS ), 1 )
456 ELSE IF( NB.EQ.1 ) THEN
457 * ------------------------------
458 * version 1: back-transform each vector with GEMV, Q*x.
460 $ CALL ZGEMV( 'N', N, KI-1, CONE, VR, LDVR,
461 $ WORK( 1 + IV*N ), 1, DCMPLX( SCALE ),
464 II = IZAMAX( N, VR( 1, KI ), 1 )
465 REMAX = ONE / CABS1( VR( II, KI ) )
466 CALL ZDSCAL( N, REMAX, VR( 1, KI ), 1 )
469 * ------------------------------
470 * version 2: back-transform block of vectors with GEMM
471 * zero out below vector
473 WORK( K + IV*N ) = CZERO
476 * Columns IV:NB of work are valid vectors.
477 * When the number of vectors stored reaches NB,
478 * or if this was last vector, do the GEMM
479 IF( (IV.EQ.1) .OR. (KI.EQ.1) ) THEN
480 CALL ZGEMM( 'N', 'N', N, NB-IV+1, KI+NB-IV, CONE,
482 $ WORK( 1 + (IV)*N ), N,
484 $ WORK( 1 + (NB+IV)*N ), N )
487 II = IZAMAX( N, WORK( 1 + (NB+K)*N ), 1 )
488 REMAX = ONE / CABS1( WORK( II + (NB+K)*N ) )
489 CALL ZDSCAL( N, REMAX, WORK( 1 + (NB+K)*N ), 1 )
491 CALL ZLACPY( 'F', N, NB-IV+1,
492 $ WORK( 1 + (NB+IV)*N ), N,
493 $ VR( 1, KI ), LDVR )
500 * Restore the original diagonal elements of T.
503 T( K, K ) = WORK( K )
512 * ============================================================
513 * Compute left eigenvectors.
515 * IV is index of column in current block.
516 * Non-blocked version always uses IV=1;
517 * blocked version starts with IV=1, goes up to NB.
518 * (Note the "0-th" column is used to store the original diagonal.)
524 IF( .NOT.SELECT( KI ) )
527 SMIN = MAX( ULP*( CABS1( T( KI, KI ) ) ), SMLNUM )
529 * --------------------------------------------------------
530 * Complex left eigenvector
532 WORK( KI + IV*N ) = CONE
534 * Form right-hand side.
537 WORK( K + IV*N ) = -CONJG( T( KI, K ) )
540 * Solve conjugate-transposed triangular system:
541 * [ T(KI+1:N,KI+1:N) - T(KI,KI) ]**H * X = SCALE*WORK.
544 T( K, K ) = T( K, K ) - T( KI, KI )
545 IF( CABS1( T( K, K ) ).LT.SMIN )
550 CALL ZLATRS( 'Upper', 'Conjugate transpose', 'Non-unit',
551 $ 'Y', N-KI, T( KI+1, KI+1 ), LDT,
552 $ WORK( KI+1 + IV*N ), SCALE, RWORK, INFO )
553 WORK( KI + IV*N ) = SCALE
556 * Copy the vector x or Q*x to VL and normalize.
559 * ------------------------------
560 * no back-transform: copy x to VL and normalize.
561 CALL ZCOPY( N-KI+1, WORK( KI + IV*N ), 1, VL(KI,IS), 1 )
563 II = IZAMAX( N-KI+1, VL( KI, IS ), 1 ) + KI - 1
564 REMAX = ONE / CABS1( VL( II, IS ) )
565 CALL ZDSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 )
571 ELSE IF( NB.EQ.1 ) THEN
572 * ------------------------------
573 * version 1: back-transform each vector with GEMV, Q*x.
575 $ CALL ZGEMV( 'N', N, N-KI, CONE, VL( 1, KI+1 ), LDVL,
576 $ WORK( KI+1 + IV*N ), 1, DCMPLX( SCALE ),
579 II = IZAMAX( N, VL( 1, KI ), 1 )
580 REMAX = ONE / CABS1( VL( II, KI ) )
581 CALL ZDSCAL( N, REMAX, VL( 1, KI ), 1 )
584 * ------------------------------
585 * version 2: back-transform block of vectors with GEMM
586 * zero out above vector
587 * could go from KI-NV+1 to KI-1
589 WORK( K + IV*N ) = CZERO
592 * Columns 1:IV of work are valid vectors.
593 * When the number of vectors stored reaches NB,
594 * or if this was last vector, do the GEMM
595 IF( (IV.EQ.NB) .OR. (KI.EQ.N) ) THEN
596 CALL ZGEMM( 'N', 'N', N, IV, N-KI+IV, CONE,
597 $ VL( 1, KI-IV+1 ), LDVL,
598 $ WORK( KI-IV+1 + (1)*N ), N,
600 $ WORK( 1 + (NB+1)*N ), N )
603 II = IZAMAX( N, WORK( 1 + (NB+K)*N ), 1 )
604 REMAX = ONE / CABS1( WORK( II + (NB+K)*N ) )
605 CALL ZDSCAL( N, REMAX, WORK( 1 + (NB+K)*N ), 1 )
607 CALL ZLACPY( 'F', N, IV,
608 $ WORK( 1 + (NB+1)*N ), N,
609 $ VL( 1, KI-IV+1 ), LDVL )
616 * Restore the original diagonal elements of T.
619 T( K, K ) = WORK( K )