LAPACK 3.3.0
|
00001 SUBROUTINE ZPST01( UPLO, N, A, LDA, AFAC, LDAFAC, PERM, LDPERM, 00002 $ PIV, RWORK, RESID, RANK ) 00003 * 00004 * -- LAPACK test routine (version 3.1) -- 00005 * Craig Lucas, University of Manchester / NAG Ltd. 00006 * October, 2008 00007 * 00008 * .. Scalar Arguments .. 00009 DOUBLE PRECISION RESID 00010 INTEGER LDA, LDAFAC, LDPERM, N, RANK 00011 CHARACTER UPLO 00012 * .. 00013 * .. Array Arguments .. 00014 COMPLEX*16 A( LDA, * ), AFAC( LDAFAC, * ), 00015 $ PERM( LDPERM, * ) 00016 DOUBLE PRECISION RWORK( * ) 00017 INTEGER PIV( * ) 00018 * .. 00019 * 00020 * Purpose 00021 * ======= 00022 * 00023 * ZPST01 reconstructs an Hermitian positive semidefinite matrix A 00024 * from its L or U factors and the permutation matrix P and computes 00025 * the residual 00026 * norm( P*L*L'*P' - A ) / ( N * norm(A) * EPS ) or 00027 * norm( P*U'*U*P' - A ) / ( N * norm(A) * EPS ), 00028 * where EPS is the machine epsilon, L' is the conjugate transpose of L, 00029 * and U' is the conjugate transpose of U. 00030 * 00031 * Arguments 00032 * ========== 00033 * 00034 * UPLO (input) CHARACTER*1 00035 * Specifies whether the upper or lower triangular part of the 00036 * Hermitian matrix A is stored: 00037 * = 'U': Upper triangular 00038 * = 'L': Lower triangular 00039 * 00040 * N (input) INTEGER 00041 * The number of rows and columns of the matrix A. N >= 0. 00042 * 00043 * A (input) COMPLEX*16 array, dimension (LDA,N) 00044 * The original Hermitian matrix A. 00045 * 00046 * LDA (input) INTEGER 00047 * The leading dimension of the array A. LDA >= max(1,N) 00048 * 00049 * AFAC (input) COMPLEX*16 array, dimension (LDAFAC,N) 00050 * The factor L or U from the L*L' or U'*U 00051 * factorization of A. 00052 * 00053 * LDAFAC (input) INTEGER 00054 * The leading dimension of the array AFAC. LDAFAC >= max(1,N). 00055 * 00056 * PERM (output) COMPLEX*16 array, dimension (LDPERM,N) 00057 * Overwritten with the reconstructed matrix, and then with the 00058 * difference P*L*L'*P' - A (or P*U'*U*P' - A) 00059 * 00060 * LDPERM (input) INTEGER 00061 * The leading dimension of the array PERM. 00062 * LDAPERM >= max(1,N). 00063 * 00064 * PIV (input) INTEGER array, dimension (N) 00065 * PIV is such that the nonzero entries are 00066 * P( PIV( K ), K ) = 1. 00067 * 00068 * RWORK (workspace) DOUBLE PRECISION array, dimension (N) 00069 * 00070 * RESID (output) DOUBLE PRECISION 00071 * If UPLO = 'L', norm(L*L' - A) / ( N * norm(A) * EPS ) 00072 * If UPLO = 'U', norm(U'*U - A) / ( N * norm(A) * EPS ) 00073 * 00074 * ===================================================================== 00075 * 00076 * .. Parameters .. 00077 DOUBLE PRECISION ZERO, ONE 00078 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) 00079 COMPLEX*16 CZERO 00080 PARAMETER ( CZERO = ( 0.0D+0, 0.0D+0 ) ) 00081 * .. 00082 * .. Local Scalars .. 00083 COMPLEX*16 TC 00084 DOUBLE PRECISION ANORM, EPS, TR 00085 INTEGER I, J, K 00086 * .. 00087 * .. External Functions .. 00088 COMPLEX*16 ZDOTC 00089 DOUBLE PRECISION DLAMCH, ZLANHE 00090 LOGICAL LSAME 00091 EXTERNAL ZDOTC, DLAMCH, ZLANHE, LSAME 00092 * .. 00093 * .. External Subroutines .. 00094 EXTERNAL ZHER, ZSCAL, ZTRMV 00095 * .. 00096 * .. Intrinsic Functions .. 00097 INTRINSIC DBLE, DCONJG, DIMAG 00098 * .. 00099 * .. Executable Statements .. 00100 * 00101 * Quick exit if N = 0. 00102 * 00103 IF( N.LE.0 ) THEN 00104 RESID = ZERO 00105 RETURN 00106 END IF 00107 * 00108 * Exit with RESID = 1/EPS if ANORM = 0. 00109 * 00110 EPS = DLAMCH( 'Epsilon' ) 00111 ANORM = ZLANHE( '1', UPLO, N, A, LDA, RWORK ) 00112 IF( ANORM.LE.ZERO ) THEN 00113 RESID = ONE / EPS 00114 RETURN 00115 END IF 00116 * 00117 * Check the imaginary parts of the diagonal elements and return with 00118 * an error code if any are nonzero. 00119 * 00120 DO 100 J = 1, N 00121 IF( DIMAG( AFAC( J, J ) ).NE.ZERO ) THEN 00122 RESID = ONE / EPS 00123 RETURN 00124 END IF 00125 100 CONTINUE 00126 * 00127 * Compute the product U'*U, overwriting U. 00128 * 00129 IF( LSAME( UPLO, 'U' ) ) THEN 00130 * 00131 IF( RANK.LT.N ) THEN 00132 DO 120 J = RANK + 1, N 00133 DO 110 I = RANK + 1, J 00134 AFAC( I, J ) = CZERO 00135 110 CONTINUE 00136 120 CONTINUE 00137 END IF 00138 * 00139 DO 130 K = N, 1, -1 00140 * 00141 * Compute the (K,K) element of the result. 00142 * 00143 TR = ZDOTC( K, AFAC( 1, K ), 1, AFAC( 1, K ), 1 ) 00144 AFAC( K, K ) = TR 00145 * 00146 * Compute the rest of column K. 00147 * 00148 CALL ZTRMV( 'Upper', 'Conjugate', 'Non-unit', K-1, AFAC, 00149 $ LDAFAC, AFAC( 1, K ), 1 ) 00150 * 00151 130 CONTINUE 00152 * 00153 * Compute the product L*L', overwriting L. 00154 * 00155 ELSE 00156 * 00157 IF( RANK.LT.N ) THEN 00158 DO 150 J = RANK + 1, N 00159 DO 140 I = J, N 00160 AFAC( I, J ) = CZERO 00161 140 CONTINUE 00162 150 CONTINUE 00163 END IF 00164 * 00165 DO 160 K = N, 1, -1 00166 * Add a multiple of column K of the factor L to each of 00167 * columns K+1 through N. 00168 * 00169 IF( K+1.LE.N ) 00170 $ CALL ZHER( 'Lower', N-K, ONE, AFAC( K+1, K ), 1, 00171 $ AFAC( K+1, K+1 ), LDAFAC ) 00172 * 00173 * Scale column K by the diagonal element. 00174 * 00175 TC = AFAC( K, K ) 00176 CALL ZSCAL( N-K+1, TC, AFAC( K, K ), 1 ) 00177 160 CONTINUE 00178 * 00179 END IF 00180 * 00181 * Form P*L*L'*P' or P*U'*U*P' 00182 * 00183 IF( LSAME( UPLO, 'U' ) ) THEN 00184 * 00185 DO 180 J = 1, N 00186 DO 170 I = 1, N 00187 IF( PIV( I ).LE.PIV( J ) ) THEN 00188 IF( I.LE.J ) THEN 00189 PERM( PIV( I ), PIV( J ) ) = AFAC( I, J ) 00190 ELSE 00191 PERM( PIV( I ), PIV( J ) ) = DCONJG( AFAC( J, I ) ) 00192 END IF 00193 END IF 00194 170 CONTINUE 00195 180 CONTINUE 00196 * 00197 * 00198 ELSE 00199 * 00200 DO 200 J = 1, N 00201 DO 190 I = 1, N 00202 IF( PIV( I ).GE.PIV( J ) ) THEN 00203 IF( I.GE.J ) THEN 00204 PERM( PIV( I ), PIV( J ) ) = AFAC( I, J ) 00205 ELSE 00206 PERM( PIV( I ), PIV( J ) ) = DCONJG( AFAC( J, I ) ) 00207 END IF 00208 END IF 00209 190 CONTINUE 00210 200 CONTINUE 00211 * 00212 END IF 00213 * 00214 * Compute the difference P*L*L'*P' - A (or P*U'*U*P' - A). 00215 * 00216 IF( LSAME( UPLO, 'U' ) ) THEN 00217 DO 220 J = 1, N 00218 DO 210 I = 1, J - 1 00219 PERM( I, J ) = PERM( I, J ) - A( I, J ) 00220 210 CONTINUE 00221 PERM( J, J ) = PERM( J, J ) - DBLE( A( J, J ) ) 00222 220 CONTINUE 00223 ELSE 00224 DO 240 J = 1, N 00225 PERM( J, J ) = PERM( J, J ) - DBLE( A( J, J ) ) 00226 DO 230 I = J + 1, N 00227 PERM( I, J ) = PERM( I, J ) - A( I, J ) 00228 230 CONTINUE 00229 240 CONTINUE 00230 END IF 00231 * 00232 * Compute norm( P*L*L'P - A ) / ( N * norm(A) * EPS ), or 00233 * ( P*U'*U*P' - A )/ ( N * norm(A) * EPS ). 00234 * 00235 RESID = ZLANHE( '1', UPLO, N, PERM, LDAFAC, RWORK ) 00236 * 00237 RESID = ( ( RESID / DBLE( N ) ) / ANORM ) / EPS 00238 * 00239 RETURN 00240 * 00241 * End of ZPST01 00242 * 00243 END