Example #1
0
void
acb_polygamma(acb_t res, const acb_t s, const acb_t z, long prec)
{
    if (acb_is_zero(s))
    {
        acb_digamma(res, z, prec);
    }
    else if (acb_is_int(s) && arb_is_positive(acb_realref(s)))
    {
        acb_t t, u;

        acb_init(t);
        acb_init(u);

        acb_add_ui(t, s, 1, prec);
        acb_gamma(u, t, prec);
        acb_hurwitz_zeta(t, t, z, prec);

        if (arf_is_int_2exp_si(arb_midref(acb_realref(s)), 1))
            acb_neg(t, t);

        acb_mul(res, t, u, prec);

        acb_clear(t);
        acb_clear(u);
    }
    else
    {
        acb_t t, u;
        acb_struct v[2];

        acb_init(t);
        acb_init(u);

        acb_init(v);
        acb_init(v + 1);

        /* u = psi(-s) + gamma */
        acb_neg(t, s);
        acb_digamma(u, t, prec);
        arb_const_euler(acb_realref(v), prec);
        arb_add(acb_realref(u), acb_realref(u), acb_realref(v), prec);

        acb_add_ui(t, s, 1, prec);
        _acb_poly_zeta_cpx_series(v, t, z, 0, 2, prec);

        acb_addmul(v + 1, v, u, prec);

        acb_neg(t, s);
        acb_rgamma(u, t, prec);
        acb_mul(res, v + 1, u, prec);

        acb_clear(v);
        acb_clear(v + 1);

        acb_clear(t);
        acb_clear(u);
    }
}
Example #2
0
void
_acb_poly_zeta_cpx_series(acb_ptr z, const acb_t s, const acb_t a, int deflate, slong d, slong prec)
{
    ulong M, N;
    slong i, bound_prec;
    mag_t bound;
    arb_ptr vb;
    int is_real, const_is_real;

    if (d < 1)
        return;

    if (!acb_is_finite(s) || !acb_is_finite(a))
    {
        _acb_vec_indeterminate(z, d);
        return;
    }

    if (acb_is_one(s) && deflate && d == 1)
    {
        acb_digamma(z, a, prec);
        acb_neg(z, z);
        if (!acb_is_finite(z))  /* todo: in digamma */
            acb_indeterminate(z);
        return;
    }

    is_real = const_is_real = 0;

    if (acb_is_real(s) && acb_is_real(a))
    {
        if (arb_is_positive(acb_realref(a)))
        {
            is_real = const_is_real = 1;
        }
        else if (arb_is_int(acb_realref(a)) &&
             arb_is_int(acb_realref(s)) &&
             arb_is_nonpositive(acb_realref(s)))
        {
            const_is_real = 1;
        }
    }

    mag_init(bound);
    vb = _arb_vec_init(d);

    bound_prec = 40 + prec / 20;

    _acb_poly_zeta_em_choose_param(bound, &N, &M, s, a, FLINT_MIN(d, 2), prec, bound_prec);
    _acb_poly_zeta_em_bound(vb, s, a, N, M, d, bound_prec);

    _acb_poly_zeta_em_sum(z, s, a, deflate, N, M, d, prec);

    for (i = 0; i < d; i++)
    {
        arb_get_mag(bound, vb + i);
        arb_add_error_mag(acb_realref(z + i), bound);

        if (!is_real && !(i == 0 && const_is_real))
            arb_add_error_mag(acb_imagref(z + i), bound);
    }

    mag_clear(bound);
    _arb_vec_clear(vb, d);
}
Example #3
0
void
_acb_poly_digamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec)
{
    int reflect;
    slong i, r, n, rflen, wp;
    acb_t zr;
    acb_ptr t, u, v;

    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        acb_digamma(res, h, prec);
        if (acb_is_finite(res))
            _acb_vec_zero(res + 1, len - 1);
        else
            _acb_vec_indeterminate(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_digamma_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 + 1);
    u = _acb_vec_init(len + 1);
    v = _acb_vec_init(len + 1);
    acb_init(zr);

    /* use Stirling series */
    acb_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 1, wp);

    /* psi(x) = psi((1-x)+r) - h(1-x,r) - pi*cot(pi*x) */
    if (reflect)
    {
        if (r != 0) /* otherwise t = 0 */
        {
            acb_sub_ui(v, h, 1, wp);
            acb_neg(v, v);
            acb_one(v + 1);
            rflen = FLINT_MIN(len + 1, r + 1);
            _acb_poly_rising_ui_series(u, v, 2, r, rflen, wp);
            _acb_poly_derivative(v, u, rflen, wp);
            _acb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp);
            for (i = 1; i < len; i += 2)
                acb_neg(t + i, t + i);
        }

        acb_sub_ui(zr, h, r + 1, wp);
        acb_neg(zr, zr);
        _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp);
        for (i = 1; i < len; i += 2)
            acb_neg(u + i, u + i);

        _acb_vec_sub(u, u, t, len, wp);

        acb_set(t, h);
        acb_one(t + 1);
        _acb_poly_cot_pi_series(t, t, 2, len, wp);
        acb_const_pi(v, wp);
        _acb_vec_scalar_mul(t, t, len, v, wp);

        _acb_vec_sub(u, u, t, len, wp);
    }
    else
    {
        if (r == 0)
        {
            acb_add_ui(zr, h, r, wp);
            _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp);
        }
        else
        {
            acb_set(v, h);
            acb_one(v + 1);
            rflen = FLINT_MIN(len + 1, r + 1);
            _acb_poly_rising_ui_series(u, v, 2, r, rflen, wp);
            _acb_poly_derivative(v, u, rflen, wp);
            _acb_poly_div_series(t, v, rflen - 1, u, rflen, len, wp);

            acb_add_ui(zr, h, r, wp);
            _acb_poly_gamma_stirling_eval2(u, zr, n, len + 1, 1, wp);

            _acb_vec_sub(u, u, t, len, wp);
        }
    }

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

    acb_clear(zr);
    _acb_vec_clear(t, len + 1);
    _acb_vec_clear(u, len + 1);
    _acb_vec_clear(v, len + 1);
}
Example #4
0
void
_acb_poly_lgamma_series(acb_ptr res, acb_srcptr h, slong hlen, slong len, slong prec)
{
    int reflect;
    slong i, r, n, wp;
    acb_t zr;
    acb_ptr t, u;

    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        acb_lgamma(res, h, prec);
        if (acb_is_finite(res))
            _acb_vec_zero(res + 1, len - 1);
        else
            _acb_vec_indeterminate(res + 1, len - 1);
        return;
    }

    if (len == 2)
    {
        acb_t v;
        acb_init(v);
        acb_set(v, h + 1);
        acb_digamma(res + 1, h, prec);
        acb_lgamma(res, h, prec);
        acb_mul(res + 1, res + 1, v, prec);
        acb_clear(v);
        return;
    }

    /* use real code for real input and output */
    if (_acb_vec_is_real(h, hlen) && arb_is_positive(acb_realref(h)))
    {
        arb_ptr tmp = _arb_vec_init(len);
        for (i = 0; i < hlen; i++)
            arb_set(tmp + i, acb_realref(h + i));
        _arb_poly_lgamma_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);
    acb_init(zr);

    /* use Stirling series */
    acb_gamma_stirling_choose_param(&reflect, &r, &n, h, 1, 0, wp);

    if (reflect)
    {
        /* log gamma(h+x) = log rf(1-(h+x), r) - log gamma(1-(h+x)+r) - log sin(pi (h+x)) + log(pi) */
        if (r != 0) /* otherwise t = 0 */
        {
            acb_sub_ui(u, h, 1, wp);
            acb_neg(u, u);
            _log_rising_ui_series(t, u, r, len, wp);
            for (i = 1; i < len; i += 2)
                acb_neg(t + i, t + i);
        }

        acb_sub_ui(u, h, 1, wp);
        acb_neg(u, u);
        acb_add_ui(zr, u, r, wp);
        _acb_poly_gamma_stirling_eval(u, zr, n, len, wp);
        for (i = 1; i < len; i += 2)
            acb_neg(u + i, u + i);

        _acb_vec_sub(t, t, u, len, wp);

        /* log(sin) is unstable with large imaginary parts;
           cot_pi is implemented in a numerically stable way */
        acb_set(u, h);
        acb_one(u + 1);
        _acb_poly_cot_pi_series(u, u, 2, len - 1, wp);
        _acb_poly_integral(u, u, len, wp);
        acb_const_pi(u, wp);
        _acb_vec_scalar_mul(u + 1, u + 1, len - 1, u, wp);
        acb_log_sin_pi(u, h, wp);

        _acb_vec_sub(u, t, u, len, wp);

        acb_const_pi(t, wp); /* todo: constant for log pi */
        acb_log(t, t, wp);
        acb_add(u, u, t, wp);
    }
    else
    {
        /* log gamma(x) = log gamma(x+r) - log rf(x,r) */

        acb_add_ui(zr, h, r, wp);
        _acb_poly_gamma_stirling_eval(u, zr, n, len, wp);

        if (r != 0)
        {
            _log_rising_ui_series(t, h, r, len, wp);
            _acb_vec_sub(u, u, t, len, wp);
        }
    }

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

    acb_clear(zr);
    _acb_vec_clear(t, len);
    _acb_vec_clear(u, len);
}
Example #5
0
int main()
{
    slong iter;
    flint_rand_t state;

    flint_printf("digamma....");
    fflush(stdout);

    flint_randinit(state);

    for (iter = 0; iter < 3000 * arb_test_multiplier(); iter++)
    {
        acb_t a, b, c;
        slong prec1, prec2;

        prec1 = 2 + n_randint(state, 1000);
        prec2 = prec1 + 30;

        acb_init(a);
        acb_init(b);
        acb_init(c);

        arb_randtest_precise(acb_realref(a), state, 1 + n_randint(state, 1000), 3);
        arb_randtest_precise(acb_imagref(a), state, 1 + n_randint(state, 1000), 3);

        acb_digamma(b, a, prec1);
        acb_digamma(c, a, prec2);

        if (!acb_overlaps(b, c))
        {
            flint_printf("FAIL: overlap\n\n");
            flint_printf("a = "); acb_print(a); flint_printf("\n\n");
            flint_printf("b = "); acb_print(b); flint_printf("\n\n");
            flint_printf("c = "); acb_print(c); flint_printf("\n\n");
            abort();
        }

        acb_set(c, a);
        acb_digamma(c, c, prec2);
        if (!acb_overlaps(b, c))
        {
            flint_printf("FAIL: aliasing\n\n");
            flint_printf("a = "); acb_print(a); flint_printf("\n\n");
            flint_printf("b = "); acb_print(b); flint_printf("\n\n");
            flint_printf("c = "); acb_print(c); flint_printf("\n\n");
            abort();
        }

        /* check digamma(z+1) = digamma(z) + 1/z */
        acb_inv(c, a, prec1);
        acb_add(b, b, c, prec1);
        acb_add_ui(c, a, 1, prec1);
        acb_digamma(c, c, prec1);

        if (!acb_overlaps(b, c))
        {
            flint_printf("FAIL: functional equation\n\n");
            flint_printf("a = "); acb_print(a); flint_printf("\n\n");
            flint_printf("b = "); acb_print(b); flint_printf("\n\n");
            flint_printf("c = "); acb_print(c); flint_printf("\n\n");
            abort();
        }

        acb_clear(a);
        acb_clear(b);
        acb_clear(c);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}