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); }
int main() { slong iter; flint_rand_t state; flint_printf("chi...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { acb_t zn1, zn2, zn1n2, zn1zn2; dirichlet_group_t G; dirichlet_char_t chi; ulong q, m, n1, n2, iter2; int res; q = 1 + n_randint(state, 1000); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); acb_init(zn1); acb_init(zn2); acb_init(zn1n2); acb_init(zn1zn2); /* check chi(n1) chi(n2) = chi(n1 n2) */ for (iter2 = 0; iter2 < 10; iter2++) { do { m = 1 + n_randint(state, q); } while (n_gcd(q, m) != 1); dirichlet_char_log(chi, G, m); n1 = n_randint(state, 1000); n2 = n_randint(state, 1000); acb_dirichlet_chi(zn1, G, chi, n1, 53); acb_dirichlet_pairing(zn2, G, m, n1, 53); if (!acb_overlaps(zn1, zn2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("n = %wu\n\n", n1); flint_printf("char = "); acb_printd(zn1, 15); flint_printf("\n\n"); flint_printf("pairing = "); acb_printd(zn2, 15); flint_printf("\n\n"); dirichlet_char_print(G, chi); dirichlet_char_log(chi, G, m); flint_printf("log(m) = "); dirichlet_char_print(G, chi); dirichlet_char_log(chi, G, n1); flint_printf("log(n1) = "); dirichlet_char_print(G, chi); flint_abort(); } acb_dirichlet_pairing(zn2, G, m, n2, 53); acb_dirichlet_pairing(zn1n2, G, m, n1 * n2, 53); acb_mul(zn1zn2, zn1, zn2, 53); if (!acb_overlaps(zn1n2, zn1zn2)) { flint_printf("FAIL: overlap\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("n1 = %wu\n\n", n1); flint_printf("n2 = %wu\n\n", n2); flint_printf("zn1 = "); acb_printd(zn1, 15); flint_printf("\n\n"); flint_printf("zn2 = "); acb_printd(zn2, 15); flint_printf("\n\n"); flint_printf("zn1n2 = "); acb_printd(zn1n2, 15); flint_printf("\n\n"); flint_printf("zn1zn2 = "); acb_printd(zn1zn2, 15); flint_printf("\n\n"); flint_abort(); } } if (iter % 10 == 0) { /* check orthogonality */ acb_zero(zn1); n1 = n_randint(state, 1000); for (m = 1; m <= q; m++) { if (n_gcd(q, m) == 1) { acb_dirichlet_pairing(zn2, G, m, n1, 53); acb_add(zn1, zn1, zn2, 53); } } if (n1 % q == 1 % q) res = arb_contains_si(acb_realref(zn1), n_euler_phi(q)) && arb_contains_zero(acb_imagref(zn1)); else res = acb_contains_zero(zn1); if (!res) { flint_printf("FAIL: orthogonality\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("phi = %wu\n\n", n_euler_phi(q)); flint_printf("n1 = %wu\n\n", n1); flint_printf("zn1 = "); acb_printd(zn1, 15); flint_printf("\n\n"); flint_abort(); } } dirichlet_group_clear(G); dirichlet_char_clear(chi); acb_clear(zn1); acb_clear(zn2); acb_clear(zn1n2); acb_clear(zn1zn2); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }