void
_acb_poly_revert_series_lagrange_fast(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong n, slong prec)
{
    slong i, j, k, m;
    acb_ptr R, S, T, tmp;
    acb_t t;

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

    m = n_sqrt(n);

    acb_init(t);
    R = _acb_vec_init((n - 1) * m);
    S = _acb_vec_init(n - 1);
    T = _acb_vec_init(n - 1);

    acb_zero(Qinv);
    acb_inv(Qinv + 1, Q + 1, prec);

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

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

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

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

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

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

    acb_clear(t);
    _acb_vec_clear(R, (n - 1) * m);
    _acb_vec_clear(S, n - 1);
    _acb_vec_clear(T, n - 1);
}
void
_acb_poly_compose_series_brent_kung(acb_ptr res,
    acb_srcptr poly1, long len1,
    acb_srcptr poly2, long len2, long n, long prec)
{
    acb_mat_t A, B, C;
    acb_ptr t, h;
    long i, m;

    if (n == 1)
    {
        acb_set(res, poly1);
        return;
    }

    m = n_sqrt(n) + 1;

    acb_mat_init(A, m, n);
    acb_mat_init(B, m, m);
    acb_mat_init(C, m, n);

    h = _acb_vec_init(n);
    t = _acb_vec_init(n);

    /* Set rows of B to the segments of poly1 */
    for (i = 0; i < len1 / m; i++)
        _acb_vec_set(B->rows[i], poly1 + i*m, m);
    _acb_vec_set(B->rows[i], poly1 + i*m, len1 % m);

    /* Set rows of A to powers of poly2 */
    acb_set_ui(A->rows[0] + 0, 1UL);
    _acb_vec_set(A->rows[1], poly2, len2);
    for (i = 2; i < m; i++)
        _acb_poly_mullow(A->rows[i], A->rows[(i + 1) / 2], n, A->rows[i / 2], n, n, prec);

    acb_mat_mul(C, B, A, prec);

    /* Evaluate block composition using the Horner scheme */
    _acb_vec_set(res, C->rows[m - 1], n);
    _acb_poly_mullow(h, A->rows[m - 1], n, poly2, len2, n, prec);

    for (i = m - 2; i >= 0; i--)
    {
        _acb_poly_mullow(t, res, n, h, n, n, prec);
        _acb_poly_add(res, t, n, C->rows[i], n, prec);
    }

    _acb_vec_clear(h, n);
    _acb_vec_clear(t, n);

    acb_mat_clear(A);
    acb_mat_clear(B);
    acb_mat_clear(C);
}
Beispiel #3
0
void
acb_poly_mullow(acb_poly_t res, const acb_poly_t poly1,
                                            const acb_poly_t poly2,
                                                slong n, slong prec)
{
    slong len1, len2;

    len1 = poly1->length;
    len2 = poly2->length;

    if (len1 == 0 || len2 == 0 || n == 0)
    {
        acb_poly_zero(res);
        return;
    }

    n = FLINT_MIN((len1 + len2 - 1), n);
    len1 = FLINT_MIN(len1, n);
    len2 = FLINT_MIN(len2, n);

    if (res == poly1 || res == poly2)
    {
        acb_poly_t t;
        acb_poly_init2(t, n);
        _acb_poly_mullow(t->coeffs, poly1->coeffs, len1,
                                poly2->coeffs, len2, n, prec);
        acb_poly_swap(res, t);
        acb_poly_clear(t);
    }
    else
    {
        acb_poly_fit_length(res, n);
        _acb_poly_mullow(res->coeffs, poly1->coeffs, len1,
                                poly2->coeffs, len2, n, prec);
    }

    _acb_poly_set_length(res, n);
    _acb_poly_normalise(res);
}
Beispiel #4
0
int
elliptic(acb_ptr out, const acb_t inp, void * params, long order, long prec)
{
    acb_ptr t;
    t = _acb_vec_init(order);
    acb_set(t, inp);
    if (order > 1)
        acb_one(t + 1);
    _acb_poly_sin_series(t, t, FLINT_MIN(2, order), order, prec);
    _acb_poly_mullow(out, t, order, t, order, order, prec);
    _acb_vec_scalar_mul_2exp_si(t, out, order, -1);
    acb_sub_ui(t, t, 1, prec);
    _acb_vec_neg(t, t, order);
    _acb_poly_rsqrt_series(out, t, order, order, prec);
    _acb_vec_clear(t, order);
    return 0;
}
Beispiel #5
0
void
_acb_poly_compose_series_horner(acb_ptr res, acb_srcptr poly1, slong len1,
                            acb_srcptr poly2, slong len2, slong n, slong prec)
{
    if (n == 1)
    {
        acb_set(res, poly1);
    }
    else
    {
        slong i = len1 - 1;
        slong lenr;

        acb_ptr t = _acb_vec_init(n);

        lenr = len2;
        _acb_vec_scalar_mul(res, poly2, len2, poly1 + i, prec);
        i--;
        acb_add(res, res, poly1 + i, prec);

        while (i > 0)
        {
            i--;
            if (lenr + len2 - 1 < n)
            {
                _acb_poly_mul(t, res, lenr, poly2, len2, prec);
                lenr = lenr + len2 - 1;
            }
            else
            {
                _acb_poly_mullow(t, res, lenr, poly2, len2, n, prec);
                lenr = n;
            }
            _acb_poly_add(res, t, lenr, poly1 + i, 1, prec);
        }

        _acb_vec_zero(res + lenr, n - lenr);
        _acb_vec_clear(t, n);
    }
}
Beispiel #6
0
void
_acb_poly_sqrt_series(acb_ptr g,
    acb_srcptr h, slong hlen, slong len, slong prec)
{
    hlen = FLINT_MIN(hlen, len);

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

    if (hlen <= 1)
    {
        acb_sqrt(g, h, prec);
        _acb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        acb_sqrt(g, h, prec);
        acb_div(g + 1, h + 1, h, prec);
        acb_mul(g + 1, g + 1, g, prec);
        acb_mul_2exp_si(g + 1, g + 1, -1);
    }
    else if (_acb_vec_is_zero(h + 1, hlen - 2))
    {
        acb_t t;
        acb_init(t);
        arf_set_si_2exp_si(arb_midref(acb_realref(t)), 1, -1);
        _acb_poly_binomial_pow_acb_series(g, h, hlen, t, len, prec);
        acb_clear(t);
    }
    else
    {
        acb_ptr t;
        t = _acb_vec_init(len);
        _acb_poly_rsqrt_series(t, h, hlen, len, prec);
        _acb_poly_mullow(g, t, len, h, hlen, len, prec);
        _acb_vec_clear(t, len);
    }
}
Beispiel #7
0
void
_acb_poly_atan_series(acb_ptr g, acb_srcptr h, slong hlen, slong n, slong prec)
{
    acb_t c;
    acb_init(c);

    acb_atan(c, h, prec);

    hlen = FLINT_MIN(hlen, n);

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

        t = _acb_vec_init(n);
        u = _acb_vec_init(n);

        /* atan(h(x)) = integral(h'(x)/(1+h(x)^2)) */
        ulen = FLINT_MIN(n, 2 * hlen - 1);
        _acb_poly_mullow(u, h, hlen, h, hlen, ulen, prec);
        acb_add_ui(u, u, 1, prec);

        _acb_poly_derivative(t, h, hlen, prec);
        _acb_poly_div_series(g, t, hlen - 1, u, ulen, n, prec);
        _acb_poly_integral(g, g, n, prec);

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

    acb_swap(g, c);
    acb_clear(c);
}
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);
}
Beispiel #9
0
void
_acb_poly_rgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec)
{
    int reflect;
    slong i, rflen, r, n, wp;
    acb_ptr t, u, v;
    acb_struct f[2];

    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        acb_rgamma(res, h, prec);
        _acb_vec_zero(res + 1, len - 1);
        return;
    }

    /* use real code for real input */
    if (_acb_vec_is_real(h, hlen))
    {
        arb_ptr tmp = _arb_vec_init(len);
        for (i = 0; i < hlen; i++)
            arb_set(tmp + i, acb_realref(h + i));
        _arb_poly_rgamma_series(tmp, tmp, hlen, len, prec);
        for (i = 0; i < len; i++)
            acb_set_arb(res + i, tmp + i);
        _arb_vec_clear(tmp, len);
        return;
    }

    wp = prec + FLINT_BIT_COUNT(prec);

    t = _acb_vec_init(len);
    u = _acb_vec_init(len);
    v = _acb_vec_init(len);
    acb_init(f);
    acb_init(f + 1);

    /* otherwise use Stirling series */
    acb_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) */
        acb_sub_ui(f, h, r + 1, wp);
        acb_neg(f, f);
        _acb_poly_gamma_stirling_eval(t, f, n, len, wp);
        _acb_poly_exp_series(u, t, len, len, wp);
        for (i = 1; i < len; i += 2)
            acb_neg(u + i, u + i);

        /* v = sin(pi x) */
        acb_set(f, h);
        acb_one(f + 1);
        _acb_poly_sin_pi_series(v, f, 2, len, wp);

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

        /* rf(1-h,r) * pi */
        if (r == 0)
        {
            acb_const_pi(u, wp);
            _acb_vec_scalar_div(v, t, len, u, wp);
        }
        else
        {
            acb_sub_ui(f, h, 1, wp);
            acb_neg(f, f);
            acb_set_si(f + 1, -1);
            rflen = FLINT_MIN(len, r + 1);
            _acb_poly_rising_ui_series(v, f, FLINT_MIN(2, len), r, rflen, wp);
            acb_const_pi(u, wp);
            _acb_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 */
            _acb_poly_inv_series(u, v, rflen, len, wp);
            _acb_poly_mullow(v, t, len, u, len, len, wp);
        }
    }
    else
    {
        /* rgamma(h) = rgamma(h+r) rf(h,r) */
        if (r == 0)
        {
            acb_add_ui(f, h, r, wp);
            _acb_poly_gamma_stirling_eval(t, f, n, len, wp);
            _acb_vec_neg(t, t, len);
            _acb_poly_exp_series(v, t, len, len, wp);
        }
        else
        {
            acb_set(f, h);
            acb_one(f + 1);
            rflen = FLINT_MIN(len, r + 1);
            _acb_poly_rising_ui_series(t, f, FLINT_MIN(2, len), r, rflen, wp);

            acb_add_ui(f, h, r, wp);
            _acb_poly_gamma_stirling_eval(v, f, n, len, wp);
            _acb_vec_neg(v, v, len);
            _acb_poly_exp_series(u, v, len, len, wp);

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

    /* compose with nonconstant part */
    acb_zero(t);
    _acb_vec_set(t + 1, h + 1, hlen - 1);
    _acb_poly_compose_series(res, v, len, t, hlen, len, prec);

    acb_clear(f);
    acb_clear(f + 1);
    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
    _acb_vec_clear(v, len);
}
int main()
{
    long iter;
    flint_rand_t state;

    printf("elliptic_p_zpx....");
    fflush(stdout);

    flint_randinit(state);

    /* Test differential equation */
    for (iter = 0; iter < 5000; iter++)
    {
        acb_t tau, z;
        acb_ptr g, wp, wp3, wpd, wpd2;
        long prec, len, i;

        len = 1 + n_randint(state, 15);
        prec = 2 + n_randint(state, 1000);

        acb_init(tau);
        acb_init(z);
        g = _acb_vec_init(2);
        wp = _acb_vec_init(len + 1);
        wp3 = _acb_vec_init(len);
        wpd = _acb_vec_init(len);
        wpd2 = _acb_vec_init(len);

        acb_randtest(tau, state, prec, 10);
        acb_randtest(z, state, prec, 10);

        acb_modular_elliptic_p_zpx(wp, z, tau, len + 1, prec);
        acb_modular_eisenstein(g, tau, 2, prec);
        acb_mul_ui(g, g, 60, prec);
        acb_mul_ui(g + 1, g + 1, 140, prec);

        _acb_poly_derivative(wpd, wp, len + 1, prec);
        _acb_poly_mullow(wpd2, wpd, len, wpd, len, len, prec);
        _acb_poly_pow_ui_trunc_binexp(wp3, wp, len, 3, len, prec);
        _acb_vec_scalar_mul_ui(wp3, wp3, len, 4, prec);
        _acb_vec_scalar_submul(wp3, wp, len, g, prec);
        acb_sub(wp3, wp3, g + 1, prec);

        for (i = 0; i < len; i++)
        {
            if (!acb_overlaps(wpd2 + i, wp3 + i))
            {
                printf("FAIL (overlap)\n");
                printf("i = %ld  len = %ld  prec = %ld\n\n", i, len, prec);
                printf("z = "); acb_printd(z, 15); printf("\n\n");
                printf("tau = "); acb_printd(tau, 15); printf("\n\n");
                printf("wp = "); acb_printd(wp + i, 15); printf("\n\n");
                printf("wpd = "); acb_printd(wpd + i, 15); printf("\n\n");
                printf("wp3 = "); acb_printd(wp3 + i, 15); printf("\n\n");
                abort();
            }
        }

        acb_clear(tau);
        acb_clear(z);
        _acb_vec_clear(g, 2);
        _acb_vec_clear(wp, len + 1);
        _acb_vec_clear(wp3, len);
        _acb_vec_clear(wpd, len);
        _acb_vec_clear(wpd2, len);
    }

    /* Consistency test */
    for (iter = 0; iter < 5000; iter++)
    {
        acb_t tau, z;
        acb_ptr wp1, wp2;
        long prec1, prec2, len1, len2, i;

        len1 = n_randint(state, 15);
        len2 = n_randint(state, 15);
        prec1 = 2 + n_randint(state, 1000);
        prec2 = 2 + n_randint(state, 1000);

        acb_init(tau);
        acb_init(z);
        wp1 = _acb_vec_init(len1);
        wp2 = _acb_vec_init(len2);

        acb_randtest(tau, state, prec1, 10);
        acb_randtest(z, state, prec1, 10);

        acb_modular_elliptic_p_zpx(wp1, z, tau, len1, prec1);
        acb_modular_elliptic_p_zpx(wp2, z, tau, len2, prec2);

        for (i = 0; i < FLINT_MIN(len1, len2); i++)
        {
            if (!acb_overlaps(wp1 + i, wp2 + i))
            {
                printf("FAIL (overlap)\n");
                printf("i = %ld len1 = %ld len2 = %ld\n\n", i, len1, len2);
                printf("tau = "); acb_printd(tau, 15); printf("\n\n");
                printf("z = "); acb_printd(z, 15); printf("\n\n");
                printf("wp1 = "); acb_printd(wp1 + i, 15); printf("\n\n");
                printf("wp2 = "); acb_printd(wp2 + i, 15); printf("\n\n");
                abort();
            }
        }

        acb_clear(tau);
        acb_clear(z);
        _acb_vec_clear(wp1, len1);
        _acb_vec_clear(wp2, len2);
    }

    flint_randclear(state);
    flint_cleanup();
    printf("PASS\n");
    return EXIT_SUCCESS;
}
Beispiel #11
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);
    }
}
Beispiel #12
0
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);
}
void
_acb_poly_pow_ui_trunc_binexp(acb_ptr res,
    acb_srcptr f, long flen, ulong exp, long len, long prec)
{
    acb_ptr v, R, S, T;
    long rlen;
    ulong bit;

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

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

        f++;
        flen--;
    }

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

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

    v = _acb_vec_init(len);
    bit = 1UL << (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;
        }
    }
    
    _acb_vec_clear(v, len);
}
Beispiel #14
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);
}
Beispiel #15
0
void
acb_elliptic_p_jet(acb_ptr r, const acb_t z, const acb_t tau, slong len, slong prec)
{
    acb_t t01, t02, t03, t04;
    acb_ptr tz1, tz2, tz3, tz4;
    acb_t t;
    int real;
    slong k;

    if (len < 1)
        return;

    if (len == 1)
    {
        acb_elliptic_p(r, z, tau, prec);
        return;
    }

    real = acb_is_real(z) && arb_is_int_2exp_si(acb_realref(tau), -1) &&
                arb_is_positive(acb_imagref(tau));

    acb_init(t);

    acb_init(t01);
    acb_init(t02);
    acb_init(t03);
    acb_init(t04);

    tz1 = _acb_vec_init(len);
    tz2 = _acb_vec_init(len);
    tz3 = _acb_vec_init(len);
    tz4 = _acb_vec_init(len);

    acb_modular_theta_jet(tz1, tz2, tz3, tz4, z, tau, len, prec);

    /* [theta_4(z) / theta_1(z)]^2 */
    _acb_poly_div_series(tz2, tz4, len, tz1, len, len, prec);
    _acb_poly_mullow(tz1, tz2, len, tz2, len, len, prec);

    acb_zero(t);
    acb_modular_theta(t01, t02, t03, t04, t, tau, prec);

    /* [theta_2(0) * theta_3(0)] ^2 */
    acb_mul(t, t02, t03, prec);
    acb_mul(t, t, t, prec);
    _acb_vec_scalar_mul(tz1, tz1, len, t, prec);

    /* - [theta_2(0)^4 + theta_3(0)^4] / 3 */
    acb_pow_ui(t02, t02, 4, prec);
    acb_pow_ui(t03, t03, 4, prec);
    acb_add(t, t02, t03, prec);
    acb_div_ui(t, t, 3, prec);
    acb_sub(tz1, tz1, t, prec);

    /* times pi^2 */
    acb_const_pi(t, prec);
    acb_mul(t, t, t, prec);
    _acb_vec_scalar_mul(r, tz1, len, t, prec);

    if (real)
    {
        for (k = 0; k < len; k++)
            arb_zero(acb_imagref(r + k));
    }

    acb_clear(t);

    acb_clear(t01);
    acb_clear(t02);
    acb_clear(t03);
    acb_clear(t04);

    _acb_vec_clear(tz1, len);
    _acb_vec_clear(tz2, len);
    _acb_vec_clear(tz3, len);
    _acb_vec_clear(tz4, len);
}
Beispiel #16
0
Datei: mul.c Projekt: isuruf/arb
void _acb_poly_mul(acb_ptr C,
                   acb_srcptr A, slong lenA,
                   acb_srcptr B, slong lenB, slong prec)
{
    _acb_poly_mullow(C, A, lenA, B, lenB, lenA + lenB - 1, prec);
}