GCDs over small finite fields
- Cost
- Over a large field, the cost of the underlying algorithm (Brown, Zippel or Hensel lifting). Over a small field, the same algorithm over for , where bounds the degrees, plus Chinese remaindering in .
The multivariate GCD algorithms of FLINT reduce the problem to fewer variables by evaluation: a variable is replaced by a value , the GCD of the images is computed recursively, and the GCD is recovered from enough images by interpolation (Brown's dense algorithm [Bro1971]), by sparse interpolation of the unknown coefficients of a known support (Zippel's algorithm [Zip1979]), or by Hensel lifting of a factorisation , of an image. These algorithms, common to all coefficient rings, are described in Greatest common divisors, Sparse interpolation and Multivariate Hensel lifting. What is specific to finite fields , , with a word-size characteristic is that the field may be too small to provide the evaluation points these algorithms need. FLINT then computes the images over larger fields, in two ways:
- medium extensions: the inputs are mapped into an extension and the algorithm runs there with evaluation points in the extension;
- reduction modulo irreducible polynomials: the variable is not evaluated at a point but reduced modulo an irreducible polynomial , so that the image lies over the field , and images are combined by the Chinese remainder theorem in .
In the sources, versions over itself are named smprime, those over extensions represented with Zech logarithms medprime, and those over with arbitrary lgprime ("small", "medium" and "large primes", the irreducible polynomials playing the role of primes). The approach of working modulo prime ideals of higher degree when the field is too small goes back to the analysis of the modular GCD algorithm over small fields by Kaltofen and Monagan [KM1999]. The implementation is due to Daniel Schultz, whose notes [Sch-mpoly] describe the algorithms of the mpoly modules.
Why small fields are a problem#
Every evaluation algorithm needs points at which the inputs keep their shape. For Brown's algorithm in the variable with the other variables , a point is bad if it is a root of (the leading coefficients with respect to , polynomials in ), and unlucky if the GCD of the images , has a larger degree than the image of the GCD. Both sets are contained in the root set of a nonzero polynomial : the leading coefficient for bad points, and a subresultant of the cofactors for unlucky ones ([GG2003, §6.7]). Sparse interpolation and Hensel lifting choose a random point for several variables at once, and have similar conditions expressed by nonzero polynomials in several variables.
Lemma 1 (Schwartz–Zippel). Let be nonzero of total degree and let be finite. For chosen uniformly at random from , the probability that is at most [Sch1980] [Zip1979].
Over a large field the probability of failure is negligible. Over with small compared with the degrees it is not, and there may be no good point at all: vanishes on all of . Taking points from an extension field restores the bound of Lemma 1 with .
Extensions do not change the GCD#
Lemma 2. Let be an extension of finite fields and , not both zero. The monic GCD of and in (with respect to any monomial ordering) has coefficients in and is the monic GCD in .
Proof. Let be the monic GCD over and write , with coprime over . Let be the monic GCD of and over . The extension is Galois; an automorphism of over , applied to the coefficients, is a ring automorphism of fixing and , so is again a monic GCD of and , hence . Thus . Division by the monic with respect to the monomial ordering gives the same quotient over and over , so divides and over and . Hence and are coprime over and is the monic GCD over .
So a GCD computed over with any algorithm, once made monic, is the GCD over ; the cofactors and also have coefficients in . This justifies the medprime Hensel-lifting GCD (nmod_mpolyl_gcd_hensel_medprime), which maps the inputs to represented by fq_zech and lifts there.
Brown's algorithm over #
Over a field with enough points, Brown's algorithm evaluates the last variable at points , computes the GCDs of the images in recursively, and interpolates the GCD and the cofactors , together [Bro1971]. The version in FLINT, nmod_mpolyn_gcd_brown_smprime (inputs in the nmod_mpolyn_t representation, with coefficients dense in ), follows the notes [Sch-mpoly] and adds two things to the textbook algorithm:
- pairs of points: for odd the points are taken in pairs , for . Writing a coefficient as , both values come from one pass over the coefficients, and the interpolants are updated modulo in one step. For the function fails, and the caller uses extensions;
- early termination: an interpolant that does not change when two new images are added has probably reached its final value, and the algorithm tests it by division before the degree bound is reached.
As in Reduction modulo irreducible polynomials, let for the leading coefficients with respect to in lex order, let leading monomials be taken with respect to these variables, and let denote the primitive part over .
Input: nonzero , odd; a limit for early termination. Output: , , , or failure.
- Remove the contents of and in (their GCD and cofactors are multiplied back at the end). Set and .
- Take the next point ; fail if there is none. If , repeat this step.
- Compute and the cofactors recursively (with the Euclidean algorithm in at the bottom); on failure go to step 2. If or is constant, return . If their leading monomials differ, go to step 2. Scale them to have leading coefficients .
- If : if the leading monomial of is larger than that of , go to step 2; if smaller, set .
- Combine with modulo . If , did not change and : let ; if and , return (made monic) and the quotients. Do the same for (if divides and divides , return ) and for . Set .
- If , go to step 2.
- If and , return and the cofactors divided by its leading coefficient. Otherwise set and go to step 2.
Theorem 3. A result returned by Algorithm 1 is correct.
Proof. For step 7 the proof of Theorem 5 applies with . For step 5, let , primitive over because the contents were removed. Every image has leading monomial at least that of , as in the proof of Theorem 5, so the same holds for and , and the leading monomial of an image of is at most , the leading monomial of . If divides and , then , so ; hence the leading monomials are equal, lies in , and it is a unit because is primitive. If divides and divides , then is a common divisor with , and ; as before and differ by a unit, using that , a divisor of the primitive , is primitive.
The early tests cost a division each and are only made while ; mpoly_gcd_info_get_brown_upper_limit sets to at most half of , smaller for dense inputs, and to 0 (no early termination) when no reliable degree bounds are known. In the bivariate case, nmod_mpolyn_gcd_brown_smprime_bivar does the same with univariate images, and nmod_mpolyn_gcd_brown_smprime_threaded_pool distributes the points over threads. The version over , Algorithm 1 of Greatest common divisors, combines images modulo word-size primes computed by this algorithm and replaces the divisibility tests by a bound on the coefficients.
Reduction modulo irreducible polynomials#
Instead of mapping all coefficients into an extension, Brown's and Zippel's algorithms can treat one variable specially. For an irreducible of degree , the reduction
replaces the evaluation , which is the case . All the properties of evaluation used by Brown's algorithm hold for with "" replaced by "", and the Chinese remainder theorem in the principal ideal domain replaces Lagrange interpolation: from images modulo pairwise coprime it recovers a polynomial with coefficients in of degree less than .
Lemma 4 (Few unlucky moduli). Let be nonzero of degree . Distinct monic irreducible polynomials that divide satisfy . In particular at most of them have degree , while the number of monic irreducible polynomials of degree over satisfies .
Proof. The are pairwise coprime divisors of , so their product divides . For the count, Gauss's formula gives .
So whatever the size of , moduli of degree suffice: a random irreducible polynomial of degree divides with probability at most . FLINT does not pick the moduli at random: it uses the irreducible polynomial chosen by fq_nmod_ctx_init_ui for (a Conway polynomial or a fixed polynomial of minimal weight) for , starting from where is the bit length of , so that has about 20 bits or more. Moduli of distinct degrees are automatically pairwise coprime, and by Lemma 4 the moduli that are bad or unlucky have total degree at most , so the process terminates. Since the degrees grow, after images the modulus has degree about , and images suffice to reach a degree bound .
The resulting algorithm for a GCD in is Brown's algorithm [Bro1971] with these "primes". Let , where the leading coefficients are taken with respect to in lexicographic order, and assume that the contents of and with respect to have been removed.
Input: , primitive over . Output: and the cofactors .
- Set , and .
- Let be the irreducible polynomial of degree , and . If , repeat this step.
- Compute over (by evaluation of the next variable at points of , which is now large), scaled to have leading coefficient , and the cofactors , .
- If , return . If and the leading monomial of is larger than that of the current , the modulus is unlucky: go to step 2. If it is smaller, all previous moduli were unlucky: set .
- Combine: , , and the previous values modulo (Chinese remainder theorem in ); .
- If , go to step 2.
- If and , return the primitive part of and the corresponding cofactors. Otherwise go to step 2.
Theorem 5. When Algorithm 2 returns in step 7, its output is correct.
Proof. Every image satisfies and , so and , the congruences holding coefficientwise in . By the test of step 7, , and likewise for , so the congruence is an equality: , and similarly . Thus is a common divisor of and , and its primitive part divides and by Gauss's lemma, so divides the true GCD . Leading monomials are taken with respect to . Since divides and , has the leading monomial of , and it divides ; hence the leading monomial of every image, and so of and , is at least that of . As divides , the quotient has leading monomial 1, that is, lies in , and is a unit because is primitive.
Termination follows from Lemma 4: only finitely many moduli are bad or unlucky, and after them every image has the correct leading monomial, so converges.
Zippel's algorithm is adapted in the same way. nmod_mpolyu_gcdm_zippel first tries the algorithm over (nmod_mpolyu_gcdp_zippel), and if that fails, reduces the last variable modulo irreducible polynomials of increasing degree, computes each image over with Zippel's algorithm (the first image fixes the monomial structure, the later ones are found by solving for the coefficients), and combines the images by Chinese remaindering in . The two-main-variable variant nmod_mpolyl_gcd_zippel_lgprime (sparse interpolation with two main variables and a known leading coefficient, as in [HuMon2016]) reduces the last variable modulo and evaluates the others at random points of .
For fq_nmod_mpoly the base field is already an extension , and the reduction is modulo an irreducible of degree . FLINT presents as with , and an embedding records the images of and ; since has roots in the large field, there are embeddings for each , which are tried in turn before is increased (bad_fq_nmod_mpoly_embed_chooser_init and bad_fq_nmod_mpoly_embed_chooser_next).
Choosing an algorithm#
nmod_mpoly_gcd and nmod_mpoly_gcd_cofactors (and, for a word-size modulus, fmpz_mod_mpoly_gcd after converting to nmod_mpoly) proceed as follows; fq_nmod_mpoly_gcd is analogous.
- If an input is zero or a monomial, or if the inputs have the same shape after removing the term contents (the cofactors may be monomials), the GCD is found directly. Inputs whose exponents need more than one word are repacked, after deflation if necessary.
- The exponents are deflated: the common powers of each variable are removed and the exponents divided by the GCD of their differences (
nmod_mpoly_deflation). If the essential parts of and share no variable, the GCD is a monomial; if they share exactly one variable and depend on no other, the computation is univariate (nmod_poly_gcd); if a variable appears in only one of them, the GCD is the GCD of the other polynomial with the coefficients of that one with respect to the variable. - Degree bounds for the GCD are estimated by evaluating all variables but one at random points, first over , then (if the bounds are not reliable, or for variables) over with Zech logarithms, then over larger extensions. If the bounds show that the GCD is 1, or that it equals or (a divisibility test), the computation stops.
- With two variables, Brown's algorithm is tried first if the inputs are dense (density above 0.05, or above 0.2 when the degree in the second variable exceeds ), otherwise Hensel lifting first.
- With more variables: for dense inputs (density above 0.08) Hensel lifting is tried first when some degree exceeds , then Brown's algorithm; then Hensel lifting if the density (relative to the total degree) exceeds 0.05 (0.001 when a degree exceeds ); then the two sparse interpolation algorithms, Zippel's first if the inputs are short compared with the degree in the second main variable; finally Hensel lifting and Brown's algorithm.
A degree above in an evaluated variable means that does not have enough points for dense interpolation; Brown's algorithm would then work modulo irreducible polynomials, while Hensel lifting needs only one good evaluation point, possibly in an extension. Each algorithm returns failure rather than an incorrect result, and the next one is tried. The returned GCD is monic, and the cofactors are scaled accordingly.
Use in FLINT#
nmod_mpoly_gcd,nmod_mpoly_gcd_cofactors: the selection of Choosing an algorithm, through_nmod_mpoly_gcd_algo.nmod_mpoly_gcd_brown,nmod_mpoly_gcd_zippel,nmod_mpoly_gcd_zippel2,nmod_mpoly_gcd_hensel: one algorithm each, falling back to extensions over small fields.- Brown modulo irreducible polynomials:
nmod_mpolyn_gcd_brown_lgprime(Algorithm 2), with the interpolation helpersnmod_mpolyn_interp_reduce_lg_mpolyn,nmod_mpolyn_interp_lift_lg_mpolynandnmod_mpolyn_interp_crt_lg_mpolyn; over itselfnmod_mpolyn_gcd_brown_smprime(Algorithm 1), with the interpolation helpersnmod_mpolyn_interp_reduce_2sm_mpolynandnmod_mpolyn_interp_crt_2sm_mpolyn. - Zippel:
nmod_mpolyu_gcdm_zippel(with fallback),nmod_mpolyu_gcdp_zippel(over ),nmod_mpolyl_gcd_zippel_smprimeandnmod_mpolyl_gcd_zippel_lgprime(two main variables). - Hensel lifting:
nmod_mpolyl_gcd_hensel_smprime, andnmod_mpolyl_gcd_hensel_medprimeover with infq_zechrepresentation (Lemma 2). - Over :
fq_nmod_mpoly_gcdwithfq_nmod_mpolyn_gcd_brown_lgprime,fq_nmod_mpolyu_gcdm_zippelandfq_nmod_mpolyl_gcd_zippel_lgprimeusing the embeddings offq_nmod_mpoly.h;fq_zech_mpoly_gcdconverts tofq_nmod_mpoly. fmpz_mod_mpoly_gcdconverts tonmod_mpolywhen the modulus fits a word; otherwise and only the algorithms over are needed.
int nmod_mpoly_gcd(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)int nmod_mpoly_gcd_cofactors(nmod_mpoly_t G, nmod_mpoly_t Abar, nmod_mpoly_t Bbar, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)int nmod_mpoly_gcd_brown(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)int nmod_mpoly_gcd_zippel(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)int nmod_mpoly_gcd_zippel2(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)int nmod_mpoly_gcd_hensel(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)int fq_nmod_mpoly_gcd(fq_nmod_mpoly_t G, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx)int fmpz_mod_mpoly_gcd(fmpz_mod_mpoly_t G, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx)Referenced from#
- Greatest common divisors (algorithm)
- Multivariate Hensel lifting (algorithm)
- Factoring over finite fields (algorithm)
- Multivariate polynomials: representations and algorithms (overview)
- Sparse interpolation (algorithm)
- fmpz_mod_mpoly.h (module)
- fmpz_mod_mpoly_factor.h (module)
- Getting started with fq_nmod_mpoly
- fq_nmod_mpoly.h (module)
- Greatest common divisors
- nmod_mpoly.h (module)
References#
- [Bro1971] W. S. Brown. On Euclid's algorithm and the computation of polynomial greatest common divisors. Journal of the ACM 18:4 (1971), 478–504. https://doi.org/10.1145/321662.321664
- [Zip1979] R. Zippel. Probabilistic algorithms for sparse polynomials. Symbolic and Algebraic Computation (EUROSAM 1979), Lecture Notes in Computer Science 72, Springer, 1979, 216–226. https://doi.org/10.1007/3-540-09519-5_73
- [KM1999] E. Kaltofen and M. Monagan. On the genericity of the modular polynomial GCD algorithm. Proceedings of ISSAC 1999, ACM, 59–66.
- [Sch-mpoly] D. Schultz. Algorithms for multivariate polynomials. Notes in the FLINT source tree, src/mpoly/doc/MPolyAlgorithms.tex.
- [GG2003] J. von zur Gathen and J. Gerhard, Modern Computer Algebra, second edition, Cambridge University Press (2003)
- [Sch1980] J. T. Schwartz. Fast probabilistic algorithms for verification of polynomial identities. Journal of the ACM 27:4 (1980), 701–717. https://doi.org/10.1145/322217.322225
- [HuMon2016] J. Hu and M. Monagan. A fast parallel sparse polynomial GCD algorithm. Proceedings of ISSAC 2016, ACM, 271–278; full version in Journal of Symbolic Computation 105 (2021), 28–63. https://doi.org/10.1016/j.jsc.2020.06.001
The FLINT team, “GCDs over small finite fields,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/multivariate/modp-gcd.html (generated 2026-11-02).
@misc{flint-doc-algorithms-multivariate-modp-gcd,
author = {{The FLINT team}},
title = {{GCDs over small finite fields}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/multivariate/modp-gcd.html},
note = {Generated 2026-11-02}
}