LAPACK 3.3.0
|
00001 SUBROUTINE SSYTRF( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO ) 00002 * 00003 * -- LAPACK routine (version 3.2) -- 00004 * -- LAPACK is a software package provided by Univ. of Tennessee, -- 00005 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 00006 * November 2006 00007 * 00008 * .. Scalar Arguments .. 00009 CHARACTER UPLO 00010 INTEGER INFO, LDA, LWORK, N 00011 * .. 00012 * .. Array Arguments .. 00013 INTEGER IPIV( * ) 00014 REAL A( LDA, * ), WORK( * ) 00015 * .. 00016 * 00017 * Purpose 00018 * ======= 00019 * 00020 * SSYTRF computes the factorization of a real symmetric matrix A using 00021 * the Bunch-Kaufman diagonal pivoting method. The form of the 00022 * factorization is 00023 * 00024 * A = U*D*U**T or A = L*D*L**T 00025 * 00026 * where U (or L) is a product of permutation and unit upper (lower) 00027 * triangular matrices, and D is symmetric and block diagonal with 00028 * 1-by-1 and 2-by-2 diagonal blocks. 00029 * 00030 * This is the blocked version of the algorithm, calling Level 3 BLAS. 00031 * 00032 * Arguments 00033 * ========= 00034 * 00035 * UPLO (input) CHARACTER*1 00036 * = 'U': Upper triangle of A is stored; 00037 * = 'L': Lower triangle of A is stored. 00038 * 00039 * N (input) INTEGER 00040 * The order of the matrix A. N >= 0. 00041 * 00042 * A (input/output) REAL array, dimension (LDA,N) 00043 * On entry, the symmetric matrix A. If UPLO = 'U', the leading 00044 * N-by-N upper triangular part of A contains the upper 00045 * triangular part of the matrix A, and the strictly lower 00046 * triangular part of A is not referenced. If UPLO = 'L', the 00047 * leading N-by-N lower triangular part of A contains the lower 00048 * triangular part of the matrix A, and the strictly upper 00049 * triangular part of A is not referenced. 00050 * 00051 * On exit, the block diagonal matrix D and the multipliers used 00052 * to obtain the factor U or L (see below for further details). 00053 * 00054 * LDA (input) INTEGER 00055 * The leading dimension of the array A. LDA >= max(1,N). 00056 * 00057 * IPIV (output) INTEGER array, dimension (N) 00058 * Details of the interchanges and the block structure of D. 00059 * If IPIV(k) > 0, then rows and columns k and IPIV(k) were 00060 * interchanged and D(k,k) is a 1-by-1 diagonal block. 00061 * If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0, then rows and 00062 * columns k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k) 00063 * is a 2-by-2 diagonal block. If UPLO = 'L' and IPIV(k) = 00064 * IPIV(k+1) < 0, then rows and columns k+1 and -IPIV(k) were 00065 * interchanged and D(k:k+1,k:k+1) is a 2-by-2 diagonal block. 00066 * 00067 * WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) 00068 * On exit, if INFO = 0, WORK(1) returns the optimal LWORK. 00069 * 00070 * LWORK (input) INTEGER 00071 * The length of WORK. LWORK >=1. For best performance 00072 * LWORK >= N*NB, where NB is the block size returned by ILAENV. 00073 * 00074 * If LWORK = -1, then a workspace query is assumed; the routine 00075 * only calculates the optimal size of the WORK array, returns 00076 * this value as the first entry of the WORK array, and no error 00077 * message related to LWORK is issued by XERBLA. 00078 * 00079 * INFO (output) INTEGER 00080 * = 0: successful exit 00081 * < 0: if INFO = -i, the i-th argument had an illegal value 00082 * > 0: if INFO = i, D(i,i) is exactly zero. The factorization 00083 * has been completed, but the block diagonal matrix D is 00084 * exactly singular, and division by zero will occur if it 00085 * is used to solve a system of equations. 00086 * 00087 * Further Details 00088 * =============== 00089 * 00090 * If UPLO = 'U', then A = U*D*U', where 00091 * U = P(n)*U(n)* ... *P(k)U(k)* ..., 00092 * i.e., U is a product of terms P(k)*U(k), where k decreases from n to 00093 * 1 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1 00094 * and 2-by-2 diagonal blocks D(k). P(k) is a permutation matrix as 00095 * defined by IPIV(k), and U(k) is a unit upper triangular matrix, such 00096 * that if the diagonal block D(k) is of order s (s = 1 or 2), then 00097 * 00098 * ( I v 0 ) k-s 00099 * U(k) = ( 0 I 0 ) s 00100 * ( 0 0 I ) n-k 00101 * k-s s n-k 00102 * 00103 * If s = 1, D(k) overwrites A(k,k), and v overwrites A(1:k-1,k). 00104 * If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k), 00105 * and A(k,k), and v overwrites A(1:k-2,k-1:k). 00106 * 00107 * If UPLO = 'L', then A = L*D*L', where 00108 * L = P(1)*L(1)* ... *P(k)*L(k)* ..., 00109 * i.e., L is a product of terms P(k)*L(k), where k increases from 1 to 00110 * n in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1 00111 * and 2-by-2 diagonal blocks D(k). P(k) is a permutation matrix as 00112 * defined by IPIV(k), and L(k) is a unit lower triangular matrix, such 00113 * that if the diagonal block D(k) is of order s (s = 1 or 2), then 00114 * 00115 * ( I 0 0 ) k-1 00116 * L(k) = ( 0 I 0 ) s 00117 * ( 0 v I ) n-k-s+1 00118 * k-1 s n-k-s+1 00119 * 00120 * If s = 1, D(k) overwrites A(k,k), and v overwrites A(k+1:n,k). 00121 * If s = 2, the lower triangle of D(k) overwrites A(k,k), A(k+1,k), 00122 * and A(k+1,k+1), and v overwrites A(k+2:n,k:k+1). 00123 * 00124 * ===================================================================== 00125 * 00126 * .. Local Scalars .. 00127 LOGICAL LQUERY, UPPER 00128 INTEGER IINFO, IWS, J, K, KB, LDWORK, LWKOPT, NB, NBMIN 00129 * .. 00130 * .. External Functions .. 00131 LOGICAL LSAME 00132 INTEGER ILAENV 00133 EXTERNAL LSAME, ILAENV 00134 * .. 00135 * .. External Subroutines .. 00136 EXTERNAL SLASYF, SSYTF2, XERBLA 00137 * .. 00138 * .. Intrinsic Functions .. 00139 INTRINSIC MAX 00140 * .. 00141 * .. Executable Statements .. 00142 * 00143 * Test the input parameters. 00144 * 00145 INFO = 0 00146 UPPER = LSAME( UPLO, 'U' ) 00147 LQUERY = ( LWORK.EQ.-1 ) 00148 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN 00149 INFO = -1 00150 ELSE IF( N.LT.0 ) THEN 00151 INFO = -2 00152 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN 00153 INFO = -4 00154 ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THEN 00155 INFO = -7 00156 END IF 00157 * 00158 IF( INFO.EQ.0 ) THEN 00159 * 00160 * Determine the block size 00161 * 00162 NB = ILAENV( 1, 'SSYTRF', UPLO, N, -1, -1, -1 ) 00163 LWKOPT = N*NB 00164 WORK( 1 ) = LWKOPT 00165 END IF 00166 * 00167 IF( INFO.NE.0 ) THEN 00168 CALL XERBLA( 'SSYTRF', -INFO ) 00169 RETURN 00170 ELSE IF( LQUERY ) THEN 00171 RETURN 00172 END IF 00173 * 00174 NBMIN = 2 00175 LDWORK = N 00176 IF( NB.GT.1 .AND. NB.LT.N ) THEN 00177 IWS = LDWORK*NB 00178 IF( LWORK.LT.IWS ) THEN 00179 NB = MAX( LWORK / LDWORK, 1 ) 00180 NBMIN = MAX( 2, ILAENV( 2, 'SSYTRF', UPLO, N, -1, -1, -1 ) ) 00181 END IF 00182 ELSE 00183 IWS = 1 00184 END IF 00185 IF( NB.LT.NBMIN ) 00186 $ NB = N 00187 * 00188 IF( UPPER ) THEN 00189 * 00190 * Factorize A as U*D*U' using the upper triangle of A 00191 * 00192 * K is the main loop index, decreasing from N to 1 in steps of 00193 * KB, where KB is the number of columns factorized by SLASYF; 00194 * KB is either NB or NB-1, or K for the last block 00195 * 00196 K = N 00197 10 CONTINUE 00198 * 00199 * If K < 1, exit from loop 00200 * 00201 IF( K.LT.1 ) 00202 $ GO TO 40 00203 * 00204 IF( K.GT.NB ) THEN 00205 * 00206 * Factorize columns k-kb+1:k of A and use blocked code to 00207 * update columns 1:k-kb 00208 * 00209 CALL SLASYF( UPLO, K, NB, KB, A, LDA, IPIV, WORK, LDWORK, 00210 $ IINFO ) 00211 ELSE 00212 * 00213 * Use unblocked code to factorize columns 1:k of A 00214 * 00215 CALL SSYTF2( UPLO, K, A, LDA, IPIV, IINFO ) 00216 KB = K 00217 END IF 00218 * 00219 * Set INFO on the first occurrence of a zero pivot 00220 * 00221 IF( INFO.EQ.0 .AND. IINFO.GT.0 ) 00222 $ INFO = IINFO 00223 * 00224 * Decrease K and return to the start of the main loop 00225 * 00226 K = K - KB 00227 GO TO 10 00228 * 00229 ELSE 00230 * 00231 * Factorize A as L*D*L' using the lower triangle of A 00232 * 00233 * K is the main loop index, increasing from 1 to N in steps of 00234 * KB, where KB is the number of columns factorized by SLASYF; 00235 * KB is either NB or NB-1, or N-K+1 for the last block 00236 * 00237 K = 1 00238 20 CONTINUE 00239 * 00240 * If K > N, exit from loop 00241 * 00242 IF( K.GT.N ) 00243 $ GO TO 40 00244 * 00245 IF( K.LE.N-NB ) THEN 00246 * 00247 * Factorize columns k:k+kb-1 of A and use blocked code to 00248 * update columns k+kb:n 00249 * 00250 CALL SLASYF( UPLO, N-K+1, NB, KB, A( K, K ), LDA, IPIV( K ), 00251 $ WORK, LDWORK, IINFO ) 00252 ELSE 00253 * 00254 * Use unblocked code to factorize columns k:n of A 00255 * 00256 CALL SSYTF2( UPLO, N-K+1, A( K, K ), LDA, IPIV( K ), IINFO ) 00257 KB = N - K + 1 00258 END IF 00259 * 00260 * Set INFO on the first occurrence of a zero pivot 00261 * 00262 IF( INFO.EQ.0 .AND. IINFO.GT.0 ) 00263 $ INFO = IINFO + K - 1 00264 * 00265 * Adjust IPIV 00266 * 00267 DO 30 J = K, K + KB - 1 00268 IF( IPIV( J ).GT.0 ) THEN 00269 IPIV( J ) = IPIV( J ) + K - 1 00270 ELSE 00271 IPIV( J ) = IPIV( J ) - K + 1 00272 END IF 00273 30 CONTINUE 00274 * 00275 * Increase K and return to the start of the main loop 00276 * 00277 K = K + KB 00278 GO TO 20 00279 * 00280 END IF 00281 * 00282 40 CONTINUE 00283 WORK( 1 ) = LWKOPT 00284 RETURN 00285 * 00286 * End of SSYTRF 00287 * 00288 END