FLINT3.7.0-dev
Algorithm

Roots of polynomials over finite fields

Cost
Over Fq\mathbb{F}_q, degree nn: O(M(n)log⁡qlog⁡n)O(M(n) \log q \log n) expected. Over Z/pkZ\mathbb{Z}/p^k\mathbb{Z}: one root finding modulo pp plus O(log⁡k)O(\log k) lifting steps per root, each one evaluation of ff and f′f'. Over Z/nZ\mathbb{Z}/n\mathbb{Z}: the product of the numbers of roots modulo the prime powers, which can be exponential in the number of prime factors.

A root aa of ff in a field KK is the same as a linear factor x−ax - a, so finding all roots of f∈Fq[x]f \in \mathbb{F}_q[x] is the part of the factorisation that concerns factors of degree 1 (Factoring polynomials over finite fields). It is much cheaper than a complete factorisation, because only one distinct-degree step is needed and the splitting does not require the trace map. Over the ring Z/nZ\mathbb{Z}/n\mathbb{Z} with nn composite the situation is different: a polynomial can have more roots than its degree, and the roots are found prime by prime.

Roots in a finite field#

By Theorem 1 of Factoring polynomials over finite fields with d=1d = 1,

xq−x=∏a∈Fq(x−a),x^q - x = \prod_{a \in \mathbb{F}_q} (x - a),

so for squarefree gg the product of the linear factors of gg is gcd⁡(g,xq−x)\gcd(g, x^q - x). For odd qq the nonzero elements split further:

Lemma 1. For odd qq,

x(q−1)/2−1=∏a∈(Fq×)2(x−a),x(q−1)/2+1=∏a∈Fq×∖(Fq×)2(x−a).x^{(q-1)/2} - 1 = \prod_{a \in (\mathbb{F}_q^\times)^2} (x - a), \qquad x^{(q-1)/2} + 1 = \prod_{a \in \mathbb{F}_q^\times \setminus (\mathbb{F}_q^\times)^2} (x - a).

For q=2kq = 2^k and T(x)=x+x2+⋯+x2k−1T(x) = x + x^2 + \cdots + x^{2^{k-1}}, xq−x=T(x)(T(x)+1)x^q - x = T(x) (T(x) + 1), and T(x)T(x), T(x)+1T(x) + 1 are the products of x−ax - a over the elements of absolute trace 0 and 1 respectively.

Proof. Fq×\mathbb{F}_q^\times is cyclic of even order q−1q - 1, so exactly half of its elements are squares, and these are the roots of x(q−1)/2−1x^{(q-1)/2} - 1 (Euler's criterion). The other half are roots of the second factor of xq−1−1=(x(q−1)/2−1)(x(q−1)/2+1)x^{q-1} - 1 = (x^{(q-1)/2} - 1)(x^{(q-1)/2} + 1). For even qq, T(x)2=T(x)+xq−xT(x)^2 = T(x) + x^q - x since squaring is additive, so T(T+1)=xq−xT (T + 1) = x^q - x; T(a)∈F2T(a) \in \mathbb{F}_2 is the trace of aa.

The same splitting applies to the shifted roots a+ca + c, which gives a randomised equal-degree factorisation for d=1d = 1, due to Berlekamp [Ber1970] and Rabin [Rab1980b]:

Algorithm 1: Roots in Fq\mathbb{F}_q

Input: f∈Fq[x]f \in \mathbb{F}_q[x] nonzero.

Output: the roots of ff with multiplicities.

  1. Compute the squarefree factorisation f=c∏igi if = c \prod_i g_i^{\,i} (Squarefree factorisation). For each g=gig = g_i:
  2. If x∣gx \mid g, output the root 0 and remove the factor xx.
  3. For odd qq: t←x(q−1)/2 mod gt \gets x^{(q-1)/2} \bmod g; u1←gcd⁡(g,t−1)u_1 \gets \gcd(g, t - 1) and u2←gcd⁡(g,t+1)u_2 \gets \gcd(g, t + 1). For q=2kq = 2^k: t←T(x) mod gt \gets T(x) \bmod g; u1←gcd⁡(g,t)u_1 \gets \gcd(g, t) and u2←gcd⁡(g,t+1)u_2 \gets \gcd(g, t + 1).
  4. Split u1u_1 and u2u_2 into linear factors: while a piece uu has degree at least 2, choose a random c∈Fqc \in \mathbb{F}_q and replace uu by gcd⁡(u,(x+c)(q−1)/2−1)\gcd(u, (x + c)^{(q-1)/2} - 1) and its cofactor if this is a proper split (for even qq, use T(αx+c)T(\alpha x + c) with random α≠0\alpha \ne 0).
  5. Output the roots of the linear pieces with multiplicity ii.

Step 3 discards all factors of gg of degree at least 2 and already splits the roots into two classes; this initial split is Rabin's. In step 4 a root ρ\rho of uu goes into the gcd if and only if ρ+c\rho + c is a nonzero square, which for a uniformly random cc happens with probability about 1/21/2, independently enough for distinct roots that a piece of degree mm is split with probability at least 4/94/9 (Lemma 7 of Factoring polynomials over finite fields) and the expected depth of the recursion is O(log⁡n)O(\log n). Each level costs exponentiations of total degree O(n)O(n), so the expected total cost is O(M(n)log⁡qlog⁡n)O(M(n) \log q \log n), dominated by the exponentiations.

Powers of x+cx + c. An exponentiation xe mod ux^e \bmod u is cheaper than ae mod ua^e \bmod u for a general aa, since the multiplications by xx in the square-and-multiply loop are shifts. FLINT uses this for the random shifts when qq has more than 16 bits:

Lemma 2. Let u(x)u(x) have degree mm and let R=xe mod u(x−c)R = x^e \bmod u(x - c). Then (x+c)e mod u(x)=R(x+c)(x + c)^e \bmod u(x) = R(x + c).

Proof. Write xe=Q(x)u(x−c)+R(x)x^e = Q(x) u(x - c) + R(x) with deg⁡R<m\deg R < m and substitute x↦x+cx \mapsto x + c: (x+c)e=Q(x+c)u(x)+R(x+c)(x + c)^e = Q(x + c) u(x) + R(x + c), and deg⁡R(x+c)<m\deg R(x + c) < m.

So (x+c)(q−1)/2 mod u(x + c)^{(q-1)/2} \bmod u costs two Taylor shifts of degree mm (Taylor shifts) and one exponentiation of xx.

Distinct nonzero roots. When ff is known to split into distinct linear factors x−ax - a with a≠0a \ne 0, as in the decoding of Reed–Solomon codes and in sparse interpolation, the squarefree factorisation is unnecessary, and step 3 decides at once whether ff has this form: the degrees of u1u_1 and u2u_2 add up to deg⁡f\deg f if and only if it does. nmod_poly_find_distinct_nonzero_roots and fmpz_mod_poly_find_distinct_nonzero_roots implement this test and the splitting (see Finding roots that are expected to be distinct).

Roots modulo prime powers#

Let f∈Z[x]f \in \mathbb{Z}[x] and k≥2k \ge 2. Every root of ff modulo pkp^k reduces to a root modulo pep^e for every e≤ke \le k, so the roots modulo pkp^k can be found by lifting all roots modulo pp, doubling the precision in each step. Unlike the classical form of Hensel's lemma [Hen1908] (see also Hensel lifting for the lifting of factorisations), this lifts roots that are multiple modulo pp as well.

Lemma 3. Let f(a)≡0(modpe)f(a) \equiv 0 \pmod{p^e} and e′=min⁡(k,2e)e' = \min(k, 2e). For t∈Zt \in \mathbb{Z},

f(a+pet)≡0(modpe′)  ⟺  f′(a) t≡−f(a)pe(modpe′−e).f(a + p^e t) \equiv 0 \pmod{p^{e'}} \iff f'(a)\, t \equiv -\frac{f(a)}{p^e} \pmod{p^{e' - e}}.

Proof. By Taylor's formula f(a+h)=f(a)+hf′(a)+h2r(a,h)f(a + h) = f(a) + h f'(a) + h^2 r(a, h) with r∈Z[x,h]r \in \mathbb{Z}[x, h] (the coefficients f(j)/j!f^{(j)}/j! of the expansion are integral). With h=peth = p^e t the last term is divisible by p2ep^{2e}, hence by pe′p^{e'}, so f(a+pet)≡f(a)+petf′(a)(modpe′)f(a + p^e t) \equiv f(a) + p^e t f'(a) \pmod{p^{e'}}. Dividing by pep^e gives the claim.

The linear congruence αt≡β(modps)\alpha t \equiv \beta \pmod{p^s} has no solution if pj=gcd⁡(α,ps)p^j = \gcd(\alpha, p^s) does not divide β\beta, and otherwise exactly pjp^j solutions modulo psp^s, an arithmetic progression with step ps−jp^{s-j} (computed by fmpz_divides_mod_list). Hence a simple root modulo pp (f′(a)≢0f'(a) \not\equiv 0) lifts to exactly one root modulo pkp^k, while a multiple root can lift to none or to many. The lifts a+peta + p^e t for tt modulo pe′−ep^{e'-e} are distinct modulo pe′p^{e'}, and every root modulo pe′p^{e'} arises from its reduction modulo pep^e, so lifting every root at every step enumerates all roots modulo pkp^k. If f≡0(modp)f \equiv 0 \pmod p, all pp residues are roots modulo pp and are lifted in the same way.

The number of roots can be large: the roots of x2x^2 modulo pkp^k are the multiples of p⌈k/2⌉p^{\lceil k/2 \rceil}, of which there are p⌊k/2⌋p^{\lfloor k/2 \rfloor}.

Composite moduli#

For n=∏jpjkjn = \prod_j p_j^{k_j}, the Chinese remainder theorem gives Z/nZ≅∏jZ/pjkjZ\mathbb{Z}/n\mathbb{Z} \cong \prod_j \mathbb{Z}/p_j^{k_j}\mathbb{Z}, and the roots of ff modulo nn are the CRT combinations of all tuples of roots modulo the pjkjp_j^{k_j}. Their number is the product of the numbers of roots modulo the prime powers, which is zero as soon as one factor is zero, and can be far larger than deg⁡f\deg f.

In (Z/nZ)[x](\mathbb{Z}/n\mathbb{Z})[x] the multiplicity of a root aa is defined as the largest ee such that (x−a)e(x - a)^e divides ff; since x−ax - a is monic, divisibility holds modulo nn if and only if it holds modulo every pjkjp_j^{k_j}, so the multiplicity is the minimum of the multiplicities modulo the prime powers, and each of these is found by repeated exact division by x−ax - a.

Use in FLINT#

gr_poly_roots_finite_field implements Algorithm 1 for every finite field context; step 4 is _gr_poly_factor_equal_deg_with_frob with d=1d = 1, which also contains the Taylor shift trick. nmod_poly_roots and fmpz_mod_poly_roots wrap it and return the roots as linear factors in an nmod_poly_factor_t or fmpz_mod_poly_factor_t; the fq_*_poly_roots functions of fq_poly_factor and its variants are analogous, with the field arithmetic of Arithmetic in finite fields.

nmod_poly_roots_factored and fmpz_mod_poly_roots_factored take the factorisation of the modulus and implement the prime-power lifting and the CRT combination. They give up and return 0 when a list of roots would exceed about 2322^{32} entries (2252^{25} on 32-bit systems); fmpz_mod_poly_roots_factored_with_length_limit takes the limit for the CRT combination as a parameter. The generic method gr_poly_roots over nmod and fmpz_mod contexts uses the finite field algorithm when the modulus is prime and otherwise factors the modulus and calls fmpz_mod_poly_roots_factored_with_length_limit with a limit of 10610^6 roots, returning GR_UNABLE if the modulus has more than 20 prime factors (with multiplicity) or there are too many roots.

void nmod_poly_roots(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity)
int nmod_poly_roots_factored(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity, const n_factor_t * n)
void fmpz_mod_poly_roots(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_roots_factored(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_factor_t n, const fmpz_mod_ctx_t ctx)

Rational roots of integer polynomials (fmpz_poly_roots_fmpq) are found from the roots modulo a suitable prime by pp-adic lifting, which is the same lifting as above for simple roots.

Referenced from#

References#

  • [Ber1970] E. R. Berlekamp. Factoring polynomials over large finite fields. Mathematics of Computation 24 (1970), 713–735.
  • [Rab1980b] M. O. Rabin. Probabilistic algorithms in finite fields. SIAM Journal on Computing 9 (1980), 273–280.
  • [Hen1908] K. Hensel. Theorie der algebraischen Zahlen. Teubner, Leipzig, 1908.
Cite this page

The FLINT team, “Roots of polynomials over finite fields,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/polynomials/root-finding.html (generated 2026-11-02).