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