diff options
Diffstat (limited to 'TESTING/LIN/cpst01.f')
-rw-r--r-- | TESTING/LIN/cpst01.f | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/TESTING/LIN/cpst01.f b/TESTING/LIN/cpst01.f new file mode 100644 index 00000000..70891d92 --- /dev/null +++ b/TESTING/LIN/cpst01.f @@ -0,0 +1,243 @@ + SUBROUTINE CPST01( UPLO, N, A, LDA, AFAC, LDAFAC, PERM, LDPERM, + $ PIV, RWORK, RESID, RANK ) +* +* -- LAPACK test routine (version 3.1) -- +* Craig Lucas, University of Manchester / NAG Ltd. +* October, 2008 +* +* .. Scalar Arguments .. + REAL RESID + INTEGER LDA, LDAFAC, LDPERM, N, RANK + CHARACTER UPLO +* .. +* .. Array Arguments .. + COMPLEX A( LDA, * ), AFAC( LDAFAC, * ), + $ PERM( LDPERM, * ) + REAL RWORK( * ) + INTEGER PIV( * ) +* .. +* +* Purpose +* ======= +* +* CPST01 reconstructs an Hermitian positive semidefinite matrix A +* from its L or U factors and the permutation matrix P and computes +* the residual +* norm( P*L*L'*P' - A ) / ( N * norm(A) * EPS ) or +* norm( P*U'*U*P' - A ) / ( N * norm(A) * EPS ), +* where EPS is the machine epsilon, L' is the conjugate transpose of L, +* and U' is the conjugate transpose of U. +* +* Arguments +* ========== +* +* UPLO (input) CHARACTER*1 +* Specifies whether the upper or lower triangular part of the +* Hermitian matrix A is stored: +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The number of rows and columns of the matrix A. N >= 0. +* +* A (input) COMPLEX array, dimension (LDA,N) +* The original Hermitian matrix A. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N) +* +* AFAC (input) COMPLEX array, dimension (LDAFAC,N) +* The factor L or U from the L*L' or U'*U +* factorization of A. +* +* LDAFAC (input) INTEGER +* The leading dimension of the array AFAC. LDAFAC >= max(1,N). +* +* PERM (output) COMPLEX array, dimension (LDPERM,N) +* Overwritten with the reconstructed matrix, and then with the +* difference P*L*L'*P' - A (or P*U'*U*P' - A) +* +* LDPERM (input) INTEGER +* The leading dimension of the array PERM. +* LDAPERM >= max(1,N). +* +* PIV (input) INTEGER array, dimension (N) +* PIV is such that the nonzero entries are +* P( PIV( K ), K ) = 1. +* +* RWORK (workspace) REAL array, dimension (N) +* +* RESID (output) REAL +* If UPLO = 'L', norm(L*L' - A) / ( N * norm(A) * EPS ) +* If UPLO = 'U', norm(U'*U - A) / ( N * norm(A) * EPS ) +* +* ===================================================================== +* +* .. Parameters .. + REAL ZERO, ONE + PARAMETER ( ZERO = 0.0E+0, ONE = 1.0E+0 ) + COMPLEX CZERO + PARAMETER ( CZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. +* .. Local Scalars .. + COMPLEX TC + REAL ANORM, EPS, TR + INTEGER I, J, K +* .. +* .. External Functions .. + COMPLEX CDOTC + REAL CLANHE, SLAMCH + LOGICAL LSAME + EXTERNAL CDOTC, CLANHE, SLAMCH, LSAME +* .. +* .. External Subroutines .. + EXTERNAL CHER, CSCAL, CTRMV +* .. +* .. Intrinsic Functions .. + INTRINSIC AIMAG, CONJG, REAL +* .. +* .. Executable Statements .. +* +* Quick exit if N = 0. +* + IF( N.LE.0 ) THEN + RESID = ZERO + RETURN + END IF +* +* Exit with RESID = 1/EPS if ANORM = 0. +* + EPS = SLAMCH( 'Epsilon' ) + ANORM = CLANHE( '1', UPLO, N, A, LDA, RWORK ) + IF( ANORM.LE.ZERO ) THEN + RESID = ONE / EPS + RETURN + END IF +* +* Check the imaginary parts of the diagonal elements and return with +* an error code if any are nonzero. +* + DO 100 J = 1, N + IF( AIMAG( AFAC( J, J ) ).NE.ZERO ) THEN + RESID = ONE / EPS + RETURN + END IF + 100 CONTINUE +* +* Compute the product U'*U, overwriting U. +* + IF( LSAME( UPLO, 'U' ) ) THEN +* + IF( RANK.LT.N ) THEN + DO 120 J = RANK + 1, N + DO 110 I = RANK + 1, J + AFAC( I, J ) = CZERO + 110 CONTINUE + 120 CONTINUE + END IF +* + DO 130 K = N, 1, -1 +* +* Compute the (K,K) element of the result. +* + TR = CDOTC( K, AFAC( 1, K ), 1, AFAC( 1, K ), 1 ) + AFAC( K, K ) = TR +* +* Compute the rest of column K. +* + CALL CTRMV( 'Upper', 'Conjugate', 'Non-unit', K-1, AFAC, + $ LDAFAC, AFAC( 1, K ), 1 ) +* + 130 CONTINUE +* +* Compute the product L*L', overwriting L. +* + ELSE +* + IF( RANK.LT.N ) THEN + DO 150 J = RANK + 1, N + DO 140 I = J, N + AFAC( I, J ) = CZERO + 140 CONTINUE + 150 CONTINUE + END IF +* + DO 160 K = N, 1, -1 +* Add a multiple of column K of the factor L to each of +* columns K+1 through N. +* + IF( K+1.LE.N ) + $ CALL CHER( 'Lower', N-K, ONE, AFAC( K+1, K ), 1, + $ AFAC( K+1, K+1 ), LDAFAC ) +* +* Scale column K by the diagonal element. +* + TC = AFAC( K, K ) + CALL CSCAL( N-K+1, TC, AFAC( K, K ), 1 ) + 160 CONTINUE +* + END IF +* +* Form P*L*L'*P' or P*U'*U*P' +* + IF( LSAME( UPLO, 'U' ) ) THEN +* + DO 180 J = 1, N + DO 170 I = 1, N + IF( PIV( I ).LE.PIV( J ) ) THEN + IF( I.LE.J ) THEN + PERM( PIV( I ), PIV( J ) ) = AFAC( I, J ) + ELSE + PERM( PIV( I ), PIV( J ) ) = CONJG( AFAC( J, I ) ) + END IF + END IF + 170 CONTINUE + 180 CONTINUE +* +* + ELSE +* + DO 200 J = 1, N + DO 190 I = 1, N + IF( PIV( I ).GE.PIV( J ) ) THEN + IF( I.GE.J ) THEN + PERM( PIV( I ), PIV( J ) ) = AFAC( I, J ) + ELSE + PERM( PIV( I ), PIV( J ) ) = CONJG( AFAC( J, I ) ) + END IF + END IF + 190 CONTINUE + 200 CONTINUE +* + END IF +* +* Compute the difference P*L*L'*P' - A (or P*U'*U*P' - A). +* + IF( LSAME( UPLO, 'U' ) ) THEN + DO 220 J = 1, N + DO 210 I = 1, J - 1 + PERM( I, J ) = PERM( I, J ) - A( I, J ) + 210 CONTINUE + PERM( J, J ) = PERM( J, J ) - REAL( A( J, J ) ) + 220 CONTINUE + ELSE + DO 240 J = 1, N + PERM( J, J ) = PERM( J, J ) - REAL( A( J, J ) ) + DO 230 I = J + 1, N + PERM( I, J ) = PERM( I, J ) - A( I, J ) + 230 CONTINUE + 240 CONTINUE + END IF +* +* Compute norm( P*L*L'P - A ) / ( N * norm(A) * EPS ), or +* ( P*U'*U*P' - A )/ ( N * norm(A) * EPS ). +* + RESID = CLANHE( '1', UPLO, N, PERM, LDAFAC, RWORK ) +* + RESID = ( ( RESID / REAL( N ) ) / ANORM ) / EPS +* + RETURN +* +* End of CPST01 +* + END |