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_hurwitz_zeta(acb_t z, const acb_t s, const acb_t a, slong prec) { if (acb_is_one(a) && acb_is_int(s) && arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), FLINT_BITS - 1) < 0) { acb_zeta_si(z, arf_get_si(arb_midref(acb_realref(s)), ARF_RND_DOWN), prec); return; } _acb_poly_zeta_cpx_series(z, s, a, 0, 1, prec); }
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("zeta_cpx_series...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++) { acb_t s, a; acb_ptr z1, z2; slong i, len, prec1, prec2; int deflate; acb_init(s); acb_init(a); if (n_randint(state, 2)) { acb_randtest(s, state, 1 + n_randint(state, 300), 3); } else { arb_set_ui(acb_realref(s), 1); arb_mul_2exp_si(acb_realref(s), acb_realref(s), -1); arb_randtest(acb_imagref(s), state, 1 + n_randint(state, 300), 4); } switch (n_randint(state, 3)) { case 0: acb_randtest(a, state, 1 + n_randint(state, 300), 3); break; case 1: arb_randtest(acb_realref(a), state, 1 + n_randint(state, 300), 3); break; case 2: acb_one(a); break; } prec1 = 2 + n_randint(state, 300); prec2 = prec1 + 30; len = 1 + n_randint(state, 20); deflate = n_randint(state, 2); z1 = _acb_vec_init(len); z2 = _acb_vec_init(len); _acb_poly_zeta_cpx_series(z1, s, a, deflate, len, prec1); _acb_poly_zeta_cpx_series(z2, s, a, deflate, len, prec2); for (i = 0; i < len; i++) { if (!acb_overlaps(z1 + i, z2 + i)) { flint_printf("FAIL: overlap\n\n"); flint_printf("iter = %wd\n", iter); flint_printf("deflate = %d, len = %wd, i = %wd\n\n", deflate, len, i); flint_printf("s = "); acb_printd(s, prec1 / 3.33); flint_printf("\n\n"); flint_printf("a = "); acb_printd(a, prec1 / 3.33); flint_printf("\n\n"); flint_printf("z1 = "); acb_printd(z1 + i, prec1 / 3.33); flint_printf("\n\n"); flint_printf("z2 = "); acb_printd(z2 + i, prec2 / 3.33); flint_printf("\n\n"); abort(); } } acb_clear(a); acb_clear(s); _acb_vec_clear(z1, len); _acb_vec_clear(z2, len); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
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); } }
void _arb_poly_zeta_series(arb_ptr res, arb_srcptr h, long hlen, const arb_t a, int deflate, long len, long prec) { long i; acb_t cs, ca; acb_ptr z; arb_ptr t, u; if (arb_contains_nonpositive(a)) { _arb_vec_indeterminate(res, len); return; } hlen = FLINT_MIN(hlen, len); z = _acb_vec_init(len); t = _arb_vec_init(len); u = _arb_vec_init(len); acb_init(cs); acb_init(ca); /* use reflection formula */ if (arf_sgn(arb_midref(h)) < 0 && arb_is_one(a)) { /* zeta(s) = (2*pi)**s * sin(pi*s/2) / pi * gamma(1-s) * zeta(1-s) */ arb_t pi; arb_ptr f, s1, s2, s3, s4; arb_init(pi); f = _arb_vec_init(2); s1 = _arb_vec_init(len); s2 = _arb_vec_init(len); s3 = _arb_vec_init(len); s4 = _arb_vec_init(len); arb_const_pi(pi, prec); /* s1 = (2*pi)**s */ arb_mul_2exp_si(pi, pi, 1); _arb_poly_pow_cpx(s1, pi, h, len, prec); arb_mul_2exp_si(pi, pi, -1); /* s2 = sin(pi*s/2) / pi */ arb_set(f, h); arb_one(f + 1); arb_mul_2exp_si(f, f, -1); arb_mul_2exp_si(f + 1, f + 1, -1); _arb_poly_sin_pi_series(s2, f, 2, len, prec); _arb_vec_scalar_div(s2, s2, len, pi, prec); /* s3 = gamma(1-s) */ arb_sub_ui(f, h, 1, prec); arb_neg(f, f); arb_set_si(f + 1, -1); _arb_poly_gamma_series(s3, f, 2, len, prec); /* s4 = zeta(1-s) */ arb_sub_ui(f, h, 1, prec); arb_neg(f, f); acb_set_arb(cs, f); acb_one(ca); _acb_poly_zeta_cpx_series(z, cs, ca, 0, len, prec); for (i = 0; i < len; i++) arb_set(s4 + i, acb_realref(z + i)); for (i = 1; i < len; i += 2) arb_neg(s4 + i, s4 + i); _arb_poly_mullow(u, s1, len, s2, len, len, prec); _arb_poly_mullow(s1, s3, len, s4, len, len, prec); _arb_poly_mullow(t, u, len, s1, len, len, prec); /* add 1/(1-(s+t)) = 1/(1-s) + t/(1-s)^2 + ... */ if (deflate) { arb_sub_ui(u, h, 1, prec); arb_neg(u, u); arb_inv(u, u, prec); for (i = 1; i < len; i++) arb_mul(u + i, u + i - 1, u, prec); _arb_vec_add(t, t, u, len, prec); } arb_clear(pi); _arb_vec_clear(f, 2); _arb_vec_clear(s1, len); _arb_vec_clear(s2, len); _arb_vec_clear(s3, len); _arb_vec_clear(s4, len); } else { acb_set_arb(cs, h); acb_set_arb(ca, a); _acb_poly_zeta_cpx_series(z, cs, ca, deflate, len, prec); for (i = 0; i < len; i++) arb_set(t + i, acb_realref(z + i)); } /* compose with nonconstant part */ arb_zero(u); _arb_vec_set(u + 1, h + 1, hlen - 1); _arb_poly_compose_series(res, t, len, u, hlen, len, prec); _acb_vec_clear(z, len); _arb_vec_clear(t, len); _arb_vec_clear(u, len); acb_init(cs); acb_init(ca); }