FLINT3.7.0-dev
Algorithm

Multimodular reduction and Chinese remaindering

Cost
O(M(N)log⁡N)O(M(N) \log N) for NN-bit products, for the precomputation and for each conversion.

A multimodular algorithm computes a result xx (an integer, or the entries of a matrix or the coefficients of a polynomial) by reducing its inputs modulo many word-size primes m1,…,mkm_1, \ldots, m_k, solving the problem modulo each prime, and recovering xx from its residues by the Chinese remainder theorem, which determines xx modulo P=m1⋯mkP = m_1 \cdots m_k. The two conversions, multi-mod (from xx to its residues) and multi-CRT (back), each cost O(k2)O(k^2) 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 vv of the moduli below it, so that the root carries PP. With NN the bit size of PP, each level of the tree has total size about NN bits, there are O(log⁡k)O(\log k) levels, and the tree is computed bottom-up in time O(M(N)log⁡k)O(M(N) \log k).

Algorithm 1: Remainder tree (multi-mod)

Input: x≥0x \ge 0 and the subproduct tree.

Output: x mod mix \bmod m_i for all ii.

  1. At the root, r←x mod Pr \gets x \bmod P.
  2. Going down, for a node with residue rr and children with products vbv_b and vcv_c, set rb←r mod vbr_b \gets r \bmod v_b and rc←r mod vcr_c \gets r \bmod v_c.
  3. At the leaves, return the residues.

Since vb∣vv_b \mid v, (x mod v) mod vb=x mod vb(x \bmod v) \bmod v_b = x \bmod v_b, so the algorithm is correct; each level costs divisions of total size O(N)O(N), so the whole costs O(M(N)log⁡k)O(M(N) \log k) with fast division.

Chinese remaindering with fractional cofactors#

The classical solution x≡∑iri ci (P/mi)(modP)x \equiv \sum_i r_i \, c_i \, (P/m_i) \pmod P with ci=(P/mi)−1 mod mic_i = (P/m_i)^{-1} \bmod m_i needs the cofactors P/miP/m_i, of NN bits each. The tree form combines the children bb and cc of a node aa with va=vbvcv_a = v_b v_c by A=Abvc+AcvbA = A_b v_c + A_c v_b, which never forms anything larger than vav_a. For this to work the values must carry the right scaling.

Lemma 1. Let xx be an integer, and for a node aa let Ra=(P/va) mod vaR_a = (P/v_a) \bmod v_a (invertible modulo vav_a if the moduli are pairwise coprime). If Ab≡Rb−1x(modvb)A_b \equiv R_b^{-1} x \pmod{v_b} and Ac≡Rc−1x(modvc)A_c \equiv R_c^{-1} x \pmod{v_c}, then A=Abvc+AcvbA = A_b v_c + A_c v_b satisfies A≡Ra−1x(modva)A \equiv R_a^{-1} x \pmod{v_a}. At the root, R=1R = 1 and A≡x(modP)A \equiv x \pmod P.

Proof. Modulo vbv_b, A≡Abvc≡Rb−1vc xA \equiv A_b v_c \equiv R_b^{-1} v_c\, x. Now P/vb=(P/va)vcP/v_b = (P/v_a) v_c, so Rb≡Ravc(modvb)R_b \equiv R_a v_c \pmod{v_b} and Rb−1vc≡Ra−1(modvb)R_b^{-1} v_c \equiv R_a^{-1} \pmod{v_b}. The same holds modulo vcv_c, and since vbv_b and vcv_c are coprime, A≡Ra−1xA \equiv R_a^{-1} x modulo their product vav_a.

The values RR themselves are computed from the root down by a remainder tree: Rb=((Ra mod vb) vc) mod vbR_b = \bigl((R_a \bmod v_b) \, v_c\bigr) \bmod v_b, which follows from Rb≡Ravc(modvb)R_b \equiv R_a v_c \pmod{v_b} and vb∣vav_b \mid v_a. At the bottom of the tree only the inverses R−1R^{-1} modulo the leaves are needed, and a leaf product fits in a word, so no multiprecision inverse is ever computed. The precomputation therefore costs O(M(N)log⁡k)O(M(N) \log k): a product tree and a remainder tree.

Algorithm 2: Multi-CRT

Input: residues xi=x mod mix_i = x \bmod m_i, the subproduct tree and the leaf cofactor data.

Output: x mod Px \bmod P.

  1. At each leaf group (a chunk of consecutive moduli with product MM), form y=∑j(xjcj mod mj)(M/mj)y = \sum_j \bigl(x_j c_j \bmod m_j\bigr) (M/m_j) with precomputed cj=(M/mj)−1R−1 mod mjc_j = (M/m_j)^{-1} R^{-1} \bmod m_j. Then y≡R−1x(modM)y \equiv R^{-1} x \pmod M and y<kMMy < k_M M for kMk_M moduli in the chunk.
  2. Combine upwards with Lemma 1, without reducing: A=Abvc+AcvbA = A_b v_c + A_c v_b.
  3. Reduce the root value modulo PP; for a signed result, subtract PP if the value exceeds P/2P/2.

Proposition 2. In Algorithm 2, every value AA at a node with product vv satisfies A<ℓ vA < \ell\, v, where ℓ\ell is the number of moduli below the node. In particular the root value is less than kPkP, and the final reduction is a division with a quotient of at most log⁡2k\log_2 k bits.

Proof. By induction: at a chunk, each term of yy is less than mj(M/mj)=Mm_j (M/m_j) = M. If Ab<ℓbvbA_b < \ell_b v_b and Ac<ℓcvcA_c < \ell_c v_c, then Abvc+Acvb<(ℓb+ℓc)vbvcA_b v_c + A_c v_b < (\ell_b + \ell_c) v_b v_c.

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 O(M(N)log⁡k)O(M(N) \log k) 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 x mod mjx \bmod m_j for all leaves at once as a dot product of the limbs of xx with precomputed powers Bi mod mjB^i \bmod m_j, with a two-limb accumulator and a single reduction per leaf.
  • Fixed-length code. When PP is a single small chunk, the CRT uses the straight-line kernels of crt_helpers.h.
  • Small values. Results are often much smaller than PP (for example the small entries of a matrix whose bound is dominated by a few large ones). The reconstruction first reconstructs xx modulo the product QQ of the first few moduli. If the result x′x' has at least a limb of slack below QQ and x′ mod mi=xix' \bmod m_i = x_i for all the other moduli, then x′≡x(modP)x' \equiv x \pmod P and 0≤x′<Q≤P0 \le x' < Q \le P, so x′=xx' = x and the tree is not traversed. A random residue passes the slack test with probability about 2−642^{-64}, 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 O(Nlog⁡k)O(N \log k) bits. The one-shot reconstruction flint_mpn_multi_crt_once instead traverses the tree depth first, recomputing subproducts as needed, with O(N)O(N) 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.

int flint_mpn_multi_crt(nn_ptr out, nn_srcptr res, const flint_mpn_crt_t C, int sign, nn_ptr tmp)
int flint_mpn_multi_crt_once(nn_ptr out, slong * outn, nn_ptr prod, nn_srcptr res, nn_srcptr primes, slong num_primes, int sign)

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
Cite this page

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).