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