void
_arb_poly_revert_series_lagrange_fast(arb_ptr Qinv, arb_srcptr Q, long Qlen, long n, long prec)
{
    long i, j, k, m;
    arb_ptr R, S, T, tmp;
    arb_t t;

    if (n <= 2)
    {
        if (n >= 1)
            arb_zero(Qinv);
        if (n == 2)
            arb_inv(Qinv + 1, Q + 1, prec);
        return;
    }

    m = n_sqrt(n);

    arb_init(t);
    R = _arb_vec_init((n - 1) * m);
    S = _arb_vec_init(n - 1);
    T = _arb_vec_init(n - 1);

    arb_zero(Qinv);
    arb_inv(Qinv + 1, Q + 1, prec);

    _arb_poly_inv_series(Ri(1), Q + 1, FLINT_MIN(Qlen, n) - 1, n - 1, prec);
    for (i = 2; i <= m; i++)
        _arb_poly_mullow(Ri(i), Ri((i + 1) / 2), n - 1, Ri(i / 2), n - 1, n - 1, prec);

    for (i = 2; i < m; i++)
        arb_div_ui(Qinv + i, Ri(i) + i - 1, i, prec);

    _arb_vec_set(S, Ri(m), n - 1);

    for (i = m; i < n; i += m)
    {
        arb_div_ui(Qinv + i, S + i - 1, i, prec);

        for (j = 1; j < m && i + j < n; j++)
        {
            arb_mul(t, S + 0, Ri(j) + i + j - 1, prec);
            for (k = 1; k <= i + j - 1; k++)
                arb_addmul(t, S + k, Ri(j) + i + j - 1 - k, prec);
            arb_div_ui(Qinv + i + j, t, i + j, prec);
        }

        if (i + 1 < n)
        {
            _arb_poly_mullow(T, S, n - 1, Ri(m), n - 1, n - 1, prec);
            tmp = S; S = T; T = tmp;
        }
    }

    arb_clear(t);
    _arb_vec_clear(R, (n - 1) * m);
    _arb_vec_clear(S, n - 1);
    _arb_vec_clear(T, n - 1);
}
Exemple #2
0
void
_arb_poly_tan_series(arb_ptr g,
    arb_srcptr h, slong hlen, slong len, slong prec)
{
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        arb_tan(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_t t;
        arb_init(t);
        arb_tan(g, h, prec);
        arb_mul(t, g, g, prec);
        arb_add_ui(t, t, 1, prec);
        arb_mul(g + 1, t, h + 1, prec);  /* safe since hlen >= 2 */
        arb_clear(t);
    }
    else
    {
        arb_ptr t, u;

        t = _arb_vec_init(2 * len);
        u = t + len;

        NEWTON_INIT(TAN_NEWTON_CUTOFF, len)

        NEWTON_BASECASE(n)
        _arb_poly_sin_cos_series_basecase(t, u, h, hlen, n, prec, 0);
        _arb_poly_div_series(g, t, n, u, n, n, prec);
        NEWTON_END_BASECASE

        NEWTON_LOOP(m, n)
        _arb_poly_mullow(u, g, m, g, m, n, prec);
        arb_add_ui(u, u, 1, prec);
        _arb_poly_atan_series(t, g, m, n, prec);
        _arb_poly_sub(t + m, h + m, FLINT_MAX(0, hlen - m), t + m, n - m, prec);
        _arb_poly_mullow(g + m, u, n, t + m, n - m, n - m, prec);
        NEWTON_END_LOOP

        NEWTON_END

        _arb_vec_clear(t, 2 * len);
    }
}
Exemple #3
0
void
_arb_poly_sqrt_series(arb_ptr g,
    arb_srcptr h, long hlen, long len, long prec)
{
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        arb_sqrt(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_sqrt(g, h, prec);
        arb_div(g + 1, h + 1, h, prec);
        arb_mul(g + 1, g + 1, g, prec);
        arb_mul_2exp_si(g + 1, g + 1, -1);
    }
    else
    {
        arb_ptr t;
        t = _arb_vec_init(len);
        _arb_poly_rsqrt_series(t, h, hlen, len, prec);
        _arb_poly_mullow(g, t, len, h, hlen, len, prec);
        _arb_vec_clear(t, len);
    }
}
Exemple #4
0
static void
_arb_poly_rising_ui_series_bsplit(arb_ptr res,
    arb_srcptr f, slong flen, ulong a, ulong b,
        slong trunc, slong prec)
{
    flen = FLINT_MIN(flen, trunc);

    if (b - a == 1)
    {
        arb_add_ui(res, f, a, prec);
        _arb_vec_set(res + 1, f + 1, flen - 1);
    }
    else
    {
        arb_ptr L, R;
        slong len1, len2;

        slong m = a + (b - a) / 2;

        len1 = poly_pow_length(flen, m - a, trunc);
        len2 = poly_pow_length(flen, b - m, trunc);

        L = _arb_vec_init(len1 + len2);
        R = L + len1;

        _arb_poly_rising_ui_series_bsplit(L, f, flen, a, m, trunc, prec);
        _arb_poly_rising_ui_series_bsplit(R, f, flen, m, b, trunc, prec);

        _arb_poly_mullow(res, L, len1, R, len2,
            FLINT_MIN(trunc, len1 + len2 - 1), prec);

        _arb_vec_clear(L, len1 + len2);
    }
}
Exemple #5
0
void _arb_poly_divrem(arb_ptr Q, arb_ptr R,
    arb_srcptr A, slong lenA,
    arb_srcptr B, slong lenB, slong prec)
{
    const slong lenQ = lenA - lenB + 1;
    _arb_poly_div(Q, A, lenA, B, lenB, prec);

    if (lenB > 1)
    {
        if (lenQ >= lenB - 1)
            _arb_poly_mullow(R, Q, lenQ, B, lenB - 1, lenB - 1, prec);
        else
            _arb_poly_mullow(R, B, lenB - 1, Q, lenQ, lenB - 1, prec);
        _arb_vec_sub(R, A, R, lenB - 1, prec);
    }
}
Exemple #6
0
void
_arb_poly_log1p_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec)
{
    arb_t a;

    flen = FLINT_MIN(flen, n);

    arb_init(a);
    arb_log1p(a, f, prec);

    if (flen == 1)
    {
        _arb_vec_zero(res + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_add_ui(res, f + 0, 1, prec);
        arb_div(res + 1, f + 1, res + 0, prec);
    }
    else if (_arb_vec_is_zero(f + 1, flen - 2))  /* f = a + bx^d */
    {
        slong i, j, d = flen - 1;

        arb_add_ui(res, f + 0, 1, prec);

        for (i = 1, j = d; j < n; j += d, i++)
        {
            if (i == 1)
                arb_div(res + j, f + d, res, prec);
            else
                arb_mul(res + j, res + j - d, res + d, prec);
            _arb_vec_zero(res + j - d + 1, flen - 2);
        }
        _arb_vec_zero(res + j - d + 1, n - (j - d + 1));

        for (i = 2, j = 2 * d; j < n; j += d, i++)
            arb_div_si(res + j, res + j, i % 2 ? i : -i, prec);
    }
    else
    {
        arb_ptr f_diff, f_inv;
        slong alloc;

        alloc = n + flen;
        f_inv = _arb_vec_init(alloc);
        f_diff = f_inv + n;

        arb_add_ui(f_diff, f, 1, prec);
        _arb_vec_set(f_diff + 1, f + 1, flen - 1);
        _arb_poly_inv_series(f_inv, f_diff, flen, n, prec);
        _arb_poly_derivative(f_diff, f, flen, prec);
        _arb_poly_mullow(res, f_inv, n - 1, f_diff, flen - 1, n - 1, prec);
        _arb_poly_integral(res, res, n, prec);

        _arb_vec_clear(f_inv, alloc);
    }

    arb_swap(res, a);
    arb_clear(a);
}
Exemple #7
0
void
_arb_poly_asin_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec)
{
    arb_t c;
    arb_init(c);

    arb_asin(c, h, prec);

    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        _arb_vec_zero(g + 1, n - 1);
    }
    else
    {
        arb_ptr t, u;
        slong ulen;

        t = _arb_vec_init(n);
        u = _arb_vec_init(n);

        /* asin(h(x)) = integral(h'(x)/sqrt(1-h(x)^2)) */
        ulen = FLINT_MIN(n, 2 * hlen - 1);
        _arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec);
        arb_sub_ui(u, u, 1, prec);
        _arb_vec_neg(u, u, ulen);
        _arb_poly_rsqrt_series(t, u, ulen, n, prec);
        _arb_poly_derivative(u, h, hlen, prec);
        _arb_poly_mullow(g, t, n, u, hlen - 1, n, prec);
        _arb_poly_integral(g, g, n, prec);

        _arb_vec_clear(t, n);
        _arb_vec_clear(u, n);
    }

    arb_swap(g, c);
    arb_clear(c);
}
Exemple #8
0
void
arb_poly_mullow(arb_poly_t res, const arb_poly_t poly1,
                                            const arb_poly_t poly2,
                                                long n, long prec)
{
    long len_out;

    if (poly1->length == 0 || poly2->length == 0 || n == 0)
    {
        arb_poly_zero(res);
        return;
    }

    len_out = poly1->length + poly2->length - 1;
    if (n > len_out)
        n = len_out;

    if (res == poly1 || res == poly2)
    {
        arb_poly_t t;
        arb_poly_init2(t, n);
        _arb_poly_mullow(t->coeffs, poly1->coeffs, poly1->length,
                                poly2->coeffs, poly2->length, n, prec);
        arb_poly_swap(res, t);
        arb_poly_clear(t);
    }
    else
    {
        arb_poly_fit_length(res, n);
        _arb_poly_mullow(res->coeffs, poly1->coeffs, poly1->length,
                                poly2->coeffs, poly2->length, n, prec);
    }

    _arb_poly_set_length(res, n);
    _arb_poly_normalise(res);
}
Exemple #9
0
void 
_arb_poly_div_series(arb_ptr Q, arb_srcptr A, long Alen,
    arb_srcptr B, long Blen, long n, long prec)
{
    Alen = FLINT_MIN(Alen, n);
    Blen = FLINT_MIN(Blen, n);

    if (Blen == 1)
    {
        _arb_vec_scalar_div(Q, A, Alen, B, prec);
        _arb_vec_zero(Q + Alen, n - Alen);
    }
    else
    {
        arb_ptr Binv;
        Binv = _arb_vec_init(n);
        _arb_poly_inv_series(Binv, B, Blen, n, prec);
        _arb_poly_mullow(Q, Binv, n, A, Alen, n, prec);
        _arb_vec_clear(Binv, n);
    }
}
Exemple #10
0
int
sin_x2(arb_ptr out, const arb_t inp, void * params, long order, long prec)
{
    arb_ptr x;

    int xlen = FLINT_MIN(2, order);
    int ylen = FLINT_MIN(3, order);

    x = _arb_vec_init(xlen);

    arb_set(x, inp);
    if (xlen > 1)
        arb_one(x + 1);

    _arb_poly_mullow(out, x, xlen, x, xlen, ylen, prec);
    _arb_poly_sin_series(out, out, ylen, order, prec);

    _arb_vec_clear(x, xlen);

    eval_count++;
    return 0;
}
Exemple #11
0
void
_arb_poly_sqrt_series(arb_ptr g,
    arb_srcptr h, slong hlen, slong len, slong prec)
{
    hlen = FLINT_MIN(hlen, len);

    while (hlen > 0 && arb_is_zero(h + hlen - 1))
        hlen--;

    if (hlen <= 1)
    {
        arb_sqrt(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_sqrt(g, h, prec);
        arb_div(g + 1, h + 1, h, prec);
        arb_mul(g + 1, g + 1, g, prec);
        arb_mul_2exp_si(g + 1, g + 1, -1);
    }
    else if (_arb_vec_is_zero(h + 1, hlen - 2))
    {
        arb_t t;
        arb_init(t);
        arf_set_si_2exp_si(arb_midref(t), 1, -1);
        _arb_poly_binomial_pow_arb_series(g, h, hlen, t, len, prec);
        arb_clear(t);
    }
    else
    {
        arb_ptr t;
        t = _arb_vec_init(len);
        _arb_poly_rsqrt_series(t, h, hlen, len, prec);
        _arb_poly_mullow(g, t, len, h, hlen, len, prec);
        _arb_vec_clear(t, len);
    }
}
Exemple #12
0
void
_arb_poly_rgamma_series(arb_ptr res, arb_srcptr h, long hlen, long len, long prec)
{
    int reflect;
    long i, rflen, r, n, wp;
    arb_ptr t, u, v;
    arb_struct f[2];

    hlen = FLINT_MIN(hlen, len);
    wp = prec + FLINT_BIT_COUNT(prec);

    t = _arb_vec_init(len);
    u = _arb_vec_init(len);
    v = _arb_vec_init(len);
    arb_init(f);
    arb_init(f + 1);

    /* use zeta values at small integers */
    if (arb_is_int(h) && (arf_cmpabs_ui(arb_midref(h), prec / 2) < 0))
    {
        r = arf_get_si(arb_midref(h), ARF_RND_DOWN);

        _arb_poly_lgamma_series_at_one(u, len, wp);

        _arb_vec_neg(u, u, len);
        _arb_poly_exp_series(t, u, len, len, wp);

        if (r == 1)
        {
            _arb_vec_swap(v, t, len);
        }
        else if (r <= 0)
        {
            arb_set(f, h);
            arb_one(f + 1);
            rflen = FLINT_MIN(len, 2 - r);
            _arb_poly_rising_ui_series(u, f, FLINT_MIN(2, len), 1 - r, rflen, wp);
            _arb_poly_mullow(v, t, len, u, rflen, len, wp);
        }
        else
        {
            arb_one(f);
            arb_one(f + 1);
            rflen = FLINT_MIN(len, r);
            _arb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r - 1, rflen, wp);

            /* TODO: use div_series? */
            _arb_poly_inv_series(u, v, rflen, len, wp);
            _arb_poly_mullow(v, t, len, u, len, len, wp);
        }
    }
    else
    {
        /* otherwise use Stirling series */
        arb_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp);

        /* rgamma(h) = (gamma(1-h+r) sin(pi h)) / (rf(1-h, r) * pi), h = h0 + t*/
        if (reflect)
        {
            /* u = gamma(r+1-h) */
            arb_sub_ui(f, h, r + 1, wp);
            arb_neg(f, f);
            _arb_poly_gamma_stirling_eval(t, f, n, len, wp);
            _arb_poly_exp_series(u, t, len, len, wp);
            for (i = 1; i < len; i += 2)
                arb_neg(u + i, u + i);

            /* v = sin(pi x) */
            arb_const_pi(f + 1, wp);
            arb_mul(f, h, f + 1, wp);
            _arb_poly_sin_series(v, f, 2, len, wp);

            _arb_poly_mullow(t, u, len, v, len, len, wp);

            /* rf(1-h,r) * pi */
            if (r == 0)
            {
                arb_const_pi(u, wp);
                _arb_vec_scalar_div(v, t, len, u, wp);
            }
            else
            {
                arb_sub_ui(f, h, 1, wp);
                arb_neg(f, f);
                arb_set_si(f + 1, -1);
                rflen = FLINT_MIN(len, r + 1);
                _arb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r, rflen, wp);
                arb_const_pi(u, wp);
                _arb_vec_scalar_mul(v, v, rflen, u, wp);

                /* divide by rising factorial */
                /* TODO: might better to use div_series, when it has a good basecase */
                _arb_poly_inv_series(u, v, rflen, len, wp);
                _arb_poly_mullow(v, t, len, u, len, len, wp);
            }
        }
        else
        {
            /* rgamma(h) = rgamma(h+r) rf(h,r) */
            if (r == 0)
            {
                arb_add_ui(f, h, r, wp);
                _arb_poly_gamma_stirling_eval(t, f, n, len, wp);
                _arb_vec_neg(t, t, len);
                _arb_poly_exp_series(v, t, len, len, wp);
            }
            else
            {
                arb_set(f, h);
                arb_one(f + 1);
                rflen = FLINT_MIN(len, r + 1);
                _arb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, wp);

                arb_add_ui(f, h, r, wp);
                _arb_poly_gamma_stirling_eval(v, f, n, len, wp);
                _arb_vec_neg(v, v, len);
                _arb_poly_exp_series(u, v, len, len, wp);

                _arb_poly_mullow(v, u, len, t, rflen, len, wp);
            }
        }
    }

    /* compose with nonconstant part */
    arb_zero(t);
    _arb_vec_set(t + 1, h + 1, hlen - 1);
    _arb_poly_compose_series(res, v, len, t, hlen, len, prec);

    arb_clear(f);
    arb_clear(f + 1);
    _arb_vec_clear(t, len);
    _arb_vec_clear(u, len);
    _arb_vec_clear(v, len);
}
Exemple #13
0
void
_arb_poly_pow_ui_trunc_binexp(arb_ptr res,
    arb_srcptr f, slong flen, ulong exp, slong len, slong prec)
{
    arb_ptr v, R, S, T;
    slong rlen;
    ulong bit;

    if (exp <= 1)
    {
        if (exp == 0)
            arb_one(res);
        else if (exp == 1)
            _arb_vec_set_round(res, f, len, prec);
        return;
    }

    /* (f * x^r)^m = x^(rm) * f^m */
    while (flen > 1 && arb_is_zero(f))
    {
        if (((ulong) len) > exp)
        {
            _arb_vec_zero(res, exp);
            len -= exp;
            res += exp;
        }
        else
        {
            _arb_vec_zero(res, len);
            return;
        }

        f++;
        flen--;
    }

    if (exp == 2)
    {
        _arb_poly_mullow(res, f, flen, f, flen, len, prec);
        return;
    }

    if (flen == 1)
    {
        arb_pow_ui(res, f, exp, prec);
        return;
    }

    v = _arb_vec_init(len);
    bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2);
    
    if (n_zerobits(exp) % 2)
    {
        R = res;
        S = v;
    }
    else
    {
        R = v;
        S = res;
    }

    MUL(R, rlen, f, flen, f, flen, len, prec);

    if (bit & exp)
    {
        MUL(S, rlen, R, rlen, f, flen, len, prec);
        T = R;
        R = S;
        S = T;
    }
    
    while (bit >>= 1)
    {
        if (bit & exp)
        {
            MUL(S, rlen, R, rlen, R, rlen, len, prec);
            MUL(R, rlen, S, rlen, f, flen, len, prec);
        }
        else
        {
            MUL(S, rlen, R, rlen, R, rlen, len, prec);
            T = R;
            R = S;
            S = T;
        }
    }
    
    _arb_vec_clear(v, len);
}
Exemple #14
0
/* with inverse=1 simultaneously computes g = exp(-x) to length n
with inverse=0 uses g as scratch space, computing
g = exp(-x) only to length (n+1)/2 */
static void
_arb_poly_exp_series_newton(arb_ptr f, arb_ptr g,
                            arb_srcptr h, slong len, slong prec, int inverse, slong cutoff)
{
    slong alloc;
    arb_ptr T, U, hprime;

    alloc = 3 * len;
    T = _arb_vec_init(alloc);
    U = T + len;
    hprime = U + len;

    _arb_poly_derivative(hprime, h, len, prec);
    arb_zero(hprime + len - 1);

    NEWTON_INIT(cutoff, len)

    /* f := exp(h) + O(x^m), g := exp(-h) + O(x^m2) */
    NEWTON_BASECASE(n)
    _arb_poly_exp_series_basecase(f, h, n, n, prec);
    _arb_poly_inv_series(g, f, (n + 1) / 2, (n + 1) / 2, prec);
    NEWTON_END_BASECASE

    /* extend from length m to length n */
    NEWTON_LOOP(m, n)

    slong m2 = (m + 1) / 2;
    slong l = m - 1; /* shifted for derivative */

    /* g := exp(-h) + O(x^m) */
    _arb_poly_mullow(T, f, m, g, m2, m, prec);
    _arb_poly_mullow(g + m2, g, m2, T + m2, m - m2, m - m2, prec);
    _arb_vec_neg(g + m2, g + m2, m - m2);

    /* U := h' + g (f' - f h') + O(x^(n-1))
        Note: should replace h' by h' mod x^(m-1) */
    _arb_vec_zero(f + m, n - m);
    _arb_poly_mullow(T, f, n, hprime, n, n, prec); /* should be mulmid */
    _arb_poly_derivative(U, f, n, prec);
    arb_zero(U + n - 1); /* should skip low terms */
    _arb_vec_sub(U + l, U + l, T + l, n - l, prec);
    _arb_poly_mullow(T + l, g, n - m, U + l, n - m, n - m, prec);
    _arb_vec_add(U + l, hprime + l, T + l, n - m, prec);

    /* f := f + f * (h - int U) + O(x^n) = exp(h) + O(x^n) */
    _arb_poly_integral(U, U, n, prec); /* should skip low terms */
    _arb_vec_sub(U + m, h + m, U + m, n - m, prec);
    _arb_poly_mullow(f + m, f, n - m, U + m, n - m, n - m, prec);

    /* g := exp(-h) + O(x^n) */
    /* not needed if we only want exp(x) */
    if (n == len && inverse)
    {
        _arb_poly_mullow(T, f, n, g, m, n, prec);
        _arb_poly_mullow(g + m, g, m, T + m, n - m, n - m, prec);
        _arb_vec_neg(g + m, g + m, n - m);
    }

    NEWTON_END_LOOP

    NEWTON_END

    _arb_vec_clear(T, alloc);
}
Exemple #15
0
void
_acb_poly_zeta_em_bound(arb_ptr bound, const acb_t s, const acb_t a, ulong N, ulong M, slong len, slong wp)
{
    arb_t K, C, AN, S2M;
    arb_ptr F, R;
    slong k;

    arb_srcptr alpha = acb_realref(a);
    arb_srcptr beta  = acb_imagref(a);
    arb_srcptr sigma = acb_realref(s);
    arb_srcptr tau   = acb_imagref(s);

    arb_init(AN);
    arb_init(S2M);

    /* require alpha + N > 1, sigma + 2M > 1 */
    arb_add_ui(AN, alpha, N - 1, wp);
    arb_add_ui(S2M, sigma, 2*M - 1, wp);

    if (!arb_is_positive(AN) || !arb_is_positive(S2M) || N < 1 || M < 1)
    {
        arb_clear(AN);
        arb_clear(S2M);

        for (k = 0; k < len; k++)
            arb_pos_inf(bound + k);

        return;
    }

    /* alpha + N, sigma + 2M */
    arb_add_ui(AN, AN, 1, wp);
    arb_add_ui(S2M, S2M, 1, wp);

    R = _arb_vec_init(len);
    F = _arb_vec_init(len);

    arb_init(K);
    arb_init(C);

    /* bound for power integral */
    bound_C(C, AN, beta, wp);
    bound_K(K, AN, beta, tau, wp);
    bound_I(R, AN, S2M, C, len, wp);

    for (k = 0; k < len; k++)
    {
        arb_mul(R + k, R + k, K, wp);
        arb_div_ui(K, K, k + 1, wp);
    }

    /* bound for rising factorial */
    bound_rfac(F, s, 2*M, len, wp);

    /* product (TODO: only need upper bound; write a function for this) */
    _arb_poly_mullow(bound, F, len, R, len, len, wp);

    /* bound for bernoulli polynomials, 4 / (2pi)^(2M) */
    arb_const_pi(C, wp);
    arb_mul_2exp_si(C, C, 1);
    arb_pow_ui(C, C, 2 * M, wp);
    arb_ui_div(C, 4, C, wp);
    _arb_vec_scalar_mul(bound, bound, len, C, wp);

    arb_clear(K);
    arb_clear(C);
    arb_clear(AN);
    arb_clear(S2M);

    _arb_vec_clear(R, len);
    _arb_vec_clear(F, len);
}
void
_arb_poly_sin_cos_series_tangent(arb_ptr s, arb_ptr c,
        arb_srcptr h, slong hlen, slong len, slong prec, int times_pi)
{
    arb_ptr t, u, v;
    arb_t s0, c0;
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        if (times_pi)
            arb_sin_cos_pi(s, c, h, prec);
        else
            arb_sin_cos(s, c, h, prec);
        _arb_vec_zero(s + 1, len - 1);
        _arb_vec_zero(c + 1, len - 1);
        return;
    }

    /*
    sin(x) = 2*tan(x/2)/(1+tan(x/2)^2)
    cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2)
    */

    arb_init(s0);
    arb_init(c0);

    t = _arb_vec_init(3 * len);
    u = t + len;
    v = u + len;

    /* sin, cos of h0 */
    if (times_pi)
        arb_sin_cos_pi(s0, c0, h, prec);
    else
        arb_sin_cos(s0, c0, h, prec);

    /* t = tan((h-h0)/2) */
    arb_zero(u);
    _arb_vec_scalar_mul_2exp_si(u + 1, h + 1, hlen - 1, -1);
    if (times_pi)
    {
        arb_const_pi(t, prec);
        _arb_vec_scalar_mul(u + 1, u + 1, hlen - 1, t, prec);
    }

    _arb_poly_tan_series(t, u, hlen, len, prec);

    /* v = 1 + t^2 */
    _arb_poly_mullow(v, t, len, t, len, len, prec);
    arb_add_ui(v, v, 1, prec);

    /* u = 1/(1+t^2) */
    _arb_poly_inv_series(u, v, len, len, prec);

    /* sine */
    _arb_poly_mullow(s, t, len, u, len, len, prec);
    _arb_vec_scalar_mul_2exp_si(s, s, len, 1);

    /* cosine */
    arb_sub_ui(v, v, 2, prec);
    _arb_vec_neg(v, v, len);
    _arb_poly_mullow(c, v, len, u, len, len, prec);

    /* sin(h0 + h1) = cos(h0) sin(h1) + sin(h0) cos(h1)
       cos(h0 + h1) = cos(h0) cos(h1) - sin(h0) sin(h1) */
    if (!arb_is_zero(s0))
    {
        _arb_vec_scalar_mul(t, s, len, c0, prec);
        _arb_vec_scalar_mul(u, c, len, s0, prec);
        _arb_vec_scalar_mul(v, s, len, s0, prec);
        _arb_vec_add(s, t, u, len, prec);
        _arb_vec_scalar_mul(t, c, len, c0, prec);
        _arb_vec_sub(c, t, v, len, prec);
    }

    _arb_vec_clear(t, 3 * len);

    arb_clear(s0);
    arb_clear(c0);
}
void
_arb_poly_zeta_series(arb_ptr res, arb_srcptr h, long hlen, const arb_t a, int deflate, long len, long prec)
{
    long i;
    acb_t cs, ca;
    acb_ptr z;
    arb_ptr t, u;

    if (arb_contains_nonpositive(a))
    {
        _arb_vec_indeterminate(res, len);
        return;
    }

    hlen = FLINT_MIN(hlen, len);

    z = _acb_vec_init(len);
    t = _arb_vec_init(len);
    u = _arb_vec_init(len);
    acb_init(cs);
    acb_init(ca);

    /* use reflection formula */
    if (arf_sgn(arb_midref(h)) < 0 && arb_is_one(a))
    {
        /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */
        arb_t pi;
        arb_ptr f, s1, s2, s3, s4;

        arb_init(pi);
        f = _arb_vec_init(2);
        s1 = _arb_vec_init(len);
        s2 = _arb_vec_init(len);
        s3 = _arb_vec_init(len);
        s4 = _arb_vec_init(len);

        arb_const_pi(pi, prec);

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

        /* s2 = sin(pi*s/2) / pi */
        arb_set(f, h);
        arb_one(f + 1);
        arb_mul_2exp_si(f, f, -1);
        arb_mul_2exp_si(f + 1, f + 1, -1);
        _arb_poly_sin_pi_series(s2, f, 2, len, prec);
        _arb_vec_scalar_div(s2, s2, len, pi, prec);

        /* s3 = gamma(1-s) */
        arb_sub_ui(f, h, 1, prec);
        arb_neg(f, f);
        arb_set_si(f + 1, -1);
        _arb_poly_gamma_series(s3, f, 2, len, prec);

        /* s4 = zeta(1-s) */
        arb_sub_ui(f, h, 1, prec);
        arb_neg(f, f);
        acb_set_arb(cs, f);
        acb_one(ca);
        _acb_poly_zeta_cpx_series(z, cs, ca, 0, len, prec);
        for (i = 0; i < len; i++)
            arb_set(s4 + i, acb_realref(z + i));
        for (i = 1; i < len; i += 2)
            arb_neg(s4 + i, s4 + i);

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

        /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */
        if (deflate)
        {
            arb_sub_ui(u, h, 1, prec);
            arb_neg(u, u);
            arb_inv(u, u, prec);
            for (i = 1; i < len; i++)
                arb_mul(u + i, u + i - 1, u, prec);
            _arb_vec_add(t, t, u, len, prec);
        }

        arb_clear(pi);
        _arb_vec_clear(f, 2);
        _arb_vec_clear(s1, len);
        _arb_vec_clear(s2, len);
        _arb_vec_clear(s3, len);
        _arb_vec_clear(s4, len);
    }
    else
    {
        acb_set_arb(cs, h);
        acb_set_arb(ca, a);
        _acb_poly_zeta_cpx_series(z, cs, ca, deflate, len, prec);
        for (i = 0; i < len; i++)
            arb_set(t + i, acb_realref(z + i));
    }

    /* compose with nonconstant part */
    arb_zero(u);
    _arb_vec_set(u + 1, h + 1, hlen - 1);
    _arb_poly_compose_series(res, t, len, u, hlen, len, prec);

    _acb_vec_clear(z, len);
    _arb_vec_clear(t, len);
    _arb_vec_clear(u, len);
    acb_init(cs);
    acb_init(ca);
}
void
_acb_poly_mullow_transpose_gauss(acb_ptr res,
                                 acb_srcptr poly1, slong len1,
                                 acb_srcptr poly2, slong len2, slong n, slong prec)
{
    arb_ptr a, b, c, d, e, f, w;
    arb_ptr t, u, v;
    slong i;

    len1 = FLINT_MIN(len1, n);
    len2 = FLINT_MIN(len2, n);

    w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + n)));
    a = w;
    b = a + len1;
    c = b + len1;
    d = c + len2;
    e = d + len2;
    f = e + n;

    t = _arb_vec_init(n);
    u = _arb_vec_init(n);
    v = _arb_vec_init(n);

    for (i = 0; i < len1; i++)
    {
        a[i] = *acb_realref(poly1 + i);
        b[i] = *acb_imagref(poly1 + i);
    }

    for (i = 0; i < len2; i++)
    {
        c[i] = *acb_realref(poly2 + i);
        d[i] = *acb_imagref(poly2 + i);
    }

    for (i = 0; i < n; i++)
    {
        e[i] = *acb_realref(res + i);
        f[i] = *acb_imagref(res + i);
    }

    _arb_vec_add(t, a, b, len1, prec);
    _arb_vec_add(u, c, d, len2, prec);

    _arb_poly_mullow(v, t, len1, u, len2, n, prec);
    _arb_poly_mullow(t, a, len1, c, len2, n, prec);
    _arb_poly_mullow(u, b, len1, d, len2, n, prec);

    _arb_vec_sub(e, t, u, n, prec);
    _arb_vec_sub(f, v, t, n, prec);
    _arb_vec_sub(f, f, u, n, prec);

    for (i = 0; i < n; i++)
    {
        *acb_realref(res + i) = e[i];
        *acb_imagref(res + i) = f[i];
    }

    _arb_vec_clear(t, n);
    _arb_vec_clear(u, n);
    _arb_vec_clear(v, n);

    flint_free(w);
}
Exemple #19
0
void _arb_poly_mul(arb_ptr C,
    arb_srcptr A, slong lenA,
    arb_srcptr B, slong lenB, slong prec)
{
    _arb_poly_mullow(C, A, lenA, B, lenB, lenA + lenB - 1, prec);
}
Exemple #20
0
void
_acb_poly_mullow_transpose(acb_ptr res,
    acb_srcptr poly1, slong len1,
    acb_srcptr poly2, slong len2, slong n, slong prec)
{
    arb_ptr a, b, c, d, e, f, w;
    arb_ptr t;
    slong i;

    len1 = FLINT_MIN(len1, n);
    len2 = FLINT_MIN(len2, n);

    w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + n)));
    a = w;
    b = a + len1;
    c = b + len1;
    d = c + len2;
    e = d + len2;
    f = e + n;

    /* (e+fi) = (a+bi)(c+di) = (ac - bd) + (ad + bc)i */
    t = _arb_vec_init(n);

    for (i = 0; i < len1; i++)
    {
        a[i] = *acb_realref(poly1 + i);
        b[i] = *acb_imagref(poly1 + i);
    }

    for (i = 0; i < len2; i++)
    {
        c[i] = *acb_realref(poly2 + i);
        d[i] = *acb_imagref(poly2 + i);
    }

    for (i = 0; i < n; i++)
    {
        e[i] = *acb_realref(res + i);
        f[i] = *acb_imagref(res + i);
    }

    _arb_poly_mullow(e, a, len1, c, len2, n, prec);
    _arb_poly_mullow(t, b, len1, d, len2, n, prec);
    _arb_vec_sub(e, e, t, n, prec);

    _arb_poly_mullow(f, a, len1, d, len2, n, prec);
    /* squaring */
    if (poly1 == poly2 && len1 == len2)
    {
        _arb_vec_scalar_mul_2exp_si(f, f, n, 1);
    }
    else
    {
        _arb_poly_mullow(t, b, len1, c, len2, n, prec);
        _arb_vec_add(f, f, t, n, prec);
    }

    for (i = 0; i < n; i++)
    {
        *acb_realref(res + i) = e[i];
        *acb_imagref(res + i) = f[i];
    }

    _arb_vec_clear(t, n);
    flint_free(w);
}