📄 dsyevd.f
字号:
SUBROUTINE DSYEVD( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, IWORK, $ LIWORK, INFO )! ---------------------------------------------------------------------- Use numerics Implicit None** -- LAPACK driver routine (version 2.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments .. CHARACTER JOBZ, UPLO INTEGER INFO, LDA, LIWORK, LWORK, N* ..* .. Array Arguments .. INTEGER IWORK( * ) Real(l_) A( LDA, * ), W( * ), WORK( * )* ..** Purpose* =======** DSYEVD computes all eigenvalues and, optionally, eigenvectors of a* real symmetric matrix A. If eigenvectors are desired, it uses a* divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) Real(l_) array, dimension (LDA, N)* On entry, the symmetric matrix A. If UPLO = 'U', the* leading N-by-N upper triangular part of A contains the* upper triangular part of the matrix A. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.* On exit, if JOBZ = 'V', then if INFO = 0, A contains the* orthonormal eigenvectors of the matrix A.* If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')* or the upper triangle (if UPLO='U') of A, including the* diagonal, is destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** W (output) Real(l_) array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** WORK (workspace/output) Real(l_) array,* dimension (LWORK)* On exit, if LWORK > 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK.* If N <= 1, LWORK must be at least 1.* If JOBZ = 'N' and N > 1, LWORK must be at least 2*N+1.* If JOBZ = 'V' and N > 1, LWORK must be at least* 1 + 5*N + 2*N*lg N + 3*N**2,* where lg( N ) = smallest integer k such* that 2**k >= N.** IWORK (workspace/output) INTEGER array, dimension (LIWORK)* On exit, if LIWORK > 0, IWORK(1) returns the optimal LIWORK.** LIWORK (input) INTEGER* The dimension of the array IWORK.* If N <= 1, LIWORK must be at least 1.* If JOBZ = 'N' and N > 1, LIWORK must be at least 1.* If JOBZ = 'V' and N > 1, LIWORK must be at least 2 + 5*N.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the algorithm failed to converge; i* off-diagonal elements of an intermediate tridiagonal* form did not converge to zero.** =====================================================================** .. Parameters .. Real(l_) ZERO, ONE, TWO PARAMETER ( ZERO = 0.0_l_, ONE = 1.0_l_, TWO = 2.0_l_ )* ..* .. Local Scalars ..* LOGICAL LOWER, WANTZ INTEGER IINFO, INDE, INDTAU, INDWK2, INDWRK, ISCALE, $ LGN, LIOPT, LIWMIN, LLWORK, LLWRK2, LOPT, LWMIN Real(l_) ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, $ SMLNUM* ..* .. External Functions .. LOGICAL LSAME Real(l_) DLAMCH, DLANSY EXTERNAL LSAME, DLAMCH, DLANSY* ..* .. External Subroutines .. EXTERNAL DLACPY, DLASCL, DORMTR, DSCAL, DSTEDC, DSTERF, $ DSYTRD, XERBLA* ..* .. Intrinsic Functions .. INTRINSIC DBLE, INT, LOG, MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.* WANTZ = LSAME( JOBZ, 'V' ) LOWER = LSAME( UPLO, 'L' )* INFO = 0 IF( N.LE.1 ) THEN LGN = 0 LIWMIN = 1 LWMIN = 1 LOPT = LWMIN LIOPT = LIWMIN ELSE LGN = INT( LOG( DBLE( N ) ) / LOG( TWO ) ) IF( 2**LGN.LT.N ) $ LGN = LGN + 1 IF( 2**LGN.LT.N ) $ LGN = LGN + 1 IF( WANTZ ) THEN LIWMIN = 2 + 5*N LWMIN = 1 + 5*N + 2*N*LGN + 3*N**2 ELSE LIWMIN = 1 LWMIN = 2*N + 1 END IF LOPT = LWMIN LIOPT = LIWMIN END IF IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN INFO = -1 ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THEN INFO = -2 ELSE IF( N.LT.0 ) THEN INFO = -3 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN INFO = -5 ELSE IF( LWORK.LT.LWMIN ) THEN INFO = -8 ELSE IF( LIWORK.LT.LIWMIN ) THEN INFO = -10 END IF* IF( INFO.NE.0 ) THEN CALL XERBLA( 'DSYEVD ', -INFO ) GO TO 10 END IF** Quick return if possible* IF( N.EQ.0 ) $ GO TO 10* IF( N.EQ.1 ) THEN W( 1 ) = A( 1, 1 ) IF( WANTZ ) $ A( 1, 1 ) = ONE GO TO 10 END IF** Get machine constants.* SAFMIN = DLAMCH( 'Safe minimum' ) EPS = DLAMCH( 'Precision' ) SMLNUM = SAFMIN / EPS BIGNUM = ONE / SMLNUM RMIN = SQRT( SMLNUM ) RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.* ANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK ) ISCALE = 0 IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THEN ISCALE = 1 SIGMA = RMIN / ANRM ELSE IF( ANRM.GT.RMAX ) THEN ISCALE = 1 SIGMA = RMAX / ANRM END IF IF( ISCALE.EQ.1 ) $ CALL DLASCL( UPLO, 0, 0, ONE, SIGMA, N, N, A, LDA, INFO )** Call DSYTRD to reduce symmetric matrix to tridiagonal form.* INDE = 1 INDTAU = INDE + N INDWRK = INDTAU + N LLWORK = LWORK - INDWRK + 1 INDWK2 = INDWRK + N*N LLWRK2 = LWORK - INDWK2 + 1* CALL DSYTRD( UPLO, N, A, LDA, W, WORK( INDE ), WORK( INDTAU ), $ WORK( INDWRK ), LLWORK, IINFO ) LOPT = 2*N + WORK( INDWRK )** For eigenvalues only, call DSTERF. For eigenvectors, first call* DSTEDC to generate the eigenvector matrix, WORK(INDWRK), of the* tridiagonal matrix, then call DORMTR to multiply it by the* Householder transformations stored in A.* IF( .NOT.WANTZ ) THEN CALL DSTERF( N, W, WORK( INDE ), INFO ) ELSE CALL DSTEDC( 'I', N, W, WORK( INDE ), WORK( INDWRK ), N, $ WORK( INDWK2 ), LLWRK2, IWORK, LIWORK, INFO ) CALL DORMTR( 'L', UPLO, 'N', N, N, A, LDA, WORK( INDTAU ), $ WORK( INDWRK ), N, WORK( INDWK2 ), LLWRK2, IINFO ) CALL DLACPY( 'A', N, N, WORK( INDWRK ), N, A, LDA ) LOPT = MAX( LOPT, 1+5*N+2*N*LGN+3*N**2 ) END IF** If matrix was scaled, then rescale eigenvalues appropriately.* IF( ISCALE.EQ.1 ) $ CALL DSCAL( N, ONE / SIGMA, W, 1 ) 10 CONTINUE IF( LWORK.GT.0 ) $ WORK( 1 ) = LOPT IF( LIWORK.GT.0 ) $ IWORK( 1 ) = LIOPT RETURN** End of DSYEVD* END! ---------------------------------------------------------------------- SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB )! ---------------------------------------------------------------------- Use numerics Implicit None** -- LAPACK auxiliary routine (version 2.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments .. CHARACTER UPLO INTEGER LDA, LDB, M, N* ..* .. Array Arguments .. Real(l_) A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DLACPY copies all or part of a two-dimensional matrix A to another* matrix B.** Arguments* =========** UPLO (input) CHARACTER*1* Specifies the part of the matrix A to be copied to B.* = 'U': Upper triangular part* = 'L': Lower triangular part* Otherwise: All of the matrix A** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrix A. N >= 0.** A (input) Real(l_) array, dimension (LDA,N)* The m by n matrix A. If UPLO = 'U', only the upper triangle* or trapezoid is accessed; if UPLO = 'L', only the lower* triangle or trapezoid is accessed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (output) Real(l_) array, dimension (LDB,N)* On exit, B = A in the locations specified by UPLO.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,M).** =====================================================================** .. Local Scalars .. INTEGER I, J* ..* .. External Functions .. LOGICAL LSAME EXTERNAL LSAME* ..* .. Intrinsic Functions .. INTRINSIC MIN* ..* .. Executable Statements ..* IF( LSAME( UPLO, 'U' ) ) THEN DO 20 J = 1, N DO 10 I = 1, MIN( J, M ) B( I, J ) = A( I, J ) 10 CONTINUE 20 CONTINUE ELSE IF( LSAME( UPLO, 'L' ) ) THEN DO 40 J = 1, N DO 30 I = J, M B( I, J ) = A( I, J ) 30 CONTINUE 40 CONTINUE ELSE DO 60 J = 1, N DO 50 I = 1, M B( I, J ) = A( I, J ) 50 CONTINUE 60 CONTINUE END IF RETURN** End of DLACPY* END! ---------------------------------------------------------------------- SUBROUTINE DLAE2( A, B, C, RT1, RT2 )! ---------------------------------------------------------------------- Use numerics Implicit None** -- LAPACK auxiliary routine (version 2.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments .. Real(l_) A, B, C, RT1, RT2* ..** Purpose* =======** DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix* [ A B ]* [ B C ].* On return, RT1 is the eigenvalue of larger absolute value, and RT2* is the eigenvalue of smaller absolute value.** Arguments* =========** A (input) Real(l_)* The (1,1) element of the 2-by-2 matrix.** B (input) Real(l_)* The (1,2) and (2,1) elements of the 2-by-2 matrix.** C (input) Real(l_)* The (2,2) element of the 2-by-2 matrix.** RT1 (output) Real(l_)* The eigenvalue of larger absolute value.** RT2 (output) Real(l_)* The eigenvalue of smaller absolute value.** Further Details* ===============** RT1 is accurate to a few ulps barring over/underflow.** RT2 may be inaccurate if there is massive cancellation in the* determinant A*C-B*B; higher precision or correctly rounded or* correctly truncated arithmetic would be needed to compute RT2* accurately in all cases.** Overflow is possible only if RT1 is within a factor of 5 of overflow.* Underflow is harmless if the input data is 0 or exceeds* underflow_threshold / macheps.** =====================================================================** .. Parameters .. Real(l_) ONE PARAMETER ( ONE = 1.0_l_ ) Real(l_) TWO PARAMETER ( TWO = 2.0_l_ ) Real(l_) ZERO PARAMETER ( ZERO = 0.0_l_ ) Real(l_) HALF PARAMETER ( HALF = 0.5_l_ )* ..* .. Local Scalars .. Real(l_) AB, ACMN, ACMX, ADF, DF, RT, SM, TB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -