Ejemplo n.º 1
0
void _fmprb_poly_mullow_ztrunc(fmprb_ptr C,
    fmprb_srcptr A, long lenA,
    fmprb_srcptr B, long lenB, long n, long prec)
{
    fmpz * Acoeffs, * Bcoeffs, * Ccoeffs;
    fmpz_t Aexp, Bexp, Cexp;
    fmpr_t Aerr, Berr, Anorm, Bnorm, err;
    long i;
    int squaring;

    lenA = FLINT_MIN(lenA, n);
    lenB = FLINT_MIN(lenB, n);

    squaring = (A == B) && (lenA == lenB);

    /* TODO: make the code below work correctly with out this workaround */
    if (_fmprb_vec_rad_has_inf_nan(A, lenA) ||
        (!squaring && _fmprb_vec_rad_has_inf_nan(B, lenB)))
    {
        _fmprb_vec_indeterminate(C, n);
        return;
    }

    fmpz_init(Aexp);
    fmpz_init(Bexp);
    fmpz_init(Cexp);

    Acoeffs = _fmpz_vec_init(lenA);
    Bcoeffs = _fmpz_vec_init(lenB);
    Ccoeffs = _fmpz_vec_init(n);

    fmpr_init(Aerr);
    fmpr_init(Berr);
    fmpr_init(Anorm);
    fmpr_init(Bnorm);
    fmpr_init(err);

    _fmprb_poly_get_fmpz_poly_2exp(Aerr, Aexp, Acoeffs, A, lenA, prec);

    if (squaring)
    {
        _fmpz_poly_sqrlow(Ccoeffs, Acoeffs, lenA, n);
        fmpz_add(Cexp, Aexp, Aexp);

        /* cross-multiply error bounds: (A+r)(B+s) = A^2 + 2Ar + r^2 */
        _fmpr_fmpz_vec_max_norm(Anorm, Acoeffs, lenA, FMPRB_RAD_PREC);
        fmpr_mul_2exp_fmpz(Anorm, Anorm, Aexp);

        fmpr_mul(err, Anorm, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_mul_2exp_si(err, err, 1);
        fmpr_addmul(err, Aerr, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP);
    }
    else
    {
        _fmprb_poly_get_fmpz_poly_2exp(Berr, Bexp, Bcoeffs, B, lenB, prec);

        /* main multiplication */
        if (lenA >= lenB)
            _fmpz_poly_mullow(Ccoeffs, Acoeffs, lenA, Bcoeffs, lenB, n);
        else
            _fmpz_poly_mullow(Ccoeffs, Bcoeffs, lenB, Acoeffs, lenA, n);

        fmpz_add(Cexp, Aexp, Bexp);

        /* cross-multiply error bounds: (A+r)(B+s) = AB + As + Br + rs */
        _fmpr_fmpz_vec_max_norm(Anorm, Acoeffs, lenA, FMPRB_RAD_PREC);
        fmpr_mul_2exp_fmpz(Anorm, Anorm, Aexp);

        _fmpr_fmpz_vec_max_norm(Bnorm, Bcoeffs, lenB, FMPRB_RAD_PREC);
        fmpr_mul_2exp_fmpz(Bnorm, Bnorm, Bexp);

        fmpr_mul(err, Aerr, Berr, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_addmul(err, Anorm, Berr, FMPRB_RAD_PREC, FMPR_RND_UP);
        fmpr_addmul(err, Bnorm, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP);
    }

    for (i = 0; i < n; i++)
    {
        fmprb_set_round_fmpz_2exp(C + i, Ccoeffs + i, Cexp, prec);

        /* there are at most (i+1) error terms for coefficient i */
        /* TODO: make this tight */
        fmpr_addmul_ui(fmprb_radref(C + i), err, i + 1,
            FMPRB_RAD_PREC, FMPR_RND_UP);
    }

    fmpr_clear(Aerr);
    fmpr_clear(Berr);
    fmpr_clear(Anorm);
    fmpr_clear(Bnorm);
    fmpr_clear(err);

    _fmpz_vec_clear(Acoeffs, lenA);
    _fmpz_vec_clear(Bcoeffs, lenB);
    _fmpz_vec_clear(Ccoeffs, n);

    fmpz_clear(Aexp);
    fmpz_clear(Bexp);
    fmpz_clear(Cexp);
}
Ejemplo n.º 2
0
void
_fmprb_poly_zeta_series(fmprb_ptr res, fmprb_srcptr h, long hlen, const fmprb_t a, int deflate, long len, long prec)
{
    long i;
    fmpcb_t cs, ca;
    fmpcb_ptr z;
    fmprb_ptr t, u;

    if (fmprb_contains_nonpositive(a))
    {
        _fmprb_vec_indeterminate(res, len);
        return;
    }

    hlen = FLINT_MIN(hlen, len);

    z = _fmpcb_vec_init(len);
    t = _fmprb_vec_init(len);
    u = _fmprb_vec_init(len);
    fmpcb_init(cs);
    fmpcb_init(ca);

    /* use reflection formula */
    if (fmpr_sgn(fmprb_midref(h)) < 0 && fmprb_is_one(a))
    {
        /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */
        fmprb_t pi;
        fmprb_ptr f, s1, s2, s3, s4;

        fmprb_init(pi);
        f = _fmprb_vec_init(2);
        s1 = _fmprb_vec_init(len);
        s2 = _fmprb_vec_init(len);
        s3 = _fmprb_vec_init(len);
        s4 = _fmprb_vec_init(len);

        fmprb_const_pi(pi, prec);

        /* s1 = (2*pi)**s */
        fmprb_mul_2exp_si(pi, pi, 1);
        _fmprb_poly_pow_cpx(s1, pi, h, len, prec);
        fmprb_mul_2exp_si(pi, pi, -1);

        /* s2 = sin(pi*s/2) / pi */
        fmprb_mul_2exp_si(pi, pi, -1);
        fmprb_mul(f, pi, h, prec);
        fmprb_set(f + 1, pi);
        fmprb_mul_2exp_si(pi, pi, 1);
        _fmprb_poly_sin_series(s2, f, 2, len, prec);
        _fmprb_vec_scalar_div(s2, s2, len, pi, prec);

        /* s3 = gamma(1-s) */
        fmprb_sub_ui(f, h, 1, prec);
        fmprb_neg(f, f);
        fmprb_set_si(f + 1, -1);
        _fmprb_poly_gamma_series(s3, f, 2, len, prec);

        /* s4 = zeta(1-s) */
        fmprb_sub_ui(f, h, 1, prec);
        fmprb_neg(f, f);
        fmpcb_set_fmprb(cs, f);
        fmpcb_one(ca);
        zeta_series(z, cs, ca, 0, len, prec);
        for (i = 0; i < len; i++)
            fmprb_set(s4 + i, fmpcb_realref(z + i));
        for (i = 1; i < len; i += 2)
            fmprb_neg(s4 + i, s4 + i);

        _fmprb_poly_mullow(u, s1, len, s2, len, len, prec);
        _fmprb_poly_mullow(s1, s3, len, s4, len, len, prec);
        _fmprb_poly_mullow(t, u, len, s1, len, len, prec);

        /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */
        if (deflate)
        {
            fmprb_sub_ui(u, h, 1, prec);
            fmprb_neg(u, u);
            fmprb_ui_div(u, 1, u, prec);
            for (i = 1; i < len; i++)
                fmprb_mul(u + i, u + i - 1, u, prec);
            _fmprb_vec_add(t, t, u, len, prec);
        }

        fmprb_clear(pi);
        _fmprb_vec_clear(f, 2);
        _fmprb_vec_clear(s1, len);
        _fmprb_vec_clear(s2, len);
        _fmprb_vec_clear(s3, len);
        _fmprb_vec_clear(s4, len);
    }
    else
    {
        fmpcb_set_fmprb(cs, h);
        fmpcb_set_fmprb(ca, a);
        zeta_series(z, cs, ca, deflate, len, prec);
        for (i = 0; i < len; i++)
            fmprb_set(t + i, fmpcb_realref(z + i));
    }

    /* compose with nonconstant part */
    fmprb_zero(u);
    _fmprb_vec_set(u + 1, h + 1, hlen - 1);
    _fmprb_poly_compose_series(res, t, len, u, hlen, len, prec);

    _fmpcb_vec_clear(z, len);
    _fmprb_vec_clear(t, len);
    _fmprb_vec_clear(u, len);
    fmpcb_init(cs);
    fmpcb_init(ca);
}