home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
octave-1.1.1p1-src.tgz
/
tar.out
/
fsf
/
octave
/
libcruft
/
lapack
/
dhseqr.f
< prev
next >
Wrap
Text File
|
1996-09-28
|
16KB
|
455 lines
SUBROUTINE DHSEQR( JOB, COMPZ, N, ILO, IHI, H, LDH, WR, WI, Z,
$ LDZ, WORK, LWORK, INFO )
*
* -- LAPACK routine (version 2.0) --
* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
* Courant Institute, Argonne National Lab, and Rice University
* September 30, 1994
*
* .. Scalar Arguments ..
CHARACTER COMPZ, JOB
INTEGER IHI, ILO, INFO, LDH, LDZ, LWORK, N
* ..
* .. Array Arguments ..
DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ),
$ Z( LDZ, * )
* ..
*
* Purpose
* =======
*
* DHSEQR computes the eigenvalues of a real upper Hessenberg matrix H
* and, optionally, the matrices T and Z from the Schur decomposition
* H = Z T Z**T, where T is an upper quasi-triangular matrix (the Schur
* form), and Z is the orthogonal matrix of Schur vectors.
*
* Optionally Z may be postmultiplied into an input orthogonal matrix Q,
* so that this routine can give the Schur factorization of a matrix A
* which has been reduced to the Hessenberg form H by the orthogonal
* matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T.
*
* Arguments
* =========
*
* JOB (input) CHARACTER*1
* = 'E': compute eigenvalues only;
* = 'S': compute eigenvalues and the Schur form T.
*
* COMPZ (input) CHARACTER*1
* = 'N': no Schur vectors are computed;
* = 'I': Z is initialized to the unit matrix and the matrix Z
* of Schur vectors of H is returned;
* = 'V': Z must contain an orthogonal matrix Q on entry, and
* the product Q*Z is returned.
*
* N (input) INTEGER
* The order of the matrix H. N >= 0.
*
* ILO (input) INTEGER
* IHI (input) INTEGER
* It is assumed that H is already upper triangular in rows
* and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally
* set by a previous call to DGEBAL, and then passed to SGEHRD
* when the matrix output by DGEBAL is reduced to Hessenberg
* form. Otherwise ILO and IHI should be set to 1 and N
* respectively.
* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.
*
* H (input/output) DOUBLE PRECISION array, dimension (LDH,N)
* On entry, the upper Hessenberg matrix H.
* On exit, if JOB = 'S', H contains the upper quasi-triangular
* matrix T from the Schur decomposition (the Schur form);
* 2-by-2 diagonal blocks (corresponding to complex conjugate
* pairs of eigenvalues) are returned in standard form, with
* H(i,i) = H(i+1,i+1) and H(i+1,i)*H(i,i+1) < 0. If JOB = 'E',
* the contents of H are unspecified on exit.
*
* LDH (input) INTEGER
* The leading dimension of the array H. LDH >= max(1,N).
*
* WR (output) DOUBLE PRECISION array, dimension (N)
* WI (output) DOUBLE PRECISION array, dimension (N)
* The real and imaginary parts, respectively, of the computed
* eigenvalues. If two eigenvalues are computed as a complex
* conjugate pair, they are stored in consecutive elements of
* WR and WI, say the i-th and (i+1)th, with WI(i) > 0 and
* WI(i+1) < 0. If JOB = 'S', the eigenvalues are stored in the
* same order as on the diagonal of the Schur form returned in
* H, with WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2
* diagonal block, WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and
* WI(i+1) = -WI(i).
*
* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
* If COMPZ = 'N': Z is not referenced.
* If COMPZ = 'I': on entry, Z need not be set, and on exit, Z
* contains the orthogonal matrix Z of the Schur vectors of H.
* If COMPZ = 'V': on entry Z must contain an N-by-N matrix Q,
* which is assumed to be equal to the unit matrix except for
* the submatrix Z(ILO:IHI,ILO:IHI); on exit Z contains Q*Z.
* Normally Q is the orthogonal matrix generated by DORGHR after
* the call to DGEHRD which formed the Hessenberg matrix H.
*
* LDZ (input) INTEGER
* The leading dimension of the array Z.
* LDZ >= max(1,N) if COMPZ = 'I' or 'V'; LDZ >= 1 otherwise.
*
* WORK (workspace) DOUBLE PRECISION array, dimension (N)
*
* LWORK (input) INTEGER
* This argument is currently redundant.
*
* INFO (output) INTEGER
* = 0: successful exit
* < 0: if INFO = -i, the i-th argument had an illegal value
* > 0: if INFO = i, DHSEQR failed to compute all of the
* eigenvalues in a total of 30*(IHI-ILO+1) iterations;
* elements 1:ilo-1 and i+1:n of WR and WI contain those
* eigenvalues which have been successfully computed.
*
* =====================================================================
*
* .. Parameters ..
DOUBLE PRECISION ZERO, ONE, TWO
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )
DOUBLE PRECISION CONST
PARAMETER ( CONST = 1.5D+0 )
INTEGER NSMAX, LDS
PARAMETER ( NSMAX = 15, LDS = NSMAX )
* ..
* .. Local Scalars ..
LOGICAL INITZ, WANTT, WANTZ
INTEGER I, I1, I2, IERR, II, ITEMP, ITN, ITS, J, K, L,
$ MAXB, NH, NR, NS, NV
DOUBLE PRECISION ABSW, OVFL, SMLNUM, TAU, TEMP, TST1, ULP, UNFL
* ..
* .. Local Arrays ..
DOUBLE PRECISION S( LDS, NSMAX ), V( NSMAX+1 ), VV( NSMAX+1 )
* ..
* .. External Functions ..
LOGICAL LSAME
INTEGER IDAMAX, ILAENV
DOUBLE PRECISION DLAMCH, DLANHS, DLAPY2
EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANHS, DLAPY2
* ..
* .. External Subroutines ..
EXTERNAL DCOPY, DGEMV, DLABAD, DLACPY, DLAHQR, DLARFG,
$ DLARFX, DLASET, DSCAL, XERBLA
* ..
* .. Intrinsic Functions ..
INTRINSIC ABS, MAX, MIN
* ..
* .. Executable Statements ..
*
* Decode and test the input parameters
*
WANTT = LSAME( JOB, 'S' )
INITZ = LSAME( COMPZ, 'I' )
WANTZ = INITZ .OR. LSAME( COMPZ, 'V' )
*
INFO = 0
IF( .NOT.LSAME( JOB, 'E' ) .AND. .NOT.WANTT ) THEN
INFO = -1
ELSE IF( .NOT.LSAME( COMPZ, 'N' ) .AND. .NOT.WANTZ ) THEN
INFO = -2
ELSE IF( N.LT.0 ) THEN
INFO = -3
ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THEN
INFO = -4
ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THEN
INFO = -5
ELSE IF( LDH.LT.MAX( 1, N ) ) THEN
INFO = -7
ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. LDZ.LT.MAX( 1, N ) ) THEN
INFO = -11
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DHSEQR', -INFO )
RETURN
END IF
*
* Initialize Z, if necessary
*
IF( INITZ )
$ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )
*
* Store the eigenvalues isolated by DGEBAL.
*
DO 10 I = 1, ILO - 1
WR( I ) = H( I, I )
WI( I ) = ZERO
10 CONTINUE
DO 20 I = IHI + 1, N
WR( I ) = H( I, I )
WI( I ) = ZERO
20 CONTINUE
*
* Quick return if possible.
*
IF( N.EQ.0 )
$ RETURN
IF( ILO.EQ.IHI ) THEN
WR( ILO ) = H( ILO, ILO )
WI( ILO ) = ZERO
RETURN
END IF
*
* Set rows and columns ILO to IHI to zero below the first
* subdiagonal.
*
DO 40 J = ILO, IHI - 2
DO 30 I = J + 2, N
H( I, J ) = ZERO
30 CONTINUE
40 CONTINUE
NH = IHI - ILO + 1
*
* Determine the order of the multi-shift QR algorithm to be used.
*
NS = ILAENV( 4, 'DHSEQR', JOB // COMPZ, N, ILO, IHI, -1 )
MAXB = ILAENV( 8, 'DHSEQR', JOB // COMPZ, N, ILO, IHI, -1 )
IF( NS.LE.2 .OR. NS.GT.NH .OR. MAXB.GE.NH ) THEN
*
* Use the standard double-shift algorithm
*
CALL DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, ILO,
$ IHI, Z, LDZ, INFO )
RETURN
END IF
MAXB = MAX( 3, MAXB )
NS = MIN( NS, MAXB, NSMAX )
*
* Now 2 < NS <= MAXB < NH.
*
* Set machine-dependent constants for the stopping criterion.
* If norm(H) <= sqrt(OVFL), overflow should not occur.
*
UNFL = DLAMCH( 'Safe minimum' )
OVFL = ONE / UNFL
CALL DLABAD( UNFL, OVFL )
ULP = DLAMCH( 'Precision' )
SMLNUM = UNFL*( NH / ULP )
*
* I1 and I2 are the indices of the first row and last column of H
* to which transformations must be applied. If eigenvalues only are
* being computed, I1 and I2 are set inside the main loop.
*
IF( WANTT ) THEN
I1 = 1
I2 = N
END IF
*
* ITN is the total number of multiple-shift QR iterations allowed.
*
ITN = 30*NH
*
* The main loop begins here. I is the loop index and decreases from
* IHI to ILO in steps of at most MAXB. Each iteration of the loop
* works with the active submatrix in rows and columns L to I.
* Eigenvalues I+1 to IHI have already converged. Either L = ILO or
* H(L,L-1) is negligible so that the matrix splits.
*
I = IHI
50 CONTINUE
L = ILO
IF( I.LT.ILO )
$ GO TO 170
*
* Perform multiple-shift QR iterations on rows and columns ILO to I
* until a submatrix of order at most MAXB splits off at the bottom
* because a subdiagonal element has become negligible.
*
DO 150 ITS = 0, ITN
*
* Look for a single small subdiagonal element.
*
DO 60 K = I, L + 1, -1
TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) )
IF( TST1.EQ.ZERO )
$ TST1 = DLANHS( '1', I-L+1, H( L, L ), LDH, WORK )
IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) )
$ GO TO 70
60 CONTINUE
70 CONTINUE
L = K
IF( L.GT.ILO ) THEN
*
* H(L,L-1) is negligible.
*
H( L, L-1 ) = ZERO
END IF
*
* Exit from loop if a submatrix of order <= MAXB has split off.
*
IF( L.GE.I-MAXB+1 )
$ GO TO 160
*
* Now the active submatrix is in rows and columns L to I. If
* eigenvalues only are being computed, only the active submatrix
* need be transformed.
*
IF( .NOT.WANTT ) THEN
I1 = L
I2 = I
END IF
*
IF( ITS.EQ.20 .OR. ITS.EQ.30 ) THEN
*
* Exceptional shifts.
*
DO 80 II = I - NS + 1, I
WR( II ) = CONST*( ABS( H( II, II-1 ) )+
$ ABS( H( II, II ) ) )
WI( II ) = ZERO
80 CONTINUE
ELSE
*
* Use eigenvalues of trailing submatrix of order NS as shifts.
*
CALL DLACPY( 'Full', NS, NS, H( I-NS+1, I-NS+1 ), LDH, S,
$ LDS )
CALL DLAHQR( .FALSE., .FALSE., NS, 1, NS, S, LDS,
$ WR( I-NS+1 ), WI( I-NS+1 ), 1, NS, Z, LDZ,
$ IERR )
IF( IERR.GT.0 ) THEN
*
* If DLAHQR failed to compute all NS eigenvalues, use the
* unconverged diagonal elements as the remaining shifts.
*
DO 90 II = 1, IERR
WR( I-NS+II ) = S( II, II )
WI( I-NS+II ) = ZERO
90 CONTINUE
END IF
END IF
*
* Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns))
* where G is the Hessenberg submatrix H(L:I,L:I) and w is
* the vector of shifts (stored in WR and WI). The result is
* stored in the local array V.
*
V( 1 ) = ONE
DO 100 II = 2, NS + 1
V( II ) = ZERO
100 CONTINUE
NV = 1
DO 120 J = I - NS + 1, I
IF( WI( J ).GE.ZERO ) THEN
IF( WI( J ).EQ.ZERO ) THEN
*
* real shift
*
CALL DCOPY( NV+1, V, 1, VV, 1 )
CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ),
$ LDH, VV, 1, -WR( J ), V, 1 )
NV = NV + 1
ELSE IF( WI( J ).GT.ZERO ) THEN
*
* complex conjugate pair of shifts
*
CALL DCOPY( NV+1, V, 1, VV, 1 )
CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ),
$ LDH, V, 1, -TWO*WR( J ), VV, 1 )
ITEMP = IDAMAX( NV+1, VV, 1 )
TEMP = ONE / MAX( ABS( VV( ITEMP ) ), SMLNUM )
CALL DSCAL( NV+1, TEMP, VV, 1 )
ABSW = DLAPY2( WR( J ), WI( J ) )
TEMP = ( TEMP*ABSW )*ABSW
CALL DGEMV( 'No transpose', NV+2, NV+1, ONE,
$ H( L, L ), LDH, VV, 1, TEMP, V, 1 )
NV = NV + 2
END IF
*
* Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero,
* reset it to the unit vector.
*
ITEMP = IDAMAX( NV, V, 1 )
TEMP = ABS( V( ITEMP ) )
IF( TEMP.EQ.ZERO ) THEN
V( 1 ) = ONE
DO 110 II = 2, NV
V( II ) = ZERO
110 CONTINUE
ELSE
TEMP = MAX( TEMP, SMLNUM )
CALL DSCAL( NV, ONE / TEMP, V, 1 )
END IF
END IF
120 CONTINUE
*
* Multiple-shift QR step
*
DO 140 K = L, I - 1
*
* The first iteration of this loop determines a reflection G
* from the vector V and applies it from left and right to H,
* thus creating a nonzero bulge below the subdiagonal.
*
* Each subsequent iteration determines a reflection G to
* restore the Hessenberg form in the (K-1)th column, and thus
* chases the bulge one step toward the bottom of the active
* submatrix. NR is the order of G.
*
NR = MIN( NS+1, I-K+1 )
IF( K.GT.L )
$ CALL DCOPY( NR, H( K, K-1 ), 1, V, 1 )
CALL DLARFG( NR, V( 1 ), V( 2 ), 1, TAU )
IF( K.GT.L ) THEN
H( K, K-1 ) = V( 1 )
DO 130 II = K + 1, I
H( II, K-1 ) = ZERO
130 CONTINUE
END IF
V( 1 ) = ONE
*
* Apply G from the left to transform the rows of the matrix in
* columns K to I2.
*
CALL DLARFX( 'Left', NR, I2-K+1, V, TAU, H( K, K ), LDH,
$ WORK )
*
* Apply G from the right to transform the columns of the
* matrix in rows I1 to min(K+NR,I).
*
CALL DLARFX( 'Right', MIN( K+NR, I )-I1+1, NR, V, TAU,
$ H( I1, K ), LDH, WORK )
*
IF( WANTZ ) THEN
*
* Accumulate transformations in the matrix Z
*
CALL DLARFX( 'Right', NH, NR, V, TAU, Z( ILO, K ), LDZ,
$ WORK )
END IF
140 CONTINUE
*
150 CONTINUE
*
* Failure to converge in remaining number of iterations
*
INFO = I
RETURN
*
160 CONTINUE
*
* A submatrix of order <= MAXB in rows and columns L to I has split
* off. Use the double-shift QR algorithm to handle it.
*
CALL DLAHQR( WANTT, WANTZ, N, L, I, H, LDH, WR, WI, ILO, IHI, Z,
$ LDZ, INFO )
IF( INFO.GT.0 )
$ RETURN
*
* Decrement number of remaining iterations, and return to start of
* the main loop with a new value of I.
*
ITN = ITN - ITS
I = L - 1
GO TO 50
*
170 CONTINUE
RETURN
*
* End of DHSEQR
*
END