Computing the partition function
- Cost
- O(n^{1/2} \log^{4+o(1)} n) bit operations for p(n), quasi-optimal since p(n) has \Theta(n^{1/2}) bits; O(n^{3/2 + o(1)}) for all of p(0), \ldots, p(n).
The partition function p(n) counts the partitions of n, the ways of writing n as a sum of positive integers without regard to order. Its generating function is Euler's product
The values grow subexponentially: \log p(n) \sim \pi \sqrt{2n/3}, so p(n) has about 3.7 \sqrt{n} bits. FLINT's methods follow [Joh2012]; for the theory see [Andrews1976, Chapter 5] and [Apostol1997, Chapter 5].
All values up to n#
By Euler's pentagonal number theorem,
a series with O(\sqrt n) nonzero terms below x^n. Inverting it gives the recurrence
which computes p(0), \ldots, p(n) with O(n^{3/2}) additions of numbers of O(\sqrt n) bits. FLINT instead inverts the pentagonal series with fast power series inversion (arith_number_of_partitions_vec, and modulo a word-size integer arith_number_of_partitions_nmod_vec), which costs O(M(n)) operations on coefficients of O(\sqrt n) bits. The recurrence is used for single values up to n = 416, in single words: since it involves only additions and subtractions, it is exact modulo 2^{64}, hence exact while p(n) < 2^{64}.
The Hardy–Ramanujan–Rademacher formula#
Hardy and Ramanujan [HardyRamanujan1918] found an asymptotic series for p(n), and Rademacher [Rademacher1937] modified it into a convergent series. In the form used by FLINT, with
it reads
where A_k(n) is the exponential sum
s(h, k) is a Dedekind sum (see fmpq_dedekind_sum), and the remainder satisfies [Rademacher1937]
The k-th term is of the order of e^{C/k}, so the first term gives almost all the bits of p(n) and the terms decrease rapidly. |A_k(n)| \le k, and the bound M(n, N) falls below 1/2 for N of the order of \sqrt n: for n = 10^9, M(n, 10^4) \approx 0.32. Since p(n) is an integer, an approximation with total error below 1/2 determines it.
Factoring the exponential sums#
Evaluating A_k(n) from its definition costs O(k) Dedekind sums, O(k^2) operations for each k and O(n^{3/2}) in total, which would dominate. Lehmer and Whiteman [Whiteman1956] showed that A_k(n) is multiplicative in a twisted sense and that its prime power factors are single cosines. FLINT uses the following form.
Proposition 1. If k = k_1 k_2 with \gcd(k_1, k_2) = 1, then A_k(n) = A_{k_1}(n_1) A_{k_2}(n_2) for explicit n_1, n_2 determined by congruences modulo k_1 and k_2. For a prime p > 3 and k = p^\lambda, let r = 1 - 24n \bmod k. Then
- if r is not a square modulo p, A_k(n) = 0;
- if p \mid r, A_k(n) = (3/p) \sqrt p for \lambda = 1 and A_k(n) = 0 for \lambda > 1;
otherwise, with m such that (24m)^2 \equiv r \pmod k,
A_k(n) = 2 \left(\frac{3}{k}\right) \sqrt k \cos\left( \frac{4\pi m}{k} \right).
Similar formulas, involving square roots modulo 8k and 3k, hold for powers of 2 and 3.
So after factoring k, A_k(n) is a product of \omega(k) cosines of rational multiples of \pi, an algebraic prefactor \pm 2^a \sqrt{u/v}, and a sign, computed with O(\log k) modular square roots and inverses (arith_hrr_expsum_factored, which returns the symbolic product as a trig_prod_t). The cost of A_k(n) becomes polylogarithmic in k, and many A_k(n) vanish.
Precision and error control#
Each term is evaluated at a precision tied to its magnitude: the term k has absolute value at most \sqrt{12k}\, e^{C/k}/(24n - 1), and it must be known to an absolute error of about 2^{-g}/N with a few guard bits g, so the working precision is
where the last term accounts for the number of operations, which depends on the number of prime factors of k. The precision thus decreases like 1/k: the first term needs the full 3.7 \sqrt n bits, the term k about 1/k of that, and most of the N = O(\sqrt n) terms need only a few dozen bits. The cost of all terms is dominated by the first few, and Johansson [Joh2012] shows a total cost of O(n^{1/2} \log^{4 + o(1)} n) for the evaluation with N = O(\sqrt n) terms, within polylogarithmic factors of the size of the output.
All operations are done in ball arithmetic, so the computed sum S comes with a radius \rho that bounds every rounding error. Adding M(n, N) to the radius gives a ball [S \pm (\rho + M(n,N))] that is guaranteed to contain p(n); if it contains exactly one integer, that integer is p(n). This makes the result a proof; the implementation of [Joh2012] used MPFR with error estimates that were not fully rigorous.
The angles of the cosines are reduced to [0, \pi/4] (using sines near \pi/2), so that every factor is known with full relative precision, and \exp(C/k) is computed from \exp(C) by a k-th root when that is cheaper than a new exponential.
Use in FLINT#
partitions_fmpz_uiandpartitions_fmpz_fmpzuse the tablepartitions_lookupfor n < 128, the pentagonal recurrence in words for n < 417, andmp_real_partitions_hrrabove.mp_real_partitions_hrrchooses the number of terms with M(n, N) < 0.4 (by bisection on a cheap estimate, then exactly), factors each A_k(n) witharith_hrr_expsum_factored, and sorts the terms by the precision they need: terms of up to about 200 bits are evaluated in batches asdfloatballs of one to four doubles with the vectorisedgr_vecfunctions, and the others asmp_realballs of the needed number of limbs. Above n = 10^8, the constants \pi, C and e^C are computed with all threads, and the terms are distributed over the threads offlint_set_num_threadsin ranges of equal estimated cost. The remainder bound comes frompartitions_rademacher_bound, and the result frommp_real_unique_integer.arith_number_of_partitionsis a wrapper ofpartitions_fmpz_ui;arith_number_of_partitions_vecandarith_number_of_partitions_nmod_vecinvert the pentagonal series.partitions_leading_fmpzevaluates the dominant part of the first term, andarb_partitions_fmpzapproximations of p(n) to a given precision.
The generic functions gr_partitions_ui, gr_partitions_fmpz and gr_partitions_vec call partitions_fmpz_ui, partitions_fmpz_fmpz and the vector functions over \mathbb{Z} and \mathbb{Z}/n\mathbb{Z}, and arb_partitions_fmpz in real and complex rings.
void partitions_fmpz_fmpz(fmpz_t p, const fmpz_t n, int use_doubles)void partitions_rademacher_bound(arf_t b, const fmpz_t n, ulong N)void arith_hrr_expsum_factored(trig_prod_t prod, ulong k, ulong n)void arith_number_of_partitions_vec(fmpz * res, slong len)Referenced from#
References#
- [Joh2012] F. Johansson, "Efficient implementation of the Hardy-Ramanujan-Rademacher formula", LMS Journal of Computation and Mathematics, Volume 15 (2012), 341-359, http://journals.cambridge.org/action/displayAbstract?fromPage=online&aid=8710297
- [Andrews1976] G. E. Andrews, The Theory of Partitions, Encyclopedia of Mathematics and its Applications 2, Addison-Wesley, 1976.
- [Apostol1997] Apostol, Tom : Modular functions and Dirichlet series in number theory, Springer (1997)
- [HardyRamanujan1918] G. H. Hardy and S. Ramanujan, "Asymptotic formulae in combinatory analysis", Proceedings of the London Mathematical Society (2) 17 (1918), 75–115.
- [Rademacher1937] Rademacher, Hans : On the partition function p(n) Proc. London Math. Soc vol. 43 (1937) 241–254
- [Whiteman1956] Whiteman, A. L. : A sum connected with the series for the partition function, Pacific Journal of Mathematics 6:1 (1956) 159–176
The FLINT team, “Computing the partition function,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/number-theory/partitions.html (generated 2026-10-20).
@misc{flint-doc-algorithms-number-theory-partitions,
author = {{The FLINT team}},
title = {{Computing the partition function}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/number-theory/partitions.html},
note = {Generated 2026-10-20}
}