FLINT3.7.0-dev

Evaluating Dirichlet L-functions

Synopsis#include <flint/acb_dirichlet.h>
void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)source
void acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)source

Set res to the root number ϵ(χ)\epsilon(\chi) of a primitive character. The theta version uses ϵ(χ)=Θq(χ,1)/Θq(χ,1)‾\epsilon(\chi) = \Theta_q(\chi, 1) / \overline{\Theta_q(\chi, 1)}; the default version uses the Gauss sum, ϵ(χ)=Gq(χ)/(iδq)\epsilon(\chi) = G_q(\chi)/(i^\delta \sqrt q), when qq has several prime factors, and the theta series otherwise. The default version throws an exception if χ\chi is not primitive.

void acb_dirichlet_l(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)source
void _acb_dirichlet_l_generic(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)source

Sets res to L(s,χ)L(s,\chi), choosing the algorithm. If ss is an exact integer, acb_dirichlet_l_si is used. If ss is an exact real number which is a rational number of small height (see _acb_dirichlet_get_small_fmpq), the approximate functional equation acb_dirichlet_l_fmpq_afe_jet is used when _acb_dirichlet_l_fmpq_use_afe estimates it to be faster (at high precision or for large conductor). Otherwise (and always in the underscore version): the Riemann zeta function for q=1q = 1, the functional equation for primitive χ\chi and Re⁡(s)<−1/2\operatorname{Re}(s) < -1/2 (or near s=0s = 0 for even χ\chi), the Euler product for large Re⁡(s)\operatorname{Re}(s), and otherwise the decomposition into Hurwitz zeta functions with a precomputation shared by the ϕ(q)\phi(q) values.

void acb_dirichlet_l_jet(acb_ptr res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec)source

Sets res to the Taylor coefficients L(s),L′(s),…,L(len−1)(s)/(len−1)!L(s), L'(s), \ldots, L^{(\text{len}-1)}(s)/(\text{len}-1)!. With deflate nonzero and principal χ\chi, the expansion of L(s,χ)−ϕ(q)q(s−1)L(s,\chi) - \frac{\phi(q)}{q (s-1)} is computed instead, which at s=1s = 1 is the regular part of the Laurent expansion; for non-principal χ\chi, deflate has no effect. For q=1q = 1 this calls acb_dirichlet_zeta_jet. Otherwise, if ss is an exact rational number of small height (see _acb_dirichlet_get_small_fmpq), the approximate functional equation acb_dirichlet_l_fmpq_afe_jet is used when _acb_dirichlet_l_jet_use_afe estimates it to be faster (this is not done for principal characters with deflation); otherwise the Hurwitz zeta expansions are summed.

acb_dirichlet_l evaluates L(s,χ)L(s, \chi) at any complex ss for a Dirichlet character χ\chi modulo qq, acb_dirichlet_l_jet its Taylor expansion, and acb_dirichlet_root_number the root number of the functional equation. With G and chi set to NULL (or q=1q = 1) these compute the Riemann zeta function. The methods are compared on Dirichlet L-functions.

Choice of method#

acb_dirichlet_l uses, in this order:

  1. for an exact integer ss, acb_dirichlet_l_si, which uses closed forms with generalized Bernoulli numbers when ss has the same parity as χ\chi, and otherwise the Euler product, a generalization of Borwein's algorithm (acb_dirichlet_l_ui_borwein_bsplit) or the approximate functional equation;
  2. for an exact dyadic ss such as 1/21/2 (more generally an exact rational number of small height), the approximate functional equation (acb_dirichlet_l_fmpq_afe_jet) when _acb_dirichlet_l_fmpq_use_afe estimates it to be faster, i.e. at high precision or for large conductor;
  3. for q=1q = 1, acb_dirichlet_zeta;
  4. for primitive χ\chi and Re⁡(s)<−1/2\operatorname{Re}(s) < -1/2 (or ss near 0 and χ\chi even), the functional equation L(s,χ)=ϵ(χ)(π/q)s−1/2Γ((1−s+δ)/2)Γ((s+δ)/2)L(1−sˉ,χ)‾L(s, \chi) = \epsilon(\chi) (\pi/q)^{s - 1/2} \frac{\Gamma((1-s+\delta)/2)}{\Gamma((s+\delta)/2)} \overline{L(1-\bar s, \chi)}, which moves the evaluation to the right half-plane;
  5. for Re⁡(s)≥8+p/(2log⁡p)\operatorname{Re}(s) \ge 8 + p/(2 \log p) at precision pp, the Euler product acb_dirichlet_l_euler_product;
  6. otherwise the decomposition L(s,χ)=q−s∑k=1qχ(k)ζ(s,k/q)L(s,\chi) = q^{-s}\sum_{k=1}^q \chi(k) \zeta(s, k/q) (acb_dirichlet_l_hurwitz), where the ϕ(q)\phi(q) Hurwitz zeta values come from a precomputed grid of Taylor expansions in aa (acb_dirichlet_hurwitz_precomp_init_num) when this is cheaper than evaluating each by Euler–Maclaurin summation.

The cost of step 6 grows linearly with qq, so these functions are meant for moderate moduli. For many characters with the same modulus, acb_dirichlet_l_vec_hurwitz computes all ϕ(q)\phi(q) values with one set of Hurwitz zeta values and a DFT. For rational ss that cannot be represented exactly by an acb_t (such as 1/31/3), acb_dirichlet_l_fmpq makes the same choices.

For exact rational ss of small height, acb_dirichlet_l_jet uses the approximate functional equation when _acb_dirichlet_l_jet_use_afe estimates it to be faster; otherwise it sums the Hurwitz zeta expansions ζ(s+x,k/q)\zeta(s + x, k/q) (deflated at s=1s = 1, where the poles cancel for non-principal χ\chi) weighted by the character values, for any length; for principal characters, deflate removes the pole ϕ(q)/(q(s−1))\phi(q)/(q(s-1)).

acb_dirichlet_root_number requires a primitive character. For composite moduli it computes ϵ(χ)=Gq(χ)/(iδq)\epsilon(\chi) = G_q(\chi)/(i^\delta\sqrt q) from the Gauss sum, which is a product of local Gauss sums; for prime power moduli it uses the theta series, ϵ(χ)=Θq(χ,1)/Θq(χ,1)‾\epsilon(\chi) = \Theta_q(\chi, 1) / \overline{\Theta_q(\chi, 1)}, which needs O(pq)O(\sqrt{pq}) terms at precision pp.

Example#

L(1,χ4)=π/4L(1, \chi_4) = \pi/4 for the nontrivial character modulo 4, and the value, derivative and root number at s=1/2s = 1/2 of the character modulo 13 with Conrey number 2 (a generator, so the character has order 12).

Exampleacb_dirichlet_l.cchecked by make checkdoc
#include <flint/acb.h>
#include <flint/acb_dirichlet.h>

int main(void)
{
    dirichlet_group_t G;
    dirichlet_char_t chi;
    acb_t s, eps;
    acb_ptr L;
    slong prec = 128;

    acb_init(s);
    acb_init(eps);
    L = _acb_vec_init(2);

    dirichlet_group_init(G, 4);
    dirichlet_char_init(chi, G);
    dirichlet_char_log(chi, G, 3);
    acb_one(s);
    acb_dirichlet_l(L, s, G, chi, prec);
    flint_printf("L(1, chi_4)  = "); acb_printn(L, 30, 0); flint_printf("\n");
    dirichlet_char_clear(chi);
    dirichlet_group_clear(G);

    dirichlet_group_init(G, 13);
    dirichlet_char_init(chi, G);
    dirichlet_char_log(chi, G, 2);
    acb_set_d(s, 0.5);
    acb_dirichlet_l_jet(L, s, G, chi, 0, 2, prec);
    flint_printf("L(1/2, chi)  = "); acb_printn(L, 20, 0); flint_printf("\n");
    flint_printf("L'(1/2, chi) = "); acb_printn(L + 1, 20, 0); flint_printf("\n");
    acb_dirichlet_root_number(eps, G, chi, prec);
    flint_printf("epsilon      = "); acb_printn(eps, 20, 0); flint_printf("\n");
    dirichlet_char_clear(chi);
    dirichlet_group_clear(G);

    acb_clear(s);
    acb_clear(eps);
    _acb_vec_clear(L, 2);
    return 0;
}
Output
L(1, chi_4)  = [0.785398163397448309615660845820 +/- 1.25e-31]
L(1/2, chi)  = [1.3468137049240637212 +/- 3.29e-20] + [0.75459682860501534409 +/- 4.17e-21]*I
L'(1/2, chi) = [-0.038182523834367601160 +/- 3.96e-22] + [-0.45987153676368484477 +/- 3.13e-21]*I
epsilon      = [0.52216611241417884070 +/- 2.28e-21] + [0.85284380225587800538 +/- 3.36e-21]*I
Cite this page

The FLINT team, “Evaluating Dirichlet L-functions (acb_dirichlet.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/acb_dirichlet/l-functions.html (generated 2026-11-02).