![]() |
LAPACK
3.4.1
LAPACK: Linear Algebra PACKage
|
00001 *> \brief <b> SSTEVD computes the eigenvalues and, optionally, the left and/or right eigenvectors for OTHER matrices</b> 00002 * 00003 * =========== DOCUMENTATION =========== 00004 * 00005 * Online html documentation available at 00006 * http://www.netlib.org/lapack/explore-html/ 00007 * 00008 *> \htmlonly 00009 *> Download SSTEVD + dependencies 00010 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sstevd.f"> 00011 *> [TGZ]</a> 00012 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sstevd.f"> 00013 *> [ZIP]</a> 00014 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstevd.f"> 00015 *> [TXT]</a> 00016 *> \endhtmlonly 00017 * 00018 * Definition: 00019 * =========== 00020 * 00021 * SUBROUTINE SSTEVD( JOBZ, N, D, E, Z, LDZ, WORK, LWORK, IWORK, 00022 * LIWORK, INFO ) 00023 * 00024 * .. Scalar Arguments .. 00025 * CHARACTER JOBZ 00026 * INTEGER INFO, LDZ, LIWORK, LWORK, N 00027 * .. 00028 * .. Array Arguments .. 00029 * INTEGER IWORK( * ) 00030 * REAL D( * ), E( * ), WORK( * ), Z( LDZ, * ) 00031 * .. 00032 * 00033 * 00034 *> \par Purpose: 00035 * ============= 00036 *> 00037 *> \verbatim 00038 *> 00039 *> SSTEVD computes all eigenvalues and, optionally, eigenvectors of a 00040 *> real symmetric tridiagonal matrix. If eigenvectors are desired, it 00041 *> uses a divide and conquer algorithm. 00042 *> 00043 *> The divide and conquer algorithm makes very mild assumptions about 00044 *> floating point arithmetic. It will work on machines with a guard 00045 *> digit in add/subtract, or on those binary machines without guard 00046 *> digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or 00047 *> Cray-2. It could conceivably fail on hexadecimal or decimal machines 00048 *> without guard digits, but we know of none. 00049 *> \endverbatim 00050 * 00051 * Arguments: 00052 * ========== 00053 * 00054 *> \param[in] JOBZ 00055 *> \verbatim 00056 *> JOBZ is CHARACTER*1 00057 *> = 'N': Compute eigenvalues only; 00058 *> = 'V': Compute eigenvalues and eigenvectors. 00059 *> \endverbatim 00060 *> 00061 *> \param[in] N 00062 *> \verbatim 00063 *> N is INTEGER 00064 *> The order of the matrix. N >= 0. 00065 *> \endverbatim 00066 *> 00067 *> \param[in,out] D 00068 *> \verbatim 00069 *> D is REAL array, dimension (N) 00070 *> On entry, the n diagonal elements of the tridiagonal matrix 00071 *> A. 00072 *> On exit, if INFO = 0, the eigenvalues in ascending order. 00073 *> \endverbatim 00074 *> 00075 *> \param[in,out] E 00076 *> \verbatim 00077 *> E is REAL array, dimension (N-1) 00078 *> On entry, the (n-1) subdiagonal elements of the tridiagonal 00079 *> matrix A, stored in elements 1 to N-1 of E. 00080 *> On exit, the contents of E are destroyed. 00081 *> \endverbatim 00082 *> 00083 *> \param[out] Z 00084 *> \verbatim 00085 *> Z is REAL array, dimension (LDZ, N) 00086 *> If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal 00087 *> eigenvectors of the matrix A, with the i-th column of Z 00088 *> holding the eigenvector associated with D(i). 00089 *> If JOBZ = 'N', then Z is not referenced. 00090 *> \endverbatim 00091 *> 00092 *> \param[in] LDZ 00093 *> \verbatim 00094 *> LDZ is INTEGER 00095 *> The leading dimension of the array Z. LDZ >= 1, and if 00096 *> JOBZ = 'V', LDZ >= max(1,N). 00097 *> \endverbatim 00098 *> 00099 *> \param[out] WORK 00100 *> \verbatim 00101 *> WORK is REAL array, 00102 *> dimension (LWORK) 00103 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. 00104 *> \endverbatim 00105 *> 00106 *> \param[in] LWORK 00107 *> \verbatim 00108 *> LWORK is INTEGER 00109 *> The dimension of the array WORK. 00110 *> If JOBZ = 'N' or N <= 1 then LWORK must be at least 1. 00111 *> If JOBZ = 'V' and N > 1 then LWORK must be at least 00112 *> ( 1 + 4*N + N**2 ). 00113 *> 00114 *> If LWORK = -1, then a workspace query is assumed; the routine 00115 *> only calculates the optimal sizes of the WORK and IWORK 00116 *> arrays, returns these values as the first entries of the WORK 00117 *> and IWORK arrays, and no error message related to LWORK or 00118 *> LIWORK is issued by XERBLA. 00119 *> \endverbatim 00120 *> 00121 *> \param[out] IWORK 00122 *> \verbatim 00123 *> IWORK is INTEGER array, dimension (MAX(1,LIWORK)) 00124 *> On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. 00125 *> \endverbatim 00126 *> 00127 *> \param[in] LIWORK 00128 *> \verbatim 00129 *> LIWORK is INTEGER 00130 *> The dimension of the array IWORK. 00131 *> If JOBZ = 'N' or N <= 1 then LIWORK must be at least 1. 00132 *> If JOBZ = 'V' and N > 1 then LIWORK must be at least 3+5*N. 00133 *> 00134 *> If LIWORK = -1, then a workspace query is assumed; the 00135 *> routine only calculates the optimal sizes of the WORK and 00136 *> IWORK arrays, returns these values as the first entries of 00137 *> the WORK and IWORK arrays, and no error message related to 00138 *> LWORK or LIWORK is issued by XERBLA. 00139 *> \endverbatim 00140 *> 00141 *> \param[out] INFO 00142 *> \verbatim 00143 *> INFO is INTEGER 00144 *> = 0: successful exit 00145 *> < 0: if INFO = -i, the i-th argument had an illegal value 00146 *> > 0: if INFO = i, the algorithm failed to converge; i 00147 *> off-diagonal elements of E did not converge to zero. 00148 *> \endverbatim 00149 * 00150 * Authors: 00151 * ======== 00152 * 00153 *> \author Univ. of Tennessee 00154 *> \author Univ. of California Berkeley 00155 *> \author Univ. of Colorado Denver 00156 *> \author NAG Ltd. 00157 * 00158 *> \date November 2011 00159 * 00160 *> \ingroup realOTHEReigen 00161 * 00162 * ===================================================================== 00163 SUBROUTINE SSTEVD( JOBZ, N, D, E, Z, LDZ, WORK, LWORK, IWORK, 00164 $ LIWORK, INFO ) 00165 * 00166 * -- LAPACK driver routine (version 3.4.0) -- 00167 * -- LAPACK is a software package provided by Univ. of Tennessee, -- 00168 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 00169 * November 2011 00170 * 00171 * .. Scalar Arguments .. 00172 CHARACTER JOBZ 00173 INTEGER INFO, LDZ, LIWORK, LWORK, N 00174 * .. 00175 * .. Array Arguments .. 00176 INTEGER IWORK( * ) 00177 REAL D( * ), E( * ), WORK( * ), Z( LDZ, * ) 00178 * .. 00179 * 00180 * ===================================================================== 00181 * 00182 * .. Parameters .. 00183 REAL ZERO, ONE 00184 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) 00185 * .. 00186 * .. Local Scalars .. 00187 LOGICAL LQUERY, WANTZ 00188 INTEGER ISCALE, LIWMIN, LWMIN 00189 REAL BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM, 00190 $ TNRM 00191 * .. 00192 * .. External Functions .. 00193 LOGICAL LSAME 00194 REAL SLAMCH, SLANST 00195 EXTERNAL LSAME, SLAMCH, SLANST 00196 * .. 00197 * .. External Subroutines .. 00198 EXTERNAL SSCAL, SSTEDC, SSTERF, XERBLA 00199 * .. 00200 * .. Intrinsic Functions .. 00201 INTRINSIC SQRT 00202 * .. 00203 * .. Executable Statements .. 00204 * 00205 * Test the input parameters. 00206 * 00207 WANTZ = LSAME( JOBZ, 'V' ) 00208 LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 ) 00209 * 00210 INFO = 0 00211 LIWMIN = 1 00212 LWMIN = 1 00213 IF( N.GT.1 .AND. WANTZ ) THEN 00214 LWMIN = 1 + 4*N + N**2 00215 LIWMIN = 3 + 5*N 00216 END IF 00217 * 00218 IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN 00219 INFO = -1 00220 ELSE IF( N.LT.0 ) THEN 00221 INFO = -2 00222 ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN 00223 INFO = -6 00224 END IF 00225 * 00226 IF( INFO.EQ.0 ) THEN 00227 WORK( 1 ) = LWMIN 00228 IWORK( 1 ) = LIWMIN 00229 * 00230 IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN 00231 INFO = -8 00232 ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN 00233 INFO = -10 00234 END IF 00235 END IF 00236 * 00237 IF( INFO.NE.0 ) THEN 00238 CALL XERBLA( 'SSTEVD', -INFO ) 00239 RETURN 00240 ELSE IF( LQUERY ) THEN 00241 RETURN 00242 END IF 00243 * 00244 * Quick return if possible 00245 * 00246 IF( N.EQ.0 ) 00247 $ RETURN 00248 * 00249 IF( N.EQ.1 ) THEN 00250 IF( WANTZ ) 00251 $ Z( 1, 1 ) = ONE 00252 RETURN 00253 END IF 00254 * 00255 * Get machine constants. 00256 * 00257 SAFMIN = SLAMCH( 'Safe minimum' ) 00258 EPS = SLAMCH( 'Precision' ) 00259 SMLNUM = SAFMIN / EPS 00260 BIGNUM = ONE / SMLNUM 00261 RMIN = SQRT( SMLNUM ) 00262 RMAX = SQRT( BIGNUM ) 00263 * 00264 * Scale matrix to allowable range, if necessary. 00265 * 00266 ISCALE = 0 00267 TNRM = SLANST( 'M', N, D, E ) 00268 IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THEN 00269 ISCALE = 1 00270 SIGMA = RMIN / TNRM 00271 ELSE IF( TNRM.GT.RMAX ) THEN 00272 ISCALE = 1 00273 SIGMA = RMAX / TNRM 00274 END IF 00275 IF( ISCALE.EQ.1 ) THEN 00276 CALL SSCAL( N, SIGMA, D, 1 ) 00277 CALL SSCAL( N-1, SIGMA, E( 1 ), 1 ) 00278 END IF 00279 * 00280 * For eigenvalues only, call SSTERF. For eigenvalues and 00281 * eigenvectors, call SSTEDC. 00282 * 00283 IF( .NOT.WANTZ ) THEN 00284 CALL SSTERF( N, D, E, INFO ) 00285 ELSE 00286 CALL SSTEDC( 'I', N, D, E, Z, LDZ, WORK, LWORK, IWORK, LIWORK, 00287 $ INFO ) 00288 END IF 00289 * 00290 * If matrix was scaled, then rescale eigenvalues appropriately. 00291 * 00292 IF( ISCALE.EQ.1 ) 00293 $ CALL SSCAL( N, ONE / SIGMA, D, 1 ) 00294 * 00295 WORK( 1 ) = LWMIN 00296 IWORK( 1 ) = LIWMIN 00297 * 00298 RETURN 00299 * 00300 * End of SSTEVD 00301 * 00302 END