void acb_tan_pi(acb_t r, const acb_t z, slong prec) { if (arb_is_zero(acb_imagref(z))) { arb_tan_pi(acb_realref(r), acb_realref(z), prec); arb_zero(acb_imagref(r)); } else if (arb_is_zero(acb_realref(z))) { arb_t t; arb_init(t); arb_const_pi(t, prec + 4); arb_mul(t, acb_imagref(z), t, prec + 4); arb_tanh(acb_imagref(r), t, prec); arb_zero(acb_realref(r)); arb_clear(t); } else { acb_t t; acb_init(t); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 0) < 0) { acb_sin_cos_pi(r, t, z, prec + 4); acb_div(r, r, t, prec); } else { acb_mul_2exp_si(t, z, 1); if (arf_sgn(arb_midref(acb_imagref(z))) > 0) { acb_exp_pi_i(t, t, prec + 4); acb_add_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_div_onei(r, r); } else { acb_neg(t, t); acb_exp_pi_i(t, t, prec + 4); acb_add_ui(r, t, 1, prec + 4); acb_div(r, t, r, prec + 4); acb_mul_2exp_si(r, r, 1); acb_sub_ui(r, r, 1, prec); acb_mul_onei(r, r); } } acb_clear(t); } }
void acb_modular_elliptic_e(acb_t res, const acb_t m, long prec) { if (acb_is_zero(m)) { acb_const_pi(res, prec); acb_mul_2exp_si(res, res, -1); } else if (acb_is_one(m)) { acb_one(res); } else { acb_struct t[2]; acb_init(t + 0); acb_init(t + 1); acb_modular_elliptic_k_cpx(t, m, 2, prec); acb_mul(t + 1, t + 1, m, prec); acb_mul_2exp_si(t + 1, t + 1, 1); acb_add(t, t, t + 1, prec); acb_sub_ui(t + 1, m, 1, prec); acb_mul(res, t, t + 1, prec); acb_neg(res, res); acb_clear(t + 0); acb_clear(t + 1); } }
/* f(z) = sin((1/1000 + (1-z)^2)^(-3/2)), example from Mioara Joldes' thesis (suggested by Nicolas Brisebarre) */ int f_sin_near_essing(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t t, u; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(t); acb_init(u); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_mul(t, t, t, prec); acb_one(u); acb_div_ui(u, u, 1000, prec); acb_add(t, t, u, prec); acb_set_d(u, -1.5); acb_pow_analytic(t, t, u, order != 0, prec); acb_sin(res, t, prec); acb_clear(t); acb_clear(u); return 0; }
/* Differential equation for F(a,b,c,y+z): (y+z)(y-1+z) F''(z) + ((y+z)(a+b+1) - c) F'(z) + a b F(z) = 0 Coefficients in the Taylor series are bounded by A * binomial(N+k, k) * nu^k using the Cauchy-Kovalevskaya majorant method. See J. van der Hoeven, "Fast evaluation of holonomic functions near and in regular singularities" */ static void bound(mag_t A, mag_t nu, mag_t N, const acb_t a, const acb_t b, const acb_t c, const acb_t y, const acb_t f0, const acb_t f1) { mag_t M0, M1, t, u; acb_t d; acb_init(d); mag_init(M0); mag_init(M1); mag_init(t); mag_init(u); /* nu = max(1/|y-1|, 1/|y|) = 1/min(|y-1|, |y|) */ acb_get_mag_lower(t, y); acb_sub_ui(d, y, 1, MAG_BITS); acb_get_mag_lower(u, d); mag_min(t, t, u); mag_one(u); mag_div(nu, u, t); /* M0 = 2 nu |ab| */ acb_get_mag(t, a); acb_get_mag(u, b); mag_mul(M0, t, u); mag_mul(M0, M0, nu); mag_mul_2exp_si(M0, M0, 1); /* M1 = 2 nu |(a+b+1)y-c| + 2|a+b+1| */ acb_add(d, a, b, MAG_BITS); acb_add_ui(d, d, 1, MAG_BITS); acb_get_mag(t, d); acb_mul(d, d, y, MAG_BITS); acb_sub(d, d, c, MAG_BITS); acb_get_mag(u, d); mag_mul(u, u, nu); mag_add(M1, t, u); mag_mul_2exp_si(M1, M1, 1); /* N = max(sqrt(2 M0), 2 M1) / nu */ mag_mul_2exp_si(M0, M0, 1); mag_sqrt(M0, M0); mag_mul_2exp_si(M1, M1, 1); mag_max(N, M0, M1); mag_div(N, N, nu); /* A = max(|f0|, |f1| / (nu (N+1)) */ acb_get_mag(t, f0); acb_get_mag(u, f1); mag_div(u, u, nu); mag_div(u, u, N); /* upper bound for dividing by N+1 */ mag_max(A, t, u); acb_clear(d); mag_clear(M0); mag_clear(M1); mag_clear(t); mag_clear(u); }
void acb_poly_add_si(acb_poly_t res, const acb_poly_t x, long y, long prec) { long len = x->length; if (len == 0) { acb_poly_set_si(res, y); } else { acb_poly_fit_length(res, len); if (y >= 0) acb_add_ui(res->coeffs, x->coeffs, y, prec); else acb_sub_ui(res->coeffs, x->coeffs, -y, prec); if (res != x) _acb_vec_set(res->coeffs + 1, x->coeffs + 1, len - 1); _acb_poly_set_length(res, len); _acb_poly_normalise(res); } }
void acb_hypgeom_expint(acb_t res, const acb_t s, const acb_t z, slong prec) { acb_t t; acb_init(t); acb_sub_ui(t, s, 1, prec); acb_neg(t, t); acb_hypgeom_gamma_upper(res, t, z, 2, prec); acb_clear(t); }
void acb_hypgeom_beta_lower(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec) { acb_t t, u; if (acb_is_zero(z) && arb_is_positive(acb_realref(a))) { acb_zero(res); return; } if (acb_is_one(z) && arb_is_positive(acb_realref(b))) { if (regularized) acb_one(res); else acb_beta(res, a, b, prec); return; } acb_init(t); acb_init(u); acb_sub_ui(t, b, 1, prec); acb_neg(t, t); acb_add_ui(u, a, 1, prec); if (regularized) { acb_hypgeom_2f1(t, a, t, u, z, 1, prec); acb_add(u, a, b, prec); acb_gamma(u, u, prec); acb_mul(t, t, u, prec); acb_rgamma(u, b, prec); acb_mul(t, t, u, prec); } else { acb_hypgeom_2f1(t, a, t, u, z, 0, prec); acb_div(t, t, a, prec); } acb_pow(u, z, a, prec); acb_mul(t, t, u, prec); acb_set(res, t); acb_clear(t); acb_clear(u); }
void acb_modular_elliptic_k(acb_t k, const acb_t m, slong prec) { acb_t t; acb_init(t); acb_sub_ui(t, m, 1, prec); acb_neg(t, t); acb_sqrt(t, t, prec); acb_agm1(k, t, prec); acb_const_pi(t, prec); acb_div(k, t, k, prec); acb_mul_2exp_si(k, k, -1); acb_clear(t); }
/* f(z) = sech(10(x-0.2))^2 + sech(100(x-0.4))^4 + sech(1000(x-0.6))^6 */ int f_spike(acb_ptr res, const acb_t z, void * param, slong order, slong prec) { acb_t a, b, c; if (order > 1) flint_abort(); /* Would be needed for Taylor method. */ acb_init(a); acb_init(b); acb_init(c); acb_mul_ui(a, z, 10, prec); acb_sub_ui(a, a, 2, prec); acb_sech(a, a, prec); acb_pow_ui(a, a, 2, prec); acb_mul_ui(b, z, 100, prec); acb_sub_ui(b, b, 40, prec); acb_sech(b, b, prec); acb_pow_ui(b, b, 4, prec); acb_mul_ui(c, z, 1000, prec); acb_sub_ui(c, c, 600, prec); acb_sech(c, c, prec); acb_pow_ui(c, c, 6, prec); acb_add(res, a, b, prec); acb_add(res, res, c, prec); acb_clear(a); acb_clear(b); acb_clear(c); return 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); }
int elliptic(acb_ptr out, const acb_t inp, void * params, long order, long prec) { acb_ptr t; t = _acb_vec_init(order); acb_set(t, inp); if (order > 1) acb_one(t + 1); _acb_poly_sin_series(t, t, FLINT_MIN(2, order), order, prec); _acb_poly_mullow(out, t, order, t, order, order, prec); _acb_vec_scalar_mul_2exp_si(t, out, order, -1); acb_sub_ui(t, t, 1, prec); _acb_vec_neg(t, t, order); _acb_poly_rsqrt_series(out, t, order, order, prec); _acb_vec_clear(t, order); return 0; }
void acb_hypgeom_jacobi_p_ui_direct(acb_t res, ulong n, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_ptr terms; acb_t t, u, v; slong k; terms = _acb_vec_init(n + 1); acb_init(t); acb_init(u); acb_init(v); acb_one(terms); acb_add_ui(u, z, 1, prec); for (k = 1; k <= n; k++) { acb_add_ui(t, a, n + 1 - k, prec); acb_mul(t, t, u, prec); acb_div_ui(t, t, 2 * k, prec); acb_mul(terms + k, terms + k - 1, t, prec); } acb_sub_ui(u, z, 1, prec); acb_one(v); for (k = 1; k <= n; k++) { acb_add_ui(t, b, n + 1 - k, prec); acb_mul(t, t, u, prec); acb_div_ui(t, t, 2 * k, prec); acb_mul(v, v, t, prec); acb_mul(terms + n - k, terms + n - k, v, prec); } acb_set(res, terms); for (k = 1; k <= n; k++) acb_add(res, res, terms + k, prec); _acb_vec_clear(terms, n + 1); acb_clear(t); acb_clear(u); acb_clear(v); }
static void _acb_hypgeom_2f1r_reduced(acb_t res, const acb_t b, const acb_t c, const acb_t z, slong prec) { acb_t t, u; acb_init(t); acb_init(u); acb_sub_ui(t, z, 1, prec); acb_neg(t, t); acb_neg(u, b); acb_pow(t, t, u, prec); acb_rgamma(u, c, prec); acb_mul(t, t, u, prec); acb_set(res, t); acb_clear(t); acb_clear(u); return; }
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); }
void acb_hypgeom_jacobi_p(acb_t res, const acb_t n, const acb_t a, const acb_t b, const acb_t z, slong prec) { acb_t t, u, v, w; if (use_recurrence(n, a, b, prec)) { acb_hypgeom_jacobi_p_ui_direct(res, arf_get_si(arb_midref(acb_realref(n)), ARF_RND_DOWN), a, b, z, prec); return; } acb_init(t); acb_init(u); acb_init(v); acb_init(w); acb_neg(t, n); acb_add_ui(v, a, 1, prec); acb_add(u, n, v, prec); acb_add(u, u, b, prec); acb_sub_ui(w, z, 1, prec); acb_mul_2exp_si(w, w, -1); acb_neg(w, w); acb_hypgeom_2f1(w, t, u, v, w, 0, prec); acb_rising(t, v, n, prec); acb_mul(w, w, t, prec); acb_add_ui(t, n, 1, prec); acb_rgamma(t, t, prec); acb_mul(w, w, t, prec); acb_set(res, w); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(w); }
void acb_acosh(acb_t res, const acb_t z, slong prec) { if (acb_is_one(z)) { acb_zero(res); } else { acb_t t, u; acb_init(t); acb_init(u); acb_add_ui(t, z, 1, prec); acb_sub_ui(u, z, 1, prec); acb_sqrt(t, t, prec); acb_sqrt(u, u, prec); acb_mul(t, t, u, prec); acb_add(t, t, z, prec); if (!arb_is_zero(acb_imagref(z))) { acb_log(res, t, prec); } else { /* pure imaginary on (-1,1) */ arb_abs(acb_realref(u), acb_realref(z)); arb_one(acb_imagref(u)); acb_log(res, t, prec); if (arb_lt(acb_realref(u), acb_imagref(u))) arb_zero(acb_realref(res)); } acb_clear(t); acb_clear(u); } }
int main() { slong iter; flint_rand_t state; flint_printf("legendre_p...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000 * arb_test_multiplier(); iter++) { acb_t n, na, nb, m, z, res1, res2, res3, t, u; slong prec1, prec2, ebits; int type; acb_init(n); acb_init(na); acb_init(nb); acb_init(m); acb_init(z); acb_init(res1); acb_init(res2); acb_init(res3); acb_init(t); acb_init(u); prec1 = 2 + n_randint(state, 300); prec2 = 2 + n_randint(state, 300); ebits = 1 + n_randint(state, 10); if (n_randint(state, 2)) { acb_set_si(m, n_randint(state, 20) - 10); acb_set_si(n, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), ebits); acb_randtest_param(m, state, 1 + n_randint(state, 400), ebits); } acb_randtest_param(z, state, 1 + n_randint(state, 400), ebits); acb_sub_ui(na, n, 1, prec2); acb_add_ui(nb, n, 1, prec2); type = n_randint(state, 2); acb_hypgeom_legendre_p(res1, n, m, z, type, prec1); acb_hypgeom_legendre_p(res2, na, m, z, type, prec2); acb_hypgeom_legendre_p(res3, nb, m, z, type, prec2); acb_add(t, n, m, prec2); acb_mul(t, t, res2, prec2); acb_sub(u, n, m, prec2); acb_add_ui(u, u, 1, prec2); acb_mul(u, u, res3, prec2); acb_add(t, t, u, prec2); acb_mul_2exp_si(u, n, 1); acb_add_ui(u, u, 1, prec2); acb_mul(u, u, z, prec2); acb_mul(u, u, res1, prec2); if (!acb_overlaps(t, u)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd, prec1 = %wd, prec2 = %wd\n\n", iter, prec1, prec2); flint_printf("type = %d\n\n", type); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_printf("res3 = "); acb_printd(res3, 30); flint_printf("\n\n"); flint_printf("t = "); acb_printd(t, 30); flint_printf("\n\n"); flint_printf("u = "); acb_printd(u, 30); flint_printf("\n\n"); abort(); } acb_clear(n); acb_clear(na); acb_clear(nb); acb_clear(m); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(res3); acb_clear(t); acb_clear(u); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int main() { long iter; flint_rand_t state; printf("bessel_j...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000; iter++) { acb_t nu0, nu1, nu2, z, w0, w1, w2, t, u; long prec0, prec1, prec2; acb_init(nu0); acb_init(nu1); acb_init(nu2); acb_init(z); acb_init(w0); acb_init(w1); acb_init(w2); acb_init(t); acb_init(u); prec0 = 2 + n_randint(state, 1000); prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); acb_randtest_param(nu0, 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_randtest(w2, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_sub_ui(nu1, nu0, 1, prec0); acb_sub_ui(nu2, nu0, 2, prec0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w0, nu0, z, prec0); break; case 1: acb_hypgeom_bessel_j_0f1(w0, nu0, z, prec0); break; default: acb_hypgeom_bessel_j(w0, nu0, z, prec0); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w1, nu0, z, prec1); break; case 1: acb_hypgeom_bessel_j_0f1(w1, nu0, z, prec1); break; default: acb_hypgeom_bessel_j(w1, nu0, z, prec1); } if (!acb_overlaps(w0, w1)) { printf("FAIL: consistency\n\n"); printf("nu = "); acb_printd(nu0, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("w0 = "); acb_printd(w0, 30); printf("\n\n"); printf("w1 = "); acb_printd(w1, 30); printf("\n\n"); abort(); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w1, nu1, z, prec1); break; case 1: acb_hypgeom_bessel_j_0f1(w1, nu1, z, prec1); break; default: acb_hypgeom_bessel_j(w1, nu1, z, prec1); } switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w2, nu2, z, prec2); break; case 1: acb_hypgeom_bessel_j_0f1(w2, nu2, z, prec2); break; default: acb_hypgeom_bessel_j(w2, nu2, z, prec2); } acb_mul(t, w1, nu1, prec0); acb_mul_2exp_si(t, t, 1); acb_submul(t, w2, z, prec0); acb_submul(t, w0, z, prec0); if (!acb_contains_zero(t)) { printf("FAIL: contiguous relation\n\n"); printf("nu = "); acb_printd(nu0, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("w0 = "); acb_printd(w0, 30); printf("\n\n"); printf("w1 = "); acb_printd(w1, 30); printf("\n\n"); printf("w2 = "); acb_printd(w2, 30); printf("\n\n"); printf("t = "); acb_printd(t, 30); printf("\n\n"); abort(); } acb_neg(t, nu0); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w2, t, z, prec2); break; case 1: acb_hypgeom_bessel_j_0f1(w2, t, z, prec2); break; default: acb_hypgeom_bessel_j(w2, t, z, prec2); } acb_mul(w1, w1, w2, prec2); acb_neg(t, nu1); switch (n_randint(state, 3)) { case 0: acb_hypgeom_bessel_j_asymp(w2, t, z, prec2); break; case 1: acb_hypgeom_bessel_j_0f1(w2, t, z, prec2); break; default: acb_hypgeom_bessel_j(w2, t, z, prec2); } acb_mul(w0, w0, w2, prec2); acb_add(w0, w0, w1, prec2); acb_sin_pi(t, nu0, prec2); acb_const_pi(u, prec2); acb_mul(u, u, z, prec2); acb_div(t, t, u, prec2); acb_mul_2exp_si(t, t, 1); if (!acb_overlaps(w0, t)) { printf("FAIL: wronskian\n\n"); printf("nu = "); acb_printd(nu0, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("w0 = "); acb_printd(w0, 30); printf("\n\n"); printf("t = "); acb_printd(t, 30); printf("\n\n"); abort(); } acb_clear(nu0); acb_clear(nu1); acb_clear(nu2); acb_clear(z); acb_clear(w0); acb_clear(w1); acb_clear(w2); acb_clear(t); acb_clear(u); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { int function, i, numtests; slong prec, goal; double t, total, logtotal; acb_t a, b, c, z, r, s; acb_init(a); acb_init(b); acb_init(c); acb_init(z); acb_init(r); acb_init(s); /* J(0,pi x) I(0,pi x) K(0,pi x) */ for (function = 0; function < 3; function++) { total = 0.0; logtotal = 0.0; if (function < 2) numtests = 40; else numtests = 30; for (i = 0; i < numtests; i++) { // printf("%2d ", i + 1); fflush(stdout); TIMEIT_START prec = 96; for (;;) { if (function == 0) { acb_set_d_d(a, input_1f1[i][0], input_1f1[i][1]); acb_set_d_d(b, input_1f1[i][2], input_1f1[i][3]); acb_set_d_d(z, input_1f1[i][4], input_1f1[i][5]); acb_hypgeom_m(r, a, b, z, 0, prec); } else if (function == 1) { acb_set_d_d(a, input_1f1[i][0], input_1f1[i][1]); acb_set_d_d(b, input_1f1[i][2], input_1f1[i][3]); acb_set_d_d(z, input_1f1[i][4], input_1f1[i][5]); acb_hypgeom_u(r, a, b, z, prec); } else if (function == 2) { acb_set_d_d(a, input_2f1[i][0], input_2f1[i][1]); acb_set_d_d(b, input_2f1[i][2], input_2f1[i][3]); acb_set_d_d(c, input_2f1[i][4], input_2f1[i][5]); acb_set_d_d(z, input_2f1[i][6], input_2f1[i][7]); acb_hypgeom_2f1(r, a, b, c, z, 0, prec); } else { acb_set_d_d(a, input_2f1[i][0], input_2f1[i][1]); acb_set_d_d(b, input_2f1[i][2], input_2f1[i][3]); acb_set_d_d(c, input_2f1[i][4], input_2f1[i][5]); acb_set_d_d(z, input_2f1[i][6], input_2f1[i][7]); acb_mul_2exp_si(z, z, 1); acb_sub_ui(z, z, 1, prec); acb_neg(z, z); acb_hypgeom_legendre_q(r, a, c, z, 0, prec); } if (function == 3) { if (acb_rel_accuracy_bits(r) >= goal) break; } else { if (arb_can_round_arf(acb_realref(r), goal, ARF_RND_NEAR) && arb_can_round_arf(acb_imagref(r), goal, ARF_RND_NEAR)) break; } prec *= 2; } TIMEIT_STOP_VAL(t) total += t; logtotal += log(t); #if 1 printf("%8g, ", t); #else printf("%8ld %8g ", prec, t); _acb_print(r, 25); printf("\n"); #endif } printf("---------------------------------------------------------------\n"); printf("Mean %g s; geometric mean %g\n", total, exp(logtotal / numtests)); printf("---------------------------------------------------------------\n"); } acb_clear(a); acb_clear(b); acb_clear(c); acb_clear(z); acb_clear(r); acb_clear(s); }
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); }
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); } }
int main() { slong iter; flint_rand_t state; flint_printf("erfc...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { acb_t a, b, c; slong prec1, prec2, prec3, prec4; prec1 = 2 + n_randint(state, 1000); prec2 = 2 + n_randint(state, 1000); prec3 = 2 + n_randint(state, 1000); prec4 = 2 + n_randint(state, 1000); acb_init(a); acb_init(b); acb_init(c); acb_randtest_special(a, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_special(b, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest_special(c, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); switch (n_randint(state, 4)) { case 0: acb_hypgeom_erf_asymp(b, a, 1, prec1, prec3); break; case 1: acb_hypgeom_erf(b, a, prec1); acb_sub_ui(b, b, 1, prec1); acb_neg(b, b); break; default: acb_hypgeom_erfc(b, a, prec1); } switch (n_randint(state, 4)) { case 0: acb_hypgeom_erf_asymp(c, a, 1, prec2, prec4); break; case 1: acb_hypgeom_erf(c, a, prec2); acb_sub_ui(c, c, 1, prec2); acb_neg(c, c); break; default: acb_hypgeom_erfc(c, a, prec2); } if (!acb_overlaps(b, c)) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("c = "); acb_printd(c, 30); 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; }
void _acb_poly_zeta_em_sum(acb_ptr z, const acb_t s, const acb_t a, int deflate, ulong N, ulong M, slong d, slong prec) { acb_ptr t, u, v, term, sum; acb_t Na, one; slong i; t = _acb_vec_init(d + 1); u = _acb_vec_init(d); v = _acb_vec_init(d); term = _acb_vec_init(d); sum = _acb_vec_init(d); acb_init(Na); acb_init(one); prec += 2 * (FLINT_BIT_COUNT(N) + FLINT_BIT_COUNT(d)); acb_one(one); /* sum 1/(k+a)^(s+x) */ if (acb_is_one(a) && d <= 3) _acb_poly_powsum_one_series_sieved(sum, s, N, d, prec); else if (N > 50 && flint_get_num_threads() > 1) _acb_poly_powsum_series_naive_threaded(sum, s, a, one, N, d, prec); else _acb_poly_powsum_series_naive(sum, s, a, one, N, d, prec); /* t = 1/(N+a)^(s+x); we might need one extra term for deflation */ acb_add_ui(Na, a, N, prec); _acb_poly_acb_invpow_cpx(t, Na, s, d + 1, prec); /* sum += (N+a) * 1/((s+x)-1) * t */ if (!deflate) { /* u = (N+a)^(1-(s+x)) */ acb_sub_ui(v, s, 1, prec); _acb_poly_acb_invpow_cpx(u, Na, v, d, prec); /* divide by 1/((s-1) + x) */ acb_sub_ui(v, s, 1, prec); acb_div(u, u, v, prec); for (i = 1; i < d; i++) { acb_sub(u + i, u + i, u + i - 1, prec); acb_div(u + i, u + i, v, prec); } _acb_vec_add(sum, sum, u, d, prec); } /* sum += ((N+a)^(1-(s+x)) - 1) / ((s+x) - 1) */ else { /* at s = 1, this becomes (N*t - 1)/x, i.e. just remove one coeff */ if (acb_is_one(s)) { for (i = 0; i < d; i++) acb_mul(u + i, t + i + 1, Na, prec); _acb_vec_add(sum, sum, u, d, prec); } else { /* TODO: this is numerically unstable for large derivatives, and divides by zero if s contains 1. We want a good way to evaluate the power series ((N+a)^y - 1) / y where y has nonzero constant term, without doing a division. How is this best done? */ _acb_vec_scalar_mul(t, t, d, Na, prec); acb_sub_ui(t + 0, t + 0, 1, prec); acb_sub_ui(u + 0, s, 1, prec); acb_inv(u + 0, u + 0, prec); for (i = 1; i < d; i++) acb_mul(u + i, u + i - 1, u + 0, prec); for (i = 1; i < d; i += 2) acb_neg(u + i, u + i); _acb_poly_mullow(v, u, d, t, d, d, prec); _acb_vec_add(sum, sum, v, d, prec); _acb_poly_acb_invpow_cpx(t, Na, s, d, prec); } } /* sum += u = 1/2 * t */ _acb_vec_scalar_mul_2exp_si(u, t, d, -WORD(1)); _acb_vec_add(sum, sum, u, d, prec); /* Euler-Maclaurin formula tail */ if (d < 5 || d < M / 10) _acb_poly_zeta_em_tail_naive(u, s, Na, t, M, d, prec); else _acb_poly_zeta_em_tail_bsplit(u, s, Na, t, M, d, prec); _acb_vec_add(z, sum, u, d, prec); _acb_vec_clear(t, d + 1); _acb_vec_clear(u, d); _acb_vec_clear(v, d); _acb_vec_clear(term, d); _acb_vec_clear(sum, d); acb_clear(Na); acb_clear(one); }
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); }
/* todo: use log(1-z) when this is better? would also need to adjust strategy in the main function */ void acb_hypgeom_dilog_bernoulli(acb_t res, const acb_t z, slong prec) { acb_t s, w, w2; slong n, k; fmpz_t c, d; mag_t m, err; double lm; int real; acb_init(s); acb_init(w); acb_init(w2); fmpz_init(c); fmpz_init(d); mag_init(m); mag_init(err); real = 0; if (acb_is_real(z)) { arb_sub_ui(acb_realref(w), acb_realref(z), 1, 30); real = arb_is_nonpositive(acb_realref(w)); } acb_log(w, z, prec); acb_get_mag(m, w); /* for k >= 4, the terms are bounded by (|w| / (2 pi))^k */ mag_set_ui_2exp_si(err, 2670177, -24); /* upper bound for 1/(2pi) */ mag_mul(err, err, m); lm = mag_get_d_log2_approx(err); if (lm < -0.25) { n = prec / (-lm) + 1; n = FLINT_MAX(n, 4); mag_geom_series(err, err, n); BERNOULLI_ENSURE_CACHED(n) acb_mul(w2, w, w, prec); for (k = n - (n % 2 == 0); k >= 3; k -= 2) { fmpz_mul_ui(c, fmpq_denref(bernoulli_cache + k - 1), k - 1); fmpz_mul_ui(d, c, (k + 1) * (k + 2)); acb_mul(s, s, w2, prec); acb_mul_fmpz(s, s, c, prec); fmpz_mul_ui(c, fmpq_numref(bernoulli_cache + k - 1), (k + 1) * (k + 2)); acb_sub_fmpz(s, s, c, prec); acb_div_fmpz(s, s, d, prec); } acb_mul(s, s, w, prec); acb_mul_2exp_si(s, s, 1); acb_sub_ui(s, s, 3, prec); acb_mul(s, s, w2, prec); acb_mul_2exp_si(s, s, -1); acb_const_pi(w2, prec); acb_addmul(s, w2, w2, prec); acb_div_ui(s, s, 6, prec); acb_neg(w2, w); acb_log(w2, w2, prec); acb_submul(s, w2, w, prec); acb_add(res, s, w, prec); acb_add_error_mag(res, err); if (real) arb_zero(acb_imagref(res)); } else { acb_indeterminate(res); } acb_clear(s); acb_clear(w); acb_clear(w2); fmpz_clear(c); fmpz_clear(d); mag_clear(m); mag_clear(err); }
void _acb_poly_zeta_cpx_reflect(acb_ptr t, const acb_t h, const acb_t a, int deflate, slong len, slong prec) { /* use reflection formula */ if (arf_sgn(arb_midref(acb_realref(h))) < 0 && acb_is_one(a)) { /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */ acb_t pi, hcopy; acb_ptr f, s1, s2, s3, s4, u; slong i; acb_init(pi); acb_init(hcopy); f = _acb_vec_init(2); s1 = _acb_vec_init(len); s2 = _acb_vec_init(len); s3 = _acb_vec_init(len); s4 = _acb_vec_init(len); u = _acb_vec_init(len); acb_set(hcopy, h); acb_const_pi(pi, prec); /* s1 = (2*pi)**s */ acb_mul_2exp_si(pi, pi, 1); _acb_poly_pow_cpx(s1, pi, h, len, prec); acb_mul_2exp_si(pi, pi, -1); /* s2 = sin(pi*s/2) / pi */ acb_set(f, h); acb_one(f + 1); acb_mul_2exp_si(f, f, -1); acb_mul_2exp_si(f + 1, f + 1, -1); _acb_poly_sin_pi_series(s2, f, 2, len, prec); _acb_vec_scalar_div(s2, s2, len, pi, prec); /* s3 = gamma(1-s) */ acb_sub_ui(f, hcopy, 1, prec); acb_neg(f, f); acb_set_si(f + 1, -1); _acb_poly_gamma_series(s3, f, 2, len, prec); /* s4 = zeta(1-s) */ acb_sub_ui(f, hcopy, 1, prec); acb_neg(f, f); _acb_poly_zeta_cpx_series(s4, f, a, 0, len, prec); for (i = 1; i < len; i += 2) acb_neg(s4 + i, s4 + i); _acb_poly_mullow(u, s1, len, s2, len, len, prec); _acb_poly_mullow(s1, s3, len, s4, len, len, prec); _acb_poly_mullow(t, u, len, s1, len, len, prec); /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */ if (deflate) { acb_sub_ui(u, hcopy, 1, prec); acb_neg(u, u); acb_inv(u, u, prec); for (i = 1; i < len; i++) acb_mul(u + i, u + i - 1, u, prec); _acb_vec_add(t, t, u, len, prec); } acb_clear(pi); acb_clear(hcopy); _acb_vec_clear(f, 2); _acb_vec_clear(s1, len); _acb_vec_clear(s2, len); _acb_vec_clear(s3, len); _acb_vec_clear(s4, len); _acb_vec_clear(u, len); } else { _acb_poly_zeta_cpx_series(t, h, a, deflate, len, prec); } }
int main() { slong iter; flint_rand_t state; flint_printf("laguerre_l...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 2000 * arb_test_multiplier(); iter++) { acb_t n, m, n1, m1, z, res1, res2, res3, s; slong prec; acb_init(n); acb_init(m); acb_init(n1); acb_init(m1); acb_init(z); acb_init(res1); acb_init(res2); acb_init(res3); acb_init(s); prec = 2 + n_randint(state, 200); if (n_randint(state, 2)) { acb_set_si(n, n_randint(state, 20) - 10); acb_set_si(m, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), 10); acb_randtest_param(m, state, 1 + n_randint(state, 400), 10); } acb_randtest_param(z, state, 1 + n_randint(state, 400), 10); acb_sub_ui(n1, n, 1, prec); acb_sub_ui(m1, m, 1, prec); acb_hypgeom_laguerre_l(res1, n, m, z, prec); acb_hypgeom_laguerre_l(res2, n1, m, z, 2 + n_randint(state, 200)); acb_hypgeom_laguerre_l(res3, n, m1, z, 2 + n_randint(state, 200)); acb_add(s, res2, res3, prec); if (acb_is_finite(res1) && acb_is_finite(s) && !acb_overlaps(res1, s)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("m = "); acb_printd(m, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_printf("res3 = "); acb_printd(res3, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); abort(); } acb_clear(n); acb_clear(m); acb_clear(n1); acb_clear(m1); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(res3); acb_clear(s); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void acb_hypgeom_erf_asymp(acb_t res, const acb_t z, int complementary, slong prec, slong prec2) { acb_t a, t, u; acb_init(a); acb_init(t); acb_init(u); if (!acb_is_exact(z) && (arf_cmpabs_ui(arb_midref(acb_realref(z)), prec) < 0) && (arf_cmpabs_ui(arb_midref(acb_imagref(z)), prec) < 0)) { acb_t zmid; mag_t re_err, im_err; acb_init(zmid); mag_init(re_err); mag_init(im_err); acb_hypgeom_erf_propagated_error(re_err, im_err, z); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); acb_hypgeom_erf_asymp(res, zmid, complementary, prec, prec2); arb_add_error_mag(acb_realref(res), re_err); arb_add_error_mag(acb_imagref(res), im_err); acb_clear(zmid); mag_clear(re_err); mag_clear(im_err); return; } acb_one(a); acb_mul_2exp_si(a, a, -1); acb_mul(t, z, z, prec2); acb_hypgeom_u_asymp(u, a, a, t, -1, prec2); acb_neg(t, t); acb_exp(t, t, prec2); acb_mul(u, u, t, prec2); arb_const_sqrt_pi(acb_realref(t), prec2); arb_zero(acb_imagref(t)); acb_mul(t, t, z, prec2); acb_div(u, u, t, prec2); /* branch cut term: -1 or 1 */ acb_csgn(acb_realref(t), z); arb_zero(acb_imagref(t)); if (complementary) { /* erfc(z) = 1 - erf(z) = u - (sgn - 1) */ acb_sub_ui(t, t, 1, prec); acb_sub(t, u, t, prec); } else { /* erf(z) = sgn - u */ acb_sub(t, t, u, prec); } if (arb_is_zero(acb_imagref(z))) { arb_zero(acb_imagref(t)); } else if (arb_is_zero(acb_realref(z))) { if (complementary) arb_one(acb_realref(t)); else arb_zero(acb_realref(t)); } acb_set(res, t); acb_clear(a); acb_clear(t); acb_clear(u); }
/* 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); }
int main() { slong iter; flint_rand_t state; flint_printf("jacobi_p...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000; iter++) { acb_t n, a, b, n1, a1, b1, z, res1, res2, res3, s; slong prec; acb_init(n); acb_init(a); acb_init(b); acb_init(n1); acb_init(a1); acb_init(b1); acb_init(z); acb_init(res1); acb_init(res2); acb_init(res3); acb_init(s); prec = 2 + n_randint(state, 300); if (n_randint(state, 2)) { acb_set_si(n, n_randint(state, 20) - 10); acb_set_si(a, n_randint(state, 20) - 10); acb_set_si(b, n_randint(state, 20) - 10); } else { acb_randtest_param(n, state, 1 + n_randint(state, 400), 10); acb_randtest_param(a, state, 1 + n_randint(state, 400), 10); acb_randtest_param(b, state, 1 + n_randint(state, 400), 10); } acb_randtest_param(z, state, 1 + n_randint(state, 400), 10); acb_sub_ui(n1, n, 1, prec); acb_sub_ui(a1, a, 1, prec); acb_sub_ui(b1, b, 1, prec); acb_hypgeom_jacobi_p(res1, n, a, b1, z, prec); acb_hypgeom_jacobi_p(res2, n, a1, b, z, 2 + n_randint(state, 300)); acb_hypgeom_jacobi_p(res3, n1, a, b, z, 2 + n_randint(state, 300)); acb_sub(s, res1, res2, prec); if (!acb_overlaps(s, res3)) { flint_printf("FAIL: consistency\n\n"); flint_printf("iter = %wd\n\n", iter); flint_printf("n = "); acb_printd(n, 30); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, 30); flint_printf("\n\n"); flint_printf("b = "); acb_printd(b, 30); flint_printf("\n\n"); flint_printf("z = "); acb_printd(z, 30); flint_printf("\n\n"); flint_printf("res1 = "); acb_printd(res1, 30); flint_printf("\n\n"); flint_printf("res2 = "); acb_printd(res2, 30); flint_printf("\n\n"); flint_printf("res3 = "); acb_printd(res3, 30); flint_printf("\n\n"); flint_printf("s = "); acb_printd(s, 30); flint_printf("\n\n"); abort(); } acb_clear(n); acb_clear(a); acb_clear(b); acb_clear(n1); acb_clear(a1); acb_clear(b1); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(res3); acb_clear(s); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }