void acb_sinc_pi(acb_t res, const acb_t x, slong prec) { mag_t m; acb_t t; if (acb_is_zero(x)) { acb_one(res); return; } mag_init(m); acb_init(t); acb_get_mag_lower(m, x); if (mag_cmp_2exp_si(m, -1) > 0) { acb_const_pi(t, prec + 4); acb_mul(t, t, x, prec + 4); acb_sin_pi(res, x, prec + 4); acb_div(res, res, t, prec); } else { acb_const_pi(t, prec + 4); acb_mul(t, t, x, prec + 4); acb_sinc(res, t, prec); } mag_clear(m); acb_clear(t); }
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); }
/* 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() { 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; }
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() { long iter; flint_rand_t state; printf("legendre_q...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000; iter++) { acb_t n, m, z, res1, res2; long prec1, prec2, ebits; acb_init(n); acb_init(m); acb_init(z); acb_init(res1); acb_init(res2); 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_hypgeom_legendre_q_single(res1, n, m, z, prec1); _acb_hypgeom_legendre_q_double(res2, n, m, z, prec2); if (!acb_overlaps(res1, res2)) { printf("FAIL: consistency 1\n\n"); printf("iter = %ld, prec1 = %ld, prec2 = %ld\n\n", iter, prec1, prec2); printf("m = "); acb_printd(m, 30); printf("\n\n"); printf("n = "); acb_printd(n, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("res1 = "); acb_printd(res1, 30); printf("\n\n"); printf("res2 = "); acb_printd(res2, 30); printf("\n\n"); abort(); } acb_clear(n); acb_clear(m); acb_clear(z); acb_clear(res1); acb_clear(res2); } for (iter = 0; iter < 2000; iter++) { acb_t n, m, z, res1, res2, t, u; long prec1, prec2, ebits; int type; acb_init(n); acb_init(m); acb_init(z); acb_init(res1); acb_init(res2); 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); type = n_randint(state, 2); acb_hypgeom_legendre_q(res1, n, m, z, type, prec1); acb_neg(t, m); acb_hypgeom_legendre_p(res2, n, t, z, type, prec2); acb_add(u, m, n, prec2); acb_add_ui(u, u, 1, prec2); acb_gamma(u, u, prec2); acb_mul(res2, res2, u, prec2); acb_sub(u, n, m, prec2); acb_add_ui(u, u, 1, prec2); acb_rgamma(u, u, prec2); acb_mul(res2, res2, u, prec2); acb_hypgeom_legendre_p(t, n, m, z, type, prec2); if (type == 0) { acb_cos_pi(u, m, prec2); acb_mul(t, t, u, prec2); } acb_sub(res2, t, res2, prec2); if (type == 1) { acb_exp_pi_i(t, m, prec2); acb_mul(res2, res2, t, prec2); } acb_sin_pi(t, m, prec2); if (acb_contains_zero(t)) acb_indeterminate(res2); else acb_div(res2, res2, t, prec2); acb_const_pi(t, prec2); acb_mul(res2, res2, t, prec2); acb_mul_2exp_si(res2, res2, -1); if (!acb_overlaps(res1, res2)) { printf("FAIL: consistency 2\n\n"); printf("iter = %ld, prec1 = %ld, prec2 = %ld\n\n", iter, prec1, prec2); printf("type = %d\n\n", type); printf("m = "); acb_printd(m, 30); printf("\n\n"); printf("n = "); acb_printd(n, 30); printf("\n\n"); printf("z = "); acb_printd(z, 30); printf("\n\n"); printf("res1 = "); acb_printd(res1, 30); printf("\n\n"); printf("res2 = "); acb_printd(res2, 30); printf("\n\n"); abort(); } acb_clear(n); acb_clear(m); acb_clear(z); acb_clear(res1); acb_clear(res2); acb_clear(t); acb_clear(u); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
void acb_hypgeom_2f1_transform_nolimit(acb_t res, const acb_t a, const acb_t b, const acb_t c, const acb_t z, int regularized, int which, slong prec) { acb_t ba, ca, cb, cab, ac1, bc1, ab1, ba1, w, t, u, v, s; if (acb_contains_zero(z) || !acb_is_finite(z)) { acb_indeterminate(res); return; } if (arb_contains_si(acb_realref(z), 1) && arb_contains_zero(acb_imagref(z))) { acb_indeterminate(res); return; } if (!regularized) { acb_init(t); acb_gamma(t, c, prec); acb_hypgeom_2f1_transform_nolimit(res, a, b, c, z, 1, which, prec); acb_mul(res, res, t, prec); acb_clear(t); return; } acb_init(ba); acb_init(ca); acb_init(cb); acb_init(cab); acb_init(ac1); acb_init(bc1); acb_init(ab1); acb_init(ba1); acb_init(w); acb_init(t); acb_init(u); acb_init(v); acb_init(s); acb_add_si(s, z, -1, prec); /* s = 1 - z */ acb_neg(s, s); acb_sub(ba, b, a, prec); /* ba = b - a */ acb_sub(ca, c, a, prec); /* ca = c - a */ acb_sub(cb, c, b, prec); /* cb = c - b */ acb_sub(cab, ca, b, prec); /* cab = c - a - b */ acb_add_si(ac1, ca, -1, prec); acb_neg(ac1, ac1); /* ac1 = a - c + 1 */ acb_add_si(bc1, cb, -1, prec); acb_neg(bc1, bc1); /* bc1 = b - c + 1 */ acb_add_si(ab1, ba, -1, prec); acb_neg(ab1, ab1); /* ab1 = a - b + 1 */ acb_add_si(ba1, ba, 1, prec); /* ba1 = b - a + 1 */ /* t = left term, u = right term (DLMF 15.8.1 - 15.8.5) */ if (which == 2) { acb_inv(w, z, prec); /* w = 1/z */ acb_hypgeom_2f1_direct(t, a, ac1, ab1, w, 1, prec); acb_hypgeom_2f1_direct(u, b, bc1, ba1, w, 1, prec); } else if (which == 3) { acb_inv(w, s, prec); /* w = 1/(1-z) */ acb_hypgeom_2f1_direct(t, a, cb, ab1, w, 1, prec); acb_hypgeom_2f1_direct(u, b, ca, ba1, w, 1, prec); } else if (which == 4) { acb_set(w, s); /* w = 1-z */ acb_add(v, ac1, b, prec); /* v = a+b-c+1 */ acb_hypgeom_2f1_direct(t, a, b, v, w, 1, prec); acb_add_si(v, cab, 1, prec); /* v = c-a-b+1 */ acb_hypgeom_2f1_direct(u, ca, cb, v, w, 1, prec); } else if (which == 5) { acb_inv(w, z, prec); /* w = 1-1/z */ acb_neg(w, w); acb_add_si(w, w, 1, prec); acb_add(v, ac1, b, prec); /* v = a+b-c+1 */ acb_hypgeom_2f1_direct(t, a, ac1, v, w, 1, prec); acb_add_si(v, cab, 1, prec); /* v = c-a-b+1 */ acb_add_si(u, a, -1, prec); /* u = 1-a */ acb_neg(u, u); acb_hypgeom_2f1_direct(u, ca, u, v, w, 1, prec); } else { flint_printf("invalid transformation!\n"); flint_abort(); } /* gamma factors */ acb_rgamma(v, a, prec); acb_mul(u, u, v, prec); acb_rgamma(v, ca, prec); acb_mul(t, t, v, prec); acb_rgamma(v, b, prec); if (which == 2 || which == 3) acb_mul(t, t, v, prec); else acb_mul(u, u, v, prec); acb_rgamma(v, cb, prec); if (which == 2 || which == 3) acb_mul(u, u, v, prec); else acb_mul(t, t, v, prec); if (which == 2 || which == 3) { if (which == 2) acb_neg(s, z); /* -z, otherwise 1-z since before */ acb_neg(v, a); acb_pow(v, s, v, prec); acb_mul(t, t, v, prec); acb_neg(v, b); acb_pow(v, s, v, prec); acb_mul(u, u, v, prec); } else { acb_pow(v, s, cab, prec); acb_mul(u, u, v, prec); if (which == 5) { acb_neg(v, a); acb_pow(v, z, v, prec); acb_mul(t, t, v, prec); acb_neg(v, ca); acb_pow(v, z, v, prec); acb_mul(u, u, v, prec); } } acb_sub(t, t, u, prec); if (which == 2 || which == 3) acb_sin_pi(v, ba, prec); else acb_sin_pi(v, cab, prec); acb_div(t, t, v, prec); acb_const_pi(v, prec); acb_mul(t, t, v, prec); acb_set(res, t); acb_clear(ba); acb_clear(ca); acb_clear(cb); acb_clear(cab); acb_clear(ac1); acb_clear(bc1); acb_clear(ab1); acb_clear(ba1); acb_clear(w); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(s); }
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); }
int main() { slong iter; flint_rand_t state; flint_printf("sin_pi...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++) { acb_t x, y, a, b, c; slong prec1, prec2; prec1 = 2 + n_randint(state, 1000); prec2 = prec1 + 30; acb_init(x); acb_init(y); acb_init(a); acb_init(b); acb_init(c); acb_randtest(x, state, 1 + n_randint(state, 1000), 2 + n_randint(state, 100)); acb_sin_pi(a, x, prec1); acb_sin_pi(b, x, prec2); /* check consistency */ if (!acb_overlaps(a, b)) { flint_printf("FAIL: overlap\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("b = "); acb_print(b); flint_printf("\n\n"); abort(); } /* compare with cos */ arb_const_pi(acb_realref(c), prec1); acb_mul_arb(y, x, acb_realref(c), prec1); acb_sin(c, y, prec1); if (!acb_overlaps(a, c)) { flint_printf("FAIL: functional equation\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); flint_printf("y = "); acb_print(y); flint_printf("\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("c = "); acb_print(c); flint_printf("\n\n"); abort(); } acb_sin_pi(x, x, prec1); if (!acb_overlaps(a, x)) { flint_printf("FAIL: aliasing\n\n"); flint_printf("a = "); acb_print(a); flint_printf("\n\n"); flint_printf("x = "); acb_print(x); flint_printf("\n\n"); abort(); } acb_clear(x); acb_clear(y); acb_clear(a); acb_clear(b); acb_clear(c); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
static void acb_log_sin_pi_half(acb_t res, const acb_t z, slong prec, int upper) { acb_t t, u, zmid; arf_t n; arb_t pi; acb_init(t); acb_init(u); acb_init(zmid); arf_init(n); arb_init(pi); arf_set(arb_midref(acb_realref(zmid)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_imagref(zmid)), arb_midref(acb_imagref(z))); arf_floor(n, arb_midref(acb_realref(zmid))); arb_sub_arf(acb_realref(zmid), acb_realref(zmid), n, prec); arb_const_pi(pi, prec); if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(zmid)), 2) < 1) { acb_sin_pi(t, zmid, prec); acb_log(t, t, prec); } else /* i*pi*(z-0.5) + log((1-exp(-2i*pi*z))/2) */ { acb_mul_2exp_si(t, zmid, 1); acb_neg(t, t); if (upper) acb_conj(t, t); acb_exp_pi_i(t, t, prec); acb_sub_ui(t, t, 1, prec); acb_neg(t, t); acb_mul_2exp_si(t, t, -1); acb_log(t, t, prec); acb_one(u); acb_mul_2exp_si(u, u, -1); acb_sub(u, zmid, u, prec); if (upper) acb_conj(u, u); acb_mul_onei(u, u); acb_addmul_arb(t, u, pi, prec); if (upper) acb_conj(t, t); } if (upper) arb_submul_arf(acb_imagref(t), pi, n, prec); else arb_addmul_arf(acb_imagref(t), pi, n, prec); /* propagated error bound from the derivative pi cot(pi z) */ if (!acb_is_exact(z)) { mag_t zm, um; mag_init(zm); mag_init(um); acb_cot_pi(u, z, prec); acb_mul_arb(u, u, pi, prec); mag_hypot(zm, arb_radref(acb_realref(z)), arb_radref(acb_imagref(z))); acb_get_mag(um, u); mag_mul(um, um, zm); acb_add_error_mag(t, um); mag_clear(zm); mag_clear(um); } acb_set(res, t); acb_clear(t); acb_clear(u); acb_clear(zmid); arf_clear(n); arb_clear(pi); }