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