spprfs.c
Go to the documentation of this file.
00001 /* spprfs.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 integer c__1 = 1;
00019 static real c_b12 = -1.f;
00020 static real c_b14 = 1.f;
00021 
00022 /* Subroutine */ int spprfs_(char *uplo, integer *n, integer *nrhs, real *ap, 
00023         real *afp, real *b, integer *ldb, real *x, integer *ldx, real *ferr, 
00024         real *berr, real *work, integer *iwork, integer *info)
00025 {
00026     /* System generated locals */
00027     integer b_dim1, b_offset, x_dim1, x_offset, i__1, i__2, i__3;
00028     real r__1, r__2, r__3;
00029 
00030     /* Local variables */
00031     integer i__, j, k;
00032     real s;
00033     integer ik, kk;
00034     real xk;
00035     integer nz;
00036     real eps;
00037     integer kase;
00038     real safe1, safe2;
00039     extern logical lsame_(char *, char *);
00040     integer isave[3], count;
00041     logical upper;
00042     extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, 
00043             integer *), saxpy_(integer *, real *, real *, integer *, real *, 
00044             integer *), sspmv_(char *, integer *, real *, real *, real *, 
00045             integer *, real *, real *, integer *), slacn2_(integer *, 
00046             real *, real *, integer *, real *, integer *, integer *);
00047     extern doublereal slamch_(char *);
00048     real safmin;
00049     extern /* Subroutine */ int xerbla_(char *, integer *);
00050     real lstres;
00051     extern /* Subroutine */ int spptrs_(char *, integer *, integer *, real *, 
00052             real *, integer *, integer *);
00053 
00054 
00055 /*  -- LAPACK routine (version 3.2) -- */
00056 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00057 /*     November 2006 */
00058 
00059 /*     Modified to call SLACN2 in place of SLACON, 7 Feb 03, SJH. */
00060 
00061 /*     .. Scalar Arguments .. */
00062 /*     .. */
00063 /*     .. Array Arguments .. */
00064 /*     .. */
00065 
00066 /*  Purpose */
00067 /*  ======= */
00068 
00069 /*  SPPRFS improves the computed solution to a system of linear */
00070 /*  equations when the coefficient matrix is symmetric positive definite */
00071 /*  and packed, and provides error bounds and backward error estimates */
00072 /*  for the solution. */
00073 
00074 /*  Arguments */
00075 /*  ========= */
00076 
00077 /*  UPLO    (input) CHARACTER*1 */
00078 /*          = 'U':  Upper triangle of A is stored; */
00079 /*          = 'L':  Lower triangle of A is stored. */
00080 
00081 /*  N       (input) INTEGER */
00082 /*          The order of the matrix A.  N >= 0. */
00083 
00084 /*  NRHS    (input) INTEGER */
00085 /*          The number of right hand sides, i.e., the number of columns */
00086 /*          of the matrices B and X.  NRHS >= 0. */
00087 
00088 /*  AP      (input) REAL array, dimension (N*(N+1)/2) */
00089 /*          The upper or lower triangle of the symmetric matrix A, packed */
00090 /*          columnwise in a linear array.  The j-th column of A is stored */
00091 /*          in the array AP as follows: */
00092 /*          if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; */
00093 /*          if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n. */
00094 
00095 /*  AFP     (input) REAL array, dimension (N*(N+1)/2) */
00096 /*          The triangular factor U or L from the Cholesky factorization */
00097 /*          A = U**T*U or A = L*L**T, as computed by SPPTRF/CPPTRF, */
00098 /*          packed columnwise in a linear array in the same format as A */
00099 /*          (see AP). */
00100 
00101 /*  B       (input) REAL array, dimension (LDB,NRHS) */
00102 /*          The right hand side matrix B. */
00103 
00104 /*  LDB     (input) INTEGER */
00105 /*          The leading dimension of the array B.  LDB >= max(1,N). */
00106 
00107 /*  X       (input/output) REAL array, dimension (LDX,NRHS) */
00108 /*          On entry, the solution matrix X, as computed by SPPTRS. */
00109 /*          On exit, the improved solution matrix X. */
00110 
00111 /*  LDX     (input) INTEGER */
00112 /*          The leading dimension of the array X.  LDX >= max(1,N). */
00113 
00114 /*  FERR    (output) REAL array, dimension (NRHS) */
00115 /*          The estimated forward error bound for each solution vector */
00116 /*          X(j) (the j-th column of the solution matrix X). */
00117 /*          If XTRUE is the true solution corresponding to X(j), FERR(j) */
00118 /*          is an estimated upper bound for the magnitude of the largest */
00119 /*          element in (X(j) - XTRUE) divided by the magnitude of the */
00120 /*          largest element in X(j).  The estimate is as reliable as */
00121 /*          the estimate for RCOND, and is almost always a slight */
00122 /*          overestimate of the true error. */
00123 
00124 /*  BERR    (output) REAL array, dimension (NRHS) */
00125 /*          The componentwise relative backward error of each solution */
00126 /*          vector X(j) (i.e., the smallest relative change in */
00127 /*          any element of A or B that makes X(j) an exact solution). */
00128 
00129 /*  WORK    (workspace) REAL array, dimension (3*N) */
00130 
00131 /*  IWORK   (workspace) INTEGER array, dimension (N) */
00132 
00133 /*  INFO    (output) INTEGER */
00134 /*          = 0:  successful exit */
00135 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00136 
00137 /*  Internal Parameters */
00138 /*  =================== */
00139 
00140 /*  ITMAX is the maximum number of steps of iterative refinement. */
00141 
00142 /*  ===================================================================== */
00143 
00144 /*     .. Parameters .. */
00145 /*     .. */
00146 /*     .. Local Scalars .. */
00147 /*     .. */
00148 /*     .. Local Arrays .. */
00149 /*     .. */
00150 /*     .. External Subroutines .. */
00151 /*     .. */
00152 /*     .. Intrinsic Functions .. */
00153 /*     .. */
00154 /*     .. External Functions .. */
00155 /*     .. */
00156 /*     .. Executable Statements .. */
00157 
00158 /*     Test the input parameters. */
00159 
00160     /* Parameter adjustments */
00161     --ap;
00162     --afp;
00163     b_dim1 = *ldb;
00164     b_offset = 1 + b_dim1;
00165     b -= b_offset;
00166     x_dim1 = *ldx;
00167     x_offset = 1 + x_dim1;
00168     x -= x_offset;
00169     --ferr;
00170     --berr;
00171     --work;
00172     --iwork;
00173 
00174     /* Function Body */
00175     *info = 0;
00176     upper = lsame_(uplo, "U");
00177     if (! upper && ! lsame_(uplo, "L")) {
00178         *info = -1;
00179     } else if (*n < 0) {
00180         *info = -2;
00181     } else if (*nrhs < 0) {
00182         *info = -3;
00183     } else if (*ldb < max(1,*n)) {
00184         *info = -7;
00185     } else if (*ldx < max(1,*n)) {
00186         *info = -9;
00187     }
00188     if (*info != 0) {
00189         i__1 = -(*info);
00190         xerbla_("SPPRFS", &i__1);
00191         return 0;
00192     }
00193 
00194 /*     Quick return if possible */
00195 
00196     if (*n == 0 || *nrhs == 0) {
00197         i__1 = *nrhs;
00198         for (j = 1; j <= i__1; ++j) {
00199             ferr[j] = 0.f;
00200             berr[j] = 0.f;
00201 /* L10: */
00202         }
00203         return 0;
00204     }
00205 
00206 /*     NZ = maximum number of nonzero elements in each row of A, plus 1 */
00207 
00208     nz = *n + 1;
00209     eps = slamch_("Epsilon");
00210     safmin = slamch_("Safe minimum");
00211     safe1 = nz * safmin;
00212     safe2 = safe1 / eps;
00213 
00214 /*     Do for each right hand side */
00215 
00216     i__1 = *nrhs;
00217     for (j = 1; j <= i__1; ++j) {
00218 
00219         count = 1;
00220         lstres = 3.f;
00221 L20:
00222 
00223 /*        Loop until stopping criterion is satisfied. */
00224 
00225 /*        Compute residual R = B - A * X */
00226 
00227         scopy_(n, &b[j * b_dim1 + 1], &c__1, &work[*n + 1], &c__1);
00228         sspmv_(uplo, n, &c_b12, &ap[1], &x[j * x_dim1 + 1], &c__1, &c_b14, &
00229                 work[*n + 1], &c__1);
00230 
00231 /*        Compute componentwise relative backward error from formula */
00232 
00233 /*        max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) ) */
00234 
00235 /*        where abs(Z) is the componentwise absolute value of the matrix */
00236 /*        or vector Z.  If the i-th component of the denominator is less */
00237 /*        than SAFE2, then SAFE1 is added to the i-th components of the */
00238 /*        numerator and denominator before dividing. */
00239 
00240         i__2 = *n;
00241         for (i__ = 1; i__ <= i__2; ++i__) {
00242             work[i__] = (r__1 = b[i__ + j * b_dim1], dabs(r__1));
00243 /* L30: */
00244         }
00245 
00246 /*        Compute abs(A)*abs(X) + abs(B). */
00247 
00248         kk = 1;
00249         if (upper) {
00250             i__2 = *n;
00251             for (k = 1; k <= i__2; ++k) {
00252                 s = 0.f;
00253                 xk = (r__1 = x[k + j * x_dim1], dabs(r__1));
00254                 ik = kk;
00255                 i__3 = k - 1;
00256                 for (i__ = 1; i__ <= i__3; ++i__) {
00257                     work[i__] += (r__1 = ap[ik], dabs(r__1)) * xk;
00258                     s += (r__1 = ap[ik], dabs(r__1)) * (r__2 = x[i__ + j * 
00259                             x_dim1], dabs(r__2));
00260                     ++ik;
00261 /* L40: */
00262                 }
00263                 work[k] = work[k] + (r__1 = ap[kk + k - 1], dabs(r__1)) * xk 
00264                         + s;
00265                 kk += k;
00266 /* L50: */
00267             }
00268         } else {
00269             i__2 = *n;
00270             for (k = 1; k <= i__2; ++k) {
00271                 s = 0.f;
00272                 xk = (r__1 = x[k + j * x_dim1], dabs(r__1));
00273                 work[k] += (r__1 = ap[kk], dabs(r__1)) * xk;
00274                 ik = kk + 1;
00275                 i__3 = *n;
00276                 for (i__ = k + 1; i__ <= i__3; ++i__) {
00277                     work[i__] += (r__1 = ap[ik], dabs(r__1)) * xk;
00278                     s += (r__1 = ap[ik], dabs(r__1)) * (r__2 = x[i__ + j * 
00279                             x_dim1], dabs(r__2));
00280                     ++ik;
00281 /* L60: */
00282                 }
00283                 work[k] += s;
00284                 kk += *n - k + 1;
00285 /* L70: */
00286             }
00287         }
00288         s = 0.f;
00289         i__2 = *n;
00290         for (i__ = 1; i__ <= i__2; ++i__) {
00291             if (work[i__] > safe2) {
00292 /* Computing MAX */
00293                 r__2 = s, r__3 = (r__1 = work[*n + i__], dabs(r__1)) / work[
00294                         i__];
00295                 s = dmax(r__2,r__3);
00296             } else {
00297 /* Computing MAX */
00298                 r__2 = s, r__3 = ((r__1 = work[*n + i__], dabs(r__1)) + safe1)
00299                          / (work[i__] + safe1);
00300                 s = dmax(r__2,r__3);
00301             }
00302 /* L80: */
00303         }
00304         berr[j] = s;
00305 
00306 /*        Test stopping criterion. Continue iterating if */
00307 /*           1) The residual BERR(J) is larger than machine epsilon, and */
00308 /*           2) BERR(J) decreased by at least a factor of 2 during the */
00309 /*              last iteration, and */
00310 /*           3) At most ITMAX iterations tried. */
00311 
00312         if (berr[j] > eps && berr[j] * 2.f <= lstres && count <= 5) {
00313 
00314 /*           Update solution and try again. */
00315 
00316             spptrs_(uplo, n, &c__1, &afp[1], &work[*n + 1], n, info);
00317             saxpy_(n, &c_b14, &work[*n + 1], &c__1, &x[j * x_dim1 + 1], &c__1)
00318                     ;
00319             lstres = berr[j];
00320             ++count;
00321             goto L20;
00322         }
00323 
00324 /*        Bound error from formula */
00325 
00326 /*        norm(X - XTRUE) / norm(X) .le. FERR = */
00327 /*        norm( abs(inv(A))* */
00328 /*           ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X) */
00329 
00330 /*        where */
00331 /*          norm(Z) is the magnitude of the largest component of Z */
00332 /*          inv(A) is the inverse of A */
00333 /*          abs(Z) is the componentwise absolute value of the matrix or */
00334 /*             vector Z */
00335 /*          NZ is the maximum number of nonzeros in any row of A, plus 1 */
00336 /*          EPS is machine epsilon */
00337 
00338 /*        The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B)) */
00339 /*        is incremented by SAFE1 if the i-th component of */
00340 /*        abs(A)*abs(X) + abs(B) is less than SAFE2. */
00341 
00342 /*        Use SLACN2 to estimate the infinity-norm of the matrix */
00343 /*           inv(A) * diag(W), */
00344 /*        where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) */
00345 
00346         i__2 = *n;
00347         for (i__ = 1; i__ <= i__2; ++i__) {
00348             if (work[i__] > safe2) {
00349                 work[i__] = (r__1 = work[*n + i__], dabs(r__1)) + nz * eps * 
00350                         work[i__];
00351             } else {
00352                 work[i__] = (r__1 = work[*n + i__], dabs(r__1)) + nz * eps * 
00353                         work[i__] + safe1;
00354             }
00355 /* L90: */
00356         }
00357 
00358         kase = 0;
00359 L100:
00360         slacn2_(n, &work[(*n << 1) + 1], &work[*n + 1], &iwork[1], &ferr[j], &
00361                 kase, isave);
00362         if (kase != 0) {
00363             if (kase == 1) {
00364 
00365 /*              Multiply by diag(W)*inv(A'). */
00366 
00367                 spptrs_(uplo, n, &c__1, &afp[1], &work[*n + 1], n, info);
00368                 i__2 = *n;
00369                 for (i__ = 1; i__ <= i__2; ++i__) {
00370                     work[*n + i__] = work[i__] * work[*n + i__];
00371 /* L110: */
00372                 }
00373             } else if (kase == 2) {
00374 
00375 /*              Multiply by inv(A)*diag(W). */
00376 
00377                 i__2 = *n;
00378                 for (i__ = 1; i__ <= i__2; ++i__) {
00379                     work[*n + i__] = work[i__] * work[*n + i__];
00380 /* L120: */
00381                 }
00382                 spptrs_(uplo, n, &c__1, &afp[1], &work[*n + 1], n, info);
00383             }
00384             goto L100;
00385         }
00386 
00387 /*        Normalize error. */
00388 
00389         lstres = 0.f;
00390         i__2 = *n;
00391         for (i__ = 1; i__ <= i__2; ++i__) {
00392 /* Computing MAX */
00393             r__2 = lstres, r__3 = (r__1 = x[i__ + j * x_dim1], dabs(r__1));
00394             lstres = dmax(r__2,r__3);
00395 /* L130: */
00396         }
00397         if (lstres != 0.f) {
00398             ferr[j] /= lstres;
00399         }
00400 
00401 /* L140: */
00402     }
00403 
00404     return 0;
00405 
00406 /*     End of SPPRFS */
00407 
00408 } /* spprfs_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:13