📄 lapack.f
字号:
* ======================================================================* Changes for DYNAMO:** There have been only a few changes all of which are preceded by CMJF* comments.** For the PG/Linux compiler it is necessary to use O1 optimization for* this subroutine due to a looping problem in DLAMC1 (the 20 loop).** ======================================================================* NIST Guide to Available Math Software.* Fullsource for module DSPEV from package LAPACK.* Retrieved from NETLIB on Tue Jun 15 12:28:20 1999.* ====================================================================== SUBROUTINE DSPEV( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, INFO )** -- LAPACK driver routine (version 2.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments .. CHARACTER JOBZ, UPLO INTEGER INFO, LDZ, N* ..* .. Array Arguments .. DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSPEV computes all the eigenvalues and, optionally, eigenvectors of a* real symmetric matrix A in packed storage.** 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.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* A, packed columnwise in a linear array. The j-th column of A* is stored in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.** On exit, AP is overwritten by values generated during the* reduction to tridiagonal form. If UPLO = 'U', the diagonal* and first superdiagonal of the tridiagonal matrix T overwrite* the corresponding elements of A, and if UPLO = 'L', the* diagonal and first subdiagonal of T overwrite the* corresponding elements of A.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal* eigenvectors of the matrix A, with the i-th column of Z* holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (3*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 .. DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars .. LOGICAL WANTZ INTEGER IINFO, IMAX, INDE, INDTAU, INDWRK, ISCALE DOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, $ SMLNUM* ..* .. External Functions .. LOGICAL LSAME DOUBLE PRECISION DLAMCH, DLANSP EXTERNAL LSAME, DLAMCH, DLANSP* ..* .. External Subroutines .. EXTERNAL DOPGTR, DSCAL, DSPTRD, DSTEQR, DSTERF, XERBLA* ..* .. Intrinsic Functions .. INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.* WANTZ = LSAME( JOBZ, 'V' )* INFO = 0 IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN INFO = -1 ELSE IF( .NOT.( LSAME( UPLO, 'U' ) .OR. LSAME( UPLO, 'L' ) ) ) $ THEN INFO = -2 ELSE IF( N.LT.0 ) THEN INFO = -3 ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN INFO = -7 END IF* IF( INFO.NE.0 ) THEN CALL XERBLA( 'DSPEV ', -INFO ) RETURN END IF** Quick return if possible* IF( N.EQ.0 ) $ RETURN* IF( N.EQ.1 ) THEN W( 1 ) = AP( 1 ) IF( WANTZ ) $ Z( 1, 1 ) = ONE RETURN END IF** Get machine constants.*CMJF SAFMIN = DLAMCH( 'Safe minimum' )CMJF EPS = DLAMCH( 'Precision' ) SAFMIN = DLAMCH( 'S' ) EPS = DLAMCH( 'P' ) SMLNUM = SAFMIN / EPS BIGNUM = ONE / SMLNUM RMIN = SQRT( SMLNUM ) RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.* ANRM = DLANSP( 'M', UPLO, N, AP, 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 ) THEN CALL DSCAL( ( N*( N+1 ) ) / 2, SIGMA, AP, 1 ) END IF** Call DSPTRD to reduce symmetric packed matrix to tridiagonal form.* INDE = 1 INDTAU = INDE + N CALL DSPTRD( UPLO, N, AP, W, WORK( INDE ), WORK( INDTAU ), IINFO )** For eigenvalues only, call DSTERF. For eigenvectors, first call* DOPGTR to generate the orthogonal matrix, then call DSTEQR.* IF( .NOT.WANTZ ) THEN CALL DSTERF( N, W, WORK( INDE ), INFO ) ELSE INDWRK = INDTAU + N CALL DOPGTR( UPLO, N, AP, WORK( INDTAU ), Z, LDZ, $ WORK( INDWRK ), IINFO ) CALL DSTEQR( JOBZ, N, W, WORK( INDE ), Z, LDZ, WORK( INDTAU ), $ INFO ) END IF** If matrix was scaled, then rescale eigenvalues appropriately.* IF( ISCALE.EQ.1 ) THEN IF( INFO.EQ.0 ) THEN IMAX = N ELSE IMAX = INFO - 1 END IF CALL DSCAL( IMAX, ONE / SIGMA, W, 1 ) END IF* RETURN** End of DSPEV* END SUBROUTINE DLAE2( A, B, C, RT1, RT2 )** -- 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 .. DOUBLE PRECISION 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) DOUBLE PRECISION* The (1,1) element of the 2-by-2 matrix.** B (input) DOUBLE PRECISION* The (1,2) and (2,1) elements of the 2-by-2 matrix.** C (input) DOUBLE PRECISION* The (2,2) element of the 2-by-2 matrix.** RT1 (output) DOUBLE PRECISION* The eigenvalue of larger absolute value.** RT2 (output) DOUBLE PRECISION* 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 .. DOUBLE PRECISION ONE PARAMETER ( ONE = 1.0D0 ) DOUBLE PRECISION TWO PARAMETER ( TWO = 2.0D0 ) DOUBLE PRECISION ZERO PARAMETER ( ZERO = 0.0D0 ) DOUBLE PRECISION HALF PARAMETER ( HALF = 0.5D0 )* ..* .. Local Scalars .. DOUBLE PRECISION AB, ACMN, ACMX, ADF, DF, RT, SM, TB* ..* .. Intrinsic Functions .. INTRINSIC ABS, SQRT* ..* .. Executable Statements ..** Compute the eigenvalues* SM = A + C DF = A - C ADF = ABS( DF ) TB = B + B AB = ABS( TB ) IF( ABS( A ).GT.ABS( C ) ) THEN ACMX = A ACMN = C ELSE ACMX = C ACMN = A END IF IF( ADF.GT.AB ) THEN RT = ADF*SQRT( ONE+( AB / ADF )**2 ) ELSE IF( ADF.LT.AB ) THEN RT = AB*SQRT( ONE+( ADF / AB )**2 ) ELSE** Includes case AB=ADF=0* RT = AB*SQRT( TWO ) END IF IF( SM.LT.ZERO ) THEN RT1 = HALF*( SM-RT )** Order of execution important.* To get fully accurate smaller eigenvalue,* next line needs to be executed in higher precision.* RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B ELSE IF( SM.GT.ZERO ) THEN RT1 = HALF*( SM+RT )** Order of execution important.* To get fully accurate smaller eigenvalue,* next line needs to be executed in higher precision.* RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B ELSE** Includes case RT1 = RT2 = 0* RT1 = HALF*RT RT2 = -HALF*RT END IF RETURN** End of DLAE2* END SUBROUTINE DLAEV2( A, B, C, RT1, RT2, CS1, SN1 )** -- 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 .. DOUBLE PRECISION A, B, C, CS1, RT1, RT2, SN1* ..** Purpose* =======** DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix* [ A B ]* [ B C ].* On return, RT1 is the eigenvalue of larger absolute value, RT2 is the* eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right* eigenvector for RT1, giving the decomposition** [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ]* [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ].** Arguments* =========** A (input) DOUBLE PRECISION* The (1,1) element of the 2-by-2 matrix.** B (input) DOUBLE PRECISION* The (1,2) element and the conjugate of the (2,1) element of* the 2-by-2 matrix.** C (input) DOUBLE PRECISION* The (2,2) element of the 2-by-2 matrix.** RT1 (output) DOUBLE PRECISION* The eigenvalue of larger absolute value.** RT2 (output) DOUBLE PRECISION* The eigenvalue of smaller absolute value.** CS1 (output) DOUBLE PRECISION* SN1 (output) DOUBLE PRECISION* The vector (CS1, SN1) is a unit right eigenvector for RT1.** 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.** CS1 and SN1 are accurate to a few ulps barring over/underflow.** 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 .. DOUBLE PRECISION ONE PARAMETER ( ONE = 1.0D0 ) DOUBLE PRECISION TWO PARAMETER ( TWO = 2.0D0 ) DOUBLE PRECISION ZERO PARAMETER ( ZERO = 0.0D0 ) DOUBLE PRECISION HALF PARAMETER ( HALF = 0.5D0 )* ..* .. Local Scalars .. INTEGER SGN1, SGN2 DOUBLE PRECISION AB, ACMN, ACMX, ACS, ADF, CS, CT, DF, RT, SM, $ TB, TN* ..* .. Intrinsic Functions .. INTRINSIC ABS, SQRT* ..* .. Executable Statements ..** Compute the eigenvalues* SM = A + C DF = A - C ADF = ABS( DF ) TB = B + B AB = ABS( TB ) IF( ABS( A ).GT.ABS( C ) ) THEN ACMX = A ACMN = C ELSE ACMX = C ACMN = A END IF IF( ADF.GT.AB ) THEN RT = ADF*SQRT( ONE+( AB / ADF )**2 ) ELSE IF( ADF.LT.AB ) THEN RT = AB*SQRT( ONE+( ADF / AB )**2 ) ELSE** Includes case AB=ADF=0* RT = AB*SQRT( TWO ) END IF IF( SM.LT.ZERO ) THEN RT1 = HALF*( SM-RT ) SGN1 = -1** Order of execution important.* To get fully accurate smaller eigenvalue,* next line needs to be executed in higher precision.* RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B ELSE IF( SM.GT.ZERO ) THEN RT1 = HALF*( SM+RT ) SGN1 = 1** Order of execution important.* To get fully accurate smaller eigenvalue,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -