void arb_fac2_ui(arb_t res, ulong n, long prec) { if (n % 2 == 0) { arb_fac_ui(res, n / 2, prec); arb_mul_2exp_si(res, res, n / 2); } else { arb_t t; arb_init(t); arb_fac2_ui(t, n - 1, prec + 5); arb_fac_ui(res, n, prec + 5); arb_div(res, res, t, prec); arb_clear(t); } }
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); } }
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); } }
void bernoulli_rev_init(bernoulli_rev_t iter, ulong nmax) { long j; fmpz_t t; arb_t x; arf_t u; int round1, round2; long wp; nmax -= (nmax % 2); iter->n = nmax; iter->alloc = 0; if (nmax < BERNOULLI_REV_MIN) return; iter->prec = wp = bernoulli_global_prec(nmax); iter->max_power = bernoulli_zeta_terms(nmax, iter->prec); iter->alloc = iter->max_power + 1; iter->powers = _fmpz_vec_init(iter->alloc); fmpz_init(iter->pow_error); arb_init(iter->prefactor); arb_init(iter->two_pi_squared); arb_init(x); fmpz_init(t); arf_init(u); /* precompute powers */ for (j = 3; j <= iter->max_power; j += 2) { arb_ui_pow_ui(x, j, nmax, bernoulli_power_prec(j, nmax, wp)); arb_inv(x, x, bernoulli_power_prec(j, nmax, wp)); round1 = arf_get_fmpz_fixed_si(t, arb_midref(x), -wp); fmpz_set(iter->powers + j, t); /* error: the radius, plus two roundings */ arf_set_mag(u, arb_radref(x)); round2 = arf_get_fmpz_fixed_si(t, u, -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 */ arb_fac_ui(iter->prefactor, nmax, wp); arb_mul_2exp_si(iter->prefactor, iter->prefactor, 1); arb_const_pi(x, wp); arb_mul_2exp_si(x, x, 1); arb_mul(iter->two_pi_squared, x, x, wp); arb_pow_ui(x, iter->two_pi_squared, nmax / 2, wp); arb_div(iter->prefactor, iter->prefactor, x, wp); fmpz_clear(t); arb_clear(x); arf_clear(u); }