00001 SUBROUTINE DSYEVX( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU,
00002 $ ABSTOL, M, W, Z, LDZ, WORK, LWORK, IWORK,
00003 $ IFAIL, INFO )
00004
00005
00006
00007
00008
00009
00010
00011 CHARACTER JOBZ, RANGE, UPLO
00012 INTEGER IL, INFO, IU, LDA, LDZ, LWORK, M, N
00013 DOUBLE PRECISION ABSTOL, VL, VU
00014
00015
00016 INTEGER IFAIL( * ), IWORK( * )
00017 DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * )
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 DOUBLE PRECISION ZERO, ONE
00155 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
00156
00157
00158 LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, TEST, VALEIG,
00159 $ WANTZ
00160 CHARACTER ORDER
00161 INTEGER I, IINFO, IMAX, INDD, INDE, INDEE, INDIBL,
00162 $ INDISP, INDIWO, INDTAU, INDWKN, INDWRK, ISCALE,
00163 $ ITMP1, J, JJ, LLWORK, LLWRKN, LWKMIN,
00164 $ LWKOPT, NB, NSPLIT
00165 DOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,
00166 $ SIGMA, SMLNUM, TMP1, VLL, VUU
00167
00168
00169 LOGICAL LSAME
00170 INTEGER ILAENV
00171 DOUBLE PRECISION DLAMCH, DLANSY
00172 EXTERNAL LSAME, ILAENV, DLAMCH, DLANSY
00173
00174
00175 EXTERNAL DCOPY, DLACPY, DORGTR, DORMTR, DSCAL, DSTEBZ,
00176 $ DSTEIN, DSTEQR, DSTERF, DSWAP, DSYTRD, XERBLA
00177
00178
00179 INTRINSIC MAX, MIN, SQRT
00180
00181
00182
00183
00184
00185 LOWER = LSAME( UPLO, 'L' )
00186 WANTZ = LSAME( JOBZ, 'V' )
00187 ALLEIG = LSAME( RANGE, 'A' )
00188 VALEIG = LSAME( RANGE, 'V' )
00189 INDEIG = LSAME( RANGE, 'I' )
00190 LQUERY = ( LWORK.EQ.-1 )
00191
00192 INFO = 0
00193 IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
00194 INFO = -1
00195 ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THEN
00196 INFO = -2
00197 ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THEN
00198 INFO = -3
00199 ELSE IF( N.LT.0 ) THEN
00200 INFO = -4
00201 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00202 INFO = -6
00203 ELSE
00204 IF( VALEIG ) THEN
00205 IF( N.GT.0 .AND. VU.LE.VL )
00206 $ INFO = -8
00207 ELSE IF( INDEIG ) THEN
00208 IF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THEN
00209 INFO = -9
00210 ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THEN
00211 INFO = -10
00212 END IF
00213 END IF
00214 END IF
00215 IF( INFO.EQ.0 ) THEN
00216 IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN
00217 INFO = -15
00218 END IF
00219 END IF
00220
00221 IF( INFO.EQ.0 ) THEN
00222 IF( N.LE.1 ) THEN
00223 LWKMIN = 1
00224 WORK( 1 ) = LWKMIN
00225 ELSE
00226 LWKMIN = 8*N
00227 NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )
00228 NB = MAX( NB, ILAENV( 1, 'DORMTR', UPLO, N, -1, -1, -1 ) )
00229 LWKOPT = MAX( LWKMIN, ( NB + 3 )*N )
00230 WORK( 1 ) = LWKOPT
00231 END IF
00232
00233 IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY )
00234 $ INFO = -17
00235 END IF
00236
00237 IF( INFO.NE.0 ) THEN
00238 CALL XERBLA( 'DSYEVX', -INFO )
00239 RETURN
00240 ELSE IF( LQUERY ) THEN
00241 RETURN
00242 END IF
00243
00244
00245
00246 M = 0
00247 IF( N.EQ.0 ) THEN
00248 RETURN
00249 END IF
00250
00251 IF( N.EQ.1 ) THEN
00252 IF( ALLEIG .OR. INDEIG ) THEN
00253 M = 1
00254 W( 1 ) = A( 1, 1 )
00255 ELSE
00256 IF( VL.LT.A( 1, 1 ) .AND. VU.GE.A( 1, 1 ) ) THEN
00257 M = 1
00258 W( 1 ) = A( 1, 1 )
00259 END IF
00260 END IF
00261 IF( WANTZ )
00262 $ Z( 1, 1 ) = ONE
00263 RETURN
00264 END IF
00265
00266
00267
00268 SAFMIN = DLAMCH( 'Safe minimum' )
00269 EPS = DLAMCH( 'Precision' )
00270 SMLNUM = SAFMIN / EPS
00271 BIGNUM = ONE / SMLNUM
00272 RMIN = SQRT( SMLNUM )
00273 RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )
00274
00275
00276
00277 ISCALE = 0
00278 ABSTLL = ABSTOL
00279 IF( VALEIG ) THEN
00280 VLL = VL
00281 VUU = VU
00282 END IF
00283 ANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK )
00284 IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THEN
00285 ISCALE = 1
00286 SIGMA = RMIN / ANRM
00287 ELSE IF( ANRM.GT.RMAX ) THEN
00288 ISCALE = 1
00289 SIGMA = RMAX / ANRM
00290 END IF
00291 IF( ISCALE.EQ.1 ) THEN
00292 IF( LOWER ) THEN
00293 DO 10 J = 1, N
00294 CALL DSCAL( N-J+1, SIGMA, A( J, J ), 1 )
00295 10 CONTINUE
00296 ELSE
00297 DO 20 J = 1, N
00298 CALL DSCAL( J, SIGMA, A( 1, J ), 1 )
00299 20 CONTINUE
00300 END IF
00301 IF( ABSTOL.GT.0 )
00302 $ ABSTLL = ABSTOL*SIGMA
00303 IF( VALEIG ) THEN
00304 VLL = VL*SIGMA
00305 VUU = VU*SIGMA
00306 END IF
00307 END IF
00308
00309
00310
00311 INDTAU = 1
00312 INDE = INDTAU + N
00313 INDD = INDE + N
00314 INDWRK = INDD + N
00315 LLWORK = LWORK - INDWRK + 1
00316 CALL DSYTRD( UPLO, N, A, LDA, WORK( INDD ), WORK( INDE ),
00317 $ WORK( INDTAU ), WORK( INDWRK ), LLWORK, IINFO )
00318
00319
00320
00321
00322
00323 TEST = .FALSE.
00324 IF( INDEIG ) THEN
00325 IF( IL.EQ.1 .AND. IU.EQ.N ) THEN
00326 TEST = .TRUE.
00327 END IF
00328 END IF
00329 IF( ( ALLEIG .OR. TEST ) .AND. ( ABSTOL.LE.ZERO ) ) THEN
00330 CALL DCOPY( N, WORK( INDD ), 1, W, 1 )
00331 INDEE = INDWRK + 2*N
00332 IF( .NOT.WANTZ ) THEN
00333 CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )
00334 CALL DSTERF( N, W, WORK( INDEE ), INFO )
00335 ELSE
00336 CALL DLACPY( 'A', N, N, A, LDA, Z, LDZ )
00337 CALL DORGTR( UPLO, N, Z, LDZ, WORK( INDTAU ),
00338 $ WORK( INDWRK ), LLWORK, IINFO )
00339 CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )
00340 CALL DSTEQR( JOBZ, N, W, WORK( INDEE ), Z, LDZ,
00341 $ WORK( INDWRK ), INFO )
00342 IF( INFO.EQ.0 ) THEN
00343 DO 30 I = 1, N
00344 IFAIL( I ) = 0
00345 30 CONTINUE
00346 END IF
00347 END IF
00348 IF( INFO.EQ.0 ) THEN
00349 M = N
00350 GO TO 40
00351 END IF
00352 INFO = 0
00353 END IF
00354
00355
00356
00357 IF( WANTZ ) THEN
00358 ORDER = 'B'
00359 ELSE
00360 ORDER = 'E'
00361 END IF
00362 INDIBL = 1
00363 INDISP = INDIBL + N
00364 INDIWO = INDISP + N
00365 CALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTLL,
00366 $ WORK( INDD ), WORK( INDE ), M, NSPLIT, W,
00367 $ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWRK ),
00368 $ IWORK( INDIWO ), INFO )
00369
00370 IF( WANTZ ) THEN
00371 CALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W,
00372 $ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ,
00373 $ WORK( INDWRK ), IWORK( INDIWO ), IFAIL, INFO )
00374
00375
00376
00377
00378 INDWKN = INDE
00379 LLWRKN = LWORK - INDWKN + 1
00380 CALL DORMTR( 'L', UPLO, 'N', N, M, A, LDA, WORK( INDTAU ), Z,
00381 $ LDZ, WORK( INDWKN ), LLWRKN, IINFO )
00382 END IF
00383
00384
00385
00386 40 CONTINUE
00387 IF( ISCALE.EQ.1 ) THEN
00388 IF( INFO.EQ.0 ) THEN
00389 IMAX = M
00390 ELSE
00391 IMAX = INFO - 1
00392 END IF
00393 CALL DSCAL( IMAX, ONE / SIGMA, W, 1 )
00394 END IF
00395
00396
00397
00398
00399 IF( WANTZ ) THEN
00400 DO 60 J = 1, M - 1
00401 I = 0
00402 TMP1 = W( J )
00403 DO 50 JJ = J + 1, M
00404 IF( W( JJ ).LT.TMP1 ) THEN
00405 I = JJ
00406 TMP1 = W( JJ )
00407 END IF
00408 50 CONTINUE
00409
00410 IF( I.NE.0 ) THEN
00411 ITMP1 = IWORK( INDIBL+I-1 )
00412 W( I ) = W( J )
00413 IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )
00414 W( J ) = TMP1
00415 IWORK( INDIBL+J-1 ) = ITMP1
00416 CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )
00417 IF( INFO.NE.0 ) THEN
00418 ITMP1 = IFAIL( I )
00419 IFAIL( I ) = IFAIL( J )
00420 IFAIL( J ) = ITMP1
00421 END IF
00422 END IF
00423 60 CONTINUE
00424 END IF
00425
00426
00427
00428 WORK( 1 ) = LWKOPT
00429
00430 RETURN
00431
00432
00433
00434 END