nmod.h
#include <flint/nmod.h>This module implements arithmetic in \mathbb{Z}/n\mathbb{Z} for a word-size modulus n \ge 1. Elements are plain ulong values in [0, n), and the modulus is passed as an nmod_t holding n together with a precomputed inverse. Most functions are inline wrappers around the _preinv functions of ulong_extras. They are the scalar building blocks of nmod_vec, nmod_poly, nmod_mat and the other modules over \mathbb{Z}/n\mathbb{Z}. The module also provides square roots modulo primes, discrete logarithms, Montgomery arithmetic, and the generic ring (gr) contexts for \mathbb{Z}/n\mathbb{Z}.
The guides below explain how to use the module; start with Basic arithmetic modulo n. The conventions common to all FLINT modules, including the naming of functions and the use of nmod_t as a context, are described in Types, naming and aliasing.
Guides#
nmod_t, which operations need reduced operands, how products are reduced, and how to divide when the divisor may not be invertible.GuideComputing discrete logarithmsHow to set up the Pohlig–Hellman precomputation for a prime, which primes it suits, how to take logarithms to another base, and examples.GuideUsing Montgomery arithmeticWhen Montgomery form pays off, how to convert values in and out, the rules for lazy residues and half-word arithmetic, and how the reduction works.Conventions#
Throughout, B = 2^{\mathtt{FLINT\_BITS}}.
A modulus n with precomputed data, set up by nmod_init. The fields are n (the modulus), norm (the number of leading zero bits of n) and ninv (the value n_preinvert_limb(n) used for Möller–Granlund division). An nmod_t is a small struct and is passed by value.
- Reduced means 0 \le a < n. Unless stated otherwise, operands must be reduced and results are reduced. Functions named
nmod_set_*andnmod_ui_*accept any input. - None of these assumptions is checked, except by
FLINT_ASSERTin builds configured with--enable-assert. - A leading underscore marks a function with an extra restriction on the modulus or the input (for example
_nmod_add), or an internal helper.
Initialisation and conversion#
Sets mod to the modulus n, computing norm and ninv. Requires n \ne 0.
NMOD_BITS(mod)The number of bits of mod.n, that is, FLINT_BITS - mod.norm.
ulong nmod_set_ui(ulong x, nmod_t mod)ulong nmod_set_si(slong x, nmod_t mod)Return x \bmod n in [0, n), for any x.
Arithmetic#
Addition, multiplication, inversion and division of residues. The guide Basic arithmetic modulo n explains which of them need reduced operands and what to do when the divisor is not invertible.
Return a + b, a - b and -a modulo n, for reduced operands and any n.
ulong nmod_ui_add_ui(ulong a, ulong b, nmod_t mod)Returns (a + b) \bmod n for any a and b.
ulong _nmod_mul_fullword(ulong a, ulong b, nmod_t mod)Returns ab \bmod n for reduced operands. Requires mod.norm = 0, that is, n \ge 2^{\mathtt{FLINT\_BITS} - 1}. It saves the normalisation shift of nmod_mul.
ulong nmod_ui_mul_ui(ulong a, ulong b, nmod_t mod)Returns ab \bmod n for any a and b.
Return s + ab and ab + cd modulo n, for reduced operands. nmod_addmul forms s + ab as a two-word integer and reduces it once.
NMOD_ADDMUL(r, a, b, mod)Sets r to (r + ab) \bmod n, for reduced r, a and b. This is r = nmod_addmul(r, a, b, mod).
Returns a^{-1} \bmod n for reduced a. Throws an exception if \gcd(a, n) \ne 1.
Returns a b^{-1} \bmod n for reduced a and b. Throws an exception if \gcd(b, n) \ne 1.
int nmod_divides(ulong * a, ulong b, ulong c, nmod_t mod)Powering#
ulong nmod_pow_ui(ulong a, ulong exp, nmod_t mod)ulong nmod_pow_fmpz(ulong a, const fmpz_t exp, nmod_t mod)Return a^{\mathit{exp}} \bmod n for reduced a, with a^0 = 1 (which is 0 when n = 1). For a negative exponent, nmod_pow_fmpz returns (a^{-1})^{-\mathit{exp}} and throws FLINT_IMPINV if a is not invertible modulo n.
ulong nmod_ui_pow_ui(ulong a, ulong exp, nmod_t mod)Returns a^{\mathit{exp}} \bmod n for any a.
ulong nmod_2_pow_ui(ulong exp, nmod_t mod)Returns 2^{\mathit{exp}} \bmod n.
Moreulong _nmod_pow_ui_binexp(ulong a, ulong exp, nmod_t mod)ulong _nmod_pow_ui_redc(ulong a, ulong exp, nmod_t mod)ulong _nmod_2_pow_ui_binexp(ulong exp, nmod_t mod)The algorithms behind nmod_pow_ui and nmod_2_pow_ui, with the same results. The first two require \mathit{exp} \ge 1 (they do not terminate for \mathit{exp} = 0), and _nmod_pow_ui_redc requires odd n. _nmod_2_pow_ui_binexp accepts any n and any exponent.
Square roots#
For prime n and reduced a: if a is a square modulo n, sets *res to the square root in [0, n/2] and returns 1; otherwise sets *res to 0 and returns 0. Primality is not checked. For composite n, a return value of 1 still gives a genuine square root, but 0 does not prove that none exists.
int _nmod_sqrt_small(ulong * res, ulong a, ulong n)For odd n and a < n, finds the least square root of a modulo n by exhaustive search in O(n) steps. Returns 1 and sets *res to the root, or returns 0 and sets *res to 0 if there is none. The answer is correct for composite n too.
The bound 128 below which nmod_sqrt uses _nmod_sqrt_small for odd n.
nmod_sqrt finds a square root modulo a word-size prime n. It uses one exponentiation when n \equiv 3 \pmod 4 or n \equiv 5 \pmod 8, and otherwise Tonelli–Shanks in two forms or Müller's variant of Cipolla–Lehmer, depending on the power of 2 dividing n - 1. Every candidate root is checked by squaring.
Discrete logarithms#
These functions compute discrete logarithms modulo a prime p to the base of the least primitive root, by the Pohlig–Hellman method with baby-step giant-step. They are efficient when p - 1 has only small prime factors. The guide Computing discrete logarithms shows how to use them, including logarithms to other bases.
Precomputed data for discrete logarithms modulo one prime: the factorisation of p - 1, the primitive root and lookup tables. The field mod is an nmod_t for p.
Initialise L and free its memory. An initialised L must be set up with nmod_discrete_log_pohlig_hellman_precompute_prime before it is used.
double nmod_discrete_log_pohlig_hellman_precompute_prime(nmod_discrete_log_pohlig_hellman_t L, ulong p)Sets up L for the prime p, which is not checked, freeing any earlier data. Returns an estimate of the number of multiplications modulo p needed by one call to nmod_discrete_log_pohlig_hellman_run.
Returns the base g of the logarithms, the least primitive root modulo p.
Returns the x \in [0, p - 1) with g^x \equiv y \pmod p. Requires 0 < y < p.
MoreMontgomery arithmetic#
In Montgomery arithmetic modulo an odd n, a residue x is represented by x R \bmod n, where R = B for the standard functions and R = 2^{\mathtt{FLINT\_BITS}/2} for the half functions. Multiplication then needs no division. Values are converted into this Montgomery form once and back at the end. The prefix of a function name tells which representation it uses:
| Prefix | Requires | R | Residues |
|---|---|---|---|
nmod_redc_ | odd n | 2^{\mathtt{FLINT\_BITS}} | [0, n) |
nmod_redc_fast_ | odd n < 2^{\mathtt{FLINT\_BITS} - 2} | 2^{\mathtt{FLINT\_BITS}} | [0, 2n) |
nmod_redc_half_ | odd n < 2^{\mathtt{FLINT\_BITS}/2 - 1} | 2^{\mathtt{FLINT\_BITS}/2} | [0, n) |
nmod_redc_half_fast_ | odd n < 2^{\mathtt{FLINT\_BITS}/2 - 2} | 2^{\mathtt{FLINT\_BITS}/2} | [0, 2n) |
The fast functions take and return lazy residues in [0, 2n), which saves a conditional subtraction per multiplication. The guide Using Montgomery arithmetic explains when Montgomery form pays off and the rules for mixing standard, fast and half functions.
A context for Montgomery arithmetic. The field mod is an ordinary nmod_t for n, used for conversions and for addition, and nred is -n^{-1} \bmod R. The context needs no clearing.
void nmod_redc_ctx_init_nmod(nmod_redc_ctx_t ctx, nmod_t mod)void nmod_redc_ctx_init_ui(nmod_redc_ctx_t ctx, ulong n)Initialise ctx for the standard and fast functions modulo n, which must be odd.
int nmod_redc_can_use_fast(const nmod_redc_ctx_t ctx)Returns whether n < 2^{\mathtt{FLINT\_BITS} - 2}, the condition for the fast functions.
ulong nmod_redc_set_nmod(ulong x, const nmod_redc_ctx_t ctx)ulong nmod_redc_set_ui(ulong x, const nmod_redc_ctx_t ctx)Return the Montgomery form x R \bmod n of x. nmod_redc_set_nmod requires x < n; nmod_redc_set_ui accepts any x.
ulong nmod_redc_get_nmod(ulong x, const nmod_redc_ctx_t ctx)Returns x R^{-1} \bmod n in [0, n), converting from Montgomery form. Any word x is accepted, in particular a lazy residue.
ulong nmod_redc_neg(ulong x, const nmod_redc_ctx_t ctx)ulong nmod_redc_add(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_sub(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_mul(ulong x, ulong y, const nmod_redc_ctx_t ctx)Negation, addition, subtraction and multiplication in Montgomery form, for inputs and output in [0, n). Negation, addition and subtraction are the same as for ordinary residues.
ulong nmod_redc_fast_neg(ulong x, const nmod_redc_ctx_t ctx)ulong nmod_redc_fast_add(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_fast_sub(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_fast_mul(ulong x, ulong y, const nmod_redc_ctx_t ctx)The same operations on lazy residues: inputs and output are in [0, 2n). Require n < 2^{\mathtt{FLINT\_BITS} - 2}.
ulong nmod_redc_fast_mul_two(ulong x, const nmod_redc_ctx_t ctx)Returns a lazy residue in [0, 2n) congruent to 2x, for x \in [0, 2n).
ulong nmod_redc_fast_normalise(ulong x, const nmod_redc_ctx_t ctx)Reduces a lazy residue x \in [0, 2n) to [0, n).
ulong _nmod_redc_pow_ui(ulong a, ulong exp, const nmod_redc_ctx_t ctx)ulong _nmod_redc_fast_pow_ui(ulong a, ulong exp, const nmod_redc_ctx_t ctx)Return a^{\mathit{exp}} with a and the result in Montgomery form, by binary exponentiation. Require \mathit{exp} \ge 1. The fast version takes and returns lazy residues.
ulong _nmod_redc_2_pow_ui(ulong exp, const nmod_redc_ctx_t ctx)ulong _nmod_redc_fast_2_pow_ui(ulong exp, const nmod_redc_ctx_t ctx)Return the Montgomery form of 2^{\mathit{exp}}, for any \mathit{exp}. The fast version returns a lazy residue.
Half-word Montgomery arithmetic#
These functions use R = 2^{\mathtt{FLINT\_BITS}/2}, so that every product fits in one word. They take the same context type, but it must be initialised with the functions below, and the resulting Montgomery form differs from that of the full-word functions, so the two cannot be mixed.
void nmod_redc_half_ctx_init_nmod(nmod_redc_ctx_t ctx, nmod_t mod)void nmod_redc_half_ctx_init_ui(nmod_redc_ctx_t ctx, ulong n)Initialise ctx for the half functions modulo n, which must be odd with n < 2^{\mathtt{FLINT\_BITS}/2 - 1}.
int nmod_redc_half_can_use_fast(const nmod_redc_ctx_t ctx)Returns whether n < 2^{\mathtt{FLINT\_BITS}/2 - 2}, the condition for the half_fast functions.
ulong nmod_redc_half_set_nmod(ulong x, const nmod_redc_ctx_t ctx)ulong nmod_redc_half_set_ui(ulong x, const nmod_redc_ctx_t ctx)ulong nmod_redc_half_get_nmod(ulong x, const nmod_redc_ctx_t ctx)Convert to and from Montgomery form with R = 2^{\mathtt{FLINT\_BITS}/2}. nmod_redc_half_set_nmod requires x < n and nmod_redc_half_set_ui accepts any x. nmod_redc_half_get_nmod returns a value in [0, n) for any x < nR, in particular for lazy residues.
ulong nmod_redc_half_add(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_half_sub(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_half_mul(ulong x, ulong y, const nmod_redc_ctx_t ctx)Addition, subtraction and multiplication in Montgomery form, for inputs and output in [0, n).
ulong nmod_redc_half_fast_add(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_half_fast_sub(ulong x, ulong y, const nmod_redc_ctx_t ctx)ulong nmod_redc_half_fast_mul(ulong x, ulong y, const nmod_redc_ctx_t ctx)The same on lazy residues in [0, 2n). Require n < 2^{\mathtt{FLINT\_BITS}/2 - 2}.
Low-level functions#
The context functions are wrappers of the following ones, which take the odd modulus n and nred = -n^{-1} \bmod R directly. Here R = B, except for the half functions, where R = 2^{\mathtt{FLINT\_BITS}/2}.
ulong n_redc_fast(ulong x, ulong n, ulong nred)Return x R^{-1} \bmod n for any word x. n_redc_fast returns a value in [0, n], which may need one more subtraction of n.
ulong n_ll_redc_fast(ull_t x, ulong n, ulong nred)Return a value congruent to x R^{-1} modulo n, for a two-word x. n_ll_redc requires x < nB and returns a value in [0, n). n_ll_redc_fast requires x + (B - 1) n < B^2 and returns a value below x/B + n.
Return a value congruent to ab R^{-1} modulo n. n_mulmod_redc requires ab < nB (for example a, b < n) and returns a value in [0, n). n_mulmod_redc_fast maps a, b \in [0, 2n) to [0, 2n) when n < 2^{\mathtt{FLINT\_BITS} - 2}.
Returns a B \bmod n for a < n, given ninv and norm as stored in an nmod_t for n. This is one division step with the precomputed inverse.
ulong n_redc_half(ulong x, ulong n, ulong nred)ulong n_redc_half_fast(ulong x, ulong n, ulong nred)The same with R = 2^{\mathtt{FLINT\_BITS}/2}. The reductions require x + (R - 1) n < B, and the ranges of inputs and outputs are those of the corresponding nmod_redc_half functions. n_to_redc_half_preinv ignores norm.
An unsigned two-word integer: __uint128_t when compiling for a 64-bit machine with a GCC-compatible compiler, and otherwise a struct of two words lo and hi. It exists for the Montgomery helpers above and may change.
Construct the two-word integer \mathit{hi} B + \mathit{lo}, and return the high or the low word of x.
ull_t ull_u_mul_u(ulong x, ulong y)Return (x + y) \bmod B^2, and the full product xy of two words.
Generic rings#
These functions create gr contexts for \mathbb{Z}/n\mathbb{Z}. Those without redc in the name are declared in gr.h.
int gr_ctx_init_nmod(gr_ctx_t ctx, ulong n)int gr_ctx_init_nmod8(gr_ctx_t ctx, ulong n)int gr_ctx_init_nmod32(gr_ctx_t ctx, ulong n)int gr_ctx_init_nmod_redc(gr_ctx_t ctx, ulong n)int gr_ctx_init_nmod_redc_fast(gr_ctx_t ctx, ulong n)Initialise ctx for the ring \mathbb{Z}/n\mathbb{Z} in the given representation and return GR_SUCCESS. If n = 0, return GR_DOMAIN; if n violates the restrictions of the representation, return GR_UNABLE. In both cases ctx is not initialised.
void _gr_ctx_init_nmod(gr_ctx_t ctx, void * nmod_t_ref)Initialises ctx like gr_ctx_init_nmod, copying the nmod_t that nmod_t_ref points to instead of recomputing it.
NMOD_CTX(ctx)NMOD_CTX_REF(ctx)The nmod_t stored in a context created by gr_ctx_init_nmod, and a pointer to it.
GR_NMOD_REDC_CTX(ctx)A pointer to the nmod_redc_ctx_struct stored in a context created by gr_ctx_init_nmod_redc or gr_ctx_init_nmod_redc_fast.
Low-level macros#
These macros are the building blocks of the arithmetic functions above and of the vector, polynomial and matrix modules. Most reduce one, two or three words modulo n with one or two steps of Möller–Granlund division. Unless stated otherwise, the first argument receives the result and mod is an nmod_t. A pair a_hi, a_lo stands for the two-word integer a_{hi} B + a_{lo}.
NMOD_RED(r, a, mod)Sets r to a \bmod n for any word a.
NMOD_RED2(r, a_hi, a_lo, mod)Sets r to (a_{hi} B + a_{lo}) \bmod n. Requires a_{hi} < n.
NMOD2_RED2(r, a_hi, a_lo, mod)Sets r to (a_{hi} B + a_{lo}) \bmod n with no restriction on a_{hi}. It reduces a_{hi} first, so it costs two division steps.
NMOD_RED3(r, a_hi, a_me, a_lo, mod)Sets r to (a_{hi} B^2 + a_{me} B + a_{lo}) \bmod n. Requires a_{hi} < n.
NMOD_RED2_FULLWORD(r, a_hi, a_lo, mod)NMOD_RED2_NONFULLWORD(r, a_hi, a_lo, mod)Versions of NMOD_RED2 without the test on mod.norm. NMOD_RED2_FULLWORD requires mod.norm = 0 (the top bit of n is set) and NMOD_RED2_NONFULLWORD requires mod.norm > 0. Both require a_{hi} < n.
NMOD_MUL_PRENORM(res, a, b, mod)NMOD_MUL_FULLWORD(res, a, b, mod)Multiply without the operand shift done by nmod_mul. NMOD_MUL_PRENORM requires a < n and b = c\, 2^{\mathit{norm}} with c < n, that is, b is a reduced value already shifted left by mod.norm bits, and sets res to the reduced residue ac \bmod n; nmod_mul(a, c, mod) is this macro applied to a and c << mod.norm. NMOD_MUL_FULLWORD requires mod.norm = 0 and reduced operands, and sets res to ab \bmod n.
NMOD_CAN_USE_SHOUP(mod)Nonzero if n < 2^{\mathtt{FLINT\_BITS} - 1}, the condition for multiplication by a fixed operand with n_mulmod_shoup.
The FLINT team, “nmod.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/nmod/index.html (generated 2026-10-20).
@misc{flint-doc-nmod-index,
author = {{The FLINT team}},
title = {{nmod.h (module overview)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/nmod/index.html},
note = {Generated 2026-10-20}
}