![]() |
LAPACK
3.4.1
LAPACK: Linear Algebra PACKage
|
00001 *> \brief <b> SSYEV computes the eigenvalues and, optionally, the left and/or right eigenvectors for SY 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 SSYEV + dependencies 00010 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ssyev.f"> 00011 *> [TGZ]</a> 00012 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ssyev.f"> 00013 *> [ZIP]</a> 00014 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyev.f"> 00015 *> [TXT]</a> 00016 *> \endhtmlonly 00017 * 00018 * Definition: 00019 * =========== 00020 * 00021 * SUBROUTINE SSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO ) 00022 * 00023 * .. Scalar Arguments .. 00024 * CHARACTER JOBZ, UPLO 00025 * INTEGER INFO, LDA, LWORK, N 00026 * .. 00027 * .. Array Arguments .. 00028 * REAL A( LDA, * ), W( * ), WORK( * ) 00029 * .. 00030 * 00031 * 00032 *> \par Purpose: 00033 * ============= 00034 *> 00035 *> \verbatim 00036 *> 00037 *> SSYEV computes all eigenvalues and, optionally, eigenvectors of a 00038 *> real symmetric matrix A. 00039 *> \endverbatim 00040 * 00041 * Arguments: 00042 * ========== 00043 * 00044 *> \param[in] JOBZ 00045 *> \verbatim 00046 *> JOBZ is CHARACTER*1 00047 *> = 'N': Compute eigenvalues only; 00048 *> = 'V': Compute eigenvalues and eigenvectors. 00049 *> \endverbatim 00050 *> 00051 *> \param[in] UPLO 00052 *> \verbatim 00053 *> UPLO is CHARACTER*1 00054 *> = 'U': Upper triangle of A is stored; 00055 *> = 'L': Lower triangle of A is stored. 00056 *> \endverbatim 00057 *> 00058 *> \param[in] N 00059 *> \verbatim 00060 *> N is INTEGER 00061 *> The order of the matrix A. N >= 0. 00062 *> \endverbatim 00063 *> 00064 *> \param[in,out] A 00065 *> \verbatim 00066 *> A is REAL array, dimension (LDA, N) 00067 *> On entry, the symmetric matrix A. If UPLO = 'U', the 00068 *> leading N-by-N upper triangular part of A contains the 00069 *> upper triangular part of the matrix A. If UPLO = 'L', 00070 *> the leading N-by-N lower triangular part of A contains 00071 *> the lower triangular part of the matrix A. 00072 *> On exit, if JOBZ = 'V', then if INFO = 0, A contains the 00073 *> orthonormal eigenvectors of the matrix A. 00074 *> If JOBZ = 'N', then on exit the lower triangle (if UPLO='L') 00075 *> or the upper triangle (if UPLO='U') of A, including the 00076 *> diagonal, is destroyed. 00077 *> \endverbatim 00078 *> 00079 *> \param[in] LDA 00080 *> \verbatim 00081 *> LDA is INTEGER 00082 *> The leading dimension of the array A. LDA >= max(1,N). 00083 *> \endverbatim 00084 *> 00085 *> \param[out] W 00086 *> \verbatim 00087 *> W is REAL array, dimension (N) 00088 *> If INFO = 0, the eigenvalues in ascending order. 00089 *> \endverbatim 00090 *> 00091 *> \param[out] WORK 00092 *> \verbatim 00093 *> WORK is REAL array, dimension (MAX(1,LWORK)) 00094 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. 00095 *> \endverbatim 00096 *> 00097 *> \param[in] LWORK 00098 *> \verbatim 00099 *> LWORK is INTEGER 00100 *> The length of the array WORK. LWORK >= max(1,3*N-1). 00101 *> For optimal efficiency, LWORK >= (NB+2)*N, 00102 *> where NB is the blocksize for SSYTRD returned by ILAENV. 00103 *> 00104 *> If LWORK = -1, then a workspace query is assumed; the routine 00105 *> only calculates the optimal size of the WORK array, returns 00106 *> this value as the first entry of the WORK array, and no error 00107 *> message related to LWORK is issued by XERBLA. 00108 *> \endverbatim 00109 *> 00110 *> \param[out] INFO 00111 *> \verbatim 00112 *> INFO is INTEGER 00113 *> = 0: successful exit 00114 *> < 0: if INFO = -i, the i-th argument had an illegal value 00115 *> > 0: if INFO = i, the algorithm failed to converge; i 00116 *> off-diagonal elements of an intermediate tridiagonal 00117 *> form did not converge to zero. 00118 *> \endverbatim 00119 * 00120 * Authors: 00121 * ======== 00122 * 00123 *> \author Univ. of Tennessee 00124 *> \author Univ. of California Berkeley 00125 *> \author Univ. of Colorado Denver 00126 *> \author NAG Ltd. 00127 * 00128 *> \date November 2011 00129 * 00130 *> \ingroup realSYeigen 00131 * 00132 * ===================================================================== 00133 SUBROUTINE SSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO ) 00134 * 00135 * -- LAPACK driver routine (version 3.4.0) -- 00136 * -- LAPACK is a software package provided by Univ. of Tennessee, -- 00137 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 00138 * November 2011 00139 * 00140 * .. Scalar Arguments .. 00141 CHARACTER JOBZ, UPLO 00142 INTEGER INFO, LDA, LWORK, N 00143 * .. 00144 * .. Array Arguments .. 00145 REAL A( LDA, * ), W( * ), WORK( * ) 00146 * .. 00147 * 00148 * ===================================================================== 00149 * 00150 * .. Parameters .. 00151 REAL ZERO, ONE 00152 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) 00153 * .. 00154 * .. Local Scalars .. 00155 LOGICAL LOWER, LQUERY, WANTZ 00156 INTEGER IINFO, IMAX, INDE, INDTAU, INDWRK, ISCALE, 00157 $ LLWORK, LWKOPT, NB 00158 REAL ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, 00159 $ SMLNUM 00160 * .. 00161 * .. External Functions .. 00162 LOGICAL LSAME 00163 INTEGER ILAENV 00164 REAL SLAMCH, SLANSY 00165 EXTERNAL ILAENV, LSAME, SLAMCH, SLANSY 00166 * .. 00167 * .. External Subroutines .. 00168 EXTERNAL SLASCL, SORGTR, SSCAL, SSTEQR, SSTERF, SSYTRD, 00169 $ XERBLA 00170 * .. 00171 * .. Intrinsic Functions .. 00172 INTRINSIC MAX, SQRT 00173 * .. 00174 * .. Executable Statements .. 00175 * 00176 * Test the input parameters. 00177 * 00178 WANTZ = LSAME( JOBZ, 'V' ) 00179 LOWER = LSAME( UPLO, 'L' ) 00180 LQUERY = ( LWORK.EQ.-1 ) 00181 * 00182 INFO = 0 00183 IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN 00184 INFO = -1 00185 ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THEN 00186 INFO = -2 00187 ELSE IF( N.LT.0 ) THEN 00188 INFO = -3 00189 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN 00190 INFO = -5 00191 END IF 00192 * 00193 IF( INFO.EQ.0 ) THEN 00194 NB = ILAENV( 1, 'SSYTRD', UPLO, N, -1, -1, -1 ) 00195 LWKOPT = MAX( 1, ( NB+2 )*N ) 00196 WORK( 1 ) = LWKOPT 00197 * 00198 IF( LWORK.LT.MAX( 1, 3*N-1 ) .AND. .NOT.LQUERY ) 00199 $ INFO = -8 00200 END IF 00201 * 00202 IF( INFO.NE.0 ) THEN 00203 CALL XERBLA( 'SSYEV ', -INFO ) 00204 RETURN 00205 ELSE IF( LQUERY ) THEN 00206 RETURN 00207 END IF 00208 * 00209 * Quick return if possible 00210 * 00211 IF( N.EQ.0 ) THEN 00212 RETURN 00213 END IF 00214 * 00215 IF( N.EQ.1 ) THEN 00216 W( 1 ) = A( 1, 1 ) 00217 WORK( 1 ) = 2 00218 IF( WANTZ ) 00219 $ A( 1, 1 ) = ONE 00220 RETURN 00221 END IF 00222 * 00223 * Get machine constants. 00224 * 00225 SAFMIN = SLAMCH( 'Safe minimum' ) 00226 EPS = SLAMCH( 'Precision' ) 00227 SMLNUM = SAFMIN / EPS 00228 BIGNUM = ONE / SMLNUM 00229 RMIN = SQRT( SMLNUM ) 00230 RMAX = SQRT( BIGNUM ) 00231 * 00232 * Scale matrix to allowable range, if necessary. 00233 * 00234 ANRM = SLANSY( 'M', UPLO, N, A, LDA, WORK ) 00235 ISCALE = 0 00236 IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THEN 00237 ISCALE = 1 00238 SIGMA = RMIN / ANRM 00239 ELSE IF( ANRM.GT.RMAX ) THEN 00240 ISCALE = 1 00241 SIGMA = RMAX / ANRM 00242 END IF 00243 IF( ISCALE.EQ.1 ) 00244 $ CALL SLASCL( UPLO, 0, 0, ONE, SIGMA, N, N, A, LDA, INFO ) 00245 * 00246 * Call SSYTRD to reduce symmetric matrix to tridiagonal form. 00247 * 00248 INDE = 1 00249 INDTAU = INDE + N 00250 INDWRK = INDTAU + N 00251 LLWORK = LWORK - INDWRK + 1 00252 CALL SSYTRD( UPLO, N, A, LDA, W, WORK( INDE ), WORK( INDTAU ), 00253 $ WORK( INDWRK ), LLWORK, IINFO ) 00254 * 00255 * For eigenvalues only, call SSTERF. For eigenvectors, first call 00256 * SORGTR to generate the orthogonal matrix, then call SSTEQR. 00257 * 00258 IF( .NOT.WANTZ ) THEN 00259 CALL SSTERF( N, W, WORK( INDE ), INFO ) 00260 ELSE 00261 CALL SORGTR( UPLO, N, A, LDA, WORK( INDTAU ), WORK( INDWRK ), 00262 $ LLWORK, IINFO ) 00263 CALL SSTEQR( JOBZ, N, W, WORK( INDE ), A, LDA, WORK( INDTAU ), 00264 $ INFO ) 00265 END IF 00266 * 00267 * If matrix was scaled, then rescale eigenvalues appropriately. 00268 * 00269 IF( ISCALE.EQ.1 ) THEN 00270 IF( INFO.EQ.0 ) THEN 00271 IMAX = N 00272 ELSE 00273 IMAX = INFO - 1 00274 END IF 00275 CALL SSCAL( IMAX, ONE / SIGMA, W, 1 ) 00276 END IF 00277 * 00278 * Set WORK(1) to optimal workspace size. 00279 * 00280 WORK( 1 ) = LWKOPT 00281 * 00282 RETURN 00283 * 00284 * End of SSYEV 00285 * 00286 END