00001 SUBROUTINE DGGES( JOBVSL, JOBVSR, SORT, SELCTG, N, A, LDA, B, LDB,
00002 $ SDIM, ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR,
00003 $ LDVSR, WORK, LWORK, BWORK, INFO )
00004
00005
00006
00007
00008
00009
00010
00011 CHARACTER JOBVSL, JOBVSR, SORT
00012 INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N, SDIM
00013
00014
00015 LOGICAL BWORK( * )
00016 DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),
00017 $ B( LDB, * ), BETA( * ), VSL( LDVSL, * ),
00018 $ VSR( LDVSR, * ), WORK( * )
00019
00020
00021 LOGICAL SELCTG
00022 EXTERNAL SELCTG
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 DOUBLE PRECISION ZERO, ONE
00190 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
00191
00192
00193 LOGICAL CURSL, ILASCL, ILBSCL, ILVSL, ILVSR, LASTSL,
00194 $ LQUERY, LST2SL, WANTST
00195 INTEGER I, ICOLS, IERR, IHI, IJOBVL, IJOBVR, ILEFT,
00196 $ ILO, IP, IRIGHT, IROWS, ITAU, IWRK, MAXWRK,
00197 $ MINWRK
00198 DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, PVSL,
00199 $ PVSR, SAFMAX, SAFMIN, SMLNUM
00200
00201
00202 INTEGER IDUM( 1 )
00203 DOUBLE PRECISION DIF( 2 )
00204
00205
00206 EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLABAD,
00207 $ DLACPY, DLASCL, DLASET, DORGQR, DORMQR, DTGSEN,
00208 $ XERBLA
00209
00210
00211 LOGICAL LSAME
00212 INTEGER ILAENV
00213 DOUBLE PRECISION DLAMCH, DLANGE
00214 EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE
00215
00216
00217 INTRINSIC ABS, MAX, SQRT
00218
00219
00220
00221
00222
00223 IF( LSAME( JOBVSL, 'N' ) ) THEN
00224 IJOBVL = 1
00225 ILVSL = .FALSE.
00226 ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN
00227 IJOBVL = 2
00228 ILVSL = .TRUE.
00229 ELSE
00230 IJOBVL = -1
00231 ILVSL = .FALSE.
00232 END IF
00233
00234 IF( LSAME( JOBVSR, 'N' ) ) THEN
00235 IJOBVR = 1
00236 ILVSR = .FALSE.
00237 ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN
00238 IJOBVR = 2
00239 ILVSR = .TRUE.
00240 ELSE
00241 IJOBVR = -1
00242 ILVSR = .FALSE.
00243 END IF
00244
00245 WANTST = LSAME( SORT, 'S' )
00246
00247
00248
00249 INFO = 0
00250 LQUERY = ( LWORK.EQ.-1 )
00251 IF( IJOBVL.LE.0 ) THEN
00252 INFO = -1
00253 ELSE IF( IJOBVR.LE.0 ) THEN
00254 INFO = -2
00255 ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN
00256 INFO = -3
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( LDB.LT.MAX( 1, N ) ) THEN
00262 INFO = -9
00263 ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN
00264 INFO = -15
00265 ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN
00266 INFO = -17
00267 END IF
00268
00269
00270
00271
00272
00273
00274
00275
00276 IF( INFO.EQ.0 ) THEN
00277 IF( N.GT.0 )THEN
00278 MINWRK = MAX( 8*N, 6*N + 16 )
00279 MAXWRK = MINWRK - N +
00280 $ N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 )
00281 MAXWRK = MAX( MAXWRK, MINWRK - N +
00282 $ N*ILAENV( 1, 'DORMQR', ' ', N, 1, N, -1 ) )
00283 IF( ILVSL ) THEN
00284 MAXWRK = MAX( MAXWRK, MINWRK - N +
00285 $ N*ILAENV( 1, 'DORGQR', ' ', N, 1, N, -1 ) )
00286 END IF
00287 ELSE
00288 MINWRK = 1
00289 MAXWRK = 1
00290 END IF
00291 WORK( 1 ) = MAXWRK
00292
00293 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY )
00294 $ INFO = -19
00295 END IF
00296
00297 IF( INFO.NE.0 ) THEN
00298 CALL XERBLA( 'DGGES ', -INFO )
00299 RETURN
00300 ELSE IF( LQUERY ) THEN
00301 RETURN
00302 END IF
00303
00304
00305
00306 IF( N.EQ.0 ) THEN
00307 SDIM = 0
00308 RETURN
00309 END IF
00310
00311
00312
00313 EPS = DLAMCH( 'P' )
00314 SAFMIN = DLAMCH( 'S' )
00315 SAFMAX = ONE / SAFMIN
00316 CALL DLABAD( SAFMIN, SAFMAX )
00317 SMLNUM = SQRT( SAFMIN ) / EPS
00318 BIGNUM = ONE / SMLNUM
00319
00320
00321
00322 ANRM = DLANGE( 'M', N, N, A, LDA, WORK )
00323 ILASCL = .FALSE.
00324 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00325 ANRMTO = SMLNUM
00326 ILASCL = .TRUE.
00327 ELSE IF( ANRM.GT.BIGNUM ) THEN
00328 ANRMTO = BIGNUM
00329 ILASCL = .TRUE.
00330 END IF
00331 IF( ILASCL )
00332 $ CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )
00333
00334
00335
00336 BNRM = DLANGE( 'M', N, N, B, LDB, WORK )
00337 ILBSCL = .FALSE.
00338 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00339 BNRMTO = SMLNUM
00340 ILBSCL = .TRUE.
00341 ELSE IF( BNRM.GT.BIGNUM ) THEN
00342 BNRMTO = BIGNUM
00343 ILBSCL = .TRUE.
00344 END IF
00345 IF( ILBSCL )
00346 $ CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )
00347
00348
00349
00350
00351 ILEFT = 1
00352 IRIGHT = N + 1
00353 IWRK = IRIGHT + N
00354 CALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),
00355 $ WORK( IRIGHT ), WORK( IWRK ), IERR )
00356
00357
00358
00359
00360 IROWS = IHI + 1 - ILO
00361 ICOLS = N + 1 - ILO
00362 ITAU = IWRK
00363 IWRK = ITAU + IROWS
00364 CALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),
00365 $ WORK( IWRK ), LWORK+1-IWRK, IERR )
00366
00367
00368
00369
00370 CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,
00371 $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),
00372 $ LWORK+1-IWRK, IERR )
00373
00374
00375
00376
00377 IF( ILVSL ) THEN
00378 CALL DLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL )
00379 IF( IROWS.GT.1 ) THEN
00380 CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,
00381 $ VSL( ILO+1, ILO ), LDVSL )
00382 END IF
00383 CALL DORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL,
00384 $ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )
00385 END IF
00386
00387
00388
00389 IF( ILVSR )
00390 $ CALL DLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR )
00391
00392
00393
00394
00395 CALL DGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL,
00396 $ LDVSL, VSR, LDVSR, IERR )
00397
00398
00399
00400
00401 IWRK = ITAU
00402 CALL DHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB,
00403 $ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,
00404 $ WORK( IWRK ), LWORK+1-IWRK, IERR )
00405 IF( IERR.NE.0 ) THEN
00406 IF( IERR.GT.0 .AND. IERR.LE.N ) THEN
00407 INFO = IERR
00408 ELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THEN
00409 INFO = IERR - N
00410 ELSE
00411 INFO = N + 1
00412 END IF
00413 GO TO 50
00414 END IF
00415
00416
00417
00418
00419 SDIM = 0
00420 IF( WANTST ) THEN
00421
00422
00423
00424 IF( ILASCL ) THEN
00425 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N,
00426 $ IERR )
00427 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N,
00428 $ IERR )
00429 END IF
00430 IF( ILBSCL )
00431 $ CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
00432
00433
00434
00435 DO 10 I = 1, N
00436 BWORK( I ) = SELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )
00437 10 CONTINUE
00438
00439 CALL DTGSEN( 0, ILVSL, ILVSR, BWORK, N, A, LDA, B, LDB, ALPHAR,
00440 $ ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, SDIM, PVSL,
00441 $ PVSR, DIF, WORK( IWRK ), LWORK-IWRK+1, IDUM, 1,
00442 $ IERR )
00443 IF( IERR.EQ.1 )
00444 $ INFO = N + 3
00445
00446 END IF
00447
00448
00449
00450
00451 IF( ILVSL )
00452 $ CALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),
00453 $ WORK( IRIGHT ), N, VSL, LDVSL, IERR )
00454
00455 IF( ILVSR )
00456 $ CALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),
00457 $ WORK( IRIGHT ), N, VSR, LDVSR, IERR )
00458
00459
00460
00461
00462
00463 IF( ILASCL ) THEN
00464 DO 20 I = 1, N
00465 IF( ALPHAI( I ).NE.ZERO ) THEN
00466 IF( ( ALPHAR( I ) / SAFMAX ).GT.( ANRMTO / ANRM ) .OR.
00467 $ ( SAFMIN / ALPHAR( I ) ).GT.( ANRM / ANRMTO ) ) THEN
00468 WORK( 1 ) = ABS( A( I, I ) / ALPHAR( I ) )
00469 BETA( I ) = BETA( I )*WORK( 1 )
00470 ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
00471 ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
00472 ELSE IF( ( ALPHAI( I ) / SAFMAX ).GT.
00473 $ ( ANRMTO / ANRM ) .OR.
00474 $ ( SAFMIN / ALPHAI( I ) ).GT.( ANRM / ANRMTO ) )
00475 $ THEN
00476 WORK( 1 ) = ABS( A( I, I+1 ) / ALPHAI( I ) )
00477 BETA( I ) = BETA( I )*WORK( 1 )
00478 ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
00479 ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
00480 END IF
00481 END IF
00482 20 CONTINUE
00483 END IF
00484
00485 IF( ILBSCL ) THEN
00486 DO 30 I = 1, N
00487 IF( ALPHAI( I ).NE.ZERO ) THEN
00488 IF( ( BETA( I ) / SAFMAX ).GT.( BNRMTO / BNRM ) .OR.
00489 $ ( SAFMIN / BETA( I ) ).GT.( BNRM / BNRMTO ) ) THEN
00490 WORK( 1 ) = ABS( B( I, I ) / BETA( I ) )
00491 BETA( I ) = BETA( I )*WORK( 1 )
00492 ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
00493 ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
00494 END IF
00495 END IF
00496 30 CONTINUE
00497 END IF
00498
00499
00500
00501 IF( ILASCL ) THEN
00502 CALL DLASCL( 'H', 0, 0, ANRMTO, ANRM, N, N, A, LDA, IERR )
00503 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )
00504 CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )
00505 END IF
00506
00507 IF( ILBSCL ) THEN
00508 CALL DLASCL( 'U', 0, 0, BNRMTO, BNRM, N, N, B, LDB, IERR )
00509 CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
00510 END IF
00511
00512 IF( WANTST ) THEN
00513
00514
00515
00516 LASTSL = .TRUE.
00517 LST2SL = .TRUE.
00518 SDIM = 0
00519 IP = 0
00520 DO 40 I = 1, N
00521 CURSL = SELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )
00522 IF( ALPHAI( I ).EQ.ZERO ) THEN
00523 IF( CURSL )
00524 $ SDIM = SDIM + 1
00525 IP = 0
00526 IF( CURSL .AND. .NOT.LASTSL )
00527 $ INFO = N + 2
00528 ELSE
00529 IF( IP.EQ.1 ) THEN
00530
00531
00532
00533 CURSL = CURSL .OR. LASTSL
00534 LASTSL = CURSL
00535 IF( CURSL )
00536 $ SDIM = SDIM + 2
00537 IP = -1
00538 IF( CURSL .AND. .NOT.LST2SL )
00539 $ INFO = N + 2
00540 ELSE
00541
00542
00543
00544 IP = 1
00545 END IF
00546 END IF
00547 LST2SL = LASTSL
00548 LASTSL = CURSL
00549 40 CONTINUE
00550
00551 END IF
00552
00553 50 CONTINUE
00554
00555 WORK( 1 ) = MAXWRK
00556
00557 RETURN
00558
00559
00560
00561 END