Bell numbers
#include <flint/arith.h>Set the result to the Bell number B_n. The default version uses a table for n \le 25 (64-bit), the Bell triangle in fixed-size multiword arithmetic for n \le 58, Dobiński's formula for n \le 3400 and the multimodular algorithm above.
The dobinski version computes P = N! \sum_{k=0}^N k^n/k! and Q = N! \sum_{k=0}^N 1/k! \approx N!\, e for N \approx n (1 + 1.2/\log n) and returns \lceil P/Q \rceil, an exact form of Dobiński's formula B_n = e^{-1} \sum_{k \ge 0} k^n/k! [Dob1877] without floating-point arithmetic. Powers of even k are obtained from those of odd k by shifts.
The multi_mod version computes B_n modulo primes of \mathtt{FLINT\_BITS} - 3 bits with the sum used by arith_bell_number_nmod, in Montgomery arithmetic and with powers j^n for composite j obtained as products from a divisor table, and combines the residues by Chinese remaindering. The number of primes is determined by arith_bell_number_size. The primes are processed in parallel with the threads set by flint_set_num_threads.
Set b to B_0, B_1, \ldots, B_{n-1}. The recursive version uses the Bell triangle (Aitken's array), with O(n^2) additions of numbers of O(n \log n) bits; the multi_mod version computes the vector modulo word-size primes with arith_bell_number_nmod_vec and combines them by Chinese remaindering, in O(n^2 \log^{O(1)} n). The default version uses the recursive algorithm for n < 5000.
Returns B_n modulo the modulus of mod, which can be any integer \ge 1.
Small n are read from the table, and the moduli 2 and 3 use the periods 3 and 13 of the sequence. If n is less than the modulus and n! is invertible, the function evaluates
with the factorials scaled by n! so that the main loop only multiplies, the powers of composite numbers sieved from those of their factors, and the sum accumulated in three words; this costs O(n) multiplications and O(n) memory. Otherwise it computes B_0, \ldots, B_n with arith_bell_number_nmod_vec (and throws if n > 2^{\mathtt{FLINT\_BITS} - 3}).
Set b to B_0, \ldots, B_{n-1} modulo the modulus of mod.
The recursive version uses the Bell triangle, with O(n^2) additions. The ogf version expands the ordinary generating function
truncated to length n, with the partial sums computed by binary splitting as a fraction R/Q and one power series division, in O(M(n) \log n). The series version computes \exp(e^x - 1) as a power series and multiplies by factorials, in O(M(n)); it requires (n-1)! to be invertible modulo the modulus and returns 0 (with b unspecified) if it is not, 1 on success. The recursive and ogf versions work for any modulus. The default version uses the recursive algorithm for n < 300, the series version if the modulus is at least n and it succeeds, the recursive algorithm for n < 500 + \mathit{bits}^2 where \mathit{bits} is the bit size of the modulus, and the ogf version otherwise.
Returns b such that B_n < 2^{\lfloor b \rfloor}, from de Bruijn's asymptotic expansion of \log B_n [deB1958] with a margin. The bound is verified for n < 2^{64} but not proved in general; an earlier version used the weaker bound B_n < (0.792n/\log(n+1))^n of [BerTas2010].
The Bell number B_n is the number of partitions of a set of n elements: B_0, B_1, \ldots = 1, 1, 2, 5, 15, 52, 203, \ldots In terms of Stirling numbers of the second kind, B_n = \sum_{k=0}^n S(n,k), and the exponential generating function is \sum_{n \ge 0} B_n x^n/n! = \exp(e^x - 1) [Comtet1974]. The numbers grow slightly slower than n!: \log B_n = n(\log n - \log\log n - 1 + o(1)), 6403 bits for n = 1000.
The module computes an isolated B_n (arith_bell_number), the vector B_0, \ldots, B_{n-1} (arith_bell_number_vec), and the same modulo a word-size integer (arith_bell_number_nmod, arith_bell_number_nmod_vec), which is much cheaper when only the residue is needed.
Isolated values#
arith_bell_number reads B_n from a table for n \le 25 (64-bit), runs the Bell triangle in fixed-size arrays of up to three words for n \le 58, uses Dobiński's formula
for n \le 3400, in an exact form without floating-point arithmetic (arith_bell_number_dobinski), and the multimodular algorithm above (arith_bell_number_multi_mod). The latter computes B_n modulo primes p > n of \mathtt{FLINT\_BITS} - 3 bits with the identity
which needs O(n) multiplications modulo p per prime, and combines the residues by Chinese remaindering; the primes are processed in parallel by the threads of flint_set_num_threads. About n \log_2 n / \mathtt{FLINT\_BITS} primes are needed, so the residues cost O(n^2 \log n) bit operations.
Vectors#
The Bell triangle (Aitken's array) computes B_0, \ldots, B_{n-1} with n^2/2 additions: each row starts with the last entry of the previous row, and each further entry is the sum of its left neighbour and the entry above it; the rows start with the Bell numbers. Over \mathbb{Z} this costs O(n^3 \log n) bit operations and is used for n < 5000; for longer vectors arith_bell_number_vec_multi_mod computes the vector modulo word-size primes and reconstructs each entry with only as many primes as it needs.
Modulo m, arith_bell_number_nmod_vec chooses between three methods: the triangle (O(n^2) operations, any m, used for n < 300), the power series \exp(e^x - 1) (O(M(n)) operations, requires (n-1)! to be invertible modulo m, so in particular m \ge n for prime m), and the ordinary generating function
summed by binary splitting (O(M(n) \log n) operations, any m).
Example#
The program prints the first Bell numbers, the size of B_{1000}, and checks arith_bell_number_nmod against the residue of the exact value for the prime m = 10^9 + 7 (where the series method applies) and for the modulus m = 2^{10} = 1024 (where it does not).
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_vec.h>
#include <flint/nmod.h>
#include <flint/arith.h>
int main(void)
{
fmpz * b;
fmpz_t B;
nmod_t mod;
slong i;
b = _fmpz_vec_init(10);
arith_bell_number_vec(b, 10);
flint_printf("B_0..B_9:");
for (i = 0; i < 10; i++)
{
flint_printf(" ");
fmpz_print(b + i);
}
flint_printf("\n");
fmpz_init(B);
arith_bell_number(B, 1000);
flint_printf("B_1000 has %wu bits\n", fmpz_bits(B));
nmod_init(&mod, 1000000007);
flint_printf("mod 10^9+7: %wu %wu\n",
arith_bell_number_nmod(1000, mod), fmpz_fdiv_ui(B, mod.n));
nmod_init(&mod, 1024);
flint_printf("mod 1024: %wu %wu\n",
arith_bell_number_nmod(1000, mod), fmpz_fdiv_ui(B, mod.n));
fmpz_clear(B);
_fmpz_vec_clear(b, 10);
return 0;
}B_0..B_9: 1 1 2 5 15 52 203 877 4140 21147 B_1000 has 6403 bits mod 10^9+7: 465231251 465231251 mod 1024: 443 443
References#
- [Dob1877] G. Dobiński, "Summirung der Reihe \sum n^m/n! für m = 1, 2, 3, 4, 5, \ldots", Archiv der Mathematik und Physik 61 (1877), 333–336.
- [deB1958] N. G. de Bruijn, Asymptotic Methods in Analysis, North-Holland, 1958 (§6.2: Bell numbers).
- [BerTas2010] D. Berend and T. Tassa : Improved bounds on Bell numbers and on moments of sums of random variables, Probability and Mathematical Statistics vol. 30 (2010) 185–205
- [Comtet1974] L. Comtet, Advanced Combinatorics: The Art of Finite and Infinite Expansions, D. Reidel, 1974.
The FLINT team, “Bell numbers (arith.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/arith/bell.html (generated 2026-10-20).
@misc{flint-doc-arith-bell,
author = {{The FLINT team}},
title = {{Bell numbers (arith.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/arith/bell.html},
note = {Generated 2026-10-20}
}