change interface to switch acb / ui output

This commit is contained in:
Pascal 2016-04-05 12:18:39 +02:00
parent 88a2725e98
commit 286ca6c84d
19 changed files with 270 additions and 151 deletions

View file

@ -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 #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_ui_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(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_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(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec);
/* introducing character type */ /* 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_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_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); ulong acb_dirichlet_ui_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, const acb_dirichlet_group_t G, slong nv); void acb_dirichlet_ui_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_ui_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_ui_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_ui_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_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); 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(ulong q, double x, slong prec);

View file

@ -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);
}
}

View file

@ -31,7 +31,7 @@ acb_dirichlet_l(acb_t res, const acb_t s,
while (1) { while (1) {
/* todo: use n_dirichlet_chi and precomputed roots instead */ /* 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_set_ui(a, cn->n);
acb_div_ui(a, a, G->q, prec); 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(u);
acb_clear(a); acb_clear(a);
} }

View file

@ -26,7 +26,7 @@
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
void 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_t t;
fmpq_init(t); fmpq_init(t);

View file

@ -19,30 +19,26 @@
=============================================================================*/ =============================================================================*/
/****************************************************************************** /******************************************************************************
Copyright (C) 2016 Pascal Molin Copyright (C) 2015 Jonathan Bober
Copyright (C) 2016 Fredrik Johansson
******************************************************************************/ ******************************************************************************/
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
ulong void
acb_dirichlet_pairing(const acb_dirichlet_group_t G, ulong m, ulong n) acb_dirichlet_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec)
{ {
ulong x; ulong expo;
acb_dirichlet_conrey_t a, b; expo = acb_dirichlet_ui_pairing(G, m, n);
if (expo == ACB_DIRICHLET_CHI_NULL)
if (n_gcd(G->q, m) > 1 || n_gcd(G->q, n) > 1) acb_zero(res);
return ACB_DIRICHLET_CHI_NULL; else
{
acb_dirichlet_conrey_init(a, G); fmpq_t t;
acb_dirichlet_conrey_init(b, G); fmpq_init(t);
acb_dirichlet_conrey_log(a, G, m); fmpq_set_si(t, 2 * expo, G->expo);
acb_dirichlet_conrey_log(b, G, n); arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec);
fmpq_clear(t);
x = acb_dirichlet_pairing_conrey(G, a, b); }
acb_dirichlet_conrey_clear(a);
acb_dirichlet_conrey_clear(b);
return x;
} }

View file

@ -19,24 +19,25 @@
=============================================================================*/ =============================================================================*/
/****************************************************************************** /******************************************************************************
Copyright (C) 2015 Jonathan Bober
Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin Copyright (C) 2016 Pascal Molin
******************************************************************************/ ******************************************************************************/
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
/* todo: modular arithmetic */ 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
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; ulong expo;
x = 0; expo = acb_dirichlet_ui_pairing_conrey(G, a, b);
if (expo == ACB_DIRICHLET_CHI_NULL)
for (k = 0; k < G->num; k++) acb_zero(res);
x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo; else
{
return x; 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);
}
} }

View file

@ -97,7 +97,7 @@ int main()
abort(); 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)) if (acb_dirichlet_char_parity(chi) != (chim1 != 0))
{ {
flint_printf("FAIL: parity\n\n"); flint_printf("FAIL: parity\n\n");
@ -114,10 +114,10 @@ int main()
while (n_gcd(q, n) > 1); while (n_gcd(q, n) > 1);
acb_dirichlet_char(chi2, G, n); 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) if (pairing != acb_dirichlet_ui_chi(G, chi, n) * (G->expo / chi->order)
|| pairing != acb_dirichlet_chi(G, chi2, m) * (G->expo / chi2->order)) || pairing != acb_dirichlet_ui_chi(G, chi2, m) * (G->expo / chi2->order))
{ {
flint_printf("FAIL: pairing\n\n"); flint_printf("FAIL: pairing\n\n");
flint_printf("q = %wu\n\n", q); flint_printf("q = %wu\n\n", q);

View file

@ -49,8 +49,8 @@ int main()
n1 = n_randint(state, 1000); n1 = n_randint(state, 1000);
n2 = n_randint(state, 1000); n2 = n_randint(state, 1000);
acb_dirichlet_acb_chi(zn1, G, chi, n1, 53); acb_dirichlet_chi(zn1, G, chi, n1, 53);
acb_dirichlet_acb_pairing(zn2, G, m, n1, 53); acb_dirichlet_pairing(zn2, G, m, n1, 53);
if (!acb_overlaps(zn1, zn2)) if (!acb_overlaps(zn1, zn2))
{ {
acb_dirichlet_conrey_t x; acb_dirichlet_conrey_t x;
@ -69,8 +69,8 @@ int main()
abort(); abort();
} }
acb_dirichlet_acb_pairing(zn2, G, m, n2, 53); acb_dirichlet_pairing(zn2, G, m, n2, 53);
acb_dirichlet_acb_pairing(zn1n2, G, m, n1 * n2, 53); acb_dirichlet_pairing(zn1n2, G, m, n1 * n2, 53);
acb_mul(zn1zn2, zn1, zn2, 53); acb_mul(zn1zn2, zn1, zn2, 53);
if (!acb_overlaps(zn1n2, zn1zn2)) if (!acb_overlaps(zn1n2, zn1zn2))
@ -97,7 +97,7 @@ int main()
{ {
if (n_gcd(q, m) == 1) 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); acb_add(zn1, zn1, zn2, 53);
} }
} }

View file

@ -61,7 +61,7 @@ int main()
acb_dirichlet_char_init(chi, G); acb_dirichlet_char_init(chi, G);
acb_init(zeta); acb_init(zeta);
acb_dirichlet_zeta(zeta, G->expo, prec); acb_dirichlet_nth_root(zeta, G->expo, prec);
z = _acb_vec_init(G->expo); z = _acb_vec_init(G->expo);
_acb_vec_set_powers(z, zeta, G->expo, prec); _acb_vec_set_powers(z, zeta, G->expo, prec);
@ -91,7 +91,7 @@ int main()
acb_zero(sum); acb_zero(sum);
acb_dirichlet_char_conrey(chi, G, x); 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; m = G->expo / chi->order;
tt = acb_dirichlet_char_parity(chi) ? kt : t; tt = acb_dirichlet_char_parity(chi) ? kt : t;

View file

@ -63,8 +63,8 @@ int main()
acb_dirichlet_char_conrey(chi, G, x); acb_dirichlet_char_conrey(chi, G, x);
acb_dirichlet_chi_vec_loop(v1, G, chi, nv); acb_dirichlet_ui_chi_vec_loop(v1, G, chi, nv);
acb_dirichlet_chi_vec_primeloop(v2, G, chi, nv); acb_dirichlet_ui_chi_vec_primeloop(v2, G, chi, nv);
if ((k = vec_diff(v1, v2, nv))) if ((k = vec_diff(v1, v2, nv)))
{ {

View file

@ -25,19 +25,22 @@
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
void ulong
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) acb_dirichlet_ui_chi(const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, ulong n)
{ {
ulong expo; if (n_gcd(G->q, n) > 1)
expo = acb_dirichlet_pairing_conrey(G, a, b); {
if (expo == ACB_DIRICHLET_CHI_NULL) return ACB_DIRICHLET_CHI_NULL;
acb_zero(res); }
else else
{ {
fmpq_t t; ulong v = 0, k;
fmpq_init(t); acb_dirichlet_conrey_t x;
fmpq_set_si(t, 2 * expo, G->expo); acb_dirichlet_conrey_init(x, G);
arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); acb_dirichlet_conrey_log(x, G, n);
fmpq_clear(t); for (k = 0; k < G->num; k++)
v = (v + chi->expo[k] * x->log[k]) % chi->order;
acb_dirichlet_conrey_clear(x);
return v;
} }
} }

View file

@ -26,10 +26,10 @@
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
void 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) 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 else
acb_dirichlet_chi_vec_primeloop(v, G, chi, nv); acb_dirichlet_ui_chi_vec_primeloop(v, G, chi, nv);
} }

View file

@ -27,7 +27,7 @@
/* loop over whole group */ /* loop over whole group */
void 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; int j;
ulong t; ulong t;

View file

@ -25,7 +25,7 @@
#include "acb_dirichlet.h" #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) 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 */ /* loop over primary components */
void 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; 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; vx = (vx + vp) % chi->order;
} }
} }
acb_dirichlet_vec_set_null(v, G, nv); acb_dirichlet_ui_vec_set_null(v, G, nv);
} }

View file

@ -27,7 +27,7 @@
/* sieve on primes */ /* sieve on primes */
void 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; slong k, p, pmax;
n_primes_t iter; 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 else
{ {
long chip; long chip;
chip = acb_dirichlet_chi(G, chi, p); chip = acb_dirichlet_ui_chi(G, chi, p);
for (k = p; k < nv; k += p) for (k = p; k < nv; k += p)
if (v[k] != -1) if (v[k] != -1)

View file

@ -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;
}

View file

@ -21,24 +21,22 @@
Copyright (C) 2015 Jonathan Bober Copyright (C) 2015 Jonathan Bober
Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin
******************************************************************************/ ******************************************************************************/
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
void /* todo: modular arithmetic */
acb_dirichlet_acb_pairing(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec)
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; ulong x, k;
expo = acb_dirichlet_pairing(G, m, n); x = 0;
if (expo == ACB_DIRICHLET_CHI_NULL)
acb_zero(res); for (k = 0; k < G->num; k++)
else x = (x + G->PHI[k] * a->log[k] * b->log[k]) % G->expo;
{
fmpq_t t; return x;
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);
}
} }

View file

@ -26,7 +26,7 @@
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
void 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; slong k, l;
if (G->q_even > 1) if (G->q_even > 1)

View file

@ -22,26 +22,48 @@ A Dirichlet L-function is the analytic continuation of an L-series
where `\chi(k)` is a Dirichlet character. 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_struct
.. type:: acb_dirichlet_group_t .. type:: acb_dirichlet_group_t
Represents the group of Dirichlet characters mod *q*. 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. of length 1, permitting it to be passed by reference.
.. function:: void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) .. function:: void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q)
Initializes *G* to the group of Dirichlet characters mod *q*. Initializes *G* to the group of Dirichlet characters mod *q*.
This method computes the prime factorization of *q* and other useful This method computes a canonical decomposition of *G* in terms of cyclic
invariants. It does *not* automatically precompute lookup tables 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 of discrete logarithms or numerical roots of unity, and can therefore
safely be called even with large *q*. safely be called even with large *q*.
For implementation reasons, the largest prime factor of *q* must not For implementation reasons, the largest prime factor of *q* must not
exceed `10^{12}` (an abort will be raised). This restriction could exceed `10^{12}` (an abort will be raised). This restriction could
be removed in the future. be removed in the future.
@ -50,13 +72,111 @@ Dirichlet characters
Clears *G*. 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 Precompute decomposition and tables for discrete log computations in *G*,
of index *m* evaluated at the integer *n*. 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 If *num* gets very large, the entire group may be indexed.
coprime to *q*. There are no restrictions on *n*.
.. 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 Euler products
------------------------------------------------------------------------------- -------------------------------------------------------------------------------