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