00001 SUBROUTINE DGGEVX( BALANC, JOBVL, JOBVR, SENSE, N, A, LDA, B, LDB,
00002 $ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, ILO,
00003 $ IHI, LSCALE, RSCALE, ABNRM, BBNRM, RCONDE,
00004 $ RCONDV, WORK, LWORK, IWORK, BWORK, INFO )
00005
00006
00007
00008
00009
00010
00011
00012 CHARACTER BALANC, JOBVL, JOBVR, SENSE
00013 INTEGER IHI, ILO, INFO, LDA, LDB, LDVL, LDVR, LWORK, N
00014 DOUBLE PRECISION ABNRM, BBNRM
00015
00016
00017 LOGICAL BWORK( * )
00018 INTEGER IWORK( * )
00019 DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),
00020 $ B( LDB, * ), BETA( * ), LSCALE( * ),
00021 $ RCONDE( * ), RCONDV( * ), RSCALE( * ),
00022 $ VL( LDVL, * ), VR( LDVR, * ), WORK( * )
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
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 DOUBLE PRECISION ZERO, ONE
00268 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
00269
00270
00271 LOGICAL ILASCL, ILBSCL, ILV, ILVL, ILVR, LQUERY, NOSCL,
00272 $ PAIR, WANTSB, WANTSE, WANTSN, WANTSV
00273 CHARACTER CHTEMP
00274 INTEGER I, ICOLS, IERR, IJOBVL, IJOBVR, IN, IROWS,
00275 $ ITAU, IWRK, IWRK1, J, JC, JR, M, MAXWRK,
00276 $ MINWRK, MM
00277 DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS,
00278 $ SMLNUM, TEMP
00279
00280
00281 LOGICAL LDUMMA( 1 )
00282
00283
00284 EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLABAD,
00285 $ DLACPY, DLASCL, DLASET, DORGQR, DORMQR, DTGEVC,
00286 $ DTGSNA, XERBLA
00287
00288
00289 LOGICAL LSAME
00290 INTEGER ILAENV
00291 DOUBLE PRECISION DLAMCH, DLANGE
00292 EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE
00293
00294
00295 INTRINSIC ABS, MAX, SQRT
00296
00297
00298
00299
00300
00301 IF( LSAME( JOBVL, 'N' ) ) THEN
00302 IJOBVL = 1
00303 ILVL = .FALSE.
00304 ELSE IF( LSAME( JOBVL, 'V' ) ) THEN
00305 IJOBVL = 2
00306 ILVL = .TRUE.
00307 ELSE
00308 IJOBVL = -1
00309 ILVL = .FALSE.
00310 END IF
00311
00312 IF( LSAME( JOBVR, 'N' ) ) THEN
00313 IJOBVR = 1
00314 ILVR = .FALSE.
00315 ELSE IF( LSAME( JOBVR, 'V' ) ) THEN
00316 IJOBVR = 2
00317 ILVR = .TRUE.
00318 ELSE
00319 IJOBVR = -1
00320 ILVR = .FALSE.
00321 END IF
00322 ILV = ILVL .OR. ILVR
00323
00324 NOSCL = LSAME( BALANC, 'N' ) .OR. LSAME( BALANC, 'P' )
00325 WANTSN = LSAME( SENSE, 'N' )
00326 WANTSE = LSAME( SENSE, 'E' )
00327 WANTSV = LSAME( SENSE, 'V' )
00328 WANTSB = LSAME( SENSE, 'B' )
00329
00330
00331
00332 INFO = 0
00333 LQUERY = ( LWORK.EQ.-1 )
00334 IF( .NOT.( LSAME( BALANC, 'N' ) .OR. LSAME( BALANC,
00335 $ 'S' ) .OR. LSAME( BALANC, 'P' ) .OR. LSAME( BALANC, 'B' ) ) )
00336 $ THEN
00337 INFO = -1
00338 ELSE IF( IJOBVL.LE.0 ) THEN
00339 INFO = -2
00340 ELSE IF( IJOBVR.LE.0 ) THEN
00341 INFO = -3
00342 ELSE IF( .NOT.( WANTSN .OR. WANTSE .OR. WANTSB .OR. WANTSV ) )
00343 $ THEN
00344 INFO = -4
00345 ELSE IF( N.LT.0 ) THEN
00346 INFO = -5
00347 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00348 INFO = -7
00349 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00350 INFO = -9
00351 ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN
00352 INFO = -14
00353 ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN
00354 INFO = -16
00355 END IF
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 IF( INFO.EQ.0 ) THEN
00366 IF( N.EQ.0 ) THEN
00367 MINWRK = 1
00368 MAXWRK = 1
00369 ELSE
00370 IF( NOSCL .AND. .NOT.ILV ) THEN
00371 MINWRK = 2*N
00372 ELSE
00373 MINWRK = 6*N
00374 END IF
00375 IF( WANTSE .OR. WANTSB ) THEN
00376 MINWRK = 10*N
00377 END IF
00378 IF( WANTSV .OR. WANTSB ) THEN
00379 MINWRK = MAX( MINWRK, 2*N*( N + 4 ) + 16 )
00380 END IF
00381 MAXWRK = MINWRK
00382 MAXWRK = MAX( MAXWRK,
00383 $ N + N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 ) )
00384 MAXWRK = MAX( MAXWRK,
00385 $ N + N*ILAENV( 1, 'DORMQR', ' ', N, 1, N, 0 ) )
00386 IF( ILVL ) THEN
00387 MAXWRK = MAX( MAXWRK, N +
00388 $ N*ILAENV( 1, 'DORGQR', ' ', N, 1, N, 0 ) )
00389 END IF
00390 END IF
00391 WORK( 1 ) = MAXWRK
00392
00393 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00394 INFO = -26
00395 END IF
00396 END IF
00397
00398 IF( INFO.NE.0 ) THEN
00399 CALL XERBLA( 'DGGEVX', -INFO )
00400 RETURN
00401 ELSE IF( LQUERY ) THEN
00402 RETURN
00403 END IF
00404
00405
00406
00407 IF( N.EQ.0 )
00408 $ RETURN
00409
00410
00411
00412
00413 EPS = DLAMCH( 'P' )
00414 SMLNUM = DLAMCH( 'S' )
00415 BIGNUM = ONE / SMLNUM
00416 CALL DLABAD( SMLNUM, BIGNUM )
00417 SMLNUM = SQRT( SMLNUM ) / EPS
00418 BIGNUM = ONE / SMLNUM
00419
00420
00421
00422 ANRM = DLANGE( 'M', N, N, A, LDA, WORK )
00423 ILASCL = .FALSE.
00424 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00425 ANRMTO = SMLNUM
00426 ILASCL = .TRUE.
00427 ELSE IF( ANRM.GT.BIGNUM ) THEN
00428 ANRMTO = BIGNUM
00429 ILASCL = .TRUE.
00430 END IF
00431 IF( ILASCL )
00432 $ CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )
00433
00434
00435
00436 BNRM = DLANGE( 'M', N, N, B, LDB, WORK )
00437 ILBSCL = .FALSE.
00438 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00439 BNRMTO = SMLNUM
00440 ILBSCL = .TRUE.
00441 ELSE IF( BNRM.GT.BIGNUM ) THEN
00442 BNRMTO = BIGNUM
00443 ILBSCL = .TRUE.
00444 END IF
00445 IF( ILBSCL )
00446 $ CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )
00447
00448
00449
00450
00451 CALL DGGBAL( BALANC, N, A, LDA, B, LDB, ILO, IHI, LSCALE, RSCALE,
00452 $ WORK, IERR )
00453
00454
00455
00456 ABNRM = DLANGE( '1', N, N, A, LDA, WORK( 1 ) )
00457 IF( ILASCL ) THEN
00458 WORK( 1 ) = ABNRM
00459 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, 1, 1, WORK( 1 ), 1,
00460 $ IERR )
00461 ABNRM = WORK( 1 )
00462 END IF
00463
00464 BBNRM = DLANGE( '1', N, N, B, LDB, WORK( 1 ) )
00465 IF( ILBSCL ) THEN
00466 WORK( 1 ) = BBNRM
00467 CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, 1, 1, WORK( 1 ), 1,
00468 $ IERR )
00469 BBNRM = WORK( 1 )
00470 END IF
00471
00472
00473
00474
00475 IROWS = IHI + 1 - ILO
00476 IF( ILV .OR. .NOT.WANTSN ) THEN
00477 ICOLS = N + 1 - ILO
00478 ELSE
00479 ICOLS = IROWS
00480 END IF
00481 ITAU = 1
00482 IWRK = ITAU + IROWS
00483 CALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),
00484 $ WORK( IWRK ), LWORK+1-IWRK, IERR )
00485
00486
00487
00488
00489 CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,
00490 $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),
00491 $ LWORK+1-IWRK, IERR )
00492
00493
00494
00495
00496 IF( ILVL ) THEN
00497 CALL DLASET( 'Full', N, N, ZERO, ONE, VL, LDVL )
00498 IF( IROWS.GT.1 ) THEN
00499 CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,
00500 $ VL( ILO+1, ILO ), LDVL )
00501 END IF
00502 CALL DORGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL,
00503 $ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )
00504 END IF
00505
00506 IF( ILVR )
00507 $ CALL DLASET( 'Full', N, N, ZERO, ONE, VR, LDVR )
00508
00509
00510
00511
00512 IF( ILV .OR. .NOT.WANTSN ) THEN
00513
00514
00515
00516 CALL DGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL,
00517 $ LDVL, VR, LDVR, IERR )
00518 ELSE
00519 CALL DGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA,
00520 $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IERR )
00521 END IF
00522
00523
00524
00525
00526
00527 IF( ILV .OR. .NOT.WANTSN ) THEN
00528 CHTEMP = 'S'
00529 ELSE
00530 CHTEMP = 'E'
00531 END IF
00532
00533 CALL DHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB,
00534 $ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, WORK,
00535 $ LWORK, IERR )
00536 IF( IERR.NE.0 ) THEN
00537 IF( IERR.GT.0 .AND. IERR.LE.N ) THEN
00538 INFO = IERR
00539 ELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THEN
00540 INFO = IERR - N
00541 ELSE
00542 INFO = N + 1
00543 END IF
00544 GO TO 130
00545 END IF
00546
00547
00548
00549
00550
00551
00552 IF( ILV .OR. .NOT.WANTSN ) THEN
00553 IF( ILV ) THEN
00554 IF( ILVL ) THEN
00555 IF( ILVR ) THEN
00556 CHTEMP = 'B'
00557 ELSE
00558 CHTEMP = 'L'
00559 END IF
00560 ELSE
00561 CHTEMP = 'R'
00562 END IF
00563
00564 CALL DTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL,
00565 $ LDVL, VR, LDVR, N, IN, WORK, IERR )
00566 IF( IERR.NE.0 ) THEN
00567 INFO = N + 2
00568 GO TO 130
00569 END IF
00570 END IF
00571
00572 IF( .NOT.WANTSN ) THEN
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 PAIR = .FALSE.
00583 DO 20 I = 1, N
00584
00585 IF( PAIR ) THEN
00586 PAIR = .FALSE.
00587 GO TO 20
00588 END IF
00589 MM = 1
00590 IF( I.LT.N ) THEN
00591 IF( A( I+1, I ).NE.ZERO ) THEN
00592 PAIR = .TRUE.
00593 MM = 2
00594 END IF
00595 END IF
00596
00597 DO 10 J = 1, N
00598 BWORK( J ) = .FALSE.
00599 10 CONTINUE
00600 IF( MM.EQ.1 ) THEN
00601 BWORK( I ) = .TRUE.
00602 ELSE IF( MM.EQ.2 ) THEN
00603 BWORK( I ) = .TRUE.
00604 BWORK( I+1 ) = .TRUE.
00605 END IF
00606
00607 IWRK = MM*N + 1
00608 IWRK1 = IWRK + MM*N
00609
00610
00611
00612
00613 IF( WANTSE .OR. WANTSB ) THEN
00614 CALL DTGEVC( 'B', 'S', BWORK, N, A, LDA, B, LDB,
00615 $ WORK( 1 ), N, WORK( IWRK ), N, MM, M,
00616 $ WORK( IWRK1 ), IERR )
00617 IF( IERR.NE.0 ) THEN
00618 INFO = N + 2
00619 GO TO 130
00620 END IF
00621 END IF
00622
00623 CALL DTGSNA( SENSE, 'S', BWORK, N, A, LDA, B, LDB,
00624 $ WORK( 1 ), N, WORK( IWRK ), N, RCONDE( I ),
00625 $ RCONDV( I ), MM, M, WORK( IWRK1 ),
00626 $ LWORK-IWRK1+1, IWORK, IERR )
00627
00628 20 CONTINUE
00629 END IF
00630 END IF
00631
00632
00633
00634
00635 IF( ILVL ) THEN
00636 CALL DGGBAK( BALANC, 'L', N, ILO, IHI, LSCALE, RSCALE, N, VL,
00637 $ LDVL, IERR )
00638
00639 DO 70 JC = 1, N
00640 IF( ALPHAI( JC ).LT.ZERO )
00641 $ GO TO 70
00642 TEMP = ZERO
00643 IF( ALPHAI( JC ).EQ.ZERO ) THEN
00644 DO 30 JR = 1, N
00645 TEMP = MAX( TEMP, ABS( VL( JR, JC ) ) )
00646 30 CONTINUE
00647 ELSE
00648 DO 40 JR = 1, N
00649 TEMP = MAX( TEMP, ABS( VL( JR, JC ) )+
00650 $ ABS( VL( JR, JC+1 ) ) )
00651 40 CONTINUE
00652 END IF
00653 IF( TEMP.LT.SMLNUM )
00654 $ GO TO 70
00655 TEMP = ONE / TEMP
00656 IF( ALPHAI( JC ).EQ.ZERO ) THEN
00657 DO 50 JR = 1, N
00658 VL( JR, JC ) = VL( JR, JC )*TEMP
00659 50 CONTINUE
00660 ELSE
00661 DO 60 JR = 1, N
00662 VL( JR, JC ) = VL( JR, JC )*TEMP
00663 VL( JR, JC+1 ) = VL( JR, JC+1 )*TEMP
00664 60 CONTINUE
00665 END IF
00666 70 CONTINUE
00667 END IF
00668 IF( ILVR ) THEN
00669 CALL DGGBAK( BALANC, 'R', N, ILO, IHI, LSCALE, RSCALE, N, VR,
00670 $ LDVR, IERR )
00671 DO 120 JC = 1, N
00672 IF( ALPHAI( JC ).LT.ZERO )
00673 $ GO TO 120
00674 TEMP = ZERO
00675 IF( ALPHAI( JC ).EQ.ZERO ) THEN
00676 DO 80 JR = 1, N
00677 TEMP = MAX( TEMP, ABS( VR( JR, JC ) ) )
00678 80 CONTINUE
00679 ELSE
00680 DO 90 JR = 1, N
00681 TEMP = MAX( TEMP, ABS( VR( JR, JC ) )+
00682 $ ABS( VR( JR, JC+1 ) ) )
00683 90 CONTINUE
00684 END IF
00685 IF( TEMP.LT.SMLNUM )
00686 $ GO TO 120
00687 TEMP = ONE / TEMP
00688 IF( ALPHAI( JC ).EQ.ZERO ) THEN
00689 DO 100 JR = 1, N
00690 VR( JR, JC ) = VR( JR, JC )*TEMP
00691 100 CONTINUE
00692 ELSE
00693 DO 110 JR = 1, N
00694 VR( JR, JC ) = VR( JR, JC )*TEMP
00695 VR( JR, JC+1 ) = VR( JR, JC+1 )*TEMP
00696 110 CONTINUE
00697 END IF
00698 120 CONTINUE
00699 END IF
00700
00701
00702
00703 IF( ILASCL ) THEN
00704 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )
00705 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )
00706 END IF
00707
00708 IF( ILBSCL ) THEN
00709 CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
00710 END IF
00711
00712 130 CONTINUE
00713 WORK( 1 ) = MAXWRK
00714
00715 RETURN
00716
00717
00718
00719 END