Modular arithmetic with integers
#include <flint/fmpz.h>Sets to in . Requires , which is not checked (a zero divisor crashes with a division by zero).
Sets to the symmetric remainder with . Requires (not checked).
If , sets to the inverse of modulo in and returns 1; otherwise returns 0 and is undefined. Every is invertible modulo , with inverse 0. Throws an exception if .
Set to in , for (an exception is raised otherwise). For the result is 0, and otherwise . fmpz_powm accepts if is invertible modulo and raises an exception if it is not.
These functions reduce, invert, exponentiate and take square roots of integers modulo an integer given as an fmpz_t. Each call is self-contained: no data about is kept between calls. They are the right choice for a few operations; for many operations with the same modulus the module fmpz_mod (which stores precomputed data in a context) or, for a word-size modulus, nmod.h is faster.
Residues#
fmpz_mod returns the residue in , and fmpz_smod the symmetric residue with . Both require without checking it. fmpz_mod_ui, fmpz_fdiv_ui and fmpz_get_nmod reduce modulo a word. For the results of fmpz_invmod, fmpz_powm and fmpz_sqrtmod, the inputs may be any integers; they are reduced first.
Inversion#
fmpz_invmod returns 1 and the inverse in if , and 0 otherwise, so it doubles as a coprimality test. Modulo every is invertible with inverse 0. Word-size moduli use n_gcdinv; larger ones GMP's mpz_invert, an extended GCD (Integer GCD). For a modulus whose factors are needed when the inverse does not exist, use fmpz_gcdinv or the extended GCD functions of GCD, LCM and Bézout coefficients.
Exponentiation#
fmpz_powm and fmpz_powm_ui require and return in ; for the result is 0 even for . fmpz_powm also accepts and then inverts first, raising an exception if is not invertible. The algorithm depends on the sizes:
- a word-size modulus with a word-size base:
n_powmod2_ui_preinv(or GMP for an exponent that is not a word); - a large base with a word-size modulus, or a large modulus below 70000 bits: GMP's
mpz_powmandmpz_powm_ui, which use Montgomery reduction [Mon1985] with a sliding window; - of at least 70000 bits, in builds with
fft_small: binary or sliding-window exponentiation in thegrcontext of (gr_ctx_init_fmpz_mod), where each modular multiplication is a product followed by a division with a precomputed inverse of (fmpz_fdiv_r_preinvn), so that both steps use FLINT's FFT multiplication (Callers and thresholds); - exponents with a large modulus are done by one to three multiplications and reductions.
Square roots#
fmpz_sqrtmod computes a square root modulo a prime . It returns 1 and a root if is a square modulo (0 and 1 are their own roots), and 0 with otherwise. It chooses, as nmod_sqrt does for words (Square roots modulo a prime), between for , Atkin's formula for , Tonelli–Shanks when for , and Müller's Lucas sequence variant of the Cipolla–Lehmer method otherwise (Square roots modulo a prime). Primality of is not checked: for even and for perfect squares the function returns 0, and for other composite a return value of 1 does not guarantee anything.
Example#
Computations modulo the Mersenne prime , and modulo 12:
#include <flint/flint.h>
#include <flint/fmpz.h>
int main(void)
{
fmpz_t p, a, b, e, x;
fmpz_init(p); fmpz_init(a); fmpz_init(b); fmpz_init(e); fmpz_init(x);
/* p = 2^127 - 1 is prime */
fmpz_one_2exp(p, 127);
fmpz_sub_ui(p, p, 1);
/* Fermat: 3^(p-1) = 1 mod p */
fmpz_set_ui(a, 3);
fmpz_sub_ui(e, p, 1);
fmpz_powm(x, a, e, p);
flint_printf("3^(p-1) mod p = "); fmpz_print(x); flint_printf("\n");
/* inverses: 3^-1 mod p, and a negative exponent */
fmpz_invmod(x, a, p);
flint_printf("3^-1 mod p = "); fmpz_print(x); flint_printf("\n");
fmpz_set_si(e, -2);
fmpz_powm(b, a, e, p);
fmpz_mul(x, x, x);
fmpz_mod(x, x, p);
flint_printf("3^-2 mod p agrees: %d\n", fmpz_equal(x, b));
/* not invertible modulo 12 */
fmpz_set_ui(b, 12);
fmpz_set_si(a, -9);
flint_printf("invmod(-9, 12) = %d\n", fmpz_invmod(x, a, b));
fmpz_mod(x, a, b);
flint_printf("-9 mod 12 = "); fmpz_print(x);
fmpz_smod(x, a, b);
flint_printf(", smod = "); fmpz_print(x); flint_printf("\n");
/* square roots modulo p */
fmpz_set_ui(a, 2);
if (fmpz_sqrtmod(x, a, p))
{
fmpz_mul(b, x, x);
fmpz_mod(b, b, p);
flint_printf("sqrt(2) mod p = "); fmpz_print(x);
flint_printf(", squared: "); fmpz_print(b); flint_printf("\n");
}
fmpz_set_si(a, -1);
flint_printf("-1 is a square mod p: %d\n", fmpz_sqrtmod(x, a, p));
fmpz_clear(p); fmpz_clear(a); fmpz_clear(b); fmpz_clear(e); fmpz_clear(x);
return 0;
}3^(p-1) mod p = 1 3^-1 mod p = 113427455640312821154458202477256070485 3^-2 mod p agrees: 1 invmod(-9, 12) = 0 -9 mod 12 = 3, smod = 3 sqrt(2) mod p = 18446744073709551616, squared: 2 -1 is a square mod p: 0
Since , the root found is . As , is not a square.
Guides#
- Where FLINT uses fft_small (
fft_small) - Getting started with fmpz
- Using fmpz_mod (
fmpz_mod) - Prime and composite moduli (
fmpz_mod_mat) - Getting started with fmpz_mod_poly (
fmpz_mod_poly) - Getting started with generic rings (
gr) - Using mpn_mod (
mpn_mod)
References#
- [Mon1985] P. L. Montgomery, "Modular multiplication without trial division", Mathematics of Computation 44 (1985), 519–521
The FLINT team, “Modular arithmetic with integers (fmpz.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz/modular.html (generated 2026-11-02).
@misc{flint-doc-fmpz-modular,
author = {{The FLINT team}},
title = {{Modular arithmetic with integers (fmpz.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/fmpz/modular.html},
note = {Generated 2026-11-02}
}