LAPACK 3.3.0

dstevx.f

Go to the documentation of this file.
00001       SUBROUTINE DSTEVX( JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL,
00002      $                   M, W, Z, LDZ, WORK, IWORK, IFAIL, INFO )
00003 *
00004 *  -- LAPACK driver routine (version 3.2) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *     November 2006
00008 *
00009 *     .. Scalar Arguments ..
00010       CHARACTER          JOBZ, RANGE
00011       INTEGER            IL, INFO, IU, LDZ, M, N
00012       DOUBLE PRECISION   ABSTOL, VL, VU
00013 *     ..
00014 *     .. Array Arguments ..
00015       INTEGER            IFAIL( * ), IWORK( * )
00016       DOUBLE PRECISION   D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )
00017 *     ..
00018 *
00019 *  Purpose
00020 *  =======
00021 *
00022 *  DSTEVX computes selected eigenvalues and, optionally, eigenvectors
00023 *  of a real symmetric tridiagonal matrix A.  Eigenvalues and
00024 *  eigenvectors can be selected by specifying either a range of values
00025 *  or a range of indices for the desired eigenvalues.
00026 *
00027 *  Arguments
00028 *  =========
00029 *
00030 *  JOBZ    (input) CHARACTER*1
00031 *          = 'N':  Compute eigenvalues only;
00032 *          = 'V':  Compute eigenvalues and eigenvectors.
00033 *
00034 *  RANGE   (input) CHARACTER*1
00035 *          = 'A': all eigenvalues will be found.
00036 *          = 'V': all eigenvalues in the half-open interval (VL,VU]
00037 *                 will be found.
00038 *          = 'I': the IL-th through IU-th eigenvalues will be found.
00039 *
00040 *  N       (input) INTEGER
00041 *          The order of the matrix.  N >= 0.
00042 *
00043 *  D       (input/output) DOUBLE PRECISION array, dimension (N)
00044 *          On entry, the n diagonal elements of the tridiagonal matrix
00045 *          A.
00046 *          On exit, D may be multiplied by a constant factor chosen
00047 *          to avoid over/underflow in computing the eigenvalues.
00048 *
00049 *  E       (input/output) DOUBLE PRECISION array, dimension (max(1,N-1))
00050 *          On entry, the (n-1) subdiagonal elements of the tridiagonal
00051 *          matrix A in elements 1 to N-1 of E.
00052 *          On exit, E may be multiplied by a constant factor chosen
00053 *          to avoid over/underflow in computing the eigenvalues.
00054 *
00055 *  VL      (input) DOUBLE PRECISION
00056 *  VU      (input) DOUBLE PRECISION
00057 *          If RANGE='V', the lower and upper bounds of the interval to
00058 *          be searched for eigenvalues. VL < VU.
00059 *          Not referenced if RANGE = 'A' or 'I'.
00060 *
00061 *  IL      (input) INTEGER
00062 *  IU      (input) INTEGER
00063 *          If RANGE='I', the indices (in ascending order) of the
00064 *          smallest and largest eigenvalues to be returned.
00065 *          1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
00066 *          Not referenced if RANGE = 'A' or 'V'.
00067 *
00068 *  ABSTOL  (input) DOUBLE PRECISION
00069 *          The absolute error tolerance for the eigenvalues.
00070 *          An approximate eigenvalue is accepted as converged
00071 *          when it is determined to lie in an interval [a,b]
00072 *          of width less than or equal to
00073 *
00074 *                  ABSTOL + EPS *   max( |a|,|b| ) ,
00075 *
00076 *          where EPS is the machine precision.  If ABSTOL is less
00077 *          than or equal to zero, then  EPS*|T|  will be used in
00078 *          its place, where |T| is the 1-norm of the tridiagonal
00079 *          matrix.
00080 *
00081 *          Eigenvalues will be computed most accurately when ABSTOL is
00082 *          set to twice the underflow threshold 2*DLAMCH('S'), not zero.
00083 *          If this routine returns with INFO>0, indicating that some
00084 *          eigenvectors did not converge, try setting ABSTOL to
00085 *          2*DLAMCH('S').
00086 *
00087 *          See "Computing Small Singular Values of Bidiagonal Matrices
00088 *          with Guaranteed High Relative Accuracy," by Demmel and
00089 *          Kahan, LAPACK Working Note #3.
00090 *
00091 *  M       (output) INTEGER
00092 *          The total number of eigenvalues found.  0 <= M <= N.
00093 *          If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
00094 *
00095 *  W       (output) DOUBLE PRECISION array, dimension (N)
00096 *          The first M elements contain the selected eigenvalues in
00097 *          ascending order.
00098 *
00099 *  Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) )
00100 *          If JOBZ = 'V', then if INFO = 0, the first M columns of Z
00101 *          contain the orthonormal eigenvectors of the matrix A
00102 *          corresponding to the selected eigenvalues, with the i-th
00103 *          column of Z holding the eigenvector associated with W(i).
00104 *          If an eigenvector fails to converge (INFO > 0), then that
00105 *          column of Z contains the latest approximation to the
00106 *          eigenvector, and the index of the eigenvector is returned
00107 *          in IFAIL.  If JOBZ = 'N', then Z is not referenced.
00108 *          Note: the user must ensure that at least max(1,M) columns are
00109 *          supplied in the array Z; if RANGE = 'V', the exact value of M
00110 *          is not known in advance and an upper bound must be used.
00111 *
00112 *  LDZ     (input) INTEGER
00113 *          The leading dimension of the array Z.  LDZ >= 1, and if
00114 *          JOBZ = 'V', LDZ >= max(1,N).
00115 *
00116 *  WORK    (workspace) DOUBLE PRECISION array, dimension (5*N)
00117 *
00118 *  IWORK   (workspace) INTEGER array, dimension (5*N)
00119 *
00120 *  IFAIL   (output) INTEGER array, dimension (N)
00121 *          If JOBZ = 'V', then if INFO = 0, the first M elements of
00122 *          IFAIL are zero.  If INFO > 0, then IFAIL contains the
00123 *          indices of the eigenvectors that failed to converge.
00124 *          If JOBZ = 'N', then IFAIL is not referenced.
00125 *
00126 *  INFO    (output) INTEGER
00127 *          = 0:  successful exit
00128 *          < 0:  if INFO = -i, the i-th argument had an illegal value
00129 *          > 0:  if INFO = i, then i eigenvectors failed to converge.
00130 *                Their indices are stored in array IFAIL.
00131 *
00132 *  =====================================================================
00133 *
00134 *     .. Parameters ..
00135       DOUBLE PRECISION   ZERO, ONE
00136       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
00137 *     ..
00138 *     .. Local Scalars ..
00139       LOGICAL            ALLEIG, INDEIG, TEST, VALEIG, WANTZ
00140       CHARACTER          ORDER
00141       INTEGER            I, IMAX, INDIBL, INDISP, INDIWO, INDWRK,
00142      $                   ISCALE, ITMP1, J, JJ, NSPLIT
00143       DOUBLE PRECISION   BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM,
00144      $                   TMP1, TNRM, VLL, VUU
00145 *     ..
00146 *     .. External Functions ..
00147       LOGICAL            LSAME
00148       DOUBLE PRECISION   DLAMCH, DLANST
00149       EXTERNAL           LSAME, DLAMCH, DLANST
00150 *     ..
00151 *     .. External Subroutines ..
00152       EXTERNAL           DCOPY, DSCAL, DSTEBZ, DSTEIN, DSTEQR, DSTERF,
00153      $                   DSWAP, XERBLA
00154 *     ..
00155 *     .. Intrinsic Functions ..
00156       INTRINSIC          MAX, MIN, SQRT
00157 *     ..
00158 *     .. Executable Statements ..
00159 *
00160 *     Test the input parameters.
00161 *
00162       WANTZ = LSAME( JOBZ, 'V' )
00163       ALLEIG = LSAME( RANGE, 'A' )
00164       VALEIG = LSAME( RANGE, 'V' )
00165       INDEIG = LSAME( RANGE, 'I' )
00166 *
00167       INFO = 0
00168       IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
00169          INFO = -1
00170       ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THEN
00171          INFO = -2
00172       ELSE IF( N.LT.0 ) THEN
00173          INFO = -3
00174       ELSE
00175          IF( VALEIG ) THEN
00176             IF( N.GT.0 .AND. VU.LE.VL )
00177      $         INFO = -7
00178          ELSE IF( INDEIG ) THEN
00179             IF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THEN
00180                INFO = -8
00181             ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THEN
00182                INFO = -9
00183             END IF
00184          END IF
00185       END IF
00186       IF( INFO.EQ.0 ) THEN
00187          IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) )
00188      $      INFO = -14
00189       END IF
00190 *
00191       IF( INFO.NE.0 ) THEN
00192          CALL XERBLA( 'DSTEVX', -INFO )
00193          RETURN
00194       END IF
00195 *
00196 *     Quick return if possible
00197 *
00198       M = 0
00199       IF( N.EQ.0 )
00200      $   RETURN
00201 *
00202       IF( N.EQ.1 ) THEN
00203          IF( ALLEIG .OR. INDEIG ) THEN
00204             M = 1
00205             W( 1 ) = D( 1 )
00206          ELSE
00207             IF( VL.LT.D( 1 ) .AND. VU.GE.D( 1 ) ) THEN
00208                M = 1
00209                W( 1 ) = D( 1 )
00210             END IF
00211          END IF
00212          IF( WANTZ )
00213      $      Z( 1, 1 ) = ONE
00214          RETURN
00215       END IF
00216 *
00217 *     Get machine constants.
00218 *
00219       SAFMIN = DLAMCH( 'Safe minimum' )
00220       EPS = DLAMCH( 'Precision' )
00221       SMLNUM = SAFMIN / EPS
00222       BIGNUM = ONE / SMLNUM
00223       RMIN = SQRT( SMLNUM )
00224       RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )
00225 *
00226 *     Scale matrix to allowable range, if necessary.
00227 *
00228       ISCALE = 0
00229       IF( VALEIG ) THEN
00230          VLL = VL
00231          VUU = VU
00232       ELSE
00233          VLL = ZERO
00234          VUU = ZERO
00235       END IF
00236       TNRM = DLANST( 'M', N, D, E )
00237       IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THEN
00238          ISCALE = 1
00239          SIGMA = RMIN / TNRM
00240       ELSE IF( TNRM.GT.RMAX ) THEN
00241          ISCALE = 1
00242          SIGMA = RMAX / TNRM
00243       END IF
00244       IF( ISCALE.EQ.1 ) THEN
00245          CALL DSCAL( N, SIGMA, D, 1 )
00246          CALL DSCAL( N-1, SIGMA, E( 1 ), 1 )
00247          IF( VALEIG ) THEN
00248             VLL = VL*SIGMA
00249             VUU = VU*SIGMA
00250          END IF
00251       END IF
00252 *
00253 *     If all eigenvalues are desired and ABSTOL is less than zero, then
00254 *     call DSTERF or SSTEQR.  If this fails for some eigenvalue, then
00255 *     try DSTEBZ.
00256 *
00257       TEST = .FALSE.
00258       IF( INDEIG ) THEN
00259          IF( IL.EQ.1 .AND. IU.EQ.N ) THEN
00260             TEST = .TRUE.
00261          END IF
00262       END IF
00263       IF( ( ALLEIG .OR. TEST ) .AND. ( ABSTOL.LE.ZERO ) ) THEN
00264          CALL DCOPY( N, D, 1, W, 1 )
00265          CALL DCOPY( N-1, E( 1 ), 1, WORK( 1 ), 1 )
00266          INDWRK = N + 1
00267          IF( .NOT.WANTZ ) THEN
00268             CALL DSTERF( N, W, WORK, INFO )
00269          ELSE
00270             CALL DSTEQR( 'I', N, W, WORK, Z, LDZ, WORK( INDWRK ), INFO )
00271             IF( INFO.EQ.0 ) THEN
00272                DO 10 I = 1, N
00273                   IFAIL( I ) = 0
00274    10          CONTINUE
00275             END IF
00276          END IF
00277          IF( INFO.EQ.0 ) THEN
00278             M = N
00279             GO TO 20
00280          END IF
00281          INFO = 0
00282       END IF
00283 *
00284 *     Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.
00285 *
00286       IF( WANTZ ) THEN
00287          ORDER = 'B'
00288       ELSE
00289          ORDER = 'E'
00290       END IF
00291       INDWRK = 1
00292       INDIBL = 1
00293       INDISP = INDIBL + N
00294       INDIWO = INDISP + N
00295       CALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTOL, D, E, M,
00296      $             NSPLIT, W, IWORK( INDIBL ), IWORK( INDISP ),
00297      $             WORK( INDWRK ), IWORK( INDIWO ), INFO )
00298 *
00299       IF( WANTZ ) THEN
00300          CALL DSTEIN( N, D, E, M, W, IWORK( INDIBL ), IWORK( INDISP ),
00301      $                Z, LDZ, WORK( INDWRK ), IWORK( INDIWO ), IFAIL,
00302      $                INFO )
00303       END IF
00304 *
00305 *     If matrix was scaled, then rescale eigenvalues appropriately.
00306 *
00307    20 CONTINUE
00308       IF( ISCALE.EQ.1 ) THEN
00309          IF( INFO.EQ.0 ) THEN
00310             IMAX = M
00311          ELSE
00312             IMAX = INFO - 1
00313          END IF
00314          CALL DSCAL( IMAX, ONE / SIGMA, W, 1 )
00315       END IF
00316 *
00317 *     If eigenvalues are not in order, then sort them, along with
00318 *     eigenvectors.
00319 *
00320       IF( WANTZ ) THEN
00321          DO 40 J = 1, M - 1
00322             I = 0
00323             TMP1 = W( J )
00324             DO 30 JJ = J + 1, M
00325                IF( W( JJ ).LT.TMP1 ) THEN
00326                   I = JJ
00327                   TMP1 = W( JJ )
00328                END IF
00329    30       CONTINUE
00330 *
00331             IF( I.NE.0 ) THEN
00332                ITMP1 = IWORK( INDIBL+I-1 )
00333                W( I ) = W( J )
00334                IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )
00335                W( J ) = TMP1
00336                IWORK( INDIBL+J-1 ) = ITMP1
00337                CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )
00338                IF( INFO.NE.0 ) THEN
00339                   ITMP1 = IFAIL( I )
00340                   IFAIL( I ) = IFAIL( J )
00341                   IFAIL( J ) = ITMP1
00342                END IF
00343             END IF
00344    40    CONTINUE
00345       END IF
00346 *
00347       RETURN
00348 *
00349 *     End of DSTEVX
00350 *
00351       END
 All Files Functions