
    template <typename Scalar>
void ei_r1updt(int m, int n, Scalar *s, int /* ls */, const Scalar *u, Scalar *v, Scalar *w, bool *sing)
{
    /* Local variables */
    int i, j, l, jj, nm1;
    Scalar tan__;
    int nmj;
    Scalar cos__, sin__, tau, temp, cotan;

    /* Parameter adjustments */
    --w;
    --u;
    --v;
    --s;

    /* Function Body */
    const Scalar giant = std::numeric_limits<Scalar>::max();

    /*     initialize the diagonal element pointer. */

    jj = n * ((m << 1) - n + 1) / 2 - (m - n);

    /*     move the nontrivial part of the last column of s into w. */

    l = jj;
    for (i = n; i <= m; ++i) {
        w[i] = s[l];
        ++l;
        /* L10: */
    }

    /*     rotate the vector v into a multiple of the n-th unit vector */
    /*     in such a way that a spike is introduced into w. */

    nm1 = n - 1;
    if (nm1 < 1) {
        goto L70;
    }
    for (nmj = 1; nmj <= nm1; ++nmj) {
        j = n - nmj;
        jj -= m - j + 1;
        w[j] = 0.;
        if (v[j] == 0.) {
            goto L50;
        }

        /*        determine a givens rotation which eliminates the */
        /*        j-th element of v. */

        if (ei_abs(v[n]) >= ei_abs(v[j]))
            goto L20;
        cotan = v[n] / v[j];
        /* Computing 2nd power */
        sin__ = Scalar(.5) / ei_sqrt(Scalar(0.25) + Scalar(0.25) * ei_abs2(cotan));
        cos__ = sin__ * cotan;
        tau = 1.;
        if (ei_abs(cos__) * giant > 1.) {
            tau = 1. / cos__;
        }
        goto L30;
L20:
        tan__ = v[j] / v[n];
        /* Computing 2nd power */
        cos__ = Scalar(.5) / ei_sqrt(Scalar(0.25) + Scalar(0.25) * ei_abs2(tan__));
        sin__ = cos__ * tan__;
        tau = sin__;
L30:

        /*        apply the transformation to v and store the information */
        /*        necessary to recover the givens rotation. */

        v[n] = sin__ * v[j] + cos__ * v[n];
        v[j] = tau;

        /*        apply the transformation to s and extend the spike in w. */

        l = jj;
        for (i = j; i <= m; ++i) {
            temp = cos__ * s[l] - sin__ * w[i];
            w[i] = sin__ * s[l] + cos__ * w[i];
            s[l] = temp;
            ++l;
            /* L40: */
        }
L50:
        /* L60: */
        ;
    }
L70:

    /*     add the spike from the rank 1 update to w. */

    for (i = 1; i <= m; ++i) {
        w[i] += v[n] * u[i];
        /* L80: */
    }

    /*     eliminate the spike. */

    *sing = false;
    if (nm1 < 1) {
        goto L140;
    }
    for (j = 1; j <= nm1; ++j) {
        if (w[j] == 0.) {
            goto L120;
        }

        /*        determine a givens rotation which eliminates the */
        /*        j-th element of the spike. */

        if (ei_abs(s[jj]) >= ei_abs(w[j]))
            goto L90;
        cotan = s[jj] / w[j];
        /* Computing 2nd power */
        sin__ = Scalar(.5) / ei_sqrt(Scalar(0.25) + Scalar(0.25) * ei_abs2(cotan));
        cos__ = sin__ * cotan;
        tau = 1.;
        if (ei_abs(cos__) * giant > 1.) {
            tau = 1. / cos__;
        }
        goto L100;
L90:
        tan__ = w[j] / s[jj];
        /* Computing 2nd power */
        cos__ = Scalar(.5) / ei_sqrt(Scalar(0.25) + Scalar(0.25) * ei_abs2(tan__));
        sin__ = cos__ * tan__;
        tau = sin__;
L100:

        /*        apply the transformation to s and reduce the spike in w. */

        l = jj;
        for (i = j; i <= m; ++i) {
            temp = cos__ * s[l] + sin__ * w[i];
            w[i] = -sin__ * s[l] + cos__ * w[i];
            s[l] = temp;
            ++l;
            /* L110: */
        }

        /*        store the information necessary to recover the */
        /*        givens rotation. */

        w[j] = tau;
L120:

        /*        test for zero diagonal elements in the output s. */

        if (s[jj] == 0.) {
            *sing = true;
        }
        jj += m - j + 1;
        /* L130: */
    }
L140:

    /*     move w back into the last column of the output s. */

    l = jj;
    for (i = n; i <= m; ++i) {
        s[l] = w[i];
        ++l;
        /* L150: */
    }
    if (s[jj] == 0.) {
        *sing = true;
    }
    return;

    /*     last card of subroutine r1updt. */

} /* r1updt_ */

