Beispiel #1
0
void
acb_hypgeom_u(acb_t res, const acb_t a, const acb_t b, const acb_t z, long prec)
{
    acb_t t;
    acb_init(t);

    acb_sub(t, a, b, prec);
    acb_add_ui(t, t, 1, prec);

    if ((acb_is_int(a) && arf_sgn(arb_midref(acb_realref(a))) <= 0) ||
        (acb_is_int(t) && arf_sgn(arb_midref(acb_realref(t))) <= 0) ||
        acb_hypgeom_u_use_asymp(z, prec))
    {
        acb_neg(t, a);
        acb_pow(t, z, t, prec);
        acb_hypgeom_u_asymp(res, a, b, z, -1, prec);
        acb_mul(res, res, t, prec);
    }
    else
    {
        acb_hypgeom_u_1f1(res, a, b, z, prec);
    }

    acb_clear(t);
}
Beispiel #2
0
void
acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, long prec)
{
    acb_struct b[2];
    acb_t w, c, t;

    if (acb_is_int(nu) && arb_is_negative(acb_realref(nu)))
    {
        acb_init(t);
        acb_neg(t, nu);

        acb_hypgeom_bessel_j_0f1(res, t, z, prec);

        acb_mul_2exp_si(t, t, -1);
        if (!acb_is_int(t))
            acb_neg(res, res);

        acb_clear(t);
        return;
    }

    acb_init(b + 0);
    acb_init(b + 1);
    acb_init(w);
    acb_init(c);
    acb_init(t);

    acb_add_ui(b + 0, nu, 1, prec);
    acb_one(b + 1);

    /* (z/2)^nu / gamma(nu+1) */
    acb_mul_2exp_si(c, z, -1);
    acb_pow(c, c, nu, prec);
    acb_rgamma(t, b + 0, prec);
    acb_mul(c, t, c, prec);

    /* -z^2/4 */
    acb_mul(w, z, z, prec);
    acb_mul_2exp_si(w, w, -2);
    acb_neg(w, w);

    acb_hypgeom_pfq_direct(t, NULL, 0, b, 2, w, -1, prec);

    acb_mul(res, t, c, prec);

    acb_clear(b + 0);
    acb_clear(b + 1);
    acb_clear(w);
    acb_clear(c);
    acb_clear(t);
}
Beispiel #3
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);
    }
}
Beispiel #4
0
void
acb_hypgeom_bessel_jy(acb_t res1, acb_t res2, const acb_t nu, const acb_t z, slong prec)
{
    acb_t jnu, t, u, v;

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

    acb_hypgeom_bessel_j(jnu, nu, z, prec);

    if (acb_is_int(nu))
    {
        int is_real = acb_is_real(nu) && acb_is_real(z)
            && arb_is_positive(acb_realref(z));

        acb_mul_onei(t, z);
        acb_hypgeom_bessel_k(t, nu, t, prec);
        acb_onei(u);
        acb_pow(u, u, nu, prec);
        acb_mul(t, t, u, prec);
        acb_const_pi(u, prec);
        acb_div(t, t, u, prec);
        acb_mul_2exp_si(t, t, 1);
        acb_neg(t, t);

        phase(v, acb_realref(z), acb_imagref(z));
        acb_mul(u, jnu, v, prec);
        acb_mul_onei(u, u);

        acb_sub(res2, t, u, prec);

        if (is_real)
            arb_zero(acb_imagref(res2));
    }
    else
    {
        acb_sin_cos_pi(t, u, nu, prec);
        acb_mul(v, jnu, u, prec);
        acb_neg(u, nu);
        acb_hypgeom_bessel_j(u, u, z, prec);
        acb_sub(v, v, u, prec);
        acb_div(res2, v, t, prec);
    }

    if (res1 != NULL)
        acb_set(res1, jnu);

    acb_clear(jnu);
    acb_clear(t);
    acb_clear(u);
    acb_clear(v);
}
Beispiel #5
0
void
acb_hurwitz_zeta(acb_t z, const acb_t s, const acb_t a, slong prec)
{
    if (acb_is_one(a) && acb_is_int(s) &&
        arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), FLINT_BITS - 1) < 0)
    {
        acb_zeta_si(z, arf_get_si(arb_midref(acb_realref(s)), ARF_RND_DOWN), prec);
        return;
    }

    _acb_poly_zeta_cpx_series(z, s, a, 0, 1, prec);
}
Beispiel #6
0
void
acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec)
{
    if (arf_sgn(arb_midref(acb_realref(z))) >= 0
        || (acb_is_int(a) && arb_is_nonpositive(acb_realref(a))))
    {
        _acb_hypgeom_m_1f1(res, a, b, z, regularized, prec, prec, 0);
    }
    else
    {
        _acb_hypgeom_m_1f1(res, a, b, z, regularized, prec, prec, 1);
    }
}
Beispiel #7
0
/* this can be improved */
static int
use_recurrence(const acb_t n, const acb_t m, slong prec)
{
    if (!acb_is_int(n) || !arb_is_nonnegative(acb_realref(n)))
        return 0;

    if (arf_cmpabs_ui(arb_midref(acb_realref(n)), prec) > 0)
        return 0;

    if (arf_cmpabs(arb_midref(acb_realref(n)), arb_midref(acb_realref(m))) >= 0)
        return 0;

    return 1;
}
Beispiel #8
0
/* this can be improved */
static int
use_recurrence(const acb_t n, const acb_t a, const acb_t b, slong prec)
{
    if (!acb_is_int(n) || !arb_is_nonnegative(acb_realref(n)))
        return 0;

    if (arf_cmpabs_ui(arb_midref(acb_realref(n)), prec) > 0)
        return 0;

    if (arb_is_nonnegative(acb_realref(a)) ||
        arf_get_d(arb_midref(acb_realref(a)), ARF_RND_DOWN) > -0.9)
        return 0;

    return 1;
}
Beispiel #9
0
static void
_acb_hypgeom_li_offset(acb_t res, const acb_t z, long prec)
{
    if (acb_is_int(z) && arf_cmp_2exp_si(arb_midref(acb_realref(z)), 1) == 0)
    {
        acb_zero(res);
    }
    else
    {
        arb_t t;
        arb_init(t);
        _acb_hypgeom_const_li2(t, prec);
        _acb_hypgeom_li(res, z, prec);
        arb_sub(acb_realref(res), acb_realref(res), t, prec);
        arb_clear(t);
    }
}
Beispiel #10
0
void
acb_rising(acb_t y, const acb_t x, const acb_t n, long prec)
{
    if (acb_is_int(n) && arf_sgn(arb_midref(acb_realref(n))) >= 0 &&
        arf_cmpabs_ui(arb_midref(acb_realref(n)), FLINT_MAX(prec, 100)) < 0)
    {
        acb_rising_ui_rec(y, x,
            arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), prec);
    }
    else
    {
        acb_t t;
        acb_init(t);
        acb_add(t, x, n, prec);
        acb_gamma(t, t, prec);
        acb_rgamma(y, x, prec);
        acb_mul(y, y, t, prec);
        acb_clear(t);
    }
}
Beispiel #11
0
void
acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, long prec)
{
    acb_t t;

    if (regularized)
    {
        acb_init(t);
        acb_rgamma(t, b, prec);
    }

    if (arf_sgn(arb_midref(acb_realref(z))) >= 0
        || (acb_is_int(a) && arb_is_nonpositive(acb_realref(a))))
    {
        _acb_hypgeom_m_1f1(res, a, b, z, prec);
    }
    else
    {
        /* Kummer's transformation */
        acb_t u, v;
        acb_init(u);
        acb_init(v);

        acb_sub(u, b, a, prec);
        acb_neg(v, z);

        _acb_hypgeom_m_1f1(u, u, b, v, prec);
        acb_exp(v, z, prec);
        acb_mul(res, u, v, prec);

        acb_clear(u);
        acb_clear(v);
    }

    if (regularized)
    {
        acb_mul(res, res, t, prec);
        acb_clear(t);
    }
}
Beispiel #12
0
void
acb_hypgeom_m_choose(int * asymp, int * kummer, slong * wp,
    const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec)
{
    double x, y, t, cancellation;
    double input_accuracy, direct_accuracy, asymp_accuracy;
    slong m = WORD_MAX;
    slong n = WORD_MAX;

    if (acb_is_int(a) &&
            arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 30) < 0)
    {
        m = arf_get_si(arb_midref(acb_realref(a)), ARF_RND_DOWN);
    }

    if (acb_is_int(b) &&
            arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0)
    {
        n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN);
    }

    *asymp = 0;
    *kummer = 0;
    *wp = prec;

    /* The 1F1 series terminates. */
    /* TODO: for large m, estimate extra precision here. */
    if (m <= 0 && m < n && m > -10 * prec && (n > 0 || !regularized))
    {
        *asymp = 0;
        return;
    }

    /* The 1F1 series terminates with the Kummer transform. */
    /* TODO: for large m, estimate extra precision here. */
    if (m >= 1 && n >= 1 && m < 0.1 * prec && n < 0.1 * prec && n <= m)
    {
        *asymp = 0;
        *kummer = 1;
        return;
    }

    input_accuracy = acb_rel_accuracy_bits(z);
    t = acb_rel_accuracy_bits(a);
    input_accuracy = FLINT_MIN(input_accuracy, t);
    t = acb_rel_accuracy_bits(b);
    input_accuracy = FLINT_MIN(input_accuracy, t);
    input_accuracy = FLINT_MAX(input_accuracy, 0.0);

    /* From here we ignore the values of a, b. Taking them into account is
       a possible future improvement... */

    /* Tiny |z|. */
    if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 2) < 0 &&
         arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 2) < 0))
    {
        *asymp = 0;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
        return;
    }

    /* Huge |z|. */
    if ((arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 64) > 0 ||
         arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 64) > 0))
    {
        *asymp = 1;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
        return;
    }

    x = arf_get_d(arb_midref(acb_realref(z)), ARF_RND_DOWN);
    y = arf_get_d(arb_midref(acb_imagref(z)), ARF_RND_DOWN);

    asymp_accuracy = sqrt(x * x + y * y) * 1.44269504088896 - 5.0;

    /* The Kummer transformation gives less cancellation with the 1F1 series. */
    if (x < 0.0)
    {
        *kummer = 1;
        x = -x;
    }

    if (asymp_accuracy >= prec)
    {
        *asymp = 1;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
        return;
    }

    cancellation = hypotmx(x, y) * 1.44269504088896;

    direct_accuracy = input_accuracy - cancellation;

    if (direct_accuracy > asymp_accuracy)
    {
        *asymp = 0;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec + cancellation));
    }
    else
    {
        *asymp = 1;
        *wp = FLINT_MAX(2, FLINT_MIN(input_accuracy + 20, prec));
    }
}
Beispiel #13
0
void
acb_hypgeom_u_1f1_series(acb_poly_t res,
    const acb_poly_t a, const acb_poly_t b, const acb_poly_t z,
    long len, long prec)
{
    acb_poly_t s, u, A, B;
    acb_poly_struct aa[3];
    arb_t c;
    long wlen;
    int singular;

    acb_poly_init(s);
    acb_poly_init(u);
    acb_poly_init(A);
    acb_poly_init(B);
    acb_poly_init(aa + 0);
    acb_poly_init(aa + 1);
    acb_poly_init(aa + 2);
    arb_init(c);

    singular = (b->length == 0) || acb_is_int(b->coeffs);
    wlen = len + (singular != 0);

    /* A = rgamma(a-b+1) * 1F~1(a,b,z) */
    acb_poly_sub(u, a, b, prec);
    acb_poly_add_si(u, u, 1, prec);
    acb_poly_rgamma_series(A, u, wlen, prec);

    /* todo: handle a = 1 efficiently */
    acb_poly_set(aa, a);
    acb_poly_set(aa + 1, b);
    acb_poly_one(aa + 2);
    acb_hypgeom_pfq_series_direct(s, aa, 1, aa + 1, 2, z, 1, -1, wlen, prec);
    acb_poly_mullow(A, A, s, wlen, prec);

    /* B = rgamma(a) * 1F~1(a-b+1,2-b,z) * z^(1-b) */
    acb_poly_set(aa, u);
    acb_poly_add_si(aa + 1, b, -2, prec);
    acb_poly_neg(aa + 1, aa + 1);
    acb_hypgeom_pfq_series_direct(s, aa, 1, aa + 1, 2, z, 1, -1, wlen, prec);
    acb_poly_rgamma_series(B, a, wlen, prec);
    acb_poly_mullow(B, B, s, wlen, prec);

    acb_poly_add_si(u, b, -1, prec);
    acb_poly_neg(u, u);
    acb_poly_pow_series(s, z, u, wlen, prec);
    acb_poly_mullow(B, B, s, wlen, prec);

    acb_poly_sub(A, A, B, prec);

    /* multiply by pi csc(pi b) */
    acb_poly_sin_pi_series(B, b, wlen, prec);

    if (singular)
    {
        acb_poly_shift_right(A, A, 1);
        acb_poly_shift_right(B, B, 1);
    }

    acb_poly_div_series(res, A, B, len, prec);

    arb_const_pi(c, prec);
    _acb_vec_scalar_mul_arb(res->coeffs, res->coeffs, res->length, c, prec);

    acb_poly_clear(s);
    acb_poly_clear(u);
    acb_poly_clear(A);
    acb_poly_clear(B);
    acb_poly_clear(aa + 0);
    acb_poly_clear(aa + 1);
    acb_poly_clear(aa + 2);
    arb_clear(c);
}
Beispiel #14
0
void
acb_hypgeom_bessel_i_asymp(acb_t res, const acb_t nu, const acb_t z, long prec)
{
    acb_t A1, A2, C, U1, U2, s, t, u;
    int is_real, is_imag;

    acb_init(A1);
    acb_init(A2);
    acb_init(C);
    acb_init(U1);
    acb_init(U2);
    acb_init(s);
    acb_init(t);
    acb_init(u);

    is_imag = 0;
    is_real = acb_is_real(nu) && acb_is_real(z)
        && (acb_is_int(nu) || arb_is_positive(acb_realref(z)));

    if (!is_real && arb_is_zero(acb_realref(z)) && acb_is_int(nu))
    {
        acb_mul_2exp_si(t, nu, -1);

        if (acb_is_int(t))
            is_real = 1;
        else
            is_imag = 1;
    }

    acb_hypgeom_bessel_i_asymp_prefactors(A1, A2, C, nu, z, prec);

    /* todo: if Ap ~ 2^a and Am = 2^b and U1 ~ U2 ~ 1, change precision? */

    if (!acb_is_finite(A1) || !acb_is_finite(A2) || !acb_is_finite(C))
    {
        acb_indeterminate(res);
    }
    else
    {
        /* s = 1/2 + nu */
        acb_one(s);
        acb_mul_2exp_si(s, s, -1);
        acb_add(s, s, nu, prec);

        /* t = 1 + 2 nu */
        acb_mul_2exp_si(t, nu, 1);
        acb_add_ui(t, t, 1, prec);

        acb_mul_2exp_si(u, z, 1);
        acb_hypgeom_u_asymp(U1, s, t, u, -1, prec);
        acb_neg(u, u);
        acb_hypgeom_u_asymp(U2, s, t, u, -1, prec);

        acb_mul(res, A1, U1, prec);
        acb_addmul(res, A2, U2, prec);
        acb_mul(res, res, C, prec);

        if (is_real)
            arb_zero(acb_imagref(res));
        if (is_imag)
            arb_zero(acb_realref(res));
    }

    acb_clear(A1);
    acb_clear(A2);
    acb_clear(C);
    acb_clear(U1);
    acb_clear(U2);
    acb_clear(s);
    acb_clear(t);
    acb_clear(u);
}
Beispiel #15
0
void
acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, long prec)
{
    long m = LONG_MAX;
    long n = LONG_MAX;

    if (acb_is_int(a) &&
            arf_cmpabs_2exp_si(arb_midref(acb_realref(a)), 30) < 0)
    {
        m = arf_get_si(arb_midref(acb_realref(a)), ARF_RND_DOWN);
    }

    if (acb_is_int(b) &&
            arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0)
    {
        n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN);
    }

    /* terminating */
    if (m <= 0 && m < n && m > -10 * prec && (n > 0 || !regularized))
    {
        acb_hypgeom_m_1f1(res, a, b, z, regularized, prec);
        return;
    }

    /* large */
    if (acb_hypgeom_u_use_asymp(z, prec))
    {
        acb_hypgeom_m_asymp(res, a, b, z, regularized, prec);
        return;
    }

    /* remove singularity */
    if (n <= 0 && n > -10 * prec && regularized)
    {
        acb_t c, d, t, u;

        acb_init(c);
        acb_init(d);
        acb_init(t);
        acb_init(u);

        acb_sub(c, a, b, prec);
        acb_add_ui(c, c, 1, prec);

        acb_neg(d, b);
        acb_add_ui(d, d, 2, prec);

        acb_hypgeom_m_1f1(t, c, d, z, 0, prec);

        acb_pow_ui(u, z, 1 - n, prec);
        acb_mul(t, t, u, prec);

        acb_rising_ui(u, a, 1 - n, prec);
        acb_mul(t, t, u, prec);

        arb_fac_ui(acb_realref(u), 1 - n, prec);
        acb_div_arb(res, t, acb_realref(u), prec);

        acb_clear(c);
        acb_clear(d);
        acb_clear(t);
        acb_clear(u);
    }
    else
    {
        acb_hypgeom_m_1f1(res, a, b, z, regularized, prec);
    }
}
Beispiel #16
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);
}
Beispiel #17
0
int main()
{
    slong iter;
    flint_rand_t state;

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

    flint_randinit(state);

    for (iter = 0; iter < 2000 * arb_test_multiplier(); iter++)
    {
        acb_t a0, a1, b, z, w0, w1, t, u, enz;
        slong prec0, prec1;
        int regularized;

        acb_init(a0);
        acb_init(a1);
        acb_init(b);
        acb_init(z);
        acb_init(w0);
        acb_init(w1);
        acb_init(t);
        acb_init(u);
        acb_init(enz);

        regularized = n_randint(state, 3);

        prec0 = 2 + n_randint(state, 1000);
        prec1 = 2 + n_randint(state, 1000);

        acb_randtest_param(a0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));
        acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));
        acb_randtest(w0, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));
        acb_randtest(w1, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));

        acb_add_ui(a1, a0, 1, prec0);

        acb_hypgeom_gamma_lower(w0, a0, z, regularized, prec0);
        acb_hypgeom_gamma_lower(w1, a1, z, regularized, prec1);

        acb_neg(enz, z);
        acb_exp(enz, enz, prec0);

        /* recurrence relations */
        if (regularized == 2)
        {
            /* gamma^{*}(a,z) - exp(-z)/Gamma(a+1) - z gamma^{*}(a+1,z) = 0 */
            /* http://dlmf.nist.gov/8.8.E4 */
            acb_set(t, w0);
            acb_rgamma(u, a1, prec0);
            acb_submul(t, enz, u, prec0);
            acb_submul(t, z, w1, prec0);
        }
        else if (regularized == 1)
        {
            /* P(a,z) - exp(-z) z^a / Gamma(a+1) - P(a+1,z) = 0 */
            /* http://dlmf.nist.gov/8.8.E5 */
            acb_pow(u, z, a0, prec0);
            acb_rgamma(b, a1, prec0);
            acb_mul(u, u, b, prec0);
            acb_sub(t, w0, w1, prec0);
            acb_submul(t, enz, u, prec0);
        }
        else
        {
            /* a gamma(a,z) - exp(-z) z^a - gamma(a+1,z) = 0 */
            /* http://dlmf.nist.gov/8.8.E1 */
            acb_pow(u, z, a0, prec0);
            acb_mul(t, a0, w0, prec0);
            acb_submul(t, enz, u, prec0);
            acb_sub(t, t, w1, prec0);
        }

        if (!acb_contains_zero(t))
        {
            flint_printf("FAIL: recurrence relation\n\n");
            flint_printf("regularized = %d\n\n", regularized);
            flint_printf("a0 = "); acb_printd(a0, 30); flint_printf("\n\n");
            flint_printf("z = ");  acb_printd(z, 30); flint_printf("\n\n");
            flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n");
            flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n");
            flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n");
            abort();
        }

        /* identities relating lower and upper incomplete gamma functions */
        if (regularized == 0 || regularized == 1)
        {
            acb_t u0;
            acb_init(u0);
            acb_hypgeom_gamma_upper(u0, a0, z, regularized, prec0);

            acb_zero(t);

            if (regularized == 1)
            {
                /* P(s,z) + Q(s,z) - 1 = 0 */
                /* http://dlmf.nist.gov/8.2.E5 */
                acb_add(t, w0, u0, prec0);
                acb_sub_ui(t, t, 1, prec0);
            }
            else
            {
                /* gamma(s,z) + Gamma(s,z) - Gamma(s) = 0 */
                /* excludes non-positive integer values of s */
                /* http://dlmf.nist.gov/8.2.E3 */
                if (!acb_is_int(a0) || arb_is_positive(acb_realref(a0)))
                {
                    acb_gamma(b, a0, prec0);
                    acb_add(t, w0, u0, prec0);
                    acb_sub(t, t, b, prec0);
                }
            }

            if (!acb_contains_zero(t))
            {
                flint_printf("FAIL: lower plus upper\n\n");
                flint_printf("regularized = %d\n\n", regularized);
                flint_printf("a0 = "); acb_printd(a0, 30); flint_printf("\n\n");
                flint_printf("z = ");  acb_printd(z, 30); flint_printf("\n\n");
                flint_printf("w0 = "); acb_printd(w0, 30); flint_printf("\n\n");
                flint_printf("w1 = "); acb_printd(w1, 30); flint_printf("\n\n");
                flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n");
                abort();
            }

            acb_clear(u0);
        }

        acb_clear(a0);
        acb_clear(a1);
        acb_clear(b);
        acb_clear(z);
        acb_clear(w0);
        acb_clear(w1);
        acb_clear(t);
        acb_clear(u);
        acb_clear(enz);
    }

    flint_randclear(state);
    flint_cleanup();
    flint_printf("PASS\n");
    return EXIT_SUCCESS;
}
Beispiel #18
0
void
acb_hypgeom_bessel_k_0f1_series(acb_poly_t res,
    const acb_poly_t nu, const acb_poly_t z,
    slong len, slong prec)
{
    acb_poly_t s, u, A, B;
    acb_poly_struct b[2];
    arb_t c;
    slong wlen;
    int singular;

    acb_poly_init(s);
    acb_poly_init(u);
    acb_poly_init(A);
    acb_poly_init(B);
    acb_poly_init(b + 0);
    acb_poly_init(b + 1);
    arb_init(c);

    singular = (nu->length == 0) || acb_is_int(nu->coeffs);
    wlen = len + (singular != 0);

    /* A = (z/2)^nu, B = 1/A */
    acb_poly_scalar_mul_2exp_si(A, z, -1);
    acb_poly_pow_series(A, A, nu, wlen, prec);
    acb_poly_inv_series(B, A, wlen, prec);

    acb_poly_mullow(u, z, z, wlen, prec);
    acb_poly_scalar_mul_2exp_si(u, u, -2);

    acb_poly_one(b + 1);
    acb_poly_add_si(b + 0, nu, 1, prec);
    acb_hypgeom_pfq_series_direct(s, NULL, 0, b, 2, u, 1, -1, wlen, prec);
    acb_poly_mullow(A, A, s, wlen, prec);

    acb_poly_add_si(b + 0, nu, -1, prec);
    acb_poly_neg(b + 0, b + 0);
    acb_hypgeom_pfq_series_direct(s, NULL, 0, b, 2, u, 1, -1, wlen, prec);
    acb_poly_mullow(B, B, s, wlen, prec);

    acb_poly_sub(A, B, A, prec);
    acb_poly_scalar_mul_2exp_si(A, A, -1);

    /* multiply by pi csc(pi nu) */
    acb_poly_sin_pi_series(B, nu, wlen, prec);

    if (singular)
    {
        acb_poly_shift_right(A, A, 1);
        acb_poly_shift_right(B, B, 1);
    }

    acb_poly_div_series(res, A, B, len, prec);

    arb_const_pi(c, prec);
    _acb_vec_scalar_mul_arb(res->coeffs, res->coeffs, res->length, c, prec);

    acb_poly_clear(s);
    acb_poly_clear(u);
    acb_poly_clear(A);
    acb_poly_clear(B);
    acb_poly_clear(b + 0);
    acb_poly_clear(b + 1);
    arb_clear(c);
}
Beispiel #19
0
void
acb_hypgeom_chebyshev_t(acb_t res, const acb_t n, const acb_t z, slong prec)
{
    acb_t t;

    if (acb_is_int(n) && 
        arf_cmpabs_2exp_si(arb_midref(acb_realref(n)), FLINT_BITS - 1) < 0)
    {
        slong k = arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN);
        acb_chebyshev_t_ui(res, FLINT_ABS(k), z, prec);
        return;
    }

    if (acb_is_zero(z))
    {
        acb_mul_2exp_si(res, n, -1);
        acb_cos_pi(res, res, prec);
        return;
    }

    if (acb_is_one(z))
    {
        acb_one(res);
        return;
    }

    acb_init(t);
    acb_set_si(t, -1);

    if (acb_equal(t, z))
    {
        acb_cos_pi(res, n, prec);
    }
    else
    {
        acb_sub_ui(t, z, 1, prec);

        if (arf_cmpabs_2exp_si(arb_midref(acb_realref(t)), -2 - prec / 10) < 0 &&
            arf_cmpabs_2exp_si(arb_midref(acb_imagref(t)), -2 - prec / 10) < 0)
        {
            acb_t a, c;

            acb_init(a);
            acb_init(c);

            acb_neg(a, n);
            acb_one(c);
            acb_mul_2exp_si(c, c, -1);
            acb_neg(t, t);
            acb_mul_2exp_si(t, t, -1);
            acb_hypgeom_2f1(res, a, n, c, t, 0, prec);

            acb_clear(a);
            acb_clear(c);
        }
        else if (arb_is_nonnegative(acb_realref(t)))
        {
            acb_acosh(t, z, prec);
            acb_mul(t, t, n, prec);
            acb_cosh(res, t, prec);
        }
        else
        {
            acb_acos(t, z, prec);
            acb_mul(t, t, n, prec);
            acb_cos(res, t, prec);
        }
    }

    acb_clear(t);
}
Beispiel #20
0
void
acb_hypgeom_u_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, long prec)
{
    if (acb_is_int(b))
    {
        acb_poly_t aa, bb, zz;

        acb_poly_init(aa);
        acb_poly_init(bb);
        acb_poly_init(zz);

        acb_poly_set_acb(aa, a);
        acb_poly_set_coeff_acb(bb, 0, b);
        acb_poly_set_coeff_si(bb, 1, 1);
        acb_poly_set_acb(zz, z);

        acb_hypgeom_u_1f1_series(zz, aa, bb, zz, 1, prec);
        acb_poly_get_coeff_acb(res, zz, 0);

        acb_poly_clear(aa);
        acb_poly_clear(bb);
        acb_poly_clear(zz);
    }
    else
    {
        acb_t t, u, v;
        acb_struct aa[3];

        acb_init(t);
        acb_init(u);
        acb_init(v);
        acb_init(aa + 0);
        acb_init(aa + 1);
        acb_init(aa + 2);

        acb_set(aa, a);
        acb_set(aa + 1, b);
        acb_one(aa + 2);
        acb_hypgeom_pfq_direct(u, aa, 1, aa + 1, 2, z, -1, prec);
        acb_sub(aa, a, b, prec);
        acb_add_ui(aa, aa, 1, prec);
        acb_sub_ui(aa + 1, b, 2, prec);
        acb_neg(aa + 1, aa + 1);
        acb_hypgeom_pfq_direct(v, aa, 1, aa + 1, 2, z, -1, prec);

        acb_sub_ui(aa + 1, b, 1, prec);

        /* rgamma(a-b+1) * gamma(1-b) * u */
        acb_rgamma(t, aa, prec);
        acb_mul(u, u, t, prec);
        acb_neg(t, aa + 1);
        acb_gamma(t, t, prec);
        acb_mul(u, u, t, prec);

        /* rgamma(a) * gamma(b-1) * z^(1-b) * v */
        acb_rgamma(t, a, prec);
        acb_mul(v, v, t, prec);
        acb_gamma(t, aa + 1, prec);
        acb_mul(v, v, t, prec);
        acb_neg(t, aa + 1);
        acb_pow(t, z, t, prec);
        acb_mul(v, v, t, prec);

        acb_add(res, u, v, prec);

        acb_clear(t);
        acb_clear(u);
        acb_clear(v);
        acb_clear(aa + 0);
        acb_clear(aa + 1);
        acb_clear(aa + 2);
    }
}
Beispiel #21
0
void
acb_hypgeom_2f1(acb_t res, const acb_t a, const acb_t b,
        const acb_t c, const acb_t z, int flags, slong prec)
{
    int algorithm, regularized;

    regularized = flags & ACB_HYPGEOM_2F1_REGULARIZED;

    if (!acb_is_finite(a) || !acb_is_finite(b) || !acb_is_finite(c) || !acb_is_finite(z))
    {
        acb_indeterminate(res);
        return;
    }

    if (acb_is_zero(z))
    {
        if (regularized)
            acb_rgamma(res, c, prec);
        else
            acb_one(res);
        return;
    }

    if (regularized && acb_is_int(c) && arb_is_nonpositive(acb_realref(c)))
    {
        if ((acb_is_int(a) && arb_is_nonpositive(acb_realref(a)) &&
            arf_cmp(arb_midref(acb_realref(a)), arb_midref(acb_realref(c))) >= 0) ||
            (acb_is_int(b) && arb_is_nonpositive(acb_realref(b)) &&
            arf_cmp(arb_midref(acb_realref(b)), arb_midref(acb_realref(c))) >= 0))
        {
            acb_zero(res);
            return;
        }
    }

    if (regularized && acb_eq(a, c))
    {
        _acb_hypgeom_2f1r_reduced(res, b, c, z, prec);
        return;
    }

    if (regularized && acb_eq(b, c))
    {
        _acb_hypgeom_2f1r_reduced(res, a, c, z, prec);
        return;
    }

    /* polynomial */
    if (acb_is_int(a) && arf_sgn(arb_midref(acb_realref(a))) <= 0 &&
         arf_cmpabs_ui(arb_midref(acb_realref(a)), prec) < 0)
    {
        acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec);
        return;
    }

    /* polynomial */
    if (acb_is_int(b) && arf_sgn(arb_midref(acb_realref(b))) <= 0 &&
         arf_cmpabs_ui(arb_midref(acb_realref(b)), prec) < 0)
    {
        acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec);
        return;
    }

    /* Try to reduce to a polynomial case using the Pfaff transformation */
    /* TODO: look at flags for integer c-b, c-a here, even when c is nonexact */
    if (acb_is_exact(c))
    {
        acb_t t;
        acb_init(t);

        acb_sub(t, c, b, prec);

        if (acb_is_int(t) && arb_is_nonpositive(acb_realref(t)))
        {
            acb_hypgeom_2f1_transform(res, a, b, c, z, flags, 1, prec);
            acb_clear(t);
            return;
        }

        acb_sub(t, c, a, prec);

        if (acb_is_int(t) && arb_is_nonpositive(acb_realref(t)))
        {
            int f1, f2;

            /* When swapping a, b, also swap the flags. */
            f1 = flags & ACB_HYPGEOM_2F1_AC;
            f2 = flags & ACB_HYPGEOM_2F1_BC;

            flags &= ~ACB_HYPGEOM_2F1_AC;
            flags &= ~ACB_HYPGEOM_2F1_BC;

            if (f1) flags |= ACB_HYPGEOM_2F1_BC;
            if (f2) flags |= ACB_HYPGEOM_2F1_AC;

            acb_hypgeom_2f1_transform(res, b, a, c, z, flags, 1, prec);
            acb_clear(t);
            return;
        }

        acb_clear(t);
    }

    /* special value at z = 1 */
    if (acb_is_one(z))
    {
        acb_t t, u, v;

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

        acb_sub(t, c, a, prec);
        acb_sub(u, c, b, prec);
        acb_sub(v, t, b, prec);

        if (arb_is_positive(acb_realref(v)))
        {
            acb_rgamma(t, t, prec);
            acb_rgamma(u, u, prec);
            acb_mul(t, t, u, prec);
            acb_gamma(v, v, prec);
            acb_mul(t, t, v, prec);

            if (!regularized)
            {
                acb_gamma(v, c, prec);
                acb_mul(t, t, v, prec);
            }

            acb_set(res, t);
        }
        else
        {
            acb_indeterminate(res);
        }

        acb_clear(t);
        acb_clear(u);
        acb_clear(v);

        return;
    }

    algorithm = acb_hypgeom_2f1_choose(z);

    if (algorithm == 0)
    {
        acb_hypgeom_2f1_direct(res, a, b, c, z, regularized, prec);
    }
    else if (algorithm >= 1 && algorithm <= 5)
    {
        acb_hypgeom_2f1_transform(res, a, b, c, z, flags, algorithm, prec);
    }
    else
    {
        acb_hypgeom_2f1_corner(res, a, b, c, z, regularized, prec);
    }
}
Beispiel #22
0
void
_acb_hypgeom_legendre_q_double(acb_t res, const acb_t n, const acb_t m,
    const acb_t z, slong prec)
{
    acb_t t, u, v;

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

    if (acb_is_int(m))
    {
        acb_sub_ui(t, z, 1, prec);
        acb_mul_2exp_si(u, m, -1);
        acb_pow(v, t, u, prec);
        acb_neg(t, t);
        acb_neg(u, u);
        acb_pow(t, t, u, prec);
        acb_mul(t, t, v, prec);

        acb_hypgeom_legendre_q(u, n, m, z, 0, prec);
        acb_mul(t, t, u, prec);

        acb_mul_2exp_si(u, m, -1);
        if (!acb_is_int(u))
            acb_neg(t, t);

        acb_sub_ui(u, z, 1, prec);
        acb_sqrt(u, u, prec);
        acb_sub_ui(v, z, 1, prec);
        acb_neg(v, v);
        acb_rsqrt(v, v, prec);
        acb_mul(u, u, v, prec);
        acb_hypgeom_legendre_p(v, n, m, z, 1, prec);
        acb_mul(u, u, v, prec);
        acb_const_pi(v, prec);
        acb_mul(u, u, v, prec);
        acb_mul_2exp_si(u, u, -1);

        acb_sub(res, t, u, prec);
    }
    else
    {
        acb_sub(t, n, m, prec);
        acb_add_ui(t, t, 1, prec);
        acb_mul_2exp_si(u, m, 1);
        acb_rising(t, t, u, prec);
        acb_neg(u, m);
        acb_hypgeom_legendre_p(u, n, u, z, 1, prec);
        acb_mul(t, t, u, prec);

        acb_hypgeom_legendre_p(u, n, m, z, 1, prec);
        acb_sub(t, u, t, prec);

        acb_exp_pi_i(u, m, prec);
        acb_mul(t, t, u, prec);

        acb_sin_pi(u, m, prec);
        acb_div(t, t, u, prec);
        acb_const_pi(u, prec);
        acb_mul(t, t, u, prec);
        acb_mul_2exp_si(t, t, -1);

        acb_set(res, t);
    }

    acb_clear(t);
    acb_clear(u);
    acb_clear(v);
}
Beispiel #23
0
static int
acb_is_nonpositive_int(const acb_t x)
{
    return acb_is_int(x) && arf_sgn(arb_midref(acb_realref(x))) <= 0;
}
Beispiel #24
0
void
acb_hypgeom_2f1_transform(acb_t res, const acb_t a, const acb_t b,
    const acb_t c, const acb_t z, int flags, int which, slong prec)
{
    int regularized;

    regularized = flags & ACB_HYPGEOM_2F1_REGULARIZED;

    if (which == 1)
    {
        acb_t t, u, v;

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

        acb_sub_ui(t, z, 1, prec); /* t = z-1 */
        acb_div(u, z, t, prec); /* u = z/(z-1) */
        acb_neg(t, t);
        acb_neg(v, a);
        acb_pow(t, t, v, prec); /* t = (1-z)^-a */
        acb_sub(v, c, b, prec); /* v = c-b */

        /* We cannot use regularized=1 directly, since if c is a nonnegative
           integer, the transformation formula reads (lhs) * 0 = (rhs) * 0. */
        acb_hypgeom_2f1_direct(u, a, v, c, u, 1, prec);

        if (!regularized)
        {
            acb_gamma(v, c, prec);
            acb_mul(u, u, v, prec);
        }

        acb_mul(res, u, t, prec);


        acb_clear(t);
        acb_clear(u);
        acb_clear(v);
    }
    else
    {
        acb_t d;
        int limit;

        acb_init(d);

        if (which == 2 || which == 3)
        {
            if (flags & ACB_HYPGEOM_2F1_AB)
            {
                limit = 1;
            }
            else
            {
                acb_sub(d, b, a, prec);
                limit = acb_is_int(d);
            }
        }
        else
        {
            if (flags & ACB_HYPGEOM_2F1_ABC)
            {
                limit = 1;
            }
            else
            {
                acb_sub(d, c, a, prec);
                acb_sub(d, d, b, prec);
                limit = acb_is_int(d);
            }
        }

        if (limit)
            acb_hypgeom_2f1_transform_limit(res, a, b, c, z, regularized, which, prec);
        else
            acb_hypgeom_2f1_transform_nolimit(res, a, b, c, z, regularized, which, prec);

        acb_clear(d);
    }

    if (!acb_is_finite(res))
        acb_indeterminate(res);
}
Beispiel #25
0
void
acb_hypgeom_bessel_k_0f1(acb_t res, const acb_t nu, const acb_t z, slong prec)
{
    if (acb_is_int(nu))
    {
        acb_poly_t nux, zx, rx;

        acb_poly_init(nux);
        acb_poly_init(zx);
        acb_poly_init(rx);

        acb_poly_set_coeff_acb(nux, 0, nu);
        acb_poly_set_coeff_si(nux, 1, 1);
        acb_poly_set_acb(zx, z);

        acb_hypgeom_bessel_k_0f1_series(rx, nux, zx, 1, prec);

        acb_poly_get_coeff_acb(res, rx, 0);

        acb_poly_clear(nux);
        acb_poly_clear(zx);
        acb_poly_clear(rx);
    }
    else
    {
        acb_t t, u, v, w;
        acb_struct b[2];

        acb_init(t);
        acb_init(u);
        acb_init(v);
        acb_init(w);
        acb_init(b + 0);
        acb_init(b + 1);

        /* u = 0F1(1+nu), v = 0F1(1-nu) */
        acb_mul(t, z, z, prec);
        acb_mul_2exp_si(t, t, -2);
        acb_add_ui(b, nu, 1, prec);
        acb_one(b + 1);
        acb_hypgeom_pfq_direct(u, NULL, 0, b, 2, t, -1, prec);
        acb_sub_ui(b, nu, 1, prec);
        acb_neg(b, b);
        acb_hypgeom_pfq_direct(v, NULL, 0, b, 2, t, -1, prec);

        /* v = v * gamma(nu) / (z/2)^nu */
        acb_mul_2exp_si(t, z, -1);
        acb_pow(t, t, nu, prec);
        acb_gamma(w, nu, prec);
        acb_mul(v, v, w, prec);
        acb_div(v, v, t, prec);

        /* u = u * t * pi / (gamma(nu) * nu * sin(pi nu)) */
        acb_mul(u, u, t, prec);
        acb_const_pi(t, prec);
        acb_mul(u, u, t, prec);
        acb_sin_pi(t, nu, prec);
        acb_mul(t, t, w, prec);
        acb_mul(t, t, nu, prec);
        acb_div(u, u, t, prec);

        acb_sub(res, v, u, prec);
        acb_mul_2exp_si(res, res, -1);

        acb_clear(t);
        acb_clear(u);
        acb_clear(v);
        acb_clear(w);
        acb_clear(b + 0);
        acb_clear(b + 1);
    }
}
Beispiel #26
0
void
_acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z,
    int regularized, slong prec, slong gamma_prec, int kummer)
{
    if (regularized)
    {
        /* Remove singularity */
        if (acb_is_int(b) && arb_is_nonpositive(acb_realref(b)) &&
            arf_cmpabs_2exp_si(arb_midref(acb_realref(b)), 30) < 0)
        {
            acb_t c, d, t, u;
            slong n;

            n = arf_get_si(arb_midref(acb_realref(b)), ARF_RND_DOWN);

            acb_init(c);
            acb_init(d);
            acb_init(t);
            acb_init(u);

            acb_sub(c, a, b, prec);
            acb_add_ui(c, c, 1, prec);

            acb_neg(d, b);
            acb_add_ui(d, d, 2, prec);

            _acb_hypgeom_m_1f1(t, c, d, z, 0, prec, gamma_prec, kummer);

            acb_pow_ui(u, z, 1 - n, prec);
            acb_mul(t, t, u, prec);

            acb_rising_ui(u, a, 1 - n, prec);
            acb_mul(t, t, u, prec);

            arb_fac_ui(acb_realref(u), 1 - n, prec);
            acb_div_arb(res, t, acb_realref(u), prec);

            acb_clear(c);
            acb_clear(d);
            acb_clear(t);
            acb_clear(u);
        }
        else
        {
            acb_t t;
            acb_init(t);
            acb_rgamma(t, b, gamma_prec);
            _acb_hypgeom_m_1f1(res, a, b, z, 0, prec, gamma_prec, kummer);
            acb_mul(res, res, t, prec);
            acb_clear(t);
        }
        return;
    }

    /* Kummer's transformation */
    if (kummer)
    {
        acb_t u, v;
        acb_init(u);
        acb_init(v);

        acb_sub(u, b, a, prec);
        acb_neg(v, z);

        _acb_hypgeom_m_1f1(u, u, b, v, regularized, prec, gamma_prec, 0);
        acb_exp(v, z, prec);
        acb_mul(res, u, v, prec);

        acb_clear(u);
        acb_clear(v);
        return;
    }

    if (acb_is_one(a))
    {
        acb_hypgeom_pfq_direct(res, NULL, 0, b, 1, z, -1, prec);
    }
    else
    {
        acb_struct c[3];
        c[0] = *a;
        c[1] = *b;

        acb_init(c + 2);
        acb_one(c + 2);

        acb_hypgeom_pfq_direct(res, c, 1, c + 1, 2, z, -1, prec);

        acb_clear(c + 2);
    }
}
Beispiel #27
0
/* todo: use euler product for complex s, and check efficiency
   for large negative integers */
void
acb_dirichlet_zeta(acb_t res, const acb_t s, slong prec)
{
    acb_t a;
    double cutoff;

    if (acb_is_int(s) &&
        arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), FLINT_BITS - 1) < 0)
    {
        acb_zeta_si(res, arf_get_si(arb_midref(acb_realref(s)), ARF_RND_DOWN), prec);
        return;
    }

    cutoff = 24.0 * prec * sqrt(prec);

    if (arf_cmpabs_d(arb_midref(acb_imagref(s)), cutoff) >= 0 &&
        arf_cmpabs_d(arb_midref(acb_realref(s)), 10 + prec * 0.1) <= 0)
    {
        acb_dirichlet_zeta_rs(res, s, 0, prec);
        return;
    }

    acb_init(a);
    acb_one(a);

    if (arf_sgn(arb_midref(acb_realref(s))) < 0)
    {
        acb_t t, u, v;
        slong wp = prec + 6;

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

        acb_sub_ui(t, s, 1, wp);

        /* 2 * (2pi)^(s-1) */
        arb_const_pi(acb_realref(u), wp);
        acb_mul_2exp_si(u, u, 1);
        acb_pow(u, u, t, wp);
        acb_mul_2exp_si(u, u, 1);

        /* sin(pi*s/2) */
        acb_mul_2exp_si(v, s, -1);
        acb_sin_pi(v, v, wp);
        acb_mul(u, u, v, wp);

        /* gamma(1-s) zeta(1-s) */
        acb_neg(t, t);
        acb_gamma(v, t, wp);
        acb_mul(u, u, v, wp);
        acb_hurwitz_zeta(v, t, a, wp);
        acb_mul(res, u, v, prec);

        acb_clear(t);
        acb_clear(u);
        acb_clear(v);
    }
    else
    {
        acb_hurwitz_zeta(res, s, a, prec);
    }

    acb_clear(a);
}
Beispiel #28
0
void
acb_hypgeom_pfq_series_direct(acb_poly_t res,
    const acb_poly_struct * a, long p,
    const acb_poly_struct * b, long q,
    const acb_poly_t z, int regularized,
    long n, long len, long prec)
{
    acb_poly_t s, t, err;
    arb_poly_t C, T;
    long i;
    int is_real;
    int terminating;

    /* default algorithm to choose number of terms */
    if (n < 0)
    {
        n = acb_hypgeom_pfq_series_choose_n(a, p, b, q, z, len, prec);
    }

    terminating = 0;

    /* check if it terminates due to a root of the numerator */
    for (i = 0; i < p; i++)
    {
        if (acb_poly_length(a + i) == 0 && n > 0)
        {
            terminating = 1;
        }
        else if (acb_poly_length(a + i) == 1)
        {
            acb_srcptr c = acb_poly_get_coeff_ptr(a + i, 0);

            if (acb_is_int(c) && arb_is_negative(acb_realref(c)) &&
                arf_cmpabs_ui(arb_midref(acb_realref(c)), n) < 0)
            {
                terminating = 1;
            }
        }
    }

    /* check if it terminates (to order n) due to z */
    /* the following tests could be made stronger... */
    if (z->length == 0 && n >= 1)
    {
        terminating = 1;
    }
    else if (!terminating && z->length > 0 && acb_is_zero(z->coeffs) && n >= len)
    {
        if (regularized)
        {
            terminating = 1;
        }
        else
        {
            terminating = 1;

            for (i = 0; i < q; i++)
            {
                acb_srcptr c = acb_poly_get_coeff_ptr(b + i, 0);

                if (!arb_is_positive(acb_realref(c)) && acb_contains_int(c))
                    terminating = 0;
            }
        }
    }

    acb_poly_init(s);
    acb_poly_init(t);
    acb_poly_init(err);
    arb_poly_init(C);
    arb_poly_init(T);

    acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z, regularized, n, len, prec);

    if (!terminating)
    {
        is_real = acb_poly_is_real(z);
        for (i = 0; i < p; i++)
            is_real = is_real && acb_poly_is_real(a + i);
        for (i = 0; i < q; i++)
            is_real = is_real && acb_poly_is_real(b + i);

        acb_poly_majorant(T, t, MAG_BITS);
        acb_hypgeom_pfq_series_bound_factor(C, a, p, b, q, z, n, len, MAG_BITS);

        if (!_arb_vec_is_finite(T->coeffs, T->length) ||
            !_arb_vec_is_finite(C->coeffs, C->length))
        {
            arb_poly_fit_length(T, len);
            _arb_vec_indeterminate(T->coeffs, len);
            _arb_poly_set_length(T, len);
        }
        else
        {
            arb_poly_mullow(T, T, C, len, MAG_BITS);
        }

        /* create polynomial of errors */
        acb_poly_fit_length(err, len);

        for (i = 0; i < FLINT_MIN(len, T->length); i++)
        {
            arb_add_error(acb_realref(err->coeffs + i), T->coeffs + i);
            if (!is_real)
                arb_add_error(acb_imagref(err->coeffs + i), T->coeffs + i);
        }

        _acb_poly_set_length(err, len);
        _acb_poly_normalise(err);

        acb_poly_add(s, s, err, prec);
    }

    acb_poly_set(res, s);

    acb_poly_clear(s);
    acb_poly_clear(t);
    acb_poly_clear(err);
    arb_poly_clear(C);
    arb_poly_clear(T);
}