예제 #1
0
void
_acb_poly_interpolate_fast_precomp(acb_ptr poly,
    acb_srcptr ys, acb_ptr * tree, acb_srcptr weights,
    slong len, slong prec)
{
    acb_ptr t, u, pa, pb;
    slong i, pow, left;

    if (len == 0)
        return;

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);

    for (i = 0; i < len; i++)
        acb_mul(poly + i, weights + i, ys + i, prec);

    for (i = 0; i < FLINT_CLOG2(len); i++)
    {
        pow = (WORD(1) << i);
        pa = tree[i];
        pb = poly;
        left = len;

        while (left >= 2 * pow)
        {
            _acb_poly_mul(t, pa, pow + 1, pb + pow, pow, prec);
            _acb_poly_mul(u, pa + pow + 1, pow + 1, pb, pow, prec);
            _acb_vec_add(pb, t, u, 2 * pow, prec);

            left -= 2 * pow;
            pa += 2 * pow + 2;
            pb += 2 * pow;
        }

        if (left > pow)
        {
            _acb_poly_mul(t, pa, pow + 1, pb + pow, left - pow, prec);
            _acb_poly_mul(u, pb, pow, pa + pow + 1, left - pow + 1, prec);
            _acb_vec_add(pb, t, u, left, prec);
        }
    }

    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
}
예제 #2
0
void
_acb_poly_powsum_one_series_sieved(acb_ptr z, const acb_t s, slong n, slong len, slong prec)
{
    slong * divisors;
    slong powers_alloc;
    slong i, j, k, ibound, kprev, power_of_two, horner_point;
    int critical_line, integer;

    acb_ptr powers;
    acb_ptr t, u, x;
    acb_ptr p1, p2;
    arb_t logk, v, w;

    critical_line = arb_is_exact(acb_realref(s)) &&
        (arf_cmp_2exp_si(arb_midref(acb_realref(s)), -1) == 0);

    integer = arb_is_zero(acb_imagref(s)) && arb_is_int(acb_realref(s));

    divisors = flint_calloc(n / 2 + 1, sizeof(slong));
    powers_alloc = (n / 6 + 1) * len;
    powers = _acb_vec_init(powers_alloc);

    ibound = n_sqrt(n);
    for (i = 3; i <= ibound; i += 2)
        if (DIVISOR(i) == 0)
            for (j = i * i; j <= n; j += 2 * i)
                DIVISOR(j) = i;

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);
    x = _acb_vec_init(len);
    arb_init(logk);
    arb_init(v);
    arb_init(w);

    power_of_two = 1;
    while (power_of_two * 2 <= n)
        power_of_two *= 2;
    horner_point = n / power_of_two;

    _acb_vec_zero(z, len);

    kprev = 0;
    COMPUTE_POWER(x, 2, kprev);

    for (k = 1; k <= n; k += 2)
    {
        /* t = k^(-s) */
        if (DIVISOR(k) == 0)
        {
            COMPUTE_POWER(t, k, kprev);
        }
        else
        {
            p1 = POWER(DIVISOR(k));
            p2 = POWER(k / DIVISOR(k));

            if (len == 1)
                acb_mul(t, p1, p2, prec);
            else
                _acb_poly_mullow(t, p1, len, p2, len, len, prec);
        }

        if (k * 3 <= n)
            _acb_vec_set(POWER(k), t, len);

        _acb_vec_add(u, u, t, len, prec);

        while (k == horner_point && power_of_two != 1)
        {
            _acb_poly_mullow(t, z, len, x, len, len, prec);
            _acb_vec_add(z, t, u, len, prec);

            power_of_two /= 2;
            horner_point = n / power_of_two;
            horner_point -= (horner_point % 2 == 0);
        }
    }

    _acb_poly_mullow(t, z, len, x, len, len, prec);
    _acb_vec_add(z, t, u, len, prec);

    flint_free(divisors);
    _acb_vec_clear(powers, powers_alloc);
    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
    _acb_vec_clear(x, len);
    arb_clear(logk);
    arb_clear(v);
    arb_clear(w);
}
예제 #3
0
void
_acb_poly_zeta_cpx_reflect(acb_ptr t, const acb_t h, const acb_t a, int deflate, slong len, slong prec)
{
    /* use reflection formula */
    if (arf_sgn(arb_midref(acb_realref(h))) < 0 && acb_is_one(a))
    {
        /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */
        acb_t pi, hcopy;
        acb_ptr f, s1, s2, s3, s4, u;
        slong i;

        acb_init(pi);
        acb_init(hcopy);
        f = _acb_vec_init(2);
        s1 = _acb_vec_init(len);
        s2 = _acb_vec_init(len);
        s3 = _acb_vec_init(len);
        s4 = _acb_vec_init(len);
        u = _acb_vec_init(len);
        acb_set(hcopy, h);

        acb_const_pi(pi, prec);

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

        /* s2 = sin(pi*s/2) / pi */
        acb_set(f, h);
        acb_one(f + 1);
        acb_mul_2exp_si(f, f, -1);
        acb_mul_2exp_si(f + 1, f + 1, -1);
        _acb_poly_sin_pi_series(s2, f, 2, len, prec);
        _acb_vec_scalar_div(s2, s2, len, pi, prec);

        /* s3 = gamma(1-s) */
        acb_sub_ui(f, hcopy, 1, prec);
        acb_neg(f, f);
        acb_set_si(f + 1, -1);
        _acb_poly_gamma_series(s3, f, 2, len, prec);

        /* s4 = zeta(1-s) */
        acb_sub_ui(f, hcopy, 1, prec);
        acb_neg(f, f);
        _acb_poly_zeta_cpx_series(s4, f, a, 0, len, prec);
        for (i = 1; i < len; i += 2)
            acb_neg(s4 + i, s4 + i);

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

        /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */
        if (deflate)
        {
            acb_sub_ui(u, hcopy, 1, prec);
            acb_neg(u, u);
            acb_inv(u, u, prec);
            for (i = 1; i < len; i++)
                acb_mul(u + i, u + i - 1, u, prec);
            _acb_vec_add(t, t, u, len, prec);
        }

        acb_clear(pi);
        acb_clear(hcopy);
        _acb_vec_clear(f, 2);
        _acb_vec_clear(s1, len);
        _acb_vec_clear(s2, len);
        _acb_vec_clear(s3, len);
        _acb_vec_clear(s4, len);
        _acb_vec_clear(u, len);
    }
    else
    {
        _acb_poly_zeta_cpx_series(t, h, a, deflate, len, prec);
    }
}
예제 #4
0
void
_acb_poly_zeta_em_tail_naive(acb_ptr sum, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong d, slong prec)
{
    acb_ptr u, term;
    acb_t Na2, splus, rec;
    arb_t x;
    fmpz_t c;
    int aint;
    slong r;

    BERNOULLI_ENSURE_CACHED(2 * M);

    u = _acb_vec_init(d);
    term = _acb_vec_init(d);
    acb_init(splus);
    acb_init(rec);
    acb_init(Na2);
    arb_init(x);
    fmpz_init(c);

    _acb_vec_zero(sum, d);

    /* u = 1/2 * Nasx */
    _acb_vec_scalar_mul_2exp_si(u, Nasx, d, -WORD(1));

    /* term = u * (s+x) / (N+a) */
    _acb_poly_mullow_cpx(u, u, d, s, d, prec);
    _acb_vec_scalar_div(term, u, d, Na, prec);

    /* (N+a)^2 or 1/(N+a)^2 */
    acb_mul(Na2, Na, Na, prec);
    aint = acb_is_int(Na2);

    if (!aint)
        acb_inv(Na2, Na2, prec);

    for (r = 1; r <= M; r++)
    {
        /* flint_printf("sum 2: %wd %wd\n", r, M); */

        /* sum += bernoulli number * term */
        arb_set_round_fmpz(x, fmpq_numref(bernoulli_cache + 2 * r), prec);
        arb_div_fmpz(x, x, fmpq_denref(bernoulli_cache + 2 * r), prec);

        _acb_vec_scalar_mul_arb(u, term, d, x, prec);
        _acb_vec_add(sum, sum, u, d, prec);

        /* multiply term by ((s+x)+2r-1)((s+x)+2r) / ((N+a)^2 * (2*r+1)*(2*r+2)) */
        acb_set(splus, s);
        arb_add_ui(acb_realref(splus), acb_realref(splus), 2*r-1, prec);
        _acb_poly_mullow_cpx(term, term, d, splus, d, prec);
        arb_add_ui(acb_realref(splus), acb_realref(splus), 1, prec);
        _acb_poly_mullow_cpx(term, term, d, splus, d, prec);

        /* TODO: combine with previous multiplication? */
        if (aint)
        {
            arb_mul_ui(x, acb_realref(Na2), 2*r+1, prec);
            arb_mul_ui(x, x, 2*r+2, prec);
            _acb_vec_scalar_div_arb(term, term, d, x, prec);
        }
        else
        {
            fmpz_set_ui(c, 2*r+1);
            fmpz_mul_ui(c, c, 2*r+2);
            acb_div_fmpz(rec, Na2, c, prec);
            _acb_vec_scalar_mul(term, term, d, rec, prec);
        }
    }

    _acb_vec_clear(u, d);
    _acb_vec_clear(term, d);
    acb_clear(splus);
    acb_clear(rec);
    acb_clear(Na2);
    arb_clear(x);
    fmpz_clear(c);
}
예제 #5
0
파일: zeta_em_sum.c 프로젝트: isuruf/arb
void
_acb_poly_zeta_em_sum(acb_ptr z, const acb_t s, const acb_t a, int deflate, ulong N, ulong M, slong d, slong prec)
{
    acb_ptr t, u, v, term, sum;
    acb_t Na, one;
    slong i;

    t = _acb_vec_init(d + 1);
    u = _acb_vec_init(d);
    v = _acb_vec_init(d);
    term = _acb_vec_init(d);
    sum = _acb_vec_init(d);
    acb_init(Na);
    acb_init(one);

    prec += 2 * (FLINT_BIT_COUNT(N) + FLINT_BIT_COUNT(d));
    acb_one(one);

    /* sum 1/(k+a)^(s+x) */
    if (acb_is_one(a) && d <= 3)
        _acb_poly_powsum_one_series_sieved(sum, s, N, d, prec);
    else if (N > 50 && flint_get_num_threads() > 1)
        _acb_poly_powsum_series_naive_threaded(sum, s, a, one, N, d, prec);
    else
        _acb_poly_powsum_series_naive(sum, s, a, one, N, d, prec);

    /* t = 1/(N+a)^(s+x); we might need one extra term for deflation */
    acb_add_ui(Na, a, N, prec);
    _acb_poly_acb_invpow_cpx(t, Na, s, d + 1, prec);

    /* sum += (N+a) * 1/((s+x)-1) * t */
    if (!deflate)
    {
        /* u = (N+a)^(1-(s+x)) */
        acb_sub_ui(v, s, 1, prec);
        _acb_poly_acb_invpow_cpx(u, Na, v, d, prec);

        /* divide by 1/((s-1) + x) */
        acb_sub_ui(v, s, 1, prec);
        acb_div(u, u, v, prec);

        for (i = 1; i < d; i++)
        {
            acb_sub(u + i, u + i, u + i - 1, prec);
            acb_div(u + i, u + i, v, prec);
        }

        _acb_vec_add(sum, sum, u, d, prec);
    }
    /* sum += ((N+a)^(1-(s+x)) - 1) / ((s+x) - 1) */
    else
    {
        /* at s = 1, this becomes (N*t - 1)/x, i.e. just remove one coeff  */
        if (acb_is_one(s))
        {
            for (i = 0; i < d; i++)
                acb_mul(u + i, t + i + 1, Na, prec);
            _acb_vec_add(sum, sum, u, d, prec);
        }
        else
        {
            /* TODO: this is numerically unstable for large derivatives,
                and divides by zero if s contains 1. We want a good
                way to evaluate the power series ((N+a)^y - 1) / y where y has
                nonzero constant term, without doing a division.
                How is this best done? */

            _acb_vec_scalar_mul(t, t, d, Na, prec);
            acb_sub_ui(t + 0, t + 0, 1, prec);
            acb_sub_ui(u + 0, s, 1, prec);
            acb_inv(u + 0, u + 0, prec);
            for (i = 1; i < d; i++)
                acb_mul(u + i, u + i - 1, u + 0, prec);
            for (i = 1; i < d; i += 2)
                acb_neg(u + i, u + i);
            _acb_poly_mullow(v, u, d, t, d, d, prec);
            _acb_vec_add(sum, sum, v, d, prec);
            _acb_poly_acb_invpow_cpx(t, Na, s, d, prec);
        }
    }

    /* sum += u = 1/2 * t */
    _acb_vec_scalar_mul_2exp_si(u, t, d, -WORD(1));
    _acb_vec_add(sum, sum, u, d, prec);

    /* Euler-Maclaurin formula tail */
    if (d < 5 || d < M / 10)
        _acb_poly_zeta_em_tail_naive(u, s, Na, t, M, d, prec);
    else
        _acb_poly_zeta_em_tail_bsplit(u, s, Na, t, M, d, prec);

    _acb_vec_add(z, sum, u, d, prec);

    _acb_vec_clear(t, d + 1);
    _acb_vec_clear(u, d);
    _acb_vec_clear(v, d);
    _acb_vec_clear(term, d);
    _acb_vec_clear(sum, d);
    acb_clear(Na);
    acb_clear(one);
}
예제 #6
0
void
_acb_poly_sin_cos_series_tangent(acb_ptr s, acb_ptr c,
        const acb_srcptr h, slong hlen, slong len, slong prec, int times_pi)
{
    acb_ptr t, u, v;
    acb_t s0, c0;
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        if (times_pi)
            acb_sin_cos_pi(s, c, h, prec);
        else
            acb_sin_cos(s, c, h, prec);
        _acb_vec_zero(s + 1, len - 1);
        _acb_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)
    */

    acb_init(s0);
    acb_init(c0);

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

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

    /* t = tan((h-h0)/2) */
    acb_zero(u);
    _acb_vec_scalar_mul_2exp_si(u + 1, h + 1, hlen - 1, -1);
    if (times_pi)
    {
        acb_const_pi(t, prec);
        _acb_vec_scalar_mul(u + 1, u + 1, hlen - 1, t, prec);
    }

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

    /* v = 1 + t^2 */
    _acb_poly_mullow(v, t, len, t, len, len, prec);
    acb_add_ui(v, v, 1, prec);

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

    /* sine */
    _acb_poly_mullow(s, t, len, u, len, len, prec);
    _acb_vec_scalar_mul_2exp_si(s, s, len, 1);

    /* cosine */
    acb_sub_ui(v, v, 2, prec);
    _acb_vec_neg(v, v, len);
    _acb_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 (!acb_is_zero(s0))
    {
        _acb_vec_scalar_mul(t, s, len, c0, prec);
        _acb_vec_scalar_mul(u, c, len, s0, prec);
        _acb_vec_scalar_mul(v, s, len, s0, prec);
        _acb_vec_add(s, t, u, len, prec);
        _acb_vec_scalar_mul(t, c, len, c0, prec);
        _acb_vec_sub(c, t, v, len, prec);
    }

    _acb_vec_clear(t, 3 * len);

    acb_clear(s0);
    acb_clear(c0);
}