00001 SUBROUTINE ZGGEV( 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 DOUBLE PRECISION ZERO, ONE
00137 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
00138 COMPLEX*16 CZERO, CONE
00139 PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ),
00140 $ CONE = ( 1.0D0, 0.0D0 ) )
00141
00142
00143 LOGICAL ILASCL, ILBSCL, ILV, ILVL, ILVR, LQUERY
00144 CHARACTER CHTEMP
00145 INTEGER ICOLS, IERR, IHI, IJOBVL, IJOBVR, ILEFT, ILO,
00146 $ IN, IRIGHT, IROWS, IRWRK, ITAU, IWRK, JC, JR,
00147 $ LWKMIN, LWKOPT
00148 DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS,
00149 $ SMLNUM, TEMP
00150 COMPLEX*16 X
00151
00152
00153 LOGICAL LDUMMA( 1 )
00154
00155
00156 EXTERNAL DLABAD, XERBLA, ZGEQRF, ZGGBAK, ZGGBAL, ZGGHRD,
00157 $ ZHGEQZ, ZLACPY, ZLASCL, ZLASET, ZTGEVC, ZUNGQR,
00158 $ ZUNMQR
00159
00160
00161 LOGICAL LSAME
00162 INTEGER ILAENV
00163 DOUBLE PRECISION DLAMCH, ZLANGE
00164 EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE
00165
00166
00167 INTRINSIC ABS, DBLE, DIMAG, MAX, SQRT
00168
00169
00170 DOUBLE PRECISION ABS1
00171
00172
00173 ABS1( X ) = ABS( DBLE( X ) ) + ABS( DIMAG( X ) )
00174
00175
00176
00177
00178
00179 IF( LSAME( JOBVL, 'N' ) ) THEN
00180 IJOBVL = 1
00181 ILVL = .FALSE.
00182 ELSE IF( LSAME( JOBVL, 'V' ) ) THEN
00183 IJOBVL = 2
00184 ILVL = .TRUE.
00185 ELSE
00186 IJOBVL = -1
00187 ILVL = .FALSE.
00188 END IF
00189
00190 IF( LSAME( JOBVR, 'N' ) ) THEN
00191 IJOBVR = 1
00192 ILVR = .FALSE.
00193 ELSE IF( LSAME( JOBVR, 'V' ) ) THEN
00194 IJOBVR = 2
00195 ILVR = .TRUE.
00196 ELSE
00197 IJOBVR = -1
00198 ILVR = .FALSE.
00199 END IF
00200 ILV = ILVL .OR. ILVR
00201
00202
00203
00204 INFO = 0
00205 LQUERY = ( LWORK.EQ.-1 )
00206 IF( IJOBVL.LE.0 ) THEN
00207 INFO = -1
00208 ELSE IF( IJOBVR.LE.0 ) THEN
00209 INFO = -2
00210 ELSE IF( N.LT.0 ) THEN
00211 INFO = -3
00212 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00213 INFO = -5
00214 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00215 INFO = -7
00216 ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN
00217 INFO = -11
00218 ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN
00219 INFO = -13
00220 END IF
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 IF( INFO.EQ.0 ) THEN
00231 LWKMIN = MAX( 1, 2*N )
00232 LWKOPT = MAX( 1, N + N*ILAENV( 1, 'ZGEQRF', ' ', N, 1, N, 0 ) )
00233 LWKOPT = MAX( LWKOPT, N +
00234 $ N*ILAENV( 1, 'ZUNMQR', ' ', N, 1, N, 0 ) )
00235 IF( ILVL ) THEN
00236 LWKOPT = MAX( LWKOPT, N +
00237 $ N*ILAENV( 1, 'ZUNGQR', ' ', N, 1, N, -1 ) )
00238 END IF
00239 WORK( 1 ) = LWKOPT
00240
00241 IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY )
00242 $ INFO = -15
00243 END IF
00244
00245 IF( INFO.NE.0 ) THEN
00246 CALL XERBLA( 'ZGGEV ', -INFO )
00247 RETURN
00248 ELSE IF( LQUERY ) THEN
00249 RETURN
00250 END IF
00251
00252
00253
00254 IF( N.EQ.0 )
00255 $ RETURN
00256
00257
00258
00259 EPS = DLAMCH( 'E' )*DLAMCH( 'B' )
00260 SMLNUM = DLAMCH( 'S' )
00261 BIGNUM = ONE / SMLNUM
00262 CALL DLABAD( SMLNUM, BIGNUM )
00263 SMLNUM = SQRT( SMLNUM ) / EPS
00264 BIGNUM = ONE / SMLNUM
00265
00266
00267
00268 ANRM = ZLANGE( 'M', N, N, A, LDA, RWORK )
00269 ILASCL = .FALSE.
00270 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00271 ANRMTO = SMLNUM
00272 ILASCL = .TRUE.
00273 ELSE IF( ANRM.GT.BIGNUM ) THEN
00274 ANRMTO = BIGNUM
00275 ILASCL = .TRUE.
00276 END IF
00277 IF( ILASCL )
00278 $ CALL ZLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )
00279
00280
00281
00282 BNRM = ZLANGE( 'M', N, N, B, LDB, RWORK )
00283 ILBSCL = .FALSE.
00284 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00285 BNRMTO = SMLNUM
00286 ILBSCL = .TRUE.
00287 ELSE IF( BNRM.GT.BIGNUM ) THEN
00288 BNRMTO = BIGNUM
00289 ILBSCL = .TRUE.
00290 END IF
00291 IF( ILBSCL )
00292 $ CALL ZLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )
00293
00294
00295
00296
00297 ILEFT = 1
00298 IRIGHT = N + 1
00299 IRWRK = IRIGHT + N
00300 CALL ZGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ),
00301 $ RWORK( IRIGHT ), RWORK( IRWRK ), IERR )
00302
00303
00304
00305
00306 IROWS = IHI + 1 - ILO
00307 IF( ILV ) THEN
00308 ICOLS = N + 1 - ILO
00309 ELSE
00310 ICOLS = IROWS
00311 END IF
00312 ITAU = 1
00313 IWRK = ITAU + IROWS
00314 CALL ZGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),
00315 $ WORK( IWRK ), LWORK+1-IWRK, IERR )
00316
00317
00318
00319
00320 CALL ZUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,
00321 $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),
00322 $ LWORK+1-IWRK, IERR )
00323
00324
00325
00326
00327 IF( ILVL ) THEN
00328 CALL ZLASET( 'Full', N, N, CZERO, CONE, VL, LDVL )
00329 IF( IROWS.GT.1 ) THEN
00330 CALL ZLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,
00331 $ VL( ILO+1, ILO ), LDVL )
00332 END IF
00333 CALL ZUNGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL,
00334 $ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )
00335 END IF
00336
00337
00338
00339 IF( ILVR )
00340 $ CALL ZLASET( 'Full', N, N, CZERO, CONE, VR, LDVR )
00341
00342
00343
00344 IF( ILV ) THEN
00345
00346
00347
00348 CALL ZGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL,
00349 $ LDVL, VR, LDVR, IERR )
00350 ELSE
00351 CALL ZGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA,
00352 $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IERR )
00353 END IF
00354
00355
00356
00357
00358
00359
00360 IWRK = ITAU
00361 IF( ILV ) THEN
00362 CHTEMP = 'S'
00363 ELSE
00364 CHTEMP = 'E'
00365 END IF
00366 CALL ZHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB,
00367 $ ALPHA, BETA, VL, LDVL, VR, LDVR, WORK( IWRK ),
00368 $ LWORK+1-IWRK, RWORK( IRWRK ), IERR )
00369 IF( IERR.NE.0 ) THEN
00370 IF( IERR.GT.0 .AND. IERR.LE.N ) THEN
00371 INFO = IERR
00372 ELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THEN
00373 INFO = IERR - N
00374 ELSE
00375 INFO = N + 1
00376 END IF
00377 GO TO 70
00378 END IF
00379
00380
00381
00382
00383
00384 IF( ILV ) THEN
00385 IF( ILVL ) THEN
00386 IF( ILVR ) THEN
00387 CHTEMP = 'B'
00388 ELSE
00389 CHTEMP = 'L'
00390 END IF
00391 ELSE
00392 CHTEMP = 'R'
00393 END IF
00394
00395 CALL ZTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL,
00396 $ VR, LDVR, N, IN, WORK( IWRK ), RWORK( IRWRK ),
00397 $ IERR )
00398 IF( IERR.NE.0 ) THEN
00399 INFO = N + 2
00400 GO TO 70
00401 END IF
00402
00403
00404
00405
00406 IF( ILVL ) THEN
00407 CALL ZGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ),
00408 $ RWORK( IRIGHT ), N, VL, LDVL, IERR )
00409 DO 30 JC = 1, N
00410 TEMP = ZERO
00411 DO 10 JR = 1, N
00412 TEMP = MAX( TEMP, ABS1( VL( JR, JC ) ) )
00413 10 CONTINUE
00414 IF( TEMP.LT.SMLNUM )
00415 $ GO TO 30
00416 TEMP = ONE / TEMP
00417 DO 20 JR = 1, N
00418 VL( JR, JC ) = VL( JR, JC )*TEMP
00419 20 CONTINUE
00420 30 CONTINUE
00421 END IF
00422 IF( ILVR ) THEN
00423 CALL ZGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ),
00424 $ RWORK( IRIGHT ), N, VR, LDVR, IERR )
00425 DO 60 JC = 1, N
00426 TEMP = ZERO
00427 DO 40 JR = 1, N
00428 TEMP = MAX( TEMP, ABS1( VR( JR, JC ) ) )
00429 40 CONTINUE
00430 IF( TEMP.LT.SMLNUM )
00431 $ GO TO 60
00432 TEMP = ONE / TEMP
00433 DO 50 JR = 1, N
00434 VR( JR, JC ) = VR( JR, JC )*TEMP
00435 50 CONTINUE
00436 60 CONTINUE
00437 END IF
00438 END IF
00439
00440
00441
00442 IF( ILASCL )
00443 $ CALL ZLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHA, N, IERR )
00444
00445 IF( ILBSCL )
00446 $ CALL ZLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
00447
00448 70 CONTINUE
00449 WORK( 1 ) = LWKOPT
00450
00451 RETURN
00452
00453
00454
00455 END