FLINT3.7.0-dev

Isolated Bernoulli numbers

Synopsis#include <flint/bernoulli.h>
void bernoulli_fmpq_ui(fmpq_t b, ulong n)source
void _bernoulli_fmpq_ui(fmpz_t num, fmpz_t den, ulong n)source

Set the result to BnB_n in lowest terms with a positive denominator. The value is copied from the cache if it is there; the cache is not extended. Otherwise odd nn and n<18000n < 18000 use _bernoulli_fmpq_ui_zeta, and larger even nn use _bernoulli_fmpq_ui_multi_mod with the default tuning.

void _bernoulli_fmpq_ui_zeta(fmpz_t num, fmpz_t den, ulong n)source
void _bernoulli_fmpq_ui_multi_mod(fmpz_t num, fmpz_t den, ulong n, double alpha)source

Set num and den to the numerator and denominator of BnB_n in lowest terms, by two methods.

The zeta version computes the denominator dd with arith_bernoulli_number_denom (von Staudt–Clausen), approximates BnB_n with arb_bernoulli_ui_zeta from ∣Bn∣=2 n! ζ(n)/(2π)n|B_n| = 2\, n!\, \zeta(n)/(2\pi)^n at a precision slightly above the size of dBnd B_n, and rounds dBnd B_n to the unique integer in the resulting ball, increasing the precision if needed.

The multi_mod version computes the numerator modulo the product MM of the primes 5≤p5 \le p with (p−1)∤n(p - 1) \nmid n (residues by bernoulli_mod_p_harvey, in parallel with the threads of flint_set_num_threads) up to a fraction alpha of the bits of the numerator, and the remaining high bits from the zeta function: the numerator is r+tMr + tM where rr is the residue and tt the unique integer in a ball for (dBn−r)/M(d B_n - r)/M. The parameter 0≤α≤10 \le \alpha \le 1 balances the two parts; a negative value selects the default, 0 for n<18000n < 18000, 0.005+3.6⋅10−6n0.005 + 3.6 \cdot 10^{-6} n for n<60000n < 60000 and min⁡(0.18+0.5⋅10−6n,0.28)\min(0.18 + 0.5 \cdot 10^{-6} n, 0.28) above. For n<10n < 10 or odd nn the zeta version is called.

ulong bernoulli_mod_p_harvey(ulong n, ulong p)source

Returns Bn mod pB_n \bmod p for a prime p<2FLINT_D_BITSp < 2^{\mathtt{FLINT\_D\_BITS}} (2532^{53} on 64-bit machines), computed with Harvey's algorithm [Har2010] in time O(plog⁡O(1)p)O(p \log^{O(1)} p), independent of nn. If pp divides the denominator of BnB_n (that is, n≥2n \ge 2 even with (p−1)∣n(p - 1) \mid n, or n=1n = 1 and p=2p = 2), returns UWORD_MAX.

A return value of 0 means that pp divides the numerator of BnB_n; for nn even, p≥5p \ge 5 and (p−1)∤n(p-1) \nmid n this happens if and only if pp is irregular with an index ≡n(modp−1)\equiv n \pmod{p-1}, or p∣np \mid n. The function reduces nn modulo p−1p - 1 by Kummer's congruence and computes Bm/m mod pB_m/m \bmod p for m=n mod (p−1)m = n \bmod (p-1).

bernoulli_fmpq_ui is the function to use for a single Bernoulli number BnB_n. For a range of consecutive values, bernoulli_fmpq_vec_no_cache or the cache (bernoulli_cache_compute) is much faster than repeated calls, and for the residue of BnB_n modulo a prime, bernoulli_mod_p_harvey avoids computing BnB_n at all.

AlgorithmBernoulli numbersComputes exact Bernoulli numbers from the zeta function (numerically, with the denominator from von Staudt–Clausen), from Harvey's multimodular algorithm, by a reverse zeta iterator with a table of powers for ranges, and by Ramanujan's recursion or power series modulo primes for short vectors.

How BnB_n is computed#

The denominator of BnB_n is known in advance: by the theorem of von Staudt and Clausen it is the product of the primes pp with (p−1)∣n(p - 1) \mid n (arith_bernoulli_number_denom). It has few bits, about O(log⁡n⋅nϵ)O(\log n \cdot n^{\epsilon}) in the worst case, so the work is in the numerator, which has about nlog⁡2nn \log_2 n bits: log⁡2∣Bn∣≈nlog⁡2(n/(2πe))\log_2 |B_n| \approx n \log_2(n / (2 \pi e)). Two methods find it.

  • The zeta function. For even n≥2n \ge 2,

    Bn=(−1)n/2+12 n!(2π)nζ(n),B_n = (-1)^{n/2+1} \frac{2\, n!}{(2\pi)^n} \zeta(n),

    and ζ(n)=1+2−n+3−n+⋯\zeta(n) = 1 + 2^{-n} + 3^{-n} + \cdots converges so fast that about n1+o(1)n^{1 + o(1)} bits of precision need only O(n/log⁡n)O(n / \log n) terms of the series, or an Euler product. Multiplying the approximation by the denominator gives a ball containing one integer, the numerator. _bernoulli_fmpq_ui_zeta does this with arb_bernoulli_ui_zeta; the cost is O(n2log⁡O(1)n)O(n^2 \log^{O(1)} n) bit operations.

  • Multimodular. Harvey's algorithm computes Bn mod pB_n \bmod p in time O(plog⁡O(1)p)O(p \log^{O(1)} p), independent of nn. With primes up to about nlog⁡nn \log n this gives the numerator modulo a number larger than itself in total time O(n2log⁡O(1)n)O(n^2 \log^{O(1)} n) [Har2010], with a better constant and trivial parallelism. _bernoulli_fmpq_ui_multi_mod computes only the low bits this way, a fraction alpha of the total, and the high bits from the zeta function, which is the cheapest combination in practice.

bernoulli_fmpq_ui first looks in the cache, then uses the zeta method for n<18000n < 18000 and the combined method above, where most of the time is spent on the residues, which run in parallel with flint_set_num_threads.

Residues modulo primes#

bernoulli_mod_p_harvey returns Bn mod pB_n \bmod p for a prime p<253p < 2^{53}. It reduces nn modulo p−1p - 1 with Kummer's congruence Bn/n≡Bm/m(modp)B_n/n \equiv B_m/m \pmod p for n≡m≢0(modp−1)n \equiv m \not\equiv 0 \pmod{p-1}, then evaluates a sum of O(p)O(p) terms whose inner loop is a table lookup on the binary expansion of 1/p1/p. When p−1p - 1 divides nn, pp divides the denominator of BnB_n and the function returns UWORD_MAX. A result of 0 means that pp divides the numerator, as for p=691p = 691 and B12=−691/2730B_{12} = -691/2730; primes with this property for some n<p−1n < p - 1 are the irregular primes.

Example#

Examplebernoulli_isolated.cchecked by make checkdoc
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpq.h>
#include <flint/bernoulli.h>

int main(void)
{
    fmpq_t b;
    fmpz_t p, r;

    fmpq_init(b);
    fmpz_init(p);
    fmpz_init(r);

    bernoulli_fmpq_ui(b, 20);
    flint_printf("B_20 = ");
    fmpq_print(b);
    flint_printf("\n");

    bernoulli_fmpq_ui(b, 10000);
    flint_printf("B_10000: numerator of %wu bits, denominator ",
        fmpz_bits(fmpq_numref(b)));
    fmpz_print(fmpq_denref(b));
    flint_printf("\n");

    /* compare with Harvey's algorithm modulo p = 1000003 */
    fmpz_set_ui(p, 1000003);
    fmpq_mod_fmpz(r, b, p);
    flint_printf("B_10000 mod p: %wu (Harvey), ",
        bernoulli_mod_p_harvey(10000, 1000003));
    fmpz_print(r);
    flint_printf(" (exact)\n");

    flint_printf("B_12 mod 691 = %wu\n", bernoulli_mod_p_harvey(12, 691));
    flint_printf("B_12 mod 13 is undefined: %d\n",
        bernoulli_mod_p_harvey(12, 13) == UWORD_MAX);

    fmpq_clear(b);
    fmpz_clear(p);
    fmpz_clear(r);
    return 0;
}
Output
B_20 = -174611/330
B_10000: numerator of 91986 bits, denominator 2338224387510
B_10000 mod p: 932435 (Harvey), 932435 (exact)
B_12 mod 691 = 0
B_12 mod 13 is undefined: 1

References#

  • [Har2010] D. Harvey, "A multimodular algorithm for computing Bernoulli numbers" (2010), Mathematics of Computation 79.272: 2361-2370
Cite this page

The FLINT team, “Isolated Bernoulli numbers (bernoulli.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/bernoulli/isolated.html (generated 2026-11-02).