
    template <typename Scalar>
void ei_qrsolv(int n, Scalar *r__, int ldr, 
        const int *ipvt, const Scalar *diag, const Scalar *qtb, Scalar *x, 
        Scalar *sdiag, Scalar *wa)
{
    /* System generated locals */
    int r_dim1, r_offset;

    /* Local variables */
    int i, j, k, l, jp1, kp1;
    Scalar tan__, cos__, sin__, sum, temp, cotan;
    int nsing;
    Scalar qtbpj;

    /* Parameter adjustments */
    --wa;
    --sdiag;
    --x;
    --qtb;
    --diag;
    --ipvt;
    r_dim1 = ldr;
    r_offset = 1 + r_dim1 * 1;
    r__ -= r_offset;

    /* Function Body */

    /*     copy r and (q transpose)*b to preserve input and initialize s. */
    /*     in particular, save the diagonal elements of r in x. */

    for (j = 1; j <= n; ++j) {
        for (i = j; i <= n; ++i) {
            r__[i + j * r_dim1] = r__[j + i * r_dim1];
            /* L10: */
        }
        x[j] = r__[j + j * r_dim1];
        wa[j] = qtb[j];
        /* L20: */
    }

    /*     eliminate the diagonal matrix d using a givens rotation. */

    for (j = 1; j <= n; ++j) {

        /*        prepare the row of d to be eliminated, locating the */
        /*        diagonal element using p from the qr factorization. */

        l = ipvt[j];
        if (diag[l] == 0.) {
            goto L90;
        }
        for (k = j; k <= n; ++k) {
            sdiag[k] = 0.;
            /* L30: */
        }
        sdiag[j] = diag[l];

        /*        the transformations to eliminate the row of d */
        /*        modify only a single element of (q transpose)*b */
        /*        beyond the first n, which is initially zero. */

        qtbpj = 0.;
        for (k = j; k <= n; ++k) {

            /*           determine a givens rotation which eliminates the */
            /*           appropriate element in the current row of d. */

            if (sdiag[k] == 0.)
                goto L70;
            if ( ei_abs(r__[k + k * r_dim1]) >= ei_abs(sdiag[k]))
                goto L40;
            cotan = r__[k + k * r_dim1] / sdiag[k];
            /* Computing 2nd power */
            sin__ = Scalar(.5) / ei_sqrt(Scalar(0.25) + Scalar(0.25) * ei_abs2(cotan));
            cos__ = sin__ * cotan;
            goto L50;
L40:
            tan__ = sdiag[k] / r__[k + k * r_dim1];
            /* Computing 2nd power */
            cos__ = Scalar(.5) / ei_sqrt(Scalar(0.25) + Scalar(0.25) * ei_abs2(tan__));
            sin__ = cos__ * tan__;
L50:

            /*           compute the modified diagonal element of r and */
            /*           the modified element of ((q transpose)*b,0). */

            r__[k + k * r_dim1] = cos__ * r__[k + k * r_dim1] + sin__ * sdiag[
                k];
            temp = cos__ * wa[k] + sin__ * qtbpj;
            qtbpj = -sin__ * wa[k] + cos__ * qtbpj;
            wa[k] = temp;

            /*           accumulate the tranformation in the row of s. */

            kp1 = k + 1;
            if (n < kp1) {
                goto L70;
            }
            for (i = kp1; i <= n; ++i) {
                temp = cos__ * r__[i + k * r_dim1] + sin__ * sdiag[i];
                sdiag[i] = -sin__ * r__[i + k * r_dim1] + cos__ * sdiag[
                    i];
                r__[i + k * r_dim1] = temp;
                /* L60: */
            }
L70:
            /* L80: */
            ;
        }
L90:

        /*        store the diagonal element of s and restore */
        /*        the corresponding diagonal element of r. */

        sdiag[j] = r__[j + j * r_dim1];
        r__[j + j * r_dim1] = x[j];
        /* L100: */
    }

    /*     solve the triangular system for z. if the system is */
    /*     singular, then obtain a least squares solution. */

    nsing = n;
    for (j = 1; j <= n; ++j) {
        if (sdiag[j] == 0. && nsing == n) {
            nsing = j - 1;
        }
        if (nsing < n) {
            wa[j] = 0.;
        }
        /* L110: */
    }
    if (nsing < 1) {
        goto L150;
    }
    for (k = 1; k <= nsing; ++k) {
        j = nsing - k + 1;
        sum = 0.;
        jp1 = j + 1;
        if (nsing < jp1) {
            goto L130;
        }
        for (i = jp1; i <= nsing; ++i) {
            sum += r__[i + j * r_dim1] * wa[i];
            /* L120: */
        }
L130:
        wa[j] = (wa[j] - sum) / sdiag[j];
        /* L140: */
    }
L150:

    /*     permute the components of z back to components of x. */

    for (j = 1; j <= n; ++j) {
        l = ipvt[j];
        x[l] = wa[j];
        /* L160: */
    }
    return;

    /*     last card of subroutine qrsolv. */

} /* qrsolv_ */

