LAPACK 3.3.1
Linear Algebra PACKage
|
00001 SUBROUTINE CPSTF2( UPLO, N, A, LDA, PIV, RANK, TOL, WORK, INFO ) 00002 * 00003 * -- LAPACK PROTOTYPE routine (version 3.2.2) -- 00004 * Craig Lucas, University of Manchester / NAG Ltd. 00005 * October, 2008 00006 * 00007 * .. Scalar Arguments .. 00008 REAL TOL 00009 INTEGER INFO, LDA, N, RANK 00010 CHARACTER UPLO 00011 * .. 00012 * .. Array Arguments .. 00013 COMPLEX A( LDA, * ) 00014 REAL WORK( 2*N ) 00015 INTEGER PIV( N ) 00016 * .. 00017 * 00018 * Purpose 00019 * ======= 00020 * 00021 * CPSTF2 computes the Cholesky factorization with complete 00022 * pivoting of a complex Hermitian positive semidefinite matrix A. 00023 * 00024 * The factorization has the form 00025 * P**T * A * P = U**H * U , if UPLO = 'U', 00026 * P**T * A * P = L * L**H, if UPLO = 'L', 00027 * where U is an upper triangular matrix and L is lower triangular, and 00028 * P is stored as vector PIV. 00029 * 00030 * This algorithm does not attempt to check that A is positive 00031 * semidefinite. This version of the algorithm calls level 2 BLAS. 00032 * 00033 * Arguments 00034 * ========= 00035 * 00036 * UPLO (input) CHARACTER*1 00037 * Specifies whether the upper or lower triangular part of the 00038 * symmetric matrix A is stored. 00039 * = 'U': Upper triangular 00040 * = 'L': Lower triangular 00041 * 00042 * N (input) INTEGER 00043 * The order of the matrix A. N >= 0. 00044 * 00045 * A (input/output) COMPLEX array, dimension (LDA,N) 00046 * On entry, the symmetric matrix A. If UPLO = 'U', the leading 00047 * n by n upper triangular part of A contains the upper 00048 * triangular part of the matrix A, and the strictly lower 00049 * triangular part of A is not referenced. If UPLO = 'L', the 00050 * leading n by n lower triangular part of A contains the lower 00051 * triangular part of the matrix A, and the strictly upper 00052 * triangular part of A is not referenced. 00053 * 00054 * On exit, if INFO = 0, the factor U or L from the Cholesky 00055 * factorization as above. 00056 * 00057 * PIV (output) INTEGER array, dimension (N) 00058 * PIV is such that the nonzero entries are P( PIV(K), K ) = 1. 00059 * 00060 * RANK (output) INTEGER 00061 * The rank of A given by the number of steps the algorithm 00062 * completed. 00063 * 00064 * TOL (input) REAL 00065 * User defined tolerance. If TOL < 0, then N*U*MAX( A( K,K ) ) 00066 * will be used. The algorithm terminates at the (K-1)st step 00067 * if the pivot <= TOL. 00068 * 00069 * LDA (input) INTEGER 00070 * The leading dimension of the array A. LDA >= max(1,N). 00071 * 00072 * WORK (workspace) REAL array, dimension (2*N) 00073 * Work space. 00074 * 00075 * INFO (output) INTEGER 00076 * < 0: If INFO = -K, the K-th argument had an illegal value, 00077 * = 0: algorithm completed successfully, and 00078 * > 0: the matrix A is either rank deficient with computed rank 00079 * as returned in RANK, or is indefinite. See Section 7 of 00080 * LAPACK Working Note #161 for further information. 00081 * 00082 * ===================================================================== 00083 * 00084 * .. Parameters .. 00085 REAL ONE, ZERO 00086 PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) 00087 COMPLEX CONE 00088 PARAMETER ( CONE = ( 1.0E+0, 0.0E+0 ) ) 00089 * .. 00090 * .. Local Scalars .. 00091 COMPLEX CTEMP 00092 REAL AJJ, SSTOP, STEMP 00093 INTEGER I, ITEMP, J, PVT 00094 LOGICAL UPPER 00095 * .. 00096 * .. External Functions .. 00097 REAL SLAMCH 00098 LOGICAL LSAME, SISNAN 00099 EXTERNAL SLAMCH, LSAME, SISNAN 00100 * .. 00101 * .. External Subroutines .. 00102 EXTERNAL CGEMV, CLACGV, CSSCAL, CSWAP, XERBLA 00103 * .. 00104 * .. Intrinsic Functions .. 00105 INTRINSIC CONJG, MAX, REAL, SQRT 00106 * .. 00107 * .. Executable Statements .. 00108 * 00109 * Test the input parameters 00110 * 00111 INFO = 0 00112 UPPER = LSAME( UPLO, 'U' ) 00113 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN 00114 INFO = -1 00115 ELSE IF( N.LT.0 ) THEN 00116 INFO = -2 00117 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN 00118 INFO = -4 00119 END IF 00120 IF( INFO.NE.0 ) THEN 00121 CALL XERBLA( 'CPSTF2', -INFO ) 00122 RETURN 00123 END IF 00124 * 00125 * Quick return if possible 00126 * 00127 IF( N.EQ.0 ) 00128 $ RETURN 00129 * 00130 * Initialize PIV 00131 * 00132 DO 100 I = 1, N 00133 PIV( I ) = I 00134 100 CONTINUE 00135 * 00136 * Compute stopping value 00137 * 00138 DO 110 I = 1, N 00139 WORK( I ) = REAL( A( I, I ) ) 00140 110 CONTINUE 00141 PVT = MAXLOC( WORK( 1:N ), 1 ) 00142 AJJ = REAL ( A( PVT, PVT ) ) 00143 IF( AJJ.EQ.ZERO.OR.SISNAN( AJJ ) ) THEN 00144 RANK = 0 00145 INFO = 1 00146 GO TO 200 00147 END IF 00148 * 00149 * Compute stopping value if not supplied 00150 * 00151 IF( TOL.LT.ZERO ) THEN 00152 SSTOP = N * SLAMCH( 'Epsilon' ) * AJJ 00153 ELSE 00154 SSTOP = TOL 00155 END IF 00156 * 00157 * Set first half of WORK to zero, holds dot products 00158 * 00159 DO 120 I = 1, N 00160 WORK( I ) = 0 00161 120 CONTINUE 00162 * 00163 IF( UPPER ) THEN 00164 * 00165 * Compute the Cholesky factorization P**T * A * P = U**H * U 00166 * 00167 DO 150 J = 1, N 00168 * 00169 * Find pivot, test for exit, else swap rows and columns 00170 * Update dot products, compute possible pivots which are 00171 * stored in the second half of WORK 00172 * 00173 DO 130 I = J, N 00174 * 00175 IF( J.GT.1 ) THEN 00176 WORK( I ) = WORK( I ) + 00177 $ REAL( CONJG( A( J-1, I ) )* 00178 $ A( J-1, I ) ) 00179 END IF 00180 WORK( N+I ) = REAL( A( I, I ) ) - WORK( I ) 00181 * 00182 130 CONTINUE 00183 * 00184 IF( J.GT.1 ) THEN 00185 ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 ) 00186 PVT = ITEMP + J - 1 00187 AJJ = WORK( N+PVT ) 00188 IF( AJJ.LE.SSTOP.OR.SISNAN( AJJ ) ) THEN 00189 A( J, J ) = AJJ 00190 GO TO 190 00191 END IF 00192 END IF 00193 * 00194 IF( J.NE.PVT ) THEN 00195 * 00196 * Pivot OK, so can now swap pivot rows and columns 00197 * 00198 A( PVT, PVT ) = A( J, J ) 00199 CALL CSWAP( J-1, A( 1, J ), 1, A( 1, PVT ), 1 ) 00200 IF( PVT.LT.N ) 00201 $ CALL CSWAP( N-PVT, A( J, PVT+1 ), LDA, 00202 $ A( PVT, PVT+1 ), LDA ) 00203 DO 140 I = J + 1, PVT - 1 00204 CTEMP = CONJG( A( J, I ) ) 00205 A( J, I ) = CONJG( A( I, PVT ) ) 00206 A( I, PVT ) = CTEMP 00207 140 CONTINUE 00208 A( J, PVT ) = CONJG( A( J, PVT ) ) 00209 * 00210 * Swap dot products and PIV 00211 * 00212 STEMP = WORK( J ) 00213 WORK( J ) = WORK( PVT ) 00214 WORK( PVT ) = STEMP 00215 ITEMP = PIV( PVT ) 00216 PIV( PVT ) = PIV( J ) 00217 PIV( J ) = ITEMP 00218 END IF 00219 * 00220 AJJ = SQRT( AJJ ) 00221 A( J, J ) = AJJ 00222 * 00223 * Compute elements J+1:N of row J 00224 * 00225 IF( J.LT.N ) THEN 00226 CALL CLACGV( J-1, A( 1, J ), 1 ) 00227 CALL CGEMV( 'Trans', J-1, N-J, -CONE, A( 1, J+1 ), LDA, 00228 $ A( 1, J ), 1, CONE, A( J, J+1 ), LDA ) 00229 CALL CLACGV( J-1, A( 1, J ), 1 ) 00230 CALL CSSCAL( N-J, ONE / AJJ, A( J, J+1 ), LDA ) 00231 END IF 00232 * 00233 150 CONTINUE 00234 * 00235 ELSE 00236 * 00237 * Compute the Cholesky factorization P**T * A * P = L * L**H 00238 * 00239 DO 180 J = 1, N 00240 * 00241 * Find pivot, test for exit, else swap rows and columns 00242 * Update dot products, compute possible pivots which are 00243 * stored in the second half of WORK 00244 * 00245 DO 160 I = J, N 00246 * 00247 IF( J.GT.1 ) THEN 00248 WORK( I ) = WORK( I ) + 00249 $ REAL( CONJG( A( I, J-1 ) )* 00250 $ A( I, J-1 ) ) 00251 END IF 00252 WORK( N+I ) = REAL( A( I, I ) ) - WORK( I ) 00253 * 00254 160 CONTINUE 00255 * 00256 IF( J.GT.1 ) THEN 00257 ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 ) 00258 PVT = ITEMP + J - 1 00259 AJJ = WORK( N+PVT ) 00260 IF( AJJ.LE.SSTOP.OR.SISNAN( AJJ ) ) THEN 00261 A( J, J ) = AJJ 00262 GO TO 190 00263 END IF 00264 END IF 00265 * 00266 IF( J.NE.PVT ) THEN 00267 * 00268 * Pivot OK, so can now swap pivot rows and columns 00269 * 00270 A( PVT, PVT ) = A( J, J ) 00271 CALL CSWAP( J-1, A( J, 1 ), LDA, A( PVT, 1 ), LDA ) 00272 IF( PVT.LT.N ) 00273 $ CALL CSWAP( N-PVT, A( PVT+1, J ), 1, A( PVT+1, PVT ), 00274 $ 1 ) 00275 DO 170 I = J + 1, PVT - 1 00276 CTEMP = CONJG( A( I, J ) ) 00277 A( I, J ) = CONJG( A( PVT, I ) ) 00278 A( PVT, I ) = CTEMP 00279 170 CONTINUE 00280 A( PVT, J ) = CONJG( A( PVT, J ) ) 00281 * 00282 * Swap dot products and PIV 00283 * 00284 STEMP = WORK( J ) 00285 WORK( J ) = WORK( PVT ) 00286 WORK( PVT ) = STEMP 00287 ITEMP = PIV( PVT ) 00288 PIV( PVT ) = PIV( J ) 00289 PIV( J ) = ITEMP 00290 END IF 00291 * 00292 AJJ = SQRT( AJJ ) 00293 A( J, J ) = AJJ 00294 * 00295 * Compute elements J+1:N of column J 00296 * 00297 IF( J.LT.N ) THEN 00298 CALL CLACGV( J-1, A( J, 1 ), LDA ) 00299 CALL CGEMV( 'No Trans', N-J, J-1, -CONE, A( J+1, 1 ), 00300 $ LDA, A( J, 1 ), LDA, CONE, A( J+1, J ), 1 ) 00301 CALL CLACGV( J-1, A( J, 1 ), LDA ) 00302 CALL CSSCAL( N-J, ONE / AJJ, A( J+1, J ), 1 ) 00303 END IF 00304 * 00305 180 CONTINUE 00306 * 00307 END IF 00308 * 00309 * Ran to completion, A has full rank 00310 * 00311 RANK = N 00312 * 00313 GO TO 200 00314 190 CONTINUE 00315 * 00316 * Rank is number of steps completed. Set INFO = 1 to signal 00317 * that the factorization cannot be used to solve a system. 00318 * 00319 RANK = J - 1 00320 INFO = 1 00321 * 00322 200 CONTINUE 00323 RETURN 00324 * 00325 * End of CPSTF2 00326 * 00327 END