00001 SUBROUTINE CGEEVX( BALANC, JOBVL, JOBVR, SENSE, N, A, LDA, W, VL,
00002 $ LDVL, VR, LDVR, ILO, IHI, SCALE, ABNRM, RCONDE,
00003 $ RCONDV, WORK, LWORK, RWORK, INFO )
00004
00005
00006
00007
00008
00009
00010
00011 CHARACTER BALANC, JOBVL, JOBVR, SENSE
00012 INTEGER IHI, ILO, INFO, LDA, LDVL, LDVR, LWORK, N
00013 REAL ABNRM
00014
00015
00016 REAL RCONDE( * ), RCONDV( * ), RWORK( * ),
00017 $ SCALE( * )
00018 COMPLEX A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ),
00019 $ W( * ), WORK( * )
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 REAL ZERO, ONE
00189 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 )
00190
00191
00192 LOGICAL LQUERY, SCALEA, WANTVL, WANTVR, WNTSNB, WNTSNE,
00193 $ WNTSNN, WNTSNV
00194 CHARACTER JOB, SIDE
00195 INTEGER HSWORK, I, ICOND, IERR, ITAU, IWRK, K, MAXWRK,
00196 $ MINWRK, NOUT
00197 REAL ANRM, BIGNUM, CSCALE, EPS, SCL, SMLNUM
00198 COMPLEX TMP
00199
00200
00201 LOGICAL SELECT( 1 )
00202 REAL DUM( 1 )
00203
00204
00205 EXTERNAL CGEBAK, CGEBAL, CGEHRD, CHSEQR, CLACPY, CLASCL,
00206 $ CSCAL, CSSCAL, CTREVC, CTRSNA, CUNGHR, SLABAD,
00207 $ SLASCL, XERBLA
00208
00209
00210 LOGICAL LSAME
00211 INTEGER ILAENV, ISAMAX
00212 REAL CLANGE, SCNRM2, SLAMCH
00213 EXTERNAL LSAME, ILAENV, ISAMAX, CLANGE, SCNRM2, SLAMCH
00214
00215
00216 INTRINSIC AIMAG, CMPLX, CONJG, MAX, REAL, SQRT
00217
00218
00219
00220
00221
00222 INFO = 0
00223 LQUERY = ( LWORK.EQ.-1 )
00224 WANTVL = LSAME( JOBVL, 'V' )
00225 WANTVR = LSAME( JOBVR, 'V' )
00226 WNTSNN = LSAME( SENSE, 'N' )
00227 WNTSNE = LSAME( SENSE, 'E' )
00228 WNTSNV = LSAME( SENSE, 'V' )
00229 WNTSNB = LSAME( SENSE, 'B' )
00230 IF( .NOT.( LSAME( BALANC, 'N' ) .OR. LSAME( BALANC, 'S' ) .OR.
00231 $ LSAME( BALANC, 'P' ) .OR. LSAME( BALANC, 'B' ) ) ) THEN
00232 INFO = -1
00233 ELSE IF( ( .NOT.WANTVL ) .AND. ( .NOT.LSAME( JOBVL, 'N' ) ) ) THEN
00234 INFO = -2
00235 ELSE IF( ( .NOT.WANTVR ) .AND. ( .NOT.LSAME( JOBVR, 'N' ) ) ) THEN
00236 INFO = -3
00237 ELSE IF( .NOT.( WNTSNN .OR. WNTSNE .OR. WNTSNB .OR. WNTSNV ) .OR.
00238 $ ( ( WNTSNE .OR. WNTSNB ) .AND. .NOT.( WANTVL .AND.
00239 $ WANTVR ) ) ) THEN
00240 INFO = -4
00241 ELSE IF( N.LT.0 ) THEN
00242 INFO = -5
00243 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00244 INFO = -7
00245 ELSE IF( LDVL.LT.1 .OR. ( WANTVL .AND. LDVL.LT.N ) ) THEN
00246 INFO = -10
00247 ELSE IF( LDVR.LT.1 .OR. ( WANTVR .AND. LDVR.LT.N ) ) THEN
00248 INFO = -12
00249 END IF
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 IF( INFO.EQ.0 ) THEN
00263 IF( N.EQ.0 ) THEN
00264 MINWRK = 1
00265 MAXWRK = 1
00266 ELSE
00267 MAXWRK = N + N*ILAENV( 1, 'CGEHRD', ' ', N, 1, N, 0 )
00268
00269 IF( WANTVL ) THEN
00270 CALL CHSEQR( 'S', 'V', N, 1, N, A, LDA, W, VL, LDVL,
00271 $ WORK, -1, INFO )
00272 ELSE IF( WANTVR ) THEN
00273 CALL CHSEQR( 'S', 'V', N, 1, N, A, LDA, W, VR, LDVR,
00274 $ WORK, -1, INFO )
00275 ELSE
00276 IF( WNTSNN ) THEN
00277 CALL CHSEQR( 'E', 'N', N, 1, N, A, LDA, W, VR, LDVR,
00278 $ WORK, -1, INFO )
00279 ELSE
00280 CALL CHSEQR( 'S', 'N', N, 1, N, A, LDA, W, VR, LDVR,
00281 $ WORK, -1, INFO )
00282 END IF
00283 END IF
00284 HSWORK = WORK( 1 )
00285
00286 IF( ( .NOT.WANTVL ) .AND. ( .NOT.WANTVR ) ) THEN
00287 MINWRK = 2*N
00288 IF( .NOT.( WNTSNN .OR. WNTSNE ) )
00289 $ MINWRK = MAX( MINWRK, N*N + 2*N )
00290 MAXWRK = MAX( MAXWRK, HSWORK )
00291 IF( .NOT.( WNTSNN .OR. WNTSNE ) )
00292 $ MAXWRK = MAX( MAXWRK, N*N + 2*N )
00293 ELSE
00294 MINWRK = 2*N
00295 IF( .NOT.( WNTSNN .OR. WNTSNE ) )
00296 $ MINWRK = MAX( MINWRK, N*N + 2*N )
00297 MAXWRK = MAX( MAXWRK, HSWORK )
00298 MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'CUNGHR',
00299 $ ' ', N, 1, N, -1 ) )
00300 IF( .NOT.( WNTSNN .OR. WNTSNE ) )
00301 $ MAXWRK = MAX( MAXWRK, N*N + 2*N )
00302 MAXWRK = MAX( MAXWRK, 2*N )
00303 END IF
00304 MAXWRK = MAX( MAXWRK, MINWRK )
00305 END IF
00306 WORK( 1 ) = MAXWRK
00307
00308 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00309 INFO = -20
00310 END IF
00311 END IF
00312
00313 IF( INFO.NE.0 ) THEN
00314 CALL XERBLA( 'CGEEVX', -INFO )
00315 RETURN
00316 ELSE IF( LQUERY ) THEN
00317 RETURN
00318 END IF
00319
00320
00321
00322 IF( N.EQ.0 )
00323 $ RETURN
00324
00325
00326
00327 EPS = SLAMCH( 'P' )
00328 SMLNUM = SLAMCH( 'S' )
00329 BIGNUM = ONE / SMLNUM
00330 CALL SLABAD( SMLNUM, BIGNUM )
00331 SMLNUM = SQRT( SMLNUM ) / EPS
00332 BIGNUM = ONE / SMLNUM
00333
00334
00335
00336 ICOND = 0
00337 ANRM = CLANGE( 'M', N, N, A, LDA, DUM )
00338 SCALEA = .FALSE.
00339 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00340 SCALEA = .TRUE.
00341 CSCALE = SMLNUM
00342 ELSE IF( ANRM.GT.BIGNUM ) THEN
00343 SCALEA = .TRUE.
00344 CSCALE = BIGNUM
00345 END IF
00346 IF( SCALEA )
00347 $ CALL CLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
00348
00349
00350
00351 CALL CGEBAL( BALANC, N, A, LDA, ILO, IHI, SCALE, IERR )
00352 ABNRM = CLANGE( '1', N, N, A, LDA, DUM )
00353 IF( SCALEA ) THEN
00354 DUM( 1 ) = ABNRM
00355 CALL SLASCL( 'G', 0, 0, CSCALE, ANRM, 1, 1, DUM, 1, IERR )
00356 ABNRM = DUM( 1 )
00357 END IF
00358
00359
00360
00361
00362
00363 ITAU = 1
00364 IWRK = ITAU + N
00365 CALL CGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
00366 $ LWORK-IWRK+1, IERR )
00367
00368 IF( WANTVL ) THEN
00369
00370
00371
00372
00373 SIDE = 'L'
00374 CALL CLACPY( 'L', N, N, A, LDA, VL, LDVL )
00375
00376
00377
00378
00379
00380 CALL CUNGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),
00381 $ LWORK-IWRK+1, IERR )
00382
00383
00384
00385
00386
00387 IWRK = ITAU
00388 CALL CHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, W, VL, LDVL,
00389 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00390
00391 IF( WANTVR ) THEN
00392
00393
00394
00395
00396 SIDE = 'B'
00397 CALL CLACPY( 'F', N, N, VL, LDVL, VR, LDVR )
00398 END IF
00399
00400 ELSE IF( WANTVR ) THEN
00401
00402
00403
00404
00405 SIDE = 'R'
00406 CALL CLACPY( 'L', N, N, A, LDA, VR, LDVR )
00407
00408
00409
00410
00411
00412 CALL CUNGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),
00413 $ LWORK-IWRK+1, IERR )
00414
00415
00416
00417
00418
00419 IWRK = ITAU
00420 CALL CHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, W, VR, LDVR,
00421 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00422
00423 ELSE
00424
00425
00426
00427
00428 IF( WNTSNN ) THEN
00429 JOB = 'E'
00430 ELSE
00431 JOB = 'S'
00432 END IF
00433
00434
00435
00436
00437 IWRK = ITAU
00438 CALL CHSEQR( JOB, 'N', N, ILO, IHI, A, LDA, W, VR, LDVR,
00439 $ WORK( IWRK ), LWORK-IWRK+1, INFO )
00440 END IF
00441
00442
00443
00444 IF( INFO.GT.0 )
00445 $ GO TO 50
00446
00447 IF( WANTVL .OR. WANTVR ) THEN
00448
00449
00450
00451
00452
00453 CALL CTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
00454 $ N, NOUT, WORK( IWRK ), RWORK, IERR )
00455 END IF
00456
00457
00458
00459
00460
00461 IF( .NOT.WNTSNN ) THEN
00462 CALL CTRSNA( SENSE, 'A', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
00463 $ RCONDE, RCONDV, N, NOUT, WORK( IWRK ), N, RWORK,
00464 $ ICOND )
00465 END IF
00466
00467 IF( WANTVL ) THEN
00468
00469
00470
00471 CALL CGEBAK( BALANC, 'L', N, ILO, IHI, SCALE, N, VL, LDVL,
00472 $ IERR )
00473
00474
00475
00476 DO 20 I = 1, N
00477 SCL = ONE / SCNRM2( N, VL( 1, I ), 1 )
00478 CALL CSSCAL( N, SCL, VL( 1, I ), 1 )
00479 DO 10 K = 1, N
00480 RWORK( K ) = REAL( VL( K, I ) )**2 +
00481 $ AIMAG( VL( K, I ) )**2
00482 10 CONTINUE
00483 K = ISAMAX( N, RWORK, 1 )
00484 TMP = CONJG( VL( K, I ) ) / SQRT( RWORK( K ) )
00485 CALL CSCAL( N, TMP, VL( 1, I ), 1 )
00486 VL( K, I ) = CMPLX( REAL( VL( K, I ) ), ZERO )
00487 20 CONTINUE
00488 END IF
00489
00490 IF( WANTVR ) THEN
00491
00492
00493
00494 CALL CGEBAK( BALANC, 'R', N, ILO, IHI, SCALE, N, VR, LDVR,
00495 $ IERR )
00496
00497
00498
00499 DO 40 I = 1, N
00500 SCL = ONE / SCNRM2( N, VR( 1, I ), 1 )
00501 CALL CSSCAL( N, SCL, VR( 1, I ), 1 )
00502 DO 30 K = 1, N
00503 RWORK( K ) = REAL( VR( K, I ) )**2 +
00504 $ AIMAG( VR( K, I ) )**2
00505 30 CONTINUE
00506 K = ISAMAX( N, RWORK, 1 )
00507 TMP = CONJG( VR( K, I ) ) / SQRT( RWORK( K ) )
00508 CALL CSCAL( N, TMP, VR( 1, I ), 1 )
00509 VR( K, I ) = CMPLX( REAL( VR( K, I ) ), ZERO )
00510 40 CONTINUE
00511 END IF
00512
00513
00514
00515 50 CONTINUE
00516 IF( SCALEA ) THEN
00517 CALL CLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, W( INFO+1 ),
00518 $ MAX( N-INFO, 1 ), IERR )
00519 IF( INFO.EQ.0 ) THEN
00520 IF( ( WNTSNV .OR. WNTSNB ) .AND. ICOND.EQ.0 )
00521 $ CALL SLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, RCONDV, N,
00522 $ IERR )
00523 ELSE
00524 CALL CLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, W, N, IERR )
00525 END IF
00526 END IF
00527
00528 WORK( 1 ) = MAXWRK
00529 RETURN
00530
00531
00532
00533 END