00001 SUBROUTINE ZGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA,
00002 $ VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 CHARACTER JOBVL, JOBVR
00011 INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N
00012
00013
00014 DOUBLE PRECISION RWORK( * )
00015 COMPLEX*16 A( LDA, * ), ALPHA( * ), B( LDB, * ),
00016 $ BETA( * ), VL( LDVL, * ), VR( LDVR, * ),
00017 $ WORK( * )
00018
00019
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 DOUBLE PRECISION ZERO, ONE
00201 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
00202 COMPLEX*16 CZERO, CONE
00203 PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ),
00204 $ CONE = ( 1.0D0, 0.0D0 ) )
00205
00206
00207 LOGICAL ILIMIT, ILV, ILVL, ILVR, LQUERY
00208 CHARACTER CHTEMP
00209 INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO,
00210 $ IN, IRIGHT, IROWS, IRWORK, ITAU, IWORK, JC, JR,
00211 $ LOPT, LWKMIN, LWKOPT, NB, NB1, NB2, NB3
00212 DOUBLE PRECISION ABSAI, ABSAR, ABSB, ANRM, ANRM1, ANRM2, BNRM,
00213 $ BNRM1, BNRM2, EPS, SAFMAX, SAFMIN, SALFAI,
00214 $ SALFAR, SBETA, SCALE, TEMP
00215 COMPLEX*16 X
00216
00217
00218 LOGICAL LDUMMA( 1 )
00219
00220
00221 EXTERNAL XERBLA, ZGEQRF, ZGGBAK, ZGGBAL, ZGGHRD, ZHGEQZ,
00222 $ ZLACPY, ZLASCL, ZLASET, ZTGEVC, ZUNGQR, ZUNMQR
00223
00224
00225 LOGICAL LSAME
00226 INTEGER ILAENV
00227 DOUBLE PRECISION DLAMCH, ZLANGE
00228 EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE
00229
00230
00231 INTRINSIC ABS, DBLE, DCMPLX, DIMAG, INT, MAX
00232
00233
00234 DOUBLE PRECISION ABS1
00235
00236
00237 ABS1( X ) = ABS( DBLE( X ) ) + ABS( DIMAG( X ) )
00238
00239
00240
00241
00242
00243 IF( LSAME( JOBVL, 'N' ) ) THEN
00244 IJOBVL = 1
00245 ILVL = .FALSE.
00246 ELSE IF( LSAME( JOBVL, 'V' ) ) THEN
00247 IJOBVL = 2
00248 ILVL = .TRUE.
00249 ELSE
00250 IJOBVL = -1
00251 ILVL = .FALSE.
00252 END IF
00253
00254 IF( LSAME( JOBVR, 'N' ) ) THEN
00255 IJOBVR = 1
00256 ILVR = .FALSE.
00257 ELSE IF( LSAME( JOBVR, 'V' ) ) THEN
00258 IJOBVR = 2
00259 ILVR = .TRUE.
00260 ELSE
00261 IJOBVR = -1
00262 ILVR = .FALSE.
00263 END IF
00264 ILV = ILVL .OR. ILVR
00265
00266
00267
00268 LWKMIN = MAX( 2*N, 1 )
00269 LWKOPT = LWKMIN
00270 WORK( 1 ) = LWKOPT
00271 LQUERY = ( LWORK.EQ.-1 )
00272 INFO = 0
00273 IF( IJOBVL.LE.0 ) THEN
00274 INFO = -1
00275 ELSE IF( IJOBVR.LE.0 ) THEN
00276 INFO = -2
00277 ELSE IF( N.LT.0 ) THEN
00278 INFO = -3
00279 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00280 INFO = -5
00281 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00282 INFO = -7
00283 ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN
00284 INFO = -11
00285 ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN
00286 INFO = -13
00287 ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN
00288 INFO = -15
00289 END IF
00290
00291 IF( INFO.EQ.0 ) THEN
00292 NB1 = ILAENV( 1, 'ZGEQRF', ' ', N, N, -1, -1 )
00293 NB2 = ILAENV( 1, 'ZUNMQR', ' ', N, N, N, -1 )
00294 NB3 = ILAENV( 1, 'ZUNGQR', ' ', N, N, N, -1 )
00295 NB = MAX( NB1, NB2, NB3 )
00296 LOPT = MAX( 2*N, N*( NB+1 ) )
00297 WORK( 1 ) = LOPT
00298 END IF
00299
00300 IF( INFO.NE.0 ) THEN
00301 CALL XERBLA( 'ZGEGV ', -INFO )
00302 RETURN
00303 ELSE IF( LQUERY ) THEN
00304 RETURN
00305 END IF
00306
00307
00308
00309 IF( N.EQ.0 )
00310 $ RETURN
00311
00312
00313
00314 EPS = DLAMCH( 'E' )*DLAMCH( 'B' )
00315 SAFMIN = DLAMCH( 'S' )
00316 SAFMIN = SAFMIN + SAFMIN
00317 SAFMAX = ONE / SAFMIN
00318
00319
00320
00321 ANRM = ZLANGE( 'M', N, N, A, LDA, RWORK )
00322 ANRM1 = ANRM
00323 ANRM2 = ONE
00324 IF( ANRM.LT.ONE ) THEN
00325 IF( SAFMAX*ANRM.LT.ONE ) THEN
00326 ANRM1 = SAFMIN
00327 ANRM2 = SAFMAX*ANRM
00328 END IF
00329 END IF
00330
00331 IF( ANRM.GT.ZERO ) THEN
00332 CALL ZLASCL( 'G', -1, -1, ANRM, ONE, N, N, A, LDA, IINFO )
00333 IF( IINFO.NE.0 ) THEN
00334 INFO = N + 10
00335 RETURN
00336 END IF
00337 END IF
00338
00339
00340
00341 BNRM = ZLANGE( 'M', N, N, B, LDB, RWORK )
00342 BNRM1 = BNRM
00343 BNRM2 = ONE
00344 IF( BNRM.LT.ONE ) THEN
00345 IF( SAFMAX*BNRM.LT.ONE ) THEN
00346 BNRM1 = SAFMIN
00347 BNRM2 = SAFMAX*BNRM
00348 END IF
00349 END IF
00350
00351 IF( BNRM.GT.ZERO ) THEN
00352 CALL ZLASCL( 'G', -1, -1, BNRM, ONE, N, N, B, LDB, IINFO )
00353 IF( IINFO.NE.0 ) THEN
00354 INFO = N + 10
00355 RETURN
00356 END IF
00357 END IF
00358
00359
00360
00361
00362 ILEFT = 1
00363 IRIGHT = N + 1
00364 IRWORK = IRIGHT + N
00365 CALL ZGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ),
00366 $ RWORK( IRIGHT ), RWORK( IRWORK ), IINFO )
00367 IF( IINFO.NE.0 ) THEN
00368 INFO = N + 1
00369 GO TO 80
00370 END IF
00371
00372
00373
00374 IROWS = IHI + 1 - ILO
00375 IF( ILV ) THEN
00376 ICOLS = N + 1 - ILO
00377 ELSE
00378 ICOLS = IROWS
00379 END IF
00380 ITAU = 1
00381 IWORK = ITAU + IROWS
00382 CALL ZGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),
00383 $ WORK( IWORK ), LWORK+1-IWORK, IINFO )
00384 IF( IINFO.GE.0 )
00385 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )
00386 IF( IINFO.NE.0 ) THEN
00387 INFO = N + 2
00388 GO TO 80
00389 END IF
00390
00391 CALL ZUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,
00392 $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ),
00393 $ LWORK+1-IWORK, IINFO )
00394 IF( IINFO.GE.0 )
00395 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )
00396 IF( IINFO.NE.0 ) THEN
00397 INFO = N + 3
00398 GO TO 80
00399 END IF
00400
00401 IF( ILVL ) THEN
00402 CALL ZLASET( 'Full', N, N, CZERO, CONE, VL, LDVL )
00403 CALL ZLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,
00404 $ VL( ILO+1, ILO ), LDVL )
00405 CALL ZUNGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL,
00406 $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK,
00407 $ IINFO )
00408 IF( IINFO.GE.0 )
00409 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )
00410 IF( IINFO.NE.0 ) THEN
00411 INFO = N + 4
00412 GO TO 80
00413 END IF
00414 END IF
00415
00416 IF( ILVR )
00417 $ CALL ZLASET( 'Full', N, N, CZERO, CONE, VR, LDVR )
00418
00419
00420
00421 IF( ILV ) THEN
00422
00423
00424
00425 CALL ZGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL,
00426 $ LDVL, VR, LDVR, IINFO )
00427 ELSE
00428 CALL ZGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA,
00429 $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IINFO )
00430 END IF
00431 IF( IINFO.NE.0 ) THEN
00432 INFO = N + 5
00433 GO TO 80
00434 END IF
00435
00436
00437
00438 IWORK = ITAU
00439 IF( ILV ) THEN
00440 CHTEMP = 'S'
00441 ELSE
00442 CHTEMP = 'E'
00443 END IF
00444 CALL ZHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB,
00445 $ ALPHA, BETA, VL, LDVL, VR, LDVR, WORK( IWORK ),
00446 $ LWORK+1-IWORK, RWORK( IRWORK ), IINFO )
00447 IF( IINFO.GE.0 )
00448 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )
00449 IF( IINFO.NE.0 ) THEN
00450 IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN
00451 INFO = IINFO
00452 ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN
00453 INFO = IINFO - N
00454 ELSE
00455 INFO = N + 6
00456 END IF
00457 GO TO 80
00458 END IF
00459
00460 IF( ILV ) THEN
00461
00462
00463
00464 IF( ILVL ) THEN
00465 IF( ILVR ) THEN
00466 CHTEMP = 'B'
00467 ELSE
00468 CHTEMP = 'L'
00469 END IF
00470 ELSE
00471 CHTEMP = 'R'
00472 END IF
00473
00474 CALL ZTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL,
00475 $ VR, LDVR, N, IN, WORK( IWORK ), RWORK( IRWORK ),
00476 $ IINFO )
00477 IF( IINFO.NE.0 ) THEN
00478 INFO = N + 7
00479 GO TO 80
00480 END IF
00481
00482
00483
00484 IF( ILVL ) THEN
00485 CALL ZGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ),
00486 $ RWORK( IRIGHT ), N, VL, LDVL, IINFO )
00487 IF( IINFO.NE.0 ) THEN
00488 INFO = N + 8
00489 GO TO 80
00490 END IF
00491 DO 30 JC = 1, N
00492 TEMP = ZERO
00493 DO 10 JR = 1, N
00494 TEMP = MAX( TEMP, ABS1( VL( JR, JC ) ) )
00495 10 CONTINUE
00496 IF( TEMP.LT.SAFMIN )
00497 $ GO TO 30
00498 TEMP = ONE / TEMP
00499 DO 20 JR = 1, N
00500 VL( JR, JC ) = VL( JR, JC )*TEMP
00501 20 CONTINUE
00502 30 CONTINUE
00503 END IF
00504 IF( ILVR ) THEN
00505 CALL ZGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ),
00506 $ RWORK( IRIGHT ), N, VR, LDVR, IINFO )
00507 IF( IINFO.NE.0 ) THEN
00508 INFO = N + 9
00509 GO TO 80
00510 END IF
00511 DO 60 JC = 1, N
00512 TEMP = ZERO
00513 DO 40 JR = 1, N
00514 TEMP = MAX( TEMP, ABS1( VR( JR, JC ) ) )
00515 40 CONTINUE
00516 IF( TEMP.LT.SAFMIN )
00517 $ GO TO 60
00518 TEMP = ONE / TEMP
00519 DO 50 JR = 1, N
00520 VR( JR, JC ) = VR( JR, JC )*TEMP
00521 50 CONTINUE
00522 60 CONTINUE
00523 END IF
00524
00525
00526
00527 END IF
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 DO 70 JC = 1, N
00538 ABSAR = ABS( DBLE( ALPHA( JC ) ) )
00539 ABSAI = ABS( DIMAG( ALPHA( JC ) ) )
00540 ABSB = ABS( DBLE( BETA( JC ) ) )
00541 SALFAR = ANRM*DBLE( ALPHA( JC ) )
00542 SALFAI = ANRM*DIMAG( ALPHA( JC ) )
00543 SBETA = BNRM*DBLE( BETA( JC ) )
00544 ILIMIT = .FALSE.
00545 SCALE = ONE
00546
00547
00548
00549 IF( ABS( SALFAI ).LT.SAFMIN .AND. ABSAI.GE.
00550 $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSB ) ) THEN
00551 ILIMIT = .TRUE.
00552 SCALE = ( SAFMIN / ANRM1 ) / MAX( SAFMIN, ANRM2*ABSAI )
00553 END IF
00554
00555
00556
00557 IF( ABS( SALFAR ).LT.SAFMIN .AND. ABSAR.GE.
00558 $ MAX( SAFMIN, EPS*ABSAI, EPS*ABSB ) ) THEN
00559 ILIMIT = .TRUE.
00560 SCALE = MAX( SCALE, ( SAFMIN / ANRM1 ) /
00561 $ MAX( SAFMIN, ANRM2*ABSAR ) )
00562 END IF
00563
00564
00565
00566 IF( ABS( SBETA ).LT.SAFMIN .AND. ABSB.GE.
00567 $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSAI ) ) THEN
00568 ILIMIT = .TRUE.
00569 SCALE = MAX( SCALE, ( SAFMIN / BNRM1 ) /
00570 $ MAX( SAFMIN, BNRM2*ABSB ) )
00571 END IF
00572
00573
00574
00575 IF( ILIMIT ) THEN
00576 TEMP = ( SCALE*SAFMIN )*MAX( ABS( SALFAR ), ABS( SALFAI ),
00577 $ ABS( SBETA ) )
00578 IF( TEMP.GT.ONE )
00579 $ SCALE = SCALE / TEMP
00580 IF( SCALE.LT.ONE )
00581 $ ILIMIT = .FALSE.
00582 END IF
00583
00584
00585
00586 IF( ILIMIT ) THEN
00587 SALFAR = ( SCALE*DBLE( ALPHA( JC ) ) )*ANRM
00588 SALFAI = ( SCALE*DIMAG( ALPHA( JC ) ) )*ANRM
00589 SBETA = ( SCALE*BETA( JC ) )*BNRM
00590 END IF
00591 ALPHA( JC ) = DCMPLX( SALFAR, SALFAI )
00592 BETA( JC ) = SBETA
00593 70 CONTINUE
00594
00595 80 CONTINUE
00596 WORK( 1 ) = LWKOPT
00597
00598 RETURN
00599
00600
00601
00602 END