00001 SUBROUTINE ZGEEV( JOBVL, JOBVR, N, A, LDA, W, VL, LDVL, VR, LDVR,
00002 $ WORK, LWORK, RWORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 CHARACTER JOBVL, JOBVR
00011 INTEGER INFO, LDA, LDVL, LDVR, LWORK, N
00012
00013
00014 DOUBLE PRECISION RWORK( * )
00015 COMPLEX*16 A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ),
00016 $ W( * ), WORK( * )
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 DOUBLE PRECISION ZERO, ONE
00107 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
00108
00109
00110 LOGICAL LQUERY, SCALEA, WANTVL, WANTVR
00111 CHARACTER SIDE
00112 INTEGER HSWORK, I, IBAL, IERR, IHI, ILO, IRWORK, ITAU,
00113 $ IWRK, K, MAXWRK, MINWRK, NOUT
00114 DOUBLE PRECISION ANRM, BIGNUM, CSCALE, EPS, SCL, SMLNUM
00115 COMPLEX*16 TMP
00116
00117
00118 LOGICAL SELECT( 1 )
00119 DOUBLE PRECISION DUM( 1 )
00120
00121
00122 EXTERNAL DLABAD, XERBLA, ZDSCAL, ZGEBAK, ZGEBAL, ZGEHRD,
00123 $ ZHSEQR, ZLACPY, ZLASCL, ZSCAL, ZTREVC, ZUNGHR
00124
00125
00126 LOGICAL LSAME
00127 INTEGER IDAMAX, ILAENV
00128 DOUBLE PRECISION DLAMCH, DZNRM2, ZLANGE
00129 EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DZNRM2, ZLANGE
00130
00131
00132 INTRINSIC DBLE, DCMPLX, DCONJG, DIMAG, MAX, SQRT
00133
00134
00135
00136
00137
00138 INFO = 0
00139 LQUERY = ( LWORK.EQ.-1 )
00140 WANTVL = LSAME( JOBVL, 'V' )
00141 WANTVR = LSAME( JOBVR, 'V' )
00142 IF( ( .NOT.WANTVL ) .AND. ( .NOT.LSAME( JOBVL, 'N' ) ) ) THEN
00143 INFO = -1
00144 ELSE IF( ( .NOT.WANTVR ) .AND. ( .NOT.LSAME( JOBVR, 'N' ) ) ) THEN
00145 INFO = -2
00146 ELSE IF( N.LT.0 ) THEN
00147 INFO = -3
00148 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00149 INFO = -5
00150 ELSE IF( LDVL.LT.1 .OR. ( WANTVL .AND. LDVL.LT.N ) ) THEN
00151 INFO = -8
00152 ELSE IF( LDVR.LT.1 .OR. ( WANTVR .AND. LDVR.LT.N ) ) THEN
00153 INFO = -10
00154 END IF
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 IF( INFO.EQ.0 ) THEN
00168 IF( N.EQ.0 ) THEN
00169 MINWRK = 1
00170 MAXWRK = 1
00171 ELSE
00172 MAXWRK = N + N*ILAENV( 1, 'ZGEHRD', ' ', N, 1, N, 0 )
00173 MINWRK = 2*N
00174 IF( WANTVL ) THEN
00175 MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'ZUNGHR',
00176 $ ' ', N, 1, N, -1 ) )
00177 CALL ZHSEQR( 'S', 'V', N, 1, N, A, LDA, W, VL, LDVL,
00178 $ WORK, -1, INFO )
00179 ELSE IF( WANTVR ) THEN
00180 MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'ZUNGHR',
00181 $ ' ', N, 1, N, -1 ) )
00182 CALL ZHSEQR( 'S', 'V', N, 1, N, A, LDA, W, VR, LDVR,
00183 $ WORK, -1, INFO )
00184 ELSE
00185 CALL ZHSEQR( 'E', 'N', N, 1, N, A, LDA, W, VR, LDVR,
00186 $ WORK, -1, INFO )
00187 END IF
00188 HSWORK = WORK( 1 )
00189 MAXWRK = MAX( MAXWRK, HSWORK, MINWRK )
00190 END IF
00191 WORK( 1 ) = MAXWRK
00192
00193 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00194 INFO = -12
00195 END IF
00196 END IF
00197
00198 IF( INFO.NE.0 ) THEN
00199 CALL XERBLA( 'ZGEEV ', -INFO )
00200 RETURN
00201 ELSE IF( LQUERY ) THEN
00202 RETURN
00203 END IF
00204
00205
00206
00207 IF( N.EQ.0 )
00208 $ RETURN
00209
00210
00211
00212 EPS = DLAMCH( 'P' )
00213 SMLNUM = DLAMCH( 'S' )
00214 BIGNUM = ONE / SMLNUM
00215 CALL DLABAD( SMLNUM, BIGNUM )
00216 SMLNUM = SQRT( SMLNUM ) / EPS
00217 BIGNUM = ONE / SMLNUM
00218
00219
00220
00221 ANRM = ZLANGE( 'M', N, N, A, LDA, DUM )
00222 SCALEA = .FALSE.
00223 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00224 SCALEA = .TRUE.
00225 CSCALE = SMLNUM
00226 ELSE IF( ANRM.GT.BIGNUM ) THEN
00227 SCALEA = .TRUE.
00228 CSCALE = BIGNUM
00229 END IF
00230 IF( SCALEA )
00231 $ CALL ZLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
00232
00233
00234
00235
00236
00237 IBAL = 1
00238 CALL ZGEBAL( 'B', N, A, LDA, ILO, IHI, RWORK( IBAL ), IERR )
00239
00240
00241
00242
00243
00244 ITAU = 1
00245 IWRK = ITAU + N
00246 CALL ZGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
00247 $ LWORK-IWRK+1, IERR )
00248
00249 IF( WANTVL ) THEN
00250
00251
00252
00253
00254 SIDE = 'L'
00255 CALL ZLACPY( 'L', N, N, A, LDA, VL, LDVL )
00256
00257
00258
00259
00260
00261 CALL ZUNGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),
00262 $ LWORK-IWRK+1, IERR )
00263
00264
00265
00266
00267
00268 IWRK = ITAU
00269 CALL ZHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, W, VL, LDVL,
00270 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00271
00272 IF( WANTVR ) THEN
00273
00274
00275
00276
00277 SIDE = 'B'
00278 CALL ZLACPY( 'F', N, N, VL, LDVL, VR, LDVR )
00279 END IF
00280
00281 ELSE IF( WANTVR ) THEN
00282
00283
00284
00285
00286 SIDE = 'R'
00287 CALL ZLACPY( 'L', N, N, A, LDA, VR, LDVR )
00288
00289
00290
00291
00292
00293 CALL ZUNGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),
00294 $ LWORK-IWRK+1, IERR )
00295
00296
00297
00298
00299
00300 IWRK = ITAU
00301 CALL ZHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, W, VR, LDVR,
00302 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00303
00304 ELSE
00305
00306
00307
00308
00309
00310 IWRK = ITAU
00311 CALL ZHSEQR( 'E', 'N', N, ILO, IHI, A, LDA, W, VR, LDVR,
00312 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00313 END IF
00314
00315
00316
00317 IF( INFO.GT.0 )
00318 $ GO TO 50
00319
00320 IF( WANTVL .OR. WANTVR ) THEN
00321
00322
00323
00324
00325
00326 IRWORK = IBAL + N
00327 CALL ZTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
00328 $ N, NOUT, WORK( IWRK ), RWORK( IRWORK ), IERR )
00329 END IF
00330
00331 IF( WANTVL ) THEN
00332
00333
00334
00335
00336
00337 CALL ZGEBAK( 'B', 'L', N, ILO, IHI, RWORK( IBAL ), N, VL, LDVL,
00338 $ IERR )
00339
00340
00341
00342 DO 20 I = 1, N
00343 SCL = ONE / DZNRM2( N, VL( 1, I ), 1 )
00344 CALL ZDSCAL( N, SCL, VL( 1, I ), 1 )
00345 DO 10 K = 1, N
00346 RWORK( IRWORK+K-1 ) = DBLE( VL( K, I ) )**2 +
00347 $ DIMAG( VL( K, I ) )**2
00348 10 CONTINUE
00349 K = IDAMAX( N, RWORK( IRWORK ), 1 )
00350 TMP = DCONJG( VL( K, I ) ) / SQRT( RWORK( IRWORK+K-1 ) )
00351 CALL ZSCAL( N, TMP, VL( 1, I ), 1 )
00352 VL( K, I ) = DCMPLX( DBLE( VL( K, I ) ), ZERO )
00353 20 CONTINUE
00354 END IF
00355
00356 IF( WANTVR ) THEN
00357
00358
00359
00360
00361
00362 CALL ZGEBAK( 'B', 'R', N, ILO, IHI, RWORK( IBAL ), N, VR, LDVR,
00363 $ IERR )
00364
00365
00366
00367 DO 40 I = 1, N
00368 SCL = ONE / DZNRM2( N, VR( 1, I ), 1 )
00369 CALL ZDSCAL( N, SCL, VR( 1, I ), 1 )
00370 DO 30 K = 1, N
00371 RWORK( IRWORK+K-1 ) = DBLE( VR( K, I ) )**2 +
00372 $ DIMAG( VR( K, I ) )**2
00373 30 CONTINUE
00374 K = IDAMAX( N, RWORK( IRWORK ), 1 )
00375 TMP = DCONJG( VR( K, I ) ) / SQRT( RWORK( IRWORK+K-1 ) )
00376 CALL ZSCAL( N, TMP, VR( 1, I ), 1 )
00377 VR( K, I ) = DCMPLX( DBLE( VR( K, I ) ), ZERO )
00378 40 CONTINUE
00379 END IF
00380
00381
00382
00383 50 CONTINUE
00384 IF( SCALEA ) THEN
00385 CALL ZLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, W( INFO+1 ),
00386 $ MAX( N-INFO, 1 ), IERR )
00387 IF( INFO.GT.0 ) THEN
00388 CALL ZLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, W, N, IERR )
00389 END IF
00390 END IF
00391
00392 WORK( 1 ) = MAXWRK
00393 RETURN
00394
00395
00396
00397 END