dirichlet.h
#include <flint/dirichlet.h>This module works with Dirichlet characters modulo a word-size integer algebraically. A character modulo takes the value 0 on integers not coprime to and roots of unity on the others; the module represents a value exactly by the exponent modulo the exponent of the group, and computes characters, their products and powers, their conductors, parities and orders, and vectors of values, using discrete logarithms from dlog. Characters are labelled in the Conrey numbering of the LMFDB [LMFDB], in which the characters modulo are indexed by the residues , written . Numerical values and -functions are in acb_dirichlet.
Warning: the interfaces in this module are experimental and may change without notice.
The guide Characters in the Conrey numbering explains the numbering and the representation with an example; Dirichlet characters gives the mathematics and the algorithms.
AlgorithmDirichlet charactersRepresents the Dirichlet characters modulo q through the decomposition of the unit group into cyclic components with Conrey's generators, so that characters, values, conductors, parities and orders are computed from discrete logarithms in each component or directly from the Conrey number.Guides#
The group modulo #
The group is a product of cyclic groups, one for each odd prime power and up to two for the power of 2. The structure dirichlet_group_t stores this decomposition with one Conrey generator per component; an element (and the character it labels) is then described by its number or by its log, the vector of exponents of on the generators.
The group with its decomposition: the modulus q, the number of components num, the group order phi_q , the group exponent expo, the generators lifted modulo and, per component, the prime power, the order phi of the component and optional discrete logarithm tables. A dirichlet_group_t is an array of length one of dirichlet_group_struct.
The size (16) of some fixed arrays indexed by the components: the largest number of components of a 64-bit modulus, two for the 2-part and 14 for the odd primes, as for .
int dirichlet_group_init(dirichlet_group_t G, ulong q)Initialises as the group of characters modulo , computing the factorisation of , the Conrey generators and the exponent. No discrete logarithm tables are computed, so this is cheap even for large . Returns 1 on success, and 0 (without allocating) if a prime factor of exceeds , for which the generator is not implemented.
Morevoid dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h)Initialises as the group modulo , for , sharing the components of (in particular its discrete logarithm tables, which must not be cleared while is in use).
Frees the memory used by , but not its discrete logarithm tables, which may be shared with subgroups; free them first with dirichlet_group_dlog_clear.
ulong dirichlet_group_size(const dirichlet_group_t G)Returns the number of elements of , which is also the number of characters modulo .
Returns the number of primitive characters modulo : 0 if , and otherwise the product over the components of for ( odd), for (), 1 for and for , .
void dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num)Precomputes discrete logarithm tables in every component for about num subsequent logarithms, with dlog_precomp_modpe_init. This speeds up dirichlet_char_log, dirichlet_chi and dirichlet_pairing when they are called many times. For very large num the whole group may be tabulated.
Frees the discrete logarithm tables of . Subgroups sharing them must be cleared first.
Characters#
An element of , used as the character : its number n and its log, an array log of num exponents with . A dirichlet_char_t is an array of length one of dirichlet_char_struct.
void dirichlet_char_init(dirichlet_char_t x, const dirichlet_group_t G)Initialises as an element of and sets it to the principal character ().
void dirichlet_char_clear(dirichlet_char_t x)Frees the memory used by .
void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t x)Prints the log of as a list [a_0, a_1, ...].
void dirichlet_char_set(dirichlet_char_t x, const dirichlet_group_t G, const dirichlet_char_t y)Sets to a copy of .
int 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)Return 1 if and are equal, otherwise 0. The first function compares the numbers only; the second also compares the logs and is meant for testing the consistency of the two representations.
void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m)Sets to the character of number , which must be coprime to and reduced modulo , computing its log by discrete logarithms in each component (with the tables of if present).
ulong dirichlet_char_exp(const dirichlet_group_t G, const dirichlet_char_t x)ulong _dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G)Return the number of . The first function reads the stored number; the second recomputes it from the log, stores it in and returns it.
void dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G)Sets to the principal character, with log and number 1.
void dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G)Sets to the first primitive character in the order of dirichlet_char_next_primitive, with log , or if . Throws if , where no primitive character exists.
int dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G)Sets to the next element of in the lexicographic order of the logs (the last component varying fastest), updating the number with one multiplication. Returns the index of the most significant component that changed, or after the last element (when wraps around to the principal character).
Moreint dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G)As dirichlet_char_next, but skips to the next primitive character, in the same order. Start from dirichlet_char_first_primitive.
ulong dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x)void dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j)Convert between an element and its index in the lexicographic order of the logs, the mixed-radix number with digits in base .
Properties#
In the Conrey numbering the conductor, parity and order of can be computed either from the number (the _ui functions) or from the log (the _char functions); neither needs a discrete logarithm.
int dirichlet_char_is_principal(const dirichlet_group_t G, const dirichlet_char_t chi)Returns 1 if is the principal character ().
ulong dirichlet_conductor_ui(const dirichlet_group_t G, ulong a)ulong dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x)Return the conductor of , the smallest such that the character is induced by a character modulo .
int dirichlet_parity_ui(const dirichlet_group_t G, ulong a)int dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x)Return the parity of , defined by : 0 for even and 1 for odd characters.
ulong dirichlet_order_ui(const dirichlet_group_t G, ulong a)ulong dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x)Return the order of in the character group, which is the multiplicative order of modulo .
int dirichlet_char_is_real(const dirichlet_group_t G, const dirichlet_char_t chi)Returns 1 if is real, that is, has order at most 2 (its number satisfies ).
int dirichlet_char_is_primitive(const dirichlet_group_t G, const dirichlet_char_t chi)Returns 1 if is primitive, that is, its conductor is .
Values#
A value is returned as an exponent with , where is the exponent G->expo of the group (or a given order), and the value 0 is encoded by the special exponent DIRICHLET_CHI_NULL. See Values as exponents.
The exponent UWORD_MAX that encodes the value , for not coprime to .
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)Return the exponent of modulo G->expo, or DIRICHLET_CHI_NULL if or is not coprime to . The pairing is symmetric: . The _char version takes both arguments as elements with their logs and needs no discrete logarithm; the other computes two.
ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n)Returns the exponent of modulo G->expo, or DIRICHLET_CHI_NULL if . Costs one discrete logarithm per component of .
void dirichlet_chi_vec(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv)void dirichlet_chi_vec_order(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv)Set to the exponent of for , modulo G->expo or modulo order, which must be a multiple of the order of ; entries with are set to DIRICHLET_CHI_NULL. The functions call the loop versions if and the primeloop versions otherwise. is DIRICHLET_CHI_NULL for , and for , where the trivial character is 1 everywhere, every entry is 0.
void dirichlet_chi_vec_loop(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)As dirichlet_chi_vec, by enumerating the whole group with dirichlet_char_next and updating the value by one addition per step; entries are copied by periodicity. Costs and needs no discrete logarithm. Requires : the function writes .
void dirichlet_chi_vec_primeloop(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv)void dirichlet_chi_vec_primeloop_order(ulong * v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv)As dirichlet_chi_vec, by adding the contributions of the components: the 2-part directly, and each odd prime power with dlog_vec_add, which computes the discrete logarithms of all by sieving (using the tables of if present). See the warning about at dirichlet_chi_vec.
void dirichlet_vec_set_null(ulong * v, const dirichlet_group_t G, slong nv)Sets to DIRICHLET_CHI_NULL for divisible by a prime factor of (except , which is not changed).
Operations on characters#
void dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b)Sets to the product : the logs are added and the numbers multiplied.
void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n)Sets to .
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)Given a character modulo (with a subgroup of created by dirichlet_subgroup_init), sets to the character modulo that it induces. Throws if .
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)Given a character modulo whose conductor divides , with the modulus of , sets to the character modulo that induces it. Throws if or the conductor does not divide .
References#
- [LMFDB] The LMFDB Collaboration, The L-functions and modular forms database, https://www.lmfdb.org (Dirichlet characters: https://www.lmfdb.org/Character/Dirichlet/).
The FLINT team, “dirichlet.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/dirichlet/index.html (generated 2026-11-02).
@misc{flint-doc-dirichlet-index,
author = {{The FLINT team}},
title = {{dirichlet.h (module overview)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/dirichlet/index.html},
note = {Generated 2026-11-02}
}