void acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { ulong k1, k2, m1, m2, g, e, m; ulong * v1, * v2; slong *v; nmod_t expo; acb_t z; v1 = flint_malloc(G->q * sizeof(ulong)); v2 = flint_malloc(G->q * sizeof(ulong)); dirichlet_vec_set_null(v1, G, G->q); dirichlet_chi_vec_loop(v1, G, chi1, G->q); dirichlet_vec_set_null(v2, G, G->q); dirichlet_chi_vec_loop(v2, G, chi2, G->q); nmod_init(&expo, G->expo); m1 = dirichlet_order_char(G, chi1); m2 = dirichlet_order_char(G, chi2); g = m1 * m2 / n_gcd(m1, m2); m = G->expo / g; v = flint_malloc(g * sizeof(slong)); for (e = 0; e < g; e++) v[e] = 0; for (k1 = 2, k2 = G->q - 1; k2 > 1; k1++, k2--) { if (v1[k1] == DIRICHLET_CHI_NULL || v2[k2] == DIRICHLET_CHI_NULL) continue; e = nmod_add(v1[k1], v2[k2], expo) / m; v[e]++; } acb_init(z); acb_unit_root(z, g, prec); acb_dirichlet_si_poly_evaluate(res, v, g, z, prec); acb_clear(z); flint_free(v); flint_free(v2); flint_free(v1); }
void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec) { slong k; ulong * a, order; acb_dirichlet_roots_t t; a = flint_malloc(nv * sizeof(ulong)); order = dirichlet_order_char(G, chi); dirichlet_chi_vec_order(a, G, chi, order, nv); acb_dirichlet_roots_init(t, order, nv, prec); acb_zero(v + 0); for (k = 0; k < nv; k++) { if (a[k] != DIRICHLET_CHI_NULL) acb_dirichlet_root(v + k, t, a[k], prec); else acb_zero(v + k); } acb_dirichlet_roots_clear(t); flint_free(a); }
void acb_dirichlet_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec) { slong len; ulong order; arb_t xt; mag_t e; len = acb_dirichlet_theta_length(G->q, t, prec); arb_init(xt); _acb_dirichlet_theta_argument_at_arb(xt, G->q, t, prec); mag_init(e); mag_tail_kexpk2_arb(e, xt, len); arb_neg(xt, xt); arb_exp(xt, xt, prec); /* TODO: tune this limit */ order = dirichlet_order_char(G, chi); if (order < 30) _acb_dirichlet_theta_arb_smallorder(res, G, chi, xt, len, prec); else _acb_dirichlet_theta_arb_naive(res, G, chi, xt, len, prec); arb_add_error_mag(acb_realref(res), e); arb_add_error_mag(acb_imagref(res), e); mag_clear(e); acb_mul_2exp_si(res, res, 1); arb_clear(xt); }
static ulong do_charplusorder(ulong q1, ulong q2) { ulong n, q, k; for (n = 0, q = q1; q <= q2; q++) { dirichlet_group_t G; dirichlet_char_t x; dirichlet_group_init(G, q); dirichlet_char_init(x, G); dirichlet_char_one(x, G); n++; for (; dirichlet_char_next(x, G) >= 0; n++) dirichlet_order_char(G, x); dirichlet_char_clear(x); dirichlet_group_clear(G); } return n; }
void _acb_dirichlet_theta_arb_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec) { ulong order, * a; acb_dirichlet_roots_t z; int parity; parity = dirichlet_parity_char(G, chi); order = dirichlet_order_char(G, chi); a = flint_malloc(len * sizeof(ulong)); dirichlet_chi_vec_order(a, G, chi, order, len); acb_dirichlet_roots_init(z, order, len, prec); acb_dirichlet_qseries_arb_powers_naive(res, xt, parity, a, z, len, prec); acb_dirichlet_roots_clear(z); flint_free(a); }
int main() { slong iter, bits; flint_rand_t state; flint_printf("properties...."); fflush(stdout); flint_randinit(state); for (bits = 5; bits <= 30; bits += 5) { for (iter = 0; iter < 50; iter++) { dirichlet_group_t G; dirichlet_char_t chi, psi; ulong q, iter2; q = 2 + n_randint(state, 1 << bits); dirichlet_group_init(G, q); dirichlet_char_init(chi, G); dirichlet_char_init(psi, G); /* check number char properties */ for (iter2 = 0; iter2 < 100; iter2++) { ulong m, n; ulong p1, p2, pairing, cm, cn, q2, q3; dirichlet_group_t G2, G3; dirichlet_char_t chi2, chi3; if (iter2 == 50) dirichlet_group_dlog_precompute(G, 5); /* one random character */ do m = n_randint(state, q); while (n_gcd(q, m) > 1); dirichlet_char_log(chi, G, m); p1 = dirichlet_order_ui(G, m); p2 = dirichlet_order_char(G, chi); check_eq(p1, p2, q, m, "order m", "order chi"); p1 = dirichlet_conductor_ui(G, m); p2 = dirichlet_conductor_char(G, chi); check_eq(p1, p2, q, m, "conductor m", "conductor chi"); p1 = dirichlet_parity_ui(G, m); p2 = dirichlet_parity_char(G, chi); check_eq(p1, p2, q, m, "parity m", "parity chi"); p1 = dirichlet_char_is_real(G, chi); p2 = (dirichlet_order_char(G, chi) <= 2); check_eq(p1, p2, q, m, "is_real", "(order <= 2)"); /* check index */ p1 = dirichlet_index_char(G, chi); dirichlet_char_index(psi, G, p1); if (!dirichlet_char_eq_deep(G, chi, psi)) { flint_printf("FAIL: index\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("chi = "); dirichlet_char_print(G, chi); flint_printf("\n\nindex(chi) = %wu\n\n", p1); flint_printf("psi(index) = %wu\n\n", psi->n); flint_printf("psi = "); dirichlet_char_print(G, psi); flint_printf("\n\n"); abort(); } /* lift to higher modulus */ q2 = q * (1 + n_randint(state, 100)); dirichlet_group_init(G2, q2); dirichlet_char_init(chi2, G2); dirichlet_char_lift(chi2, G2, chi, G); p1 = dirichlet_conductor_char(G, chi); p2 = dirichlet_conductor_char(G2, chi2); check_eq(p1, p2, q, m, "conductor chi", "conductor lift"); p1 = dirichlet_order_char(G, chi); p2 = dirichlet_order_char(G2, chi2); check_eq(p1, p2, q, m, "order chi", "order lift"); /* and lower */ dirichlet_char_lower(psi, G, chi2, G2); if (!dirichlet_char_eq_deep(G, chi, psi)) { flint_printf("FAIL: lift and lower back\n\n"); flint_printf("q = %wu\n\nchi = ", q); dirichlet_char_print(G, chi); flint_printf("\n\nq2 = %wu\n\nchi2 = ", q2); dirichlet_char_print(G2, chi2); flint_printf("\n\nq = %wu\n\npsi = ", q); dirichlet_char_print(G, psi); flint_printf("\n\n"); abort(); } q3 = dirichlet_conductor_char(G, chi) * random_divisor(state, G); q3 = n_gcd(q, q3); dirichlet_group_init(G3, q3); dirichlet_char_init(chi3, G3); dirichlet_char_lower(chi3, G3, chi2, G2); p1 = dirichlet_conductor_char(G, chi); p2 = dirichlet_conductor_char(G3, chi3); check_eq(p1, p2, q, m, "conductor chi", "conductor lower"); p1 = dirichlet_order_char(G, chi); p2 = dirichlet_order_char(G3, chi3); check_eq(p1, p2, q, m, "order chi", "order lower"); dirichlet_char_clear(chi3); dirichlet_group_clear(G3); dirichlet_char_clear(chi2); dirichlet_group_clear(G2); /* another random character */ do n = n_randint(state, q); while (n_gcd(q, n) > 1); dirichlet_char_log(psi, G, n); pairing = dirichlet_pairing(G, m, n); cn = dirichlet_chi(G, chi, n); cm = dirichlet_chi(G, psi, m); if (pairing != cn || pairing != cm) { flint_printf("FAIL: pairing\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("n = %wu\n\n", n); flint_printf("chi(m,n) = %wu\n\n", pairing); flint_printf("chi(m)(n) = %wu\n\n", cn); flint_printf("chi(n)(m) = %wu\n\n", cm); abort(); } } dirichlet_group_dlog_clear(G); dirichlet_char_clear(chi); dirichlet_char_clear(psi); dirichlet_group_clear(G); } } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }