Exemple #1
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_ */
Exemple #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_ */