00001 SUBROUTINE DGEEVX( BALANC, JOBVL, JOBVR, SENSE, N, A, LDA, WR, WI,
00002 $ VL, LDVL, VR, LDVR, ILO, IHI, SCALE, ABNRM,
00003 $ RCONDE, RCONDV, WORK, LWORK, IWORK, INFO )
00004
00005
00006
00007
00008
00009
00010
00011 CHARACTER BALANC, JOBVL, JOBVR, SENSE
00012 INTEGER IHI, ILO, INFO, LDA, LDVL, LDVR, LWORK, N
00013 DOUBLE PRECISION ABNRM
00014
00015
00016 INTEGER IWORK( * )
00017 DOUBLE PRECISION A( LDA, * ), RCONDE( * ), RCONDV( * ),
00018 $ SCALE( * ), VL( LDVL, * ), VR( LDVR, * ),
00019 $ WI( * ), WORK( * ), WR( * )
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
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 DOUBLE PRECISION ZERO, ONE
00203 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
00204
00205
00206 LOGICAL LQUERY, SCALEA, WANTVL, WANTVR, WNTSNB, WNTSNE,
00207 $ WNTSNN, WNTSNV
00208 CHARACTER JOB, SIDE
00209 INTEGER HSWORK, I, ICOND, IERR, ITAU, IWRK, K, MAXWRK,
00210 $ MINWRK, NOUT
00211 DOUBLE PRECISION ANRM, BIGNUM, CS, CSCALE, EPS, R, SCL, SMLNUM,
00212 $ SN
00213
00214
00215 LOGICAL SELECT( 1 )
00216 DOUBLE PRECISION DUM( 1 )
00217
00218
00219 EXTERNAL DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLABAD, DLACPY,
00220 $ DLARTG, DLASCL, DORGHR, DROT, DSCAL, DTREVC,
00221 $ DTRSNA, XERBLA
00222
00223
00224 LOGICAL LSAME
00225 INTEGER IDAMAX, ILAENV
00226 DOUBLE PRECISION DLAMCH, DLANGE, DLAPY2, DNRM2
00227 EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANGE, DLAPY2,
00228 $ DNRM2
00229
00230
00231 INTRINSIC MAX, SQRT
00232
00233
00234
00235
00236
00237 INFO = 0
00238 LQUERY = ( LWORK.EQ.-1 )
00239 WANTVL = LSAME( JOBVL, 'V' )
00240 WANTVR = LSAME( JOBVR, 'V' )
00241 WNTSNN = LSAME( SENSE, 'N' )
00242 WNTSNE = LSAME( SENSE, 'E' )
00243 WNTSNV = LSAME( SENSE, 'V' )
00244 WNTSNB = LSAME( SENSE, 'B' )
00245 IF( .NOT.( LSAME( BALANC, 'N' ) .OR. LSAME( BALANC,
00246 $ 'S' ) .OR. LSAME( BALANC, 'P' ) .OR. LSAME( BALANC, 'B' ) ) )
00247 $ THEN
00248 INFO = -1
00249 ELSE IF( ( .NOT.WANTVL ) .AND. ( .NOT.LSAME( JOBVL, 'N' ) ) ) THEN
00250 INFO = -2
00251 ELSE IF( ( .NOT.WANTVR ) .AND. ( .NOT.LSAME( JOBVR, 'N' ) ) ) THEN
00252 INFO = -3
00253 ELSE IF( .NOT.( WNTSNN .OR. WNTSNE .OR. WNTSNB .OR. WNTSNV ) .OR.
00254 $ ( ( WNTSNE .OR. WNTSNB ) .AND. .NOT.( WANTVL .AND.
00255 $ WANTVR ) ) ) THEN
00256 INFO = -4
00257 ELSE IF( N.LT.0 ) THEN
00258 INFO = -5
00259 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00260 INFO = -7
00261 ELSE IF( LDVL.LT.1 .OR. ( WANTVL .AND. LDVL.LT.N ) ) THEN
00262 INFO = -11
00263 ELSE IF( LDVR.LT.1 .OR. ( WANTVR .AND. LDVR.LT.N ) ) THEN
00264 INFO = -13
00265 END IF
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 IF( INFO.EQ.0 ) THEN
00278 IF( N.EQ.0 ) THEN
00279 MINWRK = 1
00280 MAXWRK = 1
00281 ELSE
00282 MAXWRK = N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 )
00283
00284 IF( WANTVL ) THEN
00285 CALL DHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VL, LDVL,
00286 $ WORK, -1, INFO )
00287 ELSE IF( WANTVR ) THEN
00288 CALL DHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VR, LDVR,
00289 $ WORK, -1, INFO )
00290 ELSE
00291 IF( WNTSNN ) THEN
00292 CALL DHSEQR( 'E', 'N', N, 1, N, A, LDA, WR, WI, VR,
00293 $ LDVR, WORK, -1, INFO )
00294 ELSE
00295 CALL DHSEQR( 'S', 'N', N, 1, N, A, LDA, WR, WI, VR,
00296 $ LDVR, WORK, -1, INFO )
00297 END IF
00298 END IF
00299 HSWORK = WORK( 1 )
00300
00301 IF( ( .NOT.WANTVL ) .AND. ( .NOT.WANTVR ) ) THEN
00302 MINWRK = 2*N
00303 IF( .NOT.WNTSNN )
00304 $ MINWRK = MAX( MINWRK, N*N+6*N )
00305 MAXWRK = MAX( MAXWRK, HSWORK )
00306 IF( .NOT.WNTSNN )
00307 $ MAXWRK = MAX( MAXWRK, N*N + 6*N )
00308 ELSE
00309 MINWRK = 3*N
00310 IF( ( .NOT.WNTSNN ) .AND. ( .NOT.WNTSNE ) )
00311 $ MINWRK = MAX( MINWRK, N*N + 6*N )
00312 MAXWRK = MAX( MAXWRK, HSWORK )
00313 MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'DORGHR',
00314 $ ' ', N, 1, N, -1 ) )
00315 IF( ( .NOT.WNTSNN ) .AND. ( .NOT.WNTSNE ) )
00316 $ MAXWRK = MAX( MAXWRK, N*N + 6*N )
00317 MAXWRK = MAX( MAXWRK, 3*N )
00318 END IF
00319 MAXWRK = MAX( MAXWRK, MINWRK )
00320 END IF
00321 WORK( 1 ) = MAXWRK
00322
00323 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00324 INFO = -21
00325 END IF
00326 END IF
00327
00328 IF( INFO.NE.0 ) THEN
00329 CALL XERBLA( 'DGEEVX', -INFO )
00330 RETURN
00331 ELSE IF( LQUERY ) THEN
00332 RETURN
00333 END IF
00334
00335
00336
00337 IF( N.EQ.0 )
00338 $ RETURN
00339
00340
00341
00342 EPS = DLAMCH( 'P' )
00343 SMLNUM = DLAMCH( 'S' )
00344 BIGNUM = ONE / SMLNUM
00345 CALL DLABAD( SMLNUM, BIGNUM )
00346 SMLNUM = SQRT( SMLNUM ) / EPS
00347 BIGNUM = ONE / SMLNUM
00348
00349
00350
00351 ICOND = 0
00352 ANRM = DLANGE( 'M', N, N, A, LDA, DUM )
00353 SCALEA = .FALSE.
00354 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00355 SCALEA = .TRUE.
00356 CSCALE = SMLNUM
00357 ELSE IF( ANRM.GT.BIGNUM ) THEN
00358 SCALEA = .TRUE.
00359 CSCALE = BIGNUM
00360 END IF
00361 IF( SCALEA )
00362 $ CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
00363
00364
00365
00366 CALL DGEBAL( BALANC, N, A, LDA, ILO, IHI, SCALE, IERR )
00367 ABNRM = DLANGE( '1', N, N, A, LDA, DUM )
00368 IF( SCALEA ) THEN
00369 DUM( 1 ) = ABNRM
00370 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, 1, 1, DUM, 1, IERR )
00371 ABNRM = DUM( 1 )
00372 END IF
00373
00374
00375
00376
00377 ITAU = 1
00378 IWRK = ITAU + N
00379 CALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
00380 $ LWORK-IWRK+1, IERR )
00381
00382 IF( WANTVL ) THEN
00383
00384
00385
00386
00387 SIDE = 'L'
00388 CALL DLACPY( 'L', N, N, A, LDA, VL, LDVL )
00389
00390
00391
00392
00393 CALL DORGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),
00394 $ LWORK-IWRK+1, IERR )
00395
00396
00397
00398
00399 IWRK = ITAU
00400 CALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VL, LDVL,
00401 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00402
00403 IF( WANTVR ) THEN
00404
00405
00406
00407
00408 SIDE = 'B'
00409 CALL DLACPY( 'F', N, N, VL, LDVL, VR, LDVR )
00410 END IF
00411
00412 ELSE IF( WANTVR ) THEN
00413
00414
00415
00416
00417 SIDE = 'R'
00418 CALL DLACPY( 'L', N, N, A, LDA, VR, LDVR )
00419
00420
00421
00422
00423 CALL DORGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),
00424 $ LWORK-IWRK+1, IERR )
00425
00426
00427
00428
00429 IWRK = ITAU
00430 CALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,
00431 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00432
00433 ELSE
00434
00435
00436
00437
00438 IF( WNTSNN ) THEN
00439 JOB = 'E'
00440 ELSE
00441 JOB = 'S'
00442 END IF
00443
00444
00445
00446 IWRK = ITAU
00447 CALL DHSEQR( JOB, 'N', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,
00448 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00449 END IF
00450
00451
00452
00453 IF( INFO.GT.0 )
00454 $ GO TO 50
00455
00456 IF( WANTVL .OR. WANTVR ) THEN
00457
00458
00459
00460
00461 CALL DTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
00462 $ N, NOUT, WORK( IWRK ), IERR )
00463 END IF
00464
00465
00466
00467
00468 IF( .NOT.WNTSNN ) THEN
00469 CALL DTRSNA( SENSE, 'A', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
00470 $ RCONDE, RCONDV, N, NOUT, WORK( IWRK ), N, IWORK,
00471 $ ICOND )
00472 END IF
00473
00474 IF( WANTVL ) THEN
00475
00476
00477
00478 CALL DGEBAK( BALANC, 'L', N, ILO, IHI, SCALE, N, VL, LDVL,
00479 $ IERR )
00480
00481
00482
00483 DO 20 I = 1, N
00484 IF( WI( I ).EQ.ZERO ) THEN
00485 SCL = ONE / DNRM2( N, VL( 1, I ), 1 )
00486 CALL DSCAL( N, SCL, VL( 1, I ), 1 )
00487 ELSE IF( WI( I ).GT.ZERO ) THEN
00488 SCL = ONE / DLAPY2( DNRM2( N, VL( 1, I ), 1 ),
00489 $ DNRM2( N, VL( 1, I+1 ), 1 ) )
00490 CALL DSCAL( N, SCL, VL( 1, I ), 1 )
00491 CALL DSCAL( N, SCL, VL( 1, I+1 ), 1 )
00492 DO 10 K = 1, N
00493 WORK( K ) = VL( K, I )**2 + VL( K, I+1 )**2
00494 10 CONTINUE
00495 K = IDAMAX( N, WORK, 1 )
00496 CALL DLARTG( VL( K, I ), VL( K, I+1 ), CS, SN, R )
00497 CALL DROT( N, VL( 1, I ), 1, VL( 1, I+1 ), 1, CS, SN )
00498 VL( K, I+1 ) = ZERO
00499 END IF
00500 20 CONTINUE
00501 END IF
00502
00503 IF( WANTVR ) THEN
00504
00505
00506
00507 CALL DGEBAK( BALANC, 'R', N, ILO, IHI, SCALE, N, VR, LDVR,
00508 $ IERR )
00509
00510
00511
00512 DO 40 I = 1, N
00513 IF( WI( I ).EQ.ZERO ) THEN
00514 SCL = ONE / DNRM2( N, VR( 1, I ), 1 )
00515 CALL DSCAL( N, SCL, VR( 1, I ), 1 )
00516 ELSE IF( WI( I ).GT.ZERO ) THEN
00517 SCL = ONE / DLAPY2( DNRM2( N, VR( 1, I ), 1 ),
00518 $ DNRM2( N, VR( 1, I+1 ), 1 ) )
00519 CALL DSCAL( N, SCL, VR( 1, I ), 1 )
00520 CALL DSCAL( N, SCL, VR( 1, I+1 ), 1 )
00521 DO 30 K = 1, N
00522 WORK( K ) = VR( K, I )**2 + VR( K, I+1 )**2
00523 30 CONTINUE
00524 K = IDAMAX( N, WORK, 1 )
00525 CALL DLARTG( VR( K, I ), VR( K, I+1 ), CS, SN, R )
00526 CALL DROT( N, VR( 1, I ), 1, VR( 1, I+1 ), 1, CS, SN )
00527 VR( K, I+1 ) = ZERO
00528 END IF
00529 40 CONTINUE
00530 END IF
00531
00532
00533
00534 50 CONTINUE
00535 IF( SCALEA ) THEN
00536 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WR( INFO+1 ),
00537 $ MAX( N-INFO, 1 ), IERR )
00538 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WI( INFO+1 ),
00539 $ MAX( N-INFO, 1 ), IERR )
00540 IF( INFO.EQ.0 ) THEN
00541 IF( ( WNTSNV .OR. WNTSNB ) .AND. ICOND.EQ.0 )
00542 $ CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, RCONDV, N,
00543 $ IERR )
00544 ELSE
00545 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WR, N,
00546 $ IERR )
00547 CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI, N,
00548 $ IERR )
00549 END IF
00550 END IF
00551
00552 WORK( 1 ) = MAXWRK
00553 RETURN
00554
00555
00556
00557 END