Multimodular reduction and Chinese remaindering
- Cost
- for -bit products, for the precomputation and for each conversion.
A multimodular algorithm computes a result (an integer, or the entries of a matrix or the coefficients of a polynomial) by reducing its inputs modulo many word-size primes , solving the problem modulo each prime, and recovering from its residues by the Chinese remainder theorem, which determines modulo . The two conversions, multi-mod (from to its residues) and multi-CRT (back), each cost limb operations if done naively; the subproduct tree makes them quasi-linear [BorMoe1974; Ber2008].
The generic and fixed-size Chinese remaindering used inside the small-prime FFT is described with crt_helpers; multimodular algorithms for matrices and polynomials are discussed in Multimodular and p-adic linear algebra over the integers and Multiplication with several primes and CRT.
The subproduct tree#
Group the moduli into the leaves of a balanced binary tree, and label each node with the product of the moduli below it, so that the root carries . With the bit size of , each level of the tree has total size about bits, there are levels, and the tree is computed bottom-up in time .
Input: and the subproduct tree.
Output: for all .
- At the root, .
- Going down, for a node with residue and children with products and , set and .
- At the leaves, return the residues.
Since , , so the algorithm is correct; each level costs divisions of total size , so the whole costs with fast division.
Chinese remaindering with fractional cofactors#
The classical solution with needs the cofactors , of bits each. The tree form combines the children and of a node with by , which never forms anything larger than . For this to work the values must carry the right scaling.
Lemma 1. Let be an integer, and for a node let (invertible modulo if the moduli are pairwise coprime). If and , then satisfies . At the root, and .
Proof. Modulo , . Now , so and . The same holds modulo , and since and are coprime, modulo their product .
The values themselves are computed from the root down by a remainder tree: , which follows from and . At the bottom of the tree only the inverses modulo the leaves are needed, and a leaf product fits in a word, so no multiprecision inverse is ever computed. The precomputation therefore costs : a product tree and a remainder tree.
Input: residues , the subproduct tree and the leaf cofactor data.
Output: .
- At each leaf group (a chunk of consecutive moduli with product ), form with precomputed . Then and for moduli in the chunk.
- Combine upwards with Lemma 1, without reducing: .
- Reduce the root value modulo ; for a signed result, subtract if the value exceeds .
Proposition 2. In Algorithm 2, every value at a node with product satisfies , where is the number of moduli below the node. In particular the root value is less than , and the final reduction is a division with a quotient of at most bits.
Proof. By induction: at a chunk, each term of is less than . If and , then .
So the values grow by about one bit per level, and the combination is a pair of unbalanced products and one addition per node, again in total.
Refinements in FLINT#
- Batched leaves. Moduli of at most 32 bits are multiplied in pairs, and 20-bit moduli in triples, so that the tree works with full-word leaves; single-word code splits and combines the individual moduli at the bottom.
- Basecases. Below a chunk of about 2048 bits the CRT is the linear sum of step 1 (by
mpn_addmul_1), and below a node of about 2048 bits the reduction computes for all leaves at once as a dot product of the limbs of with precomputed powers , with a two-limb accumulator and a single reduction per leaf. - Fixed-length code. When is a single small chunk, the CRT uses the straight-line kernels of
crt_helpers.h. - Small values. Results are often much smaller than (for example the small entries of a matrix whose bound is dominated by a few large ones). The reconstruction first reconstructs modulo the product of the first few moduli. If the result has at least a limb of slack below and for all the other moduli, then and , so and the tree is not traversed. A random residue passes the slack test with probability about , so this costs almost nothing when it fails.
- Division. Reductions down the tree use precomputed inverses of the node products (
flint_mpn_mod_preinvn) above 16 limbs. - Vectors. For many values, the tables are traversed once per block of values (
flint_mpn_multi_mod_vec,flint_mpn_multi_crt_vec). - Memory. The structure stores bits. The one-shot reconstruction
flint_mpn_multi_crt_onceinstead traverses the tree depth first, recomputing subproducts as needed, with memory, which makes reconstructions of billions of bits possible. Large nodes are processed in parallel.
Use in FLINT#
The functions are flint_mpn_crt_init, flint_mpn_multi_mod, flint_mpn_multi_crt and their variants in mpn_extras (Multimodular reduction and Chinese remaindering). They are used through fmpz_comb_t (fmpz_multi_mod_ui, fmpz_multi_CRT_ui) by the multimodular algorithms for fmpz_mat and mpn_mod matrices (multiplication), fmpz_poly and fmpq_poly (GCDs, interpolation, Taylor shifts), resultants of bivariate polynomials, and by the multimodular computation of Bernoulli, Euler and Bell numbers and Stirling numbers in arith.
void flint_mpn_crt_init(flint_mpn_crt_t C, nn_srcptr primes, slong num_primes)void flint_mpn_multi_mod(nn_ptr out, nn_srcptr x, slong xn, const flint_mpn_crt_t C, nn_ptr tmp)int flint_mpn_multi_crt(nn_ptr out, nn_srcptr res, const flint_mpn_crt_t C, int sign, nn_ptr tmp)Referenced from#
References#
- [BorMoe1974] A. Borodin and R. Moenck, "Fast modular transforms", Journal of Computer and System Sciences 8:3 (1974), 366–386
- [Ber2008] D. J. Bernstein, "Fast multiplication and its applications", in Algorithmic Number Theory, MSRI Publications 44 (2008), 325–384
The FLINT team, “Multimodular reduction and Chinese remaindering,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/integers/multimodular-reduction.html (generated 2026-11-02).
@misc{flint-doc-algorithms-integers-multimodular-reduction,
author = {{The FLINT team}},
title = {{Multimodular reduction and Chinese remaindering}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/integers/multimodular-reduction.html},
note = {Generated 2026-11-02}
}