nmod_poly_factor.h
#include <flint/nmod_poly_factor.h>This module factors polynomials over the prime field \mathbb{F}_p, p < 2^{\mathtt{FLINT\_BITS}}, represented as nmod_poly_t, tests them for irreducibility and squarefreeness, and finds their roots, over \mathbb{F}_p and also over \mathbb{Z}/n\mathbb{Z} for composite n with known factorisation. A factorisation is stored in an nmod_poly_factor_t, a list of polynomials with exponents.
The factorisation, irreducibility and root-finding functions are thin wrappers around the generic finite-field implementations in gr_poly (gr_poly_factor_finite_field, gr_poly_is_irreducible, gr_poly_roots_finite_field and the functions they call), which view the nmod_poly_t as a gr_poly_t over the nmod context without copying it. A complete factorisation consists of a squarefree factorisation followed, for each squarefree part, by either the Cantor–Zassenhaus algorithm with classical distinct-degree factorisation (small degrees and small p) or the Kaltofen–Shoup algorithm with baby-step giant-step distinct-degree factorisation and modular composition; Berlekamp's algorithm is available on request. The guide Factoring polynomials over a prime field explains the choices and their costs with examples, and the algorithms are described in detail in:
gr_poly chooses between them.AlgorithmRoots of polynomials over finite fieldsRoots in \mathbb{F}_q by squarefree factorisation, the split \gcd(f, x^{(q-1)/2} \pm 1) and random shifts, with powers of x + c computed through Taylor shifts; roots modulo prime powers by Hensel lifting of all roots, and modulo composite n by the Chinese remainder theorem.Types and conventions#
A polynomial in factored form. The structure has the fields p (an array of alloc polynomials, of which the first num are used), exp (an array of alloc exponents of type slong), num and alloc. Entry i for 0 \le i < \mathit{num} stands for the factor \mathtt{p[i]}^{\mathtt{exp[i]}}. An nmod_poly_factor_t is an array of one nmod_poly_factor_struct, so it is passed by reference.
- The factorisation, irreducibility, squarefreeness and root-finding functions require the modulus p to be prime, except
nmod_poly_roots_factored. This is not checked: a composite modulus gives wrong results or an exception. - The factors computed by this module are monic.
nmod_poly_factorand its variants return the leading coefficient of the input separately. - The factors are stored in no particular order. The algorithms are randomised, but every function seeds its own random state with a fixed value, so the output is reproducible.
- Most functions overwrite the output factorisation, but
nmod_poly_factor_cantor_zassenhaus,nmod_poly_factor_berlekamp,nmod_poly_factor_kaltofen_shoup,nmod_poly_factor_distinct_degandnmod_poly_factor_equal_degappend to it; each function says which. - Distinct-degree and equal-degree factorisation of polynomials of degree above about 200 use several threads when they have been made available with
flint_set_num_threads.
Memory management#
void nmod_poly_factor_init(nmod_poly_factor_t fac)Initialises fac as the empty factorisation (\mathit{num} = 0), with space for 5 factors.
void nmod_poly_factor_clear(nmod_poly_factor_t fac)Frees the memory used by fac, including all allocated polynomials.
void nmod_poly_factor_realloc(nmod_poly_factor_t fac, slong alloc)Changes the space of fac to exactly alloc factors. For alloc = 0 the factorisation is cleared and reinitialised (with space for 5 factors and \mathit{num} = 0). If alloc is smaller than the number of factors, the factors beyond the first alloc are discarded.
void nmod_poly_factor_fit_length(nmod_poly_factor_t fac, slong len)Ensures that fac has space for at least len factors. If it has to grow, it grows to at least twice its previous allocation.
Swaps a and b efficiently.
Basic manipulation#
void nmod_poly_factor_set(nmod_poly_factor_t res, const nmod_poly_factor_t fac)Sets res to a copy of fac, including the moduli of the factors.
void nmod_poly_factor_get_poly(nmod_poly_t a, const nmod_poly_factor_t b, slong i)Sets a to the factor b->p[i], for 0 \le i < \mathit{num}. The exponent is b->exp[i].
void nmod_poly_factor_insert(nmod_poly_factor_t fac, const nmod_poly_t poly, slong exp)Multiplies the factorisation by \mathit{poly}^{\mathit{exp}}: if poly is equal to one of the factors, exp is added to its exponent, otherwise a copy of poly is appended with exponent exp. Constant polynomials are ignored. The search is linear in the number of factors.
void nmod_poly_factor_concat(nmod_poly_factor_t res, const nmod_poly_factor_t fac)Multiplies res by the factorisation fac, by inserting each factor of fac with nmod_poly_factor_insert. res and fac must be distinct objects.
void nmod_poly_factor_pow(nmod_poly_factor_t fac, slong exp)Multiplies every exponent of fac by exp, which raises the factored polynomial to the power exp.
Input and output#
void nmod_poly_factor_print(const nmod_poly_factor_t fac)void nmod_poly_factor_print_pretty(const nmod_poly_factor_t fac, const char * var)Print the factors to standard output, one per line, as the polynomial followed by ^ and the exponent. nmod_poly_factor_print writes the polynomials in the format of nmod_poly_print, and nmod_poly_factor_print_pretty in the format of nmod_poly_print_pretty with the variable name var.
Factorisation#
ulong nmod_poly_factor(nmod_poly_factor_t result, const nmod_poly_t input)Sets result to the factorisation of input into monic irreducible polynomials over \mathbb{F}_p and returns the leading coefficient of input, so that input equals the leading coefficient times the product of the factors raised to their exponents. A constant input gives the empty factorisation and returns the constant (0 for the zero polynomial).
ulong nmod_poly_factor_with_cantor_zassenhaus(nmod_poly_factor_t result, const nmod_poly_t input)ulong nmod_poly_factor_with_berlekamp(nmod_poly_factor_t result, const nmod_poly_t input)ulong nmod_poly_factor_with_kaltofen_shoup(nmod_poly_factor_t result, const nmod_poly_t input)Like nmod_poly_factor, but split the squarefree factors with the Cantor–Zassenhaus algorithm, Berlekamp's algorithm or the Kaltofen–Shoup algorithm respectively. Deflation is still applied.
void nmod_poly_factor_cantor_zassenhaus(nmod_poly_factor_t res, const nmod_poly_t f)void nmod_poly_factor_berlekamp(nmod_poly_factor_t res, const nmod_poly_t f)void nmod_poly_factor_kaltofen_shoup(nmod_poly_factor_t res, const nmod_poly_t f)Append the factorisation of f into monic irreducible polynomials, with exponents, to res, using the Cantor–Zassenhaus algorithm, Berlekamp's algorithm or the Kaltofen–Shoup algorithm (with deflation, as in nmod_poly_factor). The leading coefficient of f is discarded; nothing is appended for a constant f.
void nmod_poly_factor_squarefree(nmod_poly_factor_t res, const nmod_poly_t f)Sets res to the squarefree factorisation of f: monic squarefree polynomials g_i, pairwise coprime and with distinct exponents e_i, such that f = c \prod_i g_i^{e_i} with c the leading coefficient of f. A constant f gives the empty factorisation.
void nmod_poly_factor_distinct_deg(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const * degs)void nmod_poly_factor_distinct_deg_threaded(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const * degs)Distinct-degree factorisation of a squarefree polynomial poly of degree at least 1, which need not be monic. Appends to res monic polynomials f_1, \ldots, f_k, each with exponent 1, such that f_j is the product of all monic irreducible factors of poly of one degree d_j, and writes d_j to (*degs)[j - 1]. The array *degs must have room for \deg(\mathit{poly}) entries; the d_j are distinct but not sorted. If poly is not squarefree the output is meaningless.
void nmod_poly_factor_equal_deg(nmod_poly_factor_t factors, const nmod_poly_t pol, slong d)Equal-degree factorisation: pol must be squarefree and a product of irreducible polynomials of degree d, and d must divide \deg(\mathit{pol}). Appends the monic irreducible factors of pol, each with exponent 1, to factors.
Irreducibility and squarefreeness#
int nmod_poly_is_irreducible(const nmod_poly_t f)Returns whether f is irreducible over \mathbb{F}_p. As a special case, constant polynomials, including zero, are considered irreducible (unlike gr_poly_is_irreducible, which returns false for them).
int nmod_poly_is_irreducible_ddf(const nmod_poly_t f)Returns whether f is irreducible, by the coarse phase of the baby-step giant-step distinct-degree factorisation: after a squarefreeness test, f is irreducible if and only if it has no factor of degree at most \deg(f)/2. Constants are considered irreducible. This is gr_poly_is_irreducible_ddf; it stops at the first interval of degrees that contains a factor.
int nmod_poly_is_irreducible_rabin(const nmod_poly_t f)int _nmod_poly_is_squarefree(nn_srcptr f, slong len, nmod_t mod)int nmod_poly_is_squarefree(const nmod_poly_t f)Return whether f (given as (f, len) in the underscore version, with any \mathit{len} \ge 0) is squarefree, by testing whether \gcd(f, f') = 1; if f' = 0 and \deg f \ge 2, then f is a p-th power and not squarefree. Nonzero constants are squarefree; as a special case, the zero polynomial is not.
Roots#
void nmod_poly_roots(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity)Sets r to the linear factors x - a for the distinct roots a \in \mathbb{F}_p of the nonzero polynomial f. If with_multiplicity is nonzero, the exponent of x - a is the multiplicity of a as a root of f, otherwise it is 1. The modulus must be prime. A zero f causes an exception.
int nmod_poly_roots_factored(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity, const n_factor_t * n)Sets r to the linear factors x - a for the distinct roots a \in \mathbb{Z}/n\mathbb{Z} of the nonzero polynomial f, where n holds the prime factorisation of the modulus n of f (not checked). If with_multiplicity is nonzero, the exponent of x - a is the largest e such that (x - a)^e divides f in (\mathbb{Z}/n\mathbb{Z})[x], otherwise it is
- Returns 1 on success and 0 if the roots were not computed because there are too many of them (more than about 2^{32}, or 2^{25} on 32-bit systems). A zero
fcauses an exception.
References#
- [Rab1980b] M. O. Rabin. Probabilistic algorithms in finite fields. SIAM Journal on Computing 9 (1980), 273–280.
The FLINT team, “nmod_poly_factor.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/nmod_poly_factor/index.html (generated 2026-10-20).
@misc{flint-doc-nmod-poly-factor-index,
author = {{The FLINT team}},
title = {{nmod\_poly\_factor.h (module overview)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/nmod_poly_factor/index.html},
note = {Generated 2026-10-20}
}