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); } }
void acb_dirichlet_l(acb_t res, const acb_t s, const acb_dirichlet_group_t G, ulong m, slong prec) { acb_t chi, t, u, a; ulong k; acb_init(chi); acb_init(t); acb_init(u); acb_init(a); acb_zero(t); for (k = 1; k <= G->q; k++) { acb_dirichlet_chi(chi, G, m, k, prec); if (!acb_is_zero(chi)) { acb_set_ui(a, k); acb_div_ui(a, a, G->q, prec); acb_hurwitz_zeta(u, s, a, prec); acb_addmul(t, chi, u, prec); } } acb_set_ui(u, G->q); acb_neg(a, s); acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); acb_clear(chi); acb_clear(t); acb_clear(u); acb_clear(a); }
/* 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); }
void acb_dirichlet_hurwitz_precomp_init(acb_dirichlet_hurwitz_precomp_t pre, const acb_t s, int deflate, slong A, slong K, slong N, slong prec) { slong i, k; if (A < 1 || K < 1 || N < 1) abort(); pre->deflate = deflate; pre->A = A; pre->K = K; pre->N = N; pre->coeffs = _acb_vec_init(N * K); mag_init(&pre->err); acb_init(&pre->s); acb_set(&pre->s, s); acb_dirichlet_hurwitz_precomp_bound(&pre->err, s, A, K, N); if (mag_is_finite(&pre->err)) { acb_t t, a; acb_init(t); acb_init(a); /* (-1)^k (s)_k / k! */ acb_one(pre->coeffs + 0); for (k = 1; k < K; k++) { acb_add_ui(pre->coeffs + k, s, k - 1, prec); acb_mul(pre->coeffs + k, pre->coeffs + k, pre->coeffs + k - 1, prec); acb_div_ui(pre->coeffs + k, pre->coeffs + k, k, prec); acb_neg(pre->coeffs + k, pre->coeffs + k); } for (i = 1; i < N; i++) _acb_vec_set(pre->coeffs + i * K, pre->coeffs, K); /* zeta(s+k,a) where a = A + (2*i+1)/(2*N) */ for (i = 0; i < N; i++) { acb_set_ui(a, 2 * i + 1); acb_div_ui(a, a, 2 * N, prec); acb_add_ui(a, a, A, prec); for (k = 0; k < K; k++) { acb_add_ui(t, s, k, prec); if (deflate && k == 0) _acb_poly_zeta_cpx_series(t, t, a, 1, 1, prec); else acb_hurwitz_zeta(t, t, a, prec); acb_mul(pre->coeffs + i * K + k, pre->coeffs + i * K + k, t, prec); } } acb_clear(t); acb_clear(a); } }
int main() { slong iter; flint_rand_t state; flint_printf("hurwitz_zeta...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++) { arb_t a, b, c; acb_t d, e, f; slong prec; prec = 2 + n_randint(state, 300); arb_init(a); arb_init(b); arb_init(c); acb_init(d); acb_init(e); acb_init(f); arb_randtest_precise(a, state, 1 + n_randint(state, 300), 5); arb_randtest_precise(b, state, 1 + n_randint(state, 300), 5); arb_randtest_precise(c, state, 1 + n_randint(state, 300), 5); acb_set_arb(d, a); acb_set_arb(e, b); arb_hurwitz_zeta(c, a, b, prec); acb_hurwitz_zeta(f, d, e, prec); if (!arb_overlaps(c, acb_realref(f)) || (arb_is_finite(c) && !arb_contains_zero(acb_imagref(f)))) { flint_printf("FAIL: overlap\n\n"); flint_printf("a = "); arb_printd(a, 15); flint_printf("\n\n"); flint_printf("b = "); arb_printd(b, 15); flint_printf("\n\n"); flint_printf("c = "); arb_printd(c, 15); flint_printf("\n\n"); flint_printf("d = "); acb_printd(d, 15); flint_printf("\n\n"); flint_printf("e = "); acb_printd(e, 15); flint_printf("\n\n"); flint_printf("f = "); acb_printd(f, 15); flint_printf("\n\n"); flint_abort(); } arb_clear(a); arb_clear(b); arb_clear(c); acb_clear(d); acb_clear(e); acb_clear(f); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }