00001 SUBROUTINE DGGESX( JOBVSL, JOBVSR, SORT, SELCTG, SENSE, N, A, LDA,
00002 $ B, LDB, SDIM, ALPHAR, ALPHAI, BETA, VSL, LDVSL,
00003 $ VSR, LDVSR, RCONDE, RCONDV, WORK, LWORK, IWORK,
00004 $ LIWORK, BWORK, INFO )
00005
00006
00007
00008
00009
00010
00011
00012 CHARACTER JOBVSL, JOBVSR, SENSE, SORT
00013 INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LIWORK, LWORK, N,
00014 $ SDIM
00015
00016
00017 LOGICAL BWORK( * )
00018 INTEGER IWORK( * )
00019 DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),
00020 $ B( LDB, * ), BETA( * ), RCONDE( 2 ),
00021 $ RCONDV( 2 ), VSL( LDVSL, * ), VSR( LDVSR, * ),
00022 $ WORK( * )
00023
00024
00025 LOGICAL SELCTG
00026 EXTERNAL SELCTG
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 DOUBLE PRECISION ZERO, ONE
00252 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
00253
00254
00255 LOGICAL CURSL, ILASCL, ILBSCL, ILVSL, ILVSR, LASTSL,
00256 $ LQUERY, LST2SL, WANTSB, WANTSE, WANTSN, WANTST,
00257 $ WANTSV
00258 INTEGER I, ICOLS, IERR, IHI, IJOB, IJOBVL, IJOBVR,
00259 $ ILEFT, ILO, IP, IRIGHT, IROWS, ITAU, IWRK,
00260 $ LIWMIN, LWRK, MAXWRK, MINWRK
00261 DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, PL,
00262 $ PR, SAFMAX, SAFMIN, SMLNUM
00263
00264
00265 DOUBLE PRECISION DIF( 2 )
00266
00267
00268 EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLABAD,
00269 $ DLACPY, DLASCL, DLASET, DORGQR, DORMQR, DTGSEN,
00270 $ XERBLA
00271
00272
00273 LOGICAL LSAME
00274 INTEGER ILAENV
00275 DOUBLE PRECISION DLAMCH, DLANGE
00276 EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE
00277
00278
00279 INTRINSIC ABS, MAX, SQRT
00280
00281
00282
00283
00284
00285 IF( LSAME( JOBVSL, 'N' ) ) THEN
00286 IJOBVL = 1
00287 ILVSL = .FALSE.
00288 ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN
00289 IJOBVL = 2
00290 ILVSL = .TRUE.
00291 ELSE
00292 IJOBVL = -1
00293 ILVSL = .FALSE.
00294 END IF
00295
00296 IF( LSAME( JOBVSR, 'N' ) ) THEN
00297 IJOBVR = 1
00298 ILVSR = .FALSE.
00299 ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN
00300 IJOBVR = 2
00301 ILVSR = .TRUE.
00302 ELSE
00303 IJOBVR = -1
00304 ILVSR = .FALSE.
00305 END IF
00306
00307 WANTST = LSAME( SORT, 'S' )
00308 WANTSN = LSAME( SENSE, 'N' )
00309 WANTSE = LSAME( SENSE, 'E' )
00310 WANTSV = LSAME( SENSE, 'V' )
00311 WANTSB = LSAME( SENSE, 'B' )
00312 LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )
00313 IF( WANTSN ) THEN
00314 IJOB = 0
00315 ELSE IF( WANTSE ) THEN
00316 IJOB = 1
00317 ELSE IF( WANTSV ) THEN
00318 IJOB = 2
00319 ELSE IF( WANTSB ) THEN
00320 IJOB = 4
00321 END IF
00322
00323
00324
00325 INFO = 0
00326 IF( IJOBVL.LE.0 ) THEN
00327 INFO = -1
00328 ELSE IF( IJOBVR.LE.0 ) THEN
00329 INFO = -2
00330 ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN
00331 INFO = -3
00332 ELSE IF( .NOT.( WANTSN .OR. WANTSE .OR. WANTSV .OR. WANTSB ) .OR.
00333 $ ( .NOT.WANTST .AND. .NOT.WANTSN ) ) THEN
00334 INFO = -5
00335 ELSE IF( N.LT.0 ) THEN
00336 INFO = -6
00337 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00338 INFO = -8
00339 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00340 INFO = -10
00341 ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN
00342 INFO = -16
00343 ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN
00344 INFO = -18
00345 END IF
00346
00347
00348
00349
00350
00351
00352
00353
00354 IF( INFO.EQ.0 ) THEN
00355 IF( N.GT.0) THEN
00356 MINWRK = MAX( 8*N, 6*N + 16 )
00357 MAXWRK = MINWRK - N +
00358 $ N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 )
00359 MAXWRK = MAX( MAXWRK, MINWRK - N +
00360 $ N*ILAENV( 1, 'DORMQR', ' ', N, 1, N, -1 ) )
00361 IF( ILVSL ) THEN
00362 MAXWRK = MAX( MAXWRK, MINWRK - N +
00363 $ N*ILAENV( 1, 'DORGQR', ' ', N, 1, N, -1 ) )
00364 END IF
00365 LWRK = MAXWRK
00366 IF( IJOB.GE.1 )
00367 $ LWRK = MAX( LWRK, N*N/2 )
00368 ELSE
00369 MINWRK = 1
00370 MAXWRK = 1
00371 LWRK = 1
00372 END IF
00373 WORK( 1 ) = LWRK
00374 IF( WANTSN .OR. N.EQ.0 ) THEN
00375 LIWMIN = 1
00376 ELSE
00377 LIWMIN = N + 6
00378 END IF
00379 IWORK( 1 ) = LIWMIN
00380
00381 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00382 INFO = -22
00383 ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
00384 INFO = -24
00385 END IF
00386 END IF
00387
00388 IF( INFO.NE.0 ) THEN
00389 CALL XERBLA( 'DGGESX', -INFO )
00390 RETURN
00391 ELSE IF (LQUERY) THEN
00392 RETURN
00393 END IF
00394
00395
00396
00397 IF( N.EQ.0 ) THEN
00398 SDIM = 0
00399 RETURN
00400 END IF
00401
00402
00403
00404 EPS = DLAMCH( 'P' )
00405 SAFMIN = DLAMCH( 'S' )
00406 SAFMAX = ONE / SAFMIN
00407 CALL DLABAD( SAFMIN, SAFMAX )
00408 SMLNUM = SQRT( SAFMIN ) / EPS
00409 BIGNUM = ONE / SMLNUM
00410
00411
00412
00413 ANRM = DLANGE( 'M', N, N, A, LDA, WORK )
00414 ILASCL = .FALSE.
00415 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00416 ANRMTO = SMLNUM
00417 ILASCL = .TRUE.
00418 ELSE IF( ANRM.GT.BIGNUM ) THEN
00419 ANRMTO = BIGNUM
00420 ILASCL = .TRUE.
00421 END IF
00422 IF( ILASCL )
00423 $ CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )
00424
00425
00426
00427 BNRM = DLANGE( 'M', N, N, B, LDB, WORK )
00428 ILBSCL = .FALSE.
00429 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00430 BNRMTO = SMLNUM
00431 ILBSCL = .TRUE.
00432 ELSE IF( BNRM.GT.BIGNUM ) THEN
00433 BNRMTO = BIGNUM
00434 ILBSCL = .TRUE.
00435 END IF
00436 IF( ILBSCL )
00437 $ CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )
00438
00439
00440
00441
00442 ILEFT = 1
00443 IRIGHT = N + 1
00444 IWRK = IRIGHT + N
00445 CALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),
00446 $ WORK( IRIGHT ), WORK( IWRK ), IERR )
00447
00448
00449
00450
00451 IROWS = IHI + 1 - ILO
00452 ICOLS = N + 1 - ILO
00453 ITAU = IWRK
00454 IWRK = ITAU + IROWS
00455 CALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),
00456 $ WORK( IWRK ), LWORK+1-IWRK, IERR )
00457
00458
00459
00460
00461 CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,
00462 $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),
00463 $ LWORK+1-IWRK, IERR )
00464
00465
00466
00467
00468 IF( ILVSL ) THEN
00469 CALL DLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL )
00470 IF( IROWS.GT.1 ) THEN
00471 CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,
00472 $ VSL( ILO+1, ILO ), LDVSL )
00473 END IF
00474 CALL DORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL,
00475 $ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )
00476 END IF
00477
00478
00479
00480 IF( ILVSR )
00481 $ CALL DLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR )
00482
00483
00484
00485
00486 CALL DGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL,
00487 $ LDVSL, VSR, LDVSR, IERR )
00488
00489 SDIM = 0
00490
00491
00492
00493
00494 IWRK = ITAU
00495 CALL DHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB,
00496 $ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,
00497 $ WORK( IWRK ), LWORK+1-IWRK, IERR )
00498 IF( IERR.NE.0 ) THEN
00499 IF( IERR.GT.0 .AND. IERR.LE.N ) THEN
00500 INFO = IERR
00501 ELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THEN
00502 INFO = IERR - N
00503 ELSE
00504 INFO = N + 1
00505 END IF
00506 GO TO 60
00507 END IF
00508
00509
00510
00511
00512
00513
00514 IF( WANTST ) THEN
00515
00516
00517
00518 IF( ILASCL ) THEN
00519 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N,
00520 $ IERR )
00521 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N,
00522 $ IERR )
00523 END IF
00524 IF( ILBSCL )
00525 $ CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
00526
00527
00528
00529 DO 10 I = 1, N
00530 BWORK( I ) = SELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )
00531 10 CONTINUE
00532
00533
00534
00535
00536 CALL DTGSEN( IJOB, ILVSL, ILVSR, BWORK, N, A, LDA, B, LDB,
00537 $ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,
00538 $ SDIM, PL, PR, DIF, WORK( IWRK ), LWORK-IWRK+1,
00539 $ IWORK, LIWORK, IERR )
00540
00541 IF( IJOB.GE.1 )
00542 $ MAXWRK = MAX( MAXWRK, 2*SDIM*( N-SDIM ) )
00543 IF( IERR.EQ.-22 ) THEN
00544
00545
00546
00547 INFO = -22
00548 ELSE
00549 IF( IJOB.EQ.1 .OR. IJOB.EQ.4 ) THEN
00550 RCONDE( 1 ) = PL
00551 RCONDE( 2 ) = PR
00552 END IF
00553 IF( IJOB.EQ.2 .OR. IJOB.EQ.4 ) THEN
00554 RCONDV( 1 ) = DIF( 1 )
00555 RCONDV( 2 ) = DIF( 2 )
00556 END IF
00557 IF( IERR.EQ.1 )
00558 $ INFO = N + 3
00559 END IF
00560
00561 END IF
00562
00563
00564
00565
00566 IF( ILVSL )
00567 $ CALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),
00568 $ WORK( IRIGHT ), N, VSL, LDVSL, IERR )
00569
00570 IF( ILVSR )
00571 $ CALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),
00572 $ WORK( IRIGHT ), N, VSR, LDVSR, IERR )
00573
00574
00575
00576
00577
00578 IF( ILASCL ) THEN
00579 DO 20 I = 1, N
00580 IF( ALPHAI( I ).NE.ZERO ) THEN
00581 IF( ( ALPHAR( I ) / SAFMAX ).GT.( ANRMTO / ANRM ) .OR.
00582 $ ( SAFMIN / ALPHAR( I ) ).GT.( ANRM / ANRMTO ) ) THEN
00583 WORK( 1 ) = ABS( A( I, I ) / ALPHAR( I ) )
00584 BETA( I ) = BETA( I )*WORK( 1 )
00585 ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
00586 ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
00587 ELSE IF( ( ALPHAI( I ) / SAFMAX ).GT.
00588 $ ( ANRMTO / ANRM ) .OR.
00589 $ ( SAFMIN / ALPHAI( I ) ).GT.( ANRM / ANRMTO ) )
00590 $ THEN
00591 WORK( 1 ) = ABS( A( I, I+1 ) / ALPHAI( I ) )
00592 BETA( I ) = BETA( I )*WORK( 1 )
00593 ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
00594 ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
00595 END IF
00596 END IF
00597 20 CONTINUE
00598 END IF
00599
00600 IF( ILBSCL ) THEN
00601 DO 30 I = 1, N
00602 IF( ALPHAI( I ).NE.ZERO ) THEN
00603 IF( ( BETA( I ) / SAFMAX ).GT.( BNRMTO / BNRM ) .OR.
00604 $ ( SAFMIN / BETA( I ) ).GT.( BNRM / BNRMTO ) ) THEN
00605 WORK( 1 ) = ABS( B( I, I ) / BETA( I ) )
00606 BETA( I ) = BETA( I )*WORK( 1 )
00607 ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
00608 ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
00609 END IF
00610 END IF
00611 30 CONTINUE
00612 END IF
00613
00614
00615
00616 IF( ILASCL ) THEN
00617 CALL DLASCL( 'H', 0, 0, ANRMTO, ANRM, N, N, A, LDA, IERR )
00618 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )
00619 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )
00620 END IF
00621
00622 IF( ILBSCL ) THEN
00623 CALL DLASCL( 'U', 0, 0, BNRMTO, BNRM, N, N, B, LDB, IERR )
00624 CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
00625 END IF
00626
00627 IF( WANTST ) THEN
00628
00629
00630
00631 LASTSL = .TRUE.
00632 LST2SL = .TRUE.
00633 SDIM = 0
00634 IP = 0
00635 DO 50 I = 1, N
00636 CURSL = SELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )
00637 IF( ALPHAI( I ).EQ.ZERO ) THEN
00638 IF( CURSL )
00639 $ SDIM = SDIM + 1
00640 IP = 0
00641 IF( CURSL .AND. .NOT.LASTSL )
00642 $ INFO = N + 2
00643 ELSE
00644 IF( IP.EQ.1 ) THEN
00645
00646
00647
00648 CURSL = CURSL .OR. LASTSL
00649 LASTSL = CURSL
00650 IF( CURSL )
00651 $ SDIM = SDIM + 2
00652 IP = -1
00653 IF( CURSL .AND. .NOT.LST2SL )
00654 $ INFO = N + 2
00655 ELSE
00656
00657
00658
00659 IP = 1
00660 END IF
00661 END IF
00662 LST2SL = LASTSL
00663 LASTSL = CURSL
00664 50 CONTINUE
00665
00666 END IF
00667
00668 60 CONTINUE
00669
00670 WORK( 1 ) = MAXWRK
00671 IWORK( 1 ) = LIWMIN
00672
00673 RETURN
00674
00675
00676
00677 END