Exemple #1
0
void
acb_lgamma(acb_t y, const acb_t x, long prec)
{
    int reflect;
    long r, n, wp;
    acb_t t, u;

    wp = prec + FLINT_BIT_COUNT(prec);

    acb_gamma_stirling_choose_param(&reflect, &r, &n, x, 0, 0, wp);

    /* log(gamma(x)) = log(gamma(x+r)) - log(rf(x,r)) */
    acb_init(t);
    acb_init(u);

    acb_add_ui(t, x, r, wp);
    acb_gamma_stirling_eval(u, t, n, 0, wp);

    acb_rising_ui_rec(t, x, r, prec);
    acb_log(t, t, prec);

    _acb_log_rising_correct_branch(t, t, x, r, wp);

    acb_sub(y, u, t, prec);

    acb_clear(t);
    acb_clear(u);
}
Exemple #2
0
static void
_acb_gamma(acb_t y, const acb_t x, long prec, int inverse)
{
    int reflect;
    long r, n, wp;
    acb_t t, u, v;

    wp = prec + FLINT_BIT_COUNT(prec);

    acb_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 0, wp);

    acb_init(t);
    acb_init(u);
    acb_init(v);

    if (reflect)
    {
        /* gamma(x) = (rf(1-x, r) * pi) / (gamma(1-x+r) sin(pi x)) */
        acb_sub_ui(t, x, 1, wp);
        acb_neg(t, t);
        acb_rising_ui_rec(u, t, r, wp);
        arb_const_pi(acb_realref(v), wp);
        acb_mul_arb(u, u, acb_realref(v), wp);
        acb_add_ui(t, t, r, wp);
        acb_gamma_stirling_eval(v, t, n, 0, wp);
        acb_exp(v, v, wp);
        acb_sin_pi(t, x, wp);
        acb_mul(v, v, t, wp);
    }
    else
    {
        /* gamma(x) = gamma(x+r) / rf(x,r) */
        acb_add_ui(t, x, r, wp);
        acb_gamma_stirling_eval(u, t, n, 0, wp);
        acb_exp(u, u, prec);
        acb_rising_ui_rec(v, x, r, wp);
    }

    if (inverse)
        acb_div(y, v, u, prec);
    else
        acb_div(y, u, v, prec);

    acb_clear(t);
    acb_clear(u);
    acb_clear(v);
}
Exemple #3
0
void
acb_digamma(acb_t y, const acb_t x, long prec)
{
    int reflect;
    long r, n, wp;
    acb_t t, u, v;

    wp = prec + FLINT_BIT_COUNT(prec);

    acb_gamma_stirling_choose_param(&reflect, &r, &n, x, 1, 1, wp);

    acb_init(t);
    acb_init(u);
    acb_init(v);

    /* psi(x) = psi((1-x)+r) - h(1-x,r) - pi*cot(pi*x) */
    if (reflect)
    {
        acb_sub_ui(t, x, 1, wp);
        acb_neg(t, t);
        acb_cot_pi(v, x, wp);
        arb_const_pi(acb_realref(u), wp);
        acb_mul_arb(v, v, acb_realref(u), wp);
        acb_rising2_ui(y, u, t, r, wp);
        acb_div(u, u, y, wp);
        acb_add(v, v, u, wp);
        acb_add_ui(t, t, r, wp);
        acb_gamma_stirling_eval(u, t, n, 1, wp);
        acb_sub(y, u, v, wp);
    }
    else
    {
        acb_add_ui(t, x, r, wp);
        acb_gamma_stirling_eval(u, t, n, 1, wp);
        acb_rising2_ui(y, t, x, r, wp);
        acb_div(t, t, y, wp);
        acb_sub(y, u, t, prec);
    }

    acb_clear(t);
    acb_clear(u);
    acb_clear(v);
}
Exemple #4
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);
}
Exemple #5
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);
}
Exemple #6
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);
}