From 230ec151c6136f931af5af74f6612f56a370ca8f Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Tue, 20 Sep 2016 14:15:30 +0200 Subject: [PATCH 001/139] acb_printn: skip parts that are 0 --- acb/fprintn.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/acb/fprintn.c b/acb/fprintn.c index f6130ea2..95d68168 100644 --- a/acb/fprintn.c +++ b/acb/fprintn.c @@ -15,24 +15,36 @@ void acb_fprintn(FILE * file, const acb_t z, long digits, ulong flags) { - arb_fprintn(file, acb_realref(z), digits, flags); - - if ((arb_is_exact(acb_imagref(z)) || (flags & ARB_STR_NO_RADIUS)) - && arf_sgn(arb_midref(acb_imagref(z))) < 0) + if (arb_is_zero(acb_imagref(z))) { - arb_t t; - arb_init(t); - arb_neg(t, acb_imagref(z)); - flint_fprintf(file, " - "); - arb_fprintn(file, t, digits, flags); - arb_clear(t); + arb_fprintn(file, acb_realref(z), digits, flags); + } + else if (arb_is_zero(acb_realref(z))) + { + arb_fprintn(file, acb_imagref(z), digits, flags); + flint_fprintf(file, "*I"); } else { - flint_fprintf(file, " + "); - arb_fprintn(file, acb_imagref(z), digits, flags); - } + arb_fprintn(file, acb_realref(z), digits, flags); - flint_fprintf(file, "*I"); + if ((arb_is_exact(acb_imagref(z)) || (flags & ARB_STR_NO_RADIUS)) + && arf_sgn(arb_midref(acb_imagref(z))) < 0) + { + arb_t t; + arb_init(t); + arb_neg(t, acb_imagref(z)); + flint_fprintf(file, " - "); + arb_fprintn(file, t, digits, flags); + arb_clear(t); + } + else + { + flint_fprintf(file, " + "); + arb_fprintn(file, acb_imagref(z), digits, flags); + } + + flint_fprintf(file, "*I"); + } } From 46fa64591057d52f71bf51b0f4ec71a04957e8b1 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 24 Feb 2016 11:06:49 +0100 Subject: [PATCH 002/139] [dirichlet] add conrey type to handle logs + char type - try to handle even and odd components the same way in the dirichlet group - switch from phi_q_odd to smaller expo = exponent of the group all character orders divide this number, and a character of that order exists - use conrey logarithm to reuse log and to loop efficiently over the group (see the diff on l.c, only 1 log in computed instead of 2 * q) - NOT TESTED, for the moment it just compiles, I know some errors (e.g. the FIXME in group_init.c : the generators have to be lifted mod q) this commit is just a proof of concept. --- acb_dirichlet.h | 68 +++++++++++++++++-- acb_dirichlet/char.c | 66 ++++++++++++++++++ acb_dirichlet/chareval.c | 56 ++++++++++++++++ acb_dirichlet/charevalvec.c | 67 +++++++++++++++++++ acb_dirichlet/chi.c | 130 +++++++++--------------------------- acb_dirichlet/conrey_log.c | 91 +++++++++++++++++++++++++ acb_dirichlet/group_init.c | 52 ++++++++++----- acb_dirichlet/l.c | 29 +++++--- 8 files changed, 428 insertions(+), 131 deletions(-) create mode 100644 acb_dirichlet/char.c create mode 100644 acb_dirichlet/chareval.c create mode 100644 acb_dirichlet/charevalvec.c create mode 100644 acb_dirichlet/conrey_log.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index da8d5498..fae55e15 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -24,18 +24,30 @@ typedef struct ulong q; /* modulus */ ulong q_even; /* even part of modulus */ ulong q_odd; /* odd part of modulus */ - ulong phi_q; /* phi(q) */ - ulong phi_q_odd; /* phi(q_odd) */ - slong num; /* number of odd prime factors */ - ulong * primes; /* odd primes p[k] */ + ulong phi_q; /* phi(q) = group size */ + ulong expo; /* group exponent = lcm(phi(q_even), phi(p[k]^e[k]) ) */ + slong neven; /* number of even components */ + slong num; /* number of prime components (even + odd) */ + ulong * primes; /* primes p[k] */ ulong * exponents; /* exponents e[k] */ - ulong * generators; /* generator for each odd prime p[k] */ - ulong * PHI; /* PHI(k) = phi(q_odd) / phi(p[k]^e[k]) */ + ulong * generators; /* generator for each prime p[k] */ + ulong * phi; /* phi(k) = phi(p[k]^e[k]) */ + ulong * PHI; /* PHI(k) = expo / phi(k) */ } acb_dirichlet_group_struct; typedef acb_dirichlet_group_struct acb_dirichlet_group_t[1]; +/* elements of the group, keep both number and log */ +typedef struct +{ + ulong n; /* number */ + ulong * log; /* s.t. prod generators[k]^log[k] = number */ +} +acb_conrey_struct; + +typedef acb_conrey_struct acb_conrey_t[1]; + void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, const signed char * chi, int mod, int reciprocal, slong prec); @@ -45,8 +57,52 @@ void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); void acb_dirichlet_group_clear(acb_dirichlet_group_t G); +void acb_conrey_init(acb_conrey_t x, const acb_dirichlet_group_t G); + +void acb_conrey_clear(acb_conrey_t x); + +void acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G); + +void acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m); + +int acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G); + +long n_dirichlet_chi_conrey(const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b); + +long n_dirichlet_chi(const acb_dirichlet_group_t G, ulong m, ulong n); + +void acb_dirichlet_chi_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b, slong prec); + void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec); +/* introducing character type */ + +/* character = reduced exponents, keep its order and number */ +typedef struct +{ + ulong q; /* modulus */ + ulong n; /* number */ + ulong order; /* order */ + ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ +} +acb_dirichlet_char_struct; + +typedef acb_dirichlet_char_struct acb_dirichlet_char_t[1]; + +void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); + +void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); + +void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); + +long n_dirichlet_char_eval(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); + +void acb_dirichlet_char_eval(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); + +void n_dirichlet_char_vec(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); + +void acb_dirichlet_char_vec(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); + #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/char.c b/acb_dirichlet/char.c new file mode 100644 index 00000000..869409bc --- /dev/null +++ b/acb_dirichlet/char.c @@ -0,0 +1,66 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { + chi->expo = flint_malloc(G->num * sizeof(ulong)); +} + +void +acb_dirichlet_char_clear(acb_dirichlet_char_t chi) { + flint_free(chi->expo); +} + +void +acb_dirichlet_char_log(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_conrey_t x) +{ + ulong k, g; + g = G->expo; + /* modify exponents */ + for (k = 0; k < G->num; k++) + { + chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; + g = n_gcd(g, chi->expo[k]); + } + for (k = 0; k < G->num; k++) + chi->expo[k] = chi->expo[k] / g; + + chi->q = G->q; + chi->order = G->expo / g; + chi->n = x->n; +} + +void +acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) +{ + acb_conrey_t x; + x->log = chi->expo; + acb_conrey_log(x, G, n); + acb_dirichlet_char_log(chi, G, x); +} + diff --git a/acb_dirichlet/chareval.c b/acb_dirichlet/chareval.c new file mode 100644 index 00000000..bafdbbdc --- /dev/null +++ b/acb_dirichlet/chareval.c @@ -0,0 +1,56 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +long +n_dirichlet_char_eval(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) +{ + ulong v = 0, k; + acb_conrey_t x; + acb_conrey_init(x, G); + acb_conrey_log(x, G, n); + for (k = 0; k < G->num; k++) + v = (v + chi->expo[k] * x->log[k]) % chi->order; + acb_conrey_clear(x); + return v; +} + +void +fmpq_dirichlet_char_eval(fmpq_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) +{ + fmpq_set_si(res, n_dirichlet_char_eval(G, chi, n), chi->order); +} + +void +acb_dirichlet_char_eval(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) +{ + fmpq_t t; + fmpq_init(t); + fmpq_dirichlet_char_eval(t, G, chi, n); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); +} diff --git a/acb_dirichlet/charevalvec.c b/acb_dirichlet/charevalvec.c new file mode 100644 index 00000000..ddb16efe --- /dev/null +++ b/acb_dirichlet/charevalvec.c @@ -0,0 +1,67 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +static void +set_non_invertible_values(long *v, const acb_dirichlet_group_t G, ulong nv) +{ + ulong k, l; + if (G->q_even > 1) + { + for (k = 2; k < nv; k += 2) + v[k] = -1; + } + for (l = 0; l < G->num; l++) + { + ulong p = G->primes[k]; + for (k = p; k < nv; k += p) + v[k] = -1; + } +} + +void +n_dirichlet_char_vec(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +{ + ulong t, k, j; + acb_conrey_t x; + acb_conrey_init(x, G); + acb_conrey_one(x, G); + t = v[1] = 0; + while( (j = acb_conrey_next(x, G)) < G->num ) { + /* exponents were modified up to j */ + for (k = 0; k < j; k++) + t = (t + chi->expo[k] * x->log[k]) % chi->order; + if (x->n < nv) + v[x->n] = t; + } + /* fix result outside primes */ + set_non_invertible_values(v, G, nv); + /* copy outside modulus */ + for (k = G->q + 1; k < nv ; k++ ) + v[k] = v[k-G->q]; + acb_conrey_clear(x); +} diff --git a/acb_dirichlet/chi.c b/acb_dirichlet/chi.c index 182b0540..fb4223d6 100644 --- a/acb_dirichlet/chi.c +++ b/acb_dirichlet/chi.c @@ -14,114 +14,50 @@ /* todo: modular arithmetic */ -static ulong -chi_odd_exponent(const acb_dirichlet_group_t G, ulong m, ulong n) +long +n_dirichlet_chi_conrey(const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b) { - ulong x, k, pk, gk, logm, logn; - - x = 0; - - for (k = 0; k < G->num; k++) - { - pk = n_pow(G->primes[k], G->exponents[k]); - gk = G->generators[k] % pk; - - logm = n_discrete_log_bsgs(m % pk, gk, pk); - logn = n_discrete_log_bsgs(n % pk, gk, pk); - - x = (x + G->PHI[k] * logm * logn) % G->phi_q_odd; - } - - return x; + ulong x, k; + x = 0; + for (k = 0; k < G->num; k++) + x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; + return x; } -static ulong -chi_even_exponent(const acb_dirichlet_group_t G, ulong m, ulong n) +long +n_dirichlet_chi(const acb_dirichlet_group_t G, ulong m, ulong n) { - ulong x; - ulong q_even = G->q_even; + ulong x; + acb_conrey_t a, b; + acb_conrey_init(a, G); + acb_conrey_init(b, G); - if (q_even <= 2) - return 0; + acb_conrey_log(a, G, m); + acb_conrey_log(b, G, n); + x = n_dirichlet_chi_conrey(G, a, b); - x = 0; + acb_conrey_clear(a); + acb_conrey_clear(b); - if ((m % 4 == 3) && (n % 4 == 3)) - x = q_even / 8; + return x; +} - if (q_even > 4) - { - ulong g2, logm, logn; - - g2 = 5; - - if (m % 4 == 3) - { - m = n_negmod(m, q_even); - } - - if (n % 4 == 3) - { - n = n_negmod(n, q_even); - } - - logm = n_discrete_log_bsgs(m % q_even, g2, q_even); - logn = n_discrete_log_bsgs(n % q_even, g2, q_even); - x += logm * logn; - } - - return x % (q_even / 4); +void +acb_dirichlet_chi_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b, slong prec) +{ + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, n_dirichlet_chi_conrey(G, a, b), G->expo); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); } void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) { - fmpq_t t, u; - - ulong odd_part, even_part; - ulong q_even = G->q_even; - ulong q_odd = G->q_odd; - - if ((q_even > 1 && (n % 2 == 0)) || (q_odd > 1 && (n_gcd(q_odd, n) != 1))) - { - acb_zero(res); - return; - } - - if (q_even > 2) - { - if (q_even == 4) - { - if (m % 4 == 3 && n % 4 == 3) - even_part = q_even / 2; /* -1 */ - else - even_part = 0; /* 1 */ - } - else - { - even_part = 4 * chi_even_exponent(G, m % q_even, n % q_even); - } - } - else - { - even_part = 0; - } - - if (q_odd > 1) - odd_part = chi_odd_exponent(G, m % q_odd, n % q_odd); - else - odd_part = 0; - - fmpq_init(t); - fmpq_init(u); - - fmpq_set_si(t, 2 * even_part, q_even); - fmpq_set_si(u, 2 * odd_part, G->phi_q_odd); - fmpq_add(t, t, u); - - arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); - - fmpq_clear(t); - fmpq_clear(u); + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, n_dirichlet_chi(G, m, n), G->expo); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); } - diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c new file mode 100644 index 00000000..f7dac634 --- /dev/null +++ b/acb_dirichlet/conrey_log.c @@ -0,0 +1,91 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* todo: modular arithmetic + discrete log can be computed along exponents or using p-adic log +*/ + +void +acb_conrey_init(acb_conrey_t x, const acb_dirichlet_group_t G) { + x->log = flint_malloc(G->num * sizeof(ulong)); +} + +void +acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G) { + ulong k; + for (k = 0; k < G->num ; k++) + x->log[k] = 0; + x->n = 1; +} + +void +acb_conrey_clear(acb_conrey_t x) { + flint_free(x->log); +} + +/* TODO: use precomputations in G if present */ +void +acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m) +{ + ulong k, pk, gk; + /* even part */ + if (G->neven >= 1) + x->log[0] = (m % 4 == 3); + if (G->neven == 2) + { + ulong q_even = G->q_even; + ulong g2 = 5; + ulong m2 = (m % 4 == 3) ? n_negmod(m, q_even) : m % q_even; + x->log[1] = n_discrete_log_bsgs(m2, g2, q_even); + } + /* odd part */ + for (k = G->neven; k < G->num; k++) + { + pk = n_pow(G->primes[k], G->exponents[k]); + gk = G->generators[k] % pk; + x->log[k] = n_discrete_log_bsgs(m % pk, gk, pk); + } + /* keep value m */ + x->n = m; +} + +int +acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G) +{ + /* update index */ + ulong k; + for (k=0; k < G->num ; k++) + { + x->n = x->n * G->generators[k]; + if(x->log[k]++ < G->phi[k]) + break; + x->log[k] = 0; + } + /* return last index modified */ + return k; +} diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index a57ff083..8820ed2f 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -36,6 +36,7 @@ void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) { slong k; + ulong e2 = 0; n_factor_t fac; G->q = q; @@ -46,39 +47,56 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) { G->q_odd /= 2; G->q_even *= 2; + e2++; } n_factor_init(&fac); n_factor(&fac, G->q_odd, 1); - G->num = fac.num; + /* number of components at p=2 */ + G->neven = (e2 >= 3) ? 2 : (e2 == 2) ? 1 : 0; + G->num = G->neven + fac.num; G->primes = flint_malloc(G->num * sizeof(ulong)); G->exponents = flint_malloc(G->num * sizeof(ulong)); G->generators = flint_malloc(G->num * sizeof(ulong)); + G->phi = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); - for (k = 0; k < G->num; k++) + /* even part */ + if (G->q_even <= 2) { - G->primes[k] = fac.p[k]; - G->exponents[k] = fac.exp[k]; + G->expo = G->phi_q = 1; + } + else + { + G->phi_q = G->q_even / 2; + G->expo = G->phi_q / 2; } - G->phi_q_odd = 1; - for (k = 0; k < G->num; k++) - G->phi_q_odd *= (G->primes[k] - 1) * n_pow(G->primes[k], G->exponents[k]-1); + for (k = 0; k < G->neven; k++) + { + G->primes[k] = 2; + G->exponents[k] = (k==0) ? 1 : e2-2; + G->generators[k] = (k==0) ? -1 : 5; + G->phi[k] = (k==0) ? 1 : G->expo; + } - if (G->q_even == 1) - G->phi_q = G->phi_q_odd; - else - G->phi_q = G->phi_q_odd * (G->q_even / 2); + for (k = G->neven; k < G->num; k++) + { + ulong phik, p1; + G->primes[k] = fac.p[k - G->neven]; + G->exponents[k] = fac.exp[k - G->neven]; + G->generators[k] = primitive_root_p_and_p2(G->primes[k]); + p1 = G->primes[k] - 1; + phik = p1 * n_pow(G->primes[k], G->exponents[k]-1); + G->expo *= phik / n_gcd(G->expo, p1); + G->phi_q *= phik; + G->phi[k] = phik; + } for (k = 0; k < G->num; k++) { - ulong phi; - - G->generators[k] = primitive_root_p_and_p2(G->primes[k]); - phi = n_pow(G->primes[k], G->exponents[k] - 1) * (G->primes[k] - 1); - G->PHI[k] = G->phi_q_odd / phi; + G->PHI[k] = G->expo / G->phi[k]; + /* FIXME: generators[k] should be lifted mod q! */ } } - diff --git a/acb_dirichlet/l.c b/acb_dirichlet/l.c index 645c36e5..d86ab4b2 100644 --- a/acb_dirichlet/l.c +++ b/acb_dirichlet/l.c @@ -16,26 +16,30 @@ 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_conrey_t cm, cn; acb_init(chi); + acb_conrey_init(cm, G); + acb_conrey_init(cn, G); acb_init(t); acb_init(u); acb_init(a); + acb_conrey_log(cm, G, m); + acb_conrey_one(cn, G); acb_zero(t); - for (k = 1; k <= G->q; k++) - { - acb_dirichlet_chi(chi, G, m, k, prec); + while (1) { + /* todo: use n_dirichlet_chi and precomputed roots instead */ + acb_dirichlet_chi_conrey(chi, G, cm, cn, 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(a, cn->n); + acb_div_ui(a, a, G->q, prec); + acb_hurwitz_zeta(u, s, a, prec); + acb_addmul(t, chi, u, prec); + + if (acb_conrey_next(cn, G) == G->num) + break; } acb_set_ui(u, G->q); @@ -43,6 +47,9 @@ acb_dirichlet_l(acb_t res, const acb_t s, acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); + acb_conrey_clear(cm); + acb_conrey_clear(cn); + acb_clear(chi); acb_clear(t); acb_clear(u); From 7e0eac0d36418059abd5de40034223d928ad8119 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 26 Feb 2016 16:49:26 +0100 Subject: [PATCH 003/139] add next_primitive, first test on conrey elts --- acb_dirichlet.h | 17 +++-- acb_dirichlet/char.c | 123 +++++++++++++++++++++++++++++++--- acb_dirichlet/conrey_log.c | 87 ++++++++++++++++++++---- acb_dirichlet/group_clear.c | 3 +- acb_dirichlet/group_init.c | 57 ++++++++++------ acb_dirichlet/test/t-chi.c | 1 - acb_dirichlet/test/t-conrey.c | 90 +++++++++++++++++++++++++ 7 files changed, 326 insertions(+), 52 deletions(-) create mode 100644 acb_dirichlet/test/t-conrey.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index fae55e15..09025312 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -26,11 +26,12 @@ typedef struct ulong q_odd; /* odd part of modulus */ ulong phi_q; /* phi(q) = group size */ ulong expo; /* group exponent = lcm(phi(q_even), phi(p[k]^e[k]) ) */ - slong neven; /* number of even components */ + slong neven; /* number of even components (in 0,1,2)*/ slong num; /* number of prime components (even + odd) */ ulong * primes; /* primes p[k] */ ulong * exponents; /* exponents e[k] */ - ulong * generators; /* generator for each prime p[k] */ + ulong * primepowers; /* powers p[k]^[k] */ + ulong * generators; /* generator for each prime p[k] lifted mod q */ ulong * phi; /* phi(k) = phi(p[k]^e[k]) */ ulong * PHI; /* PHI(k) = expo / phi(k) */ } @@ -63,6 +64,8 @@ void acb_conrey_clear(acb_conrey_t x); void acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G); +void acb_conrey_first_primitive(acb_conrey_t x, const acb_dirichlet_group_t G); + void acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m); int acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G); @@ -77,13 +80,13 @@ void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong /* introducing character type */ -/* character = reduced exponents, keep its order and number */ +/* character = reduced exponents, keep order and number */ typedef struct { - ulong q; /* modulus */ - ulong n; /* number */ - ulong order; /* order */ - ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ + ulong q; /* modulus */ + ulong n; /* number */ + ulong order; /* order */ + ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ } acb_dirichlet_char_struct; diff --git a/acb_dirichlet/char.c b/acb_dirichlet/char.c index 869409bc..2183e7d7 100644 --- a/acb_dirichlet/char.c +++ b/acb_dirichlet/char.c @@ -26,6 +26,8 @@ #include "acb_dirichlet.h" +/* FIXME: multiplications mod G->q should be n_mulmod to avoid overflow */ + void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { chi->expo = flint_malloc(G->num * sizeof(ulong)); @@ -36,23 +38,41 @@ acb_dirichlet_char_clear(acb_dirichlet_char_t chi) { flint_free(chi->expo); } -void -acb_dirichlet_char_log(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_conrey_t x) +static void +acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { ulong k, g; g = G->expo; - /* modify exponents */ for (k = 0; k < G->num; k++) - { - chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; g = n_gcd(g, chi->expo[k]); - } for (k = 0; k < G->num; k++) chi->expo[k] = chi->expo[k] / g; - - chi->q = G->q; chi->order = G->expo / g; +} + +static void +acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k, g; + g = G->expo / chi->order; + for (k = 0; k < G->num; k++) + chi->expo[k] *= g; +} + +/* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd + * so that log = expo[k] */ +static void +acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_conrey_t x) +{ + ulong k; + chi->q = G->q; chi->n = x->n; + + for (k = 0; k < G->num; k++) + chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; + + /* optional: divide by gcd to obtain true order */ + acb_dirichlet_char_normalize(chi, G); } void @@ -61,6 +81,91 @@ acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulon acb_conrey_t x; x->log = chi->expo; acb_conrey_log(x, G, n); - acb_dirichlet_char_log(chi, G, x); + acb_dirichlet_char_conrey(chi, G, x); } +ulong +acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k; + + acb_dirichlet_char_denormalize(chi, G); + + /* update index */ + for (k=0; k < G->num ; k++) + { + /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ + chi->n = chi->n * G->generators[k] % G->q; + chi->expo[k] += G->PHI[k]; + if (chi->expo[k] < G->expo) + break; + chi->expo[k] = 0; + } + + acb_dirichlet_char_normalize(chi, G); + + /* return last index modified */ + return k; +} + +ulong +acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k; + + acb_dirichlet_char_denormalize(chi, G); + + /* update index */ + k = 0; + if (G->neven == 2) + { + /* chi->n = n_mulmod(chi->n, G->generators[0], G->q); */ + chi->n = chi->n * G->generators[0] % G->q; + if (++chi->expo[0] < G->expo) + return 0; + chi->expo[0] = 0; + k = 1; + } + for (; k < G->num ; k++) + { + /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ + chi->n = chi->n * G->generators[k] % G->q; + chi->expo[k] += G->PHI[k]; + if (chi->expo[k] % G->primes[k] == 0) + { + /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ + chi->n = chi->n * G->generators[k] % G->q; + chi->expo[k] += G->PHI[k]; + } + if (chi->expo[k] < G->expo) + break; + chi->expo[k] = G->PHI[k]; + } + + acb_dirichlet_char_normalize(chi, G); + + /* return last index modified */ + return k; +} + +void +acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k; + chi->q = G->q; + chi->n = 1; + for (k = 0; k < G->num; k++) + chi->expo[k] = 0; + chi->order = 1; +} + +void +acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + acb_conrey_t x; + chi->q = G->q; + x->log = chi->expo; + acb_conrey_first_primitive(x, G); + chi->n = x->n; + acb_dirichlet_char_normalize(chi, G); +} diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index f7dac634..ab3a19bc 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -35,14 +35,6 @@ acb_conrey_init(acb_conrey_t x, const acb_dirichlet_group_t G) { x->log = flint_malloc(G->num * sizeof(ulong)); } -void -acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G) { - ulong k; - for (k = 0; k < G->num ; k++) - x->log[k] = 0; - x->n = 1; -} - void acb_conrey_clear(acb_conrey_t x) { flint_free(x->log); @@ -60,13 +52,13 @@ acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m) { ulong q_even = G->q_even; ulong g2 = 5; - ulong m2 = (m % 4 == 3) ? n_negmod(m, q_even) : m % q_even; + ulong m2 = (m % 4 == 3) ? -m % q_even : m % q_even; x->log[1] = n_discrete_log_bsgs(m2, g2, q_even); } /* odd part */ for (k = G->neven; k < G->num; k++) { - pk = n_pow(G->primes[k], G->exponents[k]); + pk = G->primepowers[k]; gk = G->generators[k] % pk; x->log[k] = n_discrete_log_bsgs(m % pk, gk, pk); } @@ -74,6 +66,34 @@ acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m) x->n = m; } +ulong +acb_conrey_exp(acb_conrey_t x, const acb_dirichlet_group_t G) +{ + ulong k, n = 1; + for (k = G->neven; k < G->num; k++) + /* n = n_mulmod(n, n_powmod(G->generators[k], x->log[k], G->q), G->q); */ + n = n * n_powmod(G->generators[k], x->log[k], G->q) % G->q; + x->n = n; + return n; +} + +void +acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G) { + ulong k; + for (k = 0; k < G->num ; k++) + x->log[k] = 0; + x->n = 1; +} + +void +acb_conrey_first_primitive(acb_conrey_t x, const acb_dirichlet_group_t G) { + ulong k; + for (k = 0; k < G->num ; k++) + x->log[k] = 1; + if (G->neven == 2) + x->log[0] = 0; +} + int acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G) { @@ -81,11 +101,54 @@ acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G) ulong k; for (k=0; k < G->num ; k++) { - x->n = x->n * G->generators[k]; - if(x->log[k]++ < G->phi[k]) + /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ + x->n = x->n * G->generators[k] % G->q; + if (++x->log[k] < G->phi[k]) break; x->log[k] = 0; } /* return last index modified */ return k; } + +int +acb_conrey_next_primitive(acb_conrey_t x, const acb_dirichlet_group_t G) +{ + /* update index avoiding multiples of p except for first component + if 8|q */ + ulong k = 0; + if (G->neven == 2) + { + /* x->n = n_mulmod(x->n, G->generators[0], G->q); */ + x->n = x->n * G->generators[0] % G->q; + if (++x->log[0] == 1) + return 0; + x->log[0] = 0; + k = 1; + } + for (; k < G->num ; k++) + { + /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ + x->n = x->n * G->generators[k] % G->q; + if (++x->log[k] % G->primes[k] == 0) + { + /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ + x->n = x->n * G->generators[k] % G->q; + ++x->log[k]; + } + if (x->log[k] < G->phi[k]) + break; + x->log[k] = 1; + } + /* return last index modified */ + return k; +} + +void +acb_conrey_mul(acb_conrey_t c, const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b) +{ + ulong k; + for (k = 0; k < G->num ; k++) + c->log[k] = a->log[k] + b->log[k] % G->phi[k]; + c->n = a->n * b->n % G->q; +} diff --git a/acb_dirichlet/group_clear.c b/acb_dirichlet/group_clear.c index 3fe83043..ccf9446b 100644 --- a/acb_dirichlet/group_clear.c +++ b/acb_dirichlet/group_clear.c @@ -17,7 +17,8 @@ acb_dirichlet_group_clear(acb_dirichlet_group_t G) { flint_free(G->primes); flint_free(G->exponents); + flint_free(G->primepowers); flint_free(G->generators); + flint_free(G->phi); flint_free(G->PHI); } - diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index 8820ed2f..133c9b53 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -58,45 +58,58 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) G->num = G->neven + fac.num; G->primes = flint_malloc(G->num * sizeof(ulong)); G->exponents = flint_malloc(G->num * sizeof(ulong)); + G->primepowers = flint_malloc(G->num * sizeof(ulong)); G->generators = flint_malloc(G->num * sizeof(ulong)); G->phi = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); /* even part */ - if (G->q_even <= 2) + G->expo = G->phi_q = 1; + if (G->neven >= 1) { - G->expo = G->phi_q = 1; + G->primes[0] = 2; + G->exponents[0] = 2; + G->phi[0] = 2; + G->primepowers[0] = G->q_even; + G->generators[0] = G->q_even-1; + G->expo = 2; + G->phi_q = 2; } - else + if (G->neven == 2) { - G->phi_q = G->q_even / 2; - G->expo = G->phi_q / 2; + G->primes[1] = 2; + G->exponents[1] = e2-2; + G->phi[1] = G->q_even / 4; + G->primepowers[1] = G->q_even; + G->generators[1] = 5; + G->expo = G->phi[1]; + G->phi_q = G->q_even / 2; } - - for (k = 0; k < G->neven; k++) - { - G->primes[k] = 2; - G->exponents[k] = (k==0) ? 1 : e2-2; - G->generators[k] = (k==0) ? -1 : 5; - G->phi[k] = (k==0) ? 1 : G->expo; - } - + /* odd part */ for (k = G->neven; k < G->num; k++) { - ulong phik, p1; + ulong p1, pe1; G->primes[k] = fac.p[k - G->neven]; G->exponents[k] = fac.exp[k - G->neven]; - G->generators[k] = primitive_root_p_and_p2(G->primes[k]); p1 = G->primes[k] - 1; - phik = p1 * n_pow(G->primes[k], G->exponents[k]-1); - G->expo *= phik / n_gcd(G->expo, p1); - G->phi_q *= phik; - G->phi[k] = phik; + pe1 = n_pow(G->primes[k], G->exponents[k]-1); + G->phi[k] = p1 * pe1; + G->primepowers[k] = pe1 * G->primes[k]; + G->generators[k] = primitive_root_p_and_p2(G->primes[k]); + G->expo *= G->phi[k] / n_gcd(G->expo, p1); + G->phi_q *= G->phi[k]; } - + /* generic odd+even */ for (k = 0; k < G->num; k++) { + ulong pe, qpe, v; G->PHI[k] = G->expo / G->phi[k]; - /* FIXME: generators[k] should be lifted mod q! */ + /* lift generators mod q */ + /* u * p^e + v * q/p^e = 1 -> g mod q = 1 + (g-1) * v*(q/p^e) */ + pe = G->primepowers[k]; + qpe = q / pe; + v = n_invmod(qpe % pe, pe); + /* no overflow since v * qpe < q */ + G->generators[k] = (1 + (G->generators[k]-1) * v * qpe) % q; } } diff --git a/acb_dirichlet/test/t-chi.c b/acb_dirichlet/test/t-chi.c index 07c2ff5c..13d20f94 100644 --- a/acb_dirichlet/test/t-chi.c +++ b/acb_dirichlet/test/t-chi.c @@ -108,4 +108,3 @@ int main() flint_printf("PASS\n"); return EXIT_SUCCESS; } - diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c new file mode 100644 index 00000000..a138d979 --- /dev/null +++ b/acb_dirichlet/test/t-conrey.c @@ -0,0 +1,90 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int main() +{ + slong iter; + flint_rand_t state; + + flint_printf("chi...."); + fflush(stdout); + flint_randinit(state); + + for (iter = 0; iter < 10000; iter++) + { + acb_dirichlet_group_t G; + acb_conrey_t x; + ulong q, n, k, sum; + long ref; + /*int * bits;*/ + + q = 1 + n_randint(state, 1000 * (1 + iter / 100)); + + acb_dirichlet_group_init(G, q); + + /* use http://oeis.org/A053818 to check all elements + * are gone through */ + ref = (q % 4 == 2) ? -2 : 1; + k = (G->neven == 2) ? 1 : 0; + for (; knum; k++) + ref = - ref * G->primes[k]; + ref = ( G->phi_q * (2 * q * q + ref) ) / 6; + + acb_conrey_init(x, G); + acb_conrey_one(x, G); + sum = 1; + + /* check group size */ + for (n = 1; acb_conrey_next(x, G) < G->num; n++) + sum += x->n * x->n; + + if (n != G->phi_q) + { + flint_printf("FAIL: group size\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("phi(q) = %wu\n\n", G->phi_q); + flint_printf("loop index = %wu\n\n", n); + abort(); + } + if (sum != ref && q > 1) + { + flint_printf("FAIL: sum test\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("sum k^2 = %wu\n\n", ref); + flint_printf("sum obtained = %wu\n\n", sum); + abort(); + } + + acb_conrey_clear(x); + acb_dirichlet_group_clear(G); + } + + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} From 2f40b276cd3ccf387f13da9a8916bfbd3f939f59 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 29 Feb 2016 00:13:58 +0100 Subject: [PATCH 004/139] fix generators and test conrey elements --- acb_dirichlet.h | 4 ++- acb_dirichlet/conrey_log.c | 5 +++ acb_dirichlet/group_init.c | 2 +- acb_dirichlet/test/t-conrey.c | 60 +++++++++++++++++++++++++++++++---- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 09025312..4ce1e7df 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -68,7 +68,9 @@ void acb_conrey_first_primitive(acb_conrey_t x, const acb_dirichlet_group_t G); void acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m); -int acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G); +int acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G); + +int acb_conrey_next_primitive(acb_conrey_t x, const acb_dirichlet_group_t G); long n_dirichlet_chi_conrey(const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b); diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index ab3a19bc..07796aa8 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -88,6 +88,11 @@ acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G) { void acb_conrey_first_primitive(acb_conrey_t x, const acb_dirichlet_group_t G) { ulong k; + if (G->q % 4 == 2) + { + flint_printf("Exception (acb_conrey_first_primitive). no primitive element mod %wu.\n",G->q); + abort(); + } for (k = 0; k < G->num ; k++) x->log[k] = 1; if (G->neven == 2) diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index 133c9b53..3312d44b 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -78,7 +78,7 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) if (G->neven == 2) { G->primes[1] = 2; - G->exponents[1] = e2-2; + G->exponents[1] = e2; G->phi[1] = G->q_even / 4; G->primepowers[1] = G->q_even; G->generators[1] = 5; diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index a138d979..d6b4bd5c 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -46,6 +46,27 @@ int main() acb_dirichlet_group_init(G, q); + acb_conrey_init(x, G); + + /* check group size and elements */ + acb_conrey_one(x, G); + sum = 1; + +#if 1 + for (n = 1; acb_conrey_next(x, G) < G->num; n++) + sum += x->n * x->n; +#else + /* iteration much faster than gcd below */ + n = 1; + for (k = 2; k < G->q; k++) + { + if (n_gcd(k, G->q) > 1) + continue; + n++; + sum += k * k; + } +#endif + /* use http://oeis.org/A053818 to check all elements * are gone through */ ref = (q % 4 == 2) ? -2 : 1; @@ -54,13 +75,6 @@ int main() ref = - ref * G->primes[k]; ref = ( G->phi_q * (2 * q * q + ref) ) / 6; - acb_conrey_init(x, G); - acb_conrey_one(x, G); - sum = 1; - - /* check group size */ - for (n = 1; acb_conrey_next(x, G) < G->num; n++) - sum += x->n * x->n; if (n != G->phi_q) { @@ -79,6 +93,38 @@ int main() abort(); } + if (q % 4 == 2) + continue; + + /* check primitive elements */ + if (q % 4 == 2) + ref = 0; + else + { + ref = 1; + k = (G->neven == 2) ? 1 : 0; + for (; k < G->num; k++) + { + ulong p = G->primes[k]; + if (G->exponents[k] == 1) + ref *= p - 2; + else + ref *= (p * (p -2) + 1) * n_pow(p, G->exponents[k] - 2); + } + } + + acb_conrey_first_primitive(x, G); + for (n = 1; (k=acb_conrey_next_primitive(x, G)) < G->num; n++); + + if (n != ref) + { + flint_printf("FAIL: number of primitive elements\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("# primitive = %wu\n\n", ref); + flint_printf("loop index = %wu\n\n", n); + abort(); + } + acb_conrey_clear(x); acb_dirichlet_group_clear(G); } From 68dac0eba2658dfb7ce831f2014034729b80967a Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 29 Feb 2016 00:14:29 +0100 Subject: [PATCH 005/139] implement 3 vector evaluations --- acb_dirichlet/charevalvec.c | 70 +++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/acb_dirichlet/charevalvec.c b/acb_dirichlet/charevalvec.c index ddb16efe..8d39f7a7 100644 --- a/acb_dirichlet/charevalvec.c +++ b/acb_dirichlet/charevalvec.c @@ -43,15 +43,17 @@ set_non_invertible_values(long *v, const acb_dirichlet_group_t G, ulong nv) } } +/* loop over whole group */ void -n_dirichlet_char_vec(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +n_dirichlet_char_vec_large(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) { ulong t, k, j; acb_conrey_t x; acb_conrey_init(x, G); acb_conrey_one(x, G); t = v[1] = 0; - while( (j = acb_conrey_next(x, G)) < G->num ) { + while ( (j = acb_conrey_next(x, G)) < G->num ) + { /* exponents were modified up to j */ for (k = 0; k < j; k++) t = (t + chi->expo[k] * x->log[k]) % chi->order; @@ -65,3 +67,67 @@ n_dirichlet_char_vec(long *v, const acb_dirichlet_group_t G, const acb_dirichlet v[k] = v[k-G->q]; acb_conrey_clear(x); } + +/* loop over primary components */ +void +n_dirichlet_char_vec_med(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +{ + /* prime by prime */ + ulong k, l; + + for(k = 1; k < nv; ++k) + v[k] = 0; + + for(l = 1; l < G->num; ++l) + { + long p, pe, g, x, vp, xp; + long j, vj; + p = G->primes[l]; + pe = G->primepowers[l]; + g = G->generators[l] % pe; + vj = vp = chi->expo[l]; + if( g < 0 ) g += pe; + /* for each x = g^j mod p^e, + * set a[x] += j*vp + * and use periodicity */ + for(j = 1, x = g; x > 1; j++) + { + for(xp = x; xp < nv; xp+=pe) + v[xp] = (v[xp] + vj) % chi->order; + x = (x*g) % pe; + vj = (vj + vp) % chi->order; + } + } + set_non_invertible_values(v, G, nv); +} + + +/* eratosthene sieve */ +void +n_dirichlet_char_vec_small(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +{ + ulong k, p, pmax; + n_primes_t iter; + + n_primes_init(iter); + + pmax = (nv < G->q) ? nv : G->q; + v[1] = 0; + while ((p = n_primes_next(iter)) < pmax) + { + if (G->q % p == 0) + { + for (k = p; k < nv; k += p) + v[k] = -1; + } + else + { + long chip; + chip = n_dirichlet_char_eval(G, chi, p); + for (k = p; k < nv; k += p) + if (v[k] != -1) + v[k] = (v[k] + chip) % chi->order; + } + } + n_primes_clear(iter); +} From 666db0a33f6290a2af46a3e2285994a4145734ef Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 7 Mar 2016 09:54:42 +0100 Subject: [PATCH 006/139] profile charevalvec --- acb_dirichlet.h | 3 + acb_dirichlet/charevalvec.c | 17 +++-- acb_dirichlet/profile/p-conrey.c | 76 ++++++++++++++++++++ acb_dirichlet/profile/p-evalvec.c | 112 ++++++++++++++++++++++++++++++ acb_dirichlet/test/t-conrey.c | 2 +- 5 files changed, 200 insertions(+), 10 deletions(-) create mode 100644 acb_dirichlet/profile/p-conrey.c create mode 100644 acb_dirichlet/profile/p-evalvec.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 4ce1e7df..d274cfa2 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -105,6 +105,9 @@ long n_dirichlet_char_eval(const acb_dirichlet_group_t G, const acb_dirichlet_ch void acb_dirichlet_char_eval(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); void n_dirichlet_char_vec(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); +void n_dirichlet_char_vec_loop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); +void n_dirichlet_char_vec_primeloop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); +void n_dirichlet_char_vec_logsieve(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); void acb_dirichlet_char_vec(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); diff --git a/acb_dirichlet/charevalvec.c b/acb_dirichlet/charevalvec.c index 8d39f7a7..b35ae191 100644 --- a/acb_dirichlet/charevalvec.c +++ b/acb_dirichlet/charevalvec.c @@ -37,7 +37,7 @@ set_non_invertible_values(long *v, const acb_dirichlet_group_t G, ulong nv) } for (l = 0; l < G->num; l++) { - ulong p = G->primes[k]; + ulong p = G->primes[l]; for (k = p; k < nv; k += p) v[k] = -1; } @@ -45,9 +45,10 @@ set_non_invertible_values(long *v, const acb_dirichlet_group_t G, ulong nv) /* loop over whole group */ void -n_dirichlet_char_vec_large(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +n_dirichlet_char_vec_loop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) { - ulong t, k, j; + int j; + ulong t, k; acb_conrey_t x; acb_conrey_init(x, G); acb_conrey_one(x, G); @@ -64,15 +65,14 @@ n_dirichlet_char_vec_large(long *v, const acb_dirichlet_group_t G, const acb_dir set_non_invertible_values(v, G, nv); /* copy outside modulus */ for (k = G->q + 1; k < nv ; k++ ) - v[k] = v[k-G->q]; + v[k] = v[k - G->q]; acb_conrey_clear(x); } /* loop over primary components */ void -n_dirichlet_char_vec_med(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +n_dirichlet_char_vec_primeloop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) { - /* prime by prime */ ulong k, l; for(k = 1; k < nv; ++k) @@ -86,7 +86,6 @@ n_dirichlet_char_vec_med(long *v, const acb_dirichlet_group_t G, const acb_diric pe = G->primepowers[l]; g = G->generators[l] % pe; vj = vp = chi->expo[l]; - if( g < 0 ) g += pe; /* for each x = g^j mod p^e, * set a[x] += j*vp * and use periodicity */ @@ -102,9 +101,9 @@ n_dirichlet_char_vec_med(long *v, const acb_dirichlet_group_t G, const acb_diric } -/* eratosthene sieve */ +/* eratosthene sieve on primes */ void -n_dirichlet_char_vec_small(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +n_dirichlet_char_vec_logsieve(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) { ulong k, p, pmax; n_primes_t iter; diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c new file mode 100644 index 00000000..11d008c1 --- /dev/null +++ b/acb_dirichlet/profile/p-conrey.c @@ -0,0 +1,76 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "profiler.h" + +int main() +{ + slong iter, k, n, nref; + ulong q, maxq; + + maxq = 4000; + flint_printf("loop over all (Z/q)* for q<=%wu....\n", maxq); + fflush(stdout); + + flint_printf("gcd................ "); + TIMEIT_ONCE_START + for (n = 0, q = 2; q <= maxq; q++) + for (k = 1; k < q; k++) + if (n_gcd(k, q) > 1) + continue; + else + n++; + TIMEIT_ONCE_STOP + nref = n; + + flint_printf("conrey elements.... "); + TIMEIT_ONCE_START + for (n = 0, q = 2; q <= maxq; q++) + { + acb_dirichlet_group_t G; + acb_conrey_t x; + + acb_dirichlet_group_init(G, q); + acb_conrey_init(x, G); + + acb_conrey_one(x, G); + n++; + + for (; acb_conrey_next(x, G) < G->num; n++); + acb_conrey_clear(x); + acb_dirichlet_group_clear(G); + } + TIMEIT_ONCE_STOP + if (n != nref) + { + flint_printf("FAIL: wrong number of elements %wu != %wu\n\n",n, nref); + abort(); + } + + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/profile/p-evalvec.c b/acb_dirichlet/profile/p-evalvec.c new file mode 100644 index 00000000..f819f9a5 --- /dev/null +++ b/acb_dirichlet/profile/p-evalvec.c @@ -0,0 +1,112 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "profiler.h" +typedef void (*dir_f) (long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); + +void +dir_empty(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +{ + return; +} + +void +vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, long * v, ulong nv) +{ + ulong q; + TIMEIT_ONCE_START + for (q = minq; q <= maxq; q++) + { + ulong r; + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi, G); + for (r = 0; r < nr; r++) + { + acb_dirichlet_char(chi, G, rand[r] % q); + dir(v, G, chi, nv); + } + acb_dirichlet_char_clear(chi); + acb_dirichlet_group_clear(G); + } + TIMEIT_ONCE_STOP +} + +int main() +{ + slong iter, k, nv, nref, r, nr; + ulong minq, maxq; + ulong * rand; + int i, ni = 5; + ulong q[5] = { 2, 1000, 3000, 10000, 100000 }; + ulong qq[5] = { 500, 2000, 5000, 12000, 100500 }; + long * v; + flint_rand_t state; + + nr = 20; + + flint_randinit(state); + rand = flint_malloc(nr * sizeof(ulong)); + v = flint_malloc(nv * sizeof(long)); + + for (r = 0; r < nr; r++) + rand[r] = n_randprime(state, 42, 0); + + for (i = 0; i < ni; i++) + { + + ulong minq = q[i], maxq = qq[i]; + nv = 2000; + + flint_printf("%wu * chi(rand, 1..%wu) for all %wu <= q <= %wu....\n", nr, nv, minq, maxq); + fflush(stdout); + + flint_printf("character only.......... "); + fflush(stdout); + vecloop(dir_empty, minq, maxq, rand, nr, v, nv); + + flint_printf("big loop................ "); + fflush(stdout); + vecloop(n_dirichlet_char_vec_loop, minq, maxq, rand, nr, v, nv); + + flint_printf("med loop................ "); + fflush(stdout); + vecloop(n_dirichlet_char_vec_primeloop, minq, maxq, rand, nr, v, nv); + + flint_printf("small loop................ "); + fflush(stdout); + vecloop(n_dirichlet_char_vec_logsieve, minq, maxq, rand, nr, v, nv); + } + + flint_free(v); + flint_free(rand); + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index d6b4bd5c..df291d83 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -19,7 +19,7 @@ =============================================================================*/ /****************************************************************************** - Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin ******************************************************************************/ From 4946ae85e436008a5b032961da9384de34b3a105 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 7 Mar 2016 09:55:19 +0100 Subject: [PATCH 007/139] add discrete log precomputations --- acb_dirichlet/dlog.h | 178 +++++++++++++++++++++++++++++++++++ acb_dirichlet/dlog_1modpe.c | 82 ++++++++++++++++ acb_dirichlet/dlog_bsgs.c | 84 +++++++++++++++++ acb_dirichlet/dlog_crt.c | 92 ++++++++++++++++++ acb_dirichlet/dlog_modpe.c | 55 +++++++++++ acb_dirichlet/dlog_power.c | 81 ++++++++++++++++ acb_dirichlet/dlog_precomp.c | 174 ++++++++++++++++++++++++++++++++++ acb_dirichlet/dlog_table.c | 55 +++++++++++ acb_dirichlet/test/t-dlog.c | 77 +++++++++++++++ 9 files changed, 878 insertions(+) create mode 100644 acb_dirichlet/dlog.h create mode 100644 acb_dirichlet/dlog_1modpe.c create mode 100644 acb_dirichlet/dlog_bsgs.c create mode 100644 acb_dirichlet/dlog_crt.c create mode 100644 acb_dirichlet/dlog_modpe.c create mode 100644 acb_dirichlet/dlog_power.c create mode 100644 acb_dirichlet/dlog_precomp.c create mode 100644 acb_dirichlet/dlog_table.c create mode 100644 acb_dirichlet/test/t-dlog.c diff --git a/acb_dirichlet/dlog.h b/acb_dirichlet/dlog.h new file mode 100644 index 00000000..ac7729a3 --- /dev/null +++ b/acb_dirichlet/dlog.h @@ -0,0 +1,178 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#ifndef DLOG_H +#define DLOG_H + +#include "padic.h" +#include "ulong_extras.h" + +enum +{ + DLOG_MODPE, DLOG_CRT, DLOG_POWER, DLOG_BSGS, DLOG_TABLE +}; + +typedef struct dlog_precomp_struct dlog_precomp_struct; + +/* log in (1+pZ/p^eZ): compute via p-adic log */ +typedef struct +{ + ulong p; + ulong e; + padic_ctx_t ctx; /* padic context */ + padic_t invlog; + padic_t x; + fmpz_t r; +} +dlog_1modpe_struct; + +typedef dlog_1modpe_struct dlog_1modpe_t[1]; + +/* log in (Z/p^eZ)^* */ +typedef struct +{ + ulong p; + ulong e; + ulong pe; + /*dlog_precomp_t modp;*/ + dlog_precomp_struct * modp; + dlog_1modpe_t modpe; +} +dlog_modpe_struct; + +typedef dlog_modpe_struct dlog_modpe_t[1]; + +/* all logs precomputed in (Z/modZ)^ast */ +typedef struct +{ + ulong mod; + ulong * table; +} +dlog_table_struct; + +typedef dlog_table_struct dlog_table_t[1]; + +/* bsgs table, already in flint */ + +typedef struct apow { + ulong k; + ulong ak; +} apow_t; + +typedef struct { + ulong n; + double ninv; + ulong m; + ulong am; + apow_t * table; +} dlog_bsgs_struct; + +typedef dlog_bsgs_struct dlog_bsgs_t[1]; +/* typedef bsgs_t dlog_bsgs_t; */ + +/* CRT decomposition (Pohlig-Hellman) */ +typedef struct +{ + ulong mod; + ulong n; + ulong num; + ulong * expo; + ulong * crt_coeffs; + dlog_precomp_struct ** pre; + /* + void * pre; + dlog_precomp_t * pre; + */ +} +dlog_crt_struct; + +typedef dlog_crt_struct dlog_crt_t[1]; + +/* dlog when generator has prime power order */ +typedef struct +{ + ulong mod; + ulong p; + ulong e; + ulong * apk; + dlog_precomp_struct * pre; + /* + void * pre; + dlog_precomp_t * pre; + */ +} +dlog_power_struct; + +typedef dlog_power_struct dlog_power_t[1]; + +/* generic decomposition */ +/*typedef */ +struct +dlog_precomp_struct +{ + int type; + union + { + dlog_table_t table; + dlog_bsgs_t bsgs; + dlog_crt_t crt; + dlog_power_t power; + dlog_modpe_t modpe; + } t; +}; + +typedef dlog_precomp_struct dlog_precomp_t[1]; + +void dlog_table_init(dlog_table_t t, ulong a, ulong mod); +void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e); +void dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); +void dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num); +void dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num); +void dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong n, ulong m); +/*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ + +void dlog_table_clear(dlog_table_t t); +void dlog_1modpe_clear(dlog_1modpe_t t); +void dlog_crt_clear(dlog_crt_t t); +void dlog_power_clear(dlog_power_t t); +void dlog_modpe_clear(dlog_modpe_t t); +void dlog_bsgs_clear(dlog_bsgs_t t); +/*#define dlog_bsgs_clear(t) bsgs_table_clear(t)*/ + +ulong dlog_table(const dlog_table_t t, ulong b); +ulong dlog_crt(const dlog_crt_t t, ulong b); +ulong dlog_power(const dlog_power_t t, ulong b); +ulong dlog_modpe(const dlog_modpe_t t, ulong b); +ulong dlog_1modpe(const dlog_1modpe_t t, ulong b); +ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); +/*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ + +void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); +void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num); +void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num); +void dlog_precomp_clear(dlog_precomp_t pre); +ulong dlog_precomp(const dlog_precomp_t pre, ulong b); + +#endif diff --git a/acb_dirichlet/dlog_1modpe.c b/acb_dirichlet/dlog_1modpe.c new file mode 100644 index 00000000..ee742f4e --- /dev/null +++ b/acb_dirichlet/dlog_1modpe.c @@ -0,0 +1,82 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "padic.h" + +typedef struct +{ + ulong p; + padic_ctx_t ctx; /* padic context */ + padic_t invlog; +} +dlog_1modpe_struct; + +typedef dlog_1modpe_struct dlog_1modpe_t[1]; + +void +dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e) +{ + fmpz_t tmp; + t->p = p; + fmpz_init(tmp); + padic_init(t->invlog); + + fmpz_set_ui(tmp, p); + padic_ctx_init(t->ctx , tmp , 0 , e, PADIC_TERSE); + + padic_set_ui(t->invlog, a1, t->ctx); + padic_inv(t->invlog, t->invlog, t->ctx); + + fmpz_clear(tmp); +} + +void +dlog_1modpe_clear(dlog_1modpe_t t) +{ + padic_clear(t->invlog); + padic_ctx_clear(t->ctx); +} + +/* assume b = 1 mod p, not checked */ +ulong +dlog_1modpe(const dlog_1modpe_t t, ulong b) +{ + padic_t px; + fmpz_t ix; + ulong ux; + padic_init(px); + fmpz_init(ix); + + padic_set_ui(px, b, t->ctx); + padic_log(px, px, t->ctx); + padic_mul(px, px, t->invlog, t->ctx); + padic_get_fmpz(ix, px, t->ctx); + ux = fmpz_get_ui(ix); + + padic_clear(px); + fmpz_clear(ix); + return ux; +} diff --git a/acb_dirichlet/dlog_bsgs.c b/acb_dirichlet/dlog_bsgs.c new file mode 100644 index 00000000..0495eaab --- /dev/null +++ b/acb_dirichlet/dlog_bsgs.c @@ -0,0 +1,84 @@ +/*============================================================================= + + This file is part of FLINT. + + FLINT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + FLINT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FLINT; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2013 Mike Hansen + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include + +#include "dlog.h" +#include "ulong_extras.h" + +static int +apow_cmp(const apow_t * x, const apow_t * y) +{ + return (x->ak < y->ak) ? -1 : (x->ak > y->ak); +} + +/* set size of table m=sqrt(nk) to compute k logs in a group of size n */ +void +dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong n, ulong m) +{ + ulong k, ak; + t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); + + t->n = n; + t->ninv = n_precompute_inverse(n); + t->m = m; + + for (k = 0, ak = 1; k < m; k++) + { + t->table[k].k = k; + t->table[k].ak = ak; + ak = n_mulmod_precomp(ak, a, n, t->ninv); + } + + t->am = n_invmod(ak, n); + qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); +} + +void +dlog_bsgs_clear(dlog_bsgs_t t) +{ + flint_free(t->table); +} + +ulong +dlog_bsgs(const dlog_bsgs_t t, ulong b) +{ + ulong i; + apow_t c, * x; + + c.k = 0; + c.ak = b; + for (i = 0; i < t->m; i++) + { + x = bsearch(&c, t->table, t->m, sizeof(apow_t), + (int(*)(const void*,const void*))apow_cmp); + if (x != NULL) + return i * t->m + x->k; + c.ak = n_mulmod_precomp(c.ak, t->am, t->n, t->ninv); + } + flint_printf("Exception (n_discrete_log_bsgs). discrete log not found.\n"); + abort(); +} diff --git a/acb_dirichlet/dlog_crt.c b/acb_dirichlet/dlog_crt.c new file mode 100644 index 00000000..f3d41153 --- /dev/null +++ b/acb_dirichlet/dlog_crt.c @@ -0,0 +1,92 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) +{ + int k; + n_factor_t fac; + ulong * M, * u; + + n_factor_init(&fac); + n_factor(&fac, n, 1); + + t->num = fac.num; + t->mod = mod; + t->n = n; + + M = t->expo = flint_malloc(t->num * sizeof(ulong)); + u = t->crt_coeffs = flint_malloc(t->num * sizeof(ulong)); + t->pre = flint_malloc(t->num * sizeof(dlog_precomp_t)); + for (k = 0; k < t->num; k++) + t->pre[k] = flint_malloc(sizeof(dlog_precomp_struct)); + + for (k = 0; k < t->num; k++) + { + ulong p, e, mk; + p = fac.p[k]; + e = fac.exp[k]; + mk = n_pow(p, e); + M[k] = n / mk; + u[k] = M[k] * n_invmod(M[k] % mk, mk) % n; + /* depends on the power */ + dlog_precomp_pe_init(t->pre[k], n_powmod(a, M[k], mod), mod, p, e, mk, num); + } +} + +void +dlog_crt_clear(dlog_crt_t t) +{ + int k; + flint_free(t->expo); + flint_free(t->crt_coeffs); + for (k = 0; k < t->num; k++) + { + dlog_precomp_clear(t->pre[k]); + flint_free(t->pre[k]); + } + flint_free(t->pre); +} + +ulong +dlog_crt(const dlog_crt_t t, ulong b) +{ + int k; + ulong r = 0; + for (k = 0; k < t->num; k++) + { + ulong bk, rk; + bk = n_powmod(b, t->expo[k], t->mod); + rk = dlog_precomp(t->pre[k], bk); +#if 0 + flint_printf("##[crt-%d]: log(%wu)=log(%wu^%wu) = %wu [size %wu mod %wu]\n", + k, bk, b, t->expo[k], rk, t->n/t->expo[k], t->mod); +#endif + r = (r + t->crt_coeffs[k] * rk) % t->n; + } + return r; +} diff --git a/acb_dirichlet/dlog_modpe.c b/acb_dirichlet/dlog_modpe.c new file mode 100644 index 00000000..a41095f2 --- /dev/null +++ b/acb_dirichlet/dlog_modpe.c @@ -0,0 +1,55 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include "padic.h" + +void +dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) +{ + t->p = p; + t->e = e; + t->pe = pe; + dlog_precomp_n_init(t->modp, a, p, p-1, num); + dlog_1modpe_init(t->modpe, n_powmod(a, p - 1, pe), p, e); +} + +void +dlog_modpe_clear(dlog_modpe_t t) +{ + dlog_precomp_clear(t->modp); + dlog_1modpe_clear(t->modpe); +} + +ulong +dlog_modpe(const dlog_modpe_t t, ulong b) +{ + ulong x; + x = dlog_precomp(t->modp, b % t->p); + /*b = b * n_powmod(t->a, -x, t->pe);*/ + b = n_powmod(b, t->p - 1, t->pe); + x = x + (t->p-1) * dlog_1modpe(t->modpe, b); + return x; +} diff --git a/acb_dirichlet/dlog_power.c b/acb_dirichlet/dlog_power.c new file mode 100644 index 00000000..826cc82d --- /dev/null +++ b/acb_dirichlet/dlog_power.c @@ -0,0 +1,81 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) +{ + int k; + t->mod = mod; + t->p = p; + t->e = e; + + t->apk = flint_malloc(e * sizeof(ulong)); + t->pre = flint_malloc(sizeof(dlog_precomp_struct)); + + t->apk[0] = n_invmod(a, mod); + for (k = 1; k < e; k++) + t->apk[k] = n_powmod(t->apk[k-1], p, mod); + + dlog_precomp_p_init(t->pre, n_invmod(t->apk[e-1], mod), mod, p, num); +} + +void +dlog_power_clear(dlog_power_t t) +{ + flint_free(t->apk); + dlog_precomp_clear(t->pre); + flint_free(t->pre); +} + +/* 3^30*2+1, 2^30*3+1 are primes */ + +ulong +dlog_power(const dlog_power_t t, ulong b) +{ + int k; +#ifdef C99 + ulong pk[t->e]; +#else + ulong pk[30]; +#endif + ulong x; + + pk[0] = 1; + for (k = 1; k < t->e; k++) + pk[k] = pk[k-1]*t->p; + + x = 0; + for(k = 0; k < t->e; k++) + { + ulong bk, xk; + bk = n_powmod(b, pk[t->e-1-k], t->mod); + xk = dlog_precomp(t->pre, bk); + b = b * n_powmod(t->apk[k], xk, t->mod) % t->mod; + x += xk * pk[k]; /* cannot overflow */ + } + return x; +} diff --git a/acb_dirichlet/dlog_precomp.c b/acb_dirichlet/dlog_precomp.c new file mode 100644 index 00000000..92a62bfe --- /dev/null +++ b/acb_dirichlet/dlog_precomp.c @@ -0,0 +1,174 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "math.h" +#include "dlog.h" + +#define TABLE_P_LIM 50 +#define TABLE_PE_LIM 50 +#define TABLE_N_LIM 50 +#define BSGS_LIM 500 + + +/* log mod p^e */ +void +dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) +{ + if ( pe < TABLE_PE_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, pe); + return; + } + if (e > 1) + { + pre->type = DLOG_MODPE; + dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); + } + else + { + dlog_precomp_n_init(pre, a, p, p - 1, num); + } +} + +/* group of order n modulo mod, mod a prime and no information on n */ +void +dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) +{ + if (n%2 && n_is_probabprime(n)) + dlog_precomp_p_init(pre, a, mod, n, num); + else { + if ( mod < TABLE_N_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, mod); + } else { + if (n < BSGS_LIM) + { + ulong m; + m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; + pre->type = DLOG_BSGS; + dlog_bsgs_init(pre->t.bsgs, a, mod, m); + } else { + pre->type = DLOG_CRT; + dlog_crt_init(pre->t.crt, a, mod, n, num); + } + } + } +} + +/* we known the order is prime */ +void +dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) +{ + if ( p < TABLE_P_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, mod); + } + else + { + ulong m; + m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; + pre->type = DLOG_BSGS; + dlog_bsgs_init(pre->t.bsgs, a, mod, m); + } +} + +void +dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) +{ + if ( pe < TABLE_PE_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, mod); + } + else + { + if ( e == 1) + { + dlog_precomp_p_init(pre, a, mod, p, num); + } + else + { + pre->type = DLOG_POWER; + dlog_power_init(pre->t.power, a, mod, p, e, num); + } + } +} + +void +dlog_precomp_clear(dlog_precomp_t pre) +{ + switch (pre->type) + { + case DLOG_MODPE: + dlog_modpe_clear(pre->t.modpe); + break; + case DLOG_CRT: + dlog_crt_clear(pre->t.crt); + break; + case DLOG_POWER: + dlog_power_clear(pre->t.power); + break; + case DLOG_TABLE: + dlog_table_clear(pre->t.table); + break; + case DLOG_BSGS: + dlog_bsgs_clear(pre->t.bsgs); + break; + default: + abort(); + break; + } +} + +ulong +dlog_precomp(const dlog_precomp_t pre, ulong b) +{ + if (b == 1) + return 0; + switch (pre->type) + { + case DLOG_MODPE: + return dlog_modpe(pre->t.modpe, b); + break; + case DLOG_CRT: + return dlog_crt(pre->t.crt, b); + break; + case DLOG_POWER: + return dlog_power(pre->t.power, b); + break; + case DLOG_TABLE: + return dlog_table(pre->t.table, b); + break; + case DLOG_BSGS: + return dlog_bsgs(pre->t.bsgs, b); + break; + default: + abort(); + break; + } +} diff --git a/acb_dirichlet/dlog_table.c b/acb_dirichlet/dlog_table.c new file mode 100644 index 00000000..ad58a9e5 --- /dev/null +++ b/acb_dirichlet/dlog_table.c @@ -0,0 +1,55 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_table_init(dlog_table_t t, ulong a, ulong mod) +{ + int k; + ulong ak; + t->mod = mod; + t->table = flint_malloc(mod * sizeof(ulong)); + ak = 1; k = 0; + /* warning: do not check a is invertible modulo mod */ + do + { + t->table[ak] = k++; + ak = (ak * a) % mod; + } + while (ak != 1); +} + +void +dlog_table_clear(dlog_table_t t) +{ + flint_free(t->table); +} + +ulong +dlog_table(const dlog_table_t t, ulong b) +{ + return t->table[b % t->mod]; +} diff --git a/acb_dirichlet/test/t-dlog.c b/acb_dirichlet/test/t-dlog.c new file mode 100644 index 00000000..793b6fb9 --- /dev/null +++ b/acb_dirichlet/test/t-dlog.c @@ -0,0 +1,77 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet/dlog.h" +#include + +int main() +{ + slong iter; + flint_rand_t state; + + flint_printf("dlog mod p...."); + fflush(stdout); + flint_randinit(state); + + for (iter = 0; iter < 1000; iter++) + { + dlog_table_t table; + dlog_bsgs_t bsgs; + dlog_precomp_t pre1, pre100; + ulong p, a, k; + + p = n_randprime(state, 15, 0); + a = n_primitive_root_prime(p); + + dlog_table_init(table, a, p); + dlog_bsgs_init(bsgs, a, p, ceil(sqrt((double)p))); + dlog_precomp_n_init(pre1, a, p, p-1, 1); + dlog_precomp_n_init(pre100, a, p, p-1, 100); + + for (k = 1; k < 100 && k < p; k++) + { + ulong l1, l2, l3, l4; + l1 = dlog_table(table, k); + l2 = dlog_bsgs(bsgs, k); + l3 = dlog_precomp(pre1, k); + l4 = dlog_precomp(pre100, k); + if (l1 != l2 || l3 != l4 || l1 != l3) + { + flint_printf("FAIL: log(%wu,%wu) mod %wu: [%wu, %wu, %wu, %wu]\n", + k, a, p, l1, l2, l3, l4); + abort(); + } + } + dlog_table_clear(table); + dlog_bsgs_clear(bsgs); + dlog_precomp_clear(pre1); + dlog_precomp_clear(pre100); + } + + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} From bd644682fd84ed0624ac6deb762972c220820d82 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 8 Mar 2016 16:40:32 +0100 Subject: [PATCH 008/139] add dlog rho method --- acb_dirichlet/dlog.h | 20 ++- acb_dirichlet/dlog_bsgs.c | 19 +-- acb_dirichlet/dlog_precomp.c | 4 +- acb_dirichlet/dlog_rho.c | 133 ++++++++++++++++++++ acb_dirichlet/profile/p-dlog_precomp.c | 167 +++++++++++++++++++++++++ acb_dirichlet/test/t-dlog.c | 18 +-- 6 files changed, 341 insertions(+), 20 deletions(-) create mode 100644 acb_dirichlet/dlog_rho.c create mode 100644 acb_dirichlet/profile/p-dlog_precomp.c diff --git a/acb_dirichlet/dlog.h b/acb_dirichlet/dlog.h index ac7729a3..e9096ef6 100644 --- a/acb_dirichlet/dlog.h +++ b/acb_dirichlet/dlog.h @@ -82,9 +82,10 @@ typedef struct apow { } apow_t; typedef struct { - ulong n; - double ninv; + ulong mod; + double modinv; ulong m; + ulong g; ulong am; apow_t * table; } dlog_bsgs_struct; @@ -92,6 +93,16 @@ typedef struct { typedef dlog_bsgs_struct dlog_bsgs_t[1]; /* typedef bsgs_t dlog_bsgs_t; */ +/* Pollard rho */ +typedef struct { + ulong a; + ulong n; + ulong mod; + int nisprime; +} dlog_rho_struct; + +typedef dlog_rho_struct dlog_rho_t[1]; + /* CRT decomposition (Pohlig-Hellman) */ typedef struct { @@ -150,7 +161,8 @@ void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e); void dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); void dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num); void dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num); -void dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong n, ulong m); +void dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m); +void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n); /*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ void dlog_table_clear(dlog_table_t t); @@ -159,6 +171,7 @@ void dlog_crt_clear(dlog_crt_t t); void dlog_power_clear(dlog_power_t t); void dlog_modpe_clear(dlog_modpe_t t); void dlog_bsgs_clear(dlog_bsgs_t t); +void dlog_rho_clear(dlog_rho_t t); /*#define dlog_bsgs_clear(t) bsgs_table_clear(t)*/ ulong dlog_table(const dlog_table_t t, ulong b); @@ -167,6 +180,7 @@ ulong dlog_power(const dlog_power_t t, ulong b); ulong dlog_modpe(const dlog_modpe_t t, ulong b); ulong dlog_1modpe(const dlog_1modpe_t t, ulong b); ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); +ulong dlog_rho(const dlog_rho_t t, ulong b); /*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); diff --git a/acb_dirichlet/dlog_bsgs.c b/acb_dirichlet/dlog_bsgs.c index 0495eaab..9e147b23 100644 --- a/acb_dirichlet/dlog_bsgs.c +++ b/acb_dirichlet/dlog_bsgs.c @@ -37,23 +37,25 @@ apow_cmp(const apow_t * x, const apow_t * y) /* set size of table m=sqrt(nk) to compute k logs in a group of size n */ void -dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong n, ulong m) +dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) { ulong k, ak; t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); + if (m > n) m = n; - t->n = n; - t->ninv = n_precompute_inverse(n); + t->mod = mod; + t->modinv = n_precompute_inverse(mod); t->m = m; + t->g = n / m; for (k = 0, ak = 1; k < m; k++) { t->table[k].k = k; t->table[k].ak = ak; - ak = n_mulmod_precomp(ak, a, n, t->ninv); + ak = n_mulmod_precomp(ak, a, mod, t->modinv); } - t->am = n_invmod(ak, n); + t->am = n_invmod(ak, mod); qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); } @@ -69,16 +71,17 @@ dlog_bsgs(const dlog_bsgs_t t, ulong b) ulong i; apow_t c, * x; - c.k = 0; c.ak = b; - for (i = 0; i < t->m; i++) + for (i = 0; i <= t->g; i++) { x = bsearch(&c, t->table, t->m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); if (x != NULL) return i * t->m + x->k; - c.ak = n_mulmod_precomp(c.ak, t->am, t->n, t->ninv); + c.ak = n_mulmod_precomp(c.ak, t->am, t->mod, t->modinv); } flint_printf("Exception (n_discrete_log_bsgs). discrete log not found.\n"); + flint_printf(" table size %wu, cosize %wu mod %wu. %wu not found\n", + t->m, t->g, t->mod, b); abort(); } diff --git a/acb_dirichlet/dlog_precomp.c b/acb_dirichlet/dlog_precomp.c index 92a62bfe..7b22e876 100644 --- a/acb_dirichlet/dlog_precomp.c +++ b/acb_dirichlet/dlog_precomp.c @@ -70,7 +70,7 @@ dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) ulong m; m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; pre->type = DLOG_BSGS; - dlog_bsgs_init(pre->t.bsgs, a, mod, m); + dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); } else { pre->type = DLOG_CRT; dlog_crt_init(pre->t.crt, a, mod, n, num); @@ -93,7 +93,7 @@ dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) ulong m; m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; pre->type = DLOG_BSGS; - dlog_bsgs_init(pre->t.bsgs, a, mod, m); + dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); } } diff --git a/acb_dirichlet/dlog_rho.c b/acb_dirichlet/dlog_rho.c new file mode 100644 index 00000000..666a841f --- /dev/null +++ b/acb_dirichlet/dlog_rho.c @@ -0,0 +1,133 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include + +void +dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) +{ + t->a = a; + t->n = n; + t->mod = mod; + t->nisprime = n_is_prime(n); +} + +void +dlog_rho_clear(dlog_rho_t t) +{ + return; +} + +static ulong +dlog_once(ulong b, ulong a, ulong mod, ulong n) +{ + if (n < 50) + { + int k; + ulong ak = 1; + for (k=0; k < n; k++) + { + if (ak == b) + return k; + ak = (ak * a) % mod; + } + flint_printf("FAIL[dlog once]: log(%wu,%wu) mod %wu not found (size %wu)\n", + b, a, mod, n); + abort(); + } else { + dlog_rho_t t; + dlog_rho_init(t, a, mod, n); + return dlog_rho(t, b); + } +} + +/* solve log knowing equation e = f * log(b) [n] */ +static ulong +dlog_quotient(const dlog_rho_t t, ulong e, ulong f, ulong g, ulong b) +{ + ulong r, n, b_ar, an; + n = t->n; + if (g == n) + { + flint_printf("FAIL[dlog quotient]: trivial relation e = %wu, f = %wu mod %wu\n", + e, f, n); + abort(); + } + n = n / g; + e = e / g; + f = f / g; + f = n_invmod(f, n); + r = ( e * f ) % n; + an = n_powmod(t->a, n, t->mod); + b_ar = (b * n_invmod(n_powmod(t->a, r, t->mod), t->mod)) % t->mod; + return r + n * dlog_once(b_ar, an, t->mod, g); +} + +#define RWALK 20 +ulong +dlog_rho(const dlog_rho_t t, ulong b) +{ + int j, k, l; + ulong m[RWALK], n[RWALK], ab[RWALK]; + ulong x[2], e[2], f[2], g; + flint_rand_t state; + flint_randinit(state); + do { + for (k = 0; k < RWALK; k++) + { + m[k] = 1 + n_randint(state, t->n - 1); + n[k] = 1 + n_randint(state, t->n - 1); + ab[k] = (n_powmod(t->a, m[k], t->mod) * n_powmod(b, n[k], t->mod)) % t->mod; + } + /* x[l] = a^e[l] * b^f[l] */ + x[0] = x[1] = 1; + e[0] = e[1] = 0; + f[0] = f[1] = 0; + do { + for(j = 0; j < 3; j++) + { + l = (j > 0); + k = floor( (double) RWALK * x[l] / t->mod ); + x[l] = (x[l] * ab[k]) % t->mod; + e[l] = (e[l] + m[k]) % t->n; + f[l] = (f[l] + n[k]) % t->n; + } + } while (x[0] != x[1]); + } while (e[0] == e[1] && f[0] == f[1]); + flint_randclear(state); + /* e = f * log(b) */ + e[0] = (e[0] > e[1]) ? e[0] - e[1] : e[0] + t->n - e[1]; + f[0] = (f[1] > f[0]) ? f[1] - f[0] : f[1] + t->n - f[0]; + if (!t->nisprime && (g = n_gcd(f[0], t->n)) > 1) + { + return dlog_quotient(t, e[0], f[0], g, b); + } + else + { + f[0] = n_invmod(f[0], t->n); + return ( e[0] * f[0] ) % t->n; + } +} diff --git a/acb_dirichlet/profile/p-dlog_precomp.c b/acb_dirichlet/profile/p-dlog_precomp.c new file mode 100644 index 00000000..533c6db9 --- /dev/null +++ b/acb_dirichlet/profile/p-dlog_precomp.c @@ -0,0 +1,167 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet/dlog.h" +#include "profiler.h" +#include + +typedef void (*multilog_f) (ulong p, ulong a, ulong num); + +void +flog_table(ulong p, ulong a, ulong num) +{ + int k; + dlog_table_t t; + dlog_table_init(t, a, p); + for (k = 1; k < num; k++) + { + if (k == p) continue; + dlog_table(t, k % p); + } + dlog_table_clear(t); +} +void +flog_bsgs(ulong p, ulong a, ulong num) +{ + int k; + dlog_bsgs_t t; + dlog_bsgs_init(t, a, p, p-1, ceil( sqrt((double)num * p))); + for (k = 1; k < num; k++) + { + if (k == p) continue; + dlog_bsgs(t, k % p); + } + dlog_bsgs_clear(t); +} +void +flog_rho(ulong p, ulong a, ulong num) +{ + int k; + dlog_rho_t t; + dlog_rho_init(t, a, p, p-1); + for (k = 1; k < num; k++) + { + if (k == p) continue; + dlog_rho(t, k % p); + } + dlog_rho_clear(t); +} +void +flog_crt(ulong p, ulong a, ulong num) +{ + int k; + dlog_crt_t t; + dlog_crt_init(t, a, p, p-1, num); + for (k = 1; k < num; k++) + { + if (k == p) continue; + dlog_crt(t, k % p); + } + dlog_crt_clear(t); +} +void +flog_gen(ulong p, ulong a, ulong num) +{ + int k; + dlog_precomp_t t; + dlog_precomp_n_init(t, a, p, p-1, num); + for (k = 1; k < num; k++) + { + if (k == p) continue; + dlog_precomp(t, k % p); + } + dlog_precomp_clear(t); +} +void +dlog_bench(multilog_f flog, const ulong * p, const ulong * a, int np, int num) +{ + int i; + ulong q; + TIMEIT_ONCE_START + for (i = 0; i < np; i ++) + flog(p[i], a[i], num); + TIMEIT_ONCE_STOP +} + +int main() +{ + slong iter, k, nv, nref, r, nr; + ulong minq, maxq; + ulong * rand; + int nbits, nl = 4; + int vl[5] = { 1, 10, 100, 1000 , 5000}; + flint_rand_t state; + + flint_randinit(state); + for (nbits = 10; nbits < 52; nbits += 10) + { + + int i, np = 100; + ulong p[100], a[100]; + for (i=0; i < np; i++) + { + p[i] = n_randprime(state, nbits, 0); + a[i] = n_primitive_root_prime(p[i]); + } + + for (i = 0; i < nl; i++) + { + flint_printf("%wu * logs mod primes of size %wu.....\n", vl[i], nbits); + + if (nbits <= 20) + { + flint_printf("table.......... "); + fflush(stdout); + dlog_bench(flog_table, p, a, np, vl[i]); + } + + if (nbits <= 40 || vl[i] <= 10) + { + flint_printf("bsgs........... "); + fflush(stdout); + dlog_bench(flog_bsgs, p, a, np, vl[i]); + } + + if (nbits <= 20 || vl[i] == 1) + { + flint_printf("rho............ "); + fflush(stdout); + dlog_bench(flog_rho, p, a, np, vl[i]); + } + + flint_printf("crt............ "); + fflush(stdout); + dlog_bench(flog_crt, p, a, np, vl[i]); + + flint_printf("generic........ "); + fflush(stdout); + dlog_bench(flog_gen, p, a, np, vl[i]); + } + } + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/test/t-dlog.c b/acb_dirichlet/test/t-dlog.c index 793b6fb9..91688e7d 100644 --- a/acb_dirichlet/test/t-dlog.c +++ b/acb_dirichlet/test/t-dlog.c @@ -39,6 +39,7 @@ int main() { dlog_table_t table; dlog_bsgs_t bsgs; + dlog_rho_t rho; dlog_precomp_t pre1, pre100; ulong p, a, k; @@ -46,26 +47,29 @@ int main() a = n_primitive_root_prime(p); dlog_table_init(table, a, p); - dlog_bsgs_init(bsgs, a, p, ceil(sqrt((double)p))); + dlog_bsgs_init(bsgs, a, p, p-1, ceil(sqrt((double)p))); + dlog_rho_init(rho, a, p, p-1); dlog_precomp_n_init(pre1, a, p, p-1, 1); dlog_precomp_n_init(pre100, a, p, p-1, 100); for (k = 1; k < 100 && k < p; k++) { - ulong l1, l2, l3, l4; + ulong l1, l2, l3, l4, l5; l1 = dlog_table(table, k); l2 = dlog_bsgs(bsgs, k); - l3 = dlog_precomp(pre1, k); - l4 = dlog_precomp(pre100, k); - if (l1 != l2 || l3 != l4 || l1 != l3) + l3 = dlog_rho(rho, k); + l4 = dlog_precomp(pre1, k); + l5 = dlog_precomp(pre100, k); + if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5) { - flint_printf("FAIL: log(%wu,%wu) mod %wu: [%wu, %wu, %wu, %wu]\n", - k, a, p, l1, l2, l3, l4); + flint_printf("FAIL: log(%wu,%wu) mod %wu: [%wu, %wu, %wu, %wu, %wu]\n", + k, a, p, l1, l2, l3, l4, l5); abort(); } } dlog_table_clear(table); dlog_bsgs_clear(bsgs); + dlog_rho_clear(rho); dlog_precomp_clear(pre1); dlog_precomp_clear(pre100); } From 5c084967408fdd475c664ae744275758bde1393e Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 11 Mar 2016 10:35:42 +0100 Subject: [PATCH 009/139] move discrete log to dlog dir --- Makefile.in | 2 +- acb_dirichlet/dlog.h => dlog.h | 0 acb_dirichlet/dlog_1modpe.c => dlog/1modpe.c | 0 acb_dirichlet/dlog_bsgs.c => dlog/bsgs.c | 0 acb_dirichlet/dlog_crt.c => dlog/crt.c | 0 acb_dirichlet/dlog_modpe.c => dlog/modpe.c | 0 acb_dirichlet/dlog_power.c => dlog/power.c | 0 acb_dirichlet/dlog_precomp.c => dlog/precomp.c | 0 .../profile/p-dlog_precomp.c => dlog/profile/p-precomp.c | 2 +- acb_dirichlet/dlog_rho.c => dlog/rho.c | 0 acb_dirichlet/dlog_table.c => dlog/table.c | 0 {acb_dirichlet => dlog}/test/t-dlog.c | 2 +- 12 files changed, 3 insertions(+), 3 deletions(-) rename acb_dirichlet/dlog.h => dlog.h (100%) rename acb_dirichlet/dlog_1modpe.c => dlog/1modpe.c (100%) rename acb_dirichlet/dlog_bsgs.c => dlog/bsgs.c (100%) rename acb_dirichlet/dlog_crt.c => dlog/crt.c (100%) rename acb_dirichlet/dlog_modpe.c => dlog/modpe.c (100%) rename acb_dirichlet/dlog_power.c => dlog/power.c (100%) rename acb_dirichlet/dlog_precomp.c => dlog/precomp.c (100%) rename acb_dirichlet/profile/p-dlog_precomp.c => dlog/profile/p-precomp.c (99%) rename acb_dirichlet/dlog_rho.c => dlog/rho.c (100%) rename acb_dirichlet/dlog_table.c => dlog/table.c (100%) rename {acb_dirichlet => dlog}/test/t-dlog.c (98%) diff --git a/Makefile.in b/Makefile.in index 0421296e..38024bd3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -14,7 +14,7 @@ AT=@ BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \ acb_calc acb_hypgeom acb_modular acb_dirichlet arb_hypgeom bernoulli hypgeom \ - fmpz_extras bool_mat partitions \ + fmpz_extras bool_mat partitions dlog \ $(EXTRA_BUILD_DIRS) TEMPLATE_DIRS = diff --git a/acb_dirichlet/dlog.h b/dlog.h similarity index 100% rename from acb_dirichlet/dlog.h rename to dlog.h diff --git a/acb_dirichlet/dlog_1modpe.c b/dlog/1modpe.c similarity index 100% rename from acb_dirichlet/dlog_1modpe.c rename to dlog/1modpe.c diff --git a/acb_dirichlet/dlog_bsgs.c b/dlog/bsgs.c similarity index 100% rename from acb_dirichlet/dlog_bsgs.c rename to dlog/bsgs.c diff --git a/acb_dirichlet/dlog_crt.c b/dlog/crt.c similarity index 100% rename from acb_dirichlet/dlog_crt.c rename to dlog/crt.c diff --git a/acb_dirichlet/dlog_modpe.c b/dlog/modpe.c similarity index 100% rename from acb_dirichlet/dlog_modpe.c rename to dlog/modpe.c diff --git a/acb_dirichlet/dlog_power.c b/dlog/power.c similarity index 100% rename from acb_dirichlet/dlog_power.c rename to dlog/power.c diff --git a/acb_dirichlet/dlog_precomp.c b/dlog/precomp.c similarity index 100% rename from acb_dirichlet/dlog_precomp.c rename to dlog/precomp.c diff --git a/acb_dirichlet/profile/p-dlog_precomp.c b/dlog/profile/p-precomp.c similarity index 99% rename from acb_dirichlet/profile/p-dlog_precomp.c rename to dlog/profile/p-precomp.c index 533c6db9..3b0638d9 100644 --- a/acb_dirichlet/profile/p-dlog_precomp.c +++ b/dlog/profile/p-precomp.c @@ -23,7 +23,7 @@ ******************************************************************************/ -#include "acb_dirichlet/dlog.h" +#include "dlog.h" #include "profiler.h" #include diff --git a/acb_dirichlet/dlog_rho.c b/dlog/rho.c similarity index 100% rename from acb_dirichlet/dlog_rho.c rename to dlog/rho.c diff --git a/acb_dirichlet/dlog_table.c b/dlog/table.c similarity index 100% rename from acb_dirichlet/dlog_table.c rename to dlog/table.c diff --git a/acb_dirichlet/test/t-dlog.c b/dlog/test/t-dlog.c similarity index 98% rename from acb_dirichlet/test/t-dlog.c rename to dlog/test/t-dlog.c index 91688e7d..020b43a1 100644 --- a/acb_dirichlet/test/t-dlog.c +++ b/dlog/test/t-dlog.c @@ -23,7 +23,7 @@ ******************************************************************************/ -#include "acb_dirichlet/dlog.h" +#include "dlog.h" #include int main() From 0a56baebf2cb2ecf16bafe4abb31708eed93a815 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 11 Mar 2016 16:59:49 +0100 Subject: [PATCH 010/139] use flint nmod structure + start dlog_vec functions --- dlog.h | 19 ++-- dlog/crt.c | 12 +-- dlog/power.c | 23 ++--- dlog/profile/p-vec.c | 103 ++++++++++++++++++++ dlog/rho.c | 60 ++++++------ dlog/vec.c | 217 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 374 insertions(+), 60 deletions(-) create mode 100644 dlog/profile/p-vec.c create mode 100644 dlog/vec.c diff --git a/dlog.h b/dlog.h index e9096ef6..cdb9ae75 100644 --- a/dlog.h +++ b/dlog.h @@ -26,8 +26,9 @@ #ifndef DLOG_H #define DLOG_H -#include "padic.h" #include "ulong_extras.h" +#include "nmod_vec.h" +#include "padic.h" enum { @@ -56,7 +57,6 @@ typedef struct ulong p; ulong e; ulong pe; - /*dlog_precomp_t modp;*/ dlog_precomp_struct * modp; dlog_1modpe_t modpe; } @@ -96,8 +96,8 @@ typedef dlog_bsgs_struct dlog_bsgs_t[1]; /* Pollard rho */ typedef struct { ulong a; - ulong n; - ulong mod; + nmod_t n; + nmod_t mod; int nisprime; } dlog_rho_struct; @@ -106,8 +106,8 @@ typedef dlog_rho_struct dlog_rho_t[1]; /* CRT decomposition (Pohlig-Hellman) */ typedef struct { - ulong mod; - ulong n; + nmod_t mod; + nmod_t n; ulong num; ulong * expo; ulong * crt_coeffs; @@ -124,7 +124,7 @@ typedef dlog_crt_struct dlog_crt_t[1]; /* dlog when generator has prime power order */ typedef struct { - ulong mod; + nmod_t mod; ulong p; ulong e; ulong * apk; @@ -189,4 +189,9 @@ void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong void dlog_precomp_clear(dlog_precomp_t pre); ulong dlog_precomp(const dlog_precomp_t pre, ulong b); +void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); +void dlog_vec_sieve(ulong * v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); +void dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); + + #endif diff --git a/dlog/crt.c b/dlog/crt.c index f3d41153..84f7c18e 100644 --- a/dlog/crt.c +++ b/dlog/crt.c @@ -36,8 +36,8 @@ dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) n_factor(&fac, n, 1); t->num = fac.num; - t->mod = mod; - t->n = n; + nmod_init(&t->mod,mod); + nmod_init(&t->n, n); M = t->expo = flint_malloc(t->num * sizeof(ulong)); u = t->crt_coeffs = flint_malloc(t->num * sizeof(ulong)); @@ -52,9 +52,9 @@ dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) e = fac.exp[k]; mk = n_pow(p, e); M[k] = n / mk; - u[k] = M[k] * n_invmod(M[k] % mk, mk) % n; + u[k] = nmod_mul(M[k], n_invmod(M[k] % mk, mk), t->n); /* depends on the power */ - dlog_precomp_pe_init(t->pre[k], n_powmod(a, M[k], mod), mod, p, e, mk, num); + dlog_precomp_pe_init(t->pre[k], nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); } } @@ -80,13 +80,13 @@ dlog_crt(const dlog_crt_t t, ulong b) for (k = 0; k < t->num; k++) { ulong bk, rk; - bk = n_powmod(b, t->expo[k], t->mod); + bk = nmod_pow_ui(b, t->expo[k], t->mod); rk = dlog_precomp(t->pre[k], bk); #if 0 flint_printf("##[crt-%d]: log(%wu)=log(%wu^%wu) = %wu [size %wu mod %wu]\n", k, bk, b, t->expo[k], rk, t->n/t->expo[k], t->mod); #endif - r = (r + t->crt_coeffs[k] * rk) % t->n; + r = nmod_add(r, nmod_mul(t->crt_coeffs[k], rk, t->n), t->n); } return r; } diff --git a/dlog/power.c b/dlog/power.c index 826cc82d..26dafe8e 100644 --- a/dlog/power.c +++ b/dlog/power.c @@ -29,18 +29,18 @@ void dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) { int k; - t->mod = mod; + nmod_init(&t->mod, mod); t->p = p; t->e = e; t->apk = flint_malloc(e * sizeof(ulong)); t->pre = flint_malloc(sizeof(dlog_precomp_struct)); - t->apk[0] = n_invmod(a, mod); + t->apk[0] = nmod_inv(a, t->mod); for (k = 1; k < e; k++) - t->apk[k] = n_powmod(t->apk[k-1], p, mod); + t->apk[k] = nmod_pow_ui(t->apk[k-1], p, t->mod); - dlog_precomp_p_init(t->pre, n_invmod(t->apk[e-1], mod), mod, p, num); + dlog_precomp_p_init(t->pre, nmod_inv(t->apk[e-1], t->mod), mod, p, num); } void @@ -51,30 +51,23 @@ dlog_power_clear(dlog_power_t t) flint_free(t->pre); } -/* 3^30*2+1, 2^30*3+1 are primes */ - ulong dlog_power(const dlog_power_t t, ulong b) { int k; -#ifdef C99 - ulong pk[t->e]; -#else - ulong pk[30]; -#endif - ulong x; + ulong x, pk[30]; /* 3^30*2+1, 2^30*3+1 are primes */ pk[0] = 1; for (k = 1; k < t->e; k++) - pk[k] = pk[k-1]*t->p; + pk[k] = pk[k-1] * t->p; x = 0; for(k = 0; k < t->e; k++) { ulong bk, xk; - bk = n_powmod(b, pk[t->e-1-k], t->mod); + bk = nmod_pow_ui(b, pk[t->e-1-k], t->mod); xk = dlog_precomp(t->pre, bk); - b = b * n_powmod(t->apk[k], xk, t->mod) % t->mod; + b = nmod_mul(b, nmod_pow_ui(t->apk[k], xk, t->mod), t->mod); x += xk * pk[k]; /* cannot overflow */ } return x; diff --git a/dlog/profile/p-vec.c b/dlog/profile/p-vec.c new file mode 100644 index 00000000..91aee7e8 --- /dev/null +++ b/dlog/profile/p-vec.c @@ -0,0 +1,103 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include "profiler.h" +typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); + +void +f_empty(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) +{ + return; +} + +int main() +{ + int i, ni = 3; + int bits[5] = { 10, 20, 30, 40, 50 }; + + int j, nj = 5; + ulong * v; + ulong nv[5] = { 50, 200, 1000, 2000, 10000 }; + + int k, np = 1000; + nmod_t * p; + ulong * a; + + int l, nf = 3; + vec_f func[4] = { f_empty, dlog_vec_loop, dlog_vec_sieve, dlog_vec_crt }; + char * n[4] = { "empty", "loop", "sieve", "crt" }; + + flint_rand_t state; + nmod_t order; + + nmod_init(&order, 100); + p = flint_malloc(np * sizeof(nmod_t)); + a = flint_malloc(np * sizeof(ulong)); + + for (i = 0; i < ni; i++) + { + for (k = 0; k < np; k++) + { + nmod_init(&p[k], n_randprime(state, bits[i], 0)); + a[k] = n_primitive_root_prime(p[k].n); + } + + for (j = 0; j < nj; j++) + { + + v = flint_malloc(nv[j] * sizeof(ulong)); + + flint_printf("log(1..%wu) mod %d primes of size %d bits....\n", nv[j], np, bits[i]); + fflush(stdout); + + for (l = 0; l < nf; l++) + { + if (l == 1 && (i >= 2 || j > 0)) + continue; + + flint_printf("%-20s... ",n[l]); + fflush(stdout); + TIMEIT_ONCE_START + for (k = 0; k < np; k++) + { + int kk; + for (kk=0; kk < nv[j]; kk++) + v[kk] = 0; + (func[l])(v, nv[j], a[k], 1, p[k], p[k].n - 1, order); + } + TIMEIT_ONCE_STOP + } + flint_free(v); + } + } + + flint_free(p); + flint_free(a); + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/dlog/rho.c b/dlog/rho.c index 666a841f..84d02681 100644 --- a/dlog/rho.c +++ b/dlog/rho.c @@ -30,8 +30,8 @@ void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) { t->a = a; - t->n = n; - t->mod = mod; + nmod_init(&t->n, n); + nmod_init(&t->mod, mod); t->nisprime = n_is_prime(n); } @@ -42,7 +42,7 @@ dlog_rho_clear(dlog_rho_t t) } static ulong -dlog_once(ulong b, ulong a, ulong mod, ulong n) +dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) { if (n < 50) { @@ -52,14 +52,14 @@ dlog_once(ulong b, ulong a, ulong mod, ulong n) { if (ak == b) return k; - ak = (ak * a) % mod; + ak = nmod_mul(ak, a, mod); } flint_printf("FAIL[dlog once]: log(%wu,%wu) mod %wu not found (size %wu)\n", - b, a, mod, n); + b, a, mod.n, n); abort(); } else { dlog_rho_t t; - dlog_rho_init(t, a, mod, n); + dlog_rho_init(t, a, mod.n, n); return dlog_rho(t, b); } } @@ -68,22 +68,21 @@ dlog_once(ulong b, ulong a, ulong mod, ulong n) static ulong dlog_quotient(const dlog_rho_t t, ulong e, ulong f, ulong g, ulong b) { - ulong r, n, b_ar, an; - n = t->n; - if (g == n) + ulong r, b_ar, an; + nmod_t n = t->n; + if (g == n.n) { flint_printf("FAIL[dlog quotient]: trivial relation e = %wu, f = %wu mod %wu\n", - e, f, n); + e, f, n.n); abort(); } - n = n / g; + nmod_init(&n, n.n / g); e = e / g; f = f / g; - f = n_invmod(f, n); - r = ( e * f ) % n; - an = n_powmod(t->a, n, t->mod); - b_ar = (b * n_invmod(n_powmod(t->a, r, t->mod), t->mod)) % t->mod; - return r + n * dlog_once(b_ar, an, t->mod, g); + r = nmod_div(e, f, n); + an = nmod_pow_ui(t->a, n.n, t->mod); + b_ar = nmod_div(b, nmod_pow_ui(t->a, r, t->mod), t->mod); + return r + n.n * dlog_once(b_ar, an, t->mod, g); } #define RWALK 20 @@ -94,13 +93,14 @@ dlog_rho(const dlog_rho_t t, ulong b) ulong m[RWALK], n[RWALK], ab[RWALK]; ulong x[2], e[2], f[2], g; flint_rand_t state; + flint_randinit(state); do { for (k = 0; k < RWALK; k++) { - m[k] = 1 + n_randint(state, t->n - 1); - n[k] = 1 + n_randint(state, t->n - 1); - ab[k] = (n_powmod(t->a, m[k], t->mod) * n_powmod(b, n[k], t->mod)) % t->mod; + m[k] = 1 + n_randint(state, t->n.n - 1); + n[k] = 1 + n_randint(state, t->n.n - 1); + ab[k] = nmod_mul(nmod_pow_ui(t->a, m[k], t->mod), nmod_pow_ui(b, n[k], t->mod), t->mod); } /* x[l] = a^e[l] * b^f[l] */ x[0] = x[1] = 1; @@ -110,24 +110,20 @@ dlog_rho(const dlog_rho_t t, ulong b) for(j = 0; j < 3; j++) { l = (j > 0); - k = floor( (double) RWALK * x[l] / t->mod ); - x[l] = (x[l] * ab[k]) % t->mod; - e[l] = (e[l] + m[k]) % t->n; - f[l] = (f[l] + n[k]) % t->n; + k = floor( (double) RWALK * x[l] / t->mod.n ); + x[l] = nmod_mul(x[l], ab[k], t->mod); + e[l] = nmod_add(e[l], m[k], t->n); + f[l] = nmod_add(f[l], n[k], t->n); } } while (x[0] != x[1]); } while (e[0] == e[1] && f[0] == f[1]); flint_randclear(state); + /* e = f * log(b) */ - e[0] = (e[0] > e[1]) ? e[0] - e[1] : e[0] + t->n - e[1]; - f[0] = (f[1] > f[0]) ? f[1] - f[0] : f[1] + t->n - f[0]; - if (!t->nisprime && (g = n_gcd(f[0], t->n)) > 1) - { + e[0] = nmod_sub(e[0], e[1], t->n); + f[0] = nmod_sub(f[1], f[0], t->n); + if (!t->nisprime && (g = n_gcd(f[0], t->n.n)) > 1) return dlog_quotient(t, e[0], f[0], g, b); - } else - { - f[0] = n_invmod(f[0], t->n); - return ( e[0] * f[0] ) % t->n; - } + return nmod_div(e[0], f[0], t->n); } diff --git a/dlog/vec.c b/dlog/vec.c new file mode 100644 index 00000000..409cf0cf --- /dev/null +++ b/dlog/vec.c @@ -0,0 +1,217 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "math.h" +#include "dlog.h" +#define NOT_FOUND UWORD_MAX + +/* vector of log(k,a)*loga % order in Z/modZ */ +void +dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) +{ + ulong x, xp; + long vx = 0; + for(x = a; x != 1; x = nmod_mul(x, a, mod)) + { + vx = nmod_add(vx, va, order); + for(xp = x; xp < nv; xp+=mod.n) + v[xp] = nmod_add(v[xp], vx, order); + } +} + +static ulong +logp_sieve(ulong * v, ulong nv, ulong p, ulong mod, ulong logm1, const nmod_t order, int maxtry) +{ + int i, j, nr = 0, nm = 0, ng = 0; + ulong l, pm, logm; + ulong u[2], r[2], t; +#if rnd + flint_rand_t state; + flint_randinit(state); +#endif +#if vbs + flint_printf("\nEnter logp_sieve p=%wu mod %wu...\n", p, mod); +#endif + while (1) { + /* find multiplier m */ + logm = 0; + pm = l = p; + do { + nm++; + /* random ? pb when p lies in a small subgroup */ + do { + nr++; +#if rnd + l = 1 + n_randint(state, p - 1); +#else + l = (l > 1) ? l - 1 : p - 1; +#endif + } while (v[l] == NOT_FOUND); + pm *= l; + logm += v[l]; + } while (pm < mod); + pm = pm % mod; +#if vbs + flint_printf("[pm=%wu, v[pm]=%ld]", pm, v[pm]); +#endif + /* half gcd u * pm + v * mod = r, ignore v */ + u[0] = 0; r[0] = mod; + u[1] = 1; r[1] = pm; + i = 1; j = 0; /* flip flap */ + do { + ng++; +#if vbs + flint_printf("[r=%d, v[r]=%d, u=%d, v[u]=%d]\n", + r[i],v[r[i]], u[i], v[u[i]]); +#endif + if (r[i] < nv && v[r[i]] != NOT_FOUND && u[i] < nv && v[u[i]] != NOT_FOUND) + { + ulong x; + /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ + x = nmod_sub(v[r[i]], nmod_add(v[u[i]], logm, order), order); + if (j) + x = nmod_add(x, logm1, order); +#if rnd + flint_randclear(state); +#endif + return x; + } + + j = i; i = 1 - i; /* switch */ + t = r[i] / r[j]; + r[i] = r[i] % r[j]; + u[i] = u[i] + t * u[j]; /* (-1)^j */ + + } while (r[i] > 0 && u[i] < p); + if (nm > maxtry) + return NOT_FOUND; + } +} + +void +dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) +{ + int maxtry; + ulong k, p, p1, pmax, logm1; + ulong * w; + dlog_precomp_t pre; + n_primes_t iter; + + w = flint_malloc( nv * sizeof(ulong)); + for (k = 0; k < nv; k++) + w[k] = NOT_FOUND; + w[1] = 0; + + /* discrete log on first primes, then sieve */ + pmax = (nv < mod.n) ? nv : mod.n; + p1 = maxtry = 50; /* FIXME: tune this limit! */ + dlog_precomp_n_init(pre, a, mod.n, na, p1); + + logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); + + n_primes_init(iter); + while ((p = n_primes_next(iter)) < pmax) + { + ulong m, wp; + if (mod.n % p == 0) /* FIXME: those primes could be known... */ + continue; /* won't be attained another time */ + if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, maxtry)) != NOT_FOUND) + wp = nmod_mul(dlog_precomp(pre, p), va, order); + for (k = p, m = 1; k < nv; k += p, m++) + w[k] = nmod_add(w[m], wp, order); + } + for (k = 0; k < nv; k++) + if (v[k] != NOT_FOUND) + v[k] = nmod_add(v[k], w[k], order); + n_primes_clear(iter); + flint_free(w); +} + +/* group components up to bound and return cofactor */ +#define LOOP 0 +#define SIEVE 1 +static void +n_factor_group(n_factor_t * fac, ulong bound) +{ + int i, j, k; + ulong m[FLINT_MAX_FACTORS_IN_LIMB]; + ulong c = 1; + i = 0; + for (k = fac->num - 1; k >= 0; k--) + { + ulong qe = n_pow(fac->p[k], fac->exp[k]); + if (qe > bound) + c *= qe; + else + { + /* try to insert somewhere in m */ + for (j = 0; j < i && (m[j] * qe > bound); j++); + if (j == i) + m[i++] = qe; + else + m[j] *= qe; + } + } + for (j = 0; j < i; j++) + { + fac->p[j] = m[j]; + fac->exp[j] = LOOP; + } + if (c > 1) + { + fac->p[i] = c; + fac->exp[i] = SIEVE; + i++; + } + fac->num = i; +} + +/* assume v[k] = -1 for bad primes? */ +/* loop on small components and keep one subgroup for DLOG + sieve */ + void +dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + n_factor_t fac; + ulong maxloop; + int k; + + maxloop = 3 * nv; /* FIXME: tune this */ + n_factor_init(&fac); + n_factor(&fac, na, 1); + n_factor_group(&fac, maxloop); + for (k = 0; k < fac.num; k++) + { + ulong m, M, aM, uM, vaM; + m = fac.p[k]; + M = na / m; + aM = nmod_pow_ui(a, M, mod); + uM = M * n_invmod(M % m, m); /* uM < n */ + vaM = nmod_mul(va, uM % order.n, order); + if (fac.exp[k] == LOOP) + dlog_vec_loop(v, nv, aM, vaM, mod, m, order); + else + dlog_vec_sieve(v, nv, aM, vaM, mod, m, order); + } +} From 390ac927353e0e240278a1a30e7a31b37455da18 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 14 Mar 2016 11:00:14 +0100 Subject: [PATCH 011/139] split dlog vec --- dlog.h | 13 +++- dlog/vec.c | 192 ++--------------------------------------------- dlog/vec_crt.c | 93 +++++++++++++++++++++++ dlog/vec_loop.c | 40 ++++++++++ dlog/vec_sieve.c | 142 +++++++++++++++++++++++++++++++++++ 5 files changed, 290 insertions(+), 190 deletions(-) create mode 100644 dlog/vec_crt.c create mode 100644 dlog/vec_loop.c create mode 100644 dlog/vec_sieve.c diff --git a/dlog.h b/dlog.h index cdb9ae75..e645a39d 100644 --- a/dlog.h +++ b/dlog.h @@ -189,9 +189,16 @@ void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong void dlog_precomp_clear(dlog_precomp_t pre); ulong dlog_precomp(const dlog_precomp_t pre, ulong b); -void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); -void dlog_vec_sieve(ulong * v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); -void dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +#define NOT_FOUND UWORD_MAX +#define LOOP_MAX_FACTOR 6 +typedef struct +{ + ulong m, logm; +} log_pair_t; +void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); #endif diff --git a/dlog/vec.c b/dlog/vec.c index 409cf0cf..8145d307 100644 --- a/dlog/vec.c +++ b/dlog/vec.c @@ -23,195 +23,13 @@ ******************************************************************************/ -#include "math.h" #include "dlog.h" -#define NOT_FOUND UWORD_MAX - -/* vector of log(k,a)*loga % order in Z/modZ */ -void -dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) -{ - ulong x, xp; - long vx = 0; - for(x = a; x != 1; x = nmod_mul(x, a, mod)) - { - vx = nmod_add(vx, va, order); - for(xp = x; xp < nv; xp+=mod.n) - v[xp] = nmod_add(v[xp], vx, order); - } -} - -static ulong -logp_sieve(ulong * v, ulong nv, ulong p, ulong mod, ulong logm1, const nmod_t order, int maxtry) -{ - int i, j, nr = 0, nm = 0, ng = 0; - ulong l, pm, logm; - ulong u[2], r[2], t; -#if rnd - flint_rand_t state; - flint_randinit(state); -#endif -#if vbs - flint_printf("\nEnter logp_sieve p=%wu mod %wu...\n", p, mod); -#endif - while (1) { - /* find multiplier m */ - logm = 0; - pm = l = p; - do { - nm++; - /* random ? pb when p lies in a small subgroup */ - do { - nr++; -#if rnd - l = 1 + n_randint(state, p - 1); -#else - l = (l > 1) ? l - 1 : p - 1; -#endif - } while (v[l] == NOT_FOUND); - pm *= l; - logm += v[l]; - } while (pm < mod); - pm = pm % mod; -#if vbs - flint_printf("[pm=%wu, v[pm]=%ld]", pm, v[pm]); -#endif - /* half gcd u * pm + v * mod = r, ignore v */ - u[0] = 0; r[0] = mod; - u[1] = 1; r[1] = pm; - i = 1; j = 0; /* flip flap */ - do { - ng++; -#if vbs - flint_printf("[r=%d, v[r]=%d, u=%d, v[u]=%d]\n", - r[i],v[r[i]], u[i], v[u[i]]); -#endif - if (r[i] < nv && v[r[i]] != NOT_FOUND && u[i] < nv && v[u[i]] != NOT_FOUND) - { - ulong x; - /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ - x = nmod_sub(v[r[i]], nmod_add(v[u[i]], logm, order), order); - if (j) - x = nmod_add(x, logm1, order); -#if rnd - flint_randclear(state); -#endif - return x; - } - - j = i; i = 1 - i; /* switch */ - t = r[i] / r[j]; - r[i] = r[i] % r[j]; - u[i] = u[i] + t * u[j]; /* (-1)^j */ - - } while (r[i] > 0 && u[i] < p); - if (nm > maxtry) - return NOT_FOUND; - } -} void -dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) +dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - int maxtry; - ulong k, p, p1, pmax, logm1; - ulong * w; - dlog_precomp_t pre; - n_primes_t iter; - - w = flint_malloc( nv * sizeof(ulong)); - for (k = 0; k < nv; k++) - w[k] = NOT_FOUND; - w[1] = 0; - - /* discrete log on first primes, then sieve */ - pmax = (nv < mod.n) ? nv : mod.n; - p1 = maxtry = 50; /* FIXME: tune this limit! */ - dlog_precomp_n_init(pre, a, mod.n, na, p1); - - logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); - - n_primes_init(iter); - while ((p = n_primes_next(iter)) < pmax) - { - ulong m, wp; - if (mod.n % p == 0) /* FIXME: those primes could be known... */ - continue; /* won't be attained another time */ - if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, maxtry)) != NOT_FOUND) - wp = nmod_mul(dlog_precomp(pre, p), va, order); - for (k = p, m = 1; k < nv; k += p, m++) - w[k] = nmod_add(w[m], wp, order); - } - for (k = 0; k < nv; k++) - if (v[k] != NOT_FOUND) - v[k] = nmod_add(v[k], w[k], order); - n_primes_clear(iter); - flint_free(w); -} - -/* group components up to bound and return cofactor */ -#define LOOP 0 -#define SIEVE 1 -static void -n_factor_group(n_factor_t * fac, ulong bound) -{ - int i, j, k; - ulong m[FLINT_MAX_FACTORS_IN_LIMB]; - ulong c = 1; - i = 0; - for (k = fac->num - 1; k >= 0; k--) - { - ulong qe = n_pow(fac->p[k], fac->exp[k]); - if (qe > bound) - c *= qe; - else - { - /* try to insert somewhere in m */ - for (j = 0; j < i && (m[j] * qe > bound); j++); - if (j == i) - m[i++] = qe; - else - m[j] *= qe; - } - } - for (j = 0; j < i; j++) - { - fac->p[j] = m[j]; - fac->exp[j] = LOOP; - } - if (c > 1) - { - fac->p[i] = c; - fac->exp[i] = SIEVE; - i++; - } - fac->num = i; -} - -/* assume v[k] = -1 for bad primes? */ -/* loop on small components and keep one subgroup for DLOG + sieve */ - void -dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) -{ - n_factor_t fac; - ulong maxloop; - int k; - - maxloop = 3 * nv; /* FIXME: tune this */ - n_factor_init(&fac); - n_factor(&fac, na, 1); - n_factor_group(&fac, maxloop); - for (k = 0; k < fac.num; k++) - { - ulong m, M, aM, uM, vaM; - m = fac.p[k]; - M = na / m; - aM = nmod_pow_ui(a, M, mod); - uM = M * n_invmod(M % m, m); /* uM < n */ - vaM = nmod_mul(va, uM % order.n, order); - if (fac.exp[k] == LOOP) - dlog_vec_loop(v, nv, aM, vaM, mod, m, order); - else - dlog_vec_sieve(v, nv, aM, vaM, mod, m, order); - } + if (na * LOOP_MAX_FACTOR > nv) + dlog_vec_loop(v, nv, a, va, mod, na, order); + else + dlog_vec_crt(v, nv, a, va, mod, na, order); } diff --git a/dlog/vec_crt.c b/dlog/vec_crt.c new file mode 100644 index 00000000..cb8b8076 --- /dev/null +++ b/dlog/vec_crt.c @@ -0,0 +1,93 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +/* group components up to bound and return cofactor */ +#define LOOP 0 +#define SIEVE 1 +static void +n_factor_group(n_factor_t * fac, ulong bound) +{ + int i, j, k; + ulong m[FLINT_MAX_FACTORS_IN_LIMB]; + ulong c = 1; + i = 0; + for (k = fac->num - 1; k >= 0; k--) + { + ulong qe = n_pow(fac->p[k], fac->exp[k]); + if (qe > bound) + c *= qe; + else + { + /* try to insert somewhere in m */ + for (j = 0; j < i && (m[j] * qe > bound); j++); + if (j == i) + m[i++] = qe; + else + m[j] *= qe; + } + } + for (j = 0; j < i; j++) + { + fac->p[j] = m[j]; + fac->exp[j] = LOOP; + } + if (c > 1) + { + fac->p[i] = c; + fac->exp[i] = SIEVE; + i++; + } + fac->num = i; +} + +/* assume v[k] = -1 for bad primes? */ +/* loop on small components and keep one subgroup for DLOG + sieve */ + void +dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + n_factor_t fac; + ulong maxloop; + int k; + + maxloop = LOOP_MAX_FACTOR * nv; + n_factor_init(&fac); + n_factor(&fac, na, 1); + n_factor_group(&fac, maxloop); + for (k = 0; k < fac.num; k++) + { + ulong m, M, aM, uM, vaM; + m = fac.p[k]; + M = na / m; + aM = nmod_pow_ui(a, M, mod); + uM = M * n_invmod(M % m, m); /* uM < n */ + vaM = nmod_mul(va, uM % order.n, order); + if (fac.exp[k] == LOOP) + dlog_vec_loop(v, nv, aM, vaM, mod, m, order); + else + dlog_vec_sieve(v, nv, aM, vaM, mod, m, order); + } +} diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c new file mode 100644 index 00000000..4bd8e792 --- /dev/null +++ b/dlog/vec_loop.c @@ -0,0 +1,40 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +/* vector of log(k,a)*loga % order in Z/modZ */ +void +dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + ulong x, xp; + ulong vx = 0; + for(x = a; x != 1; x = nmod_mul(x, a, mod)) + { + vx = nmod_add(vx, va, order); + for(xp = x; xp < nv; xp+=mod.n) + v[xp] = nmod_add(v[xp], vx, order); + } +} diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c new file mode 100644 index 00000000..9981db93 --- /dev/null +++ b/dlog/vec_sieve.c @@ -0,0 +1,142 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +static ulong +logp_sieve(log_pair_t * v, ulong nv, ulong p, ulong mod, ulong logm1, nmod_t order, int maxtry) +{ + int i, j, nr = 0, nm = 0, ng = 0; + ulong l, pm, logm; + ulong u[2], r[2], t; +#if rnd + flint_rand_t state; + flint_randinit(state); +#endif +#if vbs + flint_printf("\nEnter logp_sieve p=%wu mod %wu...\n", p, mod); +#endif + while (1) { + /* find multiplier m */ + logm = 0; + pm = l = p; + do { + nm++; + /* random ? pb when p lies in a small subgroup */ + do { + nr++; +#if rnd + l = 1 + n_randint(state, p - 1); +#else + l = (l > 1) ? l - 1 : p - 1; +#endif + } while (v[l].m != l); + pm *= l; + logm += v[l].logm; + } while (pm < mod); + pm = pm % mod; +#if vbs + flint_printf("[pm=%wu, v[pm]=%ld]", pm, v[pm]); +#endif + /* half gcd u * pm + v * mod = r, ignore v */ + u[0] = 0; r[0] = mod; + u[1] = 1; r[1] = pm; + i = 1; j = 0; /* flip flap */ + do { + ng++; +#if vbs + flint_printf("[r=%d, v[r]=%d, u=%d, v[u]=%d]\n", + r[i],v[r[i]], u[i], v[u[i]]); +#endif + if (r[i] < nv && v[r[i]].m == r[i] && u[i] < nv && v[u[i]].m == u[i]) + { + ulong x; + /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ + x = nmod_sub(v[r[i]].logm, nmod_add(v[u[i]].logm, logm, order), order); + if (j) + x = nmod_add(x, logm1, order); +#if rnd + flint_randclear(state); +#endif + return x; + } + + j = i; i = 1 - i; /* switch */ + t = r[i] / r[j]; + r[i] = r[i] % r[j]; + u[i] = u[i] + t * u[j]; /* (-1)^j */ + + } while (r[i] > 0 && u[i] < p); + if (nm > maxtry) + return NOT_FOUND; + } +} + +void +dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + int maxtry; + ulong k, p, p1, pmax, logm1; + log_pair_t * w; + dlog_precomp_t pre; + n_primes_t iter; + + /* store size */ + w = flint_malloc( nv * sizeof(log_pair_t)); + for (k = 0; k < nv; k++) + { + w[k].m = 1; + w[k].logm = 1; + } + w[1].logm = 0; + + /* discrete log on first primes, then sieve */ + pmax = (nv < mod.n) ? nv : mod.n; + p1 = maxtry = 50; /* FIXME: tune this limit! */ + dlog_precomp_n_init(pre, a, mod.n, na, p1); + + logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); + + n_primes_init(iter); + while ((p = n_primes_next(iter)) < pmax) + { + ulong m, wp; + if (mod.n % p == 0) /* FIXME: those primes could be known... */ + continue; /* won't be attained another time */ + if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, maxtry)) != NOT_FOUND) + wp = nmod_mul(dlog_precomp(pre, p), va, order); + for (k = p, m = 1; k < nv; k += p, m++) + { + w[k].m *= p; + w[k].logm = nmod_add(w[k].logm, wp, order); + } + } + /* write in v */ + for (k = 0; k < nv; k++) + if (v[k] != NOT_FOUND) + v[k] = nmod_add(v[k], w[k].logm, order); + n_primes_clear(iter); + flint_free(w); +} From 387c7f19e3c45ea70d4dae6702ddf018719fcaf9 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 14 Mar 2016 11:14:54 +0100 Subject: [PATCH 012/139] split dlog files, use nmod in bsgs --- dlog.h | 7 ++- dlog/1modpe.c | 37 +---------- dlog/1modpe_init.c | 50 +++++++++++++++ dlog/bsgs.c | 43 +------------ dlog/bsgs_init.c | 63 +++++++++++++++++++ dlog/crt.c | 47 -------------- dlog/crt_init.c | 73 ++++++++++++++++++++++ dlog/power.c | 26 -------- dlog/power_init.c | 52 ++++++++++++++++ dlog/precomp.c | 120 ------------------------------------ dlog/precomp_init.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ dlog/table.c | 23 ------- dlog/table_init.c | 50 +++++++++++++++ 13 files changed, 441 insertions(+), 296 deletions(-) create mode 100644 dlog/1modpe_init.c create mode 100644 dlog/bsgs_init.c create mode 100644 dlog/crt_init.c create mode 100644 dlog/power_init.c create mode 100644 dlog/precomp_init.c create mode 100644 dlog/table_init.c diff --git a/dlog.h b/dlog.h index e645a39d..ce63e62d 100644 --- a/dlog.h +++ b/dlog.h @@ -81,12 +81,13 @@ typedef struct apow { ulong ak; } apow_t; +int apow_cmp(const apow_t * x, const apow_t * y); + typedef struct { - ulong mod; - double modinv; + nmod_t mod; ulong m; - ulong g; ulong am; + ulong g; apow_t * table; } dlog_bsgs_struct; diff --git a/dlog/1modpe.c b/dlog/1modpe.c index ee742f4e..a037d5f4 100644 --- a/dlog/1modpe.c +++ b/dlog/1modpe.c @@ -23,42 +23,7 @@ ******************************************************************************/ -#include "acb_dirichlet.h" -#include "padic.h" - -typedef struct -{ - ulong p; - padic_ctx_t ctx; /* padic context */ - padic_t invlog; -} -dlog_1modpe_struct; - -typedef dlog_1modpe_struct dlog_1modpe_t[1]; - -void -dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e) -{ - fmpz_t tmp; - t->p = p; - fmpz_init(tmp); - padic_init(t->invlog); - - fmpz_set_ui(tmp, p); - padic_ctx_init(t->ctx , tmp , 0 , e, PADIC_TERSE); - - padic_set_ui(t->invlog, a1, t->ctx); - padic_inv(t->invlog, t->invlog, t->ctx); - - fmpz_clear(tmp); -} - -void -dlog_1modpe_clear(dlog_1modpe_t t) -{ - padic_clear(t->invlog); - padic_ctx_clear(t->ctx); -} +#include "dlog.h" /* assume b = 1 mod p, not checked */ ulong diff --git a/dlog/1modpe_init.c b/dlog/1modpe_init.c new file mode 100644 index 00000000..3226bcb2 --- /dev/null +++ b/dlog/1modpe_init.c @@ -0,0 +1,50 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e) +{ + fmpz_t tmp; + t->p = p; + fmpz_init(tmp); + padic_init(t->invlog); + + fmpz_set_ui(tmp, p); + padic_ctx_init(t->ctx , tmp , 0 , e, PADIC_TERSE); + + padic_set_ui(t->invlog, a1, t->ctx); + padic_inv(t->invlog, t->invlog, t->ctx); + + fmpz_clear(tmp); +} + +void +dlog_1modpe_clear(dlog_1modpe_t t) +{ + padic_clear(t->invlog); + padic_ctx_clear(t->ctx); +} diff --git a/dlog/bsgs.c b/dlog/bsgs.c index 9e147b23..b966814e 100644 --- a/dlog/bsgs.c +++ b/dlog/bsgs.c @@ -19,51 +19,12 @@ =============================================================================*/ /****************************************************************************** - Copyright (C) 2013 Mike Hansen Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include - #include "dlog.h" -#include "ulong_extras.h" - -static int -apow_cmp(const apow_t * x, const apow_t * y) -{ - return (x->ak < y->ak) ? -1 : (x->ak > y->ak); -} - -/* set size of table m=sqrt(nk) to compute k logs in a group of size n */ -void -dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) -{ - ulong k, ak; - t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); - if (m > n) m = n; - - t->mod = mod; - t->modinv = n_precompute_inverse(mod); - t->m = m; - t->g = n / m; - - for (k = 0, ak = 1; k < m; k++) - { - t->table[k].k = k; - t->table[k].ak = ak; - ak = n_mulmod_precomp(ak, a, mod, t->modinv); - } - - t->am = n_invmod(ak, mod); - qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); -} - -void -dlog_bsgs_clear(dlog_bsgs_t t) -{ - flint_free(t->table); -} ulong dlog_bsgs(const dlog_bsgs_t t, ulong b) @@ -78,10 +39,10 @@ dlog_bsgs(const dlog_bsgs_t t, ulong b) (int(*)(const void*,const void*))apow_cmp); if (x != NULL) return i * t->m + x->k; - c.ak = n_mulmod_precomp(c.ak, t->am, t->mod, t->modinv); + c.ak = nmod_mul(c.ak, t->am, t->mod); } flint_printf("Exception (n_discrete_log_bsgs). discrete log not found.\n"); flint_printf(" table size %wu, cosize %wu mod %wu. %wu not found\n", - t->m, t->g, t->mod, b); + t->m, t->g, t->mod.n, b); abort(); } diff --git a/dlog/bsgs_init.c b/dlog/bsgs_init.c new file mode 100644 index 00000000..2a0c68a1 --- /dev/null +++ b/dlog/bsgs_init.c @@ -0,0 +1,63 @@ +/*============================================================================= + + This file is part of FLINT. + + FLINT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + FLINT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FLINT; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2013 Mike Hansen + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include +#include "dlog.h" + +int +apow_cmp(const apow_t * x, const apow_t * y) +{ + return (x->ak < y->ak) ? -1 : (x->ak > y->ak); +} + +/* set size of table m=sqrt(nk) to compute k logs in a group of size n */ +void +dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) +{ + ulong k, ak; + t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); + if (m > n) m = n; + + nmod_init(&t->mod, mod); + t->m = m; + t->g = n / m; + + for (k = 0, ak = 1; k < m; k++) + { + t->table[k].k = k; + t->table[k].ak = ak; + ak = nmod_mul(ak, a, t->mod); + } + + t->am = nmod_inv(ak, t->mod); + qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); +} + +void +dlog_bsgs_clear(dlog_bsgs_t t) +{ + flint_free(t->table); +} diff --git a/dlog/crt.c b/dlog/crt.c index 84f7c18e..881c757b 100644 --- a/dlog/crt.c +++ b/dlog/crt.c @@ -25,53 +25,6 @@ #include "dlog.h" -void -dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) -{ - int k; - n_factor_t fac; - ulong * M, * u; - - n_factor_init(&fac); - n_factor(&fac, n, 1); - - t->num = fac.num; - nmod_init(&t->mod,mod); - nmod_init(&t->n, n); - - M = t->expo = flint_malloc(t->num * sizeof(ulong)); - u = t->crt_coeffs = flint_malloc(t->num * sizeof(ulong)); - t->pre = flint_malloc(t->num * sizeof(dlog_precomp_t)); - for (k = 0; k < t->num; k++) - t->pre[k] = flint_malloc(sizeof(dlog_precomp_struct)); - - for (k = 0; k < t->num; k++) - { - ulong p, e, mk; - p = fac.p[k]; - e = fac.exp[k]; - mk = n_pow(p, e); - M[k] = n / mk; - u[k] = nmod_mul(M[k], n_invmod(M[k] % mk, mk), t->n); - /* depends on the power */ - dlog_precomp_pe_init(t->pre[k], nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); - } -} - -void -dlog_crt_clear(dlog_crt_t t) -{ - int k; - flint_free(t->expo); - flint_free(t->crt_coeffs); - for (k = 0; k < t->num; k++) - { - dlog_precomp_clear(t->pre[k]); - flint_free(t->pre[k]); - } - flint_free(t->pre); -} - ulong dlog_crt(const dlog_crt_t t, ulong b) { diff --git a/dlog/crt_init.c b/dlog/crt_init.c new file mode 100644 index 00000000..17d41da8 --- /dev/null +++ b/dlog/crt_init.c @@ -0,0 +1,73 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) +{ + int k; + n_factor_t fac; + ulong * M, * u; + + n_factor_init(&fac); + n_factor(&fac, n, 1); + + t->num = fac.num; + nmod_init(&t->mod,mod); + nmod_init(&t->n, n); + + M = t->expo = flint_malloc(t->num * sizeof(ulong)); + u = t->crt_coeffs = flint_malloc(t->num * sizeof(ulong)); + t->pre = flint_malloc(t->num * sizeof(dlog_precomp_t)); + for (k = 0; k < t->num; k++) + t->pre[k] = flint_malloc(sizeof(dlog_precomp_struct)); + + for (k = 0; k < t->num; k++) + { + ulong p, e, mk; + p = fac.p[k]; + e = fac.exp[k]; + mk = n_pow(p, e); + M[k] = n / mk; + u[k] = nmod_mul(M[k], n_invmod(M[k] % mk, mk), t->n); + /* depends on the power */ + dlog_precomp_pe_init(t->pre[k], nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); + } +} + +void +dlog_crt_clear(dlog_crt_t t) +{ + int k; + flint_free(t->expo); + flint_free(t->crt_coeffs); + for (k = 0; k < t->num; k++) + { + dlog_precomp_clear(t->pre[k]); + flint_free(t->pre[k]); + } + flint_free(t->pre); +} diff --git a/dlog/power.c b/dlog/power.c index 26dafe8e..6e5689c4 100644 --- a/dlog/power.c +++ b/dlog/power.c @@ -25,32 +25,6 @@ #include "dlog.h" -void -dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) -{ - int k; - nmod_init(&t->mod, mod); - t->p = p; - t->e = e; - - t->apk = flint_malloc(e * sizeof(ulong)); - t->pre = flint_malloc(sizeof(dlog_precomp_struct)); - - t->apk[0] = nmod_inv(a, t->mod); - for (k = 1; k < e; k++) - t->apk[k] = nmod_pow_ui(t->apk[k-1], p, t->mod); - - dlog_precomp_p_init(t->pre, nmod_inv(t->apk[e-1], t->mod), mod, p, num); -} - -void -dlog_power_clear(dlog_power_t t) -{ - flint_free(t->apk); - dlog_precomp_clear(t->pre); - flint_free(t->pre); -} - ulong dlog_power(const dlog_power_t t, ulong b) { diff --git a/dlog/power_init.c b/dlog/power_init.c new file mode 100644 index 00000000..5ee59af8 --- /dev/null +++ b/dlog/power_init.c @@ -0,0 +1,52 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) +{ + int k; + nmod_init(&t->mod, mod); + t->p = p; + t->e = e; + + t->apk = flint_malloc(e * sizeof(ulong)); + t->pre = flint_malloc(sizeof(dlog_precomp_struct)); + + t->apk[0] = nmod_inv(a, t->mod); + for (k = 1; k < e; k++) + t->apk[k] = nmod_pow_ui(t->apk[k-1], p, t->mod); + + dlog_precomp_p_init(t->pre, nmod_inv(t->apk[e-1], t->mod), mod, p, num); +} + +void +dlog_power_clear(dlog_power_t t) +{ + flint_free(t->apk); + dlog_precomp_clear(t->pre); + flint_free(t->pre); +} diff --git a/dlog/precomp.c b/dlog/precomp.c index 7b22e876..830b3975 100644 --- a/dlog/precomp.c +++ b/dlog/precomp.c @@ -23,128 +23,8 @@ ******************************************************************************/ -#include "math.h" #include "dlog.h" -#define TABLE_P_LIM 50 -#define TABLE_PE_LIM 50 -#define TABLE_N_LIM 50 -#define BSGS_LIM 500 - - -/* log mod p^e */ -void -dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) -{ - if ( pe < TABLE_PE_LIM ) - { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, pe); - return; - } - if (e > 1) - { - pre->type = DLOG_MODPE; - dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); - } - else - { - dlog_precomp_n_init(pre, a, p, p - 1, num); - } -} - -/* group of order n modulo mod, mod a prime and no information on n */ -void -dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) -{ - if (n%2 && n_is_probabprime(n)) - dlog_precomp_p_init(pre, a, mod, n, num); - else { - if ( mod < TABLE_N_LIM ) - { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, mod); - } else { - if (n < BSGS_LIM) - { - ulong m; - m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; - pre->type = DLOG_BSGS; - dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); - } else { - pre->type = DLOG_CRT; - dlog_crt_init(pre->t.crt, a, mod, n, num); - } - } - } -} - -/* we known the order is prime */ -void -dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) -{ - if ( p < TABLE_P_LIM ) - { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, mod); - } - else - { - ulong m; - m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; - pre->type = DLOG_BSGS; - dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); - } -} - -void -dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) -{ - if ( pe < TABLE_PE_LIM ) - { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, mod); - } - else - { - if ( e == 1) - { - dlog_precomp_p_init(pre, a, mod, p, num); - } - else - { - pre->type = DLOG_POWER; - dlog_power_init(pre->t.power, a, mod, p, e, num); - } - } -} - -void -dlog_precomp_clear(dlog_precomp_t pre) -{ - switch (pre->type) - { - case DLOG_MODPE: - dlog_modpe_clear(pre->t.modpe); - break; - case DLOG_CRT: - dlog_crt_clear(pre->t.crt); - break; - case DLOG_POWER: - dlog_power_clear(pre->t.power); - break; - case DLOG_TABLE: - dlog_table_clear(pre->t.table); - break; - case DLOG_BSGS: - dlog_bsgs_clear(pre->t.bsgs); - break; - default: - abort(); - break; - } -} - ulong dlog_precomp(const dlog_precomp_t pre, ulong b) { diff --git a/dlog/precomp_init.c b/dlog/precomp_init.c new file mode 100644 index 00000000..af7f531d --- /dev/null +++ b/dlog/precomp_init.c @@ -0,0 +1,146 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "math.h" +#include "dlog.h" + +#define TABLE_P_LIM 50 +#define TABLE_PE_LIM 50 +#define TABLE_N_LIM 50 +#define BSGS_LIM 500 + + +/* log mod p^e */ +void +dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) +{ + if ( pe < TABLE_PE_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, pe); + return; + } + if (e > 1) + { + pre->type = DLOG_MODPE; + dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); + } + else + { + dlog_precomp_n_init(pre, a, p, p - 1, num); + } +} + +/* group of order n modulo mod, mod a prime and no information on n */ +void +dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) +{ + if (n%2 && n_is_probabprime(n)) + dlog_precomp_p_init(pre, a, mod, n, num); + else { + if ( mod < TABLE_N_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, mod); + } else { + if (n < BSGS_LIM) + { + ulong m; + m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; + pre->type = DLOG_BSGS; + dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); + } else { + pre->type = DLOG_CRT; + dlog_crt_init(pre->t.crt, a, mod, n, num); + } + } + } +} + +/* we known the order is prime */ +void +dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) +{ + if ( p < TABLE_P_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, mod); + } + else + { + ulong m; + m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; + pre->type = DLOG_BSGS; + dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); + } +} + +void +dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) +{ + if ( pe < TABLE_PE_LIM ) + { + pre->type = DLOG_TABLE; + dlog_table_init(pre->t.table, a, mod); + } + else + { + if ( e == 1) + { + dlog_precomp_p_init(pre, a, mod, p, num); + } + else + { + pre->type = DLOG_POWER; + dlog_power_init(pre->t.power, a, mod, p, e, num); + } + } +} + +void +dlog_precomp_clear(dlog_precomp_t pre) +{ + switch (pre->type) + { + case DLOG_MODPE: + dlog_modpe_clear(pre->t.modpe); + break; + case DLOG_CRT: + dlog_crt_clear(pre->t.crt); + break; + case DLOG_POWER: + dlog_power_clear(pre->t.power); + break; + case DLOG_TABLE: + dlog_table_clear(pre->t.table); + break; + case DLOG_BSGS: + dlog_bsgs_clear(pre->t.bsgs); + break; + default: + abort(); + break; + } +} diff --git a/dlog/table.c b/dlog/table.c index ad58a9e5..9bef0be4 100644 --- a/dlog/table.c +++ b/dlog/table.c @@ -25,29 +25,6 @@ #include "dlog.h" -void -dlog_table_init(dlog_table_t t, ulong a, ulong mod) -{ - int k; - ulong ak; - t->mod = mod; - t->table = flint_malloc(mod * sizeof(ulong)); - ak = 1; k = 0; - /* warning: do not check a is invertible modulo mod */ - do - { - t->table[ak] = k++; - ak = (ak * a) % mod; - } - while (ak != 1); -} - -void -dlog_table_clear(dlog_table_t t) -{ - flint_free(t->table); -} - ulong dlog_table(const dlog_table_t t, ulong b) { diff --git a/dlog/table_init.c b/dlog/table_init.c new file mode 100644 index 00000000..7a19cf68 --- /dev/null +++ b/dlog/table_init.c @@ -0,0 +1,50 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +/* assume mod is small so no overflow */ +void +dlog_table_init(dlog_table_t t, ulong a, ulong mod) +{ + int k; + ulong ak; + t->mod = mod; + t->table = flint_malloc(mod * sizeof(ulong)); + ak = 1; k = 0; + /* warning: do not check a is invertible modulo mod */ + do + { + t->table[ak] = k++; + ak = (ak * a) % mod; + } + while (ak != 1); +} + +void +dlog_table_clear(dlog_table_t t) +{ + flint_free(t->table); +} From 32a1c966b90cec3d9e3b22c20b0c5739a231509f Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 15 Mar 2016 15:39:26 +0100 Subject: [PATCH 013/139] fix log table for large moduli + add order 2 & 3 --- dlog.h | 22 +++++++--- dlog/bsgs.c | 6 +-- dlog/bsgs_init.c | 7 +-- dlog/crt_init.c | 12 ++++- dlog/modpe.c | 3 +- dlog/order23.c | 32 ++++++++++++++ dlog/order23_init.c | 39 +++++++++++++++++ dlog/power_init.c | 5 ++- dlog/precomp.c | 3 ++ dlog/precomp_init.c | 74 +++++++++++++++++++++---------- dlog/profile/p-precomp.c | 95 ++++++++++++++++++++-------------------- dlog/table_init.c | 3 +- 12 files changed, 214 insertions(+), 87 deletions(-) create mode 100644 dlog/order23.c create mode 100644 dlog/order23_init.c diff --git a/dlog.h b/dlog.h index ce63e62d..a4adbaf2 100644 --- a/dlog.h +++ b/dlog.h @@ -32,7 +32,7 @@ enum { - DLOG_MODPE, DLOG_CRT, DLOG_POWER, DLOG_BSGS, DLOG_TABLE + DLOG_MODPE, DLOG_CRT, DLOG_POWER, DLOG_BSGS, DLOG_TABLE, DLOG_23 }; typedef struct dlog_precomp_struct dlog_precomp_struct; @@ -139,12 +139,15 @@ dlog_power_struct; typedef dlog_power_struct dlog_power_t[1]; +typedef ulong dlog_order23_t[1]; + /* generic decomposition */ /*typedef */ struct dlog_precomp_struct { int type; + ulong cost; union { dlog_table_t table; @@ -152,20 +155,23 @@ dlog_precomp_struct dlog_crt_t crt; dlog_power_t power; dlog_modpe_t modpe; + dlog_order23_t order23; } t; }; typedef dlog_precomp_struct dlog_precomp_t[1]; -void dlog_table_init(dlog_table_t t, ulong a, ulong mod); +ulong dlog_order23_init(dlog_order23_t t, ulong a); +ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod); +ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); +ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num); +ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num); +ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m); void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e); -void dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); -void dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num); -void dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num); -void dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m); void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n); /*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ +void dlog_order23_clear(dlog_order23_t t); void dlog_table_clear(dlog_table_t t); void dlog_1modpe_clear(dlog_1modpe_t t); void dlog_crt_clear(dlog_crt_t t); @@ -175,6 +181,7 @@ void dlog_bsgs_clear(dlog_bsgs_t t); void dlog_rho_clear(dlog_rho_t t); /*#define dlog_bsgs_clear(t) bsgs_table_clear(t)*/ +ulong dlog_order23(const dlog_order23_t t, ulong b); ulong dlog_table(const dlog_table_t t, ulong b); ulong dlog_crt(const dlog_crt_t t, ulong b); ulong dlog_power(const dlog_power_t t, ulong b); @@ -198,6 +205,9 @@ typedef struct } log_pair_t; void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_eratos_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_sieve_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); diff --git a/dlog/bsgs.c b/dlog/bsgs.c index b966814e..0f85c679 100644 --- a/dlog/bsgs.c +++ b/dlog/bsgs.c @@ -33,7 +33,7 @@ dlog_bsgs(const dlog_bsgs_t t, ulong b) apow_t c, * x; c.ak = b; - for (i = 0; i <= t->g; i++) + for (i = 0; i < t->g; i++) { x = bsearch(&c, t->table, t->m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); @@ -42,7 +42,7 @@ dlog_bsgs(const dlog_bsgs_t t, ulong b) c.ak = nmod_mul(c.ak, t->am, t->mod); } flint_printf("Exception (n_discrete_log_bsgs). discrete log not found.\n"); - flint_printf(" table size %wu, cosize %wu mod %wu. %wu not found\n", - t->m, t->g, t->mod.n, b); + flint_printf(" table size %wu, cosize %wu mod %wu. %wu not found (a^-m=%wu)\n", + t->m, t->g, t->mod.n, b, t->am); abort(); } diff --git a/dlog/bsgs_init.c b/dlog/bsgs_init.c index 2a0c68a1..42fb2d19 100644 --- a/dlog/bsgs_init.c +++ b/dlog/bsgs_init.c @@ -34,16 +34,16 @@ apow_cmp(const apow_t * x, const apow_t * y) } /* set size of table m=sqrt(nk) to compute k logs in a group of size n */ -void +ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) { ulong k, ak; + if (m >= n) m = n + 1; t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); - if (m > n) m = n; nmod_init(&t->mod, mod); t->m = m; - t->g = n / m; + t->g = n / m + 1; for (k = 0, ak = 1; k < m; k++) { @@ -54,6 +54,7 @@ dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) t->am = nmod_inv(ak, t->mod); qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); + return t->g; } void diff --git a/dlog/crt_init.c b/dlog/crt_init.c index 17d41da8..381e247f 100644 --- a/dlog/crt_init.c +++ b/dlog/crt_init.c @@ -25,12 +25,13 @@ #include "dlog.h" -void +ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) { int k; n_factor_t fac; ulong * M, * u; + ulong cost = 0; n_factor_init(&fac); n_factor(&fac, n, 1); @@ -54,8 +55,17 @@ dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) M[k] = n / mk; u[k] = nmod_mul(M[k], n_invmod(M[k] % mk, mk), t->n); /* depends on the power */ +#if 0 + flint_printf("[sub-crt -- init for size %wu mod %wu]\n", mk, mod); +#endif dlog_precomp_pe_init(t->pre[k], nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); + cost += t->pre[k]->cost; } +#if 0 + if (cost > 500) + flint_printf("[crt init for size %wu mod %wu -> cost %wu]\n", n,mod,cost); +#endif + return cost; } void diff --git a/dlog/modpe.c b/dlog/modpe.c index a41095f2..1941d44b 100644 --- a/dlog/modpe.c +++ b/dlog/modpe.c @@ -26,7 +26,7 @@ #include "dlog.h" #include "padic.h" -void +ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) { t->p = p; @@ -34,6 +34,7 @@ dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) t->pe = pe; dlog_precomp_n_init(t->modp, a, p, p-1, num); dlog_1modpe_init(t->modpe, n_powmod(a, p - 1, pe), p, e); + return t->modp->cost + e; } void diff --git a/dlog/order23.c b/dlog/order23.c new file mode 100644 index 00000000..ae4d14d3 --- /dev/null +++ b/dlog/order23.c @@ -0,0 +1,32 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +ulong +dlog_order23(const dlog_order23_t t, ulong b) +{ + return (b == *t) ? 1 : (b == 1) ? 0 : 2; +} diff --git a/dlog/order23_init.c b/dlog/order23_init.c new file mode 100644 index 00000000..412818de --- /dev/null +++ b/dlog/order23_init.c @@ -0,0 +1,39 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +ulong +dlog_order23_init(dlog_order23_t t, ulong a) +{ + * t = a; + return 0; +} + +void +dlog_order23_clear(dlog_order23_t t) +{ + return; +} diff --git a/dlog/power_init.c b/dlog/power_init.c index 5ee59af8..61409db3 100644 --- a/dlog/power_init.c +++ b/dlog/power_init.c @@ -25,7 +25,7 @@ #include "dlog.h" -void +ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) { int k; @@ -40,7 +40,8 @@ dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) for (k = 1; k < e; k++) t->apk[k] = nmod_pow_ui(t->apk[k-1], p, t->mod); - dlog_precomp_p_init(t->pre, nmod_inv(t->apk[e-1], t->mod), mod, p, num); + dlog_precomp_p_init(t->pre, nmod_inv(t->apk[e-1], t->mod), mod, p, e * num); + return e * t->pre->cost; } void diff --git a/dlog/precomp.c b/dlog/precomp.c index 830b3975..8b03ff6b 100644 --- a/dlog/precomp.c +++ b/dlog/precomp.c @@ -47,6 +47,9 @@ dlog_precomp(const dlog_precomp_t pre, ulong b) case DLOG_BSGS: return dlog_bsgs(pre->t.bsgs, b); break; + case DLOG_23: + return dlog_order23(pre->t.order23, b); + break; default: abort(); break; diff --git a/dlog/precomp_init.c b/dlog/precomp_init.c index af7f531d..b2229294 100644 --- a/dlog/precomp_init.c +++ b/dlog/precomp_init.c @@ -26,30 +26,56 @@ #include "math.h" #include "dlog.h" +#define SMALL_LIM 50 +#define TABLE_LIM 50 #define TABLE_P_LIM 50 +#define TABLE_MODPE_LIM 50 #define TABLE_PE_LIM 50 #define TABLE_N_LIM 50 #define BSGS_LIM 500 +void +dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) +{ + if (n <= 3) + { + pre->type = DLOG_23; + pre->cost = dlog_order23_init(pre->t.order23, a); + } + else + { + if ( mod < TABLE_LIM ) + { + pre->type = DLOG_TABLE; + pre->cost = dlog_table_init(pre->t.table, a, mod); + } + else + { + pre->type = DLOG_BSGS; + pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, n); + } + } +} /* log mod p^e */ void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) { - if ( pe < TABLE_PE_LIM ) + if ( pe < TABLE_MODPE_LIM ) { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, pe); + dlog_precomp_small_init(pre, a, pe, pe - pe / p, num); return; } - if (e > 1) - { - pre->type = DLOG_MODPE; - dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); - } - else - { - dlog_precomp_n_init(pre, a, p, p - 1, num); + else { + if (e > 1) + { + pre->type = DLOG_MODPE; + pre->cost = dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); + } + else + { + dlog_precomp_n_init(pre, a, p, p - 1, num); + } } } @@ -60,20 +86,21 @@ dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) if (n%2 && n_is_probabprime(n)) dlog_precomp_p_init(pre, a, mod, n, num); else { - if ( mod < TABLE_N_LIM ) + if (n < TABLE_N_LIM) + { + dlog_precomp_small_init(pre, a, mod, n, num); + } + else { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, mod); - } else { if (n < BSGS_LIM) { ulong m; m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; pre->type = DLOG_BSGS; - dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); + pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); } else { pre->type = DLOG_CRT; - dlog_crt_init(pre->t.crt, a, mod, n, num); + pre->cost = dlog_crt_init(pre->t.crt, a, mod, n, num); } } } @@ -85,15 +112,14 @@ dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) { if ( p < TABLE_P_LIM ) { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, mod); + dlog_precomp_small_init(pre, a, mod, p, num); } else { ulong m; m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; pre->type = DLOG_BSGS; - dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); + pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); } } @@ -102,8 +128,7 @@ dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, u { if ( pe < TABLE_PE_LIM ) { - pre->type = DLOG_TABLE; - dlog_table_init(pre->t.table, a, mod); + dlog_precomp_small_init(pre, a, mod, pe, num); } else { @@ -114,7 +139,7 @@ dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, u else { pre->type = DLOG_POWER; - dlog_power_init(pre->t.power, a, mod, p, e, num); + pre->cost = dlog_power_init(pre->t.power, a, mod, p, e, num); } } } @@ -139,6 +164,9 @@ dlog_precomp_clear(dlog_precomp_t pre) case DLOG_BSGS: dlog_bsgs_clear(pre->t.bsgs); break; + case DLOG_23: + dlog_order23_clear(pre->t.order23); + break; default: abort(); break; diff --git a/dlog/profile/p-precomp.c b/dlog/profile/p-precomp.c index 3b0638d9..c4aa9c1b 100644 --- a/dlog/profile/p-precomp.c +++ b/dlog/profile/p-precomp.c @@ -27,7 +27,10 @@ #include "profiler.h" #include -typedef void (*multilog_f) (ulong p, ulong a, ulong num); +#define NUMPRIMES 400 +#define CSV 0 + +typedef void (*log_f) (ulong p, ulong a, ulong num); void flog_table(ulong p, ulong a, ulong num) @@ -37,7 +40,7 @@ flog_table(ulong p, ulong a, ulong num) dlog_table_init(t, a, p); for (k = 1; k < num; k++) { - if (k == p) continue; + if (k % p == 0) continue; dlog_table(t, k % p); } dlog_table_clear(t); @@ -50,7 +53,7 @@ flog_bsgs(ulong p, ulong a, ulong num) dlog_bsgs_init(t, a, p, p-1, ceil( sqrt((double)num * p))); for (k = 1; k < num; k++) { - if (k == p) continue; + if (k % p == 0) continue; dlog_bsgs(t, k % p); } dlog_bsgs_clear(t); @@ -63,7 +66,7 @@ flog_rho(ulong p, ulong a, ulong num) dlog_rho_init(t, a, p, p-1); for (k = 1; k < num; k++) { - if (k == p) continue; + if (k % p == 0) continue; dlog_rho(t, k % p); } dlog_rho_clear(t); @@ -76,7 +79,7 @@ flog_crt(ulong p, ulong a, ulong num) dlog_crt_init(t, a, p, p-1, num); for (k = 1; k < num; k++) { - if (k == p) continue; + if (k % p == 0) continue; dlog_crt(t, k % p); } dlog_crt_clear(t); @@ -89,37 +92,38 @@ flog_gen(ulong p, ulong a, ulong num) dlog_precomp_n_init(t, a, p, p-1, num); for (k = 1; k < num; k++) { - if (k == p) continue; + if (k % p == 0) continue; dlog_precomp(t, k % p); } dlog_precomp_clear(t); } -void -dlog_bench(multilog_f flog, const ulong * p, const ulong * a, int np, int num) -{ - int i; - ulong q; - TIMEIT_ONCE_START - for (i = 0; i < np; i ++) - flog(p[i], a[i], num); - TIMEIT_ONCE_STOP -} int main() { slong iter, k, nv, nref, r, nr; ulong minq, maxq; ulong * rand; - int nbits, nl = 4; - int vl[5] = { 1, 10, 100, 1000 , 5000}; + int nbits, nl = 5; + int l[5] = { 1, 10, 100, 1000 , 5000}; + + int nf = 4; + log_f func[4] = { flog_table, flog_bsgs, flog_crt, flog_gen }; + char * n[4] = { "table", "bsgs", "crt", "generic" }; + + int np = NUMPRIMES; + flint_rand_t state; flint_randinit(state); - for (nbits = 10; nbits < 52; nbits += 10) + for (nbits = 10; nbits < 50; nbits += 5) { - int i, np = 100; - ulong p[100], a[100]; + int i; + ulong p[NUMPRIMES], a[NUMPRIMES]; + + if (nbits >= 25) + np /= 2; + for (i=0; i < np; i++) { p[i] = n_randprime(state, nbits, 0); @@ -128,36 +132,33 @@ int main() for (i = 0; i < nl; i++) { - flint_printf("%wu * logs mod primes of size %wu.....\n", vl[i], nbits); + int f; +#if LOG + flint_printf("%d * logs mod primes of size %d.....\n", l[i], nbits); +#endif - if (nbits <= 20) - { - flint_printf("table.......... "); - fflush(stdout); - dlog_bench(flog_table, p, a, np, vl[i]); - } - - if (nbits <= 40 || vl[i] <= 10) + for (f = 0; f < nf; f++) { - flint_printf("bsgs........... "); + int j; + + + /* skip useless */ + if (f == 0 && nbits >= 20) + continue; + if (f == 1 && nbits >= 30 && l[i] > 10) + continue; +#if LOG + flint_printf("%-20s... ",n[f]); fflush(stdout); - dlog_bench(flog_bsgs, p, a, np, vl[i]); +#endif + TIMEIT_ONCE_START + for (j = 0; j < np; j ++) + (func[f])(p[j], a[j], l[i]); +#if LOG == 0 + flint_printf("%-8s, %2d, %4d, %3d, ",n[f],nbits,l[i],np); +#endif + TIMEIT_ONCE_STOP } - - if (nbits <= 20 || vl[i] == 1) - { - flint_printf("rho............ "); - fflush(stdout); - dlog_bench(flog_rho, p, a, np, vl[i]); - } - - flint_printf("crt............ "); - fflush(stdout); - dlog_bench(flog_crt, p, a, np, vl[i]); - - flint_printf("generic........ "); - fflush(stdout); - dlog_bench(flog_gen, p, a, np, vl[i]); } } flint_randclear(state); diff --git a/dlog/table_init.c b/dlog/table_init.c index 7a19cf68..5ed9f4f1 100644 --- a/dlog/table_init.c +++ b/dlog/table_init.c @@ -26,7 +26,7 @@ #include "dlog.h" /* assume mod is small so no overflow */ -void +ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod) { int k; @@ -41,6 +41,7 @@ dlog_table_init(dlog_table_t t, ulong a, ulong mod) ak = (ak * a) % mod; } while (ak != 1); + return 1; } void From 05ecc82d87d0154a85e400e7f6e92a0997176cf7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 16 Mar 2016 15:20:39 +0100 Subject: [PATCH 014/139] dlog vec performs as it should but still mathematically not debugged --- dlog/profile/p-vec.c | 27 +++-- dlog/vec_crt.c | 24 ++-- dlog/vec_eratos.c | 58 +++++++++ dlog/vec_loop.c | 2 +- dlog/vec_sieve.c | 271 +++++++++++++++++++++++++++++++++++-------- 5 files changed, 313 insertions(+), 69 deletions(-) create mode 100644 dlog/vec_eratos.c diff --git a/dlog/profile/p-vec.c b/dlog/profile/p-vec.c index 91aee7e8..bfedf73a 100644 --- a/dlog/profile/p-vec.c +++ b/dlog/profile/p-vec.c @@ -25,6 +25,9 @@ #include "dlog.h" #include "profiler.h" + +#define NPRIMES 640 + typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); void @@ -35,20 +38,20 @@ f_empty(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const int main() { - int i, ni = 3; - int bits[5] = { 10, 20, 30, 40, 50 }; + int i, ni = 8; + int bits[9] = { 10, 15, 20, 25, 30, 35, 40, 45, 50 }; - int j, nj = 5; + int j, nj = 6; ulong * v; - ulong nv[5] = { 50, 200, 1000, 2000, 10000 }; + ulong nv[6] = { 50, 200, 1000, 2000, 10000, 30000 }; - int k, np = 1000; + int k, np = NPRIMES; nmod_t * p; ulong * a; - int l, nf = 3; - vec_f func[4] = { f_empty, dlog_vec_loop, dlog_vec_sieve, dlog_vec_crt }; - char * n[4] = { "empty", "loop", "sieve", "crt" }; + int l, nf = 5; + vec_f func[5] = { f_empty, dlog_vec_loop, dlog_vec_eratos, dlog_vec_sieve, dlog_vec_crt }; + char * n[5] = { "empty", "loop", "eratos", "sieve", "crt" }; flint_rand_t state; nmod_t order; @@ -57,6 +60,9 @@ int main() p = flint_malloc(np * sizeof(nmod_t)); a = flint_malloc(np * sizeof(ulong)); + + flint_randinit(state); + for (i = 0; i < ni; i++) { for (k = 0; k < np; k++) @@ -75,7 +81,9 @@ int main() for (l = 0; l < nf; l++) { - if (l == 1 && (i >= 2 || j > 0)) + if (l == 1 && i > 2) + continue; + if (l == 2 && i > 5) continue; flint_printf("%-20s... ",n[l]); @@ -92,6 +100,7 @@ int main() } flint_free(v); } + np /= 2; } flint_free(p); diff --git a/dlog/vec_crt.c b/dlog/vec_crt.c index cb8b8076..09bb4928 100644 --- a/dlog/vec_crt.c +++ b/dlog/vec_crt.c @@ -25,9 +25,12 @@ #include "dlog.h" +#define SIEVE_START 100 + /* group components up to bound and return cofactor */ -#define LOOP 0 -#define SIEVE 1 +#define G_SMALL 0 +#define G_BIG 1 + static void n_factor_group(n_factor_t * fac, ulong bound) { @@ -53,19 +56,19 @@ n_factor_group(n_factor_t * fac, ulong bound) for (j = 0; j < i; j++) { fac->p[j] = m[j]; - fac->exp[j] = LOOP; + fac->exp[j] = G_SMALL; } if (c > 1) { fac->p[i] = c; - fac->exp[i] = SIEVE; + fac->exp[i] = G_BIG; i++; } fac->num = i; } /* assume v[k] = -1 for bad primes? */ -/* loop on small components and keep one subgroup for DLOG + sieve */ +/* loop on small components and if needed keep one subgroup for DLOG + sieve */ void dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { @@ -78,16 +81,21 @@ dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t n_factor(&fac, na, 1); n_factor_group(&fac, maxloop); for (k = 0; k < fac.num; k++) - { + { ulong m, M, aM, uM, vaM; m = fac.p[k]; M = na / m; aM = nmod_pow_ui(a, M, mod); uM = M * n_invmod(M % m, m); /* uM < n */ vaM = nmod_mul(va, uM % order.n, order); - if (fac.exp[k] == LOOP) + if (fac.exp[k] == G_SMALL) dlog_vec_loop(v, nv, aM, vaM, mod, m, order); else - dlog_vec_sieve(v, nv, aM, vaM, mod, m, order); + { + if (nv <= SIEVE_START) + dlog_vec_eratos_ph(v, nv, aM, vaM, M, mod, m, order); + else + dlog_vec_sieve_ph(v, nv, aM, vaM, M, mod, m, order); + } } } diff --git a/dlog/vec_eratos.c b/dlog/vec_eratos.c new file mode 100644 index 00000000..fd33374e --- /dev/null +++ b/dlog/vec_eratos.c @@ -0,0 +1,58 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_vec_eratos_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) +{ + ulong p, pmax; + dlog_precomp_t pre; + n_primes_t iter; + + /* discrete log on primes */ + pmax = (nv < mod.n) ? nv : mod.n; + dlog_precomp_n_init(pre, a, mod.n, na, n_prime_pi(nv)); + + n_primes_init(iter); + while ((p = n_primes_next(iter)) < pmax) + { + ulong k, pM, wp; + if (mod.n % p == 0) + continue; /* won't be attained another time */ + pM = (M) ? nmod_pow_ui(p, M, mod) : p; + wp = nmod_mul(dlog_precomp(pre, pM), va, order); + for (pM = p; pM < nv; pM *= p) + for (k = pM; k < nv; k += pM) + v[k] = nmod_add(v[k], wp, order); + } + n_primes_clear(iter); +} + +void +dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + dlog_vec_eratos_ph(v, nv, a, va, 1, mod, na, order); +} diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index 4bd8e792..66640ea0 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -31,7 +31,7 @@ dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod { ulong x, xp; ulong vx = 0; - for(x = a; x != 1; x = nmod_mul(x, a, mod)) + for (x = a; x != 1; x = nmod_mul(x, a, mod)) { vx = nmod_add(vx, va, order); for(xp = x; xp < nv; xp+=mod.n) diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index 9981db93..d2263c39 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -24,51 +24,41 @@ ******************************************************************************/ #include "dlog.h" +#include + +#define vbs 0 +#define FACTOR_RATIO 4 static ulong -logp_sieve(log_pair_t * v, ulong nv, ulong p, ulong mod, ulong logm1, nmod_t order, int maxtry) +logp_sieve_gcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) { - int i, j, nr = 0, nm = 0, ng = 0; - ulong l, pm, logm; + int i, j, nm = 0, ng = 0; + ulong pm, logm; ulong u[2], r[2], t; -#if rnd - flint_rand_t state; - flint_randinit(state); -#endif -#if vbs +#if vbs > 1 flint_printf("\nEnter logp_sieve p=%wu mod %wu...\n", p, mod); #endif - while (1) { - /* find multiplier m */ - logm = 0; - pm = l = p; - do { - nm++; - /* random ? pb when p lies in a small subgroup */ - do { - nr++; -#if rnd - l = 1 + n_randint(state, p - 1); -#else - l = (l > 1) ? l - 1 : p - 1; -#endif - } while (v[l].m != l); - pm *= l; - logm += v[l].logm; - } while (pm < mod); - pm = pm % mod; -#if vbs - flint_printf("[pm=%wu, v[pm]=%ld]", pm, v[pm]); -#endif + pm = p; + logm = 0; + while (nm++ < maxtry) + { + pm = nmod_mul(pm, a, mod); + logm = nmod_add(logm, loga, order); + if (2 * pm > mod.n) + { + pm = nmod_neg(pm, mod); + logm = nmod_add(logm, logm1, order); + } /* half gcd u * pm + v * mod = r, ignore v */ - u[0] = 0; r[0] = mod; + u[0] = 0; r[0] = mod.n; u[1] = 1; r[1] = pm; i = 1; j = 0; /* flip flap */ do { ng++; -#if vbs - flint_printf("[r=%d, v[r]=%d, u=%d, v[u]=%d]\n", - r[i],v[r[i]], u[i], v[u[i]]); +#if vbs > 1 + if (r[i] < nv && u[i] < nv) + flint_printf("[r=%wu, v[r]=%wu, u=%wu, v[u]=%wu -- nv=%wu]\n", + r[i], v[r[i]].m, u[i], v[u[i]].m, nv); #endif if (r[i] < nv && v[r[i]].m == r[i] && u[i] < nv && v[u[i]].m == u[i]) { @@ -77,9 +67,6 @@ logp_sieve(log_pair_t * v, ulong nv, ulong p, ulong mod, ulong logm1, nmod_t ord x = nmod_sub(v[r[i]].logm, nmod_add(v[u[i]].logm, logm, order), order); if (j) x = nmod_add(x, logm1, order); -#if rnd - flint_randclear(state); -#endif return x; } @@ -88,55 +75,237 @@ logp_sieve(log_pair_t * v, ulong nv, ulong p, ulong mod, ulong logm1, nmod_t ord r[i] = r[i] % r[j]; u[i] = u[i] + t * u[j]; /* (-1)^j */ - } while (r[i] > 0 && u[i] < p); - if (nm > maxtry) - return NOT_FOUND; + } while (r[i] > 0 && u[i] < nv); } + return NOT_FOUND; +} + +static ulong +logp_sieve_factor(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) +{ + int nm = 0; + ulong pm, logm; + + const ulong * prime; + prime = n_primes_arr_readonly(p); + + pm = p; + logm = 0; + while (pm < mod.n) + { + /*nm++;*/ /* init ignored */ + pm *= a; + logm = nmod_add(logm, loga, order); + } + pm = pm % mod.n; + do { + int i, j, ind[15], exp[15]; + /* find multiplier m */ + if (2 * pm > mod.n) + { + pm = nmod_neg(pm, mod); + logm = nmod_add(logm, logm1, order); + } + + for (i = 0, j = 0; j < p && pm >= nv && 4 * prime[j] < p; j++) + { + int e = n_remove(&pm, prime[j]); + if (e) + { + ind[i] = j; + exp[i] = e; + i++; + } + } + if (pm < nv && v[pm].m == pm) + { + /* goal! */ + ulong x = v[pm].logm; + /* chi(m)*chi(p)=chi(pm)*prod */ + for(j = 0; j < i; j++) + x = nmod_add(x, nmod_mul(exp[j], v[prime[ind[j]]].logm, order), order); + x = nmod_sub(logm, x, order); + /*flint_printf("managed %d mults / %d for p=%wu, pm=%wu\n",nm,maxtry,p,pm);*/ + return x; + } + nm++; + pm = nmod_mul(pm, a, mod); + logm = nmod_add(logm, loga, order); + } while (nm < maxtry); + return NOT_FOUND; +} + +static int +factor_until(ulong * n, ulong nlim, const ulong * p, ulong pmax, ulong * fp, int * fe) +{ + int i, j; + for (i = 0, j = 0; *n >= nlim && p[j] < pmax; j++) + { + int e = n_remove(n, p[j]); + if (e) + { + fp[i] = p[j]; + fe[i] = e; + i++; + } + } + return i; +} + +static ulong +logp_sieve_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) +{ + int nm = 0, ng = 0; + ulong pm, logm, pmax; + ulong u[2], r[2], t; + ulong up[15], rp[15]; + int ue[15], re[15]; + const ulong * prime; + prime = n_primes_arr_readonly(p); + pmax = p / FACTOR_RATIO; + pm = p; + logm = 0; + while (nm++ < maxtry) + { + int i, j, iu, ir; + ulong logr; + pm = nmod_mul(pm, a, mod); + logm = nmod_add(logm, loga, order); + /* + if (2 * pm > mod.n) + { + pm = nmod_neg(pm, mod); + logm = nmod_add(logm, logm1, order); + } + */ + /* half gcd u * pm + v * mod = r, ignore v */ + u[0] = 0; r[0] = mod.n; + u[1] = 1; r[1] = pm; + i = 1; j = 0; /* flip flap */ + while (r[i] > u[i]) + { + ng++; + if (r[i] < nv && v[r[i]].m == r[i] && u[i] < nv && v[u[i]].m == u[i]) + { + /* early smooth detection: occurs for primes < 30 bits */ + ulong x; + /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ + x = nmod_sub(v[r[i]].logm, nmod_add(v[u[i]].logm, logm, order), order); + if (j) + x = nmod_add(x, logm1, order); + return x; + } + j = i; i = 1 - i; /* switch */ + t = r[i] / r[j]; + r[i] = r[i] % r[j]; + u[i] = u[i] + t * u[j]; /* (-1)^j */ + + }; + /* try to factor both r[i] and u[i] */ + iu = factor_until(&u[i], nv, prime, pmax, up, ue); + if (u[i] >= nv || v[u[i]].m < u[i]) + continue; + ir = factor_until(&r[i], nv, prime, pmax, rp, re); + if (r[i] >= nv || v[r[i]].m < r[i]) + continue; + /* log(u)+log(p)+log(m)=log(r) */ + logr = 0; + for (i=0; i < ir; i++) + logr = nmod_add(logr, (re[i] * v[rp[i]].logm) % order.n, order); + for (i=0; i < iu; i++) + logm = nmod_add(logm, (ue[i] * v[up[i]].logm) % order.n, order); + return nmod_sub(logr, logm, order); + } + return NOT_FOUND; } void -dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +dlog_vec_sieve_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) { - int maxtry; + ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; + ulong logcost, limcount; ulong k, p, p1, pmax, logm1; log_pair_t * w; dlog_precomp_t pre; n_primes_t iter; + ulong X, aX, vaX; /* store size */ w = flint_malloc( nv * sizeof(log_pair_t)); for (k = 0; k < nv; k++) { w[k].m = 1; - w[k].logm = 1; - } - w[1].logm = 0; + w[k].logm = 0; /* could be v[k]... */ + } /* discrete log on first primes, then sieve */ pmax = (nv < mod.n) ? nv : mod.n; - p1 = maxtry = 50; /* FIXME: tune this limit! */ + p1 = 50; /* FIXME: tune this limit! */ dlog_precomp_n_init(pre, a, mod.n, na, p1); + /*flint_printf("## single log cost: %wu\n", pre->cost);*/ + logcost = pre->cost; + + if (logcost < 15) + { + /* p1 = pmax; */ + limcount = mod.n; + } + else + { + limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); + logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); + } - logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); + /* find big power of gen */ + X = n_nextprime(na / 2 + 10, 0); + X = (na % 257) ? 257 % na : 1031 % na ; /* FIXME! */ + aX = nmod_pow_ui(a, X, mod); + vaX = nmod_mul(va, X % order.n, order); n_primes_init(iter); while ((p = n_primes_next(iter)) < pmax) { + double cost = log(mod.n)/log(p); ulong m, wp; if (mod.n % p == 0) /* FIXME: those primes could be known... */ continue; /* won't be attained another time */ - if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, maxtry)) != NOT_FOUND) - wp = nmod_mul(dlog_precomp(pre, p), va, order); + cost = log(mod.n)/log(p); + cost = pow(cost,cost); + sievecount++; + /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ + /*if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ + if (logcost < cost || (wp = logp_sieve_factorgcd(w, nv, p, mod, aX, na, vaX, logm1, order, cost)) == NOT_FOUND) + { + if (logcost < cost) + sievecount--; + else + missed++; + logcount++; + wp = nmod_mul(dlog_precomp(pre, nmod_pow_ui(p, M, mod)), va, order); + } for (k = p, m = 1; k < nv; k += p, m++) { - w[k].m *= p; - w[k].logm = nmod_add(w[k].logm, wp, order); + w[k].m = w[m].m * p; + w[k].logm = nmod_add(w[m].logm, wp, order); + if (w[k].m == k) + smooth++; } } /* write in v */ for (k = 0; k < nv; k++) if (v[k] != NOT_FOUND) v[k] = nmod_add(v[k], w[k].logm, order); +#if vbs + if (missed) + flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", + smooth, limcount, mod.n, logcost, logcount, sievecount, missed); +#endif n_primes_clear(iter); flint_free(w); } + +void +dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + dlog_vec_sieve_ph(v, nv, a, va, 1, mod, na, order); +} From 4b24b265be132f82fb50e58a2f46b7079d1d7c37 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 17 Mar 2016 17:27:28 +0100 Subject: [PATCH 015/139] split files --- dlog.h | 12 +- dlog/factor_group.c | 63 ++++++++ dlog/profile/p-precomp.c | 24 ++- dlog/profile/p-vec.c | 22 ++- dlog/vec_crt.c | 46 +----- dlog/vec_eratos.c | 28 +--- dlog/vec_eratos_subgroup.c | 52 +++++++ dlog/vec_loop.c | 6 +- dlog/vec_pindex_factorgcd.c | 114 +++++++++++++++ dlog/vec_sieve.c | 281 +----------------------------------- dlog/vec_sieve_subgroup.c | 114 +++++++++++++++ 11 files changed, 399 insertions(+), 363 deletions(-) create mode 100644 dlog/factor_group.c create mode 100644 dlog/vec_eratos_subgroup.c create mode 100644 dlog/vec_pindex_factorgcd.c create mode 100644 dlog/vec_sieve_subgroup.c diff --git a/dlog.h b/dlog.h index a4adbaf2..4de69b7c 100644 --- a/dlog.h +++ b/dlog.h @@ -197,17 +197,23 @@ void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong void dlog_precomp_clear(dlog_precomp_t pre); ulong dlog_precomp(const dlog_precomp_t pre, ulong b); -#define NOT_FOUND UWORD_MAX #define LOOP_MAX_FACTOR 6 +#define G_SMALL 0 +#define G_BIG 1 +void dlog_n_factor_group(n_factor_t * fac, ulong bound); + +#define NOT_FOUND UWORD_MAX typedef struct { ulong m, logm; } log_pair_t; +ulong dlog_vec_pindex_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry); + void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_eratos_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_sieve_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); diff --git a/dlog/factor_group.c b/dlog/factor_group.c new file mode 100644 index 00000000..65bb43e8 --- /dev/null +++ b/dlog/factor_group.c @@ -0,0 +1,63 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +/* group components up to bound and return cofactor */ +void +dlog_n_factor_group(n_factor_t * fac, ulong bound) +{ + int i, j, k; + ulong m[FLINT_MAX_FACTORS_IN_LIMB]; + ulong c = 1; + i = 0; + for (k = fac->num - 1; k >= 0; k--) + { + ulong qe = n_pow(fac->p[k], fac->exp[k]); + if (qe > bound) + c *= qe; + else + { + /* try to insert somewhere in m */ + for (j = 0; j < i && (m[j] * qe > bound); j++); + if (j == i) + m[i++] = qe; + else + m[j] *= qe; + } + } + for (j = 0; j < i; j++) + { + fac->p[j] = m[j]; + fac->exp[j] = G_SMALL; + } + if (c > 1) + { + fac->p[i] = c; + fac->exp[i] = G_BIG; + i++; + } + fac->num = i; +} diff --git a/dlog/profile/p-precomp.c b/dlog/profile/p-precomp.c index c4aa9c1b..56e9eba9 100644 --- a/dlog/profile/p-precomp.c +++ b/dlog/profile/p-precomp.c @@ -28,7 +28,10 @@ #include #define NUMPRIMES 400 -#define CSV 0 +#define LOG 0 +#define CSV 1 +#define JSON 2 +#define OUT JSON typedef void (*log_f) (ulong p, ulong a, ulong num); @@ -133,7 +136,7 @@ int main() for (i = 0; i < nl; i++) { int f; -#if LOG +#if OUT == LOG flint_printf("%d * logs mod primes of size %d.....\n", l[i], nbits); #endif @@ -147,17 +150,26 @@ int main() continue; if (f == 1 && nbits >= 30 && l[i] > 10) continue; -#if LOG +#if OUT == LOG flint_printf("%-20s... ",n[f]); fflush(stdout); +#elif OUT == CSV + flint_printf("%-8s, %2d, %4d, %3d, ",n[f],nbits,l[i],np); +#elif OUT == JSON + flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nlogs\": %d, \"nprimes\": %d, \"time\": ", + n[f],nbits,l[i],np); #endif + TIMEIT_ONCE_START for (j = 0; j < np; j ++) (func[f])(p[j], a[j], l[i]); -#if LOG == 0 - flint_printf("%-8s, %2d, %4d, %3d, ",n[f],nbits,l[i],np); -#endif TIMEIT_ONCE_STOP + +#if OUT == JSON + flint_printf("}\n"); +#else + flint_printf("\n"); +#endif } } } diff --git a/dlog/profile/p-vec.c b/dlog/profile/p-vec.c index bfedf73a..cdb9fc58 100644 --- a/dlog/profile/p-vec.c +++ b/dlog/profile/p-vec.c @@ -27,6 +27,11 @@ #include "profiler.h" #define NPRIMES 640 +#define LOG 0 +#define CSV 1 +#define JSON 2 +#define OUT JSON + typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); @@ -60,7 +65,6 @@ int main() p = flint_malloc(np * sizeof(nmod_t)); a = flint_malloc(np * sizeof(ulong)); - flint_randinit(state); for (i = 0; i < ni; i++) @@ -76,8 +80,10 @@ int main() v = flint_malloc(nv[j] * sizeof(ulong)); +#if OUT == LOG flint_printf("log(1..%wu) mod %d primes of size %d bits....\n", nv[j], np, bits[i]); fflush(stdout); +#endif for (l = 0; l < nf; l++) { @@ -86,8 +92,16 @@ int main() if (l == 2 && i > 5) continue; +#if OUT == LOG flint_printf("%-20s... ",n[l]); fflush(stdout); +#elif OUT == CSV + flint_printf("%-8s, %2d, %4d, %3d, ",n[l],bits[i],nv[j],np); +#elif OUT == JSON + flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nv\": %d, \"nprimes\": %d, \"time\": ", + n[l],bits[i],nv[j],np); +#endif + TIMEIT_ONCE_START for (k = 0; k < np; k++) { @@ -97,6 +111,12 @@ int main() (func[l])(v, nv[j], a[k], 1, p[k], p[k].n - 1, order); } TIMEIT_ONCE_STOP + +#if OUT == JSON + flint_printf("}\n"); +#else + flint_printf("\n"); +#endif } flint_free(v); } diff --git a/dlog/vec_crt.c b/dlog/vec_crt.c index 09bb4928..918573bb 100644 --- a/dlog/vec_crt.c +++ b/dlog/vec_crt.c @@ -27,46 +27,6 @@ #define SIEVE_START 100 -/* group components up to bound and return cofactor */ -#define G_SMALL 0 -#define G_BIG 1 - -static void -n_factor_group(n_factor_t * fac, ulong bound) -{ - int i, j, k; - ulong m[FLINT_MAX_FACTORS_IN_LIMB]; - ulong c = 1; - i = 0; - for (k = fac->num - 1; k >= 0; k--) - { - ulong qe = n_pow(fac->p[k], fac->exp[k]); - if (qe > bound) - c *= qe; - else - { - /* try to insert somewhere in m */ - for (j = 0; j < i && (m[j] * qe > bound); j++); - if (j == i) - m[i++] = qe; - else - m[j] *= qe; - } - } - for (j = 0; j < i; j++) - { - fac->p[j] = m[j]; - fac->exp[j] = G_SMALL; - } - if (c > 1) - { - fac->p[i] = c; - fac->exp[i] = G_BIG; - i++; - } - fac->num = i; -} - /* assume v[k] = -1 for bad primes? */ /* loop on small components and if needed keep one subgroup for DLOG + sieve */ void @@ -79,7 +39,7 @@ dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t maxloop = LOOP_MAX_FACTOR * nv; n_factor_init(&fac); n_factor(&fac, na, 1); - n_factor_group(&fac, maxloop); + dlog_n_factor_group(&fac, maxloop); for (k = 0; k < fac.num; k++) { ulong m, M, aM, uM, vaM; @@ -93,9 +53,9 @@ dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t else { if (nv <= SIEVE_START) - dlog_vec_eratos_ph(v, nv, aM, vaM, M, mod, m, order); + dlog_vec_eratos_subgroup(v, nv, aM, vaM, M, mod, m, order); else - dlog_vec_sieve_ph(v, nv, aM, vaM, M, mod, m, order); + dlog_vec_sieve_subgroup(v, nv, aM, vaM, M, mod, m, order); } } } diff --git a/dlog/vec_eratos.c b/dlog/vec_eratos.c index fd33374e..7abbf7b6 100644 --- a/dlog/vec_eratos.c +++ b/dlog/vec_eratos.c @@ -25,34 +25,8 @@ #include "dlog.h" -void -dlog_vec_eratos_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) -{ - ulong p, pmax; - dlog_precomp_t pre; - n_primes_t iter; - - /* discrete log on primes */ - pmax = (nv < mod.n) ? nv : mod.n; - dlog_precomp_n_init(pre, a, mod.n, na, n_prime_pi(nv)); - - n_primes_init(iter); - while ((p = n_primes_next(iter)) < pmax) - { - ulong k, pM, wp; - if (mod.n % p == 0) - continue; /* won't be attained another time */ - pM = (M) ? nmod_pow_ui(p, M, mod) : p; - wp = nmod_mul(dlog_precomp(pre, pM), va, order); - for (pM = p; pM < nv; pM *= p) - for (k = pM; k < nv; k += pM) - v[k] = nmod_add(v[k], wp, order); - } - n_primes_clear(iter); -} - void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - dlog_vec_eratos_ph(v, nv, a, va, 1, mod, na, order); + dlog_vec_eratos_subgroup(v, nv, a, va, 1, mod, na, order); } diff --git a/dlog/vec_eratos_subgroup.c b/dlog/vec_eratos_subgroup.c new file mode 100644 index 00000000..c17e4b70 --- /dev/null +++ b/dlog/vec_eratos_subgroup.c @@ -0,0 +1,52 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) +{ + ulong p, pmax; + dlog_precomp_t pre; + n_primes_t iter; + + /* discrete log on primes */ + pmax = (nv < mod.n) ? nv : mod.n; + dlog_precomp_n_init(pre, a, mod.n, na, n_prime_pi(nv)); + + n_primes_init(iter); + while ((p = n_primes_next(iter)) < pmax) + { + ulong k, pM, wp; + if (mod.n % p == 0) + continue; /* won't be attained another time */ + pM = (M) ? nmod_pow_ui(p, M, mod) : p; + wp = nmod_mul(dlog_precomp(pre, pM), va, order); + for (pM = p; pM < nv; pM *= p) + for (k = pM; k < nv; k += pM) + v[k] = nmod_add(v[k], wp, order); + } + n_primes_clear(iter); +} diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index 66640ea0..3bfcaab3 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -33,8 +33,8 @@ dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod ulong vx = 0; for (x = a; x != 1; x = nmod_mul(x, a, mod)) { - vx = nmod_add(vx, va, order); - for(xp = x; xp < nv; xp+=mod.n) - v[xp] = nmod_add(v[xp], vx, order); + vx = nmod_add(vx, va, order); + for(xp = x; xp < nv; xp+=mod.n) + v[xp] = nmod_add(v[xp], vx, order); } } diff --git a/dlog/vec_pindex_factorgcd.c b/dlog/vec_pindex_factorgcd.c new file mode 100644 index 00000000..0458ab65 --- /dev/null +++ b/dlog/vec_pindex_factorgcd.c @@ -0,0 +1,114 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include + +#define vbs 0 +#define FACTOR_RATIO 4 + +static int +factor_until(ulong * n, ulong nlim, const ulong * p, ulong pmax, ulong * fp, int * fe) +{ + int i, j; + for (i = 0, j = 0; *n >= nlim && p[j] < pmax; j++) + { + int e = n_remove(n, p[j]); + if (e) + { + fp[i] = p[j]; + fe[i] = e; + i++; + } + } + return i; +} + +ulong +dlog_vec_pindex_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) +{ + int nm = 0, ng = 0; + ulong pm, logm, pmax; + ulong u[2], r[2], t; + ulong up[15], rp[15]; + int ue[15], re[15]; + const ulong * prime; + prime = n_primes_arr_readonly(p); + pmax = p / FACTOR_RATIO; + pm = p; + logm = 0; + while (nm++ < maxtry) + { + int i, j, iu, ir; + ulong logr; + pm = nmod_mul(pm, a, mod); + logm = nmod_add(logm, loga, order); + /* + if (2 * pm > mod.n) + { + pm = nmod_neg(pm, mod); + logm = nmod_add(logm, logm1, order); + } + */ + /* half gcd u * pm + v * mod = r, ignore v */ + u[0] = 0; r[0] = mod.n; + u[1] = 1; r[1] = pm; + i = 1; j = 0; /* flip flap */ + while (r[i] > u[i]) + { + ng++; + if (r[i] < nv && v[r[i]].m == r[i] && u[i] < nv && v[u[i]].m == u[i]) + { + /* early smooth detection: occurs for primes < 30 bits */ + ulong x; + /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ + x = nmod_sub(v[r[i]].logm, nmod_add(v[u[i]].logm, logm, order), order); + if (j) + x = nmod_add(x, logm1, order); + return x; + } + j = i; i = 1 - i; /* switch */ + t = r[i] / r[j]; + r[i] = r[i] % r[j]; + u[i] = u[i] + t * u[j]; /* (-1)^j */ + + }; + /* try to factor both r[i] and u[i] */ + iu = factor_until(&u[i], nv, prime, pmax, up, ue); + if (u[i] >= nv || v[u[i]].m < u[i]) + continue; + ir = factor_until(&r[i], nv, prime, pmax, rp, re); + if (r[i] >= nv || v[r[i]].m < r[i]) + continue; + /* log(u)+log(p)+log(m)=log(r) */ + logr = 0; + for (i=0; i < ir; i++) + logr = nmod_add(logr, (re[i] * v[rp[i]].logm) % order.n, order); + for (i=0; i < iu; i++) + logm = nmod_add(logm, (ue[i] * v[up[i]].logm) % order.n, order); + return nmod_sub(logr, logm, order); + } + return NOT_FOUND; +} diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index d2263c39..98ee3c3f 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -24,288 +24,9 @@ ******************************************************************************/ #include "dlog.h" -#include - -#define vbs 0 -#define FACTOR_RATIO 4 - -static ulong -logp_sieve_gcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) -{ - int i, j, nm = 0, ng = 0; - ulong pm, logm; - ulong u[2], r[2], t; -#if vbs > 1 - flint_printf("\nEnter logp_sieve p=%wu mod %wu...\n", p, mod); -#endif - pm = p; - logm = 0; - while (nm++ < maxtry) - { - pm = nmod_mul(pm, a, mod); - logm = nmod_add(logm, loga, order); - if (2 * pm > mod.n) - { - pm = nmod_neg(pm, mod); - logm = nmod_add(logm, logm1, order); - } - /* half gcd u * pm + v * mod = r, ignore v */ - u[0] = 0; r[0] = mod.n; - u[1] = 1; r[1] = pm; - i = 1; j = 0; /* flip flap */ - do { - ng++; -#if vbs > 1 - if (r[i] < nv && u[i] < nv) - flint_printf("[r=%wu, v[r]=%wu, u=%wu, v[u]=%wu -- nv=%wu]\n", - r[i], v[r[i]].m, u[i], v[u[i]].m, nv); -#endif - if (r[i] < nv && v[r[i]].m == r[i] && u[i] < nv && v[u[i]].m == u[i]) - { - ulong x; - /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ - x = nmod_sub(v[r[i]].logm, nmod_add(v[u[i]].logm, logm, order), order); - if (j) - x = nmod_add(x, logm1, order); - return x; - } - - j = i; i = 1 - i; /* switch */ - t = r[i] / r[j]; - r[i] = r[i] % r[j]; - u[i] = u[i] + t * u[j]; /* (-1)^j */ - - } while (r[i] > 0 && u[i] < nv); - } - return NOT_FOUND; -} - -static ulong -logp_sieve_factor(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) -{ - int nm = 0; - ulong pm, logm; - - const ulong * prime; - prime = n_primes_arr_readonly(p); - - pm = p; - logm = 0; - while (pm < mod.n) - { - /*nm++;*/ /* init ignored */ - pm *= a; - logm = nmod_add(logm, loga, order); - } - pm = pm % mod.n; - do { - int i, j, ind[15], exp[15]; - /* find multiplier m */ - if (2 * pm > mod.n) - { - pm = nmod_neg(pm, mod); - logm = nmod_add(logm, logm1, order); - } - - for (i = 0, j = 0; j < p && pm >= nv && 4 * prime[j] < p; j++) - { - int e = n_remove(&pm, prime[j]); - if (e) - { - ind[i] = j; - exp[i] = e; - i++; - } - } - if (pm < nv && v[pm].m == pm) - { - /* goal! */ - ulong x = v[pm].logm; - /* chi(m)*chi(p)=chi(pm)*prod */ - for(j = 0; j < i; j++) - x = nmod_add(x, nmod_mul(exp[j], v[prime[ind[j]]].logm, order), order); - x = nmod_sub(logm, x, order); - /*flint_printf("managed %d mults / %d for p=%wu, pm=%wu\n",nm,maxtry,p,pm);*/ - return x; - } - nm++; - pm = nmod_mul(pm, a, mod); - logm = nmod_add(logm, loga, order); - } while (nm < maxtry); - return NOT_FOUND; -} - -static int -factor_until(ulong * n, ulong nlim, const ulong * p, ulong pmax, ulong * fp, int * fe) -{ - int i, j; - for (i = 0, j = 0; *n >= nlim && p[j] < pmax; j++) - { - int e = n_remove(n, p[j]); - if (e) - { - fp[i] = p[j]; - fe[i] = e; - i++; - } - } - return i; -} - -static ulong -logp_sieve_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) -{ - int nm = 0, ng = 0; - ulong pm, logm, pmax; - ulong u[2], r[2], t; - ulong up[15], rp[15]; - int ue[15], re[15]; - const ulong * prime; - prime = n_primes_arr_readonly(p); - pmax = p / FACTOR_RATIO; - pm = p; - logm = 0; - while (nm++ < maxtry) - { - int i, j, iu, ir; - ulong logr; - pm = nmod_mul(pm, a, mod); - logm = nmod_add(logm, loga, order); - /* - if (2 * pm > mod.n) - { - pm = nmod_neg(pm, mod); - logm = nmod_add(logm, logm1, order); - } - */ - /* half gcd u * pm + v * mod = r, ignore v */ - u[0] = 0; r[0] = mod.n; - u[1] = 1; r[1] = pm; - i = 1; j = 0; /* flip flap */ - while (r[i] > u[i]) - { - ng++; - if (r[i] < nv && v[r[i]].m == r[i] && u[i] < nv && v[u[i]].m == u[i]) - { - /* early smooth detection: occurs for primes < 30 bits */ - ulong x; - /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ - x = nmod_sub(v[r[i]].logm, nmod_add(v[u[i]].logm, logm, order), order); - if (j) - x = nmod_add(x, logm1, order); - return x; - } - j = i; i = 1 - i; /* switch */ - t = r[i] / r[j]; - r[i] = r[i] % r[j]; - u[i] = u[i] + t * u[j]; /* (-1)^j */ - - }; - /* try to factor both r[i] and u[i] */ - iu = factor_until(&u[i], nv, prime, pmax, up, ue); - if (u[i] >= nv || v[u[i]].m < u[i]) - continue; - ir = factor_until(&r[i], nv, prime, pmax, rp, re); - if (r[i] >= nv || v[r[i]].m < r[i]) - continue; - /* log(u)+log(p)+log(m)=log(r) */ - logr = 0; - for (i=0; i < ir; i++) - logr = nmod_add(logr, (re[i] * v[rp[i]].logm) % order.n, order); - for (i=0; i < iu; i++) - logm = nmod_add(logm, (ue[i] * v[up[i]].logm) % order.n, order); - return nmod_sub(logr, logm, order); - } - return NOT_FOUND; -} - -void -dlog_vec_sieve_ph(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) -{ - ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; - ulong logcost, limcount; - ulong k, p, p1, pmax, logm1; - log_pair_t * w; - dlog_precomp_t pre; - n_primes_t iter; - ulong X, aX, vaX; - - /* store size */ - w = flint_malloc( nv * sizeof(log_pair_t)); - for (k = 0; k < nv; k++) - { - w[k].m = 1; - w[k].logm = 0; /* could be v[k]... */ - } - - /* discrete log on first primes, then sieve */ - pmax = (nv < mod.n) ? nv : mod.n; - p1 = 50; /* FIXME: tune this limit! */ - dlog_precomp_n_init(pre, a, mod.n, na, p1); - /*flint_printf("## single log cost: %wu\n", pre->cost);*/ - logcost = pre->cost; - - if (logcost < 15) - { - /* p1 = pmax; */ - limcount = mod.n; - } - else - { - limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); - logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); - } - - /* find big power of gen */ - X = n_nextprime(na / 2 + 10, 0); - X = (na % 257) ? 257 % na : 1031 % na ; /* FIXME! */ - aX = nmod_pow_ui(a, X, mod); - vaX = nmod_mul(va, X % order.n, order); - - n_primes_init(iter); - while ((p = n_primes_next(iter)) < pmax) - { - double cost = log(mod.n)/log(p); - ulong m, wp; - if (mod.n % p == 0) /* FIXME: those primes could be known... */ - continue; /* won't be attained another time */ - cost = log(mod.n)/log(p); - cost = pow(cost,cost); - sievecount++; - /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ - /*if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ - if (logcost < cost || (wp = logp_sieve_factorgcd(w, nv, p, mod, aX, na, vaX, logm1, order, cost)) == NOT_FOUND) - { - if (logcost < cost) - sievecount--; - else - missed++; - logcount++; - wp = nmod_mul(dlog_precomp(pre, nmod_pow_ui(p, M, mod)), va, order); - } - for (k = p, m = 1; k < nv; k += p, m++) - { - w[k].m = w[m].m * p; - w[k].logm = nmod_add(w[m].logm, wp, order); - if (w[k].m == k) - smooth++; - } - } - /* write in v */ - for (k = 0; k < nv; k++) - if (v[k] != NOT_FOUND) - v[k] = nmod_add(v[k], w[k].logm, order); -#if vbs - if (missed) - flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", - smooth, limcount, mod.n, logcost, logcount, sievecount, missed); -#endif - n_primes_clear(iter); - flint_free(w); -} void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - dlog_vec_sieve_ph(v, nv, a, va, 1, mod, na, order); + dlog_vec_sieve_subgroup(v, nv, a, va, 1, mod, na, order); } diff --git a/dlog/vec_sieve_subgroup.c b/dlog/vec_sieve_subgroup.c new file mode 100644 index 00000000..ba0b0b21 --- /dev/null +++ b/dlog/vec_sieve_subgroup.c @@ -0,0 +1,114 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include + +#define vbs 0 + +void +dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) +{ + ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; + ulong logcost, limcount; + ulong k, p, p1, pmax, logm1; + log_pair_t * w; + dlog_precomp_t pre; + n_primes_t iter; + ulong X, aX, vaX; + + /* store size */ + w = flint_malloc( nv * sizeof(log_pair_t)); + for (k = 0; k < nv; k++) + { + w[k].m = 1; + w[k].logm = 0; /* could be v[k]... */ + } + + /* discrete log on first primes, then sieve */ + pmax = (nv < mod.n) ? nv : mod.n; + p1 = 50; /* FIXME: tune this limit! */ + dlog_precomp_n_init(pre, a, mod.n, na, p1); + /*flint_printf("## single log cost: %wu\n", pre->cost);*/ + logcost = pre->cost; + + if (logcost < 15) + { + /* p1 = pmax; */ + limcount = mod.n; + } + else + { + limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); + logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); + } + + /* find big power of gen */ + X = n_nextprime(na / 2 + 10, 0); + X = (na % 257) ? 257 % na : 1031 % na ; /* FIXME! */ + aX = nmod_pow_ui(a, X, mod); + vaX = nmod_mul(va, X % order.n, order); + + n_primes_init(iter); + while ((p = n_primes_next(iter)) < pmax) + { + double cost = log(mod.n)/log(p); + ulong m, wp; + if (mod.n % p == 0) /* FIXME: those primes could be known... */ + continue; /* won't be attained another time */ + cost = log(mod.n)/log(p); + cost = pow(cost,cost); + sievecount++; + /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ + /*if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ + if (logcost < cost || (wp = dlog_vec_pindex_factorgcd(w, nv, p, mod, aX, na, vaX, logm1, order, cost)) == NOT_FOUND) + { + if (logcost < cost) + sievecount--; + else + missed++; + logcount++; + wp = nmod_mul(dlog_precomp(pre, nmod_pow_ui(p, M, mod)), va, order); + } + for (k = p, m = 1; k < nv; k += p, m++) + { + w[k].m = w[m].m * p; + w[k].logm = nmod_add(w[m].logm, wp, order); + if (w[k].m == k) + smooth++; + } + } + /* write in v */ + for (k = 0; k < nv; k++) + if (v[k] != NOT_FOUND) + v[k] = nmod_add(v[k], w[k].logm, order); +#if vbs + if (missed) + flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", + smooth, limcount, mod.n, logcost, logcount, sievecount, missed); +#endif + n_primes_clear(iter); + flint_free(w); +} From 49ff9e483084f1e8f9eed79d259a44cfbb0b0e0f Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 18 Mar 2016 18:28:11 +0100 Subject: [PATCH 016/139] start to debug dlog_vec --- dlog.h | 3 + dlog/test/t-vec.c | 120 +++++++++++++++++++++++++++++++++++++ dlog/vec_crt.c | 2 +- dlog/vec_eratos_subgroup.c | 3 +- dlog/vec_init.c | 34 +++++++++++ dlog/vec_loop.c | 13 ++-- dlog/vec_loop_subgroup.c | 40 +++++++++++++ 7 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 dlog/test/t-vec.c create mode 100644 dlog/vec_init.c create mode 100644 dlog/vec_loop_subgroup.c diff --git a/dlog.h b/dlog.h index 4de69b7c..41503b51 100644 --- a/dlog.h +++ b/dlog.h @@ -210,6 +210,9 @@ typedef struct ulong dlog_vec_pindex_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry); + +void dlog_vec_init(ulong * v, ulong nv); +void dlog_vec_loop_subgroup(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); diff --git a/dlog/test/t-vec.c b/dlog/test/t-vec.c new file mode 100644 index 00000000..600272eb --- /dev/null +++ b/dlog/test/t-vec.c @@ -0,0 +1,120 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); + +void +dlog_vec_trivial(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) +{ + ulong k; + dlog_precomp_t pre; + dlog_precomp_n_init(pre, a, mod.n, na, 50); + for (k = 1; k < nv; k++) + if (n_gcd(k, mod.n) > 1) + v[k] = NOT_FOUND; + else + v[k] = dlog_precomp(pre, k % mod.n); +} + +static ulong +dlog_vec_diff(ulong * v, ulong * ref, ulong nv) +{ + ulong k; + for (k = 1; k < nv; k++) + if (ref[k] != v[k]) + return k; + return 0; +} + +int main() +{ + slong bits, nv, iter; + flint_rand_t state; + int f, nf = 3; + vec_f func[5] = { dlog_vec_trivial, dlog_vec_loop, dlog_vec_eratos, dlog_vec_sieve, dlog_vec_crt }; + char * n[5] = { "trivial", "loop", "eratos", "sieve", "crt" }; + + + flint_printf("dlog(1..n) mod p...."); + fflush(stdout); + flint_randinit(state); + + for (bits = 10; bits <= 10; bits += 5) + { + for (nv = 10; nv <= 10000; nv *= 10) + { + + ulong *v, *ref; + int iref; + + iref = (bits == 10 && nv <= 1000) ? 0 : 2; + + ref = flint_malloc(nv * sizeof(ulong)); + v = flint_malloc(nv * sizeof(ulong)); + + for (iter = 0; iter < 10; iter++) + { + + int k; + ulong p, a, va, na; + nmod_t mod, order; + + p = n_randprime(state, bits, 0); + a = n_primitive_root_prime(p); + + nmod_init(&mod, p); + va = 1; na = p - 1; + nmod_init(&order, na); + + dlog_vec_init(ref, nv); + (func[iref])(ref, nv, a, va, mod, na, order); + + /* compare */ + for (f = 0; f < nf; f++) + { + if (f == iref) + continue; + dlog_vec_init(v, nv); + (func[f])(v, nv, a, va, mod, na, order); + + if ((k = dlog_vec_diff(v, ref, nv))) + { + flint_printf("FAIL: log(%wu,%wu) mod %wu: %s->%w != %s->%wu\n", + k, a, p, n[iref], ref[k], n[f], v[k]); + abort(); + } + } + } + flint_free(ref); + flint_free(v); + } + } + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/dlog/vec_crt.c b/dlog/vec_crt.c index 918573bb..5cdcb5f4 100644 --- a/dlog/vec_crt.c +++ b/dlog/vec_crt.c @@ -49,7 +49,7 @@ dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t uM = M * n_invmod(M % m, m); /* uM < n */ vaM = nmod_mul(va, uM % order.n, order); if (fac.exp[k] == G_SMALL) - dlog_vec_loop(v, nv, aM, vaM, mod, m, order); + dlog_vec_loop_subgroup(v, nv, aM, vaM, mod, m, order); else { if (nv <= SIEVE_START) diff --git a/dlog/vec_eratos_subgroup.c b/dlog/vec_eratos_subgroup.c index c17e4b70..4f94bfce 100644 --- a/dlog/vec_eratos_subgroup.c +++ b/dlog/vec_eratos_subgroup.c @@ -25,6 +25,7 @@ #include "dlog.h" +/* assume 1 mod n already set */ void dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) { @@ -42,7 +43,7 @@ dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t ulong k, pM, wp; if (mod.n % p == 0) continue; /* won't be attained another time */ - pM = (M) ? nmod_pow_ui(p, M, mod) : p; + pM = (M > 1) ? nmod_pow_ui(p, M, mod) : p; wp = nmod_mul(dlog_precomp(pre, pM), va, order); for (pM = p; pM < nv; pM *= p) for (k = pM; k < nv; k += pM) diff --git a/dlog/vec_init.c b/dlog/vec_init.c new file mode 100644 index 00000000..cde8125e --- /dev/null +++ b/dlog/vec_init.c @@ -0,0 +1,34 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_vec_init(ulong *v, ulong nv) +{ + ulong k; + for (k = 0; k < nv; k++) + v[k] = 0; +} diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index 3bfcaab3..643c9049 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -29,12 +29,15 @@ void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - ulong x, xp; - ulong vx = 0; - for (x = a; x != 1; x = nmod_mul(x, a, mod)) + ulong x, vx; + x = 1; vx = 0; + do { + v[x] = vx; + x = nmod_mul(x, a, mod); vx = nmod_add(vx, va, order); - for(xp = x; xp < nv; xp+=mod.n) - v[xp] = nmod_add(v[xp], vx, order); } + while (x != 1); + for(x = mod.n + 1; x < nv; x++) + v[x] = v[x - mod.n]; } diff --git a/dlog/vec_loop_subgroup.c b/dlog/vec_loop_subgroup.c new file mode 100644 index 00000000..822d5bbc --- /dev/null +++ b/dlog/vec_loop_subgroup.c @@ -0,0 +1,40 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +/* vector of log(k,a)*loga % order in Z/modZ */ +void +dlog_vec_loop_subgroup(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + ulong x, xp, vx; + vx = 0; + for (x = a; x != 1; x = nmod_mul(x, a, mod)) + { + vx = nmod_add(vx, va, order); + for(xp = x; xp < nv; xp+=mod.n) + v[xp] = nmod_add(v[xp], vx, order); + } +} From 024815e1b37e5a9e0ffe7765ab88f0074e71bf52 Mon Sep 17 00:00:00 2001 From: Pascal Date: Sun, 20 Mar 2016 22:32:47 +0100 Subject: [PATCH 017/139] debugged dlog_vec_sieve --- dlog.h | 5 ++-- dlog/vec.c | 1 + dlog/vec_crt.c | 1 + dlog/vec_eratos.c | 1 + dlog/vec_eratos_subgroup.c | 24 ++++++++++-------- dlog/vec_init.c | 4 +-- dlog/vec_loop.c | 4 ++- dlog/vec_pindex_factorgcd.c | 49 ++++++++++++++++++++++++++++--------- dlog/vec_set_not_found.c | 43 ++++++++++++++++++++++++++++++++ dlog/vec_sieve.c | 1 + dlog/vec_sieve_subgroup.c | 27 ++++++++++---------- 11 files changed, 121 insertions(+), 39 deletions(-) create mode 100644 dlog/vec_set_not_found.c diff --git a/dlog.h b/dlog.h index 41503b51..fb054ecf 100644 --- a/dlog.h +++ b/dlog.h @@ -208,10 +208,11 @@ typedef struct ulong m, logm; } log_pair_t; -ulong dlog_vec_pindex_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry); +ulong dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry); -void dlog_vec_init(ulong * v, ulong nv); +void dlog_vec_fill(ulong * v, ulong nv, ulong x); +void dlog_vec_set_not_found(ulong *v, ulong nv, nmod_t mod); void dlog_vec_loop_subgroup(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); diff --git a/dlog/vec.c b/dlog/vec.c index 8145d307..32e76404 100644 --- a/dlog/vec.c +++ b/dlog/vec.c @@ -28,6 +28,7 @@ void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { + dlog_vec_fill(v, nv, 0); if (na * LOOP_MAX_FACTOR > nv) dlog_vec_loop(v, nv, a, va, mod, na, order); else diff --git a/dlog/vec_crt.c b/dlog/vec_crt.c index 5cdcb5f4..d9fd99b7 100644 --- a/dlog/vec_crt.c +++ b/dlog/vec_crt.c @@ -36,6 +36,7 @@ dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t ulong maxloop; int k; + dlog_vec_fill(v, nv, 0); maxloop = LOOP_MAX_FACTOR * nv; n_factor_init(&fac); n_factor(&fac, na, 1); diff --git a/dlog/vec_eratos.c b/dlog/vec_eratos.c index 7abbf7b6..b9b973f0 100644 --- a/dlog/vec_eratos.c +++ b/dlog/vec_eratos.c @@ -28,5 +28,6 @@ void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { + dlog_vec_set_not_found(v, nv, mod); dlog_vec_eratos_subgroup(v, nv, a, va, 1, mod, na, order); } diff --git a/dlog/vec_eratos_subgroup.c b/dlog/vec_eratos_subgroup.c index 4f94bfce..89bcbfd0 100644 --- a/dlog/vec_eratos_subgroup.c +++ b/dlog/vec_eratos_subgroup.c @@ -25,29 +25,33 @@ #include "dlog.h" -/* assume 1 mod n already set */ +/* assume non invertible and 1 mod n already set */ void dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) { - ulong p, pmax; + ulong p, k, n; dlog_precomp_t pre; n_primes_t iter; /* discrete log on primes */ - pmax = (nv < mod.n) ? nv : mod.n; - dlog_precomp_n_init(pre, a, mod.n, na, n_prime_pi(nv)); + n = (nv < mod.n) ? nv : mod.n; + dlog_precomp_n_init(pre, a, mod.n, na, n_prime_pi(n)); n_primes_init(iter); - while ((p = n_primes_next(iter)) < pmax) + while ((p = n_primes_next(iter)) < n) { - ulong k, pM, wp; - if (mod.n % p == 0) + ulong pM, wp; + if (v[p] == NOT_FOUND) continue; /* won't be attained another time */ pM = (M > 1) ? nmod_pow_ui(p, M, mod) : p; wp = nmod_mul(dlog_precomp(pre, pM), va, order); - for (pM = p; pM < nv; pM *= p) - for (k = pM; k < nv; k += pM) - v[k] = nmod_add(v[k], wp, order); + /* fixme: could be faster sieving m*pe */ + for (pM = p; pM < n; pM *= p) + for (k = pM; k < n; k += pM) + if (v[k] != NOT_FOUND) + v[k] = nmod_add(v[k], wp, order); } n_primes_clear(iter); + for (k = mod.n + 1; k < nv; k++) + v[k] = v[k - mod.n]; } diff --git a/dlog/vec_init.c b/dlog/vec_init.c index cde8125e..6a5707c3 100644 --- a/dlog/vec_init.c +++ b/dlog/vec_init.c @@ -26,9 +26,9 @@ #include "dlog.h" void -dlog_vec_init(ulong *v, ulong nv) +dlog_vec_fill(ulong *v, ulong nv, ulong x) { ulong k; for (k = 0; k < nv; k++) - v[k] = 0; + v[k] = x; } diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index 643c9049..8c5482ab 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -30,10 +30,12 @@ void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong x, vx; + dlog_vec_fill(v, nv, NOT_FOUND); x = 1; vx = 0; do { - v[x] = vx; + if (x < nv) + v[x] = vx; x = nmod_mul(x, a, mod); vx = nmod_add(vx, va, order); } diff --git a/dlog/vec_pindex_factorgcd.c b/dlog/vec_pindex_factorgcd.c index 0458ab65..eb67341f 100644 --- a/dlog/vec_pindex_factorgcd.c +++ b/dlog/vec_pindex_factorgcd.c @@ -26,7 +26,7 @@ #include "dlog.h" #include -#define vbs 0 +#define vbs 1 #define FACTOR_RATIO 4 static int @@ -47,7 +47,7 @@ factor_until(ulong * n, ulong nlim, const ulong * p, ulong pmax, ulong * fp, int } ulong -dlog_vec_pindex_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) +dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry) { int nm = 0, ng = 0; ulong pm, logm, pmax; @@ -79,35 +79,62 @@ dlog_vec_pindex_factorgcd(log_pair_t * v, ulong nv, ulong p, nmod_t mod, ulong a while (r[i] > u[i]) { ng++; - if (r[i] < nv && v[r[i]].m == r[i] && u[i] < nv && v[u[i]].m == u[i]) + if (r[i] < nv && v[r[i]] != NOT_FOUND && u[i] < nv && v[u[i]] != NOT_FOUND) { /* early smooth detection: occurs for primes < 30 bits */ ulong x; /* chi(-1)^j*chi(u)*chi(p)*chi(m)=chi(r) */ - x = nmod_sub(v[r[i]].logm, nmod_add(v[u[i]].logm, logm, order), order); + x = nmod_sub(v[r[i]], nmod_add(v[u[i]], logm, order), order); if (j) x = nmod_add(x, logm1, order); + flint_printf("[sieve early] %wu * %wu^%wu = %wu [%wu]\n", + p, a, nm, pm, mod.n); + flint_printf("[sieve early] found %wu * %wu = (-1)^%d*%wu [%wu]\n", + u[i], pm, j, r[i], mod.n); + flint_printf("[sieve early] log(%wu^%wu) = %wu * %wu = %wu [%wu]\n", + a, nm, nm, loga, logm, order.n); + flint_printf("[ on logs] %wu + %wu + log(%wu) = %d * %wu + %wu [%wu]\n", + v[u[i]],logm,p,j,logm1,v[r[i]], order.n); + flint_printf("[ hence ] log(%wu) = %wu\n", p, x); return x; } j = i; i = 1 - i; /* switch */ t = r[i] / r[j]; r[i] = r[i] % r[j]; - u[i] = u[i] + t * u[j]; /* (-1)^j */ - + u[i] = u[i] + t * u[j]; /* times (-1)^j */ }; + flint_printf("[sieve factor] %wu * %wu^%wu = %wu [%wu]\n", + p, a, nm, pm, mod.n); + flint_printf("[sieve factor] found %wu * %wu = (-1)^%d*%wu [%wu]\n", + u[i], pm, j, r[i], mod.n); + flint_printf("[sieve factor] logm = %wu [A=%wu,logA=%wu,nm=%wu]\n", + logm,a,loga,nm); + logr = (j) ? logm1 : 0; + flint_printf("[sieve factor] logr = %wu\n",logr); /* try to factor both r[i] and u[i] */ iu = factor_until(&u[i], nv, prime, pmax, up, ue); - if (u[i] >= nv || v[u[i]].m < u[i]) + if (u[i] >= nv || v[u[i]] == NOT_FOUND) continue; + flint_printf("[sieve factor] u: found %d factors up to %wu\n",iu,u[i]); ir = factor_until(&r[i], nv, prime, pmax, rp, re); - if (r[i] >= nv || v[r[i]].m < r[i]) + if (r[i] >= nv || v[r[i]] == NOT_FOUND) continue; + flint_printf("[sieve factor] r: found %d factors up to %wu\n",ir,r[i]); /* log(u)+log(p)+log(m)=log(r) */ - logr = 0; + logm = nmod_add(logm, v[u[i]], order); + logr = nmod_add(logr, v[r[i]], order); for (i=0; i < ir; i++) - logr = nmod_add(logr, (re[i] * v[rp[i]].logm) % order.n, order); + logr = nmod_add(logr, (re[i] * v[rp[i]]) % order.n, order); + flint_printf("[sieve factor] logr = %wu\n",logr); for (i=0; i < iu; i++) - logm = nmod_add(logm, (ue[i] * v[up[i]].logm) % order.n, order); + logm = nmod_add(logm, (ue[i] * v[up[i]]) % order.n, order); + flint_printf("[sieve factor] logm = %wu\n",logm); + flint_printf("[sieve factor] log(%wu^%wu) = %wu * %wu = %wu [%wu]\n", + a, nm, nm, loga, logm, order.n); + flint_printf("[ on logs] %wu + log(%wu) = %d * %wu + %wu [%wu]\n", + logm,p,j,logm1, logr, order.n); + flint_printf("[ hence ] log(%wu) = %wu\n", p, nmod_sub(logr, logm, order)); + return nmod_sub(logr, logm, order); } return NOT_FOUND; diff --git a/dlog/vec_set_not_found.c b/dlog/vec_set_not_found.c new file mode 100644 index 00000000..347cf50b --- /dev/null +++ b/dlog/vec_set_not_found.c @@ -0,0 +1,43 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_vec_set_not_found(ulong *v, ulong nv, nmod_t mod) +{ + n_factor_t fac; + ulong i; + + n_factor_init(&fac); + n_factor(&fac, mod.n, 1); + for (i = 0; i < fac.num; i++) + { + ulong p, k; + p = fac.p[i]; + for (k = p; k < nv; k += p) + v[k] = NOT_FOUND; + } +} diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index 98ee3c3f..77867e92 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -28,5 +28,6 @@ void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { + dlog_vec_set_not_found(v, nv, mod); dlog_vec_sieve_subgroup(v, nv, a, va, 1, mod, na, order); } diff --git a/dlog/vec_sieve_subgroup.c b/dlog/vec_sieve_subgroup.c index ba0b0b21..626e77d2 100644 --- a/dlog/vec_sieve_subgroup.c +++ b/dlog/vec_sieve_subgroup.c @@ -26,7 +26,7 @@ #include "dlog.h" #include -#define vbs 0 +#define vbs 1 void dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) @@ -34,7 +34,7 @@ dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t m ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; ulong logcost, limcount; ulong k, p, p1, pmax, logm1; - log_pair_t * w; + ulong * w; dlog_precomp_t pre; n_primes_t iter; ulong X, aX, vaX; @@ -42,10 +42,9 @@ dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t m /* store size */ w = flint_malloc( nv * sizeof(log_pair_t)); for (k = 0; k < nv; k++) - { - w[k].m = 1; - w[k].logm = 0; /* could be v[k]... */ - } + w[k] = NOT_FOUND; + w[1] = 0; + logm1 = (na % 2) ? 0 : nmod_mul(na / 2, va, order); /* discrete log on first primes, then sieve */ pmax = (nv < mod.n) ? nv : mod.n; @@ -62,7 +61,6 @@ dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t m else { limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); - logm1 = (mod.n % 2) ? 0 : dlog_precomp(pre, mod.n - 1); } /* find big power of gen */ @@ -76,7 +74,7 @@ dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t m { double cost = log(mod.n)/log(p); ulong m, wp; - if (mod.n % p == 0) /* FIXME: those primes could be known... */ + if (v[p] == NOT_FOUND) continue; /* won't be attained another time */ cost = log(mod.n)/log(p); cost = pow(cost,cost); @@ -94,16 +92,19 @@ dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t m } for (k = p, m = 1; k < nv; k += p, m++) { - w[k].m = w[m].m * p; - w[k].logm = nmod_add(w[m].logm, wp, order); - if (w[k].m == k) - smooth++; + if (w[m] == NOT_FOUND) + continue; + smooth++; + w[k] = nmod_add(w[m], wp, order); + flint_printf("set log(%wu)=log(%wu)+log(%wu)=%wu\n",k,m,p,w[k]); } } + for (k = mod.n + 1; k < nv; k++) + w[k] = w[k - mod.n]; /* write in v */ for (k = 0; k < nv; k++) if (v[k] != NOT_FOUND) - v[k] = nmod_add(v[k], w[k].logm, order); + v[k] = nmod_add(v[k], w[k], order); #if vbs if (missed) flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", From 2e0b1a16e88020e1db11556444934e1085bc964a Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 21 Mar 2016 16:55:43 +0100 Subject: [PATCH 018/139] remove wrong vec_crt, rename subgroup->add --- dlog.h | 16 +-- dlog/test/t-vec.c | 22 ++-- dlog/vec.c | 3 +- dlog/{vec_crt.c => vec_add.c} | 39 +----- dlog/vec_eratos.c | 3 +- ...vec_eratos_subgroup.c => vec_eratos_add.c} | 18 +-- dlog/vec_loop.c | 2 +- dlog/{vec_loop_subgroup.c => vec_loop_add.c} | 5 +- dlog/vec_pindex_factorgcd.c | 35 +----- dlog/vec_set_not_found.c | 2 +- dlog/vec_sieve.c | 77 +++++++++++- dlog/vec_sieve_add.c | 40 ++++++ dlog/vec_sieve_subgroup.c | 115 ------------------ 13 files changed, 159 insertions(+), 218 deletions(-) rename dlog/{vec_crt.c => vec_add.c} (52%) rename dlog/{vec_eratos_subgroup.c => vec_eratos_add.c} (78%) rename dlog/{vec_loop_subgroup.c => vec_loop_add.c} (87%) create mode 100644 dlog/vec_sieve_add.c delete mode 100644 dlog/vec_sieve_subgroup.c diff --git a/dlog.h b/dlog.h index fb054ecf..16bdfd98 100644 --- a/dlog.h +++ b/dlog.h @@ -202,24 +202,18 @@ ulong dlog_precomp(const dlog_precomp_t pre, ulong b); #define G_BIG 1 void dlog_n_factor_group(n_factor_t * fac, ulong bound); -#define NOT_FOUND UWORD_MAX -typedef struct -{ - ulong m, logm; -} log_pair_t; +#define DLOG_NOT_FOUND UWORD_MAX +#define DLOG_NONE UWORD_MAX ulong dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulong na, ulong loga, ulong logm1, nmod_t order, int maxtry); - - void dlog_vec_fill(ulong * v, ulong nv, ulong x); void dlog_vec_set_not_found(ulong *v, ulong nv, nmod_t mod); -void dlog_vec_loop_subgroup(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_eratos_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_sieve_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); #endif diff --git a/dlog/test/t-vec.c b/dlog/test/t-vec.c index 600272eb..ecfb0146 100644 --- a/dlog/test/t-vec.c +++ b/dlog/test/t-vec.c @@ -35,9 +35,10 @@ dlog_vec_trivial(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong dlog_precomp_n_init(pre, a, mod.n, na, 50); for (k = 1; k < nv; k++) if (n_gcd(k, mod.n) > 1) - v[k] = NOT_FOUND; + v[k] = DLOG_NOT_FOUND; else v[k] = dlog_precomp(pre, k % mod.n); + dlog_precomp_clear(pre); } static ulong @@ -54,16 +55,17 @@ int main() { slong bits, nv, iter; flint_rand_t state; - int f, nf = 3; - vec_f func[5] = { dlog_vec_trivial, dlog_vec_loop, dlog_vec_eratos, dlog_vec_sieve, dlog_vec_crt }; - char * n[5] = { "trivial", "loop", "eratos", "sieve", "crt" }; + int f, nf = 4; + vec_f func[4] = { dlog_vec_trivial, dlog_vec_loop, dlog_vec_eratos, + dlog_vec_sieve }; + char * n[4] = { "trivial", "loop", "eratos", "sieve" }; flint_printf("dlog(1..n) mod p...."); fflush(stdout); flint_randinit(state); - for (bits = 10; bits <= 10; bits += 5) + for (bits = 10; bits <= 35; bits += 5) { for (nv = 10; nv <= 10000; nv *= 10) { @@ -90,20 +92,18 @@ int main() va = 1; na = p - 1; nmod_init(&order, na); - dlog_vec_init(ref, nv); + dlog_vec_fill(ref, nv, 0); (func[iref])(ref, nv, a, va, mod, na, order); /* compare */ - for (f = 0; f < nf; f++) + for (f = iref + 1; f < nf; f++) { - if (f == iref) - continue; - dlog_vec_init(v, nv); + dlog_vec_fill(v, nv, 0); (func[f])(v, nv, a, va, mod, na, order); if ((k = dlog_vec_diff(v, ref, nv))) { - flint_printf("FAIL: log(%wu,%wu) mod %wu: %s->%w != %s->%wu\n", + flint_printf("FAIL: log(%wu,%wu) mod %wu: %s->%w != %s->%w\n", k, a, p, n[iref], ref[k], n[f], v[k]); abort(); } diff --git a/dlog/vec.c b/dlog/vec.c index 32e76404..a4fb8da5 100644 --- a/dlog/vec.c +++ b/dlog/vec.c @@ -28,9 +28,8 @@ void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - dlog_vec_fill(v, nv, 0); if (na * LOOP_MAX_FACTOR > nv) dlog_vec_loop(v, nv, a, va, mod, na, order); else - dlog_vec_crt(v, nv, a, va, mod, na, order); + dlog_vec_sieve(v, nv, a, va, mod, na, order); } diff --git a/dlog/vec_crt.c b/dlog/vec_add.c similarity index 52% rename from dlog/vec_crt.c rename to dlog/vec_add.c index d9fd99b7..49e6f713 100644 --- a/dlog/vec_crt.c +++ b/dlog/vec_add.c @@ -25,38 +25,11 @@ #include "dlog.h" -#define SIEVE_START 100 - -/* assume v[k] = -1 for bad primes? */ -/* loop on small components and if needed keep one subgroup for DLOG + sieve */ - void -dlog_vec_crt(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +void +dlog_vec_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - n_factor_t fac; - ulong maxloop; - int k; - - dlog_vec_fill(v, nv, 0); - maxloop = LOOP_MAX_FACTOR * nv; - n_factor_init(&fac); - n_factor(&fac, na, 1); - dlog_n_factor_group(&fac, maxloop); - for (k = 0; k < fac.num; k++) - { - ulong m, M, aM, uM, vaM; - m = fac.p[k]; - M = na / m; - aM = nmod_pow_ui(a, M, mod); - uM = M * n_invmod(M % m, m); /* uM < n */ - vaM = nmod_mul(va, uM % order.n, order); - if (fac.exp[k] == G_SMALL) - dlog_vec_loop_subgroup(v, nv, aM, vaM, mod, m, order); - else - { - if (nv <= SIEVE_START) - dlog_vec_eratos_subgroup(v, nv, aM, vaM, M, mod, m, order); - else - dlog_vec_sieve_subgroup(v, nv, aM, vaM, M, mod, m, order); - } - } + if (na * LOOP_MAX_FACTOR > nv) + dlog_vec_loop_add(v, nv, a, va, mod, na, order); + else + dlog_vec_sieve_add(v, nv, a, va, mod, na, order); } diff --git a/dlog/vec_eratos.c b/dlog/vec_eratos.c index b9b973f0..b383c015 100644 --- a/dlog/vec_eratos.c +++ b/dlog/vec_eratos.c @@ -28,6 +28,7 @@ void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { + dlog_vec_fill(v, nv, 0); dlog_vec_set_not_found(v, nv, mod); - dlog_vec_eratos_subgroup(v, nv, a, va, 1, mod, na, order); + dlog_vec_eratos_add(v, nv, a, va, mod, na, order); } diff --git a/dlog/vec_eratos_subgroup.c b/dlog/vec_eratos_add.c similarity index 78% rename from dlog/vec_eratos_subgroup.c rename to dlog/vec_eratos_add.c index 89bcbfd0..4725fc51 100644 --- a/dlog/vec_eratos_subgroup.c +++ b/dlog/vec_eratos_add.c @@ -27,7 +27,7 @@ /* assume non invertible and 1 mod n already set */ void -dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) +dlog_vec_eratos_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong p, k, n; dlog_precomp_t pre; @@ -40,15 +40,15 @@ dlog_vec_eratos_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t n_primes_init(iter); while ((p = n_primes_next(iter)) < n) { - ulong pM, wp; - if (v[p] == NOT_FOUND) + ulong wp, pe; + if (v[p] == DLOG_NOT_FOUND) continue; /* won't be attained another time */ - pM = (M > 1) ? nmod_pow_ui(p, M, mod) : p; - wp = nmod_mul(dlog_precomp(pre, pM), va, order); - /* fixme: could be faster sieving m*pe */ - for (pM = p; pM < n; pM *= p) - for (k = pM; k < n; k += pM) - if (v[k] != NOT_FOUND) + wp = nmod_mul(dlog_precomp(pre, p), va, order); + /* fixme: could be faster sieving m*pe? but cannot + * use v[p*m]=v[p]*v[m]... */ + for (pe = p; pe < n; pe *= p) + for (k = pe; k < n; k += pe) + if (v[k] != DLOG_NOT_FOUND) v[k] = nmod_add(v[k], wp, order); } n_primes_clear(iter); diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index 8c5482ab..e50fb2f3 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -30,7 +30,7 @@ void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong x, vx; - dlog_vec_fill(v, nv, NOT_FOUND); + dlog_vec_fill(v, nv, DLOG_NOT_FOUND); x = 1; vx = 0; do { diff --git a/dlog/vec_loop_subgroup.c b/dlog/vec_loop_add.c similarity index 87% rename from dlog/vec_loop_subgroup.c rename to dlog/vec_loop_add.c index 822d5bbc..de03e7ab 100644 --- a/dlog/vec_loop_subgroup.c +++ b/dlog/vec_loop_add.c @@ -27,7 +27,7 @@ /* vector of log(k,a)*loga % order in Z/modZ */ void -dlog_vec_loop_subgroup(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong x, xp, vx; vx = 0; @@ -35,6 +35,7 @@ dlog_vec_loop_subgroup(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong { vx = nmod_add(vx, va, order); for(xp = x; xp < nv; xp+=mod.n) - v[xp] = nmod_add(v[xp], vx, order); + if (v[xp] != DLOG_NONE) + v[xp] = nmod_add(v[xp], vx, order); } } diff --git a/dlog/vec_pindex_factorgcd.c b/dlog/vec_pindex_factorgcd.c index eb67341f..fa8f23fc 100644 --- a/dlog/vec_pindex_factorgcd.c +++ b/dlog/vec_pindex_factorgcd.c @@ -79,7 +79,7 @@ dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulo while (r[i] > u[i]) { ng++; - if (r[i] < nv && v[r[i]] != NOT_FOUND && u[i] < nv && v[u[i]] != NOT_FOUND) + if (r[i] < nv && v[r[i]] != DLOG_NOT_FOUND && u[i] < nv && v[u[i]] != DLOG_NOT_FOUND) { /* early smooth detection: occurs for primes < 30 bits */ ulong x; @@ -87,15 +87,6 @@ dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulo x = nmod_sub(v[r[i]], nmod_add(v[u[i]], logm, order), order); if (j) x = nmod_add(x, logm1, order); - flint_printf("[sieve early] %wu * %wu^%wu = %wu [%wu]\n", - p, a, nm, pm, mod.n); - flint_printf("[sieve early] found %wu * %wu = (-1)^%d*%wu [%wu]\n", - u[i], pm, j, r[i], mod.n); - flint_printf("[sieve early] log(%wu^%wu) = %wu * %wu = %wu [%wu]\n", - a, nm, nm, loga, logm, order.n); - flint_printf("[ on logs] %wu + %wu + log(%wu) = %d * %wu + %wu [%wu]\n", - v[u[i]],logm,p,j,logm1,v[r[i]], order.n); - flint_printf("[ hence ] log(%wu) = %wu\n", p, x); return x; } j = i; i = 1 - i; /* switch */ @@ -103,39 +94,23 @@ dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulo r[i] = r[i] % r[j]; u[i] = u[i] + t * u[j]; /* times (-1)^j */ }; - flint_printf("[sieve factor] %wu * %wu^%wu = %wu [%wu]\n", - p, a, nm, pm, mod.n); - flint_printf("[sieve factor] found %wu * %wu = (-1)^%d*%wu [%wu]\n", - u[i], pm, j, r[i], mod.n); - flint_printf("[sieve factor] logm = %wu [A=%wu,logA=%wu,nm=%wu]\n", - logm,a,loga,nm); - logr = (j) ? logm1 : 0; - flint_printf("[sieve factor] logr = %wu\n",logr); /* try to factor both r[i] and u[i] */ iu = factor_until(&u[i], nv, prime, pmax, up, ue); - if (u[i] >= nv || v[u[i]] == NOT_FOUND) + if (u[i] >= nv || v[u[i]] == DLOG_NOT_FOUND) continue; - flint_printf("[sieve factor] u: found %d factors up to %wu\n",iu,u[i]); ir = factor_until(&r[i], nv, prime, pmax, rp, re); - if (r[i] >= nv || v[r[i]] == NOT_FOUND) + if (r[i] >= nv || v[r[i]] == DLOG_NOT_FOUND) continue; - flint_printf("[sieve factor] r: found %d factors up to %wu\n",ir,r[i]); /* log(u)+log(p)+log(m)=log(r) */ logm = nmod_add(logm, v[u[i]], order); + logr = (j) ? logm1 : 0; logr = nmod_add(logr, v[r[i]], order); for (i=0; i < ir; i++) logr = nmod_add(logr, (re[i] * v[rp[i]]) % order.n, order); - flint_printf("[sieve factor] logr = %wu\n",logr); for (i=0; i < iu; i++) logm = nmod_add(logm, (ue[i] * v[up[i]]) % order.n, order); - flint_printf("[sieve factor] logm = %wu\n",logm); - flint_printf("[sieve factor] log(%wu^%wu) = %wu * %wu = %wu [%wu]\n", - a, nm, nm, loga, logm, order.n); - flint_printf("[ on logs] %wu + log(%wu) = %d * %wu + %wu [%wu]\n", - logm,p,j,logm1, logr, order.n); - flint_printf("[ hence ] log(%wu) = %wu\n", p, nmod_sub(logr, logm, order)); return nmod_sub(logr, logm, order); } - return NOT_FOUND; + return DLOG_NOT_FOUND; } diff --git a/dlog/vec_set_not_found.c b/dlog/vec_set_not_found.c index 347cf50b..48a61cb3 100644 --- a/dlog/vec_set_not_found.c +++ b/dlog/vec_set_not_found.c @@ -38,6 +38,6 @@ dlog_vec_set_not_found(ulong *v, ulong nv, nmod_t mod) ulong p, k; p = fac.p[i]; for (k = p; k < nv; k += p) - v[k] = NOT_FOUND; + v[k] = DLOG_NOT_FOUND; } } diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index 77867e92..979de9e6 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -24,10 +24,83 @@ ******************************************************************************/ #include "dlog.h" +#include + +#define vbs 1 void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - dlog_vec_set_not_found(v, nv, mod); - dlog_vec_sieve_subgroup(v, nv, a, va, 1, mod, na, order); + ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; + ulong logcost, limcount; + ulong k, p, p1, pmax, logm1; + dlog_precomp_t pre; + n_primes_t iter; + ulong X, aX, vaX; + + dlog_vec_fill(v, nv, DLOG_NOT_FOUND); + v[1] = 0; + + logm1 = (na % 2) ? 0 : nmod_mul(na / 2, va, order); + + /* discrete log on first primes, then sieve */ + pmax = (nv < mod.n) ? nv : mod.n; + p1 = 50; /* FIXME: tune this limit! */ + dlog_precomp_n_init(pre, a, mod.n, na, p1); + /*flint_printf("## single log cost: %wu\n", pre->cost);*/ + logcost = pre->cost; + + if (logcost < 15) + { + /* p1 = pmax; */ + limcount = mod.n; + } + else + { + limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); + } + + /* find big power of gen */ + X = n_nextprime(na / 2 + 10, 0); + X = (na % 257) ? 257 % na : 1031 % na ; /* FIXME! */ + aX = nmod_pow_ui(a, X, mod); + vaX = nmod_mul(va, X % order.n, order); + + n_primes_init(iter); + while ((p = n_primes_next(iter)) < pmax) + { + double cost = log(mod.n)/log(p); + ulong m, vp; + if (mod.n % p == 0) + continue; /* won't be attained another time */ + cost = log(mod.n)/log(p); + cost = pow(cost,cost); + sievecount++; + /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ + /*if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ + if (logcost < cost || (vp = dlog_vec_pindex_factorgcd(v, nv, p, mod, aX, na, vaX, logm1, order, cost)) == DLOG_NOT_FOUND) + { + if (logcost < cost) + sievecount--; + else + missed++; + logcount++; + vp = nmod_mul(dlog_precomp(pre, p), va, order); + } + for (k = p, m = 1; k < nv; k += p, m++) + { + if (v[m] == DLOG_NOT_FOUND) + continue; + smooth++; + v[k] = nmod_add(v[m], vp, order); + } + } +#if vbs + if (missed) + flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", + smooth, limcount, mod.n, logcost, logcount, sievecount, missed); +#endif + n_primes_clear(iter); + for (k = mod.n + 1; k < nv; k++) + v[k] = v[k - mod.n]; } diff --git a/dlog/vec_sieve_add.c b/dlog/vec_sieve_add.c new file mode 100644 index 00000000..0b0e15f9 --- /dev/null +++ b/dlog/vec_sieve_add.c @@ -0,0 +1,40 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_vec_sieve_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + ulong * w, k; + /* store size */ + w = flint_malloc(nv * sizeof(ulong)); + dlog_vec_sieve(w, nv, a, va, mod, na, order); + /* write in v */ + for (k = 0; k < nv; k++) + if (v[k] != DLOG_NOT_FOUND) + v[k] = nmod_add(v[k], w[k], order); + flint_free(w); +} diff --git a/dlog/vec_sieve_subgroup.c b/dlog/vec_sieve_subgroup.c deleted file mode 100644 index 626e77d2..00000000 --- a/dlog/vec_sieve_subgroup.c +++ /dev/null @@ -1,115 +0,0 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2016 Pascal Molin - -******************************************************************************/ - -#include "dlog.h" -#include - -#define vbs 1 - -void -dlog_vec_sieve_subgroup(ulong *v, ulong nv, ulong a, ulong va, ulong M, nmod_t mod, ulong na, nmod_t order) -{ - ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; - ulong logcost, limcount; - ulong k, p, p1, pmax, logm1; - ulong * w; - dlog_precomp_t pre; - n_primes_t iter; - ulong X, aX, vaX; - - /* store size */ - w = flint_malloc( nv * sizeof(log_pair_t)); - for (k = 0; k < nv; k++) - w[k] = NOT_FOUND; - w[1] = 0; - logm1 = (na % 2) ? 0 : nmod_mul(na / 2, va, order); - - /* discrete log on first primes, then sieve */ - pmax = (nv < mod.n) ? nv : mod.n; - p1 = 50; /* FIXME: tune this limit! */ - dlog_precomp_n_init(pre, a, mod.n, na, p1); - /*flint_printf("## single log cost: %wu\n", pre->cost);*/ - logcost = pre->cost; - - if (logcost < 15) - { - /* p1 = pmax; */ - limcount = mod.n; - } - else - { - limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); - } - - /* find big power of gen */ - X = n_nextprime(na / 2 + 10, 0); - X = (na % 257) ? 257 % na : 1031 % na ; /* FIXME! */ - aX = nmod_pow_ui(a, X, mod); - vaX = nmod_mul(va, X % order.n, order); - - n_primes_init(iter); - while ((p = n_primes_next(iter)) < pmax) - { - double cost = log(mod.n)/log(p); - ulong m, wp; - if (v[p] == NOT_FOUND) - continue; /* won't be attained another time */ - cost = log(mod.n)/log(p); - cost = pow(cost,cost); - sievecount++; - /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ - /*if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ - if (logcost < cost || (wp = dlog_vec_pindex_factorgcd(w, nv, p, mod, aX, na, vaX, logm1, order, cost)) == NOT_FOUND) - { - if (logcost < cost) - sievecount--; - else - missed++; - logcount++; - wp = nmod_mul(dlog_precomp(pre, nmod_pow_ui(p, M, mod)), va, order); - } - for (k = p, m = 1; k < nv; k += p, m++) - { - if (w[m] == NOT_FOUND) - continue; - smooth++; - w[k] = nmod_add(w[m], wp, order); - flint_printf("set log(%wu)=log(%wu)+log(%wu)=%wu\n",k,m,p,w[k]); - } - } - for (k = mod.n + 1; k < nv; k++) - w[k] = w[k - mod.n]; - /* write in v */ - for (k = 0; k < nv; k++) - if (v[k] != NOT_FOUND) - v[k] = nmod_add(v[k], w[k], order); -#if vbs - if (missed) - flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", - smooth, limcount, mod.n, logcost, logcount, sievecount, missed); -#endif - n_primes_clear(iter); - flint_free(w); -} From 583cbd414749b087f73ee02fbacd361dedd76614 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 22 Mar 2016 11:29:21 +0100 Subject: [PATCH 019/139] huge refactor - split files, one for each function - use acb_dirichlet prefix everywhere - distinguish pairing / character value + fix bug on exponent --- acb_dirichlet.h | 54 ++++--- acb_dirichlet/acb_chi.c | 45 ++++++ acb_dirichlet/acb_pairing.c | 44 ++++++ acb_dirichlet/acb_pairing_conrey.c | 43 ++++++ acb_dirichlet/char.c | 142 +----------------- acb_dirichlet/char_clear.c | 31 ++++ acb_dirichlet/char_conrey.c | 42 ++++++ acb_dirichlet/char_first_primitive.c | 37 +++++ acb_dirichlet/char_init.c | 31 ++++ acb_dirichlet/char_next.c | 50 ++++++ acb_dirichlet/char_next_primitive.c | 66 ++++++++ acb_dirichlet/char_normalize.c | 47 ++++++ acb_dirichlet/char_one.c | 37 +++++ acb_dirichlet/char_print.c | 35 +++++ acb_dirichlet/charevalvec.c | 132 ---------------- acb_dirichlet/chi.c | 90 +++++------ acb_dirichlet/chi_vec_loop.c | 52 +++++++ acb_dirichlet/chi_vec_primeloop.c | 57 +++++++ acb_dirichlet/chi_vec_sieve.c | 56 +++++++ acb_dirichlet/conrey.c | 36 +++++ acb_dirichlet/conrey_exp.c | 37 +++++ acb_dirichlet/conrey_first_primitive.c | 40 +++++ acb_dirichlet/conrey_log.c | 110 +------------- acb_dirichlet/conrey_mul.c | 35 +++++ acb_dirichlet/conrey_next.c | 43 ++++++ acb_dirichlet/conrey_next_primitive.c | 59 ++++++++ acb_dirichlet/conrey_one.c | 34 +++++ acb_dirichlet/conrey_print.c | 36 +++++ acb_dirichlet/group_init.c | 1 + acb_dirichlet/l.c | 18 +-- acb_dirichlet/pairing.c | 48 ++++++ .../{chareval.c => pairing_conrey.c} | 34 ++--- acb_dirichlet/profile/p-conrey.c | 10 +- .../profile/{p-evalvec.c => p-vec.c} | 24 +-- acb_dirichlet/test/t-chi.c | 31 +++- acb_dirichlet/test/t-conrey.c | 16 +- acb_dirichlet/vec_set_null.c | 43 ++++++ 37 files changed, 1229 insertions(+), 517 deletions(-) create mode 100644 acb_dirichlet/acb_chi.c create mode 100644 acb_dirichlet/acb_pairing.c create mode 100644 acb_dirichlet/acb_pairing_conrey.c create mode 100644 acb_dirichlet/char_clear.c create mode 100644 acb_dirichlet/char_conrey.c create mode 100644 acb_dirichlet/char_first_primitive.c create mode 100644 acb_dirichlet/char_init.c create mode 100644 acb_dirichlet/char_next.c create mode 100644 acb_dirichlet/char_next_primitive.c create mode 100644 acb_dirichlet/char_normalize.c create mode 100644 acb_dirichlet/char_one.c create mode 100644 acb_dirichlet/char_print.c delete mode 100644 acb_dirichlet/charevalvec.c create mode 100644 acb_dirichlet/chi_vec_loop.c create mode 100644 acb_dirichlet/chi_vec_primeloop.c create mode 100644 acb_dirichlet/chi_vec_sieve.c create mode 100644 acb_dirichlet/conrey.c create mode 100644 acb_dirichlet/conrey_exp.c create mode 100644 acb_dirichlet/conrey_first_primitive.c create mode 100644 acb_dirichlet/conrey_mul.c create mode 100644 acb_dirichlet/conrey_next.c create mode 100644 acb_dirichlet/conrey_next_primitive.c create mode 100644 acb_dirichlet/conrey_one.c create mode 100644 acb_dirichlet/conrey_print.c create mode 100644 acb_dirichlet/pairing.c rename acb_dirichlet/{chareval.c => pairing_conrey.c} (61%) rename acb_dirichlet/profile/{p-evalvec.c => p-vec.c} (80%) create mode 100644 acb_dirichlet/vec_set_null.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index d274cfa2..993d240c 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -14,6 +14,7 @@ #define ACB_DIRICHLET_H #include "acb.h" +#include "dlog.h" #ifdef __cplusplus extern "C" { @@ -45,9 +46,9 @@ typedef struct ulong n; /* number */ ulong * log; /* s.t. prod generators[k]^log[k] = number */ } -acb_conrey_struct; +acb_dirichlet_conrey_struct; -typedef acb_conrey_struct acb_conrey_t[1]; +typedef acb_dirichlet_conrey_struct acb_dirichlet_conrey_t[1]; void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, const signed char * chi, int mod, int reciprocal, slong prec); @@ -55,30 +56,27 @@ void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); - void acb_dirichlet_group_clear(acb_dirichlet_group_t G); -void acb_conrey_init(acb_conrey_t x, const acb_dirichlet_group_t G); +void acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); +void acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x); +void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); -void acb_conrey_clear(acb_conrey_t x); +void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); -void acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G); +void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); +void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); -void acb_conrey_first_primitive(acb_conrey_t x, const acb_dirichlet_group_t G); +int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); +int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); -void acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m); +#define CHI_NULL UWORD_MAX -int acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G); +ulong acb_dirichlet_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); +ulong acb_dirichlet_pairing(const acb_dirichlet_group_t G, ulong m, ulong n); -int acb_conrey_next_primitive(acb_conrey_t x, const acb_dirichlet_group_t G); - -long n_dirichlet_chi_conrey(const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b); - -long n_dirichlet_chi(const acb_dirichlet_group_t G, ulong m, ulong n); - -void acb_dirichlet_chi_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b, slong prec); - -void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec); +void acb_dirichlet_acb_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec); +void acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec); /* introducing character type */ @@ -95,19 +93,25 @@ acb_dirichlet_char_struct; typedef acb_dirichlet_char_struct acb_dirichlet_char_t[1]; void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); - void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); +void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); +void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); +void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); +void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -long n_dirichlet_char_eval(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); +void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); +void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -void acb_dirichlet_char_eval(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); +ulong acb_dirichlet_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); +void acb_dirichlet_acb_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); -void n_dirichlet_char_vec(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); -void n_dirichlet_char_vec_loop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); -void n_dirichlet_char_vec_primeloop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); -void n_dirichlet_char_vec_logsieve(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); +void acb_dirichlet_vec_set_null(ulong *v, ulong nv, const acb_dirichlet_group_t G); +void acb_dirichlet_chi_vec_loop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +void acb_dirichlet_chi_vec_primeloop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +void acb_dirichlet_chi_vec_sieve(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +void acb_dirichlet_chi_vec(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); void acb_dirichlet_char_vec(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); diff --git a/acb_dirichlet/acb_chi.c b/acb_dirichlet/acb_chi.c new file mode 100644 index 00000000..82a6835c --- /dev/null +++ b/acb_dirichlet/acb_chi.c @@ -0,0 +1,45 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_acb_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) +{ + ulong expo; + expo = acb_dirichlet_chi(G, chi, n); + if (expo == CHI_NULL) + acb_zero(res); + else + { + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, 2 * expo , chi->order); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); + } +} diff --git a/acb_dirichlet/acb_pairing.c b/acb_dirichlet/acb_pairing.c new file mode 100644 index 00000000..aebabe54 --- /dev/null +++ b/acb_dirichlet/acb_pairing.c @@ -0,0 +1,44 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) +{ + ulong expo; + expo = acb_dirichlet_pairing(G, m, n); + if (expo == CHI_NULL) + acb_zero(res); + else + { + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, 2 * expo, G->expo); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); + } +} diff --git a/acb_dirichlet/acb_pairing_conrey.c b/acb_dirichlet/acb_pairing_conrey.c new file mode 100644 index 00000000..69e7134e --- /dev/null +++ b/acb_dirichlet/acb_pairing_conrey.c @@ -0,0 +1,43 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_acb_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec) +{ + ulong expo; + expo = acb_dirichlet_pairing_conrey(G, a, b); + if (expo == CHI_NULL) + acb_zero(res); + else + { + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, 2 * expo, G->expo); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); + } +} diff --git a/acb_dirichlet/char.c b/acb_dirichlet/char.c index 2183e7d7..f850acc6 100644 --- a/acb_dirichlet/char.c +++ b/acb_dirichlet/char.c @@ -19,153 +19,17 @@ =============================================================================*/ /****************************************************************************** - Copyright (C) 2015 Jonathan Bober - Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include "acb_dirichlet.h" -/* FIXME: multiplications mod G->q should be n_mulmod to avoid overflow */ - -void -acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - chi->expo = flint_malloc(G->num * sizeof(ulong)); -} - -void -acb_dirichlet_char_clear(acb_dirichlet_char_t chi) { - flint_free(chi->expo); -} - -static void -acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) -{ - ulong k, g; - g = G->expo; - for (k = 0; k < G->num; k++) - g = n_gcd(g, chi->expo[k]); - for (k = 0; k < G->num; k++) - chi->expo[k] = chi->expo[k] / g; - chi->order = G->expo / g; -} - -static void -acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) -{ - ulong k, g; - g = G->expo / chi->order; - for (k = 0; k < G->num; k++) - chi->expo[k] *= g; -} - -/* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd - * so that log = expo[k] */ -static void -acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_conrey_t x) -{ - ulong k; - chi->q = G->q; - chi->n = x->n; - - for (k = 0; k < G->num; k++) - chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; - - /* optional: divide by gcd to obtain true order */ - acb_dirichlet_char_normalize(chi, G); -} - void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) { - acb_conrey_t x; + acb_dirichlet_conrey_t x; x->log = chi->expo; - acb_conrey_log(x, G, n); + acb_dirichlet_conrey_log(x, G, n); acb_dirichlet_char_conrey(chi, G, x); } - -ulong -acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) -{ - ulong k; - - acb_dirichlet_char_denormalize(chi, G); - - /* update index */ - for (k=0; k < G->num ; k++) - { - /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ - chi->n = chi->n * G->generators[k] % G->q; - chi->expo[k] += G->PHI[k]; - if (chi->expo[k] < G->expo) - break; - chi->expo[k] = 0; - } - - acb_dirichlet_char_normalize(chi, G); - - /* return last index modified */ - return k; -} - -ulong -acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) -{ - ulong k; - - acb_dirichlet_char_denormalize(chi, G); - - /* update index */ - k = 0; - if (G->neven == 2) - { - /* chi->n = n_mulmod(chi->n, G->generators[0], G->q); */ - chi->n = chi->n * G->generators[0] % G->q; - if (++chi->expo[0] < G->expo) - return 0; - chi->expo[0] = 0; - k = 1; - } - for (; k < G->num ; k++) - { - /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ - chi->n = chi->n * G->generators[k] % G->q; - chi->expo[k] += G->PHI[k]; - if (chi->expo[k] % G->primes[k] == 0) - { - /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ - chi->n = chi->n * G->generators[k] % G->q; - chi->expo[k] += G->PHI[k]; - } - if (chi->expo[k] < G->expo) - break; - chi->expo[k] = G->PHI[k]; - } - - acb_dirichlet_char_normalize(chi, G); - - /* return last index modified */ - return k; -} - -void -acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) -{ - ulong k; - chi->q = G->q; - chi->n = 1; - for (k = 0; k < G->num; k++) - chi->expo[k] = 0; - chi->order = 1; -} - -void -acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) -{ - acb_conrey_t x; - chi->q = G->q; - x->log = chi->expo; - acb_conrey_first_primitive(x, G); - chi->n = x->n; - acb_dirichlet_char_normalize(chi, G); -} diff --git a/acb_dirichlet/char_clear.c b/acb_dirichlet/char_clear.c new file mode 100644 index 00000000..7ae309ca --- /dev/null +++ b/acb_dirichlet/char_clear.c @@ -0,0 +1,31 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_clear(acb_dirichlet_char_t chi) { + flint_free(chi->expo); +} diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c new file mode 100644 index 00000000..8414534f --- /dev/null +++ b/acb_dirichlet/char_conrey.c @@ -0,0 +1,42 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd + * so that log = expo[k] */ +void +acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +{ + ulong k; + chi->q = G->q; + chi->n = x->n; + + for (k = 0; k < G->num; k++) + chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; + + /* optional: divide by gcd to obtain true order */ + acb_dirichlet_char_normalize(chi, G); +} diff --git a/acb_dirichlet/char_first_primitive.c b/acb_dirichlet/char_first_primitive.c new file mode 100644 index 00000000..6180a154 --- /dev/null +++ b/acb_dirichlet/char_first_primitive.c @@ -0,0 +1,37 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + acb_dirichlet_conrey_t x; + chi->q = G->q; + x->log = chi->expo; + acb_dirichlet_conrey_first_primitive(x, G); + chi->n = x->n; + acb_dirichlet_char_normalize(chi, G); +} diff --git a/acb_dirichlet/char_init.c b/acb_dirichlet/char_init.c new file mode 100644 index 00000000..9c0d3108 --- /dev/null +++ b/acb_dirichlet/char_init.c @@ -0,0 +1,31 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { + chi->expo = flint_malloc(G->num * sizeof(ulong)); +} diff --git a/acb_dirichlet/char_next.c b/acb_dirichlet/char_next.c new file mode 100644 index 00000000..0ab819da --- /dev/null +++ b/acb_dirichlet/char_next.c @@ -0,0 +1,50 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k; + + acb_dirichlet_char_denormalize(chi, G); + + /* update index */ + for (k=0; k < G->num ; k++) + { + /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ + chi->n = chi->n * G->generators[k] % G->q; + chi->expo[k] += G->PHI[k]; + if (chi->expo[k] < G->expo) + break; + chi->expo[k] = 0; + } + + acb_dirichlet_char_normalize(chi, G); + + /* return last index modified */ + return k; +} diff --git a/acb_dirichlet/char_next_primitive.c b/acb_dirichlet/char_next_primitive.c new file mode 100644 index 00000000..eb3b5b9d --- /dev/null +++ b/acb_dirichlet/char_next_primitive.c @@ -0,0 +1,66 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k; + + acb_dirichlet_char_denormalize(chi, G); + + /* update index */ + k = 0; + if (G->neven == 2) + { + /* chi->n = n_mulmod(chi->n, G->generators[0], G->q); */ + chi->n = chi->n * G->generators[0] % G->q; + if (++chi->expo[0] < G->expo) + return 0; + chi->expo[0] = 0; + k = 1; + } + for (; k < G->num ; k++) + { + /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ + chi->n = chi->n * G->generators[k] % G->q; + chi->expo[k] += G->PHI[k]; + if (chi->expo[k] % G->primes[k] == 0) + { + /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ + chi->n = chi->n * G->generators[k] % G->q; + chi->expo[k] += G->PHI[k]; + } + if (chi->expo[k] < G->expo) + break; + chi->expo[k] = G->PHI[k]; + } + + acb_dirichlet_char_normalize(chi, G); + + /* return last index modified */ + return k; +} diff --git a/acb_dirichlet/char_normalize.c b/acb_dirichlet/char_normalize.c new file mode 100644 index 00000000..4c6cd4db --- /dev/null +++ b/acb_dirichlet/char_normalize.c @@ -0,0 +1,47 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k, g; + g = G->expo; + for (k = 0; k < G->num; k++) + g = n_gcd(g, chi->expo[k]); + for (k = 0; k < G->num; k++) + chi->expo[k] = chi->expo[k] / g; + chi->order = G->expo / g; +} + +void +acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k, g; + g = G->expo / chi->order; + for (k = 0; k < G->num; k++) + chi->expo[k] *= g; +} diff --git a/acb_dirichlet/char_one.c b/acb_dirichlet/char_one.c new file mode 100644 index 00000000..595972fb --- /dev/null +++ b/acb_dirichlet/char_one.c @@ -0,0 +1,37 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + ulong k; + chi->q = G->q; + chi->n = 1; + for (k = 0; k < G->num; k++) + chi->expo[k] = 0; + chi->order = 1; +} diff --git a/acb_dirichlet/char_print.c b/acb_dirichlet/char_print.c new file mode 100644 index 00000000..b70d48bd --- /dev/null +++ b/acb_dirichlet/char_print.c @@ -0,0 +1,35 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +{ + acb_dirichlet_conrey_t x; + x->log = chi->expo; + flint_printf("chi_%wu(%wu,.) of order %wu and index ", G->q, chi->n, chi->order); + acb_dirichlet_conrey_print(G, x); +} diff --git a/acb_dirichlet/charevalvec.c b/acb_dirichlet/charevalvec.c deleted file mode 100644 index b35ae191..00000000 --- a/acb_dirichlet/charevalvec.c +++ /dev/null @@ -1,132 +0,0 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2015 Jonathan Bober - Copyright (C) 2016 Fredrik Johansson - -******************************************************************************/ - -#include "acb_dirichlet.h" - -static void -set_non_invertible_values(long *v, const acb_dirichlet_group_t G, ulong nv) -{ - ulong k, l; - if (G->q_even > 1) - { - for (k = 2; k < nv; k += 2) - v[k] = -1; - } - for (l = 0; l < G->num; l++) - { - ulong p = G->primes[l]; - for (k = p; k < nv; k += p) - v[k] = -1; - } -} - -/* loop over whole group */ -void -n_dirichlet_char_vec_loop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) -{ - int j; - ulong t, k; - acb_conrey_t x; - acb_conrey_init(x, G); - acb_conrey_one(x, G); - t = v[1] = 0; - while ( (j = acb_conrey_next(x, G)) < G->num ) - { - /* exponents were modified up to j */ - for (k = 0; k < j; k++) - t = (t + chi->expo[k] * x->log[k]) % chi->order; - if (x->n < nv) - v[x->n] = t; - } - /* fix result outside primes */ - set_non_invertible_values(v, G, nv); - /* copy outside modulus */ - for (k = G->q + 1; k < nv ; k++ ) - v[k] = v[k - G->q]; - acb_conrey_clear(x); -} - -/* loop over primary components */ -void -n_dirichlet_char_vec_primeloop(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) -{ - ulong k, l; - - for(k = 1; k < nv; ++k) - v[k] = 0; - - for(l = 1; l < G->num; ++l) - { - long p, pe, g, x, vp, xp; - long j, vj; - p = G->primes[l]; - pe = G->primepowers[l]; - g = G->generators[l] % pe; - vj = vp = chi->expo[l]; - /* for each x = g^j mod p^e, - * set a[x] += j*vp - * and use periodicity */ - for(j = 1, x = g; x > 1; j++) - { - for(xp = x; xp < nv; xp+=pe) - v[xp] = (v[xp] + vj) % chi->order; - x = (x*g) % pe; - vj = (vj + vp) % chi->order; - } - } - set_non_invertible_values(v, G, nv); -} - - -/* eratosthene sieve on primes */ -void -n_dirichlet_char_vec_logsieve(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) -{ - ulong k, p, pmax; - n_primes_t iter; - - n_primes_init(iter); - - pmax = (nv < G->q) ? nv : G->q; - v[1] = 0; - while ((p = n_primes_next(iter)) < pmax) - { - if (G->q % p == 0) - { - for (k = p; k < nv; k += p) - v[k] = -1; - } - else - { - long chip; - chip = n_dirichlet_char_eval(G, chi, p); - for (k = p; k < nv; k += p) - if (v[k] != -1) - v[k] = (v[k] + chip) % chi->order; - } - } - n_primes_clear(iter); -} diff --git a/acb_dirichlet/chi.c b/acb_dirichlet/chi.c index fb4223d6..72a65ab5 100644 --- a/acb_dirichlet/chi.c +++ b/acb_dirichlet/chi.c @@ -1,63 +1,45 @@ -/* +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ +******************************************************************************/ #include "acb_dirichlet.h" -/* todo: modular arithmetic */ - -long -n_dirichlet_chi_conrey(const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b) -{ - ulong x, k; - x = 0; - for (k = 0; k < G->num; k++) - x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; - return x; -} - -long -n_dirichlet_chi(const acb_dirichlet_group_t G, ulong m, ulong n) -{ - ulong x; - acb_conrey_t a, b; - acb_conrey_init(a, G); - acb_conrey_init(b, G); - - acb_conrey_log(a, G, m); - acb_conrey_log(b, G, n); - x = n_dirichlet_chi_conrey(G, a, b); - - acb_conrey_clear(a); - acb_conrey_clear(b); - - return x; -} - void -acb_dirichlet_chi_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b, slong prec) +acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) { - fmpq_t t; - fmpq_init(t); - fmpq_set_si(t, n_dirichlet_chi_conrey(G, a, b), G->expo); - arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); - fmpq_clear(t); -} - -void -acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) -{ - fmpq_t t; - fmpq_init(t); - fmpq_set_si(t, n_dirichlet_chi(G, m, n), G->expo); - arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); - fmpq_clear(t); + ulong expo; + expo = acb_dirichlet_ui_chi(G, chi, n); + if (expo == ACB_DIRICHLET_CHI_NULL) + acb_zero(res); + else + { + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, 2 * expo , chi->order.n); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); + } } diff --git a/acb_dirichlet/chi_vec_loop.c b/acb_dirichlet/chi_vec_loop.c new file mode 100644 index 00000000..40d1f950 --- /dev/null +++ b/acb_dirichlet/chi_vec_loop.c @@ -0,0 +1,52 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* loop over whole group */ +void +acb_dirichlet_chi_vec_loop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +{ + int j; + ulong t, k; + acb_dirichlet_conrey_t x; + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_conrey_one(x, G); + t = v[1] = 0; + while ( (j = acb_dirichlet_conrey_next(x, G)) < G->num ) + { + /* exponents were modified up to j */ + for (k = 0; k < j; k++) + t = (t + chi->expo[k] * x->log[k]) % chi->order; + if (x->n < nv) + v[x->n] = t; + } + /* fix result outside primes */ + acb_dirichlet_vec_set_null(v, nv, G); + /* copy outside modulus */ + for (k = G->q + 1; k < nv ; k++ ) + v[k] = v[k - G->q]; + acb_dirichlet_conrey_clear(x); +} diff --git a/acb_dirichlet/chi_vec_primeloop.c b/acb_dirichlet/chi_vec_primeloop.c new file mode 100644 index 00000000..6f0a1928 --- /dev/null +++ b/acb_dirichlet/chi_vec_primeloop.c @@ -0,0 +1,57 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* loop over primary components */ +void +acb_dirichlet_chi_vec_primeloop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +{ + ulong k, l; + + for(k = 1; k < nv; ++k) + v[k] = 0; + + for(l = 1; l < G->num; ++l) + { + long p, pe, g, x, vp, xp; + long j, vj; + p = G->primes[l]; + pe = G->primepowers[l]; + g = G->generators[l] % pe; + vj = vp = chi->expo[l]; + /* for each x = g^j mod p^e, + * set a[x] += j*vp + * and use periodicity */ + for(j = 1, x = g; x > 1; j++) + { + for(xp = x; xp < nv; xp+=pe) + v[xp] = (v[xp] + vj) % chi->order; + x = (x*g) % pe; + vj = (vj + vp) % chi->order; + } + } + acb_dirichlet_vec_set_null(v, nv, G); +} diff --git a/acb_dirichlet/chi_vec_sieve.c b/acb_dirichlet/chi_vec_sieve.c new file mode 100644 index 00000000..19ca8a5b --- /dev/null +++ b/acb_dirichlet/chi_vec_sieve.c @@ -0,0 +1,56 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* sieve on primes */ +void +acb_dirichlet_chi_vec_sieve(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +{ + ulong k, p, pmax; + n_primes_t iter; + + n_primes_init(iter); + + pmax = (nv < G->q) ? nv : G->q; + v[1] = 0; + while ((p = n_primes_next(iter)) < pmax) + { + if (G->q % p == 0) + { + for (k = p; k < nv; k += p) + v[k] = CHI_NULL; + } + else + { + long chip; + chip = acb_dirichlet_chi(G, chi, p); + for (k = p; k < nv; k += p) + if (v[k] != -1) + v[k] = (v[k] + chip) % chi->order; + } + } + n_primes_clear(iter); +} diff --git a/acb_dirichlet/conrey.c b/acb_dirichlet/conrey.c new file mode 100644 index 00000000..c98acf39 --- /dev/null +++ b/acb_dirichlet/conrey.c @@ -0,0 +1,36 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { + x->log = flint_malloc(G->num * sizeof(ulong)); +} + +void +acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x) { + flint_free(x->log); +} diff --git a/acb_dirichlet/conrey_exp.c b/acb_dirichlet/conrey_exp.c new file mode 100644 index 00000000..3dd6c7b1 --- /dev/null +++ b/acb_dirichlet/conrey_exp.c @@ -0,0 +1,37 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +{ + ulong k, n = 1; + for (k = G->neven; k < G->num; k++) + /* n = n_mulmod(n, n_powmod(G->generators[k], x->log[k], G->q), G->q); */ + n = n * n_powmod(G->generators[k], x->log[k], G->q) % G->q; + x->n = n; + return n; +} diff --git a/acb_dirichlet/conrey_first_primitive.c b/acb_dirichlet/conrey_first_primitive.c new file mode 100644 index 00000000..488a6186 --- /dev/null +++ b/acb_dirichlet/conrey_first_primitive.c @@ -0,0 +1,40 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { + ulong k; + if (G->q % 4 == 2) + { + flint_printf("Exception (acb_dirichlet_conrey_first_primitive). no primitive element mod %wu.\n",G->q); + abort(); + } + for (k = 0; k < G->num ; k++) + x->log[k] = 1; + if (G->neven == 2) + x->log[0] = 0; +} diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index 07796aa8..bc41fb02 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -21,28 +21,16 @@ Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include "acb_dirichlet.h" -/* todo: modular arithmetic - discrete log can be computed along exponents or using p-adic log -*/ - -void -acb_conrey_init(acb_conrey_t x, const acb_dirichlet_group_t G) { - x->log = flint_malloc(G->num * sizeof(ulong)); -} - -void -acb_conrey_clear(acb_conrey_t x) { - flint_free(x->log); -} - /* TODO: use precomputations in G if present */ +/* assume m is invertible */ void -acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m) +acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) { ulong k, pk, gk; /* even part */ @@ -65,95 +53,3 @@ acb_conrey_log(acb_conrey_t x, const acb_dirichlet_group_t G, ulong m) /* keep value m */ x->n = m; } - -ulong -acb_conrey_exp(acb_conrey_t x, const acb_dirichlet_group_t G) -{ - ulong k, n = 1; - for (k = G->neven; k < G->num; k++) - /* n = n_mulmod(n, n_powmod(G->generators[k], x->log[k], G->q), G->q); */ - n = n * n_powmod(G->generators[k], x->log[k], G->q) % G->q; - x->n = n; - return n; -} - -void -acb_conrey_one(acb_conrey_t x, const acb_dirichlet_group_t G) { - ulong k; - for (k = 0; k < G->num ; k++) - x->log[k] = 0; - x->n = 1; -} - -void -acb_conrey_first_primitive(acb_conrey_t x, const acb_dirichlet_group_t G) { - ulong k; - if (G->q % 4 == 2) - { - flint_printf("Exception (acb_conrey_first_primitive). no primitive element mod %wu.\n",G->q); - abort(); - } - for (k = 0; k < G->num ; k++) - x->log[k] = 1; - if (G->neven == 2) - x->log[0] = 0; -} - -int -acb_conrey_next(acb_conrey_t x, const acb_dirichlet_group_t G) -{ - /* update index */ - ulong k; - for (k=0; k < G->num ; k++) - { - /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ - x->n = x->n * G->generators[k] % G->q; - if (++x->log[k] < G->phi[k]) - break; - x->log[k] = 0; - } - /* return last index modified */ - return k; -} - -int -acb_conrey_next_primitive(acb_conrey_t x, const acb_dirichlet_group_t G) -{ - /* update index avoiding multiples of p except for first component - if 8|q */ - ulong k = 0; - if (G->neven == 2) - { - /* x->n = n_mulmod(x->n, G->generators[0], G->q); */ - x->n = x->n * G->generators[0] % G->q; - if (++x->log[0] == 1) - return 0; - x->log[0] = 0; - k = 1; - } - for (; k < G->num ; k++) - { - /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ - x->n = x->n * G->generators[k] % G->q; - if (++x->log[k] % G->primes[k] == 0) - { - /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ - x->n = x->n * G->generators[k] % G->q; - ++x->log[k]; - } - if (x->log[k] < G->phi[k]) - break; - x->log[k] = 1; - } - /* return last index modified */ - return k; -} - -void -acb_conrey_mul(acb_conrey_t c, const acb_dirichlet_group_t G, const acb_conrey_t a, const acb_conrey_t b) -{ - ulong k; - for (k = 0; k < G->num ; k++) - c->log[k] = a->log[k] + b->log[k] % G->phi[k]; - c->n = a->n * b->n % G->q; -} diff --git a/acb_dirichlet/conrey_mul.c b/acb_dirichlet/conrey_mul.c new file mode 100644 index 00000000..c0c7d95c --- /dev/null +++ b/acb_dirichlet/conrey_mul.c @@ -0,0 +1,35 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) +{ + ulong k; + for (k = 0; k < G->num ; k++) + c->log[k] = a->log[k] + b->log[k] % G->phi[k]; + c->n = a->n * b->n % G->q; +} diff --git a/acb_dirichlet/conrey_next.c b/acb_dirichlet/conrey_next.c new file mode 100644 index 00000000..ab5b6ecf --- /dev/null +++ b/acb_dirichlet/conrey_next.c @@ -0,0 +1,43 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +{ + /* update index */ + ulong k; + for (k=0; k < G->num ; k++) + { + /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ + x->n = x->n * G->generators[k] % G->q; + if (++x->log[k] < G->phi[k]) + break; + x->log[k] = 0; + } + /* return last index modified */ + return k; +} diff --git a/acb_dirichlet/conrey_next_primitive.c b/acb_dirichlet/conrey_next_primitive.c new file mode 100644 index 00000000..acae8a76 --- /dev/null +++ b/acb_dirichlet/conrey_next_primitive.c @@ -0,0 +1,59 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +{ + /* update index avoiding multiples of p except for first component + if 8|q */ + ulong k = 0; + if (G->neven == 2) + { + /* x->n = n_mulmod(x->n, G->generators[0], G->q); */ + x->n = x->n * G->generators[0] % G->q; + if (++x->log[0] == 1) + return 0; + x->log[0] = 0; + k = 1; + } + for (; k < G->num ; k++) + { + /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ + x->n = x->n * G->generators[k] % G->q; + if (++x->log[k] % G->primes[k] == 0) + { + /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ + x->n = x->n * G->generators[k] % G->q; + ++x->log[k]; + } + if (x->log[k] < G->phi[k]) + break; + x->log[k] = 1; + } + /* return last index modified */ + return k; +} diff --git a/acb_dirichlet/conrey_one.c b/acb_dirichlet/conrey_one.c new file mode 100644 index 00000000..36e23b58 --- /dev/null +++ b/acb_dirichlet/conrey_one.c @@ -0,0 +1,34 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { + ulong k; + for (k = 0; k < G->num ; k++) + x->log[k] = 0; + x->n = 1; +} diff --git a/acb_dirichlet/conrey_print.c b/acb_dirichlet/conrey_print.c new file mode 100644 index 00000000..266bbf23 --- /dev/null +++ b/acb_dirichlet/conrey_print.c @@ -0,0 +1,36 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +{ + int k; + flint_printf("[%wu",x->log[0]); + for (k = 1; k < G->num; k++) + flint_printf(", %wu",x->log[k]); + flint_printf("]\n"); +} diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index 3312d44b..eba5b84a 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -1,6 +1,7 @@ /* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin This file is part of Arb. diff --git a/acb_dirichlet/l.c b/acb_dirichlet/l.c index d86ab4b2..2c0112e6 100644 --- a/acb_dirichlet/l.c +++ b/acb_dirichlet/l.c @@ -16,29 +16,29 @@ 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; - acb_conrey_t cm, cn; + acb_dirichlet_conrey_t cm, cn; acb_init(chi); - acb_conrey_init(cm, G); - acb_conrey_init(cn, G); + acb_dirichlet_conrey_init(cm, G); + acb_dirichlet_conrey_init(cn, G); acb_init(t); acb_init(u); acb_init(a); - acb_conrey_log(cm, G, m); - acb_conrey_one(cn, G); + acb_dirichlet_conrey_log(cm, G, m); + acb_dirichlet_conrey_one(cn, G); acb_zero(t); while (1) { /* todo: use n_dirichlet_chi and precomputed roots instead */ - acb_dirichlet_chi_conrey(chi, G, cm, cn, prec); + acb_dirichlet_acb_pairing_conrey(chi, G, cm, cn, prec); acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); acb_hurwitz_zeta(u, s, a, prec); acb_addmul(t, chi, u, prec); - if (acb_conrey_next(cn, G) == G->num) + if (acb_dirichlet_conrey_next(cn, G) == G->num) break; } @@ -47,8 +47,8 @@ acb_dirichlet_l(acb_t res, const acb_t s, acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); - acb_conrey_clear(cm); - acb_conrey_clear(cn); + acb_dirichlet_conrey_clear(cm); + acb_dirichlet_conrey_clear(cn); acb_clear(chi); acb_clear(t); diff --git a/acb_dirichlet/pairing.c b/acb_dirichlet/pairing.c new file mode 100644 index 00000000..0ff9861c --- /dev/null +++ b/acb_dirichlet/pairing.c @@ -0,0 +1,48 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) +{ + ulong x; + acb_dirichlet_conrey_t a, b; + + if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) + return CHI_NULL; + + acb_dirichlet_conrey_init(a, G); + acb_dirichlet_conrey_init(b, G); + acb_dirichlet_conrey_log(a, G, m); + acb_dirichlet_conrey_log(b, G, n); + + x = acb_dirichlet_pairing_conrey(G, a, b); + + acb_dirichlet_conrey_clear(a); + acb_dirichlet_conrey_clear(b); + + return x; +} diff --git a/acb_dirichlet/chareval.c b/acb_dirichlet/pairing_conrey.c similarity index 61% rename from acb_dirichlet/chareval.c rename to acb_dirichlet/pairing_conrey.c index bafdbbdc..4c7b5753 100644 --- a/acb_dirichlet/chareval.c +++ b/acb_dirichlet/pairing_conrey.c @@ -21,36 +21,20 @@ Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include "acb_dirichlet.h" -long -n_dirichlet_char_eval(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) +/* todo: modular arithmetic */ + +ulong +acb_dirichlet_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) { - ulong v = 0, k; - acb_conrey_t x; - acb_conrey_init(x, G); - acb_conrey_log(x, G, n); + ulong x, k; + x = 0; for (k = 0; k < G->num; k++) - v = (v + chi->expo[k] * x->log[k]) % chi->order; - acb_conrey_clear(x); - return v; -} - -void -fmpq_dirichlet_char_eval(fmpq_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) -{ - fmpq_set_si(res, n_dirichlet_char_eval(G, chi, n), chi->order); -} - -void -acb_dirichlet_char_eval(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) -{ - fmpq_t t; - fmpq_init(t); - fmpq_dirichlet_char_eval(t, G, chi, n); - arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); - fmpq_clear(t); + x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; + return x; } diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c index 11d008c1..8fc997d7 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/acb_dirichlet/profile/p-conrey.c @@ -51,16 +51,16 @@ int main() for (n = 0, q = 2; q <= maxq; q++) { acb_dirichlet_group_t G; - acb_conrey_t x; + acb_dirichlet_conrey_t x; acb_dirichlet_group_init(G, q); - acb_conrey_init(x, G); + acb_dirichlet_conrey_init(x, G); - acb_conrey_one(x, G); + acb_dirichlet_conrey_one(x, G); n++; - for (; acb_conrey_next(x, G) < G->num; n++); - acb_conrey_clear(x); + for (; acb_dirichlet_conrey_next(x, G) < G->num; n++); + acb_dirichlet_conrey_clear(x); acb_dirichlet_group_clear(G); } TIMEIT_ONCE_STOP diff --git a/acb_dirichlet/profile/p-evalvec.c b/acb_dirichlet/profile/p-vec.c similarity index 80% rename from acb_dirichlet/profile/p-evalvec.c rename to acb_dirichlet/profile/p-vec.c index f819f9a5..3dd8ce46 100644 --- a/acb_dirichlet/profile/p-evalvec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -25,16 +25,16 @@ #include "acb_dirichlet.h" #include "profiler.h" -typedef void (*dir_f) (long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv); +typedef void (*dir_f) (ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); void -dir_empty(long *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong nv) +dir_empty(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) { return; } void -vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, long * v, ulong nv) +vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ulong nv) { ulong q; TIMEIT_ONCE_START @@ -49,7 +49,7 @@ vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, long * v, ulo for (r = 0; r < nr; r++) { acb_dirichlet_char(chi, G, rand[r] % q); - dir(v, G, chi, nv); + dir(v, nv, G, chi); } acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); @@ -65,14 +65,14 @@ int main() int i, ni = 5; ulong q[5] = { 2, 1000, 3000, 10000, 100000 }; ulong qq[5] = { 500, 2000, 5000, 12000, 100500 }; - long * v; + ulong * v; flint_rand_t state; nr = 20; flint_randinit(state); rand = flint_malloc(nr * sizeof(ulong)); - v = flint_malloc(nv * sizeof(long)); + v = flint_malloc(nv * sizeof(ulong)); for (r = 0; r < nr; r++) rand[r] = n_randprime(state, 42, 0); @@ -92,15 +92,21 @@ int main() flint_printf("big loop................ "); fflush(stdout); - vecloop(n_dirichlet_char_vec_loop, minq, maxq, rand, nr, v, nv); + vecloop(acb_dirichlet_chi_vec_loop, minq, maxq, rand, nr, v, nv); flint_printf("med loop................ "); fflush(stdout); - vecloop(n_dirichlet_char_vec_primeloop, minq, maxq, rand, nr, v, nv); + vecloop(acb_dirichlet_chi_vec_primeloop, minq, maxq, rand, nr, v, nv); flint_printf("small loop................ "); fflush(stdout); - vecloop(n_dirichlet_char_vec_logsieve, minq, maxq, rand, nr, v, nv); + vecloop(acb_dirichlet_chi_vec_sieve, minq, maxq, rand, nr, v, nv); + + /* + flint_printf("generic........ "); + fflush(stdout); + vecloop(acb_dirichlet_chi_vec, minq, maxq, rand, nr, v, nv); + */ } flint_free(v); diff --git a/acb_dirichlet/test/t-chi.c b/acb_dirichlet/test/t-chi.c index 13d20f94..cac365a3 100644 --- a/acb_dirichlet/test/t-chi.c +++ b/acb_dirichlet/test/t-chi.c @@ -24,12 +24,14 @@ int main() { acb_t zn1, zn2, zn1n2, zn1zn2; acb_dirichlet_group_t G; + acb_dirichlet_char_t chi; ulong q, m, n1, n2, iter2; int res; q = 1 + n_randint(state, 1000); acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi, G); acb_init(zn1); acb_init(zn2); acb_init(zn1n2); @@ -42,12 +44,33 @@ int main() m = 1 + n_randint(state, q); } while (n_gcd(q, m) != 1); + acb_dirichlet_char(chi, G, m); + n1 = n_randint(state, 1000); n2 = n_randint(state, 1000); - acb_dirichlet_chi(zn1, G, m, n1, 53); - acb_dirichlet_chi(zn2, G, m, n2, 53); - acb_dirichlet_chi(zn1n2, G, m, n1 * n2, 53); + acb_dirichlet_acb_chi(zn1, G, chi, n1, 53); + acb_dirichlet_acb_pairing(zn2, G, m, n1, 53); + if (!acb_overlaps(zn1, zn2)) + { + acb_dirichlet_conrey_t x; + 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"); + acb_dirichlet_char_print(G, chi); + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_conrey_log(x, G, m); + flint_printf("log(m) = "); acb_dirichlet_conrey_print(G, x); + acb_dirichlet_conrey_log(x, G, n1); + flint_printf("log(n1) = "); acb_dirichlet_conrey_print(G, x); + abort(); + } + + acb_dirichlet_acb_pairing(zn2, G, m, n2, 53); + acb_dirichlet_acb_pairing(zn1n2, G, m, n1 * n2, 53); acb_mul(zn1zn2, zn1, zn2, 53); if (!acb_overlaps(zn1n2, zn1zn2)) @@ -74,7 +97,7 @@ int main() { if (n_gcd(q, m) == 1) { - acb_dirichlet_chi(zn2, G, m, n1, 53); + acb_dirichlet_acb_pairing(zn2, G, m, n1, 53); acb_add(zn1, zn1, zn2, 53); } } diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index df291d83..c1c58d83 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -30,14 +30,14 @@ int main() slong iter; flint_rand_t state; - flint_printf("chi...."); + flint_printf("conrey...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000; iter++) { acb_dirichlet_group_t G; - acb_conrey_t x; + acb_dirichlet_conrey_t x; ulong q, n, k, sum; long ref; /*int * bits;*/ @@ -46,14 +46,14 @@ int main() acb_dirichlet_group_init(G, q); - acb_conrey_init(x, G); + acb_dirichlet_conrey_init(x, G); /* check group size and elements */ - acb_conrey_one(x, G); + acb_dirichlet_conrey_one(x, G); sum = 1; #if 1 - for (n = 1; acb_conrey_next(x, G) < G->num; n++) + for (n = 1; acb_dirichlet_conrey_next(x, G) < G->num; n++) sum += x->n * x->n; #else /* iteration much faster than gcd below */ @@ -113,8 +113,8 @@ int main() } } - acb_conrey_first_primitive(x, G); - for (n = 1; (k=acb_conrey_next_primitive(x, G)) < G->num; n++); + acb_dirichlet_conrey_first_primitive(x, G); + for (n = 1; (k=acb_dirichlet_conrey_next_primitive(x, G)) < G->num; n++); if (n != ref) { @@ -125,7 +125,7 @@ int main() abort(); } - acb_conrey_clear(x); + acb_dirichlet_conrey_clear(x); acb_dirichlet_group_clear(G); } diff --git a/acb_dirichlet/vec_set_null.c b/acb_dirichlet/vec_set_null.c new file mode 100644 index 00000000..eded5823 --- /dev/null +++ b/acb_dirichlet/vec_set_null.c @@ -0,0 +1,43 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_vec_set_null(ulong *v, ulong nv, const acb_dirichlet_group_t G) +{ + ulong k, l; + if (G->q_even > 1) + { + for (k = 2; k < nv; k += 2) + v[k] = -1; + } + for (l = 0; l < G->num; l++) + { + ulong p = G->primes[l]; + for (k = p; k < nv; k += p) + v[k] = CHI_NULL; + } +} From f53fb1e76198e7cdac5a00ada820f78457917394 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 22 Mar 2016 11:32:16 +0100 Subject: [PATCH 020/139] remove deprecated dlog_vec_crt --- dlog/profile/p-vec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlog/profile/p-vec.c b/dlog/profile/p-vec.c index cdb9fc58..401323c6 100644 --- a/dlog/profile/p-vec.c +++ b/dlog/profile/p-vec.c @@ -55,8 +55,8 @@ int main() ulong * a; int l, nf = 5; - vec_f func[5] = { f_empty, dlog_vec_loop, dlog_vec_eratos, dlog_vec_sieve, dlog_vec_crt }; - char * n[5] = { "empty", "loop", "eratos", "sieve", "crt" }; + vec_f func[5] = { f_empty, dlog_vec_loop, dlog_vec_eratos, dlog_vec_sieve, dlog_vec }; + char * n[5] = { "empty", "loop", "eratos", "sieve", "default" }; flint_rand_t state; nmod_t order; From 986f7fab2faf0e3e75ab50370f7239eaf78bebb8 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 23 Mar 2016 12:53:08 +0100 Subject: [PATCH 021/139] fix bug on char_next + add log precomputations --- acb_dirichlet.h | 9 ++ acb_dirichlet/arb_quadratic_powers.c | 51 +++++++++ acb_dirichlet/char_conductor.c | 56 ++++++++++ acb_dirichlet/char_is_odd.c | 40 +++++++ acb_dirichlet/char_next.c | 3 +- acb_dirichlet/char_next_primitive.c | 9 +- acb_dirichlet/chi_vec_loop.c | 44 ++++---- acb_dirichlet/conrey_exp.c | 3 +- acb_dirichlet/conrey_first_primitive.c | 20 ++-- acb_dirichlet/conrey_log.c | 31 ++++-- acb_dirichlet/conrey_mul.c | 4 +- acb_dirichlet/conrey_next.c | 24 ++--- acb_dirichlet/conrey_next_primitive.c | 9 +- acb_dirichlet/conrey_one.c | 5 +- acb_dirichlet/conrey_print.c | 5 +- acb_dirichlet/group_dlog_precompute.c | 42 ++++++++ acb_dirichlet/group_init.c | 3 + acb_dirichlet/test/t-thetanull.c | 143 +++++++++++++++++++++++++ acb_dirichlet/zeta.c | 36 +++++++ dlog.h | 1 + 20 files changed, 468 insertions(+), 70 deletions(-) create mode 100644 acb_dirichlet/arb_quadratic_powers.c create mode 100644 acb_dirichlet/char_conductor.c create mode 100644 acb_dirichlet/char_is_odd.c create mode 100644 acb_dirichlet/group_dlog_precompute.c create mode 100644 acb_dirichlet/test/t-thetanull.c create mode 100644 acb_dirichlet/zeta.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 993d240c..3279cd39 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -23,6 +23,7 @@ extern "C" { typedef struct { ulong q; /* modulus */ + nmod_t mod; /* modulus with precomputed inverse */ ulong q_even; /* even part of modulus */ ulong q_odd; /* odd part of modulus */ ulong phi_q; /* phi(q) = group size */ @@ -35,6 +36,7 @@ typedef struct ulong * generators; /* generator for each prime p[k] lifted mod q */ ulong * phi; /* phi(k) = phi(p[k]^e[k]) */ ulong * PHI; /* PHI(k) = expo / phi(k) */ + dlog_precomp_t * dlog; /* precomputed data for discrete log mod p^e */ } acb_dirichlet_group_struct; @@ -101,6 +103,9 @@ void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_gro void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); +ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +int acb_dirichlet_char_is_odd(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); + void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); @@ -115,6 +120,10 @@ void acb_dirichlet_chi_vec(ulong *v, ulong nv, const acb_dirichlet_group_t G, co void acb_dirichlet_char_vec(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); + +void acb_dirichlet_zeta(acb_t res, ulong order, slong prec); +void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); + #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/arb_quadratic_powers.c b/acb_dirichlet/arb_quadratic_powers.c new file mode 100644 index 00000000..9e2f1bee --- /dev/null +++ b/acb_dirichlet/arb_quadratic_powers.c @@ -0,0 +1,51 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec) +{ + slong i; + arb_t dx, x2; + arb_init(dx); + arb_init(x2); + arb_set(dx, x); + arb_mul(x2, x, x, prec); + for (i = 0; i < nv; i++) + { + if (i == 0) + arb_one(v + i); + else if (i == 1) + arb_set_round(v + i, x, prec); + else + { + arb_mul(dx, dx, x2, prec); + arb_mul(v + i, v + i - 1, dx, prec); + } + } + arb_clear(dx); + arb_clear(x2); +} diff --git a/acb_dirichlet/char_conductor.c b/acb_dirichlet/char_conductor.c new file mode 100644 index 00000000..62e96f0a --- /dev/null +++ b/acb_dirichlet/char_conductor.c @@ -0,0 +1,56 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +{ + int k, f; + ulong cond = 1; + if (G->neven >= 1 && chi->expo[0] == 1) + cond = 4; + if (G->neven == 2 && chi->expo[1]) + { + ulong l2 = chi->expo[1]; + f = n_remove(&l2, 2); + cond = G->primepowers[1] >> f; + } + for (k = G->neven; k < G->neven; k++) + { + if (chi->expo[k]) + { + ulong p, lp; + p = G->primes[k]; + lp = chi->expo[k]; + f = n_remove(&lp, p); + if (f) + cond *= n_pow(p, G->exponents[k] - f); + else + cond *= G->primepowers[k]; + } + } + return cond; +} diff --git a/acb_dirichlet/char_is_odd.c b/acb_dirichlet/char_is_odd.c new file mode 100644 index 00000000..cb5d0502 --- /dev/null +++ b/acb_dirichlet/char_is_odd.c @@ -0,0 +1,40 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_char_is_odd(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +{ + slong k, odd = 0; + for (k = 0; k < G->num; k++) + { + if (k == 1 && G->neven == 2) + continue; + if (chi->expo[k] % 2 == 1) + odd = 1 - odd; + } + return odd; +} diff --git a/acb_dirichlet/char_next.c b/acb_dirichlet/char_next.c index 0ab819da..5b7efb16 100644 --- a/acb_dirichlet/char_next.c +++ b/acb_dirichlet/char_next.c @@ -35,8 +35,7 @@ acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) /* update index */ for (k=0; k < G->num ; k++) { - /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ - chi->n = chi->n * G->generators[k] % G->q; + chi->n = nmod_mul(chi->n, G->generators[k], G->mod); chi->expo[k] += G->PHI[k]; if (chi->expo[k] < G->expo) break; diff --git a/acb_dirichlet/char_next_primitive.c b/acb_dirichlet/char_next_primitive.c index eb3b5b9d..cd3bda76 100644 --- a/acb_dirichlet/char_next_primitive.c +++ b/acb_dirichlet/char_next_primitive.c @@ -36,8 +36,7 @@ acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_ k = 0; if (G->neven == 2) { - /* chi->n = n_mulmod(chi->n, G->generators[0], G->q); */ - chi->n = chi->n * G->generators[0] % G->q; + chi->n = nmod_mul(chi->n, G->generators[0], G->mod); if (++chi->expo[0] < G->expo) return 0; chi->expo[0] = 0; @@ -45,13 +44,11 @@ acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_ } for (; k < G->num ; k++) { - /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ - chi->n = chi->n * G->generators[k] % G->q; + chi->n = nmod_mul(chi->n, G->generators[k], G->mod); chi->expo[k] += G->PHI[k]; if (chi->expo[k] % G->primes[k] == 0) { - /* chi->n = n_mulmod(chi->n, G->generators[k], G->q); */ - chi->n = chi->n * G->generators[k] % G->q; + chi->n = nmod_mul(chi->n, G->generators[k], G->mod); chi->expo[k] += G->PHI[k]; } if (chi->expo[k] < G->expo) diff --git a/acb_dirichlet/chi_vec_loop.c b/acb_dirichlet/chi_vec_loop.c index 40d1f950..e2dec1db 100644 --- a/acb_dirichlet/chi_vec_loop.c +++ b/acb_dirichlet/chi_vec_loop.c @@ -29,24 +29,28 @@ void acb_dirichlet_chi_vec_loop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) { - int j; - ulong t, k; - acb_dirichlet_conrey_t x; - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_one(x, G); - t = v[1] = 0; - while ( (j = acb_dirichlet_conrey_next(x, G)) < G->num ) - { - /* exponents were modified up to j */ - for (k = 0; k < j; k++) - t = (t + chi->expo[k] * x->log[k]) % chi->order; - if (x->n < nv) - v[x->n] = t; - } - /* fix result outside primes */ - acb_dirichlet_vec_set_null(v, nv, G); - /* copy outside modulus */ - for (k = G->q + 1; k < nv ; k++ ) - v[k] = v[k - G->q]; - acb_dirichlet_conrey_clear(x); + int j; + ulong t, k; + acb_dirichlet_conrey_t x; + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_conrey_one(x, G); + + for (k = 0; k < nv; k++) + v[k] = CHI_NULL; + + t = v[1] = 0; + while ( (j = acb_dirichlet_conrey_next(x, G)) < G->num ) + { + /* exponents were modified up to j */ + for (k = 0; k <= j; k++) + t = (t + chi->expo[k]) % chi->order; + if (x->n < nv) + v[x->n] = t; + } + /* fix result outside primes */ + /*acb_dirichlet_vec_set_null(v, nv, G);*/ + /* copy outside modulus */ + for (k = G->q; k < nv ; k++ ) + v[k] = v[k - G->q]; + acb_dirichlet_conrey_clear(x); } diff --git a/acb_dirichlet/conrey_exp.c b/acb_dirichlet/conrey_exp.c index 3dd6c7b1..af268814 100644 --- a/acb_dirichlet/conrey_exp.c +++ b/acb_dirichlet/conrey_exp.c @@ -30,8 +30,7 @@ acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G { ulong k, n = 1; for (k = G->neven; k < G->num; k++) - /* n = n_mulmod(n, n_powmod(G->generators[k], x->log[k], G->q), G->q); */ - n = n * n_powmod(G->generators[k], x->log[k], G->q) % G->q; + n = nmod_mul(n, nmod_pow_ui(G->generators[k], x->log[k], G->mod), G->mod); x->n = n; return n; } diff --git a/acb_dirichlet/conrey_first_primitive.c b/acb_dirichlet/conrey_first_primitive.c index 488a6186..50913511 100644 --- a/acb_dirichlet/conrey_first_primitive.c +++ b/acb_dirichlet/conrey_first_primitive.c @@ -26,15 +26,23 @@ #include "acb_dirichlet.h" void -acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { +acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +{ ulong k; if (G->q % 4 == 2) { - flint_printf("Exception (acb_dirichlet_conrey_first_primitive). no primitive element mod %wu.\n",G->q); - abort(); + flint_printf("Exception (acb_dirichlet_conrey_first_primitive). No primitive element mod %wu.\n",G->q); + abort(); } + x->n = 1; for (k = 0; k < G->num ; k++) - x->log[k] = 1; - if (G->neven == 2) - x->log[0] = 0; + { + if (k == 0 && G->neven == 2) + x->log[k] = 0; + else + { + x->n = nmod_mul(x->n, G->generators[k], G->mod); + x->log[k] = 1; + } + } } diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index bc41fb02..a7fd1401 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -35,20 +35,31 @@ acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G ulong k, pk, gk; /* even part */ if (G->neven >= 1) - x->log[0] = (m % 4 == 3); - if (G->neven == 2) { - ulong q_even = G->q_even; - ulong g2 = 5; - ulong m2 = (m % 4 == 3) ? -m % q_even : m % q_even; - x->log[1] = n_discrete_log_bsgs(m2, g2, q_even); + x->log[0] = (m % 4 == 3); + if (G->neven == 2) + { + ulong m2 = (x->log[0]) ? -m % G->q_even : m % G->q_even; + if (G->dlog == NULL) + x->log[1] = n_discrete_log_bsgs(m2, 5, G->q_even); + else + x->log[1] = dlog_precomp(G->dlog[1], m2); + } } /* odd part */ - for (k = G->neven; k < G->num; k++) + if (G->dlog == NULL) { - pk = G->primepowers[k]; - gk = G->generators[k] % pk; - x->log[k] = n_discrete_log_bsgs(m % pk, gk, pk); + for (k = G->neven; k < G->num; k++) + { + pk = G->primepowers[k]; + gk = G->generators[k] % pk; + x->log[k] = n_discrete_log_bsgs(m % pk, gk, pk); + } + } + else + { + for (k = G->neven; k < G->num; k++) + x->log[k] = dlog_precomp(G->dlog[k], m % G->primepowers[k]); } /* keep value m */ x->n = m; diff --git a/acb_dirichlet/conrey_mul.c b/acb_dirichlet/conrey_mul.c index c0c7d95c..cdac5acd 100644 --- a/acb_dirichlet/conrey_mul.c +++ b/acb_dirichlet/conrey_mul.c @@ -30,6 +30,6 @@ acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G { ulong k; for (k = 0; k < G->num ; k++) - c->log[k] = a->log[k] + b->log[k] % G->phi[k]; - c->n = a->n * b->n % G->q; + c->log[k] = (a->log[k] + b->log[k]) % G->phi[k]; + c->n = nmod_mul(a->n, b->n, G->mod); } diff --git a/acb_dirichlet/conrey_next.c b/acb_dirichlet/conrey_next.c index ab5b6ecf..5b4be26c 100644 --- a/acb_dirichlet/conrey_next.c +++ b/acb_dirichlet/conrey_next.c @@ -28,16 +28,16 @@ int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { - /* update index */ - ulong k; - for (k=0; k < G->num ; k++) - { - /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ - x->n = x->n * G->generators[k] % G->q; - if (++x->log[k] < G->phi[k]) - break; - x->log[k] = 0; - } - /* return last index modified */ - return k; + /* update index */ + int k; + for (k=0; k < G->num; k++) + { + x->n = nmod_mul(x->n, G->generators[k], G->mod); + x->log[k] += 1; + if (x->log[k] < G->phi[k]) + break; + x->log[k] = 0; + } + /* return last index modified */ + return k; } diff --git a/acb_dirichlet/conrey_next_primitive.c b/acb_dirichlet/conrey_next_primitive.c index acae8a76..90671bd6 100644 --- a/acb_dirichlet/conrey_next_primitive.c +++ b/acb_dirichlet/conrey_next_primitive.c @@ -33,8 +33,7 @@ acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichle ulong k = 0; if (G->neven == 2) { - /* x->n = n_mulmod(x->n, G->generators[0], G->q); */ - x->n = x->n * G->generators[0] % G->q; + x->n = nmod_mul(x->n, G->generators[0], G->mod); if (++x->log[0] == 1) return 0; x->log[0] = 0; @@ -42,12 +41,10 @@ acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichle } for (; k < G->num ; k++) { - /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ - x->n = x->n * G->generators[k] % G->q; + x->n = nmod_mul(x->n, G->generators[k], G->mod); if (++x->log[k] % G->primes[k] == 0) { - /* x->n = n_mulmod(x->n, G->generators[k], G->q); */ - x->n = x->n * G->generators[k] % G->q; + x->n = nmod_mul(x->n, G->generators[k], G->mod); ++x->log[k]; } if (x->log[k] < G->phi[k]) diff --git a/acb_dirichlet/conrey_one.c b/acb_dirichlet/conrey_one.c index 36e23b58..d5eac769 100644 --- a/acb_dirichlet/conrey_one.c +++ b/acb_dirichlet/conrey_one.c @@ -26,9 +26,10 @@ #include "acb_dirichlet.h" void -acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { +acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +{ ulong k; for (k = 0; k < G->num ; k++) - x->log[k] = 0; + x->log[k] = 0; x->n = 1; } diff --git a/acb_dirichlet/conrey_print.c b/acb_dirichlet/conrey_print.c index 266bbf23..92aeee2d 100644 --- a/acb_dirichlet/conrey_print.c +++ b/acb_dirichlet/conrey_print.c @@ -29,8 +29,9 @@ void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) { int k; - flint_printf("[%wu",x->log[0]); + if (G->num) + flint_printf("[%wu", x->log[0]); for (k = 1; k < G->num; k++) - flint_printf(", %wu",x->log[k]); + flint_printf(", %wu", x->log[k]); flint_printf("]\n"); } diff --git a/acb_dirichlet/group_dlog_precompute.c b/acb_dirichlet/group_dlog_precompute.c new file mode 100644 index 00000000..f16bd567 --- /dev/null +++ b/acb_dirichlet/group_dlog_precompute.c @@ -0,0 +1,42 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) +{ + slong k; + G->dlog = flint_malloc(G->num * sizeof(dlog_precomp_t)); + for (k = G->neven; k < G->num; k++) + { + ulong p, e, pe, a; + p = G->primes[k]; + e = G->exponents[k]; + pe = G->primepowers[k]; + a = G->generators[k] % pe; + dlog_precomp_modpe_init(G->dlog[k], a, p, e, pe, num); + } +} diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index eba5b84a..ef144b60 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -41,6 +41,8 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) n_factor_t fac; G->q = q; + nmod_init(&G->mod, q); + G->q_odd = q; G->q_even = 1; @@ -63,6 +65,7 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) G->generators = flint_malloc(G->num * sizeof(ulong)); G->phi = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); + G->dlog = NULL; /* even part */ G->expo = G->phi_q = 1; diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c new file mode 100644 index 00000000..dc7ca96a --- /dev/null +++ b/acb_dirichlet/test/t-thetanull.c @@ -0,0 +1,143 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include + +#define PI 3.14159265358 +#define LOG2 0.69314718055 + +int main() +{ + slong prec = 80; + ulong q; + + flint_printf("theta null...."); + fflush(stdout); + + /* check the only theta functions + * theta(chi) = sum chi(k)* k^odd * exp(-Pi * k^2 / q) + * vanishing at 1 correspond to two specific + * characters of moduli 300 and 600 + conjugates + */ + + for (q = 3; q < 800; q ++) + { + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_dirichlet_char_t chi; + ulong * v, nv, k; + + acb_t zeta, sum; + acb_ptr z; + + arb_t eq; + arb_ptr t, kt, tt; + + if (q % 4 == 2) + continue; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_char_init(chi, G); + + acb_init(zeta); + acb_dirichlet_zeta(zeta, G->expo, prec); + + z = _acb_vec_init(G->expo); + _acb_vec_set_powers(z, zeta, G->expo, prec); + + nv = ceil(sqrt((double)q * prec * LOG2 / PI)) + 2; + v = flint_malloc(nv * sizeof(ulong)); + + arb_init(eq); + arb_const_pi(eq, prec); + arb_div_ui(eq, eq, q, prec); + arb_neg(eq, eq); + arb_exp(eq, eq, prec); + + t = _arb_vec_init(nv); + acb_dirichlet_arb_quadratic_powers(t, nv, eq, prec); + + kt = _arb_vec_init(nv); + for (k = 1; k < nv; k++) + arb_mul_ui(kt + k, t + k, k, prec); + + /* theta function on primitive characters */ + acb_init(sum); + acb_dirichlet_conrey_first_primitive(x, G); + + while (1) { + ulong m; + acb_zero(sum); + + acb_dirichlet_char_conrey(chi, G, x); + acb_dirichlet_chi_vec_loop(v, nv, G, chi); + + m = G->expo / chi->order; + /* + flint_printf("Theta(chi_%wu(%wu)) (m=%wu)\n", q, chi->n, m); + */ + tt = acb_dirichlet_char_is_odd(G, chi) ? kt : t; + for (k = 1; k < nv; k++) + if (v[k] != CHI_NULL) + acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); + + if ((q == 300 && (chi->n == 271 || chi->n == 131)) + || (q == 600 && (chi->n == 11 || chi->n == 91))) + { + if (!acb_contains_zero(sum)) + { + flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); + acb_printd(sum, 10); + flint_printf("\n"); + abort(); + } + } + else if (acb_contains_zero(sum)) + { + flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); + acb_printd(sum, 10); + flint_printf("\n"); + abort(); + } + + if (acb_dirichlet_conrey_next_primitive(x, G) == G->num) + break; + } + _acb_vec_clear(z, G->expo); + _arb_vec_clear(t, nv); + acb_clear(zeta); + acb_clear(sum); + arb_clear(eq); + acb_dirichlet_group_clear(G); + acb_dirichlet_char_clear(chi); + acb_dirichlet_conrey_clear(x); + } + + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/zeta.c b/acb_dirichlet/zeta.c new file mode 100644 index 00000000..111f6c7b --- /dev/null +++ b/acb_dirichlet/zeta.c @@ -0,0 +1,36 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_zeta(acb_t res, ulong order, slong prec) +{ + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, 2, order); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); +} diff --git a/dlog.h b/dlog.h index 16bdfd98..c35e5ff3 100644 --- a/dlog.h +++ b/dlog.h @@ -191,6 +191,7 @@ ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); ulong dlog_rho(const dlog_rho_t t, ulong b); /*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ +void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num); void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num); void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num); From 36e1682d6432753cf0e01be14e2358c6d25baf7d Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 23 Mar 2016 18:23:19 +0100 Subject: [PATCH 022/139] add parity in char (simpler to have on logs) --- acb_dirichlet.h | 24 ++++++++++++++++++- acb_dirichlet/char_conrey.c | 3 ++- .../{char_is_odd.c => conrey_parity.c} | 6 ++--- acb_dirichlet/test/t-thetanull.c | 2 +- 4 files changed, 29 insertions(+), 6 deletions(-) rename acb_dirichlet/{char_is_odd.c => conrey_parity.c} (89%) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 3279cd39..fb1e7c2a 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -1,6 +1,7 @@ /* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin This file is part of Arb. @@ -13,6 +14,12 @@ #ifndef ACB_DIRICHLET_H #define ACB_DIRICHLET_H +#ifdef ACB_INLINES_C +#define ACB_INLINE +#else +#define ACB_INLINE static __inline__ +#endif + #include "acb.h" #include "dlog.h" @@ -59,11 +66,14 @@ void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); void acb_dirichlet_group_clear(acb_dirichlet_group_t G); +void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); + void acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); void acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); +int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); @@ -89,11 +99,24 @@ typedef struct ulong n; /* number */ ulong order; /* order */ ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ + int parity; /* 0 for even char, 1 for odd */ } acb_dirichlet_char_struct; typedef acb_dirichlet_char_struct acb_dirichlet_char_t[1]; +ACB_INLINE int +acb_dirichlet_char_order(const acb_dirichlet_char_t chi) +{ + return chi->order; +} + +ACB_INLINE int +acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) +{ + return chi->parity; +} + void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); @@ -129,4 +152,3 @@ void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slon #endif #endif - diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c index 8414534f..c295c011 100644 --- a/acb_dirichlet/char_conrey.c +++ b/acb_dirichlet/char_conrey.c @@ -33,9 +33,10 @@ acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t ulong k; chi->q = G->q; chi->n = x->n; + chi->parity = acb_dirichlet_conrey_parity(G, x); for (k = 0; k < G->num; k++) - chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; + chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; /* optional: divide by gcd to obtain true order */ acb_dirichlet_char_normalize(chi, G); diff --git a/acb_dirichlet/char_is_odd.c b/acb_dirichlet/conrey_parity.c similarity index 89% rename from acb_dirichlet/char_is_odd.c rename to acb_dirichlet/conrey_parity.c index cb5d0502..ede8aaf6 100644 --- a/acb_dirichlet/char_is_odd.c +++ b/acb_dirichlet/conrey_parity.c @@ -26,14 +26,14 @@ #include "acb_dirichlet.h" int -acb_dirichlet_char_is_odd(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) { - slong k, odd = 0; + int k, odd = 0; for (k = 0; k < G->num; k++) { if (k == 1 && G->neven == 2) continue; - if (chi->expo[k] % 2 == 1) + if (x->log[k] % 2) odd = 1 - odd; } return odd; diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index dc7ca96a..e57889a2 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -100,7 +100,7 @@ int main() /* flint_printf("Theta(chi_%wu(%wu)) (m=%wu)\n", q, chi->n, m); */ - tt = acb_dirichlet_char_is_odd(G, chi) ? kt : t; + tt = acb_dirichlet_char_parity(chi) ? kt : t; for (k = 1; k < nv; k++) if (v[k] != CHI_NULL) acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); From 401f91eed1608f098fe51604d02b22e533188274 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 23 Mar 2016 22:10:58 +0100 Subject: [PATCH 023/139] split dlog precomp file --- dlog.h | 92 +++++++++++++++----- dlog/1modpe_init.c | 7 -- dlog/bsgs_init.c | 6 -- dlog/crt.c | 2 +- dlog/crt_clear.c | 37 ++++++++ dlog/crt_init.c | 22 +---- dlog/modpe.c | 18 ---- dlog/modpe_init.c | 37 ++++++++ dlog/order23_init.c | 6 -- dlog/power_init.c | 8 -- dlog/precomp_clear.c | 55 ++++++++++++ dlog/precomp_init.c | 174 -------------------------------------- dlog/precomp_modpe_init.c | 48 +++++++++++ dlog/precomp_n_init.c | 54 ++++++++++++ dlog/precomp_p_init.c | 44 ++++++++++ dlog/precomp_pe_init.c | 47 ++++++++++ dlog/precomp_small_init.c | 49 +++++++++++ dlog/profile/p-precomp.c | 2 +- dlog/rho.c | 15 ---- dlog/rho_init.c | 36 ++++++++ dlog/table_init.c | 6 -- dlog/vec_sieve.c | 4 +- 22 files changed, 484 insertions(+), 285 deletions(-) create mode 100644 dlog/crt_clear.c create mode 100644 dlog/modpe_init.c create mode 100644 dlog/precomp_clear.c delete mode 100644 dlog/precomp_init.c create mode 100644 dlog/precomp_modpe_init.c create mode 100644 dlog/precomp_n_init.c create mode 100644 dlog/precomp_p_init.c create mode 100644 dlog/precomp_pe_init.c create mode 100644 dlog/precomp_small_init.c create mode 100644 dlog/rho_init.c diff --git a/dlog.h b/dlog.h index c35e5ff3..4374aa26 100644 --- a/dlog.h +++ b/dlog.h @@ -26,6 +26,12 @@ #ifndef DLOG_H #define DLOG_H +#ifdef ACB_INLINES_C +#define ACB_INLINE +#else +#define ACB_INLINE static __inline__ +#endif + #include "ulong_extras.h" #include "nmod_vec.h" #include "padic.h" @@ -36,6 +42,7 @@ enum }; typedef struct dlog_precomp_struct dlog_precomp_struct; +typedef struct dlog_precomp_struct * dlog_precomp_ptr; /* log in (1+pZ/p^eZ): compute via p-adic log */ typedef struct @@ -112,11 +119,7 @@ typedef struct ulong num; ulong * expo; ulong * crt_coeffs; - dlog_precomp_struct ** pre; - /* - void * pre; - dlog_precomp_t * pre; - */ + dlog_precomp_ptr pre; } dlog_crt_struct; @@ -130,10 +133,6 @@ typedef struct ulong e; ulong * apk; dlog_precomp_struct * pre; - /* - void * pre; - dlog_precomp_t * pre; - */ } dlog_power_struct; @@ -161,6 +160,15 @@ dlog_precomp_struct typedef dlog_precomp_struct dlog_precomp_t[1]; +void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num); +void dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); +void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); +void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num); +void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num); +void dlog_precomp_clear(dlog_precomp_t pre); + +ulong dlog_precomp(const dlog_precomp_t pre, ulong b); + ulong dlog_order23_init(dlog_order23_t t, ulong a); ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod); ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); @@ -171,14 +179,53 @@ void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e); void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n); /*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ -void dlog_order23_clear(dlog_order23_t t); -void dlog_table_clear(dlog_table_t t); -void dlog_1modpe_clear(dlog_1modpe_t t); +ACB_INLINE void +dlog_order23_clear(dlog_order23_t t) +{ + return; +} + +ACB_INLINE void +dlog_table_clear(dlog_table_t t) +{ + flint_free(t->table); +} + +ACB_INLINE void +dlog_1modpe_clear(dlog_1modpe_t t) +{ + padic_clear(t->invlog); + padic_ctx_clear(t->ctx); +} + void dlog_crt_clear(dlog_crt_t t); -void dlog_power_clear(dlog_power_t t); -void dlog_modpe_clear(dlog_modpe_t t); -void dlog_bsgs_clear(dlog_bsgs_t t); -void dlog_rho_clear(dlog_rho_t t); + +ACB_INLINE void +dlog_power_clear(dlog_power_t t) +{ + flint_free(t->apk); + dlog_precomp_clear(t->pre); + flint_free(t->pre); +} + +ACB_INLINE void +dlog_modpe_clear(dlog_modpe_t t) +{ + dlog_precomp_clear(t->modp); + dlog_1modpe_clear(t->modpe); +} + +ACB_INLINE void +dlog_bsgs_clear(dlog_bsgs_t t) +{ + flint_free(t->table); +} + +ACB_INLINE void +dlog_rho_clear(dlog_rho_t t) +{ + return; +} /*#define dlog_bsgs_clear(t) bsgs_table_clear(t)*/ ulong dlog_order23(const dlog_order23_t t, ulong b); @@ -191,12 +238,13 @@ ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); ulong dlog_rho(const dlog_rho_t t, ulong b); /*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ -void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num); -void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); -void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num); -void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num); -void dlog_precomp_clear(dlog_precomp_t pre); -ulong dlog_precomp(const dlog_precomp_t pre, ulong b); +#define DLOG_SMALL_LIM 50 +#define DLOG_TABLE_LIM 50 +#define DLOG_TABLE_P_LIM 50 +#define DLOG_TABLE_MODPE_LIM 50 +#define DLOG_TABLE_PE_LIM 50 +#define DLOG_TABLE_N_LIM 50 +#define DLOG_BSGS_LIM 500 #define LOOP_MAX_FACTOR 6 #define G_SMALL 0 diff --git a/dlog/1modpe_init.c b/dlog/1modpe_init.c index 3226bcb2..ccf53047 100644 --- a/dlog/1modpe_init.c +++ b/dlog/1modpe_init.c @@ -41,10 +41,3 @@ dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e) fmpz_clear(tmp); } - -void -dlog_1modpe_clear(dlog_1modpe_t t) -{ - padic_clear(t->invlog); - padic_ctx_clear(t->ctx); -} diff --git a/dlog/bsgs_init.c b/dlog/bsgs_init.c index 42fb2d19..e2aa2827 100644 --- a/dlog/bsgs_init.c +++ b/dlog/bsgs_init.c @@ -56,9 +56,3 @@ dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) qsort(t->table, m, sizeof(apow_t), (int(*)(const void*,const void*))apow_cmp); return t->g; } - -void -dlog_bsgs_clear(dlog_bsgs_t t) -{ - flint_free(t->table); -} diff --git a/dlog/crt.c b/dlog/crt.c index 881c757b..867b4481 100644 --- a/dlog/crt.c +++ b/dlog/crt.c @@ -34,7 +34,7 @@ dlog_crt(const dlog_crt_t t, ulong b) { ulong bk, rk; bk = nmod_pow_ui(b, t->expo[k], t->mod); - rk = dlog_precomp(t->pre[k], bk); + rk = dlog_precomp(t->pre + k, bk); #if 0 flint_printf("##[crt-%d]: log(%wu)=log(%wu^%wu) = %wu [size %wu mod %wu]\n", k, bk, b, t->expo[k], rk, t->n/t->expo[k], t->mod); diff --git a/dlog/crt_clear.c b/dlog/crt_clear.c new file mode 100644 index 00000000..1650118f --- /dev/null +++ b/dlog/crt_clear.c @@ -0,0 +1,37 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_crt_clear(dlog_crt_t t) +{ + int k; + flint_free(t->expo); + flint_free(t->crt_coeffs); + for (k = 0; k < t->num; k++) + dlog_precomp_clear(t->pre + k); + flint_free(t->pre); +} diff --git a/dlog/crt_init.c b/dlog/crt_init.c index 381e247f..bd1a9ee3 100644 --- a/dlog/crt_init.c +++ b/dlog/crt_init.c @@ -42,9 +42,7 @@ dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) M = t->expo = flint_malloc(t->num * sizeof(ulong)); u = t->crt_coeffs = flint_malloc(t->num * sizeof(ulong)); - t->pre = flint_malloc(t->num * sizeof(dlog_precomp_t)); - for (k = 0; k < t->num; k++) - t->pre[k] = flint_malloc(sizeof(dlog_precomp_struct)); + t->pre = flint_malloc(t->num * sizeof(dlog_precomp_struct)); for (k = 0; k < t->num; k++) { @@ -58,8 +56,8 @@ dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) #if 0 flint_printf("[sub-crt -- init for size %wu mod %wu]\n", mk, mod); #endif - dlog_precomp_pe_init(t->pre[k], nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); - cost += t->pre[k]->cost; + dlog_precomp_pe_init(t->pre + k, nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); + cost += t->pre[k].cost; } #if 0 if (cost > 500) @@ -67,17 +65,3 @@ dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) #endif return cost; } - -void -dlog_crt_clear(dlog_crt_t t) -{ - int k; - flint_free(t->expo); - flint_free(t->crt_coeffs); - for (k = 0; k < t->num; k++) - { - dlog_precomp_clear(t->pre[k]); - flint_free(t->pre[k]); - } - flint_free(t->pre); -} diff --git a/dlog/modpe.c b/dlog/modpe.c index 1941d44b..a3f76e72 100644 --- a/dlog/modpe.c +++ b/dlog/modpe.c @@ -26,24 +26,6 @@ #include "dlog.h" #include "padic.h" -ulong -dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) -{ - t->p = p; - t->e = e; - t->pe = pe; - dlog_precomp_n_init(t->modp, a, p, p-1, num); - dlog_1modpe_init(t->modpe, n_powmod(a, p - 1, pe), p, e); - return t->modp->cost + e; -} - -void -dlog_modpe_clear(dlog_modpe_t t) -{ - dlog_precomp_clear(t->modp); - dlog_1modpe_clear(t->modpe); -} - ulong dlog_modpe(const dlog_modpe_t t, ulong b) { diff --git a/dlog/modpe_init.c b/dlog/modpe_init.c new file mode 100644 index 00000000..55b74be6 --- /dev/null +++ b/dlog/modpe_init.c @@ -0,0 +1,37 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +ulong +dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) +{ + t->p = p; + t->e = e; + t->pe = pe; + dlog_precomp_n_init(t->modp, a, p, p-1, num); + dlog_1modpe_init(t->modpe, n_powmod(a, p - 1, pe), p, e); + return t->modp->cost + e; +} diff --git a/dlog/order23_init.c b/dlog/order23_init.c index 412818de..7e822dca 100644 --- a/dlog/order23_init.c +++ b/dlog/order23_init.c @@ -31,9 +31,3 @@ dlog_order23_init(dlog_order23_t t, ulong a) * t = a; return 0; } - -void -dlog_order23_clear(dlog_order23_t t) -{ - return; -} diff --git a/dlog/power_init.c b/dlog/power_init.c index 61409db3..a944dd3c 100644 --- a/dlog/power_init.c +++ b/dlog/power_init.c @@ -43,11 +43,3 @@ dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) dlog_precomp_p_init(t->pre, nmod_inv(t->apk[e-1], t->mod), mod, p, e * num); return e * t->pre->cost; } - -void -dlog_power_clear(dlog_power_t t) -{ - flint_free(t->apk); - dlog_precomp_clear(t->pre); - flint_free(t->pre); -} diff --git a/dlog/precomp_clear.c b/dlog/precomp_clear.c new file mode 100644 index 00000000..64bf402d --- /dev/null +++ b/dlog/precomp_clear.c @@ -0,0 +1,55 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_precomp_clear(dlog_precomp_t pre) +{ + switch (pre->type) + { + case DLOG_MODPE: + dlog_modpe_clear(pre->t.modpe); + break; + case DLOG_CRT: + dlog_crt_clear(pre->t.crt); + break; + case DLOG_POWER: + dlog_power_clear(pre->t.power); + break; + case DLOG_TABLE: + dlog_table_clear(pre->t.table); + break; + case DLOG_BSGS: + dlog_bsgs_clear(pre->t.bsgs); + break; + case DLOG_23: + dlog_order23_clear(pre->t.order23); + break; + default: + abort(); + break; + } +} diff --git a/dlog/precomp_init.c b/dlog/precomp_init.c deleted file mode 100644 index b2229294..00000000 --- a/dlog/precomp_init.c +++ /dev/null @@ -1,174 +0,0 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2016 Pascal Molin - -******************************************************************************/ - -#include "math.h" -#include "dlog.h" - -#define SMALL_LIM 50 -#define TABLE_LIM 50 -#define TABLE_P_LIM 50 -#define TABLE_MODPE_LIM 50 -#define TABLE_PE_LIM 50 -#define TABLE_N_LIM 50 -#define BSGS_LIM 500 - -void -dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) -{ - if (n <= 3) - { - pre->type = DLOG_23; - pre->cost = dlog_order23_init(pre->t.order23, a); - } - else - { - if ( mod < TABLE_LIM ) - { - pre->type = DLOG_TABLE; - pre->cost = dlog_table_init(pre->t.table, a, mod); - } - else - { - pre->type = DLOG_BSGS; - pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, n); - } - } -} - -/* log mod p^e */ -void -dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) -{ - if ( pe < TABLE_MODPE_LIM ) - { - dlog_precomp_small_init(pre, a, pe, pe - pe / p, num); - return; - } - else { - if (e > 1) - { - pre->type = DLOG_MODPE; - pre->cost = dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); - } - else - { - dlog_precomp_n_init(pre, a, p, p - 1, num); - } - } -} - -/* group of order n modulo mod, mod a prime and no information on n */ -void -dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) -{ - if (n%2 && n_is_probabprime(n)) - dlog_precomp_p_init(pre, a, mod, n, num); - else { - if (n < TABLE_N_LIM) - { - dlog_precomp_small_init(pre, a, mod, n, num); - } - else - { - if (n < BSGS_LIM) - { - ulong m; - m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; - pre->type = DLOG_BSGS; - pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); - } else { - pre->type = DLOG_CRT; - pre->cost = dlog_crt_init(pre->t.crt, a, mod, n, num); - } - } - } -} - -/* we known the order is prime */ -void -dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) -{ - if ( p < TABLE_P_LIM ) - { - dlog_precomp_small_init(pre, a, mod, p, num); - } - else - { - ulong m; - m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; - pre->type = DLOG_BSGS; - pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); - } -} - -void -dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) -{ - if ( pe < TABLE_PE_LIM ) - { - dlog_precomp_small_init(pre, a, mod, pe, num); - } - else - { - if ( e == 1) - { - dlog_precomp_p_init(pre, a, mod, p, num); - } - else - { - pre->type = DLOG_POWER; - pre->cost = dlog_power_init(pre->t.power, a, mod, p, e, num); - } - } -} - -void -dlog_precomp_clear(dlog_precomp_t pre) -{ - switch (pre->type) - { - case DLOG_MODPE: - dlog_modpe_clear(pre->t.modpe); - break; - case DLOG_CRT: - dlog_crt_clear(pre->t.crt); - break; - case DLOG_POWER: - dlog_power_clear(pre->t.power); - break; - case DLOG_TABLE: - dlog_table_clear(pre->t.table); - break; - case DLOG_BSGS: - dlog_bsgs_clear(pre->t.bsgs); - break; - case DLOG_23: - dlog_order23_clear(pre->t.order23); - break; - default: - abort(); - break; - } -} diff --git a/dlog/precomp_modpe_init.c b/dlog/precomp_modpe_init.c new file mode 100644 index 00000000..d89b5c62 --- /dev/null +++ b/dlog/precomp_modpe_init.c @@ -0,0 +1,48 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +/* log mod p^e */ +void +dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) +{ + if ( pe < DLOG_TABLE_MODPE_LIM ) + { + dlog_precomp_small_init(pre, a, pe, pe - pe / p, num); + return; + } + else { + if (e > 1) + { + pre->type = DLOG_MODPE; + pre->cost = dlog_modpe_init(pre->t.modpe, a, p, e, pe, num); + } + else + { + dlog_precomp_n_init(pre, a, p, p - 1, num); + } + } +} diff --git a/dlog/precomp_n_init.c b/dlog/precomp_n_init.c new file mode 100644 index 00000000..de430399 --- /dev/null +++ b/dlog/precomp_n_init.c @@ -0,0 +1,54 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include "math.h" + +/* group of order n modulo mod, mod a prime and no information on n */ +void +dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) +{ + if (n%2 && n_is_probabprime(n)) + dlog_precomp_p_init(pre, a, mod, n, num); + else { + if (n < DLOG_TABLE_N_LIM) + { + dlog_precomp_small_init(pre, a, mod, n, num); + } + else + { + if (n < DLOG_BSGS_LIM) + { + ulong m; + m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; + pre->type = DLOG_BSGS; + pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); + } else { + pre->type = DLOG_CRT; + pre->cost = dlog_crt_init(pre->t.crt, a, mod, n, num); + } + } + } +} diff --git a/dlog/precomp_p_init.c b/dlog/precomp_p_init.c new file mode 100644 index 00000000..2aa972b3 --- /dev/null +++ b/dlog/precomp_p_init.c @@ -0,0 +1,44 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include "math.h" + +/* we known the order is prime */ +void +dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) +{ + if ( p < DLOG_TABLE_P_LIM ) + { + dlog_precomp_small_init(pre, a, mod, p, num); + } + else + { + ulong m; + m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; + pre->type = DLOG_BSGS; + pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); + } +} diff --git a/dlog/precomp_pe_init.c b/dlog/precomp_pe_init.c new file mode 100644 index 00000000..ce98ba14 --- /dev/null +++ b/dlog/precomp_pe_init.c @@ -0,0 +1,47 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) +{ + if ( pe < DLOG_TABLE_PE_LIM ) + { + dlog_precomp_small_init(pre, a, mod, pe, num); + } + else + { + if ( e == 1) + { + dlog_precomp_p_init(pre, a, mod, p, num); + } + else + { + pre->type = DLOG_POWER; + pre->cost = dlog_power_init(pre->t.power, a, mod, p, e, num); + } + } +} diff --git a/dlog/precomp_small_init.c b/dlog/precomp_small_init.c new file mode 100644 index 00000000..7c792e63 --- /dev/null +++ b/dlog/precomp_small_init.c @@ -0,0 +1,49 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) +{ + if (n <= 3) + { + pre->type = DLOG_23; + pre->cost = dlog_order23_init(pre->t.order23, a); + } + else + { + if ( mod < DLOG_TABLE_LIM ) + { + pre->type = DLOG_TABLE; + pre->cost = dlog_table_init(pre->t.table, a, mod); + } + else + { + pre->type = DLOG_BSGS; + pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, n); + } + } +} diff --git a/dlog/profile/p-precomp.c b/dlog/profile/p-precomp.c index 56e9eba9..c3e21891 100644 --- a/dlog/profile/p-precomp.c +++ b/dlog/profile/p-precomp.c @@ -118,7 +118,7 @@ int main() flint_rand_t state; flint_randinit(state); - for (nbits = 10; nbits < 50; nbits += 5) + for (nbits = 10; nbits <= 40; nbits += 5) { int i; diff --git a/dlog/rho.c b/dlog/rho.c index 84d02681..96766135 100644 --- a/dlog/rho.c +++ b/dlog/rho.c @@ -26,21 +26,6 @@ #include "dlog.h" #include -void -dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) -{ - t->a = a; - nmod_init(&t->n, n); - nmod_init(&t->mod, mod); - t->nisprime = n_is_prime(n); -} - -void -dlog_rho_clear(dlog_rho_t t) -{ - return; -} - static ulong dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) { diff --git a/dlog/rho_init.c b/dlog/rho_init.c new file mode 100644 index 00000000..99210795 --- /dev/null +++ b/dlog/rho_init.c @@ -0,0 +1,36 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include + +void +dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) +{ + t->a = a; + nmod_init(&t->n, n); + nmod_init(&t->mod, mod); + t->nisprime = n_is_prime(n); +} diff --git a/dlog/table_init.c b/dlog/table_init.c index 5ed9f4f1..b04e0c74 100644 --- a/dlog/table_init.c +++ b/dlog/table_init.c @@ -43,9 +43,3 @@ dlog_table_init(dlog_table_t t, ulong a, ulong mod) while (ak != 1); return 1; } - -void -dlog_table_clear(dlog_table_t t) -{ - flint_free(t->table); -} diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index 979de9e6..a2e08e2e 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -26,8 +26,9 @@ #include "dlog.h" #include -#define vbs 1 +#define vbs 0 +/* TODO: tune the limit dlog -> index calculus */ void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { @@ -47,7 +48,6 @@ dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod pmax = (nv < mod.n) ? nv : mod.n; p1 = 50; /* FIXME: tune this limit! */ dlog_precomp_n_init(pre, a, mod.n, na, p1); - /*flint_printf("## single log cost: %wu\n", pre->cost);*/ logcost = pre->cost; if (logcost < 15) From fdf49f76f4012190c541b55ca474190f01d77403 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 25 Mar 2016 15:11:14 +0100 Subject: [PATCH 024/139] add recursion formulas for log mod pe --- dlog.h | 44 +++++++++++++------ dlog/1modpe_mod1p.c | 48 +++++++++++++++++++++ dlog/{1modpe.c => 1modpe_padic.c} | 22 ++++++++-- dlog/{1modpe_init.c => 1modpe_padic_init.c} | 10 +++-- dlog/1modpe_rec.c | 40 +++++++++++++++++ dlog/1modpe_rec_init.c | 46 ++++++++++++++++++++ dlog/crt_init.c | 5 +++ dlog/modpe.c | 24 +++++++++-- dlog/modpe_init.c | 18 ++++++-- 9 files changed, 230 insertions(+), 27 deletions(-) create mode 100644 dlog/1modpe_mod1p.c rename dlog/{1modpe.c => 1modpe_padic.c} (74%) rename dlog/{1modpe_init.c => 1modpe_padic_init.c} (81%) create mode 100644 dlog/1modpe_rec.c create mode 100644 dlog/1modpe_rec_init.c diff --git a/dlog.h b/dlog.h index 4374aa26..1512d56c 100644 --- a/dlog.h +++ b/dlog.h @@ -44,28 +44,39 @@ enum typedef struct dlog_precomp_struct dlog_precomp_struct; typedef struct dlog_precomp_struct * dlog_precomp_ptr; -/* log in (1+pZ/p^eZ): compute via p-adic log */ +/* log in (1+pZ/p^eZ), e large: compute via p-adic log */ typedef struct { - ulong p; - ulong e; padic_ctx_t ctx; /* padic context */ - padic_t invlog; - padic_t x; - fmpz_t r; + padic_t invlog; /* 1 / log_p(a^(p-1)) */ } -dlog_1modpe_struct; +dlog_1modpe_padic_struct; -typedef dlog_1modpe_struct dlog_1modpe_t[1]; +typedef dlog_1modpe_padic_struct dlog_1modpe_padic_t[1]; + +/* log in (1+pZ/p^eZ), e small: use recursion formulas */ +typedef struct +{ + ulong inv1p; /* 1 / (1 + p) */ + ulong invloga1; /* 1 / log(a^(p-1),1+p) */ +} +dlog_1modpe_rec_struct; + +typedef dlog_1modpe_rec_struct dlog_1modpe_rec_t[1]; /* log in (Z/p^eZ)^* */ typedef struct { ulong p; ulong e; - ulong pe; + ulong pe1; /* p^(e-1) */ + ulong inva; + nmod_t pe; dlog_precomp_struct * modp; - dlog_1modpe_t modpe; + union { + dlog_1modpe_rec_t rec; /* if e <= 3 && e < p */ + dlog_1modpe_padic_t padic; /* otherwise */ + } modpe; } dlog_modpe_struct; @@ -175,7 +186,8 @@ ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num); ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num); ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m); -void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e); +void dlog_1modpe_rec_init(dlog_1modpe_rec_t t, ulong a1, ulong p, ulong e, nmod_t pe); +void dlog_1modpe_padic_init(dlog_1modpe_padic_t t, ulong a1, ulong p, ulong e); void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n); /*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ @@ -192,7 +204,7 @@ dlog_table_clear(dlog_table_t t) } ACB_INLINE void -dlog_1modpe_clear(dlog_1modpe_t t) +dlog_1modpe_padic_clear(dlog_1modpe_padic_t t) { padic_clear(t->invlog); padic_ctx_clear(t->ctx); @@ -212,7 +224,9 @@ ACB_INLINE void dlog_modpe_clear(dlog_modpe_t t) { dlog_precomp_clear(t->modp); - dlog_1modpe_clear(t->modpe); + if (0 && t->e > 2) + dlog_1modpe_padic_clear(t->modpe.padic); + flint_free(t->modp); } ACB_INLINE void @@ -233,9 +247,11 @@ ulong dlog_table(const dlog_table_t t, ulong b); ulong dlog_crt(const dlog_crt_t t, ulong b); ulong dlog_power(const dlog_power_t t, ulong b); ulong dlog_modpe(const dlog_modpe_t t, ulong b); -ulong dlog_1modpe(const dlog_1modpe_t t, ulong b); ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); ulong dlog_rho(const dlog_rho_t t, ulong b); +ulong dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe); +ulong dlog_1modpe_padic(const dlog_1modpe_padic_t t, ulong b1); +ulong dlog_1modpe_rec(const dlog_1modpe_rec_t t, ulong b1, ulong p, ulong e, nmod_t pe); /*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ #define DLOG_SMALL_LIM 50 diff --git a/dlog/1modpe_mod1p.c b/dlog/1modpe_mod1p.c new file mode 100644 index 00000000..293f2e66 --- /dev/null +++ b/dlog/1modpe_mod1p.c @@ -0,0 +1,48 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +ulong +dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe) +{ + int f; + ulong x, xf, pf, pf1; + pf1 = 1; + pf = p; + x = 0; + for (f = 1; f < e; f++) + { + if (b1 % pf != 1) + abort(); + xf = (b1 - 1) / pf; + xf = (xf % p) * pf1; + x += xf; + b1 = nmod_mul(b1, nmod_pow_ui(inv1p, xf, pe), pe); + pf1 = pf; + pf *= p; + } + return x; +} diff --git a/dlog/1modpe.c b/dlog/1modpe_padic.c similarity index 74% rename from dlog/1modpe.c rename to dlog/1modpe_padic.c index a037d5f4..6083e03b 100644 --- a/dlog/1modpe.c +++ b/dlog/1modpe_padic.c @@ -27,20 +27,36 @@ /* assume b = 1 mod p, not checked */ ulong -dlog_1modpe(const dlog_1modpe_t t, ulong b) +dlog_1modpe_padic(const dlog_1modpe_padic_t t, ulong b1) { padic_t px; fmpz_t ix; ulong ux; + + if (b1 == 1) + return 0; + padic_init(px); fmpz_init(ix); - padic_set_ui(px, b, t->ctx); + padic_set_ui(px, b1, t->ctx); + flint_printf("set %wu -> ", b1); + padic_print(px, t->ctx); + padic_log(px, px, t->ctx); + flint_printf("\n\n compute log -> "); + padic_print(px, t->ctx); + + flint_printf("\n\n 1/log(a^(p-1)) -> "); + padic_print(t->invlog, t->ctx); + padic_mul(px, px, t->invlog, t->ctx); + flint_printf("\n\n divide by log(a^(p-1)) -> "); + padic_print(px, t->ctx); + padic_get_fmpz(ix, px, t->ctx); ux = fmpz_get_ui(ix); - + flint_printf("\n\nlog_p(%wu)/log_p(a) = %wu\n", b1, ux); padic_clear(px); fmpz_clear(ix); return ux; diff --git a/dlog/1modpe_init.c b/dlog/1modpe_padic_init.c similarity index 81% rename from dlog/1modpe_init.c rename to dlog/1modpe_padic_init.c index ccf53047..de4579d2 100644 --- a/dlog/1modpe_init.c +++ b/dlog/1modpe_padic_init.c @@ -26,17 +26,21 @@ #include "dlog.h" void -dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e) +dlog_1modpe_padic_init(dlog_1modpe_padic_t t, ulong a1, ulong p, ulong e) { fmpz_t tmp; - t->p = p; + fmpz_init(tmp); padic_init(t->invlog); fmpz_set_ui(tmp, p); - padic_ctx_init(t->ctx , tmp , 0 , e, PADIC_TERSE); + padic_ctx_init(t->ctx , tmp , 0 , e, PADIC_SERIES); padic_set_ui(t->invlog, a1, t->ctx); + flint_printf("set %wu -> ", a1); + flint_printf("\n\n compute log -> "); + padic_log(t->invlog, t->invlog, t->ctx); + padic_print(t->invlog, t->ctx); padic_inv(t->invlog, t->invlog, t->ctx); fmpz_clear(tmp); diff --git a/dlog/1modpe_rec.c b/dlog/1modpe_rec.c new file mode 100644 index 00000000..05960fc4 --- /dev/null +++ b/dlog/1modpe_rec.c @@ -0,0 +1,40 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +ulong +dlog_1modpe_rec(const dlog_1modpe_rec_t t, ulong b1, ulong p, ulong e, nmod_t pe) +{ + if (e == 1) + return 0; + else + { + ulong logb1; + logb1 = dlog_1modpe_mod1p(b1, p, e, t->inv1p, pe); + /* only need mod p^(e-1) */ + return nmod_mul(logb1, t->invloga1, pe); + } +} diff --git a/dlog/1modpe_rec_init.c b/dlog/1modpe_rec_init.c new file mode 100644 index 00000000..180b32b2 --- /dev/null +++ b/dlog/1modpe_rec_init.c @@ -0,0 +1,46 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" + +void +dlog_1modpe_rec_init(dlog_1modpe_rec_t t, ulong a1, ulong p, ulong e, nmod_t pe) +{ + if (e == 1) + { + t->inv1p = 1; + t->invloga1 = 0; + } + else + { + ulong loga1; + if (a1 == 1) + abort(); + t->inv1p = nmod_inv(1 + p, pe); /* 1 - p + p^2 - ... */ + loga1 = dlog_1modpe_mod1p(a1, p, e, t->inv1p, pe); + /* only need inverse mod p^(e-1) but does not hurt */ + t->invloga1 = nmod_inv(loga1, pe); + } +} diff --git a/dlog/crt_init.c b/dlog/crt_init.c index bd1a9ee3..b249a0aa 100644 --- a/dlog/crt_init.c +++ b/dlog/crt_init.c @@ -49,6 +49,11 @@ dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) ulong p, e, mk; p = fac.p[k]; e = fac.exp[k]; + if (0 && mod % p == 0) + { + flint_printf("dlog_crt_init: modulus must be prime to order.\n"); + abort(); + } mk = n_pow(p, e); M[k] = n / mk; u[k] = nmod_mul(M[k], n_invmod(M[k] % mk, mk), t->n); diff --git a/dlog/modpe.c b/dlog/modpe.c index a3f76e72..09264ef9 100644 --- a/dlog/modpe.c +++ b/dlog/modpe.c @@ -24,15 +24,31 @@ ******************************************************************************/ #include "dlog.h" -#include "padic.h" ulong dlog_modpe(const dlog_modpe_t t, ulong b) { ulong x; x = dlog_precomp(t->modp, b % t->p); - /*b = b * n_powmod(t->a, -x, t->pe);*/ - b = n_powmod(b, t->p - 1, t->pe); - x = x + (t->p-1) * dlog_1modpe(t->modpe, b); + if (t->e > 1) + { + ulong b1, y; +#if 0 + b1 = nmod_mul(b, nmod_pow_ui(t->inva, x, t->pe), t->pe); +#else + b1 = nmod_pow_ui(b, t->p - 1, t->pe); +#endif + if (1 || t->e <= 2) + y = dlog_1modpe_rec(t->modpe.rec, b1, t->p, t->e, t->pe); + else + y = dlog_1modpe_padic(t->modpe.padic, b1); + y = y % t->pe1; +#if 0 + x = x + (t->p - 1) * y; +#else + x = n_submod(x, y % (t->p - 1), t->p - 1); + x = y + t->pe1 * x; +#endif + } return x; } diff --git a/dlog/modpe_init.c b/dlog/modpe_init.c index 55b74be6..40b820fa 100644 --- a/dlog/modpe_init.c +++ b/dlog/modpe_init.c @@ -28,10 +28,22 @@ ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) { + ulong a1; + t->p = p; t->e = e; - t->pe = pe; - dlog_precomp_n_init(t->modp, a, p, p-1, num); - dlog_1modpe_init(t->modpe, n_powmod(a, p - 1, pe), p, e); + t->pe1 = pe / p; + nmod_init(&t->pe, pe); + t->inva = nmod_inv(a, t->pe); + + t->modp = flint_malloc(sizeof(dlog_precomp_struct)); + dlog_precomp_n_init(t->modp, a, p, p - 1, num); + + a1 = nmod_pow_ui(a, p - 1, t->pe); + if (1 || e <= 2) + dlog_1modpe_rec_init(t->modpe.rec, a1, p, e, t->pe); + else + dlog_1modpe_padic_init(t->modpe.padic, a1, p, e); + return t->modp->cost + e; } From fdffa467576d2678b83bc3488300c4580e196a81 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 29 Mar 2016 12:09:21 +0100 Subject: [PATCH 025/139] change dlog_mope to make recursion by hand --- dlog.h | 78 ++++++++--------------- dlog/{1modpe_rec.c => 1modpe.c} | 2 +- dlog/{1modpe_rec_init.c => 1modpe_init.c} | 2 +- dlog/1modpe_mod1p.c | 5 ++ dlog/1modpe_padic.c | 63 ------------------ dlog/{1modpe_padic_init.c => mod2e.c} | 46 +++++++------ dlog/modpe.c | 14 ++-- dlog/modpe_init.c | 26 +++++--- dlog/precomp_clear.c | 2 + dlog/precomp_n_init.c | 2 +- 10 files changed, 89 insertions(+), 151 deletions(-) rename dlog/{1modpe_rec.c => 1modpe.c} (94%) rename dlog/{1modpe_rec_init.c => 1modpe_init.c} (94%) delete mode 100644 dlog/1modpe_padic.c rename dlog/{1modpe_padic_init.c => mod2e.c} (60%) diff --git a/dlog.h b/dlog.h index 1512d56c..cb6a9202 100644 --- a/dlog.h +++ b/dlog.h @@ -26,15 +26,14 @@ #ifndef DLOG_H #define DLOG_H -#ifdef ACB_INLINES_C -#define ACB_INLINE +#ifdef DLOG_INLINES_C +#define DLOG_INLINE #else -#define ACB_INLINE static __inline__ +#define DLOG_INLINE static __inline__ #endif -#include "ulong_extras.h" -#include "nmod_vec.h" -#include "padic.h" +#include "flint/ulong_extras.h" +#include "flint/nmod_vec.h" enum { @@ -44,25 +43,17 @@ enum typedef struct dlog_precomp_struct dlog_precomp_struct; typedef struct dlog_precomp_struct * dlog_precomp_ptr; -/* log in (1+pZ/p^eZ), e large: compute via p-adic log */ -typedef struct -{ - padic_ctx_t ctx; /* padic context */ - padic_t invlog; /* 1 / log_p(a^(p-1)) */ -} -dlog_1modpe_padic_struct; - -typedef dlog_1modpe_padic_struct dlog_1modpe_padic_t[1]; - -/* log in (1+pZ/p^eZ), e small: use recursion formulas */ +/* log in (1+pZ/p^eZ), e small: use recursion formulas + * could use padic log instead but exponent is small + * for ulongs */ typedef struct { ulong inv1p; /* 1 / (1 + p) */ ulong invloga1; /* 1 / log(a^(p-1),1+p) */ } -dlog_1modpe_rec_struct; +dlog_1modpe_struct; -typedef dlog_1modpe_rec_struct dlog_1modpe_rec_t[1]; +typedef dlog_1modpe_struct dlog_1modpe_t[1]; /* log in (Z/p^eZ)^* */ typedef struct @@ -73,10 +64,7 @@ typedef struct ulong inva; nmod_t pe; dlog_precomp_struct * modp; - union { - dlog_1modpe_rec_t rec; /* if e <= 3 && e < p */ - dlog_1modpe_padic_t padic; /* otherwise */ - } modpe; + dlog_1modpe_t modpe; } dlog_modpe_struct; @@ -114,10 +102,10 @@ typedef dlog_bsgs_struct dlog_bsgs_t[1]; /* Pollard rho */ typedef struct { - ulong a; - nmod_t n; - nmod_t mod; - int nisprime; + ulong a; + nmod_t n; + nmod_t mod; + int nisprime; } dlog_rho_struct; typedef dlog_rho_struct dlog_rho_t[1]; @@ -186,33 +174,25 @@ ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num); ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num); ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num); ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m); -void dlog_1modpe_rec_init(dlog_1modpe_rec_t t, ulong a1, ulong p, ulong e, nmod_t pe); -void dlog_1modpe_padic_init(dlog_1modpe_padic_t t, ulong a1, ulong p, ulong e); +void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e, nmod_t pe); void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n); /*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ -ACB_INLINE void +DLOG_INLINE void dlog_order23_clear(dlog_order23_t t) { return; } -ACB_INLINE void +DLOG_INLINE void dlog_table_clear(dlog_table_t t) { - flint_free(t->table); -} - -ACB_INLINE void -dlog_1modpe_padic_clear(dlog_1modpe_padic_t t) -{ - padic_clear(t->invlog); - padic_ctx_clear(t->ctx); + flint_free(t->table); } void dlog_crt_clear(dlog_crt_t t); -ACB_INLINE void +DLOG_INLINE void dlog_power_clear(dlog_power_t t) { flint_free(t->apk); @@ -220,25 +200,23 @@ dlog_power_clear(dlog_power_t t) flint_free(t->pre); } -ACB_INLINE void +DLOG_INLINE void dlog_modpe_clear(dlog_modpe_t t) { - dlog_precomp_clear(t->modp); - if (0 && t->e > 2) - dlog_1modpe_padic_clear(t->modpe.padic); - flint_free(t->modp); + dlog_precomp_clear(t->modp); + flint_free(t->modp); } -ACB_INLINE void +DLOG_INLINE void dlog_bsgs_clear(dlog_bsgs_t t) { flint_free(t->table); } -ACB_INLINE void +DLOG_INLINE void dlog_rho_clear(dlog_rho_t t) { - return; + return; } /*#define dlog_bsgs_clear(t) bsgs_table_clear(t)*/ @@ -247,11 +225,11 @@ ulong dlog_table(const dlog_table_t t, ulong b); ulong dlog_crt(const dlog_crt_t t, ulong b); ulong dlog_power(const dlog_power_t t, ulong b); ulong dlog_modpe(const dlog_modpe_t t, ulong b); +ulong dlog_mod2e(const dlog_modpe_t t, ulong b); ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); ulong dlog_rho(const dlog_rho_t t, ulong b); ulong dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe); -ulong dlog_1modpe_padic(const dlog_1modpe_padic_t t, ulong b1); -ulong dlog_1modpe_rec(const dlog_1modpe_rec_t t, ulong b1, ulong p, ulong e, nmod_t pe); +ulong dlog_1modpe(const dlog_1modpe_t t, ulong b1, ulong p, ulong e, nmod_t pe); /*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ #define DLOG_SMALL_LIM 50 diff --git a/dlog/1modpe_rec.c b/dlog/1modpe.c similarity index 94% rename from dlog/1modpe_rec.c rename to dlog/1modpe.c index 05960fc4..cf40d58e 100644 --- a/dlog/1modpe_rec.c +++ b/dlog/1modpe.c @@ -26,7 +26,7 @@ #include "dlog.h" ulong -dlog_1modpe_rec(const dlog_1modpe_rec_t t, ulong b1, ulong p, ulong e, nmod_t pe) +dlog_1modpe(const dlog_1modpe_t t, ulong b1, ulong p, ulong e, nmod_t pe) { if (e == 1) return 0; diff --git a/dlog/1modpe_rec_init.c b/dlog/1modpe_init.c similarity index 94% rename from dlog/1modpe_rec_init.c rename to dlog/1modpe_init.c index 180b32b2..2a942143 100644 --- a/dlog/1modpe_rec_init.c +++ b/dlog/1modpe_init.c @@ -26,7 +26,7 @@ #include "dlog.h" void -dlog_1modpe_rec_init(dlog_1modpe_rec_t t, ulong a1, ulong p, ulong e, nmod_t pe) +dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e, nmod_t pe) { if (e == 1) { diff --git a/dlog/1modpe_mod1p.c b/dlog/1modpe_mod1p.c index 293f2e66..e8427f19 100644 --- a/dlog/1modpe_mod1p.c +++ b/dlog/1modpe_mod1p.c @@ -25,6 +25,7 @@ #include "dlog.h" +/* for odd prime p, assume b1 = 1 mod p */ ulong dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe) { @@ -36,7 +37,11 @@ dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe) for (f = 1; f < e; f++) { if (b1 % pf != 1) + { + flint_printf("ERROR dlog_1modpe_1modp: %wu %% %wu != 1 mod %wu\n\n", + b1, pf, pe.n); abort(); + } xf = (b1 - 1) / pf; xf = (xf % p) * pf1; x += xf; diff --git a/dlog/1modpe_padic.c b/dlog/1modpe_padic.c deleted file mode 100644 index 6083e03b..00000000 --- a/dlog/1modpe_padic.c +++ /dev/null @@ -1,63 +0,0 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2016 Pascal Molin - -******************************************************************************/ - -#include "dlog.h" - -/* assume b = 1 mod p, not checked */ -ulong -dlog_1modpe_padic(const dlog_1modpe_padic_t t, ulong b1) -{ - padic_t px; - fmpz_t ix; - ulong ux; - - if (b1 == 1) - return 0; - - padic_init(px); - fmpz_init(ix); - - padic_set_ui(px, b1, t->ctx); - flint_printf("set %wu -> ", b1); - padic_print(px, t->ctx); - - padic_log(px, px, t->ctx); - flint_printf("\n\n compute log -> "); - padic_print(px, t->ctx); - - flint_printf("\n\n 1/log(a^(p-1)) -> "); - padic_print(t->invlog, t->ctx); - - padic_mul(px, px, t->invlog, t->ctx); - flint_printf("\n\n divide by log(a^(p-1)) -> "); - padic_print(px, t->ctx); - - padic_get_fmpz(ix, px, t->ctx); - ux = fmpz_get_ui(ix); - flint_printf("\n\nlog_p(%wu)/log_p(a) = %wu\n", b1, ux); - padic_clear(px); - fmpz_clear(ix); - return ux; -} diff --git a/dlog/1modpe_padic_init.c b/dlog/mod2e.c similarity index 60% rename from dlog/1modpe_padic_init.c rename to dlog/mod2e.c index de4579d2..8622949c 100644 --- a/dlog/1modpe_padic_init.c +++ b/dlog/mod2e.c @@ -25,23 +25,33 @@ #include "dlog.h" -void -dlog_1modpe_padic_init(dlog_1modpe_padic_t t, ulong a1, ulong p, ulong e) +ulong +dlog_mod2e(const dlog_modpe_t t, ulong b1) { - fmpz_t tmp; - - fmpz_init(tmp); - padic_init(t->invlog); - - fmpz_set_ui(tmp, p); - padic_ctx_init(t->ctx , tmp , 0 , e, PADIC_SERIES); - - padic_set_ui(t->invlog, a1, t->ctx); - flint_printf("set %wu -> ", a1); - flint_printf("\n\n compute log -> "); - padic_log(t->invlog, t->invlog, t->ctx); - padic_print(t->invlog, t->ctx); - padic_inv(t->invlog, t->invlog, t->ctx); - - fmpz_clear(tmp); + if (t->e == 2) + return (b1 % 4) == 3; + else + { + slong f; + ulong pf1, pf, x, xf; + pf1 = 1; + pf = 4; + x = 0; + for (f = 2; f < t->e; f++) + { + if (b1 % pf != 1) + { + flint_printf("ERROR dlog_mod2e: %wu %% %wu != 1 mod %wu\n\n", + b1, pf, t->pe.n); + abort(); + } + xf = (b1 - 1) / pf; + xf = (f == 2) ? xf % 4 : (xf % 2) * (pf1 / 2); + b1 = nmod_mul(b1, nmod_pow_ui(t->inva, xf, t->pe), t->pe); + x += xf; + pf1 = pf; + pf *= 2; + } + return x; + } } diff --git a/dlog/modpe.c b/dlog/modpe.c index 09264ef9..742e3f8a 100644 --- a/dlog/modpe.c +++ b/dlog/modpe.c @@ -29,23 +29,21 @@ ulong dlog_modpe(const dlog_modpe_t t, ulong b) { ulong x; + if (t->p == 2) + return dlog_mod2e(t, b); x = dlog_precomp(t->modp, b % t->p); if (t->e > 1) { ulong b1, y; #if 0 b1 = nmod_mul(b, nmod_pow_ui(t->inva, x, t->pe), t->pe); -#else - b1 = nmod_pow_ui(b, t->p - 1, t->pe); -#endif - if (1 || t->e <= 2) - y = dlog_1modpe_rec(t->modpe.rec, b1, t->p, t->e, t->pe); - else - y = dlog_1modpe_padic(t->modpe.padic, b1); + y = dlog_1modpe(t->modpe.rec, b1, t->p, t->e, t->pe); y = y % t->pe1; -#if 0 x = x + (t->p - 1) * y; #else + b1 = nmod_pow_ui(b, t->p - 1, t->pe); + y = dlog_1modpe(t->modpe, b1, t->p, t->e, t->pe); + y = y % t->pe1; x = n_submod(x, y % (t->p - 1), t->p - 1); x = y + t->pe1 * x; #endif diff --git a/dlog/modpe_init.c b/dlog/modpe_init.c index 40b820fa..dfd68c15 100644 --- a/dlog/modpe_init.c +++ b/dlog/modpe_init.c @@ -32,18 +32,26 @@ dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) t->p = p; t->e = e; - t->pe1 = pe / p; nmod_init(&t->pe, pe); t->inva = nmod_inv(a, t->pe); - t->modp = flint_malloc(sizeof(dlog_precomp_struct)); - dlog_precomp_n_init(t->modp, a, p, p - 1, num); - - a1 = nmod_pow_ui(a, p - 1, t->pe); - if (1 || e <= 2) - dlog_1modpe_rec_init(t->modpe.rec, a1, p, e, t->pe); + if (p == 2) + { + t->modp = NULL; + t->pe1 = (e <= 2) ? 2 : pe / 4; + t->modpe->inv1p = t->inva; + t->modpe->invloga1 = 1; + return e - 2; + } else - dlog_1modpe_padic_init(t->modpe.padic, a1, p, e); + { + t->modp = flint_malloc(sizeof(dlog_precomp_struct)); + t->pe1 = pe / p; + dlog_precomp_n_init(t->modp, a, p, p - 1, num); - return t->modp->cost + e; + a1 = nmod_pow_ui(a, p - 1, t->pe); + dlog_1modpe_init(t->modpe, a1, p, e, t->pe); + + return t->modp->cost + e; + } } diff --git a/dlog/precomp_clear.c b/dlog/precomp_clear.c index 64bf402d..bcae2e6e 100644 --- a/dlog/precomp_clear.c +++ b/dlog/precomp_clear.c @@ -28,6 +28,8 @@ void dlog_precomp_clear(dlog_precomp_t pre) { + if (pre == NULL) + return; switch (pre->type) { case DLOG_MODPE: diff --git a/dlog/precomp_n_init.c b/dlog/precomp_n_init.c index de430399..dd68d08d 100644 --- a/dlog/precomp_n_init.c +++ b/dlog/precomp_n_init.c @@ -30,7 +30,7 @@ void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) { - if (n%2 && n_is_probabprime(n)) + if (n % 2 && n_is_probabprime(n)) dlog_precomp_p_init(pre, a, mod, n, num); else { if (n < DLOG_TABLE_N_LIM) From 8bd17e2746c4d0a8e989cbb7d3e6471888b85e67 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 29 Mar 2016 12:52:26 +0100 Subject: [PATCH 026/139] some formatting on dlog --- dlog.h | 16 +++++-- dlog/1modpe_mod1p.c | 2 +- dlog/bsgs.c | 2 +- dlog/factor_group.c | 8 +++- dlog/modpe.c | 3 ++ dlog/modpe_init.c | 1 + dlog/power.c | 5 ++- dlog/precomp_n_init.c | 2 +- dlog/precomp_p_init.c | 2 +- dlog/precomp_small_init.c | 2 +- dlog/profile/p-precomp.c | 5 +-- dlog/profile/p-vec.c | 11 +++-- dlog/rho.c | 18 +++++++- dlog/rho_init.c | 8 ++-- dlog/table_init.c | 28 ++++++------ dlog/test/t-dlog.c | 4 +- dlog/test/t-modpe.c | 92 +++++++++++++++++++++++++++++++++++++++ dlog/test/t-vec.c | 8 +++- dlog/vec.c | 2 +- dlog/vec_add.c | 2 +- dlog/vec_eratos_add.c | 12 +++-- dlog/vec_loop.c | 2 +- dlog/vec_loop_add.c | 2 +- dlog/vec_sieve.c | 11 +++-- 24 files changed, 196 insertions(+), 52 deletions(-) create mode 100644 dlog/test/t-modpe.c diff --git a/dlog.h b/dlog.h index cb6a9202..33507f89 100644 --- a/dlog.h +++ b/dlog.h @@ -218,6 +218,16 @@ dlog_rho_clear(dlog_rho_t t) { return; } + +DLOG_INLINE ulong +dlog_bsgs_size(ulong n, ulong num) +{ + if (2 * num < n) + return (1 + n_sqrt(n)) * (1 + n_sqrt(num)); + else + return n; +} + /*#define dlog_bsgs_clear(t) bsgs_table_clear(t)*/ ulong dlog_order23(const dlog_order23_t t, ulong b); @@ -240,9 +250,9 @@ ulong dlog_1modpe(const dlog_1modpe_t t, ulong b1, ulong p, ulong e, nmod_t pe); #define DLOG_TABLE_N_LIM 50 #define DLOG_BSGS_LIM 500 -#define LOOP_MAX_FACTOR 6 -#define G_SMALL 0 -#define G_BIG 1 +#define DLOG_LOOP_MAX_FACTOR 6 +#define DLOG_G_SMALL 0 +#define DLOG_G_BIG 1 void dlog_n_factor_group(n_factor_t * fac, ulong bound); #define DLOG_NOT_FOUND UWORD_MAX diff --git a/dlog/1modpe_mod1p.c b/dlog/1modpe_mod1p.c index e8427f19..c1ec0a9d 100644 --- a/dlog/1modpe_mod1p.c +++ b/dlog/1modpe_mod1p.c @@ -35,7 +35,7 @@ dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe) pf = p; x = 0; for (f = 1; f < e; f++) - { + { if (b1 % pf != 1) { flint_printf("ERROR dlog_1modpe_1modp: %wu %% %wu != 1 mod %wu\n\n", diff --git a/dlog/bsgs.c b/dlog/bsgs.c index 0f85c679..6cd4f62f 100644 --- a/dlog/bsgs.c +++ b/dlog/bsgs.c @@ -41,7 +41,7 @@ dlog_bsgs(const dlog_bsgs_t t, ulong b) return i * t->m + x->k; c.ak = nmod_mul(c.ak, t->am, t->mod); } - flint_printf("Exception (n_discrete_log_bsgs). discrete log not found.\n"); + flint_printf("Exception (dlog_bsgs). discrete log not found.\n"); flint_printf(" table size %wu, cosize %wu mod %wu. %wu not found (a^-m=%wu)\n", t->m, t->g, t->mod.n, b, t->am); abort(); diff --git a/dlog/factor_group.c b/dlog/factor_group.c index 65bb43e8..06349c38 100644 --- a/dlog/factor_group.c +++ b/dlog/factor_group.c @@ -33,6 +33,7 @@ dlog_n_factor_group(n_factor_t * fac, ulong bound) ulong m[FLINT_MAX_FACTORS_IN_LIMB]; ulong c = 1; i = 0; + for (k = fac->num - 1; k >= 0; k--) { ulong qe = n_pow(fac->p[k], fac->exp[k]); @@ -48,16 +49,19 @@ dlog_n_factor_group(n_factor_t * fac, ulong bound) m[j] *= qe; } } + for (j = 0; j < i; j++) { fac->p[j] = m[j]; - fac->exp[j] = G_SMALL; + fac->exp[j] = DLOG_G_SMALL; } + if (c > 1) { fac->p[i] = c; - fac->exp[i] = G_BIG; + fac->exp[i] = DLOG_G_BIG; i++; } + fac->num = i; } diff --git a/dlog/modpe.c b/dlog/modpe.c index 742e3f8a..eeaca2ac 100644 --- a/dlog/modpe.c +++ b/dlog/modpe.c @@ -31,7 +31,9 @@ dlog_modpe(const dlog_modpe_t t, ulong b) ulong x; if (t->p == 2) return dlog_mod2e(t, b); + x = dlog_precomp(t->modp, b % t->p); + if (t->e > 1) { ulong b1, y; @@ -48,5 +50,6 @@ dlog_modpe(const dlog_modpe_t t, ulong b) x = y + t->pe1 * x; #endif } + return x; } diff --git a/dlog/modpe_init.c b/dlog/modpe_init.c index dfd68c15..6332e2e1 100644 --- a/dlog/modpe_init.c +++ b/dlog/modpe_init.c @@ -25,6 +25,7 @@ #include "dlog.h" +/* todo: recursion could be made quadratic (not very useful for ulongs) */ ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) { diff --git a/dlog/power.c b/dlog/power.c index 6e5689c4..0096352a 100644 --- a/dlog/power.c +++ b/dlog/power.c @@ -32,10 +32,12 @@ dlog_power(const dlog_power_t t, ulong b) ulong x, pk[30]; /* 3^30*2+1, 2^30*3+1 are primes */ pk[0] = 1; + for (k = 1; k < t->e; k++) pk[k] = pk[k-1] * t->p; - + x = 0; + for(k = 0; k < t->e; k++) { ulong bk, xk; @@ -44,5 +46,6 @@ dlog_power(const dlog_power_t t, ulong b) b = nmod_mul(b, nmod_pow_ui(t->apk[k], xk, t->mod), t->mod); x += xk * pk[k]; /* cannot overflow */ } + return x; } diff --git a/dlog/precomp_n_init.c b/dlog/precomp_n_init.c index dd68d08d..787f020f 100644 --- a/dlog/precomp_n_init.c +++ b/dlog/precomp_n_init.c @@ -42,7 +42,7 @@ dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) if (n < DLOG_BSGS_LIM) { ulong m; - m = (2 * num < n) ? ceil(sqrt((double) n * num)) : n; + m = dlog_bsgs_size(n, num); pre->type = DLOG_BSGS; pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, n, m); } else { diff --git a/dlog/precomp_p_init.c b/dlog/precomp_p_init.c index 2aa972b3..193c55cf 100644 --- a/dlog/precomp_p_init.c +++ b/dlog/precomp_p_init.c @@ -37,7 +37,7 @@ dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) else { ulong m; - m = (2 * num < p) ? ceil(sqrt((double) p * num)) : p; + m = dlog_bsgs_size(p, num); pre->type = DLOG_BSGS; pre->cost = dlog_bsgs_init(pre->t.bsgs, a, mod, p, m); } diff --git a/dlog/precomp_small_init.c b/dlog/precomp_small_init.c index 7c792e63..6309682e 100644 --- a/dlog/precomp_small_init.c +++ b/dlog/precomp_small_init.c @@ -31,7 +31,7 @@ dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong n if (n <= 3) { pre->type = DLOG_23; - pre->cost = dlog_order23_init(pre->t.order23, a); + pre->cost = dlog_order23_init(pre->t.order23, a); } else { diff --git a/dlog/profile/p-precomp.c b/dlog/profile/p-precomp.c index c3e21891..0000cb20 100644 --- a/dlog/profile/p-precomp.c +++ b/dlog/profile/p-precomp.c @@ -53,7 +53,7 @@ flog_bsgs(ulong p, ulong a, ulong num) { int k; dlog_bsgs_t t; - dlog_bsgs_init(t, a, p, p-1, ceil( sqrt((double)num * p))); + dlog_bsgs_init(t, a, p, p-1, dlog_bsgs_size(p, num)); for (k = 1; k < num; k++) { if (k % p == 0) continue; @@ -134,7 +134,7 @@ int main() } for (i = 0; i < nl; i++) - { + { int f; #if OUT == LOG flint_printf("%d * logs mod primes of size %d.....\n", l[i], nbits); @@ -144,7 +144,6 @@ int main() { int j; - /* skip useless */ if (f == 0 && nbits >= 20) continue; diff --git a/dlog/profile/p-vec.c b/dlog/profile/p-vec.c index 401323c6..cff9d199 100644 --- a/dlog/profile/p-vec.c +++ b/dlog/profile/p-vec.c @@ -34,7 +34,7 @@ typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); - + void f_empty(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) { @@ -69,6 +69,7 @@ int main() for (i = 0; i < ni; i++) { + for (k = 0; k < np; k++) { nmod_init(&p[k], n_randprime(state, bits[i], 0)); @@ -86,12 +87,12 @@ int main() #endif for (l = 0; l < nf; l++) - { + { if (l == 1 && i > 2) continue; if (l == 2 && i > 5) continue; - + #if OUT == LOG flint_printf("%-20s... ",n[l]); fflush(stdout); @@ -103,13 +104,17 @@ int main() #endif TIMEIT_ONCE_START + for (k = 0; k < np; k++) { int kk; + for (kk=0; kk < nv[j]; kk++) v[kk] = 0; + (func[l])(v, nv[j], a[k], 1, p[k], p[k].n - 1, order); } + TIMEIT_ONCE_STOP #if OUT == JSON diff --git a/dlog/rho.c b/dlog/rho.c index 96766135..3f0eee30 100644 --- a/dlog/rho.c +++ b/dlog/rho.c @@ -33,16 +33,20 @@ dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) { int k; ulong ak = 1; + for (k=0; k < n; k++) { if (ak == b) return k; ak = nmod_mul(ak, a, mod); } + flint_printf("FAIL[dlog once]: log(%wu,%wu) mod %wu not found (size %wu)\n", b, a, mod.n, n); abort(); - } else { + } + else + { dlog_rho_t t; dlog_rho_init(t, a, mod.n, n); return dlog_rho(t, b); @@ -55,18 +59,21 @@ dlog_quotient(const dlog_rho_t t, ulong e, ulong f, ulong g, ulong b) { ulong r, b_ar, an; nmod_t n = t->n; + if (g == n.n) { flint_printf("FAIL[dlog quotient]: trivial relation e = %wu, f = %wu mod %wu\n", e, f, n.n); abort(); } + nmod_init(&n, n.n / g); e = e / g; f = f / g; r = nmod_div(e, f, n); an = nmod_pow_ui(t->a, n.n, t->mod); b_ar = nmod_div(b, nmod_pow_ui(t->a, r, t->mod), t->mod); + return r + n.n * dlog_once(b_ar, an, t->mod, g); } @@ -80,18 +87,23 @@ dlog_rho(const dlog_rho_t t, ulong b) flint_rand_t state; flint_randinit(state); + do { + for (k = 0; k < RWALK; k++) { m[k] = 1 + n_randint(state, t->n.n - 1); n[k] = 1 + n_randint(state, t->n.n - 1); ab[k] = nmod_mul(nmod_pow_ui(t->a, m[k], t->mod), nmod_pow_ui(b, n[k], t->mod), t->mod); } + /* x[l] = a^e[l] * b^f[l] */ x[0] = x[1] = 1; e[0] = e[1] = 0; f[0] = f[1] = 0; + do { + for(j = 0; j < 3; j++) { l = (j > 0); @@ -100,13 +112,17 @@ dlog_rho(const dlog_rho_t t, ulong b) e[l] = nmod_add(e[l], m[k], t->n); f[l] = nmod_add(f[l], n[k], t->n); } + } while (x[0] != x[1]); + } while (e[0] == e[1] && f[0] == f[1]); + flint_randclear(state); /* e = f * log(b) */ e[0] = nmod_sub(e[0], e[1], t->n); f[0] = nmod_sub(f[1], f[0], t->n); + if (!t->nisprime && (g = n_gcd(f[0], t->n.n)) > 1) return dlog_quotient(t, e[0], f[0], g, b); else diff --git a/dlog/rho_init.c b/dlog/rho_init.c index 99210795..ae34a392 100644 --- a/dlog/rho_init.c +++ b/dlog/rho_init.c @@ -29,8 +29,8 @@ void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) { - t->a = a; - nmod_init(&t->n, n); - nmod_init(&t->mod, mod); - t->nisprime = n_is_prime(n); + t->a = a; + nmod_init(&t->n, n); + nmod_init(&t->mod, mod); + t->nisprime = n_is_prime(n); } diff --git a/dlog/table_init.c b/dlog/table_init.c index b04e0c74..54fd707f 100644 --- a/dlog/table_init.c +++ b/dlog/table_init.c @@ -29,17 +29,19 @@ ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod) { - int k; - ulong ak; - t->mod = mod; - t->table = flint_malloc(mod * sizeof(ulong)); - ak = 1; k = 0; - /* warning: do not check a is invertible modulo mod */ - do - { - t->table[ak] = k++; - ak = (ak * a) % mod; - } - while (ak != 1); - return 1; + int k; + ulong ak; + t->mod = mod; + t->table = flint_malloc(mod * sizeof(ulong)); + ak = 1; k = 0; + + /* warning: do not check a is invertible modulo mod */ + do + { + t->table[ak] = k++; + ak = (ak * a) % mod; + } + + while (ak != 1); + return 1; } diff --git a/dlog/test/t-dlog.c b/dlog/test/t-dlog.c index 020b43a1..a3b9f1fd 100644 --- a/dlog/test/t-dlog.c +++ b/dlog/test/t-dlog.c @@ -31,7 +31,7 @@ int main() slong iter; flint_rand_t state; - flint_printf("dlog mod p...."); + flint_printf("dlog...."); fflush(stdout); flint_randinit(state); @@ -47,7 +47,7 @@ int main() a = n_primitive_root_prime(p); dlog_table_init(table, a, p); - dlog_bsgs_init(bsgs, a, p, p-1, ceil(sqrt((double)p))); + dlog_bsgs_init(bsgs, a, p, p-1, dlog_bsgs_size(p, 1)); dlog_rho_init(rho, a, p, p-1); dlog_precomp_n_init(pre1, a, p, p-1, 1); dlog_precomp_n_init(pre100, a, p, p-1, 100); diff --git a/dlog/test/t-modpe.c b/dlog/test/t-modpe.c new file mode 100644 index 00000000..e828dee0 --- /dev/null +++ b/dlog/test/t-modpe.c @@ -0,0 +1,92 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "dlog.h" +#include + +int main() +{ + slong iter; + flint_rand_t state; + + flint_printf("modpe...."); + fflush(stdout); + flint_randinit(state); + + for (iter = 0; iter < 1000; iter++) + { + ulong p, e, pe, a; + + if (iter == 0) + { + p = 2; + pe = 8; + a = 5; + e = 3; + } + else + { + p = pe = n_randprime(state, 10, 0); + a = (p == 40487) ? 10 : n_primitive_root_prime(p); + e = 1; + } + + for (; pe < UWORD(1000000000000); pe *= p, e++) + { + ulong k, phi; + nmod_t mod; + + dlog_modpe_t modpe; + + nmod_init(&mod, pe); + phi = (p == 2) ? pe / 4 : pe - pe / p; + + dlog_modpe_init(modpe, a, p, e, pe, 10); + + for (k = 0; k < 100 && k < p; k++) + { + ulong l, b, x; + + l = n_randint(state, phi); + b = nmod_pow_ui(a, l, mod); + + if ((x = dlog_modpe(modpe, b)) != l) + { + flint_printf("FAIL modpe: %wu^%wu = %wu [%wu^%wu]\n\n", + a, l, b, p, e); + flint_printf("modpe returned %wu\n\n", x); + abort(); + } + } + + dlog_modpe_clear(modpe); + } + } + + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/dlog/test/t-vec.c b/dlog/test/t-vec.c index ecfb0146..2a766f61 100644 --- a/dlog/test/t-vec.c +++ b/dlog/test/t-vec.c @@ -26,7 +26,7 @@ #include "dlog.h" typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); - + void dlog_vec_trivial(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order) { @@ -61,12 +61,13 @@ int main() char * n[4] = { "trivial", "loop", "eratos", "sieve" }; - flint_printf("dlog(1..n) mod p...."); + flint_printf("vec...."); fflush(stdout); flint_randinit(state); for (bits = 10; bits <= 35; bits += 5) { + for (nv = 10; nv <= 10000; nv *= 10) { @@ -108,10 +109,13 @@ int main() abort(); } } + } + flint_free(ref); flint_free(v); } + } flint_randclear(state); flint_cleanup(); diff --git a/dlog/vec.c b/dlog/vec.c index a4fb8da5..54e09a57 100644 --- a/dlog/vec.c +++ b/dlog/vec.c @@ -28,7 +28,7 @@ void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - if (na * LOOP_MAX_FACTOR > nv) + if (na * DLOG_LOOP_MAX_FACTOR > nv) dlog_vec_loop(v, nv, a, va, mod, na, order); else dlog_vec_sieve(v, nv, a, va, mod, na, order); diff --git a/dlog/vec_add.c b/dlog/vec_add.c index 49e6f713..56c301e5 100644 --- a/dlog/vec_add.c +++ b/dlog/vec_add.c @@ -28,7 +28,7 @@ void dlog_vec_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - if (na * LOOP_MAX_FACTOR > nv) + if (na * DLOG_LOOP_MAX_FACTOR > nv) dlog_vec_loop_add(v, nv, a, va, mod, na, order); else dlog_vec_sieve_add(v, nv, a, va, mod, na, order); diff --git a/dlog/vec_eratos_add.c b/dlog/vec_eratos_add.c index 4725fc51..afedac31 100644 --- a/dlog/vec_eratos_add.c +++ b/dlog/vec_eratos_add.c @@ -38,20 +38,26 @@ dlog_vec_eratos_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, dlog_precomp_n_init(pre, a, mod.n, na, n_prime_pi(n)); n_primes_init(iter); + while ((p = n_primes_next(iter)) < n) - { - ulong wp, pe; + { + ulong wp, pe; + if (v[p] == DLOG_NOT_FOUND) continue; /* won't be attained another time */ wp = nmod_mul(dlog_precomp(pre, p), va, order); - /* fixme: could be faster sieving m*pe? but cannot + + /* FIXME: could be faster sieving m*pe? but cannot * use v[p*m]=v[p]*v[m]... */ for (pe = p; pe < n; pe *= p) for (k = pe; k < n; k += pe) if (v[k] != DLOG_NOT_FOUND) v[k] = nmod_add(v[k], wp, order); + } + n_primes_clear(iter); + for (k = mod.n + 1; k < nv; k++) v[k] = v[k - mod.n]; } diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index e50fb2f3..d3e568fb 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -25,7 +25,7 @@ #include "dlog.h" -/* vector of log(k,a)*loga % order in Z/modZ */ +/* vector of log(k,a)*loga % order in Z/modZ */ void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { diff --git a/dlog/vec_loop_add.c b/dlog/vec_loop_add.c index de03e7ab..bae5a40d 100644 --- a/dlog/vec_loop_add.c +++ b/dlog/vec_loop_add.c @@ -25,7 +25,7 @@ #include "dlog.h" -/* vector of log(k,a)*loga % order in Z/modZ */ +/* vector of log(k,a)*loga % order in Z/modZ */ void dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index a2e08e2e..d223239d 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -60,17 +60,16 @@ dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); } - /* find big power of gen */ - X = n_nextprime(na / 2 + 10, 0); - X = (na % 257) ? 257 % na : 1031 % na ; /* FIXME! */ + /* take big power of gen */ + X = n_nextprime(3 * na / 2, 0) % na; aX = nmod_pow_ui(a, X, mod); vaX = nmod_mul(va, X % order.n, order); n_primes_init(iter); while ((p = n_primes_next(iter)) < pmax) - { - double cost = log(mod.n)/log(p); - ulong m, vp; + { + double cost; + ulong m, vp; if (mod.n % p == 0) continue; /* won't be attained another time */ cost = log(mod.n)/log(p); From 4f9ef0f0c68d39f2301280e73b4745500a567626 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 29 Mar 2016 14:04:08 +0100 Subject: [PATCH 027/139] test characters --- acb_dirichlet.h | 12 +-- acb_dirichlet/acb_chi.c | 2 +- acb_dirichlet/acb_pairing.c | 2 +- acb_dirichlet/acb_pairing_conrey.c | 2 +- acb_dirichlet/char.c | 8 +- acb_dirichlet/char_clear.c | 3 +- acb_dirichlet/char_conrey.c | 16 +-- acb_dirichlet/char_first_primitive.c | 12 +-- acb_dirichlet/char_init.c | 5 +- acb_dirichlet/char_next.c | 28 +++--- acb_dirichlet/char_next_primitive.c | 58 +++++------ acb_dirichlet/char_normalize.c | 26 +++-- acb_dirichlet/char_one.c | 14 +-- acb_dirichlet/char_print.c | 8 +- acb_dirichlet/chi_vec_loop.c | 7 +- acb_dirichlet/chi_vec_primeloop.c | 43 ++++---- acb_dirichlet/chi_vec_sieve.c | 5 +- acb_dirichlet/conrey_next_primitive.c | 46 +++++---- acb_dirichlet/group_dlog_precompute.c | 2 +- acb_dirichlet/pairing.c | 2 +- acb_dirichlet/pairing_conrey.c | 12 ++- acb_dirichlet/profile/p-vec.c | 3 +- acb_dirichlet/test/t-chars.c | 140 ++++++++++++++++++++++++++ acb_dirichlet/test/t-thetanull.c | 5 +- acb_dirichlet/vec_set_null.c | 26 ++--- 25 files changed, 327 insertions(+), 160 deletions(-) create mode 100644 acb_dirichlet/test/t-chars.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index fb1e7c2a..4763d53a 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -14,10 +14,10 @@ #ifndef ACB_DIRICHLET_H #define ACB_DIRICHLET_H -#ifdef ACB_INLINES_C -#define ACB_INLINE +#ifdef ACB_DIRICHLET_INLINES_C +#define ACB_DIRICHLET_INLINE #else -#define ACB_INLINE static __inline__ +#define ACB_DIRICHLET_INLINE static __inline__ #endif #include "acb.h" @@ -82,7 +82,7 @@ void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_di int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); -#define CHI_NULL UWORD_MAX +#define ACB_DIRICHLET_CHI_NULL UWORD_MAX ulong acb_dirichlet_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); ulong acb_dirichlet_pairing(const acb_dirichlet_group_t G, ulong m, ulong n); @@ -105,13 +105,13 @@ acb_dirichlet_char_struct; typedef acb_dirichlet_char_struct acb_dirichlet_char_t[1]; -ACB_INLINE int +ACB_DIRICHLET_INLINE int acb_dirichlet_char_order(const acb_dirichlet_char_t chi) { return chi->order; } -ACB_INLINE int +ACB_DIRICHLET_INLINE int acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) { return chi->parity; diff --git a/acb_dirichlet/acb_chi.c b/acb_dirichlet/acb_chi.c index 82a6835c..b1b36aef 100644 --- a/acb_dirichlet/acb_chi.c +++ b/acb_dirichlet/acb_chi.c @@ -32,7 +32,7 @@ acb_dirichlet_acb_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirich { ulong expo; expo = acb_dirichlet_chi(G, chi, n); - if (expo == CHI_NULL) + if (expo == ACB_DIRICHLET_CHI_NULL) acb_zero(res); else { diff --git a/acb_dirichlet/acb_pairing.c b/acb_dirichlet/acb_pairing.c index aebabe54..84e65e66 100644 --- a/acb_dirichlet/acb_pairing.c +++ b/acb_dirichlet/acb_pairing.c @@ -31,7 +31,7 @@ acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulo { ulong expo; expo = acb_dirichlet_pairing(G, m, n); - if (expo == CHI_NULL) + if (expo == ACB_DIRICHLET_CHI_NULL) acb_zero(res); else { diff --git a/acb_dirichlet/acb_pairing_conrey.c b/acb_dirichlet/acb_pairing_conrey.c index 69e7134e..528e6f3d 100644 --- a/acb_dirichlet/acb_pairing_conrey.c +++ b/acb_dirichlet/acb_pairing_conrey.c @@ -30,7 +30,7 @@ acb_dirichlet_acb_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const { ulong expo; expo = acb_dirichlet_pairing_conrey(G, a, b); - if (expo == CHI_NULL) + if (expo == ACB_DIRICHLET_CHI_NULL) acb_zero(res); else { diff --git a/acb_dirichlet/char.c b/acb_dirichlet/char.c index f850acc6..9309fc79 100644 --- a/acb_dirichlet/char.c +++ b/acb_dirichlet/char.c @@ -28,8 +28,8 @@ void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) { - acb_dirichlet_conrey_t x; - x->log = chi->expo; - acb_dirichlet_conrey_log(x, G, n); - acb_dirichlet_char_conrey(chi, G, x); + acb_dirichlet_conrey_t x; + x->log = chi->expo; + acb_dirichlet_conrey_log(x, G, n); + acb_dirichlet_char_conrey(chi, G, x); } diff --git a/acb_dirichlet/char_clear.c b/acb_dirichlet/char_clear.c index 7ae309ca..3ac4ff80 100644 --- a/acb_dirichlet/char_clear.c +++ b/acb_dirichlet/char_clear.c @@ -26,6 +26,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_char_clear(acb_dirichlet_char_t chi) { +acb_dirichlet_char_clear(acb_dirichlet_char_t chi) +{ flint_free(chi->expo); } diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c index c295c011..9f9d1a38 100644 --- a/acb_dirichlet/char_conrey.c +++ b/acb_dirichlet/char_conrey.c @@ -30,14 +30,14 @@ void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) { - ulong k; - chi->q = G->q; - chi->n = x->n; - chi->parity = acb_dirichlet_conrey_parity(G, x); + ulong k; + chi->q = G->q; + chi->n = x->n; + chi->parity = acb_dirichlet_conrey_parity(G, x); - for (k = 0; k < G->num; k++) - chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; + for (k = 0; k < G->num; k++) + chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; - /* optional: divide by gcd to obtain true order */ - acb_dirichlet_char_normalize(chi, G); + /* optional: divide by gcd to obtain true order */ + acb_dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_first_primitive.c b/acb_dirichlet/char_first_primitive.c index 6180a154..71881814 100644 --- a/acb_dirichlet/char_first_primitive.c +++ b/acb_dirichlet/char_first_primitive.c @@ -28,10 +28,10 @@ void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - acb_dirichlet_conrey_t x; - chi->q = G->q; - x->log = chi->expo; - acb_dirichlet_conrey_first_primitive(x, G); - chi->n = x->n; - acb_dirichlet_char_normalize(chi, G); + acb_dirichlet_conrey_t x; + chi->q = G->q; + x->log = chi->expo; + acb_dirichlet_conrey_first_primitive(x, G); + chi->n = x->n; + acb_dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_init.c b/acb_dirichlet/char_init.c index 9c0d3108..7c39554d 100644 --- a/acb_dirichlet/char_init.c +++ b/acb_dirichlet/char_init.c @@ -26,6 +26,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - chi->expo = flint_malloc(G->num * sizeof(ulong)); +acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + chi->expo = flint_malloc(G->num * sizeof(ulong)); } diff --git a/acb_dirichlet/char_next.c b/acb_dirichlet/char_next.c index 5b7efb16..c5183766 100644 --- a/acb_dirichlet/char_next.c +++ b/acb_dirichlet/char_next.c @@ -28,22 +28,22 @@ int acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k; + ulong k; - acb_dirichlet_char_denormalize(chi, G); + acb_dirichlet_char_denormalize(chi, G); - /* update index */ - for (k=0; k < G->num ; k++) - { - chi->n = nmod_mul(chi->n, G->generators[k], G->mod); - chi->expo[k] += G->PHI[k]; - if (chi->expo[k] < G->expo) - break; - chi->expo[k] = 0; - } + /* update index */ + for (k=0; k < G->num ; k++) + { + chi->n = nmod_mul(chi->n, G->generators[k], G->mod); + chi->expo[k] += G->PHI[k]; + if (chi->expo[k] < G->expo) + break; + chi->expo[k] = 0; + } - acb_dirichlet_char_normalize(chi, G); + acb_dirichlet_char_normalize(chi, G); - /* return last index modified */ - return k; + /* return last index modified */ + return k; } diff --git a/acb_dirichlet/char_next_primitive.c b/acb_dirichlet/char_next_primitive.c index cd3bda76..b1b16819 100644 --- a/acb_dirichlet/char_next_primitive.c +++ b/acb_dirichlet/char_next_primitive.c @@ -28,36 +28,38 @@ int acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k; + ulong k; - acb_dirichlet_char_denormalize(chi, G); + acb_dirichlet_char_denormalize(chi, G); - /* update index */ - k = 0; - if (G->neven == 2) - { - chi->n = nmod_mul(chi->n, G->generators[0], G->mod); - if (++chi->expo[0] < G->expo) - return 0; - chi->expo[0] = 0; - k = 1; - } - for (; k < G->num ; k++) - { - chi->n = nmod_mul(chi->n, G->generators[k], G->mod); - chi->expo[k] += G->PHI[k]; - if (chi->expo[k] % G->primes[k] == 0) - { - chi->n = nmod_mul(chi->n, G->generators[k], G->mod); - chi->expo[k] += G->PHI[k]; - } - if (chi->expo[k] < G->expo) - break; - chi->expo[k] = G->PHI[k]; - } + /* update index */ + k = 0; + if (G->neven == 2) + { + chi->n = nmod_mul(chi->n, G->generators[0], G->mod); + chi->expo[0]++; + if (chi->expo[0] < G->expo) + return 0; + chi->expo[0] = 0; + k = 1; + } - acb_dirichlet_char_normalize(chi, G); + for (; k < G->num ; k++) + { + chi->n = nmod_mul(chi->n, G->generators[k], G->mod); + chi->expo[k] += G->PHI[k]; + if (chi->expo[k] % G->primes[k] == 0) + { + chi->n = nmod_mul(chi->n, G->generators[k], G->mod); + chi->expo[k] += G->PHI[k]; + } + if (chi->expo[k] < G->expo) + break; + chi->expo[k] = G->PHI[k]; + } - /* return last index modified */ - return k; + acb_dirichlet_char_normalize(chi, G); + + /* return last index modified */ + return k; } diff --git a/acb_dirichlet/char_normalize.c b/acb_dirichlet/char_normalize.c index 4c6cd4db..51fbe369 100644 --- a/acb_dirichlet/char_normalize.c +++ b/acb_dirichlet/char_normalize.c @@ -28,20 +28,24 @@ void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k, g; - g = G->expo; - for (k = 0; k < G->num; k++) - g = n_gcd(g, chi->expo[k]); - for (k = 0; k < G->num; k++) - chi->expo[k] = chi->expo[k] / g; - chi->order = G->expo / g; + ulong k, g; + g = G->expo; + + for (k = 0; k < G->num; k++) + g = n_gcd(g, chi->expo[k]); + + for (k = 0; k < G->num; k++) + chi->expo[k] = chi->expo[k] / g; + + chi->order = G->expo / g; } void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k, g; - g = G->expo / chi->order; - for (k = 0; k < G->num; k++) - chi->expo[k] *= g; + ulong k, g; + g = G->expo / chi->order; + + for (k = 0; k < G->num; k++) + chi->expo[k] *= g; } diff --git a/acb_dirichlet/char_one.c b/acb_dirichlet/char_one.c index 595972fb..ab6e09c2 100644 --- a/acb_dirichlet/char_one.c +++ b/acb_dirichlet/char_one.c @@ -28,10 +28,12 @@ void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k; - chi->q = G->q; - chi->n = 1; - for (k = 0; k < G->num; k++) - chi->expo[k] = 0; - chi->order = 1; + ulong k; + chi->q = G->q; + chi->n = 1; + + for (k = 0; k < G->num; k++) + chi->expo[k] = 0; + + chi->order = 1; } diff --git a/acb_dirichlet/char_print.c b/acb_dirichlet/char_print.c index b70d48bd..d9f2f449 100644 --- a/acb_dirichlet/char_print.c +++ b/acb_dirichlet/char_print.c @@ -28,8 +28,8 @@ void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) { - acb_dirichlet_conrey_t x; - x->log = chi->expo; - flint_printf("chi_%wu(%wu,.) of order %wu and index ", G->q, chi->n, chi->order); - acb_dirichlet_conrey_print(G, x); + acb_dirichlet_conrey_t x; + x->log = chi->expo; + flint_printf("chi_%wu(%wu,.) of order %wu and index ", G->q, chi->n, chi->order); + acb_dirichlet_conrey_print(G, x); } diff --git a/acb_dirichlet/chi_vec_loop.c b/acb_dirichlet/chi_vec_loop.c index e2dec1db..44450e97 100644 --- a/acb_dirichlet/chi_vec_loop.c +++ b/acb_dirichlet/chi_vec_loop.c @@ -36,21 +36,26 @@ acb_dirichlet_chi_vec_loop(ulong *v, ulong nv, const acb_dirichlet_group_t G, co acb_dirichlet_conrey_one(x, G); for (k = 0; k < nv; k++) - v[k] = CHI_NULL; + v[k] = ACB_DIRICHLET_CHI_NULL; t = v[1] = 0; + while ( (j = acb_dirichlet_conrey_next(x, G)) < G->num ) { /* exponents were modified up to j */ for (k = 0; k <= j; k++) t = (t + chi->expo[k]) % chi->order; + if (x->n < nv) v[x->n] = t; } + /* fix result outside primes */ /*acb_dirichlet_vec_set_null(v, nv, G);*/ /* copy outside modulus */ + for (k = G->q; k < nv ; k++ ) v[k] = v[k - G->q]; + acb_dirichlet_conrey_clear(x); } diff --git a/acb_dirichlet/chi_vec_primeloop.c b/acb_dirichlet/chi_vec_primeloop.c index 6f0a1928..b3cfbbd3 100644 --- a/acb_dirichlet/chi_vec_primeloop.c +++ b/acb_dirichlet/chi_vec_primeloop.c @@ -29,29 +29,30 @@ void acb_dirichlet_chi_vec_primeloop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) { - ulong k, l; + ulong k, l; - for(k = 1; k < nv; ++k) - v[k] = 0; + for (k = 1; k < nv; k++) + v[k] = 0; - for(l = 1; l < G->num; ++l) - { - long p, pe, g, x, vp, xp; - long j, vj; - p = G->primes[l]; - pe = G->primepowers[l]; - g = G->generators[l] % pe; - vj = vp = chi->expo[l]; - /* for each x = g^j mod p^e, - * set a[x] += j*vp - * and use periodicity */ - for(j = 1, x = g; x > 1; j++) + for (l = 1; l < G->num; l++) { - for(xp = x; xp < nv; xp+=pe) - v[xp] = (v[xp] + vj) % chi->order; - x = (x*g) % pe; - vj = (vj + vp) % chi->order; + long p, pe, g, x, vp, xp; + long j, vj; + p = G->primes[l]; + pe = G->primepowers[l]; + g = G->generators[l] % pe; + vj = vp = chi->expo[l]; + /* for each x = g^j mod p^e, + * set a[x] += j*vp + * and use periodicity */ + for (j = 1, x = g; x > 1; j++) + { + for (xp = x; xp < nv; xp += pe) + v[xp] = (v[xp] + vj) % chi->order; + + x = (x*g) % pe; + vj = (vj + vp) % chi->order; + } } - } - acb_dirichlet_vec_set_null(v, nv, G); + acb_dirichlet_vec_set_null(v, nv, G); } diff --git a/acb_dirichlet/chi_vec_sieve.c b/acb_dirichlet/chi_vec_sieve.c index 19ca8a5b..04de3d4e 100644 --- a/acb_dirichlet/chi_vec_sieve.c +++ b/acb_dirichlet/chi_vec_sieve.c @@ -36,21 +36,24 @@ acb_dirichlet_chi_vec_sieve(ulong *v, ulong nv, const acb_dirichlet_group_t G, c pmax = (nv < G->q) ? nv : G->q; v[1] = 0; + while ((p = n_primes_next(iter)) < pmax) { if (G->q % p == 0) { for (k = p; k < nv; k += p) - v[k] = CHI_NULL; + v[k] = ACB_DIRICHLET_CHI_NULL; } else { long chip; chip = acb_dirichlet_chi(G, chi, p); + for (k = p; k < nv; k += p) if (v[k] != -1) v[k] = (v[k] + chip) % chi->order; } } + n_primes_clear(iter); } diff --git a/acb_dirichlet/conrey_next_primitive.c b/acb_dirichlet/conrey_next_primitive.c index 90671bd6..d79306ae 100644 --- a/acb_dirichlet/conrey_next_primitive.c +++ b/acb_dirichlet/conrey_next_primitive.c @@ -28,29 +28,31 @@ int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { - /* update index avoiding multiples of p except for first component - if 8|q */ - ulong k = 0; - if (G->neven == 2) - { - x->n = nmod_mul(x->n, G->generators[0], G->mod); - if (++x->log[0] == 1) - return 0; - x->log[0] = 0; - k = 1; - } - for (; k < G->num ; k++) - { - x->n = nmod_mul(x->n, G->generators[k], G->mod); - if (++x->log[k] % G->primes[k] == 0) + /* update index avoiding multiples of p except for first component + if 8|q */ + ulong k = 0; + if (G->neven == 2) + { + x->n = nmod_mul(x->n, G->generators[0], G->mod); + x->log[0]++; + if (x->log[0] == 1) + return 0; + x->log[0] = 0; + k = 1; + } + for (; k < G->num ; k++) { x->n = nmod_mul(x->n, G->generators[k], G->mod); - ++x->log[k]; + x->log[k]++; + if (x->log[k] % G->primes[k] == 0) + { + x->n = nmod_mul(x->n, G->generators[k], G->mod); + x->log[k]++; + } + if (x->log[k] < G->phi[k]) + break; + x->log[k] = 1; } - if (x->log[k] < G->phi[k]) - break; - x->log[k] = 1; - } - /* return last index modified */ - return k; + /* return last index modified */ + return k; } diff --git a/acb_dirichlet/group_dlog_precompute.c b/acb_dirichlet/group_dlog_precompute.c index f16bd567..848b8099 100644 --- a/acb_dirichlet/group_dlog_precompute.c +++ b/acb_dirichlet/group_dlog_precompute.c @@ -30,7 +30,7 @@ acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) { slong k; G->dlog = flint_malloc(G->num * sizeof(dlog_precomp_t)); - for (k = G->neven; k < G->num; k++) + for (k = 0; k < G->num; k++) { ulong p, e, pe, a; p = G->primes[k]; diff --git a/acb_dirichlet/pairing.c b/acb_dirichlet/pairing.c index 0ff9861c..41a98bfb 100644 --- a/acb_dirichlet/pairing.c +++ b/acb_dirichlet/pairing.c @@ -32,7 +32,7 @@ acb_dirichlet_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) acb_dirichlet_conrey_t a, b; if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) - return CHI_NULL; + return ACB_DIRICHLET_CHI_NULL; acb_dirichlet_conrey_init(a, G); acb_dirichlet_conrey_init(b, G); diff --git a/acb_dirichlet/pairing_conrey.c b/acb_dirichlet/pairing_conrey.c index 4c7b5753..0623555f 100644 --- a/acb_dirichlet/pairing_conrey.c +++ b/acb_dirichlet/pairing_conrey.c @@ -32,9 +32,11 @@ ulong acb_dirichlet_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) { - ulong x, k; - x = 0; - for (k = 0; k < G->num; k++) - x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; - return x; + ulong x, k; + x = 0; + + for (k = 0; k < G->num; k++) + x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; + + return x; } diff --git a/acb_dirichlet/profile/p-vec.c b/acb_dirichlet/profile/p-vec.c index 3dd8ce46..d7fddbf0 100644 --- a/acb_dirichlet/profile/p-vec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -55,6 +55,7 @@ vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ul acb_dirichlet_group_clear(G); } TIMEIT_ONCE_STOP + flint_printf("\n"); } int main() @@ -98,7 +99,7 @@ int main() fflush(stdout); vecloop(acb_dirichlet_chi_vec_primeloop, minq, maxq, rand, nr, v, nv); - flint_printf("small loop................ "); + flint_printf("sieve................... "); fflush(stdout); vecloop(acb_dirichlet_chi_vec_sieve, minq, maxq, rand, nr, v, nv); diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c new file mode 100644 index 00000000..921a5321 --- /dev/null +++ b/acb_dirichlet/test/t-chars.c @@ -0,0 +1,140 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + + +static ulong +nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) +{ + int k; + ulong pe, ap, order = 1; + for (k = 0; k < fac.num; k++) + { + pe = n_pow(fac.p[k], fac.exp[k]); + ap = nmod_pow_ui(a, expo / pe, mod); + while ( ap != 1) + { + ap = nmod_pow_ui(ap, fac.p[k], mod); + order *= fac.p[k]; + } + } + return order; +} + +int main() +{ + slong iter, bits; + flint_rand_t state; + + flint_printf("chars...."); + fflush(stdout); + flint_randinit(state); + for (bits = 5; bits <= 30; bits += 5) + { + + for (iter = 0; iter < 50; iter++) + { + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi, chi2; + ulong q, iter2; + n_factor_t fac; + + q = 2 + n_randint(state, 1 << bits); + + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi, G); + acb_dirichlet_char_init(chi2, G); + + n_factor_init(&fac); + n_factor(&fac, G->expo, 1); + + acb_dirichlet_group_dlog_precompute(G, 50); + + /* check number char properties */ + for (iter2 = 0; iter2 < 50; iter2++) + { + ulong m, n; + ulong order, chim1, pairing; + + do + m = n_randint(state, q); + while (n_gcd(q, m) > 1); + + acb_dirichlet_char(chi, G, m); + + order = nmod_order_precomp(m, G->mod, G->expo, fac); + if (order != chi->order) + { + flint_printf("FAIL: order\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("order(m) = %wu\n\n", order); + flint_printf("chi->order = %wu\n\n", chi->order); + abort(); + } + + chim1 = acb_dirichlet_chi(G, chi, q - 1); + if (acb_dirichlet_char_parity(chi) != (chim1 != 0)) + { + flint_printf("FAIL: parity\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("chi(-1) = %wu\n\n", chim1); + flint_printf("char_parity = %d", acb_dirichlet_char_parity(chi)); + acb_dirichlet_char_print(G, chi); + abort(); + } + + do + n = n_randint(state, q); + while (n_gcd(q, n) > 1); + + acb_dirichlet_char(chi2, G, n); + pairing = acb_dirichlet_pairing(G, m, n); + + if (pairing != acb_dirichlet_chi(G, chi, n) * (G->expo / chi->order) + || pairing != acb_dirichlet_chi(G, chi2, m) * (G->expo / chi2->order)) + { + 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); + abort(); + } + } + + acb_dirichlet_char_clear(chi); + acb_dirichlet_char_clear(chi2); + acb_dirichlet_group_clear(G); + } + } + + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index e57889a2..fee009bc 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -34,7 +34,7 @@ int main() slong prec = 80; ulong q; - flint_printf("theta null...."); + flint_printf("thetanull...."); fflush(stdout); /* check the only theta functions @@ -101,8 +101,9 @@ int main() flint_printf("Theta(chi_%wu(%wu)) (m=%wu)\n", q, chi->n, m); */ tt = acb_dirichlet_char_parity(chi) ? kt : t; + for (k = 1; k < nv; k++) - if (v[k] != CHI_NULL) + if (v[k] != ACB_DIRICHLET_CHI_NULL) acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); if ((q == 300 && (chi->n == 271 || chi->n == 131)) diff --git a/acb_dirichlet/vec_set_null.c b/acb_dirichlet/vec_set_null.c index eded5823..5246f7c3 100644 --- a/acb_dirichlet/vec_set_null.c +++ b/acb_dirichlet/vec_set_null.c @@ -28,16 +28,18 @@ void acb_dirichlet_vec_set_null(ulong *v, ulong nv, const acb_dirichlet_group_t G) { - ulong k, l; - if (G->q_even > 1) - { - for (k = 2; k < nv; k += 2) - v[k] = -1; - } - for (l = 0; l < G->num; l++) - { - ulong p = G->primes[l]; - for (k = p; k < nv; k += p) - v[k] = CHI_NULL; - } + ulong k, l; + if (G->q_even > 1) + { + for (k = 2; k < nv; k += 2) + v[k] = -1; + } + + for (l = 0; l < G->num; l++) + { + ulong p = G->primes[l]; + + for (k = p; k < nv; k += p) + v[k] = ACB_DIRICHLET_CHI_NULL; + } } From 0d29c8b04285bc3bc72cdffa5236c7e574f5b0a5 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 29 Mar 2016 14:37:21 +0100 Subject: [PATCH 028/139] change argument order --- acb_dirichlet.h | 20 +++++++++--------- acb_dirichlet/chi_vec.c | 35 +++++++++++++++++++++++++++++++ acb_dirichlet/chi_vec_loop.c | 7 ++++--- acb_dirichlet/chi_vec_primeloop.c | 7 ++++--- acb_dirichlet/chi_vec_sieve.c | 4 ++-- acb_dirichlet/profile/p-vec.c | 8 +++++-- acb_dirichlet/test/t-thetanull.c | 2 +- acb_dirichlet/vec_set_null.c | 4 ++-- 8 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 acb_dirichlet/chi_vec.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 4763d53a..096f2d77 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -95,11 +95,11 @@ void acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m /* character = reduced exponents, keep order and number */ typedef struct { - ulong q; /* modulus */ - ulong n; /* number */ - ulong order; /* order */ - ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ - int parity; /* 0 for even char, 1 for odd */ + ulong q; /* modulus */ + ulong n; /* number */ + ulong order; /* order */ + ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ + int parity; /* 0 for even char, 1 for odd */ } acb_dirichlet_char_struct; @@ -135,11 +135,11 @@ void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_diri ulong acb_dirichlet_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); void acb_dirichlet_acb_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); -void acb_dirichlet_vec_set_null(ulong *v, ulong nv, const acb_dirichlet_group_t G); -void acb_dirichlet_chi_vec_loop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); -void acb_dirichlet_chi_vec_primeloop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); -void acb_dirichlet_chi_vec_sieve(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); -void acb_dirichlet_chi_vec(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +void acb_dirichlet_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv); +void acb_dirichlet_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); void acb_dirichlet_char_vec(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/chi_vec.c new file mode 100644 index 00000000..68ce20cc --- /dev/null +++ b/acb_dirichlet/chi_vec.c @@ -0,0 +1,35 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +{ + if (3 * nv > G->q) + acb_dirichlet_chi_vec_loop(v, G, chi, nv); + else + acb_dirichlet_chi_vec_primeloop(v, G, chi, nv); +} diff --git a/acb_dirichlet/chi_vec_loop.c b/acb_dirichlet/chi_vec_loop.c index 44450e97..ff6c10f1 100644 --- a/acb_dirichlet/chi_vec_loop.c +++ b/acb_dirichlet/chi_vec_loop.c @@ -27,10 +27,11 @@ /* loop over whole group */ void -acb_dirichlet_chi_vec_loop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +acb_dirichlet_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { int j; - ulong t, k; + ulong t; + slong k; acb_dirichlet_conrey_t x; acb_dirichlet_conrey_init(x, G); acb_dirichlet_conrey_one(x, G); @@ -51,7 +52,7 @@ acb_dirichlet_chi_vec_loop(ulong *v, ulong nv, const acb_dirichlet_group_t G, co } /* fix result outside primes */ - /*acb_dirichlet_vec_set_null(v, nv, G);*/ + /*acb_dirichlet_vec_set_null(v, G, nv);*/ /* copy outside modulus */ for (k = G->q; k < nv ; k++ ) diff --git a/acb_dirichlet/chi_vec_primeloop.c b/acb_dirichlet/chi_vec_primeloop.c index b3cfbbd3..d53a1fcc 100644 --- a/acb_dirichlet/chi_vec_primeloop.c +++ b/acb_dirichlet/chi_vec_primeloop.c @@ -27,9 +27,9 @@ /* loop over primary components */ void -acb_dirichlet_chi_vec_primeloop(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +acb_dirichlet_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { - ulong k, l; + slong k, l; for (k = 1; k < nv; k++) v[k] = 0; @@ -45,6 +45,7 @@ acb_dirichlet_chi_vec_primeloop(ulong *v, ulong nv, const acb_dirichlet_group_t /* for each x = g^j mod p^e, * set a[x] += j*vp * and use periodicity */ + for (j = 1, x = g; x > 1; j++) { for (xp = x; xp < nv; xp += pe) @@ -54,5 +55,5 @@ acb_dirichlet_chi_vec_primeloop(ulong *v, ulong nv, const acb_dirichlet_group_t vj = (vj + vp) % chi->order; } } - acb_dirichlet_vec_set_null(v, nv, G); + acb_dirichlet_vec_set_null(v, G, nv); } diff --git a/acb_dirichlet/chi_vec_sieve.c b/acb_dirichlet/chi_vec_sieve.c index 04de3d4e..9589d389 100644 --- a/acb_dirichlet/chi_vec_sieve.c +++ b/acb_dirichlet/chi_vec_sieve.c @@ -27,9 +27,9 @@ /* sieve on primes */ void -acb_dirichlet_chi_vec_sieve(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +acb_dirichlet_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { - ulong k, p, pmax; + slong k, p, pmax; n_primes_t iter; n_primes_init(iter); diff --git a/acb_dirichlet/profile/p-vec.c b/acb_dirichlet/profile/p-vec.c index d7fddbf0..84215127 100644 --- a/acb_dirichlet/profile/p-vec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -25,10 +25,10 @@ #include "acb_dirichlet.h" #include "profiler.h" -typedef void (*dir_f) (ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +typedef void (*dir_f) (ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); void -dir_empty(ulong *v, ulong nv, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +dir_empty(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { return; } @@ -38,6 +38,7 @@ vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ul { ulong q; TIMEIT_ONCE_START + for (q = minq; q <= maxq; q++) { ulong r; @@ -46,14 +47,17 @@ vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ul acb_dirichlet_group_init(G, q); acb_dirichlet_char_init(chi, G); + for (r = 0; r < nr; r++) { acb_dirichlet_char(chi, G, rand[r] % q); dir(v, nv, G, chi); } + acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); } + TIMEIT_ONCE_STOP flint_printf("\n"); } diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index fee009bc..7a6cb87c 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -94,7 +94,7 @@ int main() acb_zero(sum); acb_dirichlet_char_conrey(chi, G, x); - acb_dirichlet_chi_vec_loop(v, nv, G, chi); + acb_dirichlet_chi_vec_loop(v, G, chi, nv); m = G->expo / chi->order; /* diff --git a/acb_dirichlet/vec_set_null.c b/acb_dirichlet/vec_set_null.c index 5246f7c3..fd95c45e 100644 --- a/acb_dirichlet/vec_set_null.c +++ b/acb_dirichlet/vec_set_null.c @@ -26,9 +26,9 @@ #include "acb_dirichlet.h" void -acb_dirichlet_vec_set_null(ulong *v, ulong nv, const acb_dirichlet_group_t G) +acb_dirichlet_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv) { - ulong k, l; + slong k, l; if (G->q_even > 1) { for (k = 2; k < nv; k += 2) From 0cbba4b8ffeb4721e00121bd74e45a3a6fad8dbc Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 5 Apr 2016 11:55:04 +0200 Subject: [PATCH 029/139] fix and test chi_vec_primeloop --- acb_dirichlet.h | 5 +- acb_dirichlet/chi_vec_primeloop.c | 58 ++++++++++++++++---- acb_dirichlet/test/t-chars.c | 1 + acb_dirichlet/test/t-conrey.c | 4 +- acb_dirichlet/test/t-thetanull.c | 17 +++--- acb_dirichlet/test/t-vec.c | 90 +++++++++++++++++++++++++++++++ acb_dirichlet/theta_length.c | 36 +++++++++++++ 7 files changed, 186 insertions(+), 25 deletions(-) create mode 100644 acb_dirichlet/test/t-vec.c create mode 100644 acb_dirichlet/theta_length.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 096f2d77..fc91eab0 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -96,6 +96,7 @@ void acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m typedef struct { ulong q; /* modulus */ + /*? acb_dirichet_conrey_struct n; */ ulong n; /* number */ ulong order; /* order */ ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ @@ -105,7 +106,7 @@ acb_dirichlet_char_struct; typedef acb_dirichlet_char_struct acb_dirichlet_char_t[1]; -ACB_DIRICHLET_INLINE int +ACB_DIRICHLET_INLINE ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) { return chi->order; @@ -127,7 +128,6 @@ void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_ void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); -int acb_dirichlet_char_is_odd(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); @@ -146,6 +146,7 @@ void acb_dirichlet_char_vec(acb_t res, const acb_dirichlet_group_t G, const acb_ void acb_dirichlet_zeta(acb_t res, ulong order, slong prec); void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); +ulong acb_dirichlet_theta_length(ulong q, double x, slong prec); #ifdef __cplusplus } diff --git a/acb_dirichlet/chi_vec_primeloop.c b/acb_dirichlet/chi_vec_primeloop.c index d53a1fcc..4bbd8b12 100644 --- a/acb_dirichlet/chi_vec_primeloop.c +++ b/acb_dirichlet/chi_vec_primeloop.c @@ -25,6 +25,39 @@ #include "acb_dirichlet.h" +void +chi_vec_evenpart(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +{ + + ulong c3, c4, x; + + if (G->neven >= 1 && (c3 = chi->expo[0])) + { + for (x = 3; x < nv; x += 4) + v[x] = c3; + } + if (G->neven == 2 && (c4 = chi->expo[1])) + { + ulong g, pe, vx, xp; + vx = c4; + pe = G->primepowers[1]; + g = G->generators[1] % pe; + + for (x = g; x > 1;) + { + + for (xp = x; xp < nv; xp += pe) + v[xp] = (v[xp] + vx) % chi->order; + + for (xp = pe - x; xp < nv; xp += pe) + v[xp] = (v[xp] + vx) % chi->order; + + x = (x * g) % pe; + vx = (vx + c4) % chi->order; + } + } +} + /* loop over primary components */ void acb_dirichlet_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) @@ -34,25 +67,30 @@ acb_dirichlet_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const a for (k = 1; k < nv; k++) v[k] = 0; - for (l = 1; l < G->num; l++) + if (G->neven) + chi_vec_evenpart(v, G, chi, nv); + + for (l = G->neven; l < G->num; l++) { - long p, pe, g, x, vp, xp; - long j, vj; + ulong p, pe, g, x, vx, vp, xp; p = G->primes[l]; pe = G->primepowers[l]; g = G->generators[l] % pe; - vj = vp = chi->expo[l]; + vx = vp = chi->expo[l]; + + if (vp == 0) + continue; /* for each x = g^j mod p^e, * set a[x] += j*vp * and use periodicity */ - - for (j = 1, x = g; x > 1; j++) + for (x = g; x > 1;) { - for (xp = x; xp < nv; xp += pe) - v[xp] = (v[xp] + vj) % chi->order; - x = (x*g) % pe; - vj = (vj + vp) % chi->order; + for (xp = x; xp < nv; xp += pe) + v[xp] = (v[xp] + vx) % chi->order; + + x = (x * g) % pe; + vx = (vx + vp) % chi->order; } } acb_dirichlet_vec_set_null(v, G, nv); diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 921a5321..2fd5c84c 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -26,6 +26,7 @@ #include "acb_dirichlet.h" +/* order of an element knowing the factorization of a multiple */ static ulong nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) { diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index c1c58d83..d7da9844 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -34,7 +34,7 @@ int main() fflush(stdout); flint_randinit(state); - for (iter = 0; iter < 10000; iter++) + for (iter = 0; iter < 3000; iter++) { acb_dirichlet_group_t G; acb_dirichlet_conrey_t x; @@ -109,7 +109,7 @@ int main() if (G->exponents[k] == 1) ref *= p - 2; else - ref *= (p * (p -2) + 1) * n_pow(p, G->exponents[k] - 2); + ref *= (p * (p - 2) + 1) * n_pow(p, G->exponents[k] - 2); } } diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 7a6cb87c..f657fcf3 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -24,14 +24,10 @@ ******************************************************************************/ #include "acb_dirichlet.h" -#include - -#define PI 3.14159265358 -#define LOG2 0.69314718055 int main() { - slong prec = 80; + slong prec = 64; ulong q; flint_printf("thetanull...."); @@ -43,7 +39,7 @@ int main() * characters of moduli 300 and 600 + conjugates */ - for (q = 3; q < 800; q ++) + for (q = 3; q < 1000; q ++) { acb_dirichlet_group_t G; acb_dirichlet_conrey_t x; @@ -57,6 +53,7 @@ int main() arb_ptr t, kt, tt; if (q % 4 == 2) + /* no primitive character mod q */ continue; acb_dirichlet_group_init(G, q); @@ -69,7 +66,7 @@ int main() z = _acb_vec_init(G->expo); _acb_vec_set_powers(z, zeta, G->expo, prec); - nv = ceil(sqrt((double)q * prec * LOG2 / PI)) + 2; + nv = acb_dirichlet_theta_length(q, 1, prec); v = flint_malloc(nv * sizeof(ulong)); arb_init(eq); @@ -94,12 +91,9 @@ int main() acb_zero(sum); acb_dirichlet_char_conrey(chi, G, x); - acb_dirichlet_chi_vec_loop(v, G, chi, nv); + acb_dirichlet_chi_vec(v, G, chi, nv); m = G->expo / chi->order; - /* - flint_printf("Theta(chi_%wu(%wu)) (m=%wu)\n", q, chi->n, m); - */ tt = acb_dirichlet_char_parity(chi) ? kt : t; for (k = 1; k < nv; k++) @@ -133,6 +127,7 @@ int main() acb_clear(zeta); acb_clear(sum); arb_clear(eq); + flint_free(v); acb_dirichlet_group_clear(G); acb_dirichlet_char_clear(chi); acb_dirichlet_conrey_clear(x); diff --git a/acb_dirichlet/test/t-vec.c b/acb_dirichlet/test/t-vec.c new file mode 100644 index 00000000..efb7a060 --- /dev/null +++ b/acb_dirichlet/test/t-vec.c @@ -0,0 +1,90 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +static ulong +vec_diff(ulong * v, ulong * ref, ulong nv) +{ + ulong k; + for (k = 1; k < nv; k++) + if (ref[k] != v[k]) + return k; + return 0; +} + +int main() +{ + ulong q; + + flint_printf("vec...."); + fflush(stdout); + + for (q = 2; q < 600; q ++) + { + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_dirichlet_char_t chi; + ulong * v1, * v2, nv, k; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_char_init(chi, G); + + nv = 100; + v1 = flint_malloc(nv * sizeof(ulong)); + v2 = flint_malloc(nv * sizeof(ulong)); + + acb_dirichlet_conrey_one(x, G); + + while (1) { + + acb_dirichlet_char_conrey(chi, G, x); + + acb_dirichlet_chi_vec_loop(v1, G, chi, nv); + acb_dirichlet_chi_vec_primeloop(v2, G, chi, nv); + + if ((k = vec_diff(v1, v2, nv))) + { + flint_printf("FAIL: chi(%wu,%wu) = %wu != chi(%wu,%wu) = %wu mod %wu (modulus = %wu)\n", + chi->n, k, v1[k], chi->n, k, v2[k], chi->order, q); + abort(); + } + + if (acb_dirichlet_conrey_next(x, G) == G->num) + break; + } + + flint_free(v1); + flint_free(v2); + acb_dirichlet_group_clear(G); + acb_dirichlet_char_clear(chi); + acb_dirichlet_conrey_clear(x); + } + + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c new file mode 100644 index 00000000..7e6cc6cb --- /dev/null +++ b/acb_dirichlet/theta_length.c @@ -0,0 +1,36 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include +#define PI 3.14159265358 +#define LOG2 0.69314718055 + +ulong +acb_dirichlet_theta_length(ulong q, double x, slong prec) +{ + double a = PI / (double)q * x * x; + return ceil(sqrt(((double)prec * LOG2 - log(2 * a)) / a)); +} From 320e35a53a861cb0a057756f45eebe8246c475e7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 5 Apr 2016 12:18:39 +0200 Subject: [PATCH 030/139] change interface to switch acb / ui output --- acb_dirichlet.h | 25 ++-- acb_dirichlet/acb_chi.c | 45 ------ acb_dirichlet/l.c | 3 +- acb_dirichlet/{zeta.c => nth_root.c} | 2 +- acb_dirichlet/pairing.c | 36 ++--- acb_dirichlet/pairing_conrey.c | 27 ++-- acb_dirichlet/test/t-chars.c | 8 +- acb_dirichlet/test/t-chi.c | 10 +- acb_dirichlet/test/t-thetanull.c | 4 +- acb_dirichlet/test/t-vec.c | 4 +- .../{acb_pairing_conrey.c => ui_chi.c} | 25 ++-- acb_dirichlet/{chi_vec.c => ui_chi_vec.c} | 6 +- .../{chi_vec_loop.c => ui_chi_vec_loop.c} | 2 +- ...vec_primeloop.c => ui_chi_vec_primeloop.c} | 6 +- .../{chi_vec_sieve.c => ui_chi_vec_sieve.c} | 4 +- acb_dirichlet/ui_pairing.c | 48 ++++++ .../{acb_pairing.c => ui_pairng_conrey.c} | 26 ++-- .../{vec_set_null.c => ui_vec_set_null.c} | 2 +- doc/source/acb_dirichlet.rst | 138 ++++++++++++++++-- 19 files changed, 270 insertions(+), 151 deletions(-) delete mode 100644 acb_dirichlet/acb_chi.c rename acb_dirichlet/{zeta.c => nth_root.c} (95%) rename acb_dirichlet/{acb_pairing_conrey.c => ui_chi.c} (70%) rename acb_dirichlet/{chi_vec.c => ui_chi_vec.c} (83%) rename acb_dirichlet/{chi_vec_loop.c => ui_chi_vec_loop.c} (94%) rename acb_dirichlet/{chi_vec_primeloop.c => ui_chi_vec_primeloop.c} (93%) rename acb_dirichlet/{chi_vec_sieve.c => ui_chi_vec_sieve.c} (90%) create mode 100644 acb_dirichlet/ui_pairing.c rename acb_dirichlet/{acb_pairing.c => ui_pairng_conrey.c} (73%) rename acb_dirichlet/{vec_set_null.c => ui_vec_set_null.c} (94%) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index fc91eab0..5f9909f8 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -84,11 +84,11 @@ int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_diri #define ACB_DIRICHLET_CHI_NULL UWORD_MAX -ulong acb_dirichlet_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); -ulong acb_dirichlet_pairing(const acb_dirichlet_group_t G, ulong m, ulong n); +ulong acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); +ulong acb_dirichlet_ui_pairing(const acb_dirichlet_group_t G, ulong m, ulong n); -void acb_dirichlet_acb_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec); -void acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec); +void acb_dirichlet_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec); +void acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec); /* introducing character type */ @@ -132,19 +132,18 @@ ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_diri void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -ulong acb_dirichlet_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); -void acb_dirichlet_acb_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); +ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); -void acb_dirichlet_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv); -void acb_dirichlet_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void acb_dirichlet_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void acb_dirichlet_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void acb_dirichlet_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv); +void acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void acb_dirichlet_char_vec(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); +void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec); +void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); -void acb_dirichlet_zeta(acb_t res, ulong order, slong prec); void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); ulong acb_dirichlet_theta_length(ulong q, double x, slong prec); diff --git a/acb_dirichlet/acb_chi.c b/acb_dirichlet/acb_chi.c deleted file mode 100644 index b1b36aef..00000000 --- a/acb_dirichlet/acb_chi.c +++ /dev/null @@ -1,45 +0,0 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2015 Jonathan Bober - Copyright (C) 2016 Fredrik Johansson - Copyright (C) 2016 Pascal Molin - -******************************************************************************/ - -#include "acb_dirichlet.h" - -void -acb_dirichlet_acb_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) -{ - ulong expo; - expo = acb_dirichlet_chi(G, chi, n); - if (expo == ACB_DIRICHLET_CHI_NULL) - acb_zero(res); - else - { - fmpq_t t; - fmpq_init(t); - fmpq_set_si(t, 2 * expo , chi->order); - arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); - fmpq_clear(t); - } -} diff --git a/acb_dirichlet/l.c b/acb_dirichlet/l.c index 2c0112e6..2f2a41a6 100644 --- a/acb_dirichlet/l.c +++ b/acb_dirichlet/l.c @@ -31,7 +31,7 @@ acb_dirichlet_l(acb_t res, const acb_t s, while (1) { /* todo: use n_dirichlet_chi and precomputed roots instead */ - acb_dirichlet_acb_pairing_conrey(chi, G, cm, cn, prec); + acb_dirichlet_pairing_conrey(chi, G, cm, cn, prec); acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); @@ -55,4 +55,3 @@ acb_dirichlet_l(acb_t res, const acb_t s, acb_clear(u); acb_clear(a); } - diff --git a/acb_dirichlet/zeta.c b/acb_dirichlet/nth_root.c similarity index 95% rename from acb_dirichlet/zeta.c rename to acb_dirichlet/nth_root.c index 111f6c7b..01d0388c 100644 --- a/acb_dirichlet/zeta.c +++ b/acb_dirichlet/nth_root.c @@ -26,7 +26,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_zeta(acb_t res, ulong order, slong prec) +acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) { fmpq_t t; fmpq_init(t); diff --git a/acb_dirichlet/pairing.c b/acb_dirichlet/pairing.c index 41a98bfb..efc4e4f8 100644 --- a/acb_dirichlet/pairing.c +++ b/acb_dirichlet/pairing.c @@ -19,30 +19,26 @@ =============================================================================*/ /****************************************************************************** - Copyright (C) 2016 Pascal Molin + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson ******************************************************************************/ #include "acb_dirichlet.h" -ulong -acb_dirichlet_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) +void +acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) { - ulong x; - acb_dirichlet_conrey_t a, b; - - if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) - return ACB_DIRICHLET_CHI_NULL; - - acb_dirichlet_conrey_init(a, G); - acb_dirichlet_conrey_init(b, G); - acb_dirichlet_conrey_log(a, G, m); - acb_dirichlet_conrey_log(b, G, n); - - x = acb_dirichlet_pairing_conrey(G, a, b); - - acb_dirichlet_conrey_clear(a); - acb_dirichlet_conrey_clear(b); - - return x; + ulong expo; + expo = acb_dirichlet_ui_pairing(G, m, n); + if (expo == ACB_DIRICHLET_CHI_NULL) + acb_zero(res); + else + { + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, 2 * expo, G->expo); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); + } } diff --git a/acb_dirichlet/pairing_conrey.c b/acb_dirichlet/pairing_conrey.c index 0623555f..a61dd336 100644 --- a/acb_dirichlet/pairing_conrey.c +++ b/acb_dirichlet/pairing_conrey.c @@ -19,24 +19,25 @@ =============================================================================*/ /****************************************************************************** - Copyright (C) 2015 Jonathan Bober - Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include "acb_dirichlet.h" -/* todo: modular arithmetic */ - -ulong -acb_dirichlet_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) +void +acb_dirichlet_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec) { - ulong x, k; - x = 0; - - for (k = 0; k < G->num; k++) - x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; - - return x; + ulong expo; + expo = acb_dirichlet_ui_pairing_conrey(G, a, b); + if (expo == ACB_DIRICHLET_CHI_NULL) + acb_zero(res); + else + { + fmpq_t t; + fmpq_init(t); + fmpq_set_si(t, 2 * expo, G->expo); + arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); + fmpq_clear(t); + } } diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 2fd5c84c..a178811a 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -97,7 +97,7 @@ int main() abort(); } - chim1 = acb_dirichlet_chi(G, chi, q - 1); + chim1 = acb_dirichlet_ui_chi(G, chi, q - 1); if (acb_dirichlet_char_parity(chi) != (chim1 != 0)) { flint_printf("FAIL: parity\n\n"); @@ -114,10 +114,10 @@ int main() while (n_gcd(q, n) > 1); acb_dirichlet_char(chi2, G, n); - pairing = acb_dirichlet_pairing(G, m, n); + pairing = acb_dirichlet_ui_pairing(G, m, n); - if (pairing != acb_dirichlet_chi(G, chi, n) * (G->expo / chi->order) - || pairing != acb_dirichlet_chi(G, chi2, m) * (G->expo / chi2->order)) + if (pairing != acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order) + || pairing != acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order)) { flint_printf("FAIL: pairing\n\n"); flint_printf("q = %wu\n\n", q); diff --git a/acb_dirichlet/test/t-chi.c b/acb_dirichlet/test/t-chi.c index cac365a3..ed0b825a 100644 --- a/acb_dirichlet/test/t-chi.c +++ b/acb_dirichlet/test/t-chi.c @@ -49,8 +49,8 @@ int main() n1 = n_randint(state, 1000); n2 = n_randint(state, 1000); - acb_dirichlet_acb_chi(zn1, G, chi, n1, 53); - acb_dirichlet_acb_pairing(zn2, G, m, n1, 53); + acb_dirichlet_chi(zn1, G, chi, n1, 53); + acb_dirichlet_pairing(zn2, G, m, n1, 53); if (!acb_overlaps(zn1, zn2)) { acb_dirichlet_conrey_t x; @@ -69,8 +69,8 @@ int main() abort(); } - acb_dirichlet_acb_pairing(zn2, G, m, n2, 53); - acb_dirichlet_acb_pairing(zn1n2, G, m, n1 * n2, 53); + 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)) @@ -97,7 +97,7 @@ int main() { if (n_gcd(q, m) == 1) { - acb_dirichlet_acb_pairing(zn2, G, m, n1, 53); + acb_dirichlet_pairing(zn2, G, m, n1, 53); acb_add(zn1, zn1, zn2, 53); } } diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index f657fcf3..950991bb 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -61,7 +61,7 @@ int main() acb_dirichlet_char_init(chi, G); acb_init(zeta); - acb_dirichlet_zeta(zeta, G->expo, prec); + acb_dirichlet_nth_root(zeta, G->expo, prec); z = _acb_vec_init(G->expo); _acb_vec_set_powers(z, zeta, G->expo, prec); @@ -91,7 +91,7 @@ int main() acb_zero(sum); acb_dirichlet_char_conrey(chi, G, x); - acb_dirichlet_chi_vec(v, G, chi, nv); + acb_dirichlet_ui_chi_vec(v, G, chi, nv); m = G->expo / chi->order; tt = acb_dirichlet_char_parity(chi) ? kt : t; diff --git a/acb_dirichlet/test/t-vec.c b/acb_dirichlet/test/t-vec.c index efb7a060..6d4f5a38 100644 --- a/acb_dirichlet/test/t-vec.c +++ b/acb_dirichlet/test/t-vec.c @@ -63,8 +63,8 @@ int main() acb_dirichlet_char_conrey(chi, G, x); - acb_dirichlet_chi_vec_loop(v1, G, chi, nv); - acb_dirichlet_chi_vec_primeloop(v2, G, chi, nv); + acb_dirichlet_ui_chi_vec_loop(v1, G, chi, nv); + acb_dirichlet_ui_chi_vec_primeloop(v2, G, chi, nv); if ((k = vec_diff(v1, v2, nv))) { diff --git a/acb_dirichlet/acb_pairing_conrey.c b/acb_dirichlet/ui_chi.c similarity index 70% rename from acb_dirichlet/acb_pairing_conrey.c rename to acb_dirichlet/ui_chi.c index 528e6f3d..2cdfa428 100644 --- a/acb_dirichlet/acb_pairing_conrey.c +++ b/acb_dirichlet/ui_chi.c @@ -25,19 +25,22 @@ #include "acb_dirichlet.h" -void -acb_dirichlet_acb_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec) +ulong +acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) { - ulong expo; - expo = acb_dirichlet_pairing_conrey(G, a, b); - if (expo == ACB_DIRICHLET_CHI_NULL) - acb_zero(res); + if (n_gcd(G->q, n) > 1) + { + return ACB_DIRICHLET_CHI_NULL; + } else { - fmpq_t t; - fmpq_init(t); - fmpq_set_si(t, 2 * expo, G->expo); - arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); - fmpq_clear(t); + ulong v = 0, k; + acb_dirichlet_conrey_t x; + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_conrey_log(x, G, n); + for (k = 0; k < G->num; k++) + v = (v + chi->expo[k] * x->log[k]) % chi->order; + acb_dirichlet_conrey_clear(x); + return v; } } diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/ui_chi_vec.c similarity index 83% rename from acb_dirichlet/chi_vec.c rename to acb_dirichlet/ui_chi_vec.c index 68ce20cc..42080621 100644 --- a/acb_dirichlet/chi_vec.c +++ b/acb_dirichlet/ui_chi_vec.c @@ -26,10 +26,10 @@ #include "acb_dirichlet.h" void -acb_dirichlet_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { if (3 * nv > G->q) - acb_dirichlet_chi_vec_loop(v, G, chi, nv); + acb_dirichlet_ui_chi_vec_loop(v, G, chi, nv); else - acb_dirichlet_chi_vec_primeloop(v, G, chi, nv); + acb_dirichlet_ui_chi_vec_primeloop(v, G, chi, nv); } diff --git a/acb_dirichlet/chi_vec_loop.c b/acb_dirichlet/ui_chi_vec_loop.c similarity index 94% rename from acb_dirichlet/chi_vec_loop.c rename to acb_dirichlet/ui_chi_vec_loop.c index ff6c10f1..49bf4fae 100644 --- a/acb_dirichlet/chi_vec_loop.c +++ b/acb_dirichlet/ui_chi_vec_loop.c @@ -27,7 +27,7 @@ /* loop over whole group */ void -acb_dirichlet_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { int j; ulong t; diff --git a/acb_dirichlet/chi_vec_primeloop.c b/acb_dirichlet/ui_chi_vec_primeloop.c similarity index 93% rename from acb_dirichlet/chi_vec_primeloop.c rename to acb_dirichlet/ui_chi_vec_primeloop.c index 4bbd8b12..dc749c13 100644 --- a/acb_dirichlet/chi_vec_primeloop.c +++ b/acb_dirichlet/ui_chi_vec_primeloop.c @@ -25,7 +25,7 @@ #include "acb_dirichlet.h" -void +static void chi_vec_evenpart(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { @@ -60,7 +60,7 @@ chi_vec_evenpart(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_ch /* loop over primary components */ void -acb_dirichlet_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { slong k, l; @@ -93,5 +93,5 @@ acb_dirichlet_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const a vx = (vx + vp) % chi->order; } } - acb_dirichlet_vec_set_null(v, G, nv); + acb_dirichlet_ui_vec_set_null(v, G, nv); } diff --git a/acb_dirichlet/chi_vec_sieve.c b/acb_dirichlet/ui_chi_vec_sieve.c similarity index 90% rename from acb_dirichlet/chi_vec_sieve.c rename to acb_dirichlet/ui_chi_vec_sieve.c index 9589d389..6c69b5a4 100644 --- a/acb_dirichlet/chi_vec_sieve.c +++ b/acb_dirichlet/ui_chi_vec_sieve.c @@ -27,7 +27,7 @@ /* sieve on primes */ void -acb_dirichlet_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { slong k, p, pmax; n_primes_t iter; @@ -47,7 +47,7 @@ acb_dirichlet_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_d else { long chip; - chip = acb_dirichlet_chi(G, chi, p); + chip = acb_dirichlet_ui_chi(G, chi, p); for (k = p; k < nv; k += p) if (v[k] != -1) diff --git a/acb_dirichlet/ui_pairing.c b/acb_dirichlet/ui_pairing.c new file mode 100644 index 00000000..bccf29df --- /dev/null +++ b/acb_dirichlet/ui_pairing.c @@ -0,0 +1,48 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_ui_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) +{ + ulong x; + acb_dirichlet_conrey_t a, b; + + if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) + return ACB_DIRICHLET_CHI_NULL; + + acb_dirichlet_conrey_init(a, G); + acb_dirichlet_conrey_init(b, G); + acb_dirichlet_conrey_log(a, G, m); + acb_dirichlet_conrey_log(b, G, n); + + x = acb_dirichlet_ui_pairing_conrey(G, a, b); + + acb_dirichlet_conrey_clear(a); + acb_dirichlet_conrey_clear(b); + + return x; +} diff --git a/acb_dirichlet/acb_pairing.c b/acb_dirichlet/ui_pairng_conrey.c similarity index 73% rename from acb_dirichlet/acb_pairing.c rename to acb_dirichlet/ui_pairng_conrey.c index 84e65e66..a5afa42b 100644 --- a/acb_dirichlet/acb_pairing.c +++ b/acb_dirichlet/ui_pairng_conrey.c @@ -21,24 +21,22 @@ Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin ******************************************************************************/ #include "acb_dirichlet.h" -void -acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) +/* todo: modular arithmetic */ + +ulong +acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) { - ulong expo; - expo = acb_dirichlet_pairing(G, m, n); - if (expo == ACB_DIRICHLET_CHI_NULL) - acb_zero(res); - else - { - fmpq_t t; - fmpq_init(t); - fmpq_set_si(t, 2 * expo, G->expo); - arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); - fmpq_clear(t); - } + ulong x, k; + x = 0; + + for (k = 0; k < G->num; k++) + x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; + + return x; } diff --git a/acb_dirichlet/vec_set_null.c b/acb_dirichlet/ui_vec_set_null.c similarity index 94% rename from acb_dirichlet/vec_set_null.c rename to acb_dirichlet/ui_vec_set_null.c index fd95c45e..9a8e831a 100644 --- a/acb_dirichlet/vec_set_null.c +++ b/acb_dirichlet/ui_vec_set_null.c @@ -26,7 +26,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv) +acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv) { slong k, l; if (G->q_even > 1) diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 12b5c33b..a5ddeb51 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -22,26 +22,48 @@ A Dirichlet L-function is the analytic continuation of an L-series where `\chi(k)` is a Dirichlet character. -Dirichlet characters +Multiplicative group modulo *q* ------------------------------------------------------------------------------- +Working with Dirichlet characters mod *q* consists mainly +in going from residue classes mod *q* to exponents on a set +of generators of the group. + +This implementation relies on the Conrey generators introduced +in the LMFDB. We call *number* a residue class, and *index* the +corresponding vector of exponents. + +Going from an *index* to the corresponding *number* is a cheap +operation while the converse requires computing discrete +logarithms. + .. type:: acb_dirichlet_group_struct .. type:: acb_dirichlet_group_t Represents the group of Dirichlet characters mod *q*. - An *acb_dirichlet_group_t* is defined as an array of *acb_dirichlet_struct* + An *acb_dirichlet_group_t* is defined as an array of *acb_dirichlet_group_struct* of length 1, permitting it to be passed by reference. .. function:: void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) Initializes *G* to the group of Dirichlet characters mod *q*. - This method computes the prime factorization of *q* and other useful - invariants. It does *not* automatically precompute lookup tables + This method computes a canonical decomposition of *G* in terms of cyclic + groups, which are the mod `p^e` subgroups for `p^e\|q`. + In particular *G* contains: + + - the number *num* of components + + - the generators + + - the exponent *expo* of the group + + It does *not* automatically precompute lookup tables of discrete logarithms or numerical roots of unity, and can therefore safely be called even with large *q*. + For implementation reasons, the largest prime factor of *q* must not exceed `10^{12}` (an abort will be raised). This restriction could be removed in the future. @@ -50,13 +72,111 @@ Dirichlet characters Clears *G*. -.. function:: void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) +.. function:: void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) - Sets *res* to `\chi_m(n)`, the value of the Dirichlet character - of index *m* evaluated at the integer *n*. + Precompute decomposition and tables for discrete log computations in *G*, + so as to minimize the complexity of *num* calls to discrete logarithms. - Requires that *m* is a valid index, that is, `1 \le m \le q` and *m* is - coprime to *q*. There are no restrictions on *n*. + If *num* gets very large, the entire group may be indexed. + +.. type:: acb_dirichlet_conrey_struct + +.. type:: acb_dirichlet_conrey_t + + Represents elements of the unit group mod *q*, keeping both the + *number* (residue class) and *index* (exponents on the group + generators). + +.. function:: void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) + + Sets *x* to the element of number *m*, computing its index using discrete + logarithm in *G*. + +.. function:: ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) + + Compute the reverse operation. + +.. function:: void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) + + Sets *x* to the *number* `1\in G`, having *index* `[0,\dots 0]`. + +.. function:: int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) + + This function allows to iterate on the elements of *G* looping on the *index*. + It produces elements in seemingly random *number* order. The return value + is the index of the last updated exponent of *x*, or *G->num* if the last + element has been reached. + +Dirichlet characters +------------------------------------------------------------------------------- + +Dirichlet characters take value in a finite cyclic group of roots of unity plus zero. + +When evaluation functions return a *ulong*, this number corresponds to the +power of a primitive root of unity, the special value *ACB_DIRICHLET_CHI_NULL* +encoding the zero value. + +The Conrey numbering scheme makes explicit the mathematical fact that +the group *G* is isomorphic to its dual. + +.. function:: ulong acb_dirichlet_ui_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) + +.. function:: ulong acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) + + Compute the value of the Dirichlet pairing on numbers *m* and *n*, as + exponent modulo *G->expo*. + The second form takes the index *a* and *b*, and does not take discrete + logarithms. + + The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. + +.. type:: acb_dirichlet_char_struct + +.. type:: acb_dirichlet_char_t + + Represents a Dirichlet character. This structure contains various + useful invariants such as the order of the character. + + An *acb_dirichlet_char_t* is defined as an array of *acb_dirichlet_char_struct* + of length 1, permitting it to be passed by reference. + +.. function:: void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); + +.. function:: void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); + + Initializes and clear *chi*. + +.. function:: void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); + + Sets *chi* to the Dirichlet character of number *n*, using Conrey numbering scheme. + This function performs a discrete logarithm in *G*. + +.. function:: void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); + + Sets *chi* to the Dirichlet character of Conrey index *x*. + +Character properties +------------------------------------------------------------------------------- + +.. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) + +.. function:: int acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) + +.. function:: ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) + +Character evaluation +------------------------------------------------------------------------------- + +The image of a Dirichlet character is a finite cyclic group. Dirichlet +character evaluations are either exponents in this group, or an *acb_t* root of +unity. + +.. function:: void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) + + Sets *res* to `\chi(n)`, the value of the Dirichlet character *chi* + at the integer *n*. + + There are no restrictions on *n*. Euler products ------------------------------------------------------------------------------- From f7ac9d685f9443062bfad808b86f0d6c4d305845 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 12 Apr 2016 15:07:04 +0200 Subject: [PATCH 031/139] add theta functions --- acb_dirichlet.h | 28 +++++- acb_dirichlet/arb_theta.c | 149 +++++++++++++++++++++++++++++++ acb_dirichlet/chi_vec.c | 51 +++++++++++ acb_dirichlet/gauss_sum.c | 51 +++++++++++ acb_dirichlet/gauss_sum_naive.c | 45 ++++++++++ acb_dirichlet/gauss_sum_theta.c | 65 ++++++++++++++ acb_dirichlet/l.c | 28 +++--- acb_dirichlet/nth_root.c | 24 ++++- acb_dirichlet/power.c | 51 +++++++++++ acb_dirichlet/powers_clear.c | 35 ++++++++ acb_dirichlet/powers_init.c | 57 ++++++++++++ acb_dirichlet/test/t-gauss.c | 95 ++++++++++++++++++++ acb_dirichlet/test/t-thetanull.c | 2 +- acb_dirichlet/theta_length.c | 16 +++- acb_dirichlet/ui_chi.c | 8 +- acb_dirichlet/ui_chi_conrey.c | 37 ++++++++ 16 files changed, 721 insertions(+), 21 deletions(-) create mode 100644 acb_dirichlet/arb_theta.c create mode 100644 acb_dirichlet/chi_vec.c create mode 100644 acb_dirichlet/gauss_sum.c create mode 100644 acb_dirichlet/gauss_sum_naive.c create mode 100644 acb_dirichlet/gauss_sum_theta.c create mode 100644 acb_dirichlet/power.c create mode 100644 acb_dirichlet/powers_clear.c create mode 100644 acb_dirichlet/powers_init.c create mode 100644 acb_dirichlet/test/t-gauss.c create mode 100644 acb_dirichlet/ui_chi_conrey.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 5f9909f8..ce510fb4 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -132,6 +132,7 @@ ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_diri void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); +ulong acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); void acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv); @@ -140,12 +141,37 @@ void acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, void acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); void acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +/* precompute powers of a root of unity */ +typedef struct +{ + ulong order; + acb_ptr z; + ulong m; + ulong M; + acb_ptr Z; +} +acb_dirichlet_powers_struct; + +typedef acb_dirichlet_powers_struct acb_dirichlet_powers_t[1]; + +void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec); +void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t); +void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec); + void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec); void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); +void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec); void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); -ulong acb_dirichlet_theta_length(ulong q, double x, slong prec); + +ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec); +ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec); +void acb_dirichlet_chi_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t x, slong prec); + +void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); #ifdef __cplusplus } diff --git a/acb_dirichlet/arb_theta.c b/acb_dirichlet/arb_theta.c new file mode 100644 index 00000000..f7de9673 --- /dev/null +++ b/acb_dirichlet/arb_theta.c @@ -0,0 +1,149 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +/* x = Pi / q * t^2 */ +static void +acb_dirichlet_arb_theta_argt(arb_t x, ulong q, const arb_t t, slong prec) +{ + arb_const_pi(x, prec); + arb_div_ui(x, x, q, prec); + arb_mul(x, x, t, prec); + arb_mul(x, x, t, prec); + arb_neg(x, x); + arb_exp(x, x, prec); +} + +/* small order, multiply by chi at the end */ +void +acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) +{ + slong k; + ulong order = z->order; + arb_t xk2, kxk2, dx, x2; + acb_ptr t; + arb_init(xk2); + arb_init(dx); + arb_init(x2); + arb_init(kxk2); + + arb_set(dx, x); + arb_set(xk2, x); + arb_mul(x2, x, x, prec); + + t = _acb_vec_init(order); + _acb_vec_zero(t, order); + + arb_set(acb_realref(t + 0), xk2); + + /* TODO: reduce precision at each step */ + for (k = 2; k < len; k++) + { + arb_mul(dx, dx, x2, prec); + arb_mul(xk2, xk2, dx, prec); + if (a[k] != ACB_DIRICHLET_CHI_NULL) + { + if (parity) + { + arb_mul_si(kxk2, xk2, k, prec); + arb_add(acb_realref(t + a[k]), acb_realref(t + a[k]), kxk2, prec); + } + else + { + arb_add(acb_realref(t + a[k]), acb_realref(t + a[k]), xk2, prec); + } + } + } + + /* now Hörner */ + _acb_poly_evaluate(res, t, order, z->z + 1, prec); + + _acb_vec_clear(t, order); + arb_clear(xk2); + arb_clear(x2); + arb_clear(dx); +} + +void +acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) +{ + slong k; + arb_t xk2, dx, x2; + acb_t zk; + arb_init(xk2); + arb_init(dx); + arb_init(x2); + acb_init(zk); + + arb_set(dx, x); + arb_set(xk2, dx); + arb_mul(x2, dx, dx, prec); + + acb_set_arb(res, xk2); + + /* TODO: reduce prec */ + for (k = 2; k < len; k++) + { + arb_mul(dx, dx, x2, prec); + arb_mul(xk2, xk2, dx, prec); + if (a[k] != ACB_DIRICHLET_CHI_NULL) + { + acb_dirichlet_power(zk, z, a[k], prec); + if (parity) + acb_mul_si(zk, zk, k, prec); + acb_addmul_arb(res, zk, xk2, prec); + } + } + + arb_clear(xk2); + arb_clear(x2); + arb_clear(dx); + acb_clear(zk); +} + +void +acb_dirichlet_chi_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) +{ + slong len; + ulong * a; + arb_t x; + acb_dirichlet_powers_t z; + + len = acb_dirichlet_theta_length(G->q, t, prec); + + a = flint_malloc(len * sizeof(ulong)); + acb_dirichlet_ui_chi_vec(a, G, chi, len); + acb_dirichlet_powers_init(z, chi->order, len, prec); + + arb_init(x); + acb_dirichlet_arb_theta_argt(x, G->q, t, prec); + acb_dirichlet_arb_theta_naive(res, x, chi->parity, a, z, len, prec); + + arb_clear(x); + flint_free(a); + acb_dirichlet_powers_clear(z); +} diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/chi_vec.c new file mode 100644 index 00000000..7b4dcee6 --- /dev/null +++ b/acb_dirichlet/chi_vec.c @@ -0,0 +1,51 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec) +{ + slong k; + ulong * a; + acb_dirichlet_powers_t t; + + a = flint_malloc(nv * sizeof(ulong)); + acb_dirichlet_ui_chi_vec(a, G, chi, nv); + + acb_dirichlet_powers_init(t, chi->order, nv, prec); + + acb_zero(v + 0); + for (k = 0; k < nv; k++) + { + if (a[k] != ACB_DIRICHLET_CHI_NULL) + acb_dirichlet_power(v + k, t, a[k], prec); + else + *(v + k) = *(v + 0); + } + + acb_dirichlet_powers_clear(t); + flint_free(a); +} diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c new file mode 100644 index 00000000..969b75e3 --- /dev/null +++ b/acb_dirichlet/gauss_sum.c @@ -0,0 +1,51 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + if (chi->order <= 2) + { + if (chi->parity) + { + arb_sqrt_ui(acb_imagref(res), G->q, prec); + arb_zero(acb_realref(res)); + } + else + { + arb_sqrt_ui(acb_realref(res), G->q, prec); + arb_zero(acb_imagref(res)); + } + } + else + { + if (acb_dirichlet_theta_length_d(G->q, 1, prec) > G->q) + acb_dirichlet_gauss_sum_naive(res, G, chi, prec); + else + acb_dirichlet_gauss_sum_theta(res, G, chi, prec); + } +} diff --git a/acb_dirichlet/gauss_sum_naive.c b/acb_dirichlet/gauss_sum_naive.c new file mode 100644 index 00000000..2299fa5b --- /dev/null +++ b/acb_dirichlet/gauss_sum_naive.c @@ -0,0 +1,45 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +void +acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + acb_t z; + acb_ptr v; + + v = _acb_vec_init(G->q); + acb_dirichlet_chi_vec(v, G, chi, G->q, prec); + + acb_init(z); + acb_dirichlet_nth_root(z, G->q, prec); + + _acb_poly_evaluate(res, v, G->q, z, prec); + + acb_clear(z); + _acb_vec_clear(v, G->q); +} diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c new file mode 100644 index 00000000..8db71b3e --- /dev/null +++ b/acb_dirichlet/gauss_sum_theta.c @@ -0,0 +1,65 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + arb_t x; + acb_t eps; + + arb_init(x); + + if ((G->q == 300 && (chi->n == 271 || chi->n == 131)) + || (G->q == 600 && (chi->n == 11 || chi->n == 91))) + { + /* or could use l'Hopital rule */ + acb_dirichlet_gauss_sum_naive(res, G, chi, prec); + return; + } + + arb_one(x); + acb_dirichlet_chi_theta(res, G, chi, x, prec); + acb_init(eps); + acb_conj(eps, res); + acb_div(eps, res, eps, prec); + + if (chi->parity) + { + arb_zero(acb_realref(res)); + arb_sqrt_ui(acb_imagref(res), G->q, prec); + } + else + { + arb_zero(acb_imagref(res)); + arb_sqrt_ui(acb_realref(res), G->q, prec); + } + + acb_mul(res, res, eps, prec); + + arb_clear(x); + acb_clear(eps); +} diff --git a/acb_dirichlet/l.c b/acb_dirichlet/l.c index 2f2a41a6..d556eb95 100644 --- a/acb_dirichlet/l.c +++ b/acb_dirichlet/l.c @@ -12,31 +12,35 @@ #include "acb_dirichlet.h" void -acb_dirichlet_l(acb_t res, const acb_t s, - const acb_dirichlet_group_t G, ulong m, slong prec) +acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, + const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { - acb_t chi, t, u, a; - acb_dirichlet_conrey_t cm, cn; + ulong chin; + acb_t z, t, u, a; + acb_ptr xz; + acb_dirichlet_conrey_t cn; - acb_init(chi); - acb_dirichlet_conrey_init(cm, G); acb_dirichlet_conrey_init(cn, G); + acb_init(z); acb_init(t); acb_init(u); acb_init(a); - acb_dirichlet_conrey_log(cm, G, m); acb_dirichlet_conrey_one(cn, G); acb_zero(t); + acb_dirichlet_nth_root(z, chi->order, prec); + xz = _acb_vec_init(chi->order); + _acb_vec_set_powers(xz, z, chi->order, prec); + while (1) { - /* todo: use n_dirichlet_chi and precomputed roots instead */ - acb_dirichlet_pairing_conrey(chi, G, cm, cn, prec); + chin = acb_dirichlet_ui_chi_conrey(G, chi, cn); acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); acb_hurwitz_zeta(u, s, a, prec); - acb_addmul(t, chi, u, prec); + + acb_addmul(t, xz + chin, u, prec); if (acb_dirichlet_conrey_next(cn, G) == G->num) break; @@ -47,10 +51,10 @@ acb_dirichlet_l(acb_t res, const acb_t s, acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); - acb_dirichlet_conrey_clear(cm); acb_dirichlet_conrey_clear(cn); - acb_clear(chi); + _acb_vec_clear(xz, chi->order); + acb_clear(z); acb_clear(t); acb_clear(u); acb_clear(a); diff --git a/acb_dirichlet/nth_root.c b/acb_dirichlet/nth_root.c index 01d0388c..81f751df 100644 --- a/acb_dirichlet/nth_root.c +++ b/acb_dirichlet/nth_root.c @@ -25,8 +25,8 @@ #include "acb_dirichlet.h" -void -acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) +static void +_acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) { fmpq_t t; fmpq_init(t); @@ -34,3 +34,23 @@ acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); fmpq_clear(t); } + +void +acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) +{ + switch (order) + { + case 1: + acb_one(res); + break; + case 2: + acb_set_si(res, -1); + break; + case 4: + acb_onei(res); + break; + default: + _acb_dirichlet_nth_root(res, order, prec); + break; + } +} diff --git a/acb_dirichlet/power.c b/acb_dirichlet/power.c new file mode 100644 index 00000000..31dfceb1 --- /dev/null +++ b/acb_dirichlet/power.c @@ -0,0 +1,51 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +/* assume won't be modified */ +void +acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec) +{ + if (n < t->m) + { + /* acb_set(z, t->z + n); */ + *z = *(t->z + n); + } + else + { + ulong q, r; + q = n / t->m; + r = n % t->m; + if (q >= t->M) + { + flint_printf("acb_dirichlet_power: power %wu not available " + "in table of size %wu * %wu.", n, t->m, t->M); + abort(); + } + acb_mul(z, t->Z + q, t->z + r, prec); + } +} diff --git a/acb_dirichlet/powers_clear.c b/acb_dirichlet/powers_clear.c new file mode 100644 index 00000000..3417cd34 --- /dev/null +++ b/acb_dirichlet/powers_clear.c @@ -0,0 +1,35 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +void +acb_dirichlet_powers_clear(acb_dirichlet_powers_t t) +{ + _acb_vec_clear(t->z, t->m); + if (t->M) + _acb_vec_clear(t->Z, t->M); +} diff --git a/acb_dirichlet/powers_init.c b/acb_dirichlet/powers_init.c new file mode 100644 index 00000000..a6b70481 --- /dev/null +++ b/acb_dirichlet/powers_init.c @@ -0,0 +1,57 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +void +acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec) +{ + ulong m; + acb_t zeta; + t->order = order; + m = (num == 1) ? 1 : num * (prec / 64 + 1); + if (m > order) + m = order; + t->m = m; + + acb_init(zeta); + acb_dirichlet_nth_root(zeta, order, prec); + t->z = _acb_vec_init(m); + _acb_vec_set_powers(t->z, zeta, m, prec); + + if (order > m) + { + t->M = (order / m) + 1; + t->Z = _acb_vec_init(t->M); + acb_pow_ui(zeta, zeta, m, prec); + _acb_vec_set_powers(t->Z, zeta, t->M, prec); + } + else + { + t->M = 0; + t->Z = NULL; + } +} diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c new file mode 100644 index 00000000..8b4687c5 --- /dev/null +++ b/acb_dirichlet/test/t-gauss.c @@ -0,0 +1,95 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int main() +{ + slong prec = 128; + ulong q; + + flint_printf("gauss...."); + fflush(stdout); + + /* check Gauss sums */ + + for (q = 3; q < 200; q ++) + { + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_dirichlet_char_t chi; + + acb_t s1, s2, s3; + + if (q % 4 == 2) + /* no primitive character mod q */ + continue; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_char_init(chi, G); + + acb_init(s1); + acb_init(s2); + acb_init(s3); + acb_dirichlet_conrey_first_primitive(x, G); + + while (1) { + + acb_dirichlet_char_conrey(chi, G, x); + + acb_dirichlet_gauss_sum_naive(s1, G, chi, prec); + acb_dirichlet_gauss_sum_theta(s2, G, chi, prec); + acb_dirichlet_gauss_sum(s3, G, chi, prec); + + if (!acb_overlaps(s1, s2) + || !acb_overlaps(s1, s3)) + { + flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->n); + flint_printf("\nnaive ", q, x->n); + acb_printd(s1, 25); + flint_printf("\ntheta ", q, x->n); + acb_printd(s2, 25); + flint_printf("\ndefault ", q, x->n); + acb_printd(s3, 25); + abort(); + } + + if (acb_dirichlet_conrey_next_primitive(x, G) == G->num) + break; + } + acb_clear(s1); + acb_clear(s2); + acb_clear(s3); + + acb_dirichlet_group_clear(G); + acb_dirichlet_char_clear(chi); + acb_dirichlet_conrey_clear(x); + } + + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 950991bb..71517fce 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -66,7 +66,7 @@ int main() z = _acb_vec_init(G->expo); _acb_vec_set_powers(z, zeta, G->expo, prec); - nv = acb_dirichlet_theta_length(q, 1, prec); + nv = acb_dirichlet_theta_length_d(q, 1, prec); v = flint_malloc(nv * sizeof(ulong)); arb_init(eq); diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c index 7e6cc6cb..0f09d3a3 100644 --- a/acb_dirichlet/theta_length.c +++ b/acb_dirichlet/theta_length.c @@ -29,8 +29,22 @@ #define LOG2 0.69314718055 ulong -acb_dirichlet_theta_length(ulong q, double x, slong prec) +acb_dirichlet_theta_length_d(ulong q, double x, slong prec) { double a = PI / (double)q * x * x; return ceil(sqrt(((double)prec * LOG2 - log(2 * a)) / a)); } + +ulong +acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec) +{ + double dx; + ulong len; + arf_t ax; + arf_init(ax); + arb_get_lbound_arf(ax, x, 53); + dx = arf_get_d(ax, ARF_RND_DOWN); + len = acb_dirichlet_theta_length_d(q, dx, prec); + arf_clear(ax); + return len; +} diff --git a/acb_dirichlet/ui_chi.c b/acb_dirichlet/ui_chi.c index 2cdfa428..f163a874 100644 --- a/acb_dirichlet/ui_chi.c +++ b/acb_dirichlet/ui_chi.c @@ -34,13 +34,13 @@ acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t c } else { - ulong v = 0, k; + ulong v; acb_dirichlet_conrey_t x; acb_dirichlet_conrey_init(x, G); acb_dirichlet_conrey_log(x, G, n); - for (k = 0; k < G->num; k++) - v = (v + chi->expo[k] * x->log[k]) % chi->order; - acb_dirichlet_conrey_clear(x); + + v = acb_dirichlet_ui_chi_conrey(G, chi, x); + return v; } } diff --git a/acb_dirichlet/ui_chi_conrey.c b/acb_dirichlet/ui_chi_conrey.c new file mode 100644 index 00000000..51a804b5 --- /dev/null +++ b/acb_dirichlet/ui_chi_conrey.c @@ -0,0 +1,37 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const acb_dirichlet_conrey_t x) +{ + ulong v = 0, k; + + for (k = 0; k < G->num; k++) + v = (v + chi->expo[k] * x->log[k]) % chi->order; + + return v; +} From 656a426e4a9821830dfba72392b3b9d45d6edc95 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 15 Jun 2016 11:33:01 +0200 Subject: [PATCH 032/139] add conductor inside char type --- acb_dirichlet.h | 22 ++++++++--- acb_dirichlet/char_conductor.c | 26 +----------- acb_dirichlet/char_conrey.c | 1 + acb_dirichlet/char_first_primitive.c | 1 + acb_dirichlet/char_one.c | 1 + acb_dirichlet/conrey_conductor.c | 59 ++++++++++++++++++++++++++++ acb_dirichlet/conrey_pow.c | 35 +++++++++++++++++ acb_dirichlet/test/t-chars.c | 59 +++++++++++++++++++++++++++- 8 files changed, 172 insertions(+), 32 deletions(-) create mode 100644 acb_dirichlet/conrey_conductor.c create mode 100644 acb_dirichlet/conrey_pow.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index ce510fb4..00a8d47c 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -49,6 +49,16 @@ acb_dirichlet_group_struct; typedef acb_dirichlet_group_struct acb_dirichlet_group_t[1]; +ACB_DIRICHLET_INLINE ulong +acb_dirichlet_group_size(const acb_dirichlet_group_t G) +{ + return G->phi_q; +} + +void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); +void acb_dirichlet_group_clear(acb_dirichlet_group_t G); +void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); + /* elements of the group, keep both number and log */ typedef struct { @@ -64,16 +74,12 @@ void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); -void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); -void acb_dirichlet_group_clear(acb_dirichlet_group_t G); -void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); - - void acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); void acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); +ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); @@ -82,6 +88,9 @@ void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_di int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); +void acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); +void acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n); + #define ACB_DIRICHLET_CHI_NULL UWORD_MAX ulong acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); @@ -92,7 +101,7 @@ void acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ul /* introducing character type */ -/* character = reduced exponents, keep order and number */ +/* character = reduced exponents, keep order, number and conductor */ typedef struct { ulong q; /* modulus */ @@ -101,6 +110,7 @@ typedef struct ulong order; /* order */ ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ int parity; /* 0 for even char, 1 for odd */ + ulong conductor; } acb_dirichlet_char_struct; diff --git a/acb_dirichlet/char_conductor.c b/acb_dirichlet/char_conductor.c index 62e96f0a..79ff14a5 100644 --- a/acb_dirichlet/char_conductor.c +++ b/acb_dirichlet/char_conductor.c @@ -28,29 +28,5 @@ ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) { - int k, f; - ulong cond = 1; - if (G->neven >= 1 && chi->expo[0] == 1) - cond = 4; - if (G->neven == 2 && chi->expo[1]) - { - ulong l2 = chi->expo[1]; - f = n_remove(&l2, 2); - cond = G->primepowers[1] >> f; - } - for (k = G->neven; k < G->neven; k++) - { - if (chi->expo[k]) - { - ulong p, lp; - p = G->primes[k]; - lp = chi->expo[k]; - f = n_remove(&lp, p); - if (f) - cond *= n_pow(p, G->exponents[k] - f); - else - cond *= G->primepowers[k]; - } - } - return cond; + return chi->conductor; } diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c index 9f9d1a38..73f4a85a 100644 --- a/acb_dirichlet/char_conrey.c +++ b/acb_dirichlet/char_conrey.c @@ -34,6 +34,7 @@ acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t chi->q = G->q; chi->n = x->n; chi->parity = acb_dirichlet_conrey_parity(G, x); + chi->conductor = acb_dirichlet_conrey_conductor(G, x); for (k = 0; k < G->num; k++) chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; diff --git a/acb_dirichlet/char_first_primitive.c b/acb_dirichlet/char_first_primitive.c index 71881814..0310fe95 100644 --- a/acb_dirichlet/char_first_primitive.c +++ b/acb_dirichlet/char_first_primitive.c @@ -33,5 +33,6 @@ acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet x->log = chi->expo; acb_dirichlet_conrey_first_primitive(x, G); chi->n = x->n; + chi->conductor = chi->q; acb_dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_one.c b/acb_dirichlet/char_one.c index ab6e09c2..232a2460 100644 --- a/acb_dirichlet/char_one.c +++ b/acb_dirichlet/char_one.c @@ -36,4 +36,5 @@ acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) chi->expo[k] = 0; chi->order = 1; + chi->conductor = 1; } diff --git a/acb_dirichlet/conrey_conductor.c b/acb_dirichlet/conrey_conductor.c new file mode 100644 index 00000000..45f36108 --- /dev/null +++ b/acb_dirichlet/conrey_conductor.c @@ -0,0 +1,59 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +{ + int k, f; + ulong cond = 1; + + if (G->neven >= 1 && x->log[0] == 1) + cond = 4; + if (G->neven == 2 && x->log[1]) + { + ulong l2 = x->log[1]; + f = n_remove(&l2, 2); + cond = G->primepowers[1] >> f; + } + + for (k = G->neven; k < G->num; k++) + { + if (x->log[k]) + { + ulong p, lp; + p = G->primes[k]; + lp = x->log[k]; + f = n_remove(&lp, p); + if (f) + cond *= n_pow(p, G->exponents[k] - f); + else + cond *= G->primepowers[k]; + } + } + + return cond; +} diff --git a/acb_dirichlet/conrey_pow.c b/acb_dirichlet/conrey_pow.c new file mode 100644 index 00000000..960c88c7 --- /dev/null +++ b/acb_dirichlet/conrey_pow.c @@ -0,0 +1,35 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n) +{ + ulong k; + for (k = 0; k < G->num ; k++) + c->log[k] = (a->log[k] * n) % G->phi[k]; + c->n = nmod_pow_ui(a->n, n, G->mod); +} diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index a178811a..5ef34948 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -45,6 +45,52 @@ nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) return order; } +static ulong +n_conductor(ulong q, ulong a) +{ + slong k; + ulong ap, cond; + + nmod_t pe; + n_factor_t fac; + n_factor_init(&fac); + n_factor(&fac, q, 1); + + cond = 1; + + for (k = 0; k < fac.num; k++) + { + ulong p, e; + p = fac.p[k]; + e = fac.exp[k]; + + nmod_init(&pe, n_pow(p, e)); + ap = a % pe.n; + if (ap == 1) + continue; + if (p == 2) + { + cond = 4; + if (a % 4 == 3) + ap = pe.n - ap; + } + else + { + cond *= p; + ap = nmod_pow_ui(ap, p - 1, pe); + } + + while (ap != 1) + { + cond *= p; + ap = nmod_pow_ui(ap, p, pe); + } + + } + + return cond; +} + int main() { slong iter, bits; @@ -78,7 +124,7 @@ int main() for (iter2 = 0; iter2 < 50; iter2++) { ulong m, n; - ulong order, chim1, pairing; + ulong order, chim1, pairing, cond; do m = n_randint(state, q); @@ -97,6 +143,17 @@ int main() abort(); } + cond = n_conductor(G->q, m); + if (cond != acb_dirichlet_char_conductor(G, chi)) + { + flint_printf("FAIL: conductor\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("conductor(m) = %wu\n\n", cond); + flint_printf("chi->conductor = %wu\n\n", acb_dirichlet_char_conductor(G, chi)); + abort(); + } + chim1 = acb_dirichlet_ui_chi(G, chi, q - 1); if (acb_dirichlet_char_parity(chi) != (chim1 != 0)) { From 31f9665db71474cae2933607c4651039f7b94a74 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 15 Jun 2016 12:23:24 +0200 Subject: [PATCH 033/139] export conductor_ui and number_primitive --- acb_dirichlet.h | 9 +++++ acb_dirichlet/conductor_ui.c | 67 ++++++++++++++++++++++++++++++++ acb_dirichlet/number_primitive.c | 53 +++++++++++++++++++++++++ acb_dirichlet/test/t-chars.c | 48 +---------------------- acb_dirichlet/test/t-conrey.c | 18 +-------- 5 files changed, 131 insertions(+), 64 deletions(-) create mode 100644 acb_dirichlet/conductor_ui.c create mode 100644 acb_dirichlet/number_primitive.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 00a8d47c..9a498b60 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -59,6 +59,15 @@ void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); void acb_dirichlet_group_clear(acb_dirichlet_group_t G); void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); +/* properties of elements without log */ + +ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G); +ulong acb_dirichlet_conductor_ui(const acb_dirichlet_group_t G, ulong a); +/* +ulong acb_dirichlet_parity_ui(const acb_dirichlet_groupt_t G, ulong a); +ulong acb_dirichlet_order_ui(const acb_dirichlet_groupt_t G, ulong a); +*/ + /* elements of the group, keep both number and log */ typedef struct { diff --git a/acb_dirichlet/conductor_ui.c b/acb_dirichlet/conductor_ui.c new file mode 100644 index 00000000..8e5d1999 --- /dev/null +++ b/acb_dirichlet/conductor_ui.c @@ -0,0 +1,67 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_conductor_ui(const acb_dirichlet_group_t G, ulong a) +{ + slong k; + ulong ap, cond; + nmod_t pe; + + cond = 1; + + for (k = (G->neven == 2); k < G->num; k++) + { + ulong p, e; + p = G->primes[k]; + e = G->exponents[k]; + nmod_init(&pe, G->primepowers[k]); + ap = a % pe.n; + if (ap == 1) + continue; + if (p == 2) + { + cond = 4; + if (a % 4 == 3) + ap = pe.n - ap; + } + else + { + cond *= p; + ap = nmod_pow_ui(ap, p - 1, pe); + } + + while (ap != 1) + { + cond *= p; + ap = nmod_pow_ui(ap, p, pe); + } + + } + + return cond; +} diff --git a/acb_dirichlet/number_primitive.c b/acb_dirichlet/number_primitive.c new file mode 100644 index 00000000..78ebfa75 --- /dev/null +++ b/acb_dirichlet/number_primitive.c @@ -0,0 +1,53 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) +{ + if (G->q % 4 == 2) + return 0; + else + { + slong k; + ulong n = 1; + + /* no overflow since result < G->q */ + + for (k = (G->neven == 2); k < G->num; k++) + { + ulong p = G->primes[k]; + if (G->exponents[k] == 1) + n *= p - 2; + else + n *= (p * (p - 2) + 1) * n_pow(p, G->exponents[k] - 2); + } + + return n; + } +} + + diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 5ef34948..61ca894c 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -45,52 +45,6 @@ nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) return order; } -static ulong -n_conductor(ulong q, ulong a) -{ - slong k; - ulong ap, cond; - - nmod_t pe; - n_factor_t fac; - n_factor_init(&fac); - n_factor(&fac, q, 1); - - cond = 1; - - for (k = 0; k < fac.num; k++) - { - ulong p, e; - p = fac.p[k]; - e = fac.exp[k]; - - nmod_init(&pe, n_pow(p, e)); - ap = a % pe.n; - if (ap == 1) - continue; - if (p == 2) - { - cond = 4; - if (a % 4 == 3) - ap = pe.n - ap; - } - else - { - cond *= p; - ap = nmod_pow_ui(ap, p - 1, pe); - } - - while (ap != 1) - { - cond *= p; - ap = nmod_pow_ui(ap, p, pe); - } - - } - - return cond; -} - int main() { slong iter, bits; @@ -143,7 +97,7 @@ int main() abort(); } - cond = n_conductor(G->q, m); + cond = acb_dirichlet_conductor_ui(G, m); if (cond != acb_dirichlet_char_conductor(G, chi)) { flint_printf("FAIL: conductor\n\n"); diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index d7da9844..651a6e34 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -96,26 +96,10 @@ int main() if (q % 4 == 2) continue; - /* check primitive elements */ - if (q % 4 == 2) - ref = 0; - else - { - ref = 1; - k = (G->neven == 2) ? 1 : 0; - for (; k < G->num; k++) - { - ulong p = G->primes[k]; - if (G->exponents[k] == 1) - ref *= p - 2; - else - ref *= (p * (p - 2) + 1) * n_pow(p, G->exponents[k] - 2); - } - } - acb_dirichlet_conrey_first_primitive(x, G); for (n = 1; (k=acb_dirichlet_conrey_next_primitive(x, G)) < G->num; n++); + ref = acb_dirichlet_number_primitive(G); if (n != ref) { flint_printf("FAIL: number of primitive elements\n\n"); From c37c09522f8c7a47d6e846d4011b5736e858a4c2 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 15 Jun 2016 14:04:27 +0200 Subject: [PATCH 034/139] parity --- acb_dirichlet.h | 2 +- acb_dirichlet/eta.c | 1 - acb_dirichlet/parity_ui.c | 46 +++++++++++++++++++ acb_dirichlet/test/t-chars.c | 5 +- ...ui_pairng_conrey.c => ui_pairing_conrey.c} | 0 5 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 acb_dirichlet/parity_ui.c rename acb_dirichlet/{ui_pairng_conrey.c => ui_pairing_conrey.c} (100%) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 9a498b60..73398507 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -63,8 +63,8 @@ void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G); ulong acb_dirichlet_conductor_ui(const acb_dirichlet_group_t G, ulong a); +int acb_dirichlet_parity_ui(const acb_dirichlet_group_t G, ulong a); /* -ulong acb_dirichlet_parity_ui(const acb_dirichlet_groupt_t G, ulong a); ulong acb_dirichlet_order_ui(const acb_dirichlet_groupt_t G, ulong a); */ diff --git a/acb_dirichlet/eta.c b/acb_dirichlet/eta.c index 4c7f0d4e..d64b8dca 100644 --- a/acb_dirichlet/eta.c +++ b/acb_dirichlet/eta.c @@ -34,4 +34,3 @@ acb_dirichlet_eta(acb_t res, const acb_t s, slong prec) acb_clear(t); } } - diff --git a/acb_dirichlet/parity_ui.c b/acb_dirichlet/parity_ui.c new file mode 100644 index 00000000..634eb030 --- /dev/null +++ b/acb_dirichlet/parity_ui.c @@ -0,0 +1,46 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_parity_ui(const acb_dirichlet_group_t G, ulong a) +{ + slong k; + int par; + + par = 0; + + if (G->neven && a % 4 == 3) + par++; + + for (k = G->neven; k < G->num; k++) + { + if (n_jacobi_unsigned(a, G->primes[k]) == -1) + par++; + } + + return par % 2; +} diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 61ca894c..6fdbae1f 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -77,6 +77,7 @@ int main() /* check number char properties */ for (iter2 = 0; iter2 < 50; iter2++) { + int par; ulong m, n; ulong order, chim1, pairing, cond; @@ -108,14 +109,16 @@ int main() abort(); } + par = acb_dirichlet_parity_ui(G, m); chim1 = acb_dirichlet_ui_chi(G, chi, q - 1); - if (acb_dirichlet_char_parity(chi) != (chim1 != 0)) + if (acb_dirichlet_char_parity(chi) != par || par != (chim1 != 0)) { flint_printf("FAIL: parity\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("chi(-1) = %wu\n\n", chim1); flint_printf("char_parity = %d", acb_dirichlet_char_parity(chi)); + flint_printf("parity_ui = %d", par); acb_dirichlet_char_print(G, chi); abort(); } diff --git a/acb_dirichlet/ui_pairng_conrey.c b/acb_dirichlet/ui_pairing_conrey.c similarity index 100% rename from acb_dirichlet/ui_pairng_conrey.c rename to acb_dirichlet/ui_pairing_conrey.c From ed86f818c831bab9f7513265e06faf6fdcfdaadc Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 15 Jun 2016 15:24:49 +0200 Subject: [PATCH 035/139] length estimate fot odd theta series --- acb_dirichlet/char_next.c | 2 ++ acb_dirichlet/parity_ui.c | 1 + acb_dirichlet/theta_length.c | 7 +++++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/acb_dirichlet/char_next.c b/acb_dirichlet/char_next.c index c5183766..5a43bff8 100644 --- a/acb_dirichlet/char_next.c +++ b/acb_dirichlet/char_next.c @@ -42,6 +42,8 @@ acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) chi->expo[k] = 0; } + /* should do it with log, but not kept yet */ + chi->conductor = acb_dirichlet_conductor_ui(G, chi->n); acb_dirichlet_char_normalize(chi, G); /* return last index modified */ diff --git a/acb_dirichlet/parity_ui.c b/acb_dirichlet/parity_ui.c index 634eb030..73dab504 100644 --- a/acb_dirichlet/parity_ui.c +++ b/acb_dirichlet/parity_ui.c @@ -36,6 +36,7 @@ acb_dirichlet_parity_ui(const acb_dirichlet_group_t G, ulong a) if (G->neven && a % 4 == 3) par++; + /* could replace by jacobi(a, core(q_odd)) */ for (k = G->neven; k < G->num; k++) { if (n_jacobi_unsigned(a, G->primes[k]) == -1) diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c index 0f09d3a3..5cf471ee 100644 --- a/acb_dirichlet/theta_length.c +++ b/acb_dirichlet/theta_length.c @@ -31,8 +31,11 @@ ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec) { - double a = PI / (double)q * x * x; - return ceil(sqrt(((double)prec * LOG2 - log(2 * a)) / a)); + double a, la; + a = PI / (double)q * x * x; + la = (a>.3) ? -log(2*a*(1-a)) : .8; + la = ((double)prec * LOG2 + la) / a; + return ceil(sqrt(la)+.5); } ulong From a48ca38e09cdb2b7ba4805e4fc1ae45c793037c6 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 15 Jun 2016 17:25:14 +0200 Subject: [PATCH 036/139] refactor order --- acb_dirichlet.h | 18 +++--- acb_dirichlet/char_next.c | 4 +- acb_dirichlet/conrey_order.c | 38 +++++++++++++ acb_dirichlet/test/t-chars.c | 29 +--------- acb_dirichlet/theta_length.c | 2 +- .../{conductor_ui.c => ui_conductor.c} | 2 +- acb_dirichlet/ui_order.c | 55 +++++++++++++++++++ acb_dirichlet/{parity_ui.c => ui_parity.c} | 2 +- doc/source/acb_dirichlet.rst | 47 ++++++++++++++-- 9 files changed, 150 insertions(+), 47 deletions(-) create mode 100644 acb_dirichlet/conrey_order.c rename acb_dirichlet/{conductor_ui.c => ui_conductor.c} (96%) create mode 100644 acb_dirichlet/ui_order.c rename acb_dirichlet/{parity_ui.c => ui_parity.c} (95%) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 73398507..0113f25f 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -27,6 +27,11 @@ extern "C" { #endif +void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, + const signed char * chi, int mod, int reciprocal, slong prec); + +void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); + typedef struct { ulong q; /* modulus */ @@ -62,11 +67,9 @@ void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); /* properties of elements without log */ ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G); -ulong acb_dirichlet_conductor_ui(const acb_dirichlet_group_t G, ulong a); -int acb_dirichlet_parity_ui(const acb_dirichlet_group_t G, ulong a); -/* -ulong acb_dirichlet_order_ui(const acb_dirichlet_groupt_t G, ulong a); -*/ +ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a); +int acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a); +ulong acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a); /* elements of the group, keep both number and log */ typedef struct @@ -78,11 +81,6 @@ acb_dirichlet_conrey_struct; typedef acb_dirichlet_conrey_struct acb_dirichlet_conrey_t[1]; -void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, - const signed char * chi, int mod, int reciprocal, slong prec); - -void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); - void acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); void acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); diff --git a/acb_dirichlet/char_next.c b/acb_dirichlet/char_next.c index 5a43bff8..b144a590 100644 --- a/acb_dirichlet/char_next.c +++ b/acb_dirichlet/char_next.c @@ -42,8 +42,8 @@ acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) chi->expo[k] = 0; } - /* should do it with log, but not kept yet */ - chi->conductor = acb_dirichlet_conductor_ui(G, chi->n); + /* should do it with log, but log is not kept yet in the struct */ + chi->conductor = acb_dirichlet_ui_conductor(G, chi->n); acb_dirichlet_char_normalize(chi, G); /* return last index modified */ diff --git a/acb_dirichlet/conrey_order.c b/acb_dirichlet/conrey_order.c new file mode 100644 index 00000000..e30755fc --- /dev/null +++ b/acb_dirichlet/conrey_order.c @@ -0,0 +1,38 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +{ + ulong k, g; + g = G->expo; + + for (k = 0; k < G->num; k++) + g = n_gcd(g, G->PHI[k] * x->log[k]); + + return G->expo / g; +} diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 6fdbae1f..483d08a6 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -26,25 +26,6 @@ #include "acb_dirichlet.h" -/* order of an element knowing the factorization of a multiple */ -static ulong -nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) -{ - int k; - ulong pe, ap, order = 1; - for (k = 0; k < fac.num; k++) - { - pe = n_pow(fac.p[k], fac.exp[k]); - ap = nmod_pow_ui(a, expo / pe, mod); - while ( ap != 1) - { - ap = nmod_pow_ui(ap, fac.p[k], mod); - order *= fac.p[k]; - } - } - return order; -} - int main() { slong iter, bits; @@ -61,7 +42,6 @@ int main() acb_dirichlet_group_t G; acb_dirichlet_char_t chi, chi2; ulong q, iter2; - n_factor_t fac; q = 2 + n_randint(state, 1 << bits); @@ -69,9 +49,6 @@ int main() acb_dirichlet_char_init(chi, G); acb_dirichlet_char_init(chi2, G); - n_factor_init(&fac); - n_factor(&fac, G->expo, 1); - acb_dirichlet_group_dlog_precompute(G, 50); /* check number char properties */ @@ -87,7 +64,7 @@ int main() acb_dirichlet_char(chi, G, m); - order = nmod_order_precomp(m, G->mod, G->expo, fac); + order = acb_dirichlet_ui_order(G, m); if (order != chi->order) { flint_printf("FAIL: order\n\n"); @@ -98,7 +75,7 @@ int main() abort(); } - cond = acb_dirichlet_conductor_ui(G, m); + cond = acb_dirichlet_ui_conductor(G, m); if (cond != acb_dirichlet_char_conductor(G, chi)) { flint_printf("FAIL: conductor\n\n"); @@ -109,7 +86,7 @@ int main() abort(); } - par = acb_dirichlet_parity_ui(G, m); + par = acb_dirichlet_ui_parity(G, m); chim1 = acb_dirichlet_ui_chi(G, chi, q - 1); if (acb_dirichlet_char_parity(chi) != par || par != (chim1 != 0)) { diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c index 5cf471ee..91a7c0e7 100644 --- a/acb_dirichlet/theta_length.c +++ b/acb_dirichlet/theta_length.c @@ -33,7 +33,7 @@ acb_dirichlet_theta_length_d(ulong q, double x, slong prec) { double a, la; a = PI / (double)q * x * x; - la = (a>.3) ? -log(2*a*(1-a)) : .8; + la = (a < .3) ? -log(2*a*(1-a)) : .8; la = ((double)prec * LOG2 + la) / a; return ceil(sqrt(la)+.5); } diff --git a/acb_dirichlet/conductor_ui.c b/acb_dirichlet/ui_conductor.c similarity index 96% rename from acb_dirichlet/conductor_ui.c rename to acb_dirichlet/ui_conductor.c index 8e5d1999..593046a2 100644 --- a/acb_dirichlet/conductor_ui.c +++ b/acb_dirichlet/ui_conductor.c @@ -26,7 +26,7 @@ #include "acb_dirichlet.h" ulong -acb_dirichlet_conductor_ui(const acb_dirichlet_group_t G, ulong a) +acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) { slong k; ulong ap, cond; diff --git a/acb_dirichlet/ui_order.c b/acb_dirichlet/ui_order.c new file mode 100644 index 00000000..aa3babe1 --- /dev/null +++ b/acb_dirichlet/ui_order.c @@ -0,0 +1,55 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* order of an element knowing the factorization of a multiple */ +ulong +nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) +{ + int k; + ulong pe, ap, order = 1; + for (k = 0; k < fac.num; k++) + { + pe = n_pow(fac.p[k], fac.exp[k]); + ap = nmod_pow_ui(a, expo / pe, mod); + while ( ap != 1) + { + ap = nmod_pow_ui(ap, fac.p[k], mod); + order *= fac.p[k]; + } + } + return order; +} + +ulong +acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a) +{ + n_factor_t fac; + + n_factor_init(&fac); + n_factor(&fac, G->expo, 1); + return nmod_order_precomp(a, G->mod, G->expo, fac); +} diff --git a/acb_dirichlet/parity_ui.c b/acb_dirichlet/ui_parity.c similarity index 95% rename from acb_dirichlet/parity_ui.c rename to acb_dirichlet/ui_parity.c index 73dab504..c08b5423 100644 --- a/acb_dirichlet/parity_ui.c +++ b/acb_dirichlet/ui_parity.c @@ -26,7 +26,7 @@ #include "acb_dirichlet.h" int -acb_dirichlet_parity_ui(const acb_dirichlet_group_t G, ulong a) +acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) { slong k; int par; diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index a5ddeb51..c35a2ef4 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -29,9 +29,10 @@ Working with Dirichlet characters mod *q* consists mainly in going from residue classes mod *q* to exponents on a set of generators of the group. -This implementation relies on the Conrey generators introduced -in the LMFDB. We call *number* a residue class, and *index* the -corresponding vector of exponents. +This implementation relies on the Conrey numbering scheme +introduced in the LMFDB. +We call *number* a residue class modulo *q*, and *index* the +corresponding vector of exponents of Conrey generators. Going from an *index* to the corresponding *number* is a cheap operation while the converse requires computing discrete @@ -79,6 +80,9 @@ logarithms. If *num* gets very large, the entire group may be indexed. +Conrey index +............................................................................... + .. type:: acb_dirichlet_conrey_struct .. type:: acb_dirichlet_conrey_t @@ -130,12 +134,43 @@ the group *G* is isomorphic to its dual. The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. +Character properties +............................................................................... + +As a consequence of the Conrey numbering, properties of +characters such that the order, the parity or the conductor are available +at the level of their number, whithout any discrete log computation, +or at the Conrey index level. + +.. function:: ulong acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a) + +.. function:: ulong acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) + + Compute the order of a mod q. + +.. function:: ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) + +.. function:: ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) + + Compute the conductor of a mod q, that is the smallest r dividing q such + that a corresponds to an element defined modulo r. + +.. function:: ulong acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) + +.. function:: int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) + + Compute the parity of a mod q, which is the parity of the corresponding + Dirichlet character. + +Character type +------------------------------------------------------------------------------- + .. type:: acb_dirichlet_char_struct .. type:: acb_dirichlet_char_t Represents a Dirichlet character. This structure contains various - useful invariants such as the order of the character. + useful invariants such as the order, the parity and the conductor of the character. An *acb_dirichlet_char_t* is defined as an array of *acb_dirichlet_char_struct* of length 1, permitting it to be passed by reference. @@ -156,13 +191,13 @@ the group *G* is isomorphic to its dual. Sets *chi* to the Dirichlet character of Conrey index *x*. Character properties -------------------------------------------------------------------------------- +............................................................................... .. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) .. function:: int acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) -.. function:: ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +.. function:: ulong acb_dirichlet_char_conductor(const acb_dirichlet_char_t chi) Character evaluation ------------------------------------------------------------------------------- From 49e03f8a1ffba86143393340a1af454c2ba7c1fd Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 15 Jun 2016 17:48:38 +0200 Subject: [PATCH 037/139] split theta file --- acb_dirichlet.h | 4 +- acb_dirichlet/arb_theta_naive.c | 64 +++++++++++++++++ .../{arb_theta.c => arb_theta_smallorder.c} | 72 ------------------- acb_dirichlet/chi_theta_arb.c | 62 ++++++++++++++++ 4 files changed, 129 insertions(+), 73 deletions(-) create mode 100644 acb_dirichlet/arb_theta_naive.c rename acb_dirichlet/{arb_theta.c => arb_theta_smallorder.c} (57%) create mode 100644 acb_dirichlet/chi_theta_arb.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 0113f25f..73a1d791 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -184,7 +184,9 @@ void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slon ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec); ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec); -void acb_dirichlet_chi_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t x, slong prec); +void acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); +void acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); +void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t x, slong prec); void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); diff --git a/acb_dirichlet/arb_theta_naive.c b/acb_dirichlet/arb_theta_naive.c new file mode 100644 index 00000000..4b81f80e --- /dev/null +++ b/acb_dirichlet/arb_theta_naive.c @@ -0,0 +1,64 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +void +acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) +{ + slong k; + arb_t xk2, dx, x2; + acb_t zk; + arb_init(xk2); + arb_init(dx); + arb_init(x2); + acb_init(zk); + + arb_set(dx, x); + arb_set(xk2, dx); + arb_mul(x2, dx, dx, prec); + + acb_set_arb(res, xk2); + + /* TODO: reduce prec */ + for (k = 2; k < len; k++) + { + arb_mul(dx, dx, x2, prec); + arb_mul(xk2, xk2, dx, prec); + if (a[k] != ACB_DIRICHLET_CHI_NULL) + { + acb_dirichlet_power(zk, z, a[k], prec); + if (parity) + acb_mul_si(zk, zk, k, prec); + acb_addmul_arb(res, zk, xk2, prec); + } + } + + arb_clear(xk2); + arb_clear(x2); + arb_clear(dx); + acb_clear(zk); +} diff --git a/acb_dirichlet/arb_theta.c b/acb_dirichlet/arb_theta_smallorder.c similarity index 57% rename from acb_dirichlet/arb_theta.c rename to acb_dirichlet/arb_theta_smallorder.c index f7de9673..f70ccd76 100644 --- a/acb_dirichlet/arb_theta.c +++ b/acb_dirichlet/arb_theta_smallorder.c @@ -26,18 +26,6 @@ #include "acb_dirichlet.h" #include "acb_poly.h" -/* x = Pi / q * t^2 */ -static void -acb_dirichlet_arb_theta_argt(arb_t x, ulong q, const arb_t t, slong prec) -{ - arb_const_pi(x, prec); - arb_div_ui(x, x, q, prec); - arb_mul(x, x, t, prec); - arb_mul(x, x, t, prec); - arb_neg(x, x); - arb_exp(x, x, prec); -} - /* small order, multiply by chi at the end */ void acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) @@ -87,63 +75,3 @@ acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const u arb_clear(x2); arb_clear(dx); } - -void -acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) -{ - slong k; - arb_t xk2, dx, x2; - acb_t zk; - arb_init(xk2); - arb_init(dx); - arb_init(x2); - acb_init(zk); - - arb_set(dx, x); - arb_set(xk2, dx); - arb_mul(x2, dx, dx, prec); - - acb_set_arb(res, xk2); - - /* TODO: reduce prec */ - for (k = 2; k < len; k++) - { - arb_mul(dx, dx, x2, prec); - arb_mul(xk2, xk2, dx, prec); - if (a[k] != ACB_DIRICHLET_CHI_NULL) - { - acb_dirichlet_power(zk, z, a[k], prec); - if (parity) - acb_mul_si(zk, zk, k, prec); - acb_addmul_arb(res, zk, xk2, prec); - } - } - - arb_clear(xk2); - arb_clear(x2); - arb_clear(dx); - acb_clear(zk); -} - -void -acb_dirichlet_chi_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) -{ - slong len; - ulong * a; - arb_t x; - acb_dirichlet_powers_t z; - - len = acb_dirichlet_theta_length(G->q, t, prec); - - a = flint_malloc(len * sizeof(ulong)); - acb_dirichlet_ui_chi_vec(a, G, chi, len); - acb_dirichlet_powers_init(z, chi->order, len, prec); - - arb_init(x); - acb_dirichlet_arb_theta_argt(x, G->q, t, prec); - acb_dirichlet_arb_theta_naive(res, x, chi->parity, a, z, len, prec); - - arb_clear(x); - flint_free(a); - acb_dirichlet_powers_clear(z); -} diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c new file mode 100644 index 00000000..9cfd8855 --- /dev/null +++ b/acb_dirichlet/chi_theta_arb.c @@ -0,0 +1,62 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +/* x = Pi / q * t^2 */ +static void +acb_dirichlet_arb_theta_argt(arb_t x, ulong q, const arb_t t, slong prec) +{ + arb_const_pi(x, prec); + arb_div_ui(x, x, q, prec); + arb_mul(x, x, t, prec); + arb_mul(x, x, t, prec); + arb_neg(x, x); + arb_exp(x, x, prec); +} + +void +acb_dirichlet_chi_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) +{ + slong len; + ulong * a; + arb_t x; + acb_dirichlet_powers_t z; + + len = acb_dirichlet_theta_length(G->q, t, prec); + + a = flint_malloc(len * sizeof(ulong)); + acb_dirichlet_ui_chi_vec(a, G, chi, len); + acb_dirichlet_powers_init(z, chi->order, len, prec); + + arb_init(x); + acb_dirichlet_arb_theta_argt(x, G->q, t, prec); + acb_dirichlet_arb_theta_naive(res, x, chi->parity, a, z, len, prec); + + arb_clear(x); + flint_free(a); + acb_dirichlet_powers_clear(z); +} From f209d4307c2645b54c8a918b2d61520a2e159d05 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 17 Jun 2016 18:23:48 +0200 Subject: [PATCH 038/139] add conrey index inside char --- acb_dirichlet.h | 28 ++++++-- acb_dirichlet/char.c | 6 +- acb_dirichlet/char_clear.c | 1 + acb_dirichlet/char_conrey.c | 12 ++-- acb_dirichlet/char_first_primitive.c | 8 +-- acb_dirichlet/char_init.c | 1 + .../{char_conductor.c => char_mul.c} | 7 +- acb_dirichlet/char_next.c | 21 +----- acb_dirichlet/char_next_primitive.c | 35 +--------- acb_dirichlet/char_normalize.c | 8 +++ acb_dirichlet/char_one.c | 11 ++-- acb_dirichlet/char_print.c | 4 +- acb_dirichlet/chi_theta_arb.c | 2 +- acb_dirichlet/conrey_print.c | 2 +- acb_dirichlet/gauss_sum.c | 4 +- acb_dirichlet/gauss_sum_theta.c | 6 +- acb_dirichlet/jacobi_sum.c | 64 +++++++++++++++++++ acb_dirichlet/profile/p-conrey.c | 27 +++++++- acb_dirichlet/profile/p-vec.c | 8 +-- acb_dirichlet/test/t-chars.c | 4 +- acb_dirichlet/test/t-gauss.c | 2 +- acb_dirichlet/test/t-thetanull.c | 12 ++-- acb_dirichlet/test/t-vec.c | 2 +- doc/source/acb_dirichlet.rst | 22 +++++++ 24 files changed, 198 insertions(+), 99 deletions(-) rename acb_dirichlet/{char_conductor.c => char_mul.c} (80%) create mode 100644 acb_dirichlet/jacobi_sum.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 73a1d791..5320c9c2 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -85,6 +85,15 @@ void acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_gro void acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); +ACB_DIRICHLET_INLINE void +acb_dirichlet_conrey_copy(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t y) +{ + slong k; + x->n = y->n; + for (k = 0; k < G->num; k++) + x->log[k] = y->log[k]; +} + int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); @@ -112,10 +121,9 @@ void acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ul typedef struct { ulong q; /* modulus */ - /*? acb_dirichet_conrey_struct n; */ - ulong n; /* number */ ulong order; /* order */ - ulong * expo; /* reduced exponents ( order * log[k] / gcd( ) ) */ + acb_dirichlet_conrey_t x; + ulong * expo; /* reduced exponents ( log[k] * PHI[k] / gcd( ) ) */ int parity; /* 0 for even char, 1 for odd */ ulong conductor; } @@ -129,6 +137,12 @@ acb_dirichlet_char_order(const acb_dirichlet_char_t chi) return chi->order; } +ACB_DIRICHLET_INLINE ulong +acb_dirichlet_char_conductor(const acb_dirichlet_char_t chi) +{ + return chi->conductor; +} + ACB_DIRICHLET_INLINE int acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) { @@ -141,14 +155,20 @@ void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); +void acb_dirichlet_char_set_expo(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); + +/*ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi);*/ void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); +int acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); +int acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); + ulong acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); diff --git a/acb_dirichlet/char.c b/acb_dirichlet/char.c index 9309fc79..530cfb3e 100644 --- a/acb_dirichlet/char.c +++ b/acb_dirichlet/char.c @@ -28,8 +28,6 @@ void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) { - acb_dirichlet_conrey_t x; - x->log = chi->expo; - acb_dirichlet_conrey_log(x, G, n); - acb_dirichlet_char_conrey(chi, G, x); + acb_dirichlet_conrey_log(chi->x, G, n); + acb_dirichlet_char_conrey(chi, G, chi->x); } diff --git a/acb_dirichlet/char_clear.c b/acb_dirichlet/char_clear.c index 3ac4ff80..77d394d3 100644 --- a/acb_dirichlet/char_clear.c +++ b/acb_dirichlet/char_clear.c @@ -28,5 +28,6 @@ void acb_dirichlet_char_clear(acb_dirichlet_char_t chi) { + acb_dirichlet_conrey_clear(chi->x); flint_free(chi->expo); } diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c index 73f4a85a..843cee2f 100644 --- a/acb_dirichlet/char_conrey.c +++ b/acb_dirichlet/char_conrey.c @@ -30,15 +30,17 @@ void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) { - ulong k; + /* assume chi->x already set if x == NULL */ + if (x == NULL) + x = chi->x; + else + acb_dirichlet_conrey_copy(chi->x, G, x); + chi->q = G->q; - chi->n = x->n; chi->parity = acb_dirichlet_conrey_parity(G, x); chi->conductor = acb_dirichlet_conrey_conductor(G, x); - for (k = 0; k < G->num; k++) - chi->expo[k] = (x->log[k] * G->PHI[k]) % G->expo; - + acb_dirichlet_char_set_expo(chi, G); /* optional: divide by gcd to obtain true order */ acb_dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_first_primitive.c b/acb_dirichlet/char_first_primitive.c index 0310fe95..0fa70693 100644 --- a/acb_dirichlet/char_first_primitive.c +++ b/acb_dirichlet/char_first_primitive.c @@ -28,11 +28,7 @@ void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - acb_dirichlet_conrey_t x; - chi->q = G->q; - x->log = chi->expo; - acb_dirichlet_conrey_first_primitive(x, G); - chi->n = x->n; - chi->conductor = chi->q; + acb_dirichlet_conrey_first_primitive(chi->x, G); + acb_dirichlet_char_conrey(chi, G, NULL); acb_dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_init.c b/acb_dirichlet/char_init.c index 7c39554d..ffa5e866 100644 --- a/acb_dirichlet/char_init.c +++ b/acb_dirichlet/char_init.c @@ -28,5 +28,6 @@ void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { + acb_dirichlet_conrey_init(chi->x, G); chi->expo = flint_malloc(G->num * sizeof(ulong)); } diff --git a/acb_dirichlet/char_conductor.c b/acb_dirichlet/char_mul.c similarity index 80% rename from acb_dirichlet/char_conductor.c rename to acb_dirichlet/char_mul.c index 79ff14a5..1e896707 100644 --- a/acb_dirichlet/char_conductor.c +++ b/acb_dirichlet/char_mul.c @@ -25,8 +25,9 @@ #include "acb_dirichlet.h" -ulong -acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +void +acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) { - return chi->conductor; + acb_dirichlet_conrey_mul(chi12->x, G, chi1->x, chi2->x); + acb_dirichlet_char_conrey(chi12, G, chi12->x); } diff --git a/acb_dirichlet/char_next.c b/acb_dirichlet/char_next.c index b144a590..f7a57300 100644 --- a/acb_dirichlet/char_next.c +++ b/acb_dirichlet/char_next.c @@ -28,24 +28,9 @@ int acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k; - - acb_dirichlet_char_denormalize(chi, G); - - /* update index */ - for (k=0; k < G->num ; k++) - { - chi->n = nmod_mul(chi->n, G->generators[k], G->mod); - chi->expo[k] += G->PHI[k]; - if (chi->expo[k] < G->expo) - break; - chi->expo[k] = 0; - } - - /* should do it with log, but log is not kept yet in the struct */ - chi->conductor = acb_dirichlet_ui_conductor(G, chi->n); - acb_dirichlet_char_normalize(chi, G); - + int k; + k = acb_dirichlet_conrey_next(chi->x, G); + acb_dirichlet_char_conrey(chi, G, NULL); /* return last index modified */ return k; } diff --git a/acb_dirichlet/char_next_primitive.c b/acb_dirichlet/char_next_primitive.c index b1b16819..9ad9d613 100644 --- a/acb_dirichlet/char_next_primitive.c +++ b/acb_dirichlet/char_next_primitive.c @@ -28,38 +28,9 @@ int acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k; - - acb_dirichlet_char_denormalize(chi, G); - - /* update index */ - k = 0; - if (G->neven == 2) - { - chi->n = nmod_mul(chi->n, G->generators[0], G->mod); - chi->expo[0]++; - if (chi->expo[0] < G->expo) - return 0; - chi->expo[0] = 0; - k = 1; - } - - for (; k < G->num ; k++) - { - chi->n = nmod_mul(chi->n, G->generators[k], G->mod); - chi->expo[k] += G->PHI[k]; - if (chi->expo[k] % G->primes[k] == 0) - { - chi->n = nmod_mul(chi->n, G->generators[k], G->mod); - chi->expo[k] += G->PHI[k]; - } - if (chi->expo[k] < G->expo) - break; - chi->expo[k] = G->PHI[k]; - } - - acb_dirichlet_char_normalize(chi, G); - + int k; + k = acb_dirichlet_conrey_next(chi->x, G); + acb_dirichlet_char_conrey(chi, G, NULL); /* return last index modified */ return k; } diff --git a/acb_dirichlet/char_normalize.c b/acb_dirichlet/char_normalize.c index 51fbe369..8f7af3a4 100644 --- a/acb_dirichlet/char_normalize.c +++ b/acb_dirichlet/char_normalize.c @@ -25,6 +25,14 @@ #include "acb_dirichlet.h" +void +acb_dirichlet_char_set_expo(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +{ + slong k; + for (k = 0; k < G->num; k++) + chi->expo[k] = (chi->x->log[k] * G->PHI[k]) % G->expo; +} + void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { diff --git a/acb_dirichlet/char_one.c b/acb_dirichlet/char_one.c index 232a2460..22f9d9eb 100644 --- a/acb_dirichlet/char_one.c +++ b/acb_dirichlet/char_one.c @@ -28,13 +28,10 @@ void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { - ulong k; + acb_dirichlet_conrey_one(chi->x, G); chi->q = G->q; - chi->n = 1; - - for (k = 0; k < G->num; k++) - chi->expo[k] = 0; - - chi->order = 1; chi->conductor = 1; + chi->parity = 0; + acb_dirichlet_char_set_expo(chi, G); + acb_dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_print.c b/acb_dirichlet/char_print.c index d9f2f449..30eafcd9 100644 --- a/acb_dirichlet/char_print.c +++ b/acb_dirichlet/char_print.c @@ -29,7 +29,9 @@ void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) { acb_dirichlet_conrey_t x; + flint_printf("chi_%wu(%wu,.) of order %wu, index ", G->q, chi->x->n, chi->order); + acb_dirichlet_conrey_print(G, chi->x); + flint_printf(" and exponents "); x->log = chi->expo; - flint_printf("chi_%wu(%wu,.) of order %wu and index ", G->q, chi->n, chi->order); acb_dirichlet_conrey_print(G, x); } diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index 9cfd8855..ec7f4fca 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -39,7 +39,7 @@ acb_dirichlet_arb_theta_argt(arb_t x, ulong q, const arb_t t, slong prec) } void -acb_dirichlet_chi_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) +acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) { slong len; ulong * a; diff --git a/acb_dirichlet/conrey_print.c b/acb_dirichlet/conrey_print.c index 92aeee2d..8a702c69 100644 --- a/acb_dirichlet/conrey_print.c +++ b/acb_dirichlet/conrey_print.c @@ -33,5 +33,5 @@ acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_co flint_printf("[%wu", x->log[0]); for (k = 1; k < G->num; k++) flint_printf(", %wu", x->log[k]); - flint_printf("]\n"); + flint_printf("]"); } diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 969b75e3..aa5c3ea8 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -28,7 +28,9 @@ void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { - if (chi->order <= 2) + if (chi->x->n == 1) + acb_set_si(res, -1); + else if (chi->order <= 2) { if (chi->parity) { diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index 8db71b3e..5c0cb6fc 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -33,8 +33,8 @@ acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const ac arb_init(x); - if ((G->q == 300 && (chi->n == 271 || chi->n == 131)) - || (G->q == 600 && (chi->n == 11 || chi->n == 91))) + if ((G->q == 300 && (chi->x->n == 271 || chi->x->n == 131)) + || (G->q == 600 && (chi->x->n == 11 || chi->x->n == 91))) { /* or could use l'Hopital rule */ acb_dirichlet_gauss_sum_naive(res, G, chi, prec); @@ -42,7 +42,7 @@ acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const ac } arb_one(x); - acb_dirichlet_chi_theta(res, G, chi, x, prec); + acb_dirichlet_chi_theta_arb(res, G, chi, x, prec); acb_init(eps); acb_conj(eps, res); acb_div(eps, res, eps, prec); diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c new file mode 100644 index 00000000..65fd3c60 --- /dev/null +++ b/acb_dirichlet/jacobi_sum.c @@ -0,0 +1,64 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +{ + if (chi1->x->n == 1 || chi2->x->n == 1) + { + if (chi1->x->n == 1 && chi2->x->n == 1) + acb_set_si(res, G->q - 2); + else + acb_set_si(res, - 1); + } + else if (nmod_mul(chi1->x->n, chi2->x->n, G->mod) == 1) + { + if (chi1->parity) + acb_one(res); + else + acb_set_si(res, -1); + } + else + { + acb_dirichlet_char_t chi12; + acb_t tmp; + + acb_dirichlet_char_init(chi12, G); + acb_init(tmp); + + acb_dirichlet_gauss_sum(res, G, chi1, prec); + acb_dirichlet_gauss_sum(tmp, G, chi2, prec); + acb_mul(res, res, tmp, prec); + acb_dirichlet_char_mul(chi12, G, chi1, chi2); + acb_dirichlet_gauss_sum(tmp, G, chi12, prec); + acb_div(res, res, tmp, prec); + + acb_dirichlet_char_clear(chi12); + acb_clear(tmp); + } + +} diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c index 8fc997d7..4c52a062 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/acb_dirichlet/profile/p-conrey.c @@ -46,7 +46,7 @@ int main() TIMEIT_ONCE_STOP nref = n; - flint_printf("conrey elements.... "); + flint_printf("conrey.... "); TIMEIT_ONCE_START for (n = 0, q = 2; q <= maxq; q++) { @@ -70,6 +70,31 @@ int main() abort(); } + flint_printf("chars.... "); + TIMEIT_ONCE_START + for (n = 0, q = 2; q <= maxq; q++) + { + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi, G); + + acb_dirichlet_char_one(chi, G); + n++; + + for (; acb_dirichlet_char_next(chi, G) < G->num; n++); + acb_dirichlet_char_clear(chi); + acb_dirichlet_group_clear(G); + } + TIMEIT_ONCE_STOP + if (n != nref) + { + flint_printf("FAIL: wrong number of elements %wu != %wu\n\n",n, nref); + abort(); + } + + flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; diff --git a/acb_dirichlet/profile/p-vec.c b/acb_dirichlet/profile/p-vec.c index 84215127..c088f08a 100644 --- a/acb_dirichlet/profile/p-vec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -51,7 +51,7 @@ vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ul for (r = 0; r < nr; r++) { acb_dirichlet_char(chi, G, rand[r] % q); - dir(v, nv, G, chi); + dir(v, G, chi, nv); } acb_dirichlet_char_clear(chi); @@ -97,15 +97,15 @@ int main() flint_printf("big loop................ "); fflush(stdout); - vecloop(acb_dirichlet_chi_vec_loop, minq, maxq, rand, nr, v, nv); + vecloop(acb_dirichlet_ui_chi_vec_loop, minq, maxq, rand, nr, v, nv); flint_printf("med loop................ "); fflush(stdout); - vecloop(acb_dirichlet_chi_vec_primeloop, minq, maxq, rand, nr, v, nv); + vecloop(acb_dirichlet_ui_chi_vec_primeloop, minq, maxq, rand, nr, v, nv); flint_printf("sieve................... "); fflush(stdout); - vecloop(acb_dirichlet_chi_vec_sieve, minq, maxq, rand, nr, v, nv); + vecloop(acb_dirichlet_ui_chi_vec_sieve, minq, maxq, rand, nr, v, nv); /* flint_printf("generic........ "); diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 483d08a6..9b9685f9 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -76,13 +76,13 @@ int main() } cond = acb_dirichlet_ui_conductor(G, m); - if (cond != acb_dirichlet_char_conductor(G, chi)) + if (cond != chi->conductor) { flint_printf("FAIL: conductor\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("conductor(m) = %wu\n\n", cond); - flint_printf("chi->conductor = %wu\n\n", acb_dirichlet_char_conductor(G, chi)); + flint_printf("chi->conductor = %wu\n\n", chi->conductor); abort(); } diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index 8b4687c5..5da60e90 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -67,7 +67,7 @@ int main() if (!acb_overlaps(s1, s2) || !acb_overlaps(s1, s3)) { - flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->n); + flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->x->n); flint_printf("\nnaive ", q, x->n); acb_printd(s1, 25); flint_printf("\ntheta ", q, x->n); diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 71517fce..227bfba3 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -100,22 +100,26 @@ int main() if (v[k] != ACB_DIRICHLET_CHI_NULL) acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); - if ((q == 300 && (chi->n == 271 || chi->n == 131)) - || (q == 600 && (chi->n == 11 || chi->n == 91))) + if ((q == 300 && (chi->x->n == 271 || chi->x->n == 131)) + || (q == 600 && (chi->x->n == 11 || chi->x->n == 91))) { if (!acb_contains_zero(sum)) { - flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); + flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); acb_printd(sum, 10); flint_printf("\n"); + acb_dirichlet_char_print(G, chi); + flint_printf("\n"); abort(); } } else if (acb_contains_zero(sum)) { - flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); + flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); acb_printd(sum, 10); flint_printf("\n"); + acb_dirichlet_char_print(G, chi); + flint_printf("\n"); abort(); } diff --git a/acb_dirichlet/test/t-vec.c b/acb_dirichlet/test/t-vec.c index 6d4f5a38..79cc2cdf 100644 --- a/acb_dirichlet/test/t-vec.c +++ b/acb_dirichlet/test/t-vec.c @@ -69,7 +69,7 @@ int main() if ((k = vec_diff(v1, v2, nv))) { flint_printf("FAIL: chi(%wu,%wu) = %wu != chi(%wu,%wu) = %wu mod %wu (modulus = %wu)\n", - chi->n, k, v1[k], chi->n, k, v2[k], chi->order, q); + chi->x->n, k, v1[k], chi->x->n, k, v2[k], chi->order, q); abort(); } diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index c35a2ef4..ee418d12 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -213,6 +213,13 @@ unity. There are no restrictions on *n*. +Gauss and Jacobi sums +------------------------------------------------------------------------------- + +.. function:: void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + +.. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) + Euler products ------------------------------------------------------------------------------- @@ -250,3 +257,18 @@ Simple functions Note that the alternating character `\{1,-1\}` is not itself a Dirichlet character. + +Implementation notes +------------------------------------------------------------------------------- + +The current implementation introduces a *char* type which contains a *conrey* +index plus additional information which + +- make evaluation of a single character a bit faster + +- have some initialization cost. + +Even if it is straiforward to convert a *conrey* index to the +corresponding *char*, looping is faster at the +level of conrey representation. Things can be improved on this aspect +but it makes code more intricate. From 27d1877c3b5b505200c5fbe9352fc7859c7c70a7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 17 Jun 2016 22:20:35 +0200 Subject: [PATCH 039/139] equality tests --- acb_dirichlet.h | 4 + acb_dirichlet/char.c | 2 +- acb_dirichlet/char_eq.c | 52 ++++++++++ acb_dirichlet/conrey_eq.c | 41 ++++++++ acb_dirichlet/test/t-chars.c | 186 +++++++++++++++++++++-------------- 5 files changed, 208 insertions(+), 77 deletions(-) create mode 100644 acb_dirichlet/char_eq.c create mode 100644 acb_dirichlet/conrey_eq.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 5320c9c2..2f578722 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -94,6 +94,8 @@ acb_dirichlet_conrey_copy(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t x->log[k] = y->log[k]; } +int acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y); + int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); @@ -153,6 +155,8 @@ void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +int acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); + void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); void acb_dirichlet_char_set_expo(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); diff --git a/acb_dirichlet/char.c b/acb_dirichlet/char.c index 530cfb3e..cbc72727 100644 --- a/acb_dirichlet/char.c +++ b/acb_dirichlet/char.c @@ -29,5 +29,5 @@ void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) { acb_dirichlet_conrey_log(chi->x, G, n); - acb_dirichlet_char_conrey(chi, G, chi->x); + acb_dirichlet_char_conrey(chi, G, NULL); } diff --git a/acb_dirichlet/char_eq.c b/acb_dirichlet/char_eq.c new file mode 100644 index 00000000..4e73f02b --- /dev/null +++ b/acb_dirichlet/char_eq.c @@ -0,0 +1,52 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) +{ + acb_dirichlet_conrey_t x, y; + + if (chi1->q != chi2->q) + return 0; + + if (chi1->order != chi2->order) + return 0; + + if (chi1->conductor != chi2->conductor) + return 0; + + if (!acb_dirichlet_conrey_eq(G, chi1->x, chi2->x)) + return 0; + + x->n = y->n = 1; + x->log = chi1->expo; + y->log = chi2->expo; + if (!acb_dirichlet_conrey_eq(G, x, y)) + return 0; + + return 1; +} diff --git a/acb_dirichlet/conrey_eq.c b/acb_dirichlet/conrey_eq.c new file mode 100644 index 00000000..636f9e63 --- /dev/null +++ b/acb_dirichlet/conrey_eq.c @@ -0,0 +1,41 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int +acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) +{ + slong k; + + if (x->n != y->n) + return 0; + + for (k = 0; k < G->num; k++) + if (x->log[k] != y->log[k]) + return 0; + + return 1; +} diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 9b9685f9..4d340070 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -37,92 +37,126 @@ int main() for (bits = 5; bits <= 30; bits += 5) { - for (iter = 0; iter < 50; iter++) - { - acb_dirichlet_group_t G; - acb_dirichlet_char_t chi, chi2; - ulong q, iter2; + for (iter = 0; iter < 50; iter++) + { + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_dirichlet_char_t chi, chi2; + ulong q, iter2; - q = 2 + n_randint(state, 1 << bits); + q = 2 + n_randint(state, 1 << bits); - acb_dirichlet_group_init(G, q); - acb_dirichlet_char_init(chi, G); - acb_dirichlet_char_init(chi2, G); + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_char_init(chi, G); + acb_dirichlet_char_init(chi2, G); - acb_dirichlet_group_dlog_precompute(G, 50); + acb_dirichlet_group_dlog_precompute(G, 50); - /* check number char properties */ - for (iter2 = 0; iter2 < 50; iter2++) - { - int par; - ulong m, n; - ulong order, chim1, pairing, cond; + /* check number char properties */ + for (iter2 = 0; iter2 < 100; iter2++) + { + int par; + ulong m, n; + ulong order, chim1, pairing, cond; - do - m = n_randint(state, q); - while (n_gcd(q, m) > 1); + do + m = n_randint(state, q); + while (n_gcd(q, m) > 1); - acb_dirichlet_char(chi, G, m); + acb_dirichlet_char(chi, G, m); + acb_dirichlet_conrey_log(x, G, m); + acb_dirichlet_char_conrey(chi2, G, x); + + if (!acb_dirichlet_char_eq(G, chi, chi2)) + { + flint_printf("FAIL: init char\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + acb_dirichlet_char_print(G, chi); + flint_printf("\n"); + acb_dirichlet_char_print(G, chi2); + flint_printf("\n"); + abort(); + } + + order = acb_dirichlet_ui_order(G, m); + if (order != chi->order) + { + flint_printf("FAIL: order\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("order(m) = %wu\n\n", order); + flint_printf("chi->order = %wu\n\n", chi->order); + abort(); + } + + cond = acb_dirichlet_ui_conductor(G, m); + if (cond != chi->conductor) + { + flint_printf("FAIL: conductor\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("conductor(m) = %wu\n\n", cond); + flint_printf("chi->conductor = %wu\n\n", chi->conductor); + abort(); + } + + par = acb_dirichlet_ui_parity(G, m); + chim1 = acb_dirichlet_ui_chi(G, chi, q - 1); + if (acb_dirichlet_char_parity(chi) != par || par != (chim1 != 0)) + { + flint_printf("FAIL: parity\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("chi(-1) = %wu\n\n", chim1); + flint_printf("char_parity = %d", acb_dirichlet_char_parity(chi)); + flint_printf("parity_ui = %d", par); + acb_dirichlet_char_print(G, chi); + abort(); + } + + do + n = n_randint(state, q); + while (n_gcd(q, n) > 1); + + acb_dirichlet_char(chi2, G, n); + pairing = acb_dirichlet_ui_pairing(G, m, n); + + if (pairing != acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order) + || pairing != acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order)) + { + 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); + abort(); + } + + acb_dirichlet_conrey_next(x, G); + acb_dirichlet_char_next(chi, G); + acb_dirichlet_char_conrey(chi2, G, x); + + if (!acb_dirichlet_char_eq(G, chi, chi2)) + { + flint_printf("FAIL: next char\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + acb_dirichlet_char_print(G, chi); + flint_printf("\n"); + acb_dirichlet_char_print(G, chi2); + flint_printf("\n"); + abort(); + } - order = acb_dirichlet_ui_order(G, m); - if (order != chi->order) - { - flint_printf("FAIL: order\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("order(m) = %wu\n\n", order); - flint_printf("chi->order = %wu\n\n", chi->order); - abort(); } - cond = acb_dirichlet_ui_conductor(G, m); - if (cond != chi->conductor) - { - flint_printf("FAIL: conductor\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("conductor(m) = %wu\n\n", cond); - flint_printf("chi->conductor = %wu\n\n", chi->conductor); - abort(); - } - - par = acb_dirichlet_ui_parity(G, m); - chim1 = acb_dirichlet_ui_chi(G, chi, q - 1); - if (acb_dirichlet_char_parity(chi) != par || par != (chim1 != 0)) - { - flint_printf("FAIL: parity\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("chi(-1) = %wu\n\n", chim1); - flint_printf("char_parity = %d", acb_dirichlet_char_parity(chi)); - flint_printf("parity_ui = %d", par); - acb_dirichlet_char_print(G, chi); - abort(); - } - - do - n = n_randint(state, q); - while (n_gcd(q, n) > 1); - - acb_dirichlet_char(chi2, G, n); - pairing = acb_dirichlet_ui_pairing(G, m, n); - - if (pairing != acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order) - || pairing != acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order)) - { - 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); - abort(); - } + acb_dirichlet_char_clear(chi); + acb_dirichlet_char_clear(chi2); + acb_dirichlet_conrey_clear(x); + acb_dirichlet_group_clear(G); } - - acb_dirichlet_char_clear(chi); - acb_dirichlet_char_clear(chi2); - acb_dirichlet_group_clear(G); - } } flint_randclear(state); From 041f644fdaf1835684a1504e0e7bb522cdfd5a49 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 17 Jun 2016 22:36:17 +0200 Subject: [PATCH 040/139] fix stupid bug --- acb_dirichlet/char_next_primitive.c | 2 +- acb_dirichlet/test/t-thetanull.c | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/acb_dirichlet/char_next_primitive.c b/acb_dirichlet/char_next_primitive.c index 9ad9d613..07e205a9 100644 --- a/acb_dirichlet/char_next_primitive.c +++ b/acb_dirichlet/char_next_primitive.c @@ -29,7 +29,7 @@ int acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { int k; - k = acb_dirichlet_conrey_next(chi->x, G); + k = acb_dirichlet_conrey_next_primitive(chi->x, G); acb_dirichlet_char_conrey(chi, G, NULL); /* return last index modified */ return k; diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 227bfba3..3c8c17fd 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -42,7 +42,6 @@ int main() for (q = 3; q < 1000; q ++) { acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; acb_dirichlet_char_t chi; ulong * v, nv, k; @@ -57,7 +56,6 @@ int main() continue; acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); acb_dirichlet_char_init(chi, G); acb_init(zeta); @@ -84,13 +82,12 @@ int main() /* theta function on primitive characters */ acb_init(sum); - acb_dirichlet_conrey_first_primitive(x, G); + acb_dirichlet_char_first_primitive(chi, G); while (1) { ulong m; acb_zero(sum); - acb_dirichlet_char_conrey(chi, G, x); acb_dirichlet_ui_chi_vec(v, G, chi, nv); m = G->expo / chi->order; @@ -123,7 +120,7 @@ int main() abort(); } - if (acb_dirichlet_conrey_next_primitive(x, G) == G->num) + if (acb_dirichlet_char_next_primitive(chi, G) == G->num) break; } _acb_vec_clear(z, G->expo); @@ -134,7 +131,6 @@ int main() flint_free(v); acb_dirichlet_group_clear(G); acb_dirichlet_char_clear(chi); - acb_dirichlet_conrey_clear(x); } flint_cleanup(); From 4953a8b434a6f16d91ab532e6a0161cfaedf9c60 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 24 Jun 2016 16:03:22 +0200 Subject: [PATCH 041/139] jacobi sums, exceptional cases, still a pb --- acb_dirichlet.h | 7 ++ acb_dirichlet/arb_quadratic_powers.c | 1 + acb_dirichlet/char_primitive.c | 38 +++++++++ acb_dirichlet/conrey_primitive.c | 61 ++++++++++++++ acb_dirichlet/gauss_sum.c | 65 ++++++++++++++- acb_dirichlet/jacobi_sum.c | 117 +++++++++++++++++++++++---- acb_dirichlet/jacobi_sum_naive.c | 76 +++++++++++++++++ acb_dirichlet/si_poly_evaluate.c | 74 +++++++++++++++++ acb_dirichlet/test/t-gauss.c | 15 ++-- acb_dirichlet/test/t-jacobi.c | 98 ++++++++++++++++++++++ 10 files changed, 530 insertions(+), 22 deletions(-) create mode 100644 acb_dirichlet/char_primitive.c create mode 100644 acb_dirichlet/conrey_primitive.c create mode 100644 acb_dirichlet/jacobi_sum_naive.c create mode 100644 acb_dirichlet/si_poly_evaluate.c create mode 100644 acb_dirichlet/test/t-jacobi.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 2f578722..70eda1f1 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -108,6 +108,7 @@ int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_diri void acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); void acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n); +void acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, ulong cond); #define ACB_DIRICHLET_CHI_NULL UWORD_MAX @@ -164,6 +165,7 @@ void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_ void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); +void acb_dirichlet_char_primitive(acb_dirichlet_char_t chi0, const acb_dirichlet_group_t G0, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); /*ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi);*/ @@ -216,6 +218,11 @@ void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, con void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); + +void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); + #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/arb_quadratic_powers.c b/acb_dirichlet/arb_quadratic_powers.c index 9e2f1bee..ffc49e7d 100644 --- a/acb_dirichlet/arb_quadratic_powers.c +++ b/acb_dirichlet/arb_quadratic_powers.c @@ -25,6 +25,7 @@ #include "acb_dirichlet.h" +/* TODO: BSGS can reduce to nv mul */ void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec) { diff --git a/acb_dirichlet/char_primitive.c b/acb_dirichlet/char_primitive.c new file mode 100644 index 00000000..c042eb03 --- /dev/null +++ b/acb_dirichlet/char_primitive.c @@ -0,0 +1,38 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_char_primitive(acb_dirichlet_char_t chi0, const acb_dirichlet_group_t G0, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +{ + chi0->q = chi->conductor; + chi0->parity = chi->parity; + chi0->conductor = chi->conductor; + acb_dirichlet_conrey_primitive(chi0->x, G, chi->x, chi->conductor); + acb_dirichlet_char_set_expo(chi0, G0); + /* optional: divide by gcd to obtain true order */ + acb_dirichlet_char_normalize(chi0, G0); +} diff --git a/acb_dirichlet/conrey_primitive.c b/acb_dirichlet/conrey_primitive.c new file mode 100644 index 00000000..611c1272 --- /dev/null +++ b/acb_dirichlet/conrey_primitive.c @@ -0,0 +1,61 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, ulong cond) +{ + int k, l, f; + + l = 0; + if (cond % 4 == 0) + { + y->log[l++] = x->log[0]; + + if (cond % 8 == 0) + { + ulong l2 = x->log[1]; + f = n_remove(&l2, 2); + y->log[l++] = l2; + } + } + + for (k = G->neven; k < G->num; k++) + { + if (x->log[k]) + { + ulong p, lp; + p = G->primes[k]; + if (cond % p == 0) + { + lp = x->log[k]; + f = n_remove(&lp, p); + y->log[l++] = lp; + } + } + } + +} diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index aa5c3ea8..85105a86 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -25,11 +25,72 @@ #include "acb_dirichlet.h" +static void +gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + + slong k, mu = 1; + ulong NN0 = G->q / chi->conductor; + + /* G(chi) = mu(N/N0)chi0(N/N0)G(chi0) */ + + if (NN0 % 4 == 0) + { + acb_zero(res); + return; + } + + for (k = 0; k < G->num; k++) + { + ulong p = G->primes[k]; + + if (G->exponents[k] > 1 && NN0 % (p*p) == 0) + { + acb_zero(res); + return; + } + + if (NN0 % p == 0) + mu *= -1; + } + + if (chi->x->n == 1) + { + acb_set_si(res, mu); + } + else + { + + acb_dirichlet_group_t G0; + acb_dirichlet_char_t chi0; + acb_t z; + + /* TODO: implement efficient subgroup */ + acb_dirichlet_group_init(G0, chi->conductor); + acb_dirichlet_char_init(chi0, G); + acb_dirichlet_char_primitive(chi0, G0, G, chi); + + acb_init(z); + acb_dirichlet_gauss_sum(z, G0, chi0, prec); + + acb_dirichlet_chi(res, G0, chi0, NN0, prec); + + acb_mul(res, res, z, prec); + acb_mul_si(res, res, mu, prec); + + acb_dirichlet_group_clear(G0); + acb_dirichlet_char_clear(chi0); + acb_clear(z); + } +} + void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { - if (chi->x->n == 1) - acb_set_si(res, -1); + if (chi->conductor != G->q) + { + gauss_sum_non_primitive(res, G, chi, prec); + } else if (chi->order <= 2) { if (chi->parity) diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index 65fd3c60..34cda1c7 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -25,40 +25,129 @@ #include "acb_dirichlet.h" +/* J_N(1,a) = sum on x = 1 mod some p | q */ +static ulong +charsum_1modsomep(const acb_dirichlet_group_t G, ulong cond) +{ + slong k, f = 1, mu = 1, pow = 1; + + for (k = 0; k < G->num; k++) + { + ulong p = G->primes[k]; + if (G->exponents[k] > 1) + { + if (cond % (p*p)) + pow *= G->primepowers[k] / p; + else + return 0; + } + if (cond % p == 0) /* p | conductor */ + mu *= -1; + else + f *= p - 2; + } + + return mu * pow * f; +} + void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) { + + if (G->q_even > 1) + { + acb_zero(res); + return; + } + if (chi1->x->n == 1 || chi2->x->n == 1) { if (chi1->x->n == 1 && chi2->x->n == 1) - acb_set_si(res, G->q - 2); + { + /* q = prod p^e -> prod (p-2)p^(e-1) invertible x & 1-x */ + slong k, n = 1; + //flint_printf("## a=b=1[q]\n"); + for (k = 0; k < G->num; k++) + { + n *= G->primes[k] - 2; + if (G->exponents[k] > 1) + n *= G->primepowers[k] / G->primes[k]; + } + acb_set_si(res, n); + } else - acb_set_si(res, - 1); + { + ulong cond = (chi1->x->n == 1) ? chi2->conductor : chi1->conductor; + acb_set_si(res, charsum_1modsomep(G, cond)); + } } else if (nmod_mul(chi1->x->n, chi2->x->n, G->mod) == 1) { + ulong n; + //flint_printf("## ab=1[q]\n"); + n = charsum_1modsomep(G, chi1->conductor); if (chi1->parity) - acb_one(res); + acb_set_si(res, -n); else - acb_set_si(res, -1); + acb_set_si(res, n); } else { + /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ acb_dirichlet_char_t chi12; - acb_t tmp; + + //flint_printf("## via gauss\n"); acb_dirichlet_char_init(chi12, G); - acb_init(tmp); - - acb_dirichlet_gauss_sum(res, G, chi1, prec); - acb_dirichlet_gauss_sum(tmp, G, chi2, prec); - acb_mul(res, res, tmp, prec); acb_dirichlet_char_mul(chi12, G, chi1, chi2); - acb_dirichlet_gauss_sum(tmp, G, chi12, prec); - acb_div(res, res, tmp, prec); - acb_dirichlet_char_clear(chi12); - acb_clear(tmp); + if (chi12->conductor != G->q) + { + //flint_printf("## jacobi: non primitive product, %wu * %wu -> %wu\n", + //chi1->conductor, chi2->conductor, chi12->conductor); + //acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); + } + + if (1) + { + acb_t tmp; + acb_init(tmp); + + /* FIXME: remove naive */ + acb_dirichlet_gauss_sum_naive(res, G, chi1, prec); + acb_dirichlet_gauss_sum_naive(tmp, G, chi2, prec); + acb_mul(res, res, tmp, prec); + acb_dirichlet_gauss_sum_naive(tmp, G, chi12, prec); + acb_div(res, res, tmp, prec); + if (chi12->conductor < G->q) + { + /* à la louche... */ + if (chi1->conductor == chi2->conductor + && chi2->conductor == chi12->conductor) + { + slong k; + slong m = 1; + for (k = 0; k < G->num; k++) + { + ulong p = G->primes[k]; + if (chi1->conductor % p) + m = - m * (p - 2); + } + /* + flint_printf("cond = %wu, %wu, %wu -> mult by %wd\n", + chi1->conductor, chi2->conductor, chi12->conductor, + m); + */ + acb_mul_si(res, res, m, prec); + } + else + acb_div_si(res, res, G->q / chi12->conductor, prec); + } + + + acb_dirichlet_char_clear(chi12); + acb_clear(tmp); + } } } diff --git a/acb_dirichlet/jacobi_sum_naive.c b/acb_dirichlet/jacobi_sum_naive.c new file mode 100644 index 00000000..72d838fd --- /dev/null +++ b/acb_dirichlet/jacobi_sum_naive.c @@ -0,0 +1,76 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +{ + + ulong k1, k2, m1, m2, g, e; + ulong * v1, * v2; + slong *v; + nmod_t order; + acb_t z; + + v1 = flint_malloc(G->q * sizeof(ulong)); + v2 = flint_malloc(G->q * sizeof(ulong)); + + acb_dirichlet_ui_vec_set_null(v1, G, G->q); + acb_dirichlet_ui_chi_vec_loop(v1, G, chi1, G->q); + + acb_dirichlet_ui_vec_set_null(v2, G, G->q); + acb_dirichlet_ui_chi_vec_loop(v2, G, chi2, G->q); + + m1 = chi1->order; + m2 = chi2->order; + g = n_gcd(m1, m2); + nmod_init(&order, m1 * (m2 / g)); + m1 = order.n / m1; + m2 = order.n / m2; + + v = flint_malloc(order.n * sizeof(slong)); + + for (e = 0; e < order.n; e++) + v[e] = 0; + + for (k1 = 2, k2 = G->q - 1; k2 > 1; k1++, k2--) + { + if (v1[k1] == ACB_DIRICHLET_CHI_NULL || + v2[k2] == ACB_DIRICHLET_CHI_NULL) + continue; + e = nmod_add(v1[k1] * m1, v2[k2] * m2, order); + v[e]++; + } + + acb_init(z); + acb_dirichlet_nth_root(z, order.n, prec); + acb_dirichlet_si_poly_evaluate(res, v, order.n, z, prec); + + acb_clear(z); + flint_free(v); + flint_free(v2); + flint_free(v1); +} diff --git a/acb_dirichlet/si_poly_evaluate.c b/acb_dirichlet/si_poly_evaluate.c new file mode 100644 index 00000000..42cdd96b --- /dev/null +++ b/acb_dirichlet/si_poly_evaluate.c @@ -0,0 +1,74 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec) +{ + slong k, r, m; + acb_t sq; + acb_ptr zk; + + if (len < 3) + { + if (len == 0) + { + acb_zero(res); + } + else if (len == 1) + { + acb_set_si(res, v[0]); + } + else if (len == 2) + { + acb_mul_si(res, z, v[1], prec); + acb_add_si(res, res, v[0], prec); + } + return; + } + + m = n_sqrt(len) + 1; + + zk = _acb_vec_init(m + 1); + _acb_vec_set_powers(zk, z, m + 1, prec); + + acb_init(sq); + acb_zero(res); + + k = len - 1; + r = k % m; + for (; k >= 0; r = m - 1) + { + acb_zero(sq); + for (; r >= 0; r--, k--) + acb_addmul_si(sq, zk + r, v[k], prec); + acb_mul(res, res, zk + m, prec); + acb_add(res, res, sq, prec); + } + + _acb_vec_clear(zk, m + 1); + acb_clear(sq); +} diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index 5da60e90..6fc668b6 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -54,15 +54,18 @@ int main() acb_init(s1); acb_init(s2); acb_init(s3); - acb_dirichlet_conrey_first_primitive(x, G); + acb_dirichlet_conrey_one(x, G); while (1) { acb_dirichlet_char_conrey(chi, G, x); acb_dirichlet_gauss_sum_naive(s1, G, chi, prec); - acb_dirichlet_gauss_sum_theta(s2, G, chi, prec); - acb_dirichlet_gauss_sum(s3, G, chi, prec); + acb_dirichlet_gauss_sum(s2, G, chi, prec); + if (chi->conductor == G->q) + acb_dirichlet_gauss_sum_theta(s3, G, chi, prec); + else + acb_set(s3, s1); if (!acb_overlaps(s1, s2) || !acb_overlaps(s1, s3)) @@ -70,14 +73,14 @@ int main() flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->x->n); flint_printf("\nnaive ", q, x->n); acb_printd(s1, 25); - flint_printf("\ntheta ", q, x->n); - acb_printd(s2, 25); flint_printf("\ndefault ", q, x->n); + acb_printd(s2, 25); + flint_printf("\ntheta ", q, x->n); acb_printd(s3, 25); abort(); } - if (acb_dirichlet_conrey_next_primitive(x, G) == G->num) + if (acb_dirichlet_conrey_next(x, G) == G->num) break; } acb_clear(s1); diff --git a/acb_dirichlet/test/t-jacobi.c b/acb_dirichlet/test/t-jacobi.c new file mode 100644 index 00000000..3860c8ad --- /dev/null +++ b/acb_dirichlet/test/t-jacobi.c @@ -0,0 +1,98 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int main() +{ + slong prec = 128; + ulong q; + + flint_printf("jacobi...."); + fflush(stdout); + + /* check Jacobi sums */ + + for (q = 3; q < 250; q ++) + { + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi1, chi2; + + acb_t s1, s2; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi1, G); + acb_dirichlet_char_init(chi2, G); + + acb_init(s1); + acb_init(s2); + + acb_dirichlet_char_one(chi1, G); + + while (1) { + + acb_dirichlet_char_one(chi2, G); + + while (1) { + + acb_dirichlet_jacobi_sum_naive(s1, G, chi1, chi2, prec); + acb_dirichlet_jacobi_sum(s2, G, chi1, chi2, prec); + + if (!acb_overlaps(s1, s2)) + { + flint_printf("FAIL: J_%wu(%wu,%wu)", + q, chi1->x->n, chi2->x->n); + flint_printf("\nnaive "); + acb_printd(s1, 25); + flint_printf("\ntheta "); + acb_printd(s2, 25); + flint_printf("\n"); + flint_printf("cond = %wu, %wu, %wu\n", + chi1->conductor, chi2->conductor, + acb_dirichlet_ui_conductor(G, nmod_mul(chi1->x->n, chi2->x->n, G->mod)) + ); + abort(); + } + if (acb_dirichlet_char_next(chi2, G) == G->num) + break; + + } + + if (acb_dirichlet_char_next(chi1, G) == G->num) + break; + + } + + acb_clear(s1); + acb_clear(s2); + acb_dirichlet_group_clear(G); + acb_dirichlet_char_clear(chi1); + acb_dirichlet_char_clear(chi2); + } + + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} From 68faafa62a1658c1eba3311c9206c0408044d50f Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 5 Jul 2016 13:16:29 +0200 Subject: [PATCH 042/139] jacobi sums, use product --- acb_dirichlet/char_mul.c | 2 +- acb_dirichlet/gauss_sum.c | 3 + acb_dirichlet/group_init.c | 7 ++ acb_dirichlet/jacobi_sum.c | 221 +++++++++++++++++++--------------- acb_dirichlet/test/t-gauss.c | 2 +- acb_dirichlet/test/t-jacobi.c | 11 +- 6 files changed, 144 insertions(+), 102 deletions(-) diff --git a/acb_dirichlet/char_mul.c b/acb_dirichlet/char_mul.c index 1e896707..83eaf7f4 100644 --- a/acb_dirichlet/char_mul.c +++ b/acb_dirichlet/char_mul.c @@ -29,5 +29,5 @@ void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) { acb_dirichlet_conrey_mul(chi12->x, G, chi1->x, chi2->x); - acb_dirichlet_char_conrey(chi12, G, chi12->x); + acb_dirichlet_char_conrey(chi12, G, NULL); } diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 85105a86..46cd73d0 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -25,6 +25,8 @@ #include "acb_dirichlet.h" +/* TODO: factor on modulus */ + static void gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { @@ -40,6 +42,7 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri return; } + /* FIXME: check if one can start at G->neven */ for (k = 0; k < G->num; k++) { ulong p = G->primes[k]; diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index ef144b60..4b288033 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -56,6 +56,13 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) n_factor_init(&fac); n_factor(&fac, G->q_odd, 1); + /* + TODO: Dirichlet group may be an array of + prime components structs instead, since + many algorithms are done prime by prime + and this would make subgroups easier. + */ + /* number of components at p=2 */ G->neven = (e2 >= 3) ? 2 : (e2 == 2) ? 1 : 0; G->num = G->neven + fac.num; diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index 34cda1c7..ef40861f 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -27,27 +27,123 @@ /* J_N(1,a) = sum on x = 1 mod some p | q */ static ulong -charsum_1modsomep(const acb_dirichlet_group_t G, ulong cond) +jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond) { - slong k, f = 1, mu = 1, pow = 1; + if (e > 1 && cond % (p*p) == 0) + { + return 0; + } + else + { + slong r = (e > 1) ? pe / p : 1; + if (cond % p) + return r * (p - 2); + else + return -r; + } +} + +static ulong +jacobi_one(const acb_dirichlet_group_t G, ulong cond) +{ + slong k, r = 1; for (k = 0; k < G->num; k++) - { - ulong p = G->primes[k]; - if (G->exponents[k] > 1) - { - if (cond % (p*p)) - pow *= G->primepowers[k] / p; - else - return 0; - } - if (cond % p == 0) /* p | conductor */ - mu *= -1; - else - f *= p - 2; - } + r *= jacobi_one_prime(G->primes[k], G->exponents[k], + G->primepowers[k], cond); + return r; +} - return mu * pow * f; +/* should use only for prime power modulus */ +static void +acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +{ + /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ + acb_t tmp; + acb_dirichlet_char_t chi12; + + acb_dirichlet_char_init(chi12, G); + acb_dirichlet_char_mul(chi12, G, chi1, chi2); + + acb_init(tmp); + + acb_dirichlet_gauss_sum(res, G, chi1, prec); + if (chi2->x->n == chi1->x->n) + acb_set(tmp, res); + else + acb_dirichlet_gauss_sum(tmp, G, chi2, prec); + acb_mul(res, res, tmp, prec); + acb_dirichlet_gauss_sum(tmp, G, chi12, prec); + acb_div(res, res, tmp, prec); + + acb_dirichlet_char_clear(chi12); + acb_clear(tmp); +} + +static void +acb_dirichlet_jacobi_sum_primes(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +{ + slong k; + acb_t tmp; + acb_init(tmp); + acb_one(res); + + /* TODO: efficient subgroup */ + for (k = 0; k < G->num; k++) + { + ulong p, e, pe, ap, bp; + + p = G->primes[k]; + e = G->exponents[k]; + pe = G->primepowers[k]; + ap = chi1->x->n % pe; + bp = chi2->x->n % pe; + + if (ap == 1 || bp == 1 || n_mulmod2(ap, bp, pe) == 1) + { + slong r; + ulong cond; + + cond = (ap == 1) ? chi2->conductor : chi1->conductor; + r = jacobi_one_prime(p, e, pe, cond); + + /* chi(a,-1) if ap * bp = 1 */ + if (ap != 1 && bp != 1) + r *= n_jacobi_unsigned(ap, p); + + acb_mul_si(res, res, r, prec); + } + else + { + acb_dirichlet_group_t Gp; + acb_dirichlet_char_t chi1p, chi2p; + + acb_dirichlet_group_init(Gp, pe); + acb_dirichlet_char_init(chi1p, Gp); + acb_dirichlet_char_init(chi2p, Gp); + + chi1p->x->n = ap; + chi1p->x->log[0] = chi1->x->log[k]; + chi2p->x->n = ap; + chi2p->x->log[0] = chi2->x->log[k]; + + acb_dirichlet_char_conrey(chi1p, Gp, NULL); + acb_dirichlet_char_conrey(chi2p, Gp, NULL); + + /* TODO: work out gauss relations for e > 1 */ + if (p <= 100 || e > 1) + acb_dirichlet_jacobi_sum_naive(tmp, Gp, chi1p, chi2p, prec); + else + acb_dirichlet_jacobi_sum_gauss(tmp, Gp, chi1p, chi2p, prec); + + acb_mul(res, res, tmp, prec); + + acb_dirichlet_char_clear(chi1p); + acb_dirichlet_char_clear(chi2p); + acb_dirichlet_group_clear(Gp); + } + } + acb_clear(tmp); } void @@ -57,35 +153,16 @@ acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dir if (G->q_even > 1) { acb_zero(res); - return; } - - if (chi1->x->n == 1 || chi2->x->n == 1) + else if (chi1->x->n == 1 || chi2->x->n == 1) { - if (chi1->x->n == 1 && chi2->x->n == 1) - { - /* q = prod p^e -> prod (p-2)p^(e-1) invertible x & 1-x */ - slong k, n = 1; - //flint_printf("## a=b=1[q]\n"); - for (k = 0; k < G->num; k++) - { - n *= G->primes[k] - 2; - if (G->exponents[k] > 1) - n *= G->primepowers[k] / G->primes[k]; - } - acb_set_si(res, n); - } - else - { - ulong cond = (chi1->x->n == 1) ? chi2->conductor : chi1->conductor; - acb_set_si(res, charsum_1modsomep(G, cond)); - } + ulong cond = (chi1->x->n == 1) ? chi2->conductor : chi1->conductor; + acb_set_si(res, jacobi_one(G, cond)); } else if (nmod_mul(chi1->x->n, chi2->x->n, G->mod) == 1) { ulong n; - //flint_printf("## ab=1[q]\n"); - n = charsum_1modsomep(G, chi1->conductor); + n = jacobi_one(G, chi1->conductor); if (chi1->parity) acb_set_si(res, -n); else @@ -93,61 +170,13 @@ acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dir } else { - /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ - acb_dirichlet_char_t chi12; - - //flint_printf("## via gauss\n"); - - acb_dirichlet_char_init(chi12, G); - acb_dirichlet_char_mul(chi12, G, chi1, chi2); - - if (chi12->conductor != G->q) - { - //flint_printf("## jacobi: non primitive product, %wu * %wu -> %wu\n", - //chi1->conductor, chi2->conductor, chi12->conductor); - //acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); - } - - if (1) - { - acb_t tmp; - acb_init(tmp); - - /* FIXME: remove naive */ - acb_dirichlet_gauss_sum_naive(res, G, chi1, prec); - acb_dirichlet_gauss_sum_naive(tmp, G, chi2, prec); - acb_mul(res, res, tmp, prec); - acb_dirichlet_gauss_sum_naive(tmp, G, chi12, prec); - acb_div(res, res, tmp, prec); - if (chi12->conductor < G->q) - { - /* à la louche... */ - if (chi1->conductor == chi2->conductor - && chi2->conductor == chi12->conductor) - { - slong k; - slong m = 1; - for (k = 0; k < G->num; k++) - { - ulong p = G->primes[k]; - if (chi1->conductor % p) - m = - m * (p - 2); - } - /* - flint_printf("cond = %wu, %wu, %wu -> mult by %wd\n", - chi1->conductor, chi2->conductor, chi12->conductor, - m); - */ - acb_mul_si(res, res, m, prec); - } - else - acb_div_si(res, res, G->q / chi12->conductor, prec); - } - - - acb_dirichlet_char_clear(chi12); - acb_clear(tmp); - } + if (G->q <= 150) + acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); + else if (G->num > 1) + acb_dirichlet_jacobi_sum_primes(res, G, chi1, chi2, prec); + else if (G->exponents[0] > 1) + acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); + else + acb_dirichlet_jacobi_sum_gauss(res, G, chi1, chi2, prec); } - } diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index 6fc668b6..9313a442 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -35,7 +35,7 @@ int main() /* check Gauss sums */ - for (q = 3; q < 200; q ++) + for (q = 3; q < 250; q ++) { acb_dirichlet_group_t G; acb_dirichlet_conrey_t x; diff --git a/acb_dirichlet/test/t-jacobi.c b/acb_dirichlet/test/t-jacobi.c index 3860c8ad..e1f18152 100644 --- a/acb_dirichlet/test/t-jacobi.c +++ b/acb_dirichlet/test/t-jacobi.c @@ -35,8 +35,9 @@ int main() /* check Jacobi sums */ - for (q = 3; q < 250; q ++) + for (q = 29*29; q > 1; q = q%2 ? 3*q+1 : q/2) { + slong m1, m2; acb_dirichlet_group_t G; acb_dirichlet_char_t chi1, chi2; @@ -51,11 +52,13 @@ int main() acb_dirichlet_char_one(chi1, G); - while (1) { + for (m1 = 0; m1 < 50; m1++) + { acb_dirichlet_char_one(chi2, G); - while (1) { + for (m2 = 0; m2 < 50; m2++) + { acb_dirichlet_jacobi_sum_naive(s1, G, chi1, chi2, prec); acb_dirichlet_jacobi_sum(s2, G, chi1, chi2, prec); @@ -66,7 +69,7 @@ int main() q, chi1->x->n, chi2->x->n); flint_printf("\nnaive "); acb_printd(s1, 25); - flint_printf("\ntheta "); + flint_printf("\ndefault "); acb_printd(s2, 25); flint_printf("\n"); flint_printf("cond = %wu, %wu, %wu\n", From c1fd16fae4b019a22ad86964512db678fe7813d3 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 6 Jul 2016 18:39:29 +0200 Subject: [PATCH 043/139] refactor to use product of prime groups --- acb_dirichlet.h | 29 +++-- acb_dirichlet/char_print.c | 2 +- acb_dirichlet/conrey_conductor.c | 8 +- acb_dirichlet/conrey_log.c | 23 ++-- acb_dirichlet/conrey_mul.c | 2 +- acb_dirichlet/conrey_next.c | 2 +- acb_dirichlet/conrey_next_primitive.c | 4 +- acb_dirichlet/conrey_pow.c | 2 +- acb_dirichlet/conrey_primitive.c | 2 +- acb_dirichlet/gauss_sum.c | 4 +- acb_dirichlet/group_clear.c | 5 +- acb_dirichlet/group_dlog_precompute.c | 18 +-- acb_dirichlet/group_init.c | 172 +++++++++++++++++--------- acb_dirichlet/jacobi_sum.c | 25 ++-- acb_dirichlet/number_primitive.c | 6 +- acb_dirichlet/test/t-conrey.c | 2 +- acb_dirichlet/ui_chi_vec_primeloop.c | 10 +- acb_dirichlet/ui_conductor.c | 10 +- acb_dirichlet/ui_parity.c | 9 +- acb_dirichlet/ui_vec_set_null.c | 2 +- 20 files changed, 196 insertions(+), 141 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 70eda1f1..eca992bd 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -32,23 +32,30 @@ void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); +typedef struct +{ + ulong p; /* underlying prime */ + int e; /* exponent */ + nmod_t pe; /* modulus */ + ulong phi; /* phi(p^e) */ + ulong g; /* conrey generator */ + dlog_precomp_struct * dlog; /* precomputed data for discrete log mod p^e */ +} +acb_dirichlet_prime_group_struct; + typedef struct { ulong q; /* modulus */ - nmod_t mod; /* modulus with precomputed inverse */ ulong q_even; /* even part of modulus */ - ulong q_odd; /* odd part of modulus */ + nmod_t mod; /* modulus with precomputed inverse */ + ulong rad_q; /* radical = product of odd primes */ ulong phi_q; /* phi(q) = group size */ - ulong expo; /* group exponent = lcm(phi(q_even), phi(p[k]^e[k]) ) */ slong neven; /* number of even components (in 0,1,2)*/ slong num; /* number of prime components (even + odd) */ - ulong * primes; /* primes p[k] */ - ulong * exponents; /* exponents e[k] */ - ulong * primepowers; /* powers p[k]^[k] */ - ulong * generators; /* generator for each prime p[k] lifted mod q */ - ulong * phi; /* phi(k) = phi(p[k]^e[k]) */ + ulong expo; /* exponent = largest order in G */ + acb_dirichlet_prime_group_struct * P; + ulong * generators; /* generators lifted mod q */ ulong * PHI; /* PHI(k) = expo / phi(k) */ - dlog_precomp_t * dlog; /* precomputed data for discrete log mod p^e */ } acb_dirichlet_group_struct; @@ -74,8 +81,8 @@ ulong acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a); /* elements of the group, keep both number and log */ typedef struct { - ulong n; /* number */ - ulong * log; /* s.t. prod generators[k]^log[k] = number */ + ulong n; /* number */ + ulong * log; /* s.t. prod generators[k]^log[k] = number */ } acb_dirichlet_conrey_struct; diff --git a/acb_dirichlet/char_print.c b/acb_dirichlet/char_print.c index 30eafcd9..ba191376 100644 --- a/acb_dirichlet/char_print.c +++ b/acb_dirichlet/char_print.c @@ -29,7 +29,7 @@ void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) { acb_dirichlet_conrey_t x; - flint_printf("chi_%wu(%wu,.) of order %wu, index ", G->q, chi->x->n, chi->order); + flint_printf("chi_%wu(%wu,.) of order %wu, parity %wd, index ", G->q, chi->x->n, chi->order, chi->parity); acb_dirichlet_conrey_print(G, chi->x); flint_printf(" and exponents "); x->log = chi->expo; diff --git a/acb_dirichlet/conrey_conductor.c b/acb_dirichlet/conrey_conductor.c index 45f36108..7a56d1d6 100644 --- a/acb_dirichlet/conrey_conductor.c +++ b/acb_dirichlet/conrey_conductor.c @@ -37,7 +37,7 @@ acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichle { ulong l2 = x->log[1]; f = n_remove(&l2, 2); - cond = G->primepowers[1] >> f; + cond = 1 << (G->P[1].e - f); } for (k = G->neven; k < G->num; k++) @@ -45,13 +45,13 @@ acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichle if (x->log[k]) { ulong p, lp; - p = G->primes[k]; + p = G->P[k].p; lp = x->log[k]; f = n_remove(&lp, p); if (f) - cond *= n_pow(p, G->exponents[k] - f); + cond *= n_pow(p, G->P[k].e - f); else - cond *= G->primepowers[k]; + cond *= G->P[k].pe.n; } } diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index a7fd1401..b33a2ee7 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -27,7 +27,7 @@ #include "acb_dirichlet.h" -/* TODO: use precomputations in G if present */ +/* TODO: use dlog module instead of n_discrete_log_bsgs */ /* assume m is invertible */ void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) @@ -40,26 +40,25 @@ acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G if (G->neven == 2) { ulong m2 = (x->log[0]) ? -m % G->q_even : m % G->q_even; - if (G->dlog == NULL) + if (G->P[1].dlog == NULL) x->log[1] = n_discrete_log_bsgs(m2, 5, G->q_even); else - x->log[1] = dlog_precomp(G->dlog[1], m2); + x->log[1] = dlog_precomp(G->P[1].dlog, m2); } } /* odd part */ - if (G->dlog == NULL) + for (k = G->neven; k < G->num; k++) { - for (k = G->neven; k < G->num; k++) + if (G->P[k].dlog == NULL) { - pk = G->primepowers[k]; - gk = G->generators[k] % pk; + pk = G->P[k].pe.n; + gk = G->P[k].g; x->log[k] = n_discrete_log_bsgs(m % pk, gk, pk); } - } - else - { - for (k = G->neven; k < G->num; k++) - x->log[k] = dlog_precomp(G->dlog[k], m % G->primepowers[k]); + else + { + x->log[k] = dlog_precomp(G->P[k].dlog, m % G->P[k].pe.n); + } } /* keep value m */ x->n = m; diff --git a/acb_dirichlet/conrey_mul.c b/acb_dirichlet/conrey_mul.c index cdac5acd..66884087 100644 --- a/acb_dirichlet/conrey_mul.c +++ b/acb_dirichlet/conrey_mul.c @@ -30,6 +30,6 @@ acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G { ulong k; for (k = 0; k < G->num ; k++) - c->log[k] = (a->log[k] + b->log[k]) % G->phi[k]; + c->log[k] = (a->log[k] + b->log[k]) % G->P[k].phi; c->n = nmod_mul(a->n, b->n, G->mod); } diff --git a/acb_dirichlet/conrey_next.c b/acb_dirichlet/conrey_next.c index 5b4be26c..c17db899 100644 --- a/acb_dirichlet/conrey_next.c +++ b/acb_dirichlet/conrey_next.c @@ -34,7 +34,7 @@ acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] += 1; - if (x->log[k] < G->phi[k]) + if (x->log[k] < G->P[k].phi) break; x->log[k] = 0; } diff --git a/acb_dirichlet/conrey_next_primitive.c b/acb_dirichlet/conrey_next_primitive.c index d79306ae..682b9b24 100644 --- a/acb_dirichlet/conrey_next_primitive.c +++ b/acb_dirichlet/conrey_next_primitive.c @@ -44,12 +44,12 @@ acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichle { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; - if (x->log[k] % G->primes[k] == 0) + if (x->log[k] % G->P[k].p == 0) { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; } - if (x->log[k] < G->phi[k]) + if (x->log[k] < G->P[k].phi) break; x->log[k] = 1; } diff --git a/acb_dirichlet/conrey_pow.c b/acb_dirichlet/conrey_pow.c index 960c88c7..4393bfed 100644 --- a/acb_dirichlet/conrey_pow.c +++ b/acb_dirichlet/conrey_pow.c @@ -30,6 +30,6 @@ acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G { ulong k; for (k = 0; k < G->num ; k++) - c->log[k] = (a->log[k] * n) % G->phi[k]; + c->log[k] = (a->log[k] * n) % G->P[k].phi; c->n = nmod_pow_ui(a->n, n, G->mod); } diff --git a/acb_dirichlet/conrey_primitive.c b/acb_dirichlet/conrey_primitive.c index 611c1272..9a7c0242 100644 --- a/acb_dirichlet/conrey_primitive.c +++ b/acb_dirichlet/conrey_primitive.c @@ -48,7 +48,7 @@ acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_gro if (x->log[k]) { ulong p, lp; - p = G->primes[k]; + p = G->P[k].p; if (cond % p == 0) { lp = x->log[k]; diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 46cd73d0..85e29a3d 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -45,9 +45,9 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri /* FIXME: check if one can start at G->neven */ for (k = 0; k < G->num; k++) { - ulong p = G->primes[k]; + ulong p = G->P[k].p; - if (G->exponents[k] > 1 && NN0 % (p*p) == 0) + if (G->P[k].e > 1 && NN0 % (p*p) == 0) { acb_zero(res); return; diff --git a/acb_dirichlet/group_clear.c b/acb_dirichlet/group_clear.c index ccf9446b..9864ad1c 100644 --- a/acb_dirichlet/group_clear.c +++ b/acb_dirichlet/group_clear.c @@ -15,10 +15,7 @@ void acb_dirichlet_group_clear(acb_dirichlet_group_t G) { - flint_free(G->primes); - flint_free(G->exponents); - flint_free(G->primepowers); + flint_free(G->P); flint_free(G->generators); - flint_free(G->phi); flint_free(G->PHI); } diff --git a/acb_dirichlet/group_dlog_precompute.c b/acb_dirichlet/group_dlog_precompute.c index 848b8099..2f816531 100644 --- a/acb_dirichlet/group_dlog_precompute.c +++ b/acb_dirichlet/group_dlog_precompute.c @@ -25,18 +25,18 @@ #include "acb_dirichlet.h" +void +acb_dirichlet_prime_group_dlog_precompute(acb_dirichlet_prime_group_struct * P, ulong num) +{ + P->dlog = flint_malloc(sizeof(dlog_precomp_t)); + dlog_precomp_modpe_init(P->dlog, P->g, P->p, P->e, P->pe.n, num); +} + + void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) { slong k; - G->dlog = flint_malloc(G->num * sizeof(dlog_precomp_t)); for (k = 0; k < G->num; k++) - { - ulong p, e, pe, a; - p = G->primes[k]; - e = G->exponents[k]; - pe = G->primepowers[k]; - a = G->generators[k] % pe; - dlog_precomp_modpe_init(G->dlog[k], a, p, e, pe, num); - } + acb_dirichlet_prime_group_dlog_precompute(&G->P[k], num); } diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index 4b288033..cce5971f 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -33,94 +33,150 @@ primitive_root_p_and_p2(ulong p) return n_primitive_root_prime(p); } +void +acb_dirichlet_prime_group_init(acb_dirichlet_prime_group_struct * P, ulong p, int e) +{ + P->p = p; + P->e = e; + if (p == 2 || p == 4) + { + P->p = 2; + nmod_init(&P->pe, 1 << e); + if (p == 2) + { + P->e = 2; + P->phi = 2; + P->g = (1 << e) - 1; + } + else + { + P->phi = 1 << (e - 2); + P->g = 5; + } + } + else + { + ulong pe1; + pe1 = n_pow(p, e - 1); + P->phi = (p-1) * pe1; + nmod_init(&P->pe, p * pe1); + P->g = primitive_root_p_and_p2(p); + } + P->dlog = NULL; +} + +static void +acb_dirichlet_group_lift_generators(acb_dirichlet_group_t G) +{ + slong k; + acb_dirichlet_prime_group_struct * P = G->P; + + G->expo = G->phi_q = 1; + if (G->neven) + { + G->phi_q = G->q_even / 2; + G->expo = P[G->neven - 1].phi; + } + for (k = G->neven; k < G->num; k++) + { + G->phi_q *= P[k].phi; + G->expo *= P[k].phi / n_gcd(G->expo, P[k].p - 1); + } + + for (k = 0; k < G->num; k++) + { + nmod_t pe; + ulong qpe, v; + G->PHI[k] = G->expo / G->P[k].phi; + /* lift generators mod q */ + /* u * p^e + v * q/p^e = 1 -> g mod q = 1 + (g-1) * v*(q/p^e) */ + pe = G->P[k].pe; + qpe = G->q / pe.n; + v = nmod_inv(qpe % pe.n, pe); + /* no overflow since v * qpe < q */ + G->generators[k] = (1 + (G->P[k].g-1) * v * qpe) % G->q; + } +} + void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) { slong k; - ulong e2 = 0; + ulong e2; n_factor_t fac; G->q = q; nmod_init(&G->mod, q); - G->q_odd = q; G->q_even = 1; - while (G->q_odd % 2 == 0) + for (e2 = 0; q % 2 == 0; e2++) { - G->q_odd /= 2; + q /= 2; G->q_even *= 2; - e2++; } + /* warning: only factor odd part */ n_factor_init(&fac); - n_factor(&fac, G->q_odd, 1); - - /* - TODO: Dirichlet group may be an array of - prime components structs instead, since - many algorithms are done prime by prime - and this would make subgroups easier. - */ + n_factor(&fac, q, 1); /* number of components at p=2 */ G->neven = (e2 >= 3) ? 2 : (e2 == 2) ? 1 : 0; - G->num = G->neven + fac.num; - G->primes = flint_malloc(G->num * sizeof(ulong)); - G->exponents = flint_malloc(G->num * sizeof(ulong)); - G->primepowers = flint_malloc(G->num * sizeof(ulong)); + G->num = fac.num + G->neven; + G->P = flint_malloc(G->num * sizeof(acb_dirichlet_prime_group_struct)); G->generators = flint_malloc(G->num * sizeof(ulong)); - G->phi = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); - G->dlog = NULL; /* even part */ - G->expo = G->phi_q = 1; if (G->neven >= 1) - { - G->primes[0] = 2; - G->exponents[0] = 2; - G->phi[0] = 2; - G->primepowers[0] = G->q_even; - G->generators[0] = G->q_even-1; - G->expo = 2; - G->phi_q = 2; - } + acb_dirichlet_prime_group_init(&G->P[0], 2, e2); if (G->neven == 2) - { - G->primes[1] = 2; - G->exponents[1] = e2; - G->phi[1] = G->q_even / 4; - G->primepowers[1] = G->q_even; - G->generators[1] = 5; - G->expo = G->phi[1]; - G->phi_q = G->q_even / 2; - } + acb_dirichlet_prime_group_init(&G->P[1], 4, e2); + /* odd part */ + G->rad_q = 1; for (k = G->neven; k < G->num; k++) { - ulong p1, pe1; - G->primes[k] = fac.p[k - G->neven]; - G->exponents[k] = fac.exp[k - G->neven]; - p1 = G->primes[k] - 1; - pe1 = n_pow(G->primes[k], G->exponents[k]-1); - G->phi[k] = p1 * pe1; - G->primepowers[k] = pe1 * G->primes[k]; - G->generators[k] = primitive_root_p_and_p2(G->primes[k]); - G->expo *= G->phi[k] / n_gcd(G->expo, p1); - G->phi_q *= G->phi[k]; + ulong p, e; + p = fac.p[k - G->neven]; + e = fac.exp[k - G->neven]; + G->rad_q *= p; + acb_dirichlet_prime_group_init(&G->P[k], p, e); } - /* generic odd+even */ + acb_dirichlet_group_lift_generators(G); +} + +void +acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h) +{ + slong k, j; + int s[15]; /* selected components */ + + H->q = h; + for (k = 0, j = 0; k < G->num; k++) + { + ulong p = G->P[k].p; + + for(s[k] = 0; h % p == 0; h /= p) + s[k]++; + + if (s[k] > 0) + j++; + } + + H->num = j; + H->P = flint_malloc(j * sizeof(acb_dirichlet_prime_group_struct)); + + j = 0; for (k = 0; k < G->num; k++) { - ulong pe, qpe, v; - G->PHI[k] = G->expo / G->phi[k]; - /* lift generators mod q */ - /* u * p^e + v * q/p^e = 1 -> g mod q = 1 + (g-1) * v*(q/p^e) */ - pe = G->primepowers[k]; - qpe = q / pe; - v = n_invmod(qpe % pe, pe); - /* no overflow since v * qpe < q */ - G->generators[k] = (1 + (G->generators[k]-1) * v * qpe) % q; + if (s[k]) + { + H->P[j] = G->P[k]; + H->P[j].e = s[k]; + j++; + } } + + acb_dirichlet_group_lift_generators(H); } diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index ef40861f..02198218 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -49,8 +49,8 @@ jacobi_one(const acb_dirichlet_group_t G, ulong cond) slong k, r = 1; for (k = 0; k < G->num; k++) - r *= jacobi_one_prime(G->primes[k], G->exponents[k], - G->primepowers[k], cond); + r *= jacobi_one_prime(G->P[k].p, G->P[k].e, + G->P[k].pe.n, cond); return r; } @@ -91,21 +91,22 @@ acb_dirichlet_jacobi_sum_primes(acb_t res, const acb_dirichlet_group_t G, const /* TODO: efficient subgroup */ for (k = 0; k < G->num; k++) { - ulong p, e, pe, ap, bp; + nmod_t pe; + ulong p, e, ap, bp; - p = G->primes[k]; - e = G->exponents[k]; - pe = G->primepowers[k]; - ap = chi1->x->n % pe; - bp = chi2->x->n % pe; + p = G->P[k].p; + e = G->P[k].e; + pe = G->P[k].pe; + ap = chi1->x->n % pe.n; + bp = chi2->x->n % pe.n; - if (ap == 1 || bp == 1 || n_mulmod2(ap, bp, pe) == 1) + if (ap == 1 || bp == 1 || nmod_mul(ap, bp, pe) == 1) { slong r; ulong cond; cond = (ap == 1) ? chi2->conductor : chi1->conductor; - r = jacobi_one_prime(p, e, pe, cond); + r = jacobi_one_prime(p, e, pe.n, cond); /* chi(a,-1) if ap * bp = 1 */ if (ap != 1 && bp != 1) @@ -118,7 +119,7 @@ acb_dirichlet_jacobi_sum_primes(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_group_t Gp; acb_dirichlet_char_t chi1p, chi2p; - acb_dirichlet_group_init(Gp, pe); + acb_dirichlet_group_init(Gp, pe.n); acb_dirichlet_char_init(chi1p, Gp); acb_dirichlet_char_init(chi2p, Gp); @@ -174,7 +175,7 @@ acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dir acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); else if (G->num > 1) acb_dirichlet_jacobi_sum_primes(res, G, chi1, chi2, prec); - else if (G->exponents[0] > 1) + else if (G->P[0].e > 1) acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); else acb_dirichlet_jacobi_sum_gauss(res, G, chi1, chi2, prec); diff --git a/acb_dirichlet/number_primitive.c b/acb_dirichlet/number_primitive.c index 78ebfa75..94b09546 100644 --- a/acb_dirichlet/number_primitive.c +++ b/acb_dirichlet/number_primitive.c @@ -39,11 +39,11 @@ acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) for (k = (G->neven == 2); k < G->num; k++) { - ulong p = G->primes[k]; - if (G->exponents[k] == 1) + ulong p = G->P[k].p, e = G->P[k].e; + if (e == 1) n *= p - 2; else - n *= (p * (p - 2) + 1) * n_pow(p, G->exponents[k] - 2); + n *= (p * (p - 2) + 1) * n_pow(p, e - 2); } return n; diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 651a6e34..0d53b511 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -72,7 +72,7 @@ int main() ref = (q % 4 == 2) ? -2 : 1; k = (G->neven == 2) ? 1 : 0; for (; knum; k++) - ref = - ref * G->primes[k]; + ref = - ref * G->P[k].p; ref = ( G->phi_q * (2 * q * q + ref) ) / 6; diff --git a/acb_dirichlet/ui_chi_vec_primeloop.c b/acb_dirichlet/ui_chi_vec_primeloop.c index dc749c13..4a74c74b 100644 --- a/acb_dirichlet/ui_chi_vec_primeloop.c +++ b/acb_dirichlet/ui_chi_vec_primeloop.c @@ -40,8 +40,8 @@ chi_vec_evenpart(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_ch { ulong g, pe, vx, xp; vx = c4; - pe = G->primepowers[1]; - g = G->generators[1] % pe; + pe = G->P[1].pe.n; + g = G->P[1].g; for (x = g; x > 1;) { @@ -73,9 +73,9 @@ acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, cons for (l = G->neven; l < G->num; l++) { ulong p, pe, g, x, vx, vp, xp; - p = G->primes[l]; - pe = G->primepowers[l]; - g = G->generators[l] % pe; + p = G->P[l].p; + pe = G->P[l].pe.n; + g = G->P[l].g; vx = vp = chi->expo[l]; if (vp == 0) diff --git a/acb_dirichlet/ui_conductor.c b/acb_dirichlet/ui_conductor.c index 593046a2..4d015ad4 100644 --- a/acb_dirichlet/ui_conductor.c +++ b/acb_dirichlet/ui_conductor.c @@ -25,21 +25,21 @@ #include "acb_dirichlet.h" +/* TODO: product of local conductors */ ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) { slong k; ulong ap, cond; - nmod_t pe; cond = 1; for (k = (G->neven == 2); k < G->num; k++) { - ulong p, e; - p = G->primes[k]; - e = G->exponents[k]; - nmod_init(&pe, G->primepowers[k]); + ulong p; + nmod_t pe; + p = G->P[k].p; + pe = G->P[k].pe; ap = a % pe.n; if (ap == 1) continue; diff --git a/acb_dirichlet/ui_parity.c b/acb_dirichlet/ui_parity.c index c08b5423..5fa84d73 100644 --- a/acb_dirichlet/ui_parity.c +++ b/acb_dirichlet/ui_parity.c @@ -28,7 +28,6 @@ int acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) { - slong k; int par; par = 0; @@ -36,12 +35,8 @@ acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) if (G->neven && a % 4 == 3) par++; - /* could replace by jacobi(a, core(q_odd)) */ - for (k = G->neven; k < G->num; k++) - { - if (n_jacobi_unsigned(a, G->primes[k]) == -1) - par++; - } + if (n_jacobi_unsigned(a, G->rad_q) == -1) + par++; return par % 2; } diff --git a/acb_dirichlet/ui_vec_set_null.c b/acb_dirichlet/ui_vec_set_null.c index 9a8e831a..e668b9a7 100644 --- a/acb_dirichlet/ui_vec_set_null.c +++ b/acb_dirichlet/ui_vec_set_null.c @@ -37,7 +37,7 @@ acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv) for (l = 0; l < G->num; l++) { - ulong p = G->primes[l]; + ulong p = G->P[l].p; for (k = p; k < nv; k += p) v[k] = ACB_DIRICHLET_CHI_NULL; From 6dee9d41dc7a6d78e035f1aa3a2adaccd870d061 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 13 Jul 2016 15:54:45 +0200 Subject: [PATCH 044/139] gauss sums using factor --- acb_dirichlet.h | 2 + acb_dirichlet/gauss_sum.c | 22 ++++-- acb_dirichlet/gauss_sum_factor.c | 126 +++++++++++++++++++++++++++++++ acb_dirichlet/group_init.c | 70 +++++++++++++---- acb_dirichlet/test/t-gauss.c | 20 ++--- 5 files changed, 209 insertions(+), 31 deletions(-) create mode 100644 acb_dirichlet/gauss_sum_factor.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index eca992bd..8f838b65 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -68,6 +68,7 @@ acb_dirichlet_group_size(const acb_dirichlet_group_t G) } void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); +void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h); void acb_dirichlet_group_clear(acb_dirichlet_group_t G); void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); @@ -223,6 +224,7 @@ void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 85e29a3d..625ee518 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -36,14 +36,18 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri /* G(chi) = mu(N/N0)chi0(N/N0)G(chi0) */ - if (NN0 % 4 == 0) + if (NN0 % 2 == 0) { - acb_zero(res); - return; + if (G->q % 4) + mu = -1; + else + { + acb_zero(res); + return; + } } - /* FIXME: check if one can start at G->neven */ - for (k = 0; k < G->num; k++) + for (k = G->neven; k < G->num; k++) { ulong p = G->P[k].p; @@ -68,8 +72,7 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri acb_dirichlet_char_t chi0; acb_t z; - /* TODO: implement efficient subgroup */ - acb_dirichlet_group_init(G0, chi->conductor); + acb_dirichlet_subgroup_init(G0, G, chi->conductor); acb_dirichlet_char_init(chi0, G); acb_dirichlet_char_primitive(chi0, G0, G, chi); @@ -90,6 +93,7 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { + /* no need, factor also does it... */ if (chi->conductor != G->q) { gauss_sum_non_primitive(res, G, chi, prec); @@ -107,6 +111,10 @@ acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_diri arb_zero(acb_imagref(res)); } } + else if (G->num > 1 && G->num > G->neven) + { + acb_dirichlet_gauss_sum_factor(res, G, chi, prec); + } else { if (acb_dirichlet_theta_length_d(G->q, 1, prec) > G->q) diff --git a/acb_dirichlet/gauss_sum_factor.c b/acb_dirichlet/gauss_sum_factor.c new file mode 100644 index 00000000..1c382167 --- /dev/null +++ b/acb_dirichlet/gauss_sum_factor.c @@ -0,0 +1,126 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* +void +acb_dirichlet_gauss_sum_naive_prime(acb_t res, acb_dirichlet_prime_group_struct P, ulong expo, slong prec) +{ + acb_t z; + acb_ptr v; + + v = _acb_vec_init(G->q); + acb_dirichlet_chi_vec(v, G, chi, G->q, prec); + + acb_init(z); + acb_dirichlet_nth_root(z, G->q, prec); + + _acb_poly_evaluate(res, v, G->q, z, prec); + + acb_clear(z); + _acb_vec_clear(v, G->q); +} + + +static void +acb_dirichlet_gauss_sum_prime(acb_t res, acb_dirichlet_prime_group_struct P, ulong expo, slong prec) +{ + if (expo % P.p == 0) + { + if (P.e == 1) + acb_set_si(res, -1); + else + acb_zero(res); + } + else + { + if (acb_dirichlet_theta_length_d(P.pe.n, 1, prec) > P.pe.n) + acb_dirichlet_gauss_sum_naive_prime(res, P, expo, prec); + else + acb_dirichlet_gauss_sum_naive_prime(res, P, expo, prec); + } +} +*/ + +void +acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + + slong k; + acb_t tmp; + + for (k = (G->neven == 2); k < G->num; k++) + { + /* if e > 1 and not primitive, 0 */ + if (chi->x->log[k] % G->P[k].p == 0 && G->P[k].e > 1) + { + acb_zero(res); + return; + } + } + + /* factor */ + acb_one(res); + acb_init(tmp); + + for (k = (G->neven == 2); k < G->num; k++) + { + ulong pe = G->P[k].pe.n; + acb_dirichlet_group_t Gp; + acb_dirichlet_char_t chip; + + acb_dirichlet_subgroup_init(Gp, G, pe); + acb_dirichlet_char_init(chip, Gp); + + chip->x->n = chi->x->n % pe; + + if (k == 1 && G->neven == 2) + { + chip->x->log[0] = chi->x->log[0]; + chip->x->log[1] = chi->x->log[1]; + } + else + chip->x->log[0] = chi->x->log[k]; + + acb_dirichlet_char_conrey(chip, Gp, NULL); + + /* chi_pe(a, q/pe) * G_pe(a) */ + acb_dirichlet_gauss_sum(tmp, Gp, chip, prec); + acb_mul(res, res, tmp, prec); + + acb_dirichlet_chi(tmp, Gp, chip, (G->q / pe) % pe, prec); + acb_mul(res, res, tmp, prec); + + acb_dirichlet_char_clear(chip); + acb_dirichlet_group_clear(Gp); + } + + if (G->q_even == 2) + acb_neg(res, res); + + acb_clear(tmp); + +} diff --git a/acb_dirichlet/group_init.c b/acb_dirichlet/group_init.c index cce5971f..9120ae48 100644 --- a/acb_dirichlet/group_init.c +++ b/acb_dirichlet/group_init.c @@ -92,6 +92,11 @@ acb_dirichlet_group_lift_generators(acb_dirichlet_group_t G) /* u * p^e + v * q/p^e = 1 -> g mod q = 1 + (g-1) * v*(q/p^e) */ pe = G->P[k].pe; qpe = G->q / pe.n; + if (G->q < G->P[k].pe.n) + { + flint_printf("lift generator %wu from %wu to %wu e=%wu\n", + G->P[k].g, G->P[k].pe.n, G->q, G->P[k].e); + } v = nmod_inv(qpe % pe.n, pe); /* no overflow since v * qpe < q */ G->generators[k] = (1 + (G->P[k].g-1) * v * qpe) % G->q; @@ -108,20 +113,16 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) G->q = q; nmod_init(&G->mod, q); - G->q_even = 1; - for (e2 = 0; q % 2 == 0; e2++) - { - q /= 2; - G->q_even *= 2; - } + e2 = n_remove(&q, 2); + G->q_even = 1 << e2; + /* number of components at p=2 */ + G->neven = (e2 >= 3) ? 2 : (e2 == 2) ? 1 : 0; /* warning: only factor odd part */ n_factor_init(&fac); n_factor(&fac, q, 1); - /* number of components at p=2 */ - G->neven = (e2 >= 3) ? 2 : (e2 == 2) ? 1 : 0; G->num = fac.num + G->neven; G->P = flint_malloc(G->num * sizeof(acb_dirichlet_prime_group_struct)); G->generators = flint_malloc(G->num * sizeof(ulong)); @@ -149,31 +150,70 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h) { - slong k, j; - int s[15]; /* selected components */ + int s[15]; /* selected components */ + slong k, j, e2; H->q = h; - for (k = 0, j = 0; k < G->num; k++) + nmod_init(&H->mod, h); + + /* even components */ + + e2 = n_remove(&h, 2); + H->q_even = 1 << e2; + + s[0] = s[1] = 0; + j = 0; + if (e2 >= 2) + s[j++] = 2; + if (e2 >= 3) + s[j++] = e2; + + H->neven = j; + + /* odd components */ + for (k = G->neven; k < G->num; k++) { ulong p = G->P[k].p; - for(s[k] = 0; h % p == 0; h /= p) - s[k]++; + s[k] = n_remove(&h, p); if (s[k] > 0) + { j++; + H->rad_q *= p; + } } H->num = j; H->P = flint_malloc(j * sizeof(acb_dirichlet_prime_group_struct)); + H->generators = flint_malloc(j * sizeof(ulong)); + H->PHI = flint_malloc(j * sizeof(ulong)); j = 0; - for (k = 0; k < G->num; k++) + for (k = 0; k < H->neven; k++) + { + H->P[j] = G->P[k]; + if (H->q_even < G->q_even) + { + nmod_init(&H->P[j].pe, H->q_even); + H->P[j].e = s[k]; + if (k == 0) + H->P[j].g = H->q_even - 1; + } + j++; + } + + for (k = G->neven; k < G->num; k++) { if (s[k]) { H->P[j] = G->P[k]; - H->P[j].e = s[k]; + if (s[k] < G->P[k].e) + { + ulong p = H->P[j].p; + H->P[j].e = s[k]; + nmod_init(&H->P[j].pe, n_pow(p, s[k])); + } j++; } } diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index 9313a442..a44b345e 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -41,11 +41,7 @@ int main() acb_dirichlet_conrey_t x; acb_dirichlet_char_t chi; - acb_t s1, s2, s3; - - if (q % 4 == 2) - /* no primitive character mod q */ - continue; + acb_t s1, s2, s3, s4; acb_dirichlet_group_init(G, q); acb_dirichlet_conrey_init(x, G); @@ -54,6 +50,7 @@ int main() acb_init(s1); acb_init(s2); acb_init(s3); + acb_init(s4); acb_dirichlet_conrey_one(x, G); while (1) { @@ -62,21 +59,25 @@ int main() acb_dirichlet_gauss_sum_naive(s1, G, chi, prec); acb_dirichlet_gauss_sum(s2, G, chi, prec); + acb_dirichlet_gauss_sum_factor(s3, G, chi, prec); if (chi->conductor == G->q) - acb_dirichlet_gauss_sum_theta(s3, G, chi, prec); + acb_dirichlet_gauss_sum_theta(s4, G, chi, prec); else - acb_set(s3, s1); + acb_set(s4, s1); if (!acb_overlaps(s1, s2) - || !acb_overlaps(s1, s3)) + || !acb_overlaps(s1, s3) + || !acb_overlaps(s1, s4)) { flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->x->n); flint_printf("\nnaive ", q, x->n); acb_printd(s1, 25); flint_printf("\ndefault ", q, x->n); acb_printd(s2, 25); - flint_printf("\ntheta ", q, x->n); + flint_printf("\nfactor ", q, x->n); acb_printd(s3, 25); + flint_printf("\ntheta ", q, x->n); + acb_printd(s4, 25); abort(); } @@ -86,6 +87,7 @@ int main() acb_clear(s1); acb_clear(s2); acb_clear(s3); + acb_clear(s4); acb_dirichlet_group_clear(G); acb_dirichlet_char_clear(chi); From 1f5d49cfe90d3c41ec8394f2d6322548e3bb7661 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 14 Jul 2016 15:51:25 +0200 Subject: [PATCH 045/139] use dlog vec function --- acb_dirichlet/power.c | 3 ++- acb_dirichlet/ui_chi_vec_primeloop.c | 23 +++++------------------ acb_dirichlet/ui_vec_set_null.c | 2 +- dlog.h | 1 + dlog/vec.c | 2 ++ 5 files changed, 11 insertions(+), 20 deletions(-) diff --git a/acb_dirichlet/power.c b/acb_dirichlet/power.c index 31dfceb1..55c54c37 100644 --- a/acb_dirichlet/power.c +++ b/acb_dirichlet/power.c @@ -32,8 +32,9 @@ acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec { if (n < t->m) { - /* acb_set(z, t->z + n); */ + /* FIXME: I do not want to copy: is this all right? */ *z = *(t->z + n); + /* acb_set(z, t->z + n); */ } else { diff --git a/acb_dirichlet/ui_chi_vec_primeloop.c b/acb_dirichlet/ui_chi_vec_primeloop.c index 4a74c74b..af57fa30 100644 --- a/acb_dirichlet/ui_chi_vec_primeloop.c +++ b/acb_dirichlet/ui_chi_vec_primeloop.c @@ -63,6 +63,7 @@ void acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { slong k, l; + nmod_t order; for (k = 1; k < nv; k++) v[k] = 0; @@ -70,28 +71,14 @@ acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, cons if (G->neven) chi_vec_evenpart(v, G, chi, nv); + nmod_init(&order, chi->order); for (l = G->neven; l < G->num; l++) { - ulong p, pe, g, x, vx, vp, xp; - p = G->P[l].p; - pe = G->P[l].pe.n; - g = G->P[l].g; - vx = vp = chi->expo[l]; + acb_dirichlet_prime_group_struct P = G->P[l]; - if (vp == 0) - continue; - /* for each x = g^j mod p^e, - * set a[x] += j*vp - * and use periodicity */ - for (x = g; x > 1;) - { + /* FIXME: there may be some precomputed dlog in P if needed */ + dlog_vec_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, order); - for (xp = x; xp < nv; xp += pe) - v[xp] = (v[xp] + vx) % chi->order; - - x = (x * g) % pe; - vx = (vx + vp) % chi->order; - } } acb_dirichlet_ui_vec_set_null(v, G, nv); } diff --git a/acb_dirichlet/ui_vec_set_null.c b/acb_dirichlet/ui_vec_set_null.c index e668b9a7..46bf517a 100644 --- a/acb_dirichlet/ui_vec_set_null.c +++ b/acb_dirichlet/ui_vec_set_null.c @@ -35,7 +35,7 @@ acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv) v[k] = -1; } - for (l = 0; l < G->num; l++) + for (l = G->neven; l < G->num; l++) { ulong p = G->P[l].p; diff --git a/dlog.h b/dlog.h index 33507f89..f62ef63a 100644 --- a/dlog.h +++ b/dlog.h @@ -267,6 +267,7 @@ void dlog_vec_eratos_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulon void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); #endif diff --git a/dlog/vec.c b/dlog/vec.c index 54e09a57..0fc67623 100644 --- a/dlog/vec.c +++ b/dlog/vec.c @@ -28,6 +28,8 @@ void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { + if (va == 0) + return; if (na * DLOG_LOOP_MAX_FACTOR > nv) dlog_vec_loop(v, nv, a, va, mod, na, order); else From 17609d37779cefe0969a1ca9acbfdc3331047ca7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 14 Jul 2016 18:55:44 +0200 Subject: [PATCH 046/139] char->order now nmod_t --- acb_dirichlet.h | 5 +++-- acb_dirichlet/char_eq.c | 2 +- acb_dirichlet/char_normalize.c | 4 ++-- acb_dirichlet/chi_theta_arb.c | 2 +- acb_dirichlet/chi_vec.c | 2 +- acb_dirichlet/gauss_sum.c | 2 +- acb_dirichlet/jacobi_sum_naive.c | 4 ++-- acb_dirichlet/l.c | 8 ++++---- acb_dirichlet/test/t-chars.c | 6 +++--- acb_dirichlet/test/t-thetanull.c | 2 +- acb_dirichlet/ui_chi_conrey.c | 3 ++- acb_dirichlet/ui_chi_vec_loop.c | 2 +- acb_dirichlet/ui_chi_vec_primeloop.c | 21 ++++++++++----------- acb_dirichlet/ui_chi_vec_sieve.c | 6 +++++- 14 files changed, 37 insertions(+), 32 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 8f838b65..261a1f79 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -32,6 +32,7 @@ void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); +/* should this dlog pointer be in the prime or the global group? */ typedef struct { ulong p; /* underlying prime */ @@ -132,7 +133,7 @@ void acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ul typedef struct { ulong q; /* modulus */ - ulong order; /* order */ + nmod_t order; /* order */ acb_dirichlet_conrey_t x; ulong * expo; /* reduced exponents ( log[k] * PHI[k] / gcd( ) ) */ int parity; /* 0 for even char, 1 for odd */ @@ -145,7 +146,7 @@ typedef acb_dirichlet_char_struct acb_dirichlet_char_t[1]; ACB_DIRICHLET_INLINE ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) { - return chi->order; + return chi->order.n; } ACB_DIRICHLET_INLINE ulong diff --git a/acb_dirichlet/char_eq.c b/acb_dirichlet/char_eq.c index 4e73f02b..204fcada 100644 --- a/acb_dirichlet/char_eq.c +++ b/acb_dirichlet/char_eq.c @@ -33,7 +33,7 @@ acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t if (chi1->q != chi2->q) return 0; - if (chi1->order != chi2->order) + if (chi1->order.n != chi2->order.n) return 0; if (chi1->conductor != chi2->conductor) diff --git a/acb_dirichlet/char_normalize.c b/acb_dirichlet/char_normalize.c index 8f7af3a4..a4b4f1a7 100644 --- a/acb_dirichlet/char_normalize.c +++ b/acb_dirichlet/char_normalize.c @@ -45,14 +45,14 @@ acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group for (k = 0; k < G->num; k++) chi->expo[k] = chi->expo[k] / g; - chi->order = G->expo / g; + nmod_init(&chi->order, G->expo / g); } void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { ulong k, g; - g = G->expo / chi->order; + g = G->expo / chi->order.n; for (k = 0; k < G->num; k++) chi->expo[k] *= g; diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index ec7f4fca..3b7450a4 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -50,7 +50,7 @@ acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_ a = flint_malloc(len * sizeof(ulong)); acb_dirichlet_ui_chi_vec(a, G, chi, len); - acb_dirichlet_powers_init(z, chi->order, len, prec); + acb_dirichlet_powers_init(z, chi->order.n, len, prec); arb_init(x); acb_dirichlet_arb_theta_argt(x, G->q, t, prec); diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/chi_vec.c index 7b4dcee6..cb3abce2 100644 --- a/acb_dirichlet/chi_vec.c +++ b/acb_dirichlet/chi_vec.c @@ -35,7 +35,7 @@ acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirich a = flint_malloc(nv * sizeof(ulong)); acb_dirichlet_ui_chi_vec(a, G, chi, nv); - acb_dirichlet_powers_init(t, chi->order, nv, prec); + acb_dirichlet_powers_init(t, chi->order.n, nv, prec); acb_zero(v + 0); for (k = 0; k < nv; k++) diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 625ee518..c513cd99 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -98,7 +98,7 @@ acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_diri { gauss_sum_non_primitive(res, G, chi, prec); } - else if (chi->order <= 2) + else if (chi->order.n <= 2) { if (chi->parity) { diff --git a/acb_dirichlet/jacobi_sum_naive.c b/acb_dirichlet/jacobi_sum_naive.c index 72d838fd..d09c2901 100644 --- a/acb_dirichlet/jacobi_sum_naive.c +++ b/acb_dirichlet/jacobi_sum_naive.c @@ -44,8 +44,8 @@ acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const a acb_dirichlet_ui_vec_set_null(v2, G, G->q); acb_dirichlet_ui_chi_vec_loop(v2, G, chi2, G->q); - m1 = chi1->order; - m2 = chi2->order; + m1 = chi1->order.n; + m2 = chi2->order.n; g = n_gcd(m1, m2); nmod_init(&order, m1 * (m2 / g)); m1 = order.n / m1; diff --git a/acb_dirichlet/l.c b/acb_dirichlet/l.c index d556eb95..2fd4cc44 100644 --- a/acb_dirichlet/l.c +++ b/acb_dirichlet/l.c @@ -29,9 +29,9 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_dirichlet_conrey_one(cn, G); acb_zero(t); - acb_dirichlet_nth_root(z, chi->order, prec); - xz = _acb_vec_init(chi->order); - _acb_vec_set_powers(xz, z, chi->order, prec); + acb_dirichlet_nth_root(z, chi->order.n, prec); + xz = _acb_vec_init(chi->order.n); + _acb_vec_set_powers(xz, z, chi->order.n, prec); while (1) { chin = acb_dirichlet_ui_chi_conrey(G, chi, cn); @@ -53,7 +53,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_dirichlet_conrey_clear(cn); - _acb_vec_clear(xz, chi->order); + _acb_vec_clear(xz, chi->order.n); acb_clear(z); acb_clear(t); acb_clear(u); diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 4d340070..9c5c8e0d 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -81,7 +81,7 @@ int main() } order = acb_dirichlet_ui_order(G, m); - if (order != chi->order) + if (order != chi->order.n) { flint_printf("FAIL: order\n\n"); flint_printf("q = %wu\n\n", q); @@ -123,8 +123,8 @@ int main() acb_dirichlet_char(chi2, G, n); pairing = acb_dirichlet_ui_pairing(G, m, n); - if (pairing != acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order) - || pairing != acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order)) + if (pairing != acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order.n) + || pairing != acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order.n)) { flint_printf("FAIL: pairing\n\n"); flint_printf("q = %wu\n\n", q); diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 3c8c17fd..aa2dcae1 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -90,7 +90,7 @@ int main() acb_dirichlet_ui_chi_vec(v, G, chi, nv); - m = G->expo / chi->order; + m = G->expo / chi->order.n; tt = acb_dirichlet_char_parity(chi) ? kt : t; for (k = 1; k < nv; k++) diff --git a/acb_dirichlet/ui_chi_conrey.c b/acb_dirichlet/ui_chi_conrey.c index 51a804b5..cd5f4263 100644 --- a/acb_dirichlet/ui_chi_conrey.c +++ b/acb_dirichlet/ui_chi_conrey.c @@ -30,8 +30,9 @@ acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_c { ulong v = 0, k; + /* TODO: nmod_addmul? */ for (k = 0; k < G->num; k++) - v = (v + chi->expo[k] * x->log[k]) % chi->order; + v = nmod_add(v, nmod_mul(chi->expo[k], x->log[k], chi->order), chi->order); return v; } diff --git a/acb_dirichlet/ui_chi_vec_loop.c b/acb_dirichlet/ui_chi_vec_loop.c index 49bf4fae..6ad0179c 100644 --- a/acb_dirichlet/ui_chi_vec_loop.c +++ b/acb_dirichlet/ui_chi_vec_loop.c @@ -45,7 +45,7 @@ acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb { /* exponents were modified up to j */ for (k = 0; k <= j; k++) - t = (t + chi->expo[k]) % chi->order; + t = nmod_add(t, chi->expo[k], chi->order); if (x->n < nv) v[x->n] = t; diff --git a/acb_dirichlet/ui_chi_vec_primeloop.c b/acb_dirichlet/ui_chi_vec_primeloop.c index af57fa30..861160e8 100644 --- a/acb_dirichlet/ui_chi_vec_primeloop.c +++ b/acb_dirichlet/ui_chi_vec_primeloop.c @@ -38,22 +38,23 @@ chi_vec_evenpart(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_ch } if (G->neven == 2 && (c4 = chi->expo[1])) { - ulong g, pe, vx, xp; + ulong g, vx, xp; + nmod_t pe; vx = c4; - pe = G->P[1].pe.n; + pe = G->P[1].pe; g = G->P[1].g; for (x = g; x > 1;) { - for (xp = x; xp < nv; xp += pe) - v[xp] = (v[xp] + vx) % chi->order; + for (xp = x; xp < nv; xp += pe.n) + v[xp] = nmod_add(v[xp], vx, chi->order); - for (xp = pe - x; xp < nv; xp += pe) - v[xp] = (v[xp] + vx) % chi->order; + for (xp = pe.n - x; xp < nv; xp += pe.n) + v[xp] = nmod_add(v[xp], vx, chi->order); - x = (x * g) % pe; - vx = (vx + c4) % chi->order; + x = nmod_mul(x, g, pe); + vx = nmod_add(vx, c4, chi->order); } } } @@ -63,7 +64,6 @@ void acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { slong k, l; - nmod_t order; for (k = 1; k < nv; k++) v[k] = 0; @@ -71,13 +71,12 @@ acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, cons if (G->neven) chi_vec_evenpart(v, G, chi, nv); - nmod_init(&order, chi->order); for (l = G->neven; l < G->num; l++) { acb_dirichlet_prime_group_struct P = G->P[l]; /* FIXME: there may be some precomputed dlog in P if needed */ - dlog_vec_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, order); + dlog_vec_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, chi->order); } acb_dirichlet_ui_vec_set_null(v, G, nv); diff --git a/acb_dirichlet/ui_chi_vec_sieve.c b/acb_dirichlet/ui_chi_vec_sieve.c index 6c69b5a4..7c1dda04 100644 --- a/acb_dirichlet/ui_chi_vec_sieve.c +++ b/acb_dirichlet/ui_chi_vec_sieve.c @@ -26,6 +26,10 @@ #include "acb_dirichlet.h" /* sieve on primes */ +/* TODO: see if really more efficient than primeloop using dlog + * this one is cheaper propagating the values, but not sure this + * is noticeable ... + */ void acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { @@ -51,7 +55,7 @@ acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const ac for (k = p; k < nv; k += p) if (v[k] != -1) - v[k] = (v[k] + chip) % chi->order; + v[k] = nmod_add(v[k], chip, chi->order); } } From fe9116073f07354cea9b6a47ab0088709ad0c7c7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 15 Jul 2016 09:56:41 +0200 Subject: [PATCH 047/139] document dlog module --- doc/source/dlog.rst | 113 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 doc/source/dlog.rst diff --git a/doc/source/dlog.rst b/doc/source/dlog.rst new file mode 100644 index 00000000..3c3bd572 --- /dev/null +++ b/doc/source/dlog.rst @@ -0,0 +1,113 @@ +.. _dlog: + +**dlog.h** -- discrete logarithms mod ulong primes +=============================================================================== + +This module implements discrete logarithms, with in mind the application +to Dirichlet characters. + +In particular, this module defines a :type:`dlog_precomp_t` structure +permitting to describe a discrete log problem in some subgroup +of `\mathbb Z/p \mathbb Z` and store precomputed data for +faster computation of several such discrete logarithms. + +When initializing this data, the user provides both a group description and the expected +number of subsequent discrete logarithms calls. The choice of algorithm and +the amount of stored data depend both on the structure of the group and this number. + +No particular effort has been made towards single discrete logarithm +computation. Currently only machine size primepower moduli +are supported. + +Algorithms +------------------------------------------------------------------------------- + +Several discrete logarithms strategies are implemented: + +- complete lookup table for small groups + +- baby-step giant-step table + +combined with mathematical reductions + +- Pohlig-Hellman decomposition (chinese remainder decomposition on the + order of the group and base `p` decomposition for primepower order) + +- p-adic log for primepower modulus `p^e`. + +For *dlog_vec* functions which compute the vector of discrete logarithms +of successive integers `1\dots n`: + +- a simple loop on group elements avoiding all logarithms is done when + the group size is comparable with the number of elements requested + +- otherwise the logarithms are computed on primes and propagated by + Eratosthene-like sieving. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. macro:: DLOG_NONE + + return value when the discrete logarithm does not exist + +.. type:: dlog_precomp_struct + +.. type:: dlog_precomp_t + + structure for discrete logarithm precomputed data. + +.. function:: void dlog_precomp_clear(dlog_precomp_t pre) + +Precomputations +------------------------------------------------------------------------------- + +.. function:: void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); + + precompute data for *num* discrete logarithms evaluations in the subgroup generated + by *a* modulo *mod*, where *a* is known to have order *n*. + +Specialized versions are available when specific information is known about the +group: + +.. function:: void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num); + + assume that *a* generates the group of residues modulo `p^e`. + +.. function:: void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num); + + assume that *a* has prime order *p*. + +.. function:: void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num); + + assume that *a* has primepower order *p*. + + +Single evaluation +------------------------------------------------------------------------------- + +.. function:: ulong dlog_precomp(const dlog_precomp_t pre, ulong b) + + returns `\log(b)` for the group described in *pre* + +Vector evaluations +------------------------------------------------------------------------------- + +.. function:: void dlog_vec_fill(ulong * v, ulong nv, ulong x); + + Sets values *v[k]* to *x* for all *k* less than *nv*. + +.. function:: void dlog_vec_set_not_found(ulong * v, ulong nv, nmod_t mod); + + Sets values *v[k]* to :macro:`DLOG_NONE` for all *k* not coprime to *mod*. + +.. function:: void dlog_vec(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + + sets *v[k]* to `\log(k,a)` times value *va* for `0\leq k < nv`, where *a* + has order *na*. *va* should be *1* for usual log computation. + +.. function:: void dlog_vec_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + + same parameters as before, but adds `\log(k,a)` times value *va* + to *v[k]* and reduce modulo *order* instead of replacing the value. Indices + *k* such that *v[k]* equals *DLOG_NONE* are ignored. From c37fc6788432b7e0a5cf5bf6b1398f7505d04e5f Mon Sep 17 00:00:00 2001 From: Pascal Date: Sat, 16 Jul 2016 10:01:59 +0200 Subject: [PATCH 048/139] document and remove chi_vec_sieve function --- acb_dirichlet.h | 1 - acb_dirichlet/profile/p-vec.c | 42 +++++++++-- acb_dirichlet/ui_chi_vec_sieve.c | 63 ----------------- doc/source/acb_dirichlet.rst | 116 ++++++++++++++++++++++--------- 4 files changed, 119 insertions(+), 103 deletions(-) delete mode 100644 acb_dirichlet/ui_chi_vec_sieve.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 261a1f79..ba134b3e 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -190,7 +190,6 @@ ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_ch void acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv); void acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); void acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); void acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); /* precompute powers of a root of unity */ diff --git a/acb_dirichlet/profile/p-vec.c b/acb_dirichlet/profile/p-vec.c index c088f08a..1ddcabb3 100644 --- a/acb_dirichlet/profile/p-vec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -27,13 +27,13 @@ #include "profiler.h" typedef void (*dir_f) (ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void +static void dir_empty(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { return; } -void +static void vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ulong nv) { ulong q; @@ -62,6 +62,38 @@ vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ul flint_printf("\n"); } +static void +acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +{ + slong k, p, pmax; + n_primes_t iter; + + n_primes_init(iter); + + pmax = (nv < G->q) ? nv : G->q; + v[1] = 0; + + while ((p = n_primes_next(iter)) < pmax) + { + if (G->q % p == 0) + { + for (k = p; k < nv; k += p) + v[k] = ACB_DIRICHLET_CHI_NULL; + } + else + { + long chip; + chip = acb_dirichlet_ui_chi(G, chi, p); + + for (k = p; k < nv; k += p) + if (v[k] != -1) + v[k] = nmod_add(v[k], chip, chi->order); + } + } + + n_primes_clear(iter); +} + int main() { slong iter, k, nv, nref, r, nr; @@ -107,11 +139,9 @@ int main() fflush(stdout); vecloop(acb_dirichlet_ui_chi_vec_sieve, minq, maxq, rand, nr, v, nv); - /* - flint_printf("generic........ "); + flint_printf("generic................. "); fflush(stdout); - vecloop(acb_dirichlet_chi_vec, minq, maxq, rand, nr, v, nv); - */ + vecloop(acb_dirichlet_ui_chi_vec, minq, maxq, rand, nr, v, nv); } flint_free(v); diff --git a/acb_dirichlet/ui_chi_vec_sieve.c b/acb_dirichlet/ui_chi_vec_sieve.c deleted file mode 100644 index 7c1dda04..00000000 --- a/acb_dirichlet/ui_chi_vec_sieve.c +++ /dev/null @@ -1,63 +0,0 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2016 Pascal Molin - -******************************************************************************/ - -#include "acb_dirichlet.h" - -/* sieve on primes */ -/* TODO: see if really more efficient than primeloop using dlog - * this one is cheaper propagating the values, but not sure this - * is noticeable ... - */ -void -acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) -{ - slong k, p, pmax; - n_primes_t iter; - - n_primes_init(iter); - - pmax = (nv < G->q) ? nv : G->q; - v[1] = 0; - - while ((p = n_primes_next(iter)) < pmax) - { - if (G->q % p == 0) - { - for (k = p; k < nv; k += p) - v[k] = ACB_DIRICHLET_CHI_NULL; - } - else - { - long chip; - chip = acb_dirichlet_ui_chi(G, chi, p); - - for (k = p; k < nv; k += p) - if (v[k] != -1) - v[k] = nmod_add(v[k], chip, chi->order); - } - } - - n_primes_clear(iter); -} diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index ee418d12..a45b001c 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -69,6 +69,11 @@ logarithms. exceed `10^{12}` (an abort will be raised). This restriction could be removed in the future. +.. function:: void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h) + + Given an already computed group *G* mod `q`, initialize its subgroup *H* + defined mod `h\mid q`. Precomputed discrete logs tables are kept. + .. function:: void acb_dirichlet_group_clear(acb_dirichlet_group_t G) Clears *G*. @@ -80,8 +85,8 @@ logarithms. If *num* gets very large, the entire group may be indexed. -Conrey index -............................................................................... +Conrey elements +------------------------------------------------------------------------------- .. type:: acb_dirichlet_conrey_struct @@ -134,34 +139,6 @@ the group *G* is isomorphic to its dual. The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. -Character properties -............................................................................... - -As a consequence of the Conrey numbering, properties of -characters such that the order, the parity or the conductor are available -at the level of their number, whithout any discrete log computation, -or at the Conrey index level. - -.. function:: ulong acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a) - -.. function:: ulong acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - - Compute the order of a mod q. - -.. function:: ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) - -.. function:: ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - - Compute the conductor of a mod q, that is the smallest r dividing q such - that a corresponds to an element defined modulo r. - -.. function:: ulong acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) - -.. function:: int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - - Compute the parity of a mod q, which is the parity of the corresponding - Dirichlet character. - Character type ------------------------------------------------------------------------------- @@ -191,13 +168,44 @@ Character type Sets *chi* to the Dirichlet character of Conrey index *x*. Character properties -............................................................................... +------------------------------------------------------------------------------- -.. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) +As a consequence of the Conrey numbering, all these numbers are available at the +level off *number* and *index*, and for *char*. +No discrete log computation is performed. + +.. function:: ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) + + return the number of primitive elements in *G*. + +.. function:: ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) + +.. function:: ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) + +.. function:: ulong acb_dirichlet_char_conductor(const acb_dirichlet_char_t chi) + + return the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` + such `\chi_q(a,\cdot)` can be obtained as a character mod `r`. + This number is precomputed for the *char* type. + +.. function:: int acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) + +.. function:: int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) .. function:: int acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) -.. function:: ulong acb_dirichlet_char_conductor(const acb_dirichlet_char_t chi) + return the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that + `\chi_q(a,-1)=(-1)^\lambda`. + This number is precomputed for the *char* type. + +.. function:: ulong acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a) + +.. function:: int acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) + +.. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) + + return the order of `\chi_q(a,\cdot)` which is the order of `a\nmod q`. + This number is precomputed for the *char* type. Character evaluation ------------------------------------------------------------------------------- @@ -206,6 +214,12 @@ The image of a Dirichlet character is a finite cyclic group. Dirichlet character evaluations are either exponents in this group, or an *acb_t* root of unity. +.. function:: ulong acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const acb_dirichlet_conrey_t x) + +.. function:: ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) + + compute that value `\chi(a)` as the exponent mod the order of `\chi`. + .. function:: void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) Sets *res* to `\chi(n)`, the value of the Dirichlet character *chi* @@ -213,13 +227,49 @@ unity. There are no restrictions on *n*. +Vector evaluation +------------------------------------------------------------------------------- + +.. function:: void acb_dirichlet_ui_chi_vec(ulong * v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) + + compute the list of exponent values *v[k]* for `0\leq k < nv` + +.. function:: void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec) + + compute the *nv* first Dirichlet values + +Operations +------------------------------------------------------------------------------- + +.. function:: void acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) + +.. function:: void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) + + multiply two characters in the same group + +.. function:: void acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n) + + take the power of some character + Gauss and Jacobi sums ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + compute the Gauss sum + + .. math:: + + G_q(a) = \sum_{x \mod q} \chi_q(a, x)e^{\frac{2i\pi x}q} + .. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) + compute the Jacobi sum + + .. math:: + + J_q(a,b) = \sum_{x \mod q} \chi_q(a, x)\chi_q(b, 1-x) + Euler products ------------------------------------------------------------------------------- From 3a5b17e5f6da8bcaea84ce2ca65667318110f679 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 21 Jul 2016 18:43:52 +0200 Subject: [PATCH 049/139] some documentation + syntax --- acb_dirichlet.h | 69 +++++++++++++++++++++----- acb_dirichlet/chi_theta_arb.c | 27 +++++----- acb_dirichlet/power.c | 7 ++- acb_dirichlet/powers_init.c | 2 + acb_dirichlet/si_poly_evaluate.c | 1 + acb_dirichlet/theta_length.c | 20 ++++---- acb_dirichlet/ui_theta_arb.c | 39 +++++++++++++++ doc/source/acb_dirichlet.rst | 84 ++++++++++++++++++++++++++++++++ 8 files changed, 209 insertions(+), 40 deletions(-) create mode 100644 acb_dirichlet/ui_theta_arb.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index ba134b3e..f73fd2c8 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -1,15 +1,31 @@ -/* +/*============================================================================= + * + * + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ +******************************************************************************/ #ifndef ACB_DIRICHLET_H #define ACB_DIRICHLET_H @@ -108,6 +124,7 @@ int acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_c int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); +ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); @@ -196,15 +213,16 @@ void acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb typedef struct { ulong order; - acb_ptr z; - ulong m; - ulong M; - acb_ptr Z; + acb_t z; + slong size; + slong depth; + acb_ptr * Z; } acb_dirichlet_powers_struct; typedef acb_dirichlet_powers_struct acb_dirichlet_powers_t[1]; +void _acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong size, slong depth, slong prec); void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec); void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t); void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec); @@ -215,12 +233,15 @@ void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_diric void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec); void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); +void acb_dirichlet_qseries_eval_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec); ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec); ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec); void acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); void acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); -void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t x, slong prec); + +void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); +void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); @@ -232,6 +253,28 @@ void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec); + +/* Discrete Fourier Transform */ + +void acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec); +void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec); +void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); + +void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); +void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); + +ACB_DIRICHLET_INLINE void +acb_vec_printd(acb_srcptr vec, slong len, slong digits) +{ + slong i; + for (i = 0; i < len; i++) + acb_printd(vec + i, digits), flint_printf("\n"); +} + #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index 3b7450a4..e58c8813 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -26,16 +26,16 @@ #include "acb_dirichlet.h" #include "acb_poly.h" -/* x = Pi / q * t^2 */ +/* q(t) = Pi / q * t^2 */ static void -acb_dirichlet_arb_theta_argt(arb_t x, ulong q, const arb_t t, slong prec) +acb_dirichlet_arb_theta_xt(arb_t xt, ulong q, const arb_t t, slong prec) { - arb_const_pi(x, prec); - arb_div_ui(x, x, q, prec); - arb_mul(x, x, t, prec); - arb_mul(x, x, t, prec); - arb_neg(x, x); - arb_exp(x, x, prec); + arb_const_pi(xt, prec); + arb_div_ui(xt, xt, q, prec); + arb_mul(xt, xt, t, prec); + arb_mul(xt, xt, t, prec); + arb_neg(xt, xt); + arb_exp(xt, xt, prec); } void @@ -43,7 +43,7 @@ acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_ { slong len; ulong * a; - arb_t x; + arb_t xt; acb_dirichlet_powers_t z; len = acb_dirichlet_theta_length(G->q, t, prec); @@ -52,11 +52,12 @@ acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_ acb_dirichlet_ui_chi_vec(a, G, chi, len); acb_dirichlet_powers_init(z, chi->order.n, len, prec); - arb_init(x); - acb_dirichlet_arb_theta_argt(x, G->q, t, prec); - acb_dirichlet_arb_theta_naive(res, x, chi->parity, a, z, len, prec); + arb_init(xt); + acb_dirichlet_arb_theta_xt(xt, G->q, t, prec); + /* TODO: switch to theta smallorder at some point */ + acb_dirichlet_arb_theta_naive(res, xt, chi->parity, a, z, len, prec); - arb_clear(x); + arb_clear(xt); flint_free(a); acb_dirichlet_powers_clear(z); } diff --git a/acb_dirichlet/power.c b/acb_dirichlet/power.c index 55c54c37..60c358c8 100644 --- a/acb_dirichlet/power.c +++ b/acb_dirichlet/power.c @@ -26,15 +26,14 @@ #include "acb_dirichlet.h" #include "acb_poly.h" -/* assume won't be modified */ void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec) { if (n < t->m) { - /* FIXME: I do not want to copy: is this all right? */ - *z = *(t->z + n); - /* acb_set(z, t->z + n); */ + /* TODO: could avoid copy ? line below does not work + z = *(t->z + n); */ + acb_set(z, t->z + n); } else { diff --git a/acb_dirichlet/powers_init.c b/acb_dirichlet/powers_init.c index a6b70481..57d4531a 100644 --- a/acb_dirichlet/powers_init.c +++ b/acb_dirichlet/powers_init.c @@ -32,6 +32,7 @@ acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slon ulong m; acb_t zeta; t->order = order; + m = (num == 1) ? 1 : num * (prec / 64 + 1); if (m > order) m = order; @@ -54,4 +55,5 @@ acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slon t->M = 0; t->Z = NULL; } + acb_clear(zeta); } diff --git a/acb_dirichlet/si_poly_evaluate.c b/acb_dirichlet/si_poly_evaluate.c index 42cdd96b..0a10582a 100644 --- a/acb_dirichlet/si_poly_evaluate.c +++ b/acb_dirichlet/si_poly_evaluate.c @@ -25,6 +25,7 @@ #include "acb_dirichlet.h" +/* bsgs evaluation */ void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec) { diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c index 91a7c0e7..f5f66f37 100644 --- a/acb_dirichlet/theta_length.c +++ b/acb_dirichlet/theta_length.c @@ -29,25 +29,25 @@ #define LOG2 0.69314718055 ulong -acb_dirichlet_theta_length_d(ulong q, double x, slong prec) +acb_dirichlet_theta_length_d(ulong q, double t, slong prec) { double a, la; - a = PI / (double)q * x * x; + a = PI / (double)q * t * t; la = (a < .3) ? -log(2*a*(1-a)) : .8; la = ((double)prec * LOG2 + la) / a; return ceil(sqrt(la)+.5); } ulong -acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec) +acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec) { - double dx; + double dt; ulong len; - arf_t ax; - arf_init(ax); - arb_get_lbound_arf(ax, x, 53); - dx = arf_get_d(ax, ARF_RND_DOWN); - len = acb_dirichlet_theta_length_d(q, dx, prec); - arf_clear(ax); + arf_t at; + arf_init(at); + arb_get_lbound_arf(at, t, 53); + dt = arf_get_d(at, ARF_RND_DOWN); + len = acb_dirichlet_theta_length_d(q, dt, prec); + arf_clear(at); return len; } diff --git a/acb_dirichlet/ui_theta_arb.c b/acb_dirichlet/ui_theta_arb.c new file mode 100644 index 00000000..e7ba107b --- /dev/null +++ b/acb_dirichlet/ui_theta_arb.c @@ -0,0 +1,39 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec) +{ + acb_dirichlet_char_t chi; + + acb_dirichlet_char_init(chi, G); + acb_dirichlet_char(chi, G, a); + + acb_dirichlet_chi_theta_arb(res, G, chi, t, prec); + + acb_dirichlet_char_clear(chi); +} diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index a45b001c..c2dff641 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -227,6 +227,42 @@ unity. There are no restrictions on *n*. +Roots of unity +------------------------------------------------------------------------------- + +.. function:: void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) + + sets *res* to `\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. + +.. type:: acb_dirichlet_powers_struct + +.. type:: acb_dirichlet_powers_t + + this structure allows to compute *n* powers of a fixed root of unity of order *m* + using precomputations. Extremal cases are + + - all powers are stored: `O(m)` initialization + storage, `O(n)` eval + + - nothing stored: `O(1)` initialization + storage, `O(\log(m)n)` eval + + - `k` step decomposition: `O(k m^{\frac1k})` init + storage, `O((k-1)n)` eval. + + Currently, only baby-step giant-step decomposition (i.e. `k=2`) + is implemented, allowing to obtain each power using one multiplication. + +.. function:: void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec) + + initialize the powers structure for *num* evaluations of powers of the root of unity + of order *order*. + +.. function:: void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t) + + clears *t*. + +.. function:: void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec) + + sets *z* to `x^n` where *t* contains precomputed powers of `x`. + Vector evaluation ------------------------------------------------------------------------------- @@ -251,6 +287,54 @@ Operations take the power of some character +Theta sums +------------------------------------------------------------------------------- + +We call Theta series of a Dirichlet character the quadratic series + +.. math:: + + \Theta_q(a) = \sum_{n\geq 0} \chi_q(a, n) n^p x^{n^2} + +where `p` is the parity of the character `\chi_q(a,\cdot)`. + +For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define + +.. math:: + + \Theta_q(a,t) = \sum_{n\geq 0} \chi_q(a, n) x(t)^{n^2}. + +.. function:: void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); + +.. function:: void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); + + compute the theta series `\Theta_q(a,t)` for real argument `t>0`. + Beware that if `t<1` the functional equation + + .. math:: + + t \theta(a,t) = \epsilon(\chi) \theta(\frac1a, \frac1t) + + should be used, which is not done automatically (to avoid recomputing the + Gauss sum). + +.. function:: ulong acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec) + + compute the number of terms to be summed in the theta series of argument *t* + so that the tail is less than `2^{-\mathrm{prec}}`. + +.. function:: void acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) + +.. function:: void acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) + + compute the series `\sum n^p z^{a_n} x^{n^2}` for exponent list *a*, + precomputed powers *z* and parity *p* (being 0 or 1). + + The *naive* version sums the series as defined, while the *smallorder* + variant evaluates the series on the quotient ring by a cyclotomic polynomial + before evaluating at the root of unity, ignoring its argument *z*. + + Gauss and Jacobi sums ------------------------------------------------------------------------------- From 941e29330afbcd158bb22f8b1af50936b3ecc31b Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 22 Jul 2016 12:39:17 +0200 Subject: [PATCH 050/139] bug in conrey_exp --- acb_dirichlet/conrey_exp.c | 2 +- acb_dirichlet/conrey_print.c | 4 +++- acb_dirichlet/test/t-conrey.c | 45 ++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/acb_dirichlet/conrey_exp.c b/acb_dirichlet/conrey_exp.c index af268814..d85d0f6c 100644 --- a/acb_dirichlet/conrey_exp.c +++ b/acb_dirichlet/conrey_exp.c @@ -29,7 +29,7 @@ ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { ulong k, n = 1; - for (k = G->neven; k < G->num; k++) + for (k = 0; k < G->num; k++) n = nmod_mul(n, nmod_pow_ui(G->generators[k], x->log[k], G->mod), G->mod); x->n = n; return n; diff --git a/acb_dirichlet/conrey_print.c b/acb_dirichlet/conrey_print.c index 8a702c69..6a4e0b6d 100644 --- a/acb_dirichlet/conrey_print.c +++ b/acb_dirichlet/conrey_print.c @@ -28,9 +28,11 @@ void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) { - int k; + slong k; if (G->num) flint_printf("[%wu", x->log[0]); + else + flint_printf("["); for (k = 1; k < G->num; k++) flint_printf(", %wu", x->log[k]); flint_printf("]"); diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 0d53b511..7dadf2d7 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -37,7 +37,7 @@ int main() for (iter = 0; iter < 3000; iter++) { acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; + acb_dirichlet_conrey_t x, y; ulong q, n, k, sum; long ref; /*int * bits;*/ @@ -47,6 +47,7 @@ int main() acb_dirichlet_group_init(G, q); acb_dirichlet_conrey_init(x, G); + acb_dirichlet_conrey_init(y, G); /* check group size and elements */ acb_dirichlet_conrey_one(x, G); @@ -109,7 +110,49 @@ int main() abort(); } + + /* some random elements, check log and exp */ + for (n = 0; n < 30; n++) + { + slong k; + ulong m; + for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); + acb_dirichlet_conrey_log(x, G, m); + + if (m != acb_dirichlet_conrey_exp(x, G)) + { + flint_printf("FAIL: conrey log and exp\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("conrey = "); + acb_dirichlet_conrey_print(G, x); + flint_printf("\n\nnumber = %wu\n\n", x->n); + abort(); + } + + for (k = 0; k < G->num; k++) + x->log[k] = n_randint(state, G->P[k].phi); + + m = acb_dirichlet_conrey_exp(x, G); + acb_dirichlet_conrey_log(y, G, m); + + if (!acb_dirichlet_conrey_eq(G, x, y)) + { + flint_printf("FAIL: conrey log and exp\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("conrey = "); + acb_dirichlet_conrey_print(G, x); + flint_printf("m = %wu\n\n", m); + flint_printf("log = "); + acb_dirichlet_conrey_print(G, y); + flint_printf("\n\nnumber = %wu\n\n", y->n); + abort(); + } + + } + acb_dirichlet_conrey_clear(x); + acb_dirichlet_conrey_clear(y); acb_dirichlet_group_clear(G); } From 2b1837467cd1095d334e864a30e343433806c0ec Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 22 Jul 2016 16:23:09 +0200 Subject: [PATCH 051/139] improve powers struct --- acb_dirichlet/arb_theta_smallorder.c | 2 +- acb_dirichlet/chi_theta_arb.c | 19 ++++++++--- acb_dirichlet/power.c | 23 +++++++------ acb_dirichlet/powers_clear.c | 10 ++++-- acb_dirichlet/powers_init.c | 48 ++++++++++++++++------------ 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/acb_dirichlet/arb_theta_smallorder.c b/acb_dirichlet/arb_theta_smallorder.c index f70ccd76..0f2930a1 100644 --- a/acb_dirichlet/arb_theta_smallorder.c +++ b/acb_dirichlet/arb_theta_smallorder.c @@ -68,7 +68,7 @@ acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const u } /* now Hörner */ - _acb_poly_evaluate(res, t, order, z->z + 1, prec); + _acb_poly_evaluate(res, t, order, z->z, prec); _acb_vec_clear(t, order); arb_clear(xk2); diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index e58c8813..aa14e0bc 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -47,17 +47,28 @@ acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_ acb_dirichlet_powers_t z; len = acb_dirichlet_theta_length(G->q, t, prec); - a = flint_malloc(len * sizeof(ulong)); acb_dirichlet_ui_chi_vec(a, G, chi, len); - acb_dirichlet_powers_init(z, chi->order.n, len, prec); arb_init(xt); acb_dirichlet_arb_theta_xt(xt, G->q, t, prec); + + /* TODO: tune this limit */ + if (chi->order.n < 30) + { + _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); + acb_dirichlet_arb_theta_smallorder(res, xt, chi->parity, a, z, len, prec); + acb_dirichlet_powers_clear(z); + } + else + { + acb_dirichlet_powers_init(z, chi->order.n, len, prec); + acb_dirichlet_arb_theta_naive(res, xt, chi->parity, a, z, len, prec); + acb_dirichlet_powers_clear(z); + } + /* TODO: switch to theta smallorder at some point */ - acb_dirichlet_arb_theta_naive(res, xt, chi->parity, a, z, len, prec); arb_clear(xt); flint_free(a); - acb_dirichlet_powers_clear(z); } diff --git a/acb_dirichlet/power.c b/acb_dirichlet/power.c index 60c358c8..1f7be4fa 100644 --- a/acb_dirichlet/power.c +++ b/acb_dirichlet/power.c @@ -29,23 +29,22 @@ void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec) { - if (n < t->m) + if (!t->depth) { - /* TODO: could avoid copy ? line below does not work - z = *(t->z + n); */ - acb_set(z, t->z + n); + acb_pow_ui(z, t->z, n, prec); } else { - ulong q, r; - q = n / t->m; - r = n % t->m; - if (q >= t->M) + slong k; + ulong r; + r = n % t->size; + n = n / t->size; + acb_set(z, t->Z[0] + r); + for (k = 1; k < t->depth && n; k++) { - flint_printf("acb_dirichlet_power: power %wu not available " - "in table of size %wu * %wu.", n, t->m, t->M); - abort(); + r = n % t->size; + n = n / t->size; + acb_mul(z, z, t->Z[k] + r, prec); } - acb_mul(z, t->Z + q, t->z + r, prec); } } diff --git a/acb_dirichlet/powers_clear.c b/acb_dirichlet/powers_clear.c index 3417cd34..b84f4679 100644 --- a/acb_dirichlet/powers_clear.c +++ b/acb_dirichlet/powers_clear.c @@ -29,7 +29,11 @@ void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t) { - _acb_vec_clear(t->z, t->m); - if (t->M) - _acb_vec_clear(t->Z, t->M); + slong k; + + for (k = 0; k < t->depth; k++) + _acb_vec_clear(t->Z[k], t->size); + + flint_free(t->Z); + acb_clear(t->z); } diff --git a/acb_dirichlet/powers_init.c b/acb_dirichlet/powers_init.c index 57d4531a..c43040e9 100644 --- a/acb_dirichlet/powers_init.c +++ b/acb_dirichlet/powers_init.c @@ -27,33 +27,39 @@ #include "acb_poly.h" void -acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec) +_acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong size, slong depth, slong prec) { - ulong m; - acb_t zeta; + slong k; t->order = order; - - m = (num == 1) ? 1 : num * (prec / 64 + 1); - if (m > order) - m = order; - t->m = m; - - acb_init(zeta); - acb_dirichlet_nth_root(zeta, order, prec); - t->z = _acb_vec_init(m); - _acb_vec_set_powers(t->z, zeta, m, prec); - - if (order > m) + acb_init(t->z); + acb_dirichlet_nth_root(t->z, order, prec); + t->size = size; + t->depth = depth; + if (depth) { - t->M = (order / m) + 1; - t->Z = _acb_vec_init(t->M); - acb_pow_ui(zeta, zeta, m, prec); - _acb_vec_set_powers(t->Z, zeta, t->M, prec); + acb_struct * z; + z = t->z + 0; + t->Z = flint_malloc(depth * sizeof(acb_ptr)); + for (k = 0; k < depth; k++) + { + t->Z[k] = _acb_vec_init(size); + _acb_vec_set_powers(t->Z[k], z, size, prec); + z = t->Z[k] + 1; + } } else { - t->M = 0; t->Z = NULL; } - acb_clear(zeta); +} + +void +acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec) +{ + slong size, depth; + + depth = (num > order) ? 1 : n_flog(order, num); + size = n_root(order, depth) + 1; + + _acb_dirichlet_powers_init(t, order, size, depth, prec); } From f93ab4fc37cb3e7ebf7889318d828956751b3a76 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 26 Jul 2016 22:29:02 +0200 Subject: [PATCH 052/139] refactor theta and start mellin --- acb_dirichlet/arb_theta_smallorder.c | 1 + acb_dirichlet/chi_theta_arb.c | 108 ++++++++++++++++++++++----- 2 files changed, 91 insertions(+), 18 deletions(-) diff --git a/acb_dirichlet/arb_theta_smallorder.c b/acb_dirichlet/arb_theta_smallorder.c index 0f2930a1..95c598cc 100644 --- a/acb_dirichlet/arb_theta_smallorder.c +++ b/acb_dirichlet/arb_theta_smallorder.c @@ -75,3 +75,4 @@ acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const u arb_clear(x2); arb_clear(dx); } + diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index aa14e0bc..3a0e60b8 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -26,7 +26,7 @@ #include "acb_dirichlet.h" #include "acb_poly.h" -/* q(t) = Pi / q * t^2 */ +/* x(t) = exp(-Pi / q * t^2) */ static void acb_dirichlet_arb_theta_xt(arb_t xt, ulong q, const arb_t t, slong prec) { @@ -38,37 +38,109 @@ acb_dirichlet_arb_theta_xt(arb_t xt, ulong q, const arb_t t, slong prec) arb_exp(xt, xt, prec); } +void +acb_dirichlet_chi_theta_arb_smallorder(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +{ + ulong * a; + acb_dirichlet_powers_t z; + + a = flint_malloc(len * sizeof(ulong)); + acb_dirichlet_ui_chi_vec(a, G, chi, len); + + _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); + acb_dirichlet_arb_theta_smallorder(res, xt, chi->parity, a, z, len, prec); + acb_dirichlet_powers_clear(z); + + flint_free(a); +} + +void +acb_dirichlet_chi_theta_arb_series(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +{ + acb_ptr a; + a = _acb_vec_init(len); + acb_dirichlet_chi_vec(a, G, chi, len, prec); + if (chi->parity) + { + slong k; + for (k = 2; k < len; k++) + acb_mul_si(a + k, a + k, k, prec); + } + acb_dirichlet_qseries_eval_arb(res, a, xt, len, prec); + _acb_vec_clear(a, len); +} + +void +acb_dirichlet_vec_mellin_series(acb_ptr res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong len, const arb_t t, slong n, slong prec) +{ + slong k; + arb_t tk, xt, stk, st; + acb_ptr a; + a = _acb_vec_init(len); + acb_dirichlet_chi_vec(a, G, chi, len, prec); + if (chi->parity) + { + for (k = 2; k < len; k++) + acb_mul_si(a + k, a + k, k, prec); + } + arb_init(tk); + arb_init(xt); + arb_init(st); + arb_init(stk); + + arb_sqrt(st, t, prec); + arb_one(tk); + arb_one(stk); + for (k = 0; k < n; k++) + { + acb_dirichlet_arb_theta_xt(xt, G->q, tk, prec); + /* TODO: reduce len */ + acb_dirichlet_qseries_eval_arb(res + k, a, xt, len, prec); + acb_mul_arb(res + k, res + k, stk, prec); + arb_mul(tk, tk, t, prec); + arb_mul(stk, stk, st, prec); + } + arb_clear(xt); + arb_clear(tk); + arb_clear(stk); + arb_clear(st); + _acb_vec_clear(a, len); +} + +void +acb_dirichlet_chi_theta_arb_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +{ + ulong * a; + acb_dirichlet_powers_t z; + + a = flint_malloc(len * sizeof(ulong)); + acb_dirichlet_ui_chi_vec(a, G, chi, len); + + acb_dirichlet_powers_init(z, chi->order.n, len, prec); + + acb_dirichlet_arb_theta_naive(res, xt, chi->parity, a, z, len, prec); + + acb_dirichlet_powers_clear(z); + flint_free(a); +} + + void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) { slong len; - ulong * a; arb_t xt; - acb_dirichlet_powers_t z; len = acb_dirichlet_theta_length(G->q, t, prec); - a = flint_malloc(len * sizeof(ulong)); - acb_dirichlet_ui_chi_vec(a, G, chi, len); arb_init(xt); acb_dirichlet_arb_theta_xt(xt, G->q, t, prec); /* TODO: tune this limit */ if (chi->order.n < 30) - { - _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); - acb_dirichlet_arb_theta_smallorder(res, xt, chi->parity, a, z, len, prec); - acb_dirichlet_powers_clear(z); - } + acb_dirichlet_chi_theta_arb_smallorder(res, G, chi, xt, len, prec); else - { - acb_dirichlet_powers_init(z, chi->order.n, len, prec); - acb_dirichlet_arb_theta_naive(res, xt, chi->parity, a, z, len, prec); - acb_dirichlet_powers_clear(z); - } - - /* TODO: switch to theta smallorder at some point */ + acb_dirichlet_chi_theta_arb_naive(res, G, chi, xt, len, prec); arb_clear(xt); - flint_free(a); } From 8fe199324953776d99150a1462fd8a9dd9d60000 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 27 Jul 2016 16:54:50 +0200 Subject: [PATCH 053/139] simple test for l functions --- acb_dirichlet/{l.c => l_hurwitz.c} | 0 acb_dirichlet/test/t-l.c | 157 +++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) rename acb_dirichlet/{l.c => l_hurwitz.c} (100%) create mode 100644 acb_dirichlet/test/t-l.c diff --git a/acb_dirichlet/l.c b/acb_dirichlet/l_hurwitz.c similarity index 100% rename from acb_dirichlet/l.c rename to acb_dirichlet/l_hurwitz.c diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c new file mode 100644 index 00000000..65dc395d --- /dev/null +++ b/acb_dirichlet/test/t-l.c @@ -0,0 +1,157 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +#define nq 5 +#define nx 3 + +int main() +{ + + slong i, j; + ulong q[nq] = {3, 5, 61, 91, 800}; + ulong m[nq] = {2, 4, 11, 2, 3}; + slong prec = 150; + + acb_ptr x; + /* cannot test at s = 1 with hurwitz */ + const char * x_r[nx] = { "1", "0.5", "0.5" }; + const char * x_i[nx] = { "1", "0", "6" }; + + acb_t ref, res; + /* + default(realprecision, 54) + X = [ 1 + I, 1/2, 1/2 + 6 * I ] + C = [Mod(2,3),Mod(4,5),Mod(11,61),Mod(2,91),Mod(3,800)] + v = concat([ [lfun(c,x) | x<-X] | c<-C]) + apply(z->printf("\"%s\",\n",real(z)),v) + apply(z->printf("\"%s\",\n",imag(z)),v) + */ + const char * ref_r[nq * nx] = { + "0.655527984002548033786648216345221087939439503905627469", + "0.480867557696828626181220063235589877776829730832371863", + "1.56831301727577320813799211138797101541772722814204757", + "0.521271244517346991221550773660594765406476858135844321", + "0.231750947504015755883383661760877226427886696409005898", + "0.275543455389521803395512886745330595086898302178508437", + "0.598221809458540554839300433683735304093606595684903281", + "0.489264190003695740292779374874163221990017067040417393", + "0.573331076412428980263984182365365715292560207445592018", + "0.510279695870740409778738767334484809708615155539404548", + "0.635626509594367380604827545000418331455019188562281349", + "0.129304857274642475564179442785425797926079767522671163", + "1.18088858810025653590356481638012816019876881487868657", + "2.17175778983760437737667738885959799183430688287297767", + "3.41568550810774629867945639900431994221065497147578087" + }; + const char * ref_i[nq * nx] = { + "0.220206044893215842652155131408935133596486560067476474", + "0", + "-0.969458654385732175077973304161399773236957587792986099", + "0.354614573267731219242838516784605303288232150760467423", + "0", + "-0.995392028773643947872231871832838543767598301887892796", + "1.04370497561090171487193145841005574472705644411957863", + "-0.108902811943905225853677097712717212629591264759957602", + "-0.232114369998608907337769019848201890558327186146689311", + "-0.133300066189980774635445078240315148544665020358019145", + "0.0119464572932630291870372694406253796888930803905106876", + "-0.567660589679294457801153713636532209809112025502518666", + "-0.654079942571300523223917775358845549990877148918886474", + "0.970337207245832214408380510793679653538607483205616894", + "-1.43652482351673593824956935036654893593947145947637807" + }; + + flint_printf("l...."); + fflush(stdout); + + x = _acb_vec_init(nx); + + for (j = 0; j < nx; j++) + { + if (arb_set_str(acb_realref(x + j), x_r[j], prec) || + arb_set_str(acb_imagref(x + j), x_i[j], prec) ) + { + flint_printf("error while setting x[%ld] <- %s+I*%s\n", + j, x_r[j], x_i[j]); + abort(); + } + + } + + acb_init(ref); + acb_init(res); + + for (i = 0; i < nq; i++) + { + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi; + + acb_dirichlet_group_init(G, q[i]); + acb_dirichlet_char_init(chi, G); + + acb_dirichlet_char(chi, G, m[i]); + + for (j = 0; j < nx; j++) + { + + if (arb_set_str(acb_realref(ref), ref_r[i * nx + j], prec - 10) || + arb_set_str(acb_imagref(ref), ref_i[i * nx + j], prec - 10) ) + { + flint_printf("error while setting ref <- %s+I*%s\n", + ref_r[i * nx + j], ref_i[i * nx + j]); + abort(); + } + + acb_dirichlet_l_hurwitz(res, x + j, G, chi, prec + 10); + + if (!acb_contains(ref, res)) + { + flint_printf("FAIL:\n\n"); + flint_printf("q = %wu\n", q[i]); + flint_printf("m = %wu\n", m[i]); + flint_printf("x = "); + acb_printd(x, 54); + flint_printf("\nref = "); + acb_printd(ref, 54); + flint_printf("\nl(chi,x) = "); + acb_printd(res, 54); + flint_printf("\n\n"); + abort(); + } + + } + acb_dirichlet_char_clear(chi); + acb_dirichlet_group_clear(G); + } + acb_clear(ref); + acb_clear(res); + _acb_vec_clear(x, nx); + + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} From 76cc9e9b8bd9a7693fbd7dce03576fa3a7a8fbdd Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 2 Aug 2016 16:18:38 +0200 Subject: [PATCH 054/139] add dft -- first version --- acb_dirichlet.h | 15 +++++ acb_dirichlet/dft_fast.c | 131 +++++++++++++++++++++++++++++++++++++ acb_dirichlet/dft_pol.c | 55 ++++++++++++++++ acb_dirichlet/test/t-dft.c | 73 +++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 acb_dirichlet/dft_fast.c create mode 100644 acb_dirichlet/dft_pol.c create mode 100644 acb_dirichlet/test/t-dft.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index f73fd2c8..e1c27225 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -275,6 +275,21 @@ acb_vec_printd(acb_srcptr vec, slong len, slong digits) acb_printd(vec + i, digits), flint_printf("\n"); } +/* Discrete Fourier Transform */ + +acb_ptr acb_roots_init(slong len, slong prec); +void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec); +void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec); + +ACB_DIRICHLET_INLINE void +acb_vec_printd(acb_srcptr vec, slong len, slong digits) +{ + slong i; + for (i = 0; i < len; i++) + acb_printd(vec + i, digits), flint_printf("\n"); +} + #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c new file mode 100644 index 00000000..cae488e2 --- /dev/null +++ b/acb_dirichlet/dft_fast.c @@ -0,0 +1,131 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* shallow copy */ +static acb_ptr +vec_extract(acb_srcptr v, slong step, slong len) +{ + slong k; + acb_ptr res; + res = flint_malloc(len * sizeof(acb_struct)); + for (k = 0; k < len; k++) + { + res[k] = v[0]; + v += step; + } + return res; +} +void +_acb_dft_base(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong n, slong prec) +{ + acb_ptr v1, z1; + v1 = vec_extract(v, dv, n); + z1 = vec_extract(z, dz, n); + _acb_dirichlet_dft_pol(w, v1, z1, n, prec); + flint_free(v1); + flint_free(z1); +} + +typedef struct +{ + slong num; + slong n; + slong * m; + slong * M; + acb_ptr z; +} +acb_dft_struct; + +typedef acb_dft_struct acb_dft_t[1]; + +void +_acb_dft_fast(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong * cyc, slong * cocyc, slong num, slong prec) +{ + if (num == 1) + { + _acb_dft_base(w, v, dv, z, dz, cyc[0], prec); + } + else + { + slong i, j, m, M; + acb_ptr t, wi; + m = cyc[0]; + M = cocyc[0]; + t = _acb_vec_init(m * M); + wi = w; + for (i = 0; i < m; i++) + { + _acb_dft_fast(wi, v + i * dv, m * dv, z, dz * m, cyc + 1, cocyc + 1, num - 1, prec); + if (i) + { + for (j = 1; j < M; j++) + acb_mul(wi + j, wi + j, z + dz * i * j, prec); + } + wi += M; + } + /* after first pass */ + for (j = 0; j < M; j++) + _acb_dft_base(t + m * j, w + j, M, z, dz * M, m, prec); + /* reorder */ + for (i = 0; i < m; i++) + for (j = 0; j < M; j++) + w[j + M * i] = t[i + m * j]; + _acb_vec_clear(t, m * M); + } +} + +void +acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec) +{ + slong i, j, num; + n_factor_t fac; + slong * cyc, * cocyc; + acb_ptr z; + + z = acb_roots_init(len, prec); + + n_factor_init(&fac); + n_factor(&fac, len, 0); + num = 0; + for (i = 0; i < fac.num; i++) + num += fac.exp[i]; + cyc = flint_malloc(num * sizeof(slong)); + cocyc = flint_malloc(num * sizeof(slong)); + + num = 0; + for (i = 0; i < fac.num; i++) + { + for (j = 0; j < fac.exp[i]; j++) + { + cyc[num] = fac.p[i]; + cocyc[num] = (len /= cyc[num]); + num++; + } + } + + _acb_dft_fast(w, v, 1, z, 1, cyc, cocyc, num, prec); +} diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c new file mode 100644 index 00000000..d67b0439 --- /dev/null +++ b/acb_dirichlet/dft_pol.c @@ -0,0 +1,55 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_poly.h" +#include "acb_dirichlet.h" + +acb_ptr +acb_roots_init(slong len, slong prec) +{ + acb_t zeta; + acb_ptr z; + acb_init(zeta); + acb_dirichlet_nth_root(zeta, len, prec); + z = _acb_vec_init(len); + _acb_vec_set_powers(z, zeta, len, prec); + acb_clear(zeta); + return z; +} + +void +_acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec) +{ + _acb_poly_evaluate_vec_fast(w, v, len, z, len, prec); +} + +void +acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec) +{ + acb_ptr z; + z = acb_roots_init(len, prec); + _acb_dirichlet_dft_pol(w, v, z, len, prec); + _acb_vec_clear(z, len); +} diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c new file mode 100644 index 00000000..246f0a75 --- /dev/null +++ b/acb_dirichlet/test/t-dft.c @@ -0,0 +1,73 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int main() +{ + + slong k; + slong prec = 100; + slong nq = 10; + ulong q[10] = { 2, 3, 4, 5, 6, 10, 15, 30, 308, 961}; + + flint_printf("dft...."); + fflush(stdout); + + for (k = 0; k < nq; k++) + { + slong i; + acb_ptr v, w1, w2; + + v = _acb_vec_init(q[k]); + w1 = _acb_vec_init(q[k]); + w2 = _acb_vec_init(q[k]); + + for (i = 0; i < q[k]; i++) + acb_set_si(v + i, i); + + acb_dirichlet_dft_pol(w1, v, q[k], prec); + acb_dirichlet_dft_fast(w2, v, q[k], prec); + + for (i = 0; i < q[k]; i++) + { + if (!acb_overlaps(w1 + i, w2 + i)) + { + flint_printf("differ from index %ld / %ld \n\n",i,q[k]); + flint_printf("pol =\n"); + acb_vec_printd(w1, q[k], 10); + flint_printf("fast =\n"); + acb_vec_printd(w2, q[k], 10); + flint_printf("\n\n"); + abort(); + } + } + + _acb_vec_clear(v, q[k]); + _acb_vec_clear(w1, q[k]); + _acb_vec_clear(w2, q[k]); + } + flint_printf("PASS\n"); +} From 60a65844f6e68db09de73d010aebeae6154cc7ba Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 4 Aug 2016 12:32:33 +0200 Subject: [PATCH 055/139] experimental dft on Dirichlet group, pb with indexing --- acb_dirichlet.h | 15 --- acb_dirichlet/dft.c | 39 ++++++ acb_dirichlet/dft_fast.c | 236 ++++++++++++++++++++++++++++------ acb_dirichlet/l_vec_hurwitz.c | 64 +++++++++ acb_dirichlet/test/t-dft.c | 3 +- acb_dirichlet/test/t-l.c | 60 +++++++++ 6 files changed, 359 insertions(+), 58 deletions(-) create mode 100644 acb_dirichlet/dft.c create mode 100644 acb_dirichlet/l_vec_hurwitz.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index e1c27225..f73fd2c8 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -275,21 +275,6 @@ acb_vec_printd(acb_srcptr vec, slong len, slong digits) acb_printd(vec + i, digits), flint_printf("\n"); } -/* Discrete Fourier Transform */ - -acb_ptr acb_roots_init(slong len, slong prec); -void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec); -void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec); - -ACB_DIRICHLET_INLINE void -acb_vec_printd(acb_srcptr vec, slong len, slong digits) -{ - slong i; - for (i = 0; i < len; i++) - acb_printd(vec + i, digits), flint_printf("\n"); -} - #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/dft.c b/acb_dirichlet/dft.c new file mode 100644 index 00000000..aeeb99bb --- /dev/null +++ b/acb_dirichlet/dft.c @@ -0,0 +1,39 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* dft, use conrey indices */ +void +acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) +{ + slong k, l, * cyc; + cyc = flint_malloc(G->num * sizeof(slong)); + for (k = 0, l = G->num - 1; l >= 0; k++, l--) + cyc[k] = G->P[l].phi; + + acb_dirichlet_dft_prod(w, v, cyc, G->num, prec); + flint_free(cyc); +} diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c index cae488e2..59df21df 100644 --- a/acb_dirichlet/dft_fast.c +++ b/acb_dirichlet/dft_fast.c @@ -25,7 +25,7 @@ #include "acb_dirichlet.h" -/* shallow copy */ +/* shallow extract */ static acb_ptr vec_extract(acb_srcptr v, slong step, slong len) { @@ -52,40 +52,124 @@ _acb_dft_base(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong n typedef struct { - slong num; - slong n; - slong * m; - slong * M; - acb_ptr z; + slong m; + slong M; + slong dv; + acb_srcptr z; + slong dz; } -acb_dft_struct; +dft_cyc_step; -typedef acb_dft_struct acb_dft_t[1]; +typedef struct +{ + slong n; + acb_ptr z; + slong num; + dft_cyc_step * cyc; +} +acb_dft_cyc_struct; + +typedef acb_dft_cyc_struct acb_dft_cyc_t[1]; + +typedef struct +{ + slong m; + slong M; + slong dv; + acb_dft_cyc_t pre; +} +dft_prod_step; + +typedef struct +{ + slong n; + slong num; + dft_prod_step * cyc; +} +acb_dft_prod_struct; + +typedef acb_dft_prod_struct acb_dft_prod_t[1]; void -_acb_dft_fast(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong * cyc, slong * cocyc, slong num, slong prec) +_acb_dirichlet_dft_cyc_init(acb_dft_cyc_t t, slong len, slong dv, slong prec) { + slong i, j, num, dz; + n_factor_t fac; + acb_ptr z; + + t->n = len; + + n_factor_init(&fac); + n_factor(&fac, len, 0); + num = 0; + for (i = 0; i < fac.num; i++) + num += fac.exp[i]; + t->num = num; + t->cyc = flint_malloc(num * sizeof(dft_cyc_step)); + t->z = z = acb_roots_init(t->n, prec); + + num = 0; + dz = 1; + for (i = 0; i < fac.num; i++) + { + for (j = 0; j < fac.exp[i]; j++) + { + slong m = fac.p[i]; + t->cyc[num].m = m; + t->cyc[num].M = (len /= m); + t->cyc[num].dv = dv; + t->cyc[num].z = z; + t->cyc[num].dz = dz; + dv *= m; + dz *= m; + num++; + } + } +} + +static void +acb_dirichlet_dft_cyc_init(acb_dft_cyc_t t, slong len, slong prec) +{ + _acb_dirichlet_dft_cyc_init(t, len, 1, prec); +} + +void +acb_dirichlet_dft_cyc_clear(acb_dft_cyc_t t) +{ + _acb_vec_clear(t->z, t->n); + flint_free(t->cyc); +} + +void +_acb_dft_cyc(acb_ptr w, acb_srcptr v, dft_cyc_step * cyc, slong num, slong prec) +{ + dft_cyc_step c; + if (num == 0) + abort(); /* or just copy v to w */ + c = cyc[0]; if (num == 1) { - _acb_dft_base(w, v, dv, z, dz, cyc[0], prec); + _acb_dft_base(w, v, c.dv, c.z, c.dz, c.m, prec); } else { - slong i, j, m, M; + slong i, j; + slong m = c.m, M = c.M, dv = c.dv, dz = c.dz; + acb_srcptr z = c.z, vi; acb_ptr t, wi; - m = cyc[0]; - M = cocyc[0]; + t = _acb_vec_init(m * M); - wi = w; + wi = w; vi = v; for (i = 0; i < m; i++) { - _acb_dft_fast(wi, v + i * dv, m * dv, z, dz * m, cyc + 1, cocyc + 1, num - 1, prec); + _acb_dft_cyc(wi, vi, cyc + 1, num - 1, prec); if (i) { for (j = 1; j < M; j++) acb_mul(wi + j, wi + j, z + dz * i * j, prec); } wi += M; + vi += dv; } /* after first pass */ for (j = 0; j < M; j++) @@ -98,34 +182,102 @@ _acb_dft_fast(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong * } } +void +acb_dirichlet_dft_cyc_precomp(acb_ptr w, acb_srcptr v, acb_dft_cyc_t t, slong prec) +{ + _acb_dft_cyc(w, v, t->cyc, t->num, prec); +} + void acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec) { - slong i, j, num; - n_factor_t fac; - slong * cyc, * cocyc; - acb_ptr z; - - z = acb_roots_init(len, prec); - - n_factor_init(&fac); - n_factor(&fac, len, 0); - num = 0; - for (i = 0; i < fac.num; i++) - num += fac.exp[i]; - cyc = flint_malloc(num * sizeof(slong)); - cocyc = flint_malloc(num * sizeof(slong)); - - num = 0; - for (i = 0; i < fac.num; i++) - { - for (j = 0; j < fac.exp[i]; j++) - { - cyc[num] = fac.p[i]; - cocyc[num] = (len /= cyc[num]); - num++; - } - } - - _acb_dft_fast(w, v, 1, z, 1, cyc, cocyc, num, prec); + acb_dft_cyc_t t; + acb_dirichlet_dft_cyc_init(t, len, prec); + acb_dirichlet_dft_cyc_precomp(w, v, t, prec); + acb_dirichlet_dft_cyc_clear(t); +} + +void +_acb_dft_prod(acb_ptr w, acb_srcptr v, dft_prod_step * cyc, slong num, slong prec) +{ + dft_prod_step c; + if (num == 0) + abort(); /* or just copy v to w */ + c = cyc[0]; + if (num == 1) + { + acb_dirichlet_dft_cyc_precomp(w, v, c.pre, prec); + } + else + { + slong i, j; + slong m = c.m, M = c.M, dv = c.dv; + acb_srcptr vi; + acb_ptr t, wi; + + t = _acb_vec_init(m * M); + wi = w; vi = v; + for (i = 0; i < m; i++) + { + _acb_dft_prod(wi, vi, cyc + 1, num - 1, prec); + wi += M; + vi += dv; + } + /* after first pass */ + for (j = 0; j < M; j++) + acb_dirichlet_dft_cyc_precomp(t + m * j, w + j, c.pre, prec); + /* reorder */ + for (i = 0; i < m; i++) + for (j = 0; j < M; j++) + w[j + M * i] = t[i + m * j]; + _acb_vec_clear(t, m * M); + } +} + +void +acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, acb_dft_prod_t t, slong prec) +{ + _acb_dft_prod(w, v, t->cyc, t->num, prec); +} + +void +acb_dirichlet_dft_prod_init(acb_dft_prod_t t, slong * cyc, slong num, slong prec) +{ + slong i, len, dv; + + t->num = num; + t->cyc = flint_malloc(num * sizeof(dft_prod_step)); + + len = 1; dv = 1; + for (i = 0; i < num; i++) + len *= cyc[i]; + + for (i = 0; i < num; i++) + { + slong m = cyc[i]; + len /= m; + t->cyc[i].m = m; + t->cyc[i].M = len; + t->cyc[i].dv = dv; + _acb_dirichlet_dft_cyc_init(t->cyc[i].pre, m, len, prec); + dv *= m; + } +} + +void +acb_dirichlet_dft_prod_clear(acb_dft_prod_t t) +{ + slong i; + for (i = 0; i < t->num; i++) + acb_dirichlet_dft_cyc_clear(t->cyc[i].pre); + flint_free(t->cyc); +} + +void +acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) +{ + acb_dft_prod_t t; + acb_dirichlet_dft_prod_init(t, cyc, num, prec); + acb_dirichlet_dft_prod_precomp(w, v, t, prec); + acb_dirichlet_dft_prod_clear(t); } diff --git a/acb_dirichlet/l_vec_hurwitz.c b/acb_dirichlet/l_vec_hurwitz.c new file mode 100644 index 00000000..297e1e0d --- /dev/null +++ b/acb_dirichlet/l_vec_hurwitz.c @@ -0,0 +1,64 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Fredrik Johansson + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, + const acb_dirichlet_group_t G, slong prec) +{ + acb_t a, qs; + acb_ptr zeta, z; + acb_dirichlet_conrey_t cn; + + acb_dirichlet_conrey_init(cn, G); + acb_init(qs); + acb_init(a); + + acb_set_ui(qs, G->q); + acb_neg(a, s); + acb_pow(qs, qs, a, prec); + + zeta = z = _acb_vec_init(G->phi_q); + acb_dirichlet_conrey_one(cn, G); + while (1) { + + acb_set_ui(a, cn->n); + acb_div_ui(a, a, G->q, prec); + acb_hurwitz_zeta(z, s, a, prec); + acb_mul(z, z, qs, prec); + + if (acb_dirichlet_conrey_next(cn, G) == G->num) + break; + z++; + } + + acb_dirichlet_dft_conrey(res, zeta, G, prec); + + acb_dirichlet_conrey_clear(cn); + _acb_vec_clear(zeta, G->phi_q); + acb_clear(qs); + acb_clear(a); +} diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 246f0a75..c8c13c09 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -19,7 +19,7 @@ =============================================================================*/ /****************************************************************************** - Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin ******************************************************************************/ @@ -69,5 +69,6 @@ int main() _acb_vec_clear(w1, q[k]); _acb_vec_clear(w2, q[k]); } + flint_printf("PASS\n"); } diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index 65dc395d..6afade68 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -28,6 +28,63 @@ #define nq 5 #define nx 3 +void +test_dft() +{ + ulong i, q = 15; + slong prec = 100; + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_dirichlet_char_t chi; + acb_t s, z; + acb_ptr v; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_char_init(chi, G); + + acb_init(s); + acb_one(s); + acb_div_si(s, s, 2, prec); + + v = _acb_vec_init(G->phi_q); + + /* all at once */ + acb_dirichlet_l_vec_hurwitz(v, s, G, prec); + + /* check with complete loop */ + + i = 0; + acb_dirichlet_conrey_one(x, G); + while (1) { + + acb_dirichlet_char_conrey(chi, G, x); + acb_dirichlet_l_hurwitz(z, s, G, chi, prec); + + if (!acb_overlaps(z, v + i)) + { + flint_printf("\n L value differ"); + flint_printf("\nL(1/2, %wu) single = ", x->n); + acb_printd(z, 20); + flint_printf("\nL(1/2, %wu) multi = ", x->n); + acb_printd(v + i, 20); + flint_printf("\n\n"); + acb_vec_printd(v, G->phi_q, 10); + flint_printf("\n\n"); + } + + if (acb_dirichlet_conrey_next(x, G) == G->num) + break; + i++; + } + + acb_clear(s); + _acb_vec_clear(v, G->phi_q); + acb_dirichlet_char_clear(chi); + acb_dirichlet_conrey_clear(x); + acb_dirichlet_group_clear(G); +} + int main() { @@ -151,6 +208,9 @@ int main() acb_clear(res); _acb_vec_clear(x, nx); + /* test using dft */ + test_dft(); + flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; From bf8d58cbf22cdb18bed40e96e21d4e8fb924f862 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 4 Aug 2016 15:35:33 +0200 Subject: [PATCH 056/139] change loop order (last component first) --- acb_dirichlet/conrey_next.c | 2 +- acb_dirichlet/conrey_next_primitive.c | 13 +++++++++---- acb_dirichlet/dft.c | 2 +- acb_dirichlet/l_hurwitz.c | 6 ++---- acb_dirichlet/l_vec_hurwitz.c | 6 ++---- acb_dirichlet/profile/p-conrey.c | 4 ++-- acb_dirichlet/test/t-conrey.c | 8 +++----- acb_dirichlet/test/t-gauss.c | 2 +- acb_dirichlet/test/t-jacobi.c | 6 +++--- acb_dirichlet/test/t-l.c | 6 ++---- acb_dirichlet/test/t-thetanull.c | 6 ++---- acb_dirichlet/test/t-vec.c | 6 ++---- acb_dirichlet/ui_chi_vec_loop.c | 4 ++-- 13 files changed, 32 insertions(+), 39 deletions(-) diff --git a/acb_dirichlet/conrey_next.c b/acb_dirichlet/conrey_next.c index c17db899..e715ed93 100644 --- a/acb_dirichlet/conrey_next.c +++ b/acb_dirichlet/conrey_next.c @@ -30,7 +30,7 @@ acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t { /* update index */ int k; - for (k=0; k < G->num; k++) + for (k = G->num - 1; k >= 0; k--) { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] += 1; diff --git a/acb_dirichlet/conrey_next_primitive.c b/acb_dirichlet/conrey_next_primitive.c index 682b9b24..d8a98022 100644 --- a/acb_dirichlet/conrey_next_primitive.c +++ b/acb_dirichlet/conrey_next_primitive.c @@ -30,7 +30,8 @@ acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichle { /* update index avoiding multiples of p except for first component if 8|q */ - ulong k = 0; + slong k = 0; + /* if (G->neven == 2) { x->n = nmod_mul(x->n, G->generators[0], G->mod); @@ -40,14 +41,18 @@ acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichle x->log[0] = 0; k = 1; } - for (; k < G->num ; k++) + */ + for (k = G->num - 1; k >= 0; k--) { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; if (x->log[k] % G->P[k].p == 0) { - x->n = nmod_mul(x->n, G->generators[k], G->mod); - x->log[k]++; + if (k > 0 || G->neven != 2) + { + x->n = nmod_mul(x->n, G->generators[k], G->mod); + x->log[k]++; + } } if (x->log[k] < G->P[k].phi) break; diff --git a/acb_dirichlet/dft.c b/acb_dirichlet/dft.c index aeeb99bb..82ea331d 100644 --- a/acb_dirichlet/dft.c +++ b/acb_dirichlet/dft.c @@ -32,7 +32,7 @@ acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong k, l, * cyc; cyc = flint_malloc(G->num * sizeof(slong)); for (k = 0, l = G->num - 1; l >= 0; k++, l--) - cyc[k] = G->P[l].phi; + cyc[k] = G->P[k].phi; acb_dirichlet_dft_prod(w, v, cyc, G->num, prec); flint_free(cyc); diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index 2fd4cc44..125fa7b9 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -33,7 +33,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, xz = _acb_vec_init(chi->order.n); _acb_vec_set_powers(xz, z, chi->order.n, prec); - while (1) { + do { chin = acb_dirichlet_ui_chi_conrey(G, chi, cn); acb_set_ui(a, cn->n); @@ -42,9 +42,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_addmul(t, xz + chin, u, prec); - if (acb_dirichlet_conrey_next(cn, G) == G->num) - break; - } + } while (acb_dirichlet_conrey_next(cn, G) >= 0); acb_set_ui(u, G->q); acb_neg(a, s); diff --git a/acb_dirichlet/l_vec_hurwitz.c b/acb_dirichlet/l_vec_hurwitz.c index 297e1e0d..160577e8 100644 --- a/acb_dirichlet/l_vec_hurwitz.c +++ b/acb_dirichlet/l_vec_hurwitz.c @@ -43,17 +43,15 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, zeta = z = _acb_vec_init(G->phi_q); acb_dirichlet_conrey_one(cn, G); - while (1) { + do { acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); acb_hurwitz_zeta(z, s, a, prec); acb_mul(z, z, qs, prec); - if (acb_dirichlet_conrey_next(cn, G) == G->num) - break; z++; - } + } while (acb_dirichlet_conrey_next(cn, G) >= 0); acb_dirichlet_dft_conrey(res, zeta, G, prec); diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c index 4c52a062..899758b5 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/acb_dirichlet/profile/p-conrey.c @@ -59,7 +59,7 @@ int main() acb_dirichlet_conrey_one(x, G); n++; - for (; acb_dirichlet_conrey_next(x, G) < G->num; n++); + for (; acb_dirichlet_conrey_next(x, G) >= 0; n++); acb_dirichlet_conrey_clear(x); acb_dirichlet_group_clear(G); } @@ -83,7 +83,7 @@ int main() acb_dirichlet_char_one(chi, G); n++; - for (; acb_dirichlet_char_next(chi, G) < G->num; n++); + for (; acb_dirichlet_char_next(chi, G) >= 0; n++); acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); } diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 7dadf2d7..bc93570d 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -54,7 +54,7 @@ int main() sum = 1; #if 1 - for (n = 1; acb_dirichlet_conrey_next(x, G) < G->num; n++) + for (n = 1; acb_dirichlet_conrey_next(x, G) >= 0; n++) sum += x->n * x->n; #else /* iteration much faster than gcd below */ @@ -71,12 +71,10 @@ int main() /* use http://oeis.org/A053818 to check all elements * are gone through */ ref = (q % 4 == 2) ? -2 : 1; - k = (G->neven == 2) ? 1 : 0; - for (; knum; k++) + for (k = (G->neven == 2); k < G->num; k++) ref = - ref * G->P[k].p; ref = ( G->phi_q * (2 * q * q + ref) ) / 6; - if (n != G->phi_q) { flint_printf("FAIL: group size\n\n"); @@ -98,7 +96,7 @@ int main() continue; acb_dirichlet_conrey_first_primitive(x, G); - for (n = 1; (k=acb_dirichlet_conrey_next_primitive(x, G)) < G->num; n++); + for (n = 1; acb_dirichlet_conrey_next_primitive(x, G) >= 0; n++); ref = acb_dirichlet_number_primitive(G); if (n != ref) diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index a44b345e..a72f72b2 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -81,7 +81,7 @@ int main() abort(); } - if (acb_dirichlet_conrey_next(x, G) == G->num) + if (acb_dirichlet_conrey_next(x, G) < 0) break; } acb_clear(s1); diff --git a/acb_dirichlet/test/t-jacobi.c b/acb_dirichlet/test/t-jacobi.c index e1f18152..5f7dcaec 100644 --- a/acb_dirichlet/test/t-jacobi.c +++ b/acb_dirichlet/test/t-jacobi.c @@ -35,7 +35,7 @@ int main() /* check Jacobi sums */ - for (q = 29*29; q > 1; q = q%2 ? 3*q+1 : q/2) + for (q = 29 * 29; q > 1; q = q%2 ? 3*q+1 : q/2) { slong m1, m2; acb_dirichlet_group_t G; @@ -78,12 +78,12 @@ int main() ); abort(); } - if (acb_dirichlet_char_next(chi2, G) == G->num) + if (acb_dirichlet_char_next(chi2, G) < 0) break; } - if (acb_dirichlet_char_next(chi1, G) == G->num) + if (acb_dirichlet_char_next(chi1, G) < 0) break; } diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index 6afade68..40468922 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -56,7 +56,7 @@ test_dft() i = 0; acb_dirichlet_conrey_one(x, G); - while (1) { + do { acb_dirichlet_char_conrey(chi, G, x); acb_dirichlet_l_hurwitz(z, s, G, chi, prec); @@ -73,10 +73,8 @@ test_dft() flint_printf("\n\n"); } - if (acb_dirichlet_conrey_next(x, G) == G->num) - break; i++; - } + } while (acb_dirichlet_conrey_next(x, G) >= 0); acb_clear(s); _acb_vec_clear(v, G->phi_q); diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index aa2dcae1..78226781 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -84,7 +84,7 @@ int main() acb_init(sum); acb_dirichlet_char_first_primitive(chi, G); - while (1) { + do { ulong m; acb_zero(sum); @@ -119,10 +119,8 @@ int main() flint_printf("\n"); abort(); } + } while (acb_dirichlet_char_next_primitive(chi, G) >= 0); - if (acb_dirichlet_char_next_primitive(chi, G) == G->num) - break; - } _acb_vec_clear(z, G->expo); _arb_vec_clear(t, nv); acb_clear(zeta); diff --git a/acb_dirichlet/test/t-vec.c b/acb_dirichlet/test/t-vec.c index 79cc2cdf..9c094c2b 100644 --- a/acb_dirichlet/test/t-vec.c +++ b/acb_dirichlet/test/t-vec.c @@ -59,7 +59,7 @@ int main() acb_dirichlet_conrey_one(x, G); - while (1) { + do { acb_dirichlet_char_conrey(chi, G, x); @@ -73,9 +73,7 @@ int main() abort(); } - if (acb_dirichlet_conrey_next(x, G) == G->num) - break; - } + } while (acb_dirichlet_conrey_next(x, G) >= 0); flint_free(v1); flint_free(v2); diff --git a/acb_dirichlet/ui_chi_vec_loop.c b/acb_dirichlet/ui_chi_vec_loop.c index 6ad0179c..88eb88e1 100644 --- a/acb_dirichlet/ui_chi_vec_loop.c +++ b/acb_dirichlet/ui_chi_vec_loop.c @@ -41,10 +41,10 @@ acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb t = v[1] = 0; - while ( (j = acb_dirichlet_conrey_next(x, G)) < G->num ) + while ( (j = acb_dirichlet_conrey_next(x, G)) >= 0 ) { /* exponents were modified up to j */ - for (k = 0; k <= j; k++) + for (k = G->num - 1; k >= j; k--) t = nmod_add(t, chi->expo[k], chi->order); if (x->n < nv) From 9441c452ece07597605637beca585147641db887 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 4 Aug 2016 16:32:31 +0200 Subject: [PATCH 057/139] fix dft on group --- acb_dirichlet/dft_fast.c | 16 ++++++-- acb_dirichlet/test/t-dft.c | 75 +++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c index 59df21df..fd92acf1 100644 --- a/acb_dirichlet/dft_fast.c +++ b/acb_dirichlet/dft_fast.c @@ -202,7 +202,10 @@ _acb_dft_prod(acb_ptr w, acb_srcptr v, dft_prod_step * cyc, slong num, slong pre { dft_prod_step c; if (num == 0) + { + flint_printf("error: reached num = 0 in dft_prod\n"); abort(); /* or just copy v to w */ + } c = cyc[0]; if (num == 1) { @@ -221,7 +224,7 @@ _acb_dft_prod(acb_ptr w, acb_srcptr v, dft_prod_step * cyc, slong num, slong pre { _acb_dft_prod(wi, vi, cyc + 1, num - 1, prec); wi += M; - vi += dv; + vi += dv; /* here = M */ } /* after first pass */ for (j = 0; j < M; j++) @@ -237,7 +240,14 @@ _acb_dft_prod(acb_ptr w, acb_srcptr v, dft_prod_step * cyc, slong num, slong pre void acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, acb_dft_prod_t t, slong prec) { - _acb_dft_prod(w, v, t->cyc, t->num, prec); + if (t->num == 0) + { + acb_set(w + 0, v + 0); + } + else + { + _acb_dft_prod(w, v, t->cyc, t->num, prec); + } } void @@ -258,7 +268,7 @@ acb_dirichlet_dft_prod_init(acb_dft_prod_t t, slong * cyc, slong num, slong prec len /= m; t->cyc[i].m = m; t->cyc[i].M = len; - t->cyc[i].dv = dv; + t->cyc[i].dv = len; _acb_dirichlet_dft_cyc_init(t->cyc[i].pre, m, len, prec); dv *= m; } diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index c8c13c09..90278fd8 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -36,6 +36,7 @@ int main() flint_printf("dft...."); fflush(stdout); + /* cyclic dft */ for (k = 0; k < nq; k++) { slong i; @@ -64,11 +65,83 @@ int main() abort(); } } - + _acb_vec_clear(v, q[k]); _acb_vec_clear(w1, q[k]); _acb_vec_clear(w2, q[k]); } + /* Dirichlet group DFT */ + for (k = 0; k < nq; k++) + { + slong i, j, len; + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x, y; + acb_t chiy; + acb_ptr v, w1, w2; + + acb_dirichlet_group_init(G, q[k]); + + len = G->phi_q; + v = _acb_vec_init(len); + w1 = _acb_vec_init(len); + w2 = _acb_vec_init(len); + + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_conrey_one(x, G); + for (i = 0; i < len; i++) + { + acb_set_si(v + i, x->n); + acb_dirichlet_conrey_next(x, G); + } + + /* naive */ + acb_init(chiy); + acb_dirichlet_conrey_init(y, G); + acb_dirichlet_conrey_one(x, G); + for (i = 0; i < len; i++) + { + acb_zero(w1 + i); + acb_dirichlet_conrey_one(y, G); + for (j = 0; j < len; j++) + { + acb_dirichlet_pairing_conrey(chiy, G, x, y, prec); + acb_addmul(w1 + i, chiy, v + j, prec); + acb_dirichlet_conrey_next(y, G); + } + acb_dirichlet_conrey_next(x, G); + } + acb_clear(chiy); + acb_dirichlet_conrey_clear(y); + acb_dirichlet_conrey_clear(x); + + /* dft */ + acb_dirichlet_dft_conrey(w2, v, G, prec); + + for (i = 0; i < len; i++) + { + if (!acb_overlaps(w1 + i, w2 + i)) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu\n", q[k]); + flint_printf("v [size %wu]\n", len); + acb_vec_printd(v, len, 10); + flint_printf("\nDFT differ from index %ld / %ld \n", i, len); + flint_printf("\nnaive =\n"); + acb_vec_printd(w1, len, 10); + flint_printf("\nfast =\n"); + acb_vec_printd(w2, len, 10); + flint_printf("\n\n"); + abort(); + } + } + + _acb_vec_clear(v, len); + _acb_vec_clear(w1, len); + _acb_vec_clear(w2, len); + + acb_dirichlet_group_clear(G); + } + flint_printf("PASS\n"); } From 675d4485cd946888a2bc72dd52054e60e2906201 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 4 Aug 2016 18:56:27 +0200 Subject: [PATCH 058/139] fix next primitive and index thetanull accordingly --- acb_dirichlet/conrey_next_primitive.c | 23 +++++++++++++----- acb_dirichlet/gauss_sum_theta.c | 4 ++-- acb_dirichlet/test/t-conrey.c | 17 ++++++++++++++ acb_dirichlet/test/t-dft.c | 2 +- acb_dirichlet/test/t-l.c | 1 + acb_dirichlet/test/t-thetanull.c | 34 +++++++++++++++++++++++++-- 6 files changed, 70 insertions(+), 11 deletions(-) diff --git a/acb_dirichlet/conrey_next_primitive.c b/acb_dirichlet/conrey_next_primitive.c index d8a98022..0157f240 100644 --- a/acb_dirichlet/conrey_next_primitive.c +++ b/acb_dirichlet/conrey_next_primitive.c @@ -30,7 +30,7 @@ acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichle { /* update index avoiding multiples of p except for first component if 8|q */ - slong k = 0; + slong k; /* if (G->neven == 2) { @@ -44,19 +44,30 @@ acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichle */ for (k = G->num - 1; k >= 0; k--) { +#if 1 x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; if (x->log[k] % G->P[k].p == 0) { - if (k > 0 || G->neven != 2) - { - x->n = nmod_mul(x->n, G->generators[k], G->mod); - x->log[k]++; - } + x->n = nmod_mul(x->n, G->generators[k], G->mod); + x->log[k]++; } if (x->log[k] < G->P[k].phi) break; + if (x->log[k] == G->P[k].phi) + x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] = 1; +#else + do { + x->n = nmod_mul(x->n, G->generators[k], G->mod); + x->log[k]++; + } while (x->log[k] % G->P[k].p == 0); + if (x->log[k] < G->P[k].phi) + break; + if (x->log[k] == G->P[k].phi) + x->n = nmod_mul(x->n, G->generators[k], G->mod); + x->log[k] = 1; +#endif } /* return last index modified */ return k; diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index 5c0cb6fc..5a752def 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -33,8 +33,8 @@ acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const ac arb_init(x); - if ((G->q == 300 && (chi->x->n == 271 || chi->x->n == 131)) - || (G->q == 600 && (chi->x->n == 11 || chi->x->n == 91))) + if ((G->q == 300 && (chi->x->n == 71 || chi->x->n == 131)) + || (G->q == 600 && (chi->x->n == 11 || chi->x->n == 491))) { /* or could use l'Hopital rule */ acb_dirichlet_gauss_sum_naive(res, G, chi, prec); diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index bc93570d..858edb79 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -114,6 +114,7 @@ int main() { slong k; ulong m; + for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); acb_dirichlet_conrey_log(x, G, m); @@ -147,6 +148,22 @@ int main() abort(); } + acb_dirichlet_conrey_next_primitive(x, G); + m = x->n; + + if (m != acb_dirichlet_conrey_exp(x, G)) + { + flint_printf("FAIL: conrey number next primitive\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("conrey = "); + acb_dirichlet_conrey_print(G, y); + flint_printf(", m = %wu\n\n", y->n); + flint_printf("next primitive = "); + acb_dirichlet_conrey_print(G, x); + flint_printf(", m = %wu\n\n", m); + flint_printf("exp = %wu\n\n", x->n); + abort(); + } } acb_dirichlet_conrey_clear(x); diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 90278fd8..e613aef2 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -72,7 +72,7 @@ int main() } /* Dirichlet group DFT */ - for (k = 0; k < nq; k++) + for (k = 0; k < nq - 1; k++) { slong i, j, len; acb_dirichlet_group_t G; diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index 40468922..f263d088 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -55,6 +55,7 @@ test_dft() /* check with complete loop */ i = 0; + acb_init(z); acb_dirichlet_conrey_one(x, G); do { diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 78226781..bd35a24e 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -97,8 +97,37 @@ int main() if (v[k] != ACB_DIRICHLET_CHI_NULL) acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); - if ((q == 300 && (chi->x->n == 271 || chi->x->n == 131)) - || (q == 600 && (chi->x->n == 11 || chi->x->n == 91))) + /* compare with function */ + + { + acb_t res; + arb_t t; + acb_init(res); + arb_init(t); + arb_one(t); + acb_dirichlet_chi_theta_arb(res, G, chi, t, prec); + + if (!acb_overlaps(res, sum)) + { + flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); + acb_printd(sum, 10); + flint_printf("\n"); + acb_dirichlet_char_print(G, chi); + flint_printf("\n"); + flint_printf("should be \n"); + acb_printd(res, 10); + flint_printf("\n"); + abort(); + } + + acb_clear(res); + arb_clear(t); + } + + /* check null values */ + + if ((q == 300 && (chi->x->n == 71 || chi->x->n == 131)) + || (q == 600 && (chi->x->n == 11 || chi->x->n == 491))) { if (!acb_contains_zero(sum)) { @@ -119,6 +148,7 @@ int main() flint_printf("\n"); abort(); } + } while (acb_dirichlet_char_next_primitive(chi, G) >= 0); _acb_vec_clear(z, G->expo); From b00fb3ef44c7f31ff6ef10978f06bb8b65b5c212 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 4 Aug 2016 19:00:19 +0200 Subject: [PATCH 059/139] faster thetanull --- acb_dirichlet/test/t-thetanull.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index bd35a24e..01346f5a 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -97,35 +97,6 @@ int main() if (v[k] != ACB_DIRICHLET_CHI_NULL) acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); - /* compare with function */ - - { - acb_t res; - arb_t t; - acb_init(res); - arb_init(t); - arb_one(t); - acb_dirichlet_chi_theta_arb(res, G, chi, t, prec); - - if (!acb_overlaps(res, sum)) - { - flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); - acb_printd(sum, 10); - flint_printf("\n"); - acb_dirichlet_char_print(G, chi); - flint_printf("\n"); - flint_printf("should be \n"); - acb_printd(res, 10); - flint_printf("\n"); - abort(); - } - - acb_clear(res); - arb_clear(t); - } - - /* check null values */ - if ((q == 300 && (chi->x->n == 71 || chi->x->n == 131)) || (q == 600 && (chi->x->n == 11 || chi->x->n == 491))) { From 0ff04a35edeec8929e8d024abe67dd328e5da668 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 5 Aug 2016 16:13:10 +0200 Subject: [PATCH 060/139] forgot qseries source file --- acb_dirichlet/qseries_eval_arb.c | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 acb_dirichlet/qseries_eval_arb.c diff --git a/acb_dirichlet/qseries_eval_arb.c b/acb_dirichlet/qseries_eval_arb.c new file mode 100644 index 00000000..ae657fc2 --- /dev/null +++ b/acb_dirichlet/qseries_eval_arb.c @@ -0,0 +1,57 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +/* assume a[0] = 0 */ +void +acb_dirichlet_qseries_eval_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec) +{ + slong k; + arb_t xk2, dx, x2; + + arb_init(xk2); + arb_init(dx); + arb_init(x2); + + arb_set(dx, x); + arb_set(xk2, dx); + arb_mul(x2, dx, dx, prec); + + acb_mul_arb(res, a + 1, xk2, prec); + + /* TODO: reduce prec */ + for (k = 2; k < len; k++) + { + arb_mul(dx, dx, x2, prec); + arb_mul(xk2, xk2, dx, prec); + acb_addmul_arb(res, a + k, xk2, prec); + } + + arb_clear(xk2); + arb_clear(x2); + arb_clear(dx); +} From 82e0924d3ea0be51d5f33500e263f63adf24d077 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 5 Aug 2016 16:13:40 +0200 Subject: [PATCH 061/139] doc dft --- acb_dirichlet/dft.c | 36 +++++++++++++++++- doc/source/acb_dirichlet.rst | 73 +++++++++++++++++++++++++++++++----- 2 files changed, 98 insertions(+), 11 deletions(-) diff --git a/acb_dirichlet/dft.c b/acb_dirichlet/dft.c index 82ea331d..6caa901c 100644 --- a/acb_dirichlet/dft.c +++ b/acb_dirichlet/dft.c @@ -25,7 +25,7 @@ #include "acb_dirichlet.h" -/* dft, use conrey indices */ +/* dft, lexicographic conrey indexing, array size G->phi_q */ void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) { @@ -37,3 +37,37 @@ acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, acb_dirichlet_dft_prod(w, v, cyc, G->num, prec); flint_free(cyc); } + +/* dft, number indexing, array size G->q */ +void +acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) +{ + ulong i, len; + acb_ptr t1, t2; + acb_dirichlet_conrey_t x; + + len = G->phi_q; + t1 = flint_malloc(len * sizeof(acb_struct)); + + acb_dirichlet_conrey_init(x, G); + acb_dirichlet_conrey_one(x, G); + for (i = 0; i < len; i++) + { + t1[i] = v[x->n]; + acb_dirichlet_conrey_next(x, G); + }; + + t2 = _acb_vec_init(len); + acb_dirichlet_dft_conrey(t2, t1, G, prec); + + acb_dirichlet_conrey_one(x, G); + for (i = 0; i < len; i++) + { + acb_set(w + x->n, t2 + i); + acb_dirichlet_conrey_next(x, G); + }; + + _acb_vec_clear(t2, len); + acb_dirichlet_conrey_clear(x); + flint_free(t1); +} diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index c2dff641..62b834ec 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -287,6 +287,25 @@ Operations take the power of some character +Gauss and Jacobi sums +------------------------------------------------------------------------------- + +.. function:: void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + + compute the Gauss sum + + .. math:: + + G_q(a) = \sum_{x \mod q} \chi_q(a, x)e^{\frac{2i\pi x}q} + +.. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) + + compute the Jacobi sum + + .. math:: + + J_q(a,b) = \sum_{x \mod q} \chi_q(a, x)\chi_q(b, 1-x) + Theta sums ------------------------------------------------------------------------------- @@ -334,25 +353,59 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define variant evaluates the series on the quotient ring by a cyclotomic polynomial before evaluating at the root of unity, ignoring its argument *z*. - -Gauss and Jacobi sums +Discrete Fourier Transforms (DFT) ------------------------------------------------------------------------------- -.. function:: void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +Let *G* be a finite abelian group, and `\chi` a character of *G*. +For any map `f:G\to\C`, the discrete fourier transform `\hat f:\hat G\to C` +is defined by - compute the Gauss sum +.. math:: - .. math:: + \hat f(\chi) = \sum_{x\in G}\chi(x)f(x) - G_q(a) = \sum_{x \mod q} \chi_q(a, x)e^{\frac{2i\pi x}q} +Fast Fourier Transform techniques allow to compute efficiently +all values `\hat f(\chi)`. -.. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +For a Dirichlet group `G` modulo `q`, we take advantage +of the Conrey isomorphism `G \to \hat G` to consider the +the Fourier transform on Conrey labels as - compute the Jacobi sum +.. math:: - .. math:: + g(a) = \sum_{b\bmod q}\chi_q(a,b)f(b) - J_q(a,b) = \sum_{x \mod q} \chi_q(a, x)\chi_q(b, 1-x) + +.. function:: void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) + + Compute the DFT of *v* using conrey indices. + This function assumes *v* and *w* are vectors + of size *G->phi_q*, whose values correspond to a lexicographic ordering + of Conrey indices. + + For example, if `q=15`, the Conrey elements are stored in following + order + + ------- --------------------- + index number = 7^x11^y + ------- --------------------- + [0, 0] 1 + [0, 1] 7 + [0, 2] 4 + [0, 3] 13 + [0, 4] 1 + [1, 0] 11 + [1, 1] 2 + [1, 2] 14 + [1, 3] 8 + [1, 4] 11 + ------- --------------------- + +.. function:: void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) + + Compute the DFT of *v* using Conrey numbers. + This function assumes *v* and *w* are vectors of size *G->q*. + All values at index not coprime to *G->q* are ignored. Euler products ------------------------------------------------------------------------------- From 058e17e4cc338c5d0e85e0861ee685d624f33289 Mon Sep 17 00:00:00 2001 From: Pascal Date: Sat, 6 Aug 2016 14:09:00 +0200 Subject: [PATCH 062/139] doc typo --- doc/source/acb_dirichlet.rst | 53 ++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 62b834ec..079eb452 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -204,7 +204,7 @@ No discrete log computation is performed. .. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) - return the order of `\chi_q(a,\cdot)` which is the order of `a\nmod q`. + return the order of `\chi_q(a,\cdot)` which is the order of `a\mod q`. This number is precomputed for the *char* type. Character evaluation @@ -357,8 +357,8 @@ Discrete Fourier Transforms (DFT) ------------------------------------------------------------------------------- Let *G* be a finite abelian group, and `\chi` a character of *G*. -For any map `f:G\to\C`, the discrete fourier transform `\hat f:\hat G\to C` -is defined by +For any map `f:G\to\mathbb C`, the discrete fourier transform +`\hat f:\hat G\to \mathbb C` is defined by .. math:: @@ -386,20 +386,20 @@ the Fourier transform on Conrey labels as For example, if `q=15`, the Conrey elements are stored in following order - ------- --------------------- - index number = 7^x11^y - ------- --------------------- - [0, 0] 1 - [0, 1] 7 - [0, 2] 4 - [0, 3] 13 - [0, 4] 1 - [1, 0] 11 - [1, 1] 2 - [1, 2] 14 - [1, 3] 8 - [1, 4] 11 - ------- --------------------- + ============ ===================== + index [e,f] number = 7^e11^f + ============ ===================== + [0, 0] 1 + [0, 1] 7 + [0, 2] 4 + [0, 3] 13 + [0, 4] 1 + [1, 0] 11 + [1, 1] 2 + [1, 2] 14 + [1, 3] 8 + [1, 4] 11 + ============ ===================== .. function:: void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) @@ -444,6 +444,25 @@ Simple functions Note that the alternating character `\{1,-1\}` is not itself a Dirichlet character. +L functions +------------------------------------------------------------------------------- + +.. function:: void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + + Compute `L(s,\chi)` for `s\neq 1`, using decomposition in terms of Hurwitz zeta function + + .. math:: + + L(s,\chi) = q^{-s}\sum_{k=1}^{q-1} \chi(k) \zeta(s,\frac kq) + + This formula is slow for large *q*. + +.. function:: void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec) + + Compute all values `L(s,\chi)` for `\chi` mod `q`, by Hurwitz formula and + discrete Fourier transform. + *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered Conrey + index. See :func:`acb_dirichlet_dft_conrey`. Implementation notes ------------------------------------------------------------------------------- From f7de479c9e8771e0c4e6148611b9078f5058e543 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 31 Aug 2016 10:11:50 +0200 Subject: [PATCH 063/139] fix dft accuracy --- acb_dirichlet/arb_quadratic_powers.c | 2 +- acb_dirichlet/arb_theta_naive.c | 2 +- acb_dirichlet/char_conrey.c | 2 +- acb_dirichlet/char_eq.c | 2 +- acb_dirichlet/chi_theta_arb.c | 2 +- acb_dirichlet/conrey_primitive.c | 4 +- acb_dirichlet/dft_fast.c | 11 +-- acb_dirichlet/dft_pol.c | 113 +++++++++++++++++++++++++++ acb_dirichlet/gauss_sum_factor.c | 2 +- acb_dirichlet/jacobi_sum_naive.c | 2 +- acb_dirichlet/test/t-chars.c | 4 +- acb_dirichlet/test/t-dft.c | 43 +++++++--- 12 files changed, 162 insertions(+), 27 deletions(-) diff --git a/acb_dirichlet/arb_quadratic_powers.c b/acb_dirichlet/arb_quadratic_powers.c index ffc49e7d..4031ec32 100644 --- a/acb_dirichlet/arb_quadratic_powers.c +++ b/acb_dirichlet/arb_quadratic_powers.c @@ -25,7 +25,7 @@ #include "acb_dirichlet.h" -/* TODO: BSGS can reduce to nv mul */ +/* TODO: BSGS can reduce to nv mul */ void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec) { diff --git a/acb_dirichlet/arb_theta_naive.c b/acb_dirichlet/arb_theta_naive.c index 4b81f80e..1c8f8eff 100644 --- a/acb_dirichlet/arb_theta_naive.c +++ b/acb_dirichlet/arb_theta_naive.c @@ -50,7 +50,7 @@ acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong arb_mul(xk2, xk2, dx, prec); if (a[k] != ACB_DIRICHLET_CHI_NULL) { - acb_dirichlet_power(zk, z, a[k], prec); + acb_dirichlet_power(zk, z, a[k], prec); if (parity) acb_mul_si(zk, zk, k, prec); acb_addmul_arb(res, zk, xk2, prec); diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c index 843cee2f..052ecdb0 100644 --- a/acb_dirichlet/char_conrey.c +++ b/acb_dirichlet/char_conrey.c @@ -25,7 +25,7 @@ #include "acb_dirichlet.h" -/* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd +/* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd * so that log = expo[k] */ void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) diff --git a/acb_dirichlet/char_eq.c b/acb_dirichlet/char_eq.c index 204fcada..bc6b3037 100644 --- a/acb_dirichlet/char_eq.c +++ b/acb_dirichlet/char_eq.c @@ -29,7 +29,7 @@ int acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) { acb_dirichlet_conrey_t x, y; - + if (chi1->q != chi2->q) return 0; diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index 3a0e60b8..74b156cb 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -43,7 +43,7 @@ acb_dirichlet_chi_theta_arb_smallorder(acb_t res, const acb_dirichlet_group_t G, { ulong * a; acb_dirichlet_powers_t z; - + a = flint_malloc(len * sizeof(ulong)); acb_dirichlet_ui_chi_vec(a, G, chi, len); diff --git a/acb_dirichlet/conrey_primitive.c b/acb_dirichlet/conrey_primitive.c index 9a7c0242..b73bbad0 100644 --- a/acb_dirichlet/conrey_primitive.c +++ b/acb_dirichlet/conrey_primitive.c @@ -29,12 +29,12 @@ void acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, ulong cond) { int k, l, f; - + l = 0; if (cond % 4 == 0) { y->log[l++] = x->log[0]; - + if (cond % 8 == 0) { ulong l2 = x->log[1]; diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c index fd92acf1..67beb045 100644 --- a/acb_dirichlet/dft_fast.c +++ b/acb_dirichlet/dft_fast.c @@ -29,14 +29,11 @@ static acb_ptr vec_extract(acb_srcptr v, slong step, slong len) { - slong k; + slong k, l; acb_ptr res; res = flint_malloc(len * sizeof(acb_struct)); - for (k = 0; k < len; k++) - { - res[k] = v[0]; - v += step; - } + for (k = 0, l = 0; k < len; k++, l+=step) + res[k] = v[l]; return res; } void @@ -164,7 +161,7 @@ _acb_dft_cyc(acb_ptr w, acb_srcptr v, dft_cyc_step * cyc, slong num, slong prec) { _acb_dft_cyc(wi, vi, cyc + 1, num - 1, prec); if (i) - { + { for (j = 1; j < M; j++) acb_mul(wi + j, wi + j, z + dz * i * j, prec); } diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c index d67b0439..5d77d373 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dirichlet/dft_pol.c @@ -26,23 +26,136 @@ #include "acb_poly.h" #include "acb_dirichlet.h" +void +_acb_vec_set_powers_step(acb_ptr xs, slong n, slong len, slong step, slong prec) +{ + slong i, j; + prec += n_clog(n, 2); + + for (i = 0, j = 0; i < len; i++, j += step) + { + if (i == 0) + acb_one(xs + j); + else if (i == 1) + acb_dirichlet_nth_root(xs + j, n, prec); + else if (i % 2 == 0) + acb_mul(xs + j, xs + j / 2, xs + j / 2, prec); + else + acb_mul(xs + j, xs + j - step, xs + step, prec); + } +} + +void +_acb_vec_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec) +{ + if (e <= 1) + { + _acb_vec_set_powers_step(z, p, len, step, prec); + } + else + { + slong q, r; + _acb_vec_roots_pe(z, p, e - 1, len / p, step * p, prec); + _acb_vec_set_powers_step(z, n_pow(p, e), p, step, prec); + + for (q = p; q < len; q += p) + for (r = 1; r < p; r++) + acb_mul(z + (q + r) * step, z + q * step, z + r * step, prec); + } +} + +#if 1 +acb_ptr +acb_roots_init(slong len, slong prec) +{ + slong i, q, q1; + acb_ptr z; + n_factor_t fac; + z = _acb_vec_init(len); + acb_one(z + 0); + + n_factor_init(&fac); + n_factor(&fac, len, 0); + q = q1 = 1; + + for (i = 0; i < fac.num; i++) + { + slong p, e, pe, mp, mq, m; + p = fac.p[i]; + e = fac.exp[i]; + pe = n_pow(p, e); + q1 *= pe; + mp = len / pe; + mq = len / q; + m = len / q1; + + _acb_vec_roots_pe(z, p, e, pe, mp, prec); + + if (i > 0) + { + slong j, jk, jl, k, l; + + jl = mq; /* m * pe; */ + jk = mp + mq; /* m * (q + pe); */ + for (k = 1, j = jk; k < pe; k++, j += jk) + { + for (l = 1; l < q; l++, j += jl) + { + if (j >= len) + j %= len; + /* + flint_printf("[mul] (%ld * %ld + %ld * %ld) * %ld = %ld = %ld = (%ld * %ld) * (%ld * %ld)\n",k,q,l,pe,m, + ((k * q + l * pe) % q1) * m, j ,k,mp,l,mq); + */ + acb_mul(z + j, z + k * mp, z + l * mq, prec); + } + } + } + q = q1; + } + + return z; +} +#else acb_ptr acb_roots_init(slong len, slong prec) { acb_t zeta; acb_ptr z; acb_init(zeta); + prec += n_clog(len, 2); acb_dirichlet_nth_root(zeta, len, prec); z = _acb_vec_init(len); + /* should use factorization */ _acb_vec_set_powers(z, zeta, len, prec); + /* + flint_printf("\nroots [order %ld, prec %ld]\n", len, prec); + acb_vec_printd(z, len, 30); + */ acb_clear(zeta); return z; } +#endif +/* all roots are already computed */ void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec) { + /* FIXME: huge accuracy loss */ +#if 0 _acb_poly_evaluate_vec_fast(w, v, len, z, len, prec); +#elif 0 + _acb_poly_evaluate_vec_iter(w, v, len, z, len, prec); +#else + slong i, j; + + for (i = 0; i < len; i++) + { + acb_zero(w + i); + for (j = 0; j < len; j++) + acb_addmul(w + i, v + j, z + (i * j % len), prec); + } +#endif } void diff --git a/acb_dirichlet/gauss_sum_factor.c b/acb_dirichlet/gauss_sum_factor.c index 1c382167..645d0080 100644 --- a/acb_dirichlet/gauss_sum_factor.c +++ b/acb_dirichlet/gauss_sum_factor.c @@ -71,7 +71,7 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const a slong k; acb_t tmp; - + for (k = (G->neven == 2); k < G->num; k++) { /* if e > 1 and not primitive, 0 */ diff --git a/acb_dirichlet/jacobi_sum_naive.c b/acb_dirichlet/jacobi_sum_naive.c index d09c2901..3145d163 100644 --- a/acb_dirichlet/jacobi_sum_naive.c +++ b/acb_dirichlet/jacobi_sum_naive.c @@ -46,7 +46,7 @@ acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const a m1 = chi1->order.n; m2 = chi2->order.n; - g = n_gcd(m1, m2); + g = n_gcd(m1, m2); nmod_init(&order, m1 * (m2 / g)); m1 = order.n / m1; m2 = order.n / m2; diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index 9c5c8e0d..a0966555 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -35,7 +35,7 @@ int main() fflush(stdout); flint_randinit(state); for (bits = 5; bits <= 30; bits += 5) - { + { for (iter = 0; iter < 50; iter++) { @@ -55,7 +55,7 @@ int main() /* check number char properties */ for (iter2 = 0; iter2 < 100; iter2++) - { + { int par; ulong m, n; ulong order, chim1, pairing, cond; diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index e613aef2..44bf7762 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -29,15 +29,18 @@ int main() { slong k; - slong prec = 100; - slong nq = 10; - ulong q[10] = { 2, 3, 4, 5, 6, 10, 15, 30, 308, 961}; + slong prec = 100, digits = 30; + slong nq = 12; + ulong q[12] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 961}; + flint_rand_t state; flint_printf("dft...."); fflush(stdout); + flint_randinit(state); + /* cyclic dft */ - for (k = 0; k < nq; k++) + for (k = 0; k < 0 * nq; k++) /* FIXME!!!*/ { slong i; acb_ptr v, w1, w2; @@ -58,9 +61,9 @@ int main() { flint_printf("differ from index %ld / %ld \n\n",i,q[k]); flint_printf("pol =\n"); - acb_vec_printd(w1, q[k], 10); + acb_vec_printd(w1, q[k], digits); flint_printf("fast =\n"); - acb_vec_printd(w2, q[k], 10); + acb_vec_printd(w2, q[k], digits); flint_printf("\n\n"); abort(); } @@ -89,11 +92,16 @@ int main() acb_dirichlet_conrey_init(x, G); acb_dirichlet_conrey_one(x, G); +#if 0 for (i = 0; i < len; i++) { acb_set_si(v + i, x->n); acb_dirichlet_conrey_next(x, G); } +#else + for (i = 0; i < len; i++) + acb_randtest_precise(v + i, state, prec, 0); +#endif /* naive */ acb_init(chiy); @@ -125,15 +133,31 @@ int main() flint_printf("FAIL\n\n"); flint_printf("q = %wu\n", q[k]); flint_printf("v [size %wu]\n", len); - acb_vec_printd(v, len, 10); + acb_vec_printd(v, len, digits); flint_printf("\nDFT differ from index %ld / %ld \n", i, len); flint_printf("\nnaive =\n"); - acb_vec_printd(w1, len, 10); + acb_vec_printd(w1, len, digits); flint_printf("\nfast =\n"); - acb_vec_printd(w2, len, 10); + acb_vec_printd(w2, len, digits); flint_printf("\n\n"); abort(); } + else if (acb_rel_accuracy_bits(w1 + i) < 30 + || acb_rel_accuracy_bits(w2 + i) < 30) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu\n", q[k]); + flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); + flint_printf("\nnaive =\n"); + acb_printd(w1 + i, digits); + flint_printf("\nfast =\n"); + acb_printd(w2 + i, digits); + flint_printf("\nerrors %ld & %ld [prec = %wu]\n", + acb_rel_accuracy_bits(w1 + i), + acb_rel_accuracy_bits(w2 + i), prec + ); + abort(); + } } _acb_vec_clear(v, len); @@ -143,5 +167,6 @@ int main() acb_dirichlet_group_clear(G); } + flint_randclear(state); flint_printf("PASS\n"); } From a6d7afffae7040342eb617e0dc6ca23cf6a1c12d Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 31 Aug 2016 15:07:59 +0200 Subject: [PATCH 064/139] simplify roots of 1 --- acb_dirichlet/dft_pol.c | 30 ++++++++++-------------------- acb_dirichlet/test/t-dft.c | 4 ++-- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c index 5d77d373..11c71041 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dirichlet/dft_pol.c @@ -68,7 +68,7 @@ _acb_vec_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec acb_ptr acb_roots_init(slong len, slong prec) { - slong i, q, q1; + slong i, q; acb_ptr z; n_factor_t fac; z = _acb_vec_init(len); @@ -76,42 +76,32 @@ acb_roots_init(slong len, slong prec) n_factor_init(&fac); n_factor(&fac, len, 0); - q = q1 = 1; + q = 1; for (i = 0; i < fac.num; i++) { - slong p, e, pe, mp, mq, m; + slong p, e, pe, mp, mq; p = fac.p[i]; e = fac.exp[i]; pe = n_pow(p, e); - q1 *= pe; mp = len / pe; mq = len / q; - m = len / q1; _acb_vec_roots_pe(z, p, e, pe, mp, prec); if (i > 0) { - slong j, jk, jl, k, l; + slong k, l; - jl = mq; /* m * pe; */ - jk = mp + mq; /* m * (q + pe); */ - for (k = 1, j = jk; k < pe; k++, j += jk) + for (k = mp; k < len; k += mp) { - for (l = 1; l < q; l++, j += jl) - { - if (j >= len) - j %= len; - /* - flint_printf("[mul] (%ld * %ld + %ld * %ld) * %ld = %ld = %ld = (%ld * %ld) * (%ld * %ld)\n",k,q,l,pe,m, - ((k * q + l * pe) % q1) * m, j ,k,mp,l,mq); - */ - acb_mul(z + j, z + k * mp, z + l * mq, prec); - } + for (l = mq; l < len - k; l += mq) + acb_mul(z + k + l, z + k, z + l, prec); + for (; l < len; l += mq) + acb_mul(z + k + l - len, z + k, z + l, prec); } } - q = q1; + q *= pe; } return z; diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 44bf7762..f3c27165 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -40,7 +40,7 @@ int main() flint_randinit(state); /* cyclic dft */ - for (k = 0; k < 0 * nq; k++) /* FIXME!!!*/ + for (k = 0; k < nq; k++) { slong i; acb_ptr v, w1, w2; @@ -75,7 +75,7 @@ int main() } /* Dirichlet group DFT */ - for (k = 0; k < nq - 1; k++) + for (k = 0; k < nq; k++) { slong i, j, len; acb_dirichlet_group_t G; From a6c499cbbee7d07102a973a9558b4618c6649c3b Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 1 Sep 2016 12:12:33 +0200 Subject: [PATCH 065/139] reorgnanize nth roots and gauss sums --- acb_dirichlet/dft_fast.c | 3 +- acb_dirichlet/dft_pol.c | 104 +------------------------- acb_dirichlet/gauss_sum.c | 4 +- acb_dirichlet/gauss_sum_factor.c | 41 ---------- acb_dirichlet/gauss_sum_theta.c | 2 +- acb_dirichlet/profile/p-thetanull.c | 112 ++++++++++++++++++++++++++++ acb_dirichlet/test/t-dft.c | 12 +-- acb_dirichlet/vec_nth_root.c | 105 ++++++++++++++++++++++++++ 8 files changed, 225 insertions(+), 158 deletions(-) create mode 100644 acb_dirichlet/profile/p-thetanull.c create mode 100644 acb_dirichlet/vec_nth_root.c diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c index 67beb045..84038381 100644 --- a/acb_dirichlet/dft_fast.c +++ b/acb_dirichlet/dft_fast.c @@ -103,7 +103,8 @@ _acb_dirichlet_dft_cyc_init(acb_dft_cyc_t t, slong len, slong dv, slong prec) num += fac.exp[i]; t->num = num; t->cyc = flint_malloc(num * sizeof(dft_cyc_step)); - t->z = z = acb_roots_init(t->n, prec); + t->z = z = _acb_vec_init(t->n); + acb_dirichlet_vec_nth_roots(z, t->n, prec); num = 0; dz = 1; diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c index 11c71041..654f2cbf 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dirichlet/dft_pol.c @@ -26,107 +26,6 @@ #include "acb_poly.h" #include "acb_dirichlet.h" -void -_acb_vec_set_powers_step(acb_ptr xs, slong n, slong len, slong step, slong prec) -{ - slong i, j; - prec += n_clog(n, 2); - - for (i = 0, j = 0; i < len; i++, j += step) - { - if (i == 0) - acb_one(xs + j); - else if (i == 1) - acb_dirichlet_nth_root(xs + j, n, prec); - else if (i % 2 == 0) - acb_mul(xs + j, xs + j / 2, xs + j / 2, prec); - else - acb_mul(xs + j, xs + j - step, xs + step, prec); - } -} - -void -_acb_vec_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec) -{ - if (e <= 1) - { - _acb_vec_set_powers_step(z, p, len, step, prec); - } - else - { - slong q, r; - _acb_vec_roots_pe(z, p, e - 1, len / p, step * p, prec); - _acb_vec_set_powers_step(z, n_pow(p, e), p, step, prec); - - for (q = p; q < len; q += p) - for (r = 1; r < p; r++) - acb_mul(z + (q + r) * step, z + q * step, z + r * step, prec); - } -} - -#if 1 -acb_ptr -acb_roots_init(slong len, slong prec) -{ - slong i, q; - acb_ptr z; - n_factor_t fac; - z = _acb_vec_init(len); - acb_one(z + 0); - - n_factor_init(&fac); - n_factor(&fac, len, 0); - q = 1; - - for (i = 0; i < fac.num; i++) - { - slong p, e, pe, mp, mq; - p = fac.p[i]; - e = fac.exp[i]; - pe = n_pow(p, e); - mp = len / pe; - mq = len / q; - - _acb_vec_roots_pe(z, p, e, pe, mp, prec); - - if (i > 0) - { - slong k, l; - - for (k = mp; k < len; k += mp) - { - for (l = mq; l < len - k; l += mq) - acb_mul(z + k + l, z + k, z + l, prec); - for (; l < len; l += mq) - acb_mul(z + k + l - len, z + k, z + l, prec); - } - } - q *= pe; - } - - return z; -} -#else -acb_ptr -acb_roots_init(slong len, slong prec) -{ - acb_t zeta; - acb_ptr z; - acb_init(zeta); - prec += n_clog(len, 2); - acb_dirichlet_nth_root(zeta, len, prec); - z = _acb_vec_init(len); - /* should use factorization */ - _acb_vec_set_powers(z, zeta, len, prec); - /* - flint_printf("\nroots [order %ld, prec %ld]\n", len, prec); - acb_vec_printd(z, len, 30); - */ - acb_clear(zeta); - return z; -} -#endif - /* all roots are already computed */ void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec) @@ -152,7 +51,8 @@ void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec) { acb_ptr z; - z = acb_roots_init(len, prec); + z = _acb_vec_init(len); + acb_dirichlet_vec_nth_roots(z, len, prec); _acb_dirichlet_dft_pol(w, v, z, len, prec); _acb_vec_clear(z, len); } diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index c513cd99..ef574ffd 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -25,8 +25,6 @@ #include "acb_dirichlet.h" -/* TODO: factor on modulus */ - static void gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { @@ -93,7 +91,7 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { - /* no need, factor also does it... */ + /* TODO: no need, factor also does it... */ if (chi->conductor != G->q) { gauss_sum_non_primitive(res, G, chi, prec); diff --git a/acb_dirichlet/gauss_sum_factor.c b/acb_dirichlet/gauss_sum_factor.c index 645d0080..394e45b2 100644 --- a/acb_dirichlet/gauss_sum_factor.c +++ b/acb_dirichlet/gauss_sum_factor.c @@ -25,46 +25,6 @@ #include "acb_dirichlet.h" -/* -void -acb_dirichlet_gauss_sum_naive_prime(acb_t res, acb_dirichlet_prime_group_struct P, ulong expo, slong prec) -{ - acb_t z; - acb_ptr v; - - v = _acb_vec_init(G->q); - acb_dirichlet_chi_vec(v, G, chi, G->q, prec); - - acb_init(z); - acb_dirichlet_nth_root(z, G->q, prec); - - _acb_poly_evaluate(res, v, G->q, z, prec); - - acb_clear(z); - _acb_vec_clear(v, G->q); -} - - -static void -acb_dirichlet_gauss_sum_prime(acb_t res, acb_dirichlet_prime_group_struct P, ulong expo, slong prec) -{ - if (expo % P.p == 0) - { - if (P.e == 1) - acb_set_si(res, -1); - else - acb_zero(res); - } - else - { - if (acb_dirichlet_theta_length_d(P.pe.n, 1, prec) > P.pe.n) - acb_dirichlet_gauss_sum_naive_prime(res, P, expo, prec); - else - acb_dirichlet_gauss_sum_naive_prime(res, P, expo, prec); - } -} -*/ - void acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { @@ -122,5 +82,4 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const a acb_neg(res, res); acb_clear(tmp); - } diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index 5a752def..70bba63d 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -33,7 +33,7 @@ acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const ac arb_init(x); - if ((G->q == 300 && (chi->x->n == 71 || chi->x->n == 131)) + if (chi->conductor < G->q || (G->q == 300 && (chi->x->n == 71 || chi->x->n == 131)) || (G->q == 600 && (chi->x->n == 11 || chi->x->n == 491))) { /* or could use l'Hopital rule */ diff --git a/acb_dirichlet/profile/p-thetanull.c b/acb_dirichlet/profile/p-thetanull.c new file mode 100644 index 00000000..6d77fa92 --- /dev/null +++ b/acb_dirichlet/profile/p-thetanull.c @@ -0,0 +1,112 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +int main() +{ + slong prec = 64; + n_primes_t iter; + ulong q; + + flint_printf("thetanull...."); + fflush(stdout); + + /* look for vanishing theta values for prime power moduli */ + n_primes_init(iter); + +#if 0 /* just to check q=300 & q=600 values */ + q = 2; + while (q++ < 1000) +#else + while ((q = n_primes_next(iter)) < 10000) +#endif + { + slong s; + ulong k; + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + acb_ptr theta, z; + arb_t z1; + arb_ptr t; + + theta = _acb_vec_init(G->phi_q); + z = _acb_vec_init(G->phi_q); + + arb_init(z1); + arb_const_pi(z1, prec); + arb_div_ui(z1, z1, q, prec); + arb_neg(z1, z1); + arb_exp(z1, z1, prec); + + t = _arb_vec_init(q); + acb_dirichlet_arb_quadratic_powers(t, q, z1, prec); + + for (s = 0; s <= 1; s++) + { + k = 0; + acb_dirichlet_conrey_one(x, G); + do { + acb_set_arb(z + k, t + x->n); + k++; + } while (acb_dirichlet_conrey_next(x, G) >= 0); + + acb_dirichlet_dft_conrey(theta, z, G, prec); + + for (k = 0; k < G->phi_q; k++) + { + if (acb_contains_zero(theta + k)) + { + + slong i; + acb_dirichlet_conrey_one(x, G); + for (i = 0; i < k; i++) + acb_dirichlet_conrey_next(x, G); + if (acb_dirichlet_conrey_conductor(G,x) < q || acb_dirichlet_conrey_parity(G, x) != s) + continue; + flint_printf("\ntheta null q = %wu, n = %wu\n",q, x->n); + acb_printd(theta + k, 10); + } + } + + /* change t for odd characters */ + for (k = 0; k < q; k++) + arb_mul_ui(t + k, t + k, k, prec); + + } + + _arb_vec_clear(t, q); + _acb_vec_clear(theta, G->phi_q); + _acb_vec_clear(z, G->phi_q); + arb_clear(z1); + acb_dirichlet_conrey_clear(x); + acb_dirichlet_group_clear(G); + } + + flint_cleanup(); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index f3c27165..dd9e00ff 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -30,8 +30,8 @@ int main() slong k; slong prec = 100, digits = 30; - slong nq = 12; - ulong q[12] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 961}; + slong nq = 13; + ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; flint_rand_t state; flint_printf("dft...."); @@ -92,16 +92,8 @@ int main() acb_dirichlet_conrey_init(x, G); acb_dirichlet_conrey_one(x, G); -#if 0 - for (i = 0; i < len; i++) - { - acb_set_si(v + i, x->n); - acb_dirichlet_conrey_next(x, G); - } -#else for (i = 0; i < len; i++) acb_randtest_precise(v + i, state, prec, 0); -#endif /* naive */ acb_init(chiy); diff --git a/acb_dirichlet/vec_nth_root.c b/acb_dirichlet/vec_nth_root.c new file mode 100644 index 00000000..79f022cb --- /dev/null +++ b/acb_dirichlet/vec_nth_root.c @@ -0,0 +1,105 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +/* assume xs has size >= len * step */ +void +_acb_vec_set_powers_step(acb_ptr xs, slong n, slong len, slong step, slong prec) +{ + slong i, j; + prec += n_clog(n, 2); + + for (i = 0, j = 0; i < len; i++, j += step) + { + if (i == 0) + acb_one(xs + j); + else if (i == 1) + acb_dirichlet_nth_root(xs + j, n, prec); + else if (i % 2 == 0) + acb_mul(xs + j, xs + j / 2, xs + j / 2, prec); + else + acb_mul(xs + j, xs + j - step, xs + step, prec); + } +} + +/* assume len = p^e and z has size >= len * step */ +void +_acb_vec_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec) +{ + if (e <= 1) + { + _acb_vec_set_powers_step(z, p, len, step, prec); + } + else + { + slong q, r; + _acb_vec_roots_pe(z, p, e - 1, len / p, step * p, prec); + _acb_vec_set_powers_step(z, n_pow(p, e), p, step, prec); + + for (q = p; q < len; q += p) + for (r = 1; r < p; r++) + acb_mul(z + (q + r) * step, z + q * step, z + r * step, prec); + } +} + +void +acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec) +{ + slong i, q; + n_factor_t fac; + + acb_one(z + 0); + + n_factor_init(&fac); + n_factor(&fac, len, 0); + q = 1; + + for (i = 0; i < fac.num; i++) + { + slong p, e, pe, mp, mq; + p = fac.p[i]; + e = fac.exp[i]; + pe = n_pow(p, e); + mp = len / pe; + mq = len / q; + + _acb_vec_roots_pe(z, p, e, pe, mp, prec); + + if (i > 0) + { + slong k, l; + + for (k = mp; k < len; k += mp) + { + for (l = mq; l < len - k; l += mq) + acb_mul(z + k + l, z + k, z + l, prec); + for (; l < len; l += mq) + acb_mul(z + k + l - len, z + k, z + l, prec); + } + } + q *= pe; + } +} From 6705804cf7383416551da6cf8557f3a8f1c48608 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 2 Sep 2016 16:09:18 +0200 Subject: [PATCH 066/139] profile central value --- acb_dirichlet/arb_theta_smallorder.c | 1 - acb_dirichlet/chi_theta_arb.c | 1 - acb_dirichlet/l_hurwitz.c | 17 +++--- acb_dirichlet/l_vec_hurwitz.c | 2 + acb_dirichlet/profile/p-lcentral.c | 82 ++++++++++++++++++++++++++++ acb_dirichlet/test/t-l.c | 25 +++++++-- acb_dirichlet/test/t-thetanull.c | 8 +-- doc/source/acb_dirichlet.rst | 6 ++ 8 files changed, 121 insertions(+), 21 deletions(-) create mode 100644 acb_dirichlet/profile/p-lcentral.c diff --git a/acb_dirichlet/arb_theta_smallorder.c b/acb_dirichlet/arb_theta_smallorder.c index 95c598cc..0f2930a1 100644 --- a/acb_dirichlet/arb_theta_smallorder.c +++ b/acb_dirichlet/arb_theta_smallorder.c @@ -75,4 +75,3 @@ acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const u arb_clear(x2); arb_clear(dx); } - diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index 74b156cb..8a53abed 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -124,7 +124,6 @@ acb_dirichlet_chi_theta_arb_naive(acb_t res, const acb_dirichlet_group_t G, cons flint_free(a); } - void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) { diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index 125fa7b9..b2d116d6 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -16,12 +16,11 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { ulong chin; - acb_t z, t, u, a; - acb_ptr xz; + acb_t t, u, a; + acb_ptr z; acb_dirichlet_conrey_t cn; acb_dirichlet_conrey_init(cn, G); - acb_init(z); acb_init(t); acb_init(u); acb_init(a); @@ -29,9 +28,10 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_dirichlet_conrey_one(cn, G); acb_zero(t); - acb_dirichlet_nth_root(z, chi->order.n, prec); - xz = _acb_vec_init(chi->order.n); - _acb_vec_set_powers(xz, z, chi->order.n, prec); + prec += n_clog(G->phi_q, 2); + + z = _acb_vec_init(chi->order.n); + acb_dirichlet_vec_nth_roots(z, chi->order.n, prec); do { chin = acb_dirichlet_ui_chi_conrey(G, chi, cn); @@ -40,7 +40,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_div_ui(a, a, G->q, prec); acb_hurwitz_zeta(u, s, a, prec); - acb_addmul(t, xz + chin, u, prec); + acb_addmul(t, z + chin, u, prec); } while (acb_dirichlet_conrey_next(cn, G) >= 0); @@ -51,8 +51,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_dirichlet_conrey_clear(cn); - _acb_vec_clear(xz, chi->order.n); - acb_clear(z); + _acb_vec_clear(z, chi->order.n); acb_clear(t); acb_clear(u); acb_clear(a); diff --git a/acb_dirichlet/l_vec_hurwitz.c b/acb_dirichlet/l_vec_hurwitz.c index 160577e8..eaf053fa 100644 --- a/acb_dirichlet/l_vec_hurwitz.c +++ b/acb_dirichlet/l_vec_hurwitz.c @@ -37,6 +37,8 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, acb_init(qs); acb_init(a); + prec += n_clog(G->phi_q, 2); + acb_set_ui(qs, G->q); acb_neg(a, s); acb_pow(qs, qs, a, prec); diff --git a/acb_dirichlet/profile/p-lcentral.c b/acb_dirichlet/profile/p-lcentral.c new file mode 100644 index 00000000..3458e0a0 --- /dev/null +++ b/acb_dirichlet/profile/p-lcentral.c @@ -0,0 +1,82 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +#define OUT 0 + +int main() +{ + slong prec = 100, digits = 30; + ulong q; + acb_t s; + + fflush(stdout); + + acb_init(s); + acb_one(s); + acb_div_si(s, s, 2, prec); + + /* look for vanishing theta values for prime power moduli */ + for (q = 3; q < 100; q++) + { + ulong k; + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_ptr z; + + if (q % 4 == 2) + continue; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + + z = _acb_vec_init(G->phi_q); + + acb_dirichlet_l_vec_hurwitz(z, s, G, prec); + +#if OUT + k = 0; + acb_dirichlet_conrey_one(x, G); + while (acb_dirichlet_conrey_next(x, G) >= 0) + { + k++; + if (acb_dirichlet_conrey_conductor(G,x) < q) + continue; + flint_printf("%wu,%wu: ", q, x->n); + acb_printd(z + k, digits); + flint_printf("\n"); + } +#endif + + _acb_vec_clear(z, G->phi_q); + acb_dirichlet_conrey_clear(x); + acb_dirichlet_group_clear(G); + } + acb_clear(s); + + flint_cleanup(); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index f263d088..a4dac51b 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -29,9 +29,9 @@ #define nx 3 void -test_dft() +test_dft(ulong q) { - ulong i, q = 15; + ulong i; slong prec = 100; acb_dirichlet_group_t G; acb_dirichlet_conrey_t x; @@ -73,6 +73,21 @@ test_dft() acb_vec_printd(v, G->phi_q, 10); flint_printf("\n\n"); } + else if (acb_rel_accuracy_bits(z) < prec - 8 + || acb_rel_accuracy_bits(v + i) < prec - 8) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu\n", q); + flint_printf("\nL(1/2,chi_%wu(%wu,)) inaccurate\n", q, x->n); + flint_printf("\nsingle =\n"); + acb_printd(z, 30); + flint_printf("\ndft =\n"); + acb_printd(v + i, 30); + flint_printf("\nerrors %ld & %ld [prec = %wu]\n", + acb_rel_accuracy_bits(z), + acb_rel_accuracy_bits(v + i), prec); + abort(); + } i++; } while (acb_dirichlet_conrey_next(x, G) >= 0); @@ -202,13 +217,15 @@ int main() } acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); + + /* test using dft */ + test_dft(q[i]); + } acb_clear(ref); acb_clear(res); _acb_vec_clear(x, nx); - /* test using dft */ - test_dft(); flint_cleanup(); flint_printf("PASS\n"); diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 01346f5a..55c515ed 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -45,7 +45,7 @@ int main() acb_dirichlet_char_t chi; ulong * v, nv, k; - acb_t zeta, sum; + acb_t sum; acb_ptr z; arb_t eq; @@ -58,11 +58,8 @@ int main() acb_dirichlet_group_init(G, q); acb_dirichlet_char_init(chi, G); - acb_init(zeta); - acb_dirichlet_nth_root(zeta, G->expo, prec); - z = _acb_vec_init(G->expo); - _acb_vec_set_powers(z, zeta, G->expo, prec); + acb_dirichlet_vec_nth_roots(z, G->expo, prec); nv = acb_dirichlet_theta_length_d(q, 1, prec); v = flint_malloc(nv * sizeof(ulong)); @@ -124,7 +121,6 @@ int main() _acb_vec_clear(z, G->expo); _arb_vec_clear(t, nv); - acb_clear(zeta); acb_clear(sum); arb_clear(eq); flint_free(v); diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 079eb452..3b6b15b2 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -234,6 +234,12 @@ Roots of unity sets *res* to `\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. +.. function:: void acb_dirichlet_vec_nth_roots(acb_ptr z, slong order, slong prec) + + compute the vector ``1,z,z^2,\dots z^{\mathrm{order}-1}`` where `z=\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. + + In order to avoid precision loss, this function does not simply compute powers of a primitive root. + .. type:: acb_dirichlet_powers_struct .. type:: acb_dirichlet_powers_t From 669252861c29b55462d6db2cda7549ddb0143f2b Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 5 Sep 2016 10:06:45 +0200 Subject: [PATCH 067/139] fix stupid inefficiency in dlog --- dlog/profile/p-vec.c | 57 +++++++++++++++++++++++++++++--------------- dlog/vec.c | 2 +- dlog/vec_add.c | 4 +++- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/dlog/profile/p-vec.c b/dlog/profile/p-vec.c index cff9d199..ba04420b 100644 --- a/dlog/profile/p-vec.c +++ b/dlog/profile/p-vec.c @@ -23,6 +23,7 @@ ******************************************************************************/ +#include #include "dlog.h" #include "profiler.h" @@ -30,8 +31,6 @@ #define LOG 0 #define CSV 1 #define JSON 2 -#define OUT JSON - typedef void (*vec_f) (ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const nmod_t order); @@ -41,8 +40,9 @@ f_empty(ulong *v, ulong nv, ulong a, ulong va, const nmod_t mod, ulong na, const return; } -int main() +int main(int argc, char *argv[]) { + int out = LOG; int i, ni = 8; int bits[9] = { 10, 15, 20, 25, 30, 35, 40, 45, 50 }; @@ -67,6 +67,20 @@ int main() flint_randinit(state); + if (argc < 2) + out = LOG; + else if (!strcmp(argv[1], "json")) + out = JSON; + else if (!strcmp(argv[1], "csv")) + out = CSV; + else if (!strcmp(argv[1], "log")) + out = LOG; + else + { + printf("usage: %s [log|csv|json]\n", argv[0]); + abort(); + } + for (i = 0; i < ni; i++) { @@ -81,10 +95,11 @@ int main() v = flint_malloc(nv[j] * sizeof(ulong)); -#if OUT == LOG - flint_printf("log(1..%wu) mod %d primes of size %d bits....\n", nv[j], np, bits[i]); - fflush(stdout); -#endif + if (out == LOG) + { + flint_printf("log(1..%wu) mod %d primes of size %d bits....\n", nv[j], np, bits[i]); + fflush(stdout); + } for (l = 0; l < nf; l++) { @@ -93,15 +108,20 @@ int main() if (l == 2 && i > 5) continue; -#if OUT == LOG - flint_printf("%-20s... ",n[l]); - fflush(stdout); -#elif OUT == CSV - flint_printf("%-8s, %2d, %4d, %3d, ",n[l],bits[i],nv[j],np); -#elif OUT == JSON - flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nv\": %d, \"nprimes\": %d, \"time\": ", - n[l],bits[i],nv[j],np); -#endif + if (out == LOG) + { + flint_printf("%-20s... ",n[l]); + fflush(stdout); + } + else if (out == CSV) + { + flint_printf("%-8s, %2d, %4d, %3d, ",n[l],bits[i],nv[j],np); + } + else if (out == JSON) + { + flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nv\": %d, \"nprimes\": %d, \"time\": ", + n[l],bits[i],nv[j],np); + } TIMEIT_ONCE_START @@ -117,11 +137,10 @@ int main() TIMEIT_ONCE_STOP -#if OUT == JSON + if (out == JSON) flint_printf("}\n"); -#else + else flint_printf("\n"); -#endif } flint_free(v); } diff --git a/dlog/vec.c b/dlog/vec.c index 0fc67623..5c386daf 100644 --- a/dlog/vec.c +++ b/dlog/vec.c @@ -30,7 +30,7 @@ dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t ord { if (va == 0) return; - if (na * DLOG_LOOP_MAX_FACTOR > nv) + if (na * DLOG_LOOP_MAX_FACTOR < nv) dlog_vec_loop(v, nv, a, va, mod, na, order); else dlog_vec_sieve(v, nv, a, va, mod, na, order); diff --git a/dlog/vec_add.c b/dlog/vec_add.c index 56c301e5..77033cab 100644 --- a/dlog/vec_add.c +++ b/dlog/vec_add.c @@ -28,7 +28,9 @@ void dlog_vec_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - if (na * DLOG_LOOP_MAX_FACTOR > nv) + if (va == 0) + return; + if (na * DLOG_LOOP_MAX_FACTOR < nv) dlog_vec_loop_add(v, nv, a, va, mod, na, order); else dlog_vec_sieve_add(v, nv, a, va, mod, na, order); From 403c2efb6d804f384c8fb60f37768cf5ecf23195 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 5 Sep 2016 12:37:43 +0200 Subject: [PATCH 068/139] first dlog profile data --- dlog/profile/p-precomp.c | 55 +++++---- dlog/profile/precomp_160905.json | 106 +++++++++++++++++ dlog/profile/vec160905.json | 198 +++++++++++++++++++++++++++++++ 3 files changed, 339 insertions(+), 20 deletions(-) create mode 100644 dlog/profile/precomp_160905.json create mode 100644 dlog/profile/vec160905.json diff --git a/dlog/profile/p-precomp.c b/dlog/profile/p-precomp.c index 0000cb20..acfe2e7d 100644 --- a/dlog/profile/p-precomp.c +++ b/dlog/profile/p-precomp.c @@ -23,15 +23,15 @@ ******************************************************************************/ +#include +#include #include "dlog.h" #include "profiler.h" -#include #define NUMPRIMES 400 #define LOG 0 #define CSV 1 #define JSON 2 -#define OUT JSON typedef void (*log_f) (ulong p, ulong a, ulong num); @@ -101,8 +101,9 @@ flog_gen(ulong p, ulong a, ulong num) dlog_precomp_clear(t); } -int main() +int main(int argc, char *argv[]) { + int out = LOG; slong iter, k, nv, nref, r, nr; ulong minq, maxq; ulong * rand; @@ -117,6 +118,20 @@ int main() flint_rand_t state; + if (argc < 2) + out = LOG; + else if (!strcmp(argv[1], "json")) + out = JSON; + else if (!strcmp(argv[1], "csv")) + out = CSV; + else if (!strcmp(argv[1], "log")) + out = LOG; + else + { + printf("usage: %s [log|csv|json]\n", argv[0]); + abort(); + } + flint_randinit(state); for (nbits = 10; nbits <= 40; nbits += 5) { @@ -136,9 +151,9 @@ int main() for (i = 0; i < nl; i++) { int f; -#if OUT == LOG - flint_printf("%d * logs mod primes of size %d.....\n", l[i], nbits); -#endif + + if (out == LOG) + flint_printf("%d * logs mod primes of size %d.....\n", l[i], nbits); for (f = 0; f < nf; f++) { @@ -149,26 +164,26 @@ int main() continue; if (f == 1 && nbits >= 30 && l[i] > 10) continue; -#if OUT == LOG - flint_printf("%-20s... ",n[f]); - fflush(stdout); -#elif OUT == CSV - flint_printf("%-8s, %2d, %4d, %3d, ",n[f],nbits,l[i],np); -#elif OUT == JSON - flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nlogs\": %d, \"nprimes\": %d, \"time\": ", - n[f],nbits,l[i],np); -#endif + if (out == LOG) + { + flint_printf("%-20s... ",n[f]); + fflush(stdout); + } + else if (out == CSV) + flint_printf("%-8s, %2d, %4d, %3d, ",n[f],nbits,l[i],np); + else if (out == JSON) + flint_printf("{ \"name\": \"%s\", \"bits\": %d, \"nlogs\": %d, \"nprimes\": %d, \"time\": ", + n[f],nbits,l[i],np); TIMEIT_ONCE_START for (j = 0; j < np; j ++) (func[f])(p[j], a[j], l[i]); TIMEIT_ONCE_STOP -#if OUT == JSON - flint_printf("}\n"); -#else - flint_printf("\n"); -#endif + if (out == JSON) + flint_printf("}\n"); + else + flint_printf("\n"); } } } diff --git a/dlog/profile/precomp_160905.json b/dlog/profile/precomp_160905.json new file mode 100644 index 00000000..d4e5977c --- /dev/null +++ b/dlog/profile/precomp_160905.json @@ -0,0 +1,106 @@ +{ "name": "table", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.003} +{ "name": "bsgs", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.002} +{ "name": "crt", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.001} +{ "name": "generic", "bits": 10, "nlogs": 1, "nprimes": 400, "time": 0.001} +{ "name": "table", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.004} +{ "name": "bsgs", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.004} +{ "name": "crt", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.003} +{ "name": "generic", "bits": 10, "nlogs": 10, "nprimes": 400, "time": 0.003} +{ "name": "table", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.004} +{ "name": "bsgs", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.016} +{ "name": "crt", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.019} +{ "name": "generic", "bits": 10, "nlogs": 100, "nprimes": 400, "time": 0.017} +{ "name": "table", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.01} +{ "name": "bsgs", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.054} +{ "name": "crt", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.143} +{ "name": "generic", "bits": 10, "nlogs": 1000, "nprimes": 400, "time": 0.143} +{ "name": "table", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.036} +{ "name": "bsgs", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.147} +{ "name": "crt", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.692} +{ "name": "generic", "bits": 10, "nlogs": 5000, "nprimes": 400, "time": 0.694} +{ "name": "table", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.108} +{ "name": "bsgs", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.01} +{ "name": "crt", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.003} +{ "name": "generic", "bits": 15, "nlogs": 1, "nprimes": 400, "time": 0.002} +{ "name": "table", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.108} +{ "name": "bsgs", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.025} +{ "name": "crt", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.008} +{ "name": "generic", "bits": 15, "nlogs": 10, "nprimes": 400, "time": 0.007} +{ "name": "table", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.109} +{ "name": "bsgs", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.092} +{ "name": "crt", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.038} +{ "name": "generic", "bits": 15, "nlogs": 100, "nprimes": 400, "time": 0.038} +{ "name": "table", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.114} +{ "name": "bsgs", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.321} +{ "name": "crt", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.275} +{ "name": "generic", "bits": 15, "nlogs": 1000, "nprimes": 400, "time": 0.273} +{ "name": "table", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 0.14} +{ "name": "bsgs", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 0.784} +{ "name": "crt", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 1.228} +{ "name": "generic", "bits": 15, "nlogs": 5000, "nprimes": 400, "time": 1.232} +{ "name": "bsgs", "bits": 20, "nlogs": 1, "nprimes": 400, "time": 0.069} +{ "name": "crt", "bits": 20, "nlogs": 1, "nprimes": 400, "time": 0.011} +{ "name": "generic", "bits": 20, "nlogs": 1, "nprimes": 400, "time": 0.01} +{ "name": "bsgs", "bits": 20, "nlogs": 10, "nprimes": 400, "time": 0.176} +{ "name": "crt", "bits": 20, "nlogs": 10, "nprimes": 400, "time": 0.027} +{ "name": "generic", "bits": 20, "nlogs": 10, "nprimes": 400, "time": 0.027} +{ "name": "bsgs", "bits": 20, "nlogs": 100, "nprimes": 400, "time": 0.622} +{ "name": "crt", "bits": 20, "nlogs": 100, "nprimes": 400, "time": 0.114} +{ "name": "generic", "bits": 20, "nlogs": 100, "nprimes": 400, "time": 0.114} +{ "name": "bsgs", "bits": 20, "nlogs": 1000, "nprimes": 400, "time": 2.166} +{ "name": "crt", "bits": 20, "nlogs": 1000, "nprimes": 400, "time": 0.589} +{ "name": "generic", "bits": 20, "nlogs": 1000, "nprimes": 400, "time": 0.591} +{ "name": "bsgs", "bits": 20, "nlogs": 5000, "nprimes": 400, "time": 5.333} +{ "name": "crt", "bits": 20, "nlogs": 5000, "nprimes": 400, "time": 2.252} +{ "name": "generic", "bits": 20, "nlogs": 5000, "nprimes": 400, "time": 2.238} +{ "name": "bsgs", "bits": 25, "nlogs": 1, "nprimes": 200, "time": 0.23} +{ "name": "crt", "bits": 25, "nlogs": 1, "nprimes": 200, "time": 0.025} +{ "name": "generic", "bits": 25, "nlogs": 1, "nprimes": 200, "time": 0.026} +{ "name": "bsgs", "bits": 25, "nlogs": 10, "nprimes": 200, "time": 0.585} +{ "name": "crt", "bits": 25, "nlogs": 10, "nprimes": 200, "time": 0.065} +{ "name": "generic", "bits": 25, "nlogs": 10, "nprimes": 200, "time": 0.065} +{ "name": "bsgs", "bits": 25, "nlogs": 100, "nprimes": 200, "time": 2.099} +{ "name": "crt", "bits": 25, "nlogs": 100, "nprimes": 200, "time": 0.243} +{ "name": "generic", "bits": 25, "nlogs": 100, "nprimes": 200, "time": 0.243} +{ "name": "bsgs", "bits": 25, "nlogs": 1000, "nprimes": 200, "time": 7.338} +{ "name": "crt", "bits": 25, "nlogs": 1000, "nprimes": 200, "time": 0.967} +{ "name": "generic", "bits": 25, "nlogs": 1000, "nprimes": 200, "time": 0.967} +{ "name": "bsgs", "bits": 25, "nlogs": 5000, "nprimes": 200, "time": 19.051} +{ "name": "crt", "bits": 25, "nlogs": 5000, "nprimes": 200, "time": 2.893} +{ "name": "generic", "bits": 25, "nlogs": 5000, "nprimes": 200, "time": 2.882} +{ "name": "bsgs", "bits": 30, "nlogs": 1, "nprimes": 100, "time": 0.742} +{ "name": "crt", "bits": 30, "nlogs": 1, "nprimes": 100, "time": 0.07} +{ "name": "generic", "bits": 30, "nlogs": 1, "nprimes": 100, "time": 0.071} +{ "name": "bsgs", "bits": 30, "nlogs": 10, "nprimes": 100, "time": 1.914} +{ "name": "crt", "bits": 30, "nlogs": 10, "nprimes": 100, "time": 0.178} +{ "name": "generic", "bits": 30, "nlogs": 10, "nprimes": 100, "time": 0.178} +{ "name": "crt", "bits": 30, "nlogs": 100, "nprimes": 100, "time": 0.652} +{ "name": "generic", "bits": 30, "nlogs": 100, "nprimes": 100, "time": 0.655} +{ "name": "crt", "bits": 30, "nlogs": 1000, "nprimes": 100, "time": 2.495} +{ "name": "generic", "bits": 30, "nlogs": 1000, "nprimes": 100, "time": 2.493} +{ "name": "crt", "bits": 30, "nlogs": 5000, "nprimes": 100, "time": 6.465} +{ "name": "generic", "bits": 30, "nlogs": 5000, "nprimes": 100, "time": 6.432} +{ "name": "bsgs", "bits": 35, "nlogs": 1, "nprimes": 50, "time": 2.357} +{ "name": "crt", "bits": 35, "nlogs": 1, "nprimes": 50, "time": 0.118} +{ "name": "generic", "bits": 35, "nlogs": 1, "nprimes": 50, "time": 0.118} +{ "name": "bsgs", "bits": 35, "nlogs": 10, "nprimes": 50, "time": 6.562} +{ "name": "crt", "bits": 35, "nlogs": 10, "nprimes": 50, "time": 0.307} +{ "name": "generic", "bits": 35, "nlogs": 10, "nprimes": 50, "time": 0.308} +{ "name": "crt", "bits": 35, "nlogs": 100, "nprimes": 50, "time": 1.171} +{ "name": "generic", "bits": 35, "nlogs": 100, "nprimes": 50, "time": 1.175} +{ "name": "crt", "bits": 35, "nlogs": 1000, "nprimes": 50, "time": 4.329} +{ "name": "generic", "bits": 35, "nlogs": 1000, "nprimes": 50, "time": 4.297} +{ "name": "crt", "bits": 35, "nlogs": 5000, "nprimes": 50, "time": 10.904} +{ "name": "generic", "bits": 35, "nlogs": 5000, "nprimes": 50, "time": 10.916} +{ "name": "bsgs", "bits": 40, "nlogs": 1, "nprimes": 25, "time": 7.623} +{ "name": "crt", "bits": 40, "nlogs": 1, "nprimes": 25, "time": 0.472} +{ "name": "generic", "bits": 40, "nlogs": 1, "nprimes": 25, "time": 0.463} +{ "name": "bsgs", "bits": 40, "nlogs": 10, "nprimes": 25, "time": 21.817} +{ "name": "crt", "bits": 40, "nlogs": 10, "nprimes": 25, "time": 1.395} +{ "name": "generic", "bits": 40, "nlogs": 10, "nprimes": 25, "time": 1.389} +{ "name": "crt", "bits": 40, "nlogs": 100, "nprimes": 25, "time": 5.191} +{ "name": "generic", "bits": 40, "nlogs": 100, "nprimes": 25, "time": 5.158} +{ "name": "crt", "bits": 40, "nlogs": 1000, "nprimes": 25, "time": 19.911} +{ "name": "generic", "bits": 40, "nlogs": 1000, "nprimes": 25, "time": 19.722} +{ "name": "crt", "bits": 40, "nlogs": 5000, "nprimes": 25, "time": 51.207} +{ "name": "generic", "bits": 40, "nlogs": 5000, "nprimes": 25, "time": 51.084} diff --git a/dlog/profile/vec160905.json b/dlog/profile/vec160905.json new file mode 100644 index 00000000..8ba6ef78 --- /dev/null +++ b/dlog/profile/vec160905.json @@ -0,0 +1,198 @@ +{ "name": "empty", "bits": 10, "nv": 50, "nprimes": 640, "time": 0} +{ "name": "loop", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.006} +{ "name": "eratos", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.007} +{ "name": "sieve", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.009} +{ "name": "default", "bits": 10, "nv": 50, "nprimes": 640, "time": 0.01} +{ "name": "empty", "bits": 10, "nv": 200, "nprimes": 640, "time": 0} +{ "name": "loop", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.007} +{ "name": "eratos", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.016} +{ "name": "sieve", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.013} +{ "name": "default", "bits": 10, "nv": 200, "nprimes": 640, "time": 0.013} +{ "name": "empty", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0} +{ "name": "loop", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.007} +{ "name": "eratos", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.04} +{ "name": "sieve", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.024} +{ "name": "default", "bits": 10, "nv": 1000, "nprimes": 640, "time": 0.023} +{ "name": "empty", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0} +{ "name": "loop", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.006} +{ "name": "eratos", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.04} +{ "name": "sieve", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.026} +{ "name": "default", "bits": 10, "nv": 2000, "nprimes": 640, "time": 0.025} +{ "name": "empty", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.002} +{ "name": "loop", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.011} +{ "name": "eratos", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.045} +{ "name": "sieve", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.05} +{ "name": "default", "bits": 10, "nv": 10000, "nprimes": 640, "time": 0.011} +{ "name": "empty", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.005} +{ "name": "loop", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.022} +{ "name": "eratos", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.055} +{ "name": "sieve", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.109} +{ "name": "default", "bits": 10, "nv": 30000, "nprimes": 640, "time": 0.022} +{ "name": "empty", "bits": 15, "nv": 50, "nprimes": 320, "time": 0} +{ "name": "loop", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.09} +{ "name": "eratos", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.008} +{ "name": "sieve", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.014} +{ "name": "default", "bits": 15, "nv": 50, "nprimes": 320, "time": 0.013} +{ "name": "empty", "bits": 15, "nv": 200, "nprimes": 320, "time": 0} +{ "name": "loop", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.09} +{ "name": "eratos", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.018} +{ "name": "sieve", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.02} +{ "name": "default", "bits": 15, "nv": 200, "nprimes": 320, "time": 0.02} +{ "name": "empty", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0} +{ "name": "loop", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.092} +{ "name": "eratos", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.05} +{ "name": "sieve", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.029} +{ "name": "default", "bits": 15, "nv": 1000, "nprimes": 320, "time": 0.03} +{ "name": "empty", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0} +{ "name": "loop", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.097} +{ "name": "eratos", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.085} +{ "name": "sieve", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.037} +{ "name": "default", "bits": 15, "nv": 2000, "nprimes": 320, "time": 0.039} +{ "name": "empty", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.001} +{ "name": "loop", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.126} +{ "name": "eratos", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.301} +{ "name": "sieve", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.098} +{ "name": "default", "bits": 15, "nv": 10000, "nprimes": 320, "time": 0.096} +{ "name": "empty", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.003} +{ "name": "loop", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.094} +{ "name": "eratos", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.641} +{ "name": "sieve", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.193} +{ "name": "default", "bits": 15, "nv": 30000, "nprimes": 320, "time": 0.192} +{ "name": "empty", "bits": 20, "nv": 50, "nprimes": 160, "time": 0} +{ "name": "loop", "bits": 20, "nv": 50, "nprimes": 160, "time": 1.445} +{ "name": "eratos", "bits": 20, "nv": 50, "nprimes": 160, "time": 0.015} +{ "name": "sieve", "bits": 20, "nv": 50, "nprimes": 160, "time": 0.026} +{ "name": "default", "bits": 20, "nv": 50, "nprimes": 160, "time": 0.027} +{ "name": "empty", "bits": 20, "nv": 200, "nprimes": 160, "time": 0} +{ "name": "loop", "bits": 20, "nv": 200, "nprimes": 160, "time": 1.445} +{ "name": "eratos", "bits": 20, "nv": 200, "nprimes": 160, "time": 0.03} +{ "name": "sieve", "bits": 20, "nv": 200, "nprimes": 160, "time": 0.034} +{ "name": "default", "bits": 20, "nv": 200, "nprimes": 160, "time": 0.032} +{ "name": "empty", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0} +{ "name": "loop", "bits": 20, "nv": 1000, "nprimes": 160, "time": 1.45} +{ "name": "eratos", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0.07} +{ "name": "sieve", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0.041} +{ "name": "default", "bits": 20, "nv": 1000, "nprimes": 160, "time": 0.041} +{ "name": "empty", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0} +{ "name": "loop", "bits": 20, "nv": 2000, "nprimes": 160, "time": 1.454} +{ "name": "eratos", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0.107} +{ "name": "sieve", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0.048} +{ "name": "default", "bits": 20, "nv": 2000, "nprimes": 160, "time": 0.047} +{ "name": "empty", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.001} +{ "name": "loop", "bits": 20, "nv": 10000, "nprimes": 160, "time": 1.465} +{ "name": "eratos", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.308} +{ "name": "sieve", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.082} +{ "name": "default", "bits": 20, "nv": 10000, "nprimes": 160, "time": 0.081} +{ "name": "empty", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.001} +{ "name": "loop", "bits": 20, "nv": 30000, "nprimes": 160, "time": 1.505} +{ "name": "eratos", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.685} +{ "name": "sieve", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.152} +{ "name": "default", "bits": 20, "nv": 30000, "nprimes": 160, "time": 0.152} +{ "name": "empty", "bits": 25, "nv": 50, "nprimes": 80, "time": 0} +{ "name": "eratos", "bits": 25, "nv": 50, "nprimes": 80, "time": 0.029} +{ "name": "sieve", "bits": 25, "nv": 50, "nprimes": 80, "time": 0.052} +{ "name": "default", "bits": 25, "nv": 50, "nprimes": 80, "time": 0.051} +{ "name": "empty", "bits": 25, "nv": 200, "nprimes": 80, "time": 0} +{ "name": "eratos", "bits": 25, "nv": 200, "nprimes": 80, "time": 0.056} +{ "name": "sieve", "bits": 25, "nv": 200, "nprimes": 80, "time": 0.06} +{ "name": "default", "bits": 25, "nv": 200, "nprimes": 80, "time": 0.06} +{ "name": "empty", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0} +{ "name": "eratos", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0.117} +{ "name": "sieve", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0.072} +{ "name": "default", "bits": 25, "nv": 1000, "nprimes": 80, "time": 0.073} +{ "name": "empty", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0} +{ "name": "eratos", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0.168} +{ "name": "sieve", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0.082} +{ "name": "default", "bits": 25, "nv": 2000, "nprimes": 80, "time": 0.08} +{ "name": "empty", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.001} +{ "name": "eratos", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.409} +{ "name": "sieve", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.092} +{ "name": "default", "bits": 25, "nv": 10000, "nprimes": 80, "time": 0.093} +{ "name": "empty", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.001} +{ "name": "eratos", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.8} +{ "name": "sieve", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.132} +{ "name": "default", "bits": 25, "nv": 30000, "nprimes": 80, "time": 0.132} +{ "name": "empty", "bits": 30, "nv": 50, "nprimes": 40, "time": 0} +{ "name": "eratos", "bits": 30, "nv": 50, "nprimes": 40, "time": 0.073} +{ "name": "sieve", "bits": 30, "nv": 50, "nprimes": 40, "time": 0.121} +{ "name": "default", "bits": 30, "nv": 50, "nprimes": 40, "time": 0.122} +{ "name": "empty", "bits": 30, "nv": 200, "nprimes": 40, "time": 0} +{ "name": "eratos", "bits": 30, "nv": 200, "nprimes": 40, "time": 0.138} +{ "name": "sieve", "bits": 30, "nv": 200, "nprimes": 40, "time": 0.136} +{ "name": "default", "bits": 30, "nv": 200, "nprimes": 40, "time": 0.136} +{ "name": "empty", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0} +{ "name": "eratos", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0.282} +{ "name": "sieve", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0.151} +{ "name": "default", "bits": 30, "nv": 1000, "nprimes": 40, "time": 0.15} +{ "name": "empty", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0} +{ "name": "eratos", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0.409} +{ "name": "sieve", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0.166} +{ "name": "default", "bits": 30, "nv": 2000, "nprimes": 40, "time": 0.162} +{ "name": "empty", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0} +{ "name": "eratos", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0.924} +{ "name": "sieve", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0.226} +{ "name": "default", "bits": 30, "nv": 10000, "nprimes": 40, "time": 0.225} +{ "name": "empty", "bits": 30, "nv": 30000, "nprimes": 40, "time": 0} +{ "name": "eratos", "bits": 30, "nv": 30000, "nprimes": 40, "time": 1.665} +{ "name": "sieve", "bits": 30, "nv": 30000, "nprimes": 40, "time": 0.207} +{ "name": "default", "bits": 30, "nv": 30000, "nprimes": 40, "time": 0.207} +{ "name": "empty", "bits": 35, "nv": 50, "nprimes": 20, "time": 0} +{ "name": "eratos", "bits": 35, "nv": 50, "nprimes": 20, "time": 0.22} +{ "name": "sieve", "bits": 35, "nv": 50, "nprimes": 20, "time": 0.355} +{ "name": "default", "bits": 35, "nv": 50, "nprimes": 20, "time": 0.352} +{ "name": "empty", "bits": 35, "nv": 200, "nprimes": 20, "time": 0} +{ "name": "eratos", "bits": 35, "nv": 200, "nprimes": 20, "time": 0.432} +{ "name": "sieve", "bits": 35, "nv": 200, "nprimes": 20, "time": 0.403} +{ "name": "default", "bits": 35, "nv": 200, "nprimes": 20, "time": 0.407} +{ "name": "empty", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0} +{ "name": "eratos", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0.864} +{ "name": "sieve", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0.426} +{ "name": "default", "bits": 35, "nv": 1000, "nprimes": 20, "time": 0.428} +{ "name": "empty", "bits": 35, "nv": 2000, "nprimes": 20, "time": 0} +{ "name": "eratos", "bits": 35, "nv": 2000, "nprimes": 20, "time": 1.23} +{ "name": "sieve", "bits": 35, "nv": 2000, "nprimes": 20, "time": 0.442} +{ "name": "default", "bits": 35, "nv": 2000, "nprimes": 20, "time": 0.439} +{ "name": "empty", "bits": 35, "nv": 10000, "nprimes": 20, "time": 0} +{ "name": "eratos", "bits": 35, "nv": 10000, "nprimes": 20, "time": 2.717} +{ "name": "sieve", "bits": 35, "nv": 10000, "nprimes": 20, "time": 0.528} +{ "name": "default", "bits": 35, "nv": 10000, "nprimes": 20, "time": 0.53} +{ "name": "empty", "bits": 35, "nv": 30000, "nprimes": 20, "time": 0} +{ "name": "eratos", "bits": 35, "nv": 30000, "nprimes": 20, "time": 4.735} +{ "name": "sieve", "bits": 35, "nv": 30000, "nprimes": 20, "time": 0.739} +{ "name": "default", "bits": 35, "nv": 30000, "nprimes": 20, "time": 0.74} +{ "name": "empty", "bits": 40, "nv": 50, "nprimes": 10, "time": 0} +{ "name": "sieve", "bits": 40, "nv": 50, "nprimes": 10, "time": 1.31} +{ "name": "default", "bits": 40, "nv": 50, "nprimes": 10, "time": 1.306} +{ "name": "empty", "bits": 40, "nv": 200, "nprimes": 10, "time": 0} +{ "name": "sieve", "bits": 40, "nv": 200, "nprimes": 10, "time": 1.537} +{ "name": "default", "bits": 40, "nv": 200, "nprimes": 10, "time": 1.537} +{ "name": "empty", "bits": 40, "nv": 1000, "nprimes": 10, "time": 0} +{ "name": "sieve", "bits": 40, "nv": 1000, "nprimes": 10, "time": 1.58} +{ "name": "default", "bits": 40, "nv": 1000, "nprimes": 10, "time": 1.574} +{ "name": "empty", "bits": 40, "nv": 2000, "nprimes": 10, "time": 0} +{ "name": "sieve", "bits": 40, "nv": 2000, "nprimes": 10, "time": 1.597} +{ "name": "default", "bits": 40, "nv": 2000, "nprimes": 10, "time": 1.596} +{ "name": "empty", "bits": 40, "nv": 10000, "nprimes": 10, "time": 0} +{ "name": "sieve", "bits": 40, "nv": 10000, "nprimes": 10, "time": 1.753} +{ "name": "default", "bits": 40, "nv": 10000, "nprimes": 10, "time": 1.748} +{ "name": "empty", "bits": 40, "nv": 30000, "nprimes": 10, "time": 0} +{ "name": "sieve", "bits": 40, "nv": 30000, "nprimes": 10, "time": 2.396} +{ "name": "default", "bits": 40, "nv": 30000, "nprimes": 10, "time": 2.397} +{ "name": "empty", "bits": 45, "nv": 50, "nprimes": 5, "time": 0} +{ "name": "sieve", "bits": 45, "nv": 50, "nprimes": 5, "time": 1.623} +{ "name": "default", "bits": 45, "nv": 50, "nprimes": 5, "time": 1.617} +{ "name": "empty", "bits": 45, "nv": 200, "nprimes": 5, "time": 0} +{ "name": "sieve", "bits": 45, "nv": 200, "nprimes": 5, "time": 2.039} +{ "name": "default", "bits": 45, "nv": 200, "nprimes": 5, "time": 2.072} +{ "name": "empty", "bits": 45, "nv": 1000, "nprimes": 5, "time": 0} +{ "name": "sieve", "bits": 45, "nv": 1000, "nprimes": 5, "time": 2.194} +{ "name": "default", "bits": 45, "nv": 1000, "nprimes": 5, "time": 2.142} +{ "name": "empty", "bits": 45, "nv": 2000, "nprimes": 5, "time": 0} +{ "name": "sieve", "bits": 45, "nv": 2000, "nprimes": 5, "time": 2.147} +{ "name": "default", "bits": 45, "nv": 2000, "nprimes": 5, "time": 2.182} +{ "name": "empty", "bits": 45, "nv": 10000, "nprimes": 5, "time": 0} +{ "name": "sieve", "bits": 45, "nv": 10000, "nprimes": 5, "time": 2.22} +{ "name": "default", "bits": 45, "nv": 10000, "nprimes": 5, "time": 2.222} +{ "name": "empty", "bits": 45, "nv": 30000, "nprimes": 5, "time": 0} +{ "name": "sieve", "bits": 45, "nv": 30000, "nprimes": 5, "time": 2.448} +{ "name": "default", "bits": 45, "nv": 30000, "nprimes": 5, "time": 2.445} From d73fdb7f106d139e82cfd6e82e80c6125c3deac2 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 5 Sep 2016 16:24:44 +0200 Subject: [PATCH 069/139] update conrey profile --- acb_dirichlet/profile/p-conrey.c | 166 ++++++++++++++++++++++++------- 1 file changed, 132 insertions(+), 34 deletions(-) diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c index 899758b5..3785e073 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/acb_dirichlet/profile/p-conrey.c @@ -23,32 +23,34 @@ ******************************************************************************/ +#include #include "acb_dirichlet.h" #include "profiler.h" -int main() +#define LOG 0 +#define CSV 1 +#define JSON 2 + +typedef ulong (*do_f) (ulong q1, ulong q2); + +static ulong +do_gcd(ulong q1, ulong q2) { - slong iter, k, n, nref; - ulong q, maxq; + ulong n, q, k; - maxq = 4000; - flint_printf("loop over all (Z/q)* for q<=%wu....\n", maxq); - fflush(stdout); - - flint_printf("gcd................ "); - TIMEIT_ONCE_START - for (n = 0, q = 2; q <= maxq; q++) + for (n = 0, q = q1; q <= q2; q++) for (k = 1; k < q; k++) - if (n_gcd(k, q) > 1) - continue; - else - n++; - TIMEIT_ONCE_STOP - nref = n; + n += (n_gcd(k, q) == 1); - flint_printf("conrey.... "); - TIMEIT_ONCE_START - for (n = 0, q = 2; q <= maxq; q++) + return n; +} + +static ulong +do_conrey(ulong q1, ulong q2) +{ + ulong n, q; + + for (n = 0, q = q1; q <= q2; q++) { acb_dirichlet_group_t G; acb_dirichlet_conrey_t x; @@ -63,16 +65,16 @@ int main() acb_dirichlet_conrey_clear(x); acb_dirichlet_group_clear(G); } - TIMEIT_ONCE_STOP - if (n != nref) - { - flint_printf("FAIL: wrong number of elements %wu != %wu\n\n",n, nref); - abort(); - } - flint_printf("chars.... "); - TIMEIT_ONCE_START - for (n = 0, q = 2; q <= maxq; q++) + return n; +} + +static ulong +do_chars(ulong q1, ulong q2) +{ + ulong n, q; + + for (n = 0, q = q1; q <= q2; q++) { acb_dirichlet_group_t G; acb_dirichlet_char_t chi; @@ -82,20 +84,116 @@ int main() acb_dirichlet_char_one(chi, G); n++; - for (; acb_dirichlet_char_next(chi, G) >= 0; n++); + acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); } - TIMEIT_ONCE_STOP - if (n != nref) + + return n; +} + +static ulong +do_gcdpluscond(ulong q1, ulong q2) +{ + ulong n, q, k; + + for (n = 0, q = q1; q <= q2; q++) { - flint_printf("FAIL: wrong number of elements %wu != %wu\n\n",n, nref); - abort(); + acb_dirichlet_group_t G; + acb_dirichlet_group_init(G, q); + + for (k = 1; k < q; k++) + { + /* known factors -> faster gcd */ + slong i; + if (G->q_even > 1 && k % 2 == 0) + continue; + for (i = G->neven; i < G->num; i++) + if (k % G->P[i].p == 0) + break; + + if (i == G->num) + acb_dirichlet_ui_conductor(G, k); + } + + n += G->phi_q; + acb_dirichlet_group_clear(G); + } + return n; +} + +int main(int argc, char *argv[]) +{ + int out; + ulong n, nref, maxq = 5000; + + int l, nf = 4; + do_f func[4] = { do_gcd, do_conrey, do_chars, do_gcdpluscond }; + char * name[4] = { "gcd", "conrey", "chars", "gcd+cond" }; + + int i, ni = 5; + ulong qmin[5] = { 2, 1000, 10000, 100000, 1000000 }; + ulong qmax[5] = { 500, 3000, 11000, 100100, 1000010 }; + + if (argc < 2) + out = LOG; + else if (!strcmp(argv[1], "json")) + out = JSON; + else if (!strcmp(argv[1], "csv")) + out = CSV; + else if (!strcmp(argv[1], "log")) + out = LOG; + else + { + printf("usage: %s [log|csv|json]\n", argv[0]); + abort(); + } + + if (out == CSV) + flint_printf("# %-6s, %7s, %7s, %7s\n","name", "qmin", "qmax", "time"); + + for (i = 0; i < ni; i++) + { + + if (out == LOG) + { + flint_printf("loop over all (Z/q)* for %wu<=q<=%wu\n", qmin[i], qmax[i]); + } + + for (l = 0; l < nf; l++) + { + + if (out == LOG) + flint_printf("%-8s ... ",name[l]); + else if (out == CSV) + flint_printf("%-8s, %7d, %7d, ",name[l],qmin[i],qmax[i]); + else if (out == JSON) + flint_printf("{ \"name\": \"%s\", \"qmin\": %d, \"qmax\": %d, \"time\": ", + name[l],qmin[i],qmax[i]); + + TIMEIT_ONCE_START + (func[l])(qmin[i], qmax[i]); + TIMEIT_ONCE_STOP + + if (l == 0) + nref = n; + else if (n != nref) + { + flint_printf("FAIL: wrong number of elements %wu != %wu\n\n",n, nref); + abort(); + } + + if (out == JSON) + flint_printf("}\n"); + else + flint_printf("\n"); + } + + } flint_cleanup(); - flint_printf("PASS\n"); return EXIT_SUCCESS; } From 402be335d831a836ff20e0c15ca4f4b180eb9d90 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 6 Sep 2016 14:03:16 +0200 Subject: [PATCH 070/139] doc dlog --- doc/source/dlog.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/source/dlog.rst b/doc/source/dlog.rst index 3c3bd572..62fbfb09 100644 --- a/doc/source/dlog.rst +++ b/doc/source/dlog.rst @@ -42,7 +42,14 @@ of successive integers `1\dots n`: the group size is comparable with the number of elements requested - otherwise the logarithms are computed on primes and propagated by - Eratosthene-like sieving. + Eratosthene-like sieving on composite numbers. + +- when several logarithms are already computed, a basic smoothing technique + inspired by index-calculus is adopted to obtain larger logs from + smaller ones. + +- in the the present implementation, the full index-calculus method is not + implemented. Types, macros and constants ------------------------------------------------------------------------------- From 8ccd527560393e4db37a89b749e9d74fcca03e07 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 6 Sep 2016 14:19:50 +0200 Subject: [PATCH 071/139] example L central value --- .../p-lcentral.c => examples/lcentral.c | 54 ++++++++++++------- 1 file changed, 36 insertions(+), 18 deletions(-) rename acb_dirichlet/profile/p-lcentral.c => examples/lcentral.c (66%) diff --git a/acb_dirichlet/profile/p-lcentral.c b/examples/lcentral.c similarity index 66% rename from acb_dirichlet/profile/p-lcentral.c rename to examples/lcentral.c index 3458e0a0..e3e41408 100644 --- a/acb_dirichlet/profile/p-lcentral.c +++ b/examples/lcentral.c @@ -23,24 +23,41 @@ ******************************************************************************/ +#include #include "acb_dirichlet.h" -#define OUT 0 - -int main() +int main(int argc, char *argv[]) { + int i, out = 1; slong prec = 100, digits = 30; - ulong q; + ulong qmin, qmax, q; acb_t s; + if (argc < 3) + { + printf("usage: %s [--quiet] qmin qmax\n", argv[0]); + return 1; + } + for (i = 1; i < argc - 2; i++) + { + if (!strcmp(argv[i],"--quiet")) + out = 0; + /* + else if (!strcmp(argv[i],"--algo")) + { + } + */ + } + qmin = atol(argv[i++]); + qmax = atol(argv[i++]); + fflush(stdout); acb_init(s); acb_one(s); acb_div_si(s, s, 2, prec); - /* look for vanishing theta values for prime power moduli */ - for (q = 3; q < 100; q++) + for (q = qmin; q <= qmax; q++) { ulong k; acb_dirichlet_group_t G; @@ -57,19 +74,20 @@ int main() acb_dirichlet_l_vec_hurwitz(z, s, G, prec); -#if OUT - k = 0; - acb_dirichlet_conrey_one(x, G); - while (acb_dirichlet_conrey_next(x, G) >= 0) - { - k++; - if (acb_dirichlet_conrey_conductor(G,x) < q) - continue; - flint_printf("%wu,%wu: ", q, x->n); - acb_printd(z + k, digits); - flint_printf("\n"); + if (out) + { + k = 0; + acb_dirichlet_conrey_one(x, G); + while (acb_dirichlet_conrey_next(x, G) >= 0) + { + k++; + if (acb_dirichlet_conrey_conductor(G,x) < q) + continue; + flint_printf("%wu,%wu: ", q, x->n); + acb_printd(z + k, digits); + flint_printf("\n"); + } } -#endif _acb_vec_clear(z, G->phi_q); acb_dirichlet_conrey_clear(x); From a9dc8bd71153648182ae37d71588f17f4da0c414 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 6 Sep 2016 15:32:23 +0200 Subject: [PATCH 072/139] update licence --- acb_dirichlet/arb_quadratic_powers.c | 30 +++++++----------------- acb_dirichlet/arb_theta_naive.c | 30 +++++++----------------- acb_dirichlet/arb_theta_smallorder.c | 30 +++++++----------------- acb_dirichlet/char.c | 30 +++++++----------------- acb_dirichlet/char_clear.c | 30 +++++++----------------- acb_dirichlet/char_conrey.c | 30 +++++++----------------- acb_dirichlet/char_eq.c | 30 +++++++----------------- acb_dirichlet/char_first_primitive.c | 30 +++++++----------------- acb_dirichlet/char_init.c | 30 +++++++----------------- acb_dirichlet/char_mul.c | 30 +++++++----------------- acb_dirichlet/char_next.c | 30 +++++++----------------- acb_dirichlet/char_next_primitive.c | 30 +++++++----------------- acb_dirichlet/char_normalize.c | 30 +++++++----------------- acb_dirichlet/char_one.c | 30 +++++++----------------- acb_dirichlet/char_primitive.c | 30 +++++++----------------- acb_dirichlet/char_print.c | 30 +++++++----------------- acb_dirichlet/chi.c | 30 +++++++----------------- acb_dirichlet/chi_theta_arb.c | 30 +++++++----------------- acb_dirichlet/chi_vec.c | 30 +++++++----------------- acb_dirichlet/conrey.c | 30 +++++++----------------- acb_dirichlet/conrey_conductor.c | 30 +++++++----------------- acb_dirichlet/conrey_eq.c | 30 +++++++----------------- acb_dirichlet/conrey_exp.c | 30 +++++++----------------- acb_dirichlet/conrey_first_primitive.c | 30 +++++++----------------- acb_dirichlet/conrey_log.c | 30 +++++++----------------- acb_dirichlet/conrey_mul.c | 30 +++++++----------------- acb_dirichlet/conrey_next.c | 30 +++++++----------------- acb_dirichlet/conrey_next_primitive.c | 30 +++++++----------------- acb_dirichlet/conrey_one.c | 30 +++++++----------------- acb_dirichlet/conrey_order.c | 30 +++++++----------------- acb_dirichlet/conrey_parity.c | 30 +++++++----------------- acb_dirichlet/conrey_pow.c | 30 +++++++----------------- acb_dirichlet/conrey_primitive.c | 30 +++++++----------------- acb_dirichlet/conrey_print.c | 30 +++++++----------------- acb_dirichlet/dft.c | 30 +++++++----------------- acb_dirichlet/dft_fast.c | 30 +++++++----------------- acb_dirichlet/dft_pol.c | 30 +++++++----------------- acb_dirichlet/gauss_sum.c | 30 +++++++----------------- acb_dirichlet/gauss_sum_factor.c | 30 +++++++----------------- acb_dirichlet/gauss_sum_naive.c | 30 +++++++----------------- acb_dirichlet/gauss_sum_theta.c | 30 +++++++----------------- acb_dirichlet/group_dlog_precompute.c | 30 +++++++----------------- acb_dirichlet/jacobi_sum.c | 30 +++++++----------------- acb_dirichlet/jacobi_sum_naive.c | 30 +++++++----------------- acb_dirichlet/l_hurwitz.c | 1 + acb_dirichlet/l_vec_hurwitz.c | 30 +++++++----------------- acb_dirichlet/nth_root.c | 30 +++++++----------------- acb_dirichlet/number_primitive.c | 32 +++++++------------------- acb_dirichlet/pairing.c | 31 +++++++------------------ acb_dirichlet/pairing_conrey.c | 30 +++++++----------------- acb_dirichlet/power.c | 30 +++++++----------------- acb_dirichlet/powers_clear.c | 31 +++++++------------------ acb_dirichlet/powers_init.c | 30 +++++++----------------- acb_dirichlet/qseries_eval_arb.c | 31 +++++++------------------ acb_dirichlet/si_poly_evaluate.c | 31 ++++++++----------------- acb_dirichlet/theta_length.c | 30 +++++++----------------- acb_dirichlet/ui_chi.c | 30 +++++++----------------- acb_dirichlet/ui_chi_conrey.c | 30 +++++++----------------- acb_dirichlet/ui_chi_vec.c | 30 +++++++----------------- acb_dirichlet/ui_chi_vec_loop.c | 30 +++++++----------------- acb_dirichlet/ui_chi_vec_primeloop.c | 30 +++++++----------------- acb_dirichlet/ui_conductor.c | 30 +++++++----------------- acb_dirichlet/ui_order.c | 30 +++++++----------------- acb_dirichlet/ui_pairing.c | 30 +++++++----------------- acb_dirichlet/ui_pairing_conrey.c | 30 +++++++----------------- acb_dirichlet/ui_parity.c | 30 +++++++----------------- acb_dirichlet/ui_theta_arb.c | 30 +++++++----------------- acb_dirichlet/ui_vec_set_null.c | 30 +++++++----------------- acb_dirichlet/vec_nth_root.c | 30 +++++++----------------- 69 files changed, 546 insertions(+), 1501 deletions(-) diff --git a/acb_dirichlet/arb_quadratic_powers.c b/acb_dirichlet/arb_quadratic_powers.c index 4031ec32..0732d4ba 100644 --- a/acb_dirichlet/arb_quadratic_powers.c +++ b/acb_dirichlet/arb_quadratic_powers.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/arb_theta_naive.c b/acb_dirichlet/arb_theta_naive.c index 1c8f8eff..f9cb5b37 100644 --- a/acb_dirichlet/arb_theta_naive.c +++ b/acb_dirichlet/arb_theta_naive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include "acb_poly.h" diff --git a/acb_dirichlet/arb_theta_smallorder.c b/acb_dirichlet/arb_theta_smallorder.c index 0f2930a1..d9823df5 100644 --- a/acb_dirichlet/arb_theta_smallorder.c +++ b/acb_dirichlet/arb_theta_smallorder.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include "acb_poly.h" diff --git a/acb_dirichlet/char.c b/acb_dirichlet/char.c index cbc72727..cd3bff08 100644 --- a/acb_dirichlet/char.c +++ b/acb_dirichlet/char.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_clear.c b/acb_dirichlet/char_clear.c index 77d394d3..57e4e948 100644 --- a/acb_dirichlet/char_clear.c +++ b/acb_dirichlet/char_clear.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c index 052ecdb0..ffb18d31 100644 --- a/acb_dirichlet/char_conrey.c +++ b/acb_dirichlet/char_conrey.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_eq.c b/acb_dirichlet/char_eq.c index bc6b3037..bcd89703 100644 --- a/acb_dirichlet/char_eq.c +++ b/acb_dirichlet/char_eq.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_first_primitive.c b/acb_dirichlet/char_first_primitive.c index 0fa70693..6e31d30f 100644 --- a/acb_dirichlet/char_first_primitive.c +++ b/acb_dirichlet/char_first_primitive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_init.c b/acb_dirichlet/char_init.c index ffa5e866..dd15b5bd 100644 --- a/acb_dirichlet/char_init.c +++ b/acb_dirichlet/char_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_mul.c b/acb_dirichlet/char_mul.c index 83eaf7f4..c05c1cc1 100644 --- a/acb_dirichlet/char_mul.c +++ b/acb_dirichlet/char_mul.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_next.c b/acb_dirichlet/char_next.c index f7a57300..0ae26024 100644 --- a/acb_dirichlet/char_next.c +++ b/acb_dirichlet/char_next.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_next_primitive.c b/acb_dirichlet/char_next_primitive.c index 07e205a9..363cd4d7 100644 --- a/acb_dirichlet/char_next_primitive.c +++ b/acb_dirichlet/char_next_primitive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_normalize.c b/acb_dirichlet/char_normalize.c index a4b4f1a7..69a05262 100644 --- a/acb_dirichlet/char_normalize.c +++ b/acb_dirichlet/char_normalize.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_one.c b/acb_dirichlet/char_one.c index 22f9d9eb..32e2ad45 100644 --- a/acb_dirichlet/char_one.c +++ b/acb_dirichlet/char_one.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_primitive.c b/acb_dirichlet/char_primitive.c index c042eb03..8fd374bd 100644 --- a/acb_dirichlet/char_primitive.c +++ b/acb_dirichlet/char_primitive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/char_print.c b/acb_dirichlet/char_print.c index ba191376..a33e33d0 100644 --- a/acb_dirichlet/char_print.c +++ b/acb_dirichlet/char_print.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/chi.c b/acb_dirichlet/chi.c index 72a65ab5..56943bd5 100644 --- a/acb_dirichlet/chi.c +++ b/acb_dirichlet/chi.c @@ -1,29 +1,15 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c index 8a53abed..f89ff841 100644 --- a/acb_dirichlet/chi_theta_arb.c +++ b/acb_dirichlet/chi_theta_arb.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include "acb_poly.h" diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/chi_vec.c index cb3abce2..a9a07bb9 100644 --- a/acb_dirichlet/chi_vec.c +++ b/acb_dirichlet/chi_vec.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey.c b/acb_dirichlet/conrey.c index c98acf39..5bf141b2 100644 --- a/acb_dirichlet/conrey.c +++ b/acb_dirichlet/conrey.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_conductor.c b/acb_dirichlet/conrey_conductor.c index 7a56d1d6..78cb5e0e 100644 --- a/acb_dirichlet/conrey_conductor.c +++ b/acb_dirichlet/conrey_conductor.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_eq.c b/acb_dirichlet/conrey_eq.c index 636f9e63..751b1409 100644 --- a/acb_dirichlet/conrey_eq.c +++ b/acb_dirichlet/conrey_eq.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_exp.c b/acb_dirichlet/conrey_exp.c index d85d0f6c..2ba76deb 100644 --- a/acb_dirichlet/conrey_exp.c +++ b/acb_dirichlet/conrey_exp.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_first_primitive.c b/acb_dirichlet/conrey_first_primitive.c index 50913511..d1472439 100644 --- a/acb_dirichlet/conrey_first_primitive.c +++ b/acb_dirichlet/conrey_first_primitive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index b33a2ee7..15040b26 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -1,29 +1,15 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_mul.c b/acb_dirichlet/conrey_mul.c index 66884087..29e3bcbe 100644 --- a/acb_dirichlet/conrey_mul.c +++ b/acb_dirichlet/conrey_mul.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_next.c b/acb_dirichlet/conrey_next.c index e715ed93..881f54d2 100644 --- a/acb_dirichlet/conrey_next.c +++ b/acb_dirichlet/conrey_next.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_next_primitive.c b/acb_dirichlet/conrey_next_primitive.c index 0157f240..a6e050dc 100644 --- a/acb_dirichlet/conrey_next_primitive.c +++ b/acb_dirichlet/conrey_next_primitive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_one.c b/acb_dirichlet/conrey_one.c index d5eac769..7396e957 100644 --- a/acb_dirichlet/conrey_one.c +++ b/acb_dirichlet/conrey_one.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_order.c b/acb_dirichlet/conrey_order.c index e30755fc..0b4495e4 100644 --- a/acb_dirichlet/conrey_order.c +++ b/acb_dirichlet/conrey_order.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_parity.c b/acb_dirichlet/conrey_parity.c index ede8aaf6..11428e9e 100644 --- a/acb_dirichlet/conrey_parity.c +++ b/acb_dirichlet/conrey_parity.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_pow.c b/acb_dirichlet/conrey_pow.c index 4393bfed..3230fca1 100644 --- a/acb_dirichlet/conrey_pow.c +++ b/acb_dirichlet/conrey_pow.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_primitive.c b/acb_dirichlet/conrey_primitive.c index b73bbad0..5f86c7be 100644 --- a/acb_dirichlet/conrey_primitive.c +++ b/acb_dirichlet/conrey_primitive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/conrey_print.c b/acb_dirichlet/conrey_print.c index 6a4e0b6d..7790fe77 100644 --- a/acb_dirichlet/conrey_print.c +++ b/acb_dirichlet/conrey_print.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/dft.c b/acb_dirichlet/dft.c index 6caa901c..5a025374 100644 --- a/acb_dirichlet/dft.c +++ b/acb_dirichlet/dft.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c index 84038381..cef7c66c 100644 --- a/acb_dirichlet/dft_fast.c +++ b/acb_dirichlet/dft_fast.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c index 654f2cbf..116cbe70 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dirichlet/dft_pol.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_poly.h" #include "acb_dirichlet.h" diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index ef574ffd..3013cdda 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/gauss_sum_factor.c b/acb_dirichlet/gauss_sum_factor.c index 394e45b2..17ce2e2c 100644 --- a/acb_dirichlet/gauss_sum_factor.c +++ b/acb_dirichlet/gauss_sum_factor.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/gauss_sum_naive.c b/acb_dirichlet/gauss_sum_naive.c index 2299fa5b..47570590 100644 --- a/acb_dirichlet/gauss_sum_naive.c +++ b/acb_dirichlet/gauss_sum_naive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include "acb_poly.h" diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index 70bba63d..72be2601 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/group_dlog_precompute.c b/acb_dirichlet/group_dlog_precompute.c index 2f816531..292efc7f 100644 --- a/acb_dirichlet/group_dlog_precompute.c +++ b/acb_dirichlet/group_dlog_precompute.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index 02198218..c1b88291 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/jacobi_sum_naive.c b/acb_dirichlet/jacobi_sum_naive.c index 3145d163..8dc020ad 100644 --- a/acb_dirichlet/jacobi_sum_naive.c +++ b/acb_dirichlet/jacobi_sum_naive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index b2d116d6..bc9166b5 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -1,5 +1,6 @@ /* Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin This file is part of Arb. diff --git a/acb_dirichlet/l_vec_hurwitz.c b/acb_dirichlet/l_vec_hurwitz.c index eaf053fa..cedc726b 100644 --- a/acb_dirichlet/l_vec_hurwitz.c +++ b/acb_dirichlet/l_vec_hurwitz.c @@ -1,27 +1,13 @@ -/*============================================================================= +/* + Copyright (C) 2016 Pascal Molin - This file is part of ARB. + This file is part of Arb. - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2016 Fredrik Johansson - -******************************************************************************/ + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/nth_root.c b/acb_dirichlet/nth_root.c index 81f751df..70547f0a 100644 --- a/acb_dirichlet/nth_root.c +++ b/acb_dirichlet/nth_root.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/number_primitive.c b/acb_dirichlet/number_primitive.c index 94b09546..053df1a7 100644 --- a/acb_dirichlet/number_primitive.c +++ b/acb_dirichlet/number_primitive.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" @@ -49,5 +35,3 @@ acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) return n; } } - - diff --git a/acb_dirichlet/pairing.c b/acb_dirichlet/pairing.c index efc4e4f8..832b047f 100644 --- a/acb_dirichlet/pairing.c +++ b/acb_dirichlet/pairing.c @@ -1,28 +1,13 @@ -/*============================================================================= +/* + Copyright (C) 2016 Pascal Molin - This file is part of ARB. + This file is part of Arb. - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2015 Jonathan Bober - Copyright (C) 2016 Fredrik Johansson - -******************************************************************************/ + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/pairing_conrey.c b/acb_dirichlet/pairing_conrey.c index a61dd336..e59e5464 100644 --- a/acb_dirichlet/pairing_conrey.c +++ b/acb_dirichlet/pairing_conrey.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/power.c b/acb_dirichlet/power.c index 1f7be4fa..0220d5ff 100644 --- a/acb_dirichlet/power.c +++ b/acb_dirichlet/power.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include "acb_poly.h" diff --git a/acb_dirichlet/powers_clear.c b/acb_dirichlet/powers_clear.c index b84f4679..6cae589c 100644 --- a/acb_dirichlet/powers_clear.c +++ b/acb_dirichlet/powers_clear.c @@ -1,30 +1,15 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" -#include "acb_poly.h" void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t) diff --git a/acb_dirichlet/powers_init.c b/acb_dirichlet/powers_init.c index c43040e9..6033397f 100644 --- a/acb_dirichlet/powers_init.c +++ b/acb_dirichlet/powers_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include "acb_poly.h" diff --git a/acb_dirichlet/qseries_eval_arb.c b/acb_dirichlet/qseries_eval_arb.c index ae657fc2..6d7f5bb1 100644 --- a/acb_dirichlet/qseries_eval_arb.c +++ b/acb_dirichlet/qseries_eval_arb.c @@ -1,30 +1,15 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" -#include "acb_poly.h" /* assume a[0] = 0 */ void diff --git a/acb_dirichlet/si_poly_evaluate.c b/acb_dirichlet/si_poly_evaluate.c index 0a10582a..36ededd9 100644 --- a/acb_dirichlet/si_poly_evaluate.c +++ b/acb_dirichlet/si_poly_evaluate.c @@ -1,27 +1,14 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* + Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c index f5f66f37..e0534806 100644 --- a/acb_dirichlet/theta_length.c +++ b/acb_dirichlet/theta_length.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include diff --git a/acb_dirichlet/ui_chi.c b/acb_dirichlet/ui_chi.c index f163a874..d7453381 100644 --- a/acb_dirichlet/ui_chi.c +++ b/acb_dirichlet/ui_chi.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_chi_conrey.c b/acb_dirichlet/ui_chi_conrey.c index cd5f4263..5f67b9a8 100644 --- a/acb_dirichlet/ui_chi_conrey.c +++ b/acb_dirichlet/ui_chi_conrey.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_chi_vec.c b/acb_dirichlet/ui_chi_vec.c index 42080621..23476cb1 100644 --- a/acb_dirichlet/ui_chi_vec.c +++ b/acb_dirichlet/ui_chi_vec.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_chi_vec_loop.c b/acb_dirichlet/ui_chi_vec_loop.c index 88eb88e1..2cc90e0f 100644 --- a/acb_dirichlet/ui_chi_vec_loop.c +++ b/acb_dirichlet/ui_chi_vec_loop.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_chi_vec_primeloop.c b/acb_dirichlet/ui_chi_vec_primeloop.c index 861160e8..2527564f 100644 --- a/acb_dirichlet/ui_chi_vec_primeloop.c +++ b/acb_dirichlet/ui_chi_vec_primeloop.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_conductor.c b/acb_dirichlet/ui_conductor.c index 4d015ad4..69f1d43e 100644 --- a/acb_dirichlet/ui_conductor.c +++ b/acb_dirichlet/ui_conductor.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_order.c b/acb_dirichlet/ui_order.c index aa3babe1..b162d232 100644 --- a/acb_dirichlet/ui_order.c +++ b/acb_dirichlet/ui_order.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_pairing.c b/acb_dirichlet/ui_pairing.c index bccf29df..235325e9 100644 --- a/acb_dirichlet/ui_pairing.c +++ b/acb_dirichlet/ui_pairing.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_pairing_conrey.c b/acb_dirichlet/ui_pairing_conrey.c index a5afa42b..7e1a5bd8 100644 --- a/acb_dirichlet/ui_pairing_conrey.c +++ b/acb_dirichlet/ui_pairing_conrey.c @@ -1,29 +1,15 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_parity.c b/acb_dirichlet/ui_parity.c index 5fa84d73..aa5a2a4c 100644 --- a/acb_dirichlet/ui_parity.c +++ b/acb_dirichlet/ui_parity.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_theta_arb.c b/acb_dirichlet/ui_theta_arb.c index e7ba107b..1477006a 100644 --- a/acb_dirichlet/ui_theta_arb.c +++ b/acb_dirichlet/ui_theta_arb.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/ui_vec_set_null.c b/acb_dirichlet/ui_vec_set_null.c index 46bf517a..baf2333c 100644 --- a/acb_dirichlet/ui_vec_set_null.c +++ b/acb_dirichlet/ui_vec_set_null.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/vec_nth_root.c b/acb_dirichlet/vec_nth_root.c index 79f022cb..820f6826 100644 --- a/acb_dirichlet/vec_nth_root.c +++ b/acb_dirichlet/vec_nth_root.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" From 71979161c239bfd9539638978d776d4fb67d8c76 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 6 Sep 2016 15:43:12 +0200 Subject: [PATCH 073/139] update licence --- acb_dirichlet/profile/p-conrey.c | 30 ++++++++-------------------- acb_dirichlet/profile/p-thetanull.c | 30 ++++++++-------------------- acb_dirichlet/profile/p-vec.c | 30 ++++++++-------------------- acb_dirichlet/test/t-chars.c | 31 ++++++++--------------------- acb_dirichlet/test/t-conrey.c | 30 ++++++++-------------------- acb_dirichlet/test/t-dft.c | 30 ++++++++-------------------- acb_dirichlet/test/t-gauss.c | 30 ++++++++-------------------- acb_dirichlet/test/t-jacobi.c | 30 ++++++++-------------------- acb_dirichlet/test/t-l.c | 30 ++++++++-------------------- acb_dirichlet/test/t-thetanull.c | 30 ++++++++-------------------- acb_dirichlet/test/t-vec.c | 30 ++++++++-------------------- dlog/1modpe.c | 30 ++++++++-------------------- dlog/1modpe_init.c | 30 ++++++++-------------------- dlog/1modpe_mod1p.c | 30 ++++++++-------------------- dlog/bsgs.c | 30 ++++++++-------------------- dlog/bsgs_init.c | 31 ++++++++--------------------- dlog/crt.c | 30 ++++++++-------------------- dlog/crt_clear.c | 30 ++++++++-------------------- dlog/crt_init.c | 30 ++++++++-------------------- dlog/factor_group.c | 30 ++++++++-------------------- dlog/mod2e.c | 30 ++++++++-------------------- dlog/modpe.c | 30 ++++++++-------------------- dlog/modpe_init.c | 30 ++++++++-------------------- dlog/order23.c | 30 ++++++++-------------------- dlog/order23_init.c | 30 ++++++++-------------------- dlog/power.c | 30 ++++++++-------------------- dlog/power_init.c | 30 ++++++++-------------------- dlog/precomp.c | 30 ++++++++-------------------- dlog/precomp_clear.c | 30 ++++++++-------------------- dlog/precomp_modpe_init.c | 30 ++++++++-------------------- dlog/precomp_n_init.c | 30 ++++++++-------------------- dlog/precomp_p_init.c | 30 ++++++++-------------------- dlog/precomp_pe_init.c | 30 ++++++++-------------------- dlog/precomp_small_init.c | 30 ++++++++-------------------- dlog/profile/p-precomp.c | 30 ++++++++-------------------- dlog/profile/p-vec.c | 30 ++++++++-------------------- dlog/rho.c | 30 ++++++++-------------------- dlog/rho_init.c | 30 ++++++++-------------------- dlog/table.c | 30 ++++++++-------------------- dlog/table_init.c | 30 ++++++++-------------------- dlog/test/t-dlog.c | 30 ++++++++-------------------- dlog/test/t-modpe.c | 30 ++++++++-------------------- dlog/test/t-vec.c | 30 ++++++++-------------------- dlog/vec.c | 30 ++++++++-------------------- dlog/vec_add.c | 30 ++++++++-------------------- dlog/vec_eratos.c | 30 ++++++++-------------------- dlog/vec_eratos_add.c | 30 ++++++++-------------------- dlog/vec_init.c | 30 ++++++++-------------------- dlog/vec_loop.c | 30 ++++++++-------------------- dlog/vec_loop_add.c | 30 ++++++++-------------------- dlog/vec_pindex_factorgcd.c | 30 ++++++++-------------------- dlog/vec_set_not_found.c | 30 ++++++++-------------------- dlog/vec_sieve.c | 30 ++++++++-------------------- dlog/vec_sieve_add.c | 30 ++++++++-------------------- 54 files changed, 432 insertions(+), 1190 deletions(-) diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c index 3785e073..99bbf184 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/acb_dirichlet/profile/p-conrey.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include #include "acb_dirichlet.h" diff --git a/acb_dirichlet/profile/p-thetanull.c b/acb_dirichlet/profile/p-thetanull.c index 6d77fa92..2754cf92 100644 --- a/acb_dirichlet/profile/p-thetanull.c +++ b/acb_dirichlet/profile/p-thetanull.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/profile/p-vec.c b/acb_dirichlet/profile/p-vec.c index 1ddcabb3..ee2853fa 100644 --- a/acb_dirichlet/profile/p-vec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" #include "profiler.h" diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index a0966555..ac0306e6 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -1,31 +1,16 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" - int main() { slong iter, bits; diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 858edb79..9b39f5c5 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index dd9e00ff..5b45c462 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index a72f72b2..c5c8927c 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/test/t-jacobi.c b/acb_dirichlet/test/t-jacobi.c index 5f7dcaec..59edb173 100644 --- a/acb_dirichlet/test/t-jacobi.c +++ b/acb_dirichlet/test/t-jacobi.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index a4dac51b..6724a27c 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 55c515ed..e9e02905 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/acb_dirichlet/test/t-vec.c b/acb_dirichlet/test/t-vec.c index 9c094c2b..23f3ba56 100644 --- a/acb_dirichlet/test/t-vec.c +++ b/acb_dirichlet/test/t-vec.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "acb_dirichlet.h" diff --git a/dlog/1modpe.c b/dlog/1modpe.c index cf40d58e..a9d12817 100644 --- a/dlog/1modpe.c +++ b/dlog/1modpe.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/1modpe_init.c b/dlog/1modpe_init.c index 2a942143..c8bef0b1 100644 --- a/dlog/1modpe_init.c +++ b/dlog/1modpe_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/1modpe_mod1p.c b/dlog/1modpe_mod1p.c index c1ec0a9d..830e1717 100644 --- a/dlog/1modpe_mod1p.c +++ b/dlog/1modpe_mod1p.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/bsgs.c b/dlog/bsgs.c index 6cd4f62f..b4ff65d3 100644 --- a/dlog/bsgs.c +++ b/dlog/bsgs.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of FLINT. - - FLINT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - FLINT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FLINT; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include #include "dlog.h" diff --git a/dlog/bsgs_init.c b/dlog/bsgs_init.c index e2aa2827..efb07280 100644 --- a/dlog/bsgs_init.c +++ b/dlog/bsgs_init.c @@ -1,28 +1,13 @@ -/*============================================================================= - - This file is part of FLINT. - - FLINT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - FLINT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FLINT; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2013 Mike Hansen +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include #include "dlog.h" diff --git a/dlog/crt.c b/dlog/crt.c index 867b4481..afd3820a 100644 --- a/dlog/crt.c +++ b/dlog/crt.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/crt_clear.c b/dlog/crt_clear.c index 1650118f..5e044687 100644 --- a/dlog/crt_clear.c +++ b/dlog/crt_clear.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/crt_init.c b/dlog/crt_init.c index b249a0aa..beb80649 100644 --- a/dlog/crt_init.c +++ b/dlog/crt_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/factor_group.c b/dlog/factor_group.c index 06349c38..576f7890 100644 --- a/dlog/factor_group.c +++ b/dlog/factor_group.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/mod2e.c b/dlog/mod2e.c index 8622949c..ed051503 100644 --- a/dlog/mod2e.c +++ b/dlog/mod2e.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/modpe.c b/dlog/modpe.c index eeaca2ac..785488d2 100644 --- a/dlog/modpe.c +++ b/dlog/modpe.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/modpe_init.c b/dlog/modpe_init.c index 6332e2e1..24599cdf 100644 --- a/dlog/modpe_init.c +++ b/dlog/modpe_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/order23.c b/dlog/order23.c index ae4d14d3..a9a8c542 100644 --- a/dlog/order23.c +++ b/dlog/order23.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/order23_init.c b/dlog/order23_init.c index 7e822dca..dc4b6847 100644 --- a/dlog/order23_init.c +++ b/dlog/order23_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/power.c b/dlog/power.c index 0096352a..f6f1b8b8 100644 --- a/dlog/power.c +++ b/dlog/power.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/power_init.c b/dlog/power_init.c index a944dd3c..277b6e86 100644 --- a/dlog/power_init.c +++ b/dlog/power_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/precomp.c b/dlog/precomp.c index 8b03ff6b..8e58abf9 100644 --- a/dlog/precomp.c +++ b/dlog/precomp.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/precomp_clear.c b/dlog/precomp_clear.c index bcae2e6e..690c74db 100644 --- a/dlog/precomp_clear.c +++ b/dlog/precomp_clear.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/precomp_modpe_init.c b/dlog/precomp_modpe_init.c index d89b5c62..615ec966 100644 --- a/dlog/precomp_modpe_init.c +++ b/dlog/precomp_modpe_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/precomp_n_init.c b/dlog/precomp_n_init.c index 787f020f..b50faae8 100644 --- a/dlog/precomp_n_init.c +++ b/dlog/precomp_n_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include "math.h" diff --git a/dlog/precomp_p_init.c b/dlog/precomp_p_init.c index 193c55cf..6ed3344d 100644 --- a/dlog/precomp_p_init.c +++ b/dlog/precomp_p_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include "math.h" diff --git a/dlog/precomp_pe_init.c b/dlog/precomp_pe_init.c index ce98ba14..d4820f04 100644 --- a/dlog/precomp_pe_init.c +++ b/dlog/precomp_pe_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/precomp_small_init.c b/dlog/precomp_small_init.c index 6309682e..dc9ddfca 100644 --- a/dlog/precomp_small_init.c +++ b/dlog/precomp_small_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/profile/p-precomp.c b/dlog/profile/p-precomp.c index acfe2e7d..393a99dc 100644 --- a/dlog/profile/p-precomp.c +++ b/dlog/profile/p-precomp.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include #include diff --git a/dlog/profile/p-vec.c b/dlog/profile/p-vec.c index ba04420b..9af48d8d 100644 --- a/dlog/profile/p-vec.c +++ b/dlog/profile/p-vec.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include #include "dlog.h" diff --git a/dlog/rho.c b/dlog/rho.c index 3f0eee30..c49d2bfc 100644 --- a/dlog/rho.c +++ b/dlog/rho.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include diff --git a/dlog/rho_init.c b/dlog/rho_init.c index ae34a392..745dea4f 100644 --- a/dlog/rho_init.c +++ b/dlog/rho_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include diff --git a/dlog/table.c b/dlog/table.c index 9bef0be4..129070c6 100644 --- a/dlog/table.c +++ b/dlog/table.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/table_init.c b/dlog/table_init.c index 54fd707f..2d67feed 100644 --- a/dlog/table_init.c +++ b/dlog/table_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/test/t-dlog.c b/dlog/test/t-dlog.c index a3b9f1fd..1a7daeb4 100644 --- a/dlog/test/t-dlog.c +++ b/dlog/test/t-dlog.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include diff --git a/dlog/test/t-modpe.c b/dlog/test/t-modpe.c index e828dee0..733c6634 100644 --- a/dlog/test/t-modpe.c +++ b/dlog/test/t-modpe.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include diff --git a/dlog/test/t-vec.c b/dlog/test/t-vec.c index 2a766f61..e1b7dfdc 100644 --- a/dlog/test/t-vec.c +++ b/dlog/test/t-vec.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec.c b/dlog/vec.c index 5c386daf..d10d20ef 100644 --- a/dlog/vec.c +++ b/dlog/vec.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_add.c b/dlog/vec_add.c index 77033cab..f1f43329 100644 --- a/dlog/vec_add.c +++ b/dlog/vec_add.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_eratos.c b/dlog/vec_eratos.c index b383c015..67e1eb91 100644 --- a/dlog/vec_eratos.c +++ b/dlog/vec_eratos.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_eratos_add.c b/dlog/vec_eratos_add.c index afedac31..33c26c98 100644 --- a/dlog/vec_eratos_add.c +++ b/dlog/vec_eratos_add.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_init.c b/dlog/vec_init.c index 6a5707c3..31bb4063 100644 --- a/dlog/vec_init.c +++ b/dlog/vec_init.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index d3e568fb..70714db4 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_loop_add.c b/dlog/vec_loop_add.c index bae5a40d..a3628539 100644 --- a/dlog/vec_loop_add.c +++ b/dlog/vec_loop_add.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_pindex_factorgcd.c b/dlog/vec_pindex_factorgcd.c index fa8f23fc..d35a41a8 100644 --- a/dlog/vec_pindex_factorgcd.c +++ b/dlog/vec_pindex_factorgcd.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include diff --git a/dlog/vec_set_not_found.c b/dlog/vec_set_not_found.c index 48a61cb3..d2f46f82 100644 --- a/dlog/vec_set_not_found.c +++ b/dlog/vec_set_not_found.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index d223239d..ce7eb5f6 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" #include diff --git a/dlog/vec_sieve_add.c b/dlog/vec_sieve_add.c index 0b0e15f9..97b8c2a9 100644 --- a/dlog/vec_sieve_add.c +++ b/dlog/vec_sieve_add.c @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #include "dlog.h" From 35cf7579a37bf7262f8ff5f08a5aa9990f0c2158 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 6 Sep 2016 17:00:42 +0200 Subject: [PATCH 074/139] no licence on example --- examples/lcentral.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/examples/lcentral.c b/examples/lcentral.c index e3e41408..de855c0c 100644 --- a/examples/lcentral.c +++ b/examples/lcentral.c @@ -1,27 +1,4 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - - Copyright (C) 2016 Pascal Molin - -******************************************************************************/ +/* This file is public domain. Author: Pascal Molin. */ #include #include "acb_dirichlet.h" From 8834d2bf72ec26bd09c6d61a55354a59c68bc107 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 7 Sep 2016 14:09:05 +0200 Subject: [PATCH 075/139] doc --- doc/source/dlog.rst | 66 ++++++++++++++++++++--------------------- doc/source/examples.rst | 24 +++++++++++++++ doc/source/index.rst | 1 + examples/lcentral.c | 28 +++++++++++------ 4 files changed, 77 insertions(+), 42 deletions(-) diff --git a/doc/source/dlog.rst b/doc/source/dlog.rst index 62fbfb09..31261438 100644 --- a/doc/source/dlog.rst +++ b/doc/source/dlog.rst @@ -19,38 +19,6 @@ No particular effort has been made towards single discrete logarithm computation. Currently only machine size primepower moduli are supported. -Algorithms -------------------------------------------------------------------------------- - -Several discrete logarithms strategies are implemented: - -- complete lookup table for small groups - -- baby-step giant-step table - -combined with mathematical reductions - -- Pohlig-Hellman decomposition (chinese remainder decomposition on the - order of the group and base `p` decomposition for primepower order) - -- p-adic log for primepower modulus `p^e`. - -For *dlog_vec* functions which compute the vector of discrete logarithms -of successive integers `1\dots n`: - -- a simple loop on group elements avoiding all logarithms is done when - the group size is comparable with the number of elements requested - -- otherwise the logarithms are computed on primes and propagated by - Eratosthene-like sieving on composite numbers. - -- when several logarithms are already computed, a basic smoothing technique - inspired by index-calculus is adopted to obtain larger logs from - smaller ones. - -- in the the present implementation, the full index-calculus method is not - implemented. - Types, macros and constants ------------------------------------------------------------------------------- @@ -115,6 +83,38 @@ Vector evaluations .. function:: void dlog_vec_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) - same parameters as before, but adds `\log(k,a)` times value *va* + same parameters as before, but adds `\log(k,a)\times v_a` to *v[k]* and reduce modulo *order* instead of replacing the value. Indices *k* such that *v[k]* equals *DLOG_NONE* are ignored. + +Algorithms +------------------------------------------------------------------------------- + +Several discrete logarithms strategies are implemented: + +- complete lookup table for small groups + +- baby-step giant-step table + +combined with mathematical reductions + +- Pohlig-Hellman decomposition (chinese remainder decomposition on the + order of the group and base `p` decomposition for primepower order) + +- p-adic log for primepower modulus `p^e`. + +For *dlog_vec* functions which compute the vector of discrete logarithms +of successive integers `1\dots n`: + +- a simple loop on group elements avoiding all logarithms is done when + the group size is comparable with the number of elements requested + +- otherwise the logarithms are computed on primes and propagated by + Eratosthene-like sieving on composite numbers. + +- when several logarithms are already computed, a basic smoothing technique + inspired by index-calculus is adopted to obtain larger logs from + smaller ones. + +- in the the present implementation, the full index-calculus method is not + implemented. diff --git a/doc/source/examples.rst b/doc/source/examples.rst index 35630033..77d490f1 100644 --- a/doc/source/examples.rst +++ b/doc/source/examples.rst @@ -445,4 +445,28 @@ a portion of the critical strip with imaginary part between 100 and 140:: > build/examples/complex_plot zeta -range -10 10 100 140 -size 256 512 +lcentral.c +------------------------------------------------------------------------------- +This program computes the central value of Dirichlet L functions for all +primitive Dirichlet characters in some conductor range. + +Its arguments take the form:: + + > build/examples/lcentral [--quiet] [--prec ] qmin qmax + +The values are indexed by (conductor,index) pairs, sample output:: + + > build/examples/lcentral 3 8 + 3,2: (0.480867557696828626181220063235 + 0j) +/- (2.23e-30, 0j) + 4,3: (0.6676914571896091766586909293 + 0j) +/- (9.87e-31, 0j) + 5,2: (0.763747880117286878224512152639 + 0.216964767518860693638586593098j) +/- (1.04e-30, 6.72e-31j) + 5,4: (0.231750947504015755883383661761 + 0j) +/- (1.52e-30, 0j) + 5,3: (0.763747880117286878224512152639 - 0.216964767518860693638586593098j) +/- (1.04e-30, 6.72e-31j) + 7,3: (0.71394334376831949285993820742 + 0.474902182771399382637452439346j) +/- (1.15e-30, 8.87e-31j) + 7,2: (0.310089362598367660591950525344 - 0.0726419313701779052456217124547j) +/- (1.14e-30, 8.51e-31j) + 7,6: (1.14658566690370833367712697646 + 0j) +/- (1.56e-30, 0j) + 7,4: (0.310089362598367660591950525344 + 0.0726419313701779052456217124547j) +/- (1.15e-30, 8.87e-31j) + 7,5: (0.71394334376831949285993820742 - 0.474902182771399382637452439346j) +/- (1.19e-30, 8.51e-31j) + 8,5: (0.373691712912547307381586950023 + 0j) +/- (1.07e-30, 0j) + 8,3: (1.10042140952554837756713576997 + 0j) +/- (1.46e-30, 0j) diff --git a/doc/source/index.rst b/doc/source/index.rst index 42503344..6b8b1264 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -146,6 +146,7 @@ Mainly for internal use. fmpz_extras.rst bool_mat.rst + dlog.rst fmpr.rst Supplementary algorithm notes diff --git a/examples/lcentral.c b/examples/lcentral.c index de855c0c..f9ead358 100644 --- a/examples/lcentral.c +++ b/examples/lcentral.c @@ -1,8 +1,15 @@ /* This file is public domain. Author: Pascal Molin. */ #include +#include #include "acb_dirichlet.h" +static int usage(char *argv[]) +{ + printf("usage: %s [--quiet] [--prec ] qmin qmax\n", argv[0]); + return 1; +} + int main(int argc, char *argv[]) { int i, out = 1; @@ -11,22 +18,25 @@ int main(int argc, char *argv[]) acb_t s; if (argc < 3) - { - printf("usage: %s [--quiet] qmin qmax\n", argv[0]); - return 1; - } + return usage(argv); + for (i = 1; i < argc - 2; i++) { if (!strcmp(argv[i],"--quiet")) out = 0; - /* - else if (!strcmp(argv[i],"--algo")) + else if (!strcmp(argv[i],"--prec")) { + i++; + prec = atol(argv[i]); + digits = floor(prec * 0.3); } - */ } - qmin = atol(argv[i++]); - qmax = atol(argv[i++]); + + if (argc < i + 2) + return usage(argv); + + qmin = atol(argv[i]); + qmax = atol(argv[i+1]); fflush(stdout); From 72eca692af52d53b8d20a738e89584eb71d32481 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 7 Sep 2016 14:09:28 +0200 Subject: [PATCH 076/139] profile conrey+conductor --- acb_dirichlet.h | 1 + acb_dirichlet/profile/p-conrey.c | 67 +++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index f73fd2c8..bf9480df 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -123,6 +123,7 @@ int acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_c int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); +ulong acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c index 99bbf184..3d2c068d 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/acb_dirichlet/profile/p-conrey.c @@ -111,14 +111,69 @@ do_gcdpluscond(ulong q1, ulong q2) return n; } +static ulong +do_conreypluscond(ulong q1, ulong q2) +{ + ulong n, q, k; + + for (n = 0, q = q1; q <= q2; q++) + { + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + + acb_dirichlet_conrey_one(x, G); + n++; + + for (; acb_dirichlet_conrey_next(x, G) >= 0; n++) + acb_dirichlet_conrey_conductor(G, x); + + acb_dirichlet_conrey_clear(x); + acb_dirichlet_group_clear(G); + + } + + return n; +} + +static ulong +do_conreyplusorder(ulong q1, ulong q2) +{ + ulong n, q, k; + + for (n = 0, q = q1; q <= q2; q++) + { + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + + acb_dirichlet_conrey_one(x, G); + n++; + + for (; acb_dirichlet_conrey_next(x, G) >= 0; n++) + acb_dirichlet_conrey_order(G, x); + + acb_dirichlet_conrey_clear(x); + acb_dirichlet_group_clear(G); + + } + + return n; +} int main(int argc, char *argv[]) { int out; ulong n, nref, maxq = 5000; - int l, nf = 4; - do_f func[4] = { do_gcd, do_conrey, do_chars, do_gcdpluscond }; - char * name[4] = { "gcd", "conrey", "chars", "gcd+cond" }; + int l, nf = 6; + do_f func[6] = { do_gcd, do_conrey, do_chars, + do_gcdpluscond, do_conreypluscond, do_conreyplusorder }; + char * name[6] = { "gcd", "conrey", "chars", + "gcd + cond", "conrey + cond", "conrey + order" }; int i, ni = 5; ulong qmin[5] = { 2, 1000, 10000, 100000, 1000000 }; @@ -139,7 +194,7 @@ int main(int argc, char *argv[]) } if (out == CSV) - flint_printf("# %-6s, %7s, %7s, %7s\n","name", "qmin", "qmax", "time"); + flint_printf("# %-12s, %7s, %7s, %7s\n","name", "qmin", "qmax", "time"); for (i = 0; i < ni; i++) { @@ -153,9 +208,9 @@ int main(int argc, char *argv[]) { if (out == LOG) - flint_printf("%-8s ... ",name[l]); + flint_printf("%-14s ... ",name[l]); else if (out == CSV) - flint_printf("%-8s, %7d, %7d, ",name[l],qmin[i],qmax[i]); + flint_printf("%-12s, %7d, %7d, ",name[l],qmin[i],qmax[i]); else if (out == JSON) flint_printf("{ \"name\": \"%s\", \"qmin\": %d, \"qmax\": %d, \"time\": ", name[l],qmin[i],qmax[i]); From 1986f56b3787d25771cb2fc38ab9a999c3a9d2dc Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Thu, 8 Sep 2016 15:47:38 +0200 Subject: [PATCH 077/139] add missing return EXIT_SUCCESS; --- acb_dirichlet/test/t-dft.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 5b45c462..03ea4c3f 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -147,4 +147,6 @@ int main() flint_randclear(state); flint_printf("PASS\n"); + return EXIT_SUCCESS; } + From 259d0bc0a3908be3eff36a645dabfb34980b5eb4 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Thu, 8 Sep 2016 15:50:52 +0200 Subject: [PATCH 078/139] missing flint_cleanup --- acb_dirichlet/test/t-dft.c | 1 + 1 file changed, 1 insertion(+) diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 03ea4c3f..aed49e38 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -146,6 +146,7 @@ int main() } flint_randclear(state); + flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; } From cec0d2c95b5b0efdfcd0ac7b1f1c73cf93f5caf2 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Thu, 8 Sep 2016 16:53:21 +0200 Subject: [PATCH 079/139] edit documentation --- doc/source/acb_dirichlet.rst | 89 ++++++++++++++++++------------------ doc/source/credits.rst | 11 +++-- doc/source/dlog.rst | 32 ++++++------- 3 files changed, 67 insertions(+), 65 deletions(-) diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 3b6b15b2..49b57f00 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -3,17 +3,11 @@ **acb_dirichlet.h** -- Dirichlet L-functions, zeta functions, and related functions =================================================================================== -Warning: the interfaces in this module are experimental and may change -without notice. - -This module will eventually allow working with Dirichlet L-functions and -possibly slightly more general Dirichlet series. At the moment, it contains -nothing interesting. - -The code in other modules for computing the Riemann zeta function, -Hurwitz zeta function and polylogarithm will possibly be migrated to this -module in the future. +*Warning: the interfaces in this module are experimental and may change +without notice.* +This module allows working with Dirichlet characters, Dirichlet L-functions, +and related functions. A Dirichlet L-function is the analytic continuation of an L-series .. math :: @@ -22,6 +16,10 @@ A Dirichlet L-function is the analytic continuation of an L-series where `\chi(k)` is a Dirichlet character. +The code in other modules for computing the Riemann zeta function, +Hurwitz zeta function and polylogarithm will possibly be migrated to this +module in the future. + Multiplicative group modulo *q* ------------------------------------------------------------------------------- @@ -152,18 +150,18 @@ Character type An *acb_dirichlet_char_t* is defined as an array of *acb_dirichlet_char_struct* of length 1, permitting it to be passed by reference. -.. function:: void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); +.. function:: void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) -.. function:: void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); +.. function:: void acb_dirichlet_char_clear(acb_dirichlet_char_t chi) Initializes and clear *chi*. -.. function:: void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); +.. function:: void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) Sets *chi* to the Dirichlet character of number *n*, using Conrey numbering scheme. This function performs a discrete logarithm in *G*. -.. function:: void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); +.. function:: void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) Sets *chi* to the Dirichlet character of Conrey index *x*. @@ -171,7 +169,7 @@ Character properties ------------------------------------------------------------------------------- As a consequence of the Conrey numbering, all these numbers are available at the -level off *number* and *index*, and for *char*. +level of *number* and *index*, and for *char*. No discrete log computation is performed. .. function:: ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) @@ -184,7 +182,7 @@ No discrete log computation is performed. .. function:: ulong acb_dirichlet_char_conductor(const acb_dirichlet_char_t chi) - return the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` + Return the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` such `\chi_q(a,\cdot)` can be obtained as a character mod `r`. This number is precomputed for the *char* type. @@ -194,7 +192,7 @@ No discrete log computation is performed. .. function:: int acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) - return the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that + Return the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that `\chi_q(a,-1)=(-1)^\lambda`. This number is precomputed for the *char* type. @@ -204,7 +202,7 @@ No discrete log computation is performed. .. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) - return the order of `\chi_q(a,\cdot)` which is the order of `a\mod q`. + Return the order of `\chi_q(a,\cdot)` which is the order of `a\mod q`. This number is precomputed for the *char* type. Character evaluation @@ -218,7 +216,7 @@ unity. .. function:: ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) - compute that value `\chi(a)` as the exponent mod the order of `\chi`. + Compute that value `\chi(a)` as the exponent mod the order of `\chi`. .. function:: void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) @@ -232,7 +230,7 @@ Roots of unity .. function:: void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) - sets *res* to `\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. + Sets *res* to `\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. .. function:: void acb_dirichlet_vec_nth_roots(acb_ptr z, slong order, slong prec) @@ -244,61 +242,61 @@ Roots of unity .. type:: acb_dirichlet_powers_t - this structure allows to compute *n* powers of a fixed root of unity of order *m* + This structure allows to compute *n* powers of a fixed root of unity of order *m* using precomputations. Extremal cases are - - all powers are stored: `O(m)` initialization + storage, `O(n)` eval + - all powers are stored: `O(m)` initialization + storage, `O(n)` evaluations - - nothing stored: `O(1)` initialization + storage, `O(\log(m)n)` eval + - nothing stored: `O(1)` initialization + storage, `O(\log(m)n)` evaluations - - `k` step decomposition: `O(k m^{\frac1k})` init + storage, `O((k-1)n)` eval. + - `k` step decomposition: `O(k m^{\frac1k})` init + storage, `O((k-1)n)` evaluations. Currently, only baby-step giant-step decomposition (i.e. `k=2`) is implemented, allowing to obtain each power using one multiplication. .. function:: void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec) - initialize the powers structure for *num* evaluations of powers of the root of unity + Initialize the powers structure for *num* evaluations of powers of the root of unity of order *order*. .. function:: void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t) - clears *t*. + Clears *t*. .. function:: void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec) - sets *z* to `x^n` where *t* contains precomputed powers of `x`. + Sets *z* to `x^n` where *t* contains precomputed powers of `x`. Vector evaluation ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_ui_chi_vec(ulong * v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) - compute the list of exponent values *v[k]* for `0\leq k < nv` + Compute the list of exponent values *v[k]* for `0\leq k < nv`. .. function:: void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec) - compute the *nv* first Dirichlet values + Compute the *nv* first Dirichlet values. -Operations +Character operations ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) .. function:: void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) - multiply two characters in the same group + Multiply two characters in the same group. .. function:: void acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n) - take the power of some character + Take the power of some character. Gauss and Jacobi sums ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) - compute the Gauss sum + Compute the Gauss sum .. math:: @@ -306,7 +304,7 @@ Gauss and Jacobi sums .. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) - compute the Jacobi sum + Compute the Jacobi sum .. math:: @@ -315,7 +313,7 @@ Gauss and Jacobi sums Theta sums ------------------------------------------------------------------------------- -We call Theta series of a Dirichlet character the quadratic series +We call *theta series* of a Dirichlet character the quadratic series .. math:: @@ -333,7 +331,7 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define .. function:: void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); - compute the theta series `\Theta_q(a,t)` for real argument `t>0`. + Compute the theta series `\Theta_q(a,t)` for real argument `t>0`. Beware that if `t<1` the functional equation .. math:: @@ -345,14 +343,14 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define .. function:: ulong acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec) - compute the number of terms to be summed in the theta series of argument *t* + Compute the number of terms to be summed in the theta series of argument *t* so that the tail is less than `2^{-\mathrm{prec}}`. .. function:: void acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) .. function:: void acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) - compute the series `\sum n^p z^{a_n} x^{n^2}` for exponent list *a*, + Compute the series `\sum n^p z^{a_n} x^{n^2}` for exponent list *a*, precomputed powers *z* and parity *p* (being 0 or 1). The *naive* version sums the series as defined, while the *smallorder* @@ -384,7 +382,7 @@ the Fourier transform on Conrey labels as .. function:: void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) - Compute the DFT of *v* using conrey indices. + Compute the DFT of *v* using Conrey indices. This function assumes *v* and *w* are vectors of size *G->phi_q*, whose values correspond to a lexicographic ordering of Conrey indices. @@ -393,7 +391,7 @@ the Fourier transform on Conrey labels as order ============ ===================== - index [e,f] number = 7^e11^f + index [e,f] number = 7^e 11^f ============ ===================== [0, 0] 1 [0, 1] 7 @@ -450,7 +448,7 @@ Simple functions Note that the alternating character `\{1,-1\}` is not itself a Dirichlet character. -L functions +L-functions ------------------------------------------------------------------------------- .. function:: void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) @@ -476,11 +474,12 @@ Implementation notes The current implementation introduces a *char* type which contains a *conrey* index plus additional information which -- make evaluation of a single character a bit faster +- makes evaluation of a single character a bit faster -- have some initialization cost. +- has some initialization cost. -Even if it is straiforward to convert a *conrey* index to the +Even if it is straightforward to convert a *conrey* index to the corresponding *char*, looping is faster at the -level of conrey representation. Things can be improved on this aspect +level of Conrey representation. Things can be improved on this aspect but it makes code more intricate. + diff --git a/doc/source/credits.rst b/doc/source/credits.rst index f3edf2a8..2b1699dc 100644 --- a/doc/source/credits.rst +++ b/doc/source/credits.rst @@ -34,13 +34,18 @@ Fredrik Johansson is the main author. The project was started in 2012 as a numerical extension of FLINT, and the initial design was heavily based on FLINT 2.0 (with particular credit to Bill Hart and Sebastian Pancratz). +The following authors have developed major new features. + +* Pascal Molin - Dirichlet characters, Dirichlet L-functions, discrete logarithm computation +* Alex Griffing - sinc function, matrix trace, improved matrix squaring, boolean matrices, improved structured matrix exponentials, Cholesky decomposition, miscellaneous patches + Several people have contributed patches, bug reports, or substantial feedback. -This list is probably incomplete. +This list (ordered by time of first contribution) is probably incomplete. * Bill Hart - build system, Windows 64 support, design of FLINT * Sebastian Pancratz - divide-and-conquer polynomial composition algorithm (taken from FLINT) * The MPFR development team - Arb includes two-limb multiplication code taken from MPFR -* Jonathan Bober - Dirichlet characters (the code in Arb is based on his Cython implementation), C++ compatibility fixes +* Jonathan Bober - original code for Dirichlet characters, C++ compatibility fixes * Yuri Matiyasevich - feedback about the zeta function and root-finding code * Abhinav Baid - dot product and norm functions * Ondřej Čertík - bug reports, feedback @@ -48,14 +53,12 @@ This list is probably incomplete. * Francesco Biscani - C++ compatibility fixes, feedback * Clemens Heuberger - work on Arb interface in Sage, feedback * Marc Mezzarobba - work on Arb interface in Sage, bug reports, feedback -* Pascal Molin - feedback * Ricky Farr - convenience functions, feedback * Marcello Seri - fix for static builds on OS X * Tommy Hofmann - matrix transpose, comparison, other utility methods, Julia interface * Alexander Kobel - documentation and code cleanup patches * Hrvoje Abraham - patches for MinGW compatibility * Julien Puydt - soname versioning support -* Alex Griffing - sinc function, matrix trace, improved matrix squaring, boolean matrices, improved structured matrix exponentials, Cholesky decomposition, miscellaneous patches * Jeroen Demeyer - patch for major bug on PPC64 Funding diff --git a/doc/source/dlog.rst b/doc/source/dlog.rst index 31261438..b146ea01 100644 --- a/doc/source/dlog.rst +++ b/doc/source/dlog.rst @@ -3,8 +3,8 @@ **dlog.h** -- discrete logarithms mod ulong primes =============================================================================== -This module implements discrete logarithms, with in mind the application -to Dirichlet characters. +This module implements discrete logarithms, with the application +to Dirichlet characters in mind. In particular, this module defines a :type:`dlog_precomp_t` structure permitting to describe a discrete log problem in some subgroup @@ -24,38 +24,38 @@ Types, macros and constants .. macro:: DLOG_NONE - return value when the discrete logarithm does not exist + Return value when the discrete logarithm does not exist .. type:: dlog_precomp_struct .. type:: dlog_precomp_t - structure for discrete logarithm precomputed data. + Structure for discrete logarithm precomputed data. .. function:: void dlog_precomp_clear(dlog_precomp_t pre) Precomputations ------------------------------------------------------------------------------- -.. function:: void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num); +.. function:: void dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) - precompute data for *num* discrete logarithms evaluations in the subgroup generated + Precompute data for *num* discrete logarithms evaluations in the subgroup generated by *a* modulo *mod*, where *a* is known to have order *n*. Specialized versions are available when specific information is known about the group: -.. function:: void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num); +.. function:: void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) - assume that *a* generates the group of residues modulo `p^e`. + Assume that *a* generates the group of residues modulo `p^e`. -.. function:: void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num); +.. function:: void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) - assume that *a* has prime order *p*. + Assume that *a* has prime order *p*. -.. function:: void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num); +.. function:: void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) - assume that *a* has primepower order *p*. + Assume that *a* has primepower order *p*. Single evaluation @@ -63,22 +63,22 @@ Single evaluation .. function:: ulong dlog_precomp(const dlog_precomp_t pre, ulong b) - returns `\log(b)` for the group described in *pre* + Returns `\log(b)` for the group described in *pre* Vector evaluations ------------------------------------------------------------------------------- -.. function:: void dlog_vec_fill(ulong * v, ulong nv, ulong x); +.. function:: void dlog_vec_fill(ulong * v, ulong nv, ulong x) Sets values *v[k]* to *x* for all *k* less than *nv*. -.. function:: void dlog_vec_set_not_found(ulong * v, ulong nv, nmod_t mod); +.. function:: void dlog_vec_set_not_found(ulong * v, ulong nv, nmod_t mod) Sets values *v[k]* to :macro:`DLOG_NONE` for all *k* not coprime to *mod*. .. function:: void dlog_vec(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) - sets *v[k]* to `\log(k,a)` times value *va* for `0\leq k < nv`, where *a* + Sets *v[k]* to `\log(k,a)` times value *va* for `0\leq k < nv`, where *a* has order *na*. *va* should be *1* for usual log computation. .. function:: void dlog_vec_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) From 54a5dd859d21239de0084084ab39312b02b2c87a Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 8 Sep 2016 18:01:09 +0200 Subject: [PATCH 080/139] refactor and add errors to theta series --- acb_dirichlet.h | 10 +- acb_dirichlet/arb_theta_naive.c | 50 ------- acb_dirichlet/chi_theta_arb.c | 131 ------------------ acb_dirichlet/gauss_sum_theta.c | 2 +- .../{qseries_eval_arb.c => qseries_arb.c} | 4 +- ...heta_smallorder.c => qseries_arb_powers.c} | 39 +++++- acb_dirichlet/theta_arb.c | 93 +++++++++++++ acb_dirichlet/theta_length.c | 38 +++++ acb_dirichlet/ui_theta_arb.c | 2 +- acb_dirichlet/vec_mellin_arb.c | 56 ++++++++ 10 files changed, 235 insertions(+), 190 deletions(-) delete mode 100644 acb_dirichlet/arb_theta_naive.c delete mode 100644 acb_dirichlet/chi_theta_arb.c rename acb_dirichlet/{qseries_eval_arb.c => qseries_arb.c} (87%) rename acb_dirichlet/{arb_theta_smallorder.c => qseries_arb_powers.c} (60%) create mode 100644 acb_dirichlet/theta_arb.c create mode 100644 acb_dirichlet/vec_mellin_arb.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index bf9480df..361336f2 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -234,14 +234,16 @@ void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_diric void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec); void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); -void acb_dirichlet_qseries_eval_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec); +void acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec); +void acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); +void acb_dirichlet_qseries_arb_powers(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec); ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec); -void acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); -void acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); +void mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n); -void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); +void _acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slong prec); +void acb_dirichlet_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); diff --git a/acb_dirichlet/arb_theta_naive.c b/acb_dirichlet/arb_theta_naive.c deleted file mode 100644 index f9cb5b37..00000000 --- a/acb_dirichlet/arb_theta_naive.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" -#include "acb_poly.h" - -void -acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) -{ - slong k; - arb_t xk2, dx, x2; - acb_t zk; - arb_init(xk2); - arb_init(dx); - arb_init(x2); - acb_init(zk); - - arb_set(dx, x); - arb_set(xk2, dx); - arb_mul(x2, dx, dx, prec); - - acb_set_arb(res, xk2); - - /* TODO: reduce prec */ - for (k = 2; k < len; k++) - { - arb_mul(dx, dx, x2, prec); - arb_mul(xk2, xk2, dx, prec); - if (a[k] != ACB_DIRICHLET_CHI_NULL) - { - acb_dirichlet_power(zk, z, a[k], prec); - if (parity) - acb_mul_si(zk, zk, k, prec); - acb_addmul_arb(res, zk, xk2, prec); - } - } - - arb_clear(xk2); - arb_clear(x2); - arb_clear(dx); - acb_clear(zk); -} diff --git a/acb_dirichlet/chi_theta_arb.c b/acb_dirichlet/chi_theta_arb.c deleted file mode 100644 index f89ff841..00000000 --- a/acb_dirichlet/chi_theta_arb.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" -#include "acb_poly.h" - -/* x(t) = exp(-Pi / q * t^2) */ -static void -acb_dirichlet_arb_theta_xt(arb_t xt, ulong q, const arb_t t, slong prec) -{ - arb_const_pi(xt, prec); - arb_div_ui(xt, xt, q, prec); - arb_mul(xt, xt, t, prec); - arb_mul(xt, xt, t, prec); - arb_neg(xt, xt); - arb_exp(xt, xt, prec); -} - -void -acb_dirichlet_chi_theta_arb_smallorder(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) -{ - ulong * a; - acb_dirichlet_powers_t z; - - a = flint_malloc(len * sizeof(ulong)); - acb_dirichlet_ui_chi_vec(a, G, chi, len); - - _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); - acb_dirichlet_arb_theta_smallorder(res, xt, chi->parity, a, z, len, prec); - acb_dirichlet_powers_clear(z); - - flint_free(a); -} - -void -acb_dirichlet_chi_theta_arb_series(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) -{ - acb_ptr a; - a = _acb_vec_init(len); - acb_dirichlet_chi_vec(a, G, chi, len, prec); - if (chi->parity) - { - slong k; - for (k = 2; k < len; k++) - acb_mul_si(a + k, a + k, k, prec); - } - acb_dirichlet_qseries_eval_arb(res, a, xt, len, prec); - _acb_vec_clear(a, len); -} - -void -acb_dirichlet_vec_mellin_series(acb_ptr res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong len, const arb_t t, slong n, slong prec) -{ - slong k; - arb_t tk, xt, stk, st; - acb_ptr a; - a = _acb_vec_init(len); - acb_dirichlet_chi_vec(a, G, chi, len, prec); - if (chi->parity) - { - for (k = 2; k < len; k++) - acb_mul_si(a + k, a + k, k, prec); - } - arb_init(tk); - arb_init(xt); - arb_init(st); - arb_init(stk); - - arb_sqrt(st, t, prec); - arb_one(tk); - arb_one(stk); - for (k = 0; k < n; k++) - { - acb_dirichlet_arb_theta_xt(xt, G->q, tk, prec); - /* TODO: reduce len */ - acb_dirichlet_qseries_eval_arb(res + k, a, xt, len, prec); - acb_mul_arb(res + k, res + k, stk, prec); - arb_mul(tk, tk, t, prec); - arb_mul(stk, stk, st, prec); - } - arb_clear(xt); - arb_clear(tk); - arb_clear(stk); - arb_clear(st); - _acb_vec_clear(a, len); -} - -void -acb_dirichlet_chi_theta_arb_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) -{ - ulong * a; - acb_dirichlet_powers_t z; - - a = flint_malloc(len * sizeof(ulong)); - acb_dirichlet_ui_chi_vec(a, G, chi, len); - - acb_dirichlet_powers_init(z, chi->order.n, len, prec); - - acb_dirichlet_arb_theta_naive(res, xt, chi->parity, a, z, len, prec); - - acb_dirichlet_powers_clear(z); - flint_free(a); -} - -void -acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) -{ - slong len; - arb_t xt; - - len = acb_dirichlet_theta_length(G->q, t, prec); - - arb_init(xt); - acb_dirichlet_arb_theta_xt(xt, G->q, t, prec); - - /* TODO: tune this limit */ - if (chi->order.n < 30) - acb_dirichlet_chi_theta_arb_smallorder(res, G, chi, xt, len, prec); - else - acb_dirichlet_chi_theta_arb_naive(res, G, chi, xt, len, prec); - - arb_clear(xt); -} diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index 72be2601..ac83b34f 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -28,7 +28,7 @@ acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const ac } arb_one(x); - acb_dirichlet_chi_theta_arb(res, G, chi, x, prec); + acb_dirichlet_theta_arb(res, G, chi, x, prec); acb_init(eps); acb_conj(eps, res); acb_div(eps, res, eps, prec); diff --git a/acb_dirichlet/qseries_eval_arb.c b/acb_dirichlet/qseries_arb.c similarity index 87% rename from acb_dirichlet/qseries_eval_arb.c rename to acb_dirichlet/qseries_arb.c index 6d7f5bb1..a152c95f 100644 --- a/acb_dirichlet/qseries_eval_arb.c +++ b/acb_dirichlet/qseries_arb.c @@ -11,9 +11,9 @@ #include "acb_dirichlet.h" -/* assume a[0] = 0 */ +/* sum a_k x^(k^2), assume a[0] = 0 */ void -acb_dirichlet_qseries_eval_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec) +acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec) { slong k; arb_t xk2, dx, x2; diff --git a/acb_dirichlet/arb_theta_smallorder.c b/acb_dirichlet/qseries_arb_powers.c similarity index 60% rename from acb_dirichlet/arb_theta_smallorder.c rename to acb_dirichlet/qseries_arb_powers.c index d9823df5..dc086696 100644 --- a/acb_dirichlet/arb_theta_smallorder.c +++ b/acb_dirichlet/qseries_arb_powers.c @@ -12,9 +12,46 @@ #include "acb_dirichlet.h" #include "acb_poly.h" +void +acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) +{ + slong k; + arb_t xk2, dx, x2; + acb_t zk; + arb_init(xk2); + arb_init(dx); + arb_init(x2); + acb_init(zk); + + arb_set(dx, x); + arb_set(xk2, dx); + arb_mul(x2, dx, dx, prec); + + acb_set_arb(res, xk2); + + /* TODO: reduce prec */ + for (k = 2; k < len; k++) + { + arb_mul(dx, dx, x2, prec); + arb_mul(xk2, xk2, dx, prec); + if (a[k] != ACB_DIRICHLET_CHI_NULL) + { + acb_dirichlet_power(zk, z, a[k], prec); + if (parity) + acb_mul_si(zk, zk, k, prec); + acb_addmul_arb(res, zk, xk2, prec); + } + } + + arb_clear(xk2); + arb_clear(x2); + arb_clear(dx); + acb_clear(zk); +} + /* small order, multiply by chi at the end */ void -acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) +acb_dirichlet_qseries_arb_powers(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) { slong k; ulong order = z->order; diff --git a/acb_dirichlet/theta_arb.c b/acb_dirichlet/theta_arb.c new file mode 100644 index 00000000..dea7ef53 --- /dev/null +++ b/acb_dirichlet/theta_arb.c @@ -0,0 +1,93 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" +#include "acb_poly.h" + +void +_acb_dirichlet_theta_arb_smallorder(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +{ + ulong * a; + acb_dirichlet_powers_t z; + + a = flint_malloc(len * sizeof(ulong)); + acb_dirichlet_ui_chi_vec(a, G, chi, len); + + _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); + acb_dirichlet_qseries_arb_powers(res, xt, chi->parity, a, z, len, prec); + acb_dirichlet_powers_clear(z); + + flint_free(a); +} + +void +_acb_dirichlet_theta_arb_series(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +{ + acb_ptr a; + a = _acb_vec_init(len); + acb_dirichlet_chi_vec(a, G, chi, len, prec); + if (chi->parity) + { + slong k; + for (k = 2; k < len; k++) + acb_mul_si(a + k, a + k, k, prec); + } + acb_dirichlet_qseries_arb(res, a, xt, len, prec); + _acb_vec_clear(a, len); +} + +void +_acb_dirichlet_theta_arb_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +{ + ulong * a; + acb_dirichlet_powers_t z; + + a = flint_malloc(len * sizeof(ulong)); + acb_dirichlet_ui_chi_vec(a, G, chi, len); + + acb_dirichlet_powers_init(z, chi->order.n, len, prec); + + acb_dirichlet_qseries_arb_powers_naive(res, xt, chi->parity, a, z, len, prec); + + acb_dirichlet_powers_clear(z); + flint_free(a); +} + +void +acb_dirichlet_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) +{ + slong len; + 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 */ + if (chi->order.n < 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); + arb_clear(xt); +} diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c index e0534806..1f58b1be 100644 --- a/acb_dirichlet/theta_length.c +++ b/acb_dirichlet/theta_length.c @@ -37,3 +37,41 @@ acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec) arf_clear(at); return len; } + +/* bound for sum_{k>n} k*exp(-a k^2) */ +void +mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n) +{ + mag_t m; + mag_init(m); + arb_get_mag_lower(m, a); + /* a < 1/4 ? */ + if (mag_cmp_2exp_si(m, -2) <= 0) + { + mag_t c; + mag_init(c); + mag_mul_ui(c, m, 2); + mag_addmul(c, c, c); + mag_mul_ui(res, m, n*n-n+1); + mag_expinv(res, res); + mag_div(res, res, c); + mag_clear(c); + } + else + { + mag_mul_ui(res, m, n*n-n-1); + mag_expinv(res, res); + mag_mul_ui(res, res, 2); + } + mag_clear(m); +} + +/* a(t) = Pi / q * t^2 */ +void +_acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slong prec) +{ + arb_const_pi(xt, prec); + arb_div_ui(xt, xt, q, prec); + arb_mul(xt, xt, t, prec); + arb_mul(xt, xt, t, prec); +} diff --git a/acb_dirichlet/ui_theta_arb.c b/acb_dirichlet/ui_theta_arb.c index 1477006a..5679d695 100644 --- a/acb_dirichlet/ui_theta_arb.c +++ b/acb_dirichlet/ui_theta_arb.c @@ -19,7 +19,7 @@ acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, co acb_dirichlet_char_init(chi, G); acb_dirichlet_char(chi, G, a); - acb_dirichlet_chi_theta_arb(res, G, chi, t, prec); + acb_dirichlet_theta_arb(res, G, chi, t, prec); acb_dirichlet_char_clear(chi); } diff --git a/acb_dirichlet/vec_mellin_arb.c b/acb_dirichlet/vec_mellin_arb.c new file mode 100644 index 00000000..15308e16 --- /dev/null +++ b/acb_dirichlet/vec_mellin_arb.c @@ -0,0 +1,56 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_vec_mellin_arb(acb_ptr res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong len, const arb_t t, slong n, slong prec) +{ + slong k; + arb_t tk, xt, stk, st; + acb_ptr a; + mag_t e; + a = _acb_vec_init(len); + acb_dirichlet_chi_vec(a, G, chi, len, prec); + if (chi->parity) + { + for (k = 2; k < len; k++) + acb_mul_si(a + k, a + k, k, prec); + } + arb_init(tk); + arb_init(xt); + arb_init(st); + arb_init(stk); + mag_init(e); + + arb_sqrt(st, t, prec); + arb_one(tk); + arb_one(stk); + for (k = 0; k < n; k++) + { + _acb_dirichlet_theta_argument_at_arb(xt, G->q, tk, prec); + mag_tail_kexpk2_arb(e, xt, len); + arb_neg(xt, xt); + arb_exp(xt, xt, prec); + /* TODO: reduce len */ + acb_dirichlet_qseries_arb(res + k, a, xt, len, prec); + acb_add_error_mag(res + k, e); + acb_mul_arb(res + k, res + k, stk, prec); + arb_mul(tk, tk, t, prec); + arb_mul(stk, stk, st, prec); + } + mag_clear(e); + arb_clear(xt); + arb_clear(tk); + arb_clear(stk); + arb_clear(st); + _acb_vec_clear(a, len); +} From 24c36d4798a71c71c0c88a0c2b469a86c42ffd50 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 09:27:49 +0200 Subject: [PATCH 081/139] fix unused variables --- acb_dirichlet/conrey_primitive.c | 2 +- dlog/vec_sieve.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/acb_dirichlet/conrey_primitive.c b/acb_dirichlet/conrey_primitive.c index 5f86c7be..3961bcea 100644 --- a/acb_dirichlet/conrey_primitive.c +++ b/acb_dirichlet/conrey_primitive.c @@ -14,7 +14,7 @@ void acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, ulong cond) { - int k, l, f; + slong k, l; l = 0; if (cond % 4 == 0) diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index ce7eb5f6..67d5215a 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -19,7 +19,10 @@ void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; - ulong logcost, limcount; + ulong logcost; +#if 0 + ulong limcount; +#endif ulong k, p, p1, pmax, logm1; dlog_precomp_t pre; n_primes_t iter; @@ -36,6 +39,7 @@ dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod dlog_precomp_n_init(pre, a, mod.n, na, p1); logcost = pre->cost; +#if 0 if (logcost < 15) { /* p1 = pmax; */ @@ -45,6 +49,7 @@ dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod { limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); } +#endif /* take big power of gen */ X = n_nextprime(3 * na / 2, 0) % na; @@ -62,7 +67,7 @@ dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod cost = pow(cost,cost); sievecount++; /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ - /*if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ + /* if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ if (logcost < cost || (vp = dlog_vec_pindex_factorgcd(v, nv, p, mod, aX, na, vaX, logm1, order, cost)) == DLOG_NOT_FOUND) { if (logcost < cost) From 4bd41da2402785ea33e54c1c4e7a85b06473e978 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 09:32:54 +0200 Subject: [PATCH 082/139] fix unused variable + 32bits test --- acb_dirichlet/conrey_primitive.c | 4 ++-- dlog/test/t-modpe.c | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/acb_dirichlet/conrey_primitive.c b/acb_dirichlet/conrey_primitive.c index 3961bcea..c3a79411 100644 --- a/acb_dirichlet/conrey_primitive.c +++ b/acb_dirichlet/conrey_primitive.c @@ -24,7 +24,7 @@ acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_gro if (cond % 8 == 0) { ulong l2 = x->log[1]; - f = n_remove(&l2, 2); + n_remove(&l2, 2); y->log[l++] = l2; } } @@ -38,7 +38,7 @@ acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_gro if (cond % p == 0) { lp = x->log[k]; - f = n_remove(&lp, p); + n_remove(&lp, p); y->log[l++] = lp; } } diff --git a/dlog/test/t-modpe.c b/dlog/test/t-modpe.c index 733c6634..53cf57fc 100644 --- a/dlog/test/t-modpe.c +++ b/dlog/test/t-modpe.c @@ -11,6 +11,11 @@ #include "dlog.h" #include +#if FLINT_BITS == 64 +#define LIM UWORD(1000000000000) +#else +#define LIM UWORD(1000000000) +#endif int main() { @@ -39,7 +44,7 @@ int main() e = 1; } - for (; pe < UWORD(1000000000000); pe *= p, e++) + for (; pe < LIM; pe *= p, e++) { ulong k, phi; nmod_t mod; From 68c66a666470a9007c0622682da07a928634f531 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 11:13:20 +0200 Subject: [PATCH 083/139] export log mod 2^e and fix conrey_log --- acb_dirichlet/conrey_log.c | 4 ++- acb_dirichlet/test/t-conrey.c | 4 +-- dlog.h | 5 ++-- dlog/1modpe.c | 2 +- dlog/1modpe_init.c | 2 +- dlog/1modpe_mod1p.c | 2 +- dlog/mod2e.c | 50 +++++++++++++++++++---------------- 7 files changed, 38 insertions(+), 31 deletions(-) diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index 15040b26..d7a520f9 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -11,6 +11,7 @@ (at your option) any later version. See . */ +#include "dlog.h" #include "acb_dirichlet.h" /* TODO: use dlog module instead of n_discrete_log_bsgs */ @@ -27,7 +28,8 @@ acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G { ulong m2 = (x->log[0]) ? -m % G->q_even : m % G->q_even; if (G->P[1].dlog == NULL) - x->log[1] = n_discrete_log_bsgs(m2, 5, G->q_even); + x->log[1] = dlog_mod2e_1mod4(m2, G->P[1].e, + nmod_inv(5, G->P[1].pe), G->P[1].pe); else x->log[1] = dlog_precomp(G->P[1].dlog, m2); } diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 9b39f5c5..5e5a060b 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -123,11 +123,11 @@ int main() if (!acb_dirichlet_conrey_eq(G, x, y)) { - flint_printf("FAIL: conrey log and exp\n\n"); + flint_printf("FAIL: conrey exp and log\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("conrey = "); acb_dirichlet_conrey_print(G, x); - flint_printf("m = %wu\n\n", m); + flint_printf("\n\nm = %wu\n\n", m); flint_printf("log = "); acb_dirichlet_conrey_print(G, y); flint_printf("\n\nnumber = %wu\n\n", y->n); diff --git a/dlog.h b/dlog.h index f62ef63a..b9352e26 100644 --- a/dlog.h +++ b/dlog.h @@ -235,11 +235,12 @@ ulong dlog_table(const dlog_table_t t, ulong b); ulong dlog_crt(const dlog_crt_t t, ulong b); ulong dlog_power(const dlog_power_t t, ulong b); ulong dlog_modpe(const dlog_modpe_t t, ulong b); -ulong dlog_mod2e(const dlog_modpe_t t, ulong b); ulong dlog_bsgs(const dlog_bsgs_t t, ulong b); ulong dlog_rho(const dlog_rho_t t, ulong b); -ulong dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe); +ulong dlog_1modpe_1modp(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe); ulong dlog_1modpe(const dlog_1modpe_t t, ulong b1, ulong p, ulong e, nmod_t pe); +ulong dlog_mod2e_1mod4(ulong b1, ulong e, ulong inva, nmod_t pe); +ulong dlog_mod2e(const dlog_modpe_t t, ulong b); /*#define dlog_bsgs(t, b) n_discrete_log_bsgs_table(t, b)*/ #define DLOG_SMALL_LIM 50 diff --git a/dlog/1modpe.c b/dlog/1modpe.c index a9d12817..ecfa98c3 100644 --- a/dlog/1modpe.c +++ b/dlog/1modpe.c @@ -19,7 +19,7 @@ dlog_1modpe(const dlog_1modpe_t t, ulong b1, ulong p, ulong e, nmod_t pe) else { ulong logb1; - logb1 = dlog_1modpe_mod1p(b1, p, e, t->inv1p, pe); + logb1 = dlog_1modpe_1modp(b1, p, e, t->inv1p, pe); /* only need mod p^(e-1) */ return nmod_mul(logb1, t->invloga1, pe); } diff --git a/dlog/1modpe_init.c b/dlog/1modpe_init.c index c8bef0b1..a28323bc 100644 --- a/dlog/1modpe_init.c +++ b/dlog/1modpe_init.c @@ -25,7 +25,7 @@ dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e, nmod_t pe) if (a1 == 1) abort(); t->inv1p = nmod_inv(1 + p, pe); /* 1 - p + p^2 - ... */ - loga1 = dlog_1modpe_mod1p(a1, p, e, t->inv1p, pe); + loga1 = dlog_1modpe_1modp(a1, p, e, t->inv1p, pe); /* only need inverse mod p^(e-1) but does not hurt */ t->invloga1 = nmod_inv(loga1, pe); } diff --git a/dlog/1modpe_mod1p.c b/dlog/1modpe_mod1p.c index 830e1717..9693769f 100644 --- a/dlog/1modpe_mod1p.c +++ b/dlog/1modpe_mod1p.c @@ -13,7 +13,7 @@ /* for odd prime p, assume b1 = 1 mod p */ ulong -dlog_1modpe_mod1p(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe) +dlog_1modpe_1modp(ulong b1, ulong p, ulong e, ulong inv1p, nmod_t pe) { int f; ulong x, xf, pf, pf1; diff --git a/dlog/mod2e.c b/dlog/mod2e.c index ed051503..2ef8e655 100644 --- a/dlog/mod2e.c +++ b/dlog/mod2e.c @@ -11,33 +11,37 @@ #include "dlog.h" +ulong +dlog_mod2e_1mod4(ulong b1, ulong e, ulong inv5, nmod_t pe) +{ + slong f; + ulong pf1, pf, x, xf; + pf1 = 1; + pf = 4; + x = 0; + for (f = 2; f < e; f++) + { + if (b1 % pf != 1) + { + flint_printf("ERROR dlog_mod2e: %wu %% %wu != 1 mod %wu\n\n", + b1, pf, pe.n); + abort(); + } + xf = (b1 - 1) / pf; + xf = (f == 2) ? xf % 4 : (xf % 2) * (pf1 / 2); + b1 = nmod_mul(b1, nmod_pow_ui(inv5, xf, pe), pe); + x += xf; + pf1 = pf; + pf *= 2; + } + return x; +} + ulong dlog_mod2e(const dlog_modpe_t t, ulong b1) { if (t->e == 2) return (b1 % 4) == 3; else - { - slong f; - ulong pf1, pf, x, xf; - pf1 = 1; - pf = 4; - x = 0; - for (f = 2; f < t->e; f++) - { - if (b1 % pf != 1) - { - flint_printf("ERROR dlog_mod2e: %wu %% %wu != 1 mod %wu\n\n", - b1, pf, t->pe.n); - abort(); - } - xf = (b1 - 1) / pf; - xf = (f == 2) ? xf % 4 : (xf % 2) * (pf1 / 2); - b1 = nmod_mul(b1, nmod_pow_ui(t->inva, xf, t->pe), t->pe); - x += xf; - pf1 = pf; - pf *= 2; - } - return x; - } + return dlog_mod2e_1mod4(b1, t->e, t->inva, t->pe); } From 0d43e7d4fab2d8659b6338e33688b67f2b1115e8 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 12:28:23 +0200 Subject: [PATCH 084/139] add dlog_once function --- dlog.h | 2 ++ dlog/bsgs_init.c | 2 +- dlog/once.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ dlog/rho.c | 6 +++--- dlog/test/t-dlog.c | 33 +++++++++++++++++++++++---------- 5 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 dlog/once.c diff --git a/dlog.h b/dlog.h index b9352e26..1f10c7ab 100644 --- a/dlog.h +++ b/dlog.h @@ -178,6 +178,8 @@ void dlog_1modpe_init(dlog_1modpe_t t, ulong a1, ulong p, ulong e, nmod_t pe); void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n); /*#define dlog_bsgs_init(t, a, n, m) bsgs_table_init(t, a, n, m)*/ +ulong dlog_once(ulong b, ulong a, const nmod_t mod, ulong n); + DLOG_INLINE void dlog_order23_clear(dlog_order23_t t) { diff --git a/dlog/bsgs_init.c b/dlog/bsgs_init.c index efb07280..c0c92902 100644 --- a/dlog/bsgs_init.c +++ b/dlog/bsgs_init.c @@ -23,7 +23,7 @@ ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) { ulong k, ak; - if (m >= n) m = n + 1; + if (m >= n) m = n; t->table = (apow_t *)flint_malloc(m * sizeof(apow_t)); nmod_init(&t->mod, mod); diff --git a/dlog/once.c b/dlog/once.c new file mode 100644 index 00000000..aae9c3b4 --- /dev/null +++ b/dlog/once.c @@ -0,0 +1,44 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dlog.h" + +ulong +dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) +{ + if (b == 1) + return 0; + if (n < 50) + { + slong k; + ulong ak = 1; + + for (k = 0; k < n; k++) + { + if (ak == b) + return k; + ak = nmod_mul(ak, a, mod); + } + + flint_printf("FAIL[dlog once]: log(%wu,%wu) mod %wu not found (size %wu)\n", + b, a, mod.n, n); + abort(); + } + else + { + ulong l; + dlog_precomp_t pre; + dlog_precomp_n_init(pre, a, mod.n, n, 1); + l = dlog_precomp(pre, b); + dlog_precomp_clear(pre); + return l; + } +} diff --git a/dlog/rho.c b/dlog/rho.c index c49d2bfc..56b0333c 100644 --- a/dlog/rho.c +++ b/dlog/rho.c @@ -13,7 +13,7 @@ #include static ulong -dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) +dlog_single(ulong b, ulong a, const nmod_t mod, ulong n) { if (n < 50) { @@ -27,7 +27,7 @@ dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) ak = nmod_mul(ak, a, mod); } - flint_printf("FAIL[dlog once]: log(%wu,%wu) mod %wu not found (size %wu)\n", + flint_printf("FAIL[dlog single]: log(%wu,%wu) mod %wu not found (size %wu)\n", b, a, mod.n, n); abort(); } @@ -60,7 +60,7 @@ dlog_quotient(const dlog_rho_t t, ulong e, ulong f, ulong g, ulong b) an = nmod_pow_ui(t->a, n.n, t->mod); b_ar = nmod_div(b, nmod_pow_ui(t->a, r, t->mod), t->mod); - return r + n.n * dlog_once(b_ar, an, t->mod, g); + return r + n.n * dlog_single(b_ar, an, t->mod, g); } #define RWALK 20 diff --git a/dlog/test/t-dlog.c b/dlog/test/t-dlog.c index 1a7daeb4..4ed48b1c 100644 --- a/dlog/test/t-dlog.c +++ b/dlog/test/t-dlog.c @@ -10,7 +10,6 @@ */ #include "dlog.h" -#include int main() { @@ -25,37 +24,51 @@ int main() { dlog_table_t table; dlog_bsgs_t bsgs; - dlog_rho_t rho; + dlog_crt_t crt; dlog_precomp_t pre1, pre100; ulong p, a, k; + nmod_t modp; + + if (iter < 10) + p = n_nth_prime(iter + 2); + else + p = n_randprime(state, 15, 0); + nmod_init(&modp, p); - p = n_randprime(state, 15, 0); a = n_primitive_root_prime(p); dlog_table_init(table, a, p); dlog_bsgs_init(bsgs, a, p, p-1, dlog_bsgs_size(p, 1)); - dlog_rho_init(rho, a, p, p-1); + dlog_crt_init(crt, a, p, p-1, 10); dlog_precomp_n_init(pre1, a, p, p-1, 1); dlog_precomp_n_init(pre100, a, p, p-1, 100); for (k = 1; k < 100 && k < p; k++) { - ulong l1, l2, l3, l4, l5; + ulong l0, l1, l2, l3, l4, l5; + l1 = dlog_table(table, k); l2 = dlog_bsgs(bsgs, k); - l3 = dlog_rho(rho, k); + l3 = dlog_crt(crt, k); l4 = dlog_precomp(pre1, k); l5 = dlog_precomp(pre100, k); - if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5) + + if (iter < 50 && k <= 7) + l0 = dlog_once(k, a, modp, p-1); + else + l0 = l1; + + if (l0 != l1 || l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5) { - flint_printf("FAIL: log(%wu,%wu) mod %wu: [%wu, %wu, %wu, %wu, %wu]\n", - k, a, p, l1, l2, l3, l4, l5); + flint_printf("\n\nFAIL: log(%wu,%wu) mod %wu\n\n",k,a,p); + flint_printf("once: %wu\ntable: %wu\nbsgs: %wu\ncrt: %wu\nprecomp1: %wu\nprecomp100: %wu\n\n", + l0, l1, l2, l3, l4, l5); abort(); } } dlog_table_clear(table); dlog_bsgs_clear(bsgs); - dlog_rho_clear(rho); + dlog_crt_clear(crt); dlog_precomp_clear(pre1); dlog_precomp_clear(pre100); } From 71d146a10050430c0c16c91fde4e3bf5c9cdad2d Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 12:38:22 +0200 Subject: [PATCH 085/139] use dlog_once in conrey_log (instead of bsgs) --- acb_dirichlet/conrey_log.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index d7a520f9..a4fe85e8 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -19,7 +19,7 @@ void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) { - ulong k, pk, gk; + slong k; /* even part */ if (G->neven >= 1) { @@ -37,15 +37,14 @@ acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G /* odd part */ for (k = G->neven; k < G->num; k++) { - if (G->P[k].dlog == NULL) + acb_dirichlet_prime_group_struct P = G->P[k]; + if (P.dlog == NULL) { - pk = G->P[k].pe.n; - gk = G->P[k].g; - x->log[k] = n_discrete_log_bsgs(m % pk, gk, pk); + x->log[k] = dlog_once(m % P.pe.n, P.g, P.pe, P.phi); } else { - x->log[k] = dlog_precomp(G->P[k].dlog, m % G->P[k].pe.n); + x->log[k] = dlog_precomp(P.dlog, m % P.pe.n); } } /* keep value m */ From d7ebab9d2e1e540711bcbcac2f86120154066db9 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 12:47:05 +0200 Subject: [PATCH 086/139] document dlog_single --- acb_dirichlet/conrey_log.c | 1 - doc/source/dlog.rst | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/acb_dirichlet/conrey_log.c b/acb_dirichlet/conrey_log.c index a4fe85e8..b3ead4a6 100644 --- a/acb_dirichlet/conrey_log.c +++ b/acb_dirichlet/conrey_log.c @@ -14,7 +14,6 @@ #include "dlog.h" #include "acb_dirichlet.h" -/* TODO: use dlog module instead of n_discrete_log_bsgs */ /* assume m is invertible */ void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) diff --git a/doc/source/dlog.rst b/doc/source/dlog.rst index b146ea01..20eb124a 100644 --- a/doc/source/dlog.rst +++ b/doc/source/dlog.rst @@ -34,6 +34,14 @@ Types, macros and constants .. function:: void dlog_precomp_clear(dlog_precomp_t pre) +Single evaluation +------------------------------------------------------------------------------- + +.. function:: ulong dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) + + Returns `x` such that `b = a^x` in `(\mathbb Z/mod \mathbb Z)^\times`, + a has order *n*. + Precomputations ------------------------------------------------------------------------------- @@ -58,7 +66,7 @@ group: Assume that *a* has primepower order *p*. -Single evaluation +Evaluation ------------------------------------------------------------------------------- .. function:: ulong dlog_precomp(const dlog_precomp_t pre, ulong b) From 3f3dcd447c1554557939520d2683672dc1ceb56a Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 21:53:31 +0200 Subject: [PATCH 087/139] small fixes --- acb_dirichlet.h | 13 +++++- acb_dirichlet/char_init.c | 7 ++++ acb_dirichlet/char_one.c | 6 ++- acb_dirichlet/conrey.c | 1 + acb_dirichlet/qseries_arb_powers.c | 2 +- acb_dirichlet/theta_arb.c | 2 +- acb_dirichlet/theta_length.c | 13 +++--- acb_dirichlet/ui_chi_vec_primeloop.c | 2 +- doc/source/acb_dirichlet.rst | 61 ++++++++++++++++++++-------- 9 files changed, 78 insertions(+), 29 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 361336f2..6f3abf9c 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -120,7 +120,6 @@ acb_dirichlet_conrey_copy(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t } int acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y); - int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); @@ -184,6 +183,16 @@ void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); int acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); +ACB_DIRICHLET_INLINE int +acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) +{ + return (chi->x->n == 1); +} +ACB_DIRICHLET_INLINE int +acb_dirichlet_char_is_real(const acb_dirichlet_char_t chi) +{ + return (chi->order.n <= 2); +} void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); @@ -236,7 +245,7 @@ void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_d void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); void acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec); void acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); -void acb_dirichlet_qseries_arb_powers(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); +void acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec); ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec); ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec); diff --git a/acb_dirichlet/char_init.c b/acb_dirichlet/char_init.c index dd15b5bd..dc90a2bc 100644 --- a/acb_dirichlet/char_init.c +++ b/acb_dirichlet/char_init.c @@ -14,6 +14,13 @@ void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { + slong k; acb_dirichlet_conrey_init(chi->x, G); chi->expo = flint_malloc(G->num * sizeof(ulong)); + chi->q = G->q; + chi->conductor = 1; + chi->parity = 0; + for (k = 0; k < G->num; k++) + chi->expo[k] = 0; + nmod_init(&(chi->order), 1); } diff --git a/acb_dirichlet/char_one.c b/acb_dirichlet/char_one.c index 32e2ad45..57a88e45 100644 --- a/acb_dirichlet/char_one.c +++ b/acb_dirichlet/char_one.c @@ -14,10 +14,12 @@ void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) { + slong k; acb_dirichlet_conrey_one(chi->x, G); chi->q = G->q; chi->conductor = 1; chi->parity = 0; - acb_dirichlet_char_set_expo(chi, G); - acb_dirichlet_char_normalize(chi, G); + for (k = 0; k < G->num; k++) + chi->expo[k] = 0; + nmod_init(&(chi->order), 1); } diff --git a/acb_dirichlet/conrey.c b/acb_dirichlet/conrey.c index 5bf141b2..3fe26f6c 100644 --- a/acb_dirichlet/conrey.c +++ b/acb_dirichlet/conrey.c @@ -14,6 +14,7 @@ void acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { x->log = flint_malloc(G->num * sizeof(ulong)); + acb_dirichlet_conrey_one(x, G); } void diff --git a/acb_dirichlet/qseries_arb_powers.c b/acb_dirichlet/qseries_arb_powers.c index dc086696..e3d021b6 100644 --- a/acb_dirichlet/qseries_arb_powers.c +++ b/acb_dirichlet/qseries_arb_powers.c @@ -51,7 +51,7 @@ acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, con /* small order, multiply by chi at the end */ void -acb_dirichlet_qseries_arb_powers(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) +acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec) { slong k; ulong order = z->order; diff --git a/acb_dirichlet/theta_arb.c b/acb_dirichlet/theta_arb.c index dea7ef53..3e5893a2 100644 --- a/acb_dirichlet/theta_arb.c +++ b/acb_dirichlet/theta_arb.c @@ -22,7 +22,7 @@ _acb_dirichlet_theta_arb_smallorder(acb_t res, const acb_dirichlet_group_t G, co acb_dirichlet_ui_chi_vec(a, G, chi, len); _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); - acb_dirichlet_qseries_arb_powers(res, xt, chi->parity, a, z, len, prec); + acb_dirichlet_qseries_arb_powers_smallorder(res, xt, chi->parity, a, z, len, prec); acb_dirichlet_powers_clear(z); flint_free(a); diff --git a/acb_dirichlet/theta_length.c b/acb_dirichlet/theta_length.c index 1f58b1be..0d619357 100644 --- a/acb_dirichlet/theta_length.c +++ b/acb_dirichlet/theta_length.c @@ -45,21 +45,24 @@ mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n) mag_t m; mag_init(m); arb_get_mag_lower(m, a); - /* a < 1/4 ? */ + /* a < 1/4 */ if (mag_cmp_2exp_si(m, -2) <= 0) { mag_t c; mag_init(c); - mag_mul_ui(c, m, 2); - mag_addmul(c, c, c); - mag_mul_ui(res, m, n*n-n+1); + mag_mul_ui_lower(res, m, n*n-n+1); mag_expinv(res, res); + /* c = 2a(1+2a) */ + mag_mul_ui(m, m, 2); + mag_set_ui(c, 1); + mag_add_lower(c, m, c); + mag_mul_lower(c, m, c); mag_div(res, res, c); mag_clear(c); } else { - mag_mul_ui(res, m, n*n-n-1); + mag_mul_ui_lower(res, m, n*n-n-1); mag_expinv(res, res); mag_mul_ui(res, res, 2); } diff --git a/acb_dirichlet/ui_chi_vec_primeloop.c b/acb_dirichlet/ui_chi_vec_primeloop.c index 2527564f..f05cc408 100644 --- a/acb_dirichlet/ui_chi_vec_primeloop.c +++ b/acb_dirichlet/ui_chi_vec_primeloop.c @@ -51,7 +51,7 @@ acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, cons { slong k, l; - for (k = 1; k < nv; k++) + for (k = 0; k < nv; k++) v[k] = 0; if (G->neven) diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 49b57f00..1b8cdcd4 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -109,11 +109,27 @@ Conrey elements .. function:: int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - This function allows to iterate on the elements of *G* looping on the *index*. - It produces elements in seemingly random *number* order. The return value - is the index of the last updated exponent of *x*, or *G->num* if the last + Sets *x* to the next conrey index in *G* with lexicographic ordering. + The return value + is the index of the last updated exponent of *x*, or *-1* if the last element has been reached. + This function allows to iterate on the elements of *G* looping on their *index*. + Note that it produces elements in seemingly random *number* order. + + The following template can be used to loop over all elements *x* in *G*:: + + acb_conrey_one(x, G); + do { + /* use Conrey element x */ + } while (acb_dirichlet_conrey_next(x, G) >= 0); + + +.. function:: int acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) + + Return 1 if *x* equals *y*. This function checks both *number* and *index*, + writing ``(x->n == y->n)`` gives a faster check. + Dirichlet characters ------------------------------------------------------------------------------- @@ -130,12 +146,12 @@ the group *G* is isomorphic to its dual. .. function:: ulong acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) - Compute the value of the Dirichlet pairing on numbers *m* and *n*, as - exponent modulo *G->expo*. - The second form takes the index *a* and *b*, and does not take discrete - logarithms. + Compute the value of the Dirichlet pairing on numbers *m* and *n*, as + exponent modulo *G->expo*. + The second form takes the Conrey index *a* and *b*, and does not take discrete + logarithms. - The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. + The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. Character type ------------------------------------------------------------------------------- @@ -165,6 +181,14 @@ Character type Sets *chi* to the Dirichlet character of Conrey index *x*. +.. function:: int acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) + + Return 1 if *chi1* equals *chi2*. + +.. function:: acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) + + Return 1 if *chi* is the principal character mod *q*. + Character properties ------------------------------------------------------------------------------- @@ -205,6 +229,10 @@ No discrete log computation is performed. Return the order of `\chi_q(a,\cdot)` which is the order of `a\mod q`. This number is precomputed for the *char* type. +.. function:: acb_dirichlet_char_is_real(const acb_dirichlet_char_t chi) + + Return 1 if *chi* is a real character (iff it has order `\leq 2`). + Character evaluation ------------------------------------------------------------------------------- @@ -333,11 +361,11 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define Compute the theta series `\Theta_q(a,t)` for real argument `t>0`. Beware that if `t<1` the functional equation - + .. math:: - + t \theta(a,t) = \epsilon(\chi) \theta(\frac1a, \frac1t) - + should be used, which is not done automatically (to avoid recomputing the Gauss sum). @@ -346,13 +374,13 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define Compute the number of terms to be summed in the theta series of argument *t* so that the tail is less than `2^{-\mathrm{prec}}`. -.. function:: void acb_dirichlet_arb_theta_naive(acb_t res, const arb_t x, int parity, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) +.. function:: void acb_dirichlet_qseries_powers_naive(acb_t res, const arb_t x, int p, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) -.. function:: void acb_dirichlet_arb_theta_smallorder(acb_t res, const arb_t x, int parity, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) +.. function:: void acb_dirichlet_qseries_powers_smallorder(acb_t res, const arb_t x, int p, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) Compute the series `\sum n^p z^{a_n} x^{n^2}` for exponent list *a*, precomputed powers *z* and parity *p* (being 0 or 1). - + The *naive* version sums the series as defined, while the *smallorder* variant evaluates the series on the quotient ring by a cyclotomic polynomial before evaluating at the root of unity, ignoring its argument *z*. @@ -385,7 +413,7 @@ the Fourier transform on Conrey labels as Compute the DFT of *v* using Conrey indices. This function assumes *v* and *w* are vectors of size *G->phi_q*, whose values correspond to a lexicographic ordering - of Conrey indices. + of Conrey indices (as obtained using :func:`acb_dirichlet_conrey_next`). For example, if `q=15`, the Conrey elements are stored in following order @@ -459,7 +487,7 @@ L-functions L(s,\chi) = q^{-s}\sum_{k=1}^{q-1} \chi(k) \zeta(s,\frac kq) - This formula is slow for large *q*. + This formula is slow for large *q* (and not defined for `s=1`). .. function:: void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec) @@ -482,4 +510,3 @@ Even if it is straightforward to convert a *conrey* index to the corresponding *char*, looping is faster at the level of Conrey representation. Things can be improved on this aspect but it makes code more intricate. - From 658bc80b58cc23b8643c096a83a4771d36fd8306 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Fri, 9 Sep 2016 22:02:45 +0200 Subject: [PATCH 088/139] l_hurwitz and l_vec_hurwitz: allow s = 1 --- acb_dirichlet/l_hurwitz.c | 23 ++++++++++++++++++++++- acb_dirichlet/l_vec_hurwitz.c | 17 ++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index bc9166b5..049cbf00 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -11,7 +11,9 @@ */ #include "acb_dirichlet.h" +#include "acb_poly.h" +/* todo: should document or fix that it doesn't allow aliasing */ void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) @@ -20,6 +22,20 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_t t, u, a; acb_ptr z; acb_dirichlet_conrey_t cn; + int deflate; + + /* remove pole in Hurwitz zeta at s = 1 */ + deflate = 0; + if (acb_is_one(s)) + { + /* character is principal */ + if (chi->x->n == 1) + { + acb_indeterminate(res); + return; + } + deflate = 1; + } acb_dirichlet_conrey_init(cn, G); acb_init(t); @@ -39,7 +55,11 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); - acb_hurwitz_zeta(u, s, a, prec); + + if (deflate == 0) + acb_hurwitz_zeta(u, s, a, prec); + else + _acb_poly_zeta_cpx_series(u, s, a, 1, 1, prec); acb_addmul(t, z + chin, u, prec); @@ -57,3 +77,4 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_clear(u); acb_clear(a); } + diff --git a/acb_dirichlet/l_vec_hurwitz.c b/acb_dirichlet/l_vec_hurwitz.c index cedc726b..e280cf78 100644 --- a/acb_dirichlet/l_vec_hurwitz.c +++ b/acb_dirichlet/l_vec_hurwitz.c @@ -10,6 +10,7 @@ */ #include "acb_dirichlet.h" +#include "acb_poly.h" void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, @@ -18,6 +19,10 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, acb_t a, qs; acb_ptr zeta, z; acb_dirichlet_conrey_t cn; + int deflate; + + /* remove pole in Hurwitz zeta at s = 1 */ + deflate = acb_is_one(s); acb_dirichlet_conrey_init(cn, G); acb_init(qs); @@ -35,7 +40,12 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); - acb_hurwitz_zeta(z, s, a, prec); + + if (!deflate) + acb_hurwitz_zeta(z, s, a, prec); + else + _acb_poly_zeta_cpx_series(z, s, a, 1, 1, prec); + acb_mul(z, z, qs, prec); z++; @@ -43,8 +53,13 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, acb_dirichlet_dft_conrey(res, zeta, G, prec); + /* restore pole for the principal character */ + if (deflate) + acb_indeterminate(res); + acb_dirichlet_conrey_clear(cn); _acb_vec_clear(zeta, G->phi_q); acb_clear(qs); acb_clear(a); } + From cb4b272f7de8864f842e1e0bc080aebda2e50f07 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 22:07:00 +0200 Subject: [PATCH 089/139] typos --- doc/source/dlog.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/source/dlog.rst b/doc/source/dlog.rst index 20eb124a..e3c16feb 100644 --- a/doc/source/dlog.rst +++ b/doc/source/dlog.rst @@ -71,7 +71,7 @@ Evaluation .. function:: ulong dlog_precomp(const dlog_precomp_t pre, ulong b) - Returns `\log(b)` for the group described in *pre* + Returns `\log(b)` for the group described in *pre*. Vector evaluations ------------------------------------------------------------------------------- @@ -100,22 +100,22 @@ Algorithms Several discrete logarithms strategies are implemented: -- complete lookup table for small groups +- Complete lookup table for small groups. -- baby-step giant-step table +- Baby-step giant-step table. -combined with mathematical reductions +combined with mathematical reductions: -- Pohlig-Hellman decomposition (chinese remainder decomposition on the - order of the group and base `p` decomposition for primepower order) +- Pohlig-Hellman decomposition (Chinese remainder decomposition on the + order of the group and base `p` decomposition for primepower order). - p-adic log for primepower modulus `p^e`. For *dlog_vec* functions which compute the vector of discrete logarithms of successive integers `1\dots n`: -- a simple loop on group elements avoiding all logarithms is done when - the group size is comparable with the number of elements requested +- A simple loop on group elements avoiding all logarithms is done when + the group size is comparable with the number of elements requested. - otherwise the logarithms are computed on primes and propagated by Eratosthene-like sieving on composite numbers. From f89bbc6daa0c5daf733ee6cdaa55583a412afdcc Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 9 Sep 2016 22:20:10 +0200 Subject: [PATCH 090/139] fixes two memory leaks --- acb_dirichlet/test/t-thetanull.c | 1 + dlog/vec_sieve.c | 1 + 2 files changed, 2 insertions(+) diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index e9e02905..56788afe 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -106,6 +106,7 @@ int main() } while (acb_dirichlet_char_next_primitive(chi, G) >= 0); _acb_vec_clear(z, G->expo); + _arb_vec_clear(kt, nv); _arb_vec_clear(t, nv); acb_clear(sum); arb_clear(eq); diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index 67d5215a..eb877c1f 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -91,6 +91,7 @@ dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod smooth, limcount, mod.n, logcost, logcount, sievecount, missed); #endif n_primes_clear(iter); + dlog_precomp_clear(pre); for (k = mod.n + 1; k < nv; k++) v[k] = v[k - mod.n]; } From 094fce70f94eb2f5e9c2474203986a513943a464 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Sat, 10 Sep 2016 12:14:10 +0200 Subject: [PATCH 091/139] update docs --- doc/source/acb_dirichlet.rst | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 1b8cdcd4..ce9fa86a 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -198,7 +198,7 @@ No discrete log computation is performed. .. function:: ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) - return the number of primitive elements in *G*. + Return the number of primitive elements in *G*. .. function:: ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) @@ -262,7 +262,7 @@ Roots of unity .. function:: void acb_dirichlet_vec_nth_roots(acb_ptr z, slong order, slong prec) - compute the vector ``1,z,z^2,\dots z^{\mathrm{order}-1}`` where `z=\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. + Compute the vector ``1,z,z^2,\dots z^{\mathrm{order}-1}`` where `z=\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. In order to avoid precision loss, this function does not simply compute powers of a primitive root. @@ -481,20 +481,23 @@ L-functions .. function:: void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) - Compute `L(s,\chi)` for `s\neq 1`, using decomposition in terms of Hurwitz zeta function + Compute `L(s,\chi)` using decomposition in terms of the Hurwitz zeta function - .. math:: + .. math:: - L(s,\chi) = q^{-s}\sum_{k=1}^{q-1} \chi(k) \zeta(s,\frac kq) + L(s,\chi) = q^{-s}\sum_{k=1}^{q-1} \chi(k) \,\zeta\!\left(s,\frac kq\right). - This formula is slow for large *q* (and not defined for `s=1`). + If `s = 1` and `\chi` is non-principal, the deflated Hurwitz zeta function + is used to avoid poles. + + This formula is slow for large *q*. .. function:: void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec) - Compute all values `L(s,\chi)` for `\chi` mod `q`, by Hurwitz formula and - discrete Fourier transform. - *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered Conrey - index. See :func:`acb_dirichlet_dft_conrey`. + Compute all values `L(s,\chi)` for `\chi` mod `q`, by Hurwitz formula and + discrete Fourier transform. + *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered Conrey + index. See :func:`acb_dirichlet_dft_conrey`. Implementation notes ------------------------------------------------------------------------------- From 9fde3336cb05fd64e846021d6c331235ca33e6e3 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Sat, 10 Sep 2016 12:23:28 +0200 Subject: [PATCH 092/139] fix one memory leak --- acb_dirichlet/ui_chi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/acb_dirichlet/ui_chi.c b/acb_dirichlet/ui_chi.c index d7453381..cc502e9c 100644 --- a/acb_dirichlet/ui_chi.c +++ b/acb_dirichlet/ui_chi.c @@ -27,6 +27,7 @@ acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t c v = acb_dirichlet_ui_chi_conrey(G, chi, x); + acb_dirichlet_conrey_clear(x); return v; } } From cf8f5b0b933b8f1f96b21f08d170465734a0567c Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Sat, 10 Sep 2016 12:40:08 +0200 Subject: [PATCH 093/139] fix more memory leaks --- acb_dirichlet/group_clear.c | 11 +++++++++++ acb_dirichlet/test/t-chi.c | 1 + dlog/precomp_clear.c | 1 + 3 files changed, 13 insertions(+) diff --git a/acb_dirichlet/group_clear.c b/acb_dirichlet/group_clear.c index 9864ad1c..125a28ae 100644 --- a/acb_dirichlet/group_clear.c +++ b/acb_dirichlet/group_clear.c @@ -15,6 +15,17 @@ void acb_dirichlet_group_clear(acb_dirichlet_group_t G) { + slong k; + + for (k = 0; k < G->num; k++) + { + if (G->P[k].dlog != NULL) + { + dlog_precomp_clear(G->P[k].dlog); + flint_free(G->P[k].dlog); + } + } + flint_free(G->P); flint_free(G->generators); flint_free(G->PHI); diff --git a/acb_dirichlet/test/t-chi.c b/acb_dirichlet/test/t-chi.c index ed0b825a..f42099a6 100644 --- a/acb_dirichlet/test/t-chi.c +++ b/acb_dirichlet/test/t-chi.c @@ -120,6 +120,7 @@ int main() } acb_dirichlet_group_clear(G); + acb_dirichlet_char_clear(chi); acb_clear(zn1); acb_clear(zn2); acb_clear(zn1n2); diff --git a/dlog/precomp_clear.c b/dlog/precomp_clear.c index 690c74db..a80e1f84 100644 --- a/dlog/precomp_clear.c +++ b/dlog/precomp_clear.c @@ -37,6 +37,7 @@ dlog_precomp_clear(dlog_precomp_t pre) dlog_order23_clear(pre->t.order23); break; default: + printf("THE TYPE IS %d\n", pre->type); abort(); break; } From 20ef61a4474fcf2e7e656e854e57ef7ba5f80db3 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Sat, 10 Sep 2016 12:43:18 +0200 Subject: [PATCH 094/139] fix test code memory leak --- acb_dirichlet/test/t-conrey.c | 122 +++++++++++++++++----------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 5e5a060b..5f23e3a2 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -20,7 +20,7 @@ int main() fflush(stdout); flint_randinit(state); - for (iter = 0; iter < 3000; iter++) + for (iter = 0; iter < 3000 * arb_test_multiplier(); iter++) { acb_dirichlet_group_t G; acb_dirichlet_conrey_t x, y; @@ -78,77 +78,77 @@ int main() abort(); } - if (q % 4 == 2) - continue; - - acb_dirichlet_conrey_first_primitive(x, G); - for (n = 1; acb_dirichlet_conrey_next_primitive(x, G) >= 0; n++); - - ref = acb_dirichlet_number_primitive(G); - if (n != ref) + if (q % 4 != 2) { - flint_printf("FAIL: number of primitive elements\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("# primitive = %wu\n\n", ref); - flint_printf("loop index = %wu\n\n", n); - abort(); - } + acb_dirichlet_conrey_first_primitive(x, G); + for (n = 1; acb_dirichlet_conrey_next_primitive(x, G) >= 0; n++); - - /* some random elements, check log and exp */ - for (n = 0; n < 30; n++) - { - slong k; - ulong m; - - for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); - acb_dirichlet_conrey_log(x, G, m); - - if (m != acb_dirichlet_conrey_exp(x, G)) + ref = acb_dirichlet_number_primitive(G); + if (n != ref) { - flint_printf("FAIL: conrey log and exp\n\n"); + flint_printf("FAIL: number of primitive elements\n\n"); flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("conrey = "); - acb_dirichlet_conrey_print(G, x); - flint_printf("\n\nnumber = %wu\n\n", x->n); + flint_printf("# primitive = %wu\n\n", ref); + flint_printf("loop index = %wu\n\n", n); abort(); } - for (k = 0; k < G->num; k++) - x->log[k] = n_randint(state, G->P[k].phi); - m = acb_dirichlet_conrey_exp(x, G); - acb_dirichlet_conrey_log(y, G, m); - - if (!acb_dirichlet_conrey_eq(G, x, y)) + /* some random elements, check log and exp */ + for (n = 0; n < 30; n++) { - flint_printf("FAIL: conrey exp and log\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("conrey = "); - acb_dirichlet_conrey_print(G, x); - flint_printf("\n\nm = %wu\n\n", m); - flint_printf("log = "); - acb_dirichlet_conrey_print(G, y); - flint_printf("\n\nnumber = %wu\n\n", y->n); - abort(); - } + slong k; + ulong m; - acb_dirichlet_conrey_next_primitive(x, G); - m = x->n; + for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); + acb_dirichlet_conrey_log(x, G, m); - if (m != acb_dirichlet_conrey_exp(x, G)) - { - flint_printf("FAIL: conrey number next primitive\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("conrey = "); - acb_dirichlet_conrey_print(G, y); - flint_printf(", m = %wu\n\n", y->n); - flint_printf("next primitive = "); - acb_dirichlet_conrey_print(G, x); - flint_printf(", m = %wu\n\n", m); - flint_printf("exp = %wu\n\n", x->n); - abort(); + if (m != acb_dirichlet_conrey_exp(x, G)) + { + flint_printf("FAIL: conrey log and exp\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("conrey = "); + acb_dirichlet_conrey_print(G, x); + flint_printf("\n\nnumber = %wu\n\n", x->n); + abort(); + } + + for (k = 0; k < G->num; k++) + x->log[k] = n_randint(state, G->P[k].phi); + + m = acb_dirichlet_conrey_exp(x, G); + acb_dirichlet_conrey_log(y, G, m); + + if (!acb_dirichlet_conrey_eq(G, x, y)) + { + flint_printf("FAIL: conrey exp and log\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("conrey = "); + acb_dirichlet_conrey_print(G, x); + flint_printf("\n\nm = %wu\n\n", m); + flint_printf("log = "); + acb_dirichlet_conrey_print(G, y); + flint_printf("\n\nnumber = %wu\n\n", y->n); + abort(); + } + + acb_dirichlet_conrey_next_primitive(x, G); + m = x->n; + + if (m != acb_dirichlet_conrey_exp(x, G)) + { + flint_printf("FAIL: conrey number next primitive\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("conrey = "); + acb_dirichlet_conrey_print(G, y); + flint_printf(", m = %wu\n\n", y->n); + flint_printf("next primitive = "); + acb_dirichlet_conrey_print(G, x); + flint_printf(", m = %wu\n\n", m); + flint_printf("exp = %wu\n\n", x->n); + abort(); + } } } From 9340306088eb468255992b35c7c54c69fe024ab5 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Sat, 10 Sep 2016 13:28:34 +0200 Subject: [PATCH 095/139] fix memory leak --- dlog/vec_eratos_add.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dlog/vec_eratos_add.c b/dlog/vec_eratos_add.c index 33c26c98..2ee2b579 100644 --- a/dlog/vec_eratos_add.c +++ b/dlog/vec_eratos_add.c @@ -46,4 +46,7 @@ dlog_vec_eratos_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, for (k = mod.n + 1; k < nv; k++) v[k] = v[k - mod.n]; + + dlog_precomp_clear(pre); } + From 1658e7c71838892b163d46e6857a0d37425a5124 Mon Sep 17 00:00:00 2001 From: Pascal Date: Sat, 10 Sep 2016 20:21:07 +0200 Subject: [PATCH 096/139] fix severe memory bug --- acb_dirichlet/dft_fast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c index cef7c66c..ce6410e2 100644 --- a/acb_dirichlet/dft_fast.c +++ b/acb_dirichlet/dft_fast.c @@ -161,7 +161,7 @@ _acb_dft_cyc(acb_ptr w, acb_srcptr v, dft_cyc_step * cyc, slong num, slong prec) /* reorder */ for (i = 0; i < m; i++) for (j = 0; j < M; j++) - w[j + M * i] = t[i + m * j]; + acb_set(w + j + M * i, t + i + m * j); _acb_vec_clear(t, m * M); } } @@ -216,7 +216,7 @@ _acb_dft_prod(acb_ptr w, acb_srcptr v, dft_prod_step * cyc, slong num, slong pre /* reorder */ for (i = 0; i < m; i++) for (j = 0; j < M; j++) - w[j + M * i] = t[i + m * j]; + acb_set(w + j + M * i, t + i + m * j); _acb_vec_clear(t, m * M); } } From 317707255e79a970afc266bd67b303e64f170cd3 Mon Sep 17 00:00:00 2001 From: Pascal Date: Sat, 10 Sep 2016 20:21:57 +0200 Subject: [PATCH 097/139] add root number function and improve gauss --- acb_dirichlet.h | 4 +++ acb_dirichlet/gauss_sum.c | 25 +++++++++------- acb_dirichlet/gauss_sum_theta.c | 37 +++++++---------------- acb_dirichlet/root_number.c | 52 +++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 37 deletions(-) create mode 100644 acb_dirichlet/root_number.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 6f3abf9c..e81d9004 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -255,11 +255,15 @@ void _acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slon void acb_dirichlet_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); +void acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void _acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); + void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 3013cdda..beff042c 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -74,6 +74,20 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri } } +void +acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec) +{ + if (chi->parity) + { + arb_zero(acb_realref(res)); + arb_sqrt_ui(acb_imagref(res), chi->q, prec); + } + else + { + arb_zero(acb_imagref(res)); + arb_sqrt_ui(acb_realref(res), chi->q, prec); + } +} void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { @@ -84,16 +98,7 @@ acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_diri } else if (chi->order.n <= 2) { - if (chi->parity) - { - arb_sqrt_ui(acb_imagref(res), G->q, prec); - arb_zero(acb_realref(res)); - } - else - { - arb_sqrt_ui(acb_realref(res), G->q, prec); - arb_zero(acb_imagref(res)); - } + acb_dirichlet_gauss_sum_order2(res, chi, prec); } else if (G->num > 1 && G->num > G->neven) { diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index ac83b34f..0e92c19d 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -14,38 +14,21 @@ void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { - arb_t x; - acb_t eps; - - arb_init(x); - if (chi->conductor < G->q || (G->q == 300 && (chi->x->n == 71 || chi->x->n == 131)) || (G->q == 600 && (chi->x->n == 11 || chi->x->n == 491))) { - /* or could use l'Hopital rule */ - acb_dirichlet_gauss_sum_naive(res, G, chi, prec); - return; - } - - arb_one(x); - acb_dirichlet_theta_arb(res, G, chi, x, prec); - acb_init(eps); - acb_conj(eps, res); - acb_div(eps, res, eps, prec); - - if (chi->parity) - { - arb_zero(acb_realref(res)); - arb_sqrt_ui(acb_imagref(res), G->q, prec); + flint_printf("gauss_sum_theta: non available for non primitive character" + "or exceptional characters chi_300(71,.), chi_300(131,.), " + "chi_600(11,.) and chi_600(491,.)\n"); + abort(); } else { - arb_zero(acb_imagref(res)); - arb_sqrt_ui(acb_realref(res), G->q, prec); + acb_t iq; + acb_init(iq); + acb_dirichlet_gauss_sum_order2(iq, chi, prec); + _acb_dirichlet_root_number(res, G, chi, prec); + acb_mul(res, res, iq, prec); + acb_clear(iq); } - - acb_mul(res, res, eps, prec); - - arb_clear(x); - acb_clear(eps); } diff --git a/acb_dirichlet/root_number.c b/acb_dirichlet/root_number.c new file mode 100644 index 00000000..55288118 --- /dev/null +++ b/acb_dirichlet/root_number.c @@ -0,0 +1,52 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +_acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + arb_t x; + acb_t eps; + + arb_init(x); + arb_one(x); + acb_dirichlet_theta_arb(res, G, chi, x, prec); + acb_init(eps); + acb_conj(eps, res); + acb_div(res, res, eps, prec); + + arb_clear(x); + acb_clear(eps); +} + +void +acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + if (chi->conductor < G->q) + { + flint_printf("root number: need primitive character\n"); + abort(); + } + else if (G->num > 1) + { + acb_t iq; + acb_init(iq); + acb_dirichlet_gauss_sum_order2(iq, chi, prec); + acb_dirichlet_gauss_sum(res, G, chi, prec); + acb_div(res, res, iq, prec); + acb_clear(iq); + } + else + { + _acb_dirichlet_root_number(res, G, chi, prec); + } +} From ceae160de3ec9486e94b25ad7b3e8a54b1e474fa Mon Sep 17 00:00:00 2001 From: Pascal Date: Sun, 11 Sep 2016 22:58:20 +0200 Subject: [PATCH 098/139] add incgam algorithm for L functions, disabled --- acb_dirichlet.h | 1 + acb_dirichlet/l_incgam.c | 111 ++++++++++++++++++++++++++++++++++++++ acb_dirichlet/test/t-l.c | 113 +++++++++++++++++++++++++-------------- 3 files changed, 184 insertions(+), 41 deletions(-) create mode 100644 acb_dirichlet/l_incgam.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index e81d9004..1631174d 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -271,6 +271,7 @@ void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const ac void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec); +void acb_dirichlet_l_incgam(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); /* Discrete Fourier Transform */ diff --git a/acb_dirichlet/l_incgam.c b/acb_dirichlet/l_incgam.c new file mode 100644 index 00000000..b311725e --- /dev/null +++ b/acb_dirichlet/l_incgam.c @@ -0,0 +1,111 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" +#include "acb_hypgeom.h" + +ulong +_acb_dirichlet_l_incgam_length(const acb_t s, ulong q, slong prec) +{ +#if 0 + arf_t a; + arf_init(a); + arb_get_lbound_arf(a, s, 53); + a = arf_get_d(at, ARF_RND_DOWN); +#else + /* as a first approximation for Re(s) <= 1 */ + return acb_dirichlet_theta_length_d(q, 1., prec); +#endif +} + +void +acb_dirichlet_l_incgam(acb_t res, const acb_t s, + const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +{ + slong k, len; + acb_ptr a; + acb_t s1, s2, args, arg1s, eps; + acb_t g1, g2, pq, pqk2; + + len = _acb_dirichlet_l_incgam_length(s, chi->q, prec) + 2; + flint_printf("incgam length = %ld\n",len); + + prec += n_clog(len, 2); + + a = _acb_vec_init(len); + acb_dirichlet_chi_vec(a, G, chi, len, prec); + + acb_init(args); + acb_init(arg1s); + acb_init(s1); + acb_init(s2); + acb_init(eps); + acb_init(g1); + acb_init(g2); + acb_init(pq); + acb_init(pqk2); + + acb_set(args, s); + acb_one(arg1s); + acb_sub(arg1s, arg1s, s, prec); + + if (chi->parity) + { + acb_add_ui(args, args, 1, prec); + acb_add_ui(arg1s, arg1s, 1, prec); + + for (k = 2; k < len; k++) + acb_mul_si(a + k, a + k, k, prec); + + } + + acb_mul_2exp_si(args, args, -1); + acb_mul_2exp_si(arg1s, arg1s, -1); + acb_conj(arg1s, arg1s); + + arb_const_pi(acb_realref(pq), prec); + acb_div_ui(pq, pq, G->q, prec); + + acb_dirichlet_root_number(eps, G, chi, prec); + + for (k = 1; k < len; k++) + { + if (acb_is_zero(a + k)) + continue; + acb_mul_ui(pqk2, pq, k*k, prec); + /* FIXME: accuracy can be very bad */ + acb_hypgeom_gamma_upper(g1, args, pqk2, 2, prec); + acb_hypgeom_gamma_upper(g2, arg1s, pqk2, 2, prec); + acb_addmul(s1, a + k, g1, prec); + acb_addmul(s2, a + k, g2, prec); + } + + acb_conj(s2, s2); + acb_mul(s2, eps, s2, prec); + acb_add(res, s1, s2, prec); + + acb_pow(g1, pq, args, prec); + acb_mul(res, res, g1, prec); + + acb_gamma(g1, args, prec); + acb_div(res, res, g1, prec); + + acb_clear(args); + acb_clear(arg1s); + acb_clear(s1); + acb_clear(s2); + acb_clear(eps); + acb_clear(g1); + acb_clear(g2); + acb_clear(pq); + acb_clear(pqk2); + _acb_vec_clear(a, len); +} diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index 6724a27c..6d3862c6 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -11,9 +11,6 @@ #include "acb_dirichlet.h" -#define nq 5 -#define nx 3 - void test_dft(ulong q) { @@ -85,6 +82,9 @@ test_dft(ulong q) acb_dirichlet_group_clear(G); } +#define nq 5 +#define nx 4 + int main() { @@ -95,51 +95,61 @@ int main() acb_ptr x; /* cannot test at s = 1 with hurwitz */ - const char * x_r[nx] = { "1", "0.5", "0.5" }; - const char * x_i[nx] = { "1", "0", "6" }; + const char * x_r[nx] = { "0.5", "1", "1", "0.5" }; + const char * x_i[nx] = { "0", "0", "1", "6" }; acb_t ref, res; /* - default(realprecision, 54) - X = [ 1 + I, 1/2, 1/2 + 6 * I ] + default(realprecision, 100) + X = [ 1/2, 1, 1 + I, 1/2 + 6 * I ] C = [Mod(2,3),Mod(4,5),Mod(11,61),Mod(2,91),Mod(3,800)] v = concat([ [lfun(c,x) | x<-X] | c<-C]) - apply(z->printf("\"%s\",\n",real(z)),v) - apply(z->printf("\"%s\",\n",imag(z)),v) + apply(z->printf("\"%s\",\n",precision(real(z),70)),v) + apply(z->printf("\"%s\",\n",precision(imag(z),70)),v) */ const char * ref_r[nq * nx] = { - "0.655527984002548033786648216345221087939439503905627469", - "0.480867557696828626181220063235589877776829730832371863", - "1.56831301727577320813799211138797101541772722814204757", - "0.521271244517346991221550773660594765406476858135844321", - "0.231750947504015755883383661760877226427886696409005898", - "0.275543455389521803395512886745330595086898302178508437", - "0.598221809458540554839300433683735304093606595684903281", - "0.489264190003695740292779374874163221990017067040417393", - "0.573331076412428980263984182365365715292560207445592018", - "0.510279695870740409778738767334484809708615155539404548", - "0.635626509594367380604827545000418331455019188562281349", - "0.129304857274642475564179442785425797926079767522671163", - "1.18088858810025653590356481638012816019876881487868657", - "2.17175778983760437737667738885959799183430688287297767", - "3.41568550810774629867945639900431994221065497147578087" + "0.48086755769682862618122006323558987777682973083237186318155991033493348067023", + "0.60459978807807261686469275254738524409468874936424685852329497846270772704212", + "0.65552798400254803378664821634522108793943950390562746892997938695272366439543", + "1.56831301727577320813799211138797101541772722814204756600556183229594192303169", + "0.23175094750401575588338366176087722642788669640900589796611788733984438064542", + "0.43040894096400403888943323295060542542457068254028965475700610399256121546113", + "0.52127124451734699122155077366059476540647685813584432110209552194219857263213", + "0.27554345538952180339551288674533059508689830217850843726588160302316425288119", + "0.48926419000369574029277937487416322199001706704041739336662332096055431153634", + "0.53487618489463947737652797478014028523937753967835874218217650866316877024685", + "0.59822180945854055483930043368373530409360659568490328055967882287521072175030", + "0.57333107641242898026398418236536571529256020744559201810788762987710987052691", + "0.63562650959436738060482754500041833145501918856228134932017130492895859585857", + "0.58238559844425623388521061809515173901502388709897277008305502466245886012927", + "0.51027969587074040977873876733448480970861515553940454822311416220939931612454", + "0.12930485727464247556417944278542579792607976752267116291530276949569247783180", + "2.1717577898376043773766773888595979918343068828729776727671442492863726379365", + "1.59480084775553338997043324643146074042666522080647790312953333780585384429160", + "1.18088858810025653590356481638012816019876881487868657080290826197336624703523", + "3.4156855081077462986794563990043199422106549714757808711688925562811420743252" }; const char * ref_i[nq * nx] = { - "0.220206044893215842652155131408935133596486560067476474", "0", - "-0.969458654385732175077973304161399773236957587792986099", - "0.354614573267731219242838516784605303288232150760467423", "0", - "-0.995392028773643947872231871832838543767598301887892796", - "1.04370497561090171487193145841005574472705644411957863", - "-0.108902811943905225853677097712717212629591264759957602", - "-0.232114369998608907337769019848201890558327186146689311", - "-0.133300066189980774635445078240315148544665020358019145", - "0.0119464572932630291870372694406253796888930803905106876", - "-0.567660589679294457801153713636532209809112025502518666", - "-0.654079942571300523223917775358845549990877148918886474", - "0.970337207245832214408380510793679653538607483205616894", - "-1.43652482351673593824956935036654893593947145947637807" + "0.22020604489321584265215513140893513359648656006747647412735100189927138978498", + "-0.96945865438573217507797330416139977323695758779298609887525494651999839519954", + "0", + "0", + "0.35461457326773121924283851678460530328823215076046742298881317219868652838939", + "-0.99539202877364394787223187183283854376759830188789279576725217941822771397165", + "-0.108902811943905225853677097712717212629591264759957601734509998247516905304233", + "0.19365188807114177330261930603607468329782453247898970868809396136721159487113", + "1.04370497561090171487193145841005574472705644411957863465786632716182836513300", + "-0.23211436999860890733776901984820189055832718614668931112661490548978197438207", + "0.0119464572932630291870372694406253796888930803905106876170081736901046822264969", + "-0.30766179419579263291559128367018027923130717977616497873373231273162909091033", + "-0.13330006618998077463544507824031514854466502035801914491875951675974942110581", + "-0.56766058967929445780115371363653220980911202550251866578697696371454503377792", + "0.97033720724583221440838051079367965353860748320561689369676918117330599741939", + "0.38019821209845078839690749709574556766339551329040418677194351169649156337996", + "-0.65407994257130052322391777535884554999087714891888647434188545263517159257326", + "-1.43652482351673593824956935036654893593947145947637807266976772120632968400451" }; flint_printf("l...."); @@ -175,13 +185,15 @@ int main() for (j = 0; j < nx; j++) { - if (arb_set_str(acb_realref(ref), ref_r[i * nx + j], prec - 10) || - arb_set_str(acb_imagref(ref), ref_i[i * nx + j], prec - 10) ) + if (arb_set_str(acb_realref(ref), ref_r[i * nx + j], prec) || + arb_set_str(acb_imagref(ref), ref_i[i * nx + j], prec) ) { flint_printf("error while setting ref <- %s+I*%s\n", ref_r[i * nx + j], ref_i[i * nx + j]); abort(); } + arb_add_error_2exp_si(acb_realref(ref), -prec+10); + arb_add_error_2exp_si(acb_imagref(ref), -prec+10); acb_dirichlet_l_hurwitz(res, x + j, G, chi, prec + 10); @@ -191,15 +203,34 @@ int main() flint_printf("q = %wu\n", q[i]); flint_printf("m = %wu\n", m[i]); flint_printf("x = "); - acb_printd(x, 54); + acb_printd(x + j, 54); flint_printf("\nref = "); acb_printd(ref, 54); - flint_printf("\nl(chi,x) = "); + flint_printf("\nl_hurwitz(chi,x) = "); acb_printd(res, 54); flint_printf("\n\n"); abort(); } +#if INCGAM_FIXED + acb_dirichlet_l_incgam(res, x + j, G, chi, prec + 10); + + if (!acb_contains(ref, res)) + { + flint_printf("FAIL:\n\n"); + flint_printf("q = %wu\n", q[i]); + flint_printf("m = %wu\n", m[i]); + flint_printf("x = "); + acb_printd(x + j, 54); + flint_printf("\nref = "); + acb_printd(ref, 54); + flint_printf("\nl_incgam(chi,x) = "); + acb_printd(res, 54); + flint_printf("\n\n"); + abort(); + } +#endif + } acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); From f42274c5d7158895df443847ca5c285ecb699429 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 12 Sep 2016 22:16:00 +0200 Subject: [PATCH 099/139] Revert acc874e0f78 (add incgam algorithm for L functions) Keep this commit in lfunctions branch. This reverts commit acc874e0f784040797c75ae7bb9470e21974d995. --- acb_dirichlet.h | 1 - acb_dirichlet/l_incgam.c | 111 -------------------------------------- acb_dirichlet/test/t-l.c | 113 ++++++++++++++------------------------- 3 files changed, 41 insertions(+), 184 deletions(-) delete mode 100644 acb_dirichlet/l_incgam.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 1631174d..e81d9004 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -271,7 +271,6 @@ void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const ac void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec); -void acb_dirichlet_l_incgam(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); /* Discrete Fourier Transform */ diff --git a/acb_dirichlet/l_incgam.c b/acb_dirichlet/l_incgam.c deleted file mode 100644 index b311725e..00000000 --- a/acb_dirichlet/l_incgam.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" -#include "acb_hypgeom.h" - -ulong -_acb_dirichlet_l_incgam_length(const acb_t s, ulong q, slong prec) -{ -#if 0 - arf_t a; - arf_init(a); - arb_get_lbound_arf(a, s, 53); - a = arf_get_d(at, ARF_RND_DOWN); -#else - /* as a first approximation for Re(s) <= 1 */ - return acb_dirichlet_theta_length_d(q, 1., prec); -#endif -} - -void -acb_dirichlet_l_incgam(acb_t res, const acb_t s, - const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) -{ - slong k, len; - acb_ptr a; - acb_t s1, s2, args, arg1s, eps; - acb_t g1, g2, pq, pqk2; - - len = _acb_dirichlet_l_incgam_length(s, chi->q, prec) + 2; - flint_printf("incgam length = %ld\n",len); - - prec += n_clog(len, 2); - - a = _acb_vec_init(len); - acb_dirichlet_chi_vec(a, G, chi, len, prec); - - acb_init(args); - acb_init(arg1s); - acb_init(s1); - acb_init(s2); - acb_init(eps); - acb_init(g1); - acb_init(g2); - acb_init(pq); - acb_init(pqk2); - - acb_set(args, s); - acb_one(arg1s); - acb_sub(arg1s, arg1s, s, prec); - - if (chi->parity) - { - acb_add_ui(args, args, 1, prec); - acb_add_ui(arg1s, arg1s, 1, prec); - - for (k = 2; k < len; k++) - acb_mul_si(a + k, a + k, k, prec); - - } - - acb_mul_2exp_si(args, args, -1); - acb_mul_2exp_si(arg1s, arg1s, -1); - acb_conj(arg1s, arg1s); - - arb_const_pi(acb_realref(pq), prec); - acb_div_ui(pq, pq, G->q, prec); - - acb_dirichlet_root_number(eps, G, chi, prec); - - for (k = 1; k < len; k++) - { - if (acb_is_zero(a + k)) - continue; - acb_mul_ui(pqk2, pq, k*k, prec); - /* FIXME: accuracy can be very bad */ - acb_hypgeom_gamma_upper(g1, args, pqk2, 2, prec); - acb_hypgeom_gamma_upper(g2, arg1s, pqk2, 2, prec); - acb_addmul(s1, a + k, g1, prec); - acb_addmul(s2, a + k, g2, prec); - } - - acb_conj(s2, s2); - acb_mul(s2, eps, s2, prec); - acb_add(res, s1, s2, prec); - - acb_pow(g1, pq, args, prec); - acb_mul(res, res, g1, prec); - - acb_gamma(g1, args, prec); - acb_div(res, res, g1, prec); - - acb_clear(args); - acb_clear(arg1s); - acb_clear(s1); - acb_clear(s2); - acb_clear(eps); - acb_clear(g1); - acb_clear(g2); - acb_clear(pq); - acb_clear(pqk2); - _acb_vec_clear(a, len); -} diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index 6d3862c6..6724a27c 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -11,6 +11,9 @@ #include "acb_dirichlet.h" +#define nq 5 +#define nx 3 + void test_dft(ulong q) { @@ -82,9 +85,6 @@ test_dft(ulong q) acb_dirichlet_group_clear(G); } -#define nq 5 -#define nx 4 - int main() { @@ -95,61 +95,51 @@ int main() acb_ptr x; /* cannot test at s = 1 with hurwitz */ - const char * x_r[nx] = { "0.5", "1", "1", "0.5" }; - const char * x_i[nx] = { "0", "0", "1", "6" }; + const char * x_r[nx] = { "1", "0.5", "0.5" }; + const char * x_i[nx] = { "1", "0", "6" }; acb_t ref, res; /* - default(realprecision, 100) - X = [ 1/2, 1, 1 + I, 1/2 + 6 * I ] + default(realprecision, 54) + X = [ 1 + I, 1/2, 1/2 + 6 * I ] C = [Mod(2,3),Mod(4,5),Mod(11,61),Mod(2,91),Mod(3,800)] v = concat([ [lfun(c,x) | x<-X] | c<-C]) - apply(z->printf("\"%s\",\n",precision(real(z),70)),v) - apply(z->printf("\"%s\",\n",precision(imag(z),70)),v) + apply(z->printf("\"%s\",\n",real(z)),v) + apply(z->printf("\"%s\",\n",imag(z)),v) */ const char * ref_r[nq * nx] = { - "0.48086755769682862618122006323558987777682973083237186318155991033493348067023", - "0.60459978807807261686469275254738524409468874936424685852329497846270772704212", - "0.65552798400254803378664821634522108793943950390562746892997938695272366439543", - "1.56831301727577320813799211138797101541772722814204756600556183229594192303169", - "0.23175094750401575588338366176087722642788669640900589796611788733984438064542", - "0.43040894096400403888943323295060542542457068254028965475700610399256121546113", - "0.52127124451734699122155077366059476540647685813584432110209552194219857263213", - "0.27554345538952180339551288674533059508689830217850843726588160302316425288119", - "0.48926419000369574029277937487416322199001706704041739336662332096055431153634", - "0.53487618489463947737652797478014028523937753967835874218217650866316877024685", - "0.59822180945854055483930043368373530409360659568490328055967882287521072175030", - "0.57333107641242898026398418236536571529256020744559201810788762987710987052691", - "0.63562650959436738060482754500041833145501918856228134932017130492895859585857", - "0.58238559844425623388521061809515173901502388709897277008305502466245886012927", - "0.51027969587074040977873876733448480970861515553940454822311416220939931612454", - "0.12930485727464247556417944278542579792607976752267116291530276949569247783180", - "2.1717577898376043773766773888595979918343068828729776727671442492863726379365", - "1.59480084775553338997043324643146074042666522080647790312953333780585384429160", - "1.18088858810025653590356481638012816019876881487868657080290826197336624703523", - "3.4156855081077462986794563990043199422106549714757808711688925562811420743252" + "0.655527984002548033786648216345221087939439503905627469", + "0.480867557696828626181220063235589877776829730832371863", + "1.56831301727577320813799211138797101541772722814204757", + "0.521271244517346991221550773660594765406476858135844321", + "0.231750947504015755883383661760877226427886696409005898", + "0.275543455389521803395512886745330595086898302178508437", + "0.598221809458540554839300433683735304093606595684903281", + "0.489264190003695740292779374874163221990017067040417393", + "0.573331076412428980263984182365365715292560207445592018", + "0.510279695870740409778738767334484809708615155539404548", + "0.635626509594367380604827545000418331455019188562281349", + "0.129304857274642475564179442785425797926079767522671163", + "1.18088858810025653590356481638012816019876881487868657", + "2.17175778983760437737667738885959799183430688287297767", + "3.41568550810774629867945639900431994221065497147578087" }; const char * ref_i[nq * nx] = { + "0.220206044893215842652155131408935133596486560067476474", "0", + "-0.969458654385732175077973304161399773236957587792986099", + "0.354614573267731219242838516784605303288232150760467423", "0", - "0.22020604489321584265215513140893513359648656006747647412735100189927138978498", - "-0.96945865438573217507797330416139977323695758779298609887525494651999839519954", - "0", - "0", - "0.35461457326773121924283851678460530328823215076046742298881317219868652838939", - "-0.99539202877364394787223187183283854376759830188789279576725217941822771397165", - "-0.108902811943905225853677097712717212629591264759957601734509998247516905304233", - "0.19365188807114177330261930603607468329782453247898970868809396136721159487113", - "1.04370497561090171487193145841005574472705644411957863465786632716182836513300", - "-0.23211436999860890733776901984820189055832718614668931112661490548978197438207", - "0.0119464572932630291870372694406253796888930803905106876170081736901046822264969", - "-0.30766179419579263291559128367018027923130717977616497873373231273162909091033", - "-0.13330006618998077463544507824031514854466502035801914491875951675974942110581", - "-0.56766058967929445780115371363653220980911202550251866578697696371454503377792", - "0.97033720724583221440838051079367965353860748320561689369676918117330599741939", - "0.38019821209845078839690749709574556766339551329040418677194351169649156337996", - "-0.65407994257130052322391777535884554999087714891888647434188545263517159257326", - "-1.43652482351673593824956935036654893593947145947637807266976772120632968400451" + "-0.995392028773643947872231871832838543767598301887892796", + "1.04370497561090171487193145841005574472705644411957863", + "-0.108902811943905225853677097712717212629591264759957602", + "-0.232114369998608907337769019848201890558327186146689311", + "-0.133300066189980774635445078240315148544665020358019145", + "0.0119464572932630291870372694406253796888930803905106876", + "-0.567660589679294457801153713636532209809112025502518666", + "-0.654079942571300523223917775358845549990877148918886474", + "0.970337207245832214408380510793679653538607483205616894", + "-1.43652482351673593824956935036654893593947145947637807" }; flint_printf("l...."); @@ -185,15 +175,13 @@ int main() for (j = 0; j < nx; j++) { - if (arb_set_str(acb_realref(ref), ref_r[i * nx + j], prec) || - arb_set_str(acb_imagref(ref), ref_i[i * nx + j], prec) ) + if (arb_set_str(acb_realref(ref), ref_r[i * nx + j], prec - 10) || + arb_set_str(acb_imagref(ref), ref_i[i * nx + j], prec - 10) ) { flint_printf("error while setting ref <- %s+I*%s\n", ref_r[i * nx + j], ref_i[i * nx + j]); abort(); } - arb_add_error_2exp_si(acb_realref(ref), -prec+10); - arb_add_error_2exp_si(acb_imagref(ref), -prec+10); acb_dirichlet_l_hurwitz(res, x + j, G, chi, prec + 10); @@ -203,34 +191,15 @@ int main() flint_printf("q = %wu\n", q[i]); flint_printf("m = %wu\n", m[i]); flint_printf("x = "); - acb_printd(x + j, 54); + acb_printd(x, 54); flint_printf("\nref = "); acb_printd(ref, 54); - flint_printf("\nl_hurwitz(chi,x) = "); + flint_printf("\nl(chi,x) = "); acb_printd(res, 54); flint_printf("\n\n"); abort(); } -#if INCGAM_FIXED - acb_dirichlet_l_incgam(res, x + j, G, chi, prec + 10); - - if (!acb_contains(ref, res)) - { - flint_printf("FAIL:\n\n"); - flint_printf("q = %wu\n", q[i]); - flint_printf("m = %wu\n", m[i]); - flint_printf("x = "); - acb_printd(x + j, 54); - flint_printf("\nref = "); - acb_printd(ref, 54); - flint_printf("\nl_incgam(chi,x) = "); - acb_printd(res, 54); - flint_printf("\n\n"); - abort(); - } -#endif - } acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); From 10d4c05bc954dcb75d276b1cb694dbf1ed656ce8 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Wed, 14 Sep 2016 13:47:33 +0200 Subject: [PATCH 100/139] minor doc edits --- doc/source/acb_dirichlet.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index ce9fa86a..8f700356 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -226,7 +226,7 @@ No discrete log computation is performed. .. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) - Return the order of `\chi_q(a,\cdot)` which is the order of `a\mod q`. + Return the order of `\chi_q(a,\cdot)` which is the order of `a\bmod q`. This number is precomputed for the *char* type. .. function:: acb_dirichlet_char_is_real(const acb_dirichlet_char_t chi) @@ -328,7 +328,7 @@ Gauss and Jacobi sums .. math:: - G_q(a) = \sum_{x \mod q} \chi_q(a, x)e^{\frac{2i\pi x}q} + G_q(a) = \sum_{x \bmod q} \chi_q(a, x)e^{\frac{2i\pi x}q} .. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) @@ -336,7 +336,7 @@ Gauss and Jacobi sums .. math:: - J_q(a,b) = \sum_{x \mod q} \chi_q(a, x)\chi_q(b, 1-x) + J_q(a,b) = \sum_{x \bmod q} \chi_q(a, x)\chi_q(b, 1-x) Theta sums ------------------------------------------------------------------------------- @@ -355,16 +355,16 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define \Theta_q(a,t) = \sum_{n\geq 0} \chi_q(a, n) x(t)^{n^2}. -.. function:: void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); +.. function:: void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) -.. function:: void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); +.. function:: void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec) Compute the theta series `\Theta_q(a,t)` for real argument `t>0`. Beware that if `t<1` the functional equation .. math:: - t \theta(a,t) = \epsilon(\chi) \theta(\frac1a, \frac1t) + t \theta(a,t) = \epsilon(\chi) \theta\left(\frac1a, \frac1t\right) should be used, which is not done automatically (to avoid recomputing the Gauss sum). From 420dc9da208f7c7237d77772eedaebfb81ddff21 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Wed, 14 Sep 2016 14:08:31 +0200 Subject: [PATCH 101/139] minor editing --- dlog.h | 30 ++++++++---------------------- dlog/precomp_clear.c | 2 +- dlog/precomp_modpe_init.c | 5 +++-- dlog/precomp_n_init.c | 3 ++- dlog/precomp_p_init.c | 3 +-- dlog/precomp_pe_init.c | 4 ++-- dlog/precomp_small_init.c | 2 +- dlog/rho_init.c | 1 - dlog/vec_loop.c | 2 +- 9 files changed, 19 insertions(+), 33 deletions(-) diff --git a/dlog.h b/dlog.h index 1f10c7ab..cdd7927c 100644 --- a/dlog.h +++ b/dlog.h @@ -1,27 +1,13 @@ -/*============================================================================= - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #ifndef DLOG_H #define DLOG_H diff --git a/dlog/precomp_clear.c b/dlog/precomp_clear.c index a80e1f84..e13071f5 100644 --- a/dlog/precomp_clear.c +++ b/dlog/precomp_clear.c @@ -37,7 +37,7 @@ dlog_precomp_clear(dlog_precomp_t pre) dlog_order23_clear(pre->t.order23); break; default: - printf("THE TYPE IS %d\n", pre->type); + flint_printf("dlog_precomp_clear: unknown type %d\n", pre->type); abort(); break; } diff --git a/dlog/precomp_modpe_init.c b/dlog/precomp_modpe_init.c index 615ec966..a41fd221 100644 --- a/dlog/precomp_modpe_init.c +++ b/dlog/precomp_modpe_init.c @@ -15,12 +15,13 @@ void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) { - if ( pe < DLOG_TABLE_MODPE_LIM ) + if (pe < DLOG_TABLE_MODPE_LIM) { dlog_precomp_small_init(pre, a, pe, pe - pe / p, num); return; } - else { + else + { if (e > 1) { pre->type = DLOG_MODPE; diff --git a/dlog/precomp_n_init.c b/dlog/precomp_n_init.c index b50faae8..1f46d025 100644 --- a/dlog/precomp_n_init.c +++ b/dlog/precomp_n_init.c @@ -18,7 +18,8 @@ dlog_precomp_n_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) { if (n % 2 && n_is_probabprime(n)) dlog_precomp_p_init(pre, a, mod, n, num); - else { + else + { if (n < DLOG_TABLE_N_LIM) { dlog_precomp_small_init(pre, a, mod, n, num); diff --git a/dlog/precomp_p_init.c b/dlog/precomp_p_init.c index 6ed3344d..d277b87b 100644 --- a/dlog/precomp_p_init.c +++ b/dlog/precomp_p_init.c @@ -10,13 +10,12 @@ */ #include "dlog.h" -#include "math.h" /* we known the order is prime */ void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) { - if ( p < DLOG_TABLE_P_LIM ) + if (p < DLOG_TABLE_P_LIM) { dlog_precomp_small_init(pre, a, mod, p, num); } diff --git a/dlog/precomp_pe_init.c b/dlog/precomp_pe_init.c index d4820f04..563eaa58 100644 --- a/dlog/precomp_pe_init.c +++ b/dlog/precomp_pe_init.c @@ -14,13 +14,13 @@ void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) { - if ( pe < DLOG_TABLE_PE_LIM ) + if (pe < DLOG_TABLE_PE_LIM) { dlog_precomp_small_init(pre, a, mod, pe, num); } else { - if ( e == 1) + if (e == 1) { dlog_precomp_p_init(pre, a, mod, p, num); } diff --git a/dlog/precomp_small_init.c b/dlog/precomp_small_init.c index dc9ddfca..3c2c2bf5 100644 --- a/dlog/precomp_small_init.c +++ b/dlog/precomp_small_init.c @@ -21,7 +21,7 @@ dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong n } else { - if ( mod < DLOG_TABLE_LIM ) + if (mod < DLOG_TABLE_LIM) { pre->type = DLOG_TABLE; pre->cost = dlog_table_init(pre->t.table, a, mod); diff --git a/dlog/rho_init.c b/dlog/rho_init.c index 745dea4f..529f5104 100644 --- a/dlog/rho_init.c +++ b/dlog/rho_init.c @@ -10,7 +10,6 @@ */ #include "dlog.h" -#include void dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n) diff --git a/dlog/vec_loop.c b/dlog/vec_loop.c index 70714db4..c7e8815e 100644 --- a/dlog/vec_loop.c +++ b/dlog/vec_loop.c @@ -26,6 +26,6 @@ dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod vx = nmod_add(vx, va, order); } while (x != 1); - for(x = mod.n + 1; x < nv; x++) + for (x = mod.n + 1; x < nv; x++) v[x] = v[x - mod.n]; } From b4c6206d9870e940a0372515db732738d006823c Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Wed, 14 Sep 2016 14:27:36 +0200 Subject: [PATCH 102/139] minor editing and documentation --- acb_dirichlet.h | 34 ++++++++-------------------------- doc/source/acb_dirichlet.rst | 23 +++++++++++++++++++++-- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index e81d9004..3daa52a8 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -1,31 +1,15 @@ -/*============================================================================= - * - * - - This file is part of ARB. - - ARB is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - ARB is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ARB; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -=============================================================================*/ -/****************************************************************************** - +/* Copyright (C) 2015 Jonathan Bober Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Pascal Molin -******************************************************************************/ + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ #ifndef ACB_DIRICHLET_H #define ACB_DIRICHLET_H @@ -203,8 +187,6 @@ void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichle void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); void acb_dirichlet_char_primitive(acb_dirichlet_char_t chi0, const acb_dirichlet_group_t G0, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); -/*ulong acb_dirichlet_char_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi);*/ - void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 8f700356..bdf68566 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -168,9 +168,12 @@ Character type .. function:: void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) + Initializes *chi* to an element of the group *G* and sets its value + to the principal character. + .. function:: void acb_dirichlet_char_clear(acb_dirichlet_char_t chi) - Initializes and clear *chi*. + Clears *chi*. .. function:: void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) @@ -189,6 +192,22 @@ Character type Return 1 if *chi* is the principal character mod *q*. +.. function:: void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) + + Sets *chi* to the principal character. + +.. function:: int acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) + + Sets *x* to the next character in *G* with lexicographic Conrey ordering + (see :func:`acb_dirichlet_conrey_next`). The return value + is the index of the last updated exponent of *x*, or *-1* if the last + element has been reached. + +.. function:: int acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) + + Like :func:`acb_dirichlet_char_next`, but only generates primitive + characters. + Character properties ------------------------------------------------------------------------------- @@ -229,7 +248,7 @@ No discrete log computation is performed. Return the order of `\chi_q(a,\cdot)` which is the order of `a\bmod q`. This number is precomputed for the *char* type. -.. function:: acb_dirichlet_char_is_real(const acb_dirichlet_char_t chi) +.. function:: int acb_dirichlet_char_is_real(const acb_dirichlet_char_t chi) Return 1 if *chi* is a real character (iff it has order `\leq 2`). From f7e88db0be8f28de178646cc73f80b2bb50ef4cb Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Wed, 14 Sep 2016 14:49:09 +0200 Subject: [PATCH 103/139] dlog test code fixes for 32-bit --- dlog/test/t-modpe.c | 4 ++++ dlog/test/t-vec.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dlog/test/t-modpe.c b/dlog/test/t-modpe.c index 53cf57fc..24f1a9e0 100644 --- a/dlog/test/t-modpe.c +++ b/dlog/test/t-modpe.c @@ -73,6 +73,10 @@ int main() } dlog_modpe_clear(modpe); + + /* multiplication can overflow on 32-bit */ + if ((double) pe * p > LIM) + break; } } diff --git a/dlog/test/t-vec.c b/dlog/test/t-vec.c index e1b7dfdc..e12a753a 100644 --- a/dlog/test/t-vec.c +++ b/dlog/test/t-vec.c @@ -51,7 +51,7 @@ int main() fflush(stdout); flint_randinit(state); - for (bits = 10; bits <= 35; bits += 5) + for (bits = 10; bits <= FLINT_MIN(35, FLINT_BITS); bits += 5) { for (nv = 10; nv <= 10000; nv *= 10) From 16681d9269286669e2735d4ac22d77cd4876080a Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Wed, 14 Sep 2016 14:57:00 +0200 Subject: [PATCH 104/139] fix problematic assignment --- acb_dirichlet/chi_vec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/chi_vec.c index a9a07bb9..ccf12f89 100644 --- a/acb_dirichlet/chi_vec.c +++ b/acb_dirichlet/chi_vec.c @@ -29,7 +29,7 @@ acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirich if (a[k] != ACB_DIRICHLET_CHI_NULL) acb_dirichlet_power(v + k, t, a[k], prec); else - *(v + k) = *(v + 0); + acb_zero(v + k); } acb_dirichlet_powers_clear(t); From 6c5d28688d3e3731ff3e0f1e8fa46600a3826288 Mon Sep 17 00:00:00 2001 From: Fredrik Johansson Date: Wed, 14 Sep 2016 15:03:32 +0200 Subject: [PATCH 105/139] conrey_pow: fix a potential overflow issue --- acb_dirichlet/conrey_pow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acb_dirichlet/conrey_pow.c b/acb_dirichlet/conrey_pow.c index 3230fca1..446c5529 100644 --- a/acb_dirichlet/conrey_pow.c +++ b/acb_dirichlet/conrey_pow.c @@ -16,6 +16,6 @@ acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G { ulong k; for (k = 0; k < G->num ; k++) - c->log[k] = (a->log[k] * n) % G->P[k].phi; + c->log[k] = n_mulmod2(a->log[k], n, G->P[k].phi); c->n = nmod_pow_ui(a->n, n, G->mod); } From bf717dafb320d04be93837e1dce22495421e10e7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 14 Sep 2016 15:26:43 +0200 Subject: [PATCH 106/139] fix not ulong safe mul --- dlog/vec_pindex_factorgcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlog/vec_pindex_factorgcd.c b/dlog/vec_pindex_factorgcd.c index d35a41a8..e53ca6b5 100644 --- a/dlog/vec_pindex_factorgcd.c +++ b/dlog/vec_pindex_factorgcd.c @@ -92,9 +92,9 @@ dlog_vec_pindex_factorgcd(ulong * v, ulong nv, ulong p, nmod_t mod, ulong a, ulo logr = (j) ? logm1 : 0; logr = nmod_add(logr, v[r[i]], order); for (i=0; i < ir; i++) - logr = nmod_add(logr, (re[i] * v[rp[i]]) % order.n, order); + logr = nmod_add(logr, nmod_mul(re[i], v[rp[i]], order), order); for (i=0; i < iu; i++) - logm = nmod_add(logm, (ue[i] * v[up[i]]) % order.n, order); + logm = nmod_add(logm, nmod_mul(ue[i], v[up[i]], order), order); return nmod_sub(logr, logm, order); } From be38425f4e2790cc585cf0727934c8e98a23f8b9 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 14 Sep 2016 19:35:45 +0200 Subject: [PATCH 107/139] simplify equality tests --- acb_dirichlet.h | 14 ++++++++++++-- acb_dirichlet/{char_eq.c => char_eq_deep.c} | 6 +++--- acb_dirichlet/{conrey_eq.c => conrey_eq_deep.c} | 2 +- acb_dirichlet/test/t-chars.c | 13 ++++++++----- acb_dirichlet/test/t-conrey.c | 2 +- 5 files changed, 25 insertions(+), 12 deletions(-) rename acb_dirichlet/{char_eq.c => char_eq_deep.c} (76%) rename acb_dirichlet/{conrey_eq.c => conrey_eq_deep.c} (82%) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 3daa52a8..3625bfbc 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -103,7 +103,12 @@ acb_dirichlet_conrey_copy(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t x->log[k] = y->log[k]; } -int acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y); +ACB_DIRICHLET_INLINE int +acb_dirichlet_conrey_eq(const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) +{ + return (x->n == y->n); +} +int acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y); int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); @@ -166,7 +171,12 @@ void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); -int acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); +ACB_DIRICHLET_INLINE int +acb_dirichlet_char_eq(const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) +{ + return (chi1->q == chi2->q && chi1->x->n == chi2->x->n); +} +int acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); ACB_DIRICHLET_INLINE int acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) { diff --git a/acb_dirichlet/char_eq.c b/acb_dirichlet/char_eq_deep.c similarity index 76% rename from acb_dirichlet/char_eq.c rename to acb_dirichlet/char_eq_deep.c index bcd89703..ff0ad0fc 100644 --- a/acb_dirichlet/char_eq.c +++ b/acb_dirichlet/char_eq_deep.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" int -acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) +acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) { acb_dirichlet_conrey_t x, y; @@ -25,13 +25,13 @@ acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t if (chi1->conductor != chi2->conductor) return 0; - if (!acb_dirichlet_conrey_eq(G, chi1->x, chi2->x)) + if (!acb_dirichlet_conrey_eq_deep(G, chi1->x, chi2->x)) return 0; x->n = y->n = 1; x->log = chi1->expo; y->log = chi2->expo; - if (!acb_dirichlet_conrey_eq(G, x, y)) + if (!acb_dirichlet_conrey_eq_deep(G, x, y)) return 0; return 1; diff --git a/acb_dirichlet/conrey_eq.c b/acb_dirichlet/conrey_eq_deep.c similarity index 82% rename from acb_dirichlet/conrey_eq.c rename to acb_dirichlet/conrey_eq_deep.c index 751b1409..122f3c62 100644 --- a/acb_dirichlet/conrey_eq.c +++ b/acb_dirichlet/conrey_eq_deep.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" int -acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) +acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) { slong k; diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index ac0306e6..c5a4cbd0 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -43,7 +43,7 @@ int main() { int par; ulong m, n; - ulong order, chim1, pairing, cond; + ulong order, chim1, pairing, cn, cm, cond; do m = n_randint(state, q); @@ -53,7 +53,7 @@ int main() acb_dirichlet_conrey_log(x, G, m); acb_dirichlet_char_conrey(chi2, G, x); - if (!acb_dirichlet_char_eq(G, chi, chi2)) + if (!acb_dirichlet_char_eq_deep(G, chi, chi2)) { flint_printf("FAIL: init char\n\n"); flint_printf("q = %wu\n\n", q); @@ -107,15 +107,18 @@ int main() acb_dirichlet_char(chi2, G, n); pairing = acb_dirichlet_ui_pairing(G, m, n); + cn = acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order.n); + cm = acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order.n); - if (pairing != acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order.n) - || pairing != acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order.n)) + 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(); } @@ -123,7 +126,7 @@ int main() acb_dirichlet_char_next(chi, G); acb_dirichlet_char_conrey(chi2, G, x); - if (!acb_dirichlet_char_eq(G, chi, chi2)) + if (!acb_dirichlet_char_eq_deep(G, chi, chi2)) { flint_printf("FAIL: next char\n\n"); flint_printf("q = %wu\n\n", q); diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 5f23e3a2..7a7ef630 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -120,7 +120,7 @@ int main() m = acb_dirichlet_conrey_exp(x, G); acb_dirichlet_conrey_log(y, G, m); - if (!acb_dirichlet_conrey_eq(G, x, y)) + if (!acb_dirichlet_conrey_eq_deep(G, x, y)) { flint_printf("FAIL: conrey exp and log\n\n"); flint_printf("q = %wu\n\n", q); From 2f00b252c63fbf23be79057670e1b328b5a1b7be Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 15 Sep 2016 11:17:49 +0200 Subject: [PATCH 108/139] profile dirichlet vec evaluation --- acb_dirichlet/profile/p-conrey.c | 1 + acb_dirichlet/profile/p-vec.c | 171 ++++++++++++++++++++----------- acb_dirichlet/ui_chi_vec.c | 2 +- acb_dirichlet/ui_chi_vec_loop.c | 2 +- 4 files changed, 112 insertions(+), 64 deletions(-) diff --git a/acb_dirichlet/profile/p-conrey.c b/acb_dirichlet/profile/p-conrey.c index 3d2c068d..180a1e25 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/acb_dirichlet/profile/p-conrey.c @@ -164,6 +164,7 @@ do_conreyplusorder(ulong q1, ulong q2) return n; } + int main(int argc, char *argv[]) { int out; diff --git a/acb_dirichlet/profile/p-vec.c b/acb_dirichlet/profile/p-vec.c index ee2853fa..3ce17a02 100644 --- a/acb_dirichlet/profile/p-vec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -9,47 +9,40 @@ (at your option) any later version. See . */ +#include #include "acb_dirichlet.h" #include "profiler.h" -typedef void (*dir_f) (ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); + +#define LOG 0 +#define CSV 1 +#define JSON 2 + +typedef void (*do_f) (ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); static void -dir_empty(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +do_empty(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { return; } static void -vecloop(dir_f dir, ulong minq, ulong maxq, ulong * rand, ulong nr, ulong * v, ulong nv) +do_dlog_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { - ulong q; - TIMEIT_ONCE_START + slong k, l; - for (q = minq; q <= maxq; q++) + for (k = 0; k < nv; k++) + v[k] = 0; + + for (l = G->neven; l < G->num; l++) { - ulong r; - acb_dirichlet_group_t G; - acb_dirichlet_char_t chi; - - acb_dirichlet_group_init(G, q); - acb_dirichlet_char_init(chi, G); - - for (r = 0; r < nr; r++) - { - acb_dirichlet_char(chi, G, rand[r] % q); - dir(v, G, chi, nv); - } - - acb_dirichlet_char_clear(chi); - acb_dirichlet_group_clear(G); + acb_dirichlet_prime_group_struct P = G->P[l]; + dlog_vec_loop_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, chi->order); } - - TIMEIT_ONCE_STOP - flint_printf("\n"); + acb_dirichlet_ui_vec_set_null(v, G, nv); } static void -acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +do_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { slong k, p, pmax; n_primes_t iter; @@ -80,60 +73,114 @@ acb_dirichlet_ui_chi_vec_sieve(ulong *v, const acb_dirichlet_group_t G, const ac n_primes_clear(iter); } -int main() +int main(int argc, char *argv[]) { - slong iter, k, nv, nref, r, nr; - ulong minq, maxq; + int out; + ulong n, nref, maxq = 5000; ulong * rand; - int i, ni = 5; - ulong q[5] = { 2, 1000, 3000, 10000, 100000 }; - ulong qq[5] = { 500, 2000, 5000, 12000, 100500 }; - ulong * v; flint_rand_t state; + slong r, nr; + + int l, nf = 6; + do_f func[6] = { do_empty, acb_dirichlet_ui_chi_vec_loop, do_dlog_primeloop, + acb_dirichlet_ui_chi_vec_primeloop, do_sieve, + acb_dirichlet_ui_chi_vec }; + char * name[6] = { "char only", "big loop", "prime loops", + "prime dlog_vec", "manual sieve", "default" }; + + int i, ni = 5; + ulong qmin[5] = { 2, 1000, 3000, 10000, 100000 }; + ulong qmax[5] = { 500, 2000, 5000, 12000, 100500 }; + + int j, nj = 3; + slong nv[3] = { 50, 300, 2000 }; nr = 20; flint_randinit(state); + rand = flint_malloc(nr * sizeof(ulong)); - v = flint_malloc(nv * sizeof(ulong)); for (r = 0; r < nr; r++) rand[r] = n_randprime(state, 42, 0); - for (i = 0; i < ni; i++) + if (argc < 2) + out = LOG; + else if (!strcmp(argv[1], "json")) + out = JSON; + else if (!strcmp(argv[1], "csv")) + out = CSV; + else if (!strcmp(argv[1], "log")) + out = LOG; + else { - - ulong minq = q[i], maxq = qq[i]; - nv = 2000; - - flint_printf("%wu * chi(rand, 1..%wu) for all %wu <= q <= %wu....\n", nr, nv, minq, maxq); - fflush(stdout); - - flint_printf("character only.......... "); - fflush(stdout); - vecloop(dir_empty, minq, maxq, rand, nr, v, nv); - - flint_printf("big loop................ "); - fflush(stdout); - vecloop(acb_dirichlet_ui_chi_vec_loop, minq, maxq, rand, nr, v, nv); - - flint_printf("med loop................ "); - fflush(stdout); - vecloop(acb_dirichlet_ui_chi_vec_primeloop, minq, maxq, rand, nr, v, nv); - - flint_printf("sieve................... "); - fflush(stdout); - vecloop(acb_dirichlet_ui_chi_vec_sieve, minq, maxq, rand, nr, v, nv); - - flint_printf("generic................. "); - fflush(stdout); - vecloop(acb_dirichlet_ui_chi_vec, minq, maxq, rand, nr, v, nv); + printf("usage: %s [log|csv|json]\n", argv[0]); + abort(); + } + + if (out == CSV) + flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "num", "qmin", "qmax", "time"); + + for (j = 0; j < nj; j++) + { + + ulong * v; + v = flint_malloc(nv[j] * sizeof(ulong)); + + for (i = 0; i < ni; i++) + { + + if (out == LOG) + flint_printf("%wu * chi(rand, 1..%wu) for all %wu <= q <= %wu....\n", nr, nv[j], qmin[i], qmax[i]); + + for (l = 0; l < nf; l++) + { + ulong q; + + if (out == LOG) + flint_printf("%-14s ... ", name[l]); + else if (out == CSV) + flint_printf("%-12s, %7d, %7d, %7d, ", name[l], nv[j], qmin[i], qmax[i]); + else if (out == JSON) + flint_printf("{ \"name\": \"%s\", \"num\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ", + name[l], nv[j], qmin[i], qmax[i]); + + TIMEIT_ONCE_START + + for (q = qmin[i]; q <= qmax[i]; q++) + { + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi, G); + + for (r = 0; r < nr; r++) + { + acb_dirichlet_char(chi, G, rand[r] % q); + func[l](v, G, chi, nv[j]); + } + + acb_dirichlet_char_clear(chi); + acb_dirichlet_group_clear(G); + } + + TIMEIT_ONCE_STOP + + if (out == JSON) + flint_printf("}\n"); + else + flint_printf("\n"); + } + + } + flint_free(v); + } - flint_free(v); flint_free(rand); flint_randclear(state); + flint_cleanup(); - flint_printf("PASS\n"); return EXIT_SUCCESS; } diff --git a/acb_dirichlet/ui_chi_vec.c b/acb_dirichlet/ui_chi_vec.c index 23476cb1..8578c573 100644 --- a/acb_dirichlet/ui_chi_vec.c +++ b/acb_dirichlet/ui_chi_vec.c @@ -14,7 +14,7 @@ void acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { - if (3 * nv > G->q) + if (2 * nv > G->q) acb_dirichlet_ui_chi_vec_loop(v, G, chi, nv); else acb_dirichlet_ui_chi_vec_primeloop(v, G, chi, nv); diff --git a/acb_dirichlet/ui_chi_vec_loop.c b/acb_dirichlet/ui_chi_vec_loop.c index 2cc90e0f..303b069f 100644 --- a/acb_dirichlet/ui_chi_vec_loop.c +++ b/acb_dirichlet/ui_chi_vec_loop.c @@ -38,7 +38,7 @@ acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb } /* fix result outside primes */ - /*acb_dirichlet_vec_set_null(v, G, nv);*/ + /* acb_dirichlet_vec_set_null(v, G, nv);*/ /* copy outside modulus */ for (k = G->q; k < nv ; k++ ) From 4c22581e8cffc12bbf585323159e029115ffebeb Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 15 Sep 2016 15:50:46 +0200 Subject: [PATCH 109/139] fix unsafe mul (and remove useless mod) --- acb_dirichlet/char_normalize.c | 3 ++- acb_dirichlet/ui_pairing_conrey.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/acb_dirichlet/char_normalize.c b/acb_dirichlet/char_normalize.c index 69a05262..7d280d43 100644 --- a/acb_dirichlet/char_normalize.c +++ b/acb_dirichlet/char_normalize.c @@ -16,7 +16,8 @@ acb_dirichlet_char_set_expo(acb_dirichlet_char_t chi, const acb_dirichlet_group_ { slong k; for (k = 0; k < G->num; k++) - chi->expo[k] = (chi->x->log[k] * G->PHI[k]) % G->expo; + /* no overflow: log[k] < phi[k] and G->expo = phi[k] * PHI[k] */ + chi->expo[k] = chi->x->log[k] * G->PHI[k]; } void diff --git a/acb_dirichlet/ui_pairing_conrey.c b/acb_dirichlet/ui_pairing_conrey.c index 7e1a5bd8..9063bea0 100644 --- a/acb_dirichlet/ui_pairing_conrey.c +++ b/acb_dirichlet/ui_pairing_conrey.c @@ -22,7 +22,7 @@ acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichl x = 0; for (k = 0; k < G->num; k++) - x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; + x = n_addmod(x, G->PHI[k] * n_mulmod2(a->log[k], b->log[k], G->P[k].phi), G->expo); return x; } From e04483fd12927b61d25a565c32b0e367ee5fa60d Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 15 Sep 2016 17:35:51 +0200 Subject: [PATCH 110/139] sanitize conrey test for 32 bits --- acb_dirichlet/test/t-conrey.c | 61 ++++++++++++++--------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/acb_dirichlet/test/t-conrey.c b/acb_dirichlet/test/t-conrey.c index 7a7ef630..b64b314a 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/acb_dirichlet/test/t-conrey.c @@ -25,8 +25,7 @@ int main() acb_dirichlet_group_t G; acb_dirichlet_conrey_t x, y; ulong q, n, k, sum; - long ref; - /*int * bits;*/ + slong ref; q = 1 + n_randint(state, 1000 * (1 + iter / 100)); @@ -39,43 +38,34 @@ int main() acb_dirichlet_conrey_one(x, G); sum = 1; -#if 1 for (n = 1; acb_dirichlet_conrey_next(x, G) >= 0; n++) sum += x->n * x->n; -#else - /* iteration much faster than gcd below */ - n = 1; - for (k = 2; k < G->q; k++) - { - if (n_gcd(k, G->q) > 1) - continue; - n++; - sum += k * k; - } -#endif - /* use http://oeis.org/A053818 to check all elements - * are gone through */ - ref = (q % 4 == 2) ? -2 : 1; - for (k = (G->neven == 2); k < G->num; k++) - ref = - ref * G->P[k].p; - ref = ( G->phi_q * (2 * q * q + ref) ) / 6; + if (FLINT_BITS == 64 || q < 1024) + { + /* use http://oeis.org/A053818 to check all elements + * are gone through */ + ref = (q % 4 == 2) ? -2 : 1; + for (k = (G->neven == 2); k < G->num; k++) + ref = - ref * G->P[k].p; + ref = ( G->phi_q * (2 * q * q + ref) ) / 6; - if (n != G->phi_q) - { - flint_printf("FAIL: group size\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("phi(q) = %wu\n\n", G->phi_q); - flint_printf("loop index = %wu\n\n", n); - abort(); - } - if (sum != ref && q > 1) - { - flint_printf("FAIL: sum test\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("sum k^2 = %wu\n\n", ref); - flint_printf("sum obtained = %wu\n\n", sum); - abort(); + if (n != G->phi_q) + { + flint_printf("FAIL: group size\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("phi(q) = %wu\n\n", G->phi_q); + flint_printf("loop index = %wu\n\n", n); + abort(); + } + if (sum != ref && q > 1) + { + flint_printf("FAIL: sum test\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("sum k^2 = %wu\n\n", ref); + flint_printf("sum obtained = %wu\n\n", sum); + abort(); + } } if (q % 4 != 2) @@ -93,7 +83,6 @@ int main() abort(); } - /* some random elements, check log and exp */ for (n = 0; n < 30; n++) { From 6d1fcfa4e152493b4ec411481907e6541630f8ff Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 15 Sep 2016 18:32:29 +0200 Subject: [PATCH 111/139] document dlog functions --- dlog.h | 12 +-- dlog/bsgs_init.c | 1 - doc/source/dlog.rst | 225 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 204 insertions(+), 34 deletions(-) diff --git a/dlog.h b/dlog.h index cdd7927c..8a4805ec 100644 --- a/dlog.h +++ b/dlog.h @@ -252,11 +252,11 @@ void dlog_vec_fill(ulong * v, ulong nv, ulong x); void dlog_vec_set_not_found(ulong *v, ulong nv, nmod_t mod); void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_eratos_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_eratos(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_sieve_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec_add(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); -void dlog_vec(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_eratos_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_eratos(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_sieve_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_sieve(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); #endif diff --git a/dlog/bsgs_init.c b/dlog/bsgs_init.c index c0c92902..b97db5e9 100644 --- a/dlog/bsgs_init.c +++ b/dlog/bsgs_init.c @@ -18,7 +18,6 @@ apow_cmp(const apow_t * x, const apow_t * y) return (x->ak < y->ak) ? -1 : (x->ak > y->ak); } -/* set size of table m=sqrt(nk) to compute k logs in a group of size n */ ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) { diff --git a/doc/source/dlog.rst b/doc/source/dlog.rst index e3c16feb..7c7206a5 100644 --- a/doc/source/dlog.rst +++ b/doc/source/dlog.rst @@ -8,8 +8,9 @@ to Dirichlet characters in mind. In particular, this module defines a :type:`dlog_precomp_t` structure permitting to describe a discrete log problem in some subgroup -of `\mathbb Z/p \mathbb Z` and store precomputed data for -faster computation of several such discrete logarithms. +of `(\mathbb Z/p^e \mathbb Z)^\times` for primepower moduli `p^e`, +and store precomputed data for faster computation of several such +discrete logarithms. When initializing this data, the user provides both a group description and the expected number of subsequent discrete logarithms calls. The choice of algorithm and @@ -32,15 +33,17 @@ Types, macros and constants Structure for discrete logarithm precomputed data. -.. function:: void dlog_precomp_clear(dlog_precomp_t pre) + A :type:`dlog_precomp_t` is defined as an array of length one of type + :type:`dlog_precomp_struct`, permitting a :type:`dlog_precomp_t` to be passed by + reference. Single evaluation ------------------------------------------------------------------------------- .. function:: ulong dlog_once(ulong b, ulong a, const nmod_t mod, ulong n) - Returns `x` such that `b = a^x` in `(\mathbb Z/mod \mathbb Z)^\times`, - a has order *n*. + Return `x` such that `b = a^x` in `(\mathbb Z/mod \mathbb Z)^\times`, + where *a* is known to have order *n*. Precomputations ------------------------------------------------------------------------------- @@ -50,12 +53,21 @@ Precomputations Precompute data for *num* discrete logarithms evaluations in the subgroup generated by *a* modulo *mod*, where *a* is known to have order *n*. -Specialized versions are available when specific information is known about the -group: +.. function:: ulong dlog_precomp(const dlog_precomp_t pre, ulong b) + + Return `\log(b)` for the group described in *pre*. + +.. function:: void dlog_precomp_clear(dlog_precomp_t pre) + + Clears *t*. + +Specialized versions of :func:`dlog_precomp_n_init` are available when specific information +is known about the group: .. function:: void dlog_precomp_modpe_init(dlog_precomp_t pre, ulong a, ulong p, ulong e, ulong pe, ulong num) - Assume that *a* generates the group of residues modulo `p^e`. + Assume that *a* generates the group of residues modulo *pe* equal `p^e` for + prime *p*. .. function:: void dlog_precomp_p_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong num) @@ -63,19 +75,19 @@ group: .. function:: void dlog_precomp_pe_init(dlog_precomp_t pre, ulong a, ulong mod, ulong p, ulong e, ulong pe, ulong num) - Assume that *a* has primepower order *p*. + Assume that *a* has primepower order *pe* `p^e`. +.. function:: void dlog_precomp_small_init(dlog_precomp_t pre, ulong a, ulong mod, ulong n, ulong num) -Evaluation -------------------------------------------------------------------------------- - -.. function:: ulong dlog_precomp(const dlog_precomp_t pre, ulong b) - - Returns `\log(b)` for the group described in *pre*. + Make a complete lookup table of size *n*. + If *mod* is small, this is done using an element-indexed array (see + :type:`dlog_table_t`), otherwise with a sorted array allowing binary search. Vector evaluations ------------------------------------------------------------------------------- +These functions compute all logarithms of successive integers `1\dots n`. + .. function:: void dlog_vec_fill(ulong * v, ulong nv, ulong x) Sets values *v[k]* to *x* for all *k* less than *nv*. @@ -95,7 +107,35 @@ Vector evaluations to *v[k]* and reduce modulo *order* instead of replacing the value. Indices *k* such that *v[k]* equals *DLOG_NONE* are ignored. -Algorithms +Depending on the relative size of *nv* and *na*, these two *dlog_vec* functions +call one of the following functions. + +.. function:: void dlog_vec_loop(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + +.. function:: void dlog_vec_loop_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + + Perform a complete loop of size *na* on powers of *a* to fill the logarithm + values, discarding powers outside the bounds of *v*. This requires no + discrete logarithm computation. + +.. function:: void dlog_vec_eratos(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + +.. function:: void dlog_vec_eratos_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + + Compute discrete logarithms of prime numbers less than *nv* and propagate to composite numbers. + +.. function:: void dlog_vec_sieve_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + +.. function:: void dlog_vec_sieve(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) + + Compute the discrete logarithms of the first few prime numbers, then + use them as a factor base to obtain the logarithms of larger primes + by sieving techniques. + + In the the present implementation, the full index-calculus method is not + implemented. + +Internal discrete logarithm strategies ------------------------------------------------------------------------------- Several discrete logarithms strategies are implemented: @@ -111,18 +151,149 @@ combined with mathematical reductions: - p-adic log for primepower modulus `p^e`. -For *dlog_vec* functions which compute the vector of discrete logarithms -of successive integers `1\dots n`: +The *dlog_precomp* structure makes recursive use of the following +method-specific structures. -- A simple loop on group elements avoiding all logarithms is done when - the group size is comparable with the number of elements requested. +Complete table +............................................................................... -- otherwise the logarithms are computed on primes and propagated by - Eratosthene-like sieving on composite numbers. +.. type:: dlog_table -- when several logarithms are already computed, a basic smoothing technique - inspired by index-calculus is adopted to obtain larger logs from - smaller ones. +.. type:: dlog_table_t -- in the the present implementation, the full index-calculus method is not - implemented. + Structure for complete lookup table. + +.. function:: ulong dlog_table_init(dlog_table_t t, ulong a, ulong mod) + + Initialize a table of powers of *a* modulo *mod*, storing all elements + in an array of size *mod*. + +.. function:: void dlog_table_clear(dlog_table_t t) + + Clears *t*. + +.. function:: ulong dlog_table(dlog_table_t t, ulong b) + + Return `\log(b,a)` using the precomputed data *t*. + +Baby-step giant-step table +............................................................................... + +.. type:: dlog_bsgs_struct + +.. type:: dlog_bsgs_t + + Structure for Baby-Step Giant-Step decomposition. + +.. function:: ulong dlog_bsgs_init(dlog_bsgs_t t, ulong a, ulong mod, ulong n, ulong m) + + Initialize *t* and store the first *m* powers of *a* in a sorted array. The + return value is a rought measure of the cost of each logarithm using this + table. + The user should take `m\approx\sqrt{kn}` to compute k logarithms in a group of size n. + +.. function:: void dlog_bsgs_clear(dlog_bsgs_t t) + + Clears *t*. + +.. function:: ulong dlog_bsgs(dlog_bsgs_t t, ulong b) + + Return `\log(b,a)` using the precomputed data *t*. + +Prime-power modulus decomposition +............................................................................... + +.. type:: dlog_modpe_struct + +.. type:: dlog_modpe_t + + Structure for discrete logarithm modulo primepower `p^e`. + + A :type:`dlog_modpe_t` is defined as an array of length one of type + :type:`dlog_modpe_struct`, permitting a :type:`dlog_modpe_t` to be passed by + reference. + +.. function:: ulong dlog_modpe_init(dlog_modpe_t t, ulong a, ulong p, ulong e, ulong pe, ulong num) + +.. function:: void dlog_modpe_clear(dlog_modpe_t t) + + Clears *t*. + +.. function:: ulong dlog_modpe(dlog_modpe_t t, ulong b) + + Return `\log(b,a)` using the precomputed data *t*. + +CRT decomposition +............................................................................... + +.. type:: dlog_crt_struct + +.. type:: dlog_crt_t + + Structure for discrete logarithm for groups of composite order. + A :type:`dlog_crt_t` is defined as an array of length one of type + :type:`dlog_crt_struct`, permitting a :type:`dlog_crt_t` to be passed by + reference. + +.. function:: ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) + + Precompute data for *num* evaluations of discrete logarithms in base *a* modulo *mod*, + where *a* has composite order *n*, using chinese remainder decomposition. + +.. function:: void dlog_crt_clear(dlog_crt_t t) + + Clears *t*. + +.. function:: ulong dlog_crt(dlog_crt_t t, ulong b) + + Return `\log(b,a)` using the precomputed data *t*. + +padic decomposition +............................................................................... + +.. type:: dlog_power_struct + +.. type:: dlog_power_t + + Structure for discrete logarithm for groups of primepower order. + A :type:`dlog_power_t` is defined as an array of length one of type + :type:`dlog_power_struct`, permitting a :type:`dlog_power_t` to be passed by + reference. + +.. function:: ulong dlog_power_init(dlog_power_t t, ulong a, ulong mod, ulong p, ulong e, ulong num) + + Precompute data for *num* evaluations of discrete logarithms in base *a* modulo *mod*, + where *a* has prime power order *pe* equals `p^e`, using decomposition in base *p*. + +.. function:: void dlog_power_clear(dlog_power_t t) + + Clears *t*. + +.. function:: ulong dlog_power(dlog_power_t t, ulong b) + + Return `\log(b,a)` using the precomputed data *t*. + +Pollard rho method +............................................................................... + +.. type:: dlog_rho_struct + +.. type:: dlog_rho_t + + Structure for discrete logarithm using Pollard rho. + A :type:`dlog_rho_t` is defined as an array of length one of type + :type:`dlog_rho_struct`, permitting a :type:`dlog_rho_t` to be passed by + reference. + +.. function:: ulong dlog_rho_init(dlog_rho_t t, ulong a, ulong mod, ulong n, ulong num) + + Initialize random walks for evaluations of discrete logarithms in base *a* modulo *mod*, + where *a* has order *n*. + +.. function:: void dlog_rho_clear(dlog_rho_t t) + + Clears *t*. + +.. function:: ulong dlog_rho(dlog_rho_t t, ulong b) + + Return `\log(b,a)` by the rho method in the group described by *t*. From 71250d6d28b8c142c53de9b5a587328d99a8ef09 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 16 Sep 2016 16:08:18 +0200 Subject: [PATCH 112/139] more doc for acb_dirichlet --- acb_dirichlet.h | 7 ++- acb_dirichlet/gauss_sum.c | 11 +++++ acb_dirichlet/jacobi_sum.c | 42 +++++++++++++++-- doc/source/acb_dirichlet.rst | 88 +++++++++++++++++++++++++++++++----- 4 files changed, 131 insertions(+), 17 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 3625bfbc..a5f91f9c 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -247,10 +247,10 @@ void _acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slon void acb_dirichlet_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); -void acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); -void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void _acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); @@ -259,7 +259,10 @@ void acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const a void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +void acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +void acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec); void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec); diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index beff042c..4a955aa9 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -88,6 +88,7 @@ acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong arb_sqrt_ui(acb_realref(res), chi->q, prec); } } + void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { @@ -112,3 +113,13 @@ acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_diri acb_dirichlet_gauss_sum_theta(res, G, chi, prec); } } + +void +acb_dirichlet_gauss_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, slong prec) +{ + acb_dirichlet_char_t chi; + acb_dirichlet_char_init(chi, G); + acb_dirichlet_char(chi, G, a); + acb_dirichlet_gauss_sum(res, G, chi, prec); + acb_dirichlet_char_clear(chi); +} diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index c1b88291..70661c97 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -41,7 +41,7 @@ jacobi_one(const acb_dirichlet_group_t G, ulong cond) } /* should use only for prime power modulus */ -static void +void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) { /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ @@ -66,8 +66,8 @@ acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const a acb_clear(tmp); } -static void -acb_dirichlet_jacobi_sum_primes(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +void +acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) { slong k; acb_t tmp; @@ -160,10 +160,44 @@ acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dir if (G->q <= 150) acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); else if (G->num > 1) - acb_dirichlet_jacobi_sum_primes(res, G, chi1, chi2, prec); + acb_dirichlet_jacobi_sum_factor(res, G, chi1, chi2, prec); else if (G->P[0].e > 1) acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec); else acb_dirichlet_jacobi_sum_gauss(res, G, chi1, chi2, prec); } } + +void +acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec) +{ + if (G->q_even > 1) + { + acb_zero(res); + } + else if (a == 1 || b == 1) + { + ulong cond = (a == 1) ? acb_dirichlet_ui_conductor(G, b) : acb_dirichlet_ui_conductor(G, a); + acb_set_si(res, jacobi_one(G, cond)); + } + else if (nmod_mul(a, b, G->mod) == 1) + { + ulong n; + n = jacobi_one(G, acb_dirichlet_ui_conductor(G, a)); + if (acb_dirichlet_ui_parity(G, a)) + acb_set_si(res, -n); + else + acb_set_si(res, n); + } + else + { + acb_dirichlet_char_t chi1, chi2; + acb_dirichlet_char_init(chi1, G); + acb_dirichlet_char_init(chi2, G); + acb_dirichlet_char(chi1, G, a); + acb_dirichlet_char(chi2, G, b); + acb_dirichlet_jacobi_sum(res, G, chi1, chi2, prec); + acb_dirichlet_char_clear(chi1); + acb_dirichlet_char_clear(chi2); + } +} diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index bdf68566..5ec85d71 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -28,9 +28,15 @@ in going from residue classes mod *q* to exponents on a set of generators of the group. This implementation relies on the Conrey numbering scheme -introduced in the LMFDB. -We call *number* a residue class modulo *q*, and *index* the -corresponding vector of exponents of Conrey generators. +introduced in the LMFDB, which is an explicit choice of isomorphism + +.. math:: + + (\mathbb Z/q\mathbb Z)^\times & \to &\bigoplus_i \mathbb Z/\phi_i\mathbb Z \\ + x & \mapsto & (e_i) + +We call *number* a residue class `x` modulo *q*, and *index* the +corresponding vector `(e_i)` of exponents of Conrey generators. Going from an *index* to the corresponding *number* is a cheap operation while the converse requires computing discrete @@ -70,7 +76,7 @@ logarithms. .. function:: void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h) Given an already computed group *G* mod `q`, initialize its subgroup *H* - defined mod `h\mid q`. Precomputed discrete logs tables are kept. + defined mod `h\mid q`. Precomputed discrete log tables are kept. .. function:: void acb_dirichlet_group_clear(acb_dirichlet_group_t G) @@ -125,10 +131,12 @@ Conrey elements } while (acb_dirichlet_conrey_next(x, G) >= 0); -.. function:: int acb_dirichlet_conrey_eq(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) +.. function:: int acb_dirichlet_conrey_eq(const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) - Return 1 if *x* equals *y*. This function checks both *number* and *index*, - writing ``(x->n == y->n)`` gives a faster check. +.. function:: int acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) + + Return 1 if *x* equals *y*. + The second version checks every byte of the representation and is intended for testing only. Dirichlet characters ------------------------------------------------------------------------------- @@ -140,7 +148,15 @@ power of a primitive root of unity, the special value *ACB_DIRICHLET_CHI_NULL* encoding the zero value. The Conrey numbering scheme makes explicit the mathematical fact that -the group *G* is isomorphic to its dual. +the group *G* is isomorphic to its dual, so that a character is described by +a *number*. + +.. math:: + + \begin{array}{ccccc} + (\mathbb Z/q\mathbb Z)^\times \times (\mathbb Z/q\mathbb Z)^\times & \to & \bigoplus_i \mathbb Z/\phi_i\mathbb Z \times \mathbb Z/\phi_i\mathbb Z & \to &\mathbb C \\ + (m,n) & \mapsto& (a_i,b_i) &\mapsto& \chi_q(m,n) = \exp(2i\pi\sum \frac{a_ib_i}{\phi_i} ) + \end{array} .. function:: ulong acb_dirichlet_ui_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) @@ -184,9 +200,12 @@ Character type Sets *chi* to the Dirichlet character of Conrey index *x*. -.. function:: int acb_dirichlet_char_eq(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) +.. function:: int acb_dirichlet_char_eq(const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) + +.. function:: int acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) Return 1 if *chi1* equals *chi2*. + The second version checks every byte of the representation and is intended for testing only. .. function:: acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) @@ -263,7 +282,7 @@ unity. .. function:: ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) - Compute that value `\chi(a)` as the exponent mod the order of `\chi`. + Compute that value `\chi(n)` as the exponent mod the order of `\chi`. .. function:: void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) @@ -341,22 +360,69 @@ Character operations Gauss and Jacobi sums ------------------------------------------------------------------------------- +.. function:: void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + +.. function:: void acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + +.. function:: void acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec) + +.. function:: void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + .. function:: void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_gauss_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, slong prec) + Compute the Gauss sum .. math:: - G_q(a) = \sum_{x \bmod q} \chi_q(a, x)e^{\frac{2i\pi x}q} + G_q(a) = \sum_{x \bmod q} \chi_q(a, x) e^{\frac{2i\pi x}q} + + - the *naive* version computes the sum as defined. + + - the *factor* version writes it as a product of local Gauss sums by chinese + remainder theorem. + + - the *order2* version assumes *chi* is real and primitive and returns + `i^p\sqrt q` where `p` is the parity of `\chi`. + + - the *theta* version assumes that *chi* is primitive to obtain the Gauss + sum by functional equation of the theta series at `t=1`. An abort will be + raised if the theta series vanishes at `t=1`. Only 4 exceptional + characters of conductor 300 and 600 are known to have this particularity, + and none with primepower modulus. + + - the default version automatically combines the above methods. + + - the *ui* version only takes the Conrey number *a* as parameter. + +.. function:: void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) + +.. function:: void acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); + +.. function:: void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); .. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +.. function:: void acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec); + Compute the Jacobi sum .. math:: J_q(a,b) = \sum_{x \bmod q} \chi_q(a, x)\chi_q(b, 1-x) + - the *naive* version computes the sum as defined. + + - the *factor* version writes it as a product of local Jacobi sums + + - the *gauss* version assumes `ab` is primitive and uses the formula + `J_q(a,b)G_q(ab) = G_q(a)G_q(b)` + + - the default version automatically combines the above methods. + + - the *ui* version only takes the Conrey numbers *a* and *b* as parameters. + Theta sums ------------------------------------------------------------------------------- From 3a9dc880e54dc17a8dbf56c58b6ba6244e8a6d4a Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 16 Sep 2016 16:53:56 +0200 Subject: [PATCH 113/139] split gauss and jacobi source files --- acb_dirichlet.h | 1 + acb_dirichlet/gauss_sum.c | 15 ----- acb_dirichlet/gauss_sum_order2.c | 27 +++++++++ acb_dirichlet/jacobi_sum.c | 96 +------------------------------ acb_dirichlet/jacobi_sum_factor.c | 79 +++++++++++++++++++++++++ acb_dirichlet/jacobi_sum_gauss.c | 38 ++++++++++++ 6 files changed, 146 insertions(+), 110 deletions(-) create mode 100644 acb_dirichlet/gauss_sum_order2.c create mode 100644 acb_dirichlet/jacobi_sum_factor.c create mode 100644 acb_dirichlet/jacobi_sum_gauss.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index a5f91f9c..4735fd29 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -259,6 +259,7 @@ void acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const a void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +ulong jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond); void acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 4a955aa9..e2a70dc7 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -74,21 +74,6 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri } } -void -acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec) -{ - if (chi->parity) - { - arb_zero(acb_realref(res)); - arb_sqrt_ui(acb_imagref(res), chi->q, prec); - } - else - { - arb_zero(acb_imagref(res)); - arb_sqrt_ui(acb_realref(res), chi->q, prec); - } -} - void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { diff --git a/acb_dirichlet/gauss_sum_order2.c b/acb_dirichlet/gauss_sum_order2.c new file mode 100644 index 00000000..50b7b114 --- /dev/null +++ b/acb_dirichlet/gauss_sum_order2.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec) +{ + if (chi->parity) + { + arb_zero(acb_realref(res)); + arb_sqrt_ui(acb_imagref(res), chi->q, prec); + } + else + { + arb_zero(acb_imagref(res)); + arb_sqrt_ui(acb_realref(res), chi->q, prec); + } +} diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index 70661c97..d37ef326 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" /* J_N(1,a) = sum on x = 1 mod some p | q */ -static ulong +ulong jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond) { if (e > 1 && cond % (p*p) == 0) @@ -40,103 +40,9 @@ jacobi_one(const acb_dirichlet_group_t G, ulong cond) return r; } -/* should use only for prime power modulus */ -void -acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) -{ - /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ - acb_t tmp; - acb_dirichlet_char_t chi12; - - acb_dirichlet_char_init(chi12, G); - acb_dirichlet_char_mul(chi12, G, chi1, chi2); - - acb_init(tmp); - - acb_dirichlet_gauss_sum(res, G, chi1, prec); - if (chi2->x->n == chi1->x->n) - acb_set(tmp, res); - else - acb_dirichlet_gauss_sum(tmp, G, chi2, prec); - acb_mul(res, res, tmp, prec); - acb_dirichlet_gauss_sum(tmp, G, chi12, prec); - acb_div(res, res, tmp, prec); - - acb_dirichlet_char_clear(chi12); - acb_clear(tmp); -} - -void -acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) -{ - slong k; - acb_t tmp; - acb_init(tmp); - acb_one(res); - - /* TODO: efficient subgroup */ - for (k = 0; k < G->num; k++) - { - nmod_t pe; - ulong p, e, ap, bp; - - p = G->P[k].p; - e = G->P[k].e; - pe = G->P[k].pe; - ap = chi1->x->n % pe.n; - bp = chi2->x->n % pe.n; - - if (ap == 1 || bp == 1 || nmod_mul(ap, bp, pe) == 1) - { - slong r; - ulong cond; - - cond = (ap == 1) ? chi2->conductor : chi1->conductor; - r = jacobi_one_prime(p, e, pe.n, cond); - - /* chi(a,-1) if ap * bp = 1 */ - if (ap != 1 && bp != 1) - r *= n_jacobi_unsigned(ap, p); - - acb_mul_si(res, res, r, prec); - } - else - { - acb_dirichlet_group_t Gp; - acb_dirichlet_char_t chi1p, chi2p; - - acb_dirichlet_group_init(Gp, pe.n); - acb_dirichlet_char_init(chi1p, Gp); - acb_dirichlet_char_init(chi2p, Gp); - - chi1p->x->n = ap; - chi1p->x->log[0] = chi1->x->log[k]; - chi2p->x->n = ap; - chi2p->x->log[0] = chi2->x->log[k]; - - acb_dirichlet_char_conrey(chi1p, Gp, NULL); - acb_dirichlet_char_conrey(chi2p, Gp, NULL); - - /* TODO: work out gauss relations for e > 1 */ - if (p <= 100 || e > 1) - acb_dirichlet_jacobi_sum_naive(tmp, Gp, chi1p, chi2p, prec); - else - acb_dirichlet_jacobi_sum_gauss(tmp, Gp, chi1p, chi2p, prec); - - acb_mul(res, res, tmp, prec); - - acb_dirichlet_char_clear(chi1p); - acb_dirichlet_char_clear(chi2p); - acb_dirichlet_group_clear(Gp); - } - } - acb_clear(tmp); -} - void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) { - if (G->q_even > 1) { acb_zero(res); diff --git a/acb_dirichlet/jacobi_sum_factor.c b/acb_dirichlet/jacobi_sum_factor.c new file mode 100644 index 00000000..37934aed --- /dev/null +++ b/acb_dirichlet/jacobi_sum_factor.c @@ -0,0 +1,79 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +{ + slong k; + acb_t tmp; + acb_init(tmp); + acb_one(res); + + /* TODO: efficient subgroup */ + for (k = 0; k < G->num; k++) + { + nmod_t pe; + ulong p, e, ap, bp; + + p = G->P[k].p; + e = G->P[k].e; + pe = G->P[k].pe; + ap = chi1->x->n % pe.n; + bp = chi2->x->n % pe.n; + + if (ap == 1 || bp == 1 || nmod_mul(ap, bp, pe) == 1) + { + slong r; + ulong cond; + + cond = (ap == 1) ? chi2->conductor : chi1->conductor; + r = jacobi_one_prime(p, e, pe.n, cond); + + /* chi(a,-1) if ap * bp = 1 */ + if (ap != 1 && bp != 1) + r *= n_jacobi_unsigned(ap, p); + + acb_mul_si(res, res, r, prec); + } + else + { + acb_dirichlet_group_t Gp; + acb_dirichlet_char_t chi1p, chi2p; + + acb_dirichlet_group_init(Gp, pe.n); + acb_dirichlet_char_init(chi1p, Gp); + acb_dirichlet_char_init(chi2p, Gp); + + chi1p->x->n = ap; + chi1p->x->log[0] = chi1->x->log[k]; + chi2p->x->n = ap; + chi2p->x->log[0] = chi2->x->log[k]; + + acb_dirichlet_char_conrey(chi1p, Gp, NULL); + acb_dirichlet_char_conrey(chi2p, Gp, NULL); + + /* TODO: work out gauss relations for e > 1 */ + if (p <= 100 || e > 1) + acb_dirichlet_jacobi_sum_naive(tmp, Gp, chi1p, chi2p, prec); + else + acb_dirichlet_jacobi_sum_gauss(tmp, Gp, chi1p, chi2p, prec); + + acb_mul(res, res, tmp, prec); + + acb_dirichlet_char_clear(chi1p); + acb_dirichlet_char_clear(chi2p); + acb_dirichlet_group_clear(Gp); + } + } + acb_clear(tmp); +} diff --git a/acb_dirichlet/jacobi_sum_gauss.c b/acb_dirichlet/jacobi_sum_gauss.c new file mode 100644 index 00000000..9ff6ac86 --- /dev/null +++ b/acb_dirichlet/jacobi_sum_gauss.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +/* should use only for prime power modulus */ +void +acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +{ + /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ + acb_t tmp; + acb_dirichlet_char_t chi12; + + acb_dirichlet_char_init(chi12, G); + acb_dirichlet_char_mul(chi12, G, chi1, chi2); + + acb_init(tmp); + + acb_dirichlet_gauss_sum(res, G, chi1, prec); + if (chi2->x->n == chi1->x->n) + acb_set(tmp, res); + else + acb_dirichlet_gauss_sum(tmp, G, chi2, prec); + acb_mul(res, res, tmp, prec); + acb_dirichlet_gauss_sum(tmp, G, chi12, prec); + acb_div(res, res, tmp, prec); + + acb_dirichlet_char_clear(chi12); + acb_clear(tmp); +} From 387db2b9b4ccad433d1770dd788125e5f3d18489 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 16 Sep 2016 17:07:18 +0200 Subject: [PATCH 114/139] add explicit group_dlog_clear using subgroup and clearing it would have corrupted the dlog pointers --- acb_dirichlet.h | 1 + acb_dirichlet/group_clear.c | 11 ----------- acb_dirichlet/group_dlog_precompute.c | 21 +++++++++++++++++++-- acb_dirichlet/test/t-chars.c | 2 ++ doc/source/acb_dirichlet.rst | 11 +++++++++-- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 4735fd29..283147d0 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -72,6 +72,7 @@ void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h); void acb_dirichlet_group_clear(acb_dirichlet_group_t G); void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); +void acb_dirichlet_group_dlog_clear(acb_dirichlet_group_t G); /* properties of elements without log */ diff --git a/acb_dirichlet/group_clear.c b/acb_dirichlet/group_clear.c index 125a28ae..9864ad1c 100644 --- a/acb_dirichlet/group_clear.c +++ b/acb_dirichlet/group_clear.c @@ -15,17 +15,6 @@ void acb_dirichlet_group_clear(acb_dirichlet_group_t G) { - slong k; - - for (k = 0; k < G->num; k++) - { - if (G->P[k].dlog != NULL) - { - dlog_precomp_clear(G->P[k].dlog); - flint_free(G->P[k].dlog); - } - } - flint_free(G->P); flint_free(G->generators); flint_free(G->PHI); diff --git a/acb_dirichlet/group_dlog_precompute.c b/acb_dirichlet/group_dlog_precompute.c index 292efc7f..2ab1daf6 100644 --- a/acb_dirichlet/group_dlog_precompute.c +++ b/acb_dirichlet/group_dlog_precompute.c @@ -18,11 +18,28 @@ acb_dirichlet_prime_group_dlog_precompute(acb_dirichlet_prime_group_struct * P, dlog_precomp_modpe_init(P->dlog, P->g, P->p, P->e, P->pe.n, num); } - void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) { slong k; for (k = 0; k < G->num; k++) - acb_dirichlet_prime_group_dlog_precompute(&G->P[k], num); + { + if (G->P[k].dlog == NULL) + acb_dirichlet_prime_group_dlog_precompute(&G->P[k], num); + } +} + +void +acb_dirichlet_group_dlog_clear(acb_dirichlet_group_t G) +{ + slong k; + for (k = 0; k < G->num; k++) + { + if (G->P[k].dlog != NULL) + { + dlog_precomp_clear(G->P[k].dlog); + flint_free(G->P[k].dlog); + G->P[k].dlog = NULL; + } + } } diff --git a/acb_dirichlet/test/t-chars.c b/acb_dirichlet/test/t-chars.c index c5a4cbd0..a650aa95 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/acb_dirichlet/test/t-chars.c @@ -140,6 +140,8 @@ int main() } + acb_dirichlet_group_dlog_clear(G); + acb_dirichlet_char_clear(chi); acb_dirichlet_char_clear(chi2); acb_dirichlet_conrey_clear(x); diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 5ec85d71..40661bf7 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -76,11 +76,12 @@ logarithms. .. function:: void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h) Given an already computed group *G* mod `q`, initialize its subgroup *H* - defined mod `h\mid q`. Precomputed discrete log tables are kept. + defined mod `h\mid q`. Precomputed discrete log tables are inherited. .. function:: void acb_dirichlet_group_clear(acb_dirichlet_group_t G) - Clears *G*. + Clears *G*. Remark this function does *not* clear the discrete logarithm + tables stored in *G* (which may be shared with another group). .. function:: void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) @@ -89,6 +90,12 @@ logarithms. If *num* gets very large, the entire group may be indexed. +.. function:: void acb_dirichlet_group_dlog_clear(acb_dirichlet_group_t G, ulong num) + + Clear discrete logarithm tables in *G*. When discrete logarithm tables are + shared with subgroups, those subgroups must be cleared before clearing the + tables. + Conrey elements ------------------------------------------------------------------------------- From 616592c3940a78664ed6c373b77d7cbd9f99a016 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 16 Sep 2016 17:13:31 +0200 Subject: [PATCH 115/139] typo --- doc/source/acb_dirichlet.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 40661bf7..1b3c0228 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -405,13 +405,13 @@ Gauss and Jacobi sums .. function:: void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) -.. function:: void acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +.. function:: void acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) -.. function:: void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +.. function:: void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) .. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) -.. function:: void acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec); +.. function:: void acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec) Compute the Jacobi sum From 0ec9095e16302d8ce48e63903f986fa995b999a1 Mon Sep 17 00:00:00 2001 From: Pascal Date: Sun, 18 Sep 2016 22:32:53 +0200 Subject: [PATCH 116/139] conrey_set and char_set --- acb_dirichlet.h | 18 +++++++++++++++++- acb_dirichlet/char_conrey.c | 2 +- doc/source/acb_dirichlet.rst | 20 +++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 283147d0..d5504887 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -96,7 +96,7 @@ void acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x); void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ACB_DIRICHLET_INLINE void -acb_dirichlet_conrey_copy(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t y) +acb_dirichlet_conrey_set(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t y) { slong k; x->n = y->n; @@ -109,6 +109,7 @@ acb_dirichlet_conrey_eq(const acb_dirichlet_conrey_t x, const acb_dirichlet_conr { return (x->n == y->n); } + int acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y); int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); @@ -172,11 +173,26 @@ void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); +ACB_DIRICHLET_INLINE void +acb_dirichlet_char_set(acb_dirichlet_char_t chi1, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi2) +{ + slong k; + + chi1->q = chi2->q; + chi1->conductor = chi2->conductor; + chi1->order = chi2->order; + chi1->parity = chi2->parity; + acb_dirichlet_conrey_set(chi1->x, G, chi2->x); + for (k = 0; k < G->num; k++) + chi1->expo[k] = chi2->expo[k]; +} + ACB_DIRICHLET_INLINE int acb_dirichlet_char_eq(const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) { return (chi1->q == chi2->q && chi1->x->n == chi2->x->n); } + int acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); ACB_DIRICHLET_INLINE int acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) diff --git a/acb_dirichlet/char_conrey.c b/acb_dirichlet/char_conrey.c index ffb18d31..673c436a 100644 --- a/acb_dirichlet/char_conrey.c +++ b/acb_dirichlet/char_conrey.c @@ -20,7 +20,7 @@ acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t if (x == NULL) x = chi->x; else - acb_dirichlet_conrey_copy(chi->x, G, x); + acb_dirichlet_conrey_set(chi->x, G, x); chi->q = G->q; chi->parity = acb_dirichlet_conrey_parity(G, x); diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 1b3c0228..1890a030 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -120,9 +120,19 @@ Conrey elements Sets *x* to the *number* `1\in G`, having *index* `[0,\dots 0]`. +.. function:: void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) + + Sets *x* to the first primitive element of *G*, having *index* `[1,\dots 1]`, + or `[0, 1, \dots 1]` if `8\mid q`. + +.. function:: void acb_dirichlet_conrey_set(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t y) + + Sets *x* to the element *y*. + .. function:: int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) Sets *x* to the next conrey index in *G* with lexicographic ordering. + The return value is the index of the last updated exponent of *x*, or *-1* if the last element has been reached. @@ -137,6 +147,10 @@ Conrey elements /* use Conrey element x */ } while (acb_dirichlet_conrey_next(x, G) >= 0); +.. function:: int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) + + Same as :func:`acb_dirichlet_conrey_next`, but jumps to the next element + corresponding to a primitive character of *G*. .. function:: int acb_dirichlet_conrey_eq(const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) @@ -216,12 +230,16 @@ Character type .. function:: acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) - Return 1 if *chi* is the principal character mod *q*. + Return 1 if *chi* is the principal character mod *q*. .. function:: void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) Sets *chi* to the principal character. +.. function:: void acb_dirichlet_char_set(acb_dirichlet_char_t chi1, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi2) + + Sets *chi1* to the character *chi2*. + .. function:: int acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) Sets *x* to the next character in *G* with lexicographic Conrey ordering From 93e5442ab9ce5160b6500225161fb421d806bf88 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 19 Sep 2016 10:13:39 +0200 Subject: [PATCH 117/139] profile gauss and jacobi sums --- acb_dirichlet/profile/p-gauss.c | 123 ++++++++++++++++++++++++++++++ acb_dirichlet/profile/p-jacobi.c | 124 +++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 acb_dirichlet/profile/p-gauss.c create mode 100644 acb_dirichlet/profile/p-jacobi.c diff --git a/acb_dirichlet/profile/p-gauss.c b/acb_dirichlet/profile/p-gauss.c new file mode 100644 index 00000000..467f72d8 --- /dev/null +++ b/acb_dirichlet/profile/p-gauss.c @@ -0,0 +1,123 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "acb_dirichlet.h" +#include "profiler.h" + +#define LOG 0 +#define CSV 1 +#define JSON 2 + +typedef void (*do_f) (acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); + +int main(int argc, char *argv[]) +{ + int out; + ulong n, nref, maxq = 5000; + ulong * rand; + flint_rand_t state; + slong r, nr; + + int l, nf = 4; + do_f func[4] = { acb_dirichlet_gauss_sum_naive, + acb_dirichlet_gauss_sum_factor, + acb_dirichlet_gauss_sum_theta, + acb_dirichlet_gauss_sum }; + char * name[4] = { "naive", "factor", "theta", "default" }; + + int i, ni = 5; + ulong qmin[5] = { 3, 50, 500, 1000, 10000 }; + ulong qmax[5] = { 50, 100, 599, 1050, 10030 }; + + int j, nj = 3; + slong prec[3] = { 64, 128, 1024 }; + + if (argc < 2) + out = LOG; + else if (!strcmp(argv[1], "json")) + out = JSON; + else if (!strcmp(argv[1], "csv")) + out = CSV; + else if (!strcmp(argv[1], "log")) + out = LOG; + else + { + printf("usage: %s [log|csv|json]\n", argv[0]); + abort(); + } + + if (out == CSV) + flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "prec", "qmin", "qmax", "time"); + + for (j = 0; j < nj; j++) + { + + for (i = 0; i < ni; i++) + { + + if (out == LOG) + flint_printf("G_q(a) at prec %wu for all %wu <= q <= %wu....\n", prec[j], qmin[i], qmax[i]); + + for (l = 0; l < nf; l++) + { + ulong q; + + if (qmin[i] > 2000 && l == 0) + continue; + + if (out == LOG) + flint_printf("%-14s ... ", name[l]); + else if (out == CSV) + flint_printf("%-12s, %7d, %7d, %7d, ", name[l], prec[j], qmin[i], qmax[i]); + else if (out == JSON) + flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ", + name[l], prec[j], qmin[i], qmax[i]); + + TIMEIT_ONCE_START + + for (q = qmin[i]; q <= qmax[i]; q++) + { + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi; + acb_t res; + + if (q % 4 == 2) + continue; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi, G); + acb_dirichlet_char_first_primitive(chi, G); + acb_init(res); + + do { + func[l](res, G, chi, prec[j]); + } while (acb_dirichlet_char_next_primitive(chi, G) >= 0); + + acb_clear(res); + acb_dirichlet_char_clear(chi); + acb_dirichlet_group_clear(G); + } + + TIMEIT_ONCE_STOP + + if (out == JSON) + flint_printf("}\n"); + else + flint_printf("\n"); + } + + } + + } + flint_cleanup(); + return EXIT_SUCCESS; +} diff --git a/acb_dirichlet/profile/p-jacobi.c b/acb_dirichlet/profile/p-jacobi.c new file mode 100644 index 00000000..ba2fd6e1 --- /dev/null +++ b/acb_dirichlet/profile/p-jacobi.c @@ -0,0 +1,124 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "acb_dirichlet.h" +#include "profiler.h" + +#define LOG 0 +#define CSV 1 +#define JSON 2 + +typedef void (*do_f) (acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); + +int main(int argc, char *argv[]) +{ + int out; + ulong n, nref, maxq = 5000; + ulong * rand; + flint_rand_t state; + slong r, nr; + + int l, nf = 4; + do_f func[4] = { acb_dirichlet_jacobi_sum_naive, + acb_dirichlet_jacobi_sum_factor, + acb_dirichlet_jacobi_sum_gauss, + acb_dirichlet_jacobi_sum }; + char * name[4] = { "naive", "factor", "gauss", "default" }; + + int i, ni = 4; + ulong qmin[4] = { 3, 51, 501, 10001 }; + ulong qmax[4] = { 30, 100, 550, 10050 }; + + int j, nj = 3; + slong prec[3] = { 64, 128, 1024 }; + + if (argc < 2) + out = LOG; + else if (!strcmp(argv[1], "json")) + out = JSON; + else if (!strcmp(argv[1], "csv")) + out = CSV; + else if (!strcmp(argv[1], "log")) + out = LOG; + else + { + printf("usage: %s [log|csv|json]\n", argv[0]); + abort(); + } + + if (out == CSV) + flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "prec", "qmin", "qmax", "time"); + + for (j = 0; j < nj; j++) + { + + for (i = 0; i < ni; i++) + { + + if (out == LOG) + flint_printf("J_q(a,b) at prec %wu for all %wu <= q <= %wu....\n", prec[j], qmin[i], qmax[i]); + + for (l = 0; l < nf; l++) + { + ulong q; + + if (out == LOG) + flint_printf("%-14s ... ", name[l]); + else if (out == CSV) + flint_printf("%-12s, %7d, %7d, %7d, ", name[l], prec[j], qmin[i], qmax[i]); + else if (out == JSON) + flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ", + name[l], prec[j], qmin[i], qmax[i]); + + TIMEIT_ONCE_START + + for (q = qmin[i]; q <= qmax[i]; q+=2) + { + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi1, chi2; + acb_t res; + + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi1, G); + acb_dirichlet_char_init(chi2, G); + acb_init(res); + + do { + slong c = 0; + + acb_dirichlet_char_set(chi2, G, chi1); + do { + func[l](res, G, chi1, chi2, prec[j]); + } while (acb_dirichlet_char_next(chi2, G) >= 0 && c++ < 30); + + } while (acb_dirichlet_char_next(chi1, G) >= 0); + + acb_clear(res); + acb_dirichlet_char_clear(chi1); + acb_dirichlet_char_clear(chi2); + acb_dirichlet_group_clear(G); + } + + TIMEIT_ONCE_STOP + + if (out == JSON) + flint_printf("}\n"); + else + flint_printf("\n"); + } + + } + + } + flint_cleanup(); + return EXIT_SUCCESS; +} From 37140de421ace9572b8e23795aa022eff9ceabe6 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 20 Sep 2016 14:58:51 +0200 Subject: [PATCH 118/139] profile precomp --- acb_dirichlet/gauss_sum_factor.c | 3 ++- acb_dirichlet/group_dlog_precompute.c | 1 + acb_dirichlet/profile/p-gauss.c | 11 ++++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/acb_dirichlet/gauss_sum_factor.c b/acb_dirichlet/gauss_sum_factor.c index 17ce2e2c..b00002b5 100644 --- a/acb_dirichlet/gauss_sum_factor.c +++ b/acb_dirichlet/gauss_sum_factor.c @@ -18,6 +18,7 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const a slong k; acb_t tmp; + /* early check */ for (k = (G->neven == 2); k < G->num; k++) { /* if e > 1 and not primitive, 0 */ @@ -53,7 +54,7 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const a acb_dirichlet_char_conrey(chip, Gp, NULL); - /* chi_pe(a, q/pe) * G_pe(a) */ + /* chi_pe(a, q/pe) * G_pe(a) */ acb_dirichlet_gauss_sum(tmp, Gp, chip, prec); acb_mul(res, res, tmp, prec); diff --git a/acb_dirichlet/group_dlog_precompute.c b/acb_dirichlet/group_dlog_precompute.c index 2ab1daf6..f55da18e 100644 --- a/acb_dirichlet/group_dlog_precompute.c +++ b/acb_dirichlet/group_dlog_precompute.c @@ -15,6 +15,7 @@ void acb_dirichlet_prime_group_dlog_precompute(acb_dirichlet_prime_group_struct * P, ulong num) { P->dlog = flint_malloc(sizeof(dlog_precomp_t)); + /* even if e = 1 use modpe struct, more flexible if reused in bigger group */ dlog_precomp_modpe_init(P->dlog, P->g, P->p, P->e, P->pe.n, num); } diff --git a/acb_dirichlet/profile/p-gauss.c b/acb_dirichlet/profile/p-gauss.c index 467f72d8..2eb63063 100644 --- a/acb_dirichlet/profile/p-gauss.c +++ b/acb_dirichlet/profile/p-gauss.c @@ -27,12 +27,13 @@ int main(int argc, char *argv[]) flint_rand_t state; slong r, nr; - int l, nf = 4; - do_f func[4] = { acb_dirichlet_gauss_sum_naive, + int l, nf = 5; + do_f func[5] = { acb_dirichlet_gauss_sum_naive, acb_dirichlet_gauss_sum_factor, acb_dirichlet_gauss_sum_theta, + acb_dirichlet_gauss_sum, acb_dirichlet_gauss_sum }; - char * name[4] = { "naive", "factor", "theta", "default" }; + char * name[5] = { "naive", "factor", "theta", "default", "default+log" }; int i, ni = 5; ulong qmin[5] = { 3, 50, 500, 1000, 10000 }; @@ -94,6 +95,8 @@ int main(int argc, char *argv[]) continue; acb_dirichlet_group_init(G, q); + if (l == 4) + acb_dirichlet_group_dlog_precompute(G, q); acb_dirichlet_char_init(chi, G); acb_dirichlet_char_first_primitive(chi, G); acb_init(res); @@ -104,6 +107,8 @@ int main(int argc, char *argv[]) acb_clear(res); acb_dirichlet_char_clear(chi); + if (l == 4) + acb_dirichlet_group_dlog_clear(G); acb_dirichlet_group_clear(G); } From 610a79c7c71a7b0f21bc52cc749bf134c3d0a163 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 20 Sep 2016 16:20:13 +0200 Subject: [PATCH 119/139] use dlog_precomp in chi_vec --- acb_dirichlet/profile/p-gauss.c | 4 +- acb_dirichlet/profile/p-vec.c | 28 ++++++-- acb_dirichlet/ui_chi_vec_primeloop.c | 5 +- dlog.h | 5 ++ dlog/vec_add_precomp.c | 23 +++++++ dlog/{vec_init.c => vec_fill.c} | 0 dlog/vec_sieve.c | 74 +--------------------- dlog/vec_sieve_add_precomp.c | 26 ++++++++ dlog/vec_sieve_precomp.c | 95 ++++++++++++++++++++++++++++ 9 files changed, 178 insertions(+), 82 deletions(-) create mode 100644 dlog/vec_add_precomp.c rename dlog/{vec_init.c => vec_fill.c} (100%) create mode 100644 dlog/vec_sieve_add_precomp.c create mode 100644 dlog/vec_sieve_precomp.c diff --git a/acb_dirichlet/profile/p-gauss.c b/acb_dirichlet/profile/p-gauss.c index 2eb63063..d1ab2ee0 100644 --- a/acb_dirichlet/profile/p-gauss.c +++ b/acb_dirichlet/profile/p-gauss.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) acb_dirichlet_gauss_sum_theta, acb_dirichlet_gauss_sum, acb_dirichlet_gauss_sum }; - char * name[5] = { "naive", "factor", "theta", "default", "default+log" }; + char * name[5] = { "naive", "factor", "theta", "default", "precomp" }; int i, ni = 5; ulong qmin[5] = { 3, 50, 500, 1000, 10000 }; @@ -96,7 +96,7 @@ int main(int argc, char *argv[]) acb_dirichlet_group_init(G, q); if (l == 4) - acb_dirichlet_group_dlog_precompute(G, q); + acb_dirichlet_group_dlog_precompute(G, 1); acb_dirichlet_char_init(chi, G); acb_dirichlet_char_first_primitive(chi, G); acb_init(res); diff --git a/acb_dirichlet/profile/p-vec.c b/acb_dirichlet/profile/p-vec.c index 3ce17a02..098bfdd3 100644 --- a/acb_dirichlet/profile/p-vec.c +++ b/acb_dirichlet/profile/p-vec.c @@ -42,7 +42,7 @@ do_dlog_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_c } static void -do_sieve(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +do_eratos(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) { slong k, p, pmax; n_primes_t iter; @@ -81,12 +81,16 @@ int main(int argc, char *argv[]) flint_rand_t state; slong r, nr; - int l, nf = 6; - do_f func[6] = { do_empty, acb_dirichlet_ui_chi_vec_loop, do_dlog_primeloop, - acb_dirichlet_ui_chi_vec_primeloop, do_sieve, + int l, nf = 9; + do_f func[9] = { do_empty, acb_dirichlet_ui_chi_vec_loop, do_dlog_primeloop, + acb_dirichlet_ui_chi_vec_primeloop, do_eratos, + acb_dirichlet_ui_chi_vec, + acb_dirichlet_ui_chi_vec, + acb_dirichlet_ui_chi_vec, acb_dirichlet_ui_chi_vec }; - char * name[6] = { "char only", "big loop", "prime loops", - "prime dlog_vec", "manual sieve", "default" }; + char * name[9] = { "char only", "big loop", "prime loops", + "prime dlog_vec", "manual eratos", "default", + "precomp 1", "precomp 20", "precomp 100" }; int i, ni = 5; ulong qmin[5] = { 2, 1000, 3000, 10000, 100000 }; @@ -131,12 +135,16 @@ int main(int argc, char *argv[]) { if (out == LOG) - flint_printf("%wu * chi(rand, 1..%wu) for all %wu <= q <= %wu....\n", nr, nv[j], qmin[i], qmax[i]); + flint_printf("%wu * ui_chi(rand, 1..%wu) for all %wu <= q <= %wu....\n", nr, nv[j], qmin[i], qmax[i]); for (l = 0; l < nf; l++) { ulong q; + /* eratos too slow */ + if (l == 4 && i > 2) + continue; + if (out == LOG) flint_printf("%-14s ... ", name[l]); else if (out == CSV) @@ -155,12 +163,18 @@ int main(int argc, char *argv[]) acb_dirichlet_group_init(G, q); acb_dirichlet_char_init(chi, G); + if (l >= 6) + acb_dirichlet_group_dlog_precompute(G, (l == 6) ? 1 : (l==7) ? 20 : 100); + for (r = 0; r < nr; r++) { acb_dirichlet_char(chi, G, rand[r] % q); func[l](v, G, chi, nv[j]); } + if (l >= 6) + acb_dirichlet_group_dlog_clear(G); + acb_dirichlet_char_clear(chi); acb_dirichlet_group_clear(G); } diff --git a/acb_dirichlet/ui_chi_vec_primeloop.c b/acb_dirichlet/ui_chi_vec_primeloop.c index f05cc408..7e1311da 100644 --- a/acb_dirichlet/ui_chi_vec_primeloop.c +++ b/acb_dirichlet/ui_chi_vec_primeloop.c @@ -62,7 +62,10 @@ acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, cons acb_dirichlet_prime_group_struct P = G->P[l]; /* FIXME: there may be some precomputed dlog in P if needed */ - dlog_vec_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, chi->order); + if (P.dlog == NULL) + dlog_vec_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, chi->order); + else + dlog_vec_add_precomp(v, nv, P.dlog, P.g, chi->expo[l], P.pe, P.phi, chi->order); } acb_dirichlet_ui_vec_set_null(v, G, nv); diff --git a/dlog.h b/dlog.h index 8a4805ec..3a475044 100644 --- a/dlog.h +++ b/dlog.h @@ -259,4 +259,9 @@ void dlog_vec_sieve(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na void dlog_vec_add(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); void dlog_vec(ulong * v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); + +void dlog_vec_sieve_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_sieve_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); +void dlog_vec_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order); + #endif diff --git a/dlog/vec_add_precomp.c b/dlog/vec_add_precomp.c new file mode 100644 index 00000000..9bcfeeac --- /dev/null +++ b/dlog/vec_add_precomp.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dlog.h" + +void +dlog_vec_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + if (va == 0) + return; + if (na * DLOG_LOOP_MAX_FACTOR < nv) + dlog_vec_loop_add(v, nv, a, va, mod, na, order); + else + dlog_vec_sieve_add_precomp(v, nv, pre, a, va, mod, na, order); +} diff --git a/dlog/vec_init.c b/dlog/vec_fill.c similarity index 100% rename from dlog/vec_init.c rename to dlog/vec_fill.c diff --git a/dlog/vec_sieve.c b/dlog/vec_sieve.c index eb877c1f..693adcdc 100644 --- a/dlog/vec_sieve.c +++ b/dlog/vec_sieve.c @@ -18,80 +18,10 @@ void dlog_vec_sieve(ulong *v, ulong nv, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) { - ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; - ulong logcost; -#if 0 - ulong limcount; -#endif - ulong k, p, p1, pmax, logm1; + ulong p1 = 50; /* FIXME: tune this limit! */ dlog_precomp_t pre; - n_primes_t iter; - ulong X, aX, vaX; - dlog_vec_fill(v, nv, DLOG_NOT_FOUND); - v[1] = 0; - - logm1 = (na % 2) ? 0 : nmod_mul(na / 2, va, order); - - /* discrete log on first primes, then sieve */ - pmax = (nv < mod.n) ? nv : mod.n; - p1 = 50; /* FIXME: tune this limit! */ dlog_precomp_n_init(pre, a, mod.n, na, p1); - logcost = pre->cost; - -#if 0 - if (logcost < 15) - { - /* p1 = pmax; */ - limcount = mod.n; - } - else - { - limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); - } -#endif - - /* take big power of gen */ - X = n_nextprime(3 * na / 2, 0) % na; - aX = nmod_pow_ui(a, X, mod); - vaX = nmod_mul(va, X % order.n, order); - - n_primes_init(iter); - while ((p = n_primes_next(iter)) < pmax) - { - double cost; - ulong m, vp; - if (mod.n % p == 0) - continue; /* won't be attained another time */ - cost = log(mod.n)/log(p); - cost = pow(cost,cost); - sievecount++; - /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ - /* if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ - if (logcost < cost || (vp = dlog_vec_pindex_factorgcd(v, nv, p, mod, aX, na, vaX, logm1, order, cost)) == DLOG_NOT_FOUND) - { - if (logcost < cost) - sievecount--; - else - missed++; - logcount++; - vp = nmod_mul(dlog_precomp(pre, p), va, order); - } - for (k = p, m = 1; k < nv; k += p, m++) - { - if (v[m] == DLOG_NOT_FOUND) - continue; - smooth++; - v[k] = nmod_add(v[m], vp, order); - } - } -#if vbs - if (missed) - flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", - smooth, limcount, mod.n, logcost, logcount, sievecount, missed); -#endif - n_primes_clear(iter); + dlog_vec_sieve_precomp(v, nv, pre, a, va, mod, na, order); dlog_precomp_clear(pre); - for (k = mod.n + 1; k < nv; k++) - v[k] = v[k - mod.n]; } diff --git a/dlog/vec_sieve_add_precomp.c b/dlog/vec_sieve_add_precomp.c new file mode 100644 index 00000000..b753a0b7 --- /dev/null +++ b/dlog/vec_sieve_add_precomp.c @@ -0,0 +1,26 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dlog.h" + +void +dlog_vec_sieve_add_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + ulong * w, k; + /* store size */ + w = flint_malloc(nv * sizeof(ulong)); + dlog_vec_sieve_precomp(w, nv, pre, a, va, mod, na, order); + /* write in v */ + for (k = 0; k < nv; k++) + if (v[k] != DLOG_NOT_FOUND) + v[k] = nmod_add(v[k], w[k], order); + flint_free(w); +} diff --git a/dlog/vec_sieve_precomp.c b/dlog/vec_sieve_precomp.c new file mode 100644 index 00000000..71b405b6 --- /dev/null +++ b/dlog/vec_sieve_precomp.c @@ -0,0 +1,95 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dlog.h" +#include + +#define vbs 0 + +/* TODO: tune the limit dlog -> index calculus */ +void +dlog_vec_sieve_precomp(ulong *v, ulong nv, dlog_precomp_t pre, ulong a, ulong va, nmod_t mod, ulong na, nmod_t order) +{ + ulong smooth = 0, sievecount = 0, logcount = 0, missed = 0; + ulong logcost; +#if 0 + ulong limcount; +#endif + ulong k, p, pmax, logm1; + n_primes_t iter; + ulong X, aX, vaX; + + dlog_vec_fill(v, nv, DLOG_NOT_FOUND); + v[1] = 0; + + logm1 = (na % 2) ? 0 : nmod_mul(na / 2, va, order); + + /* discrete log on first primes, then sieve */ + pmax = (nv < mod.n) ? nv : mod.n; + logcost = pre->cost; + +#if 0 + if (logcost < 15) + { + /* p1 = pmax; */ + limcount = mod.n; + } + else + { + limcount = ceil(pow((double)mod.n,1./2.3) * 40 / logcost); + } +#endif + + /* take big power of gen */ + X = n_nextprime(3 * na / 2, 0) % na; + aX = nmod_pow_ui(a, X, mod); + vaX = nmod_mul(va, X % order.n, order); + + n_primes_init(iter); + while ((p = n_primes_next(iter)) < pmax) + { + double cost; + ulong m, vp; + if (mod.n % p == 0) + continue; /* won't be attained another time */ + cost = log(mod.n)/log(p); + cost = pow(cost,cost); + sievecount++; + /* if (p < p1 || (wp = logp_sieve(w, nv, p, mod.n, logm1, order, logcost)) == NOT_FOUND) */ + /* if (smooth < limcount || (wp = logp_sieve_factor(w, nv, p, mod.n, a, na, va, logm1, order, logcost)) == NOT_FOUND)*/ + if (logcost < cost || (vp = dlog_vec_pindex_factorgcd(v, nv, p, mod, aX, na, vaX, logm1, order, cost)) == DLOG_NOT_FOUND) + { + if (logcost < cost) + sievecount--; + else + missed++; + logcount++; + vp = nmod_mul(dlog_precomp(pre, p), va, order); + } + for (k = p, m = 1; k < nv; k += p, m++) + { + if (v[m] == DLOG_NOT_FOUND) + continue; + smooth++; + v[k] = nmod_add(v[m], vp, order); + } + } +#if vbs + if (missed) + flint_printf("[sieve: got %wu / %wu, n = %wu, cost %wu, logs %wu, sieve %wu missed %wu]\n", + smooth, limcount, mod.n, logcost, logcount, sievecount, missed); +#endif + n_primes_clear(iter); + + for (k = mod.n + 1; k < nv; k++) + v[k] = v[k - mod.n]; + +} From 90404742461bf4c0ac3dda5c8286ee654d5d3252 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 21 Sep 2016 15:04:01 +0200 Subject: [PATCH 120/139] vocabulary: number/log/index --- acb_dirichlet.h | 4 +++ acb_dirichlet/conrey_index.c | 40 +++++++++++++++++++++ acb_dirichlet/index_conrey.c | 38 ++++++++++++++++++++ doc/source/acb_dirichlet.rst | 69 ++++++++++++++++++++---------------- 4 files changed, 121 insertions(+), 30 deletions(-) create mode 100644 acb_dirichlet/conrey_index.c create mode 100644 acb_dirichlet/index_conrey.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index d5504887..f67e6b0c 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -114,9 +114,13 @@ int acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirich int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); ulong acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); + void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); +void acb_dirichlet_conrey_index(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong j); +ulong acb_dirichlet_index_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); + void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); diff --git a/acb_dirichlet/conrey_index.c b/acb_dirichlet/conrey_index.c new file mode 100644 index 00000000..2c02ce53 --- /dev/null +++ b/acb_dirichlet/conrey_index.c @@ -0,0 +1,40 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_conrey_index(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong j) +{ + slong k; + + for (k = 0; k < G->num; k++) + { + x->log[k] = j % G->P[k].phi; + j = j / G->P[k].phi; + } + + acb_dirichlet_conrey_exp(x, G); +} diff --git a/acb_dirichlet/index_conrey.c b/acb_dirichlet/index_conrey.c new file mode 100644 index 00000000..a3a2b543 --- /dev/null +++ b/acb_dirichlet/index_conrey.c @@ -0,0 +1,38 @@ +/*============================================================================= + + This file is part of ARB. + + ARB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ARB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ARB; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +=============================================================================*/ +/****************************************************************************** + + Copyright (C) 2016 Pascal Molin + +******************************************************************************/ + +#include "acb_dirichlet.h" + +ulong +acb_dirichlet_index_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +{ + slong k; + ulong j = 0; + + for (k = 0; k < G->num; k++) + j = j * G->P[k].phi + x->log[k]; + + return j; +} diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 1890a030..15e938f5 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -35,11 +35,11 @@ introduced in the LMFDB, which is an explicit choice of isomorphism (\mathbb Z/q\mathbb Z)^\times & \to &\bigoplus_i \mathbb Z/\phi_i\mathbb Z \\ x & \mapsto & (e_i) -We call *number* a residue class `x` modulo *q*, and *index* the +We call *number* a residue class `x` modulo *q*, and *log* the corresponding vector `(e_i)` of exponents of Conrey generators. -Going from an *index* to the corresponding *number* is a cheap -operation while the converse requires computing discrete +Going from a *log* to the corresponding *number* is a cheap +operation called exp, while the converse requires computing discrete logarithms. .. type:: acb_dirichlet_group_struct @@ -104,12 +104,12 @@ Conrey elements .. type:: acb_dirichlet_conrey_t Represents elements of the unit group mod *q*, keeping both the - *number* (residue class) and *index* (exponents on the group + *number* (residue class) and *log* (exponents on the group generators). .. function:: void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) - Sets *x* to the element of number *m*, computing its index using discrete + Sets *x* to the element of number *m*, computing its log using discrete logarithm in *G*. .. function:: ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) @@ -118,11 +118,11 @@ Conrey elements .. function:: void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - Sets *x* to the *number* `1\in G`, having *index* `[0,\dots 0]`. + Sets *x* to the *number* `1\in G`, having *log* `[0,\dots 0]`. .. function:: void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - Sets *x* to the first primitive element of *G*, having *index* `[1,\dots 1]`, + Sets *x* to the first primitive element of *G*, having *log* `[1,\dots 1]`, or `[0, 1, \dots 1]` if `8\mid q`. .. function:: void acb_dirichlet_conrey_set(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t y) @@ -131,13 +131,13 @@ Conrey elements .. function:: int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - Sets *x* to the next conrey index in *G* with lexicographic ordering. + Sets *x* to the next conrey element in *G* with lexicographic ordering. The return value is the index of the last updated exponent of *x*, or *-1* if the last element has been reached. - This function allows to iterate on the elements of *G* looping on their *index*. + This function allows to iterate on the elements of *G* looping on their *log*. Note that it produces elements in seemingly random *number* order. The following template can be used to loop over all elements *x* in *G*:: @@ -152,6 +152,14 @@ Conrey elements Same as :func:`acb_dirichlet_conrey_next`, but jumps to the next element corresponding to a primitive character of *G*. +.. function:: ulong acb_dirichlet_index_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); + + Returns the lexicographic index of *x* as an integer in `0\dots \varphi(q)`. + +.. function:: void acb_dirichlet_conrey_index(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong j) + + Sets *x* to the Conrey element of lexicographic index *j*. + .. function:: int acb_dirichlet_conrey_eq(const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) .. function:: int acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) @@ -219,7 +227,7 @@ Character type .. function:: void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - Sets *chi* to the Dirichlet character of Conrey index *x*. + Sets *chi* to the Dirichlet character corresponding to *x*. .. function:: int acb_dirichlet_char_eq(const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) @@ -256,7 +264,7 @@ Character properties ------------------------------------------------------------------------------- As a consequence of the Conrey numbering, all these numbers are available at the -level of *number* and *index*, and for *char*. +level of *number* and Conrey *log* elements, and for *char*. No discrete log computation is performed. .. function:: ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) @@ -523,25 +531,26 @@ the Fourier transform on Conrey labels as Compute the DFT of *v* using Conrey indices. This function assumes *v* and *w* are vectors of size *G->phi_q*, whose values correspond to a lexicographic ordering - of Conrey indices (as obtained using :func:`acb_dirichlet_conrey_next`). + of Conrey logs (as obtained using :func:`acb_dirichlet_conrey_next` or + by :func:`acb_dirichlet_index_conrey`). For example, if `q=15`, the Conrey elements are stored in following order - ============ ===================== - index [e,f] number = 7^e 11^f - ============ ===================== - [0, 0] 1 - [0, 1] 7 - [0, 2] 4 - [0, 3] 13 - [0, 4] 1 - [1, 0] 11 - [1, 1] 2 - [1, 2] 14 - [1, 3] 8 - [1, 4] 11 - ============ ===================== + ======= ============= ===================== + index log = [e,f] number = 7^e 11^f + ======= ============= ===================== + 0 [0, 0] 1 + 1 [0, 1] 7 + 2 [0, 2] 4 + 3 [0, 3] 13 + 4 [0, 4] 1 + 5 [1, 0] 11 + 6 [1, 1] 2 + 7 [1, 2] 14 + 8 [1, 3] 8 + 9 [1, 4] 11 + ======= ============= ===================== .. function:: void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) @@ -606,20 +615,20 @@ L-functions Compute all values `L(s,\chi)` for `\chi` mod `q`, by Hurwitz formula and discrete Fourier transform. - *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered Conrey - index. See :func:`acb_dirichlet_dft_conrey`. + *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered + Conrey logs. See :func:`acb_dirichlet_dft_conrey`. Implementation notes ------------------------------------------------------------------------------- The current implementation introduces a *char* type which contains a *conrey* -index plus additional information which +log plus additional information which - makes evaluation of a single character a bit faster - has some initialization cost. -Even if it is straightforward to convert a *conrey* index to the +Even if it is straightforward to convert a *conrey* log to the corresponding *char*, looping is faster at the level of Conrey representation. Things can be improved on this aspect but it makes code more intricate. From d58c1687b704601f5df4aa2dece839d1aaff3829 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 21 Sep 2016 15:04:25 +0200 Subject: [PATCH 121/139] thetanull search program improved --- acb_dirichlet/profile/p-thetanull.c | 229 ++++++++++++++++++++-------- acb_dirichlet/theta_arb.c | 2 + 2 files changed, 170 insertions(+), 61 deletions(-) diff --git a/acb_dirichlet/profile/p-thetanull.c b/acb_dirichlet/profile/p-thetanull.c index 2754cf92..05e66045 100644 --- a/acb_dirichlet/profile/p-thetanull.c +++ b/acb_dirichlet/profile/p-thetanull.c @@ -9,88 +9,195 @@ (at your option) any later version. See . */ +#include #include "acb_dirichlet.h" -int main() +static int usage(char *argv[]) { - slong prec = 64; - n_primes_t iter; - ulong q; + printf("usage: %s [--progress ] [--all] [--odd] [--prec ] [--onlymod] {qmin qmax | --value q a}\n", argv[0]); + return 1; +} - flint_printf("thetanull...."); - fflush(stdout); +static void +value(ulong q, ulong a, slong prec, slong digits) +{ + acb_dirichlet_group_t G; + acb_dirichlet_char_t chi; + acb_t res; + arb_t one; - /* look for vanishing theta values for prime power moduli */ - n_primes_init(iter); + acb_dirichlet_group_init(G, q); + acb_dirichlet_char_init(chi, G); + acb_dirichlet_char(chi, G, a); + acb_init(res); + arb_init(one); -#if 0 /* just to check q=300 & q=600 values */ - q = 2; - while (q++ < 1000) -#else - while ((q = n_primes_next(iter)) < 10000) -#endif + arb_one(one); + acb_dirichlet_theta_arb(res, G, chi, one, prec); + + acb_printd(res, digits); + flint_printf("\n"); + + arb_clear(one); + acb_clear(res); + acb_dirichlet_group_clear(G); + acb_dirichlet_char_clear(chi); +} + +static void +check_q(ulong q, int odd, slong prec, slong digits, int onlymod) +{ + slong s; + ulong k, len; + acb_dirichlet_group_t G; + acb_dirichlet_conrey_t x; + acb_dirichlet_group_init(G, q); + acb_dirichlet_conrey_init(x, G); + acb_ptr theta, z; + arb_t z1; + arb_ptr t; + + theta = _acb_vec_init(G->phi_q); + z = _acb_vec_init(G->phi_q); + + arb_init(z1); + arb_const_pi(z1, prec); + arb_div_ui(z1, z1, q, prec); + arb_neg(z1, z1); + arb_exp(z1, z1, prec); + + /* len = acb_dirichlet_theta_length_d(q, 1., prec); */ + t = _arb_vec_init(q); + acb_dirichlet_arb_quadratic_powers(t, q, z1, prec); + + for (s = 0; s <= odd; s++) { - slong s; - ulong k; - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); - acb_ptr theta, z; - arb_t z1; - arb_ptr t; + k = 0; + acb_dirichlet_conrey_one(x, G); + do { + acb_set_arb(z + k, t + x->n); + k++; + } while (acb_dirichlet_conrey_next(x, G) >= 0); - theta = _acb_vec_init(G->phi_q); - z = _acb_vec_init(G->phi_q); + acb_dirichlet_dft_conrey(theta, z, G, prec); - arb_init(z1); - arb_const_pi(z1, prec); - arb_div_ui(z1, z1, q, prec); - arb_neg(z1, z1); - arb_exp(z1, z1, prec); - - t = _arb_vec_init(q); - acb_dirichlet_arb_quadratic_powers(t, q, z1, prec); - - for (s = 0; s <= 1; s++) + /* check zeros */ + acb_dirichlet_conrey_one(x, G); + for (k = 0; k < G->phi_q; k++) { - k = 0; - acb_dirichlet_conrey_one(x, G); - do { - acb_set_arb(z + k, t + x->n); - k++; - } while (acb_dirichlet_conrey_next(x, G) >= 0); - - acb_dirichlet_dft_conrey(theta, z, G, prec); - - for (k = 0; k < G->phi_q; k++) + if (acb_contains_zero(theta + k) + && acb_dirichlet_conrey_conductor(G, x) == q + && acb_dirichlet_conrey_parity(G, x) == s) { - if (acb_contains_zero(theta + k)) + if (onlymod) + { + flint_printf("%wu,%wu\n",q,x->n); + } + else { - - slong i; - acb_dirichlet_conrey_one(x, G); - for (i = 0; i < k; i++) - acb_dirichlet_conrey_next(x, G); - if (acb_dirichlet_conrey_conductor(G,x) < q || acb_dirichlet_conrey_parity(G, x) != s) - continue; flint_printf("\ntheta null q = %wu, n = %wu\n",q, x->n); - acb_printd(theta + k, 10); + acb_printd(theta + k, digits); + flint_printf("\n"); } } + acb_dirichlet_conrey_next(x, G); + } + if (odd) + { /* change t for odd characters */ for (k = 0; k < q; k++) arb_mul_ui(t + k, t + k, k, prec); - } - _arb_vec_clear(t, q); - _acb_vec_clear(theta, G->phi_q); - _acb_vec_clear(z, G->phi_q); - arb_clear(z1); - acb_dirichlet_conrey_clear(x); - acb_dirichlet_group_clear(G); + } + + _arb_vec_clear(t, q); + _acb_vec_clear(theta, G->phi_q); + _acb_vec_clear(z, G->phi_q); + arb_clear(z1); + acb_dirichlet_conrey_clear(x); + acb_dirichlet_group_clear(G); +} + + +int main(int argc, char *argv[]) +{ + int i, all = 0, odd = 0, onlymod = 0, eval = 0; + slong prec = 50, digits = 10; + slong step = 0; + ulong q, qmin, qmax; + n_primes_t iter; + + if (argc < 3) + return usage(argv); + + for (i = 1; i < argc - 2; i++) + { + if (!strcmp(argv[i],"--eval")) + eval = 1; + if (!strcmp(argv[i],"--all")) + all = 1; + if (!strcmp(argv[i],"--onlymod")) + onlymod = 1; + else if (!strcmp(argv[i],"--odd")) + odd = 1; + else if (!strcmp(argv[i],"--progress")) + { + i++; + step = atol(argv[i]); + } + else if (!strcmp(argv[i],"--prec")) + { + i++; + prec = atol(argv[i]); + digits = floor(prec * 0.3); + } + } + + if (argc < i + 2) + return usage(argv); + + qmin = atol(argv[i]); + qmax = atol(argv[i+1]); + + if (eval) + { + value(qmin, qmax, prec, digits); + } + else + { + if (all) + { + for (q = qmin; q <= qmax; q++) + { + if (q % 4 == 2) + continue; + check_q(q, odd, prec, digits, onlymod); + if (step && q % step == 0) + flint_printf("[%wu]",q); + } + } + else + { + ulong p; + slong it = 0; + /* look for vanishing theta values for prime power moduli */ + n_primes_init(iter); + n_primes_jump_after(iter, qmin - 1); + + while ((p = n_primes_next(iter)) < qmax) + { + + for (q = p; q < qmax; q *= p) + check_q(q, odd, prec, digits, onlymod); + + if (step && (it++ % step == 0)) + flint_printf("[%wu]",p); + } + + n_primes_clear(iter); + } } flint_cleanup(); diff --git a/acb_dirichlet/theta_arb.c b/acb_dirichlet/theta_arb.c index 3e5893a2..fa2d4e7a 100644 --- a/acb_dirichlet/theta_arb.c +++ b/acb_dirichlet/theta_arb.c @@ -89,5 +89,7 @@ acb_dirichlet_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_diri arb_add_error_mag(acb_imagref(res), e); mag_clear(e); + + acb_mul_2exp_si(res, res, 1); arb_clear(xt); } From c5514c13ce18877a214876a8a8ea1cc55422934f Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 21 Sep 2016 15:42:22 +0200 Subject: [PATCH 122/139] thetanull missed some primepowers --- acb_dirichlet/profile/p-thetanull.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acb_dirichlet/profile/p-thetanull.c b/acb_dirichlet/profile/p-thetanull.c index 05e66045..80febca5 100644 --- a/acb_dirichlet/profile/p-thetanull.c +++ b/acb_dirichlet/profile/p-thetanull.c @@ -184,12 +184,12 @@ int main(int argc, char *argv[]) slong it = 0; /* look for vanishing theta values for prime power moduli */ n_primes_init(iter); - n_primes_jump_after(iter, qmin - 1); while ((p = n_primes_next(iter)) < qmax) { - for (q = p; q < qmax; q *= p) + for (q = p; q < qmin; q*= p); + for (; q < qmax; q *= p) check_q(q, odd, prec, digits, onlymod); if (step && (it++ % step == 0)) From 996bdfdabe29ef5ac77efe99b13412fc1439e982 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 22 Sep 2016 16:43:41 +0200 Subject: [PATCH 123/139] document root number --- acb_dirichlet.h | 2 +- acb_dirichlet/gauss_sum_theta.c | 2 +- acb_dirichlet/root_number.c | 4 ++-- acb_dirichlet/ui_conductor.c | 1 - doc/source/acb_dirichlet.rst | 14 ++++++++++++++ 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index f67e6b0c..93ff69dc 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -274,7 +274,7 @@ void acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, s void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); -void _acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_root_number_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index 0e92c19d..d46945c9 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -27,7 +27,7 @@ acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const ac acb_t iq; acb_init(iq); acb_dirichlet_gauss_sum_order2(iq, chi, prec); - _acb_dirichlet_root_number(res, G, chi, prec); + acb_dirichlet_root_number_theta(res, G, chi, prec); acb_mul(res, res, iq, prec); acb_clear(iq); } diff --git a/acb_dirichlet/root_number.c b/acb_dirichlet/root_number.c index 55288118..36eb42c6 100644 --- a/acb_dirichlet/root_number.c +++ b/acb_dirichlet/root_number.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -_acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_root_number_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) { arb_t x; acb_t eps; @@ -47,6 +47,6 @@ acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_di } else { - _acb_dirichlet_root_number(res, G, chi, prec); + acb_dirichlet_root_number_theta(res, G, chi, prec); } } diff --git a/acb_dirichlet/ui_conductor.c b/acb_dirichlet/ui_conductor.c index 69f1d43e..e5069798 100644 --- a/acb_dirichlet/ui_conductor.c +++ b/acb_dirichlet/ui_conductor.c @@ -11,7 +11,6 @@ #include "acb_dirichlet.h" -/* TODO: product of local conductors */ ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) { diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 15e938f5..a5c520df 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -598,6 +598,20 @@ Simple functions L-functions ------------------------------------------------------------------------------- +.. function:: void acb_dirichlet_root_number_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + +.. function:: void acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + + Sets *res* to the root number `\epsilon(\chi)` for a primitive character *chi*, + which appears in the functional equation (where `p` is the parity of `\chi`): + + .. math:: + + \frac{q}{π})^{\frac{s+p}2}\Gamma(\frac{s+p}2) L(s, \chi) = \epsilon(\chi) \frac{q}{π})^{\frac{1-s+p}2}\Gamma(\frac{1-s+p}2) L(1 - s, \overline\chi) + + The *theta* variant uses the evaluation at `t=1` of the Theta series. + The default version computes it via the gauss sum. + .. function:: void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) Compute `L(s,\chi)` using decomposition in terms of the Hurwitz zeta function From 4f51c02edb5f327d45bd7caf0dc551b1b9b32606 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 27 Sep 2016 15:24:49 +0200 Subject: [PATCH 124/139] add dft crt decomposition --- acb_dirichlet.h | 26 +++++++ acb_dirichlet/dft_crt.c | 143 +++++++++++++++++++++++++++++++++++++ acb_dirichlet/dft_fast.c | 1 + acb_dirichlet/test/t-dft.c | 16 ++++- 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 acb_dirichlet/dft_crt.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 93ff69dc..6cbcecc1 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -291,9 +291,27 @@ void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet /* Discrete Fourier Transform */ +#define CRT_MAX 15 +typedef struct +{ + int num; + nmod_t n; + slong m[CRT_MAX]; + ulong M[CRT_MAX]; + ulong vM[CRT_MAX]; +} +crt_struct; + +typedef crt_struct crt_t[1]; + +void crt_init(crt_t c, ulong n); + +void crt_decomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); +void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); void acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec); void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec); void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); @@ -308,6 +326,14 @@ acb_vec_printd(acb_srcptr vec, slong len, slong digits) acb_printd(vec + i, digits), flint_printf("\n"); } +ACB_DIRICHLET_INLINE void +acb_vec_printd_index(acb_srcptr vec, slong len, slong digits) +{ + slong i; + for (i = 0; i < len; i++) + flint_printf("[%ld] ",i), acb_printd(vec + i, digits), flint_printf("\n"); +} + #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/dft_crt.c b/acb_dirichlet/dft_crt.c new file mode 100644 index 00000000..83dcb241 --- /dev/null +++ b/acb_dirichlet/dft_crt.c @@ -0,0 +1,143 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +crt_init(crt_t c, ulong n) +{ + int k; + n_factor_t fac; + + n_factor_init(&fac); + n_factor(&fac, n, 1); + + nmod_init(&c->n, n); + + c->num = fac.num; + for (k = 0; k < fac.num; k++) + { + c->m[k] = n_pow(fac.p[k], fac.exp[k]); + c->M[k] = n / c->m[k]; + c->vM[k] = c->M[k] * n_invmod(c->M[k] % c->m[k], c->m[k]); + /* + flint_printf("m[%ld]=%ld, M[%ld]=%wu, vM[%ld]=%wu\n", + k, c->m[k], k, c->M[k], k, c->vM[k]); + */ + } +} + +#if 0 +/* lexicographic index of crt elt j */ +static ulong +index_crt(crt_t c, ulong j) +{ + int k; + ulong res = 0; + for (k = 0; k < c->num; k ++) + res = res * c->m[k] + (j % c->m[k]); + return res; +} + +/* crt elt of lexicographic index i */ +static ulong +crt_index(crt_t c, ulong i) +{ + int k; + ulong j, res = 0; + for (k = 0; k < c->num; k ++) + { + j = i % c->m[k]; + i = i / c->m[k]; + res = nmod_add(res, j * c->vM[k], c->n); + } + return res; +} +/* for all elements can do fast conrey-like loop just adding vM[k] */ +static acb_ptr +reorder_to_crt(acb_srcptr v, crt_t c, ulong len) +{ + ulong k; + acb_ptr res; + res = flint_malloc(len * sizeof(acb_struct)); + for (k = 0; k < len; k++) + res[index_crt(c, k)] = v[k]; + return res; +} +static acb_ptr +reorder_from_crt(acb_srcptr v, crt_t c, ulong len) +{ + ulong k; + acb_ptr res; + res = flint_malloc(len * sizeof(acb_struct)); + for (k = 0; k < len; k++) + res[k] = v[index_crt(c, k)]; + return res; +} +#endif + +void +crt_decomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) +{ + int j, e[CRT_MAX]; + ulong k, l; + + for (j = 0; j < c->num; j++) + e[j] = 0; + + l = 0; + for(k = 0; k < len; k++) + { + /*flint_printf("set y[%wu] = x[%wu]\n", k, l);*/ + acb_set(y + k, x + l); + for (j = c->num - 1; j >= 0; e[j] = 0, j--) + { + e[j]++; l = nmod_add(l, c->vM[j], c->n); + if (e[j] < c->m[j]) + break; + } + } +} + +void +crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) +{ + int j, e[CRT_MAX]; + ulong k, l; + + for (j = 0; j < c->num; j++) + e[j] = 0; + + l = 0; + for(k = 0; k < len; k++) + { + acb_set(y + l, x + k); + for (j = c->num - 1; j >= 0; e[j] = 0, j--) + { + e[j]++; l = nmod_add(l, c->M[j], c->n); + if (e[j] < c->m[j]) + break; + } + } +} + +void +acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) +{ + crt_t c; + acb_ptr t; + t = _acb_vec_init(len); + crt_init(c, len); + crt_decomp(w, v, c, len); + acb_dirichlet_dft_prod(t, w, c->m, c->num, prec); + crt_recomp(w, t, c, len); + _acb_vec_clear(t, len); +} diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c index ce6410e2..7d855639 100644 --- a/acb_dirichlet/dft_fast.c +++ b/acb_dirichlet/dft_fast.c @@ -22,6 +22,7 @@ vec_extract(acb_srcptr v, slong step, slong len) res[k] = v[l]; return res; } + void _acb_dft_base(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong n, slong prec) { diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index aed49e38..a01e1364 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -54,7 +54,21 @@ int main() abort(); } } - + acb_dirichlet_dft_crt(w2, v, q[k], prec); + for (i = 0; i < q[k]; i++) + { + if (!acb_overlaps(w1 + i, w2 + i)) + { + flint_printf("differ from index %ld / %ld \n\n",i,q[k]); + flint_printf("pol =\n"); + acb_vec_printd(w1, q[k], digits); + flint_printf("crt =\n"); + acb_vec_printd(w2, q[k], digits); + flint_printf("\n\n"); + abort(); + } + } + _acb_vec_clear(v, q[k]); _acb_vec_clear(w1, q[k]); _acb_vec_clear(w2, q[k]); From 54f2c0152acaed13149c76c3145b674fcfd21df3 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 28 Sep 2016 17:03:36 +0200 Subject: [PATCH 125/139] reorganize dft, WIP --- acb_dirichlet.h | 185 ++++++++++++++++++- acb_dirichlet/dft_crt.c | 11 ++ acb_dirichlet/dft_cyc.c | 107 +++++++++++ acb_dirichlet/{dft_fast.c => dft_fast.c.tmp} | 0 acb_dirichlet/dft_pol.c | 21 +-- acb_dirichlet/dft_precomp.c | 95 ++++++++++ acb_dirichlet/dft_prod.c | 67 +++++++ acb_dirichlet/dft_step.c | 76 ++++++++ acb_dirichlet/test/t-dft.c | 2 +- 9 files changed, 542 insertions(+), 22 deletions(-) create mode 100644 acb_dirichlet/dft_cyc.c rename acb_dirichlet/{dft_fast.c => dft_fast.c.tmp} (100%) create mode 100644 acb_dirichlet/dft_precomp.c create mode 100644 acb_dirichlet/dft_prod.c create mode 100644 acb_dirichlet/dft_step.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 6cbcecc1..8eaeb774 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -251,6 +251,7 @@ void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t); void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec); void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec); +void acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec); void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec); @@ -291,6 +292,15 @@ void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet /* Discrete Fourier Transform */ +void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec); +void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); + +void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); +void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); + #define CRT_MAX 15 typedef struct { @@ -308,15 +318,174 @@ void crt_init(crt_t c, ulong n); void crt_decomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); -void acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec); -void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec); -void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); -void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); -void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); +typedef struct acb_dirichlet_dft_step_struct acb_dirichlet_dft_step_struct; +typedef acb_dirichlet_dft_step_struct * acb_dirichlet_dft_step_ptr; + +typedef struct +{ + slong n; + acb_ptr z; + slong num; + acb_dirichlet_dft_step_ptr cyc; +} +acb_dirichlet_dft_cyc_struct; + +typedef acb_dirichlet_dft_cyc_struct acb_dirichlet_dft_cyc_t[1]; + +typedef struct +{ + slong n; + slong num; + acb_dirichlet_dft_step_ptr cyc; +} +acb_dirichlet_dft_prod_struct; + +typedef acb_dirichlet_dft_prod_struct acb_dirichlet_dft_prod_t[1]; + +typedef struct +{ + slong n; + crt_t c; + /* then a product */ + acb_dirichlet_dft_step_ptr cyc; +} +acb_dirichlet_dft_crt_struct; + +typedef acb_dirichlet_dft_crt_struct acb_dirichlet_dft_crt_t[1]; + +typedef struct +{ + slong n; + slong dv; + acb_ptr z; + slong dz; +} +acb_dirichlet_dft_pol_struct; + +typedef acb_dirichlet_dft_pol_struct acb_dirichlet_dft_pol_t[1]; + +typedef struct +{ + int type; + union + { + acb_dirichlet_dft_cyc_t cyc; + acb_dirichlet_dft_prod_t prod; + acb_dirichlet_dft_crt_t crt; + acb_dirichlet_dft_pol_t pol; + } t; +} +acb_dirichlet_dft_pre_t; + +/* covers both product and cyclic case */ +struct +acb_dirichlet_dft_step_struct +{ + /* [G:H] */ + slong m; + /* card H */ + slong M; + slong dv; /* = M for prod, also = M if cyc is reordered */ + /* roots of unity, if needed */ + acb_srcptr z; + /* index of mM in z */ + slong dz; + /* dft to call on H */ + acb_dirichlet_dft_pre_t pre; + /* dft to call on G/H ? */ +}; + +/*typedef acb_dirichlet_dft_pre_struct acb_dirichlet_dft_pre_t[1];*/ + +enum +{ + DFT_POL, DFT_CYC, DFT_PROD, DFT_CRT /*, DFT_2E, DFT_CONV */ +}; + +void acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, slong num, slong prec); + +void acb_dirichlet_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_pre_t pre, slong prec); + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_pol_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_pol_t pol, slong prec) +{ + _acb_dirichlet_dft_pol(w, v, pol->dv, pol->z, pol->dz, pol->n, prec); +} +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_cyc_t cyc, slong prec) +{ + acb_dirichlet_dft_step(w, v, cyc->cyc, cyc->num, prec); +} +void acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_crt_t crt, slong prec); +void acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_prod_t prod, slong prec); + +void _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec); +void acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong len, slong prec); +void acb_dirichlet_dft_precomp_clear(acb_dirichlet_dft_pre_t pre); + +acb_dirichlet_dft_step_ptr _acb_dirichlet_dft_steps_prod(slong * m, slong num, slong prec); + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_prod_init(acb_dirichlet_dft_prod_t t, slong * cyc, slong num, slong prec) +{ + t->num = num; + t->cyc = _acb_dirichlet_dft_steps_prod(cyc, num, prec); +} + +void acb_dirichlet_dft_prod_clear(acb_dirichlet_dft_prod_t t); + +void _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, slong len, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong prec); +void _acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong len, slong dv, slong prec); + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong len, slong prec) +{ + _acb_dirichlet_dft_cyc_init(t, len, 1, prec); +} + +void acb_dirichlet_dft_cyc_clear(acb_dirichlet_dft_cyc_t t); + +ACB_DIRICHLET_INLINE void +_acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec) +{ + pol->n = len; + pol->dv = dv; + pol->z = z; + pol->dz = dz; +} + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong len, slong prec) +{ + pol->n = len; + pol->dv = 1; + pol->z = _acb_vec_init(len); + acb_dirichlet_vec_nth_roots(pol->z, len, prec); + pol->dz = 1; +} + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_pol_clear(acb_dirichlet_dft_pol_t pol) +{ + _acb_vec_clear(pol->z, pol->n); +} + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong len, slong prec) +{ + crt->n = len; + crt_init(crt->c, len); + crt->cyc = _acb_dirichlet_dft_steps_prod(crt->c->m, crt->c->num, prec); +} + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_crt_clear(acb_dirichlet_dft_crt_t crt) +{ + flint_free(crt->cyc); +} + +/* utils */ ACB_DIRICHLET_INLINE void acb_vec_printd(acb_srcptr vec, slong len, slong digits) diff --git a/acb_dirichlet/dft_crt.c b/acb_dirichlet/dft_crt.c index 83dcb241..c554227f 100644 --- a/acb_dirichlet/dft_crt.c +++ b/acb_dirichlet/dft_crt.c @@ -141,3 +141,14 @@ acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) crt_recomp(w, t, c, len); _acb_vec_clear(t, len); } + +void +acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_crt_t crt, slong prec) +{ + acb_ptr t; + t = _acb_vec_init(crt->n); + crt_decomp(w, v, crt->c, crt->n); + acb_dirichlet_dft_step(t, w, crt->cyc, crt->c->num, prec); + crt_recomp(w, t, crt->c, crt->n); + _acb_vec_clear(t, crt->n); +} diff --git a/acb_dirichlet/dft_cyc.c b/acb_dirichlet/dft_cyc.c new file mode 100644 index 00000000..472661fb --- /dev/null +++ b/acb_dirichlet/dft_cyc.c @@ -0,0 +1,107 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +_acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, slong len, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong prec) +{ + slong i, j, num; + t->n = len; + num = 0; + for (i = 0; i < fac.num; i++) + num += fac.exp[i]; + t->num = num; + t->cyc = flint_malloc(num * sizeof(acb_dirichlet_dft_step_struct)); + + /* FIXME: if z is allocated here, it must be cleared somewhere */ + if (z == NULL) + { + z = _acb_vec_init(t->n); + acb_dirichlet_vec_nth_roots(z, t->n, prec); + dz = 1; + } + t->z = z; + + num = 0; + for (i = 0; i < fac.num; i++) + { + for (j = 0; j < fac.exp[i]; j++) + { + slong m, M; + m = fac.p[i]; + M = (len /= m); + t->cyc[num].m = m; + t->cyc[num].M = M; + t->cyc[num].dv = dv; + t->cyc[num].z = z; + t->cyc[num].dz = dz; + _acb_dirichlet_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec); + dv *= m; + dz *= m; + num++; + } + } + } + +void +_acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong dv, slong len, slong prec) +{ + n_factor_t fac; + n_factor_init(&fac); + n_factor(&fac, len, 0); + _acb_dirichlet_dft_cyc_init_z_fac(t, len, fac, dv, NULL, 0, prec); +} + +void +acb_dirichlet_dft_cyc_clear(acb_dirichlet_dft_cyc_t t) +{ + slong i; + for (i = 0; i < t->num; i++) + acb_dirichlet_dft_precomp_clear(t->cyc[i].pre); + flint_free(t->cyc); + _acb_vec_clear(t->z, t->n); +} + + +#if 0 +/* shallow extract */ +static acb_ptr +vec_extract(acb_srcptr v, slong step, slong len) +{ + slong k, l; + acb_ptr res; + res = flint_malloc(len * sizeof(acb_struct)); + for (k = 0, l = 0; k < len; k++, l+=step) + res[k] = v[l]; + return res; +} + +void +_acb_dirichlet_dft_base(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong n, slong prec) +{ + acb_ptr v1, z1; + v1 = vec_extract(v, dv, n); + z1 = vec_extract(z, dz, n); + _acb_dirichlet_dft_pol(w, v1, z1, n, prec); + flint_free(v1); + flint_free(z1); +} +#endif + +void +acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) +{ + acb_dirichlet_dft_cyc_t t; + acb_dirichlet_dft_cyc_init(t, len, prec); + acb_dirichlet_dft_cyc_precomp(w, v, t, prec); + acb_dirichlet_dft_cyc_clear(t); +} diff --git a/acb_dirichlet/dft_fast.c b/acb_dirichlet/dft_fast.c.tmp similarity index 100% rename from acb_dirichlet/dft_fast.c rename to acb_dirichlet/dft_fast.c.tmp diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c index 116cbe70..c395a736 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dirichlet/dft_pol.c @@ -14,23 +14,18 @@ /* all roots are already computed */ void -_acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, acb_srcptr z, slong len, slong prec) +_acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec) { - /* FIXME: huge accuracy loss */ -#if 0 - _acb_poly_evaluate_vec_fast(w, v, len, z, len, prec); -#elif 0 - _acb_poly_evaluate_vec_iter(w, v, len, z, len, prec); -#else slong i, j; + acb_ptr wi; + acb_srcptr vj; - for (i = 0; i < len; i++) + for (i = 0, wi = w; i < len; i++, wi++) { - acb_zero(w + i); - for (j = 0; j < len; j++) - acb_addmul(w + i, v + j, z + (i * j % len), prec); + acb_zero(wi); + for (j = 0, vj = v; j < len; j++, vj += dv) + acb_addmul(wi, vj, z + dz * (i * j % len), prec); } -#endif } void @@ -39,6 +34,6 @@ acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec) acb_ptr z; z = _acb_vec_init(len); acb_dirichlet_vec_nth_roots(z, len, prec); - _acb_dirichlet_dft_pol(w, v, z, len, prec); + _acb_dirichlet_dft_pol(w, v, 1, z, 1, len, prec); _acb_vec_clear(z, len); } diff --git a/acb_dirichlet/dft_precomp.c b/acb_dirichlet/dft_precomp.c new file mode 100644 index 00000000..5eef41f6 --- /dev/null +++ b/acb_dirichlet/dft_precomp.c @@ -0,0 +1,95 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +_acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec) +{ + if (n_is_prime(len)) + { + /* TODO: need convolution if len is large */ + pre.type = DFT_POL; + _acb_dirichlet_dft_pol_init(pre.t.pol, dv, z, dz, len, prec); + } + else + { + n_factor_t fac; + + n_factor_init(&fac); + n_factor(&fac, len, 1); + + if (fac.num == 1) + { + /* TODO: could be p^e, or 2^e */ + pre.type = DFT_CYC; + _acb_dirichlet_dft_cyc_init_z_fac(pre.t.cyc, len, fac, dv, z, dz, prec); + } + else + { + pre.type = DFT_CRT; + acb_dirichlet_dft_crt_init(pre.t.crt, len, prec); + } + } +} + +void +acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong len, slong prec) +{ +} + +void +acb_dirichlet_dft_precomp_clear(acb_dirichlet_dft_pre_t pre) +{ + switch (pre.type) + { + case DFT_POL: + acb_dirichlet_dft_pol_clear(pre.t.pol); + break; + case DFT_CYC: + acb_dirichlet_dft_cyc_clear(pre.t.cyc); + break; + case DFT_PROD: + acb_dirichlet_dft_prod_clear(pre.t.prod); + break; + case DFT_CRT: + acb_dirichlet_dft_crt_clear(pre.t.crt); + break; + default: + flint_printf("acb_dirichlet_dft_clear: unknown strategy code %i\n", pre.type); + abort(); + break; + } +} + +void +acb_dirichlet_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_pre_t pre, slong prec) +{ + switch (pre.type) + { + case DFT_POL: + acb_dirichlet_dft_pol_precomp(w, v, pre.t.pol, prec); + break; + case DFT_CYC: + acb_dirichlet_dft_cyc_precomp(w, v, pre.t.cyc, prec); + break; + case DFT_PROD: + acb_dirichlet_dft_prod_precomp(w, v, pre.t.prod, prec); + break; + case DFT_CRT: + acb_dirichlet_dft_crt_precomp(w, v, pre.t.crt, prec); + break; + default: + flint_printf("acb_dirichlet_dft_precomp: unknown strategy code %i\n", pre.type); + abort(); + break; + } +} diff --git a/acb_dirichlet/dft_prod.c b/acb_dirichlet/dft_prod.c new file mode 100644 index 00000000..ec6eafe7 --- /dev/null +++ b/acb_dirichlet/dft_prod.c @@ -0,0 +1,67 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +acb_dirichlet_dft_step_ptr +_acb_dirichlet_dft_steps_prod(slong * cyc, slong num, slong prec) +{ + slong i, len, dv; + acb_dirichlet_dft_step_ptr s; + s = flint_malloc(num * sizeof(acb_dirichlet_dft_step_struct)); + + len = 1; dv = 1; + for (i = 0; i < num; i++) + len *= cyc[i]; + + for (i = 0; i < num; i++) + { + slong m = cyc[i]; + len /= m; + s[i].m = m; + s[i].M = len; + s[i].dv = len; + s[i].dz = 0; + s[i].z = NULL; + _acb_dirichlet_dft_precomp_init(s[i].pre, m, NULL, 0, len, prec); + dv *= m; + } + + return s; +} + +void +acb_dirichlet_dft_prod_clear(acb_dirichlet_dft_prod_t t) +{ + slong i; + for (i = 0; i < t->num; i++) + acb_dirichlet_dft_precomp_clear(t->cyc[i].pre); + flint_free(t->cyc); +} + + +void +acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_prod_t prod, slong prec) +{ + if (prod->num == 0) + acb_set(w + 0, v + 0); + else + acb_dirichlet_dft_step(w, v, prod->cyc, prod->num, prec); +} + +void +acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) +{ + acb_dirichlet_dft_prod_t t; + acb_dirichlet_dft_prod_init(t, cyc, num, prec); + acb_dirichlet_dft_prod_precomp(w, v, t, prec); + acb_dirichlet_dft_prod_clear(t); +} diff --git a/acb_dirichlet/dft_step.c b/acb_dirichlet/dft_step.c new file mode 100644 index 00000000..775b2344 --- /dev/null +++ b/acb_dirichlet/dft_step.c @@ -0,0 +1,76 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +#define REORDER 0 + +void +acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, slong num, slong prec) +{ + acb_dirichlet_dft_step_struct c; + if (num == 0) + { + flint_printf("error: reached num = 0 in acb_dirichlet_dft_step\n"); + abort(); /* or just copy v to w */ + } + c = cyc[0]; + if (num == 1) + { + acb_dirichlet_dft_precomp(w, v, c.pre, prec); + /*_acb_dirichlet_dft_base(w, v, c.dv, c.z, c.dz, c.m, prec);*/ + } + else + { + slong i, j; + slong m = c.m, M = c.M, dv = c.dv, dz = c.dz; + acb_srcptr z = c.z; + acb_ptr t; +#if REORDER + acb_ptr w2; +#endif + + t = _acb_vec_init(m * M); + + /* m DFT of size M */ + for (i = 0; i < m; i++) + acb_dirichlet_dft_step(w + i * M, v + i * dv, cyc + 1, num - 1, prec); + + /* twiddle if non trivial product */ + if (c.z != NULL) + { + acb_ptr wi; + for (wi = w + M, i = 1; i < m; i++, wi += M) + for (j = 1; j < M; j++) + acb_mul(wi + j, wi + j, z + dz * i * j, prec); + } + +#if REORDER + /* reorder w to avoid shifting in next DFT */ + w2 = flint_malloc(m * M * sizeof(acb_struct)); + for (j = 0; j < M; j++) + for (i = 0; i < m; i++) + w2[j + M * i] = w[i + m * j]; +#endif + + + /* M DFT of size m */ + for (j = 0; j < M; j++) + acb_dirichlet_dft_precomp(t + m * j, w + j, c.pre, prec); + + /* reorder */ + for (i = 0; i < m; i++) + for (j = 0; j < M; j++) + acb_set(w + j + M * i, t + i + m * j); + + _acb_vec_clear(t, m * M); + } +} diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index a01e1364..a88dbaba 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -39,7 +39,7 @@ int main() acb_set_si(v + i, i); acb_dirichlet_dft_pol(w1, v, q[k], prec); - acb_dirichlet_dft_fast(w2, v, q[k], prec); + acb_dirichlet_dft_cyc(w2, v, q[k], prec); for (i = 0; i < q[k]; i++) { From 97fcc27e6afa50fc51560fe483bd61bf12f92d4a Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 29 Sep 2016 12:00:47 +0200 Subject: [PATCH 126/139] fix alloc/clear issues --- acb_dirichlet.h | 36 ++++++++++----------- acb_dirichlet/dft_crt.c | 17 ++++++++++ acb_dirichlet/dft_cyc.c | 55 +++++++++++-------------------- acb_dirichlet/dft_pol.c | 24 ++++++++++++++ acb_dirichlet/dft_precomp.c | 42 +++++++++++++----------- acb_dirichlet/dft_prod.c | 16 +++++----- acb_dirichlet/test/t-dft.c | 64 +++++++++++++++++++------------------ 7 files changed, 142 insertions(+), 112 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 8eaeb774..d03c59af 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -325,6 +325,7 @@ typedef acb_dirichlet_dft_step_struct * acb_dirichlet_dft_step_ptr; typedef struct { slong n; + int zclear; acb_ptr z; slong num; acb_dirichlet_dft_step_ptr cyc; @@ -358,6 +359,7 @@ typedef struct { slong n; slong dv; + int zclear; acb_ptr z; slong dz; } @@ -376,7 +378,9 @@ typedef struct acb_dirichlet_dft_pol_t pol; } t; } -acb_dirichlet_dft_pre_t; +acb_dirichlet_dft_pre_struct; + +typedef acb_dirichlet_dft_pre_struct acb_dirichlet_dft_pre_t[1]; /* covers both product and cyclic case */ struct @@ -387,7 +391,7 @@ acb_dirichlet_dft_step_struct /* card H */ slong M; slong dv; /* = M for prod, also = M if cyc is reordered */ - /* roots of unity, if needed */ + /* pointer on some roots of unity, if needed */ acb_srcptr z; /* index of mM in z */ slong dz; @@ -435,40 +439,34 @@ acb_dirichlet_dft_prod_init(acb_dirichlet_dft_prod_t t, slong * cyc, slong num, void acb_dirichlet_dft_prod_clear(acb_dirichlet_dft_prod_t t); -void _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, slong len, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong prec); -void _acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong len, slong dv, slong prec); +void _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec); +void _acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong dv, slong len, slong prec); ACB_DIRICHLET_INLINE void acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong len, slong prec) { - _acb_dirichlet_dft_cyc_init(t, len, 1, prec); + _acb_dirichlet_dft_cyc_init(t, 1, len, prec); } void acb_dirichlet_dft_cyc_clear(acb_dirichlet_dft_cyc_t t); -ACB_DIRICHLET_INLINE void -_acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec) -{ - pol->n = len; - pol->dv = dv; - pol->z = z; - pol->dz = dz; -} +void _acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec); ACB_DIRICHLET_INLINE void acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong len, slong prec) { - pol->n = len; - pol->dv = 1; - pol->z = _acb_vec_init(len); - acb_dirichlet_vec_nth_roots(pol->z, len, prec); - pol->dz = 1; + _acb_dirichlet_dft_pol_init(pol, 1, NULL, 0, len, prec); } ACB_DIRICHLET_INLINE void acb_dirichlet_dft_pol_clear(acb_dirichlet_dft_pol_t pol) { - _acb_vec_clear(pol->z, pol->n); + if (pol->zclear) + { + flint_printf(" ## clearing pol [len=%ld]....", pol->n); + _acb_vec_clear(pol->z, pol->n); + flint_printf("done\n"); + } } ACB_DIRICHLET_INLINE void diff --git a/acb_dirichlet/dft_crt.c b/acb_dirichlet/dft_crt.c index c554227f..e210056f 100644 --- a/acb_dirichlet/dft_crt.c +++ b/acb_dirichlet/dft_crt.c @@ -35,6 +35,21 @@ crt_init(crt_t c, ulong n) } } +void +crt_print(const crt_t c) +{ + slong k; + if (c->num == 0) + { + flint_printf("trivial group, absurd\n"); + abort(); + } + flint_printf("crt decomp "); + for (k = 0; k < c->num; k++) + flint_printf("Z/%wuZ ", c->m[k]); + flint_printf("\n"); +} + #if 0 /* lexicographic index of crt elt j */ static ulong @@ -136,6 +151,7 @@ acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) acb_ptr t; t = _acb_vec_init(len); crt_init(c, len); + crt_print(c); crt_decomp(w, v, c, len); acb_dirichlet_dft_prod(t, w, c->m, c->num, prec); crt_recomp(w, t, c, len); @@ -147,6 +163,7 @@ acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_c { acb_ptr t; t = _acb_vec_init(crt->n); + crt_print(crt->c); crt_decomp(w, v, crt->c, crt->n); acb_dirichlet_dft_step(t, w, crt->cyc, crt->c->num, prec); crt_recomp(w, t, crt->c, crt->n); diff --git a/acb_dirichlet/dft_cyc.c b/acb_dirichlet/dft_cyc.c index 472661fb..83ed005c 100644 --- a/acb_dirichlet/dft_cyc.c +++ b/acb_dirichlet/dft_cyc.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -_acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, slong len, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong prec) +_acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec) { slong i, j, num; t->n = len; @@ -22,13 +22,17 @@ _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, slong len, n_factor t->num = num; t->cyc = flint_malloc(num * sizeof(acb_dirichlet_dft_step_struct)); - /* FIXME: if z is allocated here, it must be cleared somewhere */ if (z == NULL) { + flint_printf("dft_cyc: compute roots of order %wu\n", t->n); z = _acb_vec_init(t->n); acb_dirichlet_vec_nth_roots(z, t->n, prec); dz = 1; + t->zclear = 1; } + else + t->zclear = 0; + t->z = z; num = 0; @@ -44,13 +48,17 @@ _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, slong len, n_factor t->cyc[num].dv = dv; t->cyc[num].z = z; t->cyc[num].dz = dz; - _acb_dirichlet_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec); + /* TODO: ugly, reorder should solve this */ + if (num == t->num - 1) + _acb_dirichlet_dft_precomp_init(t->cyc[num].pre, dv, z, dz, m, prec); + else + _acb_dirichlet_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec); dv *= m; dz *= m; num++; } } - } +} void _acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong dv, slong len, slong prec) @@ -58,7 +66,7 @@ _acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong dv, slong len, slon n_factor_t fac; n_factor_init(&fac); n_factor(&fac, len, 0); - _acb_dirichlet_dft_cyc_init_z_fac(t, len, fac, dv, NULL, 0, prec); + _acb_dirichlet_dft_cyc_init_z_fac(t, fac, dv, NULL, 0, len, prec); } void @@ -67,41 +75,16 @@ acb_dirichlet_dft_cyc_clear(acb_dirichlet_dft_cyc_t t) slong i; for (i = 0; i < t->num; i++) acb_dirichlet_dft_precomp_clear(t->cyc[i].pre); + if (t->zclear) + _acb_vec_clear(t->z, t->n); flint_free(t->cyc); - _acb_vec_clear(t->z, t->n); } - -#if 0 -/* shallow extract */ -static acb_ptr -vec_extract(acb_srcptr v, slong step, slong len) -{ - slong k, l; - acb_ptr res; - res = flint_malloc(len * sizeof(acb_struct)); - for (k = 0, l = 0; k < len; k++, l+=step) - res[k] = v[l]; - return res; -} - -void -_acb_dirichlet_dft_base(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong n, slong prec) -{ - acb_ptr v1, z1; - v1 = vec_extract(v, dv, n); - z1 = vec_extract(z, dz, n); - _acb_dirichlet_dft_pol(w, v1, z1, n, prec); - flint_free(v1); - flint_free(z1); -} -#endif - void acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) { - acb_dirichlet_dft_cyc_t t; - acb_dirichlet_dft_cyc_init(t, len, prec); - acb_dirichlet_dft_cyc_precomp(w, v, t, prec); - acb_dirichlet_dft_cyc_clear(t); + acb_dirichlet_dft_cyc_t cyc; + acb_dirichlet_dft_cyc_init(cyc, len, prec); + acb_dirichlet_dft_cyc_precomp(w, v, cyc, prec); + acb_dirichlet_dft_cyc_clear(cyc); } diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c index c395a736..2efefcfb 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dirichlet/dft_pol.c @@ -37,3 +37,27 @@ acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec) _acb_dirichlet_dft_pol(w, v, 1, z, 1, len, prec); _acb_vec_clear(z, len); } + +void +_acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec) +{ + pol->n = len; + pol->dv = dv; + + /* warning: if set here, must be cleared somewhere */ + if (z == NULL) + { + flint_printf("warning: init z in dft_pol, should be avoided\n"); + pol->z = _acb_vec_init(len); + acb_dirichlet_vec_nth_roots(pol->z, len, prec); + pol->dz = 1; + pol->zclear = 1; + } + else + { + pol->z = z; + pol->dz = dz; + pol->zclear = 0; + } + flint_printf("init dft_pol len = %ld, dz = %ld, dv = %ld\n", pol->n, pol->dz, pol->dv); +} diff --git a/acb_dirichlet/dft_precomp.c b/acb_dirichlet/dft_precomp.c index 5eef41f6..c1171e12 100644 --- a/acb_dirichlet/dft_precomp.c +++ b/acb_dirichlet/dft_precomp.c @@ -14,11 +14,16 @@ void _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec) { + if (len <= 1) + { + flint_printf("precomp init: trivial group. abort.\n"); + abort(); + } if (n_is_prime(len)) { /* TODO: need convolution if len is large */ - pre.type = DFT_POL; - _acb_dirichlet_dft_pol_init(pre.t.pol, dv, z, dz, len, prec); + pre->type = DFT_POL; + _acb_dirichlet_dft_pol_init(pre->t.pol, dv, z, dz, len, prec); } else { @@ -30,13 +35,13 @@ _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z if (fac.num == 1) { /* TODO: could be p^e, or 2^e */ - pre.type = DFT_CYC; - _acb_dirichlet_dft_cyc_init_z_fac(pre.t.cyc, len, fac, dv, z, dz, prec); + pre->type = DFT_CYC; + _acb_dirichlet_dft_cyc_init_z_fac(pre->t.cyc, fac, dv, z, dz, len, prec); } else { - pre.type = DFT_CRT; - acb_dirichlet_dft_crt_init(pre.t.crt, len, prec); + pre->type = DFT_CRT; + acb_dirichlet_dft_crt_init(pre->t.crt, len, prec); } } } @@ -44,27 +49,28 @@ _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z void acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong len, slong prec) { + _acb_dirichlet_dft_precomp_init(pre, 1, NULL, 0, len, prec); } void acb_dirichlet_dft_precomp_clear(acb_dirichlet_dft_pre_t pre) { - switch (pre.type) + switch (pre->type) { case DFT_POL: - acb_dirichlet_dft_pol_clear(pre.t.pol); + acb_dirichlet_dft_pol_clear(pre->t.pol); break; case DFT_CYC: - acb_dirichlet_dft_cyc_clear(pre.t.cyc); + acb_dirichlet_dft_cyc_clear(pre->t.cyc); break; case DFT_PROD: - acb_dirichlet_dft_prod_clear(pre.t.prod); + acb_dirichlet_dft_prod_clear(pre->t.prod); break; case DFT_CRT: - acb_dirichlet_dft_crt_clear(pre.t.crt); + acb_dirichlet_dft_crt_clear(pre->t.crt); break; default: - flint_printf("acb_dirichlet_dft_clear: unknown strategy code %i\n", pre.type); + flint_printf("acb_dirichlet_dft_clear: unknown strategy code %i\n", pre->type); abort(); break; } @@ -73,22 +79,22 @@ acb_dirichlet_dft_precomp_clear(acb_dirichlet_dft_pre_t pre) void acb_dirichlet_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_pre_t pre, slong prec) { - switch (pre.type) + switch (pre->type) { case DFT_POL: - acb_dirichlet_dft_pol_precomp(w, v, pre.t.pol, prec); + acb_dirichlet_dft_pol_precomp(w, v, pre->t.pol, prec); break; case DFT_CYC: - acb_dirichlet_dft_cyc_precomp(w, v, pre.t.cyc, prec); + acb_dirichlet_dft_cyc_precomp(w, v, pre->t.cyc, prec); break; case DFT_PROD: - acb_dirichlet_dft_prod_precomp(w, v, pre.t.prod, prec); + acb_dirichlet_dft_prod_precomp(w, v, pre->t.prod, prec); break; case DFT_CRT: - acb_dirichlet_dft_crt_precomp(w, v, pre.t.crt, prec); + acb_dirichlet_dft_crt_precomp(w, v, pre->t.crt, prec); break; default: - flint_printf("acb_dirichlet_dft_precomp: unknown strategy code %i\n", pre.type); + flint_printf("acb_dirichlet_dft_precomp: unknown strategy code %i\n", pre->type); abort(); break; } diff --git a/acb_dirichlet/dft_prod.c b/acb_dirichlet/dft_prod.c index ec6eafe7..ad964d46 100644 --- a/acb_dirichlet/dft_prod.c +++ b/acb_dirichlet/dft_prod.c @@ -14,25 +14,25 @@ acb_dirichlet_dft_step_ptr _acb_dirichlet_dft_steps_prod(slong * cyc, slong num, slong prec) { - slong i, len, dv; + slong i, len; acb_dirichlet_dft_step_ptr s; s = flint_malloc(num * sizeof(acb_dirichlet_dft_step_struct)); - len = 1; dv = 1; + len = 1; for (i = 0; i < num; i++) len *= cyc[i]; for (i = 0; i < num; i++) { - slong m = cyc[i]; - len /= m; + slong m, M; + m = cyc[i]; + M = (len /= m); s[i].m = m; - s[i].M = len; - s[i].dv = len; + s[i].M = M; + s[i].dv = M; s[i].dz = 0; s[i].z = NULL; - _acb_dirichlet_dft_precomp_init(s[i].pre, m, NULL, 0, len, prec); - dv *= m; + _acb_dirichlet_dft_precomp_init(s[i].pre, M, NULL, 0, m, prec); } return s; diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index a88dbaba..282e56e4 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -11,15 +11,22 @@ #include "acb_dirichlet.h" +typedef void (*do_f) (acb_ptr w, acb_srcptr v, slong len, slong prec); + int main() { slong k; slong prec = 100, digits = 30; slong nq = 13; - ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; + /*ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961};*/ + ulong q[13] = { 20, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; flint_rand_t state; + slong f, nf = 3; + do_f func[3] = { acb_dirichlet_dft_pol, acb_dirichlet_dft_cyc, acb_dirichlet_dft_crt }; + char * name[3] = { "pol", "cyc", "crt" }; + flint_printf("dft...."); fflush(stdout); @@ -38,37 +45,32 @@ int main() for (i = 0; i < q[k]; i++) acb_set_si(v + i, i); - acb_dirichlet_dft_pol(w1, v, q[k], prec); - acb_dirichlet_dft_cyc(w2, v, q[k], prec); + for (f = 0; f < nf; f++) + { - for (i = 0; i < q[k]; i++) - { - if (!acb_overlaps(w1 + i, w2 + i)) + acb_ptr w = (f == 0) ? w1 : w2; + + flint_printf("\ndo dft %s on Z/%wuZ\n", name[f], q[k]); + func[f](w, v, q[k], prec); + + if (f == 0) + continue; + + for (i = 0; i < q[k]; i++) { - flint_printf("differ from index %ld / %ld \n\n",i,q[k]); - flint_printf("pol =\n"); - acb_vec_printd(w1, q[k], digits); - flint_printf("fast =\n"); - acb_vec_printd(w2, q[k], digits); - flint_printf("\n\n"); - abort(); + if (!acb_overlaps(w1 + i, w2 + i)) + { + flint_printf("differ from index %ld / %ld \n\n",i,q[k]); + flint_printf("%s =\n", name[0]); + acb_vec_printd(w1, q[k], digits); + flint_printf("%s =\n", name[f]); + acb_vec_printd(w2, q[k], digits); + flint_printf("\n\n"); + abort(); + } } } - acb_dirichlet_dft_crt(w2, v, q[k], prec); - for (i = 0; i < q[k]; i++) - { - if (!acb_overlaps(w1 + i, w2 + i)) - { - flint_printf("differ from index %ld / %ld \n\n",i,q[k]); - flint_printf("pol =\n"); - acb_vec_printd(w1, q[k], digits); - flint_printf("crt =\n"); - acb_vec_printd(w2, q[k], digits); - flint_printf("\n\n"); - abort(); - } - } - + _acb_vec_clear(v, q[k]); _acb_vec_clear(w1, q[k]); _acb_vec_clear(w2, q[k]); @@ -125,12 +127,12 @@ int main() flint_printf("FAIL\n\n"); flint_printf("q = %wu\n", q[k]); flint_printf("v [size %wu]\n", len); - acb_vec_printd(v, len, digits); + acb_vec_printd_index(v, len, digits); flint_printf("\nDFT differ from index %ld / %ld \n", i, len); flint_printf("\nnaive =\n"); - acb_vec_printd(w1, len, digits); + acb_vec_printd_index(w1, len, digits); flint_printf("\nfast =\n"); - acb_vec_printd(w2, len, digits); + acb_vec_printd_index(w2, len, digits); flint_printf("\n\n"); abort(); } From a7a4d316a9a30a1c2a765eb34e5a211793e144d0 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 30 Sep 2016 21:22:06 +0200 Subject: [PATCH 127/139] fix dv in dft_crt --- acb_dirichlet.h | 12 +++++++----- acb_dirichlet/dft_crt.c | 39 +++++++++++++++++++++---------------- acb_dirichlet/dft_cyc.c | 5 ++++- acb_dirichlet/dft_pol.c | 5 ++--- acb_dirichlet/dft_precomp.c | 2 +- acb_dirichlet/dft_step.c | 3 +-- acb_dirichlet/test/t-dft.c | 4 +--- 7 files changed, 38 insertions(+), 32 deletions(-) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index d03c59af..28704fab 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -316,7 +316,7 @@ typedef crt_struct crt_t[1]; void crt_init(crt_t c, ulong n); -void crt_decomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); +void crt_decomp(acb_ptr y, acb_srcptr x, slong dx, const crt_t c, ulong len); void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); typedef struct acb_dirichlet_dft_step_struct acb_dirichlet_dft_step_struct; @@ -348,6 +348,7 @@ typedef struct { slong n; crt_t c; + slong dv; /* then a product */ acb_dirichlet_dft_step_ptr cyc; } @@ -402,6 +403,8 @@ acb_dirichlet_dft_step_struct /*typedef acb_dirichlet_dft_pre_struct acb_dirichlet_dft_pre_t[1];*/ +#define DFT_VERB 0 + enum { DFT_POL, DFT_CYC, DFT_PROD, DFT_CRT /*, DFT_2E, DFT_CONV */ @@ -462,18 +465,17 @@ ACB_DIRICHLET_INLINE void acb_dirichlet_dft_pol_clear(acb_dirichlet_dft_pol_t pol) { if (pol->zclear) - { - flint_printf(" ## clearing pol [len=%ld]....", pol->n); _acb_vec_clear(pol->z, pol->n); - flint_printf("done\n"); - } } +void _acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong dv, slong len, slong prec); + ACB_DIRICHLET_INLINE void acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong len, slong prec) { crt->n = len; crt_init(crt->c, len); + crt->dv = 1; crt->cyc = _acb_dirichlet_dft_steps_prod(crt->c->m, crt->c->num, prec); } diff --git a/acb_dirichlet/dft_crt.c b/acb_dirichlet/dft_crt.c index e210056f..0f8eaea5 100644 --- a/acb_dirichlet/dft_crt.c +++ b/acb_dirichlet/dft_crt.c @@ -41,10 +41,9 @@ crt_print(const crt_t c) slong k; if (c->num == 0) { - flint_printf("trivial group, absurd\n"); + flint_printf("trivial group\n"); abort(); } - flint_printf("crt decomp "); for (k = 0; k < c->num; k++) flint_printf("Z/%wuZ ", c->m[k]); flint_printf("\n"); @@ -100,7 +99,7 @@ reorder_from_crt(acb_srcptr v, crt_t c, ulong len) #endif void -crt_decomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) +crt_decomp(acb_ptr y, acb_srcptr x, slong dv, const crt_t c, ulong len) { int j, e[CRT_MAX]; ulong k, l; @@ -111,8 +110,7 @@ crt_decomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) l = 0; for(k = 0; k < len; k++) { - /*flint_printf("set y[%wu] = x[%wu]\n", k, l);*/ - acb_set(y + k, x + l); + acb_set(y + k, x + l * dv); for (j = c->num - 1; j >= 0; e[j] = 0, j--) { e[j]++; l = nmod_add(l, c->vM[j], c->n); @@ -145,17 +143,12 @@ crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) } void -acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) +_acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong dv, slong len, slong prec) { - crt_t c; - acb_ptr t; - t = _acb_vec_init(len); - crt_init(c, len); - crt_print(c); - crt_decomp(w, v, c, len); - acb_dirichlet_dft_prod(t, w, c->m, c->num, prec); - crt_recomp(w, t, c, len); - _acb_vec_clear(t, len); + crt->n = len; + crt_init(crt->c, len); + crt->dv = dv; + crt->cyc = _acb_dirichlet_dft_steps_prod(crt->c->m, crt->c->num, prec); } void @@ -163,9 +156,21 @@ acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_c { acb_ptr t; t = _acb_vec_init(crt->n); - crt_print(crt->c); - crt_decomp(w, v, crt->c, crt->n); + crt_decomp(w, v, crt->dv, crt->c, crt->n); acb_dirichlet_dft_step(t, w, crt->cyc, crt->c->num, prec); crt_recomp(w, t, crt->c, crt->n); _acb_vec_clear(t, crt->n); } + +void +acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) +{ + crt_t c; + acb_ptr t; + t = _acb_vec_init(len); + crt_init(c, len); + crt_decomp(w, v, 1, c, len); + acb_dirichlet_dft_prod(t, w, c->m, c->num, prec); + crt_recomp(w, t, c, len); + _acb_vec_clear(t, len); +} diff --git a/acb_dirichlet/dft_cyc.c b/acb_dirichlet/dft_cyc.c index 83ed005c..65601651 100644 --- a/acb_dirichlet/dft_cyc.c +++ b/acb_dirichlet/dft_cyc.c @@ -24,14 +24,17 @@ _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slo if (z == NULL) { - flint_printf("dft_cyc: compute roots of order %wu\n", t->n); z = _acb_vec_init(t->n); acb_dirichlet_vec_nth_roots(z, t->n, prec); dz = 1; t->zclear = 1; } else + { + if (DFT_VERB) + flint_printf("dft_cyc: roots of order %wu already computed\n", t->n); t->zclear = 0; + } t->z = z; diff --git a/acb_dirichlet/dft_pol.c b/acb_dirichlet/dft_pol.c index 2efefcfb..eebf657c 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dirichlet/dft_pol.c @@ -44,10 +44,10 @@ _acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, sl pol->n = len; pol->dv = dv; - /* warning: if set here, must be cleared somewhere */ if (z == NULL) { - flint_printf("warning: init z in dft_pol, should be avoided\n"); + if (DFT_VERB) + flint_printf("warning: init z[%ld] in dft_pol, should be avoided\n",len); pol->z = _acb_vec_init(len); acb_dirichlet_vec_nth_roots(pol->z, len, prec); pol->dz = 1; @@ -59,5 +59,4 @@ _acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, sl pol->dz = dz; pol->zclear = 0; } - flint_printf("init dft_pol len = %ld, dz = %ld, dv = %ld\n", pol->n, pol->dz, pol->dv); } diff --git a/acb_dirichlet/dft_precomp.c b/acb_dirichlet/dft_precomp.c index c1171e12..70e46e34 100644 --- a/acb_dirichlet/dft_precomp.c +++ b/acb_dirichlet/dft_precomp.c @@ -41,7 +41,7 @@ _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z else { pre->type = DFT_CRT; - acb_dirichlet_dft_crt_init(pre->t.crt, len, prec); + _acb_dirichlet_dft_crt_init(pre->t.crt, dv, len, prec); } } } diff --git a/acb_dirichlet/dft_step.c b/acb_dirichlet/dft_step.c index 775b2344..290f9115 100644 --- a/acb_dirichlet/dft_step.c +++ b/acb_dirichlet/dft_step.c @@ -54,13 +54,12 @@ acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, } #if REORDER - /* reorder w to avoid shifting in next DFT */ + /* reorder w to avoid dv shifts in next DFT */ w2 = flint_malloc(m * M * sizeof(acb_struct)); for (j = 0; j < M; j++) for (i = 0; i < m; i++) w2[j + M * i] = w[i + m * j]; #endif - /* M DFT of size m */ for (j = 0; j < M; j++) diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 282e56e4..b258ab5c 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -19,8 +19,7 @@ int main() slong k; slong prec = 100, digits = 30; slong nq = 13; - /*ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961};*/ - ulong q[13] = { 20, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; + ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; flint_rand_t state; slong f, nf = 3; @@ -50,7 +49,6 @@ int main() acb_ptr w = (f == 0) ? w1 : w2; - flint_printf("\ndo dft %s on Z/%wuZ\n", name[f], q[k]); func[f](w, v, q[k], prec); if (f == 0) From f25b43d0f16bbedd76e830750e1459b01a0640f7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 4 Oct 2016 18:19:51 +0200 Subject: [PATCH 128/139] dft rad2 special case --- acb_dirichlet.h | 60 ++++++++++++++++++++- acb_dirichlet/dft_rad2.c | 78 +++++++++++++++++++++++++++ acb_dirichlet/test/t-dft.c | 102 +++++++++++++++++++---------------- acb_dirichlet/vec_nth_root.c | 6 +-- 4 files changed, 195 insertions(+), 51 deletions(-) create mode 100644 acb_dirichlet/dft_rad2.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 28704fab..a28d3756 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -251,6 +251,7 @@ void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t); void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec); void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec); +void _acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec); void acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec); void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); @@ -296,6 +297,7 @@ void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slo void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dirichlet_dft_rad2(acb_ptr v, int e, slong prec); void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); @@ -334,6 +336,17 @@ acb_dirichlet_dft_cyc_struct; typedef acb_dirichlet_dft_cyc_struct acb_dirichlet_dft_cyc_t[1]; +typedef struct +{ + int e; + slong n; /* = 1 << e */ + slong nz; /* = n but could be bigger */ + acb_ptr z; +} +acb_dirichlet_dft_rad2_struct; + +typedef acb_dirichlet_dft_rad2_struct acb_dirichlet_dft_rad2_t[1]; + typedef struct { slong n; @@ -373,6 +386,7 @@ typedef struct int type; union { + acb_dirichlet_dft_rad2_t rad2; acb_dirichlet_dft_cyc_t cyc; acb_dirichlet_dft_prod_t prod; acb_dirichlet_dft_crt_t crt; @@ -407,7 +421,7 @@ acb_dirichlet_dft_step_struct enum { - DFT_POL, DFT_CYC, DFT_PROD, DFT_CRT /*, DFT_2E, DFT_CONV */ + DFT_POL, DFT_CYC, DFT_PROD, DFT_CRT , DFT_RAD2 /*, DFT_CONV */ }; void acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, slong num, slong prec); @@ -424,9 +438,12 @@ acb_dirichlet_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_c { acb_dirichlet_dft_step(w, v, cyc->cyc, cyc->num, prec); } +void acb_dirichlet_dft_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec); void acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_crt_t crt, slong prec); void acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_prod_t prod, slong prec); +void acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec); + void _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec); void acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong len, slong prec); void acb_dirichlet_dft_precomp_clear(acb_dirichlet_dft_pre_t pre); @@ -468,6 +485,23 @@ acb_dirichlet_dft_pol_clear(acb_dirichlet_dft_pol_t pol) _acb_vec_clear(pol->z, pol->n); } +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_rad2_init(acb_dirichlet_dft_rad2_t t, int e, slong prec) +{ + t->e = e; + t->n = 1 << e; + t->nz = t->n >> 1; + t->z = _acb_vec_init(t->nz); + /* set n/2 roots of order n */ + _acb_vec_nth_roots_pe(t->z, 2, e, t->nz, 1, prec); +} + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_rad2_clear(acb_dirichlet_dft_rad2_t t) +{ + _acb_vec_clear(t->z, t->nz); +} + void _acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong dv, slong len, slong prec); ACB_DIRICHLET_INLINE void @@ -485,7 +519,29 @@ acb_dirichlet_dft_crt_clear(acb_dirichlet_dft_crt_t crt) flint_free(crt->cyc); } -/* utils */ +/* utils, could be moved elsewhere */ + +ACB_DIRICHLET_INLINE void +acb_swap_ri(acb_t x) +{ + arb_swap(acb_realref(x), acb_imagref(x)); +} + +ACB_DIRICHLET_INLINE void +acb_vec_swap_ri(acb_ptr v, slong len) +{ + slong k; + for (k = 0; k < len; k++) + acb_swap_ri(v + k); +} + +ACB_DIRICHLET_INLINE void +_acb_vec_kronecker_mul(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) +{ + slong k; + for (k = 0; k < len; k++) + acb_mul(z + k, x + k, y + k, prec); +} ACB_DIRICHLET_INLINE void acb_vec_printd(acb_srcptr vec, slong len, slong digits) diff --git a/acb_dirichlet/dft_rad2.c b/acb_dirichlet/dft_rad2.c new file mode 100644 index 00000000..bfd99ff1 --- /dev/null +++ b/acb_dirichlet/dft_rad2.c @@ -0,0 +1,78 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +/* swap each element with one with bit-reversed index */ +void +acb_dirichlet_dft_rad2_reorder(acb_ptr v, slong n) +{ + slong i, j, k, l; + + for (i = 0, l = n>>1; i < l; i++) + { + /* j = bit reversal of i */ + for (k = 1, j = 0; k < n; k <<= 1) + { + j <<= 1; + if (i & k) + j |= 1; + } + if (i < j) + acb_swap(v + i, v + j); + else if (i > j) + acb_swap(v + n - 1 - i, v + n - 1 - j); + i++, j |= l; + acb_swap(v + i, v + j); + } + +} + +/* remark: can use same rad2 with smaller power of 2 */ +void +acb_dirichlet_dft_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec) +{ + slong j, k, l; + slong n = rad2->n, nz = rad2->nz; + acb_ptr p, vend = v + n, w = rad2->z; + acb_t tmp; + acb_init(tmp); + + for (k = 1, l = nz; k < n; k <<= 1, l >>= 1) + for (p = v; p < vend; p += k) + for (j = 0; j < nz; j += l, p++) + { + acb_mul(tmp, p + k, w + j, prec); + acb_sub(p + k, p + 0, tmp, prec); + acb_add(p + 0, p + 0, tmp, prec); + } + + acb_clear(tmp); +} + +void +acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec) +{ + slong k, n = rad2->n; + acb_dirichlet_dft_rad2_precomp(v, rad2, prec); + _acb_vec_scalar_mul_2exp_si(v, v, n, - rad2->e); + for (k = 1; k < n / 2; k++) + acb_swap(v + k, v + n - k); +} + +void +acb_dirichlet_dft_rad2(acb_ptr v, int e, slong prec) +{ + acb_dirichlet_dft_rad2_t rad2; + acb_dirichlet_dft_rad2_init(rad2, e, prec); + acb_dirichlet_dft_rad2_precomp(v, rad2, prec); + acb_dirichlet_dft_rad2_clear(rad2); +} diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index b258ab5c..02fa7bb6 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -13,6 +13,44 @@ typedef void (*do_f) (acb_ptr w, acb_srcptr v, slong len, slong prec); +void +check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char f1[], char f2[]) +{ + slong i; + + for (i = 0; i < len; i++) + { + if (!acb_overlaps(w1 + i, w2 + i)) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu, size = %wu\n", q, len); + flint_printf("\nDFT differ from index %ld / %ld \n", i, len); + flint_printf("\n%s =\n", f1); + acb_vec_printd_index(w1, len, digits); + flint_printf("\n%s =\n", f2); + acb_vec_printd_index(w2, len, digits); + flint_printf("\n\n"); + abort(); + } + else if (acb_rel_accuracy_bits(w1 + i) < 30 + || acb_rel_accuracy_bits(w2 + i) < 30) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu\n", q); + flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); + flint_printf("\nnaive =\n"); + acb_printd(w1 + i, digits); + flint_printf("\nfast =\n"); + acb_printd(w2 + i, digits); + flint_printf("\nerrors %ld & %ld [prec = %wu]\n", + acb_rel_accuracy_bits(w1 + i), + acb_rel_accuracy_bits(w2 + i), prec); + abort(); + } + } +} + + int main() { @@ -54,19 +92,8 @@ int main() if (f == 0) continue; - for (i = 0; i < q[k]; i++) - { - if (!acb_overlaps(w1 + i, w2 + i)) - { - flint_printf("differ from index %ld / %ld \n\n",i,q[k]); - flint_printf("%s =\n", name[0]); - acb_vec_printd(w1, q[k], digits); - flint_printf("%s =\n", name[f]); - acb_vec_printd(w2, q[k], digits); - flint_printf("\n\n"); - abort(); - } - } + check_vec_eq_prec(w1, w2, q[k], prec, digits, q[k], name[0], name[f]); + } _acb_vec_clear(v, q[k]); @@ -74,6 +101,21 @@ int main() _acb_vec_clear(w2, q[k]); } + /* radix2 dft */ + for (k = 1; k < 12; k++) + { + slong n = 1 << k; + acb_ptr v, w1, w2; + v = w2 = _acb_vec_init(n); + w1 = _acb_vec_init(n); + + acb_dirichlet_dft_pol(w1, v, n, prec); + acb_dirichlet_dft_rad2(v, k, prec); + + check_vec_eq_prec(w1, w2, n, prec, digits, n, "pol", "rad2"); + + } + /* Dirichlet group DFT */ for (k = 0; k < nq; k++) { @@ -118,39 +160,7 @@ int main() /* dft */ acb_dirichlet_dft_conrey(w2, v, G, prec); - for (i = 0; i < len; i++) - { - if (!acb_overlaps(w1 + i, w2 + i)) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu\n", q[k]); - flint_printf("v [size %wu]\n", len); - acb_vec_printd_index(v, len, digits); - flint_printf("\nDFT differ from index %ld / %ld \n", i, len); - flint_printf("\nnaive =\n"); - acb_vec_printd_index(w1, len, digits); - flint_printf("\nfast =\n"); - acb_vec_printd_index(w2, len, digits); - flint_printf("\n\n"); - abort(); - } - else if (acb_rel_accuracy_bits(w1 + i) < 30 - || acb_rel_accuracy_bits(w2 + i) < 30) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu\n", q[k]); - flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); - flint_printf("\nnaive =\n"); - acb_printd(w1 + i, digits); - flint_printf("\nfast =\n"); - acb_printd(w2 + i, digits); - flint_printf("\nerrors %ld & %ld [prec = %wu]\n", - acb_rel_accuracy_bits(w1 + i), - acb_rel_accuracy_bits(w2 + i), prec - ); - abort(); - } - } + check_vec_eq_prec(w1, w2, len, prec, digits, q[k], "naive", "group"); _acb_vec_clear(v, len); _acb_vec_clear(w1, len); diff --git a/acb_dirichlet/vec_nth_root.c b/acb_dirichlet/vec_nth_root.c index 820f6826..a7249fd5 100644 --- a/acb_dirichlet/vec_nth_root.c +++ b/acb_dirichlet/vec_nth_root.c @@ -33,7 +33,7 @@ _acb_vec_set_powers_step(acb_ptr xs, slong n, slong len, slong step, slong prec) /* assume len = p^e and z has size >= len * step */ void -_acb_vec_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec) +_acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec) { if (e <= 1) { @@ -42,7 +42,7 @@ _acb_vec_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec else { slong q, r; - _acb_vec_roots_pe(z, p, e - 1, len / p, step * p, prec); + _acb_vec_nth_roots_pe(z, p, e - 1, len / p, step * p, prec); _acb_vec_set_powers_step(z, n_pow(p, e), p, step, prec); for (q = p; q < len; q += p) @@ -72,7 +72,7 @@ acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec) mp = len / pe; mq = len / q; - _acb_vec_roots_pe(z, p, e, pe, mp, prec); + _acb_vec_nth_roots_pe(z, p, e, pe, mp, prec); if (i > 0) { From ae23aecd8fca46519328cfac4734b2f703ff717f Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 4 Oct 2016 18:20:28 +0200 Subject: [PATCH 129/139] start convol (for bluestein dft) --- acb_dirichlet/dft_convol_fft.c | 58 ++++++++++++++++++++++++++++++++ acb_dirichlet/dft_convol_naive.c | 31 +++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 acb_dirichlet/dft_convol_fft.c create mode 100644 acb_dirichlet/dft_convol_naive.c diff --git a/acb_dirichlet/dft_convol_fft.c b/acb_dirichlet/dft_convol_fft.c new file mode 100644 index 00000000..23a3b72d --- /dev/null +++ b/acb_dirichlet/dft_convol_fft.c @@ -0,0 +1,58 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +/* assume np >= 2 * n - 1 */ +void +acb_dirichlet_dft_convol_pad(acb_ptr fp, acb_ptr gp, acb_srcptr f, acb_srcptr g, slong n, slong np) +{ + slong k; + for (k = 0; k < n; k++) + acb_set(gp + k, g + k); + for (k = 0; k < n; k++) + acb_set(fp + k, f + k); + for (k = 1; k < n; k++) + acb_set(fp + np - k, f + n - k); + for (k = n; k <= np - n; k++) + acb_zero(fp + k); +} + +void +acb_dirichlet_dft_inverse_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) +{ + /* divide before to keep v const */ + _acb_vec_scalar_div_ui(w, v, len, len, prec); + acb_vec_swap_ri(w, len); + acb_dirichlet_dft_cyc(w, w, len, prec); + acb_vec_swap_ri(w, len); +} + +void +acb_dirichlet_dft_convol_fft(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) +{ + int e; + slong k, np; + acb_ptr fp, gp; + acb_dirichlet_dft_rad2_t dft; + e = n_clog(2 * len + 1, 2); + acb_dirichlet_dft_rad2_init(dft, e, prec); + np = dft->n; + fp = _acb_vec_init(np); + gp = _acb_vec_init(np); + acb_dirichlet_dft_convol_pad(fp, gp, f, g, len, np); + acb_dirichlet_dft_rad2_precomp(fp, dft, prec); + acb_dirichlet_dft_rad2_precomp(gp, dft, prec); + _acb_vec_kronecker_mul(gp, gp, fp, np, prec); + acb_dirichlet_dft_inverse_rad2_precomp(gp, dft, prec); + for (k = 0; k < len; k++) + acb_set(w + k, gp + k); +} diff --git a/acb_dirichlet/dft_convol_naive.c b/acb_dirichlet/dft_convol_naive.c new file mode 100644 index 00000000..be7f2c8e --- /dev/null +++ b/acb_dirichlet/dft_convol_naive.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) +{ + slong x, y; + for (x = 0; x < len; x ++) + { + acb_ptr wx; + acb_srcptr fx, gy; + wx = w + x; + fx = f + x; + gy = g; + acb_zero(wx); + for (y = 0; y <= x; y++) + acb_addmul(wx, fx--, gy++, prec); + for (; y < len; y++) + acb_addmul(wx, f + x - y, g + y, prec); + } +} From 0f3eea07c23650c299d9cbdfd216bc04b01c684d Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 6 Oct 2016 08:52:22 +0200 Subject: [PATCH 130/139] bluestein dft, WIP --- acb_dirichlet.h | 40 ++++++++++- acb_dirichlet/dft_bluestein.c | 67 ++++++++++++++++++ acb_dirichlet/dft_convol_fft.c | 71 +++++++++++++++---- acb_dirichlet/dft_convol_naive.c | 4 +- acb_dirichlet/dft_rad2.c | 6 +- acb_dirichlet/test/t-convol.c | 118 +++++++++++++++++++++++++++++++ acb_dirichlet/test/t-dft.c | 11 +-- 7 files changed, 295 insertions(+), 22 deletions(-) create mode 100644 acb_dirichlet/dft_bluestein.c create mode 100644 acb_dirichlet/test/t-convol.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index a28d3756..4ce3ab8d 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -298,8 +298,12 @@ void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_rad2(acb_ptr v, int e, slong prec); +void acb_dirichlet_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec); void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); +void acb_dirichlet_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); +void acb_dirichlet_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); + void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); @@ -347,6 +351,16 @@ acb_dirichlet_dft_rad2_struct; typedef acb_dirichlet_dft_rad2_struct acb_dirichlet_dft_rad2_t[1]; +typedef struct +{ + slong n; + acb_ptr z; + acb_dirichlet_dft_rad2_t rad2; +} +acb_dirichlet_dft_bluestein_struct; + +typedef acb_dirichlet_dft_bluestein_struct acb_dirichlet_dft_bluestein_t[1]; + typedef struct { slong n; @@ -438,11 +452,12 @@ acb_dirichlet_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_c { acb_dirichlet_dft_step(w, v, cyc->cyc, cyc->num, prec); } -void acb_dirichlet_dft_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec); +void acb_dirichlet_dft_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec); void acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_crt_t crt, slong prec); void acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_prod_t prod, slong prec); -void acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec); +void acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec); +void acb_dirichlet_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dirichlet_dft_rad2_t, slong prec); void _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec); void acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong len, slong prec); @@ -502,6 +517,15 @@ acb_dirichlet_dft_rad2_clear(acb_dirichlet_dft_rad2_t t) _acb_vec_clear(t->z, t->nz); } +void acb_dirichlet_dft_bluestein_init(acb_dirichlet_dft_bluestein_t t, slong n, slong prec); + +ACB_DIRICHLET_INLINE void +acb_dirichlet_dft_bluestein_clear(acb_dirichlet_dft_bluestein_t t) +{ + _acb_vec_clear(t->z, t->n); + acb_dirichlet_dft_rad2_clear(t->rad2); +} + void _acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong dv, slong len, slong prec); ACB_DIRICHLET_INLINE void @@ -543,6 +567,18 @@ _acb_vec_kronecker_mul(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong p acb_mul(z + k, x + k, y + k, prec); } +/* z[k] = conj(x[k])*y[k] */ +ACB_DIRICHLET_INLINE void +acb_vec_kronecker_mul_conj(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) +{ + slong k; + for (k = 0; k < len; k++) + { + acb_conj(z + k, x + k); + acb_mul(z + k, z + k, y + k, prec); + } +} + ACB_DIRICHLET_INLINE void acb_vec_printd(acb_srcptr vec, slong len, slong digits) { diff --git a/acb_dirichlet/dft_bluestein.c b/acb_dirichlet/dft_bluestein.c new file mode 100644 index 00000000..a73294ec --- /dev/null +++ b/acb_dirichlet/dft_bluestein.c @@ -0,0 +1,67 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +void +acb_dirichlet_dft_bluestein_init(acb_dirichlet_dft_bluestein_t t, slong n, slong prec) +{ + + nmod_t n2; + slong k, k2; + acb_ptr z2n; + int e = n_clog(2 * n - 1, 2); + acb_dirichlet_dft_rad2_init(t->rad2, e, prec); + z2n = _acb_vec_init(2 * n); + acb_dirichlet_vec_nth_roots(z2n, 2 * n, prec); + nmod_init(&n2, 2 * n); + t->n = n; + t->z = _acb_vec_init(n); + for (k = 0, k2 = 0; k < n; k++) + { + acb_conj(t->z + k, z2n + k2); + k2 = nmod_add(k2, 2 * k + 1, n2); + } + _acb_vec_clear(z2n, 2 * n); +} + +void +acb_dirichlet_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_bluestein_t t, slong prec) +{ + slong n = t->n; + acb_ptr vz, wz, z; + z = t->z; + /* TODO: allocate directly length 2^e and pad */ + flint_printf("\n\n====================\n\nv\n"); + acb_vec_printd_index(v, n, 10); + vz = _acb_vec_init(n); + acb_vec_kronecker_mul_conj(vz, z, v, n, prec); + flint_printf("\nvz\n"); + acb_vec_printd_index(vz, n, 10); + wz = _acb_vec_init(n); + acb_dirichlet_dft_convol_rad2_precomp(wz, vz, z, n, t->rad2, prec); + flint_printf("\nwz\n"); + acb_vec_printd_index(wz, n, 10); + acb_vec_kronecker_mul_conj(w, z, wz, n, prec); + flint_printf("\nw\n"); + acb_vec_printd_index(w, n, 10); + _acb_vec_clear(wz, n); + _acb_vec_clear(vz, n); +} + +void +acb_dirichlet_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec) +{ + acb_dirichlet_dft_bluestein_t t; + acb_dirichlet_dft_bluestein_init(t, len, prec); + acb_dirichlet_dft_bluestein_precomp(w, v, t, prec); + acb_dirichlet_dft_bluestein_clear(t); +} diff --git a/acb_dirichlet/dft_convol_fft.c b/acb_dirichlet/dft_convol_fft.c index 23a3b72d..07a836bc 100644 --- a/acb_dirichlet/dft_convol_fft.c +++ b/acb_dirichlet/dft_convol_fft.c @@ -16,14 +16,25 @@ void acb_dirichlet_dft_convol_pad(acb_ptr fp, acb_ptr gp, acb_srcptr f, acb_srcptr g, slong n, slong np) { slong k; + + if (np < 2 * n - 1) + { + flint_printf("dft_convol_pad: overlapping padding %ld < 2*%ld-1\n", np, n); + abort(); + } + for (k = 0; k < n; k++) acb_set(gp + k, g + k); + for (; k < np; k++) + acb_zero(gp + k); + for (k = 0; k < n; k++) acb_set(fp + k, f + k); for (k = 1; k < n; k++) acb_set(fp + np - k, f + n - k); for (k = n; k <= np - n; k++) acb_zero(fp + k); + } void @@ -37,22 +48,58 @@ acb_dirichlet_dft_inverse_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) } void -acb_dirichlet_dft_convol_fft(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) +acb_dirichlet_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dirichlet_dft_rad2_t rad2, slong prec) { - int e; - slong k, np; + slong np; acb_ptr fp, gp; - acb_dirichlet_dft_rad2_t dft; - e = n_clog(2 * len + 1, 2); - acb_dirichlet_dft_rad2_init(dft, e, prec); - np = dft->n; + np = rad2->n; + + flint_printf("\nf\n"); + acb_vec_printd_index(f, len, 10); + flint_printf("\ng\n"); + acb_vec_printd_index(g, len, 10); + fp = _acb_vec_init(np); gp = _acb_vec_init(np); acb_dirichlet_dft_convol_pad(fp, gp, f, g, len, np); - acb_dirichlet_dft_rad2_precomp(fp, dft, prec); - acb_dirichlet_dft_rad2_precomp(gp, dft, prec); + + flint_printf("\nF\n"); + acb_vec_printd_index(fp, np, 10); + flint_printf("\nG\n"); + acb_vec_printd_index(gp, np, 10); + + acb_dirichlet_dft_rad2_precomp(fp, rad2, prec); + + flint_printf("\nDFT F\n"); + acb_vec_printd_index(fp, np, 10); + + acb_dirichlet_dft_rad2_precomp(gp, rad2, prec); + + flint_printf("\nDFT G\n"); + acb_vec_printd_index(gp, np, 10); + _acb_vec_kronecker_mul(gp, gp, fp, np, prec); - acb_dirichlet_dft_inverse_rad2_precomp(gp, dft, prec); - for (k = 0; k < len; k++) - acb_set(w + k, gp + k); + + flint_printf("\n(DFT F)(DFT G)=DFT(F*G)\n"); + acb_vec_printd_index(gp, np, 10); + + acb_dirichlet_dft_inverse_rad2_precomp(gp, rad2, prec); + + flint_printf("\nF*G\n"); + acb_vec_printd_index(gp, np, 10); + + _acb_vec_set(w, gp, len); + _acb_vec_clear(fp, np); + _acb_vec_clear(gp, np); +} + +void +acb_dirichlet_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) +{ + int e; + acb_dirichlet_dft_rad2_t dft; + e = n_clog(2 * len - 1, 2); + acb_dirichlet_dft_rad2_init(dft, e, prec); + acb_dirichlet_dft_convol_rad2_precomp(w, f, g, len, dft, prec); + acb_dirichlet_dft_rad2_clear(dft); } diff --git a/acb_dirichlet/dft_convol_naive.c b/acb_dirichlet/dft_convol_naive.c index be7f2c8e..a11db829 100644 --- a/acb_dirichlet/dft_convol_naive.c +++ b/acb_dirichlet/dft_convol_naive.c @@ -24,8 +24,8 @@ acb_dirichlet_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, gy = g; acb_zero(wx); for (y = 0; y <= x; y++) - acb_addmul(wx, fx--, gy++, prec); + acb_addmul(wx, fx - y, g + y, prec); for (; y < len; y++) - acb_addmul(wx, f + x - y, g + y, prec); + acb_addmul(wx, fx + (len - y), g + y, prec); } } diff --git a/acb_dirichlet/dft_rad2.c b/acb_dirichlet/dft_rad2.c index bfd99ff1..061a6441 100644 --- a/acb_dirichlet/dft_rad2.c +++ b/acb_dirichlet/dft_rad2.c @@ -38,7 +38,7 @@ acb_dirichlet_dft_rad2_reorder(acb_ptr v, slong n) /* remark: can use same rad2 with smaller power of 2 */ void -acb_dirichlet_dft_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec) +acb_dirichlet_dft_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec) { slong j, k, l; slong n = rad2->n, nz = rad2->nz; @@ -46,6 +46,8 @@ acb_dirichlet_dft_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong p acb_t tmp; acb_init(tmp); + acb_dirichlet_dft_rad2_reorder(v, n); + for (k = 1, l = nz; k < n; k <<= 1, l >>= 1) for (p = v; p < vend; p += k) for (j = 0; j < nz; j += l, p++) @@ -59,7 +61,7 @@ acb_dirichlet_dft_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong p } void -acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, acb_dirichlet_dft_rad2_t rad2, slong prec) +acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec) { slong k, n = rad2->n; acb_dirichlet_dft_rad2_precomp(v, rad2, prec); diff --git a/acb_dirichlet/test/t-convol.c b/acb_dirichlet/test/t-convol.c new file mode 100644 index 00000000..df2a00fa --- /dev/null +++ b/acb_dirichlet/test/t-convol.c @@ -0,0 +1,118 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dirichlet.h" + +typedef void (*do_f) (acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec); + +void +check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char f1[], char f2[]) +{ + slong i; + + for (i = 0; i < len; i++) + { + if (!acb_overlaps(w1 + i, w2 + i)) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu, size = %wu\n", q, len); + flint_printf("\nDFT differ from index %ld / %ld \n", i, len); + flint_printf("\n%s =\n", f1); + acb_vec_printd_index(w1, len, digits); + flint_printf("\n%s =\n", f2); + acb_vec_printd_index(w2, len, digits); + flint_printf("\n\n"); + abort(); + } + else if (!acb_is_zero(w1+i) && (acb_rel_accuracy_bits(w1 + i) < 30 + || acb_rel_accuracy_bits(w2 + i) < 30)) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu\n", q); + flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); + flint_printf("\nnaive =\n"); + acb_printd(w1 + i, digits); + flint_printf("\nfast =\n"); + acb_printd(w2 + i, digits); + flint_printf("\nerrors %ld & %ld [prec = %wu]\n", + acb_rel_accuracy_bits(w1 + i), + acb_rel_accuracy_bits(w2 + i), prec); + abort(); + } + } +} + + +int main() +{ + + slong k; + slong prec = 100, digits = 30; + slong nq = 13; + ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; + flint_rand_t state; + + slong f, nf = 2; + do_f func[2] = { acb_dirichlet_dft_convol_naive, acb_dirichlet_dft_convol_rad2 }; + char * name[4] = { "naive", "rad2" }; + + flint_printf("convol...."); + fflush(stdout); + + flint_randinit(state); + + for (k = 0; k < nq; k++) + { + slong i; + acb_ptr z1, z2, x, y; + + z1 = _acb_vec_init(q[k]); + z2 = _acb_vec_init(q[k]); + x = _acb_vec_init(q[k]); + y = _acb_vec_init(q[k]); + + for (i = 0; i < q[k]; i++) + { + acb_set_si(x + i, q[k] - i); + acb_set_si(y + i, i * i); + /* + acb_set_si(x + i, n_randint(state, q[k])); + acb_set_si(y + i, n_randint(state, q[k])); + */ + } + + for (f = 0; f < nf; f++) + { + + acb_ptr z = (f == 0) ? z1 : z2; + + func[f](z, x, y, q[k], prec); + + if (f == 0) + continue; + + check_vec_eq_prec(z1, z2, q[k], prec, digits, q[k], name[0], name[f]); + + } + + _acb_vec_clear(x, q[k]); + _acb_vec_clear(y, q[k]); + _acb_vec_clear(z1, q[k]); + _acb_vec_clear(z2, q[k]); + } + + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} + + diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 02fa7bb6..1e783277 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -60,9 +60,9 @@ int main() ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; flint_rand_t state; - slong f, nf = 3; - do_f func[3] = { acb_dirichlet_dft_pol, acb_dirichlet_dft_cyc, acb_dirichlet_dft_crt }; - char * name[3] = { "pol", "cyc", "crt" }; + slong f, nf = 4; + do_f func[4] = { acb_dirichlet_dft_pol, acb_dirichlet_dft_cyc, acb_dirichlet_dft_crt , acb_dirichlet_dft_bluestein }; + char * name[4] = { "pol", "cyc", "crt", "bluestein" }; flint_printf("dft...."); fflush(stdout); @@ -104,11 +104,14 @@ int main() /* radix2 dft */ for (k = 1; k < 12; k++) { - slong n = 1 << k; + slong n = 1 << k, j; acb_ptr v, w1, w2; v = w2 = _acb_vec_init(n); w1 = _acb_vec_init(n); + for (j = 0; j < n; j++) + acb_set_si(v + k, k); + acb_dirichlet_dft_pol(w1, v, n, prec); acb_dirichlet_dft_rad2(v, k, prec); From 0fd358048fe1fb50cfe69ed98291a016264e0725 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 6 Oct 2016 12:39:42 +0200 Subject: [PATCH 131/139] move dft to separate directory --- Makefile.in | 2 +- acb.h | 5 + {acb_dirichlet => acb}/nth_root.c | 6 +- {acb_dirichlet => acb}/vec_nth_root.c | 4 +- acb_dft.h | 325 ++++++++++++++++++ {acb_dirichlet => acb_dft}/dft_bluestein.c | 22 +- {acb_dirichlet => acb_dft}/dft_convol_fft.c | 28 +- {acb_dirichlet => acb_dft}/dft_convol_naive.c | 4 +- {acb_dirichlet => acb_dft}/dft_crt.c | 14 +- {acb_dirichlet => acb_dft}/dft_cyc.c | 30 +- {acb_dirichlet => acb_dft}/dft_fast.c.tmp | 0 {acb_dirichlet => acb_dft}/dft_pol.c | 14 +- {acb_dirichlet => acb_dft}/dft_precomp.c | 38 +- {acb_dirichlet => acb_dft}/dft_prod.c | 30 +- {acb_dirichlet => acb_dft}/dft_rad2.c | 22 +- {acb_dirichlet => acb_dft}/dft_step.c | 16 +- {acb_dirichlet => acb_dft}/test/t-convol.c | 4 +- acb_dft/test/t-dft.c | 127 +++++++ acb_dirichlet.h | 295 +--------------- acb_dirichlet/dft.c | 3 +- acb_dirichlet/gauss_sum_naive.c | 2 +- acb_dirichlet/jacobi_sum_naive.c | 2 +- acb_dirichlet/l_hurwitz.c | 2 +- acb_dirichlet/powers_init.c | 2 +- acb_dirichlet/test/t-dft.c | 59 +--- acb_dirichlet/test/t-thetanull.c | 2 +- doc/source/acb.rst | 10 + doc/source/acb_dft.rst | 110 ++++++ doc/source/acb_dirichlet.rst | 10 - 29 files changed, 704 insertions(+), 484 deletions(-) rename {acb_dirichlet => acb}/nth_root.c (82%) rename {acb_dirichlet => acb}/vec_nth_root.c (94%) create mode 100644 acb_dft.h rename {acb_dirichlet => acb_dft}/dft_bluestein.c (67%) rename {acb_dirichlet => acb_dft}/dft_convol_fft.c (68%) rename {acb_dirichlet => acb_dft}/dft_convol_naive.c (85%) rename {acb_dirichlet => acb_dft}/dft_crt.c (87%) rename {acb_dirichlet => acb_dft}/dft_cyc.c (61%) rename {acb_dirichlet => acb_dft}/dft_fast.c.tmp (100%) rename {acb_dirichlet => acb_dft}/dft_pol.c (70%) rename {acb_dirichlet => acb_dft}/dft_precomp.c (52%) rename {acb_dirichlet => acb_dft}/dft_prod.c (50%) rename {acb_dirichlet => acb_dft}/dft_rad2.c (72%) rename {acb_dirichlet => acb_dft}/dft_step.c (75%) rename {acb_dirichlet => acb_dft}/test/t-convol.c (96%) create mode 100644 acb_dft/test/t-dft.c create mode 100644 doc/source/acb_dft.rst diff --git a/Makefile.in b/Makefile.in index 38024bd3..7a0398cc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13,7 +13,7 @@ QUIET_AR = @echo ' ' AR ' ' $@; AT=@ BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \ - acb_calc acb_hypgeom acb_modular acb_dirichlet arb_hypgeom bernoulli hypgeom \ + acb_calc acb_hypgeom acb_modular acb_dft acb_dirichlet arb_hypgeom bernoulli hypgeom \ fmpz_extras bool_mat partitions dlog \ $(EXTRA_BUILD_DIRS) diff --git a/acb.h b/acb.h index 158cbbf2..f7ca1211 100644 --- a/acb.h +++ b/acb.h @@ -1135,6 +1135,11 @@ _acb_vec_get_unique_fmpz_vec(fmpz * res, acb_srcptr vec, slong len) /* sort complex numbers in a nice-to-display order */ void _acb_vec_sort_pretty(acb_ptr vec, slong len); +/* roots of unity */ +void acb_nth_root(acb_t res, ulong order, slong prec); +void _acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec); +void _acb_vec_nth_roots(acb_ptr z, slong len, slong prec); + #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/nth_root.c b/acb/nth_root.c similarity index 82% rename from acb_dirichlet/nth_root.c rename to acb/nth_root.c index 70547f0a..ea3a6f43 100644 --- a/acb_dirichlet/nth_root.c +++ b/acb/nth_root.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" static void -_acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) +_acb_nth_root(acb_t res, ulong order, slong prec) { fmpq_t t; fmpq_init(t); @@ -22,7 +22,7 @@ _acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) } void -acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) +acb_nth_root(acb_t res, ulong order, slong prec) { switch (order) { @@ -36,7 +36,7 @@ acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) acb_onei(res); break; default: - _acb_dirichlet_nth_root(res, order, prec); + _acb_nth_root(res, order, prec); break; } } diff --git a/acb_dirichlet/vec_nth_root.c b/acb/vec_nth_root.c similarity index 94% rename from acb_dirichlet/vec_nth_root.c rename to acb/vec_nth_root.c index a7249fd5..10b22621 100644 --- a/acb_dirichlet/vec_nth_root.c +++ b/acb/vec_nth_root.c @@ -23,7 +23,7 @@ _acb_vec_set_powers_step(acb_ptr xs, slong n, slong len, slong step, slong prec) if (i == 0) acb_one(xs + j); else if (i == 1) - acb_dirichlet_nth_root(xs + j, n, prec); + acb_nth_root(xs + j, n, prec); else if (i % 2 == 0) acb_mul(xs + j, xs + j / 2, xs + j / 2, prec); else @@ -52,7 +52,7 @@ _acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong } void -acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec) +_acb_vec_nth_roots(acb_ptr z, slong len, slong prec) { slong i, q; n_factor_t fac; diff --git a/acb_dft.h b/acb_dft.h new file mode 100644 index 00000000..c73ccff8 --- /dev/null +++ b/acb_dft.h @@ -0,0 +1,325 @@ +/* + Copyright (C) 2015 Jonathan Bober + Copyright (C) 2016 Fredrik Johansson + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef ACB_DFT_H +#define ACB_DFT_H + +#ifdef ACB_DFT_INLINES_C +#define ACB_DFT_INLINE +#else +#define ACB_DFT_INLINE static __inline__ +#endif + +#include "acb.h" +#include "dlog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _acb_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec); +void acb_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dft_rad2(acb_ptr v, int e, slong prec); +void acb_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec); +void acb_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); + +void acb_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); +void acb_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); + +#define CRT_MAX 15 +typedef struct +{ + int num; + nmod_t n; + slong m[CRT_MAX]; + ulong M[CRT_MAX]; + ulong vM[CRT_MAX]; +} +crt_struct; + +typedef crt_struct crt_t[1]; + +void crt_init(crt_t c, ulong n); + +void crt_decomp(acb_ptr y, acb_srcptr x, slong dx, const crt_t c, ulong len); +void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); + +typedef struct acb_dft_step_struct acb_dft_step_struct; +typedef acb_dft_step_struct * acb_dft_step_ptr; + +typedef struct +{ + slong n; + int zclear; + acb_ptr z; + slong num; + acb_dft_step_ptr cyc; +} +acb_dft_cyc_struct; + +typedef acb_dft_cyc_struct acb_dft_cyc_t[1]; + +typedef struct +{ + int e; + slong n; /* = 1 << e */ + slong nz; /* = n but could be bigger */ + acb_ptr z; +} +acb_dft_rad2_struct; + +typedef acb_dft_rad2_struct acb_dft_rad2_t[1]; + +typedef struct +{ + slong n; + acb_ptr z; + acb_dft_rad2_t rad2; +} +acb_dft_bluestein_struct; + +typedef acb_dft_bluestein_struct acb_dft_bluestein_t[1]; + +typedef struct +{ + slong n; + slong num; + acb_dft_step_ptr cyc; +} +acb_dft_prod_struct; + +typedef acb_dft_prod_struct acb_dft_prod_t[1]; + +typedef struct +{ + slong n; + crt_t c; + slong dv; + /* then a product */ + acb_dft_step_ptr cyc; +} +acb_dft_crt_struct; + +typedef acb_dft_crt_struct acb_dft_crt_t[1]; + +typedef struct +{ + slong n; + slong dv; + int zclear; + acb_ptr z; + slong dz; +} +acb_dft_pol_struct; + +typedef acb_dft_pol_struct acb_dft_pol_t[1]; + +typedef struct +{ + int type; + union + { + acb_dft_rad2_t rad2; + acb_dft_cyc_t cyc; + acb_dft_prod_t prod; + acb_dft_crt_t crt; + acb_dft_pol_t pol; + } t; +} +acb_dft_pre_struct; + +typedef acb_dft_pre_struct acb_dft_pre_t[1]; + +/* covers both product and cyclic case */ +struct +acb_dft_step_struct +{ + /* [G:H] */ + slong m; + /* card H */ + slong M; + slong dv; /* = M for prod, also = M if cyc is reordered */ + /* pointer on some roots of unity, if needed */ + acb_srcptr z; + /* index of mM in z */ + slong dz; + /* dft to call on H */ + acb_dft_pre_t pre; + /* dft to call on G/H ? */ +}; + +/*typedef acb_dft_pre_struct acb_dft_pre_t[1];*/ + +#define DFT_VERB 0 + +enum +{ + DFT_POL, DFT_CYC, DFT_PROD, DFT_CRT , DFT_RAD2 /*, DFT_CONV */ +}; + +void acb_dft_step(acb_ptr w, acb_srcptr v, acb_dft_step_ptr cyc, slong num, slong prec); + +void acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec); + +ACB_DFT_INLINE void +acb_dft_pol_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pol_t pol, slong prec) +{ + _acb_dft_pol(w, v, pol->dv, pol->z, pol->dz, pol->n, prec); +} +ACB_DFT_INLINE void +acb_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dft_cyc_t cyc, slong prec) +{ + acb_dft_step(w, v, cyc->cyc, cyc->num, prec); +} +void acb_dft_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec); +void acb_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dft_crt_t crt, slong prec); +void acb_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dft_prod_t prod, slong prec); + +void acb_dft_inverse_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec); +void acb_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dft_rad2_t, slong prec); + +void _acb_dft_precomp_init(acb_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec); +void acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec); +void acb_dft_precomp_clear(acb_dft_pre_t pre); + +acb_dft_step_ptr _acb_dft_steps_prod(slong * m, slong num, slong prec); + +ACB_DFT_INLINE void +acb_dft_prod_init(acb_dft_prod_t t, slong * cyc, slong num, slong prec) +{ + t->num = num; + t->cyc = _acb_dft_steps_prod(cyc, num, prec); +} + +void acb_dft_prod_clear(acb_dft_prod_t t); + +void _acb_dft_cyc_init_z_fac(acb_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec); +void _acb_dft_cyc_init(acb_dft_cyc_t t, slong dv, slong len, slong prec); + +ACB_DFT_INLINE void +acb_dft_cyc_init(acb_dft_cyc_t t, slong len, slong prec) +{ + _acb_dft_cyc_init(t, 1, len, prec); +} + +void acb_dft_cyc_clear(acb_dft_cyc_t t); + +void _acb_dft_pol_init(acb_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec); + +ACB_DFT_INLINE void +acb_dft_pol_init(acb_dft_pol_t pol, slong len, slong prec) +{ + _acb_dft_pol_init(pol, 1, NULL, 0, len, prec); +} + +ACB_DFT_INLINE void +acb_dft_pol_clear(acb_dft_pol_t pol) +{ + if (pol->zclear) + _acb_vec_clear(pol->z, pol->n); +} + +ACB_DFT_INLINE void +acb_dft_rad2_init(acb_dft_rad2_t t, int e, slong prec) +{ + t->e = e; + t->n = 1 << e; + t->nz = t->n >> 1; + t->z = _acb_vec_init(t->nz); + /* set n/2 roots of order n */ + _acb_vec_nth_roots_pe(t->z, 2, e, t->nz, 1, prec); +} + +ACB_DFT_INLINE void +acb_dft_rad2_clear(acb_dft_rad2_t t) +{ + _acb_vec_clear(t->z, t->nz); +} + +void acb_dft_bluestein_init(acb_dft_bluestein_t t, slong n, slong prec); + +ACB_DFT_INLINE void +acb_dft_bluestein_clear(acb_dft_bluestein_t t) +{ + _acb_vec_clear(t->z, t->n); + acb_dft_rad2_clear(t->rad2); +} + +void _acb_dft_crt_init(acb_dft_crt_t crt, slong dv, slong len, slong prec); + +ACB_DFT_INLINE void +acb_dft_crt_init(acb_dft_crt_t crt, slong len, slong prec) +{ + crt->n = len; + crt_init(crt->c, len); + crt->dv = 1; + crt->cyc = _acb_dft_steps_prod(crt->c->m, crt->c->num, prec); +} + +ACB_DFT_INLINE void +acb_dft_crt_clear(acb_dft_crt_t crt) +{ + flint_free(crt->cyc); +} + +/* utils, could be moved elsewhere */ + +ACB_DFT_INLINE void +acb_swap_ri(acb_t x) +{ + arb_swap(acb_realref(x), acb_imagref(x)); +} + +ACB_DFT_INLINE void +acb_vec_swap_ri(acb_ptr v, slong len) +{ + slong k; + for (k = 0; k < len; k++) + acb_swap_ri(v + k); +} + +ACB_DFT_INLINE void +_acb_vec_kronecker_mul(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) +{ + slong k; + for (k = 0; k < len; k++) + acb_mul(z + k, x + k, y + k, prec); +} + +/* z[k] = conj(x[k])*y[k] */ +ACB_DFT_INLINE void +acb_vec_kronecker_mul_conj(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) +{ + slong k; + for (k = 0; k < len; k++) + { + acb_conj(z + k, x + k); + acb_mul(z + k, z + k, y + k, prec); + } +} + +ACB_DFT_INLINE void +acb_vec_printd_index(acb_srcptr vec, slong len, slong digits) +{ + slong i; + for (i = 0; i < len; i++) + flint_printf("[%ld] ",i), acb_printd(vec + i, digits), flint_printf("\n"); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/acb_dirichlet/dft_bluestein.c b/acb_dft/dft_bluestein.c similarity index 67% rename from acb_dirichlet/dft_bluestein.c rename to acb_dft/dft_bluestein.c index a73294ec..3122c15d 100644 --- a/acb_dirichlet/dft_bluestein.c +++ b/acb_dft/dft_bluestein.c @@ -9,19 +9,19 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" void -acb_dirichlet_dft_bluestein_init(acb_dirichlet_dft_bluestein_t t, slong n, slong prec) +acb_dft_bluestein_init(acb_dft_bluestein_t t, slong n, slong prec) { nmod_t n2; slong k, k2; acb_ptr z2n; int e = n_clog(2 * n - 1, 2); - acb_dirichlet_dft_rad2_init(t->rad2, e, prec); + acb_dft_rad2_init(t->rad2, e, prec); z2n = _acb_vec_init(2 * n); - acb_dirichlet_vec_nth_roots(z2n, 2 * n, prec); + _acb_vec_nth_roots(z2n, 2 * n, prec); nmod_init(&n2, 2 * n); t->n = n; t->z = _acb_vec_init(n); @@ -34,7 +34,7 @@ acb_dirichlet_dft_bluestein_init(acb_dirichlet_dft_bluestein_t t, slong n, slong } void -acb_dirichlet_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_bluestein_t t, slong prec) +acb_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dft_bluestein_t t, slong prec) { slong n = t->n; acb_ptr vz, wz, z; @@ -47,7 +47,7 @@ acb_dirichlet_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet flint_printf("\nvz\n"); acb_vec_printd_index(vz, n, 10); wz = _acb_vec_init(n); - acb_dirichlet_dft_convol_rad2_precomp(wz, vz, z, n, t->rad2, prec); + acb_dft_convol_rad2_precomp(wz, vz, z, n, t->rad2, prec); flint_printf("\nwz\n"); acb_vec_printd_index(wz, n, 10); acb_vec_kronecker_mul_conj(w, z, wz, n, prec); @@ -58,10 +58,10 @@ acb_dirichlet_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet } void -acb_dirichlet_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec) +acb_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec) { - acb_dirichlet_dft_bluestein_t t; - acb_dirichlet_dft_bluestein_init(t, len, prec); - acb_dirichlet_dft_bluestein_precomp(w, v, t, prec); - acb_dirichlet_dft_bluestein_clear(t); + acb_dft_bluestein_t t; + acb_dft_bluestein_init(t, len, prec); + acb_dft_bluestein_precomp(w, v, t, prec); + acb_dft_bluestein_clear(t); } diff --git a/acb_dirichlet/dft_convol_fft.c b/acb_dft/dft_convol_fft.c similarity index 68% rename from acb_dirichlet/dft_convol_fft.c rename to acb_dft/dft_convol_fft.c index 07a836bc..cbfc863a 100644 --- a/acb_dirichlet/dft_convol_fft.c +++ b/acb_dft/dft_convol_fft.c @@ -9,11 +9,11 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" /* assume np >= 2 * n - 1 */ void -acb_dirichlet_dft_convol_pad(acb_ptr fp, acb_ptr gp, acb_srcptr f, acb_srcptr g, slong n, slong np) +acb_dft_convol_pad(acb_ptr fp, acb_ptr gp, acb_srcptr f, acb_srcptr g, slong n, slong np) { slong k; @@ -38,17 +38,17 @@ acb_dirichlet_dft_convol_pad(acb_ptr fp, acb_ptr gp, acb_srcptr f, acb_srcptr g, } void -acb_dirichlet_dft_inverse_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) +acb_dft_inverse_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) { /* divide before to keep v const */ _acb_vec_scalar_div_ui(w, v, len, len, prec); acb_vec_swap_ri(w, len); - acb_dirichlet_dft_cyc(w, w, len, prec); + acb_dft_cyc(w, w, len, prec); acb_vec_swap_ri(w, len); } void -acb_dirichlet_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dirichlet_dft_rad2_t rad2, slong prec) +acb_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dft_rad2_t rad2, slong prec) { slong np; acb_ptr fp, gp; @@ -61,19 +61,19 @@ acb_dirichlet_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slo fp = _acb_vec_init(np); gp = _acb_vec_init(np); - acb_dirichlet_dft_convol_pad(fp, gp, f, g, len, np); + acb_dft_convol_pad(fp, gp, f, g, len, np); flint_printf("\nF\n"); acb_vec_printd_index(fp, np, 10); flint_printf("\nG\n"); acb_vec_printd_index(gp, np, 10); - acb_dirichlet_dft_rad2_precomp(fp, rad2, prec); + acb_dft_rad2_precomp(fp, rad2, prec); flint_printf("\nDFT F\n"); acb_vec_printd_index(fp, np, 10); - acb_dirichlet_dft_rad2_precomp(gp, rad2, prec); + acb_dft_rad2_precomp(gp, rad2, prec); flint_printf("\nDFT G\n"); acb_vec_printd_index(gp, np, 10); @@ -83,7 +83,7 @@ acb_dirichlet_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slo flint_printf("\n(DFT F)(DFT G)=DFT(F*G)\n"); acb_vec_printd_index(gp, np, 10); - acb_dirichlet_dft_inverse_rad2_precomp(gp, rad2, prec); + acb_dft_inverse_rad2_precomp(gp, rad2, prec); flint_printf("\nF*G\n"); acb_vec_printd_index(gp, np, 10); @@ -94,12 +94,12 @@ acb_dirichlet_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slo } void -acb_dirichlet_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) +acb_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) { int e; - acb_dirichlet_dft_rad2_t dft; + acb_dft_rad2_t dft; e = n_clog(2 * len - 1, 2); - acb_dirichlet_dft_rad2_init(dft, e, prec); - acb_dirichlet_dft_convol_rad2_precomp(w, f, g, len, dft, prec); - acb_dirichlet_dft_rad2_clear(dft); + acb_dft_rad2_init(dft, e, prec); + acb_dft_convol_rad2_precomp(w, f, g, len, dft, prec); + acb_dft_rad2_clear(dft); } diff --git a/acb_dirichlet/dft_convol_naive.c b/acb_dft/dft_convol_naive.c similarity index 85% rename from acb_dirichlet/dft_convol_naive.c rename to acb_dft/dft_convol_naive.c index a11db829..3131537a 100644 --- a/acb_dirichlet/dft_convol_naive.c +++ b/acb_dft/dft_convol_naive.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" void -acb_dirichlet_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) +acb_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) { slong x, y; for (x = 0; x < len; x ++) diff --git a/acb_dirichlet/dft_crt.c b/acb_dft/dft_crt.c similarity index 87% rename from acb_dirichlet/dft_crt.c rename to acb_dft/dft_crt.c index 0f8eaea5..a3603562 100644 --- a/acb_dirichlet/dft_crt.c +++ b/acb_dft/dft_crt.c @@ -9,7 +9,7 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" void crt_init(crt_t c, ulong n) @@ -143,34 +143,34 @@ crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) } void -_acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong dv, slong len, slong prec) +_acb_dft_crt_init(acb_dft_crt_t crt, slong dv, slong len, slong prec) { crt->n = len; crt_init(crt->c, len); crt->dv = dv; - crt->cyc = _acb_dirichlet_dft_steps_prod(crt->c->m, crt->c->num, prec); + crt->cyc = _acb_dft_steps_prod(crt->c->m, crt->c->num, prec); } void -acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_crt_t crt, slong prec) +acb_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dft_crt_t crt, slong prec) { acb_ptr t; t = _acb_vec_init(crt->n); crt_decomp(w, v, crt->dv, crt->c, crt->n); - acb_dirichlet_dft_step(t, w, crt->cyc, crt->c->num, prec); + acb_dft_step(t, w, crt->cyc, crt->c->num, prec); crt_recomp(w, t, crt->c, crt->n); _acb_vec_clear(t, crt->n); } void -acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) +acb_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) { crt_t c; acb_ptr t; t = _acb_vec_init(len); crt_init(c, len); crt_decomp(w, v, 1, c, len); - acb_dirichlet_dft_prod(t, w, c->m, c->num, prec); + acb_dft_prod(t, w, c->m, c->num, prec); crt_recomp(w, t, c, len); _acb_vec_clear(t, len); } diff --git a/acb_dirichlet/dft_cyc.c b/acb_dft/dft_cyc.c similarity index 61% rename from acb_dirichlet/dft_cyc.c rename to acb_dft/dft_cyc.c index 65601651..732e15e3 100644 --- a/acb_dirichlet/dft_cyc.c +++ b/acb_dft/dft_cyc.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" void -_acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec) +_acb_dft_cyc_init_z_fac(acb_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec) { slong i, j, num; t->n = len; @@ -20,12 +20,12 @@ _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slo for (i = 0; i < fac.num; i++) num += fac.exp[i]; t->num = num; - t->cyc = flint_malloc(num * sizeof(acb_dirichlet_dft_step_struct)); + t->cyc = flint_malloc(num * sizeof(acb_dft_step_struct)); if (z == NULL) { z = _acb_vec_init(t->n); - acb_dirichlet_vec_nth_roots(z, t->n, prec); + _acb_vec_nth_roots(z, t->n, prec); dz = 1; t->zclear = 1; } @@ -53,9 +53,9 @@ _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slo t->cyc[num].dz = dz; /* TODO: ugly, reorder should solve this */ if (num == t->num - 1) - _acb_dirichlet_dft_precomp_init(t->cyc[num].pre, dv, z, dz, m, prec); + _acb_dft_precomp_init(t->cyc[num].pre, dv, z, dz, m, prec); else - _acb_dirichlet_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec); + _acb_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec); dv *= m; dz *= m; num++; @@ -64,30 +64,30 @@ _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slo } void -_acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong dv, slong len, slong prec) +_acb_dft_cyc_init(acb_dft_cyc_t t, slong dv, slong len, slong prec) { n_factor_t fac; n_factor_init(&fac); n_factor(&fac, len, 0); - _acb_dirichlet_dft_cyc_init_z_fac(t, fac, dv, NULL, 0, len, prec); + _acb_dft_cyc_init_z_fac(t, fac, dv, NULL, 0, len, prec); } void -acb_dirichlet_dft_cyc_clear(acb_dirichlet_dft_cyc_t t) +acb_dft_cyc_clear(acb_dft_cyc_t t) { slong i; for (i = 0; i < t->num; i++) - acb_dirichlet_dft_precomp_clear(t->cyc[i].pre); + acb_dft_precomp_clear(t->cyc[i].pre); if (t->zclear) _acb_vec_clear(t->z, t->n); flint_free(t->cyc); } void -acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) +acb_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) { - acb_dirichlet_dft_cyc_t cyc; - acb_dirichlet_dft_cyc_init(cyc, len, prec); - acb_dirichlet_dft_cyc_precomp(w, v, cyc, prec); - acb_dirichlet_dft_cyc_clear(cyc); + acb_dft_cyc_t cyc; + acb_dft_cyc_init(cyc, len, prec); + acb_dft_cyc_precomp(w, v, cyc, prec); + acb_dft_cyc_clear(cyc); } diff --git a/acb_dirichlet/dft_fast.c.tmp b/acb_dft/dft_fast.c.tmp similarity index 100% rename from acb_dirichlet/dft_fast.c.tmp rename to acb_dft/dft_fast.c.tmp diff --git a/acb_dirichlet/dft_pol.c b/acb_dft/dft_pol.c similarity index 70% rename from acb_dirichlet/dft_pol.c rename to acb_dft/dft_pol.c index eebf657c..cc008015 100644 --- a/acb_dirichlet/dft_pol.c +++ b/acb_dft/dft_pol.c @@ -10,11 +10,11 @@ */ #include "acb_poly.h" -#include "acb_dirichlet.h" +#include "acb_dft.h" /* all roots are already computed */ void -_acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec) +_acb_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec) { slong i, j; acb_ptr wi; @@ -29,17 +29,17 @@ _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz } void -acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec) +acb_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec) { acb_ptr z; z = _acb_vec_init(len); - acb_dirichlet_vec_nth_roots(z, len, prec); - _acb_dirichlet_dft_pol(w, v, 1, z, 1, len, prec); + _acb_vec_nth_roots(z, len, prec); + _acb_dft_pol(w, v, 1, z, 1, len, prec); _acb_vec_clear(z, len); } void -_acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec) +_acb_dft_pol_init(acb_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec) { pol->n = len; pol->dv = dv; @@ -49,7 +49,7 @@ _acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, sl if (DFT_VERB) flint_printf("warning: init z[%ld] in dft_pol, should be avoided\n",len); pol->z = _acb_vec_init(len); - acb_dirichlet_vec_nth_roots(pol->z, len, prec); + _acb_vec_nth_roots(pol->z, len, prec); pol->dz = 1; pol->zclear = 1; } diff --git a/acb_dirichlet/dft_precomp.c b/acb_dft/dft_precomp.c similarity index 52% rename from acb_dirichlet/dft_precomp.c rename to acb_dft/dft_precomp.c index 70e46e34..2aba2d39 100644 --- a/acb_dirichlet/dft_precomp.c +++ b/acb_dft/dft_precomp.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" void -_acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec) +_acb_dft_precomp_init(acb_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec) { if (len <= 1) { @@ -23,7 +23,7 @@ _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z { /* TODO: need convolution if len is large */ pre->type = DFT_POL; - _acb_dirichlet_dft_pol_init(pre->t.pol, dv, z, dz, len, prec); + _acb_dft_pol_init(pre->t.pol, dv, z, dz, len, prec); } else { @@ -36,65 +36,65 @@ _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z { /* TODO: could be p^e, or 2^e */ pre->type = DFT_CYC; - _acb_dirichlet_dft_cyc_init_z_fac(pre->t.cyc, fac, dv, z, dz, len, prec); + _acb_dft_cyc_init_z_fac(pre->t.cyc, fac, dv, z, dz, len, prec); } else { pre->type = DFT_CRT; - _acb_dirichlet_dft_crt_init(pre->t.crt, dv, len, prec); + _acb_dft_crt_init(pre->t.crt, dv, len, prec); } } } void -acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong len, slong prec) +acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec) { - _acb_dirichlet_dft_precomp_init(pre, 1, NULL, 0, len, prec); + _acb_dft_precomp_init(pre, 1, NULL, 0, len, prec); } void -acb_dirichlet_dft_precomp_clear(acb_dirichlet_dft_pre_t pre) +acb_dft_precomp_clear(acb_dft_pre_t pre) { switch (pre->type) { case DFT_POL: - acb_dirichlet_dft_pol_clear(pre->t.pol); + acb_dft_pol_clear(pre->t.pol); break; case DFT_CYC: - acb_dirichlet_dft_cyc_clear(pre->t.cyc); + acb_dft_cyc_clear(pre->t.cyc); break; case DFT_PROD: - acb_dirichlet_dft_prod_clear(pre->t.prod); + acb_dft_prod_clear(pre->t.prod); break; case DFT_CRT: - acb_dirichlet_dft_crt_clear(pre->t.crt); + acb_dft_crt_clear(pre->t.crt); break; default: - flint_printf("acb_dirichlet_dft_clear: unknown strategy code %i\n", pre->type); + flint_printf("acb_dft_clear: unknown strategy code %i\n", pre->type); abort(); break; } } void -acb_dirichlet_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_pre_t pre, slong prec) +acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec) { switch (pre->type) { case DFT_POL: - acb_dirichlet_dft_pol_precomp(w, v, pre->t.pol, prec); + acb_dft_pol_precomp(w, v, pre->t.pol, prec); break; case DFT_CYC: - acb_dirichlet_dft_cyc_precomp(w, v, pre->t.cyc, prec); + acb_dft_cyc_precomp(w, v, pre->t.cyc, prec); break; case DFT_PROD: - acb_dirichlet_dft_prod_precomp(w, v, pre->t.prod, prec); + acb_dft_prod_precomp(w, v, pre->t.prod, prec); break; case DFT_CRT: - acb_dirichlet_dft_crt_precomp(w, v, pre->t.crt, prec); + acb_dft_crt_precomp(w, v, pre->t.crt, prec); break; default: - flint_printf("acb_dirichlet_dft_precomp: unknown strategy code %i\n", pre->type); + flint_printf("acb_dft_precomp: unknown strategy code %i\n", pre->type); abort(); break; } diff --git a/acb_dirichlet/dft_prod.c b/acb_dft/dft_prod.c similarity index 50% rename from acb_dirichlet/dft_prod.c rename to acb_dft/dft_prod.c index ad964d46..0a4f2356 100644 --- a/acb_dirichlet/dft_prod.c +++ b/acb_dft/dft_prod.c @@ -9,14 +9,14 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" -acb_dirichlet_dft_step_ptr -_acb_dirichlet_dft_steps_prod(slong * cyc, slong num, slong prec) +acb_dft_step_ptr +_acb_dft_steps_prod(slong * cyc, slong num, slong prec) { slong i, len; - acb_dirichlet_dft_step_ptr s; - s = flint_malloc(num * sizeof(acb_dirichlet_dft_step_struct)); + acb_dft_step_ptr s; + s = flint_malloc(num * sizeof(acb_dft_step_struct)); len = 1; for (i = 0; i < num; i++) @@ -32,36 +32,36 @@ _acb_dirichlet_dft_steps_prod(slong * cyc, slong num, slong prec) s[i].dv = M; s[i].dz = 0; s[i].z = NULL; - _acb_dirichlet_dft_precomp_init(s[i].pre, M, NULL, 0, m, prec); + _acb_dft_precomp_init(s[i].pre, M, NULL, 0, m, prec); } return s; } void -acb_dirichlet_dft_prod_clear(acb_dirichlet_dft_prod_t t) +acb_dft_prod_clear(acb_dft_prod_t t) { slong i; for (i = 0; i < t->num; i++) - acb_dirichlet_dft_precomp_clear(t->cyc[i].pre); + acb_dft_precomp_clear(t->cyc[i].pre); flint_free(t->cyc); } void -acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_prod_t prod, slong prec) +acb_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dft_prod_t prod, slong prec) { if (prod->num == 0) acb_set(w + 0, v + 0); else - acb_dirichlet_dft_step(w, v, prod->cyc, prod->num, prec); + acb_dft_step(w, v, prod->cyc, prod->num, prec); } void -acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) +acb_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) { - acb_dirichlet_dft_prod_t t; - acb_dirichlet_dft_prod_init(t, cyc, num, prec); - acb_dirichlet_dft_prod_precomp(w, v, t, prec); - acb_dirichlet_dft_prod_clear(t); + acb_dft_prod_t t; + acb_dft_prod_init(t, cyc, num, prec); + acb_dft_prod_precomp(w, v, t, prec); + acb_dft_prod_clear(t); } diff --git a/acb_dirichlet/dft_rad2.c b/acb_dft/dft_rad2.c similarity index 72% rename from acb_dirichlet/dft_rad2.c rename to acb_dft/dft_rad2.c index 061a6441..30f528d4 100644 --- a/acb_dirichlet/dft_rad2.c +++ b/acb_dft/dft_rad2.c @@ -9,11 +9,11 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" /* swap each element with one with bit-reversed index */ void -acb_dirichlet_dft_rad2_reorder(acb_ptr v, slong n) +acb_dft_rad2_reorder(acb_ptr v, slong n) { slong i, j, k, l; @@ -38,7 +38,7 @@ acb_dirichlet_dft_rad2_reorder(acb_ptr v, slong n) /* remark: can use same rad2 with smaller power of 2 */ void -acb_dirichlet_dft_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec) +acb_dft_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec) { slong j, k, l; slong n = rad2->n, nz = rad2->nz; @@ -46,7 +46,7 @@ acb_dirichlet_dft_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, s acb_t tmp; acb_init(tmp); - acb_dirichlet_dft_rad2_reorder(v, n); + acb_dft_rad2_reorder(v, n); for (k = 1, l = nz; k < n; k <<= 1, l >>= 1) for (p = v; p < vend; p += k) @@ -61,20 +61,20 @@ acb_dirichlet_dft_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, s } void -acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec) +acb_dft_inverse_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec) { slong k, n = rad2->n; - acb_dirichlet_dft_rad2_precomp(v, rad2, prec); + acb_dft_rad2_precomp(v, rad2, prec); _acb_vec_scalar_mul_2exp_si(v, v, n, - rad2->e); for (k = 1; k < n / 2; k++) acb_swap(v + k, v + n - k); } void -acb_dirichlet_dft_rad2(acb_ptr v, int e, slong prec) +acb_dft_rad2(acb_ptr v, int e, slong prec) { - acb_dirichlet_dft_rad2_t rad2; - acb_dirichlet_dft_rad2_init(rad2, e, prec); - acb_dirichlet_dft_rad2_precomp(v, rad2, prec); - acb_dirichlet_dft_rad2_clear(rad2); + acb_dft_rad2_t rad2; + acb_dft_rad2_init(rad2, e, prec); + acb_dft_rad2_precomp(v, rad2, prec); + acb_dft_rad2_clear(rad2); } diff --git a/acb_dirichlet/dft_step.c b/acb_dft/dft_step.c similarity index 75% rename from acb_dirichlet/dft_step.c rename to acb_dft/dft_step.c index 290f9115..019bd63d 100644 --- a/acb_dirichlet/dft_step.c +++ b/acb_dft/dft_step.c @@ -9,24 +9,24 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" #define REORDER 0 void -acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, slong num, slong prec) +acb_dft_step(acb_ptr w, acb_srcptr v, acb_dft_step_ptr cyc, slong num, slong prec) { - acb_dirichlet_dft_step_struct c; + acb_dft_step_struct c; if (num == 0) { - flint_printf("error: reached num = 0 in acb_dirichlet_dft_step\n"); + flint_printf("error: reached num = 0 in acb_dft_step\n"); abort(); /* or just copy v to w */ } c = cyc[0]; if (num == 1) { - acb_dirichlet_dft_precomp(w, v, c.pre, prec); - /*_acb_dirichlet_dft_base(w, v, c.dv, c.z, c.dz, c.m, prec);*/ + acb_dft_precomp(w, v, c.pre, prec); + /*_acb_dft_base(w, v, c.dv, c.z, c.dz, c.m, prec);*/ } else { @@ -42,7 +42,7 @@ acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, /* m DFT of size M */ for (i = 0; i < m; i++) - acb_dirichlet_dft_step(w + i * M, v + i * dv, cyc + 1, num - 1, prec); + acb_dft_step(w + i * M, v + i * dv, cyc + 1, num - 1, prec); /* twiddle if non trivial product */ if (c.z != NULL) @@ -63,7 +63,7 @@ acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, /* M DFT of size m */ for (j = 0; j < M; j++) - acb_dirichlet_dft_precomp(t + m * j, w + j, c.pre, prec); + acb_dft_precomp(t + m * j, w + j, c.pre, prec); /* reorder */ for (i = 0; i < m; i++) diff --git a/acb_dirichlet/test/t-convol.c b/acb_dft/test/t-convol.c similarity index 96% rename from acb_dirichlet/test/t-convol.c rename to acb_dft/test/t-convol.c index df2a00fa..0cd780f6 100644 --- a/acb_dirichlet/test/t-convol.c +++ b/acb_dft/test/t-convol.c @@ -9,7 +9,7 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "acb_dft.h" typedef void (*do_f) (acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec); @@ -61,7 +61,7 @@ int main() flint_rand_t state; slong f, nf = 2; - do_f func[2] = { acb_dirichlet_dft_convol_naive, acb_dirichlet_dft_convol_rad2 }; + do_f func[2] = { acb_dft_convol_naive, acb_dft_convol_rad2 }; char * name[4] = { "naive", "rad2" }; flint_printf("convol...."); diff --git a/acb_dft/test/t-dft.c b/acb_dft/test/t-dft.c new file mode 100644 index 00000000..23a4af97 --- /dev/null +++ b/acb_dft/test/t-dft.c @@ -0,0 +1,127 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "acb_dft.h" + +typedef void (*do_f) (acb_ptr w, acb_srcptr v, slong len, slong prec); + +void +check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char f1[], char f2[]) +{ + slong i; + + for (i = 0; i < len; i++) + { + if (!acb_overlaps(w1 + i, w2 + i)) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu, size = %wu\n", q, len); + flint_printf("\nDFT differ from index %ld / %ld \n", i, len); + flint_printf("\n%s =\n", f1); + acb_vec_printd_index(w1, len, digits); + flint_printf("\n%s =\n", f2); + acb_vec_printd_index(w2, len, digits); + flint_printf("\n\n"); + abort(); + } + else if (acb_rel_accuracy_bits(w1 + i) < 30 + || acb_rel_accuracy_bits(w2 + i) < 30) + { + flint_printf("FAIL\n\n"); + flint_printf("q = %wu\n", q); + flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); + flint_printf("\nnaive =\n"); + acb_printd(w1 + i, digits); + flint_printf("\nfast =\n"); + acb_printd(w2 + i, digits); + flint_printf("\nerrors %ld & %ld [prec = %wu]\n", + acb_rel_accuracy_bits(w1 + i), + acb_rel_accuracy_bits(w2 + i), prec); + abort(); + } + } +} + + +int main() +{ + + slong k; + slong prec = 100, digits = 30; + slong nq = 13; + ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; + flint_rand_t state; + + slong f, nf = 4; + do_f func[4] = { acb_dft_pol, acb_dft_cyc, acb_dft_crt , acb_dft_bluestein }; + char * name[4] = { "pol", "cyc", "crt", "bluestein" }; + + flint_printf("dft...."); + fflush(stdout); + + flint_randinit(state); + + /* cyclic dft */ + for (k = 0; k < nq; k++) + { + slong i; + acb_ptr v, w1, w2; + + v = _acb_vec_init(q[k]); + w1 = _acb_vec_init(q[k]); + w2 = _acb_vec_init(q[k]); + + for (i = 0; i < q[k]; i++) + acb_set_si(v + i, i); + + for (f = 0; f < nf; f++) + { + + acb_ptr w = (f == 0) ? w1 : w2; + + func[f](w, v, q[k], prec); + + if (f == 0) + continue; + + check_vec_eq_prec(w1, w2, q[k], prec, digits, q[k], name[0], name[f]); + + } + + _acb_vec_clear(v, q[k]); + _acb_vec_clear(w1, q[k]); + _acb_vec_clear(w2, q[k]); + } + + /* radix2 dft */ + for (k = 1; k < 12; k++) + { + slong n = 1 << k, j; + acb_ptr v, w1, w2; + v = w2 = _acb_vec_init(n); + w1 = _acb_vec_init(n); + + for (j = 0; j < n; j++) + acb_set_si(v + k, k); + + acb_dft_pol(w1, v, n, prec); + acb_dft_rad2(v, k, prec); + + check_vec_eq_prec(w1, w2, n, prec, digits, n, "pol", "rad2"); + + } + + flint_randclear(state); + flint_cleanup(); + flint_printf("PASS\n"); + return EXIT_SUCCESS; +} + diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 4ce3ab8d..cd825720 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -250,10 +250,6 @@ void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t); void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec); -void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec); -void _acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec); -void acb_dirichlet_vec_nth_roots(acb_ptr z, slong len, slong prec); - void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec); @@ -293,291 +289,10 @@ void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet /* Discrete Fourier Transform */ -void _acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec); -void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_rad2(acb_ptr v, int e, slong prec); -void acb_dirichlet_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); - -void acb_dirichlet_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); -void acb_dirichlet_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); - void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); -#define CRT_MAX 15 -typedef struct -{ - int num; - nmod_t n; - slong m[CRT_MAX]; - ulong M[CRT_MAX]; - ulong vM[CRT_MAX]; -} -crt_struct; - -typedef crt_struct crt_t[1]; - -void crt_init(crt_t c, ulong n); - -void crt_decomp(acb_ptr y, acb_srcptr x, slong dx, const crt_t c, ulong len); -void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); - -typedef struct acb_dirichlet_dft_step_struct acb_dirichlet_dft_step_struct; -typedef acb_dirichlet_dft_step_struct * acb_dirichlet_dft_step_ptr; - -typedef struct -{ - slong n; - int zclear; - acb_ptr z; - slong num; - acb_dirichlet_dft_step_ptr cyc; -} -acb_dirichlet_dft_cyc_struct; - -typedef acb_dirichlet_dft_cyc_struct acb_dirichlet_dft_cyc_t[1]; - -typedef struct -{ - int e; - slong n; /* = 1 << e */ - slong nz; /* = n but could be bigger */ - acb_ptr z; -} -acb_dirichlet_dft_rad2_struct; - -typedef acb_dirichlet_dft_rad2_struct acb_dirichlet_dft_rad2_t[1]; - -typedef struct -{ - slong n; - acb_ptr z; - acb_dirichlet_dft_rad2_t rad2; -} -acb_dirichlet_dft_bluestein_struct; - -typedef acb_dirichlet_dft_bluestein_struct acb_dirichlet_dft_bluestein_t[1]; - -typedef struct -{ - slong n; - slong num; - acb_dirichlet_dft_step_ptr cyc; -} -acb_dirichlet_dft_prod_struct; - -typedef acb_dirichlet_dft_prod_struct acb_dirichlet_dft_prod_t[1]; - -typedef struct -{ - slong n; - crt_t c; - slong dv; - /* then a product */ - acb_dirichlet_dft_step_ptr cyc; -} -acb_dirichlet_dft_crt_struct; - -typedef acb_dirichlet_dft_crt_struct acb_dirichlet_dft_crt_t[1]; - -typedef struct -{ - slong n; - slong dv; - int zclear; - acb_ptr z; - slong dz; -} -acb_dirichlet_dft_pol_struct; - -typedef acb_dirichlet_dft_pol_struct acb_dirichlet_dft_pol_t[1]; - -typedef struct -{ - int type; - union - { - acb_dirichlet_dft_rad2_t rad2; - acb_dirichlet_dft_cyc_t cyc; - acb_dirichlet_dft_prod_t prod; - acb_dirichlet_dft_crt_t crt; - acb_dirichlet_dft_pol_t pol; - } t; -} -acb_dirichlet_dft_pre_struct; - -typedef acb_dirichlet_dft_pre_struct acb_dirichlet_dft_pre_t[1]; - -/* covers both product and cyclic case */ -struct -acb_dirichlet_dft_step_struct -{ - /* [G:H] */ - slong m; - /* card H */ - slong M; - slong dv; /* = M for prod, also = M if cyc is reordered */ - /* pointer on some roots of unity, if needed */ - acb_srcptr z; - /* index of mM in z */ - slong dz; - /* dft to call on H */ - acb_dirichlet_dft_pre_t pre; - /* dft to call on G/H ? */ -}; - -/*typedef acb_dirichlet_dft_pre_struct acb_dirichlet_dft_pre_t[1];*/ - -#define DFT_VERB 0 - -enum -{ - DFT_POL, DFT_CYC, DFT_PROD, DFT_CRT , DFT_RAD2 /*, DFT_CONV */ -}; - -void acb_dirichlet_dft_step(acb_ptr w, acb_srcptr v, acb_dirichlet_dft_step_ptr cyc, slong num, slong prec); - -void acb_dirichlet_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_pre_t pre, slong prec); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_pol_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_pol_t pol, slong prec) -{ - _acb_dirichlet_dft_pol(w, v, pol->dv, pol->z, pol->dz, pol->n, prec); -} -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_cyc_t cyc, slong prec) -{ - acb_dirichlet_dft_step(w, v, cyc->cyc, cyc->num, prec); -} -void acb_dirichlet_dft_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec); -void acb_dirichlet_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_crt_t crt, slong prec); -void acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dirichlet_dft_prod_t prod, slong prec); - -void acb_dirichlet_dft_inverse_rad2_precomp(acb_ptr v, const acb_dirichlet_dft_rad2_t rad2, slong prec); -void acb_dirichlet_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dirichlet_dft_rad2_t, slong prec); - -void _acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec); -void acb_dirichlet_dft_precomp_init(acb_dirichlet_dft_pre_t pre, slong len, slong prec); -void acb_dirichlet_dft_precomp_clear(acb_dirichlet_dft_pre_t pre); - -acb_dirichlet_dft_step_ptr _acb_dirichlet_dft_steps_prod(slong * m, slong num, slong prec); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_prod_init(acb_dirichlet_dft_prod_t t, slong * cyc, slong num, slong prec) -{ - t->num = num; - t->cyc = _acb_dirichlet_dft_steps_prod(cyc, num, prec); -} - -void acb_dirichlet_dft_prod_clear(acb_dirichlet_dft_prod_t t); - -void _acb_dirichlet_dft_cyc_init_z_fac(acb_dirichlet_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec); -void _acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong dv, slong len, slong prec); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_cyc_init(acb_dirichlet_dft_cyc_t t, slong len, slong prec) -{ - _acb_dirichlet_dft_cyc_init(t, 1, len, prec); -} - -void acb_dirichlet_dft_cyc_clear(acb_dirichlet_dft_cyc_t t); - -void _acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_pol_init(acb_dirichlet_dft_pol_t pol, slong len, slong prec) -{ - _acb_dirichlet_dft_pol_init(pol, 1, NULL, 0, len, prec); -} - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_pol_clear(acb_dirichlet_dft_pol_t pol) -{ - if (pol->zclear) - _acb_vec_clear(pol->z, pol->n); -} - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_rad2_init(acb_dirichlet_dft_rad2_t t, int e, slong prec) -{ - t->e = e; - t->n = 1 << e; - t->nz = t->n >> 1; - t->z = _acb_vec_init(t->nz); - /* set n/2 roots of order n */ - _acb_vec_nth_roots_pe(t->z, 2, e, t->nz, 1, prec); -} - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_rad2_clear(acb_dirichlet_dft_rad2_t t) -{ - _acb_vec_clear(t->z, t->nz); -} - -void acb_dirichlet_dft_bluestein_init(acb_dirichlet_dft_bluestein_t t, slong n, slong prec); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_bluestein_clear(acb_dirichlet_dft_bluestein_t t) -{ - _acb_vec_clear(t->z, t->n); - acb_dirichlet_dft_rad2_clear(t->rad2); -} - -void _acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong dv, slong len, slong prec); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_crt_init(acb_dirichlet_dft_crt_t crt, slong len, slong prec) -{ - crt->n = len; - crt_init(crt->c, len); - crt->dv = 1; - crt->cyc = _acb_dirichlet_dft_steps_prod(crt->c->m, crt->c->num, prec); -} - -ACB_DIRICHLET_INLINE void -acb_dirichlet_dft_crt_clear(acb_dirichlet_dft_crt_t crt) -{ - flint_free(crt->cyc); -} - -/* utils, could be moved elsewhere */ - -ACB_DIRICHLET_INLINE void -acb_swap_ri(acb_t x) -{ - arb_swap(acb_realref(x), acb_imagref(x)); -} - -ACB_DIRICHLET_INLINE void -acb_vec_swap_ri(acb_ptr v, slong len) -{ - slong k; - for (k = 0; k < len; k++) - acb_swap_ri(v + k); -} - -ACB_DIRICHLET_INLINE void -_acb_vec_kronecker_mul(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) -{ - slong k; - for (k = 0; k < len; k++) - acb_mul(z + k, x + k, y + k, prec); -} - -/* z[k] = conj(x[k])*y[k] */ -ACB_DIRICHLET_INLINE void -acb_vec_kronecker_mul_conj(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) -{ - slong k; - for (k = 0; k < len; k++) - { - acb_conj(z + k, x + k); - acb_mul(z + k, z + k, y + k, prec); - } -} +/* utils */ ACB_DIRICHLET_INLINE void acb_vec_printd(acb_srcptr vec, slong len, slong digits) @@ -587,14 +302,6 @@ acb_vec_printd(acb_srcptr vec, slong len, slong digits) acb_printd(vec + i, digits), flint_printf("\n"); } -ACB_DIRICHLET_INLINE void -acb_vec_printd_index(acb_srcptr vec, slong len, slong digits) -{ - slong i; - for (i = 0; i < len; i++) - flint_printf("[%ld] ",i), acb_printd(vec + i, digits), flint_printf("\n"); -} - #ifdef __cplusplus } #endif diff --git a/acb_dirichlet/dft.c b/acb_dirichlet/dft.c index 5a025374..945dc241 100644 --- a/acb_dirichlet/dft.c +++ b/acb_dirichlet/dft.c @@ -9,6 +9,7 @@ (at your option) any later version. See . */ +#include "acb_dft.h" #include "acb_dirichlet.h" /* dft, lexicographic conrey indexing, array size G->phi_q */ @@ -20,7 +21,7 @@ acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, for (k = 0, l = G->num - 1; l >= 0; k++, l--) cyc[k] = G->P[k].phi; - acb_dirichlet_dft_prod(w, v, cyc, G->num, prec); + acb_dft_prod(w, v, cyc, G->num, prec); flint_free(cyc); } diff --git a/acb_dirichlet/gauss_sum_naive.c b/acb_dirichlet/gauss_sum_naive.c index 47570590..7cea0ab7 100644 --- a/acb_dirichlet/gauss_sum_naive.c +++ b/acb_dirichlet/gauss_sum_naive.c @@ -22,7 +22,7 @@ acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const ac acb_dirichlet_chi_vec(v, G, chi, G->q, prec); acb_init(z); - acb_dirichlet_nth_root(z, G->q, prec); + acb_nth_root(z, G->q, prec); _acb_poly_evaluate(res, v, G->q, z, prec); diff --git a/acb_dirichlet/jacobi_sum_naive.c b/acb_dirichlet/jacobi_sum_naive.c index 8dc020ad..359a478e 100644 --- a/acb_dirichlet/jacobi_sum_naive.c +++ b/acb_dirichlet/jacobi_sum_naive.c @@ -52,7 +52,7 @@ acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const a } acb_init(z); - acb_dirichlet_nth_root(z, order.n, prec); + acb_nth_root(z, order.n, prec); acb_dirichlet_si_poly_evaluate(res, v, order.n, z, prec); acb_clear(z); diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index 049cbf00..ec15e7ff 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -48,7 +48,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, prec += n_clog(G->phi_q, 2); z = _acb_vec_init(chi->order.n); - acb_dirichlet_vec_nth_roots(z, chi->order.n, prec); + _acb_vec_nth_roots(z, chi->order.n, prec); do { chin = acb_dirichlet_ui_chi_conrey(G, chi, cn); diff --git a/acb_dirichlet/powers_init.c b/acb_dirichlet/powers_init.c index 6033397f..523ee866 100644 --- a/acb_dirichlet/powers_init.c +++ b/acb_dirichlet/powers_init.c @@ -18,7 +18,7 @@ _acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong size, sl slong k; t->order = order; acb_init(t->z); - acb_dirichlet_nth_root(t->z, order, prec); + acb_nth_root(t->z, order, prec); t->size = size; t->depth = depth; if (depth) diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 1e783277..64919659 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -26,9 +26,9 @@ check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong dig flint_printf("q = %wu, size = %wu\n", q, len); flint_printf("\nDFT differ from index %ld / %ld \n", i, len); flint_printf("\n%s =\n", f1); - acb_vec_printd_index(w1, len, digits); + acb_vec_printd(w1, len, digits); flint_printf("\n%s =\n", f2); - acb_vec_printd_index(w2, len, digits); + acb_vec_printd(w2, len, digits); flint_printf("\n\n"); abort(); } @@ -60,65 +60,11 @@ int main() ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; flint_rand_t state; - slong f, nf = 4; - do_f func[4] = { acb_dirichlet_dft_pol, acb_dirichlet_dft_cyc, acb_dirichlet_dft_crt , acb_dirichlet_dft_bluestein }; - char * name[4] = { "pol", "cyc", "crt", "bluestein" }; - flint_printf("dft...."); fflush(stdout); flint_randinit(state); - /* cyclic dft */ - for (k = 0; k < nq; k++) - { - slong i; - acb_ptr v, w1, w2; - - v = _acb_vec_init(q[k]); - w1 = _acb_vec_init(q[k]); - w2 = _acb_vec_init(q[k]); - - for (i = 0; i < q[k]; i++) - acb_set_si(v + i, i); - - for (f = 0; f < nf; f++) - { - - acb_ptr w = (f == 0) ? w1 : w2; - - func[f](w, v, q[k], prec); - - if (f == 0) - continue; - - check_vec_eq_prec(w1, w2, q[k], prec, digits, q[k], name[0], name[f]); - - } - - _acb_vec_clear(v, q[k]); - _acb_vec_clear(w1, q[k]); - _acb_vec_clear(w2, q[k]); - } - - /* radix2 dft */ - for (k = 1; k < 12; k++) - { - slong n = 1 << k, j; - acb_ptr v, w1, w2; - v = w2 = _acb_vec_init(n); - w1 = _acb_vec_init(n); - - for (j = 0; j < n; j++) - acb_set_si(v + k, k); - - acb_dirichlet_dft_pol(w1, v, n, prec); - acb_dirichlet_dft_rad2(v, k, prec); - - check_vec_eq_prec(w1, w2, n, prec, digits, n, "pol", "rad2"); - - } - /* Dirichlet group DFT */ for (k = 0; k < nq; k++) { @@ -177,4 +123,3 @@ int main() flint_printf("PASS\n"); return EXIT_SUCCESS; } - diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 56788afe..62ad8a1c 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -45,7 +45,7 @@ int main() acb_dirichlet_char_init(chi, G); z = _acb_vec_init(G->expo); - acb_dirichlet_vec_nth_roots(z, G->expo, prec); + _acb_vec_nth_roots(z, G->expo, prec); nv = acb_dirichlet_theta_length_d(q, 1, prec); v = flint_malloc(nv * sizeof(ulong)); diff --git a/doc/source/acb.rst b/doc/source/acb.rst index 51d61235..56ca0566 100644 --- a/doc/source/acb.rst +++ b/doc/source/acb.rst @@ -525,6 +525,10 @@ Powers and roots a small exact integer, as `z = (x^{1/2})^{2y}` if `y` is a small exact half-integer, and generally as `z = \exp(y \log x)`. +.. function:: void acb_nth_root(acb_t res, ulong order, slong prec) + + Sets *res* to `\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. + Exponentials and logarithms ------------------------------------------------------------------------------- @@ -924,6 +928,12 @@ Vector functions Sets *xs* to the powers `1, x, x^2, \ldots, x^{len-1}`. +.. function:: void _acb_vec_nth_roots(acb_ptr z, slong order, slong prec) + + Sets *z* to the powers `1,z,z^2,\dots z^{\mathrm{order}-1}` where `z=\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. + + In order to avoid precision loss, this function does not simply compute powers of a primitive root. + .. function:: void _acb_vec_add_error_arf_vec(acb_ptr res, arf_srcptr err, slong len) .. function:: void _acb_vec_add_error_mag_vec(acb_ptr res, mag_srcptr err, slong len) diff --git a/doc/source/acb_dft.rst b/doc/source/acb_dft.rst new file mode 100644 index 00000000..3f7ad27a --- /dev/null +++ b/doc/source/acb_dft.rst @@ -0,0 +1,110 @@ +.. _acb-dft: + +**acb_dft.h** -- Discrete Fourier Transform on finite abelian groups +=================================================================================== + +*Warning: the interfaces in this module are experimental and may change +without notice.* + +Let *G* be a finite abelian group, and `\chi` a character of *G*. +For any map `f:G\to\mathbb C`, the discrete fourier transform +`\hat f:\hat G\to \mathbb C` is defined by + +.. math:: + + \hat f(\chi) = \sum_{x\in G}\overline{\chi(x)}f(x) + + +Fast Fourier Transform techniques allow to compute efficiently +all values `\hat f(\chi)` by reusing common computations. + +Specifically, if `H\triangleleft G` is a subgroup of size `M` and index +`[G:H]=m`, then writing `f_x(h)=f(xh)` the translate of `f` by representatives +`x` of `G/H`, one has a decomposition + +.. math:: + + \hat f(\chi) = \sum_{x\in G/H} \overline{\chi(x)} \hat{f_x}(\chi_{H}) + +so that the DFT on `G` can be computed using `m` DFT on `H` (of +appropriate translates of `f`), then `M` DFT on `G/H`, one for +each restriction `\chi_{H}`. + +This decomposition can be done recursively. + +Note that by inversion formula + +.. math:: + + \widehat{\hat f}(\chi) = \#G\times f(\chi^{-1}) + +it is straightforward to recover `f` from its DFT `\hat f`. + +DFT on Z/nZ +------------------------------------------------------------------------------- + +If `G=\mathbb Z/n\mathbb Z`, we compute the DFT according to the usual convention + +.. math:: + + w_x = \sum_{y\bmod n} v_y e^{-\frac{2iπ}nxy} + +.. function:: void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong n, slong prec) + +.. function:: void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong n, slong prec) + +.. function:: void acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong n, slong prec) + + Set *w* to the DFT of *v* of length *len*. + + The first variant uses the naive `O(n^2)` algorithm. + + The second one uses CRT to express `Z/nZ` as a product of cyclic groups. + + The *cyc* version uses each prime factor of `m` of `n` to decompose with + the subgroup `H=m\mathbb Z/n\mathbb Z`. + + +DFT on products +------------------------------------------------------------------------------- + +A finite abelian group is isomorphic to a product of cyclic components + +.. math:: + + G = \bigoplus_{i=1}^r \mathbb Z/n_i\mathbb Z + +then a character is a product of characters of all components and the DFT reads + +.. math:: + + \hat f(x_1,\dots x_r) = \sum_{y_1\dots y_r} f(y_1,\dots y_r) + e^{-2iπ\sum\frac{x_i y_i}{n_i}} + +We assume that `f` is given by a vector of length `\prod n_i` corresponding +to a lexicographic ordering of the values `y_1,\dots y_r`, and the computation +returns the same indexing for values of `\hat f`. + +.. function:: void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); + + Computes the DFT on the group product of *num* cyclic components of sizes *cyc*. + +Precomputations +------------------------------------------------------------------------------- + +Convolution +------------------------------------------------------------------------------- + +For functions `f` and `g` on `G` we consider the convolution + +.. math:: + + (f \star g)(x) = \sum_{y\in G} f(x-y)g(y) + +which satisfies + +.. math:: + + \widehat{f \star g}(\chi) = \hat f(\chi)\hat g(\chi) + + diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index a5c520df..c7ed7354 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -327,16 +327,6 @@ unity. Roots of unity ------------------------------------------------------------------------------- -.. function:: void acb_dirichlet_nth_root(acb_t res, ulong order, slong prec) - - Sets *res* to `\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. - -.. function:: void acb_dirichlet_vec_nth_roots(acb_ptr z, slong order, slong prec) - - Compute the vector ``1,z,z^2,\dots z^{\mathrm{order}-1}`` where `z=\exp(\frac{2i\pi}{\mathrm{order}})` to precision *prec*. - - In order to avoid precision loss, this function does not simply compute powers of a primitive root. - .. type:: acb_dirichlet_powers_struct .. type:: acb_dirichlet_powers_t From 55450bb62cbac16e4323b9bf604ac71968c0da30 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 6 Oct 2016 14:19:39 +0200 Subject: [PATCH 132/139] separate dirichlet/acb_dirichlet --- Makefile.in | 2 +- acb_dirichlet.h | 243 ++---------------- acb_dirichlet/char_mul.c | 19 -- acb_dirichlet/chi.c | 6 +- acb_dirichlet/chi_vec.c | 6 +- acb_dirichlet/dft.c | 18 +- acb_dirichlet/gauss_sum.c | 28 +- acb_dirichlet/gauss_sum_factor.c | 16 +- acb_dirichlet/gauss_sum_naive.c | 2 +- acb_dirichlet/gauss_sum_order2.c | 2 +- acb_dirichlet/gauss_sum_theta.c | 2 +- acb_dirichlet/jacobi_sum.c | 26 +- acb_dirichlet/jacobi_sum_factor.c | 22 +- acb_dirichlet/jacobi_sum_gauss.c | 10 +- acb_dirichlet/jacobi_sum_naive.c | 14 +- acb_dirichlet/l_hurwitz.c | 14 +- acb_dirichlet/l_vec_hurwitz.c | 12 +- acb_dirichlet/pairing.c | 6 +- acb_dirichlet/pairing_conrey.c | 6 +- acb_dirichlet/qseries_arb_powers.c | 4 +- acb_dirichlet/root_number.c | 4 +- acb_dirichlet/test/t-chi.c | 28 +- acb_dirichlet/test/t-dft.c | 26 +- acb_dirichlet/test/t-gauss.c | 24 +- acb_dirichlet/test/t-jacobi.c | 26 +- acb_dirichlet/test/t-l.c | 38 +-- acb_dirichlet/test/t-thetanull.c | 26 +- acb_dirichlet/test/t-vec.c | 28 +- acb_dirichlet/theta_arb.c | 12 +- acb_dirichlet/ui_theta_arb.c | 10 +- acb_dirichlet/vec_mellin_arb.c | 2 +- dirichlet.h | 232 +++++++++++++++++ {acb_dirichlet => dirichlet}/char.c | 8 +- {acb_dirichlet => dirichlet}/char_clear.c | 6 +- {acb_dirichlet => dirichlet}/char_conrey.c | 14 +- {acb_dirichlet => dirichlet}/char_eq_deep.c | 10 +- .../char_first_primitive.c | 10 +- {acb_dirichlet => dirichlet}/char_init.c | 6 +- dirichlet/char_mul.c | 19 ++ {acb_dirichlet => dirichlet}/char_next.c | 8 +- .../char_next_primitive.c | 8 +- {acb_dirichlet => dirichlet}/char_normalize.c | 8 +- {acb_dirichlet => dirichlet}/char_one.c | 6 +- {acb_dirichlet => dirichlet}/char_primitive.c | 10 +- {acb_dirichlet => dirichlet}/char_print.c | 10 +- {acb_dirichlet => dirichlet}/conrey.c | 8 +- .../conrey_conductor.c | 4 +- {acb_dirichlet => dirichlet}/conrey_eq_deep.c | 4 +- {acb_dirichlet => dirichlet}/conrey_exp.c | 4 +- .../conrey_first_primitive.c | 6 +- {acb_dirichlet => dirichlet}/conrey_index.c | 6 +- {acb_dirichlet => dirichlet}/conrey_log.c | 6 +- {acb_dirichlet => dirichlet}/conrey_mul.c | 4 +- {acb_dirichlet => dirichlet}/conrey_next.c | 4 +- .../conrey_next_primitive.c | 4 +- {acb_dirichlet => dirichlet}/conrey_one.c | 4 +- {acb_dirichlet => dirichlet}/conrey_order.c | 4 +- {acb_dirichlet => dirichlet}/conrey_parity.c | 4 +- {acb_dirichlet => dirichlet}/conrey_pow.c | 4 +- .../conrey_primitive.c | 4 +- {acb_dirichlet => dirichlet}/conrey_print.c | 4 +- {acb_dirichlet => dirichlet}/group_clear.c | 4 +- .../group_dlog_precompute.c | 10 +- {acb_dirichlet => dirichlet}/group_init.c | 26 +- {acb_dirichlet => dirichlet}/index_conrey.c | 4 +- .../number_primitive.c | 4 +- .../profile/p-conrey.c | 78 +++--- {acb_dirichlet => dirichlet}/test/t-chars.c | 74 +++--- {acb_dirichlet => dirichlet}/test/t-conrey.c | 52 ++-- {acb_dirichlet => dirichlet}/ui_chi.c | 16 +- {acb_dirichlet => dirichlet}/ui_chi_conrey.c | 4 +- {acb_dirichlet => dirichlet}/ui_chi_vec.c | 8 +- .../ui_chi_vec_loop.c | 18 +- .../ui_chi_vec_primeloop.c | 10 +- {acb_dirichlet => dirichlet}/ui_conductor.c | 4 +- {acb_dirichlet => dirichlet}/ui_order.c | 4 +- {acb_dirichlet => dirichlet}/ui_pairing.c | 22 +- .../ui_pairing_conrey.c | 4 +- {acb_dirichlet => dirichlet}/ui_parity.c | 4 +- .../ui_vec_set_null.c | 6 +- 80 files changed, 749 insertions(+), 714 deletions(-) delete mode 100644 acb_dirichlet/char_mul.c create mode 100644 dirichlet.h rename {acb_dirichlet => dirichlet}/char.c (65%) rename {acb_dirichlet => dirichlet}/char_clear.c (77%) rename {acb_dirichlet => dirichlet}/char_conrey.c (62%) rename {acb_dirichlet => dirichlet}/char_eq_deep.c (69%) rename {acb_dirichlet => dirichlet}/char_first_primitive.c (59%) rename {acb_dirichlet => dirichlet}/char_init.c (80%) create mode 100644 dirichlet/char_mul.c rename {acb_dirichlet => dirichlet}/char_next.c (69%) rename {acb_dirichlet => dirichlet}/char_next_primitive.c (67%) rename {acb_dirichlet => dirichlet}/char_normalize.c (75%) rename {acb_dirichlet => dirichlet}/char_one.c (78%) rename {acb_dirichlet => dirichlet}/char_primitive.c (61%) rename {acb_dirichlet => dirichlet}/char_print.c (71%) rename {acb_dirichlet => dirichlet}/conrey.c (69%) rename {acb_dirichlet => dirichlet}/conrey_conductor.c (88%) rename {acb_dirichlet => dirichlet}/conrey_eq_deep.c (78%) rename {acb_dirichlet => dirichlet}/conrey_exp.c (83%) rename {acb_dirichlet => dirichlet}/conrey_first_primitive.c (74%) rename {acb_dirichlet => dirichlet}/conrey_index.c (88%) rename {acb_dirichlet => dirichlet}/conrey_log.c (87%) rename {acb_dirichlet => dirichlet}/conrey_mul.c (75%) rename {acb_dirichlet => dirichlet}/conrey_next.c (86%) rename {acb_dirichlet => dirichlet}/conrey_next_primitive.c (92%) rename {acb_dirichlet => dirichlet}/conrey_one.c (81%) rename {acb_dirichlet => dirichlet}/conrey_order.c (81%) rename {acb_dirichlet => dirichlet}/conrey_parity.c (83%) rename {acb_dirichlet => dirichlet}/conrey_pow.c (77%) rename {acb_dirichlet => dirichlet}/conrey_primitive.c (85%) rename {acb_dirichlet => dirichlet}/conrey_print.c (83%) rename {acb_dirichlet => dirichlet}/group_clear.c (86%) rename {acb_dirichlet => dirichlet}/group_dlog_precompute.c (74%) rename {acb_dirichlet => dirichlet}/group_init.c (84%) rename {acb_dirichlet => dirichlet}/index_conrey.c (91%) rename {acb_dirichlet => dirichlet}/number_primitive.c (89%) rename {acb_dirichlet => dirichlet}/profile/p-conrey.c (70%) rename {acb_dirichlet => dirichlet}/test/t-chars.c (64%) rename {acb_dirichlet => dirichlet}/test/t-conrey.c (74%) rename {acb_dirichlet => dirichlet}/ui_chi.c (56%) rename {acb_dirichlet => dirichlet}/ui_chi_conrey.c (79%) rename {acb_dirichlet => dirichlet}/ui_chi_vec.c (62%) rename {acb_dirichlet => dirichlet}/ui_chi_vec_loop.c (66%) rename {acb_dirichlet => dirichlet}/ui_chi_vec_primeloop.c (81%) rename {acb_dirichlet => dirichlet}/ui_conductor.c (91%) rename {acb_dirichlet => dirichlet}/ui_order.c (91%) rename {acb_dirichlet => dirichlet}/ui_pairing.c (51%) rename {acb_dirichlet => dirichlet}/ui_pairing_conrey.c (81%) rename {acb_dirichlet => dirichlet}/ui_parity.c (85%) rename {acb_dirichlet => dirichlet}/ui_vec_set_null.c (80%) diff --git a/Makefile.in b/Makefile.in index 7a0398cc..ad6ef5cc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13,7 +13,7 @@ QUIET_AR = @echo ' ' AR ' ' $@; AT=@ BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \ - acb_calc acb_hypgeom acb_modular acb_dft acb_dirichlet arb_hypgeom bernoulli hypgeom \ + acb_calc acb_hypgeom acb_modular dirichlet acb_dft acb_dirichlet arb_hypgeom bernoulli hypgeom \ fmpz_extras bool_mat partitions dlog \ $(EXTRA_BUILD_DIRS) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index cd825720..8785a1ab 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -21,7 +21,7 @@ #endif #include "acb.h" -#include "dlog.h" +#include "dirichlet.h" #ifdef __cplusplus extern "C" { @@ -32,205 +32,8 @@ void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); -/* should this dlog pointer be in the prime or the global group? */ -typedef struct -{ - ulong p; /* underlying prime */ - int e; /* exponent */ - nmod_t pe; /* modulus */ - ulong phi; /* phi(p^e) */ - ulong g; /* conrey generator */ - dlog_precomp_struct * dlog; /* precomputed data for discrete log mod p^e */ -} -acb_dirichlet_prime_group_struct; - -typedef struct -{ - ulong q; /* modulus */ - ulong q_even; /* even part of modulus */ - nmod_t mod; /* modulus with precomputed inverse */ - ulong rad_q; /* radical = product of odd primes */ - ulong phi_q; /* phi(q) = group size */ - slong neven; /* number of even components (in 0,1,2)*/ - slong num; /* number of prime components (even + odd) */ - ulong expo; /* exponent = largest order in G */ - acb_dirichlet_prime_group_struct * P; - ulong * generators; /* generators lifted mod q */ - ulong * PHI; /* PHI(k) = expo / phi(k) */ -} -acb_dirichlet_group_struct; - -typedef acb_dirichlet_group_struct acb_dirichlet_group_t[1]; - -ACB_DIRICHLET_INLINE ulong -acb_dirichlet_group_size(const acb_dirichlet_group_t G) -{ - return G->phi_q; -} - -void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); -void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h); -void acb_dirichlet_group_clear(acb_dirichlet_group_t G); -void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num); -void acb_dirichlet_group_dlog_clear(acb_dirichlet_group_t G); - -/* properties of elements without log */ - -ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G); -ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a); -int acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a); -ulong acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a); - -/* elements of the group, keep both number and log */ -typedef struct -{ - ulong n; /* number */ - ulong * log; /* s.t. prod generators[k]^log[k] = number */ -} -acb_dirichlet_conrey_struct; - -typedef acb_dirichlet_conrey_struct acb_dirichlet_conrey_t[1]; - -void acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); -void acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x); -void acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_conrey_set(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t y) -{ - slong k; - x->n = y->n; - for (k = 0; k < G->num; k++) - x->log[k] = y->log[k]; -} - -ACB_DIRICHLET_INLINE int -acb_dirichlet_conrey_eq(const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) -{ - return (x->n == y->n); -} - -int acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y); -int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); -ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); -ulong acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); - -void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m); -ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); - -void acb_dirichlet_conrey_index(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong j); -ulong acb_dirichlet_index_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); - -void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); -void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); - -int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); -int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G); - -void acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); -void acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n); -void acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, ulong cond); - -#define ACB_DIRICHLET_CHI_NULL UWORD_MAX - -ulong acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b); -ulong acb_dirichlet_ui_pairing(const acb_dirichlet_group_t G, ulong m, ulong n); - -void acb_dirichlet_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec); -void acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec); - -/* introducing character type */ - -/* character = reduced exponents, keep order, number and conductor */ -typedef struct -{ - ulong q; /* modulus */ - nmod_t order; /* order */ - acb_dirichlet_conrey_t x; - ulong * expo; /* reduced exponents ( log[k] * PHI[k] / gcd( ) ) */ - int parity; /* 0 for even char, 1 for odd */ - ulong conductor; -} -acb_dirichlet_char_struct; - -typedef acb_dirichlet_char_struct acb_dirichlet_char_t[1]; - -ACB_DIRICHLET_INLINE ulong -acb_dirichlet_char_order(const acb_dirichlet_char_t chi) -{ - return chi->order.n; -} - -ACB_DIRICHLET_INLINE ulong -acb_dirichlet_char_conductor(const acb_dirichlet_char_t chi) -{ - return chi->conductor; -} - -ACB_DIRICHLET_INLINE int -acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) -{ - return chi->parity; -} - -void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -void acb_dirichlet_char_clear(acb_dirichlet_char_t chi); -void acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); - -ACB_DIRICHLET_INLINE void -acb_dirichlet_char_set(acb_dirichlet_char_t chi1, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi2) -{ - slong k; - - chi1->q = chi2->q; - chi1->conductor = chi2->conductor; - chi1->order = chi2->order; - chi1->parity = chi2->parity; - acb_dirichlet_conrey_set(chi1->x, G, chi2->x); - for (k = 0; k < G->num; k++) - chi1->expo[k] = chi2->expo[k]; -} - -ACB_DIRICHLET_INLINE int -acb_dirichlet_char_eq(const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) -{ - return (chi1->q == chi2->q && chi1->x->n == chi2->x->n); -} - -int acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); -ACB_DIRICHLET_INLINE int -acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) -{ - return (chi->x->n == 1); -} -ACB_DIRICHLET_INLINE int -acb_dirichlet_char_is_real(const acb_dirichlet_char_t chi) -{ - return (chi->order.n <= 2); -} - -void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n); -void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); -void acb_dirichlet_char_set_expo(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -void acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -void acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); - -void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2); -void acb_dirichlet_char_primitive(acb_dirichlet_char_t chi0, const acb_dirichlet_group_t G0, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi); - -void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -void acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); - -int acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); -int acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G); - -ulong acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const acb_dirichlet_conrey_t x); -ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n); - -void acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv); -void acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); -void acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv); +void acb_dirichlet_pairing_conrey(acb_t res, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b, slong prec); +void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec); /* precompute powers of a root of unity */ typedef struct @@ -250,8 +53,8 @@ void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t); void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec); -void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec); -void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec); +void acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec); +void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec); void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec); void acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec); @@ -263,34 +66,34 @@ ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec); void mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n); void _acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slong prec); -void acb_dirichlet_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec); -void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec); +void acb_dirichlet_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec); +void acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec); -void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); -void acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); -void acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec); -void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); -void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); -void acb_dirichlet_root_number_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); -void acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); +void acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); +void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec); -void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); +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 jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond); -void acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); -void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); -void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec); -void acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec); +void acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); +void acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); +void acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec); +void acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec); -void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec); -void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec); +void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); +void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const dirichlet_group_t G, slong prec); /* Discrete Fourier Transform */ -void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); -void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec); +void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec); +void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec); /* utils */ diff --git a/acb_dirichlet/char_mul.c b/acb_dirichlet/char_mul.c deleted file mode 100644 index c05c1cc1..00000000 --- a/acb_dirichlet/char_mul.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" - -void -acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) -{ - acb_dirichlet_conrey_mul(chi12->x, G, chi1->x, chi2->x); - acb_dirichlet_char_conrey(chi12, G, NULL); -} diff --git a/acb_dirichlet/chi.c b/acb_dirichlet/chi.c index 56943bd5..e8b1d6b2 100644 --- a/acb_dirichlet/chi.c +++ b/acb_dirichlet/chi.c @@ -14,11 +14,11 @@ #include "acb_dirichlet.h" void -acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) +acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec) { ulong expo; - expo = acb_dirichlet_ui_chi(G, chi, n); - if (expo == ACB_DIRICHLET_CHI_NULL) + expo = dirichlet_ui_chi(G, chi, n); + if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else { diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/chi_vec.c index ccf12f89..f5f45b18 100644 --- a/acb_dirichlet/chi_vec.c +++ b/acb_dirichlet/chi_vec.c @@ -12,21 +12,21 @@ #include "acb_dirichlet.h" void -acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec) +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; acb_dirichlet_powers_t t; a = flint_malloc(nv * sizeof(ulong)); - acb_dirichlet_ui_chi_vec(a, G, chi, nv); + dirichlet_ui_chi_vec(a, G, chi, nv); acb_dirichlet_powers_init(t, chi->order.n, nv, prec); acb_zero(v + 0); for (k = 0; k < nv; k++) { - if (a[k] != ACB_DIRICHLET_CHI_NULL) + if (a[k] != DIRICHLET_CHI_NULL) acb_dirichlet_power(v + k, t, a[k], prec); else acb_zero(v + k); diff --git a/acb_dirichlet/dft.c b/acb_dirichlet/dft.c index 945dc241..6537b010 100644 --- a/acb_dirichlet/dft.c +++ b/acb_dirichlet/dft.c @@ -14,7 +14,7 @@ /* dft, lexicographic conrey indexing, array size G->phi_q */ void -acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) +acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) { slong k, l, * cyc; cyc = flint_malloc(G->num * sizeof(slong)); @@ -27,34 +27,34 @@ acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, /* dft, number indexing, array size G->q */ void -acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) +acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) { ulong i, len; acb_ptr t1, t2; - acb_dirichlet_conrey_t x; + dirichlet_conrey_t x; len = G->phi_q; t1 = flint_malloc(len * sizeof(acb_struct)); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_init(x, G); + dirichlet_conrey_one(x, G); for (i = 0; i < len; i++) { t1[i] = v[x->n]; - acb_dirichlet_conrey_next(x, G); + dirichlet_conrey_next(x, G); }; t2 = _acb_vec_init(len); acb_dirichlet_dft_conrey(t2, t1, G, prec); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); for (i = 0; i < len; i++) { acb_set(w + x->n, t2 + i); - acb_dirichlet_conrey_next(x, G); + dirichlet_conrey_next(x, G); }; _acb_vec_clear(t2, len); - acb_dirichlet_conrey_clear(x); + dirichlet_conrey_clear(x); flint_free(t1); } diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index e2a70dc7..3b8447ff 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" static void -gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { slong k, mu = 1; @@ -52,13 +52,13 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri else { - acb_dirichlet_group_t G0; - acb_dirichlet_char_t chi0; + dirichlet_group_t G0; + dirichlet_char_t chi0; acb_t z; - acb_dirichlet_subgroup_init(G0, G, chi->conductor); - acb_dirichlet_char_init(chi0, G); - acb_dirichlet_char_primitive(chi0, G0, G, chi); + dirichlet_subgroup_init(G0, G, chi->conductor); + dirichlet_char_init(chi0, G); + dirichlet_char_primitive(chi0, G0, G, chi); acb_init(z); acb_dirichlet_gauss_sum(z, G0, chi0, prec); @@ -68,14 +68,14 @@ gauss_sum_non_primitive(acb_t res, const acb_dirichlet_group_t G, const acb_diri acb_mul(res, res, z, prec); acb_mul_si(res, res, mu, prec); - acb_dirichlet_group_clear(G0); - acb_dirichlet_char_clear(chi0); + dirichlet_group_clear(G0); + dirichlet_char_clear(chi0); acb_clear(z); } } void -acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { /* TODO: no need, factor also does it... */ if (chi->conductor != G->q) @@ -100,11 +100,11 @@ acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_diri } void -acb_dirichlet_gauss_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, slong prec) +acb_dirichlet_gauss_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, slong prec) { - acb_dirichlet_char_t chi; - acb_dirichlet_char_init(chi, G); - acb_dirichlet_char(chi, G, a); + dirichlet_char_t chi; + dirichlet_char_init(chi, G); + dirichlet_char(chi, G, a); acb_dirichlet_gauss_sum(res, G, chi, prec); - acb_dirichlet_char_clear(chi); + dirichlet_char_clear(chi); } diff --git a/acb_dirichlet/gauss_sum_factor.c b/acb_dirichlet/gauss_sum_factor.c index b00002b5..29fa0a32 100644 --- a/acb_dirichlet/gauss_sum_factor.c +++ b/acb_dirichlet/gauss_sum_factor.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { slong k; @@ -36,11 +36,11 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const a for (k = (G->neven == 2); k < G->num; k++) { ulong pe = G->P[k].pe.n; - acb_dirichlet_group_t Gp; - acb_dirichlet_char_t chip; + dirichlet_group_t Gp; + dirichlet_char_t chip; - acb_dirichlet_subgroup_init(Gp, G, pe); - acb_dirichlet_char_init(chip, Gp); + dirichlet_subgroup_init(Gp, G, pe); + dirichlet_char_init(chip, Gp); chip->x->n = chi->x->n % pe; @@ -52,7 +52,7 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const a else chip->x->log[0] = chi->x->log[k]; - acb_dirichlet_char_conrey(chip, Gp, NULL); + dirichlet_char_conrey(chip, Gp, NULL); /* chi_pe(a, q/pe) * G_pe(a) */ acb_dirichlet_gauss_sum(tmp, Gp, chip, prec); @@ -61,8 +61,8 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const a acb_dirichlet_chi(tmp, Gp, chip, (G->q / pe) % pe, prec); acb_mul(res, res, tmp, prec); - acb_dirichlet_char_clear(chip); - acb_dirichlet_group_clear(Gp); + dirichlet_char_clear(chip); + dirichlet_group_clear(Gp); } if (G->q_even == 2) diff --git a/acb_dirichlet/gauss_sum_naive.c b/acb_dirichlet/gauss_sum_naive.c index 7cea0ab7..89d477cf 100644 --- a/acb_dirichlet/gauss_sum_naive.c +++ b/acb_dirichlet/gauss_sum_naive.c @@ -13,7 +13,7 @@ #include "acb_poly.h" void -acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { acb_t z; acb_ptr v; diff --git a/acb_dirichlet/gauss_sum_order2.c b/acb_dirichlet/gauss_sum_order2.c index 50b7b114..39fed38b 100644 --- a/acb_dirichlet/gauss_sum_order2.c +++ b/acb_dirichlet/gauss_sum_order2.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_char_t chi, slong prec) { if (chi->parity) { diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index d46945c9..ab97f384 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { if (chi->conductor < G->q || (G->q == 300 && (chi->x->n == 71 || chi->x->n == 131)) || (G->q == 600 && (chi->x->n == 11 || chi->x->n == 491))) diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index d37ef326..ab67d3c4 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -30,7 +30,7 @@ jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond) } static ulong -jacobi_one(const acb_dirichlet_group_t G, ulong cond) +jacobi_one(const dirichlet_group_t G, ulong cond) { slong k, r = 1; @@ -41,7 +41,7 @@ jacobi_one(const acb_dirichlet_group_t G, ulong cond) } void -acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { if (G->q_even > 1) { @@ -75,7 +75,7 @@ acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dir } void -acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec) +acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec) { if (G->q_even > 1) { @@ -83,27 +83,27 @@ acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, u } else if (a == 1 || b == 1) { - ulong cond = (a == 1) ? acb_dirichlet_ui_conductor(G, b) : acb_dirichlet_ui_conductor(G, a); + ulong cond = (a == 1) ? dirichlet_ui_conductor(G, b) : dirichlet_ui_conductor(G, a); acb_set_si(res, jacobi_one(G, cond)); } else if (nmod_mul(a, b, G->mod) == 1) { ulong n; - n = jacobi_one(G, acb_dirichlet_ui_conductor(G, a)); - if (acb_dirichlet_ui_parity(G, a)) + n = jacobi_one(G, dirichlet_ui_conductor(G, a)); + if (dirichlet_ui_parity(G, a)) acb_set_si(res, -n); else acb_set_si(res, n); } else { - acb_dirichlet_char_t chi1, chi2; - acb_dirichlet_char_init(chi1, G); - acb_dirichlet_char_init(chi2, G); - acb_dirichlet_char(chi1, G, a); - acb_dirichlet_char(chi2, G, b); + dirichlet_char_t chi1, chi2; + dirichlet_char_init(chi1, G); + dirichlet_char_init(chi2, G); + dirichlet_char(chi1, G, a); + dirichlet_char(chi2, G, b); acb_dirichlet_jacobi_sum(res, G, chi1, chi2, prec); - acb_dirichlet_char_clear(chi1); - acb_dirichlet_char_clear(chi2); + dirichlet_char_clear(chi1); + dirichlet_char_clear(chi2); } } diff --git a/acb_dirichlet/jacobi_sum_factor.c b/acb_dirichlet/jacobi_sum_factor.c index 37934aed..ddecf60a 100644 --- a/acb_dirichlet/jacobi_sum_factor.c +++ b/acb_dirichlet/jacobi_sum_factor.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { slong k; acb_t tmp; @@ -47,20 +47,20 @@ acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const } else { - acb_dirichlet_group_t Gp; - acb_dirichlet_char_t chi1p, chi2p; + dirichlet_group_t Gp; + dirichlet_char_t chi1p, chi2p; - acb_dirichlet_group_init(Gp, pe.n); - acb_dirichlet_char_init(chi1p, Gp); - acb_dirichlet_char_init(chi2p, Gp); + dirichlet_group_init(Gp, pe.n); + dirichlet_char_init(chi1p, Gp); + dirichlet_char_init(chi2p, Gp); chi1p->x->n = ap; chi1p->x->log[0] = chi1->x->log[k]; chi2p->x->n = ap; chi2p->x->log[0] = chi2->x->log[k]; - acb_dirichlet_char_conrey(chi1p, Gp, NULL); - acb_dirichlet_char_conrey(chi2p, Gp, NULL); + dirichlet_char_conrey(chi1p, Gp, NULL); + dirichlet_char_conrey(chi2p, Gp, NULL); /* TODO: work out gauss relations for e > 1 */ if (p <= 100 || e > 1) @@ -70,9 +70,9 @@ acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_mul(res, res, tmp, prec); - acb_dirichlet_char_clear(chi1p); - acb_dirichlet_char_clear(chi2p); - acb_dirichlet_group_clear(Gp); + dirichlet_char_clear(chi1p); + dirichlet_char_clear(chi2p); + dirichlet_group_clear(Gp); } } acb_clear(tmp); diff --git a/acb_dirichlet/jacobi_sum_gauss.c b/acb_dirichlet/jacobi_sum_gauss.c index 9ff6ac86..5d825ec6 100644 --- a/acb_dirichlet/jacobi_sum_gauss.c +++ b/acb_dirichlet/jacobi_sum_gauss.c @@ -13,14 +13,14 @@ /* should use only for prime power modulus */ void -acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { /* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */ acb_t tmp; - acb_dirichlet_char_t chi12; + dirichlet_char_t chi12; - acb_dirichlet_char_init(chi12, G); - acb_dirichlet_char_mul(chi12, G, chi1, chi2); + dirichlet_char_init(chi12, G); + dirichlet_char_mul(chi12, G, chi1, chi2); acb_init(tmp); @@ -33,6 +33,6 @@ acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const a acb_dirichlet_gauss_sum(tmp, G, chi12, prec); acb_div(res, res, tmp, prec); - acb_dirichlet_char_clear(chi12); + dirichlet_char_clear(chi12); acb_clear(tmp); } diff --git a/acb_dirichlet/jacobi_sum_naive.c b/acb_dirichlet/jacobi_sum_naive.c index 359a478e..5541e6f6 100644 --- a/acb_dirichlet/jacobi_sum_naive.c +++ b/acb_dirichlet/jacobi_sum_naive.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +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; @@ -24,11 +24,11 @@ acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const a v1 = flint_malloc(G->q * sizeof(ulong)); v2 = flint_malloc(G->q * sizeof(ulong)); - acb_dirichlet_ui_vec_set_null(v1, G, G->q); - acb_dirichlet_ui_chi_vec_loop(v1, G, chi1, G->q); + dirichlet_ui_vec_set_null(v1, G, G->q); + dirichlet_ui_chi_vec_loop(v1, G, chi1, G->q); - acb_dirichlet_ui_vec_set_null(v2, G, G->q); - acb_dirichlet_ui_chi_vec_loop(v2, G, chi2, G->q); + dirichlet_ui_vec_set_null(v2, G, G->q); + dirichlet_ui_chi_vec_loop(v2, G, chi2, G->q); m1 = chi1->order.n; m2 = chi2->order.n; @@ -44,8 +44,8 @@ acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const a for (k1 = 2, k2 = G->q - 1; k2 > 1; k1++, k2--) { - if (v1[k1] == ACB_DIRICHLET_CHI_NULL || - v2[k2] == ACB_DIRICHLET_CHI_NULL) + if (v1[k1] == DIRICHLET_CHI_NULL || + v2[k2] == DIRICHLET_CHI_NULL) continue; e = nmod_add(v1[k1] * m1, v2[k2] * m2, order); v[e]++; diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index ec15e7ff..f219e6e8 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -16,12 +16,12 @@ /* todo: should document or fix that it doesn't allow aliasing */ void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, - const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { ulong chin; acb_t t, u, a; acb_ptr z; - acb_dirichlet_conrey_t cn; + dirichlet_conrey_t cn; int deflate; /* remove pole in Hurwitz zeta at s = 1 */ @@ -37,12 +37,12 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, deflate = 1; } - acb_dirichlet_conrey_init(cn, G); + dirichlet_conrey_init(cn, G); acb_init(t); acb_init(u); acb_init(a); - acb_dirichlet_conrey_one(cn, G); + dirichlet_conrey_one(cn, G); acb_zero(t); prec += n_clog(G->phi_q, 2); @@ -51,7 +51,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, _acb_vec_nth_roots(z, chi->order.n, prec); do { - chin = acb_dirichlet_ui_chi_conrey(G, chi, cn); + chin = dirichlet_ui_chi_conrey(G, chi, cn); acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); @@ -63,14 +63,14 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_addmul(t, z + chin, u, prec); - } while (acb_dirichlet_conrey_next(cn, G) >= 0); + } while (dirichlet_conrey_next(cn, G) >= 0); acb_set_ui(u, G->q); acb_neg(a, s); acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); - acb_dirichlet_conrey_clear(cn); + dirichlet_conrey_clear(cn); _acb_vec_clear(z, chi->order.n); acb_clear(t); diff --git a/acb_dirichlet/l_vec_hurwitz.c b/acb_dirichlet/l_vec_hurwitz.c index e280cf78..7bcabd99 100644 --- a/acb_dirichlet/l_vec_hurwitz.c +++ b/acb_dirichlet/l_vec_hurwitz.c @@ -14,17 +14,17 @@ void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, - const acb_dirichlet_group_t G, slong prec) + const dirichlet_group_t G, slong prec) { acb_t a, qs; acb_ptr zeta, z; - acb_dirichlet_conrey_t cn; + dirichlet_conrey_t cn; int deflate; /* remove pole in Hurwitz zeta at s = 1 */ deflate = acb_is_one(s); - acb_dirichlet_conrey_init(cn, G); + dirichlet_conrey_init(cn, G); acb_init(qs); acb_init(a); @@ -35,7 +35,7 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, acb_pow(qs, qs, a, prec); zeta = z = _acb_vec_init(G->phi_q); - acb_dirichlet_conrey_one(cn, G); + dirichlet_conrey_one(cn, G); do { acb_set_ui(a, cn->n); @@ -49,7 +49,7 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, acb_mul(z, z, qs, prec); z++; - } while (acb_dirichlet_conrey_next(cn, G) >= 0); + } while (dirichlet_conrey_next(cn, G) >= 0); acb_dirichlet_dft_conrey(res, zeta, G, prec); @@ -57,7 +57,7 @@ acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, if (deflate) acb_indeterminate(res); - acb_dirichlet_conrey_clear(cn); + dirichlet_conrey_clear(cn); _acb_vec_clear(zeta, G->phi_q); acb_clear(qs); acb_clear(a); diff --git a/acb_dirichlet/pairing.c b/acb_dirichlet/pairing.c index 832b047f..c05cbeb1 100644 --- a/acb_dirichlet/pairing.c +++ b/acb_dirichlet/pairing.c @@ -12,11 +12,11 @@ #include "acb_dirichlet.h" void -acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) +acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec) { ulong expo; - expo = acb_dirichlet_ui_pairing(G, m, n); - if (expo == ACB_DIRICHLET_CHI_NULL) + expo = dirichlet_ui_pairing(G, m, n); + if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else { diff --git a/acb_dirichlet/pairing_conrey.c b/acb_dirichlet/pairing_conrey.c index e59e5464..18d8aa54 100644 --- a/acb_dirichlet/pairing_conrey.c +++ b/acb_dirichlet/pairing_conrey.c @@ -12,11 +12,11 @@ #include "acb_dirichlet.h" void -acb_dirichlet_pairing_conrey(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b, slong prec) +acb_dirichlet_pairing_conrey(acb_t res, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b, slong prec) { ulong expo; - expo = acb_dirichlet_ui_pairing_conrey(G, a, b); - if (expo == ACB_DIRICHLET_CHI_NULL) + expo = dirichlet_ui_pairing_conrey(G, a, b); + if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else { diff --git a/acb_dirichlet/qseries_arb_powers.c b/acb_dirichlet/qseries_arb_powers.c index e3d021b6..fc6deba3 100644 --- a/acb_dirichlet/qseries_arb_powers.c +++ b/acb_dirichlet/qseries_arb_powers.c @@ -34,7 +34,7 @@ acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, con { arb_mul(dx, dx, x2, prec); arb_mul(xk2, xk2, dx, prec); - if (a[k] != ACB_DIRICHLET_CHI_NULL) + if (a[k] != DIRICHLET_CHI_NULL) { acb_dirichlet_power(zk, z, a[k], prec); if (parity) @@ -76,7 +76,7 @@ acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int parity { arb_mul(dx, dx, x2, prec); arb_mul(xk2, xk2, dx, prec); - if (a[k] != ACB_DIRICHLET_CHI_NULL) + if (a[k] != DIRICHLET_CHI_NULL) { if (parity) { diff --git a/acb_dirichlet/root_number.c b/acb_dirichlet/root_number.c index 36eb42c6..33324182 100644 --- a/acb_dirichlet/root_number.c +++ b/acb_dirichlet/root_number.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_root_number_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { arb_t x; acb_t eps; @@ -29,7 +29,7 @@ acb_dirichlet_root_number_theta(acb_t res, const acb_dirichlet_group_t G, const } void -acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { if (chi->conductor < G->q) { diff --git a/acb_dirichlet/test/t-chi.c b/acb_dirichlet/test/t-chi.c index f42099a6..e12eb7c0 100644 --- a/acb_dirichlet/test/t-chi.c +++ b/acb_dirichlet/test/t-chi.c @@ -23,15 +23,15 @@ int main() for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) { acb_t zn1, zn2, zn1n2, zn1zn2; - acb_dirichlet_group_t G; - acb_dirichlet_char_t chi; + dirichlet_group_t G; + dirichlet_char_t chi; ulong q, m, n1, n2, iter2; int res; q = 1 + n_randint(state, 1000); - acb_dirichlet_group_init(G, q); - acb_dirichlet_char_init(chi, G); + dirichlet_group_init(G, q); + dirichlet_char_init(chi, G); acb_init(zn1); acb_init(zn2); acb_init(zn1n2); @@ -44,7 +44,7 @@ int main() m = 1 + n_randint(state, q); } while (n_gcd(q, m) != 1); - acb_dirichlet_char(chi, G, m); + dirichlet_char(chi, G, m); n1 = n_randint(state, 1000); n2 = n_randint(state, 1000); @@ -53,19 +53,19 @@ int main() acb_dirichlet_pairing(zn2, G, m, n1, 53); if (!acb_overlaps(zn1, zn2)) { - acb_dirichlet_conrey_t x; + dirichlet_conrey_t x; 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"); - acb_dirichlet_char_print(G, chi); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_log(x, G, m); - flint_printf("log(m) = "); acb_dirichlet_conrey_print(G, x); - acb_dirichlet_conrey_log(x, G, n1); - flint_printf("log(n1) = "); acb_dirichlet_conrey_print(G, x); + dirichlet_char_print(G, chi); + dirichlet_conrey_init(x, G); + dirichlet_conrey_log(x, G, m); + flint_printf("log(m) = "); dirichlet_conrey_print(G, x); + dirichlet_conrey_log(x, G, n1); + flint_printf("log(n1) = "); dirichlet_conrey_print(G, x); abort(); } @@ -119,8 +119,8 @@ int main() } } - acb_dirichlet_group_clear(G); - acb_dirichlet_char_clear(chi); + dirichlet_group_clear(G); + dirichlet_char_clear(chi); acb_clear(zn1); acb_clear(zn2); acb_clear(zn1n2); diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c index 64919659..679ddfc0 100644 --- a/acb_dirichlet/test/t-dft.c +++ b/acb_dirichlet/test/t-dft.c @@ -69,42 +69,42 @@ int main() for (k = 0; k < nq; k++) { slong i, j, len; - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x, y; + dirichlet_group_t G; + dirichlet_conrey_t x, y; acb_t chiy; acb_ptr v, w1, w2; - acb_dirichlet_group_init(G, q[k]); + dirichlet_group_init(G, q[k]); len = G->phi_q; v = _acb_vec_init(len); w1 = _acb_vec_init(len); w2 = _acb_vec_init(len); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_init(x, G); + dirichlet_conrey_one(x, G); for (i = 0; i < len; i++) acb_randtest_precise(v + i, state, prec, 0); /* naive */ acb_init(chiy); - acb_dirichlet_conrey_init(y, G); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_init(y, G); + dirichlet_conrey_one(x, G); for (i = 0; i < len; i++) { acb_zero(w1 + i); - acb_dirichlet_conrey_one(y, G); + dirichlet_conrey_one(y, G); for (j = 0; j < len; j++) { acb_dirichlet_pairing_conrey(chiy, G, x, y, prec); acb_addmul(w1 + i, chiy, v + j, prec); - acb_dirichlet_conrey_next(y, G); + dirichlet_conrey_next(y, G); } - acb_dirichlet_conrey_next(x, G); + dirichlet_conrey_next(x, G); } acb_clear(chiy); - acb_dirichlet_conrey_clear(y); - acb_dirichlet_conrey_clear(x); + dirichlet_conrey_clear(y); + dirichlet_conrey_clear(x); /* dft */ acb_dirichlet_dft_conrey(w2, v, G, prec); @@ -115,7 +115,7 @@ int main() _acb_vec_clear(w1, len); _acb_vec_clear(w2, len); - acb_dirichlet_group_clear(G); + dirichlet_group_clear(G); } flint_randclear(state); diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index c5c8927c..6b2afdfd 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -23,25 +23,25 @@ int main() for (q = 3; q < 250; q ++) { - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; - acb_dirichlet_char_t chi; + dirichlet_group_t G; + dirichlet_conrey_t x; + dirichlet_char_t chi; acb_t s1, s2, s3, s4; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_char_init(chi, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); + dirichlet_char_init(chi, G); acb_init(s1); acb_init(s2); acb_init(s3); acb_init(s4); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); while (1) { - acb_dirichlet_char_conrey(chi, G, x); + dirichlet_char_conrey(chi, G, x); acb_dirichlet_gauss_sum_naive(s1, G, chi, prec); acb_dirichlet_gauss_sum(s2, G, chi, prec); @@ -67,7 +67,7 @@ int main() abort(); } - if (acb_dirichlet_conrey_next(x, G) < 0) + if (dirichlet_conrey_next(x, G) < 0) break; } acb_clear(s1); @@ -75,9 +75,9 @@ int main() acb_clear(s3); acb_clear(s4); - acb_dirichlet_group_clear(G); - acb_dirichlet_char_clear(chi); - acb_dirichlet_conrey_clear(x); + dirichlet_group_clear(G); + dirichlet_char_clear(chi); + dirichlet_conrey_clear(x); } flint_cleanup(); diff --git a/acb_dirichlet/test/t-jacobi.c b/acb_dirichlet/test/t-jacobi.c index 59edb173..e7dfa520 100644 --- a/acb_dirichlet/test/t-jacobi.c +++ b/acb_dirichlet/test/t-jacobi.c @@ -24,24 +24,24 @@ int main() for (q = 29 * 29; q > 1; q = q%2 ? 3*q+1 : q/2) { slong m1, m2; - acb_dirichlet_group_t G; - acb_dirichlet_char_t chi1, chi2; + dirichlet_group_t G; + dirichlet_char_t chi1, chi2; acb_t s1, s2; - acb_dirichlet_group_init(G, q); - acb_dirichlet_char_init(chi1, G); - acb_dirichlet_char_init(chi2, G); + dirichlet_group_init(G, q); + dirichlet_char_init(chi1, G); + dirichlet_char_init(chi2, G); acb_init(s1); acb_init(s2); - acb_dirichlet_char_one(chi1, G); + dirichlet_char_one(chi1, G); for (m1 = 0; m1 < 50; m1++) { - acb_dirichlet_char_one(chi2, G); + dirichlet_char_one(chi2, G); for (m2 = 0; m2 < 50; m2++) { @@ -60,25 +60,25 @@ int main() flint_printf("\n"); flint_printf("cond = %wu, %wu, %wu\n", chi1->conductor, chi2->conductor, - acb_dirichlet_ui_conductor(G, nmod_mul(chi1->x->n, chi2->x->n, G->mod)) + dirichlet_ui_conductor(G, nmod_mul(chi1->x->n, chi2->x->n, G->mod)) ); abort(); } - if (acb_dirichlet_char_next(chi2, G) < 0) + if (dirichlet_char_next(chi2, G) < 0) break; } - if (acb_dirichlet_char_next(chi1, G) < 0) + if (dirichlet_char_next(chi1, G) < 0) break; } acb_clear(s1); acb_clear(s2); - acb_dirichlet_group_clear(G); - acb_dirichlet_char_clear(chi1); - acb_dirichlet_char_clear(chi2); + dirichlet_group_clear(G); + dirichlet_char_clear(chi1); + dirichlet_char_clear(chi2); } flint_cleanup(); diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index 6724a27c..395bbac4 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -19,15 +19,15 @@ test_dft(ulong q) { ulong i; slong prec = 100; - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; - acb_dirichlet_char_t chi; + dirichlet_group_t G; + dirichlet_conrey_t x; + dirichlet_char_t chi; acb_t s, z; acb_ptr v; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_char_init(chi, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); + dirichlet_char_init(chi, G); acb_init(s); acb_one(s); @@ -42,10 +42,10 @@ test_dft(ulong q) i = 0; acb_init(z); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); do { - acb_dirichlet_char_conrey(chi, G, x); + dirichlet_char_conrey(chi, G, x); acb_dirichlet_l_hurwitz(z, s, G, chi, prec); if (!acb_overlaps(z, v + i)) @@ -76,13 +76,13 @@ test_dft(ulong q) } i++; - } while (acb_dirichlet_conrey_next(x, G) >= 0); + } while (dirichlet_conrey_next(x, G) >= 0); acb_clear(s); _acb_vec_clear(v, G->phi_q); - acb_dirichlet_char_clear(chi); - acb_dirichlet_conrey_clear(x); - acb_dirichlet_group_clear(G); + dirichlet_char_clear(chi); + dirichlet_conrey_clear(x); + dirichlet_group_clear(G); } int main() @@ -164,13 +164,13 @@ int main() for (i = 0; i < nq; i++) { - acb_dirichlet_group_t G; - acb_dirichlet_char_t chi; + dirichlet_group_t G; + dirichlet_char_t chi; - acb_dirichlet_group_init(G, q[i]); - acb_dirichlet_char_init(chi, G); + dirichlet_group_init(G, q[i]); + dirichlet_char_init(chi, G); - acb_dirichlet_char(chi, G, m[i]); + dirichlet_char(chi, G, m[i]); for (j = 0; j < nx; j++) { @@ -201,8 +201,8 @@ int main() } } - acb_dirichlet_char_clear(chi); - acb_dirichlet_group_clear(G); + dirichlet_char_clear(chi); + dirichlet_group_clear(G); /* test using dft */ test_dft(q[i]); diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index 62ad8a1c..f40ac1e2 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -27,8 +27,8 @@ int main() for (q = 3; q < 1000; q ++) { - acb_dirichlet_group_t G; - acb_dirichlet_char_t chi; + dirichlet_group_t G; + dirichlet_char_t chi; ulong * v, nv, k; acb_t sum; @@ -41,8 +41,8 @@ int main() /* no primitive character mod q */ continue; - acb_dirichlet_group_init(G, q); - acb_dirichlet_char_init(chi, G); + dirichlet_group_init(G, q); + dirichlet_char_init(chi, G); z = _acb_vec_init(G->expo); _acb_vec_nth_roots(z, G->expo, prec); @@ -65,19 +65,19 @@ int main() /* theta function on primitive characters */ acb_init(sum); - acb_dirichlet_char_first_primitive(chi, G); + dirichlet_char_first_primitive(chi, G); do { ulong m; acb_zero(sum); - acb_dirichlet_ui_chi_vec(v, G, chi, nv); + dirichlet_ui_chi_vec(v, G, chi, nv); m = G->expo / chi->order.n; - tt = acb_dirichlet_char_parity(chi) ? kt : t; + tt = dirichlet_char_parity(chi) ? kt : t; for (k = 1; k < nv; k++) - if (v[k] != ACB_DIRICHLET_CHI_NULL) + if (v[k] != DIRICHLET_CHI_NULL) acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); if ((q == 300 && (chi->x->n == 71 || chi->x->n == 131)) @@ -88,7 +88,7 @@ int main() flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); acb_printd(sum, 10); flint_printf("\n"); - acb_dirichlet_char_print(G, chi); + dirichlet_char_print(G, chi); flint_printf("\n"); abort(); } @@ -98,12 +98,12 @@ int main() flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); acb_printd(sum, 10); flint_printf("\n"); - acb_dirichlet_char_print(G, chi); + dirichlet_char_print(G, chi); flint_printf("\n"); abort(); } - } while (acb_dirichlet_char_next_primitive(chi, G) >= 0); + } while (dirichlet_char_next_primitive(chi, G) >= 0); _acb_vec_clear(z, G->expo); _arb_vec_clear(kt, nv); @@ -111,8 +111,8 @@ int main() acb_clear(sum); arb_clear(eq); flint_free(v); - acb_dirichlet_group_clear(G); - acb_dirichlet_char_clear(chi); + dirichlet_group_clear(G); + dirichlet_char_clear(chi); } flint_cleanup(); diff --git a/acb_dirichlet/test/t-vec.c b/acb_dirichlet/test/t-vec.c index 23f3ba56..d3cea907 100644 --- a/acb_dirichlet/test/t-vec.c +++ b/acb_dirichlet/test/t-vec.c @@ -30,27 +30,27 @@ int main() for (q = 2; q < 600; q ++) { - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; - acb_dirichlet_char_t chi; + dirichlet_group_t G; + dirichlet_conrey_t x; + dirichlet_char_t chi; ulong * v1, * v2, nv, k; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_char_init(chi, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); + dirichlet_char_init(chi, G); nv = 100; v1 = flint_malloc(nv * sizeof(ulong)); v2 = flint_malloc(nv * sizeof(ulong)); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); do { - acb_dirichlet_char_conrey(chi, G, x); + dirichlet_char_conrey(chi, G, x); - acb_dirichlet_ui_chi_vec_loop(v1, G, chi, nv); - acb_dirichlet_ui_chi_vec_primeloop(v2, G, chi, nv); + dirichlet_ui_chi_vec_loop(v1, G, chi, nv); + dirichlet_ui_chi_vec_primeloop(v2, G, chi, nv); if ((k = vec_diff(v1, v2, nv))) { @@ -59,13 +59,13 @@ int main() abort(); } - } while (acb_dirichlet_conrey_next(x, G) >= 0); + } while (dirichlet_conrey_next(x, G) >= 0); flint_free(v1); flint_free(v2); - acb_dirichlet_group_clear(G); - acb_dirichlet_char_clear(chi); - acb_dirichlet_conrey_clear(x); + dirichlet_group_clear(G); + dirichlet_char_clear(chi); + dirichlet_conrey_clear(x); } flint_cleanup(); diff --git a/acb_dirichlet/theta_arb.c b/acb_dirichlet/theta_arb.c index fa2d4e7a..f6a643e4 100644 --- a/acb_dirichlet/theta_arb.c +++ b/acb_dirichlet/theta_arb.c @@ -13,13 +13,13 @@ #include "acb_poly.h" void -_acb_dirichlet_theta_arb_smallorder(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +_acb_dirichlet_theta_arb_smallorder(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec) { ulong * a; acb_dirichlet_powers_t z; a = flint_malloc(len * sizeof(ulong)); - acb_dirichlet_ui_chi_vec(a, G, chi, len); + dirichlet_ui_chi_vec(a, G, chi, len); _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); acb_dirichlet_qseries_arb_powers_smallorder(res, xt, chi->parity, a, z, len, prec); @@ -29,7 +29,7 @@ _acb_dirichlet_theta_arb_smallorder(acb_t res, const acb_dirichlet_group_t G, co } void -_acb_dirichlet_theta_arb_series(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +_acb_dirichlet_theta_arb_series(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec) { acb_ptr a; a = _acb_vec_init(len); @@ -45,13 +45,13 @@ _acb_dirichlet_theta_arb_series(acb_t res, const acb_dirichlet_group_t G, const } void -_acb_dirichlet_theta_arb_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t xt, slong len, slong prec) +_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 * a; acb_dirichlet_powers_t z; a = flint_malloc(len * sizeof(ulong)); - acb_dirichlet_ui_chi_vec(a, G, chi, len); + dirichlet_ui_chi_vec(a, G, chi, len); acb_dirichlet_powers_init(z, chi->order.n, len, prec); @@ -62,7 +62,7 @@ _acb_dirichlet_theta_arb_naive(acb_t res, const acb_dirichlet_group_t G, const a } void -acb_dirichlet_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) +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; arb_t xt; diff --git a/acb_dirichlet/ui_theta_arb.c b/acb_dirichlet/ui_theta_arb.c index 5679d695..f98d2e42 100644 --- a/acb_dirichlet/ui_theta_arb.c +++ b/acb_dirichlet/ui_theta_arb.c @@ -12,14 +12,14 @@ #include "acb_dirichlet.h" void -acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec) +acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec) { - acb_dirichlet_char_t chi; + dirichlet_char_t chi; - acb_dirichlet_char_init(chi, G); - acb_dirichlet_char(chi, G, a); + dirichlet_char_init(chi, G); + dirichlet_char(chi, G, a); acb_dirichlet_theta_arb(res, G, chi, t, prec); - acb_dirichlet_char_clear(chi); + dirichlet_char_clear(chi); } diff --git a/acb_dirichlet/vec_mellin_arb.c b/acb_dirichlet/vec_mellin_arb.c index 15308e16..45c5ad43 100644 --- a/acb_dirichlet/vec_mellin_arb.c +++ b/acb_dirichlet/vec_mellin_arb.c @@ -12,7 +12,7 @@ #include "acb_dirichlet.h" void -acb_dirichlet_vec_mellin_arb(acb_ptr res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong len, const arb_t t, slong n, slong prec) +acb_dirichlet_vec_mellin_arb(acb_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, const arb_t t, slong n, slong prec) { slong k; arb_t tk, xt, stk, st; diff --git a/dirichlet.h b/dirichlet.h new file mode 100644 index 00000000..62b6229a --- /dev/null +++ b/dirichlet.h @@ -0,0 +1,232 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef DIRICHLET_H +#define DIRICHLET_H + +#ifdef DIRICHLET_INLINES_C +#define DIRICHLET_INLINE +#else +#define DIRICHLET_INLINE static __inline__ +#endif + +#include "acb.h" +#include "dlog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* should this dlog pointer be in the prime or the global group? */ +typedef struct +{ + ulong p; /* underlying prime */ + int e; /* exponent */ + nmod_t pe; /* modulus */ + ulong phi; /* phi(p^e) */ + ulong g; /* conrey generator */ + dlog_precomp_struct * dlog; /* precomputed data for discrete log mod p^e */ +} +dirichlet_prime_group_struct; + +typedef struct +{ + ulong q; /* modulus */ + ulong q_even; /* even part of modulus */ + nmod_t mod; /* modulus with precomputed inverse */ + ulong rad_q; /* radical = product of odd primes */ + ulong phi_q; /* phi(q) = group size */ + slong neven; /* number of even components (in 0,1,2)*/ + slong num; /* number of prime components (even + odd) */ + ulong expo; /* exponent = largest order in G */ + dirichlet_prime_group_struct * P; + ulong * generators; /* generators lifted mod q */ + ulong * PHI; /* PHI(k) = expo / phi(k) */ +} +dirichlet_group_struct; + +typedef dirichlet_group_struct dirichlet_group_t[1]; + +DIRICHLET_INLINE ulong +dirichlet_group_size(const dirichlet_group_t G) +{ + return G->phi_q; +} + +void dirichlet_group_init(dirichlet_group_t G, ulong q); +void dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h); +void dirichlet_group_clear(dirichlet_group_t G); +void dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num); +void dirichlet_group_dlog_clear(dirichlet_group_t G); + +/* properties of elements without log */ + +ulong dirichlet_number_primitive(const dirichlet_group_t G); +ulong dirichlet_ui_conductor(const dirichlet_group_t G, ulong a); +int dirichlet_ui_parity(const dirichlet_group_t G, ulong a); +ulong dirichlet_ui_order(const dirichlet_group_t G, ulong a); + +/* elements of the group, keep both number and log */ +typedef struct +{ + ulong n; /* number */ + ulong * log; /* s.t. prod generators[k]^log[k] = number */ +} +dirichlet_conrey_struct; + +typedef dirichlet_conrey_struct dirichlet_conrey_t[1]; + +void dirichlet_conrey_init(dirichlet_conrey_t x, const dirichlet_group_t G); +void dirichlet_conrey_clear(dirichlet_conrey_t x); +void dirichlet_conrey_print(const dirichlet_group_t G, const dirichlet_conrey_t x); + +DIRICHLET_INLINE void +dirichlet_conrey_set(dirichlet_conrey_t x, const dirichlet_group_t G, const dirichlet_conrey_t y) +{ + slong k; + x->n = y->n; + for (k = 0; k < G->num; k++) + x->log[k] = y->log[k]; +} + +DIRICHLET_INLINE int +dirichlet_conrey_eq(const dirichlet_conrey_t x, const dirichlet_conrey_t y) +{ + return (x->n == y->n); +} + +int dirichlet_conrey_eq_deep(const dirichlet_group_t G, const dirichlet_conrey_t x, const dirichlet_conrey_t y); +int dirichlet_conrey_parity(const dirichlet_group_t G, const dirichlet_conrey_t x); +ulong dirichlet_conrey_conductor(const dirichlet_group_t G, const dirichlet_conrey_t x); +ulong dirichlet_conrey_order(const dirichlet_group_t G, const dirichlet_conrey_t x); + +void dirichlet_conrey_log(dirichlet_conrey_t x, const dirichlet_group_t G, ulong m); +ulong dirichlet_conrey_exp(dirichlet_conrey_t x, const dirichlet_group_t G); + +void dirichlet_conrey_index(dirichlet_conrey_t x, const dirichlet_group_t G, ulong j); +ulong dirichlet_index_conrey(const dirichlet_group_t G, const dirichlet_conrey_t x); + +void dirichlet_conrey_one(dirichlet_conrey_t x, const dirichlet_group_t G); +void dirichlet_conrey_first_primitive(dirichlet_conrey_t x, const dirichlet_group_t G); + +int dirichlet_conrey_next(dirichlet_conrey_t x, const dirichlet_group_t G); +int dirichlet_conrey_next_primitive(dirichlet_conrey_t x, const dirichlet_group_t G); + +void dirichlet_conrey_mul(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b); +void dirichlet_conrey_pow(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, ulong n); +void dirichlet_conrey_primitive(dirichlet_conrey_t y, const dirichlet_group_t G, const dirichlet_conrey_t x, ulong cond); + +#define DIRICHLET_CHI_NULL UWORD_MAX + +ulong dirichlet_ui_pairing_conrey(const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b); +ulong dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n); + +void dirichlet_pairing_conrey(acb_t res, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b, slong prec); +void dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec); + +/* introducing character type */ + +/* character = reduced exponents, keep order, number and conductor */ +typedef struct +{ + ulong q; /* modulus */ + nmod_t order; /* order */ + dirichlet_conrey_t x; + ulong * expo; /* reduced exponents ( log[k] * PHI[k] / gcd( ) ) */ + int parity; /* 0 for even char, 1 for odd */ + ulong conductor; +} +dirichlet_char_struct; + +typedef dirichlet_char_struct dirichlet_char_t[1]; + +DIRICHLET_INLINE ulong +dirichlet_char_order(const dirichlet_char_t chi) +{ + return chi->order.n; +} + +DIRICHLET_INLINE ulong +dirichlet_char_conductor(const dirichlet_char_t chi) +{ + return chi->conductor; +} + +DIRICHLET_INLINE int +dirichlet_char_parity(const dirichlet_char_t chi) +{ + return chi->parity; +} + +void dirichlet_char_init(dirichlet_char_t chi, const dirichlet_group_t G); +void dirichlet_char_clear(dirichlet_char_t chi); +void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t chi); + +DIRICHLET_INLINE void +dirichlet_char_set(dirichlet_char_t chi1, const dirichlet_group_t G, const dirichlet_char_t chi2) +{ + slong k; + + chi1->q = chi2->q; + chi1->conductor = chi2->conductor; + chi1->order = chi2->order; + chi1->parity = chi2->parity; + dirichlet_conrey_set(chi1->x, G, chi2->x); + for (k = 0; k < G->num; k++) + chi1->expo[k] = chi2->expo[k]; +} + +DIRICHLET_INLINE int +dirichlet_char_eq(const dirichlet_char_t chi1, const dirichlet_char_t chi2) +{ + return (chi1->q == chi2->q && chi1->x->n == chi2->x->n); +} + +int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2); +DIRICHLET_INLINE int +dirichlet_char_is_principal(const dirichlet_char_t chi) +{ + return (chi->x->n == 1); +} +DIRICHLET_INLINE int +dirichlet_char_is_real(const dirichlet_char_t chi) +{ + return (chi->order.n <= 2); +} + +void dirichlet_char(dirichlet_char_t chi, const dirichlet_group_t G, ulong n); +void dirichlet_char_conrey(dirichlet_char_t chi, const dirichlet_group_t G, const dirichlet_conrey_t x); +void dirichlet_char_set_expo(dirichlet_char_t chi, const dirichlet_group_t G); +void dirichlet_char_normalize(dirichlet_char_t chi, const dirichlet_group_t G); +void dirichlet_char_denormalize(dirichlet_char_t chi, const dirichlet_group_t G); + +void dirichlet_char_mul(dirichlet_char_t chi12, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2); +void dirichlet_char_primitive(dirichlet_char_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_char_t chi); + +void dirichlet_char_one(dirichlet_char_t chi, const dirichlet_group_t G); +void dirichlet_char_first_primitive(dirichlet_char_t chi, const dirichlet_group_t G); + +int dirichlet_char_next(dirichlet_char_t chi, const dirichlet_group_t G); +int dirichlet_char_next_primitive(dirichlet_char_t chi, const dirichlet_group_t G); + +ulong dirichlet_ui_chi_conrey(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_conrey_t x); +ulong dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n); + +void dirichlet_ui_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv); +void dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); +void dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); +void dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/acb_dirichlet/char.c b/dirichlet/char.c similarity index 65% rename from acb_dirichlet/char.c rename to dirichlet/char.c index cd3bff08..1cc00012 100644 --- a/acb_dirichlet/char.c +++ b/dirichlet/char.c @@ -9,11 +9,11 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) +dirichlet_char(dirichlet_char_t chi, const dirichlet_group_t G, ulong n) { - acb_dirichlet_conrey_log(chi->x, G, n); - acb_dirichlet_char_conrey(chi, G, NULL); + dirichlet_conrey_log(chi->x, G, n); + dirichlet_char_conrey(chi, G, NULL); } diff --git a/acb_dirichlet/char_clear.c b/dirichlet/char_clear.c similarity index 77% rename from acb_dirichlet/char_clear.c rename to dirichlet/char_clear.c index 57e4e948..f5e28e26 100644 --- a/acb_dirichlet/char_clear.c +++ b/dirichlet/char_clear.c @@ -9,11 +9,11 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char_clear(acb_dirichlet_char_t chi) +dirichlet_char_clear(dirichlet_char_t chi) { - acb_dirichlet_conrey_clear(chi->x); + dirichlet_conrey_clear(chi->x); flint_free(chi->expo); } diff --git a/acb_dirichlet/char_conrey.c b/dirichlet/char_conrey.c similarity index 62% rename from acb_dirichlet/char_conrey.c rename to dirichlet/char_conrey.c index 673c436a..44dd304d 100644 --- a/acb_dirichlet/char_conrey.c +++ b/dirichlet/char_conrey.c @@ -9,24 +9,24 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" /* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd * so that log = expo[k] */ void -acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +dirichlet_char_conrey(dirichlet_char_t chi, const dirichlet_group_t G, const dirichlet_conrey_t x) { /* assume chi->x already set if x == NULL */ if (x == NULL) x = chi->x; else - acb_dirichlet_conrey_set(chi->x, G, x); + dirichlet_conrey_set(chi->x, G, x); chi->q = G->q; - chi->parity = acb_dirichlet_conrey_parity(G, x); - chi->conductor = acb_dirichlet_conrey_conductor(G, x); + chi->parity = dirichlet_conrey_parity(G, x); + chi->conductor = dirichlet_conrey_conductor(G, x); - acb_dirichlet_char_set_expo(chi, G); + dirichlet_char_set_expo(chi, G); /* optional: divide by gcd to obtain true order */ - acb_dirichlet_char_normalize(chi, G); + dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_eq_deep.c b/dirichlet/char_eq_deep.c similarity index 69% rename from acb_dirichlet/char_eq_deep.c rename to dirichlet/char_eq_deep.c index ff0ad0fc..2d02a69e 100644 --- a/acb_dirichlet/char_eq_deep.c +++ b/dirichlet/char_eq_deep.c @@ -9,12 +9,12 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) +dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) { - acb_dirichlet_conrey_t x, y; + dirichlet_conrey_t x, y; if (chi1->q != chi2->q) return 0; @@ -25,13 +25,13 @@ acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_ch if (chi1->conductor != chi2->conductor) return 0; - if (!acb_dirichlet_conrey_eq_deep(G, chi1->x, chi2->x)) + if (!dirichlet_conrey_eq_deep(G, chi1->x, chi2->x)) return 0; x->n = y->n = 1; x->log = chi1->expo; y->log = chi2->expo; - if (!acb_dirichlet_conrey_eq_deep(G, x, y)) + if (!dirichlet_conrey_eq_deep(G, x, y)) return 0; return 1; diff --git a/acb_dirichlet/char_first_primitive.c b/dirichlet/char_first_primitive.c similarity index 59% rename from acb_dirichlet/char_first_primitive.c rename to dirichlet/char_first_primitive.c index 6e31d30f..8bddcd24 100644 --- a/acb_dirichlet/char_first_primitive.c +++ b/dirichlet/char_first_primitive.c @@ -9,12 +9,12 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char_first_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_first_primitive(dirichlet_char_t chi, const dirichlet_group_t G) { - acb_dirichlet_conrey_first_primitive(chi->x, G); - acb_dirichlet_char_conrey(chi, G, NULL); - acb_dirichlet_char_normalize(chi, G); + dirichlet_conrey_first_primitive(chi->x, G); + dirichlet_char_conrey(chi, G, NULL); + dirichlet_char_normalize(chi, G); } diff --git a/acb_dirichlet/char_init.c b/dirichlet/char_init.c similarity index 80% rename from acb_dirichlet/char_init.c rename to dirichlet/char_init.c index dc90a2bc..cbef6829 100644 --- a/acb_dirichlet/char_init.c +++ b/dirichlet/char_init.c @@ -9,13 +9,13 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_init(dirichlet_char_t chi, const dirichlet_group_t G) { slong k; - acb_dirichlet_conrey_init(chi->x, G); + dirichlet_conrey_init(chi->x, G); chi->expo = flint_malloc(G->num * sizeof(ulong)); chi->q = G->q; chi->conductor = 1; diff --git a/dirichlet/char_mul.c b/dirichlet/char_mul.c new file mode 100644 index 00000000..e4b596cd --- /dev/null +++ b/dirichlet/char_mul.c @@ -0,0 +1,19 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dirichlet.h" + +void +dirichlet_char_mul(dirichlet_char_t chi12, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) +{ + dirichlet_conrey_mul(chi12->x, G, chi1->x, chi2->x); + dirichlet_char_conrey(chi12, G, NULL); +} diff --git a/acb_dirichlet/char_next.c b/dirichlet/char_next.c similarity index 69% rename from acb_dirichlet/char_next.c rename to dirichlet/char_next.c index 0ae26024..315d8525 100644 --- a/acb_dirichlet/char_next.c +++ b/dirichlet/char_next.c @@ -9,14 +9,14 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_next(dirichlet_char_t chi, const dirichlet_group_t G) { int k; - k = acb_dirichlet_conrey_next(chi->x, G); - acb_dirichlet_char_conrey(chi, G, NULL); + k = dirichlet_conrey_next(chi->x, G); + dirichlet_char_conrey(chi, G, NULL); /* return last index modified */ return k; } diff --git a/acb_dirichlet/char_next_primitive.c b/dirichlet/char_next_primitive.c similarity index 67% rename from acb_dirichlet/char_next_primitive.c rename to dirichlet/char_next_primitive.c index 363cd4d7..abfcc364 100644 --- a/acb_dirichlet/char_next_primitive.c +++ b/dirichlet/char_next_primitive.c @@ -9,14 +9,14 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_next_primitive(dirichlet_char_t chi, const dirichlet_group_t G) { int k; - k = acb_dirichlet_conrey_next_primitive(chi->x, G); - acb_dirichlet_char_conrey(chi, G, NULL); + k = dirichlet_conrey_next_primitive(chi->x, G); + dirichlet_char_conrey(chi, G, NULL); /* return last index modified */ return k; } diff --git a/acb_dirichlet/char_normalize.c b/dirichlet/char_normalize.c similarity index 75% rename from acb_dirichlet/char_normalize.c rename to dirichlet/char_normalize.c index 7d280d43..9905a105 100644 --- a/acb_dirichlet/char_normalize.c +++ b/dirichlet/char_normalize.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char_set_expo(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_set_expo(dirichlet_char_t chi, const dirichlet_group_t G) { slong k; for (k = 0; k < G->num; k++) @@ -21,7 +21,7 @@ acb_dirichlet_char_set_expo(acb_dirichlet_char_t chi, const acb_dirichlet_group_ } void -acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_normalize(dirichlet_char_t chi, const dirichlet_group_t G) { ulong k, g; g = G->expo; @@ -36,7 +36,7 @@ acb_dirichlet_char_normalize(acb_dirichlet_char_t chi, const acb_dirichlet_group } void -acb_dirichlet_char_denormalize(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_denormalize(dirichlet_char_t chi, const dirichlet_group_t G) { ulong k, g; g = G->expo / chi->order.n; diff --git a/acb_dirichlet/char_one.c b/dirichlet/char_one.c similarity index 78% rename from acb_dirichlet/char_one.c rename to dirichlet/char_one.c index 57a88e45..a133e7c3 100644 --- a/acb_dirichlet/char_one.c +++ b/dirichlet/char_one.c @@ -9,13 +9,13 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) +dirichlet_char_one(dirichlet_char_t chi, const dirichlet_group_t G) { slong k; - acb_dirichlet_conrey_one(chi->x, G); + dirichlet_conrey_one(chi->x, G); chi->q = G->q; chi->conductor = 1; chi->parity = 0; diff --git a/acb_dirichlet/char_primitive.c b/dirichlet/char_primitive.c similarity index 61% rename from acb_dirichlet/char_primitive.c rename to dirichlet/char_primitive.c index 8fd374bd..3172a593 100644 --- a/acb_dirichlet/char_primitive.c +++ b/dirichlet/char_primitive.c @@ -9,16 +9,16 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char_primitive(acb_dirichlet_char_t chi0, const acb_dirichlet_group_t G0, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +dirichlet_char_primitive(dirichlet_char_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_char_t chi) { chi0->q = chi->conductor; chi0->parity = chi->parity; chi0->conductor = chi->conductor; - acb_dirichlet_conrey_primitive(chi0->x, G, chi->x, chi->conductor); - acb_dirichlet_char_set_expo(chi0, G0); + dirichlet_conrey_primitive(chi0->x, G, chi->x, chi->conductor); + dirichlet_char_set_expo(chi0, G0); /* optional: divide by gcd to obtain true order */ - acb_dirichlet_char_normalize(chi0, G0); + dirichlet_char_normalize(chi0, G0); } diff --git a/acb_dirichlet/char_print.c b/dirichlet/char_print.c similarity index 71% rename from acb_dirichlet/char_print.c rename to dirichlet/char_print.c index a33e33d0..62031b0b 100644 --- a/acb_dirichlet/char_print.c +++ b/dirichlet/char_print.c @@ -9,15 +9,15 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_char_print(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi) +dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t chi) { - acb_dirichlet_conrey_t x; + dirichlet_conrey_t x; flint_printf("chi_%wu(%wu,.) of order %wu, parity %wd, index ", G->q, chi->x->n, chi->order, chi->parity); - acb_dirichlet_conrey_print(G, chi->x); + dirichlet_conrey_print(G, chi->x); flint_printf(" and exponents "); x->log = chi->expo; - acb_dirichlet_conrey_print(G, x); + dirichlet_conrey_print(G, x); } diff --git a/acb_dirichlet/conrey.c b/dirichlet/conrey.c similarity index 69% rename from acb_dirichlet/conrey.c rename to dirichlet/conrey.c index 3fe26f6c..8c76683f 100644 --- a/acb_dirichlet/conrey.c +++ b/dirichlet/conrey.c @@ -9,15 +9,15 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_init(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) { +dirichlet_conrey_init(dirichlet_conrey_t x, const dirichlet_group_t G) { x->log = flint_malloc(G->num * sizeof(ulong)); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); } void -acb_dirichlet_conrey_clear(acb_dirichlet_conrey_t x) { +dirichlet_conrey_clear(dirichlet_conrey_t x) { flint_free(x->log); } diff --git a/acb_dirichlet/conrey_conductor.c b/dirichlet/conrey_conductor.c similarity index 88% rename from acb_dirichlet/conrey_conductor.c rename to dirichlet/conrey_conductor.c index 78cb5e0e..f346432e 100644 --- a/acb_dirichlet/conrey_conductor.c +++ b/dirichlet/conrey_conductor.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +dirichlet_conrey_conductor(const dirichlet_group_t G, const dirichlet_conrey_t x) { int k, f; ulong cond = 1; diff --git a/acb_dirichlet/conrey_eq_deep.c b/dirichlet/conrey_eq_deep.c similarity index 78% rename from acb_dirichlet/conrey_eq_deep.c rename to dirichlet/conrey_eq_deep.c index 122f3c62..08950ca3 100644 --- a/acb_dirichlet/conrey_eq_deep.c +++ b/dirichlet/conrey_eq_deep.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) +dirichlet_conrey_eq_deep(const dirichlet_group_t G, const dirichlet_conrey_t x, const dirichlet_conrey_t y) { slong k; diff --git a/acb_dirichlet/conrey_exp.c b/dirichlet/conrey_exp.c similarity index 83% rename from acb_dirichlet/conrey_exp.c rename to dirichlet/conrey_exp.c index 2ba76deb..12498a36 100644 --- a/acb_dirichlet/conrey_exp.c +++ b/dirichlet/conrey_exp.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +dirichlet_conrey_exp(dirichlet_conrey_t x, const dirichlet_group_t G) { ulong k, n = 1; for (k = 0; k < G->num; k++) diff --git a/acb_dirichlet/conrey_first_primitive.c b/dirichlet/conrey_first_primitive.c similarity index 74% rename from acb_dirichlet/conrey_first_primitive.c rename to dirichlet/conrey_first_primitive.c index d1472439..1415e764 100644 --- a/acb_dirichlet/conrey_first_primitive.c +++ b/dirichlet/conrey_first_primitive.c @@ -9,15 +9,15 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +dirichlet_conrey_first_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) { ulong k; if (G->q % 4 == 2) { - flint_printf("Exception (acb_dirichlet_conrey_first_primitive). No primitive element mod %wu.\n",G->q); + flint_printf("Exception (dirichlet_conrey_first_primitive). No primitive element mod %wu.\n",G->q); abort(); } x->n = 1; diff --git a/acb_dirichlet/conrey_index.c b/dirichlet/conrey_index.c similarity index 88% rename from acb_dirichlet/conrey_index.c rename to dirichlet/conrey_index.c index 2c02ce53..e9acc235 100644 --- a/acb_dirichlet/conrey_index.c +++ b/dirichlet/conrey_index.c @@ -23,10 +23,10 @@ ******************************************************************************/ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_index(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong j) +dirichlet_conrey_index(dirichlet_conrey_t x, const dirichlet_group_t G, ulong j) { slong k; @@ -36,5 +36,5 @@ acb_dirichlet_conrey_index(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t j = j / G->P[k].phi; } - acb_dirichlet_conrey_exp(x, G); + dirichlet_conrey_exp(x, G); } diff --git a/acb_dirichlet/conrey_log.c b/dirichlet/conrey_log.c similarity index 87% rename from acb_dirichlet/conrey_log.c rename to dirichlet/conrey_log.c index b3ead4a6..15a640f6 100644 --- a/acb_dirichlet/conrey_log.c +++ b/dirichlet/conrey_log.c @@ -12,11 +12,11 @@ */ #include "dlog.h" -#include "acb_dirichlet.h" +#include "dirichlet.h" /* assume m is invertible */ void -acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) +dirichlet_conrey_log(dirichlet_conrey_t x, const dirichlet_group_t G, ulong m) { slong k; /* even part */ @@ -36,7 +36,7 @@ acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G /* odd part */ for (k = G->neven; k < G->num; k++) { - acb_dirichlet_prime_group_struct P = G->P[k]; + dirichlet_prime_group_struct P = G->P[k]; if (P.dlog == NULL) { x->log[k] = dlog_once(m % P.pe.n, P.g, P.pe, P.phi); diff --git a/acb_dirichlet/conrey_mul.c b/dirichlet/conrey_mul.c similarity index 75% rename from acb_dirichlet/conrey_mul.c rename to dirichlet/conrey_mul.c index 29e3bcbe..df3a5376 100644 --- a/acb_dirichlet/conrey_mul.c +++ b/dirichlet/conrey_mul.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) +dirichlet_conrey_mul(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) { ulong k; for (k = 0; k < G->num ; k++) diff --git a/acb_dirichlet/conrey_next.c b/dirichlet/conrey_next.c similarity index 86% rename from acb_dirichlet/conrey_next.c rename to dirichlet/conrey_next.c index 881f54d2..e9c7cc8f 100644 --- a/acb_dirichlet/conrey_next.c +++ b/dirichlet/conrey_next.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +dirichlet_conrey_next(dirichlet_conrey_t x, const dirichlet_group_t G) { /* update index */ int k; diff --git a/acb_dirichlet/conrey_next_primitive.c b/dirichlet/conrey_next_primitive.c similarity index 92% rename from acb_dirichlet/conrey_next_primitive.c rename to dirichlet/conrey_next_primitive.c index a6e050dc..521e161c 100644 --- a/acb_dirichlet/conrey_next_primitive.c +++ b/dirichlet/conrey_next_primitive.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +dirichlet_conrey_next_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) { /* update index avoiding multiples of p except for first component if 8|q */ diff --git a/acb_dirichlet/conrey_one.c b/dirichlet/conrey_one.c similarity index 81% rename from acb_dirichlet/conrey_one.c rename to dirichlet/conrey_one.c index 7396e957..252889d0 100644 --- a/acb_dirichlet/conrey_one.c +++ b/dirichlet/conrey_one.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) +dirichlet_conrey_one(dirichlet_conrey_t x, const dirichlet_group_t G) { ulong k; for (k = 0; k < G->num ; k++) diff --git a/acb_dirichlet/conrey_order.c b/dirichlet/conrey_order.c similarity index 81% rename from acb_dirichlet/conrey_order.c rename to dirichlet/conrey_order.c index 0b4495e4..23008de9 100644 --- a/acb_dirichlet/conrey_order.c +++ b/dirichlet/conrey_order.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +dirichlet_conrey_order(const dirichlet_group_t G, const dirichlet_conrey_t x) { ulong k, g; g = G->expo; diff --git a/acb_dirichlet/conrey_parity.c b/dirichlet/conrey_parity.c similarity index 83% rename from acb_dirichlet/conrey_parity.c rename to dirichlet/conrey_parity.c index 11428e9e..91a47b3f 100644 --- a/acb_dirichlet/conrey_parity.c +++ b/dirichlet/conrey_parity.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +dirichlet_conrey_parity(const dirichlet_group_t G, const dirichlet_conrey_t x) { int k, odd = 0; for (k = 0; k < G->num; k++) diff --git a/acb_dirichlet/conrey_pow.c b/dirichlet/conrey_pow.c similarity index 77% rename from acb_dirichlet/conrey_pow.c rename to dirichlet/conrey_pow.c index 446c5529..5a70aa8f 100644 --- a/acb_dirichlet/conrey_pow.c +++ b/dirichlet/conrey_pow.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n) +dirichlet_conrey_pow(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, ulong n) { ulong k; for (k = 0; k < G->num ; k++) diff --git a/acb_dirichlet/conrey_primitive.c b/dirichlet/conrey_primitive.c similarity index 85% rename from acb_dirichlet/conrey_primitive.c rename to dirichlet/conrey_primitive.c index c3a79411..2c657576 100644 --- a/acb_dirichlet/conrey_primitive.c +++ b/dirichlet/conrey_primitive.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_primitive(acb_dirichlet_conrey_t y, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, ulong cond) +dirichlet_conrey_primitive(dirichlet_conrey_t y, const dirichlet_group_t G, const dirichlet_conrey_t x, ulong cond) { slong k, l; diff --git a/acb_dirichlet/conrey_print.c b/dirichlet/conrey_print.c similarity index 83% rename from acb_dirichlet/conrey_print.c rename to dirichlet/conrey_print.c index 7790fe77..3c5970f1 100644 --- a/acb_dirichlet/conrey_print.c +++ b/dirichlet/conrey_print.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_conrey_print(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +dirichlet_conrey_print(const dirichlet_group_t G, const dirichlet_conrey_t x) { slong k; if (G->num) diff --git a/acb_dirichlet/group_clear.c b/dirichlet/group_clear.c similarity index 86% rename from acb_dirichlet/group_clear.c rename to dirichlet/group_clear.c index 9864ad1c..fcf6c2c2 100644 --- a/acb_dirichlet/group_clear.c +++ b/dirichlet/group_clear.c @@ -10,10 +10,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_group_clear(acb_dirichlet_group_t G) +dirichlet_group_clear(dirichlet_group_t G) { flint_free(G->P); flint_free(G->generators); diff --git a/acb_dirichlet/group_dlog_precompute.c b/dirichlet/group_dlog_precompute.c similarity index 74% rename from acb_dirichlet/group_dlog_precompute.c rename to dirichlet/group_dlog_precompute.c index f55da18e..26cde7d5 100644 --- a/acb_dirichlet/group_dlog_precompute.c +++ b/dirichlet/group_dlog_precompute.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_prime_group_dlog_precompute(acb_dirichlet_prime_group_struct * P, ulong num) +dirichlet_prime_group_dlog_precompute(dirichlet_prime_group_struct * P, ulong num) { P->dlog = flint_malloc(sizeof(dlog_precomp_t)); /* even if e = 1 use modpe struct, more flexible if reused in bigger group */ @@ -20,18 +20,18 @@ acb_dirichlet_prime_group_dlog_precompute(acb_dirichlet_prime_group_struct * P, } void -acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) +dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num) { slong k; for (k = 0; k < G->num; k++) { if (G->P[k].dlog == NULL) - acb_dirichlet_prime_group_dlog_precompute(&G->P[k], num); + dirichlet_prime_group_dlog_precompute(&G->P[k], num); } } void -acb_dirichlet_group_dlog_clear(acb_dirichlet_group_t G) +dirichlet_group_dlog_clear(dirichlet_group_t G) { slong k; for (k = 0; k < G->num; k++) diff --git a/acb_dirichlet/group_init.c b/dirichlet/group_init.c similarity index 84% rename from acb_dirichlet/group_init.c rename to dirichlet/group_init.c index 9120ae48..4a98121f 100644 --- a/acb_dirichlet/group_init.c +++ b/dirichlet/group_init.c @@ -11,7 +11,7 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" static ulong primitive_root_p_and_p2(ulong p) @@ -34,7 +34,7 @@ primitive_root_p_and_p2(ulong p) } void -acb_dirichlet_prime_group_init(acb_dirichlet_prime_group_struct * P, ulong p, int e) +dirichlet_prime_group_init(dirichlet_prime_group_struct * P, ulong p, int e) { P->p = p; P->e = e; @@ -66,10 +66,10 @@ acb_dirichlet_prime_group_init(acb_dirichlet_prime_group_struct * P, ulong p, in } static void -acb_dirichlet_group_lift_generators(acb_dirichlet_group_t G) +dirichlet_group_lift_generators(dirichlet_group_t G) { slong k; - acb_dirichlet_prime_group_struct * P = G->P; + dirichlet_prime_group_struct * P = G->P; G->expo = G->phi_q = 1; if (G->neven) @@ -104,7 +104,7 @@ acb_dirichlet_group_lift_generators(acb_dirichlet_group_t G) } void -acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) +dirichlet_group_init(dirichlet_group_t G, ulong q) { slong k; ulong e2; @@ -124,15 +124,15 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) n_factor(&fac, q, 1); G->num = fac.num + G->neven; - G->P = flint_malloc(G->num * sizeof(acb_dirichlet_prime_group_struct)); + G->P = flint_malloc(G->num * sizeof(dirichlet_prime_group_struct)); G->generators = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); /* even part */ if (G->neven >= 1) - acb_dirichlet_prime_group_init(&G->P[0], 2, e2); + dirichlet_prime_group_init(&G->P[0], 2, e2); if (G->neven == 2) - acb_dirichlet_prime_group_init(&G->P[1], 4, e2); + dirichlet_prime_group_init(&G->P[1], 4, e2); /* odd part */ G->rad_q = 1; @@ -142,13 +142,13 @@ acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) p = fac.p[k - G->neven]; e = fac.exp[k - G->neven]; G->rad_q *= p; - acb_dirichlet_prime_group_init(&G->P[k], p, e); + dirichlet_prime_group_init(&G->P[k], p, e); } - acb_dirichlet_group_lift_generators(G); + dirichlet_group_lift_generators(G); } void -acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h) +dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h) { int s[15]; /* selected components */ slong k, j, e2; @@ -185,7 +185,7 @@ acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t } H->num = j; - H->P = flint_malloc(j * sizeof(acb_dirichlet_prime_group_struct)); + H->P = flint_malloc(j * sizeof(dirichlet_prime_group_struct)); H->generators = flint_malloc(j * sizeof(ulong)); H->PHI = flint_malloc(j * sizeof(ulong)); @@ -218,5 +218,5 @@ acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t } } - acb_dirichlet_group_lift_generators(H); + dirichlet_group_lift_generators(H); } diff --git a/acb_dirichlet/index_conrey.c b/dirichlet/index_conrey.c similarity index 91% rename from acb_dirichlet/index_conrey.c rename to dirichlet/index_conrey.c index a3a2b543..e55783f5 100644 --- a/acb_dirichlet/index_conrey.c +++ b/dirichlet/index_conrey.c @@ -23,10 +23,10 @@ ******************************************************************************/ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_index_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) +dirichlet_index_conrey(const dirichlet_group_t G, const dirichlet_conrey_t x) { slong k; ulong j = 0; diff --git a/acb_dirichlet/number_primitive.c b/dirichlet/number_primitive.c similarity index 89% rename from acb_dirichlet/number_primitive.c rename to dirichlet/number_primitive.c index 053df1a7..202e5114 100644 --- a/acb_dirichlet/number_primitive.c +++ b/dirichlet/number_primitive.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) +dirichlet_number_primitive(const dirichlet_group_t G) { if (G->q % 4 == 2) return 0; diff --git a/acb_dirichlet/profile/p-conrey.c b/dirichlet/profile/p-conrey.c similarity index 70% rename from acb_dirichlet/profile/p-conrey.c rename to dirichlet/profile/p-conrey.c index 180a1e25..12cc437e 100644 --- a/acb_dirichlet/profile/p-conrey.c +++ b/dirichlet/profile/p-conrey.c @@ -10,7 +10,7 @@ */ #include -#include "acb_dirichlet.h" +#include "dirichlet.h" #include "profiler.h" #define LOG 0 @@ -38,18 +38,18 @@ do_conrey(ulong q1, ulong q2) for (n = 0, q = q1; q <= q2; q++) { - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; + dirichlet_group_t G; + dirichlet_conrey_t x; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); n++; - for (; acb_dirichlet_conrey_next(x, G) >= 0; n++); - acb_dirichlet_conrey_clear(x); - acb_dirichlet_group_clear(G); + for (; dirichlet_conrey_next(x, G) >= 0; n++); + dirichlet_conrey_clear(x); + dirichlet_group_clear(G); } return n; @@ -62,18 +62,18 @@ do_chars(ulong q1, ulong q2) for (n = 0, q = q1; q <= q2; q++) { - acb_dirichlet_group_t G; - acb_dirichlet_char_t chi; + dirichlet_group_t G; + dirichlet_char_t chi; - acb_dirichlet_group_init(G, q); - acb_dirichlet_char_init(chi, G); + dirichlet_group_init(G, q); + dirichlet_char_init(chi, G); - acb_dirichlet_char_one(chi, G); + dirichlet_char_one(chi, G); n++; - for (; acb_dirichlet_char_next(chi, G) >= 0; n++); + for (; dirichlet_char_next(chi, G) >= 0; n++); - acb_dirichlet_char_clear(chi); - acb_dirichlet_group_clear(G); + dirichlet_char_clear(chi); + dirichlet_group_clear(G); } return n; @@ -86,8 +86,8 @@ do_gcdpluscond(ulong q1, ulong q2) for (n = 0, q = q1; q <= q2; q++) { - acb_dirichlet_group_t G; - acb_dirichlet_group_init(G, q); + dirichlet_group_t G; + dirichlet_group_init(G, q); for (k = 1; k < q; k++) { @@ -100,11 +100,11 @@ do_gcdpluscond(ulong q1, ulong q2) break; if (i == G->num) - acb_dirichlet_ui_conductor(G, k); + dirichlet_ui_conductor(G, k); } n += G->phi_q; - acb_dirichlet_group_clear(G); + dirichlet_group_clear(G); } @@ -118,20 +118,20 @@ do_conreypluscond(ulong q1, ulong q2) for (n = 0, q = q1; q <= q2; q++) { - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; + dirichlet_group_t G; + dirichlet_conrey_t x; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); n++; - for (; acb_dirichlet_conrey_next(x, G) >= 0; n++) - acb_dirichlet_conrey_conductor(G, x); + for (; dirichlet_conrey_next(x, G) >= 0; n++) + dirichlet_conrey_conductor(G, x); - acb_dirichlet_conrey_clear(x); - acb_dirichlet_group_clear(G); + dirichlet_conrey_clear(x); + dirichlet_group_clear(G); } @@ -145,20 +145,20 @@ do_conreyplusorder(ulong q1, ulong q2) for (n = 0, q = q1; q <= q2; q++) { - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; + dirichlet_group_t G; + dirichlet_conrey_t x; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); n++; - for (; acb_dirichlet_conrey_next(x, G) >= 0; n++) - acb_dirichlet_conrey_order(G, x); + for (; dirichlet_conrey_next(x, G) >= 0; n++) + dirichlet_conrey_order(G, x); - acb_dirichlet_conrey_clear(x); - acb_dirichlet_group_clear(G); + dirichlet_conrey_clear(x); + dirichlet_group_clear(G); } diff --git a/acb_dirichlet/test/t-chars.c b/dirichlet/test/t-chars.c similarity index 64% rename from acb_dirichlet/test/t-chars.c rename to dirichlet/test/t-chars.c index a650aa95..d2a79a30 100644 --- a/acb_dirichlet/test/t-chars.c +++ b/dirichlet/test/t-chars.c @@ -9,7 +9,7 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int main() { @@ -24,19 +24,19 @@ int main() for (iter = 0; iter < 50; iter++) { - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; - acb_dirichlet_char_t chi, chi2; + dirichlet_group_t G; + dirichlet_conrey_t x; + dirichlet_char_t chi, chi2; ulong q, iter2; q = 2 + n_randint(state, 1 << bits); - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_char_init(chi, G); - acb_dirichlet_char_init(chi2, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); + dirichlet_char_init(chi, G); + dirichlet_char_init(chi2, G); - acb_dirichlet_group_dlog_precompute(G, 50); + dirichlet_group_dlog_precompute(G, 50); /* check number char properties */ for (iter2 = 0; iter2 < 100; iter2++) @@ -49,23 +49,23 @@ int main() m = n_randint(state, q); while (n_gcd(q, m) > 1); - acb_dirichlet_char(chi, G, m); - acb_dirichlet_conrey_log(x, G, m); - acb_dirichlet_char_conrey(chi2, G, x); + dirichlet_char(chi, G, m); + dirichlet_conrey_log(x, G, m); + dirichlet_char_conrey(chi2, G, x); - if (!acb_dirichlet_char_eq_deep(G, chi, chi2)) + if (!dirichlet_char_eq_deep(G, chi, chi2)) { flint_printf("FAIL: init char\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); - acb_dirichlet_char_print(G, chi); + dirichlet_char_print(G, chi); flint_printf("\n"); - acb_dirichlet_char_print(G, chi2); + dirichlet_char_print(G, chi2); flint_printf("\n"); abort(); } - order = acb_dirichlet_ui_order(G, m); + order = dirichlet_ui_order(G, m); if (order != chi->order.n) { flint_printf("FAIL: order\n\n"); @@ -76,7 +76,7 @@ int main() abort(); } - cond = acb_dirichlet_ui_conductor(G, m); + cond = dirichlet_ui_conductor(G, m); if (cond != chi->conductor) { flint_printf("FAIL: conductor\n\n"); @@ -87,17 +87,17 @@ int main() abort(); } - par = acb_dirichlet_ui_parity(G, m); - chim1 = acb_dirichlet_ui_chi(G, chi, q - 1); - if (acb_dirichlet_char_parity(chi) != par || par != (chim1 != 0)) + par = dirichlet_ui_parity(G, m); + chim1 = dirichlet_ui_chi(G, chi, q - 1); + if (dirichlet_char_parity(chi) != par || par != (chim1 != 0)) { flint_printf("FAIL: parity\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("chi(-1) = %wu\n\n", chim1); - flint_printf("char_parity = %d", acb_dirichlet_char_parity(chi)); + flint_printf("char_parity = %d", dirichlet_char_parity(chi)); flint_printf("parity_ui = %d", par); - acb_dirichlet_char_print(G, chi); + dirichlet_char_print(G, chi); abort(); } @@ -105,10 +105,10 @@ int main() n = n_randint(state, q); while (n_gcd(q, n) > 1); - acb_dirichlet_char(chi2, G, n); - pairing = acb_dirichlet_ui_pairing(G, m, n); - cn = acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order.n); - cm = acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order.n); + dirichlet_char(chi2, G, n); + pairing = dirichlet_ui_pairing(G, m, n); + cn = dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order.n); + cm = dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order.n); if (pairing != cn || pairing != cm) { @@ -122,30 +122,30 @@ int main() abort(); } - acb_dirichlet_conrey_next(x, G); - acb_dirichlet_char_next(chi, G); - acb_dirichlet_char_conrey(chi2, G, x); + dirichlet_conrey_next(x, G); + dirichlet_char_next(chi, G); + dirichlet_char_conrey(chi2, G, x); - if (!acb_dirichlet_char_eq_deep(G, chi, chi2)) + if (!dirichlet_char_eq_deep(G, chi, chi2)) { flint_printf("FAIL: next char\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); - acb_dirichlet_char_print(G, chi); + dirichlet_char_print(G, chi); flint_printf("\n"); - acb_dirichlet_char_print(G, chi2); + dirichlet_char_print(G, chi2); flint_printf("\n"); abort(); } } - acb_dirichlet_group_dlog_clear(G); + dirichlet_group_dlog_clear(G); - acb_dirichlet_char_clear(chi); - acb_dirichlet_char_clear(chi2); - acb_dirichlet_conrey_clear(x); - acb_dirichlet_group_clear(G); + dirichlet_char_clear(chi); + dirichlet_char_clear(chi2); + dirichlet_conrey_clear(x); + dirichlet_group_clear(G); } } diff --git a/acb_dirichlet/test/t-conrey.c b/dirichlet/test/t-conrey.c similarity index 74% rename from acb_dirichlet/test/t-conrey.c rename to dirichlet/test/t-conrey.c index b64b314a..525d7c00 100644 --- a/acb_dirichlet/test/t-conrey.c +++ b/dirichlet/test/t-conrey.c @@ -9,7 +9,7 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int main() { @@ -22,23 +22,23 @@ int main() for (iter = 0; iter < 3000 * arb_test_multiplier(); iter++) { - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x, y; + dirichlet_group_t G; + dirichlet_conrey_t x, y; ulong q, n, k, sum; slong ref; q = 1 + n_randint(state, 1000 * (1 + iter / 100)); - acb_dirichlet_group_init(G, q); + dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_init(y, G); + dirichlet_conrey_init(x, G); + dirichlet_conrey_init(y, G); /* check group size and elements */ - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_one(x, G); sum = 1; - for (n = 1; acb_dirichlet_conrey_next(x, G) >= 0; n++) + for (n = 1; dirichlet_conrey_next(x, G) >= 0; n++) sum += x->n * x->n; if (FLINT_BITS == 64 || q < 1024) @@ -70,10 +70,10 @@ int main() if (q % 4 != 2) { - acb_dirichlet_conrey_first_primitive(x, G); - for (n = 1; acb_dirichlet_conrey_next_primitive(x, G) >= 0; n++); + dirichlet_conrey_first_primitive(x, G); + for (n = 1; dirichlet_conrey_next_primitive(x, G) >= 0; n++); - ref = acb_dirichlet_number_primitive(G); + ref = dirichlet_number_primitive(G); if (n != ref) { flint_printf("FAIL: number of primitive elements\n\n"); @@ -90,15 +90,15 @@ int main() ulong m; for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); - acb_dirichlet_conrey_log(x, G, m); + dirichlet_conrey_log(x, G, m); - if (m != acb_dirichlet_conrey_exp(x, G)) + if (m != dirichlet_conrey_exp(x, G)) { flint_printf("FAIL: conrey log and exp\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); flint_printf("conrey = "); - acb_dirichlet_conrey_print(G, x); + dirichlet_conrey_print(G, x); flint_printf("\n\nnumber = %wu\n\n", x->n); abort(); } @@ -106,34 +106,34 @@ int main() for (k = 0; k < G->num; k++) x->log[k] = n_randint(state, G->P[k].phi); - m = acb_dirichlet_conrey_exp(x, G); - acb_dirichlet_conrey_log(y, G, m); + m = dirichlet_conrey_exp(x, G); + dirichlet_conrey_log(y, G, m); - if (!acb_dirichlet_conrey_eq_deep(G, x, y)) + if (!dirichlet_conrey_eq_deep(G, x, y)) { flint_printf("FAIL: conrey exp and log\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("conrey = "); - acb_dirichlet_conrey_print(G, x); + dirichlet_conrey_print(G, x); flint_printf("\n\nm = %wu\n\n", m); flint_printf("log = "); - acb_dirichlet_conrey_print(G, y); + dirichlet_conrey_print(G, y); flint_printf("\n\nnumber = %wu\n\n", y->n); abort(); } - acb_dirichlet_conrey_next_primitive(x, G); + dirichlet_conrey_next_primitive(x, G); m = x->n; - if (m != acb_dirichlet_conrey_exp(x, G)) + if (m != dirichlet_conrey_exp(x, G)) { flint_printf("FAIL: conrey number next primitive\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("conrey = "); - acb_dirichlet_conrey_print(G, y); + dirichlet_conrey_print(G, y); flint_printf(", m = %wu\n\n", y->n); flint_printf("next primitive = "); - acb_dirichlet_conrey_print(G, x); + dirichlet_conrey_print(G, x); flint_printf(", m = %wu\n\n", m); flint_printf("exp = %wu\n\n", x->n); abort(); @@ -141,9 +141,9 @@ int main() } } - acb_dirichlet_conrey_clear(x); - acb_dirichlet_conrey_clear(y); - acb_dirichlet_group_clear(G); + dirichlet_conrey_clear(x); + dirichlet_conrey_clear(y); + dirichlet_group_clear(G); } flint_randclear(state); diff --git a/acb_dirichlet/ui_chi.c b/dirichlet/ui_chi.c similarity index 56% rename from acb_dirichlet/ui_chi.c rename to dirichlet/ui_chi.c index cc502e9c..8166a0f1 100644 --- a/acb_dirichlet/ui_chi.c +++ b/dirichlet/ui_chi.c @@ -9,25 +9,25 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) +dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) { if (n_gcd(G->q, n) > 1) { - return ACB_DIRICHLET_CHI_NULL; + return DIRICHLET_CHI_NULL; } else { ulong v; - acb_dirichlet_conrey_t x; - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_log(x, G, n); + dirichlet_conrey_t x; + dirichlet_conrey_init(x, G); + dirichlet_conrey_log(x, G, n); - v = acb_dirichlet_ui_chi_conrey(G, chi, x); + v = dirichlet_ui_chi_conrey(G, chi, x); - acb_dirichlet_conrey_clear(x); + dirichlet_conrey_clear(x); return v; } } diff --git a/acb_dirichlet/ui_chi_conrey.c b/dirichlet/ui_chi_conrey.c similarity index 79% rename from acb_dirichlet/ui_chi_conrey.c rename to dirichlet/ui_chi_conrey.c index 5f67b9a8..37af059b 100644 --- a/acb_dirichlet/ui_chi_conrey.c +++ b/dirichlet/ui_chi_conrey.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const acb_dirichlet_conrey_t x) +dirichlet_ui_chi_conrey(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_conrey_t x) { ulong v = 0, k; diff --git a/acb_dirichlet/ui_chi_vec.c b/dirichlet/ui_chi_vec.c similarity index 62% rename from acb_dirichlet/ui_chi_vec.c rename to dirichlet/ui_chi_vec.c index 8578c573..bc16cc75 100644 --- a/acb_dirichlet/ui_chi_vec.c +++ b/dirichlet/ui_chi_vec.c @@ -9,13 +9,13 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_ui_chi_vec(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { if (2 * nv > G->q) - acb_dirichlet_ui_chi_vec_loop(v, G, chi, nv); + dirichlet_ui_chi_vec_loop(v, G, chi, nv); else - acb_dirichlet_ui_chi_vec_primeloop(v, G, chi, nv); + dirichlet_ui_chi_vec_primeloop(v, G, chi, nv); } diff --git a/acb_dirichlet/ui_chi_vec_loop.c b/dirichlet/ui_chi_vec_loop.c similarity index 66% rename from acb_dirichlet/ui_chi_vec_loop.c rename to dirichlet/ui_chi_vec_loop.c index 303b069f..2e71d6fd 100644 --- a/acb_dirichlet/ui_chi_vec_loop.c +++ b/dirichlet/ui_chi_vec_loop.c @@ -9,25 +9,25 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" /* loop over whole group */ void -acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { int j; ulong t; slong k; - acb_dirichlet_conrey_t x; - acb_dirichlet_conrey_init(x, G); - acb_dirichlet_conrey_one(x, G); + dirichlet_conrey_t x; + dirichlet_conrey_init(x, G); + dirichlet_conrey_one(x, G); for (k = 0; k < nv; k++) - v[k] = ACB_DIRICHLET_CHI_NULL; + v[k] = DIRICHLET_CHI_NULL; t = v[1] = 0; - while ( (j = acb_dirichlet_conrey_next(x, G)) >= 0 ) + while ( (j = dirichlet_conrey_next(x, G)) >= 0 ) { /* exponents were modified up to j */ for (k = G->num - 1; k >= j; k--) @@ -38,11 +38,11 @@ acb_dirichlet_ui_chi_vec_loop(ulong *v, const acb_dirichlet_group_t G, const acb } /* fix result outside primes */ - /* acb_dirichlet_vec_set_null(v, G, nv);*/ + /* dirichlet_vec_set_null(v, G, nv);*/ /* copy outside modulus */ for (k = G->q; k < nv ; k++ ) v[k] = v[k - G->q]; - acb_dirichlet_conrey_clear(x); + dirichlet_conrey_clear(x); } diff --git a/acb_dirichlet/ui_chi_vec_primeloop.c b/dirichlet/ui_chi_vec_primeloop.c similarity index 81% rename from acb_dirichlet/ui_chi_vec_primeloop.c rename to dirichlet/ui_chi_vec_primeloop.c index 7e1311da..2d415537 100644 --- a/acb_dirichlet/ui_chi_vec_primeloop.c +++ b/dirichlet/ui_chi_vec_primeloop.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" static void -chi_vec_evenpart(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +chi_vec_evenpart(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { ulong c3, c4, x; @@ -47,7 +47,7 @@ chi_vec_evenpart(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_ch /* loop over primary components */ void -acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) +dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) { slong k, l; @@ -59,7 +59,7 @@ acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, cons for (l = G->neven; l < G->num; l++) { - acb_dirichlet_prime_group_struct P = G->P[l]; + dirichlet_prime_group_struct P = G->P[l]; /* FIXME: there may be some precomputed dlog in P if needed */ if (P.dlog == NULL) @@ -68,5 +68,5 @@ acb_dirichlet_ui_chi_vec_primeloop(ulong *v, const acb_dirichlet_group_t G, cons dlog_vec_add_precomp(v, nv, P.dlog, P.g, chi->expo[l], P.pe, P.phi, chi->order); } - acb_dirichlet_ui_vec_set_null(v, G, nv); + dirichlet_ui_vec_set_null(v, G, nv); } diff --git a/acb_dirichlet/ui_conductor.c b/dirichlet/ui_conductor.c similarity index 91% rename from acb_dirichlet/ui_conductor.c rename to dirichlet/ui_conductor.c index e5069798..4c2d1295 100644 --- a/acb_dirichlet/ui_conductor.c +++ b/dirichlet/ui_conductor.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) +dirichlet_ui_conductor(const dirichlet_group_t G, ulong a) { slong k; ulong ap, cond; diff --git a/acb_dirichlet/ui_order.c b/dirichlet/ui_order.c similarity index 91% rename from acb_dirichlet/ui_order.c rename to dirichlet/ui_order.c index b162d232..6c58db89 100644 --- a/acb_dirichlet/ui_order.c +++ b/dirichlet/ui_order.c @@ -9,7 +9,7 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" /* order of an element knowing the factorization of a multiple */ ulong @@ -31,7 +31,7 @@ nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) } ulong -acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a) +dirichlet_ui_order(const dirichlet_group_t G, ulong a) { n_factor_t fac; diff --git a/acb_dirichlet/ui_pairing.c b/dirichlet/ui_pairing.c similarity index 51% rename from acb_dirichlet/ui_pairing.c rename to dirichlet/ui_pairing.c index 235325e9..e6d21baf 100644 --- a/acb_dirichlet/ui_pairing.c +++ b/dirichlet/ui_pairing.c @@ -9,26 +9,26 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" ulong -acb_dirichlet_ui_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) +dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n) { ulong x; - acb_dirichlet_conrey_t a, b; + dirichlet_conrey_t a, b; if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) - return ACB_DIRICHLET_CHI_NULL; + return DIRICHLET_CHI_NULL; - acb_dirichlet_conrey_init(a, G); - acb_dirichlet_conrey_init(b, G); - acb_dirichlet_conrey_log(a, G, m); - acb_dirichlet_conrey_log(b, G, n); + dirichlet_conrey_init(a, G); + dirichlet_conrey_init(b, G); + dirichlet_conrey_log(a, G, m); + dirichlet_conrey_log(b, G, n); - x = acb_dirichlet_ui_pairing_conrey(G, a, b); + x = dirichlet_ui_pairing_conrey(G, a, b); - acb_dirichlet_conrey_clear(a); - acb_dirichlet_conrey_clear(b); + dirichlet_conrey_clear(a); + dirichlet_conrey_clear(b); return x; } diff --git a/acb_dirichlet/ui_pairing_conrey.c b/dirichlet/ui_pairing_conrey.c similarity index 81% rename from acb_dirichlet/ui_pairing_conrey.c rename to dirichlet/ui_pairing_conrey.c index 9063bea0..cd6638e7 100644 --- a/acb_dirichlet/ui_pairing_conrey.c +++ b/dirichlet/ui_pairing_conrey.c @@ -11,12 +11,12 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" /* todo: modular arithmetic */ ulong -acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) +dirichlet_ui_pairing_conrey(const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) { ulong x, k; x = 0; diff --git a/acb_dirichlet/ui_parity.c b/dirichlet/ui_parity.c similarity index 85% rename from acb_dirichlet/ui_parity.c rename to dirichlet/ui_parity.c index aa5a2a4c..6312dc81 100644 --- a/acb_dirichlet/ui_parity.c +++ b/dirichlet/ui_parity.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" int -acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) +dirichlet_ui_parity(const dirichlet_group_t G, ulong a) { int par; diff --git a/acb_dirichlet/ui_vec_set_null.c b/dirichlet/ui_vec_set_null.c similarity index 80% rename from acb_dirichlet/ui_vec_set_null.c rename to dirichlet/ui_vec_set_null.c index baf2333c..834a5c0b 100644 --- a/acb_dirichlet/ui_vec_set_null.c +++ b/dirichlet/ui_vec_set_null.c @@ -9,10 +9,10 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" void -acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv) +dirichlet_ui_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv) { slong k, l; if (G->q_even > 1) @@ -26,6 +26,6 @@ acb_dirichlet_ui_vec_set_null(ulong *v, const acb_dirichlet_group_t G, slong nv) ulong p = G->P[l].p; for (k = p; k < nv; k += p) - v[k] = ACB_DIRICHLET_CHI_NULL; + v[k] = DIRICHLET_CHI_NULL; } } From 0428ebf80602930e6f8bf5e7af6c8cceb24fe0a7 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 6 Oct 2016 14:45:58 +0200 Subject: [PATCH 133/139] split doc also --- doc/source/acb_dirichlet.rst | 398 +++-------------------------------- doc/source/dirichlet.rst | 342 ++++++++++++++++++++++++++++++ doc/source/index.rst | 2 + examples/lcentral.c | 18 +- 4 files changed, 388 insertions(+), 372 deletions(-) create mode 100644 doc/source/dirichlet.rst diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index c7ed7354..af2516d4 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -6,8 +6,10 @@ *Warning: the interfaces in this module are experimental and may change without notice.* -This module allows working with Dirichlet characters, Dirichlet L-functions, -and related functions. +This module allows working with values of Dirichlet characters, Dirichlet L-functions, +and related functions. Working with Dirichlet characters is documented in +:ref:`dirichlet`. + A Dirichlet L-function is the analytic continuation of an L-series .. math :: @@ -20,309 +22,17 @@ The code in other modules for computing the Riemann zeta function, Hurwitz zeta function and polylogarithm will possibly be migrated to this module in the future. -Multiplicative group modulo *q* -------------------------------------------------------------------------------- - -Working with Dirichlet characters mod *q* consists mainly -in going from residue classes mod *q* to exponents on a set -of generators of the group. - -This implementation relies on the Conrey numbering scheme -introduced in the LMFDB, which is an explicit choice of isomorphism - -.. math:: - - (\mathbb Z/q\mathbb Z)^\times & \to &\bigoplus_i \mathbb Z/\phi_i\mathbb Z \\ - x & \mapsto & (e_i) - -We call *number* a residue class `x` modulo *q*, and *log* the -corresponding vector `(e_i)` of exponents of Conrey generators. - -Going from a *log* to the corresponding *number* is a cheap -operation called exp, while the converse requires computing discrete -logarithms. - -.. type:: acb_dirichlet_group_struct - -.. type:: acb_dirichlet_group_t - - Represents the group of Dirichlet characters mod *q*. - - An *acb_dirichlet_group_t* is defined as an array of *acb_dirichlet_group_struct* - of length 1, permitting it to be passed by reference. - -.. function:: void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) - - Initializes *G* to the group of Dirichlet characters mod *q*. - - This method computes a canonical decomposition of *G* in terms of cyclic - groups, which are the mod `p^e` subgroups for `p^e\|q`. - In particular *G* contains: - - - the number *num* of components - - - the generators - - - the exponent *expo* of the group - - It does *not* automatically precompute lookup tables - of discrete logarithms or numerical roots of unity, and can therefore - safely be called even with large *q*. - - For implementation reasons, the largest prime factor of *q* must not - exceed `10^{12}` (an abort will be raised). This restriction could - be removed in the future. - -.. function:: void acb_dirichlet_subgroup_init(acb_dirichlet_group_t H, const acb_dirichlet_group_t G, ulong h) - - Given an already computed group *G* mod `q`, initialize its subgroup *H* - defined mod `h\mid q`. Precomputed discrete log tables are inherited. - -.. function:: void acb_dirichlet_group_clear(acb_dirichlet_group_t G) - - Clears *G*. Remark this function does *not* clear the discrete logarithm - tables stored in *G* (which may be shared with another group). - -.. function:: void acb_dirichlet_group_dlog_precompute(acb_dirichlet_group_t G, ulong num) - - Precompute decomposition and tables for discrete log computations in *G*, - so as to minimize the complexity of *num* calls to discrete logarithms. - - If *num* gets very large, the entire group may be indexed. - -.. function:: void acb_dirichlet_group_dlog_clear(acb_dirichlet_group_t G, ulong num) - - Clear discrete logarithm tables in *G*. When discrete logarithm tables are - shared with subgroups, those subgroups must be cleared before clearing the - tables. - -Conrey elements -------------------------------------------------------------------------------- - -.. type:: acb_dirichlet_conrey_struct - -.. type:: acb_dirichlet_conrey_t - - Represents elements of the unit group mod *q*, keeping both the - *number* (residue class) and *log* (exponents on the group - generators). - -.. function:: void acb_dirichlet_conrey_log(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong m) - - Sets *x* to the element of number *m*, computing its log using discrete - logarithm in *G*. - -.. function:: ulong acb_dirichlet_conrey_exp(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - - Compute the reverse operation. - -.. function:: void acb_dirichlet_conrey_one(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - - Sets *x* to the *number* `1\in G`, having *log* `[0,\dots 0]`. - -.. function:: void acb_dirichlet_conrey_first_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - - Sets *x* to the first primitive element of *G*, having *log* `[1,\dots 1]`, - or `[0, 1, \dots 1]` if `8\mid q`. - -.. function:: void acb_dirichlet_conrey_set(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t y) - - Sets *x* to the element *y*. - -.. function:: int acb_dirichlet_conrey_next(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - - Sets *x* to the next conrey element in *G* with lexicographic ordering. - - The return value - is the index of the last updated exponent of *x*, or *-1* if the last - element has been reached. - - This function allows to iterate on the elements of *G* looping on their *log*. - Note that it produces elements in seemingly random *number* order. - - The following template can be used to loop over all elements *x* in *G*:: - - acb_conrey_one(x, G); - do { - /* use Conrey element x */ - } while (acb_dirichlet_conrey_next(x, G) >= 0); - -.. function:: int acb_dirichlet_conrey_next_primitive(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G) - - Same as :func:`acb_dirichlet_conrey_next`, but jumps to the next element - corresponding to a primitive character of *G*. - -.. function:: ulong acb_dirichlet_index_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x); - - Returns the lexicographic index of *x* as an integer in `0\dots \varphi(q)`. - -.. function:: void acb_dirichlet_conrey_index(acb_dirichlet_conrey_t x, const acb_dirichlet_group_t G, ulong j) - - Sets *x* to the Conrey element of lexicographic index *j*. - -.. function:: int acb_dirichlet_conrey_eq(const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) - -.. function:: int acb_dirichlet_conrey_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x, const acb_dirichlet_conrey_t y) - - Return 1 if *x* equals *y*. - The second version checks every byte of the representation and is intended for testing only. - -Dirichlet characters -------------------------------------------------------------------------------- - -Dirichlet characters take value in a finite cyclic group of roots of unity plus zero. - -When evaluation functions return a *ulong*, this number corresponds to the -power of a primitive root of unity, the special value *ACB_DIRICHLET_CHI_NULL* -encoding the zero value. - -The Conrey numbering scheme makes explicit the mathematical fact that -the group *G* is isomorphic to its dual, so that a character is described by -a *number*. - -.. math:: - - \begin{array}{ccccc} - (\mathbb Z/q\mathbb Z)^\times \times (\mathbb Z/q\mathbb Z)^\times & \to & \bigoplus_i \mathbb Z/\phi_i\mathbb Z \times \mathbb Z/\phi_i\mathbb Z & \to &\mathbb C \\ - (m,n) & \mapsto& (a_i,b_i) &\mapsto& \chi_q(m,n) = \exp(2i\pi\sum \frac{a_ib_i}{\phi_i} ) - \end{array} - -.. function:: ulong acb_dirichlet_ui_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) - -.. function:: ulong acb_dirichlet_ui_pairing_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) - - Compute the value of the Dirichlet pairing on numbers *m* and *n*, as - exponent modulo *G->expo*. - The second form takes the Conrey index *a* and *b*, and does not take discrete - logarithms. - - The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. - -Character type -------------------------------------------------------------------------------- - -.. type:: acb_dirichlet_char_struct - -.. type:: acb_dirichlet_char_t - - Represents a Dirichlet character. This structure contains various - useful invariants such as the order, the parity and the conductor of the character. - - An *acb_dirichlet_char_t* is defined as an array of *acb_dirichlet_char_struct* - of length 1, permitting it to be passed by reference. - -.. function:: void acb_dirichlet_char_init(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) - - Initializes *chi* to an element of the group *G* and sets its value - to the principal character. - -.. function:: void acb_dirichlet_char_clear(acb_dirichlet_char_t chi) - - Clears *chi*. - -.. function:: void acb_dirichlet_char(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, ulong n) - - Sets *chi* to the Dirichlet character of number *n*, using Conrey numbering scheme. - This function performs a discrete logarithm in *G*. - -.. function:: void acb_dirichlet_char_conrey(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - - Sets *chi* to the Dirichlet character corresponding to *x*. - -.. function:: int acb_dirichlet_char_eq(const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) - -.. function:: int acb_dirichlet_char_eq_deep(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) - - Return 1 if *chi1* equals *chi2*. - The second version checks every byte of the representation and is intended for testing only. - -.. function:: acb_dirichlet_char_is_principal(const acb_dirichlet_char_t chi) - - Return 1 if *chi* is the principal character mod *q*. - -.. function:: void acb_dirichlet_char_one(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) - - Sets *chi* to the principal character. - -.. function:: void acb_dirichlet_char_set(acb_dirichlet_char_t chi1, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi2) - - Sets *chi1* to the character *chi2*. - -.. function:: int acb_dirichlet_char_next(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) - - Sets *x* to the next character in *G* with lexicographic Conrey ordering - (see :func:`acb_dirichlet_conrey_next`). The return value - is the index of the last updated exponent of *x*, or *-1* if the last - element has been reached. - -.. function:: int acb_dirichlet_char_next_primitive(acb_dirichlet_char_t chi, const acb_dirichlet_group_t G) - - Like :func:`acb_dirichlet_char_next`, but only generates primitive - characters. - -Character properties -------------------------------------------------------------------------------- - -As a consequence of the Conrey numbering, all these numbers are available at the -level of *number* and Conrey *log* elements, and for *char*. -No discrete log computation is performed. - -.. function:: ulong acb_dirichlet_number_primitive(const acb_dirichlet_group_t G) - - Return the number of primitive elements in *G*. - -.. function:: ulong acb_dirichlet_ui_conductor(const acb_dirichlet_group_t G, ulong a) - -.. function:: ulong acb_dirichlet_conrey_conductor(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - -.. function:: ulong acb_dirichlet_char_conductor(const acb_dirichlet_char_t chi) - - Return the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` - such `\chi_q(a,\cdot)` can be obtained as a character mod `r`. - This number is precomputed for the *char* type. - -.. function:: int acb_dirichlet_ui_parity(const acb_dirichlet_group_t G, ulong a) - -.. function:: int acb_dirichlet_conrey_parity(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - -.. function:: int acb_dirichlet_char_parity(const acb_dirichlet_char_t chi) - - Return the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that - `\chi_q(a,-1)=(-1)^\lambda`. - This number is precomputed for the *char* type. - -.. function:: ulong acb_dirichlet_ui_order(const acb_dirichlet_group_t G, ulong a) - -.. function:: int acb_dirichlet_conrey_order(const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t x) - -.. function:: ulong acb_dirichlet_char_order(const acb_dirichlet_char_t chi) - - Return the order of `\chi_q(a,\cdot)` which is the order of `a\bmod q`. - This number is precomputed for the *char* type. - -.. function:: int acb_dirichlet_char_is_real(const acb_dirichlet_char_t chi) - - Return 1 if *chi* is a real character (iff it has order `\leq 2`). - Character evaluation ------------------------------------------------------------------------------- -The image of a Dirichlet character is a finite cyclic group. Dirichlet -character evaluations are either exponents in this group, or an *acb_t* root of -unity. - -.. function:: ulong acb_dirichlet_ui_chi_conrey(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const acb_dirichlet_conrey_t x) - -.. function:: ulong acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n) - - Compute that value `\chi(n)` as the exponent mod the order of `\chi`. - -.. function:: void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n, slong prec) +.. function:: void acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec) Sets *res* to `\chi(n)`, the value of the Dirichlet character *chi* at the integer *n*. - There are no restrictions on *n*. +.. function:: void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec) + + Compute the *nv* first Dirichlet values. Roots of unity ------------------------------------------------------------------------------- @@ -356,46 +66,22 @@ Roots of unity Sets *z* to `x^n` where *t* contains precomputed powers of `x`. -Vector evaluation -------------------------------------------------------------------------------- - -.. function:: void acb_dirichlet_ui_chi_vec(ulong * v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv) - - Compute the list of exponent values *v[k]* for `0\leq k < nv`. - -.. function:: void acb_dirichlet_chi_vec(acb_ptr v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv, slong prec) - - Compute the *nv* first Dirichlet values. - -Character operations -------------------------------------------------------------------------------- - -.. function:: void acb_dirichlet_conrey_mul(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, const acb_dirichlet_conrey_t b) - -.. function:: void acb_dirichlet_char_mul(acb_dirichlet_char_t chi12, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2) - - Multiply two characters in the same group. - -.. function:: void acb_dirichlet_conrey_pow(acb_dirichlet_conrey_t c, const acb_dirichlet_group_t G, const acb_dirichlet_conrey_t a, ulong n) - - Take the power of some character. - Gauss and Jacobi sums ------------------------------------------------------------------------------- -.. function:: void acb_dirichlet_gauss_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) -.. function:: void acb_dirichlet_gauss_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) -.. function:: void acb_dirichlet_gauss_sum_order2(acb_t res, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_char_t chi, slong prec) -.. function:: void acb_dirichlet_gauss_sum_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) -.. function:: void acb_dirichlet_gauss_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) -.. function:: void acb_dirichlet_gauss_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, slong prec) +.. function:: void acb_dirichlet_gauss_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, slong prec) - Compute the Gauss sum + Sets *res* to the Gauss sum .. math:: @@ -419,17 +105,17 @@ Gauss and Jacobi sums - the *ui* version only takes the Conrey number *a* as parameter. -.. function:: void acb_dirichlet_jacobi_sum_naive(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +.. function:: 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) -.. function:: void acb_dirichlet_jacobi_sum_factor(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +.. function:: void acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) -.. function:: void acb_dirichlet_jacobi_sum_gauss(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +.. function:: void acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) -.. function:: void acb_dirichlet_jacobi_sum(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec) +.. function:: void acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) -.. function:: void acb_dirichlet_jacobi_sum_ui(acb_t res, const acb_dirichlet_group_t G, ulong a, ulong b, slong prec) +.. function:: void acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec) - Compute the Jacobi sum + Computes the Jacobi sum .. math:: @@ -463,9 +149,9 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define \Theta_q(a,t) = \sum_{n\geq 0} \chi_q(a, n) x(t)^{n^2}. -.. function:: void acb_dirichlet_chi_theta_arb(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, const arb_t t, slong prec) +.. function:: void acb_dirichlet_chi_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec) -.. function:: void acb_dirichlet_ui_theta_arb(acb_t res, const acb_dirichlet_group_t G, ulong a, const arb_t t, slong prec) +.. function:: void acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec) Compute the theta series `\Theta_q(a,t)` for real argument `t>0`. Beware that if `t<1` the functional equation @@ -516,13 +202,13 @@ the Fourier transform on Conrey labels as g(a) = \sum_{b\bmod q}\chi_q(a,b)f(b) -.. function:: void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) +.. function:: void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) Compute the DFT of *v* using Conrey indices. This function assumes *v* and *w* are vectors of size *G->phi_q*, whose values correspond to a lexicographic ordering - of Conrey logs (as obtained using :func:`acb_dirichlet_conrey_next` or - by :func:`acb_dirichlet_index_conrey`). + of Conrey logs (as obtained using :func:`dirichlet_conrey_next` or + by :func:`dirichlet_index_conrey`). For example, if `q=15`, the Conrey elements are stored in following order @@ -542,7 +228,7 @@ the Fourier transform on Conrey labels as 9 [1, 4] 11 ======= ============= ===================== -.. function:: void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const acb_dirichlet_group_t G, slong prec) +.. function:: void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) Compute the DFT of *v* using Conrey numbers. This function assumes *v* and *w* are vectors of size *G->q*. @@ -588,21 +274,22 @@ Simple functions L-functions ------------------------------------------------------------------------------- -.. function:: void acb_dirichlet_root_number_theta(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) -.. function:: void acb_dirichlet_root_number(acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) +.. function:: void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Sets *res* to the root number `\epsilon(\chi)` for a primitive character *chi*, which appears in the functional equation (where `p` is the parity of `\chi`): .. math:: - \frac{q}{π})^{\frac{s+p}2}\Gamma(\frac{s+p}2) L(s, \chi) = \epsilon(\chi) \frac{q}{π})^{\frac{1-s+p}2}\Gamma(\frac{1-s+p}2) L(1 - s, \overline\chi) + (\frac{q}{π})^{\frac{s+p}2}\Gamma(\frac{s+p}2) L(s, \chi) = \epsilon(\chi) (\frac{q}{π})^{\frac{1-s+p}2}\Gamma(\frac{1-s+p}2) L(1 - s, \overline\chi) - The *theta* variant uses the evaluation at `t=1` of the Theta series. - The default version computes it via the gauss sum. + - The *theta* variant uses the evaluation at `t=1` of the Theta series. -.. function:: void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec) + - The default version computes it via the gauss sum. + +.. function:: void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) Compute `L(s,\chi)` using decomposition in terms of the Hurwitz zeta function @@ -615,24 +302,9 @@ L-functions This formula is slow for large *q*. -.. function:: void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const acb_dirichlet_group_t G, slong prec) +.. function:: void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const dirichlet_group_t G, slong prec) Compute all values `L(s,\chi)` for `\chi` mod `q`, by Hurwitz formula and discrete Fourier transform. *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered Conrey logs. See :func:`acb_dirichlet_dft_conrey`. - -Implementation notes -------------------------------------------------------------------------------- - -The current implementation introduces a *char* type which contains a *conrey* -log plus additional information which - -- makes evaluation of a single character a bit faster - -- has some initialization cost. - -Even if it is straightforward to convert a *conrey* log to the -corresponding *char*, looping is faster at the -level of Conrey representation. Things can be improved on this aspect -but it makes code more intricate. diff --git a/doc/source/dirichlet.rst b/doc/source/dirichlet.rst new file mode 100644 index 00000000..5d5c8603 --- /dev/null +++ b/doc/source/dirichlet.rst @@ -0,0 +1,342 @@ +.. _dirichlet: + +**dirichlet.h** -- Dirichlet characters +=================================================================================== + +*Warning: the interfaces in this module are experimental and may change +without notice.* + +This module allows working with Dirichlet characters algebraically. +For evaluations of characters as complex numbers and Dirichlet L-functions, +see the :ref:`acb_dirichlet` module. + +Multiplicative group modulo *q* +------------------------------------------------------------------------------- + +Working with Dirichlet characters mod *q* consists mainly +in going from residue classes mod *q* to exponents on a set +of generators of the group. + +This implementation relies on the Conrey numbering scheme +introduced in the LMFDB, which is an explicit choice of isomorphism + +.. math:: + + (\mathbb Z/q\mathbb Z)^\times & \to &\bigoplus_i \mathbb Z/\phi_i\mathbb Z \\ + x & \mapsto & (e_i) + +We call *number* a residue class `x` modulo *q*, and *log* the +corresponding vector `(e_i)` of exponents of Conrey generators. + +Going from a *log* to the corresponding *number* is a cheap +operation called exp, while the converse requires computing discrete +logarithms. + +.. type:: dirichlet_group_struct + +.. type:: dirichlet_group_t + + Represents the group of Dirichlet characters mod *q*. + + An *dirichlet_group_t* is defined as an array of *dirichlet_group_struct* + of length 1, permitting it to be passed by reference. + +.. function:: void dirichlet_group_init(dirichlet_group_t G, ulong q) + + Initializes *G* to the group of Dirichlet characters mod *q*. + + This method computes a canonical decomposition of *G* in terms of cyclic + groups, which are the mod `p^e` subgroups for `p^e\|q`. + In particular *G* contains: + + - the number *num* of components + + - the generators + + - the exponent *expo* of the group + + It does *not* automatically precompute lookup tables + of discrete logarithms or numerical roots of unity, and can therefore + safely be called even with large *q*. + + For implementation reasons, the largest prime factor of *q* must not + exceed `10^{12}` (an abort will be raised). This restriction could + be removed in the future. + +.. function:: void dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h) + + Given an already computed group *G* mod `q`, initialize its subgroup *H* + defined mod `h\mid q`. Precomputed discrete log tables are inherited. + +.. function:: void dirichlet_group_clear(dirichlet_group_t G) + + Clears *G*. Remark this function does *not* clear the discrete logarithm + tables stored in *G* (which may be shared with another group). + +.. function:: void dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num) + + Precompute decomposition and tables for discrete log computations in *G*, + so as to minimize the complexity of *num* calls to discrete logarithms. + + If *num* gets very large, the entire group may be indexed. + +.. function:: void dirichlet_group_dlog_clear(dirichlet_group_t G, ulong num) + + Clear discrete logarithm tables in *G*. When discrete logarithm tables are + shared with subgroups, those subgroups must be cleared before clearing the + tables. + +Conrey elements +------------------------------------------------------------------------------- + +.. type:: dirichlet_conrey_struct + +.. type:: dirichlet_conrey_t + + Represents elements of the unit group mod *q*, keeping both the + *number* (residue class) and *log* (exponents on the group + generators). + +.. function:: void dirichlet_conrey_log(dirichlet_conrey_t x, const dirichlet_group_t G, ulong m) + + Sets *x* to the element of number *m*, computing its log using discrete + logarithm in *G*. + +.. function:: ulong dirichlet_conrey_exp(dirichlet_conrey_t x, const dirichlet_group_t G) + + Compute the reverse operation. + +.. function:: void dirichlet_conrey_one(dirichlet_conrey_t x, const dirichlet_group_t G) + + Sets *x* to the *number* `1\in G`, having *log* `[0,\dots 0]`. + +.. function:: void dirichlet_conrey_first_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) + + Sets *x* to the first primitive element of *G*, having *log* `[1,\dots 1]`, + or `[0, 1, \dots 1]` if `8\mid q`. + +.. function:: void dirichlet_conrey_set(dirichlet_conrey_t x, const dirichlet_group_t G, const dirichlet_conrey_t y) + + Sets *x* to the element *y*. + +.. function:: int dirichlet_conrey_next(dirichlet_conrey_t x, const dirichlet_group_t G) + + Sets *x* to the next conrey element in *G* with lexicographic ordering. + + The return value + is the index of the last updated exponent of *x*, or *-1* if the last + element has been reached. + + This function allows to iterate on the elements of *G* looping on their *log*. + Note that it produces elements in seemingly random *number* order. + + The following template can be used to loop over all elements *x* in *G*:: + + acb_conrey_one(x, G); + do { + /* use Conrey element x */ + } while (dirichlet_conrey_next(x, G) >= 0); + +.. function:: int dirichlet_conrey_next_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) + + Same as :func:`dirichlet_conrey_next`, but jumps to the next element + corresponding to a primitive character of *G*. + +.. function:: ulong dirichlet_index_conrey(const dirichlet_group_t G, const dirichlet_conrey_t x); + + Returns the lexicographic index of *x* as an integer in `0\dots \varphi(q)`. + +.. function:: void dirichlet_conrey_index(dirichlet_conrey_t x, const dirichlet_group_t G, ulong j) + + Sets *x* to the Conrey element of lexicographic index *j*. + +.. function:: int dirichlet_conrey_eq(const dirichlet_conrey_t x, const dirichlet_conrey_t y) + +.. function:: int dirichlet_conrey_eq_deep(const dirichlet_group_t G, const dirichlet_conrey_t x, const dirichlet_conrey_t y) + + Return 1 if *x* equals *y*. + The second version checks every byte of the representation and is intended for testing only. + +Dirichlet characters +------------------------------------------------------------------------------- + +Dirichlet characters take value in a finite cyclic group of roots of unity plus zero. + +When evaluation functions return a *ulong*, this number corresponds to the +power of a primitive root of unity, the special value *DIRICHLET_CHI_NULL* +encoding the zero value. + +The Conrey numbering scheme makes explicit the mathematical fact that +the group *G* is isomorphic to its dual, so that a character is described by +a *number*. + +.. math:: + + \begin{array}{ccccc} + (\mathbb Z/q\mathbb Z)^\times \times (\mathbb Z/q\mathbb Z)^\times & \to & \bigoplus_i \mathbb Z/\phi_i\mathbb Z \times \mathbb Z/\phi_i\mathbb Z & \to &\mathbb C \\ + (m,n) & \mapsto& (a_i,b_i) &\mapsto& \chi_q(m,n) = \exp(2i\pi\sum \frac{a_ib_i}{\phi_i} ) + \end{array} + +.. function:: ulong dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n) + +.. function:: ulong dirichlet_ui_pairing_conrey(const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) + + Compute the value of the Dirichlet pairing on numbers *m* and *n*, as + exponent modulo *G->expo*. + The second form takes the Conrey index *a* and *b*, and does not take discrete + logarithms. + + The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. + +Character type +------------------------------------------------------------------------------- + +.. type:: dirichlet_char_struct + +.. type:: dirichlet_char_t + + Represents a Dirichlet character. This structure contains various + useful invariants such as the order, the parity and the conductor of the character. + + An *dirichlet_char_t* is defined as an array of *dirichlet_char_struct* + of length 1, permitting it to be passed by reference. + +.. function:: void dirichlet_char_init(dirichlet_char_t chi, const dirichlet_group_t G) + + Initializes *chi* to an element of the group *G* and sets its value + to the principal character. + +.. function:: void dirichlet_char_clear(dirichlet_char_t chi) + + Clears *chi*. + +.. function:: void dirichlet_char(dirichlet_char_t chi, const dirichlet_group_t G, ulong n) + + Sets *chi* to the Dirichlet character of number *n*, using Conrey numbering scheme. + This function performs a discrete logarithm in *G*. + +.. function:: void dirichlet_char_conrey(dirichlet_char_t chi, const dirichlet_group_t G, const dirichlet_conrey_t x) + + Sets *chi* to the Dirichlet character corresponding to *x*. + +.. function:: int dirichlet_char_eq(const dirichlet_char_t chi1, const dirichlet_char_t chi2) + +.. function:: int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) + + Return 1 if *chi1* equals *chi2*. + The second version checks every byte of the representation and is intended for testing only. + +.. function:: int dirichlet_char_is_principal(const dirichlet_char_t chi) + + Return 1 if *chi* is the principal character mod *q*. + +.. function:: void dirichlet_char_one(dirichlet_char_t chi, const dirichlet_group_t G) + + Sets *chi* to the principal character. + +.. function:: void dirichlet_char_set(dirichlet_char_t chi1, const dirichlet_group_t G, const dirichlet_char_t chi2) + + Sets *chi1* to the character *chi2*. + +.. function:: int dirichlet_char_next(dirichlet_char_t chi, const dirichlet_group_t G) + + Sets *x* to the next character in *G* with lexicographic Conrey ordering + (see :func:`dirichlet_conrey_next`). The return value + is the index of the last updated exponent of *x*, or *-1* if the last + element has been reached. + +.. function:: int dirichlet_char_next_primitive(dirichlet_char_t chi, const dirichlet_group_t G) + + Like :func:`dirichlet_char_next`, but only generates primitive + characters. + +Character properties +------------------------------------------------------------------------------- + +As a consequence of the Conrey numbering, all these numbers are available at the +level of *number* and Conrey *log* elements, and for *char*. +No discrete log computation is performed. + +.. function:: ulong dirichlet_number_primitive(const dirichlet_group_t G) + + Return the number of primitive elements in *G*. + +.. function:: ulong dirichlet_ui_conductor(const dirichlet_group_t G, ulong a) + +.. function:: ulong dirichlet_conrey_conductor(const dirichlet_group_t G, const dirichlet_conrey_t x) + +.. function:: ulong dirichlet_char_conductor(const dirichlet_char_t chi) + + Return the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` + such `\chi_q(a,\cdot)` can be obtained as a character mod `r`. + This number is precomputed for the *char* type. + +.. function:: int dirichlet_ui_parity(const dirichlet_group_t G, ulong a) + +.. function:: int dirichlet_conrey_parity(const dirichlet_group_t G, const dirichlet_conrey_t x) + +.. function:: int dirichlet_char_parity(const dirichlet_char_t chi) + + Return the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that + `\chi_q(a,-1)=(-1)^\lambda`. + This number is precomputed for the *char* type. + +.. function:: ulong dirichlet_ui_order(const dirichlet_group_t G, ulong a) + +.. function:: ulong dirichlet_conrey_order(const dirichlet_group_t G, const dirichlet_conrey_t x) + +.. function:: ulong dirichlet_char_order(const dirichlet_char_t chi) + + Return the order of `\chi_q(a,\cdot)` which is the order of `a\bmod q`. + This number is precomputed for the *char* type. + +.. function:: int dirichlet_char_is_real(const dirichlet_char_t chi) + + Return 1 if *chi* is a real character (iff it has order `\leq 2`). + +Character evaluation +------------------------------------------------------------------------------- + +The image of a Dirichlet character is a finite cyclic group. Dirichlet +character evaluations are exponents in this group. + +.. function:: ulong dirichlet_ui_chi_conrey(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_conrey_t x) + +.. function:: ulong dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) + + Compute that value `\chi(n)` as the exponent mod the order of `\chi`. + +Vector evaluation +------------------------------------------------------------------------------- + +.. function:: void dirichlet_ui_chi_vec(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) + + Compute the list of exponent values *v[k]* for `0\leq k < nv`. + +Character operations +------------------------------------------------------------------------------- + +.. function:: void dirichlet_conrey_mul(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) + +.. function:: void dirichlet_char_mul(dirichlet_char_t chi12, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) + + Multiply two characters in the same group. + +.. function:: void dirichlet_conrey_pow(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, ulong n) + + Take the power of some character. + +Implementation notes +------------------------------------------------------------------------------- + +The current implementation introduces a *char* type which contains a *conrey* +log plus additional information which + +- makes evaluation of a single character a bit faster + +- has some initialization cost. + +Even if it is straightforward to convert a *conrey* log to the +corresponding *char*, looping is faster at the +level of Conrey representation. Things can be improved on this aspect +but it makes code more intricate. diff --git a/doc/source/index.rst b/doc/source/index.rst index 6b8b1264..43392787 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -118,10 +118,12 @@ modules. acb_hypgeom.rst arb_hypgeom.rst acb_modular.rst + dirichlet.rst acb_dirichlet.rst bernoulli.rst hypgeom.rst partitions.rst + acb_dft.rst Calculus :::::::::::::::::::::::::::::::::::: diff --git a/examples/lcentral.c b/examples/lcentral.c index f9ead358..e16ad598 100644 --- a/examples/lcentral.c +++ b/examples/lcentral.c @@ -47,15 +47,15 @@ int main(int argc, char *argv[]) for (q = qmin; q <= qmax; q++) { ulong k; - acb_dirichlet_group_t G; - acb_dirichlet_conrey_t x; + dirichlet_group_t G; + dirichlet_conrey_t x; acb_ptr z; if (q % 4 == 2) continue; - acb_dirichlet_group_init(G, q); - acb_dirichlet_conrey_init(x, G); + dirichlet_group_init(G, q); + dirichlet_conrey_init(x, G); z = _acb_vec_init(G->phi_q); @@ -64,11 +64,11 @@ int main(int argc, char *argv[]) if (out) { k = 0; - acb_dirichlet_conrey_one(x, G); - while (acb_dirichlet_conrey_next(x, G) >= 0) + dirichlet_conrey_one(x, G); + while (dirichlet_conrey_next(x, G) >= 0) { k++; - if (acb_dirichlet_conrey_conductor(G,x) < q) + if (dirichlet_conrey_conductor(G,x) < q) continue; flint_printf("%wu,%wu: ", q, x->n); acb_printd(z + k, digits); @@ -77,8 +77,8 @@ int main(int argc, char *argv[]) } _acb_vec_clear(z, G->phi_q); - acb_dirichlet_conrey_clear(x); - acb_dirichlet_group_clear(G); + dirichlet_conrey_clear(x); + dirichlet_group_clear(G); } acb_clear(s); From 30525ec26a5c5c5159cdd5c8d540116284259f04 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 6 Oct 2016 14:59:37 +0200 Subject: [PATCH 134/139] temporary remove acb_dft and hide theta internals --- Makefile.in | 2 +- acb_dft/dft_bluestein.c | 67 -------- acb_dft/dft_convol_fft.c | 105 ------------- acb_dft/dft_convol_naive.c | 31 ---- acb_dft/dft_crt.c | 176 --------------------- acb_dft/dft_cyc.c | 93 ----------- acb_dft/dft_fast.c.tmp | 278 --------------------------------- acb_dft/dft_pol.c | 62 -------- acb_dft/dft_precomp.c | 101 ------------ acb_dft/dft_prod.c | 67 -------- acb_dft/dft_rad2.c | 80 ---------- acb_dft/dft_step.c | 75 --------- acb_dft/test/t-convol.c | 118 -------------- acb_dft/test/t-dft.c | 127 --------------- acb_dirichlet.h | 6 - acb_dirichlet/dft.c | 60 ------- acb_dirichlet/l_vec_hurwitz.c | 65 -------- acb_dirichlet/test/t-dft.c | 125 --------------- acb_dirichlet/test/t-l.c | 74 --------- acb_dirichlet/vec_mellin_arb.c | 56 ------- doc/source/acb_dft.rst | 110 ------------- doc/source/acb_dirichlet.rst | 110 ------------- doc/source/index.rst | 1 - 23 files changed, 1 insertion(+), 1988 deletions(-) delete mode 100644 acb_dft/dft_bluestein.c delete mode 100644 acb_dft/dft_convol_fft.c delete mode 100644 acb_dft/dft_convol_naive.c delete mode 100644 acb_dft/dft_crt.c delete mode 100644 acb_dft/dft_cyc.c delete mode 100644 acb_dft/dft_fast.c.tmp delete mode 100644 acb_dft/dft_pol.c delete mode 100644 acb_dft/dft_precomp.c delete mode 100644 acb_dft/dft_prod.c delete mode 100644 acb_dft/dft_rad2.c delete mode 100644 acb_dft/dft_step.c delete mode 100644 acb_dft/test/t-convol.c delete mode 100644 acb_dft/test/t-dft.c delete mode 100644 acb_dirichlet/dft.c delete mode 100644 acb_dirichlet/l_vec_hurwitz.c delete mode 100644 acb_dirichlet/test/t-dft.c delete mode 100644 acb_dirichlet/vec_mellin_arb.c delete mode 100644 doc/source/acb_dft.rst diff --git a/Makefile.in b/Makefile.in index ad6ef5cc..c03a270d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13,7 +13,7 @@ QUIET_AR = @echo ' ' AR ' ' $@; AT=@ BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \ - acb_calc acb_hypgeom acb_modular dirichlet acb_dft acb_dirichlet arb_hypgeom bernoulli hypgeom \ + acb_calc acb_hypgeom acb_modular dirichlet acb_dirichlet arb_hypgeom bernoulli hypgeom \ fmpz_extras bool_mat partitions dlog \ $(EXTRA_BUILD_DIRS) diff --git a/acb_dft/dft_bluestein.c b/acb_dft/dft_bluestein.c deleted file mode 100644 index 3122c15d..00000000 --- a/acb_dft/dft_bluestein.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -void -acb_dft_bluestein_init(acb_dft_bluestein_t t, slong n, slong prec) -{ - - nmod_t n2; - slong k, k2; - acb_ptr z2n; - int e = n_clog(2 * n - 1, 2); - acb_dft_rad2_init(t->rad2, e, prec); - z2n = _acb_vec_init(2 * n); - _acb_vec_nth_roots(z2n, 2 * n, prec); - nmod_init(&n2, 2 * n); - t->n = n; - t->z = _acb_vec_init(n); - for (k = 0, k2 = 0; k < n; k++) - { - acb_conj(t->z + k, z2n + k2); - k2 = nmod_add(k2, 2 * k + 1, n2); - } - _acb_vec_clear(z2n, 2 * n); -} - -void -acb_dft_bluestein_precomp(acb_ptr w, acb_srcptr v, const acb_dft_bluestein_t t, slong prec) -{ - slong n = t->n; - acb_ptr vz, wz, z; - z = t->z; - /* TODO: allocate directly length 2^e and pad */ - flint_printf("\n\n====================\n\nv\n"); - acb_vec_printd_index(v, n, 10); - vz = _acb_vec_init(n); - acb_vec_kronecker_mul_conj(vz, z, v, n, prec); - flint_printf("\nvz\n"); - acb_vec_printd_index(vz, n, 10); - wz = _acb_vec_init(n); - acb_dft_convol_rad2_precomp(wz, vz, z, n, t->rad2, prec); - flint_printf("\nwz\n"); - acb_vec_printd_index(wz, n, 10); - acb_vec_kronecker_mul_conj(w, z, wz, n, prec); - flint_printf("\nw\n"); - acb_vec_printd_index(w, n, 10); - _acb_vec_clear(wz, n); - _acb_vec_clear(vz, n); -} - -void -acb_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec) -{ - acb_dft_bluestein_t t; - acb_dft_bluestein_init(t, len, prec); - acb_dft_bluestein_precomp(w, v, t, prec); - acb_dft_bluestein_clear(t); -} diff --git a/acb_dft/dft_convol_fft.c b/acb_dft/dft_convol_fft.c deleted file mode 100644 index cbfc863a..00000000 --- a/acb_dft/dft_convol_fft.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -/* assume np >= 2 * n - 1 */ -void -acb_dft_convol_pad(acb_ptr fp, acb_ptr gp, acb_srcptr f, acb_srcptr g, slong n, slong np) -{ - slong k; - - if (np < 2 * n - 1) - { - flint_printf("dft_convol_pad: overlapping padding %ld < 2*%ld-1\n", np, n); - abort(); - } - - for (k = 0; k < n; k++) - acb_set(gp + k, g + k); - for (; k < np; k++) - acb_zero(gp + k); - - for (k = 0; k < n; k++) - acb_set(fp + k, f + k); - for (k = 1; k < n; k++) - acb_set(fp + np - k, f + n - k); - for (k = n; k <= np - n; k++) - acb_zero(fp + k); - -} - -void -acb_dft_inverse_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) -{ - /* divide before to keep v const */ - _acb_vec_scalar_div_ui(w, v, len, len, prec); - acb_vec_swap_ri(w, len); - acb_dft_cyc(w, w, len, prec); - acb_vec_swap_ri(w, len); -} - -void -acb_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dft_rad2_t rad2, slong prec) -{ - slong np; - acb_ptr fp, gp; - np = rad2->n; - - flint_printf("\nf\n"); - acb_vec_printd_index(f, len, 10); - flint_printf("\ng\n"); - acb_vec_printd_index(g, len, 10); - - fp = _acb_vec_init(np); - gp = _acb_vec_init(np); - acb_dft_convol_pad(fp, gp, f, g, len, np); - - flint_printf("\nF\n"); - acb_vec_printd_index(fp, np, 10); - flint_printf("\nG\n"); - acb_vec_printd_index(gp, np, 10); - - acb_dft_rad2_precomp(fp, rad2, prec); - - flint_printf("\nDFT F\n"); - acb_vec_printd_index(fp, np, 10); - - acb_dft_rad2_precomp(gp, rad2, prec); - - flint_printf("\nDFT G\n"); - acb_vec_printd_index(gp, np, 10); - - _acb_vec_kronecker_mul(gp, gp, fp, np, prec); - - flint_printf("\n(DFT F)(DFT G)=DFT(F*G)\n"); - acb_vec_printd_index(gp, np, 10); - - acb_dft_inverse_rad2_precomp(gp, rad2, prec); - - flint_printf("\nF*G\n"); - acb_vec_printd_index(gp, np, 10); - - _acb_vec_set(w, gp, len); - _acb_vec_clear(fp, np); - _acb_vec_clear(gp, np); -} - -void -acb_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) -{ - int e; - acb_dft_rad2_t dft; - e = n_clog(2 * len - 1, 2); - acb_dft_rad2_init(dft, e, prec); - acb_dft_convol_rad2_precomp(w, f, g, len, dft, prec); - acb_dft_rad2_clear(dft); -} diff --git a/acb_dft/dft_convol_naive.c b/acb_dft/dft_convol_naive.c deleted file mode 100644 index 3131537a..00000000 --- a/acb_dft/dft_convol_naive.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -void -acb_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec) -{ - slong x, y; - for (x = 0; x < len; x ++) - { - acb_ptr wx; - acb_srcptr fx, gy; - wx = w + x; - fx = f + x; - gy = g; - acb_zero(wx); - for (y = 0; y <= x; y++) - acb_addmul(wx, fx - y, g + y, prec); - for (; y < len; y++) - acb_addmul(wx, fx + (len - y), g + y, prec); - } -} diff --git a/acb_dft/dft_crt.c b/acb_dft/dft_crt.c deleted file mode 100644 index a3603562..00000000 --- a/acb_dft/dft_crt.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -void -crt_init(crt_t c, ulong n) -{ - int k; - n_factor_t fac; - - n_factor_init(&fac); - n_factor(&fac, n, 1); - - nmod_init(&c->n, n); - - c->num = fac.num; - for (k = 0; k < fac.num; k++) - { - c->m[k] = n_pow(fac.p[k], fac.exp[k]); - c->M[k] = n / c->m[k]; - c->vM[k] = c->M[k] * n_invmod(c->M[k] % c->m[k], c->m[k]); - /* - flint_printf("m[%ld]=%ld, M[%ld]=%wu, vM[%ld]=%wu\n", - k, c->m[k], k, c->M[k], k, c->vM[k]); - */ - } -} - -void -crt_print(const crt_t c) -{ - slong k; - if (c->num == 0) - { - flint_printf("trivial group\n"); - abort(); - } - for (k = 0; k < c->num; k++) - flint_printf("Z/%wuZ ", c->m[k]); - flint_printf("\n"); -} - -#if 0 -/* lexicographic index of crt elt j */ -static ulong -index_crt(crt_t c, ulong j) -{ - int k; - ulong res = 0; - for (k = 0; k < c->num; k ++) - res = res * c->m[k] + (j % c->m[k]); - return res; -} - -/* crt elt of lexicographic index i */ -static ulong -crt_index(crt_t c, ulong i) -{ - int k; - ulong j, res = 0; - for (k = 0; k < c->num; k ++) - { - j = i % c->m[k]; - i = i / c->m[k]; - res = nmod_add(res, j * c->vM[k], c->n); - } - return res; -} -/* for all elements can do fast conrey-like loop just adding vM[k] */ -static acb_ptr -reorder_to_crt(acb_srcptr v, crt_t c, ulong len) -{ - ulong k; - acb_ptr res; - res = flint_malloc(len * sizeof(acb_struct)); - for (k = 0; k < len; k++) - res[index_crt(c, k)] = v[k]; - return res; -} -static acb_ptr -reorder_from_crt(acb_srcptr v, crt_t c, ulong len) -{ - ulong k; - acb_ptr res; - res = flint_malloc(len * sizeof(acb_struct)); - for (k = 0; k < len; k++) - res[k] = v[index_crt(c, k)]; - return res; -} -#endif - -void -crt_decomp(acb_ptr y, acb_srcptr x, slong dv, const crt_t c, ulong len) -{ - int j, e[CRT_MAX]; - ulong k, l; - - for (j = 0; j < c->num; j++) - e[j] = 0; - - l = 0; - for(k = 0; k < len; k++) - { - acb_set(y + k, x + l * dv); - for (j = c->num - 1; j >= 0; e[j] = 0, j--) - { - e[j]++; l = nmod_add(l, c->vM[j], c->n); - if (e[j] < c->m[j]) - break; - } - } -} - -void -crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len) -{ - int j, e[CRT_MAX]; - ulong k, l; - - for (j = 0; j < c->num; j++) - e[j] = 0; - - l = 0; - for(k = 0; k < len; k++) - { - acb_set(y + l, x + k); - for (j = c->num - 1; j >= 0; e[j] = 0, j--) - { - e[j]++; l = nmod_add(l, c->M[j], c->n); - if (e[j] < c->m[j]) - break; - } - } -} - -void -_acb_dft_crt_init(acb_dft_crt_t crt, slong dv, slong len, slong prec) -{ - crt->n = len; - crt_init(crt->c, len); - crt->dv = dv; - crt->cyc = _acb_dft_steps_prod(crt->c->m, crt->c->num, prec); -} - -void -acb_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dft_crt_t crt, slong prec) -{ - acb_ptr t; - t = _acb_vec_init(crt->n); - crt_decomp(w, v, crt->dv, crt->c, crt->n); - acb_dft_step(t, w, crt->cyc, crt->c->num, prec); - crt_recomp(w, t, crt->c, crt->n); - _acb_vec_clear(t, crt->n); -} - -void -acb_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec) -{ - crt_t c; - acb_ptr t; - t = _acb_vec_init(len); - crt_init(c, len); - crt_decomp(w, v, 1, c, len); - acb_dft_prod(t, w, c->m, c->num, prec); - crt_recomp(w, t, c, len); - _acb_vec_clear(t, len); -} diff --git a/acb_dft/dft_cyc.c b/acb_dft/dft_cyc.c deleted file mode 100644 index 732e15e3..00000000 --- a/acb_dft/dft_cyc.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -void -_acb_dft_cyc_init_z_fac(acb_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec) -{ - slong i, j, num; - t->n = len; - num = 0; - for (i = 0; i < fac.num; i++) - num += fac.exp[i]; - t->num = num; - t->cyc = flint_malloc(num * sizeof(acb_dft_step_struct)); - - if (z == NULL) - { - z = _acb_vec_init(t->n); - _acb_vec_nth_roots(z, t->n, prec); - dz = 1; - t->zclear = 1; - } - else - { - if (DFT_VERB) - flint_printf("dft_cyc: roots of order %wu already computed\n", t->n); - t->zclear = 0; - } - - t->z = z; - - num = 0; - for (i = 0; i < fac.num; i++) - { - for (j = 0; j < fac.exp[i]; j++) - { - slong m, M; - m = fac.p[i]; - M = (len /= m); - t->cyc[num].m = m; - t->cyc[num].M = M; - t->cyc[num].dv = dv; - t->cyc[num].z = z; - t->cyc[num].dz = dz; - /* TODO: ugly, reorder should solve this */ - if (num == t->num - 1) - _acb_dft_precomp_init(t->cyc[num].pre, dv, z, dz, m, prec); - else - _acb_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec); - dv *= m; - dz *= m; - num++; - } - } -} - -void -_acb_dft_cyc_init(acb_dft_cyc_t t, slong dv, slong len, slong prec) -{ - n_factor_t fac; - n_factor_init(&fac); - n_factor(&fac, len, 0); - _acb_dft_cyc_init_z_fac(t, fac, dv, NULL, 0, len, prec); -} - -void -acb_dft_cyc_clear(acb_dft_cyc_t t) -{ - slong i; - for (i = 0; i < t->num; i++) - acb_dft_precomp_clear(t->cyc[i].pre); - if (t->zclear) - _acb_vec_clear(t->z, t->n); - flint_free(t->cyc); -} - -void -acb_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec) -{ - acb_dft_cyc_t cyc; - acb_dft_cyc_init(cyc, len, prec); - acb_dft_cyc_precomp(w, v, cyc, prec); - acb_dft_cyc_clear(cyc); -} diff --git a/acb_dft/dft_fast.c.tmp b/acb_dft/dft_fast.c.tmp deleted file mode 100644 index 7d855639..00000000 --- a/acb_dft/dft_fast.c.tmp +++ /dev/null @@ -1,278 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" - -/* shallow extract */ -static acb_ptr -vec_extract(acb_srcptr v, slong step, slong len) -{ - slong k, l; - acb_ptr res; - res = flint_malloc(len * sizeof(acb_struct)); - for (k = 0, l = 0; k < len; k++, l+=step) - res[k] = v[l]; - return res; -} - -void -_acb_dft_base(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong n, slong prec) -{ - acb_ptr v1, z1; - v1 = vec_extract(v, dv, n); - z1 = vec_extract(z, dz, n); - _acb_dirichlet_dft_pol(w, v1, z1, n, prec); - flint_free(v1); - flint_free(z1); -} - -typedef struct -{ - slong m; - slong M; - slong dv; - acb_srcptr z; - slong dz; -} -dft_cyc_step; - -typedef struct -{ - slong n; - acb_ptr z; - slong num; - dft_cyc_step * cyc; -} -acb_dft_cyc_struct; - -typedef acb_dft_cyc_struct acb_dft_cyc_t[1]; - -typedef struct -{ - slong m; - slong M; - slong dv; - acb_dft_cyc_t pre; -} -dft_prod_step; - -typedef struct -{ - slong n; - slong num; - dft_prod_step * cyc; -} -acb_dft_prod_struct; - -typedef acb_dft_prod_struct acb_dft_prod_t[1]; - -void -_acb_dirichlet_dft_cyc_init(acb_dft_cyc_t t, slong len, slong dv, slong prec) -{ - slong i, j, num, dz; - n_factor_t fac; - acb_ptr z; - - t->n = len; - - n_factor_init(&fac); - n_factor(&fac, len, 0); - num = 0; - for (i = 0; i < fac.num; i++) - num += fac.exp[i]; - t->num = num; - t->cyc = flint_malloc(num * sizeof(dft_cyc_step)); - t->z = z = _acb_vec_init(t->n); - acb_dirichlet_vec_nth_roots(z, t->n, prec); - - num = 0; - dz = 1; - for (i = 0; i < fac.num; i++) - { - for (j = 0; j < fac.exp[i]; j++) - { - slong m = fac.p[i]; - t->cyc[num].m = m; - t->cyc[num].M = (len /= m); - t->cyc[num].dv = dv; - t->cyc[num].z = z; - t->cyc[num].dz = dz; - dv *= m; - dz *= m; - num++; - } - } -} - -static void -acb_dirichlet_dft_cyc_init(acb_dft_cyc_t t, slong len, slong prec) -{ - _acb_dirichlet_dft_cyc_init(t, len, 1, prec); -} - -void -acb_dirichlet_dft_cyc_clear(acb_dft_cyc_t t) -{ - _acb_vec_clear(t->z, t->n); - flint_free(t->cyc); -} - -void -_acb_dft_cyc(acb_ptr w, acb_srcptr v, dft_cyc_step * cyc, slong num, slong prec) -{ - dft_cyc_step c; - if (num == 0) - abort(); /* or just copy v to w */ - c = cyc[0]; - if (num == 1) - { - _acb_dft_base(w, v, c.dv, c.z, c.dz, c.m, prec); - } - else - { - slong i, j; - slong m = c.m, M = c.M, dv = c.dv, dz = c.dz; - acb_srcptr z = c.z, vi; - acb_ptr t, wi; - - t = _acb_vec_init(m * M); - wi = w; vi = v; - for (i = 0; i < m; i++) - { - _acb_dft_cyc(wi, vi, cyc + 1, num - 1, prec); - if (i) - { - for (j = 1; j < M; j++) - acb_mul(wi + j, wi + j, z + dz * i * j, prec); - } - wi += M; - vi += dv; - } - /* after first pass */ - for (j = 0; j < M; j++) - _acb_dft_base(t + m * j, w + j, M, z, dz * M, m, prec); - /* reorder */ - for (i = 0; i < m; i++) - for (j = 0; j < M; j++) - acb_set(w + j + M * i, t + i + m * j); - _acb_vec_clear(t, m * M); - } -} - -void -acb_dirichlet_dft_cyc_precomp(acb_ptr w, acb_srcptr v, acb_dft_cyc_t t, slong prec) -{ - _acb_dft_cyc(w, v, t->cyc, t->num, prec); -} - -void -acb_dirichlet_dft_fast(acb_ptr w, acb_srcptr v, slong len, slong prec) -{ - acb_dft_cyc_t t; - acb_dirichlet_dft_cyc_init(t, len, prec); - acb_dirichlet_dft_cyc_precomp(w, v, t, prec); - acb_dirichlet_dft_cyc_clear(t); -} - -void -_acb_dft_prod(acb_ptr w, acb_srcptr v, dft_prod_step * cyc, slong num, slong prec) -{ - dft_prod_step c; - if (num == 0) - { - flint_printf("error: reached num = 0 in dft_prod\n"); - abort(); /* or just copy v to w */ - } - c = cyc[0]; - if (num == 1) - { - acb_dirichlet_dft_cyc_precomp(w, v, c.pre, prec); - } - else - { - slong i, j; - slong m = c.m, M = c.M, dv = c.dv; - acb_srcptr vi; - acb_ptr t, wi; - - t = _acb_vec_init(m * M); - wi = w; vi = v; - for (i = 0; i < m; i++) - { - _acb_dft_prod(wi, vi, cyc + 1, num - 1, prec); - wi += M; - vi += dv; /* here = M */ - } - /* after first pass */ - for (j = 0; j < M; j++) - acb_dirichlet_dft_cyc_precomp(t + m * j, w + j, c.pre, prec); - /* reorder */ - for (i = 0; i < m; i++) - for (j = 0; j < M; j++) - acb_set(w + j + M * i, t + i + m * j); - _acb_vec_clear(t, m * M); - } -} - -void -acb_dirichlet_dft_prod_precomp(acb_ptr w, acb_srcptr v, acb_dft_prod_t t, slong prec) -{ - if (t->num == 0) - { - acb_set(w + 0, v + 0); - } - else - { - _acb_dft_prod(w, v, t->cyc, t->num, prec); - } -} - -void -acb_dirichlet_dft_prod_init(acb_dft_prod_t t, slong * cyc, slong num, slong prec) -{ - slong i, len, dv; - - t->num = num; - t->cyc = flint_malloc(num * sizeof(dft_prod_step)); - - len = 1; dv = 1; - for (i = 0; i < num; i++) - len *= cyc[i]; - - for (i = 0; i < num; i++) - { - slong m = cyc[i]; - len /= m; - t->cyc[i].m = m; - t->cyc[i].M = len; - t->cyc[i].dv = len; - _acb_dirichlet_dft_cyc_init(t->cyc[i].pre, m, len, prec); - dv *= m; - } -} - -void -acb_dirichlet_dft_prod_clear(acb_dft_prod_t t) -{ - slong i; - for (i = 0; i < t->num; i++) - acb_dirichlet_dft_cyc_clear(t->cyc[i].pre); - flint_free(t->cyc); -} - -void -acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) -{ - acb_dft_prod_t t; - acb_dirichlet_dft_prod_init(t, cyc, num, prec); - acb_dirichlet_dft_prod_precomp(w, v, t, prec); - acb_dirichlet_dft_prod_clear(t); -} diff --git a/acb_dft/dft_pol.c b/acb_dft/dft_pol.c deleted file mode 100644 index cc008015..00000000 --- a/acb_dft/dft_pol.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_poly.h" -#include "acb_dft.h" - -/* all roots are already computed */ -void -_acb_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec) -{ - slong i, j; - acb_ptr wi; - acb_srcptr vj; - - for (i = 0, wi = w; i < len; i++, wi++) - { - acb_zero(wi); - for (j = 0, vj = v; j < len; j++, vj += dv) - acb_addmul(wi, vj, z + dz * (i * j % len), prec); - } -} - -void -acb_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec) -{ - acb_ptr z; - z = _acb_vec_init(len); - _acb_vec_nth_roots(z, len, prec); - _acb_dft_pol(w, v, 1, z, 1, len, prec); - _acb_vec_clear(z, len); -} - -void -_acb_dft_pol_init(acb_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec) -{ - pol->n = len; - pol->dv = dv; - - if (z == NULL) - { - if (DFT_VERB) - flint_printf("warning: init z[%ld] in dft_pol, should be avoided\n",len); - pol->z = _acb_vec_init(len); - _acb_vec_nth_roots(pol->z, len, prec); - pol->dz = 1; - pol->zclear = 1; - } - else - { - pol->z = z; - pol->dz = dz; - pol->zclear = 0; - } -} diff --git a/acb_dft/dft_precomp.c b/acb_dft/dft_precomp.c deleted file mode 100644 index 2aba2d39..00000000 --- a/acb_dft/dft_precomp.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -void -_acb_dft_precomp_init(acb_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec) -{ - if (len <= 1) - { - flint_printf("precomp init: trivial group. abort.\n"); - abort(); - } - if (n_is_prime(len)) - { - /* TODO: need convolution if len is large */ - pre->type = DFT_POL; - _acb_dft_pol_init(pre->t.pol, dv, z, dz, len, prec); - } - else - { - n_factor_t fac; - - n_factor_init(&fac); - n_factor(&fac, len, 1); - - if (fac.num == 1) - { - /* TODO: could be p^e, or 2^e */ - pre->type = DFT_CYC; - _acb_dft_cyc_init_z_fac(pre->t.cyc, fac, dv, z, dz, len, prec); - } - else - { - pre->type = DFT_CRT; - _acb_dft_crt_init(pre->t.crt, dv, len, prec); - } - } -} - -void -acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec) -{ - _acb_dft_precomp_init(pre, 1, NULL, 0, len, prec); -} - -void -acb_dft_precomp_clear(acb_dft_pre_t pre) -{ - switch (pre->type) - { - case DFT_POL: - acb_dft_pol_clear(pre->t.pol); - break; - case DFT_CYC: - acb_dft_cyc_clear(pre->t.cyc); - break; - case DFT_PROD: - acb_dft_prod_clear(pre->t.prod); - break; - case DFT_CRT: - acb_dft_crt_clear(pre->t.crt); - break; - default: - flint_printf("acb_dft_clear: unknown strategy code %i\n", pre->type); - abort(); - break; - } -} - -void -acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec) -{ - switch (pre->type) - { - case DFT_POL: - acb_dft_pol_precomp(w, v, pre->t.pol, prec); - break; - case DFT_CYC: - acb_dft_cyc_precomp(w, v, pre->t.cyc, prec); - break; - case DFT_PROD: - acb_dft_prod_precomp(w, v, pre->t.prod, prec); - break; - case DFT_CRT: - acb_dft_crt_precomp(w, v, pre->t.crt, prec); - break; - default: - flint_printf("acb_dft_precomp: unknown strategy code %i\n", pre->type); - abort(); - break; - } -} diff --git a/acb_dft/dft_prod.c b/acb_dft/dft_prod.c deleted file mode 100644 index 0a4f2356..00000000 --- a/acb_dft/dft_prod.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -acb_dft_step_ptr -_acb_dft_steps_prod(slong * cyc, slong num, slong prec) -{ - slong i, len; - acb_dft_step_ptr s; - s = flint_malloc(num * sizeof(acb_dft_step_struct)); - - len = 1; - for (i = 0; i < num; i++) - len *= cyc[i]; - - for (i = 0; i < num; i++) - { - slong m, M; - m = cyc[i]; - M = (len /= m); - s[i].m = m; - s[i].M = M; - s[i].dv = M; - s[i].dz = 0; - s[i].z = NULL; - _acb_dft_precomp_init(s[i].pre, M, NULL, 0, m, prec); - } - - return s; -} - -void -acb_dft_prod_clear(acb_dft_prod_t t) -{ - slong i; - for (i = 0; i < t->num; i++) - acb_dft_precomp_clear(t->cyc[i].pre); - flint_free(t->cyc); -} - - -void -acb_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dft_prod_t prod, slong prec) -{ - if (prod->num == 0) - acb_set(w + 0, v + 0); - else - acb_dft_step(w, v, prod->cyc, prod->num, prec); -} - -void -acb_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec) -{ - acb_dft_prod_t t; - acb_dft_prod_init(t, cyc, num, prec); - acb_dft_prod_precomp(w, v, t, prec); - acb_dft_prod_clear(t); -} diff --git a/acb_dft/dft_rad2.c b/acb_dft/dft_rad2.c deleted file mode 100644 index 30f528d4..00000000 --- a/acb_dft/dft_rad2.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -/* swap each element with one with bit-reversed index */ -void -acb_dft_rad2_reorder(acb_ptr v, slong n) -{ - slong i, j, k, l; - - for (i = 0, l = n>>1; i < l; i++) - { - /* j = bit reversal of i */ - for (k = 1, j = 0; k < n; k <<= 1) - { - j <<= 1; - if (i & k) - j |= 1; - } - if (i < j) - acb_swap(v + i, v + j); - else if (i > j) - acb_swap(v + n - 1 - i, v + n - 1 - j); - i++, j |= l; - acb_swap(v + i, v + j); - } - -} - -/* remark: can use same rad2 with smaller power of 2 */ -void -acb_dft_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec) -{ - slong j, k, l; - slong n = rad2->n, nz = rad2->nz; - acb_ptr p, vend = v + n, w = rad2->z; - acb_t tmp; - acb_init(tmp); - - acb_dft_rad2_reorder(v, n); - - for (k = 1, l = nz; k < n; k <<= 1, l >>= 1) - for (p = v; p < vend; p += k) - for (j = 0; j < nz; j += l, p++) - { - acb_mul(tmp, p + k, w + j, prec); - acb_sub(p + k, p + 0, tmp, prec); - acb_add(p + 0, p + 0, tmp, prec); - } - - acb_clear(tmp); -} - -void -acb_dft_inverse_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec) -{ - slong k, n = rad2->n; - acb_dft_rad2_precomp(v, rad2, prec); - _acb_vec_scalar_mul_2exp_si(v, v, n, - rad2->e); - for (k = 1; k < n / 2; k++) - acb_swap(v + k, v + n - k); -} - -void -acb_dft_rad2(acb_ptr v, int e, slong prec) -{ - acb_dft_rad2_t rad2; - acb_dft_rad2_init(rad2, e, prec); - acb_dft_rad2_precomp(v, rad2, prec); - acb_dft_rad2_clear(rad2); -} diff --git a/acb_dft/dft_step.c b/acb_dft/dft_step.c deleted file mode 100644 index 019bd63d..00000000 --- a/acb_dft/dft_step.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -#define REORDER 0 - -void -acb_dft_step(acb_ptr w, acb_srcptr v, acb_dft_step_ptr cyc, slong num, slong prec) -{ - acb_dft_step_struct c; - if (num == 0) - { - flint_printf("error: reached num = 0 in acb_dft_step\n"); - abort(); /* or just copy v to w */ - } - c = cyc[0]; - if (num == 1) - { - acb_dft_precomp(w, v, c.pre, prec); - /*_acb_dft_base(w, v, c.dv, c.z, c.dz, c.m, prec);*/ - } - else - { - slong i, j; - slong m = c.m, M = c.M, dv = c.dv, dz = c.dz; - acb_srcptr z = c.z; - acb_ptr t; -#if REORDER - acb_ptr w2; -#endif - - t = _acb_vec_init(m * M); - - /* m DFT of size M */ - for (i = 0; i < m; i++) - acb_dft_step(w + i * M, v + i * dv, cyc + 1, num - 1, prec); - - /* twiddle if non trivial product */ - if (c.z != NULL) - { - acb_ptr wi; - for (wi = w + M, i = 1; i < m; i++, wi += M) - for (j = 1; j < M; j++) - acb_mul(wi + j, wi + j, z + dz * i * j, prec); - } - -#if REORDER - /* reorder w to avoid dv shifts in next DFT */ - w2 = flint_malloc(m * M * sizeof(acb_struct)); - for (j = 0; j < M; j++) - for (i = 0; i < m; i++) - w2[j + M * i] = w[i + m * j]; -#endif - - /* M DFT of size m */ - for (j = 0; j < M; j++) - acb_dft_precomp(t + m * j, w + j, c.pre, prec); - - /* reorder */ - for (i = 0; i < m; i++) - for (j = 0; j < M; j++) - acb_set(w + j + M * i, t + i + m * j); - - _acb_vec_clear(t, m * M); - } -} diff --git a/acb_dft/test/t-convol.c b/acb_dft/test/t-convol.c deleted file mode 100644 index 0cd780f6..00000000 --- a/acb_dft/test/t-convol.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -typedef void (*do_f) (acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec); - -void -check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char f1[], char f2[]) -{ - slong i; - - for (i = 0; i < len; i++) - { - if (!acb_overlaps(w1 + i, w2 + i)) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu, size = %wu\n", q, len); - flint_printf("\nDFT differ from index %ld / %ld \n", i, len); - flint_printf("\n%s =\n", f1); - acb_vec_printd_index(w1, len, digits); - flint_printf("\n%s =\n", f2); - acb_vec_printd_index(w2, len, digits); - flint_printf("\n\n"); - abort(); - } - else if (!acb_is_zero(w1+i) && (acb_rel_accuracy_bits(w1 + i) < 30 - || acb_rel_accuracy_bits(w2 + i) < 30)) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu\n", q); - flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); - flint_printf("\nnaive =\n"); - acb_printd(w1 + i, digits); - flint_printf("\nfast =\n"); - acb_printd(w2 + i, digits); - flint_printf("\nerrors %ld & %ld [prec = %wu]\n", - acb_rel_accuracy_bits(w1 + i), - acb_rel_accuracy_bits(w2 + i), prec); - abort(); - } - } -} - - -int main() -{ - - slong k; - slong prec = 100, digits = 30; - slong nq = 13; - ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; - flint_rand_t state; - - slong f, nf = 2; - do_f func[2] = { acb_dft_convol_naive, acb_dft_convol_rad2 }; - char * name[4] = { "naive", "rad2" }; - - flint_printf("convol...."); - fflush(stdout); - - flint_randinit(state); - - for (k = 0; k < nq; k++) - { - slong i; - acb_ptr z1, z2, x, y; - - z1 = _acb_vec_init(q[k]); - z2 = _acb_vec_init(q[k]); - x = _acb_vec_init(q[k]); - y = _acb_vec_init(q[k]); - - for (i = 0; i < q[k]; i++) - { - acb_set_si(x + i, q[k] - i); - acb_set_si(y + i, i * i); - /* - acb_set_si(x + i, n_randint(state, q[k])); - acb_set_si(y + i, n_randint(state, q[k])); - */ - } - - for (f = 0; f < nf; f++) - { - - acb_ptr z = (f == 0) ? z1 : z2; - - func[f](z, x, y, q[k], prec); - - if (f == 0) - continue; - - check_vec_eq_prec(z1, z2, q[k], prec, digits, q[k], name[0], name[f]); - - } - - _acb_vec_clear(x, q[k]); - _acb_vec_clear(y, q[k]); - _acb_vec_clear(z1, q[k]); - _acb_vec_clear(z2, q[k]); - } - - flint_randclear(state); - flint_cleanup(); - flint_printf("PASS\n"); - return EXIT_SUCCESS; -} - - diff --git a/acb_dft/test/t-dft.c b/acb_dft/test/t-dft.c deleted file mode 100644 index 23a4af97..00000000 --- a/acb_dft/test/t-dft.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" - -typedef void (*do_f) (acb_ptr w, acb_srcptr v, slong len, slong prec); - -void -check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char f1[], char f2[]) -{ - slong i; - - for (i = 0; i < len; i++) - { - if (!acb_overlaps(w1 + i, w2 + i)) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu, size = %wu\n", q, len); - flint_printf("\nDFT differ from index %ld / %ld \n", i, len); - flint_printf("\n%s =\n", f1); - acb_vec_printd_index(w1, len, digits); - flint_printf("\n%s =\n", f2); - acb_vec_printd_index(w2, len, digits); - flint_printf("\n\n"); - abort(); - } - else if (acb_rel_accuracy_bits(w1 + i) < 30 - || acb_rel_accuracy_bits(w2 + i) < 30) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu\n", q); - flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); - flint_printf("\nnaive =\n"); - acb_printd(w1 + i, digits); - flint_printf("\nfast =\n"); - acb_printd(w2 + i, digits); - flint_printf("\nerrors %ld & %ld [prec = %wu]\n", - acb_rel_accuracy_bits(w1 + i), - acb_rel_accuracy_bits(w2 + i), prec); - abort(); - } - } -} - - -int main() -{ - - slong k; - slong prec = 100, digits = 30; - slong nq = 13; - ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; - flint_rand_t state; - - slong f, nf = 4; - do_f func[4] = { acb_dft_pol, acb_dft_cyc, acb_dft_crt , acb_dft_bluestein }; - char * name[4] = { "pol", "cyc", "crt", "bluestein" }; - - flint_printf("dft...."); - fflush(stdout); - - flint_randinit(state); - - /* cyclic dft */ - for (k = 0; k < nq; k++) - { - slong i; - acb_ptr v, w1, w2; - - v = _acb_vec_init(q[k]); - w1 = _acb_vec_init(q[k]); - w2 = _acb_vec_init(q[k]); - - for (i = 0; i < q[k]; i++) - acb_set_si(v + i, i); - - for (f = 0; f < nf; f++) - { - - acb_ptr w = (f == 0) ? w1 : w2; - - func[f](w, v, q[k], prec); - - if (f == 0) - continue; - - check_vec_eq_prec(w1, w2, q[k], prec, digits, q[k], name[0], name[f]); - - } - - _acb_vec_clear(v, q[k]); - _acb_vec_clear(w1, q[k]); - _acb_vec_clear(w2, q[k]); - } - - /* radix2 dft */ - for (k = 1; k < 12; k++) - { - slong n = 1 << k, j; - acb_ptr v, w1, w2; - v = w2 = _acb_vec_init(n); - w1 = _acb_vec_init(n); - - for (j = 0; j < n; j++) - acb_set_si(v + k, k); - - acb_dft_pol(w1, v, n, prec); - acb_dft_rad2(v, k, prec); - - check_vec_eq_prec(w1, w2, n, prec, digits, n, "pol", "rad2"); - - } - - flint_randclear(state); - flint_cleanup(); - flint_printf("PASS\n"); - return EXIT_SUCCESS; -} - diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 8785a1ab..607e5e44 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -88,12 +88,6 @@ void acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirich void acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec); void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); -void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const dirichlet_group_t G, slong prec); - -/* Discrete Fourier Transform */ - -void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec); -void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec); /* utils */ diff --git a/acb_dirichlet/dft.c b/acb_dirichlet/dft.c deleted file mode 100644 index 6537b010..00000000 --- a/acb_dirichlet/dft.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dft.h" -#include "acb_dirichlet.h" - -/* dft, lexicographic conrey indexing, array size G->phi_q */ -void -acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) -{ - slong k, l, * cyc; - cyc = flint_malloc(G->num * sizeof(slong)); - for (k = 0, l = G->num - 1; l >= 0; k++, l--) - cyc[k] = G->P[k].phi; - - acb_dft_prod(w, v, cyc, G->num, prec); - flint_free(cyc); -} - -/* dft, number indexing, array size G->q */ -void -acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) -{ - ulong i, len; - acb_ptr t1, t2; - dirichlet_conrey_t x; - - len = G->phi_q; - t1 = flint_malloc(len * sizeof(acb_struct)); - - dirichlet_conrey_init(x, G); - dirichlet_conrey_one(x, G); - for (i = 0; i < len; i++) - { - t1[i] = v[x->n]; - dirichlet_conrey_next(x, G); - }; - - t2 = _acb_vec_init(len); - acb_dirichlet_dft_conrey(t2, t1, G, prec); - - dirichlet_conrey_one(x, G); - for (i = 0; i < len; i++) - { - acb_set(w + x->n, t2 + i); - dirichlet_conrey_next(x, G); - }; - - _acb_vec_clear(t2, len); - dirichlet_conrey_clear(x); - flint_free(t1); -} diff --git a/acb_dirichlet/l_vec_hurwitz.c b/acb_dirichlet/l_vec_hurwitz.c deleted file mode 100644 index 7bcabd99..00000000 --- a/acb_dirichlet/l_vec_hurwitz.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" -#include "acb_poly.h" - -void -acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, - const dirichlet_group_t G, slong prec) -{ - acb_t a, qs; - acb_ptr zeta, z; - dirichlet_conrey_t cn; - int deflate; - - /* remove pole in Hurwitz zeta at s = 1 */ - deflate = acb_is_one(s); - - dirichlet_conrey_init(cn, G); - acb_init(qs); - acb_init(a); - - prec += n_clog(G->phi_q, 2); - - acb_set_ui(qs, G->q); - acb_neg(a, s); - acb_pow(qs, qs, a, prec); - - zeta = z = _acb_vec_init(G->phi_q); - dirichlet_conrey_one(cn, G); - do { - - acb_set_ui(a, cn->n); - acb_div_ui(a, a, G->q, prec); - - if (!deflate) - acb_hurwitz_zeta(z, s, a, prec); - else - _acb_poly_zeta_cpx_series(z, s, a, 1, 1, prec); - - acb_mul(z, z, qs, prec); - - z++; - } while (dirichlet_conrey_next(cn, G) >= 0); - - acb_dirichlet_dft_conrey(res, zeta, G, prec); - - /* restore pole for the principal character */ - if (deflate) - acb_indeterminate(res); - - dirichlet_conrey_clear(cn); - _acb_vec_clear(zeta, G->phi_q); - acb_clear(qs); - acb_clear(a); -} - diff --git a/acb_dirichlet/test/t-dft.c b/acb_dirichlet/test/t-dft.c deleted file mode 100644 index 679ddfc0..00000000 --- a/acb_dirichlet/test/t-dft.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" - -typedef void (*do_f) (acb_ptr w, acb_srcptr v, slong len, slong prec); - -void -check_vec_eq_prec(acb_srcptr w1, acb_srcptr w2, slong len, slong prec, slong digits, ulong q, char f1[], char f2[]) -{ - slong i; - - for (i = 0; i < len; i++) - { - if (!acb_overlaps(w1 + i, w2 + i)) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu, size = %wu\n", q, len); - flint_printf("\nDFT differ from index %ld / %ld \n", i, len); - flint_printf("\n%s =\n", f1); - acb_vec_printd(w1, len, digits); - flint_printf("\n%s =\n", f2); - acb_vec_printd(w2, len, digits); - flint_printf("\n\n"); - abort(); - } - else if (acb_rel_accuracy_bits(w1 + i) < 30 - || acb_rel_accuracy_bits(w2 + i) < 30) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu\n", q); - flint_printf("\nDFT inaccurate from index %ld / %ld \n", i, len); - flint_printf("\nnaive =\n"); - acb_printd(w1 + i, digits); - flint_printf("\nfast =\n"); - acb_printd(w2 + i, digits); - flint_printf("\nerrors %ld & %ld [prec = %wu]\n", - acb_rel_accuracy_bits(w1 + i), - acb_rel_accuracy_bits(w2 + i), prec); - abort(); - } - } -} - - -int main() -{ - - slong k; - slong prec = 100, digits = 30; - slong nq = 13; - ulong q[13] = { 2, 3, 4, 5, 6, 23, 10, 15, 30, 59, 308, 335, 961}; - flint_rand_t state; - - flint_printf("dft...."); - fflush(stdout); - - flint_randinit(state); - - /* Dirichlet group DFT */ - for (k = 0; k < nq; k++) - { - slong i, j, len; - dirichlet_group_t G; - dirichlet_conrey_t x, y; - acb_t chiy; - acb_ptr v, w1, w2; - - dirichlet_group_init(G, q[k]); - - len = G->phi_q; - v = _acb_vec_init(len); - w1 = _acb_vec_init(len); - w2 = _acb_vec_init(len); - - dirichlet_conrey_init(x, G); - dirichlet_conrey_one(x, G); - for (i = 0; i < len; i++) - acb_randtest_precise(v + i, state, prec, 0); - - /* naive */ - acb_init(chiy); - dirichlet_conrey_init(y, G); - dirichlet_conrey_one(x, G); - for (i = 0; i < len; i++) - { - acb_zero(w1 + i); - dirichlet_conrey_one(y, G); - for (j = 0; j < len; j++) - { - acb_dirichlet_pairing_conrey(chiy, G, x, y, prec); - acb_addmul(w1 + i, chiy, v + j, prec); - dirichlet_conrey_next(y, G); - } - dirichlet_conrey_next(x, G); - } - acb_clear(chiy); - dirichlet_conrey_clear(y); - dirichlet_conrey_clear(x); - - /* dft */ - acb_dirichlet_dft_conrey(w2, v, G, prec); - - check_vec_eq_prec(w1, w2, len, prec, digits, q[k], "naive", "group"); - - _acb_vec_clear(v, len); - _acb_vec_clear(w1, len); - _acb_vec_clear(w2, len); - - dirichlet_group_clear(G); - } - - flint_randclear(state); - flint_cleanup(); - flint_printf("PASS\n"); - return EXIT_SUCCESS; -} diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index 395bbac4..e37a5efb 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -14,77 +14,6 @@ #define nq 5 #define nx 3 -void -test_dft(ulong q) -{ - ulong i; - slong prec = 100; - dirichlet_group_t G; - dirichlet_conrey_t x; - dirichlet_char_t chi; - acb_t s, z; - acb_ptr v; - - dirichlet_group_init(G, q); - dirichlet_conrey_init(x, G); - dirichlet_char_init(chi, G); - - acb_init(s); - acb_one(s); - acb_div_si(s, s, 2, prec); - - v = _acb_vec_init(G->phi_q); - - /* all at once */ - acb_dirichlet_l_vec_hurwitz(v, s, G, prec); - - /* check with complete loop */ - - i = 0; - acb_init(z); - dirichlet_conrey_one(x, G); - do { - - dirichlet_char_conrey(chi, G, x); - acb_dirichlet_l_hurwitz(z, s, G, chi, prec); - - if (!acb_overlaps(z, v + i)) - { - flint_printf("\n L value differ"); - flint_printf("\nL(1/2, %wu) single = ", x->n); - acb_printd(z, 20); - flint_printf("\nL(1/2, %wu) multi = ", x->n); - acb_printd(v + i, 20); - flint_printf("\n\n"); - acb_vec_printd(v, G->phi_q, 10); - flint_printf("\n\n"); - } - else if (acb_rel_accuracy_bits(z) < prec - 8 - || acb_rel_accuracy_bits(v + i) < prec - 8) - { - flint_printf("FAIL\n\n"); - flint_printf("q = %wu\n", q); - flint_printf("\nL(1/2,chi_%wu(%wu,)) inaccurate\n", q, x->n); - flint_printf("\nsingle =\n"); - acb_printd(z, 30); - flint_printf("\ndft =\n"); - acb_printd(v + i, 30); - flint_printf("\nerrors %ld & %ld [prec = %wu]\n", - acb_rel_accuracy_bits(z), - acb_rel_accuracy_bits(v + i), prec); - abort(); - } - - i++; - } while (dirichlet_conrey_next(x, G) >= 0); - - acb_clear(s); - _acb_vec_clear(v, G->phi_q); - dirichlet_char_clear(chi); - dirichlet_conrey_clear(x); - dirichlet_group_clear(G); -} - int main() { @@ -204,9 +133,6 @@ int main() dirichlet_char_clear(chi); dirichlet_group_clear(G); - /* test using dft */ - test_dft(q[i]); - } acb_clear(ref); acb_clear(res); diff --git a/acb_dirichlet/vec_mellin_arb.c b/acb_dirichlet/vec_mellin_arb.c deleted file mode 100644 index 45c5ad43..00000000 --- a/acb_dirichlet/vec_mellin_arb.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "acb_dirichlet.h" - -void -acb_dirichlet_vec_mellin_arb(acb_ptr res, const dirichlet_group_t G, const dirichlet_char_t chi, slong len, const arb_t t, slong n, slong prec) -{ - slong k; - arb_t tk, xt, stk, st; - acb_ptr a; - mag_t e; - a = _acb_vec_init(len); - acb_dirichlet_chi_vec(a, G, chi, len, prec); - if (chi->parity) - { - for (k = 2; k < len; k++) - acb_mul_si(a + k, a + k, k, prec); - } - arb_init(tk); - arb_init(xt); - arb_init(st); - arb_init(stk); - mag_init(e); - - arb_sqrt(st, t, prec); - arb_one(tk); - arb_one(stk); - for (k = 0; k < n; k++) - { - _acb_dirichlet_theta_argument_at_arb(xt, G->q, tk, prec); - mag_tail_kexpk2_arb(e, xt, len); - arb_neg(xt, xt); - arb_exp(xt, xt, prec); - /* TODO: reduce len */ - acb_dirichlet_qseries_arb(res + k, a, xt, len, prec); - acb_add_error_mag(res + k, e); - acb_mul_arb(res + k, res + k, stk, prec); - arb_mul(tk, tk, t, prec); - arb_mul(stk, stk, st, prec); - } - mag_clear(e); - arb_clear(xt); - arb_clear(tk); - arb_clear(stk); - arb_clear(st); - _acb_vec_clear(a, len); -} diff --git a/doc/source/acb_dft.rst b/doc/source/acb_dft.rst deleted file mode 100644 index 3f7ad27a..00000000 --- a/doc/source/acb_dft.rst +++ /dev/null @@ -1,110 +0,0 @@ -.. _acb-dft: - -**acb_dft.h** -- Discrete Fourier Transform on finite abelian groups -=================================================================================== - -*Warning: the interfaces in this module are experimental and may change -without notice.* - -Let *G* be a finite abelian group, and `\chi` a character of *G*. -For any map `f:G\to\mathbb C`, the discrete fourier transform -`\hat f:\hat G\to \mathbb C` is defined by - -.. math:: - - \hat f(\chi) = \sum_{x\in G}\overline{\chi(x)}f(x) - - -Fast Fourier Transform techniques allow to compute efficiently -all values `\hat f(\chi)` by reusing common computations. - -Specifically, if `H\triangleleft G` is a subgroup of size `M` and index -`[G:H]=m`, then writing `f_x(h)=f(xh)` the translate of `f` by representatives -`x` of `G/H`, one has a decomposition - -.. math:: - - \hat f(\chi) = \sum_{x\in G/H} \overline{\chi(x)} \hat{f_x}(\chi_{H}) - -so that the DFT on `G` can be computed using `m` DFT on `H` (of -appropriate translates of `f`), then `M` DFT on `G/H`, one for -each restriction `\chi_{H}`. - -This decomposition can be done recursively. - -Note that by inversion formula - -.. math:: - - \widehat{\hat f}(\chi) = \#G\times f(\chi^{-1}) - -it is straightforward to recover `f` from its DFT `\hat f`. - -DFT on Z/nZ -------------------------------------------------------------------------------- - -If `G=\mathbb Z/n\mathbb Z`, we compute the DFT according to the usual convention - -.. math:: - - w_x = \sum_{y\bmod n} v_y e^{-\frac{2iπ}nxy} - -.. function:: void acb_dirichlet_dft_pol(acb_ptr w, acb_srcptr v, slong n, slong prec) - -.. function:: void acb_dirichlet_dft_crt(acb_ptr w, acb_srcptr v, slong n, slong prec) - -.. function:: void acb_dirichlet_dft_cyc(acb_ptr w, acb_srcptr v, slong n, slong prec) - - Set *w* to the DFT of *v* of length *len*. - - The first variant uses the naive `O(n^2)` algorithm. - - The second one uses CRT to express `Z/nZ` as a product of cyclic groups. - - The *cyc* version uses each prime factor of `m` of `n` to decompose with - the subgroup `H=m\mathbb Z/n\mathbb Z`. - - -DFT on products -------------------------------------------------------------------------------- - -A finite abelian group is isomorphic to a product of cyclic components - -.. math:: - - G = \bigoplus_{i=1}^r \mathbb Z/n_i\mathbb Z - -then a character is a product of characters of all components and the DFT reads - -.. math:: - - \hat f(x_1,\dots x_r) = \sum_{y_1\dots y_r} f(y_1,\dots y_r) - e^{-2iπ\sum\frac{x_i y_i}{n_i}} - -We assume that `f` is given by a vector of length `\prod n_i` corresponding -to a lexicographic ordering of the values `y_1,\dots y_r`, and the computation -returns the same indexing for values of `\hat f`. - -.. function:: void acb_dirichlet_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); - - Computes the DFT on the group product of *num* cyclic components of sizes *cyc*. - -Precomputations -------------------------------------------------------------------------------- - -Convolution -------------------------------------------------------------------------------- - -For functions `f` and `g` on `G` we consider the convolution - -.. math:: - - (f \star g)(x) = \sum_{y\in G} f(x-y)g(y) - -which satisfies - -.. math:: - - \widehat{f \star g}(\chi) = \hat f(\chi)\hat g(\chi) - - diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index af2516d4..53f64094 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -34,38 +34,6 @@ Character evaluation Compute the *nv* first Dirichlet values. -Roots of unity -------------------------------------------------------------------------------- - -.. type:: acb_dirichlet_powers_struct - -.. type:: acb_dirichlet_powers_t - - This structure allows to compute *n* powers of a fixed root of unity of order *m* - using precomputations. Extremal cases are - - - all powers are stored: `O(m)` initialization + storage, `O(n)` evaluations - - - nothing stored: `O(1)` initialization + storage, `O(\log(m)n)` evaluations - - - `k` step decomposition: `O(k m^{\frac1k})` init + storage, `O((k-1)n)` evaluations. - - Currently, only baby-step giant-step decomposition (i.e. `k=2`) - is implemented, allowing to obtain each power using one multiplication. - -.. function:: void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec) - - Initialize the powers structure for *num* evaluations of powers of the root of unity - of order *order*. - -.. function:: void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t) - - Clears *t*. - -.. function:: void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec) - - Sets *z* to `x^n` where *t* contains precomputed powers of `x`. - Gauss and Jacobi sums ------------------------------------------------------------------------------- @@ -163,77 +131,6 @@ For `\Re(t)>0` we write `x(t)=\exp(-\frac{\pi}{N}t^2)` and define should be used, which is not done automatically (to avoid recomputing the Gauss sum). -.. function:: ulong acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec) - - Compute the number of terms to be summed in the theta series of argument *t* - so that the tail is less than `2^{-\mathrm{prec}}`. - -.. function:: void acb_dirichlet_qseries_powers_naive(acb_t res, const arb_t x, int p, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) - -.. function:: void acb_dirichlet_qseries_powers_smallorder(acb_t res, const arb_t x, int p, const ulong * a, const acb_dirichlet_powers_t z, slong len, slong prec) - - Compute the series `\sum n^p z^{a_n} x^{n^2}` for exponent list *a*, - precomputed powers *z* and parity *p* (being 0 or 1). - - The *naive* version sums the series as defined, while the *smallorder* - variant evaluates the series on the quotient ring by a cyclotomic polynomial - before evaluating at the root of unity, ignoring its argument *z*. - -Discrete Fourier Transforms (DFT) -------------------------------------------------------------------------------- - -Let *G* be a finite abelian group, and `\chi` a character of *G*. -For any map `f:G\to\mathbb C`, the discrete fourier transform -`\hat f:\hat G\to \mathbb C` is defined by - -.. math:: - - \hat f(\chi) = \sum_{x\in G}\chi(x)f(x) - -Fast Fourier Transform techniques allow to compute efficiently -all values `\hat f(\chi)`. - -For a Dirichlet group `G` modulo `q`, we take advantage -of the Conrey isomorphism `G \to \hat G` to consider the -the Fourier transform on Conrey labels as - -.. math:: - - g(a) = \sum_{b\bmod q}\chi_q(a,b)f(b) - - -.. function:: void acb_dirichlet_dft_conrey(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) - - Compute the DFT of *v* using Conrey indices. - This function assumes *v* and *w* are vectors - of size *G->phi_q*, whose values correspond to a lexicographic ordering - of Conrey logs (as obtained using :func:`dirichlet_conrey_next` or - by :func:`dirichlet_index_conrey`). - - For example, if `q=15`, the Conrey elements are stored in following - order - - ======= ============= ===================== - index log = [e,f] number = 7^e 11^f - ======= ============= ===================== - 0 [0, 0] 1 - 1 [0, 1] 7 - 2 [0, 2] 4 - 3 [0, 3] 13 - 4 [0, 4] 1 - 5 [1, 0] 11 - 6 [1, 1] 2 - 7 [1, 2] 14 - 8 [1, 3] 8 - 9 [1, 4] 11 - ======= ============= ===================== - -.. function:: void acb_dirichlet_dft(acb_ptr w, acb_srcptr v, const dirichlet_group_t G, slong prec) - - Compute the DFT of *v* using Conrey numbers. - This function assumes *v* and *w* are vectors of size *G->q*. - All values at index not coprime to *G->q* are ignored. - Euler products ------------------------------------------------------------------------------- @@ -301,10 +198,3 @@ L-functions is used to avoid poles. This formula is slow for large *q*. - -.. function:: void acb_dirichlet_l_vec_hurwitz(acb_ptr res, const acb_t s, const dirichlet_group_t G, slong prec) - - Compute all values `L(s,\chi)` for `\chi` mod `q`, by Hurwitz formula and - discrete Fourier transform. - *res* is assumed to have length *G->phi_q* and values are stored by lexicographically ordered - Conrey logs. See :func:`acb_dirichlet_dft_conrey`. diff --git a/doc/source/index.rst b/doc/source/index.rst index 43392787..17957ad2 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -123,7 +123,6 @@ modules. bernoulli.rst hypgeom.rst partitions.rst - acb_dft.rst Calculus :::::::::::::::::::::::::::::::::::: From 99b1882610fbce142b0250d66fb49c488ba23a4b Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 6 Oct 2016 15:02:35 +0200 Subject: [PATCH 135/139] forgot to remove acb_dft.h --- acb_dft.h | 325 ------------------------------------------------------ 1 file changed, 325 deletions(-) delete mode 100644 acb_dft.h diff --git a/acb_dft.h b/acb_dft.h deleted file mode 100644 index c73ccff8..00000000 --- a/acb_dft.h +++ /dev/null @@ -1,325 +0,0 @@ -/* - Copyright (C) 2015 Jonathan Bober - Copyright (C) 2016 Fredrik Johansson - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#ifndef ACB_DFT_H -#define ACB_DFT_H - -#ifdef ACB_DFT_INLINES_C -#define ACB_DFT_INLINE -#else -#define ACB_DFT_INLINE static __inline__ -#endif - -#include "acb.h" -#include "dlog.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void _acb_dft_pol(acb_ptr w, acb_srcptr v, slong dv, acb_srcptr z, slong dz, slong len, slong prec); -void acb_dft_pol(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dft_crt(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dft_rad2(acb_ptr v, int e, slong prec); -void acb_dft_bluestein(acb_ptr w, acb_srcptr v, slong len, slong prec); -void acb_dft_prod(acb_ptr w, acb_srcptr v, slong * cyc, slong num, slong prec); - -void acb_dft_convol_naive(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); -void acb_dft_convol_rad2(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, slong prec); - -#define CRT_MAX 15 -typedef struct -{ - int num; - nmod_t n; - slong m[CRT_MAX]; - ulong M[CRT_MAX]; - ulong vM[CRT_MAX]; -} -crt_struct; - -typedef crt_struct crt_t[1]; - -void crt_init(crt_t c, ulong n); - -void crt_decomp(acb_ptr y, acb_srcptr x, slong dx, const crt_t c, ulong len); -void crt_recomp(acb_ptr y, acb_srcptr x, const crt_t c, ulong len); - -typedef struct acb_dft_step_struct acb_dft_step_struct; -typedef acb_dft_step_struct * acb_dft_step_ptr; - -typedef struct -{ - slong n; - int zclear; - acb_ptr z; - slong num; - acb_dft_step_ptr cyc; -} -acb_dft_cyc_struct; - -typedef acb_dft_cyc_struct acb_dft_cyc_t[1]; - -typedef struct -{ - int e; - slong n; /* = 1 << e */ - slong nz; /* = n but could be bigger */ - acb_ptr z; -} -acb_dft_rad2_struct; - -typedef acb_dft_rad2_struct acb_dft_rad2_t[1]; - -typedef struct -{ - slong n; - acb_ptr z; - acb_dft_rad2_t rad2; -} -acb_dft_bluestein_struct; - -typedef acb_dft_bluestein_struct acb_dft_bluestein_t[1]; - -typedef struct -{ - slong n; - slong num; - acb_dft_step_ptr cyc; -} -acb_dft_prod_struct; - -typedef acb_dft_prod_struct acb_dft_prod_t[1]; - -typedef struct -{ - slong n; - crt_t c; - slong dv; - /* then a product */ - acb_dft_step_ptr cyc; -} -acb_dft_crt_struct; - -typedef acb_dft_crt_struct acb_dft_crt_t[1]; - -typedef struct -{ - slong n; - slong dv; - int zclear; - acb_ptr z; - slong dz; -} -acb_dft_pol_struct; - -typedef acb_dft_pol_struct acb_dft_pol_t[1]; - -typedef struct -{ - int type; - union - { - acb_dft_rad2_t rad2; - acb_dft_cyc_t cyc; - acb_dft_prod_t prod; - acb_dft_crt_t crt; - acb_dft_pol_t pol; - } t; -} -acb_dft_pre_struct; - -typedef acb_dft_pre_struct acb_dft_pre_t[1]; - -/* covers both product and cyclic case */ -struct -acb_dft_step_struct -{ - /* [G:H] */ - slong m; - /* card H */ - slong M; - slong dv; /* = M for prod, also = M if cyc is reordered */ - /* pointer on some roots of unity, if needed */ - acb_srcptr z; - /* index of mM in z */ - slong dz; - /* dft to call on H */ - acb_dft_pre_t pre; - /* dft to call on G/H ? */ -}; - -/*typedef acb_dft_pre_struct acb_dft_pre_t[1];*/ - -#define DFT_VERB 0 - -enum -{ - DFT_POL, DFT_CYC, DFT_PROD, DFT_CRT , DFT_RAD2 /*, DFT_CONV */ -}; - -void acb_dft_step(acb_ptr w, acb_srcptr v, acb_dft_step_ptr cyc, slong num, slong prec); - -void acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec); - -ACB_DFT_INLINE void -acb_dft_pol_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pol_t pol, slong prec) -{ - _acb_dft_pol(w, v, pol->dv, pol->z, pol->dz, pol->n, prec); -} -ACB_DFT_INLINE void -acb_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dft_cyc_t cyc, slong prec) -{ - acb_dft_step(w, v, cyc->cyc, cyc->num, prec); -} -void acb_dft_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec); -void acb_dft_crt_precomp(acb_ptr w, acb_srcptr v, const acb_dft_crt_t crt, slong prec); -void acb_dft_prod_precomp(acb_ptr w, acb_srcptr v, const acb_dft_prod_t prod, slong prec); - -void acb_dft_inverse_rad2_precomp(acb_ptr v, const acb_dft_rad2_t rad2, slong prec); -void acb_dft_convol_rad2_precomp(acb_ptr w, acb_srcptr f, acb_srcptr g, slong len, const acb_dft_rad2_t, slong prec); - -void _acb_dft_precomp_init(acb_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec); -void acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec); -void acb_dft_precomp_clear(acb_dft_pre_t pre); - -acb_dft_step_ptr _acb_dft_steps_prod(slong * m, slong num, slong prec); - -ACB_DFT_INLINE void -acb_dft_prod_init(acb_dft_prod_t t, slong * cyc, slong num, slong prec) -{ - t->num = num; - t->cyc = _acb_dft_steps_prod(cyc, num, prec); -} - -void acb_dft_prod_clear(acb_dft_prod_t t); - -void _acb_dft_cyc_init_z_fac(acb_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec); -void _acb_dft_cyc_init(acb_dft_cyc_t t, slong dv, slong len, slong prec); - -ACB_DFT_INLINE void -acb_dft_cyc_init(acb_dft_cyc_t t, slong len, slong prec) -{ - _acb_dft_cyc_init(t, 1, len, prec); -} - -void acb_dft_cyc_clear(acb_dft_cyc_t t); - -void _acb_dft_pol_init(acb_dft_pol_t pol, slong dv, acb_ptr z, slong dz, slong len, slong prec); - -ACB_DFT_INLINE void -acb_dft_pol_init(acb_dft_pol_t pol, slong len, slong prec) -{ - _acb_dft_pol_init(pol, 1, NULL, 0, len, prec); -} - -ACB_DFT_INLINE void -acb_dft_pol_clear(acb_dft_pol_t pol) -{ - if (pol->zclear) - _acb_vec_clear(pol->z, pol->n); -} - -ACB_DFT_INLINE void -acb_dft_rad2_init(acb_dft_rad2_t t, int e, slong prec) -{ - t->e = e; - t->n = 1 << e; - t->nz = t->n >> 1; - t->z = _acb_vec_init(t->nz); - /* set n/2 roots of order n */ - _acb_vec_nth_roots_pe(t->z, 2, e, t->nz, 1, prec); -} - -ACB_DFT_INLINE void -acb_dft_rad2_clear(acb_dft_rad2_t t) -{ - _acb_vec_clear(t->z, t->nz); -} - -void acb_dft_bluestein_init(acb_dft_bluestein_t t, slong n, slong prec); - -ACB_DFT_INLINE void -acb_dft_bluestein_clear(acb_dft_bluestein_t t) -{ - _acb_vec_clear(t->z, t->n); - acb_dft_rad2_clear(t->rad2); -} - -void _acb_dft_crt_init(acb_dft_crt_t crt, slong dv, slong len, slong prec); - -ACB_DFT_INLINE void -acb_dft_crt_init(acb_dft_crt_t crt, slong len, slong prec) -{ - crt->n = len; - crt_init(crt->c, len); - crt->dv = 1; - crt->cyc = _acb_dft_steps_prod(crt->c->m, crt->c->num, prec); -} - -ACB_DFT_INLINE void -acb_dft_crt_clear(acb_dft_crt_t crt) -{ - flint_free(crt->cyc); -} - -/* utils, could be moved elsewhere */ - -ACB_DFT_INLINE void -acb_swap_ri(acb_t x) -{ - arb_swap(acb_realref(x), acb_imagref(x)); -} - -ACB_DFT_INLINE void -acb_vec_swap_ri(acb_ptr v, slong len) -{ - slong k; - for (k = 0; k < len; k++) - acb_swap_ri(v + k); -} - -ACB_DFT_INLINE void -_acb_vec_kronecker_mul(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) -{ - slong k; - for (k = 0; k < len; k++) - acb_mul(z + k, x + k, y + k, prec); -} - -/* z[k] = conj(x[k])*y[k] */ -ACB_DFT_INLINE void -acb_vec_kronecker_mul_conj(acb_ptr z, acb_srcptr x, acb_srcptr y, slong len, slong prec) -{ - slong k; - for (k = 0; k < len; k++) - { - acb_conj(z + k, x + k); - acb_mul(z + k, z + k, y + k, prec); - } -} - -ACB_DFT_INLINE void -acb_vec_printd_index(acb_srcptr vec, slong len, slong digits) -{ - slong i; - for (i = 0; i < len; i++) - flint_printf("[%ld] ",i), acb_printd(vec + i, digits), flint_printf("\n"); -} - -#ifdef __cplusplus -} -#endif - -#endif From 949e3d2cb11abe7f29eb016feb92fcacbd72bb7c Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 6 Oct 2016 15:06:56 +0200 Subject: [PATCH 136/139] also remove lcentral (needs dft) --- examples/lcentral.c | 87 --------------------------------------------- 1 file changed, 87 deletions(-) delete mode 100644 examples/lcentral.c diff --git a/examples/lcentral.c b/examples/lcentral.c deleted file mode 100644 index e16ad598..00000000 --- a/examples/lcentral.c +++ /dev/null @@ -1,87 +0,0 @@ -/* This file is public domain. Author: Pascal Molin. */ - -#include -#include -#include "acb_dirichlet.h" - -static int usage(char *argv[]) -{ - printf("usage: %s [--quiet] [--prec ] qmin qmax\n", argv[0]); - return 1; -} - -int main(int argc, char *argv[]) -{ - int i, out = 1; - slong prec = 100, digits = 30; - ulong qmin, qmax, q; - acb_t s; - - if (argc < 3) - return usage(argv); - - for (i = 1; i < argc - 2; i++) - { - if (!strcmp(argv[i],"--quiet")) - out = 0; - else if (!strcmp(argv[i],"--prec")) - { - i++; - prec = atol(argv[i]); - digits = floor(prec * 0.3); - } - } - - if (argc < i + 2) - return usage(argv); - - qmin = atol(argv[i]); - qmax = atol(argv[i+1]); - - fflush(stdout); - - acb_init(s); - acb_one(s); - acb_div_si(s, s, 2, prec); - - for (q = qmin; q <= qmax; q++) - { - ulong k; - dirichlet_group_t G; - dirichlet_conrey_t x; - acb_ptr z; - - if (q % 4 == 2) - continue; - - dirichlet_group_init(G, q); - dirichlet_conrey_init(x, G); - - z = _acb_vec_init(G->phi_q); - - acb_dirichlet_l_vec_hurwitz(z, s, G, prec); - - if (out) - { - k = 0; - dirichlet_conrey_one(x, G); - while (dirichlet_conrey_next(x, G) >= 0) - { - k++; - if (dirichlet_conrey_conductor(G,x) < q) - continue; - flint_printf("%wu,%wu: ", q, x->n); - acb_printd(z + k, digits); - flint_printf("\n"); - } - } - - _acb_vec_clear(z, G->phi_q); - dirichlet_conrey_clear(x); - dirichlet_group_clear(G); - } - acb_clear(s); - - flint_cleanup(); - return EXIT_SUCCESS; -} From 846f4bcd584271edac08a227336b200541356258 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 7 Oct 2016 13:06:05 +0200 Subject: [PATCH 137/139] switch conrey->char->fullchar --- dirichlet.h | 113 ++++++++++++++--------------- dirichlet/char.c | 6 +- dirichlet/char_clear.c | 4 +- dirichlet/char_conrey.c | 12 +-- dirichlet/char_eq_deep.c | 8 +- dirichlet/char_first_primitive.c | 8 +- dirichlet/char_init.c | 4 +- dirichlet/char_mul.c | 6 +- dirichlet/char_next.c | 6 +- dirichlet/char_next_primitive.c | 6 +- dirichlet/char_normalize.c | 6 +- dirichlet/char_one.c | 4 +- dirichlet/char_primitive.c | 8 +- dirichlet/char_print.c | 8 +- dirichlet/conrey.c | 6 +- dirichlet/conrey_conductor.c | 2 +- dirichlet/conrey_eq_deep.c | 2 +- dirichlet/conrey_exp.c | 2 +- dirichlet/conrey_first_primitive.c | 4 +- dirichlet/conrey_index.c | 4 +- dirichlet/conrey_log.c | 2 +- dirichlet/conrey_mul.c | 2 +- dirichlet/conrey_next.c | 2 +- dirichlet/conrey_next_primitive.c | 2 +- dirichlet/conrey_one.c | 2 +- dirichlet/conrey_order.c | 2 +- dirichlet/conrey_parity.c | 2 +- dirichlet/conrey_pow.c | 2 +- dirichlet/conrey_primitive.c | 2 +- dirichlet/conrey_print.c | 2 +- dirichlet/index_conrey.c | 2 +- dirichlet/ui_chi.c | 12 +-- dirichlet/ui_chi_conrey.c | 2 +- dirichlet/ui_chi_vec.c | 2 +- dirichlet/ui_chi_vec_loop.c | 12 +-- dirichlet/ui_chi_vec_primeloop.c | 4 +- dirichlet/ui_pairing.c | 16 ++-- dirichlet/ui_pairing_conrey.c | 4 +- 38 files changed, 145 insertions(+), 148 deletions(-) diff --git a/dirichlet.h b/dirichlet.h index 62b6229a..01d0cfca 100644 --- a/dirichlet.h +++ b/dirichlet.h @@ -18,7 +18,6 @@ #define DIRICHLET_INLINE static __inline__ #endif -#include "acb.h" #include "dlog.h" #ifdef __cplusplus @@ -74,22 +73,22 @@ ulong dirichlet_ui_conductor(const dirichlet_group_t G, ulong a); int dirichlet_ui_parity(const dirichlet_group_t G, ulong a); ulong dirichlet_ui_order(const dirichlet_group_t G, ulong a); -/* elements of the group, keep both number and log */ +/* characters, keep both number and log */ typedef struct { ulong n; /* number */ ulong * log; /* s.t. prod generators[k]^log[k] = number */ } -dirichlet_conrey_struct; +dirichlet_char_struct; -typedef dirichlet_conrey_struct dirichlet_conrey_t[1]; +typedef dirichlet_char_struct dirichlet_char_t[1]; -void dirichlet_conrey_init(dirichlet_conrey_t x, const dirichlet_group_t G); -void dirichlet_conrey_clear(dirichlet_conrey_t x); -void dirichlet_conrey_print(const dirichlet_group_t G, const dirichlet_conrey_t x); +void dirichlet_char_init(dirichlet_char_t x, const dirichlet_group_t G); +void dirichlet_char_clear(dirichlet_char_t x); +void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t x); DIRICHLET_INLINE void -dirichlet_conrey_set(dirichlet_conrey_t x, const dirichlet_group_t G, const dirichlet_conrey_t y) +dirichlet_char_set(dirichlet_char_t x, const dirichlet_group_t G, const dirichlet_char_t y) { slong k; x->n = y->n; @@ -98,38 +97,38 @@ dirichlet_conrey_set(dirichlet_conrey_t x, const dirichlet_group_t G, const diri } DIRICHLET_INLINE int -dirichlet_conrey_eq(const dirichlet_conrey_t x, const dirichlet_conrey_t y) +dirichlet_char_eq(const dirichlet_char_t x, const dirichlet_char_t y) { return (x->n == y->n); } -int dirichlet_conrey_eq_deep(const dirichlet_group_t G, const dirichlet_conrey_t x, const dirichlet_conrey_t y); -int dirichlet_conrey_parity(const dirichlet_group_t G, const dirichlet_conrey_t x); -ulong dirichlet_conrey_conductor(const dirichlet_group_t G, const dirichlet_conrey_t x); -ulong dirichlet_conrey_order(const dirichlet_group_t G, const dirichlet_conrey_t x); +int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y); +int dirichlet_char_parity(const dirichlet_group_t G, const dirichlet_char_t x); +ulong dirichlet_char_conductor(const dirichlet_group_t G, const dirichlet_char_t x); +ulong dirichlet_char_order(const dirichlet_group_t G, const dirichlet_char_t x); -void dirichlet_conrey_log(dirichlet_conrey_t x, const dirichlet_group_t G, ulong m); -ulong dirichlet_conrey_exp(dirichlet_conrey_t x, const dirichlet_group_t G); +void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m); +ulong dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G); -void dirichlet_conrey_index(dirichlet_conrey_t x, const dirichlet_group_t G, ulong j); -ulong dirichlet_index_conrey(const dirichlet_group_t G, const dirichlet_conrey_t x); +void dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j); +ulong dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x); -void dirichlet_conrey_one(dirichlet_conrey_t x, const dirichlet_group_t G); -void dirichlet_conrey_first_primitive(dirichlet_conrey_t x, const dirichlet_group_t G); +void dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G); +void dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G); -int dirichlet_conrey_next(dirichlet_conrey_t x, const dirichlet_group_t G); -int dirichlet_conrey_next_primitive(dirichlet_conrey_t x, const dirichlet_group_t G); +int dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G); +int dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G); -void dirichlet_conrey_mul(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b); -void dirichlet_conrey_pow(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, ulong n); -void dirichlet_conrey_primitive(dirichlet_conrey_t y, const dirichlet_group_t G, const dirichlet_conrey_t x, ulong cond); +void dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); +void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n); +void dirichlet_char_primitive(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, ulong cond); #define DIRICHLET_CHI_NULL UWORD_MAX -ulong dirichlet_ui_pairing_conrey(const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b); +ulong dirichlet_ui_pairing_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); ulong dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n); -void dirichlet_pairing_conrey(acb_t res, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b, slong prec); +void dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec); void dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec); /* introducing character type */ @@ -139,39 +138,39 @@ typedef struct { ulong q; /* modulus */ nmod_t order; /* order */ - dirichlet_conrey_t x; + dirichlet_char_t x; ulong * expo; /* reduced exponents ( log[k] * PHI[k] / gcd( ) ) */ int parity; /* 0 for even char, 1 for odd */ ulong conductor; } -dirichlet_char_struct; +dirichlet_fullchar_struct; -typedef dirichlet_char_struct dirichlet_char_t[1]; +typedef dirichlet_fullchar_struct dirichlet_fullchar_t[1]; DIRICHLET_INLINE ulong -dirichlet_char_order(const dirichlet_char_t chi) +dirichlet_fullchar_order(const dirichlet_fullchar_t chi) { return chi->order.n; } DIRICHLET_INLINE ulong -dirichlet_char_conductor(const dirichlet_char_t chi) +dirichlet_fullchar_conductor(const dirichlet_fullchar_t chi) { return chi->conductor; } DIRICHLET_INLINE int -dirichlet_char_parity(const dirichlet_char_t chi) +dirichlet_fullchar_parity(const dirichlet_fullchar_t chi) { return chi->parity; } -void dirichlet_char_init(dirichlet_char_t chi, const dirichlet_group_t G); -void dirichlet_char_clear(dirichlet_char_t chi); -void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t chi); +void dirichlet_fullchar_init(dirichlet_fullchar_t chi, const dirichlet_group_t G); +void dirichlet_fullchar_clear(dirichlet_fullchar_t chi); +void dirichlet_fullchar_print(const dirichlet_group_t G, const dirichlet_fullchar_t chi); DIRICHLET_INLINE void -dirichlet_char_set(dirichlet_char_t chi1, const dirichlet_group_t G, const dirichlet_char_t chi2) +dirichlet_fullchar_set(dirichlet_fullchar_t chi1, const dirichlet_group_t G, const dirichlet_fullchar_t chi2) { slong k; @@ -179,51 +178,51 @@ dirichlet_char_set(dirichlet_char_t chi1, const dirichlet_group_t G, const diric chi1->conductor = chi2->conductor; chi1->order = chi2->order; chi1->parity = chi2->parity; - dirichlet_conrey_set(chi1->x, G, chi2->x); + dirichlet_char_set(chi1->x, G, chi2->x); for (k = 0; k < G->num; k++) chi1->expo[k] = chi2->expo[k]; } DIRICHLET_INLINE int -dirichlet_char_eq(const dirichlet_char_t chi1, const dirichlet_char_t chi2) +dirichlet_fullchar_eq(const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2) { return (chi1->q == chi2->q && chi1->x->n == chi2->x->n); } -int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2); +int dirichlet_fullchar_eq_deep(const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2); DIRICHLET_INLINE int -dirichlet_char_is_principal(const dirichlet_char_t chi) +dirichlet_fullchar_is_principal(const dirichlet_fullchar_t chi) { return (chi->x->n == 1); } DIRICHLET_INLINE int -dirichlet_char_is_real(const dirichlet_char_t chi) +dirichlet_fullchar_is_real(const dirichlet_fullchar_t chi) { return (chi->order.n <= 2); } -void dirichlet_char(dirichlet_char_t chi, const dirichlet_group_t G, ulong n); -void dirichlet_char_conrey(dirichlet_char_t chi, const dirichlet_group_t G, const dirichlet_conrey_t x); -void dirichlet_char_set_expo(dirichlet_char_t chi, const dirichlet_group_t G); -void dirichlet_char_normalize(dirichlet_char_t chi, const dirichlet_group_t G); -void dirichlet_char_denormalize(dirichlet_char_t chi, const dirichlet_group_t G); +void dirichlet_fullchar(dirichlet_fullchar_t chi, const dirichlet_group_t G, ulong n); +void dirichlet_fullchar_char(dirichlet_fullchar_t chi, const dirichlet_group_t G, const dirichlet_char_t x); +void dirichlet_fullchar_set_expo(dirichlet_fullchar_t chi, const dirichlet_group_t G); +void dirichlet_fullchar_normalize(dirichlet_fullchar_t chi, const dirichlet_group_t G); +void dirichlet_fullchar_denormalize(dirichlet_fullchar_t chi, const dirichlet_group_t G); -void dirichlet_char_mul(dirichlet_char_t chi12, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2); -void dirichlet_char_primitive(dirichlet_char_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_char_t chi); +void dirichlet_fullchar_mul(dirichlet_fullchar_t chi12, const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2); +void dirichlet_fullchar_primitive(dirichlet_fullchar_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_fullchar_t chi); -void dirichlet_char_one(dirichlet_char_t chi, const dirichlet_group_t G); -void dirichlet_char_first_primitive(dirichlet_char_t chi, const dirichlet_group_t G); +void dirichlet_fullchar_one(dirichlet_fullchar_t chi, const dirichlet_group_t G); +void dirichlet_fullchar_first_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G); -int dirichlet_char_next(dirichlet_char_t chi, const dirichlet_group_t G); -int dirichlet_char_next_primitive(dirichlet_char_t chi, const dirichlet_group_t G); +int dirichlet_fullchar_next(dirichlet_fullchar_t chi, const dirichlet_group_t G); +int dirichlet_fullchar_next_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G); -ulong dirichlet_ui_chi_conrey(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_conrey_t x); -ulong dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n); +ulong dirichlet_ui_chi_char(const dirichlet_group_t G, const dirichlet_fullchar_t chi, const dirichlet_char_t x); +ulong dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_fullchar_t chi, ulong n); void dirichlet_ui_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv); -void dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); -void dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); -void dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); +void dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv); +void dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv); +void dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv); #ifdef __cplusplus } diff --git a/dirichlet/char.c b/dirichlet/char.c index 1cc00012..c8f57ad9 100644 --- a/dirichlet/char.c +++ b/dirichlet/char.c @@ -12,8 +12,8 @@ #include "dirichlet.h" void -dirichlet_char(dirichlet_char_t chi, const dirichlet_group_t G, ulong n) +dirichlet_fullchar(dirichlet_fullchar_t chi, const dirichlet_group_t G, ulong n) { - dirichlet_conrey_log(chi->x, G, n); - dirichlet_char_conrey(chi, G, NULL); + dirichlet_char_log(chi->x, G, n); + dirichlet_fullchar_char(chi, G, NULL); } diff --git a/dirichlet/char_clear.c b/dirichlet/char_clear.c index f5e28e26..f4432c79 100644 --- a/dirichlet/char_clear.c +++ b/dirichlet/char_clear.c @@ -12,8 +12,8 @@ #include "dirichlet.h" void -dirichlet_char_clear(dirichlet_char_t chi) +dirichlet_fullchar_clear(dirichlet_fullchar_t chi) { - dirichlet_conrey_clear(chi->x); + dirichlet_char_clear(chi->x); flint_free(chi->expo); } diff --git a/dirichlet/char_conrey.c b/dirichlet/char_conrey.c index 44dd304d..4f82fbfa 100644 --- a/dirichlet/char_conrey.c +++ b/dirichlet/char_conrey.c @@ -14,19 +14,19 @@ /* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd * so that log = expo[k] */ void -dirichlet_char_conrey(dirichlet_char_t chi, const dirichlet_group_t G, const dirichlet_conrey_t x) +dirichlet_fullchar_char(dirichlet_fullchar_t chi, const dirichlet_group_t G, const dirichlet_char_t x) { /* assume chi->x already set if x == NULL */ if (x == NULL) x = chi->x; else - dirichlet_conrey_set(chi->x, G, x); + dirichlet_char_set(chi->x, G, x); chi->q = G->q; - chi->parity = dirichlet_conrey_parity(G, x); - chi->conductor = dirichlet_conrey_conductor(G, x); + chi->parity = dirichlet_char_parity(G, x); + chi->conductor = dirichlet_char_conductor(G, x); - dirichlet_char_set_expo(chi, G); + dirichlet_fullchar_set_expo(chi, G); /* optional: divide by gcd to obtain true order */ - dirichlet_char_normalize(chi, G); + dirichlet_fullchar_normalize(chi, G); } diff --git a/dirichlet/char_eq_deep.c b/dirichlet/char_eq_deep.c index 2d02a69e..d4e845f6 100644 --- a/dirichlet/char_eq_deep.c +++ b/dirichlet/char_eq_deep.c @@ -12,9 +12,9 @@ #include "dirichlet.h" int -dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) +dirichlet_fullchar_eq_deep(const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2) { - dirichlet_conrey_t x, y; + dirichlet_char_t x, y; if (chi1->q != chi2->q) return 0; @@ -25,13 +25,13 @@ dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t chi1, c if (chi1->conductor != chi2->conductor) return 0; - if (!dirichlet_conrey_eq_deep(G, chi1->x, chi2->x)) + if (!dirichlet_char_eq_deep(G, chi1->x, chi2->x)) return 0; x->n = y->n = 1; x->log = chi1->expo; y->log = chi2->expo; - if (!dirichlet_conrey_eq_deep(G, x, y)) + if (!dirichlet_char_eq_deep(G, x, y)) return 0; return 1; diff --git a/dirichlet/char_first_primitive.c b/dirichlet/char_first_primitive.c index 8bddcd24..acf378a3 100644 --- a/dirichlet/char_first_primitive.c +++ b/dirichlet/char_first_primitive.c @@ -12,9 +12,9 @@ #include "dirichlet.h" void -dirichlet_char_first_primitive(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_first_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G) { - dirichlet_conrey_first_primitive(chi->x, G); - dirichlet_char_conrey(chi, G, NULL); - dirichlet_char_normalize(chi, G); + dirichlet_char_first_primitive(chi->x, G); + dirichlet_fullchar_char(chi, G, NULL); + dirichlet_fullchar_normalize(chi, G); } diff --git a/dirichlet/char_init.c b/dirichlet/char_init.c index cbef6829..67d5c9a6 100644 --- a/dirichlet/char_init.c +++ b/dirichlet/char_init.c @@ -12,10 +12,10 @@ #include "dirichlet.h" void -dirichlet_char_init(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_init(dirichlet_fullchar_t chi, const dirichlet_group_t G) { slong k; - dirichlet_conrey_init(chi->x, G); + dirichlet_char_init(chi->x, G); chi->expo = flint_malloc(G->num * sizeof(ulong)); chi->q = G->q; chi->conductor = 1; diff --git a/dirichlet/char_mul.c b/dirichlet/char_mul.c index e4b596cd..28ceee77 100644 --- a/dirichlet/char_mul.c +++ b/dirichlet/char_mul.c @@ -12,8 +12,8 @@ #include "dirichlet.h" void -dirichlet_char_mul(dirichlet_char_t chi12, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) +dirichlet_fullchar_mul(dirichlet_fullchar_t chi12, const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2) { - dirichlet_conrey_mul(chi12->x, G, chi1->x, chi2->x); - dirichlet_char_conrey(chi12, G, NULL); + dirichlet_char_mul(chi12->x, G, chi1->x, chi2->x); + dirichlet_fullchar_char(chi12, G, NULL); } diff --git a/dirichlet/char_next.c b/dirichlet/char_next.c index 315d8525..f00206a0 100644 --- a/dirichlet/char_next.c +++ b/dirichlet/char_next.c @@ -12,11 +12,11 @@ #include "dirichlet.h" int -dirichlet_char_next(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_next(dirichlet_fullchar_t chi, const dirichlet_group_t G) { int k; - k = dirichlet_conrey_next(chi->x, G); - dirichlet_char_conrey(chi, G, NULL); + k = dirichlet_char_next(chi->x, G); + dirichlet_fullchar_char(chi, G, NULL); /* return last index modified */ return k; } diff --git a/dirichlet/char_next_primitive.c b/dirichlet/char_next_primitive.c index abfcc364..eba33457 100644 --- a/dirichlet/char_next_primitive.c +++ b/dirichlet/char_next_primitive.c @@ -12,11 +12,11 @@ #include "dirichlet.h" int -dirichlet_char_next_primitive(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_next_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G) { int k; - k = dirichlet_conrey_next_primitive(chi->x, G); - dirichlet_char_conrey(chi, G, NULL); + k = dirichlet_char_next_primitive(chi->x, G); + dirichlet_fullchar_char(chi, G, NULL); /* return last index modified */ return k; } diff --git a/dirichlet/char_normalize.c b/dirichlet/char_normalize.c index 9905a105..a7287c74 100644 --- a/dirichlet/char_normalize.c +++ b/dirichlet/char_normalize.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_char_set_expo(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_set_expo(dirichlet_fullchar_t chi, const dirichlet_group_t G) { slong k; for (k = 0; k < G->num; k++) @@ -21,7 +21,7 @@ dirichlet_char_set_expo(dirichlet_char_t chi, const dirichlet_group_t G) } void -dirichlet_char_normalize(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_normalize(dirichlet_fullchar_t chi, const dirichlet_group_t G) { ulong k, g; g = G->expo; @@ -36,7 +36,7 @@ dirichlet_char_normalize(dirichlet_char_t chi, const dirichlet_group_t G) } void -dirichlet_char_denormalize(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_denormalize(dirichlet_fullchar_t chi, const dirichlet_group_t G) { ulong k, g; g = G->expo / chi->order.n; diff --git a/dirichlet/char_one.c b/dirichlet/char_one.c index a133e7c3..7f872555 100644 --- a/dirichlet/char_one.c +++ b/dirichlet/char_one.c @@ -12,10 +12,10 @@ #include "dirichlet.h" void -dirichlet_char_one(dirichlet_char_t chi, const dirichlet_group_t G) +dirichlet_fullchar_one(dirichlet_fullchar_t chi, const dirichlet_group_t G) { slong k; - dirichlet_conrey_one(chi->x, G); + dirichlet_char_one(chi->x, G); chi->q = G->q; chi->conductor = 1; chi->parity = 0; diff --git a/dirichlet/char_primitive.c b/dirichlet/char_primitive.c index 3172a593..c8fc771f 100644 --- a/dirichlet/char_primitive.c +++ b/dirichlet/char_primitive.c @@ -12,13 +12,13 @@ #include "dirichlet.h" void -dirichlet_char_primitive(dirichlet_char_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_char_t chi) +dirichlet_fullchar_primitive(dirichlet_fullchar_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_fullchar_t chi) { chi0->q = chi->conductor; chi0->parity = chi->parity; chi0->conductor = chi->conductor; - dirichlet_conrey_primitive(chi0->x, G, chi->x, chi->conductor); - dirichlet_char_set_expo(chi0, G0); + dirichlet_char_primitive(chi0->x, G, chi->x, chi->conductor); + dirichlet_fullchar_set_expo(chi0, G0); /* optional: divide by gcd to obtain true order */ - dirichlet_char_normalize(chi0, G0); + dirichlet_fullchar_normalize(chi0, G0); } diff --git a/dirichlet/char_print.c b/dirichlet/char_print.c index 62031b0b..6898bfe2 100644 --- a/dirichlet/char_print.c +++ b/dirichlet/char_print.c @@ -12,12 +12,12 @@ #include "dirichlet.h" void -dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t chi) +dirichlet_fullchar_print(const dirichlet_group_t G, const dirichlet_fullchar_t chi) { - dirichlet_conrey_t x; + dirichlet_char_t x; flint_printf("chi_%wu(%wu,.) of order %wu, parity %wd, index ", G->q, chi->x->n, chi->order, chi->parity); - dirichlet_conrey_print(G, chi->x); + dirichlet_char_print(G, chi->x); flint_printf(" and exponents "); x->log = chi->expo; - dirichlet_conrey_print(G, x); + dirichlet_char_print(G, x); } diff --git a/dirichlet/conrey.c b/dirichlet/conrey.c index 8c76683f..ec5b864b 100644 --- a/dirichlet/conrey.c +++ b/dirichlet/conrey.c @@ -12,12 +12,12 @@ #include "dirichlet.h" void -dirichlet_conrey_init(dirichlet_conrey_t x, const dirichlet_group_t G) { +dirichlet_char_init(dirichlet_char_t x, const dirichlet_group_t G) { x->log = flint_malloc(G->num * sizeof(ulong)); - dirichlet_conrey_one(x, G); + dirichlet_char_one(x, G); } void -dirichlet_conrey_clear(dirichlet_conrey_t x) { +dirichlet_char_clear(dirichlet_char_t x) { flint_free(x->log); } diff --git a/dirichlet/conrey_conductor.c b/dirichlet/conrey_conductor.c index f346432e..24afc2b9 100644 --- a/dirichlet/conrey_conductor.c +++ b/dirichlet/conrey_conductor.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_conrey_conductor(const dirichlet_group_t G, const dirichlet_conrey_t x) +dirichlet_char_conductor(const dirichlet_group_t G, const dirichlet_char_t x) { int k, f; ulong cond = 1; diff --git a/dirichlet/conrey_eq_deep.c b/dirichlet/conrey_eq_deep.c index 08950ca3..8c01650f 100644 --- a/dirichlet/conrey_eq_deep.c +++ b/dirichlet/conrey_eq_deep.c @@ -12,7 +12,7 @@ #include "dirichlet.h" int -dirichlet_conrey_eq_deep(const dirichlet_group_t G, const dirichlet_conrey_t x, const dirichlet_conrey_t y) +dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y) { slong k; diff --git a/dirichlet/conrey_exp.c b/dirichlet/conrey_exp.c index 12498a36..c978347d 100644 --- a/dirichlet/conrey_exp.c +++ b/dirichlet/conrey_exp.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_conrey_exp(dirichlet_conrey_t x, const dirichlet_group_t G) +dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G) { ulong k, n = 1; for (k = 0; k < G->num; k++) diff --git a/dirichlet/conrey_first_primitive.c b/dirichlet/conrey_first_primitive.c index 1415e764..fa0d1834 100644 --- a/dirichlet/conrey_first_primitive.c +++ b/dirichlet/conrey_first_primitive.c @@ -12,12 +12,12 @@ #include "dirichlet.h" void -dirichlet_conrey_first_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) +dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G) { ulong k; if (G->q % 4 == 2) { - flint_printf("Exception (dirichlet_conrey_first_primitive). No primitive element mod %wu.\n",G->q); + flint_printf("Exception (dirichlet_char_first_primitive). No primitive element mod %wu.\n",G->q); abort(); } x->n = 1; diff --git a/dirichlet/conrey_index.c b/dirichlet/conrey_index.c index e9acc235..ddea9463 100644 --- a/dirichlet/conrey_index.c +++ b/dirichlet/conrey_index.c @@ -26,7 +26,7 @@ #include "dirichlet.h" void -dirichlet_conrey_index(dirichlet_conrey_t x, const dirichlet_group_t G, ulong j) +dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j) { slong k; @@ -36,5 +36,5 @@ dirichlet_conrey_index(dirichlet_conrey_t x, const dirichlet_group_t G, ulong j) j = j / G->P[k].phi; } - dirichlet_conrey_exp(x, G); + dirichlet_char_exp(x, G); } diff --git a/dirichlet/conrey_log.c b/dirichlet/conrey_log.c index 15a640f6..e53245ad 100644 --- a/dirichlet/conrey_log.c +++ b/dirichlet/conrey_log.c @@ -16,7 +16,7 @@ /* assume m is invertible */ void -dirichlet_conrey_log(dirichlet_conrey_t x, const dirichlet_group_t G, ulong m) +dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m) { slong k; /* even part */ diff --git a/dirichlet/conrey_mul.c b/dirichlet/conrey_mul.c index df3a5376..a8071405 100644 --- a/dirichlet/conrey_mul.c +++ b/dirichlet/conrey_mul.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_conrey_mul(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) +dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b) { ulong k; for (k = 0; k < G->num ; k++) diff --git a/dirichlet/conrey_next.c b/dirichlet/conrey_next.c index e9c7cc8f..4a1db3c1 100644 --- a/dirichlet/conrey_next.c +++ b/dirichlet/conrey_next.c @@ -12,7 +12,7 @@ #include "dirichlet.h" int -dirichlet_conrey_next(dirichlet_conrey_t x, const dirichlet_group_t G) +dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G) { /* update index */ int k; diff --git a/dirichlet/conrey_next_primitive.c b/dirichlet/conrey_next_primitive.c index 521e161c..a39b6fc1 100644 --- a/dirichlet/conrey_next_primitive.c +++ b/dirichlet/conrey_next_primitive.c @@ -12,7 +12,7 @@ #include "dirichlet.h" int -dirichlet_conrey_next_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) +dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G) { /* update index avoiding multiples of p except for first component if 8|q */ diff --git a/dirichlet/conrey_one.c b/dirichlet/conrey_one.c index 252889d0..ed3c760b 100644 --- a/dirichlet/conrey_one.c +++ b/dirichlet/conrey_one.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_conrey_one(dirichlet_conrey_t x, const dirichlet_group_t G) +dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G) { ulong k; for (k = 0; k < G->num ; k++) diff --git a/dirichlet/conrey_order.c b/dirichlet/conrey_order.c index 23008de9..d8da6fc7 100644 --- a/dirichlet/conrey_order.c +++ b/dirichlet/conrey_order.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_conrey_order(const dirichlet_group_t G, const dirichlet_conrey_t x) +dirichlet_char_order(const dirichlet_group_t G, const dirichlet_char_t x) { ulong k, g; g = G->expo; diff --git a/dirichlet/conrey_parity.c b/dirichlet/conrey_parity.c index 91a47b3f..3ba6d181 100644 --- a/dirichlet/conrey_parity.c +++ b/dirichlet/conrey_parity.c @@ -12,7 +12,7 @@ #include "dirichlet.h" int -dirichlet_conrey_parity(const dirichlet_group_t G, const dirichlet_conrey_t x) +dirichlet_char_parity(const dirichlet_group_t G, const dirichlet_char_t x) { int k, odd = 0; for (k = 0; k < G->num; k++) diff --git a/dirichlet/conrey_pow.c b/dirichlet/conrey_pow.c index 5a70aa8f..3a682bd7 100644 --- a/dirichlet/conrey_pow.c +++ b/dirichlet/conrey_pow.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_conrey_pow(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, ulong n) +dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n) { ulong k; for (k = 0; k < G->num ; k++) diff --git a/dirichlet/conrey_primitive.c b/dirichlet/conrey_primitive.c index 2c657576..2a73c64b 100644 --- a/dirichlet/conrey_primitive.c +++ b/dirichlet/conrey_primitive.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_conrey_primitive(dirichlet_conrey_t y, const dirichlet_group_t G, const dirichlet_conrey_t x, ulong cond) +dirichlet_char_primitive(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, ulong cond) { slong k, l; diff --git a/dirichlet/conrey_print.c b/dirichlet/conrey_print.c index 3c5970f1..c90dc666 100644 --- a/dirichlet/conrey_print.c +++ b/dirichlet/conrey_print.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_conrey_print(const dirichlet_group_t G, const dirichlet_conrey_t x) +dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t x) { slong k; if (G->num) diff --git a/dirichlet/index_conrey.c b/dirichlet/index_conrey.c index e55783f5..4747d4e4 100644 --- a/dirichlet/index_conrey.c +++ b/dirichlet/index_conrey.c @@ -26,7 +26,7 @@ #include "dirichlet.h" ulong -dirichlet_index_conrey(const dirichlet_group_t G, const dirichlet_conrey_t x) +dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x) { slong k; ulong j = 0; diff --git a/dirichlet/ui_chi.c b/dirichlet/ui_chi.c index 8166a0f1..7133e614 100644 --- a/dirichlet/ui_chi.c +++ b/dirichlet/ui_chi.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) +dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_fullchar_t chi, ulong n) { if (n_gcd(G->q, n) > 1) { @@ -21,13 +21,13 @@ dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) else { ulong v; - dirichlet_conrey_t x; - dirichlet_conrey_init(x, G); - dirichlet_conrey_log(x, G, n); + dirichlet_char_t x; + dirichlet_char_init(x, G); + dirichlet_char_log(x, G, n); - v = dirichlet_ui_chi_conrey(G, chi, x); + v = dirichlet_ui_chi_char(G, chi, x); - dirichlet_conrey_clear(x); + dirichlet_char_clear(x); return v; } } diff --git a/dirichlet/ui_chi_conrey.c b/dirichlet/ui_chi_conrey.c index 37af059b..44f93fcc 100644 --- a/dirichlet/ui_chi_conrey.c +++ b/dirichlet/ui_chi_conrey.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_ui_chi_conrey(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_conrey_t x) +dirichlet_ui_chi_char(const dirichlet_group_t G, const dirichlet_fullchar_t chi, const dirichlet_char_t x) { ulong v = 0, k; diff --git a/dirichlet/ui_chi_vec.c b/dirichlet/ui_chi_vec.c index bc16cc75..92ca6817 100644 --- a/dirichlet/ui_chi_vec.c +++ b/dirichlet/ui_chi_vec.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) +dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) { if (2 * nv > G->q) dirichlet_ui_chi_vec_loop(v, G, chi, nv); diff --git a/dirichlet/ui_chi_vec_loop.c b/dirichlet/ui_chi_vec_loop.c index 2e71d6fd..8ff81d76 100644 --- a/dirichlet/ui_chi_vec_loop.c +++ b/dirichlet/ui_chi_vec_loop.c @@ -13,21 +13,21 @@ /* loop over whole group */ void -dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) +dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) { int j; ulong t; slong k; - dirichlet_conrey_t x; - dirichlet_conrey_init(x, G); - dirichlet_conrey_one(x, G); + dirichlet_char_t x; + dirichlet_char_init(x, G); + dirichlet_char_one(x, G); for (k = 0; k < nv; k++) v[k] = DIRICHLET_CHI_NULL; t = v[1] = 0; - while ( (j = dirichlet_conrey_next(x, G)) >= 0 ) + while ( (j = dirichlet_char_next(x, G)) >= 0 ) { /* exponents were modified up to j */ for (k = G->num - 1; k >= j; k--) @@ -44,5 +44,5 @@ dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_c for (k = G->q; k < nv ; k++ ) v[k] = v[k - G->q]; - dirichlet_conrey_clear(x); + dirichlet_char_clear(x); } diff --git a/dirichlet/ui_chi_vec_primeloop.c b/dirichlet/ui_chi_vec_primeloop.c index 2d415537..31dd4ca7 100644 --- a/dirichlet/ui_chi_vec_primeloop.c +++ b/dirichlet/ui_chi_vec_primeloop.c @@ -12,7 +12,7 @@ #include "dirichlet.h" static void -chi_vec_evenpart(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) +chi_vec_evenpart(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) { ulong c3, c4, x; @@ -47,7 +47,7 @@ chi_vec_evenpart(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi /* loop over primary components */ void -dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) +dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) { slong k, l; diff --git a/dirichlet/ui_pairing.c b/dirichlet/ui_pairing.c index e6d21baf..4d572ff4 100644 --- a/dirichlet/ui_pairing.c +++ b/dirichlet/ui_pairing.c @@ -15,20 +15,20 @@ ulong dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n) { ulong x; - dirichlet_conrey_t a, b; + dirichlet_char_t a, b; if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) return DIRICHLET_CHI_NULL; - dirichlet_conrey_init(a, G); - dirichlet_conrey_init(b, G); - dirichlet_conrey_log(a, G, m); - dirichlet_conrey_log(b, G, n); + dirichlet_char_init(a, G); + dirichlet_char_init(b, G); + dirichlet_char_log(a, G, m); + dirichlet_char_log(b, G, n); - x = dirichlet_ui_pairing_conrey(G, a, b); + x = dirichlet_ui_pairing_char(G, a, b); - dirichlet_conrey_clear(a); - dirichlet_conrey_clear(b); + dirichlet_char_clear(a); + dirichlet_char_clear(b); return x; } diff --git a/dirichlet/ui_pairing_conrey.c b/dirichlet/ui_pairing_conrey.c index cd6638e7..3488f873 100644 --- a/dirichlet/ui_pairing_conrey.c +++ b/dirichlet/ui_pairing_conrey.c @@ -13,10 +13,8 @@ #include "dirichlet.h" -/* todo: modular arithmetic */ - ulong -dirichlet_ui_pairing_conrey(const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) +dirichlet_ui_pairing_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b) { ulong x, k; x = 0; From e0bdb9438bd27a594e0bc94235c047169671a13c Mon Sep 17 00:00:00 2001 From: Pascal Date: Sat, 8 Oct 2016 17:22:19 +0200 Subject: [PATCH 138/139] remove all conrey --- acb_dirichlet.h | 4 +- acb_dirichlet/chi.c | 4 +- acb_dirichlet/chi_vec.c | 7 +- acb_dirichlet/gauss_sum.c | 26 +- acb_dirichlet/gauss_sum_factor.c | 12 +- acb_dirichlet/gauss_sum_order2.c | 8 +- acb_dirichlet/gauss_sum_theta.c | 7 +- acb_dirichlet/jacobi_sum.c | 20 +- acb_dirichlet/jacobi_sum_factor.c | 17 +- acb_dirichlet/jacobi_sum_gauss.c | 2 +- acb_dirichlet/jacobi_sum_naive.c | 33 ++- acb_dirichlet/l_hurwitz.c | 25 +- acb_dirichlet/pairing.c | 2 +- acb_dirichlet/pairing_conrey.c | 4 +- acb_dirichlet/root_number.c | 4 +- acb_dirichlet/test/t-chi.c | 12 +- acb_dirichlet/test/t-gauss.c | 21 +- acb_dirichlet/test/t-jacobi.c | 7 +- acb_dirichlet/test/t-l.c | 2 +- acb_dirichlet/test/t-thetanull.c | 18 +- acb_dirichlet/theta_arb.c | 27 +- acb_dirichlet/ui_theta_arb.c | 2 +- dirichlet.h | 124 ++------- dirichlet/char.c | 19 -- dirichlet/char_clear.c | 19 -- dirichlet/char_conrey.c | 32 --- dirichlet/char_eq_deep.c | 38 --- dirichlet/char_first_primitive.c | 20 -- dirichlet/char_init.c | 26 -- dirichlet/char_mul.c | 19 -- dirichlet/char_next.c | 22 -- dirichlet/char_next_primitive.c | 22 -- dirichlet/char_normalize.c | 46 ---- dirichlet/char_primitive.c | 24 -- dirichlet/char_print.c | 23 -- dirichlet/{ui_chi.c => chi.c} | 4 +- dirichlet/{char_one.c => chi_char.c} | 19 +- dirichlet/chi_vec.c | 30 +++ .../{ui_chi_vec_loop.c => chi_vec_loop.c} | 26 +- dirichlet/chi_vec_primeloop.c | 82 ++++++ dirichlet/conrey_conductor.c | 2 +- dirichlet/conrey_index.c | 6 +- dirichlet/conrey_lift.c | 36 +++ dirichlet/conrey_log.c | 2 +- dirichlet/conrey_lower.c | 42 ++++ dirichlet/conrey_mul.c | 2 +- dirichlet/conrey_next.c | 2 +- dirichlet/conrey_next_primitive.c | 4 +- dirichlet/conrey_order.c | 2 +- dirichlet/conrey_parity.c | 2 +- dirichlet/conrey_pow.c | 2 +- dirichlet/conrey_primitive.c | 47 ---- dirichlet/group_init.c | 22 +- dirichlet/index_conrey.c | 2 +- dirichlet/{ui_pairing.c => pairing.c} | 4 +- dirichlet/test/t-chars.c | 235 +++++++++--------- dirichlet/test/t-conrey.c | 153 ------------ dirichlet/test/t-properties.c | 199 +++++++++++++++ {acb_dirichlet => dirichlet}/test/t-vec.c | 36 ++- dirichlet/ui_chi_conrey.c | 24 -- dirichlet/ui_chi_vec.c | 21 -- dirichlet/ui_chi_vec_primeloop.c | 72 ------ dirichlet/ui_conductor.c | 2 +- dirichlet/ui_order.c | 2 +- dirichlet/ui_pairing_conrey.c | 26 -- dirichlet/ui_parity.c | 2 +- dirichlet/ui_vec_set_null.c | 2 +- 67 files changed, 757 insertions(+), 1053 deletions(-) delete mode 100644 dirichlet/char.c delete mode 100644 dirichlet/char_clear.c delete mode 100644 dirichlet/char_conrey.c delete mode 100644 dirichlet/char_eq_deep.c delete mode 100644 dirichlet/char_first_primitive.c delete mode 100644 dirichlet/char_init.c delete mode 100644 dirichlet/char_mul.c delete mode 100644 dirichlet/char_next.c delete mode 100644 dirichlet/char_next_primitive.c delete mode 100644 dirichlet/char_normalize.c delete mode 100644 dirichlet/char_primitive.c delete mode 100644 dirichlet/char_print.c rename dirichlet/{ui_chi.c => chi.c} (83%) rename dirichlet/{char_one.c => chi_char.c} (60%) create mode 100644 dirichlet/chi_vec.c rename dirichlet/{ui_chi_vec_loop.c => chi_vec_loop.c} (57%) create mode 100644 dirichlet/chi_vec_primeloop.c create mode 100644 dirichlet/conrey_lift.c create mode 100644 dirichlet/conrey_lower.c delete mode 100644 dirichlet/conrey_primitive.c rename dirichlet/{ui_pairing.c => pairing.c} (87%) delete mode 100644 dirichlet/test/t-conrey.c create mode 100644 dirichlet/test/t-properties.c rename {acb_dirichlet => dirichlet}/test/t-vec.c (51%) delete mode 100644 dirichlet/ui_chi_conrey.c delete mode 100644 dirichlet/ui_chi_vec.c delete mode 100644 dirichlet/ui_chi_vec_primeloop.c delete mode 100644 dirichlet/ui_pairing_conrey.c diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 607e5e44..7330f572 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -32,8 +32,8 @@ void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); -void acb_dirichlet_pairing_conrey(acb_t res, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b, slong prec); void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec); +void acb_dirichlet_chi_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec); /* precompute powers of a root of unity */ typedef struct @@ -71,7 +71,7 @@ void acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, c void acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); -void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_char_t chi, slong prec); +void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec); diff --git a/acb_dirichlet/chi.c b/acb_dirichlet/chi.c index e8b1d6b2..3d67536c 100644 --- a/acb_dirichlet/chi.c +++ b/acb_dirichlet/chi.c @@ -17,14 +17,14 @@ void acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec) { ulong expo; - expo = dirichlet_ui_chi(G, chi, n); + expo = dirichlet_chi(G, chi, n); if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else { fmpq_t t; fmpq_init(t); - fmpq_set_si(t, 2 * expo , chi->order.n); + fmpq_set_si(t, 2 * expo , G->expo); arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); fmpq_clear(t); } diff --git a/acb_dirichlet/chi_vec.c b/acb_dirichlet/chi_vec.c index f5f45b18..c3462cdc 100644 --- a/acb_dirichlet/chi_vec.c +++ b/acb_dirichlet/chi_vec.c @@ -15,13 +15,14 @@ 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; + ulong * a, order; acb_dirichlet_powers_t t; a = flint_malloc(nv * sizeof(ulong)); - dirichlet_ui_chi_vec(a, G, chi, nv); + order = dirichlet_order_char(G, chi); + dirichlet_chi_vec_order(a, G, chi, order, nv); - acb_dirichlet_powers_init(t, chi->order.n, nv, prec); + acb_dirichlet_powers_init(t, order, nv, prec); acb_zero(v + 0); for (k = 0; k < nv; k++) diff --git a/acb_dirichlet/gauss_sum.c b/acb_dirichlet/gauss_sum.c index 3b8447ff..15816498 100644 --- a/acb_dirichlet/gauss_sum.c +++ b/acb_dirichlet/gauss_sum.c @@ -12,11 +12,11 @@ #include "acb_dirichlet.h" static void -gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) +gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong cond, slong prec) { slong k, mu = 1; - ulong NN0 = G->q / chi->conductor; + ulong NN0 = G->q / cond; /* G(chi) = mu(N/N0)chi0(N/N0)G(chi0) */ @@ -45,7 +45,7 @@ gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_ch mu *= -1; } - if (chi->x->n == 1) + if (chi->n == 1) { acb_set_si(res, mu); } @@ -56,15 +56,15 @@ gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_ch dirichlet_char_t chi0; acb_t z; - dirichlet_subgroup_init(G0, G, chi->conductor); - dirichlet_char_init(chi0, G); - dirichlet_char_primitive(chi0, G0, G, chi); + /* primitive char associated to chi */ + dirichlet_subgroup_init(G0, G, cond); + dirichlet_char_init(chi0, G0); + dirichlet_char_lower(chi0, G0, chi, G); acb_init(z); acb_dirichlet_gauss_sum(z, G0, chi0, prec); acb_dirichlet_chi(res, G0, chi0, NN0, prec); - acb_mul(res, res, z, prec); acb_mul_si(res, res, mu, prec); @@ -77,14 +77,15 @@ gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_ch void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { + ulong cond = dirichlet_conductor_char(G, chi); /* TODO: no need, factor also does it... */ - if (chi->conductor != G->q) + if (cond != G->q) { - gauss_sum_non_primitive(res, G, chi, prec); + gauss_sum_non_primitive(res, G, chi, cond, prec); } - else if (chi->order.n <= 2) + else if (dirichlet_char_is_real(G, chi)) { - acb_dirichlet_gauss_sum_order2(res, chi, prec); + acb_dirichlet_gauss_sum_order2(res, G, chi, prec); } else if (G->num > 1 && G->num > G->neven) { @@ -92,6 +93,7 @@ acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_ch } else { + /* must be non primitive */ if (acb_dirichlet_theta_length_d(G->q, 1, prec) > G->q) acb_dirichlet_gauss_sum_naive(res, G, chi, prec); else @@ -104,7 +106,7 @@ acb_dirichlet_gauss_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, slong { dirichlet_char_t chi; dirichlet_char_init(chi, G); - dirichlet_char(chi, G, a); + dirichlet_char_log(chi, G, a); acb_dirichlet_gauss_sum(res, G, chi, prec); dirichlet_char_clear(chi); } diff --git a/acb_dirichlet/gauss_sum_factor.c b/acb_dirichlet/gauss_sum_factor.c index 29fa0a32..fe96bd87 100644 --- a/acb_dirichlet/gauss_sum_factor.c +++ b/acb_dirichlet/gauss_sum_factor.c @@ -22,7 +22,7 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const diric for (k = (G->neven == 2); k < G->num; k++) { /* if e > 1 and not primitive, 0 */ - if (chi->x->log[k] % G->P[k].p == 0 && G->P[k].e > 1) + if (chi->log[k] % G->P[k].p == 0 && G->P[k].e > 1) { acb_zero(res); return; @@ -42,17 +42,15 @@ acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const diric dirichlet_subgroup_init(Gp, G, pe); dirichlet_char_init(chip, Gp); - chip->x->n = chi->x->n % pe; + chip->n = chi->n % pe; if (k == 1 && G->neven == 2) { - chip->x->log[0] = chi->x->log[0]; - chip->x->log[1] = chi->x->log[1]; + chip->log[0] = chi->log[0]; + chip->log[1] = chi->log[1]; } else - chip->x->log[0] = chi->x->log[k]; - - dirichlet_char_conrey(chip, Gp, NULL); + chip->log[0] = chi->log[k]; /* chi_pe(a, q/pe) * G_pe(a) */ acb_dirichlet_gauss_sum(tmp, Gp, chip, prec); diff --git a/acb_dirichlet/gauss_sum_order2.c b/acb_dirichlet/gauss_sum_order2.c index 39fed38b..863626d8 100644 --- a/acb_dirichlet/gauss_sum_order2.c +++ b/acb_dirichlet/gauss_sum_order2.c @@ -12,16 +12,16 @@ #include "acb_dirichlet.h" void -acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_char_t chi, slong prec) +acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { - if (chi->parity) + if (dirichlet_parity_char(G, chi)) { arb_zero(acb_realref(res)); - arb_sqrt_ui(acb_imagref(res), chi->q, prec); + arb_sqrt_ui(acb_imagref(res), G->q, prec); } else { arb_zero(acb_imagref(res)); - arb_sqrt_ui(acb_realref(res), chi->q, prec); + arb_sqrt_ui(acb_realref(res), G->q, prec); } } diff --git a/acb_dirichlet/gauss_sum_theta.c b/acb_dirichlet/gauss_sum_theta.c index ab97f384..21a5a09a 100644 --- a/acb_dirichlet/gauss_sum_theta.c +++ b/acb_dirichlet/gauss_sum_theta.c @@ -14,8 +14,9 @@ void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { - if (chi->conductor < G->q || (G->q == 300 && (chi->x->n == 71 || chi->x->n == 131)) - || (G->q == 600 && (chi->x->n == 11 || chi->x->n == 491))) + ulong cond = dirichlet_conductor_char(G, chi); + if (cond < G->q || (G->q == 300 && (chi->n == 71 || chi->n == 131)) + || (G->q == 600 && (chi->n == 11 || chi->n == 491))) { flint_printf("gauss_sum_theta: non available for non primitive character" "or exceptional characters chi_300(71,.), chi_300(131,.), " @@ -26,7 +27,7 @@ acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirich { acb_t iq; acb_init(iq); - acb_dirichlet_gauss_sum_order2(iq, chi, prec); + acb_dirichlet_gauss_sum_order2(iq, G, chi, prec); acb_dirichlet_root_number_theta(res, G, chi, prec); acb_mul(res, res, iq, prec); acb_clear(iq); diff --git a/acb_dirichlet/jacobi_sum.c b/acb_dirichlet/jacobi_sum.c index ab67d3c4..8ce90fad 100644 --- a/acb_dirichlet/jacobi_sum.c +++ b/acb_dirichlet/jacobi_sum.c @@ -47,16 +47,16 @@ acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_c { acb_zero(res); } - else if (chi1->x->n == 1 || chi2->x->n == 1) + else if (chi1->n == 1 || chi2->n == 1) { - ulong cond = (chi1->x->n == 1) ? chi2->conductor : chi1->conductor; + ulong cond = (chi1->n == 1) ? dirichlet_conductor_char(G, chi2) : dirichlet_conductor_char(G, chi1); acb_set_si(res, jacobi_one(G, cond)); } - else if (nmod_mul(chi1->x->n, chi2->x->n, G->mod) == 1) + else if (nmod_mul(chi1->n, chi2->n, G->mod) == 1) { ulong n; - n = jacobi_one(G, chi1->conductor); - if (chi1->parity) + n = jacobi_one(G, dirichlet_conductor_char(G, chi1)); + if (dirichlet_parity_char(G, chi1)) acb_set_si(res, -n); else acb_set_si(res, n); @@ -83,14 +83,14 @@ acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong } else if (a == 1 || b == 1) { - ulong cond = (a == 1) ? dirichlet_ui_conductor(G, b) : dirichlet_ui_conductor(G, a); + ulong cond = (a == 1) ? dirichlet_conductor_ui(G, b) : dirichlet_conductor_ui(G, a); acb_set_si(res, jacobi_one(G, cond)); } else if (nmod_mul(a, b, G->mod) == 1) { ulong n; - n = jacobi_one(G, dirichlet_ui_conductor(G, a)); - if (dirichlet_ui_parity(G, a)) + n = jacobi_one(G, dirichlet_conductor_ui(G, a)); + if (dirichlet_parity_ui(G, a)) acb_set_si(res, -n); else acb_set_si(res, n); @@ -100,8 +100,8 @@ acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong dirichlet_char_t chi1, chi2; dirichlet_char_init(chi1, G); dirichlet_char_init(chi2, G); - dirichlet_char(chi1, G, a); - dirichlet_char(chi2, G, b); + dirichlet_char_log(chi1, G, a); + dirichlet_char_log(chi2, G, b); acb_dirichlet_jacobi_sum(res, G, chi1, chi2, prec); dirichlet_char_clear(chi1); dirichlet_char_clear(chi2); diff --git a/acb_dirichlet/jacobi_sum_factor.c b/acb_dirichlet/jacobi_sum_factor.c index ddecf60a..90c9bf44 100644 --- a/acb_dirichlet/jacobi_sum_factor.c +++ b/acb_dirichlet/jacobi_sum_factor.c @@ -28,15 +28,15 @@ acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dir p = G->P[k].p; e = G->P[k].e; pe = G->P[k].pe; - ap = chi1->x->n % pe.n; - bp = chi2->x->n % pe.n; + ap = chi1->n % pe.n; + bp = chi2->n % pe.n; if (ap == 1 || bp == 1 || nmod_mul(ap, bp, pe) == 1) { slong r; ulong cond; - cond = (ap == 1) ? chi2->conductor : chi1->conductor; + cond = (ap == 1) ? dirichlet_conductor_char(G, chi2) : dirichlet_conductor_char(G, chi1); r = jacobi_one_prime(p, e, pe.n, cond); /* chi(a,-1) if ap * bp = 1 */ @@ -54,13 +54,10 @@ acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dir dirichlet_char_init(chi1p, Gp); dirichlet_char_init(chi2p, Gp); - chi1p->x->n = ap; - chi1p->x->log[0] = chi1->x->log[k]; - chi2p->x->n = ap; - chi2p->x->log[0] = chi2->x->log[k]; - - dirichlet_char_conrey(chi1p, Gp, NULL); - dirichlet_char_conrey(chi2p, Gp, NULL); + chi1p->n = ap; + chi1p->log[0] = chi1->log[k]; + chi2p->n = ap; + chi2p->log[0] = chi2->log[k]; /* TODO: work out gauss relations for e > 1 */ if (p <= 100 || e > 1) diff --git a/acb_dirichlet/jacobi_sum_gauss.c b/acb_dirichlet/jacobi_sum_gauss.c index 5d825ec6..7b2cdc2a 100644 --- a/acb_dirichlet/jacobi_sum_gauss.c +++ b/acb_dirichlet/jacobi_sum_gauss.c @@ -25,7 +25,7 @@ acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const diric acb_init(tmp); acb_dirichlet_gauss_sum(res, G, chi1, prec); - if (chi2->x->n == chi1->x->n) + if (chi2->n == chi1->n) acb_set(tmp, res); else acb_dirichlet_gauss_sum(tmp, G, chi2, prec); diff --git a/acb_dirichlet/jacobi_sum_naive.c b/acb_dirichlet/jacobi_sum_naive.c index 5541e6f6..bbbbfc0e 100644 --- a/acb_dirichlet/jacobi_sum_naive.c +++ b/acb_dirichlet/jacobi_sum_naive.c @@ -15,31 +15,30 @@ 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; + ulong k1, k2, m1, m2, g, e, m; ulong * v1, * v2; slong *v; - nmod_t order; + nmod_t expo; acb_t z; v1 = flint_malloc(G->q * sizeof(ulong)); v2 = flint_malloc(G->q * sizeof(ulong)); - dirichlet_ui_vec_set_null(v1, G, G->q); - dirichlet_ui_chi_vec_loop(v1, G, chi1, G->q); + dirichlet_vec_set_null(v1, G, G->q); + dirichlet_chi_vec_loop(v1, G, chi1, G->q); - dirichlet_ui_vec_set_null(v2, G, G->q); - dirichlet_ui_chi_vec_loop(v2, G, chi2, G->q); + dirichlet_vec_set_null(v2, G, G->q); + dirichlet_chi_vec_loop(v2, G, chi2, G->q); - m1 = chi1->order.n; - m2 = chi2->order.n; - g = n_gcd(m1, m2); - nmod_init(&order, m1 * (m2 / g)); - m1 = order.n / m1; - m2 = order.n / m2; + 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(order.n * sizeof(slong)); + v = flint_malloc(g * sizeof(slong)); - for (e = 0; e < order.n; e++) + for (e = 0; e < g; e++) v[e] = 0; for (k1 = 2, k2 = G->q - 1; k2 > 1; k1++, k2--) @@ -47,13 +46,13 @@ acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const diric if (v1[k1] == DIRICHLET_CHI_NULL || v2[k2] == DIRICHLET_CHI_NULL) continue; - e = nmod_add(v1[k1] * m1, v2[k2] * m2, order); + e = nmod_add(v1[k1], v2[k2], expo) / m; v[e]++; } acb_init(z); - acb_nth_root(z, order.n, prec); - acb_dirichlet_si_poly_evaluate(res, v, order.n, z, prec); + acb_nth_root(z, g, prec); + acb_dirichlet_si_poly_evaluate(res, v, g, z, prec); acb_clear(z); flint_free(v); diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index f219e6e8..5d10e72a 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -18,18 +18,17 @@ void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { - ulong chin; + ulong order, chin, mult; acb_t t, u, a; acb_ptr z; - dirichlet_conrey_t cn; + dirichlet_char_t cn; int deflate; /* remove pole in Hurwitz zeta at s = 1 */ deflate = 0; if (acb_is_one(s)) { - /* character is principal */ - if (chi->x->n == 1) + if (dirichlet_char_is_principal(chi)) { acb_indeterminate(res); return; @@ -37,21 +36,23 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, deflate = 1; } - dirichlet_conrey_init(cn, G); + dirichlet_char_init(cn, G); acb_init(t); acb_init(u); acb_init(a); - dirichlet_conrey_one(cn, G); + dirichlet_char_one(cn, G); acb_zero(t); prec += n_clog(G->phi_q, 2); - z = _acb_vec_init(chi->order.n); - _acb_vec_nth_roots(z, chi->order.n, prec); + order = dirichlet_order_char(G, chi); + mult = G->expo / order; + z = _acb_vec_init(order); + _acb_vec_nth_roots(z, order, prec); do { - chin = dirichlet_ui_chi_conrey(G, chi, cn); + chin = dirichlet_chi_char(G, chi, cn) / mult; acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); @@ -63,16 +64,16 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, acb_addmul(t, z + chin, u, prec); - } while (dirichlet_conrey_next(cn, G) >= 0); + } while (dirichlet_char_next(cn, G) >= 0); acb_set_ui(u, G->q); acb_neg(a, s); acb_pow(u, u, a, prec); acb_mul(res, t, u, prec); - dirichlet_conrey_clear(cn); + dirichlet_char_clear(cn); - _acb_vec_clear(z, chi->order.n); + _acb_vec_clear(z, order); acb_clear(t); acb_clear(u); acb_clear(a); diff --git a/acb_dirichlet/pairing.c b/acb_dirichlet/pairing.c index c05cbeb1..871e405f 100644 --- a/acb_dirichlet/pairing.c +++ b/acb_dirichlet/pairing.c @@ -15,7 +15,7 @@ void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec) { ulong expo; - expo = dirichlet_ui_pairing(G, m, n); + expo = dirichlet_pairing(G, m, n); if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else diff --git a/acb_dirichlet/pairing_conrey.c b/acb_dirichlet/pairing_conrey.c index 18d8aa54..c9c1284a 100644 --- a/acb_dirichlet/pairing_conrey.c +++ b/acb_dirichlet/pairing_conrey.c @@ -12,10 +12,10 @@ #include "acb_dirichlet.h" void -acb_dirichlet_pairing_conrey(acb_t res, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b, slong prec) +acb_dirichlet_chi_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec) { ulong expo; - expo = dirichlet_ui_pairing_conrey(G, a, b); + expo = dirichlet_chi_char(G, a, b); if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else diff --git a/acb_dirichlet/root_number.c b/acb_dirichlet/root_number.c index 33324182..1e4869b9 100644 --- a/acb_dirichlet/root_number.c +++ b/acb_dirichlet/root_number.c @@ -31,7 +31,7 @@ acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const diri void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec) { - if (chi->conductor < G->q) + if (dirichlet_conductor_char(G, chi) < G->q) { flint_printf("root number: need primitive character\n"); abort(); @@ -40,7 +40,7 @@ acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_ { acb_t iq; acb_init(iq); - acb_dirichlet_gauss_sum_order2(iq, chi, prec); + acb_dirichlet_gauss_sum_order2(iq, G, chi, prec); acb_dirichlet_gauss_sum(res, G, chi, prec); acb_div(res, res, iq, prec); acb_clear(iq); diff --git a/acb_dirichlet/test/t-chi.c b/acb_dirichlet/test/t-chi.c index e12eb7c0..ba67142b 100644 --- a/acb_dirichlet/test/t-chi.c +++ b/acb_dirichlet/test/t-chi.c @@ -44,7 +44,7 @@ int main() m = 1 + n_randint(state, q); } while (n_gcd(q, m) != 1); - dirichlet_char(chi, G, m); + dirichlet_char_log(chi, G, m); n1 = n_randint(state, 1000); n2 = n_randint(state, 1000); @@ -53,7 +53,6 @@ int main() acb_dirichlet_pairing(zn2, G, m, n1, 53); if (!acb_overlaps(zn1, zn2)) { - dirichlet_conrey_t x; flint_printf("FAIL: overlap\n\n"); flint_printf("q = %wu\n\n", q); flint_printf("m = %wu\n\n", m); @@ -61,11 +60,10 @@ int main() 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_conrey_init(x, G); - dirichlet_conrey_log(x, G, m); - flint_printf("log(m) = "); dirichlet_conrey_print(G, x); - dirichlet_conrey_log(x, G, n1); - flint_printf("log(n1) = "); dirichlet_conrey_print(G, x); + 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); abort(); } diff --git a/acb_dirichlet/test/t-gauss.c b/acb_dirichlet/test/t-gauss.c index 6b2afdfd..5cc2d6da 100644 --- a/acb_dirichlet/test/t-gauss.c +++ b/acb_dirichlet/test/t-gauss.c @@ -24,29 +24,25 @@ int main() for (q = 3; q < 250; q ++) { dirichlet_group_t G; - dirichlet_conrey_t x; dirichlet_char_t chi; acb_t s1, s2, s3, s4; dirichlet_group_init(G, q); - dirichlet_conrey_init(x, G); dirichlet_char_init(chi, G); acb_init(s1); acb_init(s2); acb_init(s3); acb_init(s4); - dirichlet_conrey_one(x, G); + dirichlet_char_one(chi, G); while (1) { - dirichlet_char_conrey(chi, G, x); - acb_dirichlet_gauss_sum_naive(s1, G, chi, prec); acb_dirichlet_gauss_sum(s2, G, chi, prec); acb_dirichlet_gauss_sum_factor(s3, G, chi, prec); - if (chi->conductor == G->q) + if (dirichlet_conductor_char(G, chi) == G->q) acb_dirichlet_gauss_sum_theta(s4, G, chi, prec); else acb_set(s4, s1); @@ -55,19 +51,19 @@ int main() || !acb_overlaps(s1, s3) || !acb_overlaps(s1, s4)) { - flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->x->n); - flint_printf("\nnaive ", q, x->n); + flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->n); + flint_printf("\nnaive "); acb_printd(s1, 25); - flint_printf("\ndefault ", q, x->n); + flint_printf("\ndefault "); acb_printd(s2, 25); - flint_printf("\nfactor ", q, x->n); + flint_printf("\nfactor "); acb_printd(s3, 25); - flint_printf("\ntheta ", q, x->n); + flint_printf("\ntheta "); acb_printd(s4, 25); abort(); } - if (dirichlet_conrey_next(x, G) < 0) + if (dirichlet_char_next(chi, G) < 0) break; } acb_clear(s1); @@ -77,7 +73,6 @@ int main() dirichlet_group_clear(G); dirichlet_char_clear(chi); - dirichlet_conrey_clear(x); } flint_cleanup(); diff --git a/acb_dirichlet/test/t-jacobi.c b/acb_dirichlet/test/t-jacobi.c index e7dfa520..b68b7a09 100644 --- a/acb_dirichlet/test/t-jacobi.c +++ b/acb_dirichlet/test/t-jacobi.c @@ -52,15 +52,16 @@ int main() if (!acb_overlaps(s1, s2)) { flint_printf("FAIL: J_%wu(%wu,%wu)", - q, chi1->x->n, chi2->x->n); + q, chi1->n, chi2->n); flint_printf("\nnaive "); acb_printd(s1, 25); flint_printf("\ndefault "); acb_printd(s2, 25); flint_printf("\n"); flint_printf("cond = %wu, %wu, %wu\n", - chi1->conductor, chi2->conductor, - dirichlet_ui_conductor(G, nmod_mul(chi1->x->n, chi2->x->n, G->mod)) + dirichlet_conductor_char(G, chi1), + dirichlet_conductor_char(G, chi2), + dirichlet_conductor_ui(G, nmod_mul(chi1->n, chi2->n, G->mod)) ); abort(); } diff --git a/acb_dirichlet/test/t-l.c b/acb_dirichlet/test/t-l.c index e37a5efb..5e472569 100644 --- a/acb_dirichlet/test/t-l.c +++ b/acb_dirichlet/test/t-l.c @@ -99,7 +99,7 @@ int main() dirichlet_group_init(G, q[i]); dirichlet_char_init(chi, G); - dirichlet_char(chi, G, m[i]); + dirichlet_char_log(chi, G, m[i]); for (j = 0; j < nx; j++) { diff --git a/acb_dirichlet/test/t-thetanull.c b/acb_dirichlet/test/t-thetanull.c index f40ac1e2..a5a37e09 100644 --- a/acb_dirichlet/test/t-thetanull.c +++ b/acb_dirichlet/test/t-thetanull.c @@ -68,24 +68,22 @@ int main() dirichlet_char_first_primitive(chi, G); do { - ulong m; + acb_zero(sum); + dirichlet_chi_vec(v, G, chi, nv); - dirichlet_ui_chi_vec(v, G, chi, nv); - - m = G->expo / chi->order.n; - tt = dirichlet_char_parity(chi) ? kt : t; + tt = dirichlet_parity_char(G, chi) ? kt : t; for (k = 1; k < nv; k++) if (v[k] != DIRICHLET_CHI_NULL) - acb_addmul_arb(sum, z + (v[k] * m), tt + k, prec); + acb_addmul_arb(sum, z + v[k], tt + k, prec); - if ((q == 300 && (chi->x->n == 71 || chi->x->n == 131)) - || (q == 600 && (chi->x->n == 11 || chi->x->n == 491))) + if ((q == 300 && (chi->n == 71 || chi->n == 131)) + || (q == 600 && (chi->n == 11 || chi->n == 491))) { if (!acb_contains_zero(sum)) { - flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); + flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); acb_printd(sum, 10); flint_printf("\n"); dirichlet_char_print(G, chi); @@ -95,7 +93,7 @@ int main() } else if (acb_contains_zero(sum)) { - flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->x->n); + flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n); acb_printd(sum, 10); flint_printf("\n"); dirichlet_char_print(G, chi); diff --git a/acb_dirichlet/theta_arb.c b/acb_dirichlet/theta_arb.c index f6a643e4..4e7774ee 100644 --- a/acb_dirichlet/theta_arb.c +++ b/acb_dirichlet/theta_arb.c @@ -15,14 +15,18 @@ void _acb_dirichlet_theta_arb_smallorder(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec) { + ulong order; ulong * a; + int parity; acb_dirichlet_powers_t z; + parity = dirichlet_parity_char(G, chi); + order = dirichlet_order_char(G, chi); a = flint_malloc(len * sizeof(ulong)); - dirichlet_ui_chi_vec(a, G, chi, len); + dirichlet_chi_vec_order(a, G, chi, order, len); - _acb_dirichlet_powers_init(z, chi->order.n, 0, 0, prec); - acb_dirichlet_qseries_arb_powers_smallorder(res, xt, chi->parity, a, z, len, prec); + _acb_dirichlet_powers_init(z, order, 0, 0, prec); + acb_dirichlet_qseries_arb_powers_smallorder(res, xt, parity, a, z, len, prec); acb_dirichlet_powers_clear(z); flint_free(a); @@ -34,7 +38,7 @@ _acb_dirichlet_theta_arb_series(acb_t res, const dirichlet_group_t G, const diri acb_ptr a; a = _acb_vec_init(len); acb_dirichlet_chi_vec(a, G, chi, len, prec); - if (chi->parity) + if (dirichlet_parity_char(G, chi)) { slong k; for (k = 2; k < len; k++) @@ -47,15 +51,18 @@ _acb_dirichlet_theta_arb_series(acb_t res, const dirichlet_group_t G, const diri 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 * a; + ulong order, * a; acb_dirichlet_powers_t z; + int parity; + parity = dirichlet_parity_char(G, chi); + order = dirichlet_order_char(G, chi); a = flint_malloc(len * sizeof(ulong)); - dirichlet_ui_chi_vec(a, G, chi, len); + dirichlet_chi_vec_order(a, G, chi, order, len); - acb_dirichlet_powers_init(z, chi->order.n, len, prec); + acb_dirichlet_powers_init(z, order, len, prec); - acb_dirichlet_qseries_arb_powers_naive(res, xt, chi->parity, a, z, len, prec); + acb_dirichlet_qseries_arb_powers_naive(res, xt, parity, a, z, len, prec); acb_dirichlet_powers_clear(z); flint_free(a); @@ -65,6 +72,7 @@ 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; @@ -80,7 +88,8 @@ acb_dirichlet_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_ch arb_exp(xt, xt, prec); /* TODO: tune this limit */ - if (chi->order.n < 30) + 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); diff --git a/acb_dirichlet/ui_theta_arb.c b/acb_dirichlet/ui_theta_arb.c index f98d2e42..51f7043c 100644 --- a/acb_dirichlet/ui_theta_arb.c +++ b/acb_dirichlet/ui_theta_arb.c @@ -17,7 +17,7 @@ acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const dirichlet_char_t chi; dirichlet_char_init(chi, G); - dirichlet_char(chi, G, a); + dirichlet_char_log(chi, G, a); acb_dirichlet_theta_arb(res, G, chi, t, prec); diff --git a/dirichlet.h b/dirichlet.h index 01d0cfca..673bde66 100644 --- a/dirichlet.h +++ b/dirichlet.h @@ -24,13 +24,15 @@ extern "C" { #endif +#define MAX_FACTORS 15 + /* should this dlog pointer be in the prime or the global group? */ typedef struct { ulong p; /* underlying prime */ int e; /* exponent */ nmod_t pe; /* modulus */ - ulong phi; /* phi(p^e) */ + nmod_t phi; /* phi(p^e) */ ulong g; /* conrey generator */ dlog_precomp_struct * dlog; /* precomputed data for discrete log mod p^e */ } @@ -69,9 +71,9 @@ void dirichlet_group_dlog_clear(dirichlet_group_t G); /* properties of elements without log */ ulong dirichlet_number_primitive(const dirichlet_group_t G); -ulong dirichlet_ui_conductor(const dirichlet_group_t G, ulong a); -int dirichlet_ui_parity(const dirichlet_group_t G, ulong a); -ulong dirichlet_ui_order(const dirichlet_group_t G, ulong a); +ulong dirichlet_conductor_ui(const dirichlet_group_t G, ulong a); +int dirichlet_parity_ui(const dirichlet_group_t G, ulong a); +ulong dirichlet_order_ui(const dirichlet_group_t G, ulong a); /* characters, keep both number and log */ typedef struct @@ -103,9 +105,9 @@ dirichlet_char_eq(const dirichlet_char_t x, const dirichlet_char_t y) } int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y); -int dirichlet_char_parity(const dirichlet_group_t G, const dirichlet_char_t x); -ulong dirichlet_char_conductor(const dirichlet_group_t G, const dirichlet_char_t x); -ulong dirichlet_char_order(const dirichlet_group_t G, const dirichlet_char_t x); +int dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x); +ulong dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x); +ulong dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x); void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m); ulong dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G); @@ -121,108 +123,36 @@ int dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G) void dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n); -void dirichlet_char_primitive(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, ulong cond); + +void dirichlet_char_lower(dirichlet_char_t y, const dirichlet_group_t H, const dirichlet_char_t x, const dirichlet_group_t G); +void dirichlet_char_lift(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_group_t H); #define DIRICHLET_CHI_NULL UWORD_MAX -ulong dirichlet_ui_pairing_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); -ulong dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n); +ulong dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n); -void dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec); -void dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec); - -/* introducing character type */ - -/* character = reduced exponents, keep order, number and conductor */ -typedef struct +DIRICHLET_INLINE int +dirichlet_char_is_principal(const dirichlet_char_t chi) { - ulong q; /* modulus */ - nmod_t order; /* order */ - dirichlet_char_t x; - ulong * expo; /* reduced exponents ( log[k] * PHI[k] / gcd( ) ) */ - int parity; /* 0 for even char, 1 for odd */ - ulong conductor; -} -dirichlet_fullchar_struct; - -typedef dirichlet_fullchar_struct dirichlet_fullchar_t[1]; - -DIRICHLET_INLINE ulong -dirichlet_fullchar_order(const dirichlet_fullchar_t chi) -{ - return chi->order.n; -} - -DIRICHLET_INLINE ulong -dirichlet_fullchar_conductor(const dirichlet_fullchar_t chi) -{ - return chi->conductor; + return (chi->n == 1); } DIRICHLET_INLINE int -dirichlet_fullchar_parity(const dirichlet_fullchar_t chi) +dirichlet_char_is_real(const dirichlet_group_t G, const dirichlet_char_t chi) { - return chi->parity; + return (nmod_mul(chi->n, chi->n, G->mod) == 1); } -void dirichlet_fullchar_init(dirichlet_fullchar_t chi, const dirichlet_group_t G); -void dirichlet_fullchar_clear(dirichlet_fullchar_t chi); -void dirichlet_fullchar_print(const dirichlet_group_t G, const dirichlet_fullchar_t chi); +ulong dirichlet_chi_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); +ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n); -DIRICHLET_INLINE void -dirichlet_fullchar_set(dirichlet_fullchar_t chi1, const dirichlet_group_t G, const dirichlet_fullchar_t chi2) -{ - slong k; - - chi1->q = chi2->q; - chi1->conductor = chi2->conductor; - chi1->order = chi2->order; - chi1->parity = chi2->parity; - dirichlet_char_set(chi1->x, G, chi2->x); - for (k = 0; k < G->num; k++) - chi1->expo[k] = chi2->expo[k]; -} - -DIRICHLET_INLINE int -dirichlet_fullchar_eq(const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2) -{ - return (chi1->q == chi2->q && chi1->x->n == chi2->x->n); -} - -int dirichlet_fullchar_eq_deep(const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2); -DIRICHLET_INLINE int -dirichlet_fullchar_is_principal(const dirichlet_fullchar_t chi) -{ - return (chi->x->n == 1); -} -DIRICHLET_INLINE int -dirichlet_fullchar_is_real(const dirichlet_fullchar_t chi) -{ - return (chi->order.n <= 2); -} - -void dirichlet_fullchar(dirichlet_fullchar_t chi, const dirichlet_group_t G, ulong n); -void dirichlet_fullchar_char(dirichlet_fullchar_t chi, const dirichlet_group_t G, const dirichlet_char_t x); -void dirichlet_fullchar_set_expo(dirichlet_fullchar_t chi, const dirichlet_group_t G); -void dirichlet_fullchar_normalize(dirichlet_fullchar_t chi, const dirichlet_group_t G); -void dirichlet_fullchar_denormalize(dirichlet_fullchar_t chi, const dirichlet_group_t G); - -void dirichlet_fullchar_mul(dirichlet_fullchar_t chi12, const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2); -void dirichlet_fullchar_primitive(dirichlet_fullchar_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_fullchar_t chi); - -void dirichlet_fullchar_one(dirichlet_fullchar_t chi, const dirichlet_group_t G); -void dirichlet_fullchar_first_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G); - -int dirichlet_fullchar_next(dirichlet_fullchar_t chi, const dirichlet_group_t G); -int dirichlet_fullchar_next_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G); - -ulong dirichlet_ui_chi_char(const dirichlet_group_t G, const dirichlet_fullchar_t chi, const dirichlet_char_t x); -ulong dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_fullchar_t chi, ulong n); - -void dirichlet_ui_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv); -void dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv); -void dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv); -void dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv); +void dirichlet_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv); +void dirichlet_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); +void dirichlet_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); +void dirichlet_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv); +void dirichlet_chi_vec_loop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv); +void dirichlet_chi_vec_primeloop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv); +void dirichlet_chi_vec_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv); #ifdef __cplusplus } diff --git a/dirichlet/char.c b/dirichlet/char.c deleted file mode 100644 index c8f57ad9..00000000 --- a/dirichlet/char.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar(dirichlet_fullchar_t chi, const dirichlet_group_t G, ulong n) -{ - dirichlet_char_log(chi->x, G, n); - dirichlet_fullchar_char(chi, G, NULL); -} diff --git a/dirichlet/char_clear.c b/dirichlet/char_clear.c deleted file mode 100644 index f4432c79..00000000 --- a/dirichlet/char_clear.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar_clear(dirichlet_fullchar_t chi) -{ - dirichlet_char_clear(chi->x); - flint_free(chi->expo); -} diff --git a/dirichlet/char_conrey.c b/dirichlet/char_conrey.c deleted file mode 100644 index 4f82fbfa..00000000 --- a/dirichlet/char_conrey.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -/* char n has exponents = log[k]*PHI[k] / gcd and order expo / gcd - * so that log = expo[k] */ -void -dirichlet_fullchar_char(dirichlet_fullchar_t chi, const dirichlet_group_t G, const dirichlet_char_t x) -{ - /* assume chi->x already set if x == NULL */ - if (x == NULL) - x = chi->x; - else - dirichlet_char_set(chi->x, G, x); - - chi->q = G->q; - chi->parity = dirichlet_char_parity(G, x); - chi->conductor = dirichlet_char_conductor(G, x); - - dirichlet_fullchar_set_expo(chi, G); - /* optional: divide by gcd to obtain true order */ - dirichlet_fullchar_normalize(chi, G); -} diff --git a/dirichlet/char_eq_deep.c b/dirichlet/char_eq_deep.c deleted file mode 100644 index d4e845f6..00000000 --- a/dirichlet/char_eq_deep.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -int -dirichlet_fullchar_eq_deep(const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2) -{ - dirichlet_char_t x, y; - - if (chi1->q != chi2->q) - return 0; - - if (chi1->order.n != chi2->order.n) - return 0; - - if (chi1->conductor != chi2->conductor) - return 0; - - if (!dirichlet_char_eq_deep(G, chi1->x, chi2->x)) - return 0; - - x->n = y->n = 1; - x->log = chi1->expo; - y->log = chi2->expo; - if (!dirichlet_char_eq_deep(G, x, y)) - return 0; - - return 1; -} diff --git a/dirichlet/char_first_primitive.c b/dirichlet/char_first_primitive.c deleted file mode 100644 index acf378a3..00000000 --- a/dirichlet/char_first_primitive.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar_first_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G) -{ - dirichlet_char_first_primitive(chi->x, G); - dirichlet_fullchar_char(chi, G, NULL); - dirichlet_fullchar_normalize(chi, G); -} diff --git a/dirichlet/char_init.c b/dirichlet/char_init.c deleted file mode 100644 index 67d5c9a6..00000000 --- a/dirichlet/char_init.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar_init(dirichlet_fullchar_t chi, const dirichlet_group_t G) -{ - slong k; - dirichlet_char_init(chi->x, G); - chi->expo = flint_malloc(G->num * sizeof(ulong)); - chi->q = G->q; - chi->conductor = 1; - chi->parity = 0; - for (k = 0; k < G->num; k++) - chi->expo[k] = 0; - nmod_init(&(chi->order), 1); -} diff --git a/dirichlet/char_mul.c b/dirichlet/char_mul.c deleted file mode 100644 index 28ceee77..00000000 --- a/dirichlet/char_mul.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar_mul(dirichlet_fullchar_t chi12, const dirichlet_group_t G, const dirichlet_fullchar_t chi1, const dirichlet_fullchar_t chi2) -{ - dirichlet_char_mul(chi12->x, G, chi1->x, chi2->x); - dirichlet_fullchar_char(chi12, G, NULL); -} diff --git a/dirichlet/char_next.c b/dirichlet/char_next.c deleted file mode 100644 index f00206a0..00000000 --- a/dirichlet/char_next.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -int -dirichlet_fullchar_next(dirichlet_fullchar_t chi, const dirichlet_group_t G) -{ - int k; - k = dirichlet_char_next(chi->x, G); - dirichlet_fullchar_char(chi, G, NULL); - /* return last index modified */ - return k; -} diff --git a/dirichlet/char_next_primitive.c b/dirichlet/char_next_primitive.c deleted file mode 100644 index eba33457..00000000 --- a/dirichlet/char_next_primitive.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -int -dirichlet_fullchar_next_primitive(dirichlet_fullchar_t chi, const dirichlet_group_t G) -{ - int k; - k = dirichlet_char_next_primitive(chi->x, G); - dirichlet_fullchar_char(chi, G, NULL); - /* return last index modified */ - return k; -} diff --git a/dirichlet/char_normalize.c b/dirichlet/char_normalize.c deleted file mode 100644 index a7287c74..00000000 --- a/dirichlet/char_normalize.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar_set_expo(dirichlet_fullchar_t chi, const dirichlet_group_t G) -{ - slong k; - for (k = 0; k < G->num; k++) - /* no overflow: log[k] < phi[k] and G->expo = phi[k] * PHI[k] */ - chi->expo[k] = chi->x->log[k] * G->PHI[k]; -} - -void -dirichlet_fullchar_normalize(dirichlet_fullchar_t chi, const dirichlet_group_t G) -{ - ulong k, g; - g = G->expo; - - for (k = 0; k < G->num; k++) - g = n_gcd(g, chi->expo[k]); - - for (k = 0; k < G->num; k++) - chi->expo[k] = chi->expo[k] / g; - - nmod_init(&chi->order, G->expo / g); -} - -void -dirichlet_fullchar_denormalize(dirichlet_fullchar_t chi, const dirichlet_group_t G) -{ - ulong k, g; - g = G->expo / chi->order.n; - - for (k = 0; k < G->num; k++) - chi->expo[k] *= g; -} diff --git a/dirichlet/char_primitive.c b/dirichlet/char_primitive.c deleted file mode 100644 index c8fc771f..00000000 --- a/dirichlet/char_primitive.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar_primitive(dirichlet_fullchar_t chi0, const dirichlet_group_t G0, const dirichlet_group_t G, const dirichlet_fullchar_t chi) -{ - chi0->q = chi->conductor; - chi0->parity = chi->parity; - chi0->conductor = chi->conductor; - dirichlet_char_primitive(chi0->x, G, chi->x, chi->conductor); - dirichlet_fullchar_set_expo(chi0, G0); - /* optional: divide by gcd to obtain true order */ - dirichlet_fullchar_normalize(chi0, G0); -} diff --git a/dirichlet/char_print.c b/dirichlet/char_print.c deleted file mode 100644 index 6898bfe2..00000000 --- a/dirichlet/char_print.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_fullchar_print(const dirichlet_group_t G, const dirichlet_fullchar_t chi) -{ - dirichlet_char_t x; - flint_printf("chi_%wu(%wu,.) of order %wu, parity %wd, index ", G->q, chi->x->n, chi->order, chi->parity); - dirichlet_char_print(G, chi->x); - flint_printf(" and exponents "); - x->log = chi->expo; - dirichlet_char_print(G, x); -} diff --git a/dirichlet/ui_chi.c b/dirichlet/chi.c similarity index 83% rename from dirichlet/ui_chi.c rename to dirichlet/chi.c index 7133e614..43901218 100644 --- a/dirichlet/ui_chi.c +++ b/dirichlet/chi.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_fullchar_t chi, ulong n) +dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) { if (n_gcd(G->q, n) > 1) { @@ -25,7 +25,7 @@ dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_fullchar_t chi, ulon dirichlet_char_init(x, G); dirichlet_char_log(x, G, n); - v = dirichlet_ui_chi_char(G, chi, x); + v = dirichlet_chi_char(G, chi, x); dirichlet_char_clear(x); return v; diff --git a/dirichlet/char_one.c b/dirichlet/chi_char.c similarity index 60% rename from dirichlet/char_one.c rename to dirichlet/chi_char.c index 7f872555..951b4cb2 100644 --- a/dirichlet/char_one.c +++ b/dirichlet/chi_char.c @@ -11,15 +11,16 @@ #include "dirichlet.h" -void -dirichlet_fullchar_one(dirichlet_fullchar_t chi, const dirichlet_group_t G) +ulong +dirichlet_chi_char(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_char_t x) { - slong k; - dirichlet_char_one(chi->x, G); - chi->q = G->q; - chi->conductor = 1; - chi->parity = 0; + ulong v = 0, k; + nmod_t order; + + nmod_init(&order, G->expo); + for (k = 0; k < G->num; k++) - chi->expo[k] = 0; - nmod_init(&(chi->order), 1); + v = nmod_add(v, G->PHI[k] * nmod_mul(chi->log[k], x->log[k], G->P[k].phi), order); + + return v; } diff --git a/dirichlet/chi_vec.c b/dirichlet/chi_vec.c new file mode 100644 index 00000000..f56fc293 --- /dev/null +++ b/dirichlet/chi_vec.c @@ -0,0 +1,30 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dirichlet.h" + +void +dirichlet_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) +{ + if (2 * nv > G->phi_q) + dirichlet_chi_vec_loop(v, G, chi, nv); + else + dirichlet_chi_vec_primeloop(v, G, chi, nv); +} + +void +dirichlet_chi_vec_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) +{ + if (2 * nv > G->phi_q) + dirichlet_chi_vec_loop_order(v, G, chi, order, nv); + else + dirichlet_chi_vec_primeloop_order(v, G, chi, order, nv); +} diff --git a/dirichlet/ui_chi_vec_loop.c b/dirichlet/chi_vec_loop.c similarity index 57% rename from dirichlet/ui_chi_vec_loop.c rename to dirichlet/chi_vec_loop.c index 8ff81d76..d58341cf 100644 --- a/dirichlet/ui_chi_vec_loop.c +++ b/dirichlet/chi_vec_loop.c @@ -11,17 +11,33 @@ #include "dirichlet.h" +static void +dirichlet_exponents_char(ulong * expo, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order) +{ + slong k; + ulong factor = G->expo / order; + for (k = 0; k < G->num; k++) + /* no overflow: log[k] < phi[k] and G->expo = phi[k] * PHI[k] */ + expo[k] = (chi->log[k] * G->PHI[k]) / factor; +} + /* loop over whole group */ void -dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) +dirichlet_chi_vec_loop_order(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) { int j; ulong t; slong k; + ulong expo[MAX_FACTORS]; dirichlet_char_t x; + nmod_t o; + dirichlet_char_init(x, G); dirichlet_char_one(x, G); + dirichlet_exponents_char(expo, G, chi, order); + nmod_init(&o, order); + for (k = 0; k < nv; k++) v[k] = DIRICHLET_CHI_NULL; @@ -31,7 +47,7 @@ dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_f { /* exponents were modified up to j */ for (k = G->num - 1; k >= j; k--) - t = nmod_add(t, chi->expo[k], chi->order); + t = nmod_add(t, expo[k], o); if (x->n < nv) v[x->n] = t; @@ -46,3 +62,9 @@ dirichlet_ui_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_f dirichlet_char_clear(x); } + +void +dirichlet_chi_vec_loop(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) +{ + dirichlet_chi_vec_loop_order(v, G, chi, G->expo, nv); +} diff --git a/dirichlet/chi_vec_primeloop.c b/dirichlet/chi_vec_primeloop.c new file mode 100644 index 00000000..90536a07 --- /dev/null +++ b/dirichlet/chi_vec_primeloop.c @@ -0,0 +1,82 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dirichlet.h" + +static void +dirichlet_chi_vec_evenpart(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) +{ + ulong mult = G->expo / order; + if (G->neven >= 1 && chi->log[0]) + { + ulong x, c3 = G->PHI[0] / mult; + for (x = 3; x < nv; x += 4) + v[x] = c3; + } + if (G->neven == 2 && chi->log[1]) + { + ulong x, g, vx, xp, c4; + nmod_t pe, o; + nmod_init(&o, order); + + pe = G->P[1].pe; + g = G->P[1].g; + + vx = c4 = (chi->log[1] * G->PHI[1]) / mult; + for (x = g; x > 1;) + { + + for (xp = x; xp < nv; xp += pe.n) + v[xp] = nmod_add(v[xp], vx, o); + + for (xp = pe.n - x; xp < nv; xp += pe.n) + v[xp] = nmod_add(v[xp], vx, o); + + x = nmod_mul(x, g, pe); + vx = nmod_add(vx, c4, o); + } + } +} + +/* loop over primary components */ +void +dirichlet_chi_vec_primeloop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) +{ + slong k, l; + ulong mult = G->expo / order; + nmod_t o; + nmod_init(&o, order); + + for (k = 0; k < nv; k++) + v[k] = 0; + + if (G->neven) + dirichlet_chi_vec_evenpart(v, G, chi, order, nv); + + for (l = G->neven; l < G->num; l++) + { + dirichlet_prime_group_struct P = G->P[l]; + + /* FIXME: there may be some precomputed dlog in P if needed */ + if (P.dlog == NULL) + dlog_vec_add(v, nv, P.g, (chi->log[l] * G->PHI[l]) / mult, P.pe, P.phi.n, o); + else + dlog_vec_add_precomp(v, nv, P.dlog, P.g, (chi->log[l] * G->PHI[l]) / mult, P.pe, P.phi.n, o); + + } + dirichlet_vec_set_null(v, G, nv); +} + +void +dirichlet_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) +{ + dirichlet_chi_vec_primeloop_order(v, G, chi, G->expo, nv); +} diff --git a/dirichlet/conrey_conductor.c b/dirichlet/conrey_conductor.c index 24afc2b9..281c4ccb 100644 --- a/dirichlet/conrey_conductor.c +++ b/dirichlet/conrey_conductor.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_char_conductor(const dirichlet_group_t G, const dirichlet_char_t x) +dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x) { int k, f; ulong cond = 1; diff --git a/dirichlet/conrey_index.c b/dirichlet/conrey_index.c index ddea9463..50d14cfb 100644 --- a/dirichlet/conrey_index.c +++ b/dirichlet/conrey_index.c @@ -30,10 +30,10 @@ dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j) { slong k; - for (k = 0; k < G->num; k++) + for (k = G->num - 1; k >= 0; k--) { - x->log[k] = j % G->P[k].phi; - j = j / G->P[k].phi; + x->log[k] = j % G->P[k].phi.n; + j = j / G->P[k].phi.n; } dirichlet_char_exp(x, G); diff --git a/dirichlet/conrey_lift.c b/dirichlet/conrey_lift.c new file mode 100644 index 00000000..36854a70 --- /dev/null +++ b/dirichlet/conrey_lift.c @@ -0,0 +1,36 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dirichlet.h" + +void +dirichlet_char_lift(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_group_t H) +{ + slong k, l; + + if (G->q % H->q != 0) + { + flint_printf("conrey_lift: lower modulus %wu does not divide %wu\n", H->q, G->q); + abort(); + } + + for (k = 0, l = 0; k < G->num && l < H->num; k++) + { + if (G->P[k].p == H->P[l].p) + { + slong e = n_pow(G->P[k].p, G->P[k].e - H->P[l].e); + y->log[k] = x->log[l] * e; + l++; + } + } + + dirichlet_char_exp(y, G); +} diff --git a/dirichlet/conrey_log.c b/dirichlet/conrey_log.c index e53245ad..a989627f 100644 --- a/dirichlet/conrey_log.c +++ b/dirichlet/conrey_log.c @@ -39,7 +39,7 @@ dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m) dirichlet_prime_group_struct P = G->P[k]; if (P.dlog == NULL) { - x->log[k] = dlog_once(m % P.pe.n, P.g, P.pe, P.phi); + x->log[k] = dlog_once(m % P.pe.n, P.g, P.pe, P.phi.n); } else { diff --git a/dirichlet/conrey_lower.c b/dirichlet/conrey_lower.c new file mode 100644 index 00000000..16bdcc8d --- /dev/null +++ b/dirichlet/conrey_lower.c @@ -0,0 +1,42 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dirichlet.h" + +void +dirichlet_char_lower(dirichlet_char_t y, const dirichlet_group_t H, const dirichlet_char_t x, const dirichlet_group_t G) +{ + slong k, l; + + if (G->q % H->q != 0) + { + flint_printf("conrey_lower: lower modulus %wu does not divide %wu\n", H->q, G->q); + abort(); + } + + for (k = 0, l = 0; k < G->num && l < H->num; k++) + { + ulong p = G->P[k].p; + if (p == H->P[l].p) + { + ulong pef = n_pow(G->P[k].p, G->P[k].e - H->P[l].e); + ulong a = x->log[k]; + if (a % pef) + { + flint_printf("conrey_lower: conductor does not divide lower modulus %wu", H->q); + abort(); + } + y->log[l] = a / pef; + l++; + } + } + dirichlet_char_exp(y, H); +} diff --git a/dirichlet/conrey_mul.c b/dirichlet/conrey_mul.c index a8071405..6194455d 100644 --- a/dirichlet/conrey_mul.c +++ b/dirichlet/conrey_mul.c @@ -16,6 +16,6 @@ dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichle { ulong k; for (k = 0; k < G->num ; k++) - c->log[k] = (a->log[k] + b->log[k]) % G->P[k].phi; + c->log[k] = nmod_add(a->log[k], b->log[k], G->P[k].phi); c->n = nmod_mul(a->n, b->n, G->mod); } diff --git a/dirichlet/conrey_next.c b/dirichlet/conrey_next.c index 4a1db3c1..140ecbf0 100644 --- a/dirichlet/conrey_next.c +++ b/dirichlet/conrey_next.c @@ -20,7 +20,7 @@ dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G) { x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] += 1; - if (x->log[k] < G->P[k].phi) + if (x->log[k] < G->P[k].phi.n) break; x->log[k] = 0; } diff --git a/dirichlet/conrey_next_primitive.c b/dirichlet/conrey_next_primitive.c index a39b6fc1..9831d785 100644 --- a/dirichlet/conrey_next_primitive.c +++ b/dirichlet/conrey_next_primitive.c @@ -38,9 +38,9 @@ dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G) x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k]++; } - if (x->log[k] < G->P[k].phi) + if (x->log[k] < G->P[k].phi.n) break; - if (x->log[k] == G->P[k].phi) + if (x->log[k] == G->P[k].phi.n) x->n = nmod_mul(x->n, G->generators[k], G->mod); x->log[k] = 1; #else diff --git a/dirichlet/conrey_order.c b/dirichlet/conrey_order.c index d8da6fc7..51875f2b 100644 --- a/dirichlet/conrey_order.c +++ b/dirichlet/conrey_order.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_char_order(const dirichlet_group_t G, const dirichlet_char_t x) +dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x) { ulong k, g; g = G->expo; diff --git a/dirichlet/conrey_parity.c b/dirichlet/conrey_parity.c index 3ba6d181..dcaba5a1 100644 --- a/dirichlet/conrey_parity.c +++ b/dirichlet/conrey_parity.c @@ -12,7 +12,7 @@ #include "dirichlet.h" int -dirichlet_char_parity(const dirichlet_group_t G, const dirichlet_char_t x) +dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x) { int k, odd = 0; for (k = 0; k < G->num; k++) diff --git a/dirichlet/conrey_pow.c b/dirichlet/conrey_pow.c index 3a682bd7..804b9767 100644 --- a/dirichlet/conrey_pow.c +++ b/dirichlet/conrey_pow.c @@ -16,6 +16,6 @@ dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichle { ulong k; for (k = 0; k < G->num ; k++) - c->log[k] = n_mulmod2(a->log[k], n, G->P[k].phi); + c->log[k] = nmod_mul(a->log[k], n, G->P[k].phi); c->n = nmod_pow_ui(a->n, n, G->mod); } diff --git a/dirichlet/conrey_primitive.c b/dirichlet/conrey_primitive.c deleted file mode 100644 index 2a73c64b..00000000 --- a/dirichlet/conrey_primitive.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_char_primitive(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, ulong cond) -{ - slong k, l; - - l = 0; - if (cond % 4 == 0) - { - y->log[l++] = x->log[0]; - - if (cond % 8 == 0) - { - ulong l2 = x->log[1]; - n_remove(&l2, 2); - y->log[l++] = l2; - } - } - - for (k = G->neven; k < G->num; k++) - { - if (x->log[k]) - { - ulong p, lp; - p = G->P[k].p; - if (cond % p == 0) - { - lp = x->log[k]; - n_remove(&lp, p); - y->log[l++] = lp; - } - } - } - -} diff --git a/dirichlet/group_init.c b/dirichlet/group_init.c index 4a98121f..7c6c9523 100644 --- a/dirichlet/group_init.c +++ b/dirichlet/group_init.c @@ -45,12 +45,12 @@ dirichlet_prime_group_init(dirichlet_prime_group_struct * P, ulong p, int e) if (p == 2) { P->e = 2; - P->phi = 2; + nmod_init(&P->phi, 2); P->g = (1 << e) - 1; } else { - P->phi = 1 << (e - 2); + nmod_init(&P->phi, 1 << (e - 2)); P->g = 5; } } @@ -58,7 +58,7 @@ dirichlet_prime_group_init(dirichlet_prime_group_struct * P, ulong p, int e) { ulong pe1; pe1 = n_pow(p, e - 1); - P->phi = (p-1) * pe1; + nmod_init(&P->phi, (p-1) * pe1); nmod_init(&P->pe, p * pe1); P->g = primitive_root_p_and_p2(p); } @@ -75,19 +75,19 @@ dirichlet_group_lift_generators(dirichlet_group_t G) if (G->neven) { G->phi_q = G->q_even / 2; - G->expo = P[G->neven - 1].phi; + G->expo = P[G->neven - 1].phi.n; } for (k = G->neven; k < G->num; k++) { - G->phi_q *= P[k].phi; - G->expo *= P[k].phi / n_gcd(G->expo, P[k].p - 1); + G->phi_q *= P[k].phi.n; + G->expo *= P[k].phi.n / n_gcd(G->expo, P[k].p - 1); } for (k = 0; k < G->num; k++) { nmod_t pe; ulong qpe, v; - G->PHI[k] = G->expo / G->P[k].phi; + G->PHI[k] = G->expo / G->P[k].phi.n; /* lift generators mod q */ /* u * p^e + v * q/p^e = 1 -> g mod q = 1 + (g-1) * v*(q/p^e) */ pe = G->P[k].pe; @@ -199,6 +199,8 @@ dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h) H->P[j].e = s[k]; if (k == 0) H->P[j].g = H->q_even - 1; + else + nmod_init(&H->P[j].phi, H->q_even / 4); } j++; } @@ -210,9 +212,11 @@ dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h) H->P[j] = G->P[k]; if (s[k] < G->P[k].e) { - ulong p = H->P[j].p; + ulong pf, p = H->P[j].p; H->P[j].e = s[k]; - nmod_init(&H->P[j].pe, n_pow(p, s[k])); + pf = n_pow(p, s[k]); + nmod_init(&H->P[j].pe, pf); + nmod_init(&H->P[j].phi, (p-1) * pf / p); } j++; } diff --git a/dirichlet/index_conrey.c b/dirichlet/index_conrey.c index 4747d4e4..18993f32 100644 --- a/dirichlet/index_conrey.c +++ b/dirichlet/index_conrey.c @@ -32,7 +32,7 @@ dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x) ulong j = 0; for (k = 0; k < G->num; k++) - j = j * G->P[k].phi + x->log[k]; + j = j * G->P[k].phi.n + x->log[k]; return j; } diff --git a/dirichlet/ui_pairing.c b/dirichlet/pairing.c similarity index 87% rename from dirichlet/ui_pairing.c rename to dirichlet/pairing.c index 4d572ff4..cf4fd648 100644 --- a/dirichlet/ui_pairing.c +++ b/dirichlet/pairing.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n) +dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n) { ulong x; dirichlet_char_t a, b; @@ -25,7 +25,7 @@ dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n) dirichlet_char_log(a, G, m); dirichlet_char_log(b, G, n); - x = dirichlet_ui_pairing_char(G, a, b); + x = dirichlet_chi_char(G, a, b); dirichlet_char_clear(a); dirichlet_char_clear(b); diff --git a/dirichlet/test/t-chars.c b/dirichlet/test/t-chars.c index d2a79a30..06b849a8 100644 --- a/dirichlet/test/t-chars.c +++ b/dirichlet/test/t-chars.c @@ -13,140 +13,137 @@ int main() { - slong iter, bits; + slong iter; flint_rand_t state; - flint_printf("chars...."); + flint_printf("char...."); fflush(stdout); flint_randinit(state); - for (bits = 5; bits <= 30; bits += 5) + + for (iter = 0; iter < 3000 * arb_test_multiplier(); iter++) { + dirichlet_group_t G; + dirichlet_char_t x, y; + ulong q, n, k, sum; + slong ref; - for (iter = 0; iter < 50; iter++) + q = 1 + n_randint(state, 1000 * (1 + iter / 100)); + + dirichlet_group_init(G, q); + + dirichlet_char_init(x, G); + dirichlet_char_init(y, G); + + /* check group size and elements */ + dirichlet_char_one(x, G); + sum = 1; + + for (n = 1; dirichlet_char_next(x, G) >= 0; n++) + sum += x->n * x->n; + + if (FLINT_BITS == 64 || q < 1024) { - dirichlet_group_t G; - dirichlet_conrey_t x; - dirichlet_char_t chi, chi2; - ulong q, iter2; + /* use http://oeis.org/A053818 to check all elements + * are gone through */ + ref = (q % 4 == 2) ? -2 : 1; + for (k = (G->neven == 2); k < G->num; k++) + ref = - ref * G->P[k].p; + ref = ( G->phi_q * (2 * q * q + ref) ) / 6; - q = 2 + n_randint(state, 1 << bits); - - dirichlet_group_init(G, q); - dirichlet_conrey_init(x, G); - dirichlet_char_init(chi, G); - dirichlet_char_init(chi2, G); - - dirichlet_group_dlog_precompute(G, 50); - - /* check number char properties */ - for (iter2 = 0; iter2 < 100; iter2++) + if (n != G->phi_q) { - int par; - ulong m, n; - ulong order, chim1, pairing, cn, cm, cond; + flint_printf("FAIL: group size\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("phi(q) = %wu\n\n", G->phi_q); + flint_printf("loop index = %wu\n\n", n); + abort(); + } + if (sum != ref && q > 1) + { + flint_printf("FAIL: sum test\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("sum k^2 = %wu\n\n", ref); + flint_printf("sum obtained = %wu\n\n", sum); + abort(); + } + } - do - m = n_randint(state, q); - while (n_gcd(q, m) > 1); - - dirichlet_char(chi, G, m); - dirichlet_conrey_log(x, G, m); - dirichlet_char_conrey(chi2, G, x); - - if (!dirichlet_char_eq_deep(G, chi, chi2)) - { - flint_printf("FAIL: init char\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - dirichlet_char_print(G, chi); - flint_printf("\n"); - dirichlet_char_print(G, chi2); - flint_printf("\n"); - abort(); - } - - order = dirichlet_ui_order(G, m); - if (order != chi->order.n) - { - flint_printf("FAIL: order\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("order(m) = %wu\n\n", order); - flint_printf("chi->order = %wu\n\n", chi->order); - abort(); - } - - cond = dirichlet_ui_conductor(G, m); - if (cond != chi->conductor) - { - flint_printf("FAIL: conductor\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("conductor(m) = %wu\n\n", cond); - flint_printf("chi->conductor = %wu\n\n", chi->conductor); - abort(); - } - - par = dirichlet_ui_parity(G, m); - chim1 = dirichlet_ui_chi(G, chi, q - 1); - if (dirichlet_char_parity(chi) != par || par != (chim1 != 0)) - { - flint_printf("FAIL: parity\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("chi(-1) = %wu\n\n", chim1); - flint_printf("char_parity = %d", dirichlet_char_parity(chi)); - flint_printf("parity_ui = %d", par); - dirichlet_char_print(G, chi); - abort(); - } - - do - n = n_randint(state, q); - while (n_gcd(q, n) > 1); - - dirichlet_char(chi2, G, n); - pairing = dirichlet_ui_pairing(G, m, n); - cn = dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order.n); - cm = dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order.n); - - 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_conrey_next(x, G); - dirichlet_char_next(chi, G); - dirichlet_char_conrey(chi2, G, x); - - if (!dirichlet_char_eq_deep(G, chi, chi2)) - { - flint_printf("FAIL: next char\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - dirichlet_char_print(G, chi); - flint_printf("\n"); - dirichlet_char_print(G, chi2); - flint_printf("\n"); - abort(); - } + if (q % 4 != 2) + { + dirichlet_char_first_primitive(x, G); + for (n = 1; dirichlet_char_next_primitive(x, G) >= 0; n++); + ref = dirichlet_number_primitive(G); + if (n != ref) + { + flint_printf("FAIL: number of primitive elements\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("# primitive = %wu\n\n", ref); + flint_printf("loop index = %wu\n\n", n); + abort(); } - dirichlet_group_dlog_clear(G); + /* some random elements, check log and exp */ + for (n = 0; n < 30; n++) + { + slong k; + ulong m; - dirichlet_char_clear(chi); - dirichlet_char_clear(chi2); - dirichlet_conrey_clear(x); - dirichlet_group_clear(G); + for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); + dirichlet_char_log(x, G, m); + + if (m != dirichlet_char_exp(x, G)) + { + flint_printf("FAIL: char log and exp\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("m = %wu\n\n", m); + flint_printf("char = "); + dirichlet_char_print(G, x); + flint_printf("\n\nnumber = %wu\n\n", x->n); + abort(); + } + + for (k = 0; k < G->num; k++) + x->log[k] = n_randint(state, G->P[k].phi.n); + + m = dirichlet_char_exp(x, G); + dirichlet_char_log(y, G, m); + + if (!dirichlet_char_eq_deep(G, x, y)) + { + flint_printf("FAIL: char exp and log\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("char = "); + dirichlet_char_print(G, x); + flint_printf("\n\nm = %wu\n\n", m); + flint_printf("log = "); + dirichlet_char_print(G, y); + flint_printf("\n\nnumber = %wu\n\n", y->n); + abort(); + } + + dirichlet_char_next_primitive(x, G); + m = x->n; + + if (m != dirichlet_char_exp(x, G)) + { + flint_printf("FAIL: char number next primitive\n\n"); + flint_printf("q = %wu\n\n", q); + flint_printf("char = "); + dirichlet_char_print(G, y); + flint_printf(", m = %wu\n\n", y->n); + flint_printf("next primitive = "); + dirichlet_char_print(G, x); + flint_printf(", m = %wu\n\n", m); + flint_printf("exp = %wu\n\n", x->n); + abort(); + } + } } + + dirichlet_char_clear(x); + dirichlet_char_clear(y); + dirichlet_group_clear(G); } flint_randclear(state); diff --git a/dirichlet/test/t-conrey.c b/dirichlet/test/t-conrey.c deleted file mode 100644 index 525d7c00..00000000 --- a/dirichlet/test/t-conrey.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -int main() -{ - slong iter; - flint_rand_t state; - - flint_printf("conrey...."); - fflush(stdout); - flint_randinit(state); - - for (iter = 0; iter < 3000 * arb_test_multiplier(); iter++) - { - dirichlet_group_t G; - dirichlet_conrey_t x, y; - ulong q, n, k, sum; - slong ref; - - q = 1 + n_randint(state, 1000 * (1 + iter / 100)); - - dirichlet_group_init(G, q); - - dirichlet_conrey_init(x, G); - dirichlet_conrey_init(y, G); - - /* check group size and elements */ - dirichlet_conrey_one(x, G); - sum = 1; - - for (n = 1; dirichlet_conrey_next(x, G) >= 0; n++) - sum += x->n * x->n; - - if (FLINT_BITS == 64 || q < 1024) - { - /* use http://oeis.org/A053818 to check all elements - * are gone through */ - ref = (q % 4 == 2) ? -2 : 1; - for (k = (G->neven == 2); k < G->num; k++) - ref = - ref * G->P[k].p; - ref = ( G->phi_q * (2 * q * q + ref) ) / 6; - - if (n != G->phi_q) - { - flint_printf("FAIL: group size\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("phi(q) = %wu\n\n", G->phi_q); - flint_printf("loop index = %wu\n\n", n); - abort(); - } - if (sum != ref && q > 1) - { - flint_printf("FAIL: sum test\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("sum k^2 = %wu\n\n", ref); - flint_printf("sum obtained = %wu\n\n", sum); - abort(); - } - } - - if (q % 4 != 2) - { - dirichlet_conrey_first_primitive(x, G); - for (n = 1; dirichlet_conrey_next_primitive(x, G) >= 0; n++); - - ref = dirichlet_number_primitive(G); - if (n != ref) - { - flint_printf("FAIL: number of primitive elements\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("# primitive = %wu\n\n", ref); - flint_printf("loop index = %wu\n\n", n); - abort(); - } - - /* some random elements, check log and exp */ - for (n = 0; n < 30; n++) - { - slong k; - ulong m; - - for (m = 1; n_gcd(m, q) > 1; m = n_randint(state, q)); - dirichlet_conrey_log(x, G, m); - - if (m != dirichlet_conrey_exp(x, G)) - { - flint_printf("FAIL: conrey log and exp\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("m = %wu\n\n", m); - flint_printf("conrey = "); - dirichlet_conrey_print(G, x); - flint_printf("\n\nnumber = %wu\n\n", x->n); - abort(); - } - - for (k = 0; k < G->num; k++) - x->log[k] = n_randint(state, G->P[k].phi); - - m = dirichlet_conrey_exp(x, G); - dirichlet_conrey_log(y, G, m); - - if (!dirichlet_conrey_eq_deep(G, x, y)) - { - flint_printf("FAIL: conrey exp and log\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("conrey = "); - dirichlet_conrey_print(G, x); - flint_printf("\n\nm = %wu\n\n", m); - flint_printf("log = "); - dirichlet_conrey_print(G, y); - flint_printf("\n\nnumber = %wu\n\n", y->n); - abort(); - } - - dirichlet_conrey_next_primitive(x, G); - m = x->n; - - if (m != dirichlet_conrey_exp(x, G)) - { - flint_printf("FAIL: conrey number next primitive\n\n"); - flint_printf("q = %wu\n\n", q); - flint_printf("conrey = "); - dirichlet_conrey_print(G, y); - flint_printf(", m = %wu\n\n", y->n); - flint_printf("next primitive = "); - dirichlet_conrey_print(G, x); - flint_printf(", m = %wu\n\n", m); - flint_printf("exp = %wu\n\n", x->n); - abort(); - } - } - } - - dirichlet_conrey_clear(x); - dirichlet_conrey_clear(y); - dirichlet_group_clear(G); - } - - flint_randclear(state); - flint_cleanup(); - flint_printf("PASS\n"); - return EXIT_SUCCESS; -} diff --git a/dirichlet/test/t-properties.c b/dirichlet/test/t-properties.c new file mode 100644 index 00000000..11cd1b79 --- /dev/null +++ b/dirichlet/test/t-properties.c @@ -0,0 +1,199 @@ +/* + Copyright (C) 2016 Pascal Molin + + This file is part of Arb. + + Arb is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "dirichlet.h" + +static void +check_eq(ulong p1, ulong p2, ulong q, ulong m, char * fct1, char * fct2) +{ + if (p1 != p2) + { + flint_printf("FAIL:\n\n"); + flint_printf("chi_%wu(%wu,.)\n\n", q, m); + flint_printf("%s = %wu\n\n", fct1, p1); + flint_printf("%s = %wu\n\n", fct2, p2); + abort(); + } +} + +static ulong +random_divisor(flint_rand_t state, const dirichlet_group_t G) +{ + ulong d; + slong k; + d = 1; + for (k = (G->neven == 2); k < G->num; k++) + d *= n_pow(G->P[k].p, n_randint(state, G->P[k].e)); + return d; +} + +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; +} diff --git a/acb_dirichlet/test/t-vec.c b/dirichlet/test/t-vec.c similarity index 51% rename from acb_dirichlet/test/t-vec.c rename to dirichlet/test/t-vec.c index d3cea907..edb2ad08 100644 --- a/acb_dirichlet/test/t-vec.c +++ b/dirichlet/test/t-vec.c @@ -9,7 +9,7 @@ (at your option) any later version. See . */ -#include "acb_dirichlet.h" +#include "dirichlet.h" static ulong vec_diff(ulong * v, ulong * ref, ulong nv) @@ -31,41 +31,55 @@ int main() for (q = 2; q < 600; q ++) { dirichlet_group_t G; - dirichlet_conrey_t x; dirichlet_char_t chi; ulong * v1, * v2, nv, k; dirichlet_group_init(G, q); - dirichlet_conrey_init(x, G); dirichlet_char_init(chi, G); nv = 100; v1 = flint_malloc(nv * sizeof(ulong)); v2 = flint_malloc(nv * sizeof(ulong)); - dirichlet_conrey_one(x, G); + dirichlet_char_one(chi, G); do { - dirichlet_char_conrey(chi, G, x); + ulong order; - dirichlet_ui_chi_vec_loop(v1, G, chi, nv); - dirichlet_ui_chi_vec_primeloop(v2, G, chi, nv); + dirichlet_chi_vec_loop(v1, G, chi, nv); + dirichlet_chi_vec_primeloop(v2, G, chi, nv); if ((k = vec_diff(v1, v2, nv))) { - flint_printf("FAIL: chi(%wu,%wu) = %wu != chi(%wu,%wu) = %wu mod %wu (modulus = %wu)\n", - chi->x->n, k, v1[k], chi->x->n, k, v2[k], chi->order, q); + flint_printf("FAIL: chi_%wu(%wu,%wu) [mod %wu]\n", q, chi->n, k, G->expo); + flint_printf("vec_loop -> %wu\n", v1[k]); + flint_printf("vec_primeloop -> %wu\n", v2[k]); + flint_printf("pairing = %wu\n", dirichlet_pairing(G, chi->n, k)); abort(); } - } while (dirichlet_conrey_next(x, G) >= 0); + order = dirichlet_order_char(G, chi); + dirichlet_chi_vec_loop_order(v1, G, chi, order, nv); + dirichlet_chi_vec_primeloop_order(v2, G, chi, order, nv); + + if ((k = vec_diff(v1, v2, nv))) + { + flint_printf("FAIL: chi_%wu(%wu,%wu) [mod %wu]\n", q, chi->n, k, order); + flint_printf("vec_loop -> %wu\n", v1[k]); + flint_printf("vec_primeloop -> %wu\n", v2[k]); + flint_printf("pairing = %wu mod %wu\n", dirichlet_pairing(G, chi->n, k), G->expo); + abort(); + } + + + + } while (dirichlet_char_next(chi, G) >= 0); flint_free(v1); flint_free(v2); dirichlet_group_clear(G); dirichlet_char_clear(chi); - dirichlet_conrey_clear(x); } flint_cleanup(); diff --git a/dirichlet/ui_chi_conrey.c b/dirichlet/ui_chi_conrey.c deleted file mode 100644 index 44f93fcc..00000000 --- a/dirichlet/ui_chi_conrey.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -ulong -dirichlet_ui_chi_char(const dirichlet_group_t G, const dirichlet_fullchar_t chi, const dirichlet_char_t x) -{ - ulong v = 0, k; - - /* TODO: nmod_addmul? */ - for (k = 0; k < G->num; k++) - v = nmod_add(v, nmod_mul(chi->expo[k], x->log[k], chi->order), chi->order); - - return v; -} diff --git a/dirichlet/ui_chi_vec.c b/dirichlet/ui_chi_vec.c deleted file mode 100644 index 92ca6817..00000000 --- a/dirichlet/ui_chi_vec.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -void -dirichlet_ui_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) -{ - if (2 * nv > G->q) - dirichlet_ui_chi_vec_loop(v, G, chi, nv); - else - dirichlet_ui_chi_vec_primeloop(v, G, chi, nv); -} diff --git a/dirichlet/ui_chi_vec_primeloop.c b/dirichlet/ui_chi_vec_primeloop.c deleted file mode 100644 index 31dd4ca7..00000000 --- a/dirichlet/ui_chi_vec_primeloop.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -static void -chi_vec_evenpart(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) -{ - - ulong c3, c4, x; - - if (G->neven >= 1 && (c3 = chi->expo[0])) - { - for (x = 3; x < nv; x += 4) - v[x] = c3; - } - if (G->neven == 2 && (c4 = chi->expo[1])) - { - ulong g, vx, xp; - nmod_t pe; - vx = c4; - pe = G->P[1].pe; - g = G->P[1].g; - - for (x = g; x > 1;) - { - - for (xp = x; xp < nv; xp += pe.n) - v[xp] = nmod_add(v[xp], vx, chi->order); - - for (xp = pe.n - x; xp < nv; xp += pe.n) - v[xp] = nmod_add(v[xp], vx, chi->order); - - x = nmod_mul(x, g, pe); - vx = nmod_add(vx, c4, chi->order); - } - } -} - -/* loop over primary components */ -void -dirichlet_ui_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_fullchar_t chi, slong nv) -{ - slong k, l; - - for (k = 0; k < nv; k++) - v[k] = 0; - - if (G->neven) - chi_vec_evenpart(v, G, chi, nv); - - for (l = G->neven; l < G->num; l++) - { - dirichlet_prime_group_struct P = G->P[l]; - - /* FIXME: there may be some precomputed dlog in P if needed */ - if (P.dlog == NULL) - dlog_vec_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, chi->order); - else - dlog_vec_add_precomp(v, nv, P.dlog, P.g, chi->expo[l], P.pe, P.phi, chi->order); - - } - dirichlet_ui_vec_set_null(v, G, nv); -} diff --git a/dirichlet/ui_conductor.c b/dirichlet/ui_conductor.c index 4c2d1295..63d68273 100644 --- a/dirichlet/ui_conductor.c +++ b/dirichlet/ui_conductor.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_ui_conductor(const dirichlet_group_t G, ulong a) +dirichlet_conductor_ui(const dirichlet_group_t G, ulong a) { slong k; ulong ap, cond; diff --git a/dirichlet/ui_order.c b/dirichlet/ui_order.c index 6c58db89..c812d015 100644 --- a/dirichlet/ui_order.c +++ b/dirichlet/ui_order.c @@ -31,7 +31,7 @@ nmod_order_precomp(ulong a, nmod_t mod, ulong expo, n_factor_t fac) } ulong -dirichlet_ui_order(const dirichlet_group_t G, ulong a) +dirichlet_order_ui(const dirichlet_group_t G, ulong a) { n_factor_t fac; diff --git a/dirichlet/ui_pairing_conrey.c b/dirichlet/ui_pairing_conrey.c deleted file mode 100644 index 3488f873..00000000 --- a/dirichlet/ui_pairing_conrey.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2015 Jonathan Bober - Copyright (C) 2016 Fredrik Johansson - Copyright (C) 2016 Pascal Molin - - This file is part of Arb. - - Arb is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include "dirichlet.h" - -ulong -dirichlet_ui_pairing_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b) -{ - ulong x, k; - x = 0; - - for (k = 0; k < G->num; k++) - x = n_addmod(x, G->PHI[k] * n_mulmod2(a->log[k], b->log[k], G->P[k].phi), G->expo); - - return x; -} diff --git a/dirichlet/ui_parity.c b/dirichlet/ui_parity.c index 6312dc81..44191e25 100644 --- a/dirichlet/ui_parity.c +++ b/dirichlet/ui_parity.c @@ -12,7 +12,7 @@ #include "dirichlet.h" int -dirichlet_ui_parity(const dirichlet_group_t G, ulong a) +dirichlet_parity_ui(const dirichlet_group_t G, ulong a) { int par; diff --git a/dirichlet/ui_vec_set_null.c b/dirichlet/ui_vec_set_null.c index 834a5c0b..65a05aef 100644 --- a/dirichlet/ui_vec_set_null.c +++ b/dirichlet/ui_vec_set_null.c @@ -12,7 +12,7 @@ #include "dirichlet.h" void -dirichlet_ui_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv) +dirichlet_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv) { slong k, l; if (G->q_even > 1) From cba285dd4d6b75d61a2ac288b21d014b5fc34077 Mon Sep 17 00:00:00 2001 From: Pascal Date: Sat, 8 Oct 2016 22:43:29 +0200 Subject: [PATCH 139/139] update doc and change chi_char to pairing_char --- acb_dirichlet.h | 2 +- acb_dirichlet/l_hurwitz.c | 2 +- acb_dirichlet/pairing_conrey.c | 4 +- dirichlet.h | 2 +- dirichlet/chi.c | 2 +- dirichlet/pairing.c | 2 +- dirichlet/{chi_char.c => pairing_char.c} | 2 +- doc/source/acb_dirichlet.rst | 9 +- doc/source/dirichlet.rst | 298 +++++++++-------------- 9 files changed, 134 insertions(+), 189 deletions(-) rename dirichlet/{chi_char.c => pairing_char.c} (85%) diff --git a/acb_dirichlet.h b/acb_dirichlet.h index 7330f572..49a5c06a 100644 --- a/acb_dirichlet.h +++ b/acb_dirichlet.h @@ -33,7 +33,7 @@ void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec); -void acb_dirichlet_chi_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec); +void acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec); /* precompute powers of a root of unity */ typedef struct diff --git a/acb_dirichlet/l_hurwitz.c b/acb_dirichlet/l_hurwitz.c index 5d10e72a..380b8749 100644 --- a/acb_dirichlet/l_hurwitz.c +++ b/acb_dirichlet/l_hurwitz.c @@ -52,7 +52,7 @@ acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, _acb_vec_nth_roots(z, order, prec); do { - chin = dirichlet_chi_char(G, chi, cn) / mult; + chin = dirichlet_pairing_char(G, chi, cn) / mult; acb_set_ui(a, cn->n); acb_div_ui(a, a, G->q, prec); diff --git a/acb_dirichlet/pairing_conrey.c b/acb_dirichlet/pairing_conrey.c index c9c1284a..bc57bb1c 100644 --- a/acb_dirichlet/pairing_conrey.c +++ b/acb_dirichlet/pairing_conrey.c @@ -12,10 +12,10 @@ #include "acb_dirichlet.h" void -acb_dirichlet_chi_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec) +acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec) { ulong expo; - expo = dirichlet_chi_char(G, a, b); + expo = dirichlet_pairing_char(G, a, b); if (expo == DIRICHLET_CHI_NULL) acb_zero(res); else diff --git a/dirichlet.h b/dirichlet.h index 673bde66..861f422d 100644 --- a/dirichlet.h +++ b/dirichlet.h @@ -130,6 +130,7 @@ void dirichlet_char_lift(dirichlet_char_t y, const dirichlet_group_t G, const di #define DIRICHLET_CHI_NULL UWORD_MAX ulong dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n); +ulong dirichlet_pairing_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); DIRICHLET_INLINE int dirichlet_char_is_principal(const dirichlet_char_t chi) @@ -143,7 +144,6 @@ dirichlet_char_is_real(const dirichlet_group_t G, const dirichlet_char_t chi) return (nmod_mul(chi->n, chi->n, G->mod) == 1); } -ulong dirichlet_chi_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b); ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n); void dirichlet_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv); diff --git a/dirichlet/chi.c b/dirichlet/chi.c index 43901218..3adddfa7 100644 --- a/dirichlet/chi.c +++ b/dirichlet/chi.c @@ -25,7 +25,7 @@ dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) dirichlet_char_init(x, G); dirichlet_char_log(x, G, n); - v = dirichlet_chi_char(G, chi, x); + v = dirichlet_pairing_char(G, chi, x); dirichlet_char_clear(x); return v; diff --git a/dirichlet/pairing.c b/dirichlet/pairing.c index cf4fd648..8d7cd05f 100644 --- a/dirichlet/pairing.c +++ b/dirichlet/pairing.c @@ -25,7 +25,7 @@ dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n) dirichlet_char_log(a, G, m); dirichlet_char_log(b, G, n); - x = dirichlet_chi_char(G, a, b); + x = dirichlet_pairing_char(G, a, b); dirichlet_char_clear(a); dirichlet_char_clear(b); diff --git a/dirichlet/chi_char.c b/dirichlet/pairing_char.c similarity index 85% rename from dirichlet/chi_char.c rename to dirichlet/pairing_char.c index 951b4cb2..01fa1e47 100644 --- a/dirichlet/chi_char.c +++ b/dirichlet/pairing_char.c @@ -12,7 +12,7 @@ #include "dirichlet.h" ulong -dirichlet_chi_char(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_char_t x) +dirichlet_pairing_char(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_char_t x) { ulong v = 0, k; nmod_t order; diff --git a/doc/source/acb_dirichlet.rst b/doc/source/acb_dirichlet.rst index 53f64094..d5588b94 100644 --- a/doc/source/acb_dirichlet.rst +++ b/doc/source/acb_dirichlet.rst @@ -34,6 +34,13 @@ Character evaluation Compute the *nv* first Dirichlet values. +.. function:: void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec) + +.. function:: void acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec) + + Sets *res* to the value of the Dirichlet pairing `\chi(m,n)` at numbers `m` and `n`. + The second form takes two characters as input. + Gauss and Jacobi sums ------------------------------------------------------------------------------- @@ -180,7 +187,7 @@ L-functions .. math:: - (\frac{q}{π})^{\frac{s+p}2}\Gamma(\frac{s+p}2) L(s, \chi) = \epsilon(\chi) (\frac{q}{π})^{\frac{1-s+p}2}\Gamma(\frac{1-s+p}2) L(1 - s, \overline\chi) + \left(\frac{q}{π}\right)^{\frac{s+p}2}\Gamma\left(\frac{s+p}2\right) L(s, \chi) = \epsilon(\chi) \left(\frac{q}{π}\right)^{\frac{1-s+p}2}\Gamma\left(\frac{1-s+p}2\right) L(1 - s, \overline\chi) - The *theta* variant uses the evaluation at `t=1` of the Theta series. diff --git a/doc/source/dirichlet.rst b/doc/source/dirichlet.rst index 5d5c8603..a77bf45f 100644 --- a/doc/source/dirichlet.rst +++ b/doc/source/dirichlet.rst @@ -7,10 +7,9 @@ without notice.* This module allows working with Dirichlet characters algebraically. -For evaluations of characters as complex numbers and Dirichlet L-functions, -see the :ref:`acb_dirichlet` module. +For evaluations of characters as complex numbers, see :ref:`acb-dirichlet`. -Multiplicative group modulo *q* +Dirichlet characters ------------------------------------------------------------------------------- Working with Dirichlet characters mod *q* consists mainly @@ -18,20 +17,28 @@ in going from residue classes mod *q* to exponents on a set of generators of the group. This implementation relies on the Conrey numbering scheme -introduced in the LMFDB, which is an explicit choice of isomorphism +introduced in the +`L-functions and Modular Forms DataBase `_, +which is an explicit choice of generators +allowing to represent Dirichlet characters via the pairing .. math:: - (\mathbb Z/q\mathbb Z)^\times & \to &\bigoplus_i \mathbb Z/\phi_i\mathbb Z \\ - x & \mapsto & (e_i) + \begin{array}{ccccc} + (\mathbb Z/q\mathbb Z)^\times \times (\mathbb Z/q\mathbb Z)^\times & \to & \bigoplus_i \mathbb Z/\phi_i\mathbb Z \times \mathbb Z/\phi_i\mathbb Z & \to &\mathbb C \\ + (m,n) & \mapsto& (a_i,b_i) &\mapsto& \chi_q(m,n) = \exp(2i\pi\sum \frac{a_ib_i}{\phi_i} ) + \end{array} -We call *number* a residue class `x` modulo *q*, and *log* the -corresponding vector `(e_i)` of exponents of Conrey generators. +We call *number* a residue class `m` modulo *q*, and *log* the +corresponding vector `(a_i)` of exponents of Conrey generators. Going from a *log* to the corresponding *number* is a cheap -operation called exp, while the converse requires computing discrete +operation we call exponential, while the converse requires computing discrete logarithms. +Multiplicative group modulo *q* +------------------------------------------------------------------------------- + .. type:: dirichlet_group_struct .. type:: dirichlet_group_t @@ -46,7 +53,9 @@ logarithms. Initializes *G* to the group of Dirichlet characters mod *q*. This method computes a canonical decomposition of *G* in terms of cyclic - groups, which are the mod `p^e` subgroups for `p^e\|q`. + groups, which are the mod `p^e` subgroups for `p^e\|q`, plus + the specific generator described by Conrey for each subgroup. + In particular *G* contains: - the number *num* of components @@ -86,108 +95,6 @@ logarithms. shared with subgroups, those subgroups must be cleared before clearing the tables. -Conrey elements -------------------------------------------------------------------------------- - -.. type:: dirichlet_conrey_struct - -.. type:: dirichlet_conrey_t - - Represents elements of the unit group mod *q*, keeping both the - *number* (residue class) and *log* (exponents on the group - generators). - -.. function:: void dirichlet_conrey_log(dirichlet_conrey_t x, const dirichlet_group_t G, ulong m) - - Sets *x* to the element of number *m*, computing its log using discrete - logarithm in *G*. - -.. function:: ulong dirichlet_conrey_exp(dirichlet_conrey_t x, const dirichlet_group_t G) - - Compute the reverse operation. - -.. function:: void dirichlet_conrey_one(dirichlet_conrey_t x, const dirichlet_group_t G) - - Sets *x* to the *number* `1\in G`, having *log* `[0,\dots 0]`. - -.. function:: void dirichlet_conrey_first_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) - - Sets *x* to the first primitive element of *G*, having *log* `[1,\dots 1]`, - or `[0, 1, \dots 1]` if `8\mid q`. - -.. function:: void dirichlet_conrey_set(dirichlet_conrey_t x, const dirichlet_group_t G, const dirichlet_conrey_t y) - - Sets *x* to the element *y*. - -.. function:: int dirichlet_conrey_next(dirichlet_conrey_t x, const dirichlet_group_t G) - - Sets *x* to the next conrey element in *G* with lexicographic ordering. - - The return value - is the index of the last updated exponent of *x*, or *-1* if the last - element has been reached. - - This function allows to iterate on the elements of *G* looping on their *log*. - Note that it produces elements in seemingly random *number* order. - - The following template can be used to loop over all elements *x* in *G*:: - - acb_conrey_one(x, G); - do { - /* use Conrey element x */ - } while (dirichlet_conrey_next(x, G) >= 0); - -.. function:: int dirichlet_conrey_next_primitive(dirichlet_conrey_t x, const dirichlet_group_t G) - - Same as :func:`dirichlet_conrey_next`, but jumps to the next element - corresponding to a primitive character of *G*. - -.. function:: ulong dirichlet_index_conrey(const dirichlet_group_t G, const dirichlet_conrey_t x); - - Returns the lexicographic index of *x* as an integer in `0\dots \varphi(q)`. - -.. function:: void dirichlet_conrey_index(dirichlet_conrey_t x, const dirichlet_group_t G, ulong j) - - Sets *x* to the Conrey element of lexicographic index *j*. - -.. function:: int dirichlet_conrey_eq(const dirichlet_conrey_t x, const dirichlet_conrey_t y) - -.. function:: int dirichlet_conrey_eq_deep(const dirichlet_group_t G, const dirichlet_conrey_t x, const dirichlet_conrey_t y) - - Return 1 if *x* equals *y*. - The second version checks every byte of the representation and is intended for testing only. - -Dirichlet characters -------------------------------------------------------------------------------- - -Dirichlet characters take value in a finite cyclic group of roots of unity plus zero. - -When evaluation functions return a *ulong*, this number corresponds to the -power of a primitive root of unity, the special value *DIRICHLET_CHI_NULL* -encoding the zero value. - -The Conrey numbering scheme makes explicit the mathematical fact that -the group *G* is isomorphic to its dual, so that a character is described by -a *number*. - -.. math:: - - \begin{array}{ccccc} - (\mathbb Z/q\mathbb Z)^\times \times (\mathbb Z/q\mathbb Z)^\times & \to & \bigoplus_i \mathbb Z/\phi_i\mathbb Z \times \mathbb Z/\phi_i\mathbb Z & \to &\mathbb C \\ - (m,n) & \mapsto& (a_i,b_i) &\mapsto& \chi_q(m,n) = \exp(2i\pi\sum \frac{a_ib_i}{\phi_i} ) - \end{array} - -.. function:: ulong dirichlet_ui_pairing(const dirichlet_group_t G, ulong m, ulong n) - -.. function:: ulong dirichlet_ui_pairing_conrey(const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) - - Compute the value of the Dirichlet pairing on numbers *m* and *n*, as - exponent modulo *G->expo*. - The second form takes the Conrey index *a* and *b*, and does not take discrete - logarithms. - - The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. - Character type ------------------------------------------------------------------------------- @@ -195,8 +102,9 @@ Character type .. type:: dirichlet_char_t - Represents a Dirichlet character. This structure contains various - useful invariants such as the order, the parity and the conductor of the character. + Represents a Dirichlet character. + This structure contains both a *number* (residue class) and + the corresponding *log* (exponents on the group generators). An *dirichlet_char_t* is defined as an array of *dirichlet_char_struct* of length 1, permitting it to be passed by reference. @@ -210,133 +118,163 @@ Character type Clears *chi*. -.. function:: void dirichlet_char(dirichlet_char_t chi, const dirichlet_group_t G, ulong n) +.. function:: void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m) - Sets *chi* to the Dirichlet character of number *n*, using Conrey numbering scheme. - This function performs a discrete logarithm in *G*. + Sets *x* to the character of number *m*, computing its log using discrete + logarithm in *G*. -.. function:: void dirichlet_char_conrey(dirichlet_char_t chi, const dirichlet_group_t G, const dirichlet_conrey_t x) +.. function:: ulong dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G) - Sets *chi* to the Dirichlet character corresponding to *x*. + Computes and returns the number *m* corresponding to exponents in *chi*. -.. function:: int dirichlet_char_eq(const dirichlet_char_t chi1, const dirichlet_char_t chi2) + Since *chi* should always contain its *number*, this function is for internal use + only. -.. function:: int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) +.. function:: void dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G) - Return 1 if *chi1* equals *chi2*. - The second version checks every byte of the representation and is intended for testing only. + Sets *x* to the principal character in *G*, having *log* `[0,\dots 0]`. -.. function:: int dirichlet_char_is_principal(const dirichlet_char_t chi) +.. function:: void dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G) - Return 1 if *chi* is the principal character mod *q*. + Sets *x* to the first primitive character of *G*, having *log* `[1,\dots 1]`, + or `[0, 1, \dots 1]` if `8\mid q`. -.. function:: void dirichlet_char_one(dirichlet_char_t chi, const dirichlet_group_t G) +.. function:: void dirichlet_char_set(dirichlet_char_t x, const dirichlet_group_t G, const dirichlet_char_t y) - Sets *chi* to the principal character. + Sets *x* to the element *y*. -.. function:: void dirichlet_char_set(dirichlet_char_t chi1, const dirichlet_group_t G, const dirichlet_char_t chi2) +.. function:: int dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G) - Sets *chi1* to the character *chi2*. + Sets *x* to the next character in *G* according to lexicographic ordering + of *log*. -.. function:: int dirichlet_char_next(dirichlet_char_t chi, const dirichlet_group_t G) - - Sets *x* to the next character in *G* with lexicographic Conrey ordering - (see :func:`dirichlet_conrey_next`). The return value + The return value is the index of the last updated exponent of *x*, or *-1* if the last element has been reached. -.. function:: int dirichlet_char_next_primitive(dirichlet_char_t chi, const dirichlet_group_t G) + This function allows to iterate on all elements of *G* looping on their *log*. + Note that it produces elements in seemingly random *number* order. - Like :func:`dirichlet_char_next`, but only generates primitive - characters. + The following template can be used for such a loop:: + + dirichlet_char_one(chi, G); + do { + /* use character chi */ + } while (dirichlet_char_next(chi, G) >= 0); + +.. function:: int dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G) + + Same as :func:`dirichlet_char_next`, but jumps to the next primitive character of *G*. + +.. function:: ulong dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x); + + Returns the lexicographic index of the *log* of *x* as an integer in `0\dots \varphi(q)`. + +.. function:: void dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j) + + Sets *x* to the character whose *log* has lexicographic index *j*. + +.. function:: int dirichlet_char_eq(const dirichlet_char_t x, const dirichlet_char_t y) + +.. function:: int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y) + + Return 1 if *x* equals *y*. + + The second version checks every byte of the representation and is intended for testing only. Character properties ------------------------------------------------------------------------------- As a consequence of the Conrey numbering, all these numbers are available at the -level of *number* and Conrey *log* elements, and for *char*. -No discrete log computation is performed. +level of *number* and *char* object. Both case require no discrete log computation. .. function:: ulong dirichlet_number_primitive(const dirichlet_group_t G) - Return the number of primitive elements in *G*. + Returns the number of primitive elements in *G*. -.. function:: ulong dirichlet_ui_conductor(const dirichlet_group_t G, ulong a) +.. function:: int dirichlet_char_is_principal(const dirichlet_group_t G, const dirichlet_char_t chi) -.. function:: ulong dirichlet_conrey_conductor(const dirichlet_group_t G, const dirichlet_conrey_t x) + Returns 1 if *chi* is the principal character mod *q*. -.. function:: ulong dirichlet_char_conductor(const dirichlet_char_t chi) +.. function:: ulong dirichlet_conductor_ui(const dirichlet_group_t G, ulong a) - Return the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` +.. function:: ulong dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x) + + Returns the *conductor* of `\chi_q(a,\cdot)`, that is the smallest `r` dividing `q` such `\chi_q(a,\cdot)` can be obtained as a character mod `r`. - This number is precomputed for the *char* type. -.. function:: int dirichlet_ui_parity(const dirichlet_group_t G, ulong a) +.. function:: int dirichlet_parity_ui(const dirichlet_group_t G, ulong a) -.. function:: int dirichlet_conrey_parity(const dirichlet_group_t G, const dirichlet_conrey_t x) +.. function:: int dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x) -.. function:: int dirichlet_char_parity(const dirichlet_char_t chi) - - Return the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that + Returns the *parity* `\lambda` in `\{0,1\}` of `\chi_q(a,\cdot)`, such that `\chi_q(a,-1)=(-1)^\lambda`. - This number is precomputed for the *char* type. -.. function:: ulong dirichlet_ui_order(const dirichlet_group_t G, ulong a) +.. function:: ulong dirichlet_order_ui(const dirichlet_group_t G, ulong a) -.. function:: ulong dirichlet_conrey_order(const dirichlet_group_t G, const dirichlet_conrey_t x) +.. function:: ulong dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x) -.. function:: ulong dirichlet_char_order(const dirichlet_char_t chi) - - Return the order of `\chi_q(a,\cdot)` which is the order of `a\bmod q`. - This number is precomputed for the *char* type. + Returns the order of `\chi_q(a,\cdot)` which is the order of `a\bmod q`. .. function:: int dirichlet_char_is_real(const dirichlet_char_t chi) - Return 1 if *chi* is a real character (iff it has order `\leq 2`). + Returns 1 if *chi* is a real character (iff it has order `\leq 2`). Character evaluation ------------------------------------------------------------------------------- -The image of a Dirichlet character is a finite cyclic group. Dirichlet -character evaluations are exponents in this group. +Dirichlet characters take value in a finite cyclic group of roots of unity plus zero. -.. function:: ulong dirichlet_ui_chi_conrey(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_conrey_t x) +Evaluation functions return a *ulong*, this number corresponds to the +power of a primitive root of unity, the special value *DIRICHLET_CHI_NULL* +encoding the zero value. -.. function:: ulong dirichlet_ui_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) +.. function:: ulong dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n) - Compute that value `\chi(n)` as the exponent mod the order of `\chi`. +.. function:: ulong dirichlet_pairing_char(const dirichlet_group_t G, const dirichlet_char_t chi, const dirichlet_char_t psi) -Vector evaluation -------------------------------------------------------------------------------- + Compute the value of the Dirichlet pairing on numbers *m* and *n*, as + exponent modulo *G->expo*. -.. function:: void dirichlet_ui_chi_vec(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) + The *char* variant takes as input two characters, so that no discrete + logarithm is computed. - Compute the list of exponent values *v[k]* for `0\leq k < nv`. + The returned value is the numerator of the actual value exponent mod the group exponent *G->expo*. + +.. function:: ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n) + + Compute that value `\chi(n)` as the exponent modulo *G->expo*. + +.. function:: void dirichlet_chi_vec(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv) + + Compute the list of exponent values *v[k]* for `0\leq k < nv`, as exponents + modulo *G->expo*. + +.. function:: void dirichlet_chi_vec_order(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv) + + Compute the list of exponent values *v[k]* for `0\leq k < nv`, as exponents + modulo *order*, which is assumed to be a multiple of the order of *chi*. Character operations ------------------------------------------------------------------------------- -.. function:: void dirichlet_conrey_mul(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, const dirichlet_conrey_t b) - .. function:: void dirichlet_char_mul(dirichlet_char_t chi12, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2) - Multiply two characters in the same group. + Multiply two characters of the same group *G*. -.. function:: void dirichlet_conrey_pow(dirichlet_conrey_t c, const dirichlet_group_t G, const dirichlet_conrey_t a, ulong n) +.. function:: void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n) Take the power of some character. -Implementation notes -------------------------------------------------------------------------------- +.. function:: void dirichlet_char_lift(dirichlet_char_t chi_G, const dirichlet_group_t G, const dirichlet_char_t chi_H, const dirichlet_group_t H) -The current implementation introduces a *char* type which contains a *conrey* -log plus additional information which + If *H* is a subgroup of *G*, computes the character in *G* corresponding to + *chi_H* in *H*. -- makes evaluation of a single character a bit faster +.. function:: void dirichlet_char_lower(dirichlet_char_t chi_H, const dirichlet_group_t H, const dirichlet_char_t chi_G, const dirichlet_group_t G) -- has some initialization cost. + If *chi_G* is a character of *G* which factors through *H*, sets *chi_H* to + the corresponding restriction in *H*. -Even if it is straightforward to convert a *conrey* log to the -corresponding *char*, looping is faster at the -level of Conrey representation. Things can be improved on this aspect -but it makes code more intricate. + This requires `c(\chi_G)\mid q_H\mid q_G`, where `c(\chi_G)` is the + conductor of `\chi_G` and `q_G, q_H` are the moduli of G and H.