コード例 #1
0
ファイル: rev_init.c プロジェクト: jwbober/arb
void
bernoulli_rev_init(bernoulli_rev_t iter, ulong nmax)
{
    long j;
    fmpz_t t;
    fmprb_t x;
    int round1, round2;
    long wp;

    nmax -= (nmax % 2);
    iter->n = nmax;

    iter->alloc = 0;
    if (nmax < BERNOULLI_REV_MIN)
        return;

    iter->prec = wp = global_prec(nmax);

    iter->max_power = zeta_terms(nmax, iter->prec);
    iter->alloc = iter->max_power + 1;
    iter->powers = _fmpz_vec_init(iter->alloc);
    fmpz_init(iter->pow_error);
    fmprb_init(iter->prefactor);
    fmprb_init(iter->two_pi_squared);

    fmprb_init(x);
    fmpz_init(t);

    /* precompute powers */
    for (j = 3; j <= iter->max_power; j += 2)
    {
        fmprb_ui_pow_ui(x, j, nmax, power_prec(j, nmax, wp));
        fmprb_ui_div(x, 1UL, x, power_prec(j, nmax, wp));
        round1 = fmpr_get_fmpz_fixed_si(t, fmprb_midref(x), -wp);
        fmpz_set(iter->powers + j, t);

        /* error: the radius, plus two roundings */
        round2 = fmpr_get_fmpz_fixed_si(t, fmprb_radref(x), -wp);
        fmpz_add_ui(t, t, (round1 != 0) + (round2 != 0));
        if (fmpz_cmp(iter->pow_error, t) < 0)
            fmpz_set(iter->pow_error, t);
    }

    /* precompute (2pi)^2 and 2*(n!)/(2pi)^n */
    fmprb_fac_ui(iter->prefactor, nmax, wp);
    fmprb_mul_2exp_si(iter->prefactor, iter->prefactor, 1);

    fmprb_const_pi(x, wp);
    fmprb_mul_2exp_si(x, x, 1);
    fmprb_mul(iter->two_pi_squared, x, x, wp);

    fmprb_pow_ui(x, iter->two_pi_squared, nmax / 2, wp);
    fmprb_div(iter->prefactor, iter->prefactor, x, wp);

    fmpz_clear(t);
    fmprb_clear(x);
}
コード例 #2
0
ファイル: stirling_eval_fmprb.c プロジェクト: jwbober/arb
void
gamma_stirling_eval_fmprb(fmprb_t s, const fmprb_t z, long nterms, int digamma, long prec)
{
    fmprb_t b, t, logz, zinv, zinv2;
    fmpr_t err;

    long k, term_prec;
    double z_mag, term_mag;

    fmprb_init(b);
    fmprb_init(t);
    fmprb_init(logz);
    fmprb_init(zinv);
    fmprb_init(zinv2);

    fmprb_log(logz, z, prec);
    fmprb_ui_div(zinv, 1UL, z, prec);

    nterms = FLINT_MAX(nterms, 1);

    fmprb_zero(s);

    if (nterms > 1)
    {
        fmprb_mul(zinv2, zinv, zinv, prec);

        z_mag = fmpr_get_d(fmprb_midref(logz), FMPR_RND_UP) * 1.44269504088896;

        for (k = nterms - 1; k >= 1; k--)
        {
            term_mag = bernoulli_bound_2exp_si(2 * k);
            term_mag -= (2 * k - 1) * z_mag;
            term_prec = prec + term_mag;
            term_prec = FLINT_MIN(term_prec, prec);
            term_prec = FLINT_MAX(term_prec, 10);

            if (prec > 2000)
            {
                fmprb_set_round(t, zinv2, term_prec);
                fmprb_mul(s, s, t, term_prec);
            }
            else
                fmprb_mul(s, s, zinv2, term_prec);

            gamma_stirling_coeff(b, k, digamma, term_prec);
            fmprb_add(s, s, b, term_prec);
        }

        if (digamma)
            fmprb_mul(s, s, zinv2, prec);
        else
            fmprb_mul(s, s, zinv, prec);
    }

    /* remainder bound */
    fmpr_init(err);
    gamma_stirling_bound_fmprb(err, z, digamma ? 1 : 0, 1, nterms);
    fmprb_add_error_fmpr(s, err);
    fmpr_clear(err);

    if (digamma)
    {
        fmprb_neg(s, s);
        fmprb_mul_2exp_si(zinv, zinv, -1);
        fmprb_sub(s, s, zinv, prec);
        fmprb_add(s, s, logz, prec);
    }
    else
    {
        /* (z-0.5)*log(z) - z + log(2*pi)/2 */
        fmprb_one(t);
        fmprb_mul_2exp_si(t, t, -1);
        fmprb_sub(t, z, t, prec);
        fmprb_mul(t, logz, t, prec);
        fmprb_add(s, s, t, prec);
        fmprb_sub(s, s, z, prec);
        fmprb_const_log_sqrt2pi(t, prec);
        fmprb_add(s, s, t, prec);
    }

    fmprb_clear(t);
    fmprb_clear(b);
    fmprb_clear(zinv);
    fmprb_clear(zinv2);
    fmprb_clear(logz);
}
コード例 #3
0
ファイル: series_em_bound.c プロジェクト: certik/arb
void
zeta_series_em_vec_bound(fmprb_ptr bound, const fmpcb_t s, const fmpcb_t a, ulong N, ulong M, long len, long wp)
{
    fmprb_t K, C, AN, S2M;
    fmprb_ptr F, R;
    long k;

    fmprb_srcptr alpha = fmpcb_realref(a);
    fmprb_srcptr beta  = fmpcb_imagref(a);
    fmprb_srcptr sigma = fmpcb_realref(s);
    fmprb_srcptr tau   = fmpcb_imagref(s);

    fmprb_init(AN);
    fmprb_init(S2M);

    /* require alpha + N > 1, sigma + 2M > 1 */
    fmprb_add_ui(AN, alpha, N - 1, wp);
    fmprb_add_ui(S2M, sigma, 2*M - 1, wp);

    if (!fmprb_is_positive(AN) || !fmprb_is_positive(S2M) || N < 1 || M < 1)
    {
        fmprb_clear(AN);
        fmprb_clear(S2M);

        for (k = 0; k < len; k++)
        {
            fmpr_pos_inf(fmprb_midref(bound + k));
            fmpr_zero(fmprb_radref(bound + k));
        }
        return;
    }

    /* alpha + N, sigma + 2M */
    fmprb_add_ui(AN, AN, 1, wp);
    fmprb_add_ui(S2M, S2M, 1, wp);

    R = _fmprb_vec_init(len);
    F = _fmprb_vec_init(len);

    fmprb_init(K);
    fmprb_init(C);

    /* bound for power integral */
    bound_C(C, AN, beta, wp);
    bound_K(K, AN, beta, tau, wp);
    bound_I(R, AN, S2M, C, len, wp);

    for (k = 0; k < len; k++)
    {
        fmprb_mul(R + k, R + k, K, wp);
        fmprb_div_ui(K, K, k + 1, wp);
    }

    /* bound for rising factorial */
    bound_rfac(F, s, 2*M, len, wp);

    /* product (TODO: only need upper bound; write a function for this) */
    _fmprb_poly_mullow(bound, F, len, R, len, len, wp);

    /* bound for bernoulli polynomials, 4 / (2pi)^(2M) */
    fmprb_const_pi(C, wp);
    fmprb_mul_2exp_si(C, C, 1);
    fmprb_pow_ui(C, C, 2 * M, wp);
    fmprb_ui_div(C, 4, C, wp);
    _fmprb_vec_scalar_mul(bound, bound, len, C, wp);

    fmprb_clear(K);
    fmprb_clear(C);
    fmprb_clear(AN);
    fmprb_clear(S2M);

    _fmprb_vec_clear(R, len);
    _fmprb_vec_clear(F, len);
}
コード例 #4
0
ファイル: zeta_series.c プロジェクト: jwbober/arb
void
_fmprb_poly_zeta_series(fmprb_ptr res, fmprb_srcptr h, long hlen, const fmprb_t a, int deflate, long len, long prec)
{
    long i;
    fmpcb_t cs, ca;
    fmpcb_ptr z;
    fmprb_ptr t, u;

    if (fmprb_contains_nonpositive(a))
    {
        _fmprb_vec_indeterminate(res, len);
        return;
    }

    hlen = FLINT_MIN(hlen, len);

    z = _fmpcb_vec_init(len);
    t = _fmprb_vec_init(len);
    u = _fmprb_vec_init(len);
    fmpcb_init(cs);
    fmpcb_init(ca);

    /* use reflection formula */
    if (fmpr_sgn(fmprb_midref(h)) < 0 && fmprb_is_one(a))
    {
        /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */
        fmprb_t pi;
        fmprb_ptr f, s1, s2, s3, s4;

        fmprb_init(pi);
        f = _fmprb_vec_init(2);
        s1 = _fmprb_vec_init(len);
        s2 = _fmprb_vec_init(len);
        s3 = _fmprb_vec_init(len);
        s4 = _fmprb_vec_init(len);

        fmprb_const_pi(pi, prec);

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

        /* s2 = sin(pi*s/2) / pi */
        fmprb_mul_2exp_si(pi, pi, -1);
        fmprb_mul(f, pi, h, prec);
        fmprb_set(f + 1, pi);
        fmprb_mul_2exp_si(pi, pi, 1);
        _fmprb_poly_sin_series(s2, f, 2, len, prec);
        _fmprb_vec_scalar_div(s2, s2, len, pi, prec);

        /* s3 = gamma(1-s) */
        fmprb_sub_ui(f, h, 1, prec);
        fmprb_neg(f, f);
        fmprb_set_si(f + 1, -1);
        _fmprb_poly_gamma_series(s3, f, 2, len, prec);

        /* s4 = zeta(1-s) */
        fmprb_sub_ui(f, h, 1, prec);
        fmprb_neg(f, f);
        fmpcb_set_fmprb(cs, f);
        fmpcb_one(ca);
        zeta_series(z, cs, ca, 0, len, prec);
        for (i = 0; i < len; i++)
            fmprb_set(s4 + i, fmpcb_realref(z + i));
        for (i = 1; i < len; i += 2)
            fmprb_neg(s4 + i, s4 + i);

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

        /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */
        if (deflate)
        {
            fmprb_sub_ui(u, h, 1, prec);
            fmprb_neg(u, u);
            fmprb_ui_div(u, 1, u, prec);
            for (i = 1; i < len; i++)
                fmprb_mul(u + i, u + i - 1, u, prec);
            _fmprb_vec_add(t, t, u, len, prec);
        }

        fmprb_clear(pi);
        _fmprb_vec_clear(f, 2);
        _fmprb_vec_clear(s1, len);
        _fmprb_vec_clear(s2, len);
        _fmprb_vec_clear(s3, len);
        _fmprb_vec_clear(s4, len);
    }
    else
    {
        fmpcb_set_fmprb(cs, h);
        fmpcb_set_fmprb(ca, a);
        zeta_series(z, cs, ca, deflate, len, prec);
        for (i = 0; i < len; i++)
            fmprb_set(t + i, fmpcb_realref(z + i));
    }

    /* compose with nonconstant part */
    fmprb_zero(u);
    _fmprb_vec_set(u + 1, h + 1, hlen - 1);
    _fmprb_poly_compose_series(res, t, len, u, hlen, len, prec);

    _fmpcb_vec_clear(z, len);
    _fmprb_vec_clear(t, len);
    _fmprb_vec_clear(u, len);
    fmpcb_init(cs);
    fmpcb_init(ca);
}
コード例 #5
0
ファイル: gamma.c プロジェクト: jwbober/arb
static void
_fmprb_gamma(fmprb_t y, const fmprb_t x, long prec, int inverse)
{
    int reflect;
    long r, n, wp;
    fmprb_t t, u, v;

    if (fmprb_is_exact(x))
    {
        const fmpr_struct * mid = fmprb_midref(x);

        if (fmpr_is_special(mid))
        {
            if (!inverse && fmpr_is_pos_inf(mid))
            {
                fmprb_set(y, x);
            }
            else if (fmpr_is_nan(mid) || fmpr_is_neg_inf(mid) || !inverse)
            {
                fmpr_nan(fmprb_midref(y));
                fmpr_pos_inf(fmprb_radref(y));
            }
            else
            {
                fmprb_zero(y);
            }
            return;
        }
        else
        {
            const fmpz exp = *fmpr_expref(mid);
            const fmpz man = *fmpr_manref(mid);

            /* fast gamma(n), gamma(n/2) or gamma(n/4) */
            if (!COEFF_IS_MPZ(exp) && (exp >= -2) &&
                ((double) fmpz_bits(&man) + exp < prec))
            {
                fmpq_t a;
                fmpq_init(a);
                fmpr_get_fmpq(a, mid);
                fmprb_gamma_fmpq(y, a, prec + 2 * inverse);
                if (inverse)
                    fmprb_ui_div(y, 1, y, prec);
                fmpq_clear(a);
                return;
            }
        }
    }

    wp = prec + FLINT_BIT_COUNT(prec);

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

    fmprb_init(t);
    fmprb_init(u);
    fmprb_init(v);

    if (reflect)
    {
        /* gamma(x) = (rf(1-x, r) * pi) / (gamma(1-x+r) sin(pi x)) */
        fmprb_sub_ui(t, x, 1, wp);
        fmprb_neg(t, t);
        gamma_rising_fmprb_ui_bsplit(u, t, r, wp);
        fmprb_const_pi(v, wp);
        fmprb_mul(u, u, v, wp);
        fmprb_add_ui(t, t, r, wp);
        gamma_stirling_eval_fmprb(v, t, n, 0, wp);
        fmprb_exp(v, v, wp);
        fmprb_sin_pi(t, x, wp);
        fmprb_mul(v, v, t, wp);
    }
    else
    {
        /* gamma(x) = gamma(x+r) / rf(x,r) */
        fmprb_add_ui(t, x, r, wp);
        gamma_stirling_eval_fmprb(u, t, n, 0, wp);
        fmprb_exp(u, u, prec);
        gamma_rising_fmprb_ui_bsplit(v, x, r, wp);
    }

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

    fmprb_clear(t);
    fmprb_clear(u);
    fmprb_clear(v);
}