FLINT3.7.0-dev
Algorithm

Barrett and Lemire reduction

Cost
Barrett: one high and one low product and one conditional subtraction. Lemire: one low and one high product, no correction.

The methods of Barrett and of Lemire, Kaser and Kurz reduce a single word xx modulo nn, rather than a two-word product, using a precomputed approximation of B/nB/n. They are cheaper than a two-word Möller–Granlund reduction when the value to be reduced is known to fit in one word, as in hashing, sieving and table lookups. Throughout, B=2FLINT_BITSB = 2^{\mathtt{FLINT\_BITS}}.

Barrett reduction#

Barrett's method [Bar1987] estimates the quotient as follows.

Proposition 1. Let 2≤n<B2 \le n < B, m=⌊B/n⌋m = \lfloor B/n \rfloor and 0≤x<B0 \le x < B, and let q~=⌊xm/B⌋\tilde q = \lfloor x m / B \rfloor. Then ⌊x/n⌋−1≤q~≤⌊x/n⌋\lfloor x/n \rfloor - 1 \le \tilde q \le \lfloor x/n \rfloor, so 0≤x−q~n<2n0 \le x - \tilde q n < 2n.

Proof. From B/n−1<m≤B/nB/n - 1 < m \le B/n we get

xn−1<xn−xB<xmB≤xn,\frac{x}{n} - 1 < \frac{x}{n} - \frac{x}{B} < \frac{x m}{B} \le \frac{x}{n},

using x<Bx < B. Taking floors gives the claim.

The value x−q~nx - \tilde q n is at most xx, so it is computed exactly with word arithmetic even when 2n>B2n > B. n_mod_barrett_lazy returns it, and n_mod_barrett subtracts nn once if needed. n_barrett_precomp computes mm with one division.

Barrett reduction with an nmod_t#

NMOD_RED reduces a word with the same kind of quotient estimate, but its constant comes from the nmod_t, so it needs no division and no extra field. Let ν\nu be the number of bits of nn, that is 2ν−1≤n<2ν2^{\nu - 1} \le n < 2^{\nu} and norm=FLINT_BITS−ν\mathit{norm} = \mathtt{FLINT\_BITS} - \nu. The ninv field is the Möller–Granlund reciprocal of n2normn 2^{\mathit{norm}}.

Lemma 2. Let m=2FLINT_BITS−1+⌊ninv/2⌋m = 2^{\mathtt{FLINT\_BITS} - 1} + \lfloor \mathit{ninv}/2 \rfloor. Then m=⌊(2ν+FLINT_BITS−1−1)/n⌋m = \lfloor (2^{\nu + \mathtt{FLINT\_BITS} - 1} - 1)/n \rfloor, and 2FLINT_BITS−1≤m<B2^{\mathtt{FLINT\_BITS} - 1} \le m < B.

Proof. By definition B+ninv=⌊(B2−1)/(n2norm)⌋=⌊(2ν+FLINT_BITS−1)/n⌋B + \mathit{ninv} = \lfloor (B^2 - 1)/(n 2^{\mathit{norm}}) \rfloor = \lfloor (2^{\nu + \mathtt{FLINT\_BITS}} - 1)/n \rfloor, using ⌊⌊x⌋/k⌋=⌊x/k⌋\lfloor \lfloor x \rfloor / k \rfloor = \lfloor x/k \rfloor for integers k≥1k \ge 1 and ⌊(B2−1)/2norm⌋=2ν+FLINT_BITS−1\lfloor (B^2 - 1)/2^{\mathit{norm}} \rfloor = 2^{\nu + \mathtt{FLINT\_BITS}} - 1. Hence m=⌊(B+ninv)/2⌋=⌊(2ν+FLINT_BITS−1)/(2n)⌋m = \lfloor (B + \mathit{ninv})/2 \rfloor = \lfloor (2^{\nu + \mathtt{FLINT\_BITS}} - 1)/(2n) \rfloor. With y=2ν+FLINT_BITS−1y = 2^{\nu + \mathtt{FLINT\_BITS} - 1}, an integer kk satisfies 2nk≤2y−12nk \le 2y - 1 if and only if 2nk≤2y−22nk \le 2y - 2, since 2nk2nk is even; so this is ⌊(y−1)/n⌋\lfloor (y - 1)/n \rfloor. The bounds follow from ninv<B\mathit{ninv} < B.

Theorem 3. Let 1≤n<B1 \le n < B, 0≤a<B0 \le a < B, mm as in Lemma 2, and q~=⌊am/2ν+FLINT_BITS−1⌋\tilde q = \lfloor a m / 2^{\nu + \mathtt{FLINT\_BITS} - 1} \rfloor. Then ⌊a/n⌋−1≤q~≤⌊a/n⌋\lfloor a/n \rfloor - 1 \le \tilde q \le \lfloor a/n \rfloor, so 0≤a−q~n<2n0 \le a - \tilde q n < 2n.

Proof. Write mn=2ν+FLINT_BITS−1−1−ρmn = 2^{\nu + \mathtt{FLINT\_BITS} - 1} - 1 - \rho with 0≤ρ<n0 \le \rho < n (Lemma 2). Then

am2ν+FLINT_BITS−1=an−a(1+ρ)n 2ν+FLINT_BITS−1,\frac{a m}{2^{\nu + \mathtt{FLINT\_BITS} - 1}} = \frac{a}{n} - \frac{a (1 + \rho)}{n\, 2^{\nu + \mathtt{FLINT\_BITS} - 1}},

and the subtracted term is in [0,1)[0, 1) because a<Ba < B, 1+ρ≤n1 + \rho \le n and ν≥1\nu \ge 1. Taking floors gives the claim.

So NMOD_RED computes q~\tilde q as the high word of ama m shifted right by FLINT_BITS−1−norm\mathtt{FLINT\_BITS} - 1 - \mathit{norm} bits, subtracts q~n\tilde q n (at most aa, so there is no overflow) and corrects once. This holds for every modulus 1≤n<B1 \le n < B, including powers of two and n≥2FLINT_BITS−1n \ge 2^{\mathtt{FLINT\_BITS} - 1}, and every word aa. The cost is one high product, one low product and one comparison, against a full product, a low product and two corrections for a Möller–Granlund step on the two-word number (0,a)(0, a).

When nn has FLINT_BITS bits (mod.norm =0= 0), a<2na < 2n for every word aa, so NMOD_RED skips the product and only corrects once. The test on mod.norm is moved out of loops by the compiler, and the remaining loop of comparisons can then be trivially vectorized.

Shifting mm gives the constants of the same family for other input sizes: ⌊m/2k⌋=⌊(2ν+FLINT_BITS−1−k−1)/n⌋\lfloor m / 2^k \rfloor = \lfloor (2^{\nu + \mathtt{FLINT\_BITS} - 1 - k} - 1)/n \rfloor for 0≤k<ν+FLINT_BITS−10 \le k < \nu + \mathtt{FLINT\_BITS} - 1. For instance k=ν−1k = \nu - 1 gives ⌊(B−1)/n⌋\lfloor (B - 1)/n \rfloor, which is the constant of n_barrett_precomp unless nn is a power of two.

Lemire–Kaser–Kurz reduction#

The method of Lemire, Kaser and Kurz [LKK2019] computes the remainder directly from the fractional part of x/nx/n. With c=⌈B/n⌉c = \lceil B/n \rceil, the low word xc mod Bxc \bmod B approximates B{x/n}B \{x/n\}, where {⋅}\{\cdot\} denotes the fractional part; multiplying it by nn and keeping the high word gives x mod nx \bmod n. The approximation is exact when nn and xx are below 2FLINT_BITS/22^{\mathtt{FLINT\_BITS}/2}, which is the condition required by n_mod_lemire. The method needs no correction step, but its range restriction makes it useful only for half-word values.

Referenced from#

References#

  • [Bar1987] P. Barrett, "Implementing the Rivest Shamir and Adleman public key encryption algorithm on a standard digital signal processor", Advances in Cryptology – CRYPTO '86, LNCS 263 (1987), 311–323
  • [LKK2019] D. Lemire, O. Kaser and N. Kurz, "Faster remainder by direct computation: applications to compilers and software libraries", Software: Practice and Experience 49 (2019), 953–970, https://arxiv.org/abs/1902.01961
Cite this page

The FLINT team, “Barrett and Lemire reduction,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/arithmetic/barrett.html (generated 2026-11-02).