Пример #1
0
/* Subroutine */ int chesv_(char *uplo, integer *n, integer *nrhs, complex *a,
	 integer *lda, integer *ipiv, complex *b, integer *ldb, complex *work,
	 integer *lwork, integer *info, ftnlen uplo_len)
{
    /* System generated locals */
    integer a_dim1, a_offset, b_dim1, b_offset, i__1;

    /* Local variables */
    static integer nb;
    extern logical lsame_(char *, char *, ftnlen, ftnlen);
    extern /* Subroutine */ int chetrf_(char *, integer *, complex *, integer 
	    *, integer *, complex *, integer *, integer *, ftnlen), xerbla_(
	    char *, integer *, ftnlen);
    extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
	    integer *, integer *, ftnlen, ftnlen);
    extern /* Subroutine */ int chetrs_(char *, integer *, integer *, complex 
	    *, integer *, integer *, complex *, integer *, integer *, ftnlen);
    static integer lwkopt;
    static logical lquery;


/*  -- LAPACK driver routine (version 3.0) -- */
/*     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */
/*     Courant Institute, Argonne National Lab, and Rice University */
/*     June 30, 1999 */

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

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

/*  CHESV computes the solution to a complex system of linear equations */
/*     A * X = B, */
/*  where A is an N-by-N Hermitian matrix and X and B are N-by-NRHS */
/*  matrices. */

/*  The diagonal pivoting method is used to factor A as */
/*     A = U * D * U**H,  if UPLO = 'U', or */
/*     A = L * D * L**H,  if UPLO = 'L', */
/*  where U (or L) is a product of permutation and unit upper (lower) */
/*  triangular matrices, and D is Hermitian and block diagonal with */
/*  1-by-1 and 2-by-2 diagonal blocks.  The factored form of A is then */
/*  used to solve the system of equations A * X = B. */

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

/*  UPLO    (input) CHARACTER*1 */
/*          = 'U':  Upper triangle of A is stored; */
/*          = 'L':  Lower triangle of A is stored. */

/*  N       (input) INTEGER */
/*          The number of linear equations, i.e., 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. */

/*  A       (input/output) COMPLEX array, dimension (LDA,N) */
/*          On entry, the Hermitian matrix A.  If UPLO = 'U', the leading */
/*          N-by-N upper triangular part of A contains the upper */
/*          triangular part of the matrix A, and the strictly lower */
/*          triangular part of A is not referenced.  If UPLO = 'L', the */
/*          leading N-by-N lower triangular part of A contains the lower */
/*          triangular part of the matrix A, and the strictly upper */
/*          triangular part of A is not referenced. */

/*          On exit, if INFO = 0, the block diagonal matrix D and the */
/*          multipliers used to obtain the factor U or L from the */
/*          factorization A = U*D*U**H or A = L*D*L**H as computed by */
/*          CHETRF. */

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

/*  IPIV    (output) INTEGER array, dimension (N) */
/*          Details of the interchanges and the block structure of D, as */
/*          determined by CHETRF.  If IPIV(k) > 0, then rows and columns */
/*          k and IPIV(k) were interchanged, and D(k,k) is a 1-by-1 */
/*          diagonal block.  If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0, */
/*          then rows and columns k-1 and -IPIV(k) were interchanged and */
/*          D(k-1:k,k-1:k) is a 2-by-2 diagonal block.  If UPLO = 'L' and */
/*          IPIV(k) = IPIV(k+1) < 0, then rows and columns k+1 and */
/*          -IPIV(k) were interchanged and D(k:k+1,k:k+1) is a 2-by-2 */
/*          diagonal block. */

/*  B       (input/output) COMPLEX array, dimension (LDB,NRHS) */
/*          On entry, the N-by-NRHS right hand side matrix B. */
/*          On exit, if INFO = 0, the N-by-NRHS solution matrix X. */

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

/*  WORK    (workspace/output) COMPLEX array, dimension (LWORK) */
/*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */

/*  LWORK   (input) INTEGER */
/*          The length of WORK.  LWORK >= 1, and for best performance */
/*          LWORK >= N*NB, where NB is the optimal blocksize for */
/*          CHETRF. */

/*          If LWORK = -1, then a workspace query is assumed; the routine */
/*          only calculates the optimal size of the WORK array, returns */
/*          this value as the first entry of the WORK array, and no error */
/*          message related to LWORK is issued by XERBLA. */

/*  INFO    (output) INTEGER */
/*          = 0: successful exit */
/*          < 0: if INFO = -i, the i-th argument had an illegal value */
/*          > 0: if INFO = i, D(i,i) is exactly zero.  The factorization */
/*               has been completed, but the block diagonal matrix D is */
/*               exactly singular, so the solution could not be computed. */

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

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

/*     Test the input parameters. */

    /* Parameter adjustments */
    a_dim1 = *lda;
    a_offset = 1 + a_dim1;
    a -= a_offset;
    --ipiv;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;
    --work;

    /* Function Body */
    *info = 0;
    lquery = *lwork == -1;
    if (! lsame_(uplo, "U", (ftnlen)1, (ftnlen)1) && ! lsame_(uplo, "L", (
	    ftnlen)1, (ftnlen)1)) {
	*info = -1;
    } else if (*n < 0) {
	*info = -2;
    } else if (*nrhs < 0) {
	*info = -3;
    } else if (*lda < max(1,*n)) {
	*info = -5;
    } else if (*ldb < max(1,*n)) {
	*info = -8;
    } else if (*lwork < 1 && ! lquery) {
	*info = -10;
    }

    if (*info == 0) {
	nb = ilaenv_(&c__1, "CHETRF", uplo, n, &c_n1, &c_n1, &c_n1, (ftnlen)6,
		 (ftnlen)1);
	lwkopt = *n * nb;
	work[1].r = (real) lwkopt, work[1].i = 0.f;
    }

    if (*info != 0) {
	i__1 = -(*info);
	xerbla_("CHESV ", &i__1, (ftnlen)6);
	return 0;
    } else if (lquery) {
	return 0;
    }

/*     Compute the factorization A = U*D*U' or A = L*D*L'. */

    chetrf_(uplo, n, &a[a_offset], lda, &ipiv[1], &work[1], lwork, info, (
	    ftnlen)1);
    if (*info == 0) {

/*        Solve the system A*X = B, overwriting B with X. */

	chetrs_(uplo, n, nrhs, &a[a_offset], lda, &ipiv[1], &b[b_offset], ldb,
		 info, (ftnlen)1);

    }

    work[1].r = (real) lwkopt, work[1].i = 0.f;

    return 0;

/*     End of CHESV */

} /* chesv_ */
Пример #2
0
/* Subroutine */ int chesvx_(char *fact, char *uplo, integer *n, integer *
	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
	ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, 
	 real *ferr, real *berr, complex *work, integer *lwork, real *rwork, 
	integer *info)
{
    /* System generated locals */
    integer a_dim1, a_offset, af_dim1, af_offset, b_dim1, b_offset, x_dim1, 
	    x_offset, i__1, i__2;

    /* Local variables */
    integer nb;
    extern logical lsame_(char *, char *);
    real anorm;
    extern doublereal clanhe_(char *, char *, integer *, complex *, integer *, 
	     real *);
    extern /* Subroutine */ int checon_(char *, integer *, complex *, integer 
	    *, integer *, real *, real *, complex *, integer *);
    extern doublereal slamch_(char *);
    logical nofact;
    extern /* Subroutine */ int cherfs_(char *, integer *, integer *, complex 
	    *, integer *, complex *, integer *, integer *, complex *, integer 
	    *, complex *, integer *, real *, real *, complex *, real *, 
	    integer *), chetrf_(char *, integer *, complex *, integer 
	    *, integer *, complex *, integer *, integer *), clacpy_(
	    char *, integer *, integer *, complex *, integer *, complex *, 
	    integer *);
    extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
	    integer *, integer *);
    extern /* Subroutine */ int xerbla_(char *, integer *), chetrs_(
	    char *, integer *, integer *, complex *, integer *, integer *, 
	    complex *, integer *, integer *);
    integer lwkopt;
    logical lquery;


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

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

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

/*  CHESVX uses the diagonal pivoting factorization to compute the */
/*  solution to a complex system of linear equations A * X = B, */
/*  where A is an N-by-N Hermitian matrix and X and B are N-by-NRHS */
/*  matrices. */

/*  Error bounds on the solution and a condition estimate are also */
/*  provided. */

/*  Description */
/*  =========== */

/*  The following steps are performed: */

/*  1. If FACT = 'N', the diagonal pivoting method is used to factor A. */
/*     The form of the factorization is */
/*        A = U * D * U**H,  if UPLO = 'U', or */
/*        A = L * D * L**H,  if UPLO = 'L', */
/*     where U (or L) is a product of permutation and unit upper (lower) */
/*     triangular matrices, and D is Hermitian and block diagonal with */
/*     1-by-1 and 2-by-2 diagonal blocks. */

/*  2. If some D(i,i)=0, so that D is exactly singular, then the routine */
/*     returns with INFO = i. Otherwise, the factored form of A is used */
/*     to estimate the condition number of the matrix A.  If the */
/*     reciprocal of the condition number is less than machine precision, */
/*     INFO = N+1 is returned as a warning, but the routine still goes on */
/*     to solve for X and compute error bounds as described below. */

/*  3. The system of equations is solved for X using the factored form */
/*     of A. */

/*  4. Iterative refinement is applied to improve the computed solution */
/*     matrix and calculate error bounds and backward error estimates */
/*     for it. */

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

/*  FACT    (input) CHARACTER*1 */
/*          Specifies whether or not the factored form of A has been */
/*          supplied on entry. */
/*          = 'F':  On entry, AF and IPIV contain the factored form */
/*                  of A.  A, AF and IPIV will not be modified. */
/*          = 'N':  The matrix A will be copied to AF and factored. */

/*  UPLO    (input) CHARACTER*1 */
/*          = 'U':  Upper triangle of A is stored; */
/*          = 'L':  Lower triangle of A is stored. */

/*  N       (input) INTEGER */
/*          The number of linear equations, i.e., 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. */

/*  A       (input) COMPLEX array, dimension (LDA,N) */
/*          The Hermitian matrix A.  If UPLO = 'U', the leading N-by-N */
/*          upper triangular part of A contains the upper triangular part */
/*          of the matrix A, and the strictly lower triangular part of A */
/*          is not referenced.  If UPLO = 'L', the leading N-by-N lower */
/*          triangular part of A contains the lower triangular part of */
/*          the matrix A, and the strictly upper triangular part of A is */
/*          not referenced. */

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

/*  AF      (input or output) COMPLEX array, dimension (LDAF,N) */
/*          If FACT = 'F', then AF is an input argument and on entry */
/*          contains the block diagonal matrix D and the multipliers used */
/*          to obtain the factor U or L from the factorization */
/*          A = U*D*U**H or A = L*D*L**H as computed by CHETRF. */

/*          If FACT = 'N', then AF is an output argument and on exit */
/*          returns the block diagonal matrix D and the multipliers used */
/*          to obtain the factor U or L from the factorization */
/*          A = U*D*U**H or A = L*D*L**H. */

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

/*  IPIV    (input or output) INTEGER array, dimension (N) */
/*          If FACT = 'F', then IPIV is an input argument and on entry */
/*          contains details of the interchanges and the block structure */
/*          of D, as determined by CHETRF. */
/*          If IPIV(k) > 0, then rows and columns k and IPIV(k) were */
/*          interchanged and D(k,k) is a 1-by-1 diagonal block. */
/*          If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0, then rows and */
/*          columns k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k) */
/*          is a 2-by-2 diagonal block.  If UPLO = 'L' and IPIV(k) = */
/*          IPIV(k+1) < 0, then rows and columns k+1 and -IPIV(k) were */
/*          interchanged and D(k:k+1,k:k+1) is a 2-by-2 diagonal block. */

/*          If FACT = 'N', then IPIV is an output argument and on exit */
/*          contains details of the interchanges and the block structure */
/*          of D, as determined by CHETRF. */

/*  B       (input) COMPLEX array, dimension (LDB,NRHS) */
/*          The N-by-NRHS right hand side matrix B. */

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

/*  X       (output) COMPLEX array, dimension (LDX,NRHS) */
/*          If INFO = 0 or INFO = N+1, the N-by-NRHS solution matrix X. */

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

/*  RCOND   (output) REAL */
/*          The estimate of the reciprocal condition number of the matrix */
/*          A.  If RCOND is less than the machine precision (in */
/*          particular, if RCOND = 0), the matrix is singular to working */
/*          precision.  This condition is indicated by a return code of */
/*          INFO > 0. */

/*  FERR    (output) REAL 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) REAL 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/output) COMPLEX array, dimension (MAX(1,LWORK)) */
/*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */

/*  LWORK   (input) INTEGER */
/*          The length of WORK.  LWORK >= max(1,2*N), and for best */
/*          performance, when FACT = 'N', LWORK >= max(1,2*N,N*NB), where */
/*          NB is the optimal blocksize for CHETRF. */

/*          If LWORK = -1, then a workspace query is assumed; the routine */
/*          only calculates the optimal size of the WORK array, returns */
/*          this value as the first entry of the WORK array, and no error */
/*          message related to LWORK is issued by XERBLA. */

/*  RWORK   (workspace) REAL array, dimension (N) */

/*  INFO    (output) INTEGER */
/*          = 0: successful exit */
/*          < 0: if INFO = -i, the i-th argument had an illegal value */
/*          > 0: if INFO = i, and i is */
/*                <= N:  D(i,i) is exactly zero.  The factorization */
/*                       has been completed but the factor D is exactly */
/*                       singular, so the solution and error bounds could */
/*                       not be computed. RCOND = 0 is returned. */
/*                = N+1: D is nonsingular, but RCOND is less than machine */
/*                       precision, meaning that the matrix is singular */
/*                       to working precision.  Nevertheless, the */
/*                       solution and error bounds are computed because */
/*                       there are a number of situations where the */
/*                       computed solution can be more accurate than the */
/*                       value of RCOND would suggest. */

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

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

/*     Test the input parameters. */

    /* Parameter adjustments */
    a_dim1 = *lda;
    a_offset = 1 + a_dim1;
    a -= a_offset;
    af_dim1 = *ldaf;
    af_offset = 1 + af_dim1;
    af -= af_offset;
    --ipiv;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;
    x_dim1 = *ldx;
    x_offset = 1 + x_dim1;
    x -= x_offset;
    --ferr;
    --berr;
    --work;
    --rwork;

    /* Function Body */
    *info = 0;
    nofact = lsame_(fact, "N");
    lquery = *lwork == -1;
    if (! nofact && ! lsame_(fact, "F")) {
	*info = -1;
    } else if (! lsame_(uplo, "U") && ! lsame_(uplo, 
	    "L")) {
	*info = -2;
    } else if (*n < 0) {
	*info = -3;
    } else if (*nrhs < 0) {
	*info = -4;
    } else if (*lda < max(1,*n)) {
	*info = -6;
    } else if (*ldaf < max(1,*n)) {
	*info = -8;
    } else if (*ldb < max(1,*n)) {
	*info = -11;
    } else if (*ldx < max(1,*n)) {
	*info = -13;
    } else /* if(complicated condition) */ {
/* Computing MAX */
	i__1 = 1, i__2 = *n << 1;
	if (*lwork < max(i__1,i__2) && ! lquery) {
	    *info = -18;
	}
    }

    if (*info == 0) {
/* Computing MAX */
	i__1 = 1, i__2 = *n << 1;
	lwkopt = max(i__1,i__2);
	if (nofact) {
	    nb = ilaenv_(&c__1, "CHETRF", uplo, n, &c_n1, &c_n1, &c_n1);
/* Computing MAX */
	    i__1 = lwkopt, i__2 = *n * nb;
	    lwkopt = max(i__1,i__2);
	}
	work[1].r = (real) lwkopt, work[1].i = 0.f;
    }

    if (*info != 0) {
	i__1 = -(*info);
	xerbla_("CHESVX", &i__1);
	return 0;
    } else if (lquery) {
	return 0;
    }

    if (nofact) {

/*        Compute the factorization A = U*D*U' or A = L*D*L'. */

	clacpy_(uplo, n, n, &a[a_offset], lda, &af[af_offset], ldaf);
	chetrf_(uplo, n, &af[af_offset], ldaf, &ipiv[1], &work[1], lwork, 
		info);

/*        Return if INFO is non-zero. */

	if (*info > 0) {
	    *rcond = 0.f;
	    return 0;
	}
    }

/*     Compute the norm of the matrix A. */

    anorm = clanhe_("I", uplo, n, &a[a_offset], lda, &rwork[1]);

/*     Compute the reciprocal of the condition number of A. */

    checon_(uplo, n, &af[af_offset], ldaf, &ipiv[1], &anorm, rcond, &work[1], 
	    info);

/*     Compute the solution vectors X. */

    clacpy_("Full", n, nrhs, &b[b_offset], ldb, &x[x_offset], ldx);
    chetrs_(uplo, n, nrhs, &af[af_offset], ldaf, &ipiv[1], &x[x_offset], ldx, 
	    info);

/*     Use iterative refinement to improve the computed solutions and */
/*     compute error bounds and backward error estimates for them. */

    cherfs_(uplo, n, nrhs, &a[a_offset], lda, &af[af_offset], ldaf, &ipiv[1], 
	    &b[b_offset], ldb, &x[x_offset], ldx, &ferr[1], &berr[1], &work[1]
, &rwork[1], info);

/*     Set INFO = N+1 if the matrix is singular to working precision. */

    if (*rcond < slamch_("Epsilon")) {
	*info = *n + 1;
    }

    work[1].r = (real) lwkopt, work[1].i = 0.f;

    return 0;

/*     End of CHESVX */

} /* chesvx_ */
Пример #3
0
/* Subroutine */ int cchkhe_(logical *dotype, integer *nn, integer *nval,
                             integer *nnb, integer *nbval, integer *nns, integer *nsval, real *
                             thresh, logical *tsterr, integer *nmax, complex *a, complex *afac,
                             complex *ainv, complex *b, complex *x, complex *xact, complex *work,
                             real *rwork, integer *iwork, integer *nout)
{
    /* Initialized data */

    static integer iseedy[4] = { 1988,1989,1990,1991 };
    static char uplos[1*2] = "U" "L";

    /* Format strings */
    static char fmt_9999[] = "(\002 UPLO = '\002,a1,\002', N =\002,i5,\002, "
                             "NB =\002,i4,\002, type \002,i2,\002, test \002,i2,\002, ratio "
                             "=\002,g12.5)";
    static char fmt_9998[] = "(\002 UPLO = '\002,a1,\002', N =\002,i5,\002, "
                             "NRHS=\002,i3,\002, type \002,i2,\002, test(\002,i2,\002) =\002,g"
                             "12.5)";
    static char fmt_9997[] = "(\002 UPLO = '\002,a1,\002', N =\002,i5,\002"
                             ",\002,10x,\002 type \002,i2,\002, test(\002,i2,\002) =\002,g12.5)"
                             ;

    /* System generated locals */
    integer i__1, i__2, i__3, i__4, i__5;

    /* Builtin functions */
    /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);
    integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void);

    /* Local variables */
    integer i__, j, k, n, i1, i2, nb, in, kl, ku, nt, lda, inb, ioff, mode,
            imat, info;
    char path[3], dist[1];
    integer irhs, nrhs;
    char uplo[1], type__[1];
    integer nrun;
    extern /* Subroutine */ int alahd_(integer *, char *), chet01_(
        char *, integer *, complex *, integer *, complex *, integer *,
        integer *, complex *, integer *, real *, real *), cget04_(
            integer *, integer *, complex *, integer *, complex *, integer *,
            real *, real *);
    integer nfail, iseed[4];
    real rcond;
    extern /* Subroutine */ int cpot02_(char *, integer *, integer *, complex
                                        *, integer *, complex *, integer *, complex *, integer *, real *,
                                        real *);
    integer nimat;
    extern doublereal sget06_(real *, real *);
    extern /* Subroutine */ int cpot03_(char *, integer *, complex *, integer
                                        *, complex *, integer *, complex *, integer *, real *, real *,
                                        real *), cpot05_(char *, integer *, integer *, complex *,
                                                integer *, complex *, integer *, complex *, integer *, complex *,
                                                integer *, real *, real *, real *);
    real anorm;
    integer iuplo, izero, nerrs, lwork;
    logical zerot;
    char xtype[1];
    extern /* Subroutine */ int clatb4_(char *, integer *, integer *, integer
                                        *, char *, integer *, integer *, real *, integer *, real *, char *
                                       );
    extern doublereal clanhe_(char *, char *, integer *, complex *, integer *,
                              real *);
    extern /* Subroutine */ int alaerh_(char *, char *, integer *, integer *,
                                        char *, integer *, integer *, integer *, integer *, integer *,
                                        integer *, integer *, integer *, integer *), claipd_(integer *, complex *, integer *, integer *),
                                                checon_(char *, integer *, complex *, integer *, integer *, real *
                                                        , real *, complex *, integer *);
    real rcondc;
    extern /* Subroutine */ int cerrhe_(char *, integer *), cherfs_(
        char *, integer *, integer *, complex *, integer *, complex *,
        integer *, integer *, complex *, integer *, complex *, integer *,
        real *, real *, complex *, real *, integer *), chetrf_(
            char *, integer *, complex *, integer *, integer *, complex *,
            integer *, integer *), clacpy_(char *, integer *, integer
                                           *, complex *, integer *, complex *, integer *), clarhs_(
                                                   char *, char *, char *, char *, integer *, integer *, integer *,
                                                   integer *, integer *, complex *, integer *, complex *, integer *,
                                                   complex *, integer *, integer *, integer *), chetri_(char *, integer *, complex *, integer *,
                                                           integer *, complex *, integer *), alasum_(char *, integer
                                                                   *, integer *, integer *, integer *);
    real cndnum;
    extern /* Subroutine */ int clatms_(integer *, integer *, char *, integer
                                        *, char *, real *, integer *, real *, real *, integer *, integer *
                                        , char *, complex *, integer *, complex *, integer *), chetrs_(char *, integer *, integer *, complex *,
                                                integer *, integer *, complex *, integer *, integer *);
    logical trfcon;
    extern /* Subroutine */ int xlaenv_(integer *, integer *);
    real result[8];

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



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

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

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

    /*  CCHKHE tests CHETRF, -TRI, -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. */

    /*  NNB     (input) INTEGER */
    /*          The number of values of NB contained in the vector NBVAL. */

    /*  NBVAL   (input) INTEGER array, dimension (NBVAL) */
    /*          The values of the blocksize NB. */

    /*  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) REAL */
    /*          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. */

    /*  NMAX    (input) INTEGER */
    /*          The maximum value permitted for N, used in dimensioning the */
    /*          work arrays. */

    /*  A       (workspace) COMPLEX array, dimension (NMAX*NMAX) */

    /*  AFAC    (workspace) COMPLEX array, dimension (NMAX*NMAX) */

    /*  AINV    (workspace) COMPLEX array, dimension (NMAX*NMAX) */

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

    /*  X       (workspace) COMPLEX array, dimension (NMAX*NSMAX) */

    /*  XACT    (workspace) COMPLEX array, dimension (NMAX*NSMAX) */

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

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

    /*  IWORK   (workspace) INTEGER array, dimension (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;
    --ainv;
    --afac;
    --a;
    --nsval;
    --nbval;
    --nval;
    --dotype;

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

    /*     Initialize constants and the random number seed. */

    s_copy(path, "Complex precision", (ftnlen)1, (ftnlen)17);
    s_copy(path + 1, "HE", (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) {
        cerrhe_(path, nout);
    }
    infoc_1.infot = 0;

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

    i__1 = *nn;
    for (in = 1; in <= i__1; ++in) {
        n = nval[in];
        lda = max(n,1);
        *(unsigned char *)xtype = 'N';
        nimat = 10;
        if (n <= 0) {
            nimat = 1;
        }

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

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

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

            /*           Skip types 3, 4, 5, or 6 if the matrix size is too small. */

            zerot = imat >= 3 && imat <= 6;
            if (zerot && n < imat - 2) {
                goto L170;
            }

            /*           Do first for UPLO = 'U', then for UPLO = 'L' */

            for (iuplo = 1; iuplo <= 2; ++iuplo) {
                *(unsigned char *)uplo = *(unsigned char *)&uplos[iuplo - 1];

                /*              Set up parameters with CLATB4 and generate a test matrix */
                /*              with CLATMS. */

                clatb4_(path, &imat, &n, &n, type__, &kl, &ku, &anorm, &mode,
                        &cndnum, dist);

                s_copy(srnamc_1.srnamt, "CLATMS", (ftnlen)32, (ftnlen)6);
                clatms_(&n, &n, dist, iseed, type__, &rwork[1], &mode, &
                        cndnum, &anorm, &kl, &ku, uplo, &a[1], &lda, &work[1],
                        &info);

                /*              Check error code from CLATMS. */

                if (info != 0) {
                    alaerh_(path, "CLATMS", &info, &c__0, uplo, &n, &n, &c_n1,
                            &c_n1, &c_n1, &imat, &nfail, &nerrs, nout);
                    goto L160;
                }

                /*              For types 3-6, zero one or more rows and columns of */
                /*              the matrix to test that INFO is returned correctly. */

                if (zerot) {
                    if (imat == 3) {
                        izero = 1;
                    } else if (imat == 4) {
                        izero = n;
                    } else {
                        izero = n / 2 + 1;
                    }

                    if (imat < 6) {

                        /*                    Set row and column IZERO to zero. */

                        if (iuplo == 1) {
                            ioff = (izero - 1) * lda;
                            i__3 = izero - 1;
                            for (i__ = 1; i__ <= i__3; ++i__) {
                                i__4 = ioff + i__;
                                a[i__4].r = 0.f, a[i__4].i = 0.f;
                                /* L20: */
                            }
                            ioff += izero;
                            i__3 = n;
                            for (i__ = izero; i__ <= i__3; ++i__) {
                                i__4 = ioff;
                                a[i__4].r = 0.f, a[i__4].i = 0.f;
                                ioff += lda;
                                /* L30: */
                            }
                        } else {
                            ioff = izero;
                            i__3 = izero - 1;
                            for (i__ = 1; i__ <= i__3; ++i__) {
                                i__4 = ioff;
                                a[i__4].r = 0.f, a[i__4].i = 0.f;
                                ioff += lda;
                                /* L40: */
                            }
                            ioff -= izero;
                            i__3 = n;
                            for (i__ = izero; i__ <= i__3; ++i__) {
                                i__4 = ioff + i__;
                                a[i__4].r = 0.f, a[i__4].i = 0.f;
                                /* L50: */
                            }
                        }
                    } else {
                        ioff = 0;
                        if (iuplo == 1) {

                            /*                       Set the first IZERO rows and columns to zero. */

                            i__3 = n;
                            for (j = 1; j <= i__3; ++j) {
                                i2 = min(j,izero);
                                i__4 = i2;
                                for (i__ = 1; i__ <= i__4; ++i__) {
                                    i__5 = ioff + i__;
                                    a[i__5].r = 0.f, a[i__5].i = 0.f;
                                    /* L60: */
                                }
                                ioff += lda;
                                /* L70: */
                            }
                        } else {

                            /*                       Set the last IZERO rows and columns to zero. */

                            i__3 = n;
                            for (j = 1; j <= i__3; ++j) {
                                i1 = max(j,izero);
                                i__4 = n;
                                for (i__ = i1; i__ <= i__4; ++i__) {
                                    i__5 = ioff + i__;
                                    a[i__5].r = 0.f, a[i__5].i = 0.f;
                                    /* L80: */
                                }
                                ioff += lda;
                                /* L90: */
                            }
                        }
                    }
                } else {
                    izero = 0;
                }

                /*              Set the imaginary part of the diagonals. */

                i__3 = lda + 1;
                claipd_(&n, &a[1], &i__3, &c__0);

                /*              Do for each value of NB in NBVAL */

                i__3 = *nnb;
                for (inb = 1; inb <= i__3; ++inb) {
                    nb = nbval[inb];
                    xlaenv_(&c__1, &nb);

                    /*                 Compute the L*D*L' or U*D*U' factorization of the */
                    /*                 matrix. */

                    clacpy_(uplo, &n, &n, &a[1], &lda, &afac[1], &lda);
                    lwork = max(2,nb) * lda;
                    s_copy(srnamc_1.srnamt, "CHETRF", (ftnlen)32, (ftnlen)6);
                    chetrf_(uplo, &n, &afac[1], &lda, &iwork[1], &ainv[1], &
                            lwork, &info);

                    /*                 Adjust the expected value of INFO to account for */
                    /*                 pivoting. */

                    k = izero;
                    if (k > 0) {
L100:
                        if (iwork[k] < 0) {
                            if (iwork[k] != -k) {
                                k = -iwork[k];
                                goto L100;
                            }
                        } else if (iwork[k] != k) {
                            k = iwork[k];
                            goto L100;
                        }
                    }

                    /*                 Check error code from CHETRF. */

                    if (info != k) {
                        alaerh_(path, "CHETRF", &info, &k, uplo, &n, &n, &
                                c_n1, &c_n1, &nb, &imat, &nfail, &nerrs, nout);
                    }
                    if (info != 0) {
                        trfcon = TRUE_;
                    } else {
                        trfcon = FALSE_;
                    }

                    /* +    TEST 1 */
                    /*                 Reconstruct matrix from factors and compute residual. */

                    chet01_(uplo, &n, &a[1], &lda, &afac[1], &lda, &iwork[1],
                            &ainv[1], &lda, &rwork[1], result);
                    nt = 1;

                    /* +    TEST 2 */
                    /*                 Form the inverse and compute the residual. */

                    if (inb == 1 && ! trfcon) {
                        clacpy_(uplo, &n, &n, &afac[1], &lda, &ainv[1], &lda);
                        s_copy(srnamc_1.srnamt, "CHETRI", (ftnlen)32, (ftnlen)
                               6);
                        chetri_(uplo, &n, &ainv[1], &lda, &iwork[1], &work[1],
                                &info);

                        /*                 Check error code from CHETRI. */

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

                        cpot03_(uplo, &n, &a[1], &lda, &ainv[1], &lda, &work[
                                    1], &lda, &rwork[1], &rcondc, &result[1]);
                        nt = 2;
                    }

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

                    i__4 = nt;
                    for (k = 1; k <= i__4; ++k) {
                        if (result[k - 1] >= *thresh) {
                            if (nfail == 0 && nerrs == 0) {
                                alahd_(nout, path);
                            }
                            io___39.ciunit = *nout;
                            s_wsfe(&io___39);
                            do_fio(&c__1, uplo, (ftnlen)1);
                            do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer))
                            ;
                            do_fio(&c__1, (char *)&nb, (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(real));
                            e_wsfe();
                            ++nfail;
                        }
                        /* L110: */
                    }
                    nrun += nt;

                    /*                 Skip the other tests if this is not the first block */
                    /*                 size. */

                    if (inb > 1) {
                        goto L150;
                    }

                    /*                 Do only the condition estimate if INFO is not 0. */

                    if (trfcon) {
                        rcondc = 0.f;
                        goto L140;
                    }

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

                        /* +    TEST 3 */
                        /*                 Solve and compute residual for  A * X = B. */

                        s_copy(srnamc_1.srnamt, "CLARHS", (ftnlen)32, (ftnlen)
                               6);
                        clarhs_(path, xtype, uplo, " ", &n, &n, &kl, &ku, &
                                nrhs, &a[1], &lda, &xact[1], &lda, &b[1], &
                                lda, iseed, &info);
                        clacpy_("Full", &n, &nrhs, &b[1], &lda, &x[1], &lda);

                        s_copy(srnamc_1.srnamt, "CHETRS", (ftnlen)32, (ftnlen)
                               6);
                        chetrs_(uplo, &n, &nrhs, &afac[1], &lda, &iwork[1], &
                                x[1], &lda, &info);

                        /*                 Check error code from CHETRS. */

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

                        clacpy_("Full", &n, &nrhs, &b[1], &lda, &work[1], &
                                lda);
                        cpot02_(uplo, &n, &nrhs, &a[1], &lda, &x[1], &lda, &
                                work[1], &lda, &rwork[1], &result[2]);

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

                        cget04_(&n, &nrhs, &x[1], &lda, &xact[1], &lda, &
                                rcondc, &result[3]);

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

                        s_copy(srnamc_1.srnamt, "CHERFS", (ftnlen)32, (ftnlen)
                               6);
                        cherfs_(uplo, &n, &nrhs, &a[1], &lda, &afac[1], &lda,
                                &iwork[1], &b[1], &lda, &x[1], &lda, &rwork[1]
                                , &rwork[nrhs + 1], &work[1], &rwork[(nrhs <<
                                        1) + 1], &info);

                        /*                 Check error code from CHERFS. */

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

                        cget04_(&n, &nrhs, &x[1], &lda, &xact[1], &lda, &
                                rcondc, &result[4]);
                        cpot05_(uplo, &n, &nrhs, &a[1], &lda, &b[1], &lda, &x[
                                    1], &lda, &xact[1], &lda, &rwork[1], &rwork[
                                    nrhs + 1], &result[5]);

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

                        for (k = 3; k <= 7; ++k) {
                            if (result[k - 1] >= *thresh) {
                                if (nfail == 0 && nerrs == 0) {
                                    alahd_(nout, path);
                                }
                                io___42.ciunit = *nout;
                                s_wsfe(&io___42);
                                do_fio(&c__1, uplo, (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(real));
                                e_wsfe();
                                ++nfail;
                            }
                            /* L120: */
                        }
                        nrun += 5;
                        /* L130: */
                    }

                    /* +    TEST 8 */
                    /*                 Get an estimate of RCOND = 1/CNDNUM. */

L140:
                    anorm = clanhe_("1", uplo, &n, &a[1], &lda, &rwork[1]);
                    s_copy(srnamc_1.srnamt, "CHECON", (ftnlen)32, (ftnlen)6);
                    checon_(uplo, &n, &afac[1], &lda, &iwork[1], &anorm, &
                            rcond, &work[1], &info);

                    /*                 Check error code from CHECON. */

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

                    result[7] = sget06_(&rcond, &rcondc);

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

                    if (result[7] >= *thresh) {
                        if (nfail == 0 && nerrs == 0) {
                            alahd_(nout, path);
                        }
                        io___44.ciunit = *nout;
                        s_wsfe(&io___44);
                        do_fio(&c__1, uplo, (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__8, (ftnlen)sizeof(integer));
                        do_fio(&c__1, (char *)&result[7], (ftnlen)sizeof(real)
                              );
                        e_wsfe();
                        ++nfail;
                    }
                    ++nrun;
L150:
                    ;
                }
L160:
                ;
            }
L170:
            ;
        }
        /* L180: */
    }

    /*     Print a summary of the results. */

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

    return 0;

    /*     End of CCHKHE */

} /* cchkhe_ */
Пример #4
0
/* Subroutine */ int chesvxx_(char *fact, char *uplo, integer *n, integer *
	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
	ipiv, char *equed, real *s, complex *b, integer *ldb, complex *x, 
	integer *ldx, real *rcond, real *rpvgrw, real *berr, integer *
	n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, integer *
	nparams, real *params, complex *work, real *rwork, integer *info)
{
    /* System generated locals */
    integer a_dim1, a_offset, af_dim1, af_offset, b_dim1, b_offset, x_dim1, 
	    x_offset, err_bnds_norm_dim1, err_bnds_norm_offset, 
	    err_bnds_comp_dim1, err_bnds_comp_offset, i__1;
    real r__1, r__2;

    /* Local variables */
    integer j;
    real amax, smin, smax;
    extern doublereal cla_herpvgrw__(char *, integer *, integer *, complex *, 
	    integer *, complex *, integer *, integer *, real *, ftnlen);
    extern logical lsame_(char *, char *);
    real scond;
    logical equil, rcequ;
    extern /* Subroutine */ int claqhe_(char *, integer *, complex *, integer 
	    *, real *, real *, real *, char *);
    extern doublereal slamch_(char *);
    logical nofact;
    extern /* Subroutine */ int chetrf_(char *, integer *, complex *, integer 
	    *, integer *, complex *, integer *, integer *), clacpy_(
	    char *, integer *, integer *, complex *, integer *, complex *, 
	    integer *), xerbla_(char *, integer *);
    real bignum;
    integer infequ;
    extern /* Subroutine */ int chetrs_(char *, integer *, integer *, complex 
	    *, integer *, integer *, complex *, integer *, integer *);
    real smlnum;
    extern /* Subroutine */ int clascl2_(integer *, integer *, real *, 
	    complex *, integer *), cheequb_(char *, integer *, complex *, 
	    integer *, real *, real *, real *, complex *, integer *), 
	    cherfsx_(char *, char *, integer *, integer *, complex *, integer 
	    *, complex *, integer *, integer *, real *, complex *, integer *, 
	    complex *, integer *, real *, real *, integer *, real *, real *, 
	    integer *, real *, complex *, real *, integer *);


/*     -- LAPACK driver routine (version 3.2.1)                          -- */
/*     -- Contributed by James Demmel, Deaglan Halligan, Yozo Hida and -- */
/*     -- Jason Riedy of Univ. of California Berkeley.                 -- */
/*     -- April 2009                                                   -- */

/*     -- LAPACK is a software package provided by Univ. of Tennessee, -- */
/*     -- Univ. of California Berkeley and NAG Ltd.                    -- */

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

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

/*     CHESVXX uses the diagonal pivoting factorization to compute the */
/*     solution to a complex system of linear equations A * X = B, where */
/*     A is an N-by-N symmetric matrix and X and B are N-by-NRHS */
/*     matrices. */

/*     If requested, both normwise and maximum componentwise error bounds */
/*     are returned. CHESVXX will return a solution with a tiny */
/*     guaranteed error (O(eps) where eps is the working machine */
/*     precision) unless the matrix is very ill-conditioned, in which */
/*     case a warning is returned. Relevant condition numbers also are */
/*     calculated and returned. */

/*     CHESVXX accepts user-provided factorizations and equilibration */
/*     factors; see the definitions of the FACT and EQUED options. */
/*     Solving with refinement and using a factorization from a previous */
/*     CHESVXX call will also produce a solution with either O(eps) */
/*     errors or warnings, but we cannot make that claim for general */
/*     user-provided factorizations and equilibration factors if they */
/*     differ from what CHESVXX would itself produce. */

/*     Description */
/*     =========== */

/*     The following steps are performed: */

/*     1. If FACT = 'E', real scaling factors are computed to equilibrate */
/*     the system: */

/*       diag(S)*A*diag(S)     *inv(diag(S))*X = diag(S)*B */

/*     Whether or not the system will be equilibrated depends on the */
/*     scaling of the matrix A, but if equilibration is used, A is */
/*     overwritten by diag(S)*A*diag(S) and B by diag(S)*B. */

/*     2. If FACT = 'N' or 'E', the LU decomposition is used to factor */
/*     the matrix A (after equilibration if FACT = 'E') as */

/*        A = U * D * U**T,  if UPLO = 'U', or */
/*        A = L * D * L**T,  if UPLO = 'L', */

/*     where U (or L) is a product of permutation and unit upper (lower) */
/*     triangular matrices, and D is symmetric and block diagonal with */
/*     1-by-1 and 2-by-2 diagonal blocks. */

/*     3. If some D(i,i)=0, so that D is exactly singular, then the */
/*     routine returns with INFO = i. Otherwise, the factored form of A */
/*     is used to estimate the condition number of the matrix A (see */
/*     argument RCOND).  If the reciprocal of the condition number is */
/*     less than machine precision, the routine still goes on to solve */
/*     for X and compute error bounds as described below. */

/*     4. The system of equations is solved for X using the factored form */
/*     of A. */

/*     5. By default (unless PARAMS(LA_LINRX_ITREF_I) is set to zero), */
/*     the routine will use iterative refinement to try to get a small */
/*     error and error bounds.  Refinement calculates the residual to at */
/*     least twice the working precision. */

/*     6. If equilibration was used, the matrix X is premultiplied by */
/*     diag(R) so that it solves the original system before */
/*     equilibration. */

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

/*     Some optional parameters are bundled in the PARAMS array.  These */
/*     settings determine how refinement is performed, but often the */
/*     defaults are acceptable.  If the defaults are acceptable, users */
/*     can pass NPARAMS = 0 which prevents the source code from accessing */
/*     the PARAMS argument. */

/*     FACT    (input) CHARACTER*1 */
/*     Specifies whether or not the factored form of the matrix A is */
/*     supplied on entry, and if not, whether the matrix A should be */
/*     equilibrated before it is factored. */
/*       = 'F':  On entry, AF and IPIV contain the factored form of A. */
/*               If EQUED is not 'N', the matrix A has been */
/*               equilibrated with scaling factors given by S. */
/*               A, AF, and IPIV are not modified. */
/*       = 'N':  The matrix A will be copied to AF and factored. */
/*       = 'E':  The matrix A will be equilibrated if necessary, then */
/*               copied to AF and factored. */

/*     N       (input) INTEGER */
/*     The number of linear equations, i.e., 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. */

/*     A       (input/output) COMPLEX array, dimension (LDA,N) */
/*     The symmetric matrix A.  If UPLO = 'U', the leading N-by-N */
/*     upper triangular part of A contains the upper triangular */
/*     part of the matrix A, and the strictly lower triangular */
/*     part of A is not referenced.  If UPLO = 'L', the leading */
/*     N-by-N lower triangular part of A contains the lower */
/*     triangular part of the matrix A, and the strictly upper */
/*     triangular part of A is not referenced. */

/*     On exit, if FACT = 'E' and EQUED = 'Y', A is overwritten by */
/*     diag(S)*A*diag(S). */

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

/*     AF      (input or output) COMPLEX array, dimension (LDAF,N) */
/*     If FACT = 'F', then AF is an input argument and on entry */
/*     contains the block diagonal matrix D and the multipliers */
/*     used to obtain the factor U or L from the factorization A = */
/*     U*D*U**T or A = L*D*L**T as computed by SSYTRF. */

/*     If FACT = 'N', then AF is an output argument and on exit */
/*     returns the block diagonal matrix D and the multipliers */
/*     used to obtain the factor U or L from the factorization A = */
/*     U*D*U**T or A = L*D*L**T. */

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

/*     IPIV    (input or output) INTEGER array, dimension (N) */
/*     If FACT = 'F', then IPIV is an input argument and on entry */
/*     contains details of the interchanges and the block */
/*     structure of D, as determined by CHETRF.  If IPIV(k) > 0, */
/*     then rows and columns k and IPIV(k) were interchanged and */
/*     D(k,k) is a 1-by-1 diagonal block.  If UPLO = 'U' and */
/*     IPIV(k) = IPIV(k-1) < 0, then rows and columns k-1 and */
/*     -IPIV(k) were interchanged and D(k-1:k,k-1:k) is a 2-by-2 */
/*     diagonal block.  If UPLO = 'L' and IPIV(k) = IPIV(k+1) < 0, */
/*     then rows and columns k+1 and -IPIV(k) were interchanged */
/*     and D(k:k+1,k:k+1) is a 2-by-2 diagonal block. */

/*     If FACT = 'N', then IPIV is an output argument and on exit */
/*     contains details of the interchanges and the block */
/*     structure of D, as determined by CHETRF. */

/*     EQUED   (input or output) CHARACTER*1 */
/*     Specifies the form of equilibration that was done. */
/*       = 'N':  No equilibration (always true if FACT = 'N'). */
/*       = 'Y':  Both row and column equilibration, i.e., A has been */
/*               replaced by diag(S) * A * diag(S). */
/*     EQUED is an input argument if FACT = 'F'; otherwise, it is an */
/*     output argument. */

/*     S       (input or output) REAL array, dimension (N) */
/*     The scale factors for A.  If EQUED = 'Y', A is multiplied on */
/*     the left and right by diag(S).  S is an input argument if FACT = */
/*     'F'; otherwise, S is an output argument.  If FACT = 'F' and EQUED */
/*     = 'Y', each element of S must be positive.  If S is output, each */
/*     element of S is a power of the radix. If S is input, each element */
/*     of S should be a power of the radix to ensure a reliable solution */
/*     and error estimates. Scaling by powers of the radix does not cause */
/*     rounding errors unless the result underflows or overflows. */
/*     Rounding errors during scaling lead to refining with a matrix that */
/*     is not equivalent to the input matrix, producing error estimates */
/*     that may not be reliable. */

/*     B       (input/output) COMPLEX array, dimension (LDB,NRHS) */
/*     On entry, the N-by-NRHS right hand side matrix B. */
/*     On exit, */
/*     if EQUED = 'N', B is not modified; */
/*     if EQUED = 'Y', B is overwritten by diag(S)*B; */

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

/*     X       (output) COMPLEX array, dimension (LDX,NRHS) */
/*     If INFO = 0, the N-by-NRHS solution matrix X to the original */
/*     system of equations.  Note that A and B are modified on exit if */
/*     EQUED .ne. 'N', and the solution to the equilibrated system is */
/*     inv(diag(S))*X. */

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

/*     RCOND   (output) REAL */
/*     Reciprocal scaled condition number.  This is an estimate of the */
/*     reciprocal Skeel condition number of the matrix A after */
/*     equilibration (if done).  If this is less than the machine */
/*     precision (in particular, if it is zero), the matrix is singular */
/*     to working precision.  Note that the error may still be small even */
/*     if this number is very small and the matrix appears ill- */
/*     conditioned. */

/*     RPVGRW  (output) REAL */
/*     Reciprocal pivot growth.  On exit, this contains the reciprocal */
/*     pivot growth factor norm(A)/norm(U). The "max absolute element" */
/*     norm is used.  If this is much less than 1, then the stability of */
/*     the LU factorization of the (equilibrated) matrix A could be poor. */
/*     This also means that the solution X, estimated condition numbers, */
/*     and error bounds could be unreliable. If factorization fails with */
/*     0<INFO<=N, then this contains the reciprocal pivot growth factor */
/*     for the leading INFO columns of A. */

/*     BERR    (output) REAL array, dimension (NRHS) */
/*     Componentwise relative backward error.  This is 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). */

/*     N_ERR_BNDS (input) INTEGER */
/*     Number of error bounds to return for each right hand side */
/*     and each type (normwise or componentwise).  See ERR_BNDS_NORM and */
/*     ERR_BNDS_COMP below. */

/*     ERR_BNDS_NORM  (output) REAL array, dimension (NRHS, N_ERR_BNDS) */
/*     For each right-hand side, this array contains information about */
/*     various error bounds and condition numbers corresponding to the */
/*     normwise relative error, which is defined as follows: */

/*     Normwise relative error in the ith solution vector: */
/*             max_j (abs(XTRUE(j,i) - X(j,i))) */
/*            ------------------------------ */
/*                  max_j abs(X(j,i)) */

/*     The array is indexed by the type of error information as described */
/*     below. There currently are up to three pieces of information */
/*     returned. */

/*     The first index in ERR_BNDS_NORM(i,:) corresponds to the ith */
/*     right-hand side. */

/*     The second index in ERR_BNDS_NORM(:,err) contains the following */
/*     three fields: */
/*     err = 1 "Trust/don't trust" boolean. Trust the answer if the */
/*              reciprocal condition number is less than the threshold */
/*              sqrt(n) * slamch('Epsilon'). */

/*     err = 2 "Guaranteed" error bound: The estimated forward error, */
/*              almost certainly within a factor of 10 of the true error */
/*              so long as the next entry is greater than the threshold */
/*              sqrt(n) * slamch('Epsilon'). This error bound should only */
/*              be trusted if the previous boolean is true. */

/*     err = 3  Reciprocal condition number: Estimated normwise */
/*              reciprocal condition number.  Compared with the threshold */
/*              sqrt(n) * slamch('Epsilon') to determine if the error */
/*              estimate is "guaranteed". These reciprocal condition */
/*              numbers are 1 / (norm(Z^{-1},inf) * norm(Z,inf)) for some */
/*              appropriately scaled matrix Z. */
/*              Let Z = S*A, where S scales each row by a power of the */
/*              radix so all absolute row sums of Z are approximately 1. */

/*     See Lapack Working Note 165 for further details and extra */
/*     cautions. */

/*     ERR_BNDS_COMP  (output) REAL array, dimension (NRHS, N_ERR_BNDS) */
/*     For each right-hand side, this array contains information about */
/*     various error bounds and condition numbers corresponding to the */
/*     componentwise relative error, which is defined as follows: */

/*     Componentwise relative error in the ith solution vector: */
/*                    abs(XTRUE(j,i) - X(j,i)) */
/*             max_j ---------------------- */
/*                         abs(X(j,i)) */

/*     The array is indexed by the right-hand side i (on which the */
/*     componentwise relative error depends), and the type of error */
/*     information as described below. There currently are up to three */
/*     pieces of information returned for each right-hand side. If */
/*     componentwise accuracy is not requested (PARAMS(3) = 0.0), then */
/*     ERR_BNDS_COMP is not accessed.  If N_ERR_BNDS .LT. 3, then at most */
/*     the first (:,N_ERR_BNDS) entries are returned. */

/*     The first index in ERR_BNDS_COMP(i,:) corresponds to the ith */
/*     right-hand side. */

/*     The second index in ERR_BNDS_COMP(:,err) contains the following */
/*     three fields: */
/*     err = 1 "Trust/don't trust" boolean. Trust the answer if the */
/*              reciprocal condition number is less than the threshold */
/*              sqrt(n) * slamch('Epsilon'). */

/*     err = 2 "Guaranteed" error bound: The estimated forward error, */
/*              almost certainly within a factor of 10 of the true error */
/*              so long as the next entry is greater than the threshold */
/*              sqrt(n) * slamch('Epsilon'). This error bound should only */
/*              be trusted if the previous boolean is true. */

/*     err = 3  Reciprocal condition number: Estimated componentwise */
/*              reciprocal condition number.  Compared with the threshold */
/*              sqrt(n) * slamch('Epsilon') to determine if the error */
/*              estimate is "guaranteed". These reciprocal condition */
/*              numbers are 1 / (norm(Z^{-1},inf) * norm(Z,inf)) for some */
/*              appropriately scaled matrix Z. */
/*              Let Z = S*(A*diag(x)), where x is the solution for the */
/*              current right-hand side and S scales each row of */
/*              A*diag(x) by a power of the radix so all absolute row */
/*              sums of Z are approximately 1. */

/*     See Lapack Working Note 165 for further details and extra */
/*     cautions. */

/*     NPARAMS (input) INTEGER */
/*     Specifies the number of parameters set in PARAMS.  If .LE. 0, the */
/*     PARAMS array is never referenced and default values are used. */

/*     PARAMS  (input / output) REAL array, dimension NPARAMS */
/*     Specifies algorithm parameters.  If an entry is .LT. 0.0, then */
/*     that entry will be filled with default value used for that */
/*     parameter.  Only positions up to NPARAMS are accessed; defaults */
/*     are used for higher-numbered parameters. */

/*       PARAMS(LA_LINRX_ITREF_I = 1) : Whether to perform iterative */
/*            refinement or not. */
/*         Default: 1.0 */
/*            = 0.0 : No refinement is performed, and no error bounds are */
/*                    computed. */
/*            = 1.0 : Use the double-precision refinement algorithm, */
/*                    possibly with doubled-single computations if the */
/*                    compilation environment does not support DOUBLE */
/*                    PRECISION. */
/*              (other values are reserved for future use) */

/*       PARAMS(LA_LINRX_ITHRESH_I = 2) : Maximum number of residual */
/*            computations allowed for refinement. */
/*         Default: 10 */
/*         Aggressive: Set to 100 to permit convergence using approximate */
/*                     factorizations or factorizations other than LU. If */
/*                     the factorization uses a technique other than */
/*                     Gaussian elimination, the guarantees in */
/*                     err_bnds_norm and err_bnds_comp may no longer be */
/*                     trustworthy. */

/*       PARAMS(LA_LINRX_CWISE_I = 3) : Flag determining if the code */
/*            will attempt to find a solution with small componentwise */
/*            relative error in the double-precision algorithm.  Positive */
/*            is true, 0.0 is false. */
/*         Default: 1.0 (attempt componentwise convergence) */

/*     WORK    (workspace) COMPLEX array, dimension (2*N) */

/*     RWORK   (workspace) REAL array, dimension (2*N) */

/*     INFO    (output) INTEGER */
/*       = 0:  Successful exit. The solution to every right-hand side is */
/*         guaranteed. */
/*       < 0:  If INFO = -i, the i-th argument had an illegal value */
/*       > 0 and <= N:  U(INFO,INFO) is exactly zero.  The factorization */
/*         has been completed, but the factor U is exactly singular, so */
/*         the solution and error bounds could not be computed. RCOND = 0 */
/*         is returned. */
/*       = N+J: The solution corresponding to the Jth right-hand side is */
/*         not guaranteed. The solutions corresponding to other right- */
/*         hand sides K with K > J may not be guaranteed as well, but */
/*         only the first such right-hand side is reported. If a small */
/*         componentwise error is not requested (PARAMS(3) = 0.0) then */
/*         the Jth right-hand side is the first with a normwise error */
/*         bound that is not guaranteed (the smallest J such */
/*         that ERR_BNDS_NORM(J,1) = 0.0). By default (PARAMS(3) = 1.0) */
/*         the Jth right-hand side is the first with either a normwise or */
/*         componentwise error bound that is not guaranteed (the smallest */
/*         J such that either ERR_BNDS_NORM(J,1) = 0.0 or */
/*         ERR_BNDS_COMP(J,1) = 0.0). See the definition of */
/*         ERR_BNDS_NORM(:,1) and ERR_BNDS_COMP(:,1). To get information */
/*         about all of the right-hand sides check ERR_BNDS_NORM or */
/*         ERR_BNDS_COMP. */

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

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

    /* Parameter adjustments */
    err_bnds_comp_dim1 = *nrhs;
    err_bnds_comp_offset = 1 + err_bnds_comp_dim1;
    err_bnds_comp__ -= err_bnds_comp_offset;
    err_bnds_norm_dim1 = *nrhs;
    err_bnds_norm_offset = 1 + err_bnds_norm_dim1;
    err_bnds_norm__ -= err_bnds_norm_offset;
    a_dim1 = *lda;
    a_offset = 1 + a_dim1;
    a -= a_offset;
    af_dim1 = *ldaf;
    af_offset = 1 + af_dim1;
    af -= af_offset;
    --ipiv;
    --s;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1;
    b -= b_offset;
    x_dim1 = *ldx;
    x_offset = 1 + x_dim1;
    x -= x_offset;
    --berr;
    --params;
    --work;
    --rwork;

    /* Function Body */
    *info = 0;
    nofact = lsame_(fact, "N");
    equil = lsame_(fact, "E");
    smlnum = slamch_("Safe minimum");
    bignum = 1.f / smlnum;
    if (nofact || equil) {
	*(unsigned char *)equed = 'N';
	rcequ = FALSE_;
    } else {
	rcequ = lsame_(equed, "Y");
    }

/*     Default is failure.  If an input parameter is wrong or */
/*     factorization fails, make everything look horrible.  Only the */
/*     pivot growth is set here, the rest is initialized in CHERFSX. */

    *rpvgrw = 0.f;

/*     Test the input parameters.  PARAMS is not tested until CHERFSX. */

    if (! nofact && ! equil && ! lsame_(fact, "F")) {
	*info = -1;
    } else if (! lsame_(uplo, "U") && ! lsame_(uplo, 
	    "L")) {
	*info = -2;
    } else if (*n < 0) {
	*info = -3;
    } else if (*nrhs < 0) {
	*info = -4;
    } else if (*lda < max(1,*n)) {
	*info = -6;
    } else if (*ldaf < max(1,*n)) {
	*info = -8;
    } else if (lsame_(fact, "F") && ! (rcequ || lsame_(
	    equed, "N"))) {
	*info = -9;
    } else {
	if (rcequ) {
	    smin = bignum;
	    smax = 0.f;
	    i__1 = *n;
	    for (j = 1; j <= i__1; ++j) {
/* Computing MIN */
		r__1 = smin, r__2 = s[j];
		smin = dmin(r__1,r__2);
/* Computing MAX */
		r__1 = smax, r__2 = s[j];
		smax = dmax(r__1,r__2);
/* L10: */
	    }
	    if (smin <= 0.f) {
		*info = -10;
	    } else if (*n > 0) {
		scond = dmax(smin,smlnum) / dmin(smax,bignum);
	    } else {
		scond = 1.f;
	    }
	}
	if (*info == 0) {
	    if (*ldb < max(1,*n)) {
		*info = -12;
	    } else if (*ldx < max(1,*n)) {
		*info = -14;
	    }
	}
    }

    if (*info != 0) {
	i__1 = -(*info);
	xerbla_("CHESVXX", &i__1);
	return 0;
    }

    if (equil) {

/*     Compute row and column scalings to equilibrate the matrix A. */

	cheequb_(uplo, n, &a[a_offset], lda, &s[1], &scond, &amax, &work[1], &
		infequ);
	if (infequ == 0) {

/*     Equilibrate the matrix. */

	    claqhe_(uplo, n, &a[a_offset], lda, &s[1], &scond, &amax, equed);
	    rcequ = lsame_(equed, "Y");
	}
    }

/*     Scale the right-hand side. */

    if (rcequ) {
	clascl2_(n, nrhs, &s[1], &b[b_offset], ldb);
    }

    if (nofact || equil) {

/*        Compute the LU factorization of A. */

	clacpy_(uplo, n, n, &a[a_offset], lda, &af[af_offset], ldaf);
	i__1 = max(1,*n) * 5;
	chetrf_(uplo, n, &af[af_offset], ldaf, &ipiv[1], &work[1], &i__1, 
		info);

/*        Return if INFO is non-zero. */

	if (*info > 0) {

/*           Pivot in column INFO is exactly 0 */
/*           Compute the reciprocal pivot growth factor of the */
/*           leading rank-deficient INFO columns of A. */

	    if (*n > 0) {
		*rpvgrw = cla_herpvgrw__(uplo, n, info, &a[a_offset], lda, &
			af[af_offset], ldaf, &ipiv[1], &rwork[1], (ftnlen)1);
	    }
	    return 0;
	}
    }

/*     Compute the reciprocal pivot growth factor RPVGRW. */

    if (*n > 0) {
	*rpvgrw = cla_herpvgrw__(uplo, n, info, &a[a_offset], lda, &af[
		af_offset], ldaf, &ipiv[1], &rwork[1], (ftnlen)1);
    }

/*     Compute the solution matrix X. */

    clacpy_("Full", n, nrhs, &b[b_offset], ldb, &x[x_offset], ldx);
    chetrs_(uplo, n, nrhs, &af[af_offset], ldaf, &ipiv[1], &x[x_offset], ldx, 
	    info);

/*     Use iterative refinement to improve the computed solution and */
/*     compute error bounds and backward error estimates for it. */

    cherfsx_(uplo, equed, n, nrhs, &a[a_offset], lda, &af[af_offset], ldaf, &
	    ipiv[1], &s[1], &b[b_offset], ldb, &x[x_offset], ldx, rcond, &
	    berr[1], n_err_bnds__, &err_bnds_norm__[err_bnds_norm_offset], &
	    err_bnds_comp__[err_bnds_comp_offset], nparams, &params[1], &work[
	    1], &rwork[1], info);

/*     Scale solutions. */

    if (rcequ) {
	clascl2_(n, nrhs, &s[1], &x[x_offset], ldx);
    }

    return 0;

/*     End of CHESVXX */

} /* chesvxx_ */