Multiplication with a precomputed inverse
#include <flint/ulong_extras.h>Returns . No restrictions on , or .
Returns , computing the inverse of on the fly. Use n_mulmod2_preinv when is reused.
These functions compute for a word-size modulus . They form the inner loop of most modular arithmetic in FLINT; the nmod module wraps them together with the modulus and its inverse in an nmod_t.
Choosing a function#
n_mulmod2_preinvis the general-purpose function. Computeninv = n_preinvert_limb(n)once per modulus.n_mulmod2computesninvitself and is only worth using for a single multiplication.n_mulmod_preinvsaves a few operations by requiring the modulus to be normalised (top bit set) and the operands reduced. To use it with any , work with and operands shifted left by bits, where is the number of leading zero bits of , and pass asnorm. Results then also come out shifted by bits.
n_mulmod_precomp uses a double inverse instead and requires . When one operand is fixed, n_mulmod_shoup is faster still; see Choosing a method for modular arithmetic for all options.
Algorithm#
The product is computed as a two-word integer and reduced with one step of Möller–Granlund division: one full and one low multiplication by the precomputed inverse, followed by at most two corrections. n_mulmod_preinv performs exactly this step, since its operands are already shifted. n_mulmod2_preinv passes the product to n_ll_mod_preinv, which shifts it to normalise the modulus; if the operands are not reduced, the high word of the product may be at least , and a second division step reduces it first.
Examples#
The most basic use:
#include <flint/flint.h>
#include <flint/ulong_extras.h>
int main(void)
{
ulong a = 12345678, b = 87654321, n = 111111111;
ulong ninv = n_preinvert_limb(n);
flint_printf("%wu * %wu mod %wu = %wu\n", a, b, n,
n_mulmod2_preinv(a, b, n, ninv));
return 0;
}12345678 * 87654321 mod 111111111 = 23456790
The inverse pays off when the modulus is reused. This computes modulo a prime with 999 multiplications and checks the result against n_factorial_mod2_preinv:
#include <flint/flint.h>
#include <flint/ulong_extras.h>
int main(void)
{
ulong p = 4294967291; /* the largest prime below 2^32 */
ulong pinv = n_preinvert_limb(p); /* computed once, used 999 times */
ulong f = 1, k;
for (k = 2; k <= 1000; k++)
f = n_mulmod2_preinv(f, k, p, pinv);
flint_printf("1000! mod p = %wu\n", f);
flint_printf("check = %wu\n", n_factorial_mod2_preinv(1000, p, pinv));
return 0;
}1000! mod p = 444887038 check = 444887038
Guides#
- Two-word arithmetic with longlong.h (
longlong) - Portable vec4d code (
machine_vectors)
The FLINT team, “Multiplication with a precomputed inverse (ulong_extras.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/ulong_extras/mulmod.html (generated 2026-11-02).
@misc{flint-doc-ulong-extras-mulmod,
author = {{The FLINT team}},
title = {{Multiplication with a precomputed inverse (ulong\_extras.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/ulong_extras/mulmod.html},
note = {Generated 2026-11-02}
}