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


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