10506 lines
305 KiB
FortranFixed
10506 lines
305 KiB
FortranFixed
subroutine eigen_sym_up(N,A,W)
|
|
implicit none
|
|
!
|
|
!compute the eigenvalues and eigenvectors of a symmetrical matrix.
|
|
!A: On entry, A is a symmetrical matrix with its upper triangle filled.
|
|
! on exit, A contains the normalized eigenvectors in its columns.
|
|
!W: contains the eigenvalues in descending order.
|
|
|
|
CHARACTER JOBZ, UPLO
|
|
INTEGER INFO, LDA, LWORK, N
|
|
DOUBLE PRECISION A(N, N), W( N ), WORK(3*N-1)
|
|
double precision p
|
|
integer i,j
|
|
|
|
JOBZ='V'
|
|
UPLO='U'
|
|
LWORK=3*N-1
|
|
LDA=N
|
|
call DSYEV(JOBZ,UPLO,N,A(1:N,1:N),LDA,W,WORK,LWORK,INFO)
|
|
* 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.
|
|
if(INFO.lt.0)then
|
|
write(*,*)'The ',-INFO,
|
|
& 'th argument in DSYEV has an illegal value'
|
|
stop
|
|
endif
|
|
if(INFO.gt.0)then
|
|
write(*,*)'The algorithm failed to converge'
|
|
stop
|
|
endif
|
|
|
|
! Change the eigenvalue array from ascending to descending order and rearrange
|
|
! the eigen vectors accordingly.
|
|
!---------------------------------------------
|
|
do i=1,N/2
|
|
p=W(i)
|
|
W(i)=W(N-i+1)
|
|
W(N-i+1)=p
|
|
do j=1,N
|
|
p=A(j,i)
|
|
A(j,i)=A(j,N-i+1)
|
|
A(j,N-i+1)=p
|
|
enddo
|
|
enddo
|
|
!---------------------------------------------
|
|
return
|
|
end
|
|
LOGICAL FUNCTION DISNAN( DIN )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* June 2010
|
|
*
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION DIN
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DISNAN returns .TRUE. if its argument is NaN, and .FALSE.
|
|
* otherwise. To be replaced by the Fortran 2003 intrinsic in the
|
|
* future.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* DIN (input) DOUBLE PRECISION
|
|
* Input to test for NaN.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. External Functions ..
|
|
LOGICAL DLAISNAN
|
|
EXTERNAL DLAISNAN
|
|
* ..
|
|
* .. Executable Statements ..
|
|
DISNAN = DLAISNAN(DIN,DIN)
|
|
RETURN
|
|
END
|
|
SUBROUTINE DLAE2( A, B, C, RT1, RT2 )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. 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 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. 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,
|
|
* 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
|
|
SGN1 = 1
|
|
END IF
|
|
*
|
|
* Compute the eigenvector
|
|
*
|
|
IF( DF.GE.ZERO ) THEN
|
|
CS = DF + RT
|
|
SGN2 = 1
|
|
ELSE
|
|
CS = DF - RT
|
|
SGN2 = -1
|
|
END IF
|
|
ACS = ABS( CS )
|
|
IF( ACS.GT.AB ) THEN
|
|
CT = -TB / CS
|
|
SN1 = ONE / SQRT( ONE+CT*CT )
|
|
CS1 = CT*SN1
|
|
ELSE
|
|
IF( AB.EQ.ZERO ) THEN
|
|
CS1 = ONE
|
|
SN1 = ZERO
|
|
ELSE
|
|
TN = -CS / TB
|
|
CS1 = ONE / SQRT( ONE+TN*TN )
|
|
SN1 = TN*CS1
|
|
END IF
|
|
END IF
|
|
IF( SGN1.EQ.SGN2 ) THEN
|
|
TN = CS1
|
|
CS1 = -SN1
|
|
SN1 = TN
|
|
END IF
|
|
RETURN
|
|
*
|
|
* End of DLAEV2
|
|
*
|
|
END
|
|
LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* June 2010
|
|
*
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION DIN1, DIN2
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* This routine is not for general use. It exists solely to avoid
|
|
* over-optimization in DISNAN.
|
|
*
|
|
* DLAISNAN checks for NaNs by comparing its two arguments for
|
|
* inequality. NaN is the only floating-point value where NaN != NaN
|
|
* returns .TRUE. To check for NaNs, pass the same variable as both
|
|
* arguments.
|
|
*
|
|
* A compiler must assume that the two arguments are
|
|
* not the same variable, and the test will not be optimized away.
|
|
* Interprocedural or whole-program optimization may delete this
|
|
* test. The ISNAN functions will be replaced by the correct
|
|
* Fortran 03 intrinsic once the intrinsic is widely available.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* DIN1 (input) DOUBLE PRECISION
|
|
*
|
|
* DIN2 (input) DOUBLE PRECISION
|
|
* Two numbers to compare for inequality.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Executable Statements ..
|
|
DLAISNAN = (DIN1.NE.DIN2)
|
|
RETURN
|
|
END
|
|
DOUBLE PRECISION FUNCTION DLANST( NORM, N, D, E )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER NORM
|
|
INTEGER N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION D( * ), E( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLANST returns the value of the one norm, or the Frobenius norm, or
|
|
* the infinity norm, or the element of largest absolute value of a
|
|
* real symmetric tridiagonal matrix A.
|
|
*
|
|
* Description
|
|
* ===========
|
|
*
|
|
* DLANST returns the value
|
|
*
|
|
* DLANST = ( max(abs(A(i,j))), NORM = 'M' or 'm'
|
|
* (
|
|
* ( norm1(A), NORM = '1', 'O' or 'o'
|
|
* (
|
|
* ( normI(A), NORM = 'I' or 'i'
|
|
* (
|
|
* ( normF(A), NORM = 'F', 'f', 'E' or 'e'
|
|
*
|
|
* where norm1 denotes the one norm of a matrix (maximum column sum),
|
|
* normI denotes the infinity norm of a matrix (maximum row sum) and
|
|
* normF denotes the Frobenius norm of a matrix (square root of sum of
|
|
* squares). Note that max(abs(A(i,j))) is not a consistent matrix norm.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* NORM (input) CHARACTER*1
|
|
* Specifies the value to be returned in DLANST as described
|
|
* above.
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the matrix A. N >= 0. When N = 0, DLANST is
|
|
* set to zero.
|
|
*
|
|
* D (input) DOUBLE PRECISION array, dimension (N)
|
|
* The diagonal elements of A.
|
|
*
|
|
* E (input) DOUBLE PRECISION array, dimension (N-1)
|
|
* The (n-1) sub-diagonal or super-diagonal elements of A.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I
|
|
DOUBLE PRECISION ANORM, SCALE, SUM
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLASSQ
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, MAX, SQRT
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
IF( N.LE.0 ) THEN
|
|
ANORM = ZERO
|
|
ELSE IF( LSAME( NORM, 'M' ) ) THEN
|
|
*
|
|
* Find max(abs(A(i,j))).
|
|
*
|
|
ANORM = ABS( D( N ) )
|
|
DO 10 I = 1, N - 1
|
|
ANORM = MAX( ANORM, ABS( D( I ) ) )
|
|
ANORM = MAX( ANORM, ABS( E( I ) ) )
|
|
10 CONTINUE
|
|
ELSE IF( LSAME( NORM, 'O' ) .OR. NORM.EQ.'1' .OR.
|
|
$ LSAME( NORM, 'I' ) ) THEN
|
|
*
|
|
* Find norm1(A).
|
|
*
|
|
IF( N.EQ.1 ) THEN
|
|
ANORM = ABS( D( 1 ) )
|
|
ELSE
|
|
ANORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ),
|
|
$ ABS( E( N-1 ) )+ABS( D( N ) ) )
|
|
DO 20 I = 2, N - 1
|
|
ANORM = MAX( ANORM, ABS( D( I ) )+ABS( E( I ) )+
|
|
$ ABS( E( I-1 ) ) )
|
|
20 CONTINUE
|
|
END IF
|
|
ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN
|
|
*
|
|
* Find normF(A).
|
|
*
|
|
SCALE = ZERO
|
|
SUM = ONE
|
|
IF( N.GT.1 ) THEN
|
|
CALL DLASSQ( N-1, E, 1, SCALE, SUM )
|
|
SUM = 2*SUM
|
|
END IF
|
|
CALL DLASSQ( N, D, 1, SCALE, SUM )
|
|
ANORM = SCALE*SQRT( SUM )
|
|
END IF
|
|
*
|
|
DLANST = ANORM
|
|
RETURN
|
|
*
|
|
* End of DLANST
|
|
*
|
|
END
|
|
DOUBLE PRECISION FUNCTION DLANSY( NORM, UPLO, N, A, LDA, WORK )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER NORM, UPLO
|
|
INTEGER LDA, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLANSY returns the value of the one norm, or the Frobenius norm, or
|
|
* the infinity norm, or the element of largest absolute value of a
|
|
* real symmetric matrix A.
|
|
*
|
|
* Description
|
|
* ===========
|
|
*
|
|
* DLANSY returns the value
|
|
*
|
|
* DLANSY = ( max(abs(A(i,j))), NORM = 'M' or 'm'
|
|
* (
|
|
* ( norm1(A), NORM = '1', 'O' or 'o'
|
|
* (
|
|
* ( normI(A), NORM = 'I' or 'i'
|
|
* (
|
|
* ( normF(A), NORM = 'F', 'f', 'E' or 'e'
|
|
*
|
|
* where norm1 denotes the one norm of a matrix (maximum column sum),
|
|
* normI denotes the infinity norm of a matrix (maximum row sum) and
|
|
* normF denotes the Frobenius norm of a matrix (square root of sum of
|
|
* squares). Note that max(abs(A(i,j))) is not a consistent matrix norm.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* NORM (input) CHARACTER*1
|
|
* Specifies the value to be returned in DLANSY as described
|
|
* above.
|
|
*
|
|
* UPLO (input) CHARACTER*1
|
|
* Specifies whether the upper or lower triangular part of the
|
|
* symmetric matrix A is to be referenced.
|
|
* = 'U': Upper triangular part of A is referenced
|
|
* = 'L': Lower triangular part of A is referenced
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the matrix A. N >= 0. When N = 0, DLANSY is
|
|
* set to zero.
|
|
*
|
|
* A (input) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* 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, and the strictly lower triangular part of A
|
|
* is not referenced. If UPLO = 'L', the leading n by n lower
|
|
* triangular part of A contains the lower triangular part of
|
|
* the matrix A, and the strictly upper triangular part of A is
|
|
* not referenced.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= max(N,1).
|
|
*
|
|
* WORK (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)),
|
|
* where LWORK >= N when NORM = 'I' or '1' or 'O'; otherwise,
|
|
* WORK is not referenced.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, J
|
|
DOUBLE PRECISION ABSA, SCALE, SUM, VALUE
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLASSQ
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, MAX, SQRT
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
IF( N.EQ.0 ) THEN
|
|
VALUE = ZERO
|
|
ELSE IF( LSAME( NORM, 'M' ) ) THEN
|
|
*
|
|
* Find max(abs(A(i,j))).
|
|
*
|
|
VALUE = ZERO
|
|
IF( LSAME( UPLO, 'U' ) ) THEN
|
|
DO 20 J = 1, N
|
|
DO 10 I = 1, J
|
|
VALUE = MAX( VALUE, ABS( A( I, J ) ) )
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
ELSE
|
|
DO 40 J = 1, N
|
|
DO 30 I = J, N
|
|
VALUE = MAX( VALUE, ABS( A( I, J ) ) )
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
END IF
|
|
ELSE IF( ( LSAME( NORM, 'I' ) ) .OR. ( LSAME( NORM, 'O' ) ) .OR.
|
|
$ ( NORM.EQ.'1' ) ) THEN
|
|
*
|
|
* Find normI(A) ( = norm1(A), since A is symmetric).
|
|
*
|
|
VALUE = ZERO
|
|
IF( LSAME( UPLO, 'U' ) ) THEN
|
|
DO 60 J = 1, N
|
|
SUM = ZERO
|
|
DO 50 I = 1, J - 1
|
|
ABSA = ABS( A( I, J ) )
|
|
SUM = SUM + ABSA
|
|
WORK( I ) = WORK( I ) + ABSA
|
|
50 CONTINUE
|
|
WORK( J ) = SUM + ABS( A( J, J ) )
|
|
60 CONTINUE
|
|
DO 70 I = 1, N
|
|
VALUE = MAX( VALUE, WORK( I ) )
|
|
70 CONTINUE
|
|
ELSE
|
|
DO 80 I = 1, N
|
|
WORK( I ) = ZERO
|
|
80 CONTINUE
|
|
DO 100 J = 1, N
|
|
SUM = WORK( J ) + ABS( A( J, J ) )
|
|
DO 90 I = J + 1, N
|
|
ABSA = ABS( A( I, J ) )
|
|
SUM = SUM + ABSA
|
|
WORK( I ) = WORK( I ) + ABSA
|
|
90 CONTINUE
|
|
VALUE = MAX( VALUE, SUM )
|
|
100 CONTINUE
|
|
END IF
|
|
ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN
|
|
*
|
|
* Find normF(A).
|
|
*
|
|
SCALE = ZERO
|
|
SUM = ONE
|
|
IF( LSAME( UPLO, 'U' ) ) THEN
|
|
DO 110 J = 2, N
|
|
CALL DLASSQ( J-1, A( 1, J ), 1, SCALE, SUM )
|
|
110 CONTINUE
|
|
ELSE
|
|
DO 120 J = 1, N - 1
|
|
CALL DLASSQ( N-J, A( J+1, J ), 1, SCALE, SUM )
|
|
120 CONTINUE
|
|
END IF
|
|
SUM = 2*SUM
|
|
CALL DLASSQ( N, A, LDA+1, SCALE, SUM )
|
|
VALUE = SCALE*SQRT( SUM )
|
|
END IF
|
|
*
|
|
DLANSY = VALUE
|
|
RETURN
|
|
*
|
|
* End of DLANSY
|
|
*
|
|
END
|
|
DOUBLE PRECISION FUNCTION DLAPY2( X, Y )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION X, Y
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary
|
|
* overflow.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* X (input) DOUBLE PRECISION
|
|
* Y (input) DOUBLE PRECISION
|
|
* X and Y specify the values x and y.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER ( ZERO = 0.0D0 )
|
|
DOUBLE PRECISION ONE
|
|
PARAMETER ( ONE = 1.0D0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION W, XABS, YABS, Z
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, MAX, MIN, SQRT
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
XABS = ABS( X )
|
|
YABS = ABS( Y )
|
|
W = MAX( XABS, YABS )
|
|
Z = MIN( XABS, YABS )
|
|
IF( Z.EQ.ZERO ) THEN
|
|
DLAPY2 = W
|
|
ELSE
|
|
DLAPY2 = W*SQRT( ONE+( Z / W )**2 )
|
|
END IF
|
|
RETURN
|
|
*
|
|
* End of DLAPY2
|
|
*
|
|
END
|
|
SUBROUTINE DLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
|
|
IMPLICIT NONE
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER SIDE
|
|
INTEGER INCV, LDC, M, N
|
|
DOUBLE PRECISION TAU
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLARF applies a real elementary reflector H to a real m by n matrix
|
|
* C, from either the left or the right. H is represented in the form
|
|
*
|
|
* H = I - tau * v * v**T
|
|
*
|
|
* where tau is a real scalar and v is a real vector.
|
|
*
|
|
* If tau = 0, then H is taken to be the unit matrix.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* SIDE (input) CHARACTER*1
|
|
* = 'L': form H * C
|
|
* = 'R': form C * H
|
|
*
|
|
* M (input) INTEGER
|
|
* The number of rows of the matrix C.
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of columns of the matrix C.
|
|
*
|
|
* V (input) DOUBLE PRECISION array, dimension
|
|
* (1 + (M-1)*abs(INCV)) if SIDE = 'L'
|
|
* or (1 + (N-1)*abs(INCV)) if SIDE = 'R'
|
|
* The vector v in the representation of H. V is not used if
|
|
* TAU = 0.
|
|
*
|
|
* INCV (input) INTEGER
|
|
* The increment between elements of v. INCV <> 0.
|
|
*
|
|
* TAU (input) DOUBLE PRECISION
|
|
* The value tau in the representation of H.
|
|
*
|
|
* C (input/output) DOUBLE PRECISION array, dimension (LDC,N)
|
|
* On entry, the m by n matrix C.
|
|
* On exit, C is overwritten by the matrix H * C if SIDE = 'L',
|
|
* or C * H if SIDE = 'R'.
|
|
*
|
|
* LDC (input) INTEGER
|
|
* The leading dimension of the array C. LDC >= max(1,M).
|
|
*
|
|
* WORK (workspace) DOUBLE PRECISION array, dimension
|
|
* (N) if SIDE = 'L'
|
|
* or (M) if SIDE = 'R'
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL APPLYLEFT
|
|
INTEGER I, LASTV, LASTC
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DGEMV, DGER
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
INTEGER ILADLR, ILADLC
|
|
EXTERNAL LSAME, ILADLR, ILADLC
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
APPLYLEFT = LSAME( SIDE, 'L' )
|
|
LASTV = 0
|
|
LASTC = 0
|
|
IF( TAU.NE.ZERO ) THEN
|
|
! Set up variables for scanning V. LASTV begins pointing to the end
|
|
! of V.
|
|
IF( APPLYLEFT ) THEN
|
|
LASTV = M
|
|
ELSE
|
|
LASTV = N
|
|
END IF
|
|
IF( INCV.GT.0 ) THEN
|
|
I = 1 + (LASTV-1) * INCV
|
|
ELSE
|
|
I = 1
|
|
END IF
|
|
! Look for the last non-zero row in V.
|
|
DO WHILE( LASTV.GT.0 .AND. V( I ).EQ.ZERO )
|
|
LASTV = LASTV - 1
|
|
I = I - INCV
|
|
END DO
|
|
IF( APPLYLEFT ) THEN
|
|
! Scan for the last non-zero column in C(1:lastv,:).
|
|
LASTC = ILADLC(LASTV, N, C, LDC)
|
|
ELSE
|
|
! Scan for the last non-zero row in C(:,1:lastv).
|
|
LASTC = ILADLR(M, LASTV, C, LDC)
|
|
END IF
|
|
END IF
|
|
! Note that lastc.eq.0 renders the BLAS operations null; no special
|
|
! case is needed at this level.
|
|
IF( APPLYLEFT ) THEN
|
|
*
|
|
* Form H * C
|
|
*
|
|
IF( LASTV.GT.0 ) THEN
|
|
*
|
|
* w(1:lastc,1) := C(1:lastv,1:lastc)**T * v(1:lastv,1)
|
|
*
|
|
CALL DGEMV( 'Transpose', LASTV, LASTC, ONE, C, LDC, V, INCV,
|
|
$ ZERO, WORK, 1 )
|
|
*
|
|
* C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**T
|
|
*
|
|
CALL DGER( LASTV, LASTC, -TAU, V, INCV, WORK, 1, C, LDC )
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form C * H
|
|
*
|
|
IF( LASTV.GT.0 ) THEN
|
|
*
|
|
* w(1:lastc,1) := C(1:lastc,1:lastv) * v(1:lastv,1)
|
|
*
|
|
CALL DGEMV( 'No transpose', LASTC, LASTV, ONE, C, LDC,
|
|
$ V, INCV, ZERO, WORK, 1 )
|
|
*
|
|
* C(1:lastc,1:lastv) := C(...) - w(1:lastc,1) * v(1:lastv,1)**T
|
|
*
|
|
CALL DGER( LASTC, LASTV, -TAU, WORK, 1, V, INCV, C, LDC )
|
|
END IF
|
|
END IF
|
|
RETURN
|
|
*
|
|
* End of DLARF
|
|
*
|
|
END
|
|
SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
|
|
$ T, LDT, C, LDC, WORK, LDWORK )
|
|
IMPLICIT NONE
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER DIRECT, SIDE, STOREV, TRANS
|
|
INTEGER K, LDC, LDT, LDV, LDWORK, M, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),
|
|
$ WORK( LDWORK, * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLARFB applies a real block reflector H or its transpose H**T to a
|
|
* real m by n matrix C, from either the left or the right.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* SIDE (input) CHARACTER*1
|
|
* = 'L': apply H or H**T from the Left
|
|
* = 'R': apply H or H**T from the Right
|
|
*
|
|
* TRANS (input) CHARACTER*1
|
|
* = 'N': apply H (No transpose)
|
|
* = 'T': apply H**T (Transpose)
|
|
*
|
|
* DIRECT (input) CHARACTER*1
|
|
* Indicates how H is formed from a product of elementary
|
|
* reflectors
|
|
* = 'F': H = H(1) H(2) . . . H(k) (Forward)
|
|
* = 'B': H = H(k) . . . H(2) H(1) (Backward)
|
|
*
|
|
* STOREV (input) CHARACTER*1
|
|
* Indicates how the vectors which define the elementary
|
|
* reflectors are stored:
|
|
* = 'C': Columnwise
|
|
* = 'R': Rowwise
|
|
*
|
|
* M (input) INTEGER
|
|
* The number of rows of the matrix C.
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of columns of the matrix C.
|
|
*
|
|
* K (input) INTEGER
|
|
* The order of the matrix T (= the number of elementary
|
|
* reflectors whose product defines the block reflector).
|
|
*
|
|
* V (input) DOUBLE PRECISION array, dimension
|
|
* (LDV,K) if STOREV = 'C'
|
|
* (LDV,M) if STOREV = 'R' and SIDE = 'L'
|
|
* (LDV,N) if STOREV = 'R' and SIDE = 'R'
|
|
* The matrix V. See Further Details.
|
|
*
|
|
* LDV (input) INTEGER
|
|
* The leading dimension of the array V.
|
|
* If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);
|
|
* if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);
|
|
* if STOREV = 'R', LDV >= K.
|
|
*
|
|
* T (input) DOUBLE PRECISION array, dimension (LDT,K)
|
|
* The triangular k by k matrix T in the representation of the
|
|
* block reflector.
|
|
*
|
|
* LDT (input) INTEGER
|
|
* The leading dimension of the array T. LDT >= K.
|
|
*
|
|
* C (input/output) DOUBLE PRECISION array, dimension (LDC,N)
|
|
* On entry, the m by n matrix C.
|
|
* On exit, C is overwritten by H*C or H**T*C or C*H or C*H**T.
|
|
*
|
|
* LDC (input) INTEGER
|
|
* The leading dimension of the array C. LDC >= max(1,M).
|
|
*
|
|
* WORK (workspace) DOUBLE PRECISION array, dimension (LDWORK,K)
|
|
*
|
|
* LDWORK (input) INTEGER
|
|
* The leading dimension of the array WORK.
|
|
* If SIDE = 'L', LDWORK >= max(1,N);
|
|
* if SIDE = 'R', LDWORK >= max(1,M).
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* The shape of the matrix V and the storage of the vectors which define
|
|
* the H(i) is best illustrated by the following example with n = 5 and
|
|
* k = 3. The elements equal to 1 are not stored; the corresponding
|
|
* array elements are modified but restored on exit. The rest of the
|
|
* array is not used.
|
|
*
|
|
* DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
|
|
*
|
|
* V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
|
|
* ( v1 1 ) ( 1 v2 v2 v2 )
|
|
* ( v1 v2 1 ) ( 1 v3 v3 )
|
|
* ( v1 v2 v3 )
|
|
* ( v1 v2 v3 )
|
|
*
|
|
* DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
|
|
*
|
|
* V = ( v1 v2 v3 ) V = ( v1 v1 1 )
|
|
* ( v1 v2 v3 ) ( v2 v2 v2 1 )
|
|
* ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
|
|
* ( 1 v3 )
|
|
* ( 1 )
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE
|
|
PARAMETER ( ONE = 1.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
CHARACTER TRANST
|
|
INTEGER I, J, LASTV, LASTC
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
INTEGER ILADLR, ILADLC
|
|
EXTERNAL LSAME, ILADLR, ILADLC
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DCOPY, DGEMM, DTRMM
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( M.LE.0 .OR. N.LE.0 )
|
|
$ RETURN
|
|
*
|
|
IF( LSAME( TRANS, 'N' ) ) THEN
|
|
TRANST = 'T'
|
|
ELSE
|
|
TRANST = 'N'
|
|
END IF
|
|
*
|
|
IF( LSAME( STOREV, 'C' ) ) THEN
|
|
*
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
*
|
|
* Let V = ( V1 ) (first K rows)
|
|
* ( V2 )
|
|
* where V1 is unit lower triangular.
|
|
*
|
|
IF( LSAME( SIDE, 'L' ) ) THEN
|
|
*
|
|
* Form H * C or H**T * C where C = ( C1 )
|
|
* ( C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLR( M, K, V, LDV ) )
|
|
LASTC = ILADLC( LASTV, N, C, LDC )
|
|
*
|
|
* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
|
|
*
|
|
* W := C1**T
|
|
*
|
|
DO 10 J = 1, K
|
|
CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
|
|
10 CONTINUE
|
|
*
|
|
* W := W * V1
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C2**T *V2
|
|
*
|
|
CALL DGEMM( 'Transpose', 'No transpose',
|
|
$ LASTC, K, LASTV-K,
|
|
$ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T**T or W * T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - V * W**T
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C2 := C2 - V2 * W**T
|
|
*
|
|
CALL DGEMM( 'No transpose', 'Transpose',
|
|
$ LASTV-K, LASTC, K,
|
|
$ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE,
|
|
$ C( K+1, 1 ), LDC )
|
|
END IF
|
|
*
|
|
* W := W * V1**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
*
|
|
* C1 := C1 - W**T
|
|
*
|
|
DO 30 J = 1, K
|
|
DO 20 I = 1, LASTC
|
|
C( J, I ) = C( J, I ) - WORK( I, J )
|
|
20 CONTINUE
|
|
30 CONTINUE
|
|
*
|
|
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
|
|
*
|
|
* Form C * H or C * H**T where C = ( C1 C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLR( N, K, V, LDV ) )
|
|
LASTC = ILADLR( M, LASTV, C, LDC )
|
|
*
|
|
* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
|
|
*
|
|
* W := C1
|
|
*
|
|
DO 40 J = 1, K
|
|
CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
|
|
40 CONTINUE
|
|
*
|
|
* W := W * V1
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C2 * V2
|
|
*
|
|
CALL DGEMM( 'No transpose', 'No transpose',
|
|
$ LASTC, K, LASTV-K,
|
|
$ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T or W * T**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - W * V**T
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C2 := C2 - W * V2**T
|
|
*
|
|
CALL DGEMM( 'No transpose', 'Transpose',
|
|
$ LASTC, LASTV-K, K,
|
|
$ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE,
|
|
$ C( 1, K+1 ), LDC )
|
|
END IF
|
|
*
|
|
* W := W * V1**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
*
|
|
* C1 := C1 - W
|
|
*
|
|
DO 60 J = 1, K
|
|
DO 50 I = 1, LASTC
|
|
C( I, J ) = C( I, J ) - WORK( I, J )
|
|
50 CONTINUE
|
|
60 CONTINUE
|
|
END IF
|
|
*
|
|
ELSE
|
|
*
|
|
* Let V = ( V1 )
|
|
* ( V2 ) (last K rows)
|
|
* where V2 is unit upper triangular.
|
|
*
|
|
IF( LSAME( SIDE, 'L' ) ) THEN
|
|
*
|
|
* Form H * C or H**T * C where C = ( C1 )
|
|
* ( C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLR( M, K, V, LDV ) )
|
|
LASTC = ILADLC( LASTV, N, C, LDC )
|
|
*
|
|
* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
|
|
*
|
|
* W := C2**T
|
|
*
|
|
DO 70 J = 1, K
|
|
CALL DCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
|
|
$ WORK( 1, J ), 1 )
|
|
70 CONTINUE
|
|
*
|
|
* W := W * V2
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C1**T*V1
|
|
*
|
|
CALL DGEMM( 'Transpose', 'No transpose',
|
|
$ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T**T or W * T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - V * W**T
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C1 := C1 - V1 * W**T
|
|
*
|
|
CALL DGEMM( 'No transpose', 'Transpose',
|
|
$ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
|
|
$ ONE, C, LDC )
|
|
END IF
|
|
*
|
|
* W := W * V2**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
*
|
|
* C2 := C2 - W**T
|
|
*
|
|
DO 90 J = 1, K
|
|
DO 80 I = 1, LASTC
|
|
C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J)
|
|
80 CONTINUE
|
|
90 CONTINUE
|
|
*
|
|
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
|
|
*
|
|
* Form C * H or C * H**T where C = ( C1 C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLR( N, K, V, LDV ) )
|
|
LASTC = ILADLR( M, LASTV, C, LDC )
|
|
*
|
|
* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
|
|
*
|
|
* W := C2
|
|
*
|
|
DO 100 J = 1, K
|
|
CALL DCOPY( LASTC, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
|
|
100 CONTINUE
|
|
*
|
|
* W := W * V2
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C1 * V1
|
|
*
|
|
CALL DGEMM( 'No transpose', 'No transpose',
|
|
$ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T or W * T**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - W * V**T
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C1 := C1 - W * V1**T
|
|
*
|
|
CALL DGEMM( 'No transpose', 'Transpose',
|
|
$ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
|
|
$ ONE, C, LDC )
|
|
END IF
|
|
*
|
|
* W := W * V2**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
*
|
|
* C2 := C2 - W
|
|
*
|
|
DO 120 J = 1, K
|
|
DO 110 I = 1, LASTC
|
|
C( I, LASTV-K+J ) = C( I, LASTV-K+J ) - WORK(I, J)
|
|
110 CONTINUE
|
|
120 CONTINUE
|
|
END IF
|
|
END IF
|
|
*
|
|
ELSE IF( LSAME( STOREV, 'R' ) ) THEN
|
|
*
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
*
|
|
* Let V = ( V1 V2 ) (V1: first K columns)
|
|
* where V1 is unit upper triangular.
|
|
*
|
|
IF( LSAME( SIDE, 'L' ) ) THEN
|
|
*
|
|
* Form H * C or H**T * C where C = ( C1 )
|
|
* ( C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLC( K, M, V, LDV ) )
|
|
LASTC = ILADLC( LASTV, N, C, LDC )
|
|
*
|
|
* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
|
|
*
|
|
* W := C1**T
|
|
*
|
|
DO 130 J = 1, K
|
|
CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
|
|
130 CONTINUE
|
|
*
|
|
* W := W * V1**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C2**T*V2**T
|
|
*
|
|
CALL DGEMM( 'Transpose', 'Transpose',
|
|
$ LASTC, K, LASTV-K,
|
|
$ ONE, C( K+1, 1 ), LDC, V( 1, K+1 ), LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T**T or W * T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - V**T * W**T
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C2 := C2 - V2**T * W**T
|
|
*
|
|
CALL DGEMM( 'Transpose', 'Transpose',
|
|
$ LASTV-K, LASTC, K,
|
|
$ -ONE, V( 1, K+1 ), LDV, WORK, LDWORK,
|
|
$ ONE, C( K+1, 1 ), LDC )
|
|
END IF
|
|
*
|
|
* W := W * V1
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
*
|
|
* C1 := C1 - W**T
|
|
*
|
|
DO 150 J = 1, K
|
|
DO 140 I = 1, LASTC
|
|
C( J, I ) = C( J, I ) - WORK( I, J )
|
|
140 CONTINUE
|
|
150 CONTINUE
|
|
*
|
|
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
|
|
*
|
|
* Form C * H or C * H**T where C = ( C1 C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLC( K, N, V, LDV ) )
|
|
LASTC = ILADLR( M, LASTV, C, LDC )
|
|
*
|
|
* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
|
|
*
|
|
* W := C1
|
|
*
|
|
DO 160 J = 1, K
|
|
CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
|
|
160 CONTINUE
|
|
*
|
|
* W := W * V1**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C2 * V2**T
|
|
*
|
|
CALL DGEMM( 'No transpose', 'Transpose',
|
|
$ LASTC, K, LASTV-K,
|
|
$ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T or W * T**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - W * V
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C2 := C2 - W * V2
|
|
*
|
|
CALL DGEMM( 'No transpose', 'No transpose',
|
|
$ LASTC, LASTV-K, K,
|
|
$ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV,
|
|
$ ONE, C( 1, K+1 ), LDC )
|
|
END IF
|
|
*
|
|
* W := W * V1
|
|
*
|
|
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
|
|
*
|
|
* C1 := C1 - W
|
|
*
|
|
DO 180 J = 1, K
|
|
DO 170 I = 1, LASTC
|
|
C( I, J ) = C( I, J ) - WORK( I, J )
|
|
170 CONTINUE
|
|
180 CONTINUE
|
|
*
|
|
END IF
|
|
*
|
|
ELSE
|
|
*
|
|
* Let V = ( V1 V2 ) (V2: last K columns)
|
|
* where V2 is unit lower triangular.
|
|
*
|
|
IF( LSAME( SIDE, 'L' ) ) THEN
|
|
*
|
|
* Form H * C or H**T * C where C = ( C1 )
|
|
* ( C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLC( K, M, V, LDV ) )
|
|
LASTC = ILADLC( LASTV, N, C, LDC )
|
|
*
|
|
* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
|
|
*
|
|
* W := C2**T
|
|
*
|
|
DO 190 J = 1, K
|
|
CALL DCOPY( LASTC, C( LASTV-K+J, 1 ), LDC,
|
|
$ WORK( 1, J ), 1 )
|
|
190 CONTINUE
|
|
*
|
|
* W := W * V2**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C1**T * V1**T
|
|
*
|
|
CALL DGEMM( 'Transpose', 'Transpose',
|
|
$ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T**T or W * T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - V**T * W**T
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C1 := C1 - V1**T * W**T
|
|
*
|
|
CALL DGEMM( 'Transpose', 'Transpose',
|
|
$ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
|
|
$ ONE, C, LDC )
|
|
END IF
|
|
*
|
|
* W := W * V2
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
*
|
|
* C2 := C2 - W**T
|
|
*
|
|
DO 210 J = 1, K
|
|
DO 200 I = 1, LASTC
|
|
C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J)
|
|
200 CONTINUE
|
|
210 CONTINUE
|
|
*
|
|
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
|
|
*
|
|
* Form C * H or C * H**T where C = ( C1 C2 )
|
|
*
|
|
LASTV = MAX( K, ILADLC( K, N, V, LDV ) )
|
|
LASTC = ILADLR( M, LASTV, C, LDC )
|
|
*
|
|
* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
|
|
*
|
|
* W := C2
|
|
*
|
|
DO 220 J = 1, K
|
|
CALL DCOPY( LASTC, C( 1, LASTV-K+J ), 1,
|
|
$ WORK( 1, J ), 1 )
|
|
220 CONTINUE
|
|
*
|
|
* W := W * V2**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* W := W + C1 * V1**T
|
|
*
|
|
CALL DGEMM( 'No transpose', 'Transpose',
|
|
$ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV,
|
|
$ ONE, WORK, LDWORK )
|
|
END IF
|
|
*
|
|
* W := W * T or W * T**T
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
|
|
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
|
|
*
|
|
* C := C - W * V
|
|
*
|
|
IF( LASTV.GT.K ) THEN
|
|
*
|
|
* C1 := C1 - W * V1
|
|
*
|
|
CALL DGEMM( 'No transpose', 'No transpose',
|
|
$ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV,
|
|
$ ONE, C, LDC )
|
|
END IF
|
|
*
|
|
* W := W * V2
|
|
*
|
|
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
|
|
$ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV,
|
|
$ WORK, LDWORK )
|
|
*
|
|
* C1 := C1 - W
|
|
*
|
|
DO 240 J = 1, K
|
|
DO 230 I = 1, LASTC
|
|
C( I, LASTV-K+J ) = C( I, LASTV-K+J ) - WORK(I, J)
|
|
230 CONTINUE
|
|
240 CONTINUE
|
|
*
|
|
END IF
|
|
*
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DLARFB
|
|
*
|
|
END
|
|
SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER INCX, N
|
|
DOUBLE PRECISION ALPHA, TAU
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION X( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLARFG generates a real elementary reflector H of order n, such
|
|
* that
|
|
*
|
|
* H * ( alpha ) = ( beta ), H**T * H = I.
|
|
* ( x ) ( 0 )
|
|
*
|
|
* where alpha and beta are scalars, and x is an (n-1)-element real
|
|
* vector. H is represented in the form
|
|
*
|
|
* H = I - tau * ( 1 ) * ( 1 v**T ) ,
|
|
* ( v )
|
|
*
|
|
* where tau is a real scalar and v is a real (n-1)-element
|
|
* vector.
|
|
*
|
|
* If the elements of x are all zero, then tau = 0 and H is taken to be
|
|
* the unit matrix.
|
|
*
|
|
* Otherwise 1 <= tau <= 2.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the elementary reflector.
|
|
*
|
|
* ALPHA (input/output) DOUBLE PRECISION
|
|
* On entry, the value alpha.
|
|
* On exit, it is overwritten with the value beta.
|
|
*
|
|
* X (input/output) DOUBLE PRECISION array, dimension
|
|
* (1+(N-2)*abs(INCX))
|
|
* On entry, the vector x.
|
|
* On exit, it is overwritten with the vector v.
|
|
*
|
|
* INCX (input) INTEGER
|
|
* The increment between elements of X. INCX > 0.
|
|
*
|
|
* TAU (output) DOUBLE PRECISION
|
|
* The value tau.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER J, KNT
|
|
DOUBLE PRECISION BETA, RSAFMN, SAFMIN, XNORM
|
|
* ..
|
|
* .. External Functions ..
|
|
DOUBLE PRECISION DLAMCH, DLAPY2, DNRM2
|
|
EXTERNAL DLAMCH, DLAPY2, DNRM2
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, SIGN
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DSCAL
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
IF( N.LE.1 ) THEN
|
|
TAU = ZERO
|
|
RETURN
|
|
END IF
|
|
*
|
|
XNORM = DNRM2( N-1, X, INCX )
|
|
*
|
|
IF( XNORM.EQ.ZERO ) THEN
|
|
*
|
|
* H = I
|
|
*
|
|
TAU = ZERO
|
|
ELSE
|
|
*
|
|
* general case
|
|
*
|
|
BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )
|
|
SAFMIN = DLAMCH( 'S' ) / DLAMCH( 'E' )
|
|
KNT = 0
|
|
IF( ABS( BETA ).LT.SAFMIN ) THEN
|
|
*
|
|
* XNORM, BETA may be inaccurate; scale X and recompute them
|
|
*
|
|
RSAFMN = ONE / SAFMIN
|
|
10 CONTINUE
|
|
KNT = KNT + 1
|
|
CALL DSCAL( N-1, RSAFMN, X, INCX )
|
|
BETA = BETA*RSAFMN
|
|
ALPHA = ALPHA*RSAFMN
|
|
IF( ABS( BETA ).LT.SAFMIN )
|
|
$ GO TO 10
|
|
*
|
|
* New BETA is at most 1, at least SAFMIN
|
|
*
|
|
XNORM = DNRM2( N-1, X, INCX )
|
|
BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )
|
|
END IF
|
|
TAU = ( BETA-ALPHA ) / BETA
|
|
CALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX )
|
|
*
|
|
* If ALPHA is subnormal, it may lose relative accuracy
|
|
*
|
|
DO 20 J = 1, KNT
|
|
BETA = BETA*SAFMIN
|
|
20 CONTINUE
|
|
ALPHA = BETA
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DLARFG
|
|
*
|
|
END
|
|
SUBROUTINE DLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
|
|
IMPLICIT NONE
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER DIRECT, STOREV
|
|
INTEGER K, LDT, LDV, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLARFT forms the triangular factor T of a real block reflector H
|
|
* of order n, which is defined as a product of k elementary reflectors.
|
|
*
|
|
* If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
|
|
*
|
|
* If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
|
|
*
|
|
* If STOREV = 'C', the vector which defines the elementary reflector
|
|
* H(i) is stored in the i-th column of the array V, and
|
|
*
|
|
* H = I - V * T * V**T
|
|
*
|
|
* If STOREV = 'R', the vector which defines the elementary reflector
|
|
* H(i) is stored in the i-th row of the array V, and
|
|
*
|
|
* H = I - V**T * T * V
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* DIRECT (input) CHARACTER*1
|
|
* Specifies the order in which the elementary reflectors are
|
|
* multiplied to form the block reflector:
|
|
* = 'F': H = H(1) H(2) . . . H(k) (Forward)
|
|
* = 'B': H = H(k) . . . H(2) H(1) (Backward)
|
|
*
|
|
* STOREV (input) CHARACTER*1
|
|
* Specifies how the vectors which define the elementary
|
|
* reflectors are stored (see also Further Details):
|
|
* = 'C': columnwise
|
|
* = 'R': rowwise
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the block reflector H. N >= 0.
|
|
*
|
|
* K (input) INTEGER
|
|
* The order of the triangular factor T (= the number of
|
|
* elementary reflectors). K >= 1.
|
|
*
|
|
* V (input/output) DOUBLE PRECISION array, dimension
|
|
* (LDV,K) if STOREV = 'C'
|
|
* (LDV,N) if STOREV = 'R'
|
|
* The matrix V. See further details.
|
|
*
|
|
* LDV (input) INTEGER
|
|
* The leading dimension of the array V.
|
|
* If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
|
|
*
|
|
* TAU (input) DOUBLE PRECISION array, dimension (K)
|
|
* TAU(i) must contain the scalar factor of the elementary
|
|
* reflector H(i).
|
|
*
|
|
* T (output) DOUBLE PRECISION array, dimension (LDT,K)
|
|
* The k by k triangular factor T of the block reflector.
|
|
* If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
|
|
* lower triangular. The rest of the array is not used.
|
|
*
|
|
* LDT (input) INTEGER
|
|
* The leading dimension of the array T. LDT >= K.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* The shape of the matrix V and the storage of the vectors which define
|
|
* the H(i) is best illustrated by the following example with n = 5 and
|
|
* k = 3. The elements equal to 1 are not stored; the corresponding
|
|
* array elements are modified but restored on exit. The rest of the
|
|
* array is not used.
|
|
*
|
|
* DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
|
|
*
|
|
* V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
|
|
* ( v1 1 ) ( 1 v2 v2 v2 )
|
|
* ( v1 v2 1 ) ( 1 v3 v3 )
|
|
* ( v1 v2 v3 )
|
|
* ( v1 v2 v3 )
|
|
*
|
|
* DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
|
|
*
|
|
* V = ( v1 v2 v3 ) V = ( v1 v1 1 )
|
|
* ( v1 v2 v3 ) ( v2 v2 v2 1 )
|
|
* ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
|
|
* ( 1 v3 )
|
|
* ( 1 )
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, J, PREVLASTV, LASTV
|
|
DOUBLE PRECISION VII
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DGEMV, DTRMV
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.EQ.0 )
|
|
$ RETURN
|
|
*
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
PREVLASTV = N
|
|
DO 20 I = 1, K
|
|
PREVLASTV = MAX( I, PREVLASTV )
|
|
IF( TAU( I ).EQ.ZERO ) THEN
|
|
*
|
|
* H(i) = I
|
|
*
|
|
DO 10 J = 1, I
|
|
T( J, I ) = ZERO
|
|
10 CONTINUE
|
|
ELSE
|
|
*
|
|
* general case
|
|
*
|
|
VII = V( I, I )
|
|
V( I, I ) = ONE
|
|
IF( LSAME( STOREV, 'C' ) ) THEN
|
|
! Skip any trailing zeros.
|
|
DO LASTV = N, I+1, -1
|
|
IF( V( LASTV, I ).NE.ZERO ) EXIT
|
|
END DO
|
|
J = MIN( LASTV, PREVLASTV )
|
|
*
|
|
* T(1:i-1,i) := - tau(i) * V(i:j,1:i-1)**T * V(i:j,i)
|
|
*
|
|
CALL DGEMV( 'Transpose', J-I+1, I-1, -TAU( I ),
|
|
$ V( I, 1 ), LDV, V( I, I ), 1, ZERO,
|
|
$ T( 1, I ), 1 )
|
|
ELSE
|
|
! Skip any trailing zeros.
|
|
DO LASTV = N, I+1, -1
|
|
IF( V( I, LASTV ).NE.ZERO ) EXIT
|
|
END DO
|
|
J = MIN( LASTV, PREVLASTV )
|
|
*
|
|
* T(1:i-1,i) := - tau(i) * V(1:i-1,i:j) * V(i,i:j)**T
|
|
*
|
|
CALL DGEMV( 'No transpose', I-1, J-I+1, -TAU( I ),
|
|
$ V( 1, I ), LDV, V( I, I ), LDV, ZERO,
|
|
$ T( 1, I ), 1 )
|
|
END IF
|
|
V( I, I ) = VII
|
|
*
|
|
* T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i)
|
|
*
|
|
CALL DTRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T,
|
|
$ LDT, T( 1, I ), 1 )
|
|
T( I, I ) = TAU( I )
|
|
IF( I.GT.1 ) THEN
|
|
PREVLASTV = MAX( PREVLASTV, LASTV )
|
|
ELSE
|
|
PREVLASTV = LASTV
|
|
END IF
|
|
END IF
|
|
20 CONTINUE
|
|
ELSE
|
|
PREVLASTV = 1
|
|
DO 40 I = K, 1, -1
|
|
IF( TAU( I ).EQ.ZERO ) THEN
|
|
*
|
|
* H(i) = I
|
|
*
|
|
DO 30 J = I, K
|
|
T( J, I ) = ZERO
|
|
30 CONTINUE
|
|
ELSE
|
|
*
|
|
* general case
|
|
*
|
|
IF( I.LT.K ) THEN
|
|
IF( LSAME( STOREV, 'C' ) ) THEN
|
|
VII = V( N-K+I, I )
|
|
V( N-K+I, I ) = ONE
|
|
! Skip any leading zeros.
|
|
DO LASTV = 1, I-1
|
|
IF( V( LASTV, I ).NE.ZERO ) EXIT
|
|
END DO
|
|
J = MAX( LASTV, PREVLASTV )
|
|
*
|
|
* T(i+1:k,i) :=
|
|
* - tau(i) * V(j:n-k+i,i+1:k)**T * V(j:n-k+i,i)
|
|
*
|
|
CALL DGEMV( 'Transpose', N-K+I-J+1, K-I, -TAU( I ),
|
|
$ V( J, I+1 ), LDV, V( J, I ), 1, ZERO,
|
|
$ T( I+1, I ), 1 )
|
|
V( N-K+I, I ) = VII
|
|
ELSE
|
|
VII = V( I, N-K+I )
|
|
V( I, N-K+I ) = ONE
|
|
! Skip any leading zeros.
|
|
DO LASTV = 1, I-1
|
|
IF( V( I, LASTV ).NE.ZERO ) EXIT
|
|
END DO
|
|
J = MAX( LASTV, PREVLASTV )
|
|
*
|
|
* T(i+1:k,i) :=
|
|
* - tau(i) * V(i+1:k,j:n-k+i) * V(i,j:n-k+i)**T
|
|
*
|
|
CALL DGEMV( 'No transpose', K-I, N-K+I-J+1,
|
|
$ -TAU( I ), V( I+1, J ), LDV, V( I, J ), LDV,
|
|
$ ZERO, T( I+1, I ), 1 )
|
|
V( I, N-K+I ) = VII
|
|
END IF
|
|
*
|
|
* T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i)
|
|
*
|
|
CALL DTRMV( 'Lower', 'No transpose', 'Non-unit', K-I,
|
|
$ T( I+1, I+1 ), LDT, T( I+1, I ), 1 )
|
|
IF( I.GT.1 ) THEN
|
|
PREVLASTV = MIN( PREVLASTV, LASTV )
|
|
ELSE
|
|
PREVLASTV = LASTV
|
|
END IF
|
|
END IF
|
|
T( I, I ) = TAU( I )
|
|
END IF
|
|
40 CONTINUE
|
|
END IF
|
|
RETURN
|
|
*
|
|
* End of DLARFT
|
|
*
|
|
END
|
|
SUBROUTINE DLARTG( F, G, CS, SN, R )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION CS, F, G, R, SN
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLARTG generate a plane rotation so that
|
|
*
|
|
* [ CS SN ] . [ F ] = [ R ] where CS**2 + SN**2 = 1.
|
|
* [ -SN CS ] [ G ] [ 0 ]
|
|
*
|
|
* This is a slower, more accurate version of the BLAS1 routine DROTG,
|
|
* with the following other differences:
|
|
* F and G are unchanged on return.
|
|
* If G=0, then CS=1 and SN=0.
|
|
* If F=0 and (G .ne. 0), then CS=0 and SN=1 without doing any
|
|
* floating point operations (saves work in DBDSQR when
|
|
* there are zeros on the diagonal).
|
|
*
|
|
* If F exceeds G in magnitude, CS will be positive.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* F (input) DOUBLE PRECISION
|
|
* The first component of vector to be rotated.
|
|
*
|
|
* G (input) DOUBLE PRECISION
|
|
* The second component of vector to be rotated.
|
|
*
|
|
* CS (output) DOUBLE PRECISION
|
|
* The cosine of the rotation.
|
|
*
|
|
* SN (output) DOUBLE PRECISION
|
|
* The sine of the rotation.
|
|
*
|
|
* R (output) DOUBLE PRECISION
|
|
* The nonzero component of the rotated vector.
|
|
*
|
|
* This version has a few statements commented out for thread safety
|
|
* (machine parameters are computed on each entry). 10 feb 03, SJH.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER ( ZERO = 0.0D0 )
|
|
DOUBLE PRECISION ONE
|
|
PARAMETER ( ONE = 1.0D0 )
|
|
DOUBLE PRECISION TWO
|
|
PARAMETER ( TWO = 2.0D0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
* LOGICAL FIRST
|
|
INTEGER COUNT, I
|
|
DOUBLE PRECISION EPS, F1, G1, SAFMIN, SAFMN2, SAFMX2, SCALE
|
|
* ..
|
|
* .. External Functions ..
|
|
DOUBLE PRECISION DLAMCH
|
|
EXTERNAL DLAMCH
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, INT, LOG, MAX, SQRT
|
|
* ..
|
|
* .. Save statement ..
|
|
* SAVE FIRST, SAFMX2, SAFMIN, SAFMN2
|
|
* ..
|
|
* .. Data statements ..
|
|
* DATA FIRST / .TRUE. /
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* IF( FIRST ) THEN
|
|
SAFMIN = DLAMCH( 'S' )
|
|
EPS = DLAMCH( 'E' )
|
|
SAFMN2 = DLAMCH( 'B' )**INT( LOG( SAFMIN / EPS ) /
|
|
$ LOG( DLAMCH( 'B' ) ) / TWO )
|
|
SAFMX2 = ONE / SAFMN2
|
|
* FIRST = .FALSE.
|
|
* END IF
|
|
IF( G.EQ.ZERO ) THEN
|
|
CS = ONE
|
|
SN = ZERO
|
|
R = F
|
|
ELSE IF( F.EQ.ZERO ) THEN
|
|
CS = ZERO
|
|
SN = ONE
|
|
R = G
|
|
ELSE
|
|
F1 = F
|
|
G1 = G
|
|
SCALE = MAX( ABS( F1 ), ABS( G1 ) )
|
|
IF( SCALE.GE.SAFMX2 ) THEN
|
|
COUNT = 0
|
|
10 CONTINUE
|
|
COUNT = COUNT + 1
|
|
F1 = F1*SAFMN2
|
|
G1 = G1*SAFMN2
|
|
SCALE = MAX( ABS( F1 ), ABS( G1 ) )
|
|
IF( SCALE.GE.SAFMX2 )
|
|
$ GO TO 10
|
|
R = SQRT( F1**2+G1**2 )
|
|
CS = F1 / R
|
|
SN = G1 / R
|
|
DO 20 I = 1, COUNT
|
|
R = R*SAFMX2
|
|
20 CONTINUE
|
|
ELSE IF( SCALE.LE.SAFMN2 ) THEN
|
|
COUNT = 0
|
|
30 CONTINUE
|
|
COUNT = COUNT + 1
|
|
F1 = F1*SAFMX2
|
|
G1 = G1*SAFMX2
|
|
SCALE = MAX( ABS( F1 ), ABS( G1 ) )
|
|
IF( SCALE.LE.SAFMN2 )
|
|
$ GO TO 30
|
|
R = SQRT( F1**2+G1**2 )
|
|
CS = F1 / R
|
|
SN = G1 / R
|
|
DO 40 I = 1, COUNT
|
|
R = R*SAFMN2
|
|
40 CONTINUE
|
|
ELSE
|
|
R = SQRT( F1**2+G1**2 )
|
|
CS = F1 / R
|
|
SN = G1 / R
|
|
END IF
|
|
IF( ABS( F ).GT.ABS( G ) .AND. CS.LT.ZERO ) THEN
|
|
CS = -CS
|
|
SN = -SN
|
|
R = -R
|
|
END IF
|
|
END IF
|
|
RETURN
|
|
*
|
|
* End of DLARTG
|
|
*
|
|
END
|
|
SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.3.0) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2010
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER TYPE
|
|
INTEGER INFO, KL, KU, LDA, M, N
|
|
DOUBLE PRECISION CFROM, CTO
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLASCL multiplies the M by N real matrix A by the real scalar
|
|
* CTO/CFROM. This is done without over/underflow as long as the final
|
|
* result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that
|
|
* A may be full, upper triangular, lower triangular, upper Hessenberg,
|
|
* or banded.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* TYPE (input) CHARACTER*1
|
|
* TYPE indices the storage type of the input matrix.
|
|
* = 'G': A is a full matrix.
|
|
* = 'L': A is a lower triangular matrix.
|
|
* = 'U': A is an upper triangular matrix.
|
|
* = 'H': A is an upper Hessenberg matrix.
|
|
* = 'B': A is a symmetric band matrix with lower bandwidth KL
|
|
* and upper bandwidth KU and with the only the lower
|
|
* half stored.
|
|
* = 'Q': A is a symmetric band matrix with lower bandwidth KL
|
|
* and upper bandwidth KU and with the only the upper
|
|
* half stored.
|
|
* = 'Z': A is a band matrix with lower bandwidth KL and upper
|
|
* bandwidth KU. See DGBTRF for storage details.
|
|
*
|
|
* KL (input) INTEGER
|
|
* The lower bandwidth of A. Referenced only if TYPE = 'B',
|
|
* 'Q' or 'Z'.
|
|
*
|
|
* KU (input) INTEGER
|
|
* The upper bandwidth of A. Referenced only if TYPE = 'B',
|
|
* 'Q' or 'Z'.
|
|
*
|
|
* CFROM (input) DOUBLE PRECISION
|
|
* CTO (input) DOUBLE PRECISION
|
|
* The matrix A is multiplied by CTO/CFROM. A(I,J) is computed
|
|
* without over/underflow if the final result CTO*A(I,J)/CFROM
|
|
* can be represented without over/underflow. CFROM must be
|
|
* nonzero.
|
|
*
|
|
* 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/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* The matrix to be multiplied by CTO/CFROM. See TYPE for the
|
|
* storage type.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= max(1,M).
|
|
*
|
|
* INFO (output) INTEGER
|
|
* 0 - successful exit
|
|
* <0 - if INFO = -i, the i-th argument had an illegal value.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO, ONE
|
|
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL DONE
|
|
INTEGER I, ITYPE, J, K1, K2, K3, K4
|
|
DOUBLE PRECISION BIGNUM, CFROM1, CFROMC, CTO1, CTOC, MUL, SMLNUM
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME, DISNAN
|
|
DOUBLE PRECISION DLAMCH
|
|
EXTERNAL LSAME, DLAMCH, DISNAN
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, MAX, MIN
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input arguments
|
|
*
|
|
INFO = 0
|
|
*
|
|
IF( LSAME( TYPE, 'G' ) ) THEN
|
|
ITYPE = 0
|
|
ELSE IF( LSAME( TYPE, 'L' ) ) THEN
|
|
ITYPE = 1
|
|
ELSE IF( LSAME( TYPE, 'U' ) ) THEN
|
|
ITYPE = 2
|
|
ELSE IF( LSAME( TYPE, 'H' ) ) THEN
|
|
ITYPE = 3
|
|
ELSE IF( LSAME( TYPE, 'B' ) ) THEN
|
|
ITYPE = 4
|
|
ELSE IF( LSAME( TYPE, 'Q' ) ) THEN
|
|
ITYPE = 5
|
|
ELSE IF( LSAME( TYPE, 'Z' ) ) THEN
|
|
ITYPE = 6
|
|
ELSE
|
|
ITYPE = -1
|
|
END IF
|
|
*
|
|
IF( ITYPE.EQ.-1 ) THEN
|
|
INFO = -1
|
|
ELSE IF( CFROM.EQ.ZERO .OR. DISNAN(CFROM) ) THEN
|
|
INFO = -4
|
|
ELSE IF( DISNAN(CTO) ) THEN
|
|
INFO = -5
|
|
ELSE IF( M.LT.0 ) THEN
|
|
INFO = -6
|
|
ELSE IF( N.LT.0 .OR. ( ITYPE.EQ.4 .AND. N.NE.M ) .OR.
|
|
$ ( ITYPE.EQ.5 .AND. N.NE.M ) ) THEN
|
|
INFO = -7
|
|
ELSE IF( ITYPE.LE.3 .AND. LDA.LT.MAX( 1, M ) ) THEN
|
|
INFO = -9
|
|
ELSE IF( ITYPE.GE.4 ) THEN
|
|
IF( KL.LT.0 .OR. KL.GT.MAX( M-1, 0 ) ) THEN
|
|
INFO = -2
|
|
ELSE IF( KU.LT.0 .OR. KU.GT.MAX( N-1, 0 ) .OR.
|
|
$ ( ( ITYPE.EQ.4 .OR. ITYPE.EQ.5 ) .AND. KL.NE.KU ) )
|
|
$ THEN
|
|
INFO = -3
|
|
ELSE IF( ( ITYPE.EQ.4 .AND. LDA.LT.KL+1 ) .OR.
|
|
$ ( ITYPE.EQ.5 .AND. LDA.LT.KU+1 ) .OR.
|
|
$ ( ITYPE.EQ.6 .AND. LDA.LT.2*KL+KU+1 ) ) THEN
|
|
INFO = -9
|
|
END IF
|
|
END IF
|
|
*
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DLASCL', -INFO )
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.EQ.0 .OR. M.EQ.0 )
|
|
$ RETURN
|
|
*
|
|
* Get machine parameters
|
|
*
|
|
SMLNUM = DLAMCH( 'S' )
|
|
BIGNUM = ONE / SMLNUM
|
|
*
|
|
CFROMC = CFROM
|
|
CTOC = CTO
|
|
*
|
|
10 CONTINUE
|
|
CFROM1 = CFROMC*SMLNUM
|
|
IF( CFROM1.EQ.CFROMC ) THEN
|
|
! CFROMC is an inf. Multiply by a correctly signed zero for
|
|
! finite CTOC, or a NaN if CTOC is infinite.
|
|
MUL = CTOC / CFROMC
|
|
DONE = .TRUE.
|
|
CTO1 = CTOC
|
|
ELSE
|
|
CTO1 = CTOC / BIGNUM
|
|
IF( CTO1.EQ.CTOC ) THEN
|
|
! CTOC is either 0 or an inf. In both cases, CTOC itself
|
|
! serves as the correct multiplication factor.
|
|
MUL = CTOC
|
|
DONE = .TRUE.
|
|
CFROMC = ONE
|
|
ELSE IF( ABS( CFROM1 ).GT.ABS( CTOC ) .AND. CTOC.NE.ZERO ) THEN
|
|
MUL = SMLNUM
|
|
DONE = .FALSE.
|
|
CFROMC = CFROM1
|
|
ELSE IF( ABS( CTO1 ).GT.ABS( CFROMC ) ) THEN
|
|
MUL = BIGNUM
|
|
DONE = .FALSE.
|
|
CTOC = CTO1
|
|
ELSE
|
|
MUL = CTOC / CFROMC
|
|
DONE = .TRUE.
|
|
END IF
|
|
END IF
|
|
*
|
|
IF( ITYPE.EQ.0 ) THEN
|
|
*
|
|
* Full matrix
|
|
*
|
|
DO 30 J = 1, N
|
|
DO 20 I = 1, M
|
|
A( I, J ) = A( I, J )*MUL
|
|
20 CONTINUE
|
|
30 CONTINUE
|
|
*
|
|
ELSE IF( ITYPE.EQ.1 ) THEN
|
|
*
|
|
* Lower triangular matrix
|
|
*
|
|
DO 50 J = 1, N
|
|
DO 40 I = J, M
|
|
A( I, J ) = A( I, J )*MUL
|
|
40 CONTINUE
|
|
50 CONTINUE
|
|
*
|
|
ELSE IF( ITYPE.EQ.2 ) THEN
|
|
*
|
|
* Upper triangular matrix
|
|
*
|
|
DO 70 J = 1, N
|
|
DO 60 I = 1, MIN( J, M )
|
|
A( I, J ) = A( I, J )*MUL
|
|
60 CONTINUE
|
|
70 CONTINUE
|
|
*
|
|
ELSE IF( ITYPE.EQ.3 ) THEN
|
|
*
|
|
* Upper Hessenberg matrix
|
|
*
|
|
DO 90 J = 1, N
|
|
DO 80 I = 1, MIN( J+1, M )
|
|
A( I, J ) = A( I, J )*MUL
|
|
80 CONTINUE
|
|
90 CONTINUE
|
|
*
|
|
ELSE IF( ITYPE.EQ.4 ) THEN
|
|
*
|
|
* Lower half of a symmetric band matrix
|
|
*
|
|
K3 = KL + 1
|
|
K4 = N + 1
|
|
DO 110 J = 1, N
|
|
DO 100 I = 1, MIN( K3, K4-J )
|
|
A( I, J ) = A( I, J )*MUL
|
|
100 CONTINUE
|
|
110 CONTINUE
|
|
*
|
|
ELSE IF( ITYPE.EQ.5 ) THEN
|
|
*
|
|
* Upper half of a symmetric band matrix
|
|
*
|
|
K1 = KU + 2
|
|
K3 = KU + 1
|
|
DO 130 J = 1, N
|
|
DO 120 I = MAX( K1-J, 1 ), K3
|
|
A( I, J ) = A( I, J )*MUL
|
|
120 CONTINUE
|
|
130 CONTINUE
|
|
*
|
|
ELSE IF( ITYPE.EQ.6 ) THEN
|
|
*
|
|
* Band matrix
|
|
*
|
|
K1 = KL + KU + 2
|
|
K2 = KL + 1
|
|
K3 = 2*KL + KU + 1
|
|
K4 = KL + KU + 1 + M
|
|
DO 150 J = 1, N
|
|
DO 140 I = MAX( K1-J, K2 ), MIN( K3, K4-J )
|
|
A( I, J ) = A( I, J )*MUL
|
|
140 CONTINUE
|
|
150 CONTINUE
|
|
*
|
|
END IF
|
|
*
|
|
IF( .NOT.DONE )
|
|
$ GO TO 10
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DLASCL
|
|
*
|
|
END
|
|
SUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER UPLO
|
|
INTEGER LDA, M, N
|
|
DOUBLE PRECISION ALPHA, BETA
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLASET initializes an m-by-n matrix A to BETA on the diagonal and
|
|
* ALPHA on the offdiagonals.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* UPLO (input) CHARACTER*1
|
|
* Specifies the part of the matrix A to be set.
|
|
* = 'U': Upper triangular part is set; the strictly lower
|
|
* triangular part of A is not changed.
|
|
* = 'L': Lower triangular part is set; the strictly upper
|
|
* triangular part of A is not changed.
|
|
* Otherwise: All of the matrix A is set.
|
|
*
|
|
* 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.
|
|
*
|
|
* ALPHA (input) DOUBLE PRECISION
|
|
* The constant to which the offdiagonal elements are to be set.
|
|
*
|
|
* BETA (input) DOUBLE PRECISION
|
|
* The constant to which the diagonal elements are to be set.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* On exit, the leading m-by-n submatrix of A is set as follows:
|
|
*
|
|
* if UPLO = 'U', A(i,j) = ALPHA, 1<=i<=j-1, 1<=j<=n,
|
|
* if UPLO = 'L', A(i,j) = ALPHA, j+1<=i<=m, 1<=j<=n,
|
|
* otherwise, A(i,j) = ALPHA, 1<=i<=m, 1<=j<=n, i.ne.j,
|
|
*
|
|
* and, for all UPLO, A(i,i) = BETA, 1<=i<=min(m,n).
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= 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
|
|
*
|
|
* Set the strictly upper triangular or trapezoidal part of the
|
|
* array to ALPHA.
|
|
*
|
|
DO 20 J = 2, N
|
|
DO 10 I = 1, MIN( J-1, M )
|
|
A( I, J ) = ALPHA
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
*
|
|
ELSE IF( LSAME( UPLO, 'L' ) ) THEN
|
|
*
|
|
* Set the strictly lower triangular or trapezoidal part of the
|
|
* array to ALPHA.
|
|
*
|
|
DO 40 J = 1, MIN( M, N )
|
|
DO 30 I = J + 1, M
|
|
A( I, J ) = ALPHA
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
*
|
|
ELSE
|
|
*
|
|
* Set the leading m-by-n submatrix to ALPHA.
|
|
*
|
|
DO 60 J = 1, N
|
|
DO 50 I = 1, M
|
|
A( I, J ) = ALPHA
|
|
50 CONTINUE
|
|
60 CONTINUE
|
|
END IF
|
|
*
|
|
* Set the first min(M,N) diagonal elements to BETA.
|
|
*
|
|
DO 70 I = 1, MIN( M, N )
|
|
A( I, I ) = BETA
|
|
70 CONTINUE
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DLASET
|
|
*
|
|
END
|
|
SUBROUTINE DLASR( SIDE, PIVOT, DIRECT, M, N, C, S, A, LDA )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER DIRECT, PIVOT, SIDE
|
|
INTEGER LDA, M, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), C( * ), S( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLASR applies a sequence of plane rotations to a real matrix A,
|
|
* from either the left or the right.
|
|
*
|
|
* When SIDE = 'L', the transformation takes the form
|
|
*
|
|
* A := P*A
|
|
*
|
|
* and when SIDE = 'R', the transformation takes the form
|
|
*
|
|
* A := A*P**T
|
|
*
|
|
* where P is an orthogonal matrix consisting of a sequence of z plane
|
|
* rotations, with z = M when SIDE = 'L' and z = N when SIDE = 'R',
|
|
* and P**T is the transpose of P.
|
|
*
|
|
* When DIRECT = 'F' (Forward sequence), then
|
|
*
|
|
* P = P(z-1) * ... * P(2) * P(1)
|
|
*
|
|
* and when DIRECT = 'B' (Backward sequence), then
|
|
*
|
|
* P = P(1) * P(2) * ... * P(z-1)
|
|
*
|
|
* where P(k) is a plane rotation matrix defined by the 2-by-2 rotation
|
|
*
|
|
* R(k) = ( c(k) s(k) )
|
|
* = ( -s(k) c(k) ).
|
|
*
|
|
* When PIVOT = 'V' (Variable pivot), the rotation is performed
|
|
* for the plane (k,k+1), i.e., P(k) has the form
|
|
*
|
|
* P(k) = ( 1 )
|
|
* ( ... )
|
|
* ( 1 )
|
|
* ( c(k) s(k) )
|
|
* ( -s(k) c(k) )
|
|
* ( 1 )
|
|
* ( ... )
|
|
* ( 1 )
|
|
*
|
|
* where R(k) appears as a rank-2 modification to the identity matrix in
|
|
* rows and columns k and k+1.
|
|
*
|
|
* When PIVOT = 'T' (Top pivot), the rotation is performed for the
|
|
* plane (1,k+1), so P(k) has the form
|
|
*
|
|
* P(k) = ( c(k) s(k) )
|
|
* ( 1 )
|
|
* ( ... )
|
|
* ( 1 )
|
|
* ( -s(k) c(k) )
|
|
* ( 1 )
|
|
* ( ... )
|
|
* ( 1 )
|
|
*
|
|
* where R(k) appears in rows and columns 1 and k+1.
|
|
*
|
|
* Similarly, when PIVOT = 'B' (Bottom pivot), the rotation is
|
|
* performed for the plane (k,z), giving P(k) the form
|
|
*
|
|
* P(k) = ( 1 )
|
|
* ( ... )
|
|
* ( 1 )
|
|
* ( c(k) s(k) )
|
|
* ( 1 )
|
|
* ( ... )
|
|
* ( 1 )
|
|
* ( -s(k) c(k) )
|
|
*
|
|
* where R(k) appears in rows and columns k and z. The rotations are
|
|
* performed without ever forming P(k) explicitly.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* SIDE (input) CHARACTER*1
|
|
* Specifies whether the plane rotation matrix P is applied to
|
|
* A on the left or the right.
|
|
* = 'L': Left, compute A := P*A
|
|
* = 'R': Right, compute A:= A*P**T
|
|
*
|
|
* PIVOT (input) CHARACTER*1
|
|
* Specifies the plane for which P(k) is a plane rotation
|
|
* matrix.
|
|
* = 'V': Variable pivot, the plane (k,k+1)
|
|
* = 'T': Top pivot, the plane (1,k+1)
|
|
* = 'B': Bottom pivot, the plane (k,z)
|
|
*
|
|
* DIRECT (input) CHARACTER*1
|
|
* Specifies whether P is a forward or backward sequence of
|
|
* plane rotations.
|
|
* = 'F': Forward, P = P(z-1)*...*P(2)*P(1)
|
|
* = 'B': Backward, P = P(1)*P(2)*...*P(z-1)
|
|
*
|
|
* M (input) INTEGER
|
|
* The number of rows of the matrix A. If m <= 1, an immediate
|
|
* return is effected.
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of columns of the matrix A. If n <= 1, an
|
|
* immediate return is effected.
|
|
*
|
|
* C (input) DOUBLE PRECISION array, dimension
|
|
* (M-1) if SIDE = 'L'
|
|
* (N-1) if SIDE = 'R'
|
|
* The cosines c(k) of the plane rotations.
|
|
*
|
|
* S (input) DOUBLE PRECISION array, dimension
|
|
* (M-1) if SIDE = 'L'
|
|
* (N-1) if SIDE = 'R'
|
|
* The sines s(k) of the plane rotations. The 2-by-2 plane
|
|
* rotation part of the matrix P(k), R(k), has the form
|
|
* R(k) = ( c(k) s(k) )
|
|
* ( -s(k) c(k) ).
|
|
*
|
|
* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* The M-by-N matrix A. On exit, A is overwritten by P*A if
|
|
* SIDE = 'R' or by A*P**T if SIDE = 'L'.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= max(1,M).
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, INFO, J
|
|
DOUBLE PRECISION CTEMP, STEMP, TEMP
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input parameters
|
|
*
|
|
INFO = 0
|
|
IF( .NOT.( LSAME( SIDE, 'L' ) .OR. LSAME( SIDE, 'R' ) ) ) THEN
|
|
INFO = 1
|
|
ELSE IF( .NOT.( LSAME( PIVOT, 'V' ) .OR. LSAME( PIVOT,
|
|
$ 'T' ) .OR. LSAME( PIVOT, 'B' ) ) ) THEN
|
|
INFO = 2
|
|
ELSE IF( .NOT.( LSAME( DIRECT, 'F' ) .OR. LSAME( DIRECT, 'B' ) ) )
|
|
$ THEN
|
|
INFO = 3
|
|
ELSE IF( M.LT.0 ) THEN
|
|
INFO = 4
|
|
ELSE IF( N.LT.0 ) THEN
|
|
INFO = 5
|
|
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
|
|
INFO = 9
|
|
END IF
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DLASR ', INFO )
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( ( M.EQ.0 ) .OR. ( N.EQ.0 ) )
|
|
$ RETURN
|
|
IF( LSAME( SIDE, 'L' ) ) THEN
|
|
*
|
|
* Form P * A
|
|
*
|
|
IF( LSAME( PIVOT, 'V' ) ) THEN
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
DO 20 J = 1, M - 1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 10 I = 1, N
|
|
TEMP = A( J+1, I )
|
|
A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I )
|
|
A( J, I ) = STEMP*TEMP + CTEMP*A( J, I )
|
|
10 CONTINUE
|
|
END IF
|
|
20 CONTINUE
|
|
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
|
|
DO 40 J = M - 1, 1, -1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 30 I = 1, N
|
|
TEMP = A( J+1, I )
|
|
A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I )
|
|
A( J, I ) = STEMP*TEMP + CTEMP*A( J, I )
|
|
30 CONTINUE
|
|
END IF
|
|
40 CONTINUE
|
|
END IF
|
|
ELSE IF( LSAME( PIVOT, 'T' ) ) THEN
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
DO 60 J = 2, M
|
|
CTEMP = C( J-1 )
|
|
STEMP = S( J-1 )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 50 I = 1, N
|
|
TEMP = A( J, I )
|
|
A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I )
|
|
A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I )
|
|
50 CONTINUE
|
|
END IF
|
|
60 CONTINUE
|
|
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
|
|
DO 80 J = M, 2, -1
|
|
CTEMP = C( J-1 )
|
|
STEMP = S( J-1 )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 70 I = 1, N
|
|
TEMP = A( J, I )
|
|
A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I )
|
|
A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I )
|
|
70 CONTINUE
|
|
END IF
|
|
80 CONTINUE
|
|
END IF
|
|
ELSE IF( LSAME( PIVOT, 'B' ) ) THEN
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
DO 100 J = 1, M - 1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 90 I = 1, N
|
|
TEMP = A( J, I )
|
|
A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMP
|
|
A( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP
|
|
90 CONTINUE
|
|
END IF
|
|
100 CONTINUE
|
|
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
|
|
DO 120 J = M - 1, 1, -1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 110 I = 1, N
|
|
TEMP = A( J, I )
|
|
A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMP
|
|
A( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP
|
|
110 CONTINUE
|
|
END IF
|
|
120 CONTINUE
|
|
END IF
|
|
END IF
|
|
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
|
|
*
|
|
* Form A * P**T
|
|
*
|
|
IF( LSAME( PIVOT, 'V' ) ) THEN
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
DO 140 J = 1, N - 1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 130 I = 1, M
|
|
TEMP = A( I, J+1 )
|
|
A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J )
|
|
A( I, J ) = STEMP*TEMP + CTEMP*A( I, J )
|
|
130 CONTINUE
|
|
END IF
|
|
140 CONTINUE
|
|
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
|
|
DO 160 J = N - 1, 1, -1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 150 I = 1, M
|
|
TEMP = A( I, J+1 )
|
|
A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J )
|
|
A( I, J ) = STEMP*TEMP + CTEMP*A( I, J )
|
|
150 CONTINUE
|
|
END IF
|
|
160 CONTINUE
|
|
END IF
|
|
ELSE IF( LSAME( PIVOT, 'T' ) ) THEN
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
DO 180 J = 2, N
|
|
CTEMP = C( J-1 )
|
|
STEMP = S( J-1 )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 170 I = 1, M
|
|
TEMP = A( I, J )
|
|
A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 )
|
|
A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 )
|
|
170 CONTINUE
|
|
END IF
|
|
180 CONTINUE
|
|
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
|
|
DO 200 J = N, 2, -1
|
|
CTEMP = C( J-1 )
|
|
STEMP = S( J-1 )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 190 I = 1, M
|
|
TEMP = A( I, J )
|
|
A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 )
|
|
A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 )
|
|
190 CONTINUE
|
|
END IF
|
|
200 CONTINUE
|
|
END IF
|
|
ELSE IF( LSAME( PIVOT, 'B' ) ) THEN
|
|
IF( LSAME( DIRECT, 'F' ) ) THEN
|
|
DO 220 J = 1, N - 1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 210 I = 1, M
|
|
TEMP = A( I, J )
|
|
A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMP
|
|
A( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP
|
|
210 CONTINUE
|
|
END IF
|
|
220 CONTINUE
|
|
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
|
|
DO 240 J = N - 1, 1, -1
|
|
CTEMP = C( J )
|
|
STEMP = S( J )
|
|
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
|
|
DO 230 I = 1, M
|
|
TEMP = A( I, J )
|
|
A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMP
|
|
A( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP
|
|
230 CONTINUE
|
|
END IF
|
|
240 CONTINUE
|
|
END IF
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DLASR
|
|
*
|
|
END
|
|
SUBROUTINE DLASRT( ID, N, D, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER ID
|
|
INTEGER INFO, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION D( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* Sort the numbers in D in increasing order (if ID = 'I') or
|
|
* in decreasing order (if ID = 'D' ).
|
|
*
|
|
* Use Quick Sort, reverting to Insertion sort on arrays of
|
|
* size <= 20. Dimension of STACK limits N to about 2**32.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* ID (input) CHARACTER*1
|
|
* = 'I': sort D in increasing order;
|
|
* = 'D': sort D in decreasing order.
|
|
*
|
|
* N (input) INTEGER
|
|
* The length of the array D.
|
|
*
|
|
* D (input/output) DOUBLE PRECISION array, dimension (N)
|
|
* On entry, the array to be sorted.
|
|
* On exit, D has been sorted into increasing order
|
|
* (D(1) <= ... <= D(N) ) or into decreasing order
|
|
* (D(1) >= ... >= D(N) ), depending on ID.
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument had an illegal value
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
INTEGER SELECT
|
|
PARAMETER ( SELECT = 20 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER DIR, ENDD, I, J, START, STKPNT
|
|
DOUBLE PRECISION D1, D2, D3, DMNMX, TMP
|
|
* ..
|
|
* .. Local Arrays ..
|
|
INTEGER STACK( 2, 32 )
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input paramters.
|
|
*
|
|
INFO = 0
|
|
DIR = -1
|
|
IF( LSAME( ID, 'D' ) ) THEN
|
|
DIR = 0
|
|
ELSE IF( LSAME( ID, 'I' ) ) THEN
|
|
DIR = 1
|
|
END IF
|
|
IF( DIR.EQ.-1 ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 ) THEN
|
|
INFO = -2
|
|
END IF
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DLASRT', -INFO )
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LE.1 )
|
|
$ RETURN
|
|
*
|
|
STKPNT = 1
|
|
STACK( 1, 1 ) = 1
|
|
STACK( 2, 1 ) = N
|
|
10 CONTINUE
|
|
START = STACK( 1, STKPNT )
|
|
ENDD = STACK( 2, STKPNT )
|
|
STKPNT = STKPNT - 1
|
|
IF( ENDD-START.LE.SELECT .AND. ENDD-START.GT.0 ) THEN
|
|
*
|
|
* Do Insertion sort on D( START:ENDD )
|
|
*
|
|
IF( DIR.EQ.0 ) THEN
|
|
*
|
|
* Sort into decreasing order
|
|
*
|
|
DO 30 I = START + 1, ENDD
|
|
DO 20 J = I, START + 1, -1
|
|
IF( D( J ).GT.D( J-1 ) ) THEN
|
|
DMNMX = D( J )
|
|
D( J ) = D( J-1 )
|
|
D( J-1 ) = DMNMX
|
|
ELSE
|
|
GO TO 30
|
|
END IF
|
|
20 CONTINUE
|
|
30 CONTINUE
|
|
*
|
|
ELSE
|
|
*
|
|
* Sort into increasing order
|
|
*
|
|
DO 50 I = START + 1, ENDD
|
|
DO 40 J = I, START + 1, -1
|
|
IF( D( J ).LT.D( J-1 ) ) THEN
|
|
DMNMX = D( J )
|
|
D( J ) = D( J-1 )
|
|
D( J-1 ) = DMNMX
|
|
ELSE
|
|
GO TO 50
|
|
END IF
|
|
40 CONTINUE
|
|
50 CONTINUE
|
|
*
|
|
END IF
|
|
*
|
|
ELSE IF( ENDD-START.GT.SELECT ) THEN
|
|
*
|
|
* Partition D( START:ENDD ) and stack parts, largest one first
|
|
*
|
|
* Choose partition entry as median of 3
|
|
*
|
|
D1 = D( START )
|
|
D2 = D( ENDD )
|
|
I = ( START+ENDD ) / 2
|
|
D3 = D( I )
|
|
IF( D1.LT.D2 ) THEN
|
|
IF( D3.LT.D1 ) THEN
|
|
DMNMX = D1
|
|
ELSE IF( D3.LT.D2 ) THEN
|
|
DMNMX = D3
|
|
ELSE
|
|
DMNMX = D2
|
|
END IF
|
|
ELSE
|
|
IF( D3.LT.D2 ) THEN
|
|
DMNMX = D2
|
|
ELSE IF( D3.LT.D1 ) THEN
|
|
DMNMX = D3
|
|
ELSE
|
|
DMNMX = D1
|
|
END IF
|
|
END IF
|
|
*
|
|
IF( DIR.EQ.0 ) THEN
|
|
*
|
|
* Sort into decreasing order
|
|
*
|
|
I = START - 1
|
|
J = ENDD + 1
|
|
60 CONTINUE
|
|
70 CONTINUE
|
|
J = J - 1
|
|
IF( D( J ).LT.DMNMX )
|
|
$ GO TO 70
|
|
80 CONTINUE
|
|
I = I + 1
|
|
IF( D( I ).GT.DMNMX )
|
|
$ GO TO 80
|
|
IF( I.LT.J ) THEN
|
|
TMP = D( I )
|
|
D( I ) = D( J )
|
|
D( J ) = TMP
|
|
GO TO 60
|
|
END IF
|
|
IF( J-START.GT.ENDD-J-1 ) THEN
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = START
|
|
STACK( 2, STKPNT ) = J
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = J + 1
|
|
STACK( 2, STKPNT ) = ENDD
|
|
ELSE
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = J + 1
|
|
STACK( 2, STKPNT ) = ENDD
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = START
|
|
STACK( 2, STKPNT ) = J
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Sort into increasing order
|
|
*
|
|
I = START - 1
|
|
J = ENDD + 1
|
|
90 CONTINUE
|
|
100 CONTINUE
|
|
J = J - 1
|
|
IF( D( J ).GT.DMNMX )
|
|
$ GO TO 100
|
|
110 CONTINUE
|
|
I = I + 1
|
|
IF( D( I ).LT.DMNMX )
|
|
$ GO TO 110
|
|
IF( I.LT.J ) THEN
|
|
TMP = D( I )
|
|
D( I ) = D( J )
|
|
D( J ) = TMP
|
|
GO TO 90
|
|
END IF
|
|
IF( J-START.GT.ENDD-J-1 ) THEN
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = START
|
|
STACK( 2, STKPNT ) = J
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = J + 1
|
|
STACK( 2, STKPNT ) = ENDD
|
|
ELSE
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = J + 1
|
|
STACK( 2, STKPNT ) = ENDD
|
|
STKPNT = STKPNT + 1
|
|
STACK( 1, STKPNT ) = START
|
|
STACK( 2, STKPNT ) = J
|
|
END IF
|
|
END IF
|
|
END IF
|
|
IF( STKPNT.GT.0 )
|
|
$ GO TO 10
|
|
RETURN
|
|
*
|
|
* End of DLASRT
|
|
*
|
|
END
|
|
SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER INCX, N
|
|
DOUBLE PRECISION SCALE, SUMSQ
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION X( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLASSQ returns the values scl and smsq such that
|
|
*
|
|
* ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq,
|
|
*
|
|
* where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is
|
|
* assumed to be non-negative and scl returns the value
|
|
*
|
|
* scl = max( scale, abs( x( i ) ) ).
|
|
*
|
|
* scale and sumsq must be supplied in SCALE and SUMSQ and
|
|
* scl and smsq are overwritten on SCALE and SUMSQ respectively.
|
|
*
|
|
* The routine makes only one pass through the vector x.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of elements to be used from the vector X.
|
|
*
|
|
* X (input) DOUBLE PRECISION array, dimension (N)
|
|
* The vector for which a scaled sum of squares is computed.
|
|
* x( i ) = X( 1 + ( i - 1 )*INCX ), 1 <= i <= n.
|
|
*
|
|
* INCX (input) INTEGER
|
|
* The increment between successive values of the vector X.
|
|
* INCX > 0.
|
|
*
|
|
* SCALE (input/output) DOUBLE PRECISION
|
|
* On entry, the value scale in the equation above.
|
|
* On exit, SCALE is overwritten with scl , the scaling factor
|
|
* for the sum of squares.
|
|
*
|
|
* SUMSQ (input/output) DOUBLE PRECISION
|
|
* On entry, the value sumsq in the equation above.
|
|
* On exit, SUMSQ is overwritten with smsq , the basic sum of
|
|
* squares from which scl has been factored out.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER ( ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER IX
|
|
DOUBLE PRECISION ABSXI
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
IF( N.GT.0 ) THEN
|
|
DO 10 IX = 1, 1 + ( N-1 )*INCX, INCX
|
|
IF( X( IX ).NE.ZERO ) THEN
|
|
ABSXI = ABS( X( IX ) )
|
|
IF( SCALE.LT.ABSXI ) THEN
|
|
SUMSQ = 1 + SUMSQ*( SCALE / ABSXI )**2
|
|
SCALE = ABSXI
|
|
ELSE
|
|
SUMSQ = SUMSQ + ( ABSXI / SCALE )**2
|
|
END IF
|
|
END IF
|
|
10 CONTINUE
|
|
END IF
|
|
RETURN
|
|
*
|
|
* End of DLASSQ
|
|
*
|
|
END
|
|
SUBROUTINE DLATRD( UPLO, N, NB, A, LDA, E, TAU, W, LDW )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER UPLO
|
|
INTEGER LDA, LDW, N, NB
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), E( * ), TAU( * ), W( LDW, * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DLATRD reduces NB rows and columns of a real symmetric matrix A to
|
|
* symmetric tridiagonal form by an orthogonal similarity
|
|
* transformation Q**T * A * Q, and returns the matrices V and W which are
|
|
* needed to apply the transformation to the unreduced part of A.
|
|
*
|
|
* If UPLO = 'U', DLATRD reduces the last NB rows and columns of a
|
|
* matrix, of which the upper triangle is supplied;
|
|
* if UPLO = 'L', DLATRD reduces the first NB rows and columns of a
|
|
* matrix, of which the lower triangle is supplied.
|
|
*
|
|
* This is an auxiliary routine called by DSYTRD.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* UPLO (input) CHARACTER*1
|
|
* Specifies whether the upper or lower triangular part of the
|
|
* symmetric matrix A is stored:
|
|
* = 'U': Upper triangular
|
|
* = 'L': Lower triangular
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the matrix A.
|
|
*
|
|
* NB (input) INTEGER
|
|
* The number of rows and columns to be reduced.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION 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, and the strictly lower
|
|
* triangular part of A is not referenced. If UPLO = 'L', the
|
|
* leading n-by-n lower triangular part of A contains the lower
|
|
* triangular part of the matrix A, and the strictly upper
|
|
* triangular part of A is not referenced.
|
|
* On exit:
|
|
* if UPLO = 'U', the last NB columns have been reduced to
|
|
* tridiagonal form, with the diagonal elements overwriting
|
|
* the diagonal elements of A; the elements above the diagonal
|
|
* with the array TAU, represent the orthogonal matrix Q as a
|
|
* product of elementary reflectors;
|
|
* if UPLO = 'L', the first NB columns have been reduced to
|
|
* tridiagonal form, with the diagonal elements overwriting
|
|
* the diagonal elements of A; the elements below the diagonal
|
|
* with the array TAU, represent the orthogonal matrix Q as a
|
|
* product of elementary reflectors.
|
|
* See Further Details.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= (1,N).
|
|
*
|
|
* E (output) DOUBLE PRECISION array, dimension (N-1)
|
|
* If UPLO = 'U', E(n-nb:n-1) contains the superdiagonal
|
|
* elements of the last NB columns of the reduced matrix;
|
|
* if UPLO = 'L', E(1:nb) contains the subdiagonal elements of
|
|
* the first NB columns of the reduced matrix.
|
|
*
|
|
* TAU (output) DOUBLE PRECISION array, dimension (N-1)
|
|
* The scalar factors of the elementary reflectors, stored in
|
|
* TAU(n-nb:n-1) if UPLO = 'U', and in TAU(1:nb) if UPLO = 'L'.
|
|
* See Further Details.
|
|
*
|
|
* W (output) DOUBLE PRECISION array, dimension (LDW,NB)
|
|
* The n-by-nb matrix W required to update the unreduced part
|
|
* of A.
|
|
*
|
|
* LDW (input) INTEGER
|
|
* The leading dimension of the array W. LDW >= max(1,N).
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* If UPLO = 'U', the matrix Q is represented as a product of elementary
|
|
* reflectors
|
|
*
|
|
* Q = H(n) H(n-1) . . . H(n-nb+1).
|
|
*
|
|
* Each H(i) has the form
|
|
*
|
|
* H(i) = I - tau * v * v**T
|
|
*
|
|
* where tau is a real scalar, and v is a real vector with
|
|
* v(i:n) = 0 and v(i-1) = 1; v(1:i-1) is stored on exit in A(1:i-1,i),
|
|
* and tau in TAU(i-1).
|
|
*
|
|
* If UPLO = 'L', the matrix Q is represented as a product of elementary
|
|
* reflectors
|
|
*
|
|
* Q = H(1) H(2) . . . H(nb).
|
|
*
|
|
* Each H(i) has the form
|
|
*
|
|
* H(i) = I - tau * v * v**T
|
|
*
|
|
* where tau is a real scalar, and v is a real vector with
|
|
* v(1:i) = 0 and v(i+1) = 1; v(i+1:n) is stored on exit in A(i+1:n,i),
|
|
* and tau in TAU(i).
|
|
*
|
|
* The elements of the vectors v together form the n-by-nb matrix V
|
|
* which is needed, with W, to apply the transformation to the unreduced
|
|
* part of the matrix, using a symmetric rank-2k update of the form:
|
|
* A := A - V*W**T - W*V**T.
|
|
*
|
|
* The contents of A on exit are illustrated by the following examples
|
|
* with n = 5 and nb = 2:
|
|
*
|
|
* if UPLO = 'U': if UPLO = 'L':
|
|
*
|
|
* ( a a a v4 v5 ) ( d )
|
|
* ( a a v4 v5 ) ( 1 d )
|
|
* ( a 1 v5 ) ( v1 1 a )
|
|
* ( d 1 ) ( v1 v2 a a )
|
|
* ( d ) ( v1 v2 a a a )
|
|
*
|
|
* where d denotes a diagonal element of the reduced matrix, a denotes
|
|
* an element of the original matrix that is unchanged, and vi denotes
|
|
* an element of the vector defining H(i).
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO, ONE, HALF
|
|
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, HALF = 0.5D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, IW
|
|
DOUBLE PRECISION ALPHA
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DAXPY, DGEMV, DLARFG, DSCAL, DSYMV
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
DOUBLE PRECISION DDOT
|
|
EXTERNAL LSAME, DDOT
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MIN
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LE.0 )
|
|
$ RETURN
|
|
*
|
|
IF( LSAME( UPLO, 'U' ) ) THEN
|
|
*
|
|
* Reduce last NB columns of upper triangle
|
|
*
|
|
DO 10 I = N, N - NB + 1, -1
|
|
IW = I - N + NB
|
|
IF( I.LT.N ) THEN
|
|
*
|
|
* Update A(1:i,i)
|
|
*
|
|
CALL DGEMV( 'No transpose', I, N-I, -ONE, A( 1, I+1 ),
|
|
$ LDA, W( I, IW+1 ), LDW, ONE, A( 1, I ), 1 )
|
|
CALL DGEMV( 'No transpose', I, N-I, -ONE, W( 1, IW+1 ),
|
|
$ LDW, A( I, I+1 ), LDA, ONE, A( 1, I ), 1 )
|
|
END IF
|
|
IF( I.GT.1 ) THEN
|
|
*
|
|
* Generate elementary reflector H(i) to annihilate
|
|
* A(1:i-2,i)
|
|
*
|
|
CALL DLARFG( I-1, A( I-1, I ), A( 1, I ), 1, TAU( I-1 ) )
|
|
E( I-1 ) = A( I-1, I )
|
|
A( I-1, I ) = ONE
|
|
*
|
|
* Compute W(1:i-1,i)
|
|
*
|
|
CALL DSYMV( 'Upper', I-1, ONE, A, LDA, A( 1, I ), 1,
|
|
$ ZERO, W( 1, IW ), 1 )
|
|
IF( I.LT.N ) THEN
|
|
CALL DGEMV( 'Transpose', I-1, N-I, ONE, W( 1, IW+1 ),
|
|
$ LDW, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 )
|
|
CALL DGEMV( 'No transpose', I-1, N-I, -ONE,
|
|
$ A( 1, I+1 ), LDA, W( I+1, IW ), 1, ONE,
|
|
$ W( 1, IW ), 1 )
|
|
CALL DGEMV( 'Transpose', I-1, N-I, ONE, A( 1, I+1 ),
|
|
$ LDA, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 )
|
|
CALL DGEMV( 'No transpose', I-1, N-I, -ONE,
|
|
$ W( 1, IW+1 ), LDW, W( I+1, IW ), 1, ONE,
|
|
$ W( 1, IW ), 1 )
|
|
END IF
|
|
CALL DSCAL( I-1, TAU( I-1 ), W( 1, IW ), 1 )
|
|
ALPHA = -HALF*TAU( I-1 )*DDOT( I-1, W( 1, IW ), 1,
|
|
$ A( 1, I ), 1 )
|
|
CALL DAXPY( I-1, ALPHA, A( 1, I ), 1, W( 1, IW ), 1 )
|
|
END IF
|
|
*
|
|
10 CONTINUE
|
|
ELSE
|
|
*
|
|
* Reduce first NB columns of lower triangle
|
|
*
|
|
DO 20 I = 1, NB
|
|
*
|
|
* Update A(i:n,i)
|
|
*
|
|
CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, A( I, 1 ),
|
|
$ LDA, W( I, 1 ), LDW, ONE, A( I, I ), 1 )
|
|
CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, W( I, 1 ),
|
|
$ LDW, A( I, 1 ), LDA, ONE, A( I, I ), 1 )
|
|
IF( I.LT.N ) THEN
|
|
*
|
|
* Generate elementary reflector H(i) to annihilate
|
|
* A(i+2:n,i)
|
|
*
|
|
CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,
|
|
$ TAU( I ) )
|
|
E( I ) = A( I+1, I )
|
|
A( I+1, I ) = ONE
|
|
*
|
|
* Compute W(i+1:n,i)
|
|
*
|
|
CALL DSYMV( 'Lower', N-I, ONE, A( I+1, I+1 ), LDA,
|
|
$ A( I+1, I ), 1, ZERO, W( I+1, I ), 1 )
|
|
CALL DGEMV( 'Transpose', N-I, I-1, ONE, W( I+1, 1 ), LDW,
|
|
$ A( I+1, I ), 1, ZERO, W( 1, I ), 1 )
|
|
CALL DGEMV( 'No transpose', N-I, I-1, -ONE, A( I+1, 1 ),
|
|
$ LDA, W( 1, I ), 1, ONE, W( I+1, I ), 1 )
|
|
CALL DGEMV( 'Transpose', N-I, I-1, ONE, A( I+1, 1 ), LDA,
|
|
$ A( I+1, I ), 1, ZERO, W( 1, I ), 1 )
|
|
CALL DGEMV( 'No transpose', N-I, I-1, -ONE, W( I+1, 1 ),
|
|
$ LDW, W( 1, I ), 1, ONE, W( I+1, I ), 1 )
|
|
CALL DSCAL( N-I, TAU( I ), W( I+1, I ), 1 )
|
|
ALPHA = -HALF*TAU( I )*DDOT( N-I, W( I+1, I ), 1,
|
|
$ A( I+1, I ), 1 )
|
|
CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, W( I+1, I ), 1 )
|
|
END IF
|
|
*
|
|
20 CONTINUE
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DLATRD
|
|
*
|
|
END
|
|
SUBROUTINE DORG2L( M, N, K, A, LDA, TAU, WORK, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER INFO, K, LDA, M, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DORG2L generates an m by n real matrix Q with orthonormal columns,
|
|
* which is defined as the last n columns of a product of k elementary
|
|
* reflectors of order m
|
|
*
|
|
* Q = H(k) . . . H(2) H(1)
|
|
*
|
|
* as returned by DGEQLF.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* M (input) INTEGER
|
|
* The number of rows of the matrix Q. M >= 0.
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of columns of the matrix Q. M >= N >= 0.
|
|
*
|
|
* K (input) INTEGER
|
|
* The number of elementary reflectors whose product defines the
|
|
* matrix Q. N >= K >= 0.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* On entry, the (n-k+i)-th column must contain the vector which
|
|
* defines the elementary reflector H(i), for i = 1,2,...,k, as
|
|
* returned by DGEQLF in the last k columns of its array
|
|
* argument A.
|
|
* On exit, the m by n matrix Q.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The first dimension of the array A. LDA >= max(1,M).
|
|
*
|
|
* TAU (input) DOUBLE PRECISION array, dimension (K)
|
|
* TAU(i) must contain the scalar factor of the elementary
|
|
* reflector H(i), as returned by DGEQLF.
|
|
*
|
|
* WORK (workspace) DOUBLE PRECISION array, dimension (N)
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument has an illegal value
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, II, J, L
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLARF, DSCAL, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input arguments
|
|
*
|
|
INFO = 0
|
|
IF( M.LT.0 ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
|
|
INFO = -2
|
|
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
|
|
INFO = -3
|
|
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
|
|
INFO = -5
|
|
END IF
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DORG2L', -INFO )
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LE.0 )
|
|
$ RETURN
|
|
*
|
|
* Initialise columns 1:n-k to columns of the unit matrix
|
|
*
|
|
DO 20 J = 1, N - K
|
|
DO 10 L = 1, M
|
|
A( L, J ) = ZERO
|
|
10 CONTINUE
|
|
A( M-N+J, J ) = ONE
|
|
20 CONTINUE
|
|
*
|
|
DO 40 I = 1, K
|
|
II = N - K + I
|
|
*
|
|
* Apply H(i) to A(1:m-k+i,1:n-k+i) from the left
|
|
*
|
|
A( M-N+II, II ) = ONE
|
|
CALL DLARF( 'Left', M-N+II, II-1, A( 1, II ), 1, TAU( I ), A,
|
|
$ LDA, WORK )
|
|
CALL DSCAL( M-N+II-1, -TAU( I ), A( 1, II ), 1 )
|
|
A( M-N+II, II ) = ONE - TAU( I )
|
|
*
|
|
* Set A(m-k+i+1:m,n-k+i) to zero
|
|
*
|
|
DO 30 L = M - N + II + 1, M
|
|
A( L, II ) = ZERO
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
RETURN
|
|
*
|
|
* End of DORG2L
|
|
*
|
|
END
|
|
SUBROUTINE DORG2R( M, N, K, A, LDA, TAU, WORK, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER INFO, K, LDA, M, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DORG2R generates an m by n real matrix Q with orthonormal columns,
|
|
* which is defined as the first n columns of a product of k elementary
|
|
* reflectors of order m
|
|
*
|
|
* Q = H(1) H(2) . . . H(k)
|
|
*
|
|
* as returned by DGEQRF.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* M (input) INTEGER
|
|
* The number of rows of the matrix Q. M >= 0.
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of columns of the matrix Q. M >= N >= 0.
|
|
*
|
|
* K (input) INTEGER
|
|
* The number of elementary reflectors whose product defines the
|
|
* matrix Q. N >= K >= 0.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* On entry, the i-th column must contain the vector which
|
|
* defines the elementary reflector H(i), for i = 1,2,...,k, as
|
|
* returned by DGEQRF in the first k columns of its array
|
|
* argument A.
|
|
* On exit, the m-by-n matrix Q.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The first dimension of the array A. LDA >= max(1,M).
|
|
*
|
|
* TAU (input) DOUBLE PRECISION array, dimension (K)
|
|
* TAU(i) must contain the scalar factor of the elementary
|
|
* reflector H(i), as returned by DGEQRF.
|
|
*
|
|
* WORK (workspace) DOUBLE PRECISION array, dimension (N)
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument has an illegal value
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, J, L
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLARF, DSCAL, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input arguments
|
|
*
|
|
INFO = 0
|
|
IF( M.LT.0 ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
|
|
INFO = -2
|
|
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
|
|
INFO = -3
|
|
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
|
|
INFO = -5
|
|
END IF
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DORG2R', -INFO )
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LE.0 )
|
|
$ RETURN
|
|
*
|
|
* Initialise columns k+1:n to columns of the unit matrix
|
|
*
|
|
DO 20 J = K + 1, N
|
|
DO 10 L = 1, M
|
|
A( L, J ) = ZERO
|
|
10 CONTINUE
|
|
A( J, J ) = ONE
|
|
20 CONTINUE
|
|
*
|
|
DO 40 I = K, 1, -1
|
|
*
|
|
* Apply H(i) to A(i:m,i:n) from the left
|
|
*
|
|
IF( I.LT.N ) THEN
|
|
A( I, I ) = ONE
|
|
CALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAU( I ),
|
|
$ A( I, I+1 ), LDA, WORK )
|
|
END IF
|
|
IF( I.LT.M )
|
|
$ CALL DSCAL( M-I, -TAU( I ), A( I+1, I ), 1 )
|
|
A( I, I ) = ONE - TAU( I )
|
|
*
|
|
* Set A(1:i-1,i) to zero
|
|
*
|
|
DO 30 L = 1, I - 1
|
|
A( L, I ) = ZERO
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
RETURN
|
|
*
|
|
* End of DORG2R
|
|
*
|
|
END
|
|
SUBROUTINE DORGQL( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER INFO, K, LDA, LWORK, M, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DORGQL generates an M-by-N real matrix Q with orthonormal columns,
|
|
* which is defined as the last N columns of a product of K elementary
|
|
* reflectors of order M
|
|
*
|
|
* Q = H(k) . . . H(2) H(1)
|
|
*
|
|
* as returned by DGEQLF.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* M (input) INTEGER
|
|
* The number of rows of the matrix Q. M >= 0.
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of columns of the matrix Q. M >= N >= 0.
|
|
*
|
|
* K (input) INTEGER
|
|
* The number of elementary reflectors whose product defines the
|
|
* matrix Q. N >= K >= 0.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* On entry, the (n-k+i)-th column must contain the vector which
|
|
* defines the elementary reflector H(i), for i = 1,2,...,k, as
|
|
* returned by DGEQLF in the last k columns of its array
|
|
* argument A.
|
|
* On exit, the M-by-N matrix Q.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The first dimension of the array A. LDA >= max(1,M).
|
|
*
|
|
* TAU (input) DOUBLE PRECISION array, dimension (K)
|
|
* TAU(i) must contain the scalar factor of the elementary
|
|
* reflector H(i), as returned by DGEQLF.
|
|
*
|
|
* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
|
|
* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
|
*
|
|
* LWORK (input) INTEGER
|
|
* The dimension of the array WORK. LWORK >= max(1,N).
|
|
* For optimum performance LWORK >= N*NB, where NB is the
|
|
* optimal blocksize.
|
|
*
|
|
* If LWORK = -1, then a workspace query is assumed; the routine
|
|
* only calculates the optimal size of the WORK array, returns
|
|
* this value as the first entry of the WORK array, and no error
|
|
* message related to LWORK is issued by XERBLA.
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument has an illegal value
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER ( ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL LQUERY
|
|
INTEGER I, IB, IINFO, IWS, J, KK, L, LDWORK, LWKOPT,
|
|
$ NB, NBMIN, NX
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLARFB, DLARFT, DORG2L, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX, MIN
|
|
* ..
|
|
* .. External Functions ..
|
|
INTEGER ILAENV
|
|
EXTERNAL ILAENV
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input arguments
|
|
*
|
|
INFO = 0
|
|
LQUERY = ( LWORK.EQ.-1 )
|
|
IF( M.LT.0 ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
|
|
INFO = -2
|
|
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
|
|
INFO = -3
|
|
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
|
|
INFO = -5
|
|
END IF
|
|
*
|
|
IF( INFO.EQ.0 ) THEN
|
|
IF( N.EQ.0 ) THEN
|
|
LWKOPT = 1
|
|
ELSE
|
|
NB = ILAENV( 1, 'DORGQL', ' ', M, N, K, -1 )
|
|
LWKOPT = N*NB
|
|
END IF
|
|
WORK( 1 ) = LWKOPT
|
|
*
|
|
IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN
|
|
INFO = -8
|
|
END IF
|
|
END IF
|
|
*
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DORGQL', -INFO )
|
|
RETURN
|
|
ELSE IF( LQUERY ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LE.0 ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
NBMIN = 2
|
|
NX = 0
|
|
IWS = N
|
|
IF( NB.GT.1 .AND. NB.LT.K ) THEN
|
|
*
|
|
* Determine when to cross over from blocked to unblocked code.
|
|
*
|
|
NX = MAX( 0, ILAENV( 3, 'DORGQL', ' ', M, N, K, -1 ) )
|
|
IF( NX.LT.K ) THEN
|
|
*
|
|
* Determine if workspace is large enough for blocked code.
|
|
*
|
|
LDWORK = N
|
|
IWS = LDWORK*NB
|
|
IF( LWORK.LT.IWS ) THEN
|
|
*
|
|
* Not enough workspace to use optimal NB: reduce NB and
|
|
* determine the minimum value of NB.
|
|
*
|
|
NB = LWORK / LDWORK
|
|
NBMIN = MAX( 2, ILAENV( 2, 'DORGQL', ' ', M, N, K, -1 ) )
|
|
END IF
|
|
END IF
|
|
END IF
|
|
*
|
|
IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN
|
|
*
|
|
* Use blocked code after the first block.
|
|
* The last kk columns are handled by the block method.
|
|
*
|
|
KK = MIN( K, ( ( K-NX+NB-1 ) / NB )*NB )
|
|
*
|
|
* Set A(m-kk+1:m,1:n-kk) to zero.
|
|
*
|
|
DO 20 J = 1, N - KK
|
|
DO 10 I = M - KK + 1, M
|
|
A( I, J ) = ZERO
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
ELSE
|
|
KK = 0
|
|
END IF
|
|
*
|
|
* Use unblocked code for the first or only block.
|
|
*
|
|
CALL DORG2L( M-KK, N-KK, K-KK, A, LDA, TAU, WORK, IINFO )
|
|
*
|
|
IF( KK.GT.0 ) THEN
|
|
*
|
|
* Use blocked code
|
|
*
|
|
DO 50 I = K - KK + 1, K, NB
|
|
IB = MIN( NB, K-I+1 )
|
|
IF( N-K+I.GT.1 ) THEN
|
|
*
|
|
* Form the triangular factor of the block reflector
|
|
* H = H(i+ib-1) . . . H(i+1) H(i)
|
|
*
|
|
CALL DLARFT( 'Backward', 'Columnwise', M-K+I+IB-1, IB,
|
|
$ A( 1, N-K+I ), LDA, TAU( I ), WORK, LDWORK )
|
|
*
|
|
* Apply H to A(1:m-k+i+ib-1,1:n-k+i-1) from the left
|
|
*
|
|
CALL DLARFB( 'Left', 'No transpose', 'Backward',
|
|
$ 'Columnwise', M-K+I+IB-1, N-K+I-1, IB,
|
|
$ A( 1, N-K+I ), LDA, WORK, LDWORK, A, LDA,
|
|
$ WORK( IB+1 ), LDWORK )
|
|
END IF
|
|
*
|
|
* Apply H to rows 1:m-k+i+ib-1 of current block
|
|
*
|
|
CALL DORG2L( M-K+I+IB-1, IB, IB, A( 1, N-K+I ), LDA,
|
|
$ TAU( I ), WORK, IINFO )
|
|
*
|
|
* Set rows m-k+i+ib:m of current block to zero
|
|
*
|
|
DO 40 J = N - K + I, N - K + I + IB - 1
|
|
DO 30 L = M - K + I + IB, M
|
|
A( L, J ) = ZERO
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
50 CONTINUE
|
|
END IF
|
|
*
|
|
WORK( 1 ) = IWS
|
|
RETURN
|
|
*
|
|
* End of DORGQL
|
|
*
|
|
END
|
|
SUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER INFO, K, LDA, LWORK, M, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DORGQR generates an M-by-N real matrix Q with orthonormal columns,
|
|
* which is defined as the first N columns of a product of K elementary
|
|
* reflectors of order M
|
|
*
|
|
* Q = H(1) H(2) . . . H(k)
|
|
*
|
|
* as returned by DGEQRF.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* M (input) INTEGER
|
|
* The number of rows of the matrix Q. M >= 0.
|
|
*
|
|
* N (input) INTEGER
|
|
* The number of columns of the matrix Q. M >= N >= 0.
|
|
*
|
|
* K (input) INTEGER
|
|
* The number of elementary reflectors whose product defines the
|
|
* matrix Q. N >= K >= 0.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* On entry, the i-th column must contain the vector which
|
|
* defines the elementary reflector H(i), for i = 1,2,...,k, as
|
|
* returned by DGEQRF in the first k columns of its array
|
|
* argument A.
|
|
* On exit, the M-by-N matrix Q.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The first dimension of the array A. LDA >= max(1,M).
|
|
*
|
|
* TAU (input) DOUBLE PRECISION array, dimension (K)
|
|
* TAU(i) must contain the scalar factor of the elementary
|
|
* reflector H(i), as returned by DGEQRF.
|
|
*
|
|
* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
|
|
* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
|
*
|
|
* LWORK (input) INTEGER
|
|
* The dimension of the array WORK. LWORK >= max(1,N).
|
|
* For optimum performance LWORK >= N*NB, where NB is the
|
|
* optimal blocksize.
|
|
*
|
|
* If LWORK = -1, then a workspace query is assumed; the routine
|
|
* only calculates the optimal size of the WORK array, returns
|
|
* this value as the first entry of the WORK array, and no error
|
|
* message related to LWORK is issued by XERBLA.
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument has an illegal value
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER ( ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL LQUERY
|
|
INTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK,
|
|
$ LWKOPT, NB, NBMIN, NX
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLARFB, DLARFT, DORG2R, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX, MIN
|
|
* ..
|
|
* .. External Functions ..
|
|
INTEGER ILAENV
|
|
EXTERNAL ILAENV
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input arguments
|
|
*
|
|
INFO = 0
|
|
NB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 )
|
|
LWKOPT = MAX( 1, N )*NB
|
|
WORK( 1 ) = LWKOPT
|
|
LQUERY = ( LWORK.EQ.-1 )
|
|
IF( M.LT.0 ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
|
|
INFO = -2
|
|
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
|
|
INFO = -3
|
|
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
|
|
INFO = -5
|
|
ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN
|
|
INFO = -8
|
|
END IF
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DORGQR', -INFO )
|
|
RETURN
|
|
ELSE IF( LQUERY ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LE.0 ) THEN
|
|
WORK( 1 ) = 1
|
|
RETURN
|
|
END IF
|
|
*
|
|
NBMIN = 2
|
|
NX = 0
|
|
IWS = N
|
|
IF( NB.GT.1 .AND. NB.LT.K ) THEN
|
|
*
|
|
* Determine when to cross over from blocked to unblocked code.
|
|
*
|
|
NX = MAX( 0, ILAENV( 3, 'DORGQR', ' ', M, N, K, -1 ) )
|
|
IF( NX.LT.K ) THEN
|
|
*
|
|
* Determine if workspace is large enough for blocked code.
|
|
*
|
|
LDWORK = N
|
|
IWS = LDWORK*NB
|
|
IF( LWORK.LT.IWS ) THEN
|
|
*
|
|
* Not enough workspace to use optimal NB: reduce NB and
|
|
* determine the minimum value of NB.
|
|
*
|
|
NB = LWORK / LDWORK
|
|
NBMIN = MAX( 2, ILAENV( 2, 'DORGQR', ' ', M, N, K, -1 ) )
|
|
END IF
|
|
END IF
|
|
END IF
|
|
*
|
|
IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN
|
|
*
|
|
* Use blocked code after the last block.
|
|
* The first kk columns are handled by the block method.
|
|
*
|
|
KI = ( ( K-NX-1 ) / NB )*NB
|
|
KK = MIN( K, KI+NB )
|
|
*
|
|
* Set A(1:kk,kk+1:n) to zero.
|
|
*
|
|
DO 20 J = KK + 1, N
|
|
DO 10 I = 1, KK
|
|
A( I, J ) = ZERO
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
ELSE
|
|
KK = 0
|
|
END IF
|
|
*
|
|
* Use unblocked code for the last or only block.
|
|
*
|
|
IF( KK.LT.N )
|
|
$ CALL DORG2R( M-KK, N-KK, K-KK, A( KK+1, KK+1 ), LDA,
|
|
$ TAU( KK+1 ), WORK, IINFO )
|
|
*
|
|
IF( KK.GT.0 ) THEN
|
|
*
|
|
* Use blocked code
|
|
*
|
|
DO 50 I = KI + 1, 1, -NB
|
|
IB = MIN( NB, K-I+1 )
|
|
IF( I+IB.LE.N ) THEN
|
|
*
|
|
* Form the triangular factor of the block reflector
|
|
* H = H(i) H(i+1) . . . H(i+ib-1)
|
|
*
|
|
CALL DLARFT( 'Forward', 'Columnwise', M-I+1, IB,
|
|
$ A( I, I ), LDA, TAU( I ), WORK, LDWORK )
|
|
*
|
|
* Apply H to A(i:m,i+ib:n) from the left
|
|
*
|
|
CALL DLARFB( 'Left', 'No transpose', 'Forward',
|
|
$ 'Columnwise', M-I+1, N-I-IB+1, IB,
|
|
$ A( I, I ), LDA, WORK, LDWORK, A( I, I+IB ),
|
|
$ LDA, WORK( IB+1 ), LDWORK )
|
|
END IF
|
|
*
|
|
* Apply H to rows i:m of current block
|
|
*
|
|
CALL DORG2R( M-I+1, IB, IB, A( I, I ), LDA, TAU( I ), WORK,
|
|
$ IINFO )
|
|
*
|
|
* Set rows 1:i-1 of current block to zero
|
|
*
|
|
DO 40 J = I, I + IB - 1
|
|
DO 30 L = 1, I - 1
|
|
A( L, J ) = ZERO
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
50 CONTINUE
|
|
END IF
|
|
*
|
|
WORK( 1 ) = IWS
|
|
RETURN
|
|
*
|
|
* End of DORGQR
|
|
*
|
|
END
|
|
SUBROUTINE DORGTR( UPLO, N, A, LDA, TAU, WORK, LWORK, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER UPLO
|
|
INTEGER INFO, LDA, LWORK, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DORGTR generates a real orthogonal matrix Q which is defined as the
|
|
* product of n-1 elementary reflectors of order N, as returned by
|
|
* DSYTRD:
|
|
*
|
|
* if UPLO = 'U', Q = H(n-1) . . . H(2) H(1),
|
|
*
|
|
* if UPLO = 'L', Q = H(1) H(2) . . . H(n-1).
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* UPLO (input) CHARACTER*1
|
|
* = 'U': Upper triangle of A contains elementary reflectors
|
|
* from DSYTRD;
|
|
* = 'L': Lower triangle of A contains elementary reflectors
|
|
* from DSYTRD.
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the matrix Q. N >= 0.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
|
|
* On entry, the vectors which define the elementary reflectors,
|
|
* as returned by DSYTRD.
|
|
* On exit, the N-by-N orthogonal matrix Q.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= max(1,N).
|
|
*
|
|
* TAU (input) DOUBLE PRECISION array, dimension (N-1)
|
|
* TAU(i) must contain the scalar factor of the elementary
|
|
* reflector H(i), as returned by DSYTRD.
|
|
*
|
|
* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
|
|
* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
|
*
|
|
* LWORK (input) INTEGER
|
|
* The dimension of the array WORK. LWORK >= max(1,N-1).
|
|
* For optimum performance LWORK >= (N-1)*NB, where NB is
|
|
* the optimal blocksize.
|
|
*
|
|
* If LWORK = -1, then a workspace query is assumed; the routine
|
|
* only calculates the optimal size of the WORK array, returns
|
|
* this value as the first entry of the WORK array, and no error
|
|
* message related to LWORK is issued by XERBLA.
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument had an illegal value
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO, ONE
|
|
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL LQUERY, UPPER
|
|
INTEGER I, IINFO, J, LWKOPT, NB
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
INTEGER ILAENV
|
|
EXTERNAL LSAME, ILAENV
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DORGQL, DORGQR, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input arguments
|
|
*
|
|
INFO = 0
|
|
LQUERY = ( LWORK.EQ.-1 )
|
|
UPPER = LSAME( UPLO, 'U' )
|
|
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 ) THEN
|
|
INFO = -2
|
|
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
|
|
INFO = -4
|
|
ELSE IF( LWORK.LT.MAX( 1, N-1 ) .AND. .NOT.LQUERY ) THEN
|
|
INFO = -7
|
|
END IF
|
|
*
|
|
IF( INFO.EQ.0 ) THEN
|
|
IF( UPPER ) THEN
|
|
NB = ILAENV( 1, 'DORGQL', ' ', N-1, N-1, N-1, -1 )
|
|
ELSE
|
|
NB = ILAENV( 1, 'DORGQR', ' ', N-1, N-1, N-1, -1 )
|
|
END IF
|
|
LWKOPT = MAX( 1, N-1 )*NB
|
|
WORK( 1 ) = LWKOPT
|
|
END IF
|
|
*
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DORGTR', -INFO )
|
|
RETURN
|
|
ELSE IF( LQUERY ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.EQ.0 ) THEN
|
|
WORK( 1 ) = 1
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( UPPER ) THEN
|
|
*
|
|
* Q was determined by a call to DSYTRD with UPLO = 'U'
|
|
*
|
|
* Shift the vectors which define the elementary reflectors one
|
|
* column to the left, and set the last row and column of Q to
|
|
* those of the unit matrix
|
|
*
|
|
DO 20 J = 1, N - 1
|
|
DO 10 I = 1, J - 1
|
|
A( I, J ) = A( I, J+1 )
|
|
10 CONTINUE
|
|
A( N, J ) = ZERO
|
|
20 CONTINUE
|
|
DO 30 I = 1, N - 1
|
|
A( I, N ) = ZERO
|
|
30 CONTINUE
|
|
A( N, N ) = ONE
|
|
*
|
|
* Generate Q(1:n-1,1:n-1)
|
|
*
|
|
CALL DORGQL( N-1, N-1, N-1, A, LDA, TAU, WORK, LWORK, IINFO )
|
|
*
|
|
ELSE
|
|
*
|
|
* Q was determined by a call to DSYTRD with UPLO = 'L'.
|
|
*
|
|
* Shift the vectors which define the elementary reflectors one
|
|
* column to the right, and set the first row and column of Q to
|
|
* those of the unit matrix
|
|
*
|
|
DO 50 J = N, 2, -1
|
|
A( 1, J ) = ZERO
|
|
DO 40 I = J + 1, N
|
|
A( I, J ) = A( I, J-1 )
|
|
40 CONTINUE
|
|
50 CONTINUE
|
|
A( 1, 1 ) = ONE
|
|
DO 60 I = 2, N
|
|
A( I, 1 ) = ZERO
|
|
60 CONTINUE
|
|
IF( N.GT.1 ) THEN
|
|
*
|
|
* Generate Q(2:n,2:n)
|
|
*
|
|
CALL DORGQR( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,
|
|
$ LWORK, IINFO )
|
|
END IF
|
|
END IF
|
|
WORK( 1 ) = LWKOPT
|
|
RETURN
|
|
*
|
|
* End of DORGTR
|
|
*
|
|
END
|
|
SUBROUTINE DSTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER COMPZ
|
|
INTEGER INFO, LDZ, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSTEQR computes all eigenvalues and, optionally, eigenvectors of a
|
|
* symmetric tridiagonal matrix using the implicit QL or QR method.
|
|
* The eigenvectors of a full or band symmetric matrix can also be found
|
|
* if DSYTRD or DSPTRD or DSBTRD has been used to reduce this matrix to
|
|
* tridiagonal form.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* COMPZ (input) CHARACTER*1
|
|
* = 'N': Compute eigenvalues only.
|
|
* = 'V': Compute eigenvalues and eigenvectors of the original
|
|
* symmetric matrix. On entry, Z must contain the
|
|
* orthogonal matrix used to reduce the original matrix
|
|
* to tridiagonal form.
|
|
* = 'I': Compute eigenvalues and eigenvectors of the
|
|
* tridiagonal matrix. Z is initialized to the identity
|
|
* matrix.
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the matrix. N >= 0.
|
|
*
|
|
* D (input/output) DOUBLE PRECISION array, dimension (N)
|
|
* On entry, the diagonal elements of the tridiagonal matrix.
|
|
* On exit, if INFO = 0, the eigenvalues in ascending order.
|
|
*
|
|
* E (input/output) DOUBLE PRECISION array, dimension (N-1)
|
|
* On entry, the (n-1) subdiagonal elements of the tridiagonal
|
|
* matrix.
|
|
* On exit, E has been destroyed.
|
|
*
|
|
* Z (input/output) DOUBLE PRECISION array, dimension (LDZ, N)
|
|
* On entry, if COMPZ = 'V', then Z contains the orthogonal
|
|
* matrix used in the reduction to tridiagonal form.
|
|
* On exit, if INFO = 0, then if COMPZ = 'V', Z contains the
|
|
* orthonormal eigenvectors of the original symmetric matrix,
|
|
* and if COMPZ = 'I', Z contains the orthonormal eigenvectors
|
|
* of the symmetric tridiagonal matrix.
|
|
* If COMPZ = 'N', then Z is not referenced.
|
|
*
|
|
* LDZ (input) INTEGER
|
|
* The leading dimension of the array Z. LDZ >= 1, and if
|
|
* eigenvectors are desired, then LDZ >= max(1,N).
|
|
*
|
|
* WORK (workspace) DOUBLE PRECISION array, dimension (max(1,2*N-2))
|
|
* If COMPZ = 'N', then WORK is not referenced.
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument had an illegal value
|
|
* > 0: the algorithm has failed to find all the eigenvalues in
|
|
* a total of 30*N iterations; if INFO = i, then i
|
|
* elements of E have not converged to zero; on exit, D
|
|
* and E contain the elements of a symmetric tridiagonal
|
|
* matrix which is orthogonally similar to the original
|
|
* matrix.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO, ONE, TWO, THREE
|
|
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
|
|
$ THREE = 3.0D0 )
|
|
INTEGER MAXIT
|
|
PARAMETER ( MAXIT = 30 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, ICOMPZ, II, ISCALE, J, JTOT, K, L, L1, LEND,
|
|
$ LENDM1, LENDP1, LENDSV, LM1, LSV, M, MM, MM1,
|
|
$ NM1, NMAXIT
|
|
DOUBLE PRECISION ANORM, B, C, EPS, EPS2, F, G, P, R, RT1, RT2,
|
|
$ S, SAFMAX, SAFMIN, SSFMAX, SSFMIN, TST
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
DOUBLE PRECISION DLAMCH, DLANST, DLAPY2
|
|
EXTERNAL LSAME, DLAMCH, DLANST, DLAPY2
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLAE2, DLAEV2, DLARTG, DLASCL, DLASET, DLASR,
|
|
$ DLASRT, DSWAP, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, MAX, SIGN, SQRT
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
*
|
|
IF( LSAME( COMPZ, 'N' ) ) THEN
|
|
ICOMPZ = 0
|
|
ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
|
|
ICOMPZ = 1
|
|
ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
|
|
ICOMPZ = 2
|
|
ELSE
|
|
ICOMPZ = -1
|
|
END IF
|
|
IF( ICOMPZ.LT.0 ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 ) THEN
|
|
INFO = -2
|
|
ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,
|
|
$ N ) ) ) THEN
|
|
INFO = -6
|
|
END IF
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DSTEQR', -INFO )
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.EQ.0 )
|
|
$ RETURN
|
|
*
|
|
IF( N.EQ.1 ) THEN
|
|
IF( ICOMPZ.EQ.2 )
|
|
$ Z( 1, 1 ) = ONE
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Determine the unit roundoff and over/underflow thresholds.
|
|
*
|
|
EPS = DLAMCH( 'E' )
|
|
EPS2 = EPS**2
|
|
SAFMIN = DLAMCH( 'S' )
|
|
SAFMAX = ONE / SAFMIN
|
|
SSFMAX = SQRT( SAFMAX ) / THREE
|
|
SSFMIN = SQRT( SAFMIN ) / EPS2
|
|
*
|
|
* Compute the eigenvalues and eigenvectors of the tridiagonal
|
|
* matrix.
|
|
*
|
|
IF( ICOMPZ.EQ.2 )
|
|
$ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )
|
|
*
|
|
NMAXIT = N*MAXIT
|
|
JTOT = 0
|
|
*
|
|
* Determine where the matrix splits and choose QL or QR iteration
|
|
* for each block, according to whether top or bottom diagonal
|
|
* element is smaller.
|
|
*
|
|
L1 = 1
|
|
NM1 = N - 1
|
|
*
|
|
10 CONTINUE
|
|
IF( L1.GT.N )
|
|
$ GO TO 160
|
|
IF( L1.GT.1 )
|
|
$ E( L1-1 ) = ZERO
|
|
IF( L1.LE.NM1 ) THEN
|
|
DO 20 M = L1, NM1
|
|
TST = ABS( E( M ) )
|
|
IF( TST.EQ.ZERO )
|
|
$ GO TO 30
|
|
IF( TST.LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+
|
|
$ 1 ) ) ) )*EPS ) THEN
|
|
E( M ) = ZERO
|
|
GO TO 30
|
|
END IF
|
|
20 CONTINUE
|
|
END IF
|
|
M = N
|
|
*
|
|
30 CONTINUE
|
|
L = L1
|
|
LSV = L
|
|
LEND = M
|
|
LENDSV = LEND
|
|
L1 = M + 1
|
|
IF( LEND.EQ.L )
|
|
$ GO TO 10
|
|
*
|
|
* Scale submatrix in rows and columns L to LEND
|
|
*
|
|
ANORM = DLANST( 'M', LEND-L+1, D( L ), E( L ) )
|
|
ISCALE = 0
|
|
IF( ANORM.EQ.ZERO )
|
|
$ GO TO 10
|
|
IF( ANORM.GT.SSFMAX ) THEN
|
|
ISCALE = 1
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,
|
|
$ INFO )
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,
|
|
$ INFO )
|
|
ELSE IF( ANORM.LT.SSFMIN ) THEN
|
|
ISCALE = 2
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,
|
|
$ INFO )
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,
|
|
$ INFO )
|
|
END IF
|
|
*
|
|
* Choose between QL and QR iteration
|
|
*
|
|
IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN
|
|
LEND = LSV
|
|
L = LENDSV
|
|
END IF
|
|
*
|
|
IF( LEND.GT.L ) THEN
|
|
*
|
|
* QL Iteration
|
|
*
|
|
* Look for small subdiagonal element.
|
|
*
|
|
40 CONTINUE
|
|
IF( L.NE.LEND ) THEN
|
|
LENDM1 = LEND - 1
|
|
DO 50 M = L, LENDM1
|
|
TST = ABS( E( M ) )**2
|
|
IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M+1 ) )+
|
|
$ SAFMIN )GO TO 60
|
|
50 CONTINUE
|
|
END IF
|
|
*
|
|
M = LEND
|
|
*
|
|
60 CONTINUE
|
|
IF( M.LT.LEND )
|
|
$ E( M ) = ZERO
|
|
P = D( L )
|
|
IF( M.EQ.L )
|
|
$ GO TO 80
|
|
*
|
|
* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
|
|
* to compute its eigensystem.
|
|
*
|
|
IF( M.EQ.L+1 ) THEN
|
|
IF( ICOMPZ.GT.0 ) THEN
|
|
CALL DLAEV2( D( L ), E( L ), D( L+1 ), RT1, RT2, C, S )
|
|
WORK( L ) = C
|
|
WORK( N-1+L ) = S
|
|
CALL DLASR( 'R', 'V', 'B', N, 2, WORK( L ),
|
|
$ WORK( N-1+L ), Z( 1, L ), LDZ )
|
|
ELSE
|
|
CALL DLAE2( D( L ), E( L ), D( L+1 ), RT1, RT2 )
|
|
END IF
|
|
D( L ) = RT1
|
|
D( L+1 ) = RT2
|
|
E( L ) = ZERO
|
|
L = L + 2
|
|
IF( L.LE.LEND )
|
|
$ GO TO 40
|
|
GO TO 140
|
|
END IF
|
|
*
|
|
IF( JTOT.EQ.NMAXIT )
|
|
$ GO TO 140
|
|
JTOT = JTOT + 1
|
|
*
|
|
* Form shift.
|
|
*
|
|
G = ( D( L+1 )-P ) / ( TWO*E( L ) )
|
|
R = DLAPY2( G, ONE )
|
|
G = D( M ) - P + ( E( L ) / ( G+SIGN( R, G ) ) )
|
|
*
|
|
S = ONE
|
|
C = ONE
|
|
P = ZERO
|
|
*
|
|
* Inner loop
|
|
*
|
|
MM1 = M - 1
|
|
DO 70 I = MM1, L, -1
|
|
F = S*E( I )
|
|
B = C*E( I )
|
|
CALL DLARTG( G, F, C, S, R )
|
|
IF( I.NE.M-1 )
|
|
$ E( I+1 ) = R
|
|
G = D( I+1 ) - P
|
|
R = ( D( I )-G )*S + TWO*C*B
|
|
P = S*R
|
|
D( I+1 ) = G + P
|
|
G = C*R - B
|
|
*
|
|
* If eigenvectors are desired, then save rotations.
|
|
*
|
|
IF( ICOMPZ.GT.0 ) THEN
|
|
WORK( I ) = C
|
|
WORK( N-1+I ) = -S
|
|
END IF
|
|
*
|
|
70 CONTINUE
|
|
*
|
|
* If eigenvectors are desired, then apply saved rotations.
|
|
*
|
|
IF( ICOMPZ.GT.0 ) THEN
|
|
MM = M - L + 1
|
|
CALL DLASR( 'R', 'V', 'B', N, MM, WORK( L ), WORK( N-1+L ),
|
|
$ Z( 1, L ), LDZ )
|
|
END IF
|
|
*
|
|
D( L ) = D( L ) - P
|
|
E( L ) = G
|
|
GO TO 40
|
|
*
|
|
* Eigenvalue found.
|
|
*
|
|
80 CONTINUE
|
|
D( L ) = P
|
|
*
|
|
L = L + 1
|
|
IF( L.LE.LEND )
|
|
$ GO TO 40
|
|
GO TO 140
|
|
*
|
|
ELSE
|
|
*
|
|
* QR Iteration
|
|
*
|
|
* Look for small superdiagonal element.
|
|
*
|
|
90 CONTINUE
|
|
IF( L.NE.LEND ) THEN
|
|
LENDP1 = LEND + 1
|
|
DO 100 M = L, LENDP1, -1
|
|
TST = ABS( E( M-1 ) )**2
|
|
IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M-1 ) )+
|
|
$ SAFMIN )GO TO 110
|
|
100 CONTINUE
|
|
END IF
|
|
*
|
|
M = LEND
|
|
*
|
|
110 CONTINUE
|
|
IF( M.GT.LEND )
|
|
$ E( M-1 ) = ZERO
|
|
P = D( L )
|
|
IF( M.EQ.L )
|
|
$ GO TO 130
|
|
*
|
|
* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
|
|
* to compute its eigensystem.
|
|
*
|
|
IF( M.EQ.L-1 ) THEN
|
|
IF( ICOMPZ.GT.0 ) THEN
|
|
CALL DLAEV2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2, C, S )
|
|
WORK( M ) = C
|
|
WORK( N-1+M ) = S
|
|
CALL DLASR( 'R', 'V', 'F', N, 2, WORK( M ),
|
|
$ WORK( N-1+M ), Z( 1, L-1 ), LDZ )
|
|
ELSE
|
|
CALL DLAE2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2 )
|
|
END IF
|
|
D( L-1 ) = RT1
|
|
D( L ) = RT2
|
|
E( L-1 ) = ZERO
|
|
L = L - 2
|
|
IF( L.GE.LEND )
|
|
$ GO TO 90
|
|
GO TO 140
|
|
END IF
|
|
*
|
|
IF( JTOT.EQ.NMAXIT )
|
|
$ GO TO 140
|
|
JTOT = JTOT + 1
|
|
*
|
|
* Form shift.
|
|
*
|
|
G = ( D( L-1 )-P ) / ( TWO*E( L-1 ) )
|
|
R = DLAPY2( G, ONE )
|
|
G = D( M ) - P + ( E( L-1 ) / ( G+SIGN( R, G ) ) )
|
|
*
|
|
S = ONE
|
|
C = ONE
|
|
P = ZERO
|
|
*
|
|
* Inner loop
|
|
*
|
|
LM1 = L - 1
|
|
DO 120 I = M, LM1
|
|
F = S*E( I )
|
|
B = C*E( I )
|
|
CALL DLARTG( G, F, C, S, R )
|
|
IF( I.NE.M )
|
|
$ E( I-1 ) = R
|
|
G = D( I ) - P
|
|
R = ( D( I+1 )-G )*S + TWO*C*B
|
|
P = S*R
|
|
D( I ) = G + P
|
|
G = C*R - B
|
|
*
|
|
* If eigenvectors are desired, then save rotations.
|
|
*
|
|
IF( ICOMPZ.GT.0 ) THEN
|
|
WORK( I ) = C
|
|
WORK( N-1+I ) = S
|
|
END IF
|
|
*
|
|
120 CONTINUE
|
|
*
|
|
* If eigenvectors are desired, then apply saved rotations.
|
|
*
|
|
IF( ICOMPZ.GT.0 ) THEN
|
|
MM = L - M + 1
|
|
CALL DLASR( 'R', 'V', 'F', N, MM, WORK( M ), WORK( N-1+M ),
|
|
$ Z( 1, M ), LDZ )
|
|
END IF
|
|
*
|
|
D( L ) = D( L ) - P
|
|
E( LM1 ) = G
|
|
GO TO 90
|
|
*
|
|
* Eigenvalue found.
|
|
*
|
|
130 CONTINUE
|
|
D( L ) = P
|
|
*
|
|
L = L - 1
|
|
IF( L.GE.LEND )
|
|
$ GO TO 90
|
|
GO TO 140
|
|
*
|
|
END IF
|
|
*
|
|
* Undo scaling if necessary
|
|
*
|
|
140 CONTINUE
|
|
IF( ISCALE.EQ.1 ) THEN
|
|
CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,
|
|
$ D( LSV ), N, INFO )
|
|
CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV, 1, E( LSV ),
|
|
$ N, INFO )
|
|
ELSE IF( ISCALE.EQ.2 ) THEN
|
|
CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,
|
|
$ D( LSV ), N, INFO )
|
|
CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV, 1, E( LSV ),
|
|
$ N, INFO )
|
|
END IF
|
|
*
|
|
* Check for no convergence to an eigenvalue after a total
|
|
* of N*MAXIT iterations.
|
|
*
|
|
IF( JTOT.LT.NMAXIT )
|
|
$ GO TO 10
|
|
DO 150 I = 1, N - 1
|
|
IF( E( I ).NE.ZERO )
|
|
$ INFO = INFO + 1
|
|
150 CONTINUE
|
|
GO TO 190
|
|
*
|
|
* Order eigenvalues and eigenvectors.
|
|
*
|
|
160 CONTINUE
|
|
IF( ICOMPZ.EQ.0 ) THEN
|
|
*
|
|
* Use Quick Sort
|
|
*
|
|
CALL DLASRT( 'I', N, D, INFO )
|
|
*
|
|
ELSE
|
|
*
|
|
* Use Selection Sort to minimize swaps of eigenvectors
|
|
*
|
|
DO 180 II = 2, N
|
|
I = II - 1
|
|
K = I
|
|
P = D( I )
|
|
DO 170 J = II, N
|
|
IF( D( J ).LT.P ) THEN
|
|
K = J
|
|
P = D( J )
|
|
END IF
|
|
170 CONTINUE
|
|
IF( K.NE.I ) THEN
|
|
D( K ) = D( I )
|
|
D( I ) = P
|
|
CALL DSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 )
|
|
END IF
|
|
180 CONTINUE
|
|
END IF
|
|
*
|
|
190 CONTINUE
|
|
RETURN
|
|
*
|
|
* End of DSTEQR
|
|
*
|
|
END
|
|
SUBROUTINE DSTERF( N, D, E, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER INFO, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION D( * ), E( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSTERF computes all eigenvalues of a symmetric tridiagonal matrix
|
|
* using the Pal-Walker-Kahan variant of the QL or QR algorithm.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the matrix. N >= 0.
|
|
*
|
|
* D (input/output) DOUBLE PRECISION array, dimension (N)
|
|
* On entry, the n diagonal elements of the tridiagonal matrix.
|
|
* On exit, if INFO = 0, the eigenvalues in ascending order.
|
|
*
|
|
* E (input/output) DOUBLE PRECISION array, dimension (N-1)
|
|
* On entry, the (n-1) subdiagonal elements of the tridiagonal
|
|
* matrix.
|
|
* On exit, E has been destroyed.
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument had an illegal value
|
|
* > 0: the algorithm failed to find all of the eigenvalues in
|
|
* a total of 30*N iterations; if INFO = i, then i
|
|
* elements of E have not converged to zero.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO, ONE, TWO, THREE
|
|
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
|
|
$ THREE = 3.0D0 )
|
|
INTEGER MAXIT
|
|
PARAMETER ( MAXIT = 30 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M,
|
|
$ NMAXIT
|
|
DOUBLE PRECISION ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC,
|
|
$ OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN,
|
|
$ SIGMA, SSFMAX, SSFMIN, RMAX
|
|
* ..
|
|
* .. External Functions ..
|
|
DOUBLE PRECISION DLAMCH, DLANST, DLAPY2
|
|
EXTERNAL DLAMCH, DLANST, DLAPY2
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLAE2, DLASCL, DLASRT, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS, SIGN, SQRT
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LT.0 ) THEN
|
|
INFO = -1
|
|
CALL XERBLA( 'DSTERF', -INFO )
|
|
RETURN
|
|
END IF
|
|
IF( N.LE.1 )
|
|
$ RETURN
|
|
*
|
|
* Determine the unit roundoff for this environment.
|
|
*
|
|
EPS = DLAMCH( 'E' )
|
|
EPS2 = EPS**2
|
|
SAFMIN = DLAMCH( 'S' )
|
|
SAFMAX = ONE / SAFMIN
|
|
SSFMAX = SQRT( SAFMAX ) / THREE
|
|
SSFMIN = SQRT( SAFMIN ) / EPS2
|
|
RMAX = DLAMCH( 'O' )
|
|
*
|
|
* Compute the eigenvalues of the tridiagonal matrix.
|
|
*
|
|
NMAXIT = N*MAXIT
|
|
SIGMA = ZERO
|
|
JTOT = 0
|
|
*
|
|
* Determine where the matrix splits and choose QL or QR iteration
|
|
* for each block, according to whether top or bottom diagonal
|
|
* element is smaller.
|
|
*
|
|
L1 = 1
|
|
*
|
|
10 CONTINUE
|
|
IF( L1.GT.N )
|
|
$ GO TO 170
|
|
IF( L1.GT.1 )
|
|
$ E( L1-1 ) = ZERO
|
|
DO 20 M = L1, N - 1
|
|
IF( ABS( E( M ) ).LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+
|
|
$ 1 ) ) ) )*EPS ) THEN
|
|
E( M ) = ZERO
|
|
GO TO 30
|
|
END IF
|
|
20 CONTINUE
|
|
M = N
|
|
*
|
|
30 CONTINUE
|
|
L = L1
|
|
LSV = L
|
|
LEND = M
|
|
LENDSV = LEND
|
|
L1 = M + 1
|
|
IF( LEND.EQ.L )
|
|
$ GO TO 10
|
|
*
|
|
* Scale submatrix in rows and columns L to LEND
|
|
*
|
|
ANORM = DLANST( 'M', LEND-L+1, D( L ), E( L ) )
|
|
ISCALE = 0
|
|
IF( ANORM.EQ.ZERO )
|
|
$ GO TO 10
|
|
IF( (ANORM.GT.SSFMAX) ) THEN
|
|
ISCALE = 1
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,
|
|
$ INFO )
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,
|
|
$ INFO )
|
|
ELSE IF( ANORM.LT.SSFMIN ) THEN
|
|
ISCALE = 2
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,
|
|
$ INFO )
|
|
CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,
|
|
$ INFO )
|
|
END IF
|
|
*
|
|
DO 40 I = L, LEND - 1
|
|
E( I ) = E( I )**2
|
|
40 CONTINUE
|
|
*
|
|
* Choose between QL and QR iteration
|
|
*
|
|
IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN
|
|
LEND = LSV
|
|
L = LENDSV
|
|
END IF
|
|
*
|
|
IF( LEND.GE.L ) THEN
|
|
*
|
|
* QL Iteration
|
|
*
|
|
* Look for small subdiagonal element.
|
|
*
|
|
50 CONTINUE
|
|
IF( L.NE.LEND ) THEN
|
|
DO 60 M = L, LEND - 1
|
|
IF( ABS( E( M ) ).LE.EPS2*ABS( D( M )*D( M+1 ) ) )
|
|
$ GO TO 70
|
|
60 CONTINUE
|
|
END IF
|
|
M = LEND
|
|
*
|
|
70 CONTINUE
|
|
IF( M.LT.LEND )
|
|
$ E( M ) = ZERO
|
|
P = D( L )
|
|
IF( M.EQ.L )
|
|
$ GO TO 90
|
|
*
|
|
* If remaining matrix is 2 by 2, use DLAE2 to compute its
|
|
* eigenvalues.
|
|
*
|
|
IF( M.EQ.L+1 ) THEN
|
|
RTE = SQRT( E( L ) )
|
|
CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 )
|
|
D( L ) = RT1
|
|
D( L+1 ) = RT2
|
|
E( L ) = ZERO
|
|
L = L + 2
|
|
IF( L.LE.LEND )
|
|
$ GO TO 50
|
|
GO TO 150
|
|
END IF
|
|
*
|
|
IF( JTOT.EQ.NMAXIT )
|
|
$ GO TO 150
|
|
JTOT = JTOT + 1
|
|
*
|
|
* Form shift.
|
|
*
|
|
RTE = SQRT( E( L ) )
|
|
SIGMA = ( D( L+1 )-P ) / ( TWO*RTE )
|
|
R = DLAPY2( SIGMA, ONE )
|
|
SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )
|
|
*
|
|
C = ONE
|
|
S = ZERO
|
|
GAMMA = D( M ) - SIGMA
|
|
P = GAMMA*GAMMA
|
|
*
|
|
* Inner loop
|
|
*
|
|
DO 80 I = M - 1, L, -1
|
|
BB = E( I )
|
|
R = P + BB
|
|
IF( I.NE.M-1 )
|
|
$ E( I+1 ) = S*R
|
|
OLDC = C
|
|
C = P / R
|
|
S = BB / R
|
|
OLDGAM = GAMMA
|
|
ALPHA = D( I )
|
|
GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM
|
|
D( I+1 ) = OLDGAM + ( ALPHA-GAMMA )
|
|
IF( C.NE.ZERO ) THEN
|
|
P = ( GAMMA*GAMMA ) / C
|
|
ELSE
|
|
P = OLDC*BB
|
|
END IF
|
|
80 CONTINUE
|
|
*
|
|
E( L ) = S*P
|
|
D( L ) = SIGMA + GAMMA
|
|
GO TO 50
|
|
*
|
|
* Eigenvalue found.
|
|
*
|
|
90 CONTINUE
|
|
D( L ) = P
|
|
*
|
|
L = L + 1
|
|
IF( L.LE.LEND )
|
|
$ GO TO 50
|
|
GO TO 150
|
|
*
|
|
ELSE
|
|
*
|
|
* QR Iteration
|
|
*
|
|
* Look for small superdiagonal element.
|
|
*
|
|
100 CONTINUE
|
|
DO 110 M = L, LEND + 1, -1
|
|
IF( ABS( E( M-1 ) ).LE.EPS2*ABS( D( M )*D( M-1 ) ) )
|
|
$ GO TO 120
|
|
110 CONTINUE
|
|
M = LEND
|
|
*
|
|
120 CONTINUE
|
|
IF( M.GT.LEND )
|
|
$ E( M-1 ) = ZERO
|
|
P = D( L )
|
|
IF( M.EQ.L )
|
|
$ GO TO 140
|
|
*
|
|
* If remaining matrix is 2 by 2, use DLAE2 to compute its
|
|
* eigenvalues.
|
|
*
|
|
IF( M.EQ.L-1 ) THEN
|
|
RTE = SQRT( E( L-1 ) )
|
|
CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 )
|
|
D( L ) = RT1
|
|
D( L-1 ) = RT2
|
|
E( L-1 ) = ZERO
|
|
L = L - 2
|
|
IF( L.GE.LEND )
|
|
$ GO TO 100
|
|
GO TO 150
|
|
END IF
|
|
*
|
|
IF( JTOT.EQ.NMAXIT )
|
|
$ GO TO 150
|
|
JTOT = JTOT + 1
|
|
*
|
|
* Form shift.
|
|
*
|
|
RTE = SQRT( E( L-1 ) )
|
|
SIGMA = ( D( L-1 )-P ) / ( TWO*RTE )
|
|
R = DLAPY2( SIGMA, ONE )
|
|
SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )
|
|
*
|
|
C = ONE
|
|
S = ZERO
|
|
GAMMA = D( M ) - SIGMA
|
|
P = GAMMA*GAMMA
|
|
*
|
|
* Inner loop
|
|
*
|
|
DO 130 I = M, L - 1
|
|
BB = E( I )
|
|
R = P + BB
|
|
IF( I.NE.M )
|
|
$ E( I-1 ) = S*R
|
|
OLDC = C
|
|
C = P / R
|
|
S = BB / R
|
|
OLDGAM = GAMMA
|
|
ALPHA = D( I+1 )
|
|
GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM
|
|
D( I ) = OLDGAM + ( ALPHA-GAMMA )
|
|
IF( C.NE.ZERO ) THEN
|
|
P = ( GAMMA*GAMMA ) / C
|
|
ELSE
|
|
P = OLDC*BB
|
|
END IF
|
|
130 CONTINUE
|
|
*
|
|
E( L-1 ) = S*P
|
|
D( L ) = SIGMA + GAMMA
|
|
GO TO 100
|
|
*
|
|
* Eigenvalue found.
|
|
*
|
|
140 CONTINUE
|
|
D( L ) = P
|
|
*
|
|
L = L - 1
|
|
IF( L.GE.LEND )
|
|
$ GO TO 100
|
|
GO TO 150
|
|
*
|
|
END IF
|
|
*
|
|
* Undo scaling if necessary
|
|
*
|
|
150 CONTINUE
|
|
IF( ISCALE.EQ.1 )
|
|
$ CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,
|
|
$ D( LSV ), N, INFO )
|
|
IF( ISCALE.EQ.2 )
|
|
$ CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,
|
|
$ D( LSV ), N, INFO )
|
|
*
|
|
* Check for no convergence to an eigenvalue after a total
|
|
* of N*MAXIT iterations.
|
|
*
|
|
IF( JTOT.LT.NMAXIT )
|
|
$ GO TO 10
|
|
DO 160 I = 1, N - 1
|
|
IF( E( I ).NE.ZERO )
|
|
$ INFO = INFO + 1
|
|
160 CONTINUE
|
|
GO TO 180
|
|
*
|
|
* Sort eigenvalues in increasing order.
|
|
*
|
|
170 CONTINUE
|
|
CALL DLASRT( 'I', N, D, INFO )
|
|
*
|
|
180 CONTINUE
|
|
RETURN
|
|
*
|
|
* End of DSTERF
|
|
*
|
|
END
|
|
SUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )
|
|
*
|
|
* -- LAPACK driver routine (version 3.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2006
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER JOBZ, UPLO
|
|
INTEGER INFO, LDA, LWORK, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSYEV computes all eigenvalues and, optionally, eigenvectors of a
|
|
* real symmetric matrix A.
|
|
*
|
|
* 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) DOUBLE PRECISION 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) DOUBLE PRECISION array, dimension (N)
|
|
* If INFO = 0, the eigenvalues in ascending order.
|
|
*
|
|
* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
|
|
* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
|
*
|
|
* LWORK (input) INTEGER
|
|
* The length of the array WORK. LWORK >= max(1,3*N-1).
|
|
* For optimal efficiency, LWORK >= (NB+2)*N,
|
|
* where NB is the blocksize for DSYTRD returned by ILAENV.
|
|
*
|
|
* If LWORK = -1, then a workspace query is assumed; the routine
|
|
* only calculates the optimal size of the WORK array, returns
|
|
* this value as the first entry of the WORK array, and no error
|
|
* message related to LWORK is issued by XERBLA.
|
|
*
|
|
* 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 LOWER, LQUERY, WANTZ
|
|
INTEGER IINFO, IMAX, INDE, INDTAU, INDWRK, ISCALE,
|
|
$ LLWORK, LWKOPT, NB
|
|
DOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,
|
|
$ SMLNUM
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
INTEGER ILAENV
|
|
DOUBLE PRECISION DLAMCH, DLANSY
|
|
EXTERNAL LSAME, ILAENV, DLAMCH, DLANSY
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLASCL, DORGTR, DSCAL, DSTEQR, DSTERF, DSYTRD,
|
|
$ XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX, SQRT
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
WANTZ = LSAME( JOBZ, 'V' )
|
|
LOWER = LSAME( UPLO, 'L' )
|
|
LQUERY = ( LWORK.EQ.-1 )
|
|
*
|
|
INFO = 0
|
|
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
|
|
END IF
|
|
*
|
|
IF( INFO.EQ.0 ) THEN
|
|
NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )
|
|
LWKOPT = MAX( 1, ( NB+2 )*N )
|
|
WORK( 1 ) = LWKOPT
|
|
*
|
|
IF( LWORK.LT.MAX( 1, 3*N-1 ) .AND. .NOT.LQUERY )
|
|
$ INFO = -8
|
|
END IF
|
|
*
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DSYEV ', -INFO )
|
|
RETURN
|
|
ELSE IF( LQUERY ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.EQ.0 ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( N.EQ.1 ) THEN
|
|
W( 1 ) = A( 1, 1 )
|
|
WORK( 1 ) = 2
|
|
IF( WANTZ )
|
|
$ A( 1, 1 ) = ONE
|
|
RETURN
|
|
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
|
|
CALL DSYTRD( UPLO, N, A, LDA, W, WORK( INDE ), WORK( INDTAU ),
|
|
$ WORK( INDWRK ), LLWORK, IINFO )
|
|
*
|
|
* For eigenvalues only, call DSTERF. For eigenvectors, first call
|
|
* DORGTR to generate the orthogonal matrix, then call DSTEQR.
|
|
*
|
|
IF( .NOT.WANTZ ) THEN
|
|
CALL DSTERF( N, W, WORK( INDE ), INFO )
|
|
ELSE
|
|
CALL DORGTR( UPLO, N, A, LDA, WORK( INDTAU ), WORK( INDWRK ),
|
|
$ LLWORK, IINFO )
|
|
CALL DSTEQR( JOBZ, N, W, WORK( INDE ), A, LDA, 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
|
|
*
|
|
* Set WORK(1) to optimal workspace size.
|
|
*
|
|
WORK( 1 ) = LWKOPT
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DSYEV
|
|
*
|
|
END
|
|
SUBROUTINE DSYTD2( UPLO, N, A, LDA, D, E, TAU, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER UPLO
|
|
INTEGER INFO, LDA, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSYTD2 reduces a real symmetric matrix A to symmetric tridiagonal
|
|
* form T by an orthogonal similarity transformation: Q**T * A * Q = T.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* UPLO (input) CHARACTER*1
|
|
* Specifies whether the upper or lower triangular part of the
|
|
* symmetric matrix A is stored:
|
|
* = 'U': Upper triangular
|
|
* = 'L': Lower triangular
|
|
*
|
|
* N (input) INTEGER
|
|
* The order of the matrix A. N >= 0.
|
|
*
|
|
* A (input/output) DOUBLE PRECISION 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, and the strictly lower
|
|
* triangular part of A is not referenced. If UPLO = 'L', the
|
|
* leading n-by-n lower triangular part of A contains the lower
|
|
* triangular part of the matrix A, and the strictly upper
|
|
* triangular part of A is not referenced.
|
|
* On exit, if UPLO = 'U', the diagonal and first superdiagonal
|
|
* of A are overwritten by the corresponding elements of the
|
|
* tridiagonal matrix T, and the elements above the first
|
|
* superdiagonal, with the array TAU, represent the orthogonal
|
|
* matrix Q as a product of elementary reflectors; if UPLO
|
|
* = 'L', the diagonal and first subdiagonal of A are over-
|
|
* written by the corresponding elements of the tridiagonal
|
|
* matrix T, and the elements below the first subdiagonal, with
|
|
* the array TAU, represent the orthogonal matrix Q as a product
|
|
* of elementary reflectors. See Further Details.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= max(1,N).
|
|
*
|
|
* D (output) DOUBLE PRECISION array, dimension (N)
|
|
* The diagonal elements of the tridiagonal matrix T:
|
|
* D(i) = A(i,i).
|
|
*
|
|
* E (output) DOUBLE PRECISION array, dimension (N-1)
|
|
* The off-diagonal elements of the tridiagonal matrix T:
|
|
* E(i) = A(i,i+1) if UPLO = 'U', E(i) = A(i+1,i) if UPLO = 'L'.
|
|
*
|
|
* TAU (output) DOUBLE PRECISION array, dimension (N-1)
|
|
* The scalar factors of the elementary reflectors (see Further
|
|
* Details).
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument had an illegal value.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* If UPLO = 'U', the matrix Q is represented as a product of elementary
|
|
* reflectors
|
|
*
|
|
* Q = H(n-1) . . . H(2) H(1).
|
|
*
|
|
* Each H(i) has the form
|
|
*
|
|
* H(i) = I - tau * v * v**T
|
|
*
|
|
* where tau is a real scalar, and v is a real vector with
|
|
* v(i+1:n) = 0 and v(i) = 1; v(1:i-1) is stored on exit in
|
|
* A(1:i-1,i+1), and tau in TAU(i).
|
|
*
|
|
* If UPLO = 'L', the matrix Q is represented as a product of elementary
|
|
* reflectors
|
|
*
|
|
* Q = H(1) H(2) . . . H(n-1).
|
|
*
|
|
* Each H(i) has the form
|
|
*
|
|
* H(i) = I - tau * v * v**T
|
|
*
|
|
* where tau is a real scalar, and v is a real vector with
|
|
* v(1:i) = 0 and v(i+1) = 1; v(i+2:n) is stored on exit in A(i+2:n,i),
|
|
* and tau in TAU(i).
|
|
*
|
|
* The contents of A on exit are illustrated by the following examples
|
|
* with n = 5:
|
|
*
|
|
* if UPLO = 'U': if UPLO = 'L':
|
|
*
|
|
* ( d e v2 v3 v4 ) ( d )
|
|
* ( d e v3 v4 ) ( e d )
|
|
* ( d e v4 ) ( v1 e d )
|
|
* ( d e ) ( v1 v2 e d )
|
|
* ( d ) ( v1 v2 v3 e d )
|
|
*
|
|
* where d and e denote diagonal and off-diagonal elements of T, and vi
|
|
* denotes an element of the vector defining H(i).
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO, HALF
|
|
PARAMETER ( ONE = 1.0D0, ZERO = 0.0D0,
|
|
$ HALF = 1.0D0 / 2.0D0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL UPPER
|
|
INTEGER I
|
|
DOUBLE PRECISION ALPHA, TAUI
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DAXPY, DLARFG, DSYMV, DSYR2, XERBLA
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
DOUBLE PRECISION DDOT
|
|
EXTERNAL LSAME, DDOT
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX, MIN
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input parameters
|
|
*
|
|
INFO = 0
|
|
UPPER = LSAME( UPLO, 'U' )
|
|
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 ) THEN
|
|
INFO = -2
|
|
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
|
|
INFO = -4
|
|
END IF
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DSYTD2', -INFO )
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.LE.0 )
|
|
$ RETURN
|
|
*
|
|
IF( UPPER ) THEN
|
|
*
|
|
* Reduce the upper triangle of A
|
|
*
|
|
DO 10 I = N - 1, 1, -1
|
|
*
|
|
* Generate elementary reflector H(i) = I - tau * v * v**T
|
|
* to annihilate A(1:i-1,i+1)
|
|
*
|
|
CALL DLARFG( I, A( I, I+1 ), A( 1, I+1 ), 1, TAUI )
|
|
E( I ) = A( I, I+1 )
|
|
*
|
|
IF( TAUI.NE.ZERO ) THEN
|
|
*
|
|
* Apply H(i) from both sides to A(1:i,1:i)
|
|
*
|
|
A( I, I+1 ) = ONE
|
|
*
|
|
* Compute x := tau * A * v storing x in TAU(1:i)
|
|
*
|
|
CALL DSYMV( UPLO, I, TAUI, A, LDA, A( 1, I+1 ), 1, ZERO,
|
|
$ TAU, 1 )
|
|
*
|
|
* Compute w := x - 1/2 * tau * (x**T * v) * v
|
|
*
|
|
ALPHA = -HALF*TAUI*DDOT( I, TAU, 1, A( 1, I+1 ), 1 )
|
|
CALL DAXPY( I, ALPHA, A( 1, I+1 ), 1, TAU, 1 )
|
|
*
|
|
* Apply the transformation as a rank-2 update:
|
|
* A := A - v * w**T - w * v**T
|
|
*
|
|
CALL DSYR2( UPLO, I, -ONE, A( 1, I+1 ), 1, TAU, 1, A,
|
|
$ LDA )
|
|
*
|
|
A( I, I+1 ) = E( I )
|
|
END IF
|
|
D( I+1 ) = A( I+1, I+1 )
|
|
TAU( I ) = TAUI
|
|
10 CONTINUE
|
|
D( 1 ) = A( 1, 1 )
|
|
ELSE
|
|
*
|
|
* Reduce the lower triangle of A
|
|
*
|
|
DO 20 I = 1, N - 1
|
|
*
|
|
* Generate elementary reflector H(i) = I - tau * v * v**T
|
|
* to annihilate A(i+2:n,i)
|
|
*
|
|
CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,
|
|
$ TAUI )
|
|
E( I ) = A( I+1, I )
|
|
*
|
|
IF( TAUI.NE.ZERO ) THEN
|
|
*
|
|
* Apply H(i) from both sides to A(i+1:n,i+1:n)
|
|
*
|
|
A( I+1, I ) = ONE
|
|
*
|
|
* Compute x := tau * A * v storing y in TAU(i:n-1)
|
|
*
|
|
CALL DSYMV( UPLO, N-I, TAUI, A( I+1, I+1 ), LDA,
|
|
$ A( I+1, I ), 1, ZERO, TAU( I ), 1 )
|
|
*
|
|
* Compute w := x - 1/2 * tau * (x**T * v) * v
|
|
*
|
|
ALPHA = -HALF*TAUI*DDOT( N-I, TAU( I ), 1, A( I+1, I ),
|
|
$ 1 )
|
|
CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, TAU( I ), 1 )
|
|
*
|
|
* Apply the transformation as a rank-2 update:
|
|
* A := A - v * w**T - w * v**T
|
|
*
|
|
CALL DSYR2( UPLO, N-I, -ONE, A( I+1, I ), 1, TAU( I ), 1,
|
|
$ A( I+1, I+1 ), LDA )
|
|
*
|
|
A( I+1, I ) = E( I )
|
|
END IF
|
|
D( I ) = A( I, I )
|
|
TAU( I ) = TAUI
|
|
20 CONTINUE
|
|
D( N ) = A( N, N )
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DSYTD2
|
|
*
|
|
END
|
|
SUBROUTINE DSYTRD( UPLO, N, A, LDA, D, E, TAU, WORK, LWORK, INFO )
|
|
*
|
|
* -- LAPACK routine (version 3.3.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* -- April 2011 --
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER UPLO
|
|
INTEGER INFO, LDA, LWORK, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * ),
|
|
$ WORK( * )
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSYTRD reduces a real symmetric matrix A to real symmetric
|
|
* tridiagonal form T by an orthogonal similarity transformation:
|
|
* Q**T * A * Q = T.
|
|
*
|
|
* Arguments
|
|
* =========
|
|
*
|
|
* 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) DOUBLE PRECISION 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, and the strictly lower
|
|
* triangular part of A is not referenced. If UPLO = 'L', the
|
|
* leading N-by-N lower triangular part of A contains the lower
|
|
* triangular part of the matrix A, and the strictly upper
|
|
* triangular part of A is not referenced.
|
|
* On exit, if UPLO = 'U', the diagonal and first superdiagonal
|
|
* of A are overwritten by the corresponding elements of the
|
|
* tridiagonal matrix T, and the elements above the first
|
|
* superdiagonal, with the array TAU, represent the orthogonal
|
|
* matrix Q as a product of elementary reflectors; if UPLO
|
|
* = 'L', the diagonal and first subdiagonal of A are over-
|
|
* written by the corresponding elements of the tridiagonal
|
|
* matrix T, and the elements below the first subdiagonal, with
|
|
* the array TAU, represent the orthogonal matrix Q as a product
|
|
* of elementary reflectors. See Further Details.
|
|
*
|
|
* LDA (input) INTEGER
|
|
* The leading dimension of the array A. LDA >= max(1,N).
|
|
*
|
|
* D (output) DOUBLE PRECISION array, dimension (N)
|
|
* The diagonal elements of the tridiagonal matrix T:
|
|
* D(i) = A(i,i).
|
|
*
|
|
* E (output) DOUBLE PRECISION array, dimension (N-1)
|
|
* The off-diagonal elements of the tridiagonal matrix T:
|
|
* E(i) = A(i,i+1) if UPLO = 'U', E(i) = A(i+1,i) if UPLO = 'L'.
|
|
*
|
|
* TAU (output) DOUBLE PRECISION array, dimension (N-1)
|
|
* The scalar factors of the elementary reflectors (see Further
|
|
* Details).
|
|
*
|
|
* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
|
|
* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
|
*
|
|
* LWORK (input) INTEGER
|
|
* The dimension of the array WORK. LWORK >= 1.
|
|
* For optimum performance LWORK >= N*NB, where NB is the
|
|
* optimal blocksize.
|
|
*
|
|
* If LWORK = -1, then a workspace query is assumed; the routine
|
|
* only calculates the optimal size of the WORK array, returns
|
|
* this value as the first entry of the WORK array, and no error
|
|
* message related to LWORK is issued by XERBLA.
|
|
*
|
|
* INFO (output) INTEGER
|
|
* = 0: successful exit
|
|
* < 0: if INFO = -i, the i-th argument had an illegal value
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* If UPLO = 'U', the matrix Q is represented as a product of elementary
|
|
* reflectors
|
|
*
|
|
* Q = H(n-1) . . . H(2) H(1).
|
|
*
|
|
* Each H(i) has the form
|
|
*
|
|
* H(i) = I - tau * v * v**T
|
|
*
|
|
* where tau is a real scalar, and v is a real vector with
|
|
* v(i+1:n) = 0 and v(i) = 1; v(1:i-1) is stored on exit in
|
|
* A(1:i-1,i+1), and tau in TAU(i).
|
|
*
|
|
* If UPLO = 'L', the matrix Q is represented as a product of elementary
|
|
* reflectors
|
|
*
|
|
* Q = H(1) H(2) . . . H(n-1).
|
|
*
|
|
* Each H(i) has the form
|
|
*
|
|
* H(i) = I - tau * v * v**T
|
|
*
|
|
* where tau is a real scalar, and v is a real vector with
|
|
* v(1:i) = 0 and v(i+1) = 1; v(i+2:n) is stored on exit in A(i+2:n,i),
|
|
* and tau in TAU(i).
|
|
*
|
|
* The contents of A on exit are illustrated by the following examples
|
|
* with n = 5:
|
|
*
|
|
* if UPLO = 'U': if UPLO = 'L':
|
|
*
|
|
* ( d e v2 v3 v4 ) ( d )
|
|
* ( d e v3 v4 ) ( e d )
|
|
* ( d e v4 ) ( v1 e d )
|
|
* ( d e ) ( v1 v2 e d )
|
|
* ( d ) ( v1 v2 v3 e d )
|
|
*
|
|
* where d and e denote diagonal and off-diagonal elements of T, and vi
|
|
* denotes an element of the vector defining H(i).
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE
|
|
PARAMETER ( ONE = 1.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL LQUERY, UPPER
|
|
INTEGER I, IINFO, IWS, J, KK, LDWORK, LWKOPT, NB,
|
|
$ NBMIN, NX
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL DLATRD, DSYR2K, DSYTD2, XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
INTEGER ILAENV
|
|
EXTERNAL LSAME, ILAENV
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input parameters
|
|
*
|
|
INFO = 0
|
|
UPPER = LSAME( UPLO, 'U' )
|
|
LQUERY = ( LWORK.EQ.-1 )
|
|
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
|
|
INFO = -1
|
|
ELSE IF( N.LT.0 ) THEN
|
|
INFO = -2
|
|
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
|
|
INFO = -4
|
|
ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THEN
|
|
INFO = -9
|
|
END IF
|
|
*
|
|
IF( INFO.EQ.0 ) THEN
|
|
*
|
|
* Determine the block size.
|
|
*
|
|
NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )
|
|
LWKOPT = N*NB
|
|
WORK( 1 ) = LWKOPT
|
|
END IF
|
|
*
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'DSYTRD', -INFO )
|
|
RETURN
|
|
ELSE IF( LQUERY ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.EQ.0 ) THEN
|
|
WORK( 1 ) = 1
|
|
RETURN
|
|
END IF
|
|
*
|
|
NX = N
|
|
IWS = 1
|
|
IF( NB.GT.1 .AND. NB.LT.N ) THEN
|
|
*
|
|
* Determine when to cross over from blocked to unblocked code
|
|
* (last block is always handled by unblocked code).
|
|
*
|
|
NX = MAX( NB, ILAENV( 3, 'DSYTRD', UPLO, N, -1, -1, -1 ) )
|
|
IF( NX.LT.N ) THEN
|
|
*
|
|
* Determine if workspace is large enough for blocked code.
|
|
*
|
|
LDWORK = N
|
|
IWS = LDWORK*NB
|
|
IF( LWORK.LT.IWS ) THEN
|
|
*
|
|
* Not enough workspace to use optimal NB: determine the
|
|
* minimum value of NB, and reduce NB or force use of
|
|
* unblocked code by setting NX = N.
|
|
*
|
|
NB = MAX( LWORK / LDWORK, 1 )
|
|
NBMIN = ILAENV( 2, 'DSYTRD', UPLO, N, -1, -1, -1 )
|
|
IF( NB.LT.NBMIN )
|
|
$ NX = N
|
|
END IF
|
|
ELSE
|
|
NX = N
|
|
END IF
|
|
ELSE
|
|
NB = 1
|
|
END IF
|
|
*
|
|
IF( UPPER ) THEN
|
|
*
|
|
* Reduce the upper triangle of A.
|
|
* Columns 1:kk are handled by the unblocked method.
|
|
*
|
|
KK = N - ( ( N-NX+NB-1 ) / NB )*NB
|
|
DO 20 I = N - NB + 1, KK + 1, -NB
|
|
*
|
|
* Reduce columns i:i+nb-1 to tridiagonal form and form the
|
|
* matrix W which is needed to update the unreduced part of
|
|
* the matrix
|
|
*
|
|
CALL DLATRD( UPLO, I+NB-1, NB, A, LDA, E, TAU, WORK,
|
|
$ LDWORK )
|
|
*
|
|
* Update the unreduced submatrix A(1:i-1,1:i-1), using an
|
|
* update of the form: A := A - V*W**T - W*V**T
|
|
*
|
|
CALL DSYR2K( UPLO, 'No transpose', I-1, NB, -ONE, A( 1, I ),
|
|
$ LDA, WORK, LDWORK, ONE, A, LDA )
|
|
*
|
|
* Copy superdiagonal elements back into A, and diagonal
|
|
* elements into D
|
|
*
|
|
DO 10 J = I, I + NB - 1
|
|
A( J-1, J ) = E( J-1 )
|
|
D( J ) = A( J, J )
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
*
|
|
* Use unblocked code to reduce the last or only block
|
|
*
|
|
CALL DSYTD2( UPLO, KK, A, LDA, D, E, TAU, IINFO )
|
|
ELSE
|
|
*
|
|
* Reduce the lower triangle of A
|
|
*
|
|
DO 40 I = 1, N - NX, NB
|
|
*
|
|
* Reduce columns i:i+nb-1 to tridiagonal form and form the
|
|
* matrix W which is needed to update the unreduced part of
|
|
* the matrix
|
|
*
|
|
CALL DLATRD( UPLO, N-I+1, NB, A( I, I ), LDA, E( I ),
|
|
$ TAU( I ), WORK, LDWORK )
|
|
*
|
|
* Update the unreduced submatrix A(i+ib:n,i+ib:n), using
|
|
* an update of the form: A := A - V*W**T - W*V**T
|
|
*
|
|
CALL DSYR2K( UPLO, 'No transpose', N-I-NB+1, NB, -ONE,
|
|
$ A( I+NB, I ), LDA, WORK( NB+1 ), LDWORK, ONE,
|
|
$ A( I+NB, I+NB ), LDA )
|
|
*
|
|
* Copy subdiagonal elements back into A, and diagonal
|
|
* elements into D
|
|
*
|
|
DO 30 J = I, I + NB - 1
|
|
A( J+1, J ) = E( J )
|
|
D( J ) = A( J, J )
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
*
|
|
* Use unblocked code to reduce the last or only block
|
|
*
|
|
CALL DSYTD2( UPLO, N-I+1, A( I, I ), LDA, D( I ), E( I ),
|
|
$ TAU( I ), IINFO )
|
|
END IF
|
|
*
|
|
WORK( 1 ) = LWKOPT
|
|
RETURN
|
|
*
|
|
* End of DSYTRD
|
|
*
|
|
END
|
|
*> \brief \b DLAMCH
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* DOUBLE PRECISION FUNCTION DLAMCH( CMACH )
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> DLAMCH determines double precision machine parameters.
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] CMACH
|
|
*> \verbatim
|
|
*> Specifies the value to be returned by DLAMCH:
|
|
*> = 'E' or 'e', DLAMCH := eps
|
|
*> = 'S' or 's , DLAMCH := sfmin
|
|
*> = 'B' or 'b', DLAMCH := base
|
|
*> = 'P' or 'p', DLAMCH := eps*base
|
|
*> = 'N' or 'n', DLAMCH := t
|
|
*> = 'R' or 'r', DLAMCH := rnd
|
|
*> = 'M' or 'm', DLAMCH := emin
|
|
*> = 'U' or 'u', DLAMCH := rmin
|
|
*> = 'L' or 'l', DLAMCH := emax
|
|
*> = 'O' or 'o', DLAMCH := rmax
|
|
*> where
|
|
*> eps = relative machine precision
|
|
*> sfmin = safe minimum, such that 1/sfmin does not overflow
|
|
*> base = base of the machine
|
|
*> prec = eps*base
|
|
*> t = number of (base) digits in the mantissa
|
|
*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise
|
|
*> emin = minimum exponent before (gradual) underflow
|
|
*> rmin = underflow threshold - base**(emin-1)
|
|
*> emax = largest exponent before overflow
|
|
*> rmax = overflow threshold - (base**emax)*(1-eps)
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date November 2015
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
* =====================================================================
|
|
DOUBLE PRECISION FUNCTION DLAMCH( CMACH )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.6.0) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2015
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER CMACH
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE, ZERO
|
|
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT,
|
|
$ MINEXPONENT, RADIX, TINY
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
*
|
|
* Assume rounding, not chopping. Always.
|
|
*
|
|
RND = ONE
|
|
*
|
|
IF( ONE.EQ.RND ) THEN
|
|
EPS = EPSILON(ZERO) * 0.5
|
|
ELSE
|
|
EPS = EPSILON(ZERO)
|
|
END IF
|
|
*
|
|
IF( LSAME( CMACH, 'E' ) ) THEN
|
|
RMACH = EPS
|
|
ELSE IF( LSAME( CMACH, 'S' ) ) THEN
|
|
SFMIN = TINY(ZERO)
|
|
SMALL = ONE / HUGE(ZERO)
|
|
IF( SMALL.GE.SFMIN ) THEN
|
|
*
|
|
* Use SMALL plus a bit, to avoid the possibility of rounding
|
|
* causing overflow when computing 1/sfmin.
|
|
*
|
|
SFMIN = SMALL*( ONE+EPS )
|
|
END IF
|
|
RMACH = SFMIN
|
|
ELSE IF( LSAME( CMACH, 'B' ) ) THEN
|
|
RMACH = RADIX(ZERO)
|
|
ELSE IF( LSAME( CMACH, 'P' ) ) THEN
|
|
RMACH = EPS * RADIX(ZERO)
|
|
ELSE IF( LSAME( CMACH, 'N' ) ) THEN
|
|
RMACH = DIGITS(ZERO)
|
|
ELSE IF( LSAME( CMACH, 'R' ) ) THEN
|
|
RMACH = RND
|
|
ELSE IF( LSAME( CMACH, 'M' ) ) THEN
|
|
RMACH = MINEXPONENT(ZERO)
|
|
ELSE IF( LSAME( CMACH, 'U' ) ) THEN
|
|
RMACH = tiny(zero)
|
|
ELSE IF( LSAME( CMACH, 'L' ) ) THEN
|
|
RMACH = MAXEXPONENT(ZERO)
|
|
ELSE IF( LSAME( CMACH, 'O' ) ) THEN
|
|
RMACH = HUGE(ZERO)
|
|
ELSE
|
|
RMACH = ZERO
|
|
END IF
|
|
*
|
|
DLAMCH = RMACH
|
|
RETURN
|
|
*
|
|
* End of DLAMCH
|
|
*
|
|
END
|
|
************************************************************************
|
|
*> \brief \b DLAMC3
|
|
*> \details
|
|
*> \b Purpose:
|
|
*> \verbatim
|
|
*> DLAMC3 is intended to force A and B to be stored prior to doing
|
|
*> the addition of A and B , for use in situations where optimizers
|
|
*> might hold one of these in a register.
|
|
*> \endverbatim
|
|
*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..
|
|
*> \date November 2015
|
|
*> \ingroup auxOTHERauxiliary
|
|
*>
|
|
*> \param[in] A
|
|
*> \verbatim
|
|
*> A is a DOUBLE PRECISION
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] B
|
|
*> \verbatim
|
|
*> B is a DOUBLE PRECISION
|
|
*> The values A and B.
|
|
*> \endverbatim
|
|
*>
|
|
DOUBLE PRECISION FUNCTION DLAMC3( A, B )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.6.0) --
|
|
* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
|
|
* November 2010
|
|
*
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION A, B
|
|
* ..
|
|
* =====================================================================
|
|
*
|
|
* .. Executable Statements ..
|
|
*
|
|
DLAMC3 = A + B
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DLAMC3
|
|
*
|
|
END
|
|
*
|
|
************************************************************************
|
|
*> \brief \b IEEECK
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
*> \htmlonly
|
|
*> Download IEEECK + dependencies
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ieeeck.f">
|
|
*> [TGZ]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ieeeck.f">
|
|
*> [ZIP]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ieeeck.f">
|
|
*> [TXT]</a>
|
|
*> \endhtmlonly
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* INTEGER ISPEC
|
|
* REAL ONE, ZERO
|
|
* ..
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> IEEECK is called from the ILAENV to verify that Infinity and
|
|
*> possibly NaN arithmetic is safe (i.e. will not trap).
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] ISPEC
|
|
*> \verbatim
|
|
*> ISPEC is INTEGER
|
|
*> Specifies whether to test just for inifinity arithmetic
|
|
*> or whether to test for infinity and NaN arithmetic.
|
|
*> = 0: Verify infinity arithmetic only.
|
|
*> = 1: Verify infinity and NaN arithmetic.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] ZERO
|
|
*> \verbatim
|
|
*> ZERO is REAL
|
|
*> Must contain the value 0.0
|
|
*> This is passed to prevent the compiler from optimizing
|
|
*> away this code.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] ONE
|
|
*> \verbatim
|
|
*> ONE is REAL
|
|
*> Must contain the value 1.0
|
|
*> This is passed to prevent the compiler from optimizing
|
|
*> away this code.
|
|
*>
|
|
*> RETURN VALUE: INTEGER
|
|
*> = 0: Arithmetic failed to produce the correct answers
|
|
*> = 1: Arithmetic produced the correct answers
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date November 2011
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
* =====================================================================
|
|
INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.4.0) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2011
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER ISPEC
|
|
REAL ONE, ZERO
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Local Scalars ..
|
|
REAL NAN1, NAN2, NAN3, NAN4, NAN5, NAN6, NEGINF,
|
|
$ NEGZRO, NEWZRO, POSINF
|
|
* ..
|
|
* .. Executable Statements ..
|
|
IEEECK = 1
|
|
*
|
|
POSINF = ONE / ZERO
|
|
IF( POSINF.LE.ONE ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
NEGINF = -ONE / ZERO
|
|
IF( NEGINF.GE.ZERO ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
NEGZRO = ONE / ( NEGINF+ONE )
|
|
IF( NEGZRO.NE.ZERO ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
NEGINF = ONE / NEGZRO
|
|
IF( NEGINF.GE.ZERO ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
NEWZRO = NEGZRO + ZERO
|
|
IF( NEWZRO.NE.ZERO ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
POSINF = ONE / NEWZRO
|
|
IF( POSINF.LE.ONE ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
NEGINF = NEGINF*POSINF
|
|
IF( NEGINF.GE.ZERO ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
POSINF = POSINF*POSINF
|
|
IF( POSINF.LE.ONE ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
*
|
|
*
|
|
*
|
|
* Return if we were only asked to check infinity arithmetic
|
|
*
|
|
IF( ISPEC.EQ.0 )
|
|
$ RETURN
|
|
*
|
|
NAN1 = POSINF + NEGINF
|
|
*
|
|
NAN2 = POSINF / NEGINF
|
|
*
|
|
NAN3 = POSINF / POSINF
|
|
*
|
|
NAN4 = POSINF*ZERO
|
|
*
|
|
NAN5 = NEGINF*NEGZRO
|
|
*
|
|
NAN6 = NAN5*ZERO
|
|
*
|
|
IF( NAN1.EQ.NAN1 ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( NAN2.EQ.NAN2 ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( NAN3.EQ.NAN3 ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( NAN4.EQ.NAN4 ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( NAN5.EQ.NAN5 ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( NAN6.EQ.NAN6 ) THEN
|
|
IEEECK = 0
|
|
RETURN
|
|
END IF
|
|
*
|
|
RETURN
|
|
END
|
|
*> \brief \b ILADLC scans a matrix for its last non-zero column.
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
*> \htmlonly
|
|
*> Download ILADLC + dependencies
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/iladlc.f">
|
|
*> [TGZ]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/iladlc.f">
|
|
*> [ZIP]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/iladlc.f">
|
|
*> [TXT]</a>
|
|
*> \endhtmlonly
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* INTEGER FUNCTION ILADLC( M, N, A, LDA )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* INTEGER M, N, LDA
|
|
* ..
|
|
* .. Array Arguments ..
|
|
* DOUBLE PRECISION A( LDA, * )
|
|
* ..
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> ILADLC scans A for its last non-zero column.
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] M
|
|
*> \verbatim
|
|
*> M is INTEGER
|
|
*> The number of rows of the matrix A.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N
|
|
*> \verbatim
|
|
*> N is INTEGER
|
|
*> The number of columns of the matrix A.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] A
|
|
*> \verbatim
|
|
*> A is DOUBLE PRECISION array, dimension (LDA,N)
|
|
*> The m by n matrix A.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] LDA
|
|
*> \verbatim
|
|
*> LDA is INTEGER
|
|
*> The leading dimension of the array A. LDA >= max(1,M).
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date September 2012
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
* =====================================================================
|
|
INTEGER FUNCTION ILADLC( M, N, A, LDA )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.4.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* September 2012
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER M, N, LDA
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * )
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER ( ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Quick test for the common case where one corner is non-zero.
|
|
IF( N.EQ.0 ) THEN
|
|
ILADLC = N
|
|
ELSE IF( A(1, N).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
|
|
ILADLC = N
|
|
ELSE
|
|
* Now scan each column from the end, returning with the first non-zero.
|
|
DO ILADLC = N, 1, -1
|
|
DO I = 1, M
|
|
IF( A(I, ILADLC).NE.ZERO ) RETURN
|
|
END DO
|
|
END DO
|
|
END IF
|
|
RETURN
|
|
END
|
|
*> \brief \b ILADLR scans a matrix for its last non-zero row.
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
*> \htmlonly
|
|
*> Download ILADLR + dependencies
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/iladlr.f">
|
|
*> [TGZ]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/iladlr.f">
|
|
*> [ZIP]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/iladlr.f">
|
|
*> [TXT]</a>
|
|
*> \endhtmlonly
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* INTEGER FUNCTION ILADLR( M, N, A, LDA )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* INTEGER M, N, LDA
|
|
* ..
|
|
* .. Array Arguments ..
|
|
* DOUBLE PRECISION A( LDA, * )
|
|
* ..
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> ILADLR scans A for its last non-zero row.
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] M
|
|
*> \verbatim
|
|
*> M is INTEGER
|
|
*> The number of rows of the matrix A.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N
|
|
*> \verbatim
|
|
*> N is INTEGER
|
|
*> The number of columns of the matrix A.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] A
|
|
*> \verbatim
|
|
*> A is DOUBLE PRECISION array, dimension (LDA,N)
|
|
*> The m by n matrix A.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] LDA
|
|
*> \verbatim
|
|
*> LDA is INTEGER
|
|
*> The leading dimension of the array A. LDA >= max(1,M).
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date September 2012
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
* =====================================================================
|
|
INTEGER FUNCTION ILADLR( M, N, A, LDA )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.4.2) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* September 2012
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER M, N, LDA
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A( LDA, * )
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER ( ZERO = 0.0D+0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER I, J
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Quick test for the common case where one corner is non-zero.
|
|
IF( M.EQ.0 ) THEN
|
|
ILADLR = M
|
|
ELSE IF( A(M, 1).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN
|
|
ILADLR = M
|
|
ELSE
|
|
* Scan up each column tracking the last zero row seen.
|
|
ILADLR = 0
|
|
DO J = 1, N
|
|
I=M
|
|
DO WHILE((A(MAX(I,1),J).EQ.ZERO).AND.(I.GE.1))
|
|
I=I-1
|
|
ENDDO
|
|
ILADLR = MAX( ILADLR, I )
|
|
END DO
|
|
END IF
|
|
RETURN
|
|
END
|
|
*> \brief \b ILAENV
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
*> \htmlonly
|
|
*> Download ILAENV + dependencies
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ilaenv.f">
|
|
*> [TGZ]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ilaenv.f">
|
|
*> [ZIP]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ilaenv.f">
|
|
*> [TXT]</a>
|
|
*> \endhtmlonly
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* CHARACTER*( * ) NAME, OPTS
|
|
* INTEGER ISPEC, N1, N2, N3, N4
|
|
* ..
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> ILAENV is called from the LAPACK routines to choose problem-dependent
|
|
*> parameters for the local environment. See ISPEC for a description of
|
|
*> the parameters.
|
|
*>
|
|
*> ILAENV returns an INTEGER
|
|
*> if ILAENV >= 0: ILAENV returns the value of the parameter specified by ISPEC
|
|
*> if ILAENV < 0: if ILAENV = -k, the k-th argument had an illegal value.
|
|
*>
|
|
*> This version provides a set of parameters which should give good,
|
|
*> but not optimal, performance on many of the currently available
|
|
*> computers. Users are encouraged to modify this subroutine to set
|
|
*> the tuning parameters for their particular machine using the option
|
|
*> and problem size information in the arguments.
|
|
*>
|
|
*> This routine will not function correctly if it is converted to all
|
|
*> lower case. Converting it to all upper case is allowed.
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] ISPEC
|
|
*> \verbatim
|
|
*> ISPEC is INTEGER
|
|
*> Specifies the parameter to be returned as the value of
|
|
*> ILAENV.
|
|
*> = 1: the optimal blocksize; if this value is 1, an unblocked
|
|
*> algorithm will give the best performance.
|
|
*> = 2: the minimum block size for which the block routine
|
|
*> should be used; if the usable block size is less than
|
|
*> this value, an unblocked routine should be used.
|
|
*> = 3: the crossover point (in a block routine, for N less
|
|
*> than this value, an unblocked routine should be used)
|
|
*> = 4: the number of shifts, used in the nonsymmetric
|
|
*> eigenvalue routines (DEPRECATED)
|
|
*> = 5: the minimum column dimension for blocking to be used;
|
|
*> rectangular blocks must have dimension at least k by m,
|
|
*> where k is given by ILAENV(2,...) and m by ILAENV(5,...)
|
|
*> = 6: the crossover point for the SVD (when reducing an m by n
|
|
*> matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds
|
|
*> this value, a QR factorization is used first to reduce
|
|
*> the matrix to a triangular form.)
|
|
*> = 7: the number of processors
|
|
*> = 8: the crossover point for the multishift QR method
|
|
*> for nonsymmetric eigenvalue problems (DEPRECATED)
|
|
*> = 9: maximum size of the subproblems at the bottom of the
|
|
*> computation tree in the divide-and-conquer algorithm
|
|
*> (used by xGELSD and xGESDD)
|
|
*> =10: ieee NaN arithmetic can be trusted not to trap
|
|
*> =11: infinity arithmetic can be trusted not to trap
|
|
*> 12 <= ISPEC <= 16:
|
|
*> xHSEQR or related subroutines,
|
|
*> see IPARMQ for detailed explanation
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] NAME
|
|
*> \verbatim
|
|
*> NAME is CHARACTER*(*)
|
|
*> The name of the calling subroutine, in either upper case or
|
|
*> lower case.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] OPTS
|
|
*> \verbatim
|
|
*> OPTS is CHARACTER*(*)
|
|
*> The character options to the subroutine NAME, concatenated
|
|
*> into a single character string. For example, UPLO = 'U',
|
|
*> TRANS = 'T', and DIAG = 'N' for a triangular routine would
|
|
*> be specified as OPTS = 'UTN'.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N1
|
|
*> \verbatim
|
|
*> N1 is INTEGER
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N2
|
|
*> \verbatim
|
|
*> N2 is INTEGER
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N3
|
|
*> \verbatim
|
|
*> N3 is INTEGER
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N4
|
|
*> \verbatim
|
|
*> N4 is INTEGER
|
|
*> Problem dimensions for the subroutine NAME; these may not all
|
|
*> be required.
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date June 2016
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
*> \par Further Details:
|
|
* =====================
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> The following conventions have been used when calling ILAENV from the
|
|
*> LAPACK routines:
|
|
*> 1) OPTS is a concatenation of all of the character options to
|
|
*> subroutine NAME, in the same order that they appear in the
|
|
*> argument list for NAME, even if they are not used in determining
|
|
*> the value of the parameter specified by ISPEC.
|
|
*> 2) The problem dimensions N1, N2, N3, N4 are specified in the order
|
|
*> that they appear in the argument list for NAME. N1 is used
|
|
*> first, N2 second, and so on, and unused problem dimensions are
|
|
*> passed a value of -1.
|
|
*> 3) The parameter value returned by ILAENV is checked for validity in
|
|
*> the calling subroutine. For example, ILAENV is used to retrieve
|
|
*> the optimal blocksize for STRTRI as follows:
|
|
*>
|
|
*> NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 )
|
|
*> IF( NB.LE.1 ) NB = MAX( 1, N )
|
|
*> \endverbatim
|
|
*>
|
|
* =====================================================================
|
|
INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.6.1) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* June 2016
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER*( * ) NAME, OPTS
|
|
INTEGER ISPEC, N1, N2, N3, N4
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Local Scalars ..
|
|
INTEGER I, IC, IZ, NB, NBMIN, NX
|
|
LOGICAL CNAME, SNAME
|
|
CHARACTER C1*1, C2*2, C4*2, C3*3, SUBNAM*6
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC CHAR, ICHAR, INT, MIN, REAL
|
|
* ..
|
|
* .. External Functions ..
|
|
INTEGER IEEECK, IPARMQ
|
|
EXTERNAL IEEECK, IPARMQ
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
GO TO ( 10, 10, 10, 80, 90, 100, 110, 120,
|
|
$ 130, 140, 150, 160, 160, 160, 160, 160 )ISPEC
|
|
*
|
|
* Invalid value for ISPEC
|
|
*
|
|
ILAENV = -1
|
|
RETURN
|
|
*
|
|
10 CONTINUE
|
|
*
|
|
* Convert NAME to upper case if the first character is lower case.
|
|
*
|
|
ILAENV = 1
|
|
SUBNAM = NAME
|
|
IC = ICHAR( SUBNAM( 1: 1 ) )
|
|
IZ = ICHAR( 'Z' )
|
|
IF( IZ.EQ.90 .OR. IZ.EQ.122 ) THEN
|
|
*
|
|
* ASCII character set
|
|
*
|
|
IF( IC.GE.97 .AND. IC.LE.122 ) THEN
|
|
SUBNAM( 1: 1 ) = CHAR( IC-32 )
|
|
DO 20 I = 2, 6
|
|
IC = ICHAR( SUBNAM( I: I ) )
|
|
IF( IC.GE.97 .AND. IC.LE.122 )
|
|
$ SUBNAM( I: I ) = CHAR( IC-32 )
|
|
20 CONTINUE
|
|
END IF
|
|
*
|
|
ELSE IF( IZ.EQ.233 .OR. IZ.EQ.169 ) THEN
|
|
*
|
|
* EBCDIC character set
|
|
*
|
|
IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.
|
|
$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.
|
|
$ ( IC.GE.162 .AND. IC.LE.169 ) ) THEN
|
|
SUBNAM( 1: 1 ) = CHAR( IC+64 )
|
|
DO 30 I = 2, 6
|
|
IC = ICHAR( SUBNAM( I: I ) )
|
|
IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.
|
|
$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.
|
|
$ ( IC.GE.162 .AND. IC.LE.169 ) )SUBNAM( I:
|
|
$ I ) = CHAR( IC+64 )
|
|
30 CONTINUE
|
|
END IF
|
|
*
|
|
ELSE IF( IZ.EQ.218 .OR. IZ.EQ.250 ) THEN
|
|
*
|
|
* Prime machines: ASCII+128
|
|
*
|
|
IF( IC.GE.225 .AND. IC.LE.250 ) THEN
|
|
SUBNAM( 1: 1 ) = CHAR( IC-32 )
|
|
DO 40 I = 2, 6
|
|
IC = ICHAR( SUBNAM( I: I ) )
|
|
IF( IC.GE.225 .AND. IC.LE.250 )
|
|
$ SUBNAM( I: I ) = CHAR( IC-32 )
|
|
40 CONTINUE
|
|
END IF
|
|
END IF
|
|
*
|
|
C1 = SUBNAM( 1: 1 )
|
|
SNAME = C1.EQ.'S' .OR. C1.EQ.'D'
|
|
CNAME = C1.EQ.'C' .OR. C1.EQ.'Z'
|
|
IF( .NOT.( CNAME .OR. SNAME ) )
|
|
$ RETURN
|
|
C2 = SUBNAM( 2: 3 )
|
|
C3 = SUBNAM( 4: 6 )
|
|
C4 = C3( 2: 3 )
|
|
*
|
|
GO TO ( 50, 60, 70 )ISPEC
|
|
*
|
|
50 CONTINUE
|
|
*
|
|
* ISPEC = 1: block size
|
|
*
|
|
* In these examples, separate code is provided for setting NB for
|
|
* real and complex. We assume that NB will take the same value in
|
|
* single or double precision.
|
|
*
|
|
NB = 1
|
|
*
|
|
IF( C2.EQ.'GE' ) THEN
|
|
IF( C3.EQ.'TRF' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 64
|
|
ELSE
|
|
NB = 64
|
|
END IF
|
|
ELSE IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR.
|
|
$ C3.EQ.'QLF' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 32
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
ELSE IF( C3.EQ.'HRD' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 32
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
ELSE IF( C3.EQ.'BRD' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 32
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
ELSE IF( C3.EQ.'TRI' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 64
|
|
ELSE
|
|
NB = 64
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'PO' ) THEN
|
|
IF( C3.EQ.'TRF' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 64
|
|
ELSE
|
|
NB = 64
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'SY' ) THEN
|
|
IF( C3.EQ.'TRF' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 64
|
|
ELSE
|
|
NB = 64
|
|
END IF
|
|
ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN
|
|
NB = 32
|
|
ELSE IF( SNAME .AND. C3.EQ.'GST' ) THEN
|
|
NB = 64
|
|
END IF
|
|
ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN
|
|
IF( C3.EQ.'TRF' ) THEN
|
|
NB = 64
|
|
ELSE IF( C3.EQ.'TRD' ) THEN
|
|
NB = 32
|
|
ELSE IF( C3.EQ.'GST' ) THEN
|
|
NB = 64
|
|
END IF
|
|
ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN
|
|
IF( C3( 1: 1 ).EQ.'G' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NB = 32
|
|
END IF
|
|
ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NB = 32
|
|
END IF
|
|
END IF
|
|
ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN
|
|
IF( C3( 1: 1 ).EQ.'G' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NB = 32
|
|
END IF
|
|
ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NB = 32
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'GB' ) THEN
|
|
IF( C3.EQ.'TRF' ) THEN
|
|
IF( SNAME ) THEN
|
|
IF( N4.LE.64 ) THEN
|
|
NB = 1
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
ELSE
|
|
IF( N4.LE.64 ) THEN
|
|
NB = 1
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'PB' ) THEN
|
|
IF( C3.EQ.'TRF' ) THEN
|
|
IF( SNAME ) THEN
|
|
IF( N2.LE.64 ) THEN
|
|
NB = 1
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
ELSE
|
|
IF( N2.LE.64 ) THEN
|
|
NB = 1
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'TR' ) THEN
|
|
IF( C3.EQ.'TRI' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 64
|
|
ELSE
|
|
NB = 64
|
|
END IF
|
|
ELSE IF ( C3.EQ.'EVC' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 64
|
|
ELSE
|
|
NB = 64
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'LA' ) THEN
|
|
IF( C3.EQ.'UUM' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 64
|
|
ELSE
|
|
NB = 64
|
|
END IF
|
|
END IF
|
|
ELSE IF( SNAME .AND. C2.EQ.'ST' ) THEN
|
|
IF( C3.EQ.'EBZ' ) THEN
|
|
NB = 1
|
|
END IF
|
|
ELSE IF( C2.EQ.'GG' ) THEN
|
|
NB = 32
|
|
IF( C3.EQ.'HD3' ) THEN
|
|
IF( SNAME ) THEN
|
|
NB = 32
|
|
ELSE
|
|
NB = 32
|
|
END IF
|
|
END IF
|
|
END IF
|
|
ILAENV = NB
|
|
RETURN
|
|
*
|
|
60 CONTINUE
|
|
*
|
|
* ISPEC = 2: minimum block size
|
|
*
|
|
NBMIN = 2
|
|
IF( C2.EQ.'GE' ) THEN
|
|
IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ.
|
|
$ 'QLF' ) THEN
|
|
IF( SNAME ) THEN
|
|
NBMIN = 2
|
|
ELSE
|
|
NBMIN = 2
|
|
END IF
|
|
ELSE IF( C3.EQ.'HRD' ) THEN
|
|
IF( SNAME ) THEN
|
|
NBMIN = 2
|
|
ELSE
|
|
NBMIN = 2
|
|
END IF
|
|
ELSE IF( C3.EQ.'BRD' ) THEN
|
|
IF( SNAME ) THEN
|
|
NBMIN = 2
|
|
ELSE
|
|
NBMIN = 2
|
|
END IF
|
|
ELSE IF( C3.EQ.'TRI' ) THEN
|
|
IF( SNAME ) THEN
|
|
NBMIN = 2
|
|
ELSE
|
|
NBMIN = 2
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'SY' ) THEN
|
|
IF( C3.EQ.'TRF' ) THEN
|
|
IF( SNAME ) THEN
|
|
NBMIN = 8
|
|
ELSE
|
|
NBMIN = 8
|
|
END IF
|
|
ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN
|
|
NBMIN = 2
|
|
END IF
|
|
ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN
|
|
IF( C3.EQ.'TRD' ) THEN
|
|
NBMIN = 2
|
|
END IF
|
|
ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN
|
|
IF( C3( 1: 1 ).EQ.'G' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NBMIN = 2
|
|
END IF
|
|
ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NBMIN = 2
|
|
END IF
|
|
END IF
|
|
ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN
|
|
IF( C3( 1: 1 ).EQ.'G' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NBMIN = 2
|
|
END IF
|
|
ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NBMIN = 2
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'GG' ) THEN
|
|
NBMIN = 2
|
|
IF( C3.EQ.'HD3' ) THEN
|
|
NBMIN = 2
|
|
END IF
|
|
END IF
|
|
ILAENV = NBMIN
|
|
RETURN
|
|
*
|
|
70 CONTINUE
|
|
*
|
|
* ISPEC = 3: crossover point
|
|
*
|
|
NX = 0
|
|
IF( C2.EQ.'GE' ) THEN
|
|
IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ.
|
|
$ 'QLF' ) THEN
|
|
IF( SNAME ) THEN
|
|
NX = 128
|
|
ELSE
|
|
NX = 128
|
|
END IF
|
|
ELSE IF( C3.EQ.'HRD' ) THEN
|
|
IF( SNAME ) THEN
|
|
NX = 128
|
|
ELSE
|
|
NX = 128
|
|
END IF
|
|
ELSE IF( C3.EQ.'BRD' ) THEN
|
|
IF( SNAME ) THEN
|
|
NX = 128
|
|
ELSE
|
|
NX = 128
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'SY' ) THEN
|
|
IF( SNAME .AND. C3.EQ.'TRD' ) THEN
|
|
NX = 32
|
|
END IF
|
|
ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN
|
|
IF( C3.EQ.'TRD' ) THEN
|
|
NX = 32
|
|
END IF
|
|
ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN
|
|
IF( C3( 1: 1 ).EQ.'G' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NX = 128
|
|
END IF
|
|
END IF
|
|
ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN
|
|
IF( C3( 1: 1 ).EQ.'G' ) THEN
|
|
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ.
|
|
$ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' )
|
|
$ THEN
|
|
NX = 128
|
|
END IF
|
|
END IF
|
|
ELSE IF( C2.EQ.'GG' ) THEN
|
|
NX = 128
|
|
IF( C3.EQ.'HD3' ) THEN
|
|
NX = 128
|
|
END IF
|
|
END IF
|
|
ILAENV = NX
|
|
RETURN
|
|
*
|
|
80 CONTINUE
|
|
*
|
|
* ISPEC = 4: number of shifts (used by xHSEQR)
|
|
*
|
|
ILAENV = 6
|
|
RETURN
|
|
*
|
|
90 CONTINUE
|
|
*
|
|
* ISPEC = 5: minimum column dimension (not used)
|
|
*
|
|
ILAENV = 2
|
|
RETURN
|
|
*
|
|
100 CONTINUE
|
|
*
|
|
* ISPEC = 6: crossover point for SVD (used by xGELSS and xGESVD)
|
|
*
|
|
ILAENV = INT( REAL( MIN( N1, N2 ) )*1.6E0 )
|
|
RETURN
|
|
*
|
|
110 CONTINUE
|
|
*
|
|
* ISPEC = 7: number of processors (not used)
|
|
*
|
|
ILAENV = 1
|
|
RETURN
|
|
*
|
|
120 CONTINUE
|
|
*
|
|
* ISPEC = 8: crossover point for multishift (used by xHSEQR)
|
|
*
|
|
ILAENV = 50
|
|
RETURN
|
|
*
|
|
130 CONTINUE
|
|
*
|
|
* ISPEC = 9: maximum size of the subproblems at the bottom of the
|
|
* computation tree in the divide-and-conquer algorithm
|
|
* (used by xGELSD and xGESDD)
|
|
*
|
|
ILAENV = 25
|
|
RETURN
|
|
*
|
|
140 CONTINUE
|
|
*
|
|
* ISPEC = 10: ieee NaN arithmetic can be trusted not to trap
|
|
*
|
|
* ILAENV = 0
|
|
ILAENV = 1
|
|
IF( ILAENV.EQ.1 ) THEN
|
|
ILAENV = IEEECK( 1, 0.0, 1.0 )
|
|
END IF
|
|
RETURN
|
|
*
|
|
150 CONTINUE
|
|
*
|
|
* ISPEC = 11: infinity arithmetic can be trusted not to trap
|
|
*
|
|
* ILAENV = 0
|
|
ILAENV = 1
|
|
IF( ILAENV.EQ.1 ) THEN
|
|
ILAENV = IEEECK( 0, 0.0, 1.0 )
|
|
END IF
|
|
RETURN
|
|
*
|
|
160 CONTINUE
|
|
*
|
|
* 12 <= ISPEC <= 16: xHSEQR or related subroutines.
|
|
*
|
|
ILAENV = IPARMQ( ISPEC, NAME, OPTS, N1, N2, N3, N4 )
|
|
RETURN
|
|
*
|
|
* End of ILAENV
|
|
*
|
|
END
|
|
*> \brief \b IPARMQ
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
*> \htmlonly
|
|
*> Download IPARMQ + dependencies
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/iparmq.f">
|
|
*> [TGZ]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/iparmq.f">
|
|
*> [ZIP]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/iparmq.f">
|
|
*> [TXT]</a>
|
|
*> \endhtmlonly
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* INTEGER IHI, ILO, ISPEC, LWORK, N
|
|
* CHARACTER NAME*( * ), OPTS*( * )
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> This program sets problem and machine dependent parameters
|
|
*> useful for xHSEQR and related subroutines for eigenvalue
|
|
*> problems. It is called whenever
|
|
*> IPARMQ is called with 12 <= ISPEC <= 16
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] ISPEC
|
|
*> \verbatim
|
|
*> ISPEC is integer scalar
|
|
*> ISPEC specifies which tunable parameter IPARMQ should
|
|
*> return.
|
|
*>
|
|
*> ISPEC=12: (INMIN) Matrices of order nmin or less
|
|
*> are sent directly to xLAHQR, the implicit
|
|
*> double shift QR algorithm. NMIN must be
|
|
*> at least 11.
|
|
*>
|
|
*> ISPEC=13: (INWIN) Size of the deflation window.
|
|
*> This is best set greater than or equal to
|
|
*> the number of simultaneous shifts NS.
|
|
*> Larger matrices benefit from larger deflation
|
|
*> windows.
|
|
*>
|
|
*> ISPEC=14: (INIBL) Determines when to stop nibbling and
|
|
*> invest in an (expensive) multi-shift QR sweep.
|
|
*> If the aggressive early deflation subroutine
|
|
*> finds LD converged eigenvalues from an order
|
|
*> NW deflation window and LD.GT.(NW*NIBBLE)/100,
|
|
*> then the next QR sweep is skipped and early
|
|
*> deflation is applied immediately to the
|
|
*> remaining active diagonal block. Setting
|
|
*> IPARMQ(ISPEC=14) = 0 causes TTQRE to skip a
|
|
*> multi-shift QR sweep whenever early deflation
|
|
*> finds a converged eigenvalue. Setting
|
|
*> IPARMQ(ISPEC=14) greater than or equal to 100
|
|
*> prevents TTQRE from skipping a multi-shift
|
|
*> QR sweep.
|
|
*>
|
|
*> ISPEC=15: (NSHFTS) The number of simultaneous shifts in
|
|
*> a multi-shift QR iteration.
|
|
*>
|
|
*> ISPEC=16: (IACC22) IPARMQ is set to 0, 1 or 2 with the
|
|
*> following meanings.
|
|
*> 0: During the multi-shift QR/QZ sweep,
|
|
*> blocked eigenvalue reordering, blocked
|
|
*> Hessenberg-triangular reduction,
|
|
*> reflections and/or rotations are not
|
|
*> accumulated when updating the
|
|
*> far-from-diagonal matrix entries.
|
|
*> 1: During the multi-shift QR/QZ sweep,
|
|
*> blocked eigenvalue reordering, blocked
|
|
*> Hessenberg-triangular reduction,
|
|
*> reflections and/or rotations are
|
|
*> accumulated, and matrix-matrix
|
|
*> multiplication is used to update the
|
|
*> far-from-diagonal matrix entries.
|
|
*> 2: During the multi-shift QR/QZ sweep,
|
|
*> blocked eigenvalue reordering, blocked
|
|
*> Hessenberg-triangular reduction,
|
|
*> reflections and/or rotations are
|
|
*> accumulated, and 2-by-2 block structure
|
|
*> is exploited during matrix-matrix
|
|
*> multiplies.
|
|
*> (If xTRMM is slower than xGEMM, then
|
|
*> IPARMQ(ISPEC=16)=1 may be more efficient than
|
|
*> IPARMQ(ISPEC=16)=2 despite the greater level of
|
|
*> arithmetic work implied by the latter choice.)
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] NAME
|
|
*> \verbatim
|
|
*> NAME is character string
|
|
*> Name of the calling subroutine
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] OPTS
|
|
*> \verbatim
|
|
*> OPTS is character string
|
|
*> This is a concatenation of the string arguments to
|
|
*> TTQRE.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N
|
|
*> \verbatim
|
|
*> N is integer scalar
|
|
*> N is the order of the Hessenberg matrix H.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] ILO
|
|
*> \verbatim
|
|
*> ILO is INTEGER
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] IHI
|
|
*> \verbatim
|
|
*> IHI is INTEGER
|
|
*> It is assumed that H is already upper triangular
|
|
*> in rows and columns 1:ILO-1 and IHI+1:N.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] LWORK
|
|
*> \verbatim
|
|
*> LWORK is integer scalar
|
|
*> The amount of workspace available.
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date November 2015
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
*> \par Further Details:
|
|
* =====================
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> Little is known about how best to choose these parameters.
|
|
*> It is possible to use different values of the parameters
|
|
*> for each of CHSEQR, DHSEQR, SHSEQR and ZHSEQR.
|
|
*>
|
|
*> It is probably best to choose different parameters for
|
|
*> different matrices and different parameters at different
|
|
*> times during the iteration, but this has not been
|
|
*> implemented --- yet.
|
|
*>
|
|
*>
|
|
*> The best choices of most of the parameters depend
|
|
*> in an ill-understood way on the relative execution
|
|
*> rate of xLAQR3 and xLAQR5 and on the nature of each
|
|
*> particular eigenvalue problem. Experiment may be the
|
|
*> only practical way to determine which choices are most
|
|
*> effective.
|
|
*>
|
|
*> Following is a list of default values supplied by IPARMQ.
|
|
*> These defaults may be adjusted in order to attain better
|
|
*> performance in any particular computational environment.
|
|
*>
|
|
*> IPARMQ(ISPEC=12) The xLAHQR vs xLAQR0 crossover point.
|
|
*> Default: 75. (Must be at least 11.)
|
|
*>
|
|
*> IPARMQ(ISPEC=13) Recommended deflation window size.
|
|
*> This depends on ILO, IHI and NS, the
|
|
*> number of simultaneous shifts returned
|
|
*> by IPARMQ(ISPEC=15). The default for
|
|
*> (IHI-ILO+1).LE.500 is NS. The default
|
|
*> for (IHI-ILO+1).GT.500 is 3*NS/2.
|
|
*>
|
|
*> IPARMQ(ISPEC=14) Nibble crossover point. Default: 14.
|
|
*>
|
|
*> IPARMQ(ISPEC=15) Number of simultaneous shifts, NS.
|
|
*> a multi-shift QR iteration.
|
|
*>
|
|
*> If IHI-ILO+1 is ...
|
|
*>
|
|
*> greater than ...but less ... the
|
|
*> or equal to ... than default is
|
|
*>
|
|
*> 0 30 NS = 2+
|
|
*> 30 60 NS = 4+
|
|
*> 60 150 NS = 10
|
|
*> 150 590 NS = **
|
|
*> 590 3000 NS = 64
|
|
*> 3000 6000 NS = 128
|
|
*> 6000 infinity NS = 256
|
|
*>
|
|
*> (+) By default matrices of this order are
|
|
*> passed to the implicit double shift routine
|
|
*> xLAHQR. See IPARMQ(ISPEC=12) above. These
|
|
*> values of NS are used only in case of a rare
|
|
*> xLAHQR failure.
|
|
*>
|
|
*> (**) The asterisks (**) indicate an ad-hoc
|
|
*> function increasing from 10 to 64.
|
|
*>
|
|
*> IPARMQ(ISPEC=16) Select structured matrix multiply.
|
|
*> (See ISPEC=16 above for details.)
|
|
*> Default: 3.
|
|
*> \endverbatim
|
|
*>
|
|
* =====================================================================
|
|
INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.6.0) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2015
|
|
*
|
|
* .. Scalar Arguments ..
|
|
INTEGER IHI, ILO, ISPEC, LWORK, N
|
|
CHARACTER NAME*( * ), OPTS*( * )
|
|
*
|
|
* ================================================================
|
|
* .. Parameters ..
|
|
INTEGER INMIN, INWIN, INIBL, ISHFTS, IACC22
|
|
PARAMETER ( INMIN = 12, INWIN = 13, INIBL = 14,
|
|
$ ISHFTS = 15, IACC22 = 16 )
|
|
INTEGER NMIN, K22MIN, KACMIN, NIBBLE, KNWSWP
|
|
PARAMETER ( NMIN = 75, K22MIN = 14, KACMIN = 14,
|
|
$ NIBBLE = 14, KNWSWP = 500 )
|
|
REAL TWO
|
|
PARAMETER ( TWO = 2.0 )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER NH, NS
|
|
INTEGER I, IC, IZ
|
|
CHARACTER SUBNAM*6
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC LOG, MAX, MOD, NINT, REAL
|
|
* ..
|
|
* .. Executable Statements ..
|
|
IF( ( ISPEC.EQ.ISHFTS ) .OR. ( ISPEC.EQ.INWIN ) .OR.
|
|
$ ( ISPEC.EQ.IACC22 ) ) THEN
|
|
*
|
|
* ==== Set the number simultaneous shifts ====
|
|
*
|
|
NH = IHI - ILO + 1
|
|
NS = 2
|
|
IF( NH.GE.30 )
|
|
$ NS = 4
|
|
IF( NH.GE.60 )
|
|
$ NS = 10
|
|
IF( NH.GE.150 )
|
|
$ NS = MAX( 10, NH / NINT( LOG( REAL( NH ) ) / LOG( TWO ) ) )
|
|
IF( NH.GE.590 )
|
|
$ NS = 64
|
|
IF( NH.GE.3000 )
|
|
$ NS = 128
|
|
IF( NH.GE.6000 )
|
|
$ NS = 256
|
|
NS = MAX( 2, NS-MOD( NS, 2 ) )
|
|
END IF
|
|
*
|
|
IF( ISPEC.EQ.INMIN ) THEN
|
|
*
|
|
*
|
|
* ===== Matrices of order smaller than NMIN get sent
|
|
* . to xLAHQR, the classic double shift algorithm.
|
|
* . This must be at least 11. ====
|
|
*
|
|
IPARMQ = NMIN
|
|
*
|
|
ELSE IF( ISPEC.EQ.INIBL ) THEN
|
|
*
|
|
* ==== INIBL: skip a multi-shift qr iteration and
|
|
* . whenever aggressive early deflation finds
|
|
* . at least (NIBBLE*(window size)/100) deflations. ====
|
|
*
|
|
IPARMQ = NIBBLE
|
|
*
|
|
ELSE IF( ISPEC.EQ.ISHFTS ) THEN
|
|
*
|
|
* ==== NSHFTS: The number of simultaneous shifts =====
|
|
*
|
|
IPARMQ = NS
|
|
*
|
|
ELSE IF( ISPEC.EQ.INWIN ) THEN
|
|
*
|
|
* ==== NW: deflation window size. ====
|
|
*
|
|
IF( NH.LE.KNWSWP ) THEN
|
|
IPARMQ = NS
|
|
ELSE
|
|
IPARMQ = 3*NS / 2
|
|
END IF
|
|
*
|
|
ELSE IF( ISPEC.EQ.IACC22 ) THEN
|
|
*
|
|
* ==== IACC22: Whether to accumulate reflections
|
|
* . before updating the far-from-diagonal elements
|
|
* . and whether to use 2-by-2 block structure while
|
|
* . doing it. A small amount of work could be saved
|
|
* . by making this choice dependent also upon the
|
|
* . NH=IHI-ILO+1.
|
|
*
|
|
*
|
|
* Convert NAME to upper case if the first character is lower case.
|
|
*
|
|
IPARMQ = 0
|
|
SUBNAM = NAME
|
|
IC = ICHAR( SUBNAM( 1: 1 ) )
|
|
IZ = ICHAR( 'Z' )
|
|
IF( IZ.EQ.90 .OR. IZ.EQ.122 ) THEN
|
|
*
|
|
* ASCII character set
|
|
*
|
|
IF( IC.GE.97 .AND. IC.LE.122 ) THEN
|
|
SUBNAM( 1: 1 ) = CHAR( IC-32 )
|
|
DO I = 2, 6
|
|
IC = ICHAR( SUBNAM( I: I ) )
|
|
IF( IC.GE.97 .AND. IC.LE.122 )
|
|
$ SUBNAM( I: I ) = CHAR( IC-32 )
|
|
END DO
|
|
END IF
|
|
*
|
|
ELSE IF( IZ.EQ.233 .OR. IZ.EQ.169 ) THEN
|
|
*
|
|
* EBCDIC character set
|
|
*
|
|
IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.
|
|
$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.
|
|
$ ( IC.GE.162 .AND. IC.LE.169 ) ) THEN
|
|
SUBNAM( 1: 1 ) = CHAR( IC+64 )
|
|
DO I = 2, 6
|
|
IC = ICHAR( SUBNAM( I: I ) )
|
|
IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.
|
|
$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.
|
|
$ ( IC.GE.162 .AND. IC.LE.169 ) )SUBNAM( I:
|
|
$ I ) = CHAR( IC+64 )
|
|
END DO
|
|
END IF
|
|
*
|
|
ELSE IF( IZ.EQ.218 .OR. IZ.EQ.250 ) THEN
|
|
*
|
|
* Prime machines: ASCII+128
|
|
*
|
|
IF( IC.GE.225 .AND. IC.LE.250 ) THEN
|
|
SUBNAM( 1: 1 ) = CHAR( IC-32 )
|
|
DO I = 2, 6
|
|
IC = ICHAR( SUBNAM( I: I ) )
|
|
IF( IC.GE.225 .AND. IC.LE.250 )
|
|
$ SUBNAM( I: I ) = CHAR( IC-32 )
|
|
END DO
|
|
END IF
|
|
END IF
|
|
*
|
|
IF( SUBNAM( 2:6 ).EQ.'GGHRD' .OR.
|
|
$ SUBNAM( 2:6 ).EQ.'GGHD3' ) THEN
|
|
IPARMQ = 1
|
|
IF( NH.GE.K22MIN )
|
|
$ IPARMQ = 2
|
|
ELSE IF ( SUBNAM( 4:6 ).EQ.'EXC' ) THEN
|
|
IF( NH.GE.KACMIN )
|
|
$ IPARMQ = 1
|
|
IF( NH.GE.K22MIN )
|
|
$ IPARMQ = 2
|
|
ELSE IF ( SUBNAM( 2:6 ).EQ.'HSEQR' .OR.
|
|
$ SUBNAM( 2:5 ).EQ.'LAQR' ) THEN
|
|
IF( NS.GE.KACMIN )
|
|
$ IPARMQ = 1
|
|
IF( NS.GE.K22MIN )
|
|
$ IPARMQ = 2
|
|
END IF
|
|
*
|
|
ELSE
|
|
* ===== invalid value of ispec =====
|
|
IPARMQ = -1
|
|
*
|
|
END IF
|
|
*
|
|
* ==== End of IPARMQ ====
|
|
*
|
|
END
|
|
*> \brief \b LSAME
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* LOGICAL FUNCTION LSAME( CA, CB )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* CHARACTER CA, CB
|
|
* ..
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> LSAME returns .TRUE. if CA is the same letter as CB regardless of
|
|
*> case.
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] CA
|
|
*> \verbatim
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] CB
|
|
*> \verbatim
|
|
*> CA and CB specify the single characters to be compared.
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date November 2011
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
* =====================================================================
|
|
LOGICAL FUNCTION LSAME( CA, CB )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.4.0) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2011
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER CA, CB
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ICHAR
|
|
* ..
|
|
* .. Local Scalars ..
|
|
INTEGER INTA, INTB, ZCODE
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test if the characters are equal
|
|
*
|
|
LSAME = CA.EQ.CB
|
|
IF( LSAME )
|
|
$ RETURN
|
|
*
|
|
* Now test for equivalence if both characters are alphabetic.
|
|
*
|
|
ZCODE = ICHAR( 'Z' )
|
|
*
|
|
* Use 'Z' rather than 'A' so that ASCII can be detected on Prime
|
|
* machines, on which ICHAR returns a value with bit 8 set.
|
|
* ICHAR('A') on Prime machines returns 193 which is the same as
|
|
* ICHAR('A') on an EBCDIC machine.
|
|
*
|
|
INTA = ICHAR( CA )
|
|
INTB = ICHAR( CB )
|
|
*
|
|
IF( ZCODE.EQ.90 .OR. ZCODE.EQ.122 ) THEN
|
|
*
|
|
* ASCII is assumed - ZCODE is the ASCII code of either lower or
|
|
* upper case 'Z'.
|
|
*
|
|
IF( INTA.GE.97 .AND. INTA.LE.122 ) INTA = INTA - 32
|
|
IF( INTB.GE.97 .AND. INTB.LE.122 ) INTB = INTB - 32
|
|
*
|
|
ELSE IF( ZCODE.EQ.233 .OR. ZCODE.EQ.169 ) THEN
|
|
*
|
|
* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or
|
|
* upper case 'Z'.
|
|
*
|
|
IF( INTA.GE.129 .AND. INTA.LE.137 .OR.
|
|
$ INTA.GE.145 .AND. INTA.LE.153 .OR.
|
|
$ INTA.GE.162 .AND. INTA.LE.169 ) INTA = INTA + 64
|
|
IF( INTB.GE.129 .AND. INTB.LE.137 .OR.
|
|
$ INTB.GE.145 .AND. INTB.LE.153 .OR.
|
|
$ INTB.GE.162 .AND. INTB.LE.169 ) INTB = INTB + 64
|
|
*
|
|
ELSE IF( ZCODE.EQ.218 .OR. ZCODE.EQ.250 ) THEN
|
|
*
|
|
* ASCII is assumed, on Prime machines - ZCODE is the ASCII code
|
|
* plus 128 of either lower or upper case 'Z'.
|
|
*
|
|
IF( INTA.GE.225 .AND. INTA.LE.250 ) INTA = INTA - 32
|
|
IF( INTB.GE.225 .AND. INTB.LE.250 ) INTB = INTB - 32
|
|
END IF
|
|
LSAME = INTA.EQ.INTB
|
|
*
|
|
* RETURN
|
|
*
|
|
* End of LSAME
|
|
*
|
|
END
|
|
*> \brief \b XERBLA
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
*> \htmlonly
|
|
*> Download XERBLA + dependencies
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/xerbla.f">
|
|
*> [TGZ]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/xerbla.f">
|
|
*> [ZIP]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/xerbla.f">
|
|
*> [TXT]</a>
|
|
*> \endhtmlonly
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* SUBROUTINE XERBLA( SRNAME, INFO )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* CHARACTER*(*) SRNAME
|
|
* INTEGER INFO
|
|
* ..
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> XERBLA is an error handler for the LAPACK routines.
|
|
*> It is called by an LAPACK routine if an input parameter has an
|
|
*> invalid value. A message is printed and execution stops.
|
|
*>
|
|
*> Installers may consider modifying the STOP statement in order to
|
|
*> call system-specific exception-handling facilities.
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] SRNAME
|
|
*> \verbatim
|
|
*> SRNAME is CHARACTER*(*)
|
|
*> The name of the routine which called XERBLA.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] INFO
|
|
*> \verbatim
|
|
*> INFO is INTEGER
|
|
*> The position of the invalid parameter in the parameter list
|
|
*> of the calling routine.
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date November 2011
|
|
*
|
|
*> \ingroup auxOTHERauxiliary
|
|
*
|
|
* =====================================================================
|
|
SUBROUTINE XERBLA( SRNAME, INFO )
|
|
*
|
|
* -- LAPACK auxiliary routine (version 3.4.0) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2011
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER*(*) SRNAME
|
|
INTEGER INFO
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC LEN_TRIM
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO
|
|
*
|
|
STOP
|
|
*
|
|
9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ',
|
|
$ 'an illegal value' )
|
|
*
|
|
* End of XERBLA
|
|
*
|
|
END
|
|
|
|
SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION DA
|
|
INTEGER INCX,INCY,N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION DX(*),DY(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DAXPY constant times a vector plus a vector.
|
|
* uses unrolled loops for increments equal to one.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* jack dongarra, linpack, 3/11/78.
|
|
* modified 12/3/93, array(1) declarations changed to array(*)
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Local Scalars ..
|
|
INTEGER I,IX,IY,M,MP1
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MOD
|
|
* ..
|
|
IF (N.LE.0) RETURN
|
|
IF (DA.EQ.0.0d0) RETURN
|
|
IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN
|
|
*
|
|
* code for both increments equal to 1
|
|
*
|
|
*
|
|
* clean-up loop
|
|
*
|
|
M = MOD(N,4)
|
|
IF (M.NE.0) THEN
|
|
DO I = 1,M
|
|
DY(I) = DY(I) + DA*DX(I)
|
|
END DO
|
|
END IF
|
|
IF (N.LT.4) RETURN
|
|
MP1 = M + 1
|
|
DO I = MP1,N,4
|
|
DY(I) = DY(I) + DA*DX(I)
|
|
DY(I+1) = DY(I+1) + DA*DX(I+1)
|
|
DY(I+2) = DY(I+2) + DA*DX(I+2)
|
|
DY(I+3) = DY(I+3) + DA*DX(I+3)
|
|
END DO
|
|
ELSE
|
|
*
|
|
* code for unequal increments or equal increments
|
|
* not equal to 1
|
|
*
|
|
IX = 1
|
|
IY = 1
|
|
IF (INCX.LT.0) IX = (-N+1)*INCX + 1
|
|
IF (INCY.LT.0) IY = (-N+1)*INCY + 1
|
|
DO I = 1,N
|
|
DY(IY) = DY(IY) + DA*DX(IX)
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
END DO
|
|
END IF
|
|
RETURN
|
|
END
|
|
SUBROUTINE DCOPY(N,DX,INCX,DY,INCY)
|
|
* .. Scalar Arguments ..
|
|
INTEGER INCX,INCY,N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION DX(*),DY(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DCOPY copies a vector, x, to a vector, y.
|
|
* uses unrolled loops for increments equal to one.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* jack dongarra, linpack, 3/11/78.
|
|
* modified 12/3/93, array(1) declarations changed to array(*)
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Local Scalars ..
|
|
INTEGER I,IX,IY,M,MP1
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MOD
|
|
* ..
|
|
IF (N.LE.0) RETURN
|
|
IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN
|
|
*
|
|
* code for both increments equal to 1
|
|
*
|
|
*
|
|
* clean-up loop
|
|
*
|
|
M = MOD(N,7)
|
|
IF (M.NE.0) THEN
|
|
DO I = 1,M
|
|
DY(I) = DX(I)
|
|
END DO
|
|
IF (N.LT.7) RETURN
|
|
END IF
|
|
MP1 = M + 1
|
|
DO I = MP1,N,7
|
|
DY(I) = DX(I)
|
|
DY(I+1) = DX(I+1)
|
|
DY(I+2) = DX(I+2)
|
|
DY(I+3) = DX(I+3)
|
|
DY(I+4) = DX(I+4)
|
|
DY(I+5) = DX(I+5)
|
|
DY(I+6) = DX(I+6)
|
|
END DO
|
|
ELSE
|
|
*
|
|
* code for unequal increments or equal increments
|
|
* not equal to 1
|
|
*
|
|
IX = 1
|
|
IY = 1
|
|
IF (INCX.LT.0) IX = (-N+1)*INCX + 1
|
|
IF (INCY.LT.0) IY = (-N+1)*INCY + 1
|
|
DO I = 1,N
|
|
DY(IY) = DX(IX)
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
END DO
|
|
END IF
|
|
RETURN
|
|
END
|
|
DOUBLE PRECISION FUNCTION DDOT(N,DX,INCX,DY,INCY)
|
|
* .. Scalar Arguments ..
|
|
INTEGER INCX,INCY,N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION DX(*),DY(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DDOT forms the dot product of two vectors.
|
|
* uses unrolled loops for increments equal to one.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* jack dongarra, linpack, 3/11/78.
|
|
* modified 12/3/93, array(1) declarations changed to array(*)
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION DTEMP
|
|
INTEGER I,IX,IY,M,MP1
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MOD
|
|
* ..
|
|
DDOT = 0.0d0
|
|
DTEMP = 0.0d0
|
|
IF (N.LE.0) RETURN
|
|
IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN
|
|
*
|
|
* code for both increments equal to 1
|
|
*
|
|
*
|
|
* clean-up loop
|
|
*
|
|
M = MOD(N,5)
|
|
IF (M.NE.0) THEN
|
|
DO I = 1,M
|
|
DTEMP = DTEMP + DX(I)*DY(I)
|
|
END DO
|
|
IF (N.LT.5) THEN
|
|
DDOT=DTEMP
|
|
RETURN
|
|
END IF
|
|
END IF
|
|
MP1 = M + 1
|
|
DO I = MP1,N,5
|
|
DTEMP = DTEMP + DX(I)*DY(I) + DX(I+1)*DY(I+1) +
|
|
$ DX(I+2)*DY(I+2) + DX(I+3)*DY(I+3) + DX(I+4)*DY(I+4)
|
|
END DO
|
|
ELSE
|
|
*
|
|
* code for unequal increments or equal increments
|
|
* not equal to 1
|
|
*
|
|
IX = 1
|
|
IY = 1
|
|
IF (INCX.LT.0) IX = (-N+1)*INCX + 1
|
|
IF (INCY.LT.0) IY = (-N+1)*INCY + 1
|
|
DO I = 1,N
|
|
DTEMP = DTEMP + DX(IX)*DY(IY)
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
END DO
|
|
END IF
|
|
DDOT = DTEMP
|
|
RETURN
|
|
END
|
|
SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION ALPHA,BETA
|
|
INTEGER K,LDA,LDB,LDC,M,N
|
|
CHARACTER TRANSA,TRANSB
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DGEMM performs one of the matrix-matrix operations
|
|
*
|
|
* C := alpha*op( A )*op( B ) + beta*C,
|
|
*
|
|
* where op( X ) is one of
|
|
*
|
|
* op( X ) = X or op( X ) = X**T,
|
|
*
|
|
* alpha and beta are scalars, and A, B and C are matrices, with op( A )
|
|
* an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* TRANSA - CHARACTER*1.
|
|
* On entry, TRANSA specifies the form of op( A ) to be used in
|
|
* the matrix multiplication as follows:
|
|
*
|
|
* TRANSA = 'N' or 'n', op( A ) = A.
|
|
*
|
|
* TRANSA = 'T' or 't', op( A ) = A**T.
|
|
*
|
|
* TRANSA = 'C' or 'c', op( A ) = A**T.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* TRANSB - CHARACTER*1.
|
|
* On entry, TRANSB specifies the form of op( B ) to be used in
|
|
* the matrix multiplication as follows:
|
|
*
|
|
* TRANSB = 'N' or 'n', op( B ) = B.
|
|
*
|
|
* TRANSB = 'T' or 't', op( B ) = B**T.
|
|
*
|
|
* TRANSB = 'C' or 'c', op( B ) = B**T.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* M - INTEGER.
|
|
* On entry, M specifies the number of rows of the matrix
|
|
* op( A ) and of the matrix C. M must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the number of columns of the matrix
|
|
* op( B ) and the number of columns of the matrix C. N must be
|
|
* at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* K - INTEGER.
|
|
* On entry, K specifies the number of columns of the matrix
|
|
* op( A ) and the number of rows of the matrix op( B ). K must
|
|
* be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* ALPHA - DOUBLE PRECISION.
|
|
* On entry, ALPHA specifies the scalar alpha.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is
|
|
* k when TRANSA = 'N' or 'n', and is m otherwise.
|
|
* Before entry with TRANSA = 'N' or 'n', the leading m by k
|
|
* part of the array A must contain the matrix A, otherwise
|
|
* the leading k by m part of the array A must contain the
|
|
* matrix A.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. When TRANSA = 'N' or 'n' then
|
|
* LDA must be at least max( 1, m ), otherwise LDA must be at
|
|
* least max( 1, k ).
|
|
* Unchanged on exit.
|
|
*
|
|
* B - DOUBLE PRECISION array of DIMENSION ( LDB, kb ), where kb is
|
|
* n when TRANSB = 'N' or 'n', and is k otherwise.
|
|
* Before entry with TRANSB = 'N' or 'n', the leading k by n
|
|
* part of the array B must contain the matrix B, otherwise
|
|
* the leading n by k part of the array B must contain the
|
|
* matrix B.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDB - INTEGER.
|
|
* On entry, LDB specifies the first dimension of B as declared
|
|
* in the calling (sub) program. When TRANSB = 'N' or 'n' then
|
|
* LDB must be at least max( 1, k ), otherwise LDB must be at
|
|
* least max( 1, n ).
|
|
* Unchanged on exit.
|
|
*
|
|
* BETA - DOUBLE PRECISION.
|
|
* On entry, BETA specifies the scalar beta. When BETA is
|
|
* supplied as zero then C need not be set on input.
|
|
* Unchanged on exit.
|
|
*
|
|
* C - DOUBLE PRECISION array of DIMENSION ( LDC, n ).
|
|
* Before entry, the leading m by n part of the array C must
|
|
* contain the matrix C, except when beta is zero, in which
|
|
* case C need not be set on entry.
|
|
* On exit, the array C is overwritten by the m by n matrix
|
|
* ( alpha*op( A )*op( B ) + beta*C ).
|
|
*
|
|
* LDC - INTEGER.
|
|
* On entry, LDC specifies the first dimension of C as declared
|
|
* in the calling (sub) program. LDC must be at least
|
|
* max( 1, m ).
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 3 Blas routine.
|
|
*
|
|
* -- Written on 8-February-1989.
|
|
* Jack Dongarra, Argonne National Laboratory.
|
|
* Iain Duff, AERE Harwell.
|
|
* Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
|
* Sven Hammarling, Numerical Algorithms Group Ltd.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP
|
|
INTEGER I,INFO,J,L,NCOLA,NROWA,NROWB
|
|
LOGICAL NOTA,NOTB
|
|
* ..
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE,ZERO
|
|
PARAMETER (ONE=1.0D+0,ZERO=0.0D+0)
|
|
* ..
|
|
*
|
|
* Set NOTA and NOTB as true if A and B respectively are not
|
|
* transposed and set NROWA, NCOLA and NROWB as the number of rows
|
|
* and columns of A and the number of rows of B respectively.
|
|
*
|
|
NOTA = LSAME(TRANSA,'N')
|
|
NOTB = LSAME(TRANSB,'N')
|
|
IF (NOTA) THEN
|
|
NROWA = M
|
|
NCOLA = K
|
|
ELSE
|
|
NROWA = K
|
|
NCOLA = M
|
|
END IF
|
|
IF (NOTB) THEN
|
|
NROWB = K
|
|
ELSE
|
|
NROWB = N
|
|
END IF
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
IF ((.NOT.NOTA) .AND. (.NOT.LSAME(TRANSA,'C')) .AND.
|
|
+ (.NOT.LSAME(TRANSA,'T'))) THEN
|
|
INFO = 1
|
|
ELSE IF ((.NOT.NOTB) .AND. (.NOT.LSAME(TRANSB,'C')) .AND.
|
|
+ (.NOT.LSAME(TRANSB,'T'))) THEN
|
|
INFO = 2
|
|
ELSE IF (M.LT.0) THEN
|
|
INFO = 3
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 4
|
|
ELSE IF (K.LT.0) THEN
|
|
INFO = 5
|
|
ELSE IF (LDA.LT.MAX(1,NROWA)) THEN
|
|
INFO = 8
|
|
ELSE IF (LDB.LT.MAX(1,NROWB)) THEN
|
|
INFO = 10
|
|
ELSE IF (LDC.LT.MAX(1,M)) THEN
|
|
INFO = 13
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DGEMM ',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF ((M.EQ.0) .OR. (N.EQ.0) .OR.
|
|
+ (((ALPHA.EQ.ZERO).OR. (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN
|
|
*
|
|
* And if alpha.eq.zero.
|
|
*
|
|
IF (ALPHA.EQ.ZERO) THEN
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 20 J = 1,N
|
|
DO 10 I = 1,M
|
|
C(I,J) = ZERO
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
ELSE
|
|
DO 40 J = 1,N
|
|
DO 30 I = 1,M
|
|
C(I,J) = BETA*C(I,J)
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
END IF
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Start the operations.
|
|
*
|
|
IF (NOTB) THEN
|
|
IF (NOTA) THEN
|
|
*
|
|
* Form C := alpha*A*B + beta*C.
|
|
*
|
|
DO 90 J = 1,N
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 50 I = 1,M
|
|
C(I,J) = ZERO
|
|
50 CONTINUE
|
|
ELSE IF (BETA.NE.ONE) THEN
|
|
DO 60 I = 1,M
|
|
C(I,J) = BETA*C(I,J)
|
|
60 CONTINUE
|
|
END IF
|
|
DO 80 L = 1,K
|
|
IF (B(L,J).NE.ZERO) THEN
|
|
TEMP = ALPHA*B(L,J)
|
|
DO 70 I = 1,M
|
|
C(I,J) = C(I,J) + TEMP*A(I,L)
|
|
70 CONTINUE
|
|
END IF
|
|
80 CONTINUE
|
|
90 CONTINUE
|
|
ELSE
|
|
*
|
|
* Form C := alpha*A**T*B + beta*C
|
|
*
|
|
DO 120 J = 1,N
|
|
DO 110 I = 1,M
|
|
TEMP = ZERO
|
|
DO 100 L = 1,K
|
|
TEMP = TEMP + A(L,I)*B(L,J)
|
|
100 CONTINUE
|
|
IF (BETA.EQ.ZERO) THEN
|
|
C(I,J) = ALPHA*TEMP
|
|
ELSE
|
|
C(I,J) = ALPHA*TEMP + BETA*C(I,J)
|
|
END IF
|
|
110 CONTINUE
|
|
120 CONTINUE
|
|
END IF
|
|
ELSE
|
|
IF (NOTA) THEN
|
|
*
|
|
* Form C := alpha*A*B**T + beta*C
|
|
*
|
|
DO 170 J = 1,N
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 130 I = 1,M
|
|
C(I,J) = ZERO
|
|
130 CONTINUE
|
|
ELSE IF (BETA.NE.ONE) THEN
|
|
DO 140 I = 1,M
|
|
C(I,J) = BETA*C(I,J)
|
|
140 CONTINUE
|
|
END IF
|
|
DO 160 L = 1,K
|
|
IF (B(J,L).NE.ZERO) THEN
|
|
TEMP = ALPHA*B(J,L)
|
|
DO 150 I = 1,M
|
|
C(I,J) = C(I,J) + TEMP*A(I,L)
|
|
150 CONTINUE
|
|
END IF
|
|
160 CONTINUE
|
|
170 CONTINUE
|
|
ELSE
|
|
*
|
|
* Form C := alpha*A**T*B**T + beta*C
|
|
*
|
|
DO 200 J = 1,N
|
|
DO 190 I = 1,M
|
|
TEMP = ZERO
|
|
DO 180 L = 1,K
|
|
TEMP = TEMP + A(L,I)*B(J,L)
|
|
180 CONTINUE
|
|
IF (BETA.EQ.ZERO) THEN
|
|
C(I,J) = ALPHA*TEMP
|
|
ELSE
|
|
C(I,J) = ALPHA*TEMP + BETA*C(I,J)
|
|
END IF
|
|
190 CONTINUE
|
|
200 CONTINUE
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DGEMM .
|
|
*
|
|
END
|
|
SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION ALPHA,BETA
|
|
INTEGER INCX,INCY,LDA,M,N
|
|
CHARACTER TRANS
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),X(*),Y(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DGEMV performs one of the matrix-vector operations
|
|
*
|
|
* y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y,
|
|
*
|
|
* where alpha and beta are scalars, x and y are vectors and A is an
|
|
* m by n matrix.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* TRANS - CHARACTER*1.
|
|
* On entry, TRANS specifies the operation to be performed as
|
|
* follows:
|
|
*
|
|
* TRANS = 'N' or 'n' y := alpha*A*x + beta*y.
|
|
*
|
|
* TRANS = 'T' or 't' y := alpha*A**T*x + beta*y.
|
|
*
|
|
* TRANS = 'C' or 'c' y := alpha*A**T*x + beta*y.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* M - INTEGER.
|
|
* On entry, M specifies the number of rows of the matrix A.
|
|
* M must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the number of columns of the matrix A.
|
|
* N must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* ALPHA - DOUBLE PRECISION.
|
|
* On entry, ALPHA specifies the scalar alpha.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
|
|
* Before entry, the leading m by n part of the array A must
|
|
* contain the matrix of coefficients.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. LDA must be at least
|
|
* max( 1, m ).
|
|
* Unchanged on exit.
|
|
*
|
|
* X - DOUBLE PRECISION array of DIMENSION at least
|
|
* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n'
|
|
* and at least
|
|
* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise.
|
|
* Before entry, the incremented array X must contain the
|
|
* vector x.
|
|
* Unchanged on exit.
|
|
*
|
|
* INCX - INTEGER.
|
|
* On entry, INCX specifies the increment for the elements of
|
|
* X. INCX must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* BETA - DOUBLE PRECISION.
|
|
* On entry, BETA specifies the scalar beta. When BETA is
|
|
* supplied as zero then Y need not be set on input.
|
|
* Unchanged on exit.
|
|
*
|
|
* Y - DOUBLE PRECISION array of DIMENSION at least
|
|
* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n'
|
|
* and at least
|
|
* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise.
|
|
* Before entry with BETA non-zero, the incremented array Y
|
|
* must contain the vector y. On exit, Y is overwritten by the
|
|
* updated vector y.
|
|
*
|
|
* INCY - INTEGER.
|
|
* On entry, INCY specifies the increment for the elements of
|
|
* Y. INCY must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 2 Blas routine.
|
|
* The vector and matrix arguments are not referenced when N = 0, or M = 0
|
|
*
|
|
* -- Written on 22-October-1986.
|
|
* Jack Dongarra, Argonne National Lab.
|
|
* Jeremy Du Croz, Nag Central Office.
|
|
* Sven Hammarling, Nag Central Office.
|
|
* Richard Hanson, Sandia National Labs.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE,ZERO
|
|
PARAMETER (ONE=1.0D+0,ZERO=0.0D+0)
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP
|
|
INTEGER I,INFO,IX,IY,J,JX,JY,KX,KY,LENX,LENY
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
|
|
+ .NOT.LSAME(TRANS,'C')) THEN
|
|
INFO = 1
|
|
ELSE IF (M.LT.0) THEN
|
|
INFO = 2
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 3
|
|
ELSE IF (LDA.LT.MAX(1,M)) THEN
|
|
INFO = 6
|
|
ELSE IF (INCX.EQ.0) THEN
|
|
INFO = 8
|
|
ELSE IF (INCY.EQ.0) THEN
|
|
INFO = 11
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DGEMV ',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF ((M.EQ.0) .OR. (N.EQ.0) .OR.
|
|
+ ((ALPHA.EQ.ZERO).AND. (BETA.EQ.ONE))) RETURN
|
|
*
|
|
* Set LENX and LENY, the lengths of the vectors x and y, and set
|
|
* up the start points in X and Y.
|
|
*
|
|
IF (LSAME(TRANS,'N')) THEN
|
|
LENX = N
|
|
LENY = M
|
|
ELSE
|
|
LENX = M
|
|
LENY = N
|
|
END IF
|
|
IF (INCX.GT.0) THEN
|
|
KX = 1
|
|
ELSE
|
|
KX = 1 - (LENX-1)*INCX
|
|
END IF
|
|
IF (INCY.GT.0) THEN
|
|
KY = 1
|
|
ELSE
|
|
KY = 1 - (LENY-1)*INCY
|
|
END IF
|
|
*
|
|
* Start the operations. In this version the elements of A are
|
|
* accessed sequentially with one pass through A.
|
|
*
|
|
* First form y := beta*y.
|
|
*
|
|
IF (BETA.NE.ONE) THEN
|
|
IF (INCY.EQ.1) THEN
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 10 I = 1,LENY
|
|
Y(I) = ZERO
|
|
10 CONTINUE
|
|
ELSE
|
|
DO 20 I = 1,LENY
|
|
Y(I) = BETA*Y(I)
|
|
20 CONTINUE
|
|
END IF
|
|
ELSE
|
|
IY = KY
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 30 I = 1,LENY
|
|
Y(IY) = ZERO
|
|
IY = IY + INCY
|
|
30 CONTINUE
|
|
ELSE
|
|
DO 40 I = 1,LENY
|
|
Y(IY) = BETA*Y(IY)
|
|
IY = IY + INCY
|
|
40 CONTINUE
|
|
END IF
|
|
END IF
|
|
END IF
|
|
IF (ALPHA.EQ.ZERO) RETURN
|
|
IF (LSAME(TRANS,'N')) THEN
|
|
*
|
|
* Form y := alpha*A*x + y.
|
|
*
|
|
JX = KX
|
|
IF (INCY.EQ.1) THEN
|
|
DO 60 J = 1,N
|
|
IF (X(JX).NE.ZERO) THEN
|
|
TEMP = ALPHA*X(JX)
|
|
DO 50 I = 1,M
|
|
Y(I) = Y(I) + TEMP*A(I,J)
|
|
50 CONTINUE
|
|
END IF
|
|
JX = JX + INCX
|
|
60 CONTINUE
|
|
ELSE
|
|
DO 80 J = 1,N
|
|
IF (X(JX).NE.ZERO) THEN
|
|
TEMP = ALPHA*X(JX)
|
|
IY = KY
|
|
DO 70 I = 1,M
|
|
Y(IY) = Y(IY) + TEMP*A(I,J)
|
|
IY = IY + INCY
|
|
70 CONTINUE
|
|
END IF
|
|
JX = JX + INCX
|
|
80 CONTINUE
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form y := alpha*A**T*x + y.
|
|
*
|
|
JY = KY
|
|
IF (INCX.EQ.1) THEN
|
|
DO 100 J = 1,N
|
|
TEMP = ZERO
|
|
DO 90 I = 1,M
|
|
TEMP = TEMP + A(I,J)*X(I)
|
|
90 CONTINUE
|
|
Y(JY) = Y(JY) + ALPHA*TEMP
|
|
JY = JY + INCY
|
|
100 CONTINUE
|
|
ELSE
|
|
DO 120 J = 1,N
|
|
TEMP = ZERO
|
|
IX = KX
|
|
DO 110 I = 1,M
|
|
TEMP = TEMP + A(I,J)*X(IX)
|
|
IX = IX + INCX
|
|
110 CONTINUE
|
|
Y(JY) = Y(JY) + ALPHA*TEMP
|
|
JY = JY + INCY
|
|
120 CONTINUE
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DGEMV .
|
|
*
|
|
END
|
|
SUBROUTINE DGER(M,N,ALPHA,X,INCX,Y,INCY,A,LDA)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION ALPHA
|
|
INTEGER INCX,INCY,LDA,M,N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),X(*),Y(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DGER performs the rank 1 operation
|
|
*
|
|
* A := alpha*x*y**T + A,
|
|
*
|
|
* where alpha is a scalar, x is an m element vector, y is an n element
|
|
* vector and A is an m by n matrix.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* M - INTEGER.
|
|
* On entry, M specifies the number of rows of the matrix A.
|
|
* M must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the number of columns of the matrix A.
|
|
* N must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* ALPHA - DOUBLE PRECISION.
|
|
* On entry, ALPHA specifies the scalar alpha.
|
|
* Unchanged on exit.
|
|
*
|
|
* X - DOUBLE PRECISION array of dimension at least
|
|
* ( 1 + ( m - 1 )*abs( INCX ) ).
|
|
* Before entry, the incremented array X must contain the m
|
|
* element vector x.
|
|
* Unchanged on exit.
|
|
*
|
|
* INCX - INTEGER.
|
|
* On entry, INCX specifies the increment for the elements of
|
|
* X. INCX must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* Y - DOUBLE PRECISION array of dimension at least
|
|
* ( 1 + ( n - 1 )*abs( INCY ) ).
|
|
* Before entry, the incremented array Y must contain the n
|
|
* element vector y.
|
|
* Unchanged on exit.
|
|
*
|
|
* INCY - INTEGER.
|
|
* On entry, INCY specifies the increment for the elements of
|
|
* Y. INCY must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
|
|
* Before entry, the leading m by n part of the array A must
|
|
* contain the matrix of coefficients. On exit, A is
|
|
* overwritten by the updated matrix.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. LDA must be at least
|
|
* max( 1, m ).
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 2 Blas routine.
|
|
*
|
|
* -- Written on 22-October-1986.
|
|
* Jack Dongarra, Argonne National Lab.
|
|
* Jeremy Du Croz, Nag Central Office.
|
|
* Sven Hammarling, Nag Central Office.
|
|
* Richard Hanson, Sandia National Labs.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER (ZERO=0.0D+0)
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP
|
|
INTEGER I,INFO,IX,J,JY,KX
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
IF (M.LT.0) THEN
|
|
INFO = 1
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 2
|
|
ELSE IF (INCX.EQ.0) THEN
|
|
INFO = 5
|
|
ELSE IF (INCY.EQ.0) THEN
|
|
INFO = 7
|
|
ELSE IF (LDA.LT.MAX(1,M)) THEN
|
|
INFO = 9
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DGER ',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF ((M.EQ.0) .OR. (N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
|
|
*
|
|
* Start the operations. In this version the elements of A are
|
|
* accessed sequentially with one pass through A.
|
|
*
|
|
IF (INCY.GT.0) THEN
|
|
JY = 1
|
|
ELSE
|
|
JY = 1 - (N-1)*INCY
|
|
END IF
|
|
IF (INCX.EQ.1) THEN
|
|
DO 20 J = 1,N
|
|
IF (Y(JY).NE.ZERO) THEN
|
|
TEMP = ALPHA*Y(JY)
|
|
DO 10 I = 1,M
|
|
A(I,J) = A(I,J) + X(I)*TEMP
|
|
10 CONTINUE
|
|
END IF
|
|
JY = JY + INCY
|
|
20 CONTINUE
|
|
ELSE
|
|
IF (INCX.GT.0) THEN
|
|
KX = 1
|
|
ELSE
|
|
KX = 1 - (M-1)*INCX
|
|
END IF
|
|
DO 40 J = 1,N
|
|
IF (Y(JY).NE.ZERO) THEN
|
|
TEMP = ALPHA*Y(JY)
|
|
IX = KX
|
|
DO 30 I = 1,M
|
|
A(I,J) = A(I,J) + X(IX)*TEMP
|
|
IX = IX + INCX
|
|
30 CONTINUE
|
|
END IF
|
|
JY = JY + INCY
|
|
40 CONTINUE
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DGER .
|
|
*
|
|
END
|
|
DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX)
|
|
* .. Scalar Arguments ..
|
|
INTEGER INCX,N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION X(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DNRM2 returns the euclidean norm of a vector via the function
|
|
* name, so that
|
|
*
|
|
* DNRM2 := sqrt( x'*x )
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* -- This version written on 25-October-1982.
|
|
* Modified on 14-October-1993 to inline the call to DLASSQ.
|
|
* Sven Hammarling, Nag Ltd.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE,ZERO
|
|
PARAMETER (ONE=1.0D+0,ZERO=0.0D+0)
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION ABSXI,NORM,SCALE,SSQ
|
|
INTEGER IX
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC ABS,SQRT
|
|
* ..
|
|
IF (N.LT.1 .OR. INCX.LT.1) THEN
|
|
NORM = ZERO
|
|
ELSE IF (N.EQ.1) THEN
|
|
NORM = ABS(X(1))
|
|
ELSE
|
|
SCALE = ZERO
|
|
SSQ = ONE
|
|
* The following loop is equivalent to this call to the LAPACK
|
|
* auxiliary routine:
|
|
* CALL DLASSQ( N, X, INCX, SCALE, SSQ )
|
|
*
|
|
DO 10 IX = 1,1 + (N-1)*INCX,INCX
|
|
IF (X(IX).NE.ZERO) THEN
|
|
ABSXI = ABS(X(IX))
|
|
IF (SCALE.LT.ABSXI) THEN
|
|
SSQ = ONE + SSQ* (SCALE/ABSXI)**2
|
|
SCALE = ABSXI
|
|
ELSE
|
|
SSQ = SSQ + (ABSXI/SCALE)**2
|
|
END IF
|
|
END IF
|
|
10 CONTINUE
|
|
NORM = SCALE*SQRT(SSQ)
|
|
END IF
|
|
*
|
|
DNRM2 = NORM
|
|
RETURN
|
|
*
|
|
* End of DNRM2.
|
|
*
|
|
END
|
|
SUBROUTINE DSCAL(N,DA,DX,INCX)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION DA
|
|
INTEGER INCX,N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION DX(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSCAL scales a vector by a constant.
|
|
* uses unrolled loops for increment equal to one.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* jack dongarra, linpack, 3/11/78.
|
|
* modified 3/93 to return if incx .le. 0.
|
|
* modified 12/3/93, array(1) declarations changed to array(*)
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Local Scalars ..
|
|
INTEGER I,M,MP1,NINCX
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MOD
|
|
* ..
|
|
IF (N.LE.0 .OR. INCX.LE.0) RETURN
|
|
IF (INCX.EQ.1) THEN
|
|
*
|
|
* code for increment equal to 1
|
|
*
|
|
*
|
|
* clean-up loop
|
|
*
|
|
M = MOD(N,5)
|
|
IF (M.NE.0) THEN
|
|
DO I = 1,M
|
|
DX(I) = DA*DX(I)
|
|
END DO
|
|
IF (N.LT.5) RETURN
|
|
END IF
|
|
MP1 = M + 1
|
|
DO I = MP1,N,5
|
|
DX(I) = DA*DX(I)
|
|
DX(I+1) = DA*DX(I+1)
|
|
DX(I+2) = DA*DX(I+2)
|
|
DX(I+3) = DA*DX(I+3)
|
|
DX(I+4) = DA*DX(I+4)
|
|
END DO
|
|
ELSE
|
|
*
|
|
* code for increment not equal to 1
|
|
*
|
|
NINCX = N*INCX
|
|
DO I = 1,NINCX,INCX
|
|
DX(I) = DA*DX(I)
|
|
END DO
|
|
END IF
|
|
RETURN
|
|
END
|
|
SUBROUTINE DSWAP(N,DX,INCX,DY,INCY)
|
|
* .. Scalar Arguments ..
|
|
INTEGER INCX,INCY,N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION DX(*),DY(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* interchanges two vectors.
|
|
* uses unrolled loops for increments equal one.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* jack dongarra, linpack, 3/11/78.
|
|
* modified 12/3/93, array(1) declarations changed to array(*)
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION DTEMP
|
|
INTEGER I,IX,IY,M,MP1
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MOD
|
|
* ..
|
|
IF (N.LE.0) RETURN
|
|
IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN
|
|
*
|
|
* code for both increments equal to 1
|
|
*
|
|
*
|
|
* clean-up loop
|
|
*
|
|
M = MOD(N,3)
|
|
IF (M.NE.0) THEN
|
|
DO I = 1,M
|
|
DTEMP = DX(I)
|
|
DX(I) = DY(I)
|
|
DY(I) = DTEMP
|
|
END DO
|
|
IF (N.LT.3) RETURN
|
|
END IF
|
|
MP1 = M + 1
|
|
DO I = MP1,N,3
|
|
DTEMP = DX(I)
|
|
DX(I) = DY(I)
|
|
DY(I) = DTEMP
|
|
DTEMP = DX(I+1)
|
|
DX(I+1) = DY(I+1)
|
|
DY(I+1) = DTEMP
|
|
DTEMP = DX(I+2)
|
|
DX(I+2) = DY(I+2)
|
|
DY(I+2) = DTEMP
|
|
END DO
|
|
ELSE
|
|
*
|
|
* code for unequal increments or equal increments not equal
|
|
* to 1
|
|
*
|
|
IX = 1
|
|
IY = 1
|
|
IF (INCX.LT.0) IX = (-N+1)*INCX + 1
|
|
IF (INCY.LT.0) IY = (-N+1)*INCY + 1
|
|
DO I = 1,N
|
|
DTEMP = DX(IX)
|
|
DX(IX) = DY(IY)
|
|
DY(IY) = DTEMP
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
END DO
|
|
END IF
|
|
RETURN
|
|
END
|
|
SUBROUTINE DSYMV(UPLO,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION ALPHA,BETA
|
|
INTEGER INCX,INCY,LDA,N
|
|
CHARACTER UPLO
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),X(*),Y(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSYMV performs the matrix-vector operation
|
|
*
|
|
* y := alpha*A*x + beta*y,
|
|
*
|
|
* where alpha and beta are scalars, x and y are n element vectors and
|
|
* A is an n by n symmetric matrix.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* UPLO - CHARACTER*1.
|
|
* On entry, UPLO specifies whether the upper or lower
|
|
* triangular part of the array A is to be referenced as
|
|
* follows:
|
|
*
|
|
* UPLO = 'U' or 'u' Only the upper triangular part of A
|
|
* is to be referenced.
|
|
*
|
|
* UPLO = 'L' or 'l' Only the lower triangular part of A
|
|
* is to be referenced.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the order of the matrix A.
|
|
* N must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* ALPHA - DOUBLE PRECISION.
|
|
* On entry, ALPHA specifies the scalar alpha.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
|
|
* Before entry with UPLO = 'U' or 'u', the leading n by n
|
|
* upper triangular part of the array A must contain the upper
|
|
* triangular part of the symmetric matrix and the strictly
|
|
* lower triangular part of A is not referenced.
|
|
* Before entry with UPLO = 'L' or 'l', the leading n by n
|
|
* lower triangular part of the array A must contain the lower
|
|
* triangular part of the symmetric matrix and the strictly
|
|
* upper triangular part of A is not referenced.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. LDA must be at least
|
|
* max( 1, n ).
|
|
* Unchanged on exit.
|
|
*
|
|
* X - DOUBLE PRECISION array of dimension at least
|
|
* ( 1 + ( n - 1 )*abs( INCX ) ).
|
|
* Before entry, the incremented array X must contain the n
|
|
* element vector x.
|
|
* Unchanged on exit.
|
|
*
|
|
* INCX - INTEGER.
|
|
* On entry, INCX specifies the increment for the elements of
|
|
* X. INCX must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* BETA - DOUBLE PRECISION.
|
|
* On entry, BETA specifies the scalar beta. When BETA is
|
|
* supplied as zero then Y need not be set on input.
|
|
* Unchanged on exit.
|
|
*
|
|
* Y - DOUBLE PRECISION array of dimension at least
|
|
* ( 1 + ( n - 1 )*abs( INCY ) ).
|
|
* Before entry, the incremented array Y must contain the n
|
|
* element vector y. On exit, Y is overwritten by the updated
|
|
* vector y.
|
|
*
|
|
* INCY - INTEGER.
|
|
* On entry, INCY specifies the increment for the elements of
|
|
* Y. INCY must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 2 Blas routine.
|
|
* The vector and matrix arguments are not referenced when N = 0, or M = 0
|
|
*
|
|
* -- Written on 22-October-1986.
|
|
* Jack Dongarra, Argonne National Lab.
|
|
* Jeremy Du Croz, Nag Central Office.
|
|
* Sven Hammarling, Nag Central Office.
|
|
* Richard Hanson, Sandia National Labs.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE,ZERO
|
|
PARAMETER (ONE=1.0D+0,ZERO=0.0D+0)
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP1,TEMP2
|
|
INTEGER I,INFO,IX,IY,J,JX,JY,KX,KY
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
|
|
INFO = 1
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 2
|
|
ELSE IF (LDA.LT.MAX(1,N)) THEN
|
|
INFO = 5
|
|
ELSE IF (INCX.EQ.0) THEN
|
|
INFO = 7
|
|
ELSE IF (INCY.EQ.0) THEN
|
|
INFO = 10
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DSYMV ',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF ((N.EQ.0) .OR. ((ALPHA.EQ.ZERO).AND. (BETA.EQ.ONE))) RETURN
|
|
*
|
|
* Set up the start points in X and Y.
|
|
*
|
|
IF (INCX.GT.0) THEN
|
|
KX = 1
|
|
ELSE
|
|
KX = 1 - (N-1)*INCX
|
|
END IF
|
|
IF (INCY.GT.0) THEN
|
|
KY = 1
|
|
ELSE
|
|
KY = 1 - (N-1)*INCY
|
|
END IF
|
|
*
|
|
* Start the operations. In this version the elements of A are
|
|
* accessed sequentially with one pass through the triangular part
|
|
* of A.
|
|
*
|
|
* First form y := beta*y.
|
|
*
|
|
IF (BETA.NE.ONE) THEN
|
|
IF (INCY.EQ.1) THEN
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 10 I = 1,N
|
|
Y(I) = ZERO
|
|
10 CONTINUE
|
|
ELSE
|
|
DO 20 I = 1,N
|
|
Y(I) = BETA*Y(I)
|
|
20 CONTINUE
|
|
END IF
|
|
ELSE
|
|
IY = KY
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 30 I = 1,N
|
|
Y(IY) = ZERO
|
|
IY = IY + INCY
|
|
30 CONTINUE
|
|
ELSE
|
|
DO 40 I = 1,N
|
|
Y(IY) = BETA*Y(IY)
|
|
IY = IY + INCY
|
|
40 CONTINUE
|
|
END IF
|
|
END IF
|
|
END IF
|
|
IF (ALPHA.EQ.ZERO) RETURN
|
|
IF (LSAME(UPLO,'U')) THEN
|
|
*
|
|
* Form y when A is stored in upper triangle.
|
|
*
|
|
IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
|
|
DO 60 J = 1,N
|
|
TEMP1 = ALPHA*X(J)
|
|
TEMP2 = ZERO
|
|
DO 50 I = 1,J - 1
|
|
Y(I) = Y(I) + TEMP1*A(I,J)
|
|
TEMP2 = TEMP2 + A(I,J)*X(I)
|
|
50 CONTINUE
|
|
Y(J) = Y(J) + TEMP1*A(J,J) + ALPHA*TEMP2
|
|
60 CONTINUE
|
|
ELSE
|
|
JX = KX
|
|
JY = KY
|
|
DO 80 J = 1,N
|
|
TEMP1 = ALPHA*X(JX)
|
|
TEMP2 = ZERO
|
|
IX = KX
|
|
IY = KY
|
|
DO 70 I = 1,J - 1
|
|
Y(IY) = Y(IY) + TEMP1*A(I,J)
|
|
TEMP2 = TEMP2 + A(I,J)*X(IX)
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
70 CONTINUE
|
|
Y(JY) = Y(JY) + TEMP1*A(J,J) + ALPHA*TEMP2
|
|
JX = JX + INCX
|
|
JY = JY + INCY
|
|
80 CONTINUE
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form y when A is stored in lower triangle.
|
|
*
|
|
IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
|
|
DO 100 J = 1,N
|
|
TEMP1 = ALPHA*X(J)
|
|
TEMP2 = ZERO
|
|
Y(J) = Y(J) + TEMP1*A(J,J)
|
|
DO 90 I = J + 1,N
|
|
Y(I) = Y(I) + TEMP1*A(I,J)
|
|
TEMP2 = TEMP2 + A(I,J)*X(I)
|
|
90 CONTINUE
|
|
Y(J) = Y(J) + ALPHA*TEMP2
|
|
100 CONTINUE
|
|
ELSE
|
|
JX = KX
|
|
JY = KY
|
|
DO 120 J = 1,N
|
|
TEMP1 = ALPHA*X(JX)
|
|
TEMP2 = ZERO
|
|
Y(JY) = Y(JY) + TEMP1*A(J,J)
|
|
IX = JX
|
|
IY = JY
|
|
DO 110 I = J + 1,N
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
Y(IY) = Y(IY) + TEMP1*A(I,J)
|
|
TEMP2 = TEMP2 + A(I,J)*X(IX)
|
|
110 CONTINUE
|
|
Y(JY) = Y(JY) + ALPHA*TEMP2
|
|
JX = JX + INCX
|
|
JY = JY + INCY
|
|
120 CONTINUE
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DSYMV .
|
|
*
|
|
END
|
|
SUBROUTINE DSYR2(UPLO,N,ALPHA,X,INCX,Y,INCY,A,LDA)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION ALPHA
|
|
INTEGER INCX,INCY,LDA,N
|
|
CHARACTER UPLO
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),X(*),Y(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSYR2 performs the symmetric rank 2 operation
|
|
*
|
|
* A := alpha*x*y**T + alpha*y*x**T + A,
|
|
*
|
|
* where alpha is a scalar, x and y are n element vectors and A is an n
|
|
* by n symmetric matrix.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* UPLO - CHARACTER*1.
|
|
* On entry, UPLO specifies whether the upper or lower
|
|
* triangular part of the array A is to be referenced as
|
|
* follows:
|
|
*
|
|
* UPLO = 'U' or 'u' Only the upper triangular part of A
|
|
* is to be referenced.
|
|
*
|
|
* UPLO = 'L' or 'l' Only the lower triangular part of A
|
|
* is to be referenced.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the order of the matrix A.
|
|
* N must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* ALPHA - DOUBLE PRECISION.
|
|
* On entry, ALPHA specifies the scalar alpha.
|
|
* Unchanged on exit.
|
|
*
|
|
* X - DOUBLE PRECISION array of dimension at least
|
|
* ( 1 + ( n - 1 )*abs( INCX ) ).
|
|
* Before entry, the incremented array X must contain the n
|
|
* element vector x.
|
|
* Unchanged on exit.
|
|
*
|
|
* INCX - INTEGER.
|
|
* On entry, INCX specifies the increment for the elements of
|
|
* X. INCX must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* Y - DOUBLE PRECISION array of dimension at least
|
|
* ( 1 + ( n - 1 )*abs( INCY ) ).
|
|
* Before entry, the incremented array Y must contain the n
|
|
* element vector y.
|
|
* Unchanged on exit.
|
|
*
|
|
* INCY - INTEGER.
|
|
* On entry, INCY specifies the increment for the elements of
|
|
* Y. INCY must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
|
|
* Before entry with UPLO = 'U' or 'u', the leading n by n
|
|
* upper triangular part of the array A must contain the upper
|
|
* triangular part of the symmetric matrix and the strictly
|
|
* lower triangular part of A is not referenced. On exit, the
|
|
* upper triangular part of the array A is overwritten by the
|
|
* upper triangular part of the updated matrix.
|
|
* Before entry with UPLO = 'L' or 'l', the leading n by n
|
|
* lower triangular part of the array A must contain the lower
|
|
* triangular part of the symmetric matrix and the strictly
|
|
* upper triangular part of A is not referenced. On exit, the
|
|
* lower triangular part of the array A is overwritten by the
|
|
* lower triangular part of the updated matrix.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. LDA must be at least
|
|
* max( 1, n ).
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 2 Blas routine.
|
|
*
|
|
* -- Written on 22-October-1986.
|
|
* Jack Dongarra, Argonne National Lab.
|
|
* Jeremy Du Croz, Nag Central Office.
|
|
* Sven Hammarling, Nag Central Office.
|
|
* Richard Hanson, Sandia National Labs.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER (ZERO=0.0D+0)
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP1,TEMP2
|
|
INTEGER I,INFO,IX,IY,J,JX,JY,KX,KY
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
|
|
INFO = 1
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 2
|
|
ELSE IF (INCX.EQ.0) THEN
|
|
INFO = 5
|
|
ELSE IF (INCY.EQ.0) THEN
|
|
INFO = 7
|
|
ELSE IF (LDA.LT.MAX(1,N)) THEN
|
|
INFO = 9
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DSYR2 ',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF ((N.EQ.0) .OR. (ALPHA.EQ.ZERO)) RETURN
|
|
*
|
|
* Set up the start points in X and Y if the increments are not both
|
|
* unity.
|
|
*
|
|
IF ((INCX.NE.1) .OR. (INCY.NE.1)) THEN
|
|
IF (INCX.GT.0) THEN
|
|
KX = 1
|
|
ELSE
|
|
KX = 1 - (N-1)*INCX
|
|
END IF
|
|
IF (INCY.GT.0) THEN
|
|
KY = 1
|
|
ELSE
|
|
KY = 1 - (N-1)*INCY
|
|
END IF
|
|
JX = KX
|
|
JY = KY
|
|
END IF
|
|
*
|
|
* Start the operations. In this version the elements of A are
|
|
* accessed sequentially with one pass through the triangular part
|
|
* of A.
|
|
*
|
|
IF (LSAME(UPLO,'U')) THEN
|
|
*
|
|
* Form A when A is stored in the upper triangle.
|
|
*
|
|
IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
|
|
DO 20 J = 1,N
|
|
IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
|
|
TEMP1 = ALPHA*Y(J)
|
|
TEMP2 = ALPHA*X(J)
|
|
DO 10 I = 1,J
|
|
A(I,J) = A(I,J) + X(I)*TEMP1 + Y(I)*TEMP2
|
|
10 CONTINUE
|
|
END IF
|
|
20 CONTINUE
|
|
ELSE
|
|
DO 40 J = 1,N
|
|
IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
|
|
TEMP1 = ALPHA*Y(JY)
|
|
TEMP2 = ALPHA*X(JX)
|
|
IX = KX
|
|
IY = KY
|
|
DO 30 I = 1,J
|
|
A(I,J) = A(I,J) + X(IX)*TEMP1 + Y(IY)*TEMP2
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
30 CONTINUE
|
|
END IF
|
|
JX = JX + INCX
|
|
JY = JY + INCY
|
|
40 CONTINUE
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form A when A is stored in the lower triangle.
|
|
*
|
|
IF ((INCX.EQ.1) .AND. (INCY.EQ.1)) THEN
|
|
DO 60 J = 1,N
|
|
IF ((X(J).NE.ZERO) .OR. (Y(J).NE.ZERO)) THEN
|
|
TEMP1 = ALPHA*Y(J)
|
|
TEMP2 = ALPHA*X(J)
|
|
DO 50 I = J,N
|
|
A(I,J) = A(I,J) + X(I)*TEMP1 + Y(I)*TEMP2
|
|
50 CONTINUE
|
|
END IF
|
|
60 CONTINUE
|
|
ELSE
|
|
DO 80 J = 1,N
|
|
IF ((X(JX).NE.ZERO) .OR. (Y(JY).NE.ZERO)) THEN
|
|
TEMP1 = ALPHA*Y(JY)
|
|
TEMP2 = ALPHA*X(JX)
|
|
IX = JX
|
|
IY = JY
|
|
DO 70 I = J,N
|
|
A(I,J) = A(I,J) + X(IX)*TEMP1 + Y(IY)*TEMP2
|
|
IX = IX + INCX
|
|
IY = IY + INCY
|
|
70 CONTINUE
|
|
END IF
|
|
JX = JX + INCX
|
|
JY = JY + INCY
|
|
80 CONTINUE
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DSYR2 .
|
|
*
|
|
END
|
|
SUBROUTINE DSYR2K(UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION ALPHA,BETA
|
|
INTEGER K,LDA,LDB,LDC,N
|
|
CHARACTER TRANS,UPLO
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DSYR2K performs one of the symmetric rank 2k operations
|
|
*
|
|
* C := alpha*A*B**T + alpha*B*A**T + beta*C,
|
|
*
|
|
* or
|
|
*
|
|
* C := alpha*A**T*B + alpha*B**T*A + beta*C,
|
|
*
|
|
* where alpha and beta are scalars, C is an n by n symmetric matrix
|
|
* and A and B are n by k matrices in the first case and k by n
|
|
* matrices in the second case.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* UPLO - CHARACTER*1.
|
|
* On entry, UPLO specifies whether the upper or lower
|
|
* triangular part of the array C is to be referenced as
|
|
* follows:
|
|
*
|
|
* UPLO = 'U' or 'u' Only the upper triangular part of C
|
|
* is to be referenced.
|
|
*
|
|
* UPLO = 'L' or 'l' Only the lower triangular part of C
|
|
* is to be referenced.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* TRANS - CHARACTER*1.
|
|
* On entry, TRANS specifies the operation to be performed as
|
|
* follows:
|
|
*
|
|
* TRANS = 'N' or 'n' C := alpha*A*B**T + alpha*B*A**T +
|
|
* beta*C.
|
|
*
|
|
* TRANS = 'T' or 't' C := alpha*A**T*B + alpha*B**T*A +
|
|
* beta*C.
|
|
*
|
|
* TRANS = 'C' or 'c' C := alpha*A**T*B + alpha*B**T*A +
|
|
* beta*C.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the order of the matrix C. N must be
|
|
* at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* K - INTEGER.
|
|
* On entry with TRANS = 'N' or 'n', K specifies the number
|
|
* of columns of the matrices A and B, and on entry with
|
|
* TRANS = 'T' or 't' or 'C' or 'c', K specifies the number
|
|
* of rows of the matrices A and B. K must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* ALPHA - DOUBLE PRECISION.
|
|
* On entry, ALPHA specifies the scalar alpha.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is
|
|
* k when TRANS = 'N' or 'n', and is n otherwise.
|
|
* Before entry with TRANS = 'N' or 'n', the leading n by k
|
|
* part of the array A must contain the matrix A, otherwise
|
|
* the leading k by n part of the array A must contain the
|
|
* matrix A.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. When TRANS = 'N' or 'n'
|
|
* then LDA must be at least max( 1, n ), otherwise LDA must
|
|
* be at least max( 1, k ).
|
|
* Unchanged on exit.
|
|
*
|
|
* B - DOUBLE PRECISION array of DIMENSION ( LDB, kb ), where kb is
|
|
* k when TRANS = 'N' or 'n', and is n otherwise.
|
|
* Before entry with TRANS = 'N' or 'n', the leading n by k
|
|
* part of the array B must contain the matrix B, otherwise
|
|
* the leading k by n part of the array B must contain the
|
|
* matrix B.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDB - INTEGER.
|
|
* On entry, LDB specifies the first dimension of B as declared
|
|
* in the calling (sub) program. When TRANS = 'N' or 'n'
|
|
* then LDB must be at least max( 1, n ), otherwise LDB must
|
|
* be at least max( 1, k ).
|
|
* Unchanged on exit.
|
|
*
|
|
* BETA - DOUBLE PRECISION.
|
|
* On entry, BETA specifies the scalar beta.
|
|
* Unchanged on exit.
|
|
*
|
|
* C - DOUBLE PRECISION array of DIMENSION ( LDC, n ).
|
|
* Before entry with UPLO = 'U' or 'u', the leading n by n
|
|
* upper triangular part of the array C must contain the upper
|
|
* triangular part of the symmetric matrix and the strictly
|
|
* lower triangular part of C is not referenced. On exit, the
|
|
* upper triangular part of the array C is overwritten by the
|
|
* upper triangular part of the updated matrix.
|
|
* Before entry with UPLO = 'L' or 'l', the leading n by n
|
|
* lower triangular part of the array C must contain the lower
|
|
* triangular part of the symmetric matrix and the strictly
|
|
* upper triangular part of C is not referenced. On exit, the
|
|
* lower triangular part of the array C is overwritten by the
|
|
* lower triangular part of the updated matrix.
|
|
*
|
|
* LDC - INTEGER.
|
|
* On entry, LDC specifies the first dimension of C as declared
|
|
* in the calling (sub) program. LDC must be at least
|
|
* max( 1, n ).
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 3 Blas routine.
|
|
*
|
|
*
|
|
* -- Written on 8-February-1989.
|
|
* Jack Dongarra, Argonne National Laboratory.
|
|
* Iain Duff, AERE Harwell.
|
|
* Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
|
* Sven Hammarling, Numerical Algorithms Group Ltd.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP1,TEMP2
|
|
INTEGER I,INFO,J,L,NROWA
|
|
LOGICAL UPPER
|
|
* ..
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE,ZERO
|
|
PARAMETER (ONE=1.0D+0,ZERO=0.0D+0)
|
|
* ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
IF (LSAME(TRANS,'N')) THEN
|
|
NROWA = N
|
|
ELSE
|
|
NROWA = K
|
|
END IF
|
|
UPPER = LSAME(UPLO,'U')
|
|
*
|
|
INFO = 0
|
|
IF ((.NOT.UPPER) .AND. (.NOT.LSAME(UPLO,'L'))) THEN
|
|
INFO = 1
|
|
ELSE IF ((.NOT.LSAME(TRANS,'N')) .AND.
|
|
+ (.NOT.LSAME(TRANS,'T')) .AND.
|
|
+ (.NOT.LSAME(TRANS,'C'))) THEN
|
|
INFO = 2
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 3
|
|
ELSE IF (K.LT.0) THEN
|
|
INFO = 4
|
|
ELSE IF (LDA.LT.MAX(1,NROWA)) THEN
|
|
INFO = 7
|
|
ELSE IF (LDB.LT.MAX(1,NROWA)) THEN
|
|
INFO = 9
|
|
ELSE IF (LDC.LT.MAX(1,N)) THEN
|
|
INFO = 12
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DSYR2K',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF ((N.EQ.0) .OR. (((ALPHA.EQ.ZERO).OR.
|
|
+ (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN
|
|
*
|
|
* And when alpha.eq.zero.
|
|
*
|
|
IF (ALPHA.EQ.ZERO) THEN
|
|
IF (UPPER) THEN
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 20 J = 1,N
|
|
DO 10 I = 1,J
|
|
C(I,J) = ZERO
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
ELSE
|
|
DO 40 J = 1,N
|
|
DO 30 I = 1,J
|
|
C(I,J) = BETA*C(I,J)
|
|
30 CONTINUE
|
|
40 CONTINUE
|
|
END IF
|
|
ELSE
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 60 J = 1,N
|
|
DO 50 I = J,N
|
|
C(I,J) = ZERO
|
|
50 CONTINUE
|
|
60 CONTINUE
|
|
ELSE
|
|
DO 80 J = 1,N
|
|
DO 70 I = J,N
|
|
C(I,J) = BETA*C(I,J)
|
|
70 CONTINUE
|
|
80 CONTINUE
|
|
END IF
|
|
END IF
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Start the operations.
|
|
*
|
|
IF (LSAME(TRANS,'N')) THEN
|
|
*
|
|
* Form C := alpha*A*B**T + alpha*B*A**T + C.
|
|
*
|
|
IF (UPPER) THEN
|
|
DO 130 J = 1,N
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 90 I = 1,J
|
|
C(I,J) = ZERO
|
|
90 CONTINUE
|
|
ELSE IF (BETA.NE.ONE) THEN
|
|
DO 100 I = 1,J
|
|
C(I,J) = BETA*C(I,J)
|
|
100 CONTINUE
|
|
END IF
|
|
DO 120 L = 1,K
|
|
IF ((A(J,L).NE.ZERO) .OR. (B(J,L).NE.ZERO)) THEN
|
|
TEMP1 = ALPHA*B(J,L)
|
|
TEMP2 = ALPHA*A(J,L)
|
|
DO 110 I = 1,J
|
|
C(I,J) = C(I,J) + A(I,L)*TEMP1 +
|
|
+ B(I,L)*TEMP2
|
|
110 CONTINUE
|
|
END IF
|
|
120 CONTINUE
|
|
130 CONTINUE
|
|
ELSE
|
|
DO 180 J = 1,N
|
|
IF (BETA.EQ.ZERO) THEN
|
|
DO 140 I = J,N
|
|
C(I,J) = ZERO
|
|
140 CONTINUE
|
|
ELSE IF (BETA.NE.ONE) THEN
|
|
DO 150 I = J,N
|
|
C(I,J) = BETA*C(I,J)
|
|
150 CONTINUE
|
|
END IF
|
|
DO 170 L = 1,K
|
|
IF ((A(J,L).NE.ZERO) .OR. (B(J,L).NE.ZERO)) THEN
|
|
TEMP1 = ALPHA*B(J,L)
|
|
TEMP2 = ALPHA*A(J,L)
|
|
DO 160 I = J,N
|
|
C(I,J) = C(I,J) + A(I,L)*TEMP1 +
|
|
+ B(I,L)*TEMP2
|
|
160 CONTINUE
|
|
END IF
|
|
170 CONTINUE
|
|
180 CONTINUE
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form C := alpha*A**T*B + alpha*B**T*A + C.
|
|
*
|
|
IF (UPPER) THEN
|
|
DO 210 J = 1,N
|
|
DO 200 I = 1,J
|
|
TEMP1 = ZERO
|
|
TEMP2 = ZERO
|
|
DO 190 L = 1,K
|
|
TEMP1 = TEMP1 + A(L,I)*B(L,J)
|
|
TEMP2 = TEMP2 + B(L,I)*A(L,J)
|
|
190 CONTINUE
|
|
IF (BETA.EQ.ZERO) THEN
|
|
C(I,J) = ALPHA*TEMP1 + ALPHA*TEMP2
|
|
ELSE
|
|
C(I,J) = BETA*C(I,J) + ALPHA*TEMP1 +
|
|
+ ALPHA*TEMP2
|
|
END IF
|
|
200 CONTINUE
|
|
210 CONTINUE
|
|
ELSE
|
|
DO 240 J = 1,N
|
|
DO 230 I = J,N
|
|
TEMP1 = ZERO
|
|
TEMP2 = ZERO
|
|
DO 220 L = 1,K
|
|
TEMP1 = TEMP1 + A(L,I)*B(L,J)
|
|
TEMP2 = TEMP2 + B(L,I)*A(L,J)
|
|
220 CONTINUE
|
|
IF (BETA.EQ.ZERO) THEN
|
|
C(I,J) = ALPHA*TEMP1 + ALPHA*TEMP2
|
|
ELSE
|
|
C(I,J) = BETA*C(I,J) + ALPHA*TEMP1 +
|
|
+ ALPHA*TEMP2
|
|
END IF
|
|
230 CONTINUE
|
|
240 CONTINUE
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DSYR2K.
|
|
*
|
|
END
|
|
SUBROUTINE DTRMM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB)
|
|
* .. Scalar Arguments ..
|
|
DOUBLE PRECISION ALPHA
|
|
INTEGER LDA,LDB,M,N
|
|
CHARACTER DIAG,SIDE,TRANSA,UPLO
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),B(LDB,*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DTRMM performs one of the matrix-matrix operations
|
|
*
|
|
* B := alpha*op( A )*B, or B := alpha*B*op( A ),
|
|
*
|
|
* where alpha is a scalar, B is an m by n matrix, A is a unit, or
|
|
* non-unit, upper or lower triangular matrix and op( A ) is one of
|
|
*
|
|
* op( A ) = A or op( A ) = A**T.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* SIDE - CHARACTER*1.
|
|
* On entry, SIDE specifies whether op( A ) multiplies B from
|
|
* the left or right as follows:
|
|
*
|
|
* SIDE = 'L' or 'l' B := alpha*op( A )*B.
|
|
*
|
|
* SIDE = 'R' or 'r' B := alpha*B*op( A ).
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* UPLO - CHARACTER*1.
|
|
* On entry, UPLO specifies whether the matrix A is an upper or
|
|
* lower triangular matrix as follows:
|
|
*
|
|
* UPLO = 'U' or 'u' A is an upper triangular matrix.
|
|
*
|
|
* UPLO = 'L' or 'l' A is a lower triangular matrix.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* TRANSA - CHARACTER*1.
|
|
* On entry, TRANSA specifies the form of op( A ) to be used in
|
|
* the matrix multiplication as follows:
|
|
*
|
|
* TRANSA = 'N' or 'n' op( A ) = A.
|
|
*
|
|
* TRANSA = 'T' or 't' op( A ) = A**T.
|
|
*
|
|
* TRANSA = 'C' or 'c' op( A ) = A**T.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* DIAG - CHARACTER*1.
|
|
* On entry, DIAG specifies whether or not A is unit triangular
|
|
* as follows:
|
|
*
|
|
* DIAG = 'U' or 'u' A is assumed to be unit triangular.
|
|
*
|
|
* DIAG = 'N' or 'n' A is not assumed to be unit
|
|
* triangular.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* M - INTEGER.
|
|
* On entry, M specifies the number of rows of B. M must be at
|
|
* least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the number of columns of B. N must be
|
|
* at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* ALPHA - DOUBLE PRECISION.
|
|
* On entry, ALPHA specifies the scalar alpha. When alpha is
|
|
* zero then A is not referenced and B need not be set before
|
|
* entry.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m
|
|
* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'.
|
|
* Before entry with UPLO = 'U' or 'u', the leading k by k
|
|
* upper triangular part of the array A must contain the upper
|
|
* triangular matrix and the strictly lower triangular part of
|
|
* A is not referenced.
|
|
* Before entry with UPLO = 'L' or 'l', the leading k by k
|
|
* lower triangular part of the array A must contain the lower
|
|
* triangular matrix and the strictly upper triangular part of
|
|
* A is not referenced.
|
|
* Note that when DIAG = 'U' or 'u', the diagonal elements of
|
|
* A are not referenced either, but are assumed to be unity.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. When SIDE = 'L' or 'l' then
|
|
* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r'
|
|
* then LDA must be at least max( 1, n ).
|
|
* Unchanged on exit.
|
|
*
|
|
* B - DOUBLE PRECISION array of DIMENSION ( LDB, n ).
|
|
* Before entry, the leading m by n part of the array B must
|
|
* contain the matrix B, and on exit is overwritten by the
|
|
* transformed matrix.
|
|
*
|
|
* LDB - INTEGER.
|
|
* On entry, LDB specifies the first dimension of B as declared
|
|
* in the calling (sub) program. LDB must be at least
|
|
* max( 1, m ).
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 3 Blas routine.
|
|
*
|
|
* -- Written on 8-February-1989.
|
|
* Jack Dongarra, Argonne National Laboratory.
|
|
* Iain Duff, AERE Harwell.
|
|
* Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
|
* Sven Hammarling, Numerical Algorithms Group Ltd.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP
|
|
INTEGER I,INFO,J,K,NROWA
|
|
LOGICAL LSIDE,NOUNIT,UPPER
|
|
* ..
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ONE,ZERO
|
|
PARAMETER (ONE=1.0D+0,ZERO=0.0D+0)
|
|
* ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
LSIDE = LSAME(SIDE,'L')
|
|
IF (LSIDE) THEN
|
|
NROWA = M
|
|
ELSE
|
|
NROWA = N
|
|
END IF
|
|
NOUNIT = LSAME(DIAG,'N')
|
|
UPPER = LSAME(UPLO,'U')
|
|
*
|
|
INFO = 0
|
|
IF ((.NOT.LSIDE) .AND. (.NOT.LSAME(SIDE,'R'))) THEN
|
|
INFO = 1
|
|
ELSE IF ((.NOT.UPPER) .AND. (.NOT.LSAME(UPLO,'L'))) THEN
|
|
INFO = 2
|
|
ELSE IF ((.NOT.LSAME(TRANSA,'N')) .AND.
|
|
+ (.NOT.LSAME(TRANSA,'T')) .AND.
|
|
+ (.NOT.LSAME(TRANSA,'C'))) THEN
|
|
INFO = 3
|
|
ELSE IF ((.NOT.LSAME(DIAG,'U')) .AND. (.NOT.LSAME(DIAG,'N'))) THEN
|
|
INFO = 4
|
|
ELSE IF (M.LT.0) THEN
|
|
INFO = 5
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 6
|
|
ELSE IF (LDA.LT.MAX(1,NROWA)) THEN
|
|
INFO = 9
|
|
ELSE IF (LDB.LT.MAX(1,M)) THEN
|
|
INFO = 11
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DTRMM ',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF (M.EQ.0 .OR. N.EQ.0) RETURN
|
|
*
|
|
* And when alpha.eq.zero.
|
|
*
|
|
IF (ALPHA.EQ.ZERO) THEN
|
|
DO 20 J = 1,N
|
|
DO 10 I = 1,M
|
|
B(I,J) = ZERO
|
|
10 CONTINUE
|
|
20 CONTINUE
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Start the operations.
|
|
*
|
|
IF (LSIDE) THEN
|
|
IF (LSAME(TRANSA,'N')) THEN
|
|
*
|
|
* Form B := alpha*A*B.
|
|
*
|
|
IF (UPPER) THEN
|
|
DO 50 J = 1,N
|
|
DO 40 K = 1,M
|
|
IF (B(K,J).NE.ZERO) THEN
|
|
TEMP = ALPHA*B(K,J)
|
|
DO 30 I = 1,K - 1
|
|
B(I,J) = B(I,J) + TEMP*A(I,K)
|
|
30 CONTINUE
|
|
IF (NOUNIT) TEMP = TEMP*A(K,K)
|
|
B(K,J) = TEMP
|
|
END IF
|
|
40 CONTINUE
|
|
50 CONTINUE
|
|
ELSE
|
|
DO 80 J = 1,N
|
|
DO 70 K = M,1,-1
|
|
IF (B(K,J).NE.ZERO) THEN
|
|
TEMP = ALPHA*B(K,J)
|
|
B(K,J) = TEMP
|
|
IF (NOUNIT) B(K,J) = B(K,J)*A(K,K)
|
|
DO 60 I = K + 1,M
|
|
B(I,J) = B(I,J) + TEMP*A(I,K)
|
|
60 CONTINUE
|
|
END IF
|
|
70 CONTINUE
|
|
80 CONTINUE
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form B := alpha*A**T*B.
|
|
*
|
|
IF (UPPER) THEN
|
|
DO 110 J = 1,N
|
|
DO 100 I = M,1,-1
|
|
TEMP = B(I,J)
|
|
IF (NOUNIT) TEMP = TEMP*A(I,I)
|
|
DO 90 K = 1,I - 1
|
|
TEMP = TEMP + A(K,I)*B(K,J)
|
|
90 CONTINUE
|
|
B(I,J) = ALPHA*TEMP
|
|
100 CONTINUE
|
|
110 CONTINUE
|
|
ELSE
|
|
DO 140 J = 1,N
|
|
DO 130 I = 1,M
|
|
TEMP = B(I,J)
|
|
IF (NOUNIT) TEMP = TEMP*A(I,I)
|
|
DO 120 K = I + 1,M
|
|
TEMP = TEMP + A(K,I)*B(K,J)
|
|
120 CONTINUE
|
|
B(I,J) = ALPHA*TEMP
|
|
130 CONTINUE
|
|
140 CONTINUE
|
|
END IF
|
|
END IF
|
|
ELSE
|
|
IF (LSAME(TRANSA,'N')) THEN
|
|
*
|
|
* Form B := alpha*B*A.
|
|
*
|
|
IF (UPPER) THEN
|
|
DO 180 J = N,1,-1
|
|
TEMP = ALPHA
|
|
IF (NOUNIT) TEMP = TEMP*A(J,J)
|
|
DO 150 I = 1,M
|
|
B(I,J) = TEMP*B(I,J)
|
|
150 CONTINUE
|
|
DO 170 K = 1,J - 1
|
|
IF (A(K,J).NE.ZERO) THEN
|
|
TEMP = ALPHA*A(K,J)
|
|
DO 160 I = 1,M
|
|
B(I,J) = B(I,J) + TEMP*B(I,K)
|
|
160 CONTINUE
|
|
END IF
|
|
170 CONTINUE
|
|
180 CONTINUE
|
|
ELSE
|
|
DO 220 J = 1,N
|
|
TEMP = ALPHA
|
|
IF (NOUNIT) TEMP = TEMP*A(J,J)
|
|
DO 190 I = 1,M
|
|
B(I,J) = TEMP*B(I,J)
|
|
190 CONTINUE
|
|
DO 210 K = J + 1,N
|
|
IF (A(K,J).NE.ZERO) THEN
|
|
TEMP = ALPHA*A(K,J)
|
|
DO 200 I = 1,M
|
|
B(I,J) = B(I,J) + TEMP*B(I,K)
|
|
200 CONTINUE
|
|
END IF
|
|
210 CONTINUE
|
|
220 CONTINUE
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form B := alpha*B*A**T.
|
|
*
|
|
IF (UPPER) THEN
|
|
DO 260 K = 1,N
|
|
DO 240 J = 1,K - 1
|
|
IF (A(J,K).NE.ZERO) THEN
|
|
TEMP = ALPHA*A(J,K)
|
|
DO 230 I = 1,M
|
|
B(I,J) = B(I,J) + TEMP*B(I,K)
|
|
230 CONTINUE
|
|
END IF
|
|
240 CONTINUE
|
|
TEMP = ALPHA
|
|
IF (NOUNIT) TEMP = TEMP*A(K,K)
|
|
IF (TEMP.NE.ONE) THEN
|
|
DO 250 I = 1,M
|
|
B(I,K) = TEMP*B(I,K)
|
|
250 CONTINUE
|
|
END IF
|
|
260 CONTINUE
|
|
ELSE
|
|
DO 300 K = N,1,-1
|
|
DO 280 J = K + 1,N
|
|
IF (A(J,K).NE.ZERO) THEN
|
|
TEMP = ALPHA*A(J,K)
|
|
DO 270 I = 1,M
|
|
B(I,J) = B(I,J) + TEMP*B(I,K)
|
|
270 CONTINUE
|
|
END IF
|
|
280 CONTINUE
|
|
TEMP = ALPHA
|
|
IF (NOUNIT) TEMP = TEMP*A(K,K)
|
|
IF (TEMP.NE.ONE) THEN
|
|
DO 290 I = 1,M
|
|
B(I,K) = TEMP*B(I,K)
|
|
290 CONTINUE
|
|
END IF
|
|
300 CONTINUE
|
|
END IF
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DTRMM .
|
|
*
|
|
END
|
|
SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX)
|
|
* .. Scalar Arguments ..
|
|
INTEGER INCX,LDA,N
|
|
CHARACTER DIAG,TRANS,UPLO
|
|
* ..
|
|
* .. Array Arguments ..
|
|
DOUBLE PRECISION A(LDA,*),X(*)
|
|
* ..
|
|
*
|
|
* Purpose
|
|
* =======
|
|
*
|
|
* DTRMV performs one of the matrix-vector operations
|
|
*
|
|
* x := A*x, or x := A**T*x,
|
|
*
|
|
* where x is an n element vector and A is an n by n unit, or non-unit,
|
|
* upper or lower triangular matrix.
|
|
*
|
|
* Arguments
|
|
* ==========
|
|
*
|
|
* UPLO - CHARACTER*1.
|
|
* On entry, UPLO specifies whether the matrix is an upper or
|
|
* lower triangular matrix as follows:
|
|
*
|
|
* UPLO = 'U' or 'u' A is an upper triangular matrix.
|
|
*
|
|
* UPLO = 'L' or 'l' A is a lower triangular matrix.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* TRANS - CHARACTER*1.
|
|
* On entry, TRANS specifies the operation to be performed as
|
|
* follows:
|
|
*
|
|
* TRANS = 'N' or 'n' x := A*x.
|
|
*
|
|
* TRANS = 'T' or 't' x := A**T*x.
|
|
*
|
|
* TRANS = 'C' or 'c' x := A**T*x.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* DIAG - CHARACTER*1.
|
|
* On entry, DIAG specifies whether or not A is unit
|
|
* triangular as follows:
|
|
*
|
|
* DIAG = 'U' or 'u' A is assumed to be unit triangular.
|
|
*
|
|
* DIAG = 'N' or 'n' A is not assumed to be unit
|
|
* triangular.
|
|
*
|
|
* Unchanged on exit.
|
|
*
|
|
* N - INTEGER.
|
|
* On entry, N specifies the order of the matrix A.
|
|
* N must be at least zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
|
|
* Before entry with UPLO = 'U' or 'u', the leading n by n
|
|
* upper triangular part of the array A must contain the upper
|
|
* triangular matrix and the strictly lower triangular part of
|
|
* A is not referenced.
|
|
* Before entry with UPLO = 'L' or 'l', the leading n by n
|
|
* lower triangular part of the array A must contain the lower
|
|
* triangular matrix and the strictly upper triangular part of
|
|
* A is not referenced.
|
|
* Note that when DIAG = 'U' or 'u', the diagonal elements of
|
|
* A are not referenced either, but are assumed to be unity.
|
|
* Unchanged on exit.
|
|
*
|
|
* LDA - INTEGER.
|
|
* On entry, LDA specifies the first dimension of A as declared
|
|
* in the calling (sub) program. LDA must be at least
|
|
* max( 1, n ).
|
|
* Unchanged on exit.
|
|
*
|
|
* X - DOUBLE PRECISION array of dimension at least
|
|
* ( 1 + ( n - 1 )*abs( INCX ) ).
|
|
* Before entry, the incremented array X must contain the n
|
|
* element vector x. On exit, X is overwritten with the
|
|
* tranformed vector x.
|
|
*
|
|
* INCX - INTEGER.
|
|
* On entry, INCX specifies the increment for the elements of
|
|
* X. INCX must not be zero.
|
|
* Unchanged on exit.
|
|
*
|
|
* Further Details
|
|
* ===============
|
|
*
|
|
* Level 2 Blas routine.
|
|
* The vector and matrix arguments are not referenced when N = 0, or M = 0
|
|
*
|
|
* -- Written on 22-October-1986.
|
|
* Jack Dongarra, Argonne National Lab.
|
|
* Jeremy Du Croz, Nag Central Office.
|
|
* Sven Hammarling, Nag Central Office.
|
|
* Richard Hanson, Sandia National Labs.
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
DOUBLE PRECISION ZERO
|
|
PARAMETER (ZERO=0.0D+0)
|
|
* ..
|
|
* .. Local Scalars ..
|
|
DOUBLE PRECISION TEMP
|
|
INTEGER I,INFO,IX,J,JX,KX
|
|
LOGICAL NOUNIT
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
EXTERNAL LSAME
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX
|
|
* ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
INFO = 0
|
|
IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN
|
|
INFO = 1
|
|
ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND.
|
|
+ .NOT.LSAME(TRANS,'C')) THEN
|
|
INFO = 2
|
|
ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN
|
|
INFO = 3
|
|
ELSE IF (N.LT.0) THEN
|
|
INFO = 4
|
|
ELSE IF (LDA.LT.MAX(1,N)) THEN
|
|
INFO = 6
|
|
ELSE IF (INCX.EQ.0) THEN
|
|
INFO = 8
|
|
END IF
|
|
IF (INFO.NE.0) THEN
|
|
CALL XERBLA('DTRMV ',INFO)
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible.
|
|
*
|
|
IF (N.EQ.0) RETURN
|
|
*
|
|
NOUNIT = LSAME(DIAG,'N')
|
|
*
|
|
* Set up the start point in X if the increment is not unity. This
|
|
* will be ( N - 1 )*INCX too small for descending loops.
|
|
*
|
|
IF (INCX.LE.0) THEN
|
|
KX = 1 - (N-1)*INCX
|
|
ELSE IF (INCX.NE.1) THEN
|
|
KX = 1
|
|
END IF
|
|
*
|
|
* Start the operations. In this version the elements of A are
|
|
* accessed sequentially with one pass through A.
|
|
*
|
|
IF (LSAME(TRANS,'N')) THEN
|
|
*
|
|
* Form x := A*x.
|
|
*
|
|
IF (LSAME(UPLO,'U')) THEN
|
|
IF (INCX.EQ.1) THEN
|
|
DO 20 J = 1,N
|
|
IF (X(J).NE.ZERO) THEN
|
|
TEMP = X(J)
|
|
DO 10 I = 1,J - 1
|
|
X(I) = X(I) + TEMP*A(I,J)
|
|
10 CONTINUE
|
|
IF (NOUNIT) X(J) = X(J)*A(J,J)
|
|
END IF
|
|
20 CONTINUE
|
|
ELSE
|
|
JX = KX
|
|
DO 40 J = 1,N
|
|
IF (X(JX).NE.ZERO) THEN
|
|
TEMP = X(JX)
|
|
IX = KX
|
|
DO 30 I = 1,J - 1
|
|
X(IX) = X(IX) + TEMP*A(I,J)
|
|
IX = IX + INCX
|
|
30 CONTINUE
|
|
IF (NOUNIT) X(JX) = X(JX)*A(J,J)
|
|
END IF
|
|
JX = JX + INCX
|
|
40 CONTINUE
|
|
END IF
|
|
ELSE
|
|
IF (INCX.EQ.1) THEN
|
|
DO 60 J = N,1,-1
|
|
IF (X(J).NE.ZERO) THEN
|
|
TEMP = X(J)
|
|
DO 50 I = N,J + 1,-1
|
|
X(I) = X(I) + TEMP*A(I,J)
|
|
50 CONTINUE
|
|
IF (NOUNIT) X(J) = X(J)*A(J,J)
|
|
END IF
|
|
60 CONTINUE
|
|
ELSE
|
|
KX = KX + (N-1)*INCX
|
|
JX = KX
|
|
DO 80 J = N,1,-1
|
|
IF (X(JX).NE.ZERO) THEN
|
|
TEMP = X(JX)
|
|
IX = KX
|
|
DO 70 I = N,J + 1,-1
|
|
X(IX) = X(IX) + TEMP*A(I,J)
|
|
IX = IX - INCX
|
|
70 CONTINUE
|
|
IF (NOUNIT) X(JX) = X(JX)*A(J,J)
|
|
END IF
|
|
JX = JX - INCX
|
|
80 CONTINUE
|
|
END IF
|
|
END IF
|
|
ELSE
|
|
*
|
|
* Form x := A**T*x.
|
|
*
|
|
IF (LSAME(UPLO,'U')) THEN
|
|
IF (INCX.EQ.1) THEN
|
|
DO 100 J = N,1,-1
|
|
TEMP = X(J)
|
|
IF (NOUNIT) TEMP = TEMP*A(J,J)
|
|
DO 90 I = J - 1,1,-1
|
|
TEMP = TEMP + A(I,J)*X(I)
|
|
90 CONTINUE
|
|
X(J) = TEMP
|
|
100 CONTINUE
|
|
ELSE
|
|
JX = KX + (N-1)*INCX
|
|
DO 120 J = N,1,-1
|
|
TEMP = X(JX)
|
|
IX = JX
|
|
IF (NOUNIT) TEMP = TEMP*A(J,J)
|
|
DO 110 I = J - 1,1,-1
|
|
IX = IX - INCX
|
|
TEMP = TEMP + A(I,J)*X(IX)
|
|
110 CONTINUE
|
|
X(JX) = TEMP
|
|
JX = JX - INCX
|
|
120 CONTINUE
|
|
END IF
|
|
ELSE
|
|
IF (INCX.EQ.1) THEN
|
|
DO 140 J = 1,N
|
|
TEMP = X(J)
|
|
IF (NOUNIT) TEMP = TEMP*A(J,J)
|
|
DO 130 I = J + 1,N
|
|
TEMP = TEMP + A(I,J)*X(I)
|
|
130 CONTINUE
|
|
X(J) = TEMP
|
|
140 CONTINUE
|
|
ELSE
|
|
JX = KX
|
|
DO 160 J = 1,N
|
|
TEMP = X(JX)
|
|
IX = JX
|
|
IF (NOUNIT) TEMP = TEMP*A(J,J)
|
|
DO 150 I = J + 1,N
|
|
IX = IX + INCX
|
|
TEMP = TEMP + A(I,J)*X(IX)
|
|
150 CONTINUE
|
|
X(JX) = TEMP
|
|
JX = JX + INCX
|
|
160 CONTINUE
|
|
END IF
|
|
END IF
|
|
END IF
|
|
*
|
|
RETURN
|
|
*
|
|
* End of DTRMV .
|
|
*
|
|
END
|