00001 SUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR,
00002 $ LDVR, WORK, LWORK, 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 A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ),
00015 $ WI( * ), WORK( * ), WR( * )
00016
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
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 DOUBLE PRECISION ZERO, ONE
00118 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
00119
00120
00121 LOGICAL LQUERY, SCALEA, WANTVL, WANTVR
00122 CHARACTER SIDE
00123 INTEGER HSWORK, I, IBAL, IERR, IHI, ILO, ITAU, IWRK, K,
00124 $ MAXWRK, MINWRK, NOUT
00125 DOUBLE PRECISION ANRM, BIGNUM, CS, CSCALE, EPS, R, SCL, SMLNUM,
00126 $ SN
00127
00128
00129 LOGICAL SELECT( 1 )
00130 DOUBLE PRECISION DUM( 1 )
00131
00132
00133 EXTERNAL DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLABAD, DLACPY,
00134 $ DLARTG, DLASCL, DORGHR, DROT, DSCAL, DTREVC,
00135 $ XERBLA
00136
00137
00138 LOGICAL LSAME
00139 INTEGER IDAMAX, ILAENV
00140 DOUBLE PRECISION DLAMCH, DLANGE, DLAPY2, DNRM2
00141 EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANGE, DLAPY2,
00142 $ DNRM2
00143
00144
00145 INTRINSIC MAX, SQRT
00146
00147
00148
00149
00150
00151 INFO = 0
00152 LQUERY = ( LWORK.EQ.-1 )
00153 WANTVL = LSAME( JOBVL, 'V' )
00154 WANTVR = LSAME( JOBVR, 'V' )
00155 IF( ( .NOT.WANTVL ) .AND. ( .NOT.LSAME( JOBVL, 'N' ) ) ) THEN
00156 INFO = -1
00157 ELSE IF( ( .NOT.WANTVR ) .AND. ( .NOT.LSAME( JOBVR, 'N' ) ) ) THEN
00158 INFO = -2
00159 ELSE IF( N.LT.0 ) THEN
00160 INFO = -3
00161 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00162 INFO = -5
00163 ELSE IF( LDVL.LT.1 .OR. ( WANTVL .AND. LDVL.LT.N ) ) THEN
00164 INFO = -9
00165 ELSE IF( LDVR.LT.1 .OR. ( WANTVR .AND. LDVR.LT.N ) ) THEN
00166 INFO = -11
00167 END IF
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 IF( INFO.EQ.0 ) THEN
00180 IF( N.EQ.0 ) THEN
00181 MINWRK = 1
00182 MAXWRK = 1
00183 ELSE
00184 MAXWRK = 2*N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 )
00185 IF( WANTVL ) THEN
00186 MINWRK = 4*N
00187 MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
00188 $ 'DORGHR', ' ', N, 1, N, -1 ) )
00189 CALL DHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VL, LDVL,
00190 $ WORK, -1, INFO )
00191 HSWORK = WORK( 1 )
00192 MAXWRK = MAX( MAXWRK, N + 1, N + HSWORK )
00193 MAXWRK = MAX( MAXWRK, 4*N )
00194 ELSE IF( WANTVR ) THEN
00195 MINWRK = 4*N
00196 MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
00197 $ 'DORGHR', ' ', N, 1, N, -1 ) )
00198 CALL DHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VR, LDVR,
00199 $ WORK, -1, INFO )
00200 HSWORK = WORK( 1 )
00201 MAXWRK = MAX( MAXWRK, N + 1, N + HSWORK )
00202 MAXWRK = MAX( MAXWRK, 4*N )
00203 ELSE
00204 MINWRK = 3*N
00205 CALL DHSEQR( 'E', 'N', N, 1, N, A, LDA, WR, WI, VR, LDVR,
00206 $ WORK, -1, INFO )
00207 HSWORK = WORK( 1 )
00208 MAXWRK = MAX( MAXWRK, N + 1, N + HSWORK )
00209 END IF
00210 MAXWRK = MAX( MAXWRK, MINWRK )
00211 END IF
00212 WORK( 1 ) = MAXWRK
00213
00214 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00215 INFO = -13
00216 END IF
00217 END IF
00218
00219 IF( INFO.NE.0 ) THEN
00220 CALL XERBLA( 'DGEEV ', -INFO )
00221 RETURN
00222 ELSE IF( LQUERY ) THEN
00223 RETURN
00224 END IF
00225
00226
00227
00228 IF( N.EQ.0 )
00229 $ RETURN
00230
00231
00232
00233 EPS = DLAMCH( 'P' )
00234 SMLNUM = DLAMCH( 'S' )
00235 BIGNUM = ONE / SMLNUM
00236 CALL DLABAD( SMLNUM, BIGNUM )
00237 SMLNUM = SQRT( SMLNUM ) / EPS
00238 BIGNUM = ONE / SMLNUM
00239
00240
00241
00242 ANRM = DLANGE( 'M', N, N, A, LDA, DUM )
00243 SCALEA = .FALSE.
00244 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00245 SCALEA = .TRUE.
00246 CSCALE = SMLNUM
00247 ELSE IF( ANRM.GT.BIGNUM ) THEN
00248 SCALEA = .TRUE.
00249 CSCALE = BIGNUM
00250 END IF
00251 IF( SCALEA )
00252 $ CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
00253
00254
00255
00256
00257 IBAL = 1
00258 CALL DGEBAL( 'B', N, A, LDA, ILO, IHI, WORK( IBAL ), IERR )
00259
00260
00261
00262
00263 ITAU = IBAL + N
00264 IWRK = ITAU + N
00265 CALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
00266 $ LWORK-IWRK+1, IERR )
00267
00268 IF( WANTVL ) THEN
00269
00270
00271
00272
00273 SIDE = 'L'
00274 CALL DLACPY( 'L', N, N, A, LDA, VL, LDVL )
00275
00276
00277
00278
00279 CALL DORGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),
00280 $ LWORK-IWRK+1, IERR )
00281
00282
00283
00284
00285 IWRK = ITAU
00286 CALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VL, LDVL,
00287 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00288
00289 IF( WANTVR ) THEN
00290
00291
00292
00293
00294 SIDE = 'B'
00295 CALL DLACPY( 'F', N, N, VL, LDVL, VR, LDVR )
00296 END IF
00297
00298 ELSE IF( WANTVR ) THEN
00299
00300
00301
00302
00303 SIDE = 'R'
00304 CALL DLACPY( 'L', N, N, A, LDA, VR, LDVR )
00305
00306
00307
00308
00309 CALL DORGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),
00310 $ LWORK-IWRK+1, IERR )
00311
00312
00313
00314
00315 IWRK = ITAU
00316 CALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,
00317 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00318
00319 ELSE
00320
00321
00322
00323
00324 IWRK = ITAU
00325 CALL DHSEQR( 'E', 'N', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,
00326 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00327 END IF
00328
00329
00330
00331 IF( INFO.GT.0 )
00332 $ GO TO 50
00333
00334 IF( WANTVL .OR. WANTVR ) THEN
00335
00336
00337
00338
00339 CALL DTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
00340 $ N, NOUT, WORK( IWRK ), IERR )
00341 END IF
00342
00343 IF( WANTVL ) THEN
00344
00345
00346
00347
00348 CALL DGEBAK( 'B', 'L', N, ILO, IHI, WORK( IBAL ), N, VL, LDVL,
00349 $ IERR )
00350
00351
00352
00353 DO 20 I = 1, N
00354 IF( WI( I ).EQ.ZERO ) THEN
00355 SCL = ONE / DNRM2( N, VL( 1, I ), 1 )
00356 CALL DSCAL( N, SCL, VL( 1, I ), 1 )
00357 ELSE IF( WI( I ).GT.ZERO ) THEN
00358 SCL = ONE / DLAPY2( DNRM2( N, VL( 1, I ), 1 ),
00359 $ DNRM2( N, VL( 1, I+1 ), 1 ) )
00360 CALL DSCAL( N, SCL, VL( 1, I ), 1 )
00361 CALL DSCAL( N, SCL, VL( 1, I+1 ), 1 )
00362 DO 10 K = 1, N
00363 WORK( IWRK+K-1 ) = VL( K, I )**2 + VL( K, I+1 )**2
00364 10 CONTINUE
00365 K = IDAMAX( N, WORK( IWRK ), 1 )
00366 CALL DLARTG( VL( K, I ), VL( K, I+1 ), CS, SN, R )
00367 CALL DROT( N, VL( 1, I ), 1, VL( 1, I+1 ), 1, CS, SN )
00368 VL( K, I+1 ) = ZERO
00369 END IF
00370 20 CONTINUE
00371 END IF
00372
00373 IF( WANTVR ) THEN
00374
00375
00376
00377
00378 CALL DGEBAK( 'B', 'R', N, ILO, IHI, WORK( IBAL ), N, VR, LDVR,
00379 $ IERR )
00380
00381
00382
00383 DO 40 I = 1, N
00384 IF( WI( I ).EQ.ZERO ) THEN
00385 SCL = ONE / DNRM2( N, VR( 1, I ), 1 )
00386 CALL DSCAL( N, SCL, VR( 1, I ), 1 )
00387 ELSE IF( WI( I ).GT.ZERO ) THEN
00388 SCL = ONE / DLAPY2( DNRM2( N, VR( 1, I ), 1 ),
00389 $ DNRM2( N, VR( 1, I+1 ), 1 ) )
00390 CALL DSCAL( N, SCL, VR( 1, I ), 1 )
00391 CALL DSCAL( N, SCL, VR( 1, I+1 ), 1 )
00392 DO 30 K = 1, N
00393 WORK( IWRK+K-1 ) = VR( K, I )**2 + VR( K, I+1 )**2
00394 30 CONTINUE
00395 K = IDAMAX( N, WORK( IWRK ), 1 )
00396 CALL DLARTG( VR( K, I ), VR( K, I+1 ), CS, SN, R )
00397 CALL DROT( N, VR( 1, I ), 1, VR( 1, I+1 ), 1, CS, SN )
00398 VR( K, I+1 ) = ZERO
00399 END IF
00400 40 CONTINUE
00401 END IF
00402
00403
00404
00405 50 CONTINUE
00406 IF( SCALEA ) THEN
00407 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WR( INFO+1 ),
00408 $ MAX( N-INFO, 1 ), IERR )
00409 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WI( INFO+1 ),
00410 $ MAX( N-INFO, 1 ), IERR )
00411 IF( INFO.GT.0 ) THEN
00412 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WR, N,
00413 $ IERR )
00414 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI, N,
00415 $ IERR )
00416 END IF
00417 END IF
00418
00419 WORK( 1 ) = MAXWRK
00420 RETURN
00421
00422
00423
00424 END