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