00001 SUBROUTINE ZGGES( JOBVSL, JOBVSR, SORT, SELCTG, N, A, LDA, B, LDB,
00002 $ SDIM, ALPHA, BETA, VSL, LDVSL, VSR, LDVSR, WORK,
00003 $ LWORK, RWORK, 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 RWORK( * )
00017 COMPLEX*16 A( LDA, * ), ALPHA( * ), B( LDB, * ),
00018 $ BETA( * ), VSL( LDVSL, * ), VSR( LDVSR, * ),
00019 $ WORK( * )
00020
00021
00022 LOGICAL SELCTG
00023 EXTERNAL SELCTG
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 DOUBLE PRECISION ZERO, ONE
00177 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
00178 COMPLEX*16 CZERO, CONE
00179 PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ),
00180 $ CONE = ( 1.0D0, 0.0D0 ) )
00181
00182
00183 LOGICAL CURSL, ILASCL, ILBSCL, ILVSL, ILVSR, LASTSL,
00184 $ LQUERY, WANTST
00185 INTEGER I, ICOLS, IERR, IHI, IJOBVL, IJOBVR, ILEFT,
00186 $ ILO, IRIGHT, IROWS, IRWRK, ITAU, IWRK, LWKMIN,
00187 $ LWKOPT
00188 DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, PVSL,
00189 $ PVSR, SMLNUM
00190
00191
00192 INTEGER IDUM( 1 )
00193 DOUBLE PRECISION DIF( 2 )
00194
00195
00196 EXTERNAL DLABAD, XERBLA, ZGEQRF, ZGGBAK, ZGGBAL, ZGGHRD,
00197 $ ZHGEQZ, ZLACPY, ZLASCL, ZLASET, ZTGSEN, ZUNGQR,
00198 $ ZUNMQR
00199
00200
00201 LOGICAL LSAME
00202 INTEGER ILAENV
00203 DOUBLE PRECISION DLAMCH, ZLANGE
00204 EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE
00205
00206
00207 INTRINSIC MAX, SQRT
00208
00209
00210
00211
00212
00213 IF( LSAME( JOBVSL, 'N' ) ) THEN
00214 IJOBVL = 1
00215 ILVSL = .FALSE.
00216 ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN
00217 IJOBVL = 2
00218 ILVSL = .TRUE.
00219 ELSE
00220 IJOBVL = -1
00221 ILVSL = .FALSE.
00222 END IF
00223
00224 IF( LSAME( JOBVSR, 'N' ) ) THEN
00225 IJOBVR = 1
00226 ILVSR = .FALSE.
00227 ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN
00228 IJOBVR = 2
00229 ILVSR = .TRUE.
00230 ELSE
00231 IJOBVR = -1
00232 ILVSR = .FALSE.
00233 END IF
00234
00235 WANTST = LSAME( SORT, 'S' )
00236
00237
00238
00239 INFO = 0
00240 LQUERY = ( LWORK.EQ.-1 )
00241 IF( IJOBVL.LE.0 ) THEN
00242 INFO = -1
00243 ELSE IF( IJOBVR.LE.0 ) THEN
00244 INFO = -2
00245 ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN
00246 INFO = -3
00247 ELSE IF( N.LT.0 ) THEN
00248 INFO = -5
00249 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00250 INFO = -7
00251 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00252 INFO = -9
00253 ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN
00254 INFO = -14
00255 ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN
00256 INFO = -16
00257 END IF
00258
00259
00260
00261
00262
00263
00264
00265
00266 IF( INFO.EQ.0 ) THEN
00267 LWKMIN = MAX( 1, 2*N )
00268 LWKOPT = MAX( 1, N + N*ILAENV( 1, 'ZGEQRF', ' ', N, 1, N, 0 ) )
00269 LWKOPT = MAX( LWKOPT, N +
00270 $ N*ILAENV( 1, 'ZUNMQR', ' ', N, 1, N, -1 ) )
00271 IF( ILVSL ) THEN
00272 LWKOPT = MAX( LWKOPT, N +
00273 $ N*ILAENV( 1, 'ZUNGQR', ' ', N, 1, N, -1 ) )
00274 END IF
00275 WORK( 1 ) = LWKOPT
00276
00277 IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY )
00278 $ INFO = -18
00279 END IF
00280
00281 IF( INFO.NE.0 ) THEN
00282 CALL XERBLA( 'ZGGES ', -INFO )
00283 RETURN
00284 ELSE IF( LQUERY ) THEN
00285 RETURN
00286 END IF
00287
00288
00289
00290 IF( N.EQ.0 ) THEN
00291 SDIM = 0
00292 RETURN
00293 END IF
00294
00295
00296
00297 EPS = DLAMCH( 'P' )
00298 SMLNUM = DLAMCH( 'S' )
00299 BIGNUM = ONE / SMLNUM
00300 CALL DLABAD( SMLNUM, BIGNUM )
00301 SMLNUM = SQRT( SMLNUM ) / EPS
00302 BIGNUM = ONE / SMLNUM
00303
00304
00305
00306 ANRM = ZLANGE( 'M', N, N, A, LDA, RWORK )
00307 ILASCL = .FALSE.
00308 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00309 ANRMTO = SMLNUM
00310 ILASCL = .TRUE.
00311 ELSE IF( ANRM.GT.BIGNUM ) THEN
00312 ANRMTO = BIGNUM
00313 ILASCL = .TRUE.
00314 END IF
00315
00316 IF( ILASCL )
00317 $ CALL ZLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )
00318
00319
00320
00321 BNRM = ZLANGE( 'M', N, N, B, LDB, RWORK )
00322 ILBSCL = .FALSE.
00323 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00324 BNRMTO = SMLNUM
00325 ILBSCL = .TRUE.
00326 ELSE IF( BNRM.GT.BIGNUM ) THEN
00327 BNRMTO = BIGNUM
00328 ILBSCL = .TRUE.
00329 END IF
00330
00331 IF( ILBSCL )
00332 $ CALL ZLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )
00333
00334
00335
00336
00337 ILEFT = 1
00338 IRIGHT = N + 1
00339 IRWRK = IRIGHT + N
00340 CALL ZGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ),
00341 $ RWORK( IRIGHT ), RWORK( IRWRK ), IERR )
00342
00343
00344
00345
00346 IROWS = IHI + 1 - ILO
00347 ICOLS = N + 1 - ILO
00348 ITAU = 1
00349 IWRK = ITAU + IROWS
00350 CALL ZGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),
00351 $ WORK( IWRK ), LWORK+1-IWRK, IERR )
00352
00353
00354
00355
00356 CALL ZUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,
00357 $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),
00358 $ LWORK+1-IWRK, IERR )
00359
00360
00361
00362
00363 IF( ILVSL ) THEN
00364 CALL ZLASET( 'Full', N, N, CZERO, CONE, VSL, LDVSL )
00365 IF( IROWS.GT.1 ) THEN
00366 CALL ZLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,
00367 $ VSL( ILO+1, ILO ), LDVSL )
00368 END IF
00369 CALL ZUNGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL,
00370 $ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )
00371 END IF
00372
00373
00374
00375 IF( ILVSR )
00376 $ CALL ZLASET( 'Full', N, N, CZERO, CONE, VSR, LDVSR )
00377
00378
00379
00380
00381 CALL ZGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL,
00382 $ LDVSL, VSR, LDVSR, IERR )
00383
00384 SDIM = 0
00385
00386
00387
00388
00389
00390 IWRK = ITAU
00391 CALL ZHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB,
00392 $ ALPHA, BETA, VSL, LDVSL, VSR, LDVSR, WORK( IWRK ),
00393 $ LWORK+1-IWRK, RWORK( IRWRK ), IERR )
00394 IF( IERR.NE.0 ) THEN
00395 IF( IERR.GT.0 .AND. IERR.LE.N ) THEN
00396 INFO = IERR
00397 ELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THEN
00398 INFO = IERR - N
00399 ELSE
00400 INFO = N + 1
00401 END IF
00402 GO TO 30
00403 END IF
00404
00405
00406
00407
00408 IF( WANTST ) THEN
00409
00410
00411
00412 IF( ILASCL )
00413 $ CALL ZLASCL( 'G', 0, 0, ANRM, ANRMTO, N, 1, ALPHA, N, IERR )
00414 IF( ILBSCL )
00415 $ CALL ZLASCL( 'G', 0, 0, BNRM, BNRMTO, N, 1, BETA, N, IERR )
00416
00417
00418
00419 DO 10 I = 1, N
00420 BWORK( I ) = SELCTG( ALPHA( I ), BETA( I ) )
00421 10 CONTINUE
00422
00423 CALL ZTGSEN( 0, ILVSL, ILVSR, BWORK, N, A, LDA, B, LDB, ALPHA,
00424 $ BETA, VSL, LDVSL, VSR, LDVSR, SDIM, PVSL, PVSR,
00425 $ DIF, WORK( IWRK ), LWORK-IWRK+1, IDUM, 1, IERR )
00426 IF( IERR.EQ.1 )
00427 $ INFO = N + 3
00428
00429 END IF
00430
00431
00432
00433
00434 IF( ILVSL )
00435 $ CALL ZGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ),
00436 $ RWORK( IRIGHT ), N, VSL, LDVSL, IERR )
00437 IF( ILVSR )
00438 $ CALL ZGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ),
00439 $ RWORK( IRIGHT ), N, VSR, LDVSR, IERR )
00440
00441
00442
00443 IF( ILASCL ) THEN
00444 CALL ZLASCL( 'U', 0, 0, ANRMTO, ANRM, N, N, A, LDA, IERR )
00445 CALL ZLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHA, N, IERR )
00446 END IF
00447
00448 IF( ILBSCL ) THEN
00449 CALL ZLASCL( 'U', 0, 0, BNRMTO, BNRM, N, N, B, LDB, IERR )
00450 CALL ZLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
00451 END IF
00452
00453 IF( WANTST ) THEN
00454
00455
00456
00457 LASTSL = .TRUE.
00458 SDIM = 0
00459 DO 20 I = 1, N
00460 CURSL = SELCTG( ALPHA( I ), BETA( I ) )
00461 IF( CURSL )
00462 $ SDIM = SDIM + 1
00463 IF( CURSL .AND. .NOT.LASTSL )
00464 $ INFO = N + 2
00465 LASTSL = CURSL
00466 20 CONTINUE
00467
00468 END IF
00469
00470 30 CONTINUE
00471
00472 WORK( 1 ) = LWKOPT
00473
00474 RETURN
00475
00476
00477
00478 END