00001 /* dsposv.f -- translated by f2c (version 20061008). 00002 You must link the resulting object file with libf2c: 00003 on Microsoft Windows system, link with libf2c.lib; 00004 on Linux or Unix systems, link with .../path/to/libf2c.a -lm 00005 or, if you install libf2c.a in a standard place, with -lf2c -lm 00006 -- in that order, at the end of the command line, as in 00007 cc *.o -lf2c -lm 00008 Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., 00009 00010 http://www.netlib.org/f2c/libf2c.zip 00011 */ 00012 00013 #include "f2c.h" 00014 #include "blaswrap.h" 00015 00016 /* Table of constant values */ 00017 00018 static doublereal c_b10 = -1.; 00019 static doublereal c_b11 = 1.; 00020 static integer c__1 = 1; 00021 00022 /* Subroutine */ int dsposv_(char *uplo, integer *n, integer *nrhs, 00023 doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal * 00024 x, integer *ldx, doublereal *work, real *swork, integer *iter, 00025 integer *info) 00026 { 00027 /* System generated locals */ 00028 integer a_dim1, a_offset, b_dim1, b_offset, work_dim1, work_offset, 00029 x_dim1, x_offset, i__1; 00030 doublereal d__1; 00031 00032 /* Builtin functions */ 00033 double sqrt(doublereal); 00034 00035 /* Local variables */ 00036 integer i__; 00037 doublereal cte, eps, anrm; 00038 integer ptsa; 00039 doublereal rnrm, xnrm; 00040 integer ptsx; 00041 extern logical lsame_(char *, char *); 00042 integer iiter; 00043 extern /* Subroutine */ int daxpy_(integer *, doublereal *, doublereal *, 00044 integer *, doublereal *, integer *), dsymm_(char *, char *, 00045 integer *, integer *, doublereal *, doublereal *, integer *, 00046 doublereal *, integer *, doublereal *, doublereal *, integer *), dlag2s_(integer *, integer *, doublereal *, 00047 integer *, real *, integer *, integer *), slag2d_(integer *, 00048 integer *, real *, integer *, doublereal *, integer *, integer *), 00049 dlat2s_(char *, integer *, doublereal *, integer *, real *, 00050 integer *, integer *); 00051 extern doublereal dlamch_(char *); 00052 extern integer idamax_(integer *, doublereal *, integer *); 00053 extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, 00054 doublereal *, integer *, doublereal *, integer *), 00055 xerbla_(char *, integer *); 00056 extern doublereal dlansy_(char *, char *, integer *, doublereal *, 00057 integer *, doublereal *); 00058 extern /* Subroutine */ int dpotrf_(char *, integer *, doublereal *, 00059 integer *, integer *), dpotrs_(char *, integer *, integer 00060 *, doublereal *, integer *, doublereal *, integer *, integer *), spotrf_(char *, integer *, real *, integer *, integer *), spotrs_(char *, integer *, integer *, real *, integer *, 00061 real *, integer *, integer *); 00062 00063 00064 /* -- LAPACK PROTOTYPE driver routine (version 3.1.2) -- */ 00065 /* Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. */ 00066 /* May 2007 */ 00067 00068 /* .. */ 00069 /* .. Scalar Arguments .. */ 00070 /* .. */ 00071 /* .. Array Arguments .. */ 00072 /* .. */ 00073 00074 /* Purpose */ 00075 /* ======= */ 00076 00077 /* DSPOSV computes the solution to a real system of linear equations */ 00078 /* A * X = B, */ 00079 /* where A is an N-by-N symmetric positive definite matrix and X and B */ 00080 /* are N-by-NRHS matrices. */ 00081 00082 /* DSPOSV first attempts to factorize the matrix in SINGLE PRECISION */ 00083 /* and use this factorization within an iterative refinement procedure */ 00084 /* to produce a solution with DOUBLE PRECISION normwise backward error */ 00085 /* quality (see below). If the approach fails the method switches to a */ 00086 /* DOUBLE PRECISION factorization and solve. */ 00087 00088 /* The iterative refinement is not going to be a winning strategy if */ 00089 /* the ratio SINGLE PRECISION performance over DOUBLE PRECISION */ 00090 /* performance is too small. A reasonable strategy should take the */ 00091 /* number of right-hand sides and the size of the matrix into account. */ 00092 /* This might be done with a call to ILAENV in the future. Up to now, we */ 00093 /* always try iterative refinement. */ 00094 00095 /* The iterative refinement process is stopped if */ 00096 /* ITER > ITERMAX */ 00097 /* or for all the RHS we have: */ 00098 /* RNRM < SQRT(N)*XNRM*ANRM*EPS*BWDMAX */ 00099 /* where */ 00100 /* o ITER is the number of the current iteration in the iterative */ 00101 /* refinement process */ 00102 /* o RNRM is the infinity-norm of the residual */ 00103 /* o XNRM is the infinity-norm of the solution */ 00104 /* o ANRM is the infinity-operator-norm of the matrix A */ 00105 /* o EPS is the machine epsilon returned by DLAMCH('Epsilon') */ 00106 /* The value ITERMAX and BWDMAX are fixed to 30 and 1.0D+00 */ 00107 /* respectively. */ 00108 00109 /* Arguments */ 00110 /* ========= */ 00111 00112 /* UPLO (input) CHARACTER */ 00113 /* = 'U': Upper triangle of A is stored; */ 00114 /* = 'L': Lower triangle of A is stored. */ 00115 00116 /* N (input) INTEGER */ 00117 /* The number of linear equations, i.e., the order of the */ 00118 /* matrix A. N >= 0. */ 00119 00120 /* NRHS (input) INTEGER */ 00121 /* The number of right hand sides, i.e., the number of columns */ 00122 /* of the matrix B. NRHS >= 0. */ 00123 00124 /* A (input or input/ouptut) DOUBLE PRECISION array, */ 00125 /* dimension (LDA,N) */ 00126 /* On entry, the symmetric matrix A. If UPLO = 'U', the leading */ 00127 /* N-by-N upper triangular part of A contains the upper */ 00128 /* triangular part of the matrix A, and the strictly lower */ 00129 /* triangular part of A is not referenced. If UPLO = 'L', the */ 00130 /* leading N-by-N lower triangular part of A contains the lower */ 00131 /* triangular part of the matrix A, and the strictly upper */ 00132 /* triangular part of A is not referenced. */ 00133 /* On exit, if iterative refinement has been successfully used */ 00134 /* (INFO.EQ.0 and ITER.GE.0, see description below), then A is */ 00135 /* unchanged, if double precision factorization has been used */ 00136 /* (INFO.EQ.0 and ITER.LT.0, see description below), then the */ 00137 /* array A contains the factor U or L from the Cholesky */ 00138 /* factorization A = U**T*U or A = L*L**T. */ 00139 00140 00141 /* LDA (input) INTEGER */ 00142 /* The leading dimension of the array A. LDA >= max(1,N). */ 00143 00144 /* B (input) DOUBLE PRECISION array, dimension (LDB,NRHS) */ 00145 /* The N-by-NRHS right hand side matrix B. */ 00146 00147 /* LDB (input) INTEGER */ 00148 /* The leading dimension of the array B. LDB >= max(1,N). */ 00149 00150 /* X (output) DOUBLE PRECISION array, dimension (LDX,NRHS) */ 00151 /* If INFO = 0, the N-by-NRHS solution matrix X. */ 00152 00153 /* LDX (input) INTEGER */ 00154 /* The leading dimension of the array X. LDX >= max(1,N). */ 00155 00156 /* WORK (workspace) DOUBLE PRECISION array, dimension (N*NRHS) */ 00157 /* This array is used to hold the residual vectors. */ 00158 00159 /* SWORK (workspace) REAL array, dimension (N*(N+NRHS)) */ 00160 /* This array is used to use the single precision matrix and the */ 00161 /* right-hand sides or solutions in single precision. */ 00162 00163 /* ITER (output) INTEGER */ 00164 /* < 0: iterative refinement has failed, double precision */ 00165 /* factorization has been performed */ 00166 /* -1 : the routine fell back to full precision for */ 00167 /* implementation- or machine-specific reasons */ 00168 /* -2 : narrowing the precision induced an overflow, */ 00169 /* the routine fell back to full precision */ 00170 /* -3 : failure of SPOTRF */ 00171 /* -31: stop the iterative refinement after the 30th */ 00172 /* iterations */ 00173 /* > 0: iterative refinement has been sucessfully used. */ 00174 /* Returns the number of iterations */ 00175 00176 /* INFO (output) INTEGER */ 00177 /* = 0: successful exit */ 00178 /* < 0: if INFO = -i, the i-th argument had an illegal value */ 00179 /* > 0: if INFO = i, the leading minor of order i of (DOUBLE */ 00180 /* PRECISION) A is not positive definite, so the */ 00181 /* factorization could not be completed, and the solution */ 00182 /* has not been computed. */ 00183 00184 /* ========= */ 00185 00186 /* .. Parameters .. */ 00187 00188 00189 00190 00191 /* .. Local Scalars .. */ 00192 00193 /* .. External Subroutines .. */ 00194 /* .. */ 00195 /* .. External Functions .. */ 00196 /* .. */ 00197 /* .. Intrinsic Functions .. */ 00198 /* .. */ 00199 /* .. Executable Statements .. */ 00200 00201 /* Parameter adjustments */ 00202 work_dim1 = *n; 00203 work_offset = 1 + work_dim1; 00204 work -= work_offset; 00205 a_dim1 = *lda; 00206 a_offset = 1 + a_dim1; 00207 a -= a_offset; 00208 b_dim1 = *ldb; 00209 b_offset = 1 + b_dim1; 00210 b -= b_offset; 00211 x_dim1 = *ldx; 00212 x_offset = 1 + x_dim1; 00213 x -= x_offset; 00214 --swork; 00215 00216 /* Function Body */ 00217 *info = 0; 00218 *iter = 0; 00219 00220 /* Test the input parameters. */ 00221 00222 if (! lsame_(uplo, "U") && ! lsame_(uplo, "L")) { 00223 *info = -1; 00224 } else if (*n < 0) { 00225 *info = -2; 00226 } else if (*nrhs < 0) { 00227 *info = -3; 00228 } else if (*lda < max(1,*n)) { 00229 *info = -5; 00230 } else if (*ldb < max(1,*n)) { 00231 *info = -7; 00232 } else if (*ldx < max(1,*n)) { 00233 *info = -9; 00234 } 00235 if (*info != 0) { 00236 i__1 = -(*info); 00237 xerbla_("DSPOSV", &i__1); 00238 return 0; 00239 } 00240 00241 /* Quick return if (N.EQ.0). */ 00242 00243 if (*n == 0) { 00244 return 0; 00245 } 00246 00247 /* Skip single precision iterative refinement if a priori slower */ 00248 /* than double precision factorization. */ 00249 00250 if (FALSE_) { 00251 *iter = -1; 00252 goto L40; 00253 } 00254 00255 /* Compute some constants. */ 00256 00257 anrm = dlansy_("I", uplo, n, &a[a_offset], lda, &work[work_offset]); 00258 eps = dlamch_("Epsilon"); 00259 cte = anrm * eps * sqrt((doublereal) (*n)) * 1.; 00260 00261 /* Set the indices PTSA, PTSX for referencing SA and SX in SWORK. */ 00262 00263 ptsa = 1; 00264 ptsx = ptsa + *n * *n; 00265 00266 /* Convert B from double precision to single precision and store the */ 00267 /* result in SX. */ 00268 00269 dlag2s_(n, nrhs, &b[b_offset], ldb, &swork[ptsx], n, info); 00270 00271 if (*info != 0) { 00272 *iter = -2; 00273 goto L40; 00274 } 00275 00276 /* Convert A from double precision to single precision and store the */ 00277 /* result in SA. */ 00278 00279 dlat2s_(uplo, n, &a[a_offset], lda, &swork[ptsa], n, info); 00280 00281 if (*info != 0) { 00282 *iter = -2; 00283 goto L40; 00284 } 00285 00286 /* Compute the Cholesky factorization of SA. */ 00287 00288 spotrf_(uplo, n, &swork[ptsa], n, info); 00289 00290 if (*info != 0) { 00291 *iter = -3; 00292 goto L40; 00293 } 00294 00295 /* Solve the system SA*SX = SB. */ 00296 00297 spotrs_(uplo, n, nrhs, &swork[ptsa], n, &swork[ptsx], n, info); 00298 00299 /* Convert SX back to double precision */ 00300 00301 slag2d_(n, nrhs, &swork[ptsx], n, &x[x_offset], ldx, info); 00302 00303 /* Compute R = B - AX (R is WORK). */ 00304 00305 dlacpy_("All", n, nrhs, &b[b_offset], ldb, &work[work_offset], n); 00306 00307 dsymm_("Left", uplo, n, nrhs, &c_b10, &a[a_offset], lda, &x[x_offset], 00308 ldx, &c_b11, &work[work_offset], n); 00309 00310 /* Check whether the NRHS normwise backward errors satisfy the */ 00311 /* stopping criterion. If yes, set ITER=0 and return. */ 00312 00313 i__1 = *nrhs; 00314 for (i__ = 1; i__ <= i__1; ++i__) { 00315 xnrm = (d__1 = x[idamax_(n, &x[i__ * x_dim1 + 1], &c__1) + i__ * 00316 x_dim1], abs(d__1)); 00317 rnrm = (d__1 = work[idamax_(n, &work[i__ * work_dim1 + 1], &c__1) + 00318 i__ * work_dim1], abs(d__1)); 00319 if (rnrm > xnrm * cte) { 00320 goto L10; 00321 } 00322 } 00323 00324 /* If we are here, the NRHS normwise backward errors satisfy the */ 00325 /* stopping criterion. We are good to exit. */ 00326 00327 *iter = 0; 00328 return 0; 00329 00330 L10: 00331 00332 for (iiter = 1; iiter <= 30; ++iiter) { 00333 00334 /* Convert R (in WORK) from double precision to single precision */ 00335 /* and store the result in SX. */ 00336 00337 dlag2s_(n, nrhs, &work[work_offset], n, &swork[ptsx], n, info); 00338 00339 if (*info != 0) { 00340 *iter = -2; 00341 goto L40; 00342 } 00343 00344 /* Solve the system SA*SX = SR. */ 00345 00346 spotrs_(uplo, n, nrhs, &swork[ptsa], n, &swork[ptsx], n, info); 00347 00348 /* Convert SX back to double precision and update the current */ 00349 /* iterate. */ 00350 00351 slag2d_(n, nrhs, &swork[ptsx], n, &work[work_offset], n, info); 00352 00353 i__1 = *nrhs; 00354 for (i__ = 1; i__ <= i__1; ++i__) { 00355 daxpy_(n, &c_b11, &work[i__ * work_dim1 + 1], &c__1, &x[i__ * 00356 x_dim1 + 1], &c__1); 00357 } 00358 00359 /* Compute R = B - AX (R is WORK). */ 00360 00361 dlacpy_("All", n, nrhs, &b[b_offset], ldb, &work[work_offset], n); 00362 00363 dsymm_("L", uplo, n, nrhs, &c_b10, &a[a_offset], lda, &x[x_offset], 00364 ldx, &c_b11, &work[work_offset], n); 00365 00366 /* Check whether the NRHS normwise backward errors satisfy the */ 00367 /* stopping criterion. If yes, set ITER=IITER>0 and return. */ 00368 00369 i__1 = *nrhs; 00370 for (i__ = 1; i__ <= i__1; ++i__) { 00371 xnrm = (d__1 = x[idamax_(n, &x[i__ * x_dim1 + 1], &c__1) + i__ * 00372 x_dim1], abs(d__1)); 00373 rnrm = (d__1 = work[idamax_(n, &work[i__ * work_dim1 + 1], &c__1) 00374 + i__ * work_dim1], abs(d__1)); 00375 if (rnrm > xnrm * cte) { 00376 goto L20; 00377 } 00378 } 00379 00380 /* If we are here, the NRHS normwise backward errors satisfy the */ 00381 /* stopping criterion, we are good to exit. */ 00382 00383 *iter = iiter; 00384 00385 return 0; 00386 00387 L20: 00388 00389 /* L30: */ 00390 ; 00391 } 00392 00393 /* If we are at this place of the code, this is because we have */ 00394 /* performed ITER=ITERMAX iterations and never satisified the */ 00395 /* stopping criterion, set up the ITER flag accordingly and follow */ 00396 /* up on double precision routine. */ 00397 00398 *iter = -31; 00399 00400 L40: 00401 00402 /* Single-precision iterative refinement failed to converge to a */ 00403 /* satisfactory solution, so we resort to double precision. */ 00404 00405 dpotrf_(uplo, n, &a[a_offset], lda, info); 00406 00407 if (*info != 0) { 00408 return 0; 00409 } 00410 00411 dlacpy_("All", n, nrhs, &b[b_offset], ldb, &x[x_offset], ldx); 00412 dpotrs_(uplo, n, nrhs, &a[a_offset], lda, &x[x_offset], ldx, info); 00413 00414 return 0; 00415 00416 /* End of DSPOSV. */ 00417 00418 } /* dsposv_ */