Exemplo n.º 1
0
/* Subroutine */ int dgtt02_(char *trans, integer *n, integer *nrhs, 
	doublereal *dl, doublereal *d__, doublereal *du, doublereal *x, 
	integer *ldx, doublereal *b, integer *ldb, doublereal *rwork, 
	doublereal *resid)
{
    /* System generated locals */
    integer b_dim1, b_offset, x_dim1, x_offset, i__1;
    doublereal d__1, d__2;

    /* Local variables */
    integer j;
    doublereal eps;
    doublereal anorm, bnorm, xnorm;


/*  -- LAPACK test routine (version 3.1) -- */
/*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
/*     November 2006 */

/*     .. Scalar Arguments .. */
/*     .. */
/*     .. Array Arguments .. */
/*     .. */

/*  Purpose */
/*  ======= */

/*  DGTT02 computes the residual for the solution to a tridiagonal */
/*  system of equations: */
/*     RESID = norm(B - op(A)*X) / (norm(A) * norm(X) * EPS), */
/*  where EPS is the machine epsilon. */

/*  Arguments */
/*  ========= */

/*  TRANS   (input) CHARACTER */
/*          Specifies the form of the residual. */
/*          = 'N':  B - A * X  (No transpose) */
/*          = 'T':  B - A'* X  (Transpose) */
/*          = 'C':  B - A'* X  (Conjugate transpose = Transpose) */

/*  N       (input) INTEGTER */
/*          The order of the matrix A.  N >= 0. */

/*  NRHS    (input) INTEGER */
/*          The number of right hand sides, i.e., the number of columns */
/*          of the matrices B and X.  NRHS >= 0. */

/*  DL      (input) DOUBLE PRECISION array, dimension (N-1) */
/*          The (n-1) sub-diagonal elements of A. */

/*  D       (input) DOUBLE PRECISION array, dimension (N) */
/*          The diagonal elements of A. */

/*  DU      (input) DOUBLE PRECISION array, dimension (N-1) */
/*          The (n-1) super-diagonal elements of A. */

/*  X       (input) DOUBLE PRECISION array, dimension (LDX,NRHS) */
/*          The computed solution vectors X. */

/*  LDX     (input) INTEGER */
/*          The leading dimension of the array X.  LDX >= max(1,N). */

/*  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) */
/*          On entry, the right hand side vectors for the system of */
/*          linear equations. */
/*          On exit, B is overwritten with the difference B - op(A)*X. */

/*  LDB     (input) INTEGER */
/*          The leading dimension of the array B.  LDB >= max(1,N). */

/*  RWORK   (workspace) DOUBLE PRECISION array, dimension (N) */

/*  RESID   (output) DOUBLE PRECISION */
/*          norm(B - op(A)*X) / (norm(A) * norm(X) * EPS) */

/*  ===================================================================== */

/*     .. Parameters .. */
/*     .. */
/*     .. Local Scalars .. */
/*     .. */
/*     .. External Functions .. */
/*     .. */
/*     .. External Subroutines .. */
/*     .. */
/*     .. Intrinsic Functions .. */
/*     .. */
/*     .. Executable Statements .. */

/*     Quick exit if N = 0 or NRHS = 0 */

    /* Parameter adjustments */
    --dl;
    --d__;
    --du;
    x_dim1 = *ldx;
    x_offset = 1 + x_dim1;
    x -= x_offset;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;
    --rwork;

    /* Function Body */
    *resid = 0.;
    if (*n <= 0 || *nrhs == 0) {
	return 0;
    }

/*     Compute the maximum over the number of right hand sides of */
/*        norm(B - op(A)*X) / ( norm(A) * norm(X) * EPS ). */

    if (lsame_(trans, "N")) {
	anorm = dlangt_("1", n, &dl[1], &d__[1], &du[1]);
    } else {
	anorm = dlangt_("I", n, &dl[1], &d__[1], &du[1]);
    }

/*     Exit with RESID = 1/EPS if ANORM = 0. */

    eps = dlamch_("Epsilon");
    if (anorm <= 0.) {
	*resid = 1. / eps;
	return 0;
    }

/*     Compute B - op(A)*X. */

    dlagtm_(trans, n, nrhs, &c_b6, &dl[1], &d__[1], &du[1], &x[x_offset], ldx, 
	     &c_b7, &b[b_offset], ldb);

    i__1 = *nrhs;
    for (j = 1; j <= i__1; ++j) {
	bnorm = dasum_(n, &b[j * b_dim1 + 1], &c__1);
	xnorm = dasum_(n, &x[j * x_dim1 + 1], &c__1);
	if (xnorm <= 0.) {
	    *resid = 1. / eps;
	} else {
/* Computing MAX */
	    d__1 = *resid, d__2 = bnorm / anorm / xnorm / eps;
	    *resid = max(d__1,d__2);
	}
/* L10: */
    }

    return 0;

/*     End of DGTT02 */

} /* dgtt02_ */
Exemplo n.º 2
0
/* Subroutine */ int dchkgt_(logical *dotype, integer *nn, integer *nval, 
	integer *nns, integer *nsval, doublereal *thresh, logical *tsterr, 
	doublereal *a, doublereal *af, doublereal *b, doublereal *x, 
	doublereal *xact, doublereal *work, doublereal *rwork, integer *iwork, 
	 integer *nout)
{
    /* Initialized data */

    static integer iseedy[4] = { 0,0,0,1 };
    static char transs[1*3] = "N" "T" "C";

    /* Format strings */
    static char fmt_9999[] = "(12x,\002N =\002,i5,\002,\002,10x,\002 type"
	    " \002,i2,\002, test(\002,i2,\002) = \002,g12.5)";
    static char fmt_9997[] = "(\002 NORM ='\002,a1,\002', N =\002,i5,\002"
	    ",\002,10x,\002 type \002,i2,\002, test(\002,i2,\002) = \002,g12."
	    "5)";
    static char fmt_9998[] = "(\002 TRANS='\002,a1,\002', N =\002,i5,\002, N"
	    "RHS=\002,i3,\002, type \002,i2,\002, test(\002,i2,\002) = \002,g"
	    "12.5)";

    /* System generated locals */
    integer i__1, i__2, i__3, i__4;
    doublereal d__1, d__2;

    /* Local variables */
    integer i__, j, k, m, n;
    doublereal z__[3];
    integer in, kl, ku, ix, lda;
    doublereal cond;
    integer mode, koff, imat, info;
    char path[3], dist[1];
    integer irhs, nrhs;
    char norm[1], type__[1];
    integer nrun;
    integer nfail, iseed[4];
    doublereal rcond;
    integer nimat;
    doublereal anorm;
    integer itran;
    char trans[1];
    integer izero, nerrs;
    logical zerot;
    doublereal rcondc;
    doublereal rcondi;
    doublereal rcondo;
    doublereal ainvnm;
    logical trfcon;
    doublereal result[7];

    /* Fortran I/O blocks */
    static cilist io___29 = { 0, 0, 0, fmt_9999, 0 };
    static cilist io___39 = { 0, 0, 0, fmt_9997, 0 };
    static cilist io___44 = { 0, 0, 0, fmt_9998, 0 };



/*  -- LAPACK test routine (version 3.1) -- */
/*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
/*     November 2006 */

/*     .. Scalar Arguments .. */
/*     .. */
/*     .. Array Arguments .. */
/*     .. */

/*  Purpose */
/*  ======= */

/*  DCHKGT tests DGTTRF, -TRS, -RFS, and -CON */

/*  Arguments */
/*  ========= */

/*  DOTYPE  (input) LOGICAL array, dimension (NTYPES) */
/*          The matrix types to be used for testing.  Matrices of type j */
/*          (for 1 <= j <= NTYPES) are used for testing if DOTYPE(j) = */
/*          .TRUE.; if DOTYPE(j) = .FALSE., then type j is not used. */

/*  NN      (input) INTEGER */
/*          The number of values of N contained in the vector NVAL. */

/*  NVAL    (input) INTEGER array, dimension (NN) */
/*          The values of the matrix dimension N. */

/*  NNS     (input) INTEGER */
/*          The number of values of NRHS contained in the vector NSVAL. */

/*  NSVAL   (input) INTEGER array, dimension (NNS) */
/*          The values of the number of right hand sides NRHS. */

/*  THRESH  (input) DOUBLE PRECISION */
/*          The threshold value for the test ratios.  A result is */
/*          included in the output file if RESULT >= THRESH.  To have */
/*          every test ratio printed, use THRESH = 0. */

/*  TSTERR  (input) LOGICAL */
/*          Flag that indicates whether error exits are to be tested. */

/*  A       (workspace) DOUBLE PRECISION array, dimension (NMAX*4) */

/*  AF      (workspace) DOUBLE PRECISION array, dimension (NMAX*4) */

/*  B       (workspace) DOUBLE PRECISION array, dimension (NMAX*NSMAX) */
/*          where NSMAX is the largest entry in NSVAL. */

/*  X       (workspace) DOUBLE PRECISION array, dimension (NMAX*NSMAX) */

/*  XACT    (workspace) DOUBLE PRECISION array, dimension (NMAX*NSMAX) */

/*  WORK    (workspace) DOUBLE PRECISION array, dimension */
/*                      (NMAX*max(3,NSMAX)) */

/*  RWORK   (workspace) DOUBLE PRECISION array, dimension */
/*                      (max(NMAX,2*NSMAX)) */

/*  IWORK   (workspace) INTEGER array, dimension (2*NMAX) */

/*  NOUT    (input) INTEGER */
/*          The unit number for output. */

/*  ===================================================================== */

/*     .. Parameters .. */
/*     .. */
/*     .. Local Scalars .. */
/*     .. */
/*     .. Local Arrays .. */
/*     .. */
/*     .. External Functions .. */
/*     .. */
/*     .. External Subroutines .. */
/*     .. */
/*     .. Intrinsic Functions .. */
/*     .. */
/*     .. Scalars in Common .. */
/*     .. */
/*     .. Common blocks .. */
/*     .. */
/*     .. Data statements .. */
    /* Parameter adjustments */
    --iwork;
    --rwork;
    --work;
    --xact;
    --x;
    --b;
    --af;
    --a;
    --nsval;
    --nval;
    --dotype;

    /* Function Body */
/*     .. */
/*     .. Executable Statements .. */

    s_copy(path, "Double precision", (ftnlen)1, (ftnlen)16);
    s_copy(path + 1, "GT", (ftnlen)2, (ftnlen)2);
    nrun = 0;
    nfail = 0;
    nerrs = 0;
    for (i__ = 1; i__ <= 4; ++i__) {
	iseed[i__ - 1] = iseedy[i__ - 1];
/* L10: */
    }

/*     Test the error exits */

    if (*tsterr) {
	derrge_(path, nout);
    }
    infoc_1.infot = 0;

    i__1 = *nn;
    for (in = 1; in <= i__1; ++in) {

/*        Do for each value of N in NVAL. */

	n = nval[in];
/* Computing MAX */
	i__2 = n - 1;
	m = max(i__2,0);
	lda = max(1,n);
	nimat = 12;
	if (n <= 0) {
	    nimat = 1;
	}

	i__2 = nimat;
	for (imat = 1; imat <= i__2; ++imat) {

/*           Do the tests only if DOTYPE( IMAT ) is true. */

	    if (! dotype[imat]) {
		goto L100;
	    }

/*           Set up parameters with DLATB4. */

	    dlatb4_(path, &imat, &n, &n, type__, &kl, &ku, &anorm, &mode, &
		    cond, dist);

	    zerot = imat >= 8 && imat <= 10;
	    if (imat <= 6) {

/*              Types 1-6:  generate matrices of known condition number. */

/* Computing MAX */
		i__3 = 2 - ku, i__4 = 3 - max(1,n);
		koff = max(i__3,i__4);
		s_copy(srnamc_1.srnamt, "DLATMS", (ftnlen)32, (ftnlen)6);
		dlatms_(&n, &n, dist, iseed, type__, &rwork[1], &mode, &cond, 
			&anorm, &kl, &ku, "Z", &af[koff], &c__3, &work[1], &
			info);

/*              Check the error code from DLATMS. */

		if (info != 0) {
		    alaerh_(path, "DLATMS", &info, &c__0, " ", &n, &n, &kl, &
			    ku, &c_n1, &imat, &nfail, &nerrs, nout);
		    goto L100;
		}
		izero = 0;

		if (n > 1) {
		    i__3 = n - 1;
		    dcopy_(&i__3, &af[4], &c__3, &a[1], &c__1);
		    i__3 = n - 1;
		    dcopy_(&i__3, &af[3], &c__3, &a[n + m + 1], &c__1);
		}
		dcopy_(&n, &af[2], &c__3, &a[m + 1], &c__1);
	    } else {

/*              Types 7-12:  generate tridiagonal matrices with */
/*              unknown condition numbers. */

		if (! zerot || ! dotype[7]) {

/*                 Generate a matrix with elements from [-1,1]. */

		    i__3 = n + (m << 1);
		    dlarnv_(&c__2, iseed, &i__3, &a[1]);
		    if (anorm != 1.) {
			i__3 = n + (m << 1);
			dscal_(&i__3, &anorm, &a[1], &c__1);
		    }
		} else if (izero > 0) {

/*                 Reuse the last matrix by copying back the zeroed out */
/*                 elements. */

		    if (izero == 1) {
			a[n] = z__[1];
			if (n > 1) {
			    a[1] = z__[2];
			}
		    } else if (izero == n) {
			a[n * 3 - 2] = z__[0];
			a[(n << 1) - 1] = z__[1];
		    } else {
			a[(n << 1) - 2 + izero] = z__[0];
			a[n - 1 + izero] = z__[1];
			a[izero] = z__[2];
		    }
		}

/*              If IMAT > 7, set one column of the matrix to 0. */

		if (! zerot) {
		    izero = 0;
		} else if (imat == 8) {
		    izero = 1;
		    z__[1] = a[n];
		    a[n] = 0.;
		    if (n > 1) {
			z__[2] = a[1];
			a[1] = 0.;
		    }
		} else if (imat == 9) {
		    izero = n;
		    z__[0] = a[n * 3 - 2];
		    z__[1] = a[(n << 1) - 1];
		    a[n * 3 - 2] = 0.;
		    a[(n << 1) - 1] = 0.;
		} else {
		    izero = (n + 1) / 2;
		    i__3 = n - 1;
		    for (i__ = izero; i__ <= i__3; ++i__) {
			a[(n << 1) - 2 + i__] = 0.;
			a[n - 1 + i__] = 0.;
			a[i__] = 0.;
/* L20: */
		    }
		    a[n * 3 - 2] = 0.;
		    a[(n << 1) - 1] = 0.;
		}
	    }

/* +    TEST 1 */
/*           Factor A as L*U and compute the ratio */
/*              norm(L*U - A) / (n * norm(A) * EPS ) */

	    i__3 = n + (m << 1);
	    dcopy_(&i__3, &a[1], &c__1, &af[1], &c__1);
	    s_copy(srnamc_1.srnamt, "DGTTRF", (ftnlen)32, (ftnlen)6);
	    dgttrf_(&n, &af[1], &af[m + 1], &af[n + m + 1], &af[n + (m << 1) 
		    + 1], &iwork[1], &info);

/*           Check error code from DGTTRF. */

	    if (info != izero) {
		alaerh_(path, "DGTTRF", &info, &izero, " ", &n, &n, &c__1, &
			c__1, &c_n1, &imat, &nfail, &nerrs, nout);
	    }
	    trfcon = info != 0;

	    dgtt01_(&n, &a[1], &a[m + 1], &a[n + m + 1], &af[1], &af[m + 1], &
		    af[n + m + 1], &af[n + (m << 1) + 1], &iwork[1], &work[1], 
		     &lda, &rwork[1], result);

/*           Print the test ratio if it is .GE. THRESH. */

	    if (result[0] >= *thresh) {
		if (nfail == 0 && nerrs == 0) {
		    alahd_(nout, path);
		}
		io___29.ciunit = *nout;
		s_wsfe(&io___29);
		do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer));
		do_fio(&c__1, (char *)&imat, (ftnlen)sizeof(integer));
		do_fio(&c__1, (char *)&c__1, (ftnlen)sizeof(integer));
		do_fio(&c__1, (char *)&result[0], (ftnlen)sizeof(doublereal));
		e_wsfe();
		++nfail;
	    }
	    ++nrun;

	    for (itran = 1; itran <= 2; ++itran) {
		*(unsigned char *)trans = *(unsigned char *)&transs[itran - 1]
			;
		if (itran == 1) {
		    *(unsigned char *)norm = 'O';
		} else {
		    *(unsigned char *)norm = 'I';
		}
		anorm = dlangt_(norm, &n, &a[1], &a[m + 1], &a[n + m + 1]);

		if (! trfcon) {

/*                 Use DGTTRS to solve for one column at a time of inv(A) */
/*                 or inv(A^T), computing the maximum column sum as we */
/*                 go. */

		    ainvnm = 0.;
		    i__3 = n;
		    for (i__ = 1; i__ <= i__3; ++i__) {
			i__4 = n;
			for (j = 1; j <= i__4; ++j) {
			    x[j] = 0.;
/* L30: */
			}
			x[i__] = 1.;
			dgttrs_(trans, &n, &c__1, &af[1], &af[m + 1], &af[n + 
				m + 1], &af[n + (m << 1) + 1], &iwork[1], &x[
				1], &lda, &info);
/* Computing MAX */
			d__1 = ainvnm, d__2 = dasum_(&n, &x[1], &c__1);
			ainvnm = max(d__1,d__2);
/* L40: */
		    }

/*                 Compute RCONDC = 1 / (norm(A) * norm(inv(A)) */

		    if (anorm <= 0. || ainvnm <= 0.) {
			rcondc = 1.;
		    } else {
			rcondc = 1. / anorm / ainvnm;
		    }
		    if (itran == 1) {
			rcondo = rcondc;
		    } else {
			rcondi = rcondc;
		    }
		} else {
		    rcondc = 0.;
		}

/* +    TEST 7 */
/*              Estimate the reciprocal of the condition number of the */
/*              matrix. */

		s_copy(srnamc_1.srnamt, "DGTCON", (ftnlen)32, (ftnlen)6);
		dgtcon_(norm, &n, &af[1], &af[m + 1], &af[n + m + 1], &af[n + 
			(m << 1) + 1], &iwork[1], &anorm, &rcond, &work[1], &
			iwork[n + 1], &info);

/*              Check error code from DGTCON. */

		if (info != 0) {
		    alaerh_(path, "DGTCON", &info, &c__0, norm, &n, &n, &c_n1, 
			     &c_n1, &c_n1, &imat, &nfail, &nerrs, nout);
		}

		result[6] = dget06_(&rcond, &rcondc);

/*              Print the test ratio if it is .GE. THRESH. */

		if (result[6] >= *thresh) {
		    if (nfail == 0 && nerrs == 0) {
			alahd_(nout, path);
		    }
		    io___39.ciunit = *nout;
		    s_wsfe(&io___39);
		    do_fio(&c__1, norm, (ftnlen)1);
		    do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer));
		    do_fio(&c__1, (char *)&imat, (ftnlen)sizeof(integer));
		    do_fio(&c__1, (char *)&c__7, (ftnlen)sizeof(integer));
		    do_fio(&c__1, (char *)&result[6], (ftnlen)sizeof(
			    doublereal));
		    e_wsfe();
		    ++nfail;
		}
		++nrun;
/* L50: */
	    }

/*           Skip the remaining tests if the matrix is singular. */

	    if (trfcon) {
		goto L100;
	    }

	    i__3 = *nns;
	    for (irhs = 1; irhs <= i__3; ++irhs) {
		nrhs = nsval[irhs];

/*              Generate NRHS random solution vectors. */

		ix = 1;
		i__4 = nrhs;
		for (j = 1; j <= i__4; ++j) {
		    dlarnv_(&c__2, iseed, &n, &xact[ix]);
		    ix += lda;
/* L60: */
		}

		for (itran = 1; itran <= 3; ++itran) {
		    *(unsigned char *)trans = *(unsigned char *)&transs[itran 
			    - 1];
		    if (itran == 1) {
			rcondc = rcondo;
		    } else {
			rcondc = rcondi;
		    }

/*                 Set the right hand side. */

		    dlagtm_(trans, &n, &nrhs, &c_b63, &a[1], &a[m + 1], &a[n 
			    + m + 1], &xact[1], &lda, &c_b64, &b[1], &lda);

/* +    TEST 2 */
/*                 Solve op(A) * X = B and compute the residual. */

		    dlacpy_("Full", &n, &nrhs, &b[1], &lda, &x[1], &lda);
		    s_copy(srnamc_1.srnamt, "DGTTRS", (ftnlen)32, (ftnlen)6);
		    dgttrs_(trans, &n, &nrhs, &af[1], &af[m + 1], &af[n + m + 
			    1], &af[n + (m << 1) + 1], &iwork[1], &x[1], &lda, 
			     &info);

/*                 Check error code from DGTTRS. */

		    if (info != 0) {
			alaerh_(path, "DGTTRS", &info, &c__0, trans, &n, &n, &
				c_n1, &c_n1, &nrhs, &imat, &nfail, &nerrs, 
				nout);
		    }

		    dlacpy_("Full", &n, &nrhs, &b[1], &lda, &work[1], &lda);
		    dgtt02_(trans, &n, &nrhs, &a[1], &a[m + 1], &a[n + m + 1], 
			     &x[1], &lda, &work[1], &lda, &rwork[1], &result[
			    1]);

/* +    TEST 3 */
/*                 Check solution from generated exact solution. */

		    dget04_(&n, &nrhs, &x[1], &lda, &xact[1], &lda, &rcondc, &
			    result[2]);

/* +    TESTS 4, 5, and 6 */
/*                 Use iterative refinement to improve the solution. */

		    s_copy(srnamc_1.srnamt, "DGTRFS", (ftnlen)32, (ftnlen)6);
		    dgtrfs_(trans, &n, &nrhs, &a[1], &a[m + 1], &a[n + m + 1], 
			     &af[1], &af[m + 1], &af[n + m + 1], &af[n + (m <<
			     1) + 1], &iwork[1], &b[1], &lda, &x[1], &lda, &
			    rwork[1], &rwork[nrhs + 1], &work[1], &iwork[n + 
			    1], &info);

/*                 Check error code from DGTRFS. */

		    if (info != 0) {
			alaerh_(path, "DGTRFS", &info, &c__0, trans, &n, &n, &
				c_n1, &c_n1, &nrhs, &imat, &nfail, &nerrs, 
				nout);
		    }

		    dget04_(&n, &nrhs, &x[1], &lda, &xact[1], &lda, &rcondc, &
			    result[3]);
		    dgtt05_(trans, &n, &nrhs, &a[1], &a[m + 1], &a[n + m + 1], 
			     &b[1], &lda, &x[1], &lda, &xact[1], &lda, &rwork[
			    1], &rwork[nrhs + 1], &result[4]);

/*                 Print information about the tests that did not pass */
/*                 the threshold. */

		    for (k = 2; k <= 6; ++k) {
			if (result[k - 1] >= *thresh) {
			    if (nfail == 0 && nerrs == 0) {
				alahd_(nout, path);
			    }
			    io___44.ciunit = *nout;
			    s_wsfe(&io___44);
			    do_fio(&c__1, trans, (ftnlen)1);
			    do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer))
				    ;
			    do_fio(&c__1, (char *)&nrhs, (ftnlen)sizeof(
				    integer));
			    do_fio(&c__1, (char *)&imat, (ftnlen)sizeof(
				    integer));
			    do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer))
				    ;
			    do_fio(&c__1, (char *)&result[k - 1], (ftnlen)
				    sizeof(doublereal));
			    e_wsfe();
			    ++nfail;
			}
/* L70: */
		    }
		    nrun += 5;
/* L80: */
		}
/* L90: */
	    }

L100:
	    ;
	}
/* L110: */
    }

/*     Print a summary of the results. */

    alasum_(path, nout, &nfail, &nrun, &nerrs);

    return 0;

/*     End of DCHKGT */

} /* dchkgt_ */
Exemplo n.º 3
0
/* Subroutine */ int dgtrfs_(char *trans, integer *n, integer *nrhs,
                             doublereal *dl, doublereal *d__, doublereal *du, doublereal *dlf,
                             doublereal *df, doublereal *duf, doublereal *du2, integer *ipiv,
                             doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
                             ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
                             info)
{
    /*  -- LAPACK routine (version 3.0) --
           Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
           Courant Institute, Argonne National Lab, and Rice University
           September 30, 1994


        Purpose
        =======

        DGTRFS improves the computed solution to a system of linear
        equations when the coefficient matrix is tridiagonal, and provides
        error bounds and backward error estimates for the solution.

        Arguments
        =========

        TRANS   (input) CHARACTER*1
                Specifies the form of the system of equations:
                = 'N':  A * X = B     (No transpose)
                = 'T':  A**T * X = B  (Transpose)
                = 'C':  A**H * X = B  (Conjugate transpose = Transpose)

        N       (input) INTEGER
                The order of the matrix A.  N >= 0.

        NRHS    (input) INTEGER
                The number of right hand sides, i.e., the number of columns
                of the matrix B.  NRHS >= 0.

        DL      (input) DOUBLE PRECISION array, dimension (N-1)
                The (n-1) subdiagonal elements of A.

        D       (input) DOUBLE PRECISION array, dimension (N)
                The diagonal elements of A.

        DU      (input) DOUBLE PRECISION array, dimension (N-1)
                The (n-1) superdiagonal elements of A.

        DLF     (input) DOUBLE PRECISION array, dimension (N-1)
                The (n-1) multipliers that define the matrix L from the
                LU factorization of A as computed by DGTTRF.

        DF      (input) DOUBLE PRECISION array, dimension (N)
                The n diagonal elements of the upper triangular matrix U from
                the LU factorization of A.

        DUF     (input) DOUBLE PRECISION array, dimension (N-1)
                The (n-1) elements of the first superdiagonal of U.

        DU2     (input) DOUBLE PRECISION array, dimension (N-2)
                The (n-2) elements of the second superdiagonal of U.

        IPIV    (input) INTEGER array, dimension (N)
                The pivot indices; for 1 <= i <= n, row i of the matrix was
                interchanged with row IPIV(i).  IPIV(i) will always be either
                i or i+1; IPIV(i) = i indicates a row interchange was not
                required.

        B       (input) DOUBLE PRECISION array, dimension (LDB,NRHS)
                The right hand side matrix B.

        LDB     (input) INTEGER
                The leading dimension of the array B.  LDB >= max(1,N).

        X       (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)
                On entry, the solution matrix X, as computed by DGTTRS.
                On exit, the improved solution matrix X.

        LDX     (input) INTEGER
                The leading dimension of the array X.  LDX >= max(1,N).

        FERR    (output) DOUBLE PRECISION array, dimension (NRHS)
                The estimated forward error bound for each solution vector
                X(j) (the j-th column of the solution matrix X).
                If XTRUE is the true solution corresponding to X(j), FERR(j)
                is an estimated upper bound for the magnitude of the largest
                element in (X(j) - XTRUE) divided by the magnitude of the
                largest element in X(j).  The estimate is as reliable as
                the estimate for RCOND, and is almost always a slight
                overestimate of the true error.

        BERR    (output) DOUBLE PRECISION array, dimension (NRHS)
                The componentwise relative backward error of each solution
                vector X(j) (i.e., the smallest relative change in
                any element of A or B that makes X(j) an exact solution).

        WORK    (workspace) DOUBLE PRECISION array, dimension (3*N)

        IWORK   (workspace) INTEGER array, dimension (N)

        INFO    (output) INTEGER
                = 0:  successful exit
                < 0:  if INFO = -i, the i-th argument had an illegal value

        Internal Parameters
        ===================

        ITMAX is the maximum number of steps of iterative refinement.

        =====================================================================


           Test the input parameters.

           Parameter adjustments */
    /* Table of constant values */
    static integer c__1 = 1;
    static doublereal c_b18 = -1.;
    static doublereal c_b19 = 1.;

    /* System generated locals */
    integer b_dim1, b_offset, x_dim1, x_offset, i__1, i__2;
    doublereal d__1, d__2, d__3, d__4;
    /* Local variables */
    static integer kase;
    static doublereal safe1, safe2;
    static integer i__, j;
    static doublereal s;
    extern logical lsame_(char *, char *);
    extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *,
                                       doublereal *, integer *), daxpy_(integer *, doublereal *,
                                               doublereal *, integer *, doublereal *, integer *);
    static integer count;
    extern doublereal dlamch_(char *);
    extern /* Subroutine */ int dlacon_(integer *, doublereal *, doublereal *,
                                        integer *, doublereal *, integer *);
    static integer nz;
    extern /* Subroutine */ int dlagtm_(char *, integer *, integer *,
                                        doublereal *, doublereal *, doublereal *, doublereal *,
                                        doublereal *, integer *, doublereal *, doublereal *, integer *);
    static doublereal safmin;
    extern /* Subroutine */ int xerbla_(char *, integer *);
    static logical notran;
    static char transn[1];
    extern /* Subroutine */ int dgttrs_(char *, integer *, integer *,
                                        doublereal *, doublereal *, doublereal *, doublereal *, integer *,
                                        doublereal *, integer *, integer *);
    static char transt[1];
    static doublereal lstres, eps;
#define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1]
#define x_ref(a_1,a_2) x[(a_2)*x_dim1 + a_1]


    --dl;
    --d__;
    --du;
    --dlf;
    --df;
    --duf;
    --du2;
    --ipiv;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1 * 1;
    b -= b_offset;
    x_dim1 = *ldx;
    x_offset = 1 + x_dim1 * 1;
    x -= x_offset;
    --ferr;
    --berr;
    --work;
    --iwork;

    /* Function Body */
    *info = 0;
    notran = lsame_(trans, "N");
    if (! notran && ! lsame_(trans, "T") && ! lsame_(
                trans, "C")) {
        *info = -1;
    } else if (*n < 0) {
        *info = -2;
    } else if (*nrhs < 0) {
        *info = -3;
    } else if (*ldb < max(1,*n)) {
        *info = -13;
    } else if (*ldx < max(1,*n)) {
        *info = -15;
    }
    if (*info != 0) {
        i__1 = -(*info);
        xerbla_("DGTRFS", &i__1);
        return 0;
    }

    /*     Quick return if possible */

    if (*n == 0 || *nrhs == 0) {
        i__1 = *nrhs;
        for (j = 1; j <= i__1; ++j) {
            ferr[j] = 0.;
            berr[j] = 0.;
            /* L10: */
        }
        return 0;
    }

    if (notran) {
        *(unsigned char *)transn = 'N';
        *(unsigned char *)transt = 'T';
    } else {
        *(unsigned char *)transn = 'T';
        *(unsigned char *)transt = 'N';
    }

    /*     NZ = maximum number of nonzero elements in each row of A, plus 1 */

    nz = 4;
    eps = dlamch_("Epsilon");
    safmin = dlamch_("Safe minimum");
    safe1 = nz * safmin;
    safe2 = safe1 / eps;

    /*     Do for each right hand side */

    i__1 = *nrhs;
    for (j = 1; j <= i__1; ++j) {

        count = 1;
        lstres = 3.;
L20:

        /*        Loop until stopping criterion is satisfied.

                  Compute residual R = B - op(A) * X,
                  where op(A) = A, A**T, or A**H, depending on TRANS. */

        dcopy_(n, &b_ref(1, j), &c__1, &work[*n + 1], &c__1);
        dlagtm_(trans, n, &c__1, &c_b18, &dl[1], &d__[1], &du[1], &x_ref(1, j)
                , ldx, &c_b19, &work[*n + 1], n);

        /*        Compute abs(op(A))*abs(x) + abs(b) for use in the backward
                  error bound. */

        if (notran) {
            if (*n == 1) {
                work[1] = (d__1 = b_ref(1, j), abs(d__1)) + (d__2 = d__[1] *
                          x_ref(1, j), abs(d__2));
            } else {
                work[1] = (d__1 = b_ref(1, j), abs(d__1)) + (d__2 = d__[1] *
                          x_ref(1, j), abs(d__2)) + (d__3 = du[1] * x_ref(2, j),
                                                     abs(d__3));
                i__2 = *n - 1;
                for (i__ = 2; i__ <= i__2; ++i__) {
                    work[i__] = (d__1 = b_ref(i__, j), abs(d__1)) + (d__2 =
                                    dl[i__ - 1] * x_ref(i__ - 1, j), abs(d__2)) + (
                                    d__3 = d__[i__] * x_ref(i__, j), abs(d__3)) + (
                                    d__4 = du[i__] * x_ref(i__ + 1, j), abs(d__4));
                    /* L30: */
                }
                work[*n] = (d__1 = b_ref(*n, j), abs(d__1)) + (d__2 = dl[*n -
                           1] * x_ref(*n - 1, j), abs(d__2)) + (d__3 = d__[*n] *
                                   x_ref(*n, j), abs(d__3));
            }
        } else {
            if (*n == 1) {
                work[1] = (d__1 = b_ref(1, j), abs(d__1)) + (d__2 = d__[1] *
                          x_ref(1, j), abs(d__2));
            } else {
                work[1] = (d__1 = b_ref(1, j), abs(d__1)) + (d__2 = d__[1] *
                          x_ref(1, j), abs(d__2)) + (d__3 = dl[1] * x_ref(2, j),
                                                     abs(d__3));
                i__2 = *n - 1;
                for (i__ = 2; i__ <= i__2; ++i__) {
                    work[i__] = (d__1 = b_ref(i__, j), abs(d__1)) + (d__2 =
                                    du[i__ - 1] * x_ref(i__ - 1, j), abs(d__2)) + (
                                    d__3 = d__[i__] * x_ref(i__, j), abs(d__3)) + (
                                    d__4 = dl[i__] * x_ref(i__ + 1, j), abs(d__4));
                    /* L40: */
                }
                work[*n] = (d__1 = b_ref(*n, j), abs(d__1)) + (d__2 = du[*n -
                           1] * x_ref(*n - 1, j), abs(d__2)) + (d__3 = d__[*n] *
                                   x_ref(*n, j), abs(d__3));
            }
        }

        /*        Compute componentwise relative backward error from formula

                  max(i) ( abs(R(i)) / ( abs(op(A))*abs(X) + abs(B) )(i) )

                  where abs(Z) is the componentwise absolute value of the matrix
                  or vector Z.  If the i-th component of the denominator is less
                  than SAFE2, then SAFE1 is added to the i-th components of the
                  numerator and denominator before dividing. */

        s = 0.;
        i__2 = *n;
        for (i__ = 1; i__ <= i__2; ++i__) {
            if (work[i__] > safe2) {
                /* Computing MAX */
                d__2 = s, d__3 = (d__1 = work[*n + i__], abs(d__1)) / work[
                                     i__];
                s = max(d__2,d__3);
            } else {
                /* Computing MAX */
                d__2 = s, d__3 = ((d__1 = work[*n + i__], abs(d__1)) + safe1)
                                 / (work[i__] + safe1);
                s = max(d__2,d__3);
            }
            /* L50: */
        }
        berr[j] = s;

        /*        Test stopping criterion. Continue iterating if
                     1) The residual BERR(J) is larger than machine epsilon, and
                     2) BERR(J) decreased by at least a factor of 2 during the
                        last iteration, and
                     3) At most ITMAX iterations tried. */

        if (berr[j] > eps && berr[j] * 2. <= lstres && count <= 5) {

            /*           Update solution and try again. */

            dgttrs_(trans, n, &c__1, &dlf[1], &df[1], &duf[1], &du2[1], &ipiv[
                        1], &work[*n + 1], n, info);
            daxpy_(n, &c_b19, &work[*n + 1], &c__1, &x_ref(1, j), &c__1);
            lstres = berr[j];
            ++count;
            goto L20;
        }

        /*        Bound error from formula

                  norm(X - XTRUE) / norm(X) .le. FERR =
                  norm( abs(inv(op(A)))*
                     ( abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) ))) / norm(X)

                  where
                    norm(Z) is the magnitude of the largest component of Z
                    inv(op(A)) is the inverse of op(A)
                    abs(Z) is the componentwise absolute value of the matrix or
                       vector Z
                    NZ is the maximum number of nonzeros in any row of A, plus 1
                    EPS is machine epsilon

                  The i-th component of abs(R)+NZ*EPS*(abs(op(A))*abs(X)+abs(B))
                  is incremented by SAFE1 if the i-th component of
                  abs(op(A))*abs(X) + abs(B) is less than SAFE2.

                  Use DLACON to estimate the infinity-norm of the matrix
                     inv(op(A)) * diag(W),
                  where W = abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) ))) */

        i__2 = *n;
        for (i__ = 1; i__ <= i__2; ++i__) {
            if (work[i__] > safe2) {
                work[i__] = (d__1 = work[*n + i__], abs(d__1)) + nz * eps *
                            work[i__];
            } else {
                work[i__] = (d__1 = work[*n + i__], abs(d__1)) + nz * eps *
                            work[i__] + safe1;
            }
            /* L60: */
        }

        kase = 0;
L70:
        dlacon_(n, &work[(*n << 1) + 1], &work[*n + 1], &iwork[1], &ferr[j], &
                kase);
        if (kase != 0) {
            if (kase == 1) {

                /*              Multiply by diag(W)*inv(op(A)**T). */

                dgttrs_(transt, n, &c__1, &dlf[1], &df[1], &duf[1], &du2[1], &
                        ipiv[1], &work[*n + 1], n, info);
                i__2 = *n;
                for (i__ = 1; i__ <= i__2; ++i__) {
                    work[*n + i__] = work[i__] * work[*n + i__];
                    /* L80: */
                }
            } else {

                /*              Multiply by inv(op(A))*diag(W). */

                i__2 = *n;
                for (i__ = 1; i__ <= i__2; ++i__) {
                    work[*n + i__] = work[i__] * work[*n + i__];
                    /* L90: */
                }
                dgttrs_(transn, n, &c__1, &dlf[1], &df[1], &duf[1], &du2[1], &
                        ipiv[1], &work[*n + 1], n, info);
            }
            goto L70;
        }

        /*        Normalize error. */

        lstres = 0.;
        i__2 = *n;
        for (i__ = 1; i__ <= i__2; ++i__) {
            /* Computing MAX */
            d__2 = lstres, d__3 = (d__1 = x_ref(i__, j), abs(d__1));
            lstres = max(d__2,d__3);
            /* L100: */
        }
        if (lstres != 0.) {
            ferr[j] /= lstres;
        }

        /* L110: */
    }

    return 0;

    /*     End of DGTRFS */

} /* dgtrfs_ */