Greatest common divisors
- Cost
- Brown: polynomial in the dense sizes of the inputs and the coefficient size. Zippel and Hu–Monagan: polynomial in the number of terms of the GCD and cofactors, the number of variables, the degrees and the coefficient size, for inputs without unlucky evaluations. Hensel lifting: like dense multivariate Hensel lifting of two factors.
is a unique factorisation domain, so two polynomials , have a greatest common divisor , unique up to sign; FLINT returns the one with positive leading coefficient, and also the cofactors and if requested. Euclid's algorithm with pseudo-remainders works in principle, but the coefficients of the intermediate remainders grow and their supports fill up even when and the cofactors are small and sparse. All competitive algorithms are therefore modular: they compute images of modulo primes and at evaluation points, where the problem is univariate or bivariate over a finite field, and reconstruct from these images [Bro1971; GCL1992, Ch. 7; GG2003, §6]. The difficulty is to know the shape of in advance or to detect the images that do not reflect it.
The algorithms below are those used for fmpz_mpoly (and through it fmpq_mpoly); the function-level description, with an example, is Greatest common divisors. The algorithms over finite fields are the same inside, with the additional problem that a small field may not have enough evaluation points, which is treated in GCDs over small finite fields. The reconstruction of sparse polynomials from values is described in Sparse interpolation and the lifting of factorisations on Multivariate Hensel lifting. There is no generic multivariate GCD in gr_mpoly; the gr contexts of these modules call the specialised functions.
Contents and normalisation#
Write , so that . The content is the GCD of the coefficients of as a polynomial in , and is primitive if this content is 1. By Gauss's lemma products of primitive polynomials are primitive, so
and the algorithms below assume primitive inputs, computing contents by recursive GCDs in fewer variables (fmpz_mpolyl_content). For an integer content this is the usual in .
Lemma 1 (Leading coefficient). Let , be primitive with respect to and . Then divides , and is the unique multiple of by an element of with leading coefficient . It satisfies and for , .
Proof. gives , and similarly for , so . Multiplying by gives , and similarly for . Two multiples of by elements of with the same leading coefficient are equal, since is a domain.
The images of modulo a prime or at an evaluation point are determined up to the normalisation of the leading coefficient, which is known: this is how images computed independently are made consistent before they are combined. At the end, is the primitive part of .
The same reasoning applies with several main variables, which gives a common frame for the algorithms below [Sch-mpoly]. View and in with , make them primitive over , compute GCDs in variables of images at evaluation points of the other variables, impose the image of (leading coefficients with respect to ) as their leading coefficient, and interpolate. If the primitive part of the interpolated polynomial divides and , it is the GCD. Brown's algorithm takes , with dense interpolation in the last variable and recursion down to the Euclidean algorithm; Zippel's algorithm takes , and the algorithm of Hu and Monagan , both with sparse interpolation.
Easy cases#
Before any modular computation, fmpz_mpoly_gcd removes as much structure as possible; the list of steps is described in Easy cases. They rest on three facts.
- Monomials: the GCD of the monomial contents (term-wise minima of the exponents) can be split off, and is .
- Deflation: by Lemma 4 of Monomial orderings and exponent packing, exponents can be divided by common strides without changing the GCD, which reduces degrees, and inputs can then be repacked into one word.
- Missing variables: if occurs in but not in , then , because every divisor of is free of and divides if and only if it divides all coefficients of with respect to .
With one common variable the GCD is univariate (fmpz_poly_gcd, see GCDs of polynomials over Z), and when one input is a monomial times a univariate polynomial of degree at most 100 in some variable, the GCD is computed with the coefficients of the other input with respect to the remaining variables.
Degree bounds#
Lemma 2 (Degrees of images). Let be a ring homomorphism from to that reduces modulo and evaluates all variables except , and assume . Then divides and . Equality holds unless maps a certain nonzero subresultant of and (with respect to ) to zero.
Proof. and similarly for , so divides both images. Since divides , whose image is nonzero, . The images and are coprime unless their resultant vanishes, and the resultant of the images is the image of the resultant when the leading coefficients survive; the general statement with subresultants is in [GG2003, §6.7].
mpoly_gcd_info_set_estimates uses this with a random 63-bit prime and random evaluation points, for each variable in turn: the degrees of the univariate GCDs are upper bounds for the degrees of (exactly the degrees with high probability), and the numbers of their nonzero terms estimate the term counts of . If all bounds are zero, is the GCD of the contents; if they equal the degrees of (or ), the code tests whether (or ) by exact division. The estimates then feed the cost model of Choosing an algorithm.
Brown's algorithm#
Brown's algorithm [Bro1971] computes images of , and modulo primes and reconstructs them by the Chinese remainder theorem. Modulo it recurses on the variables: the last variable is evaluated at points of , the GCDs of the images in one variable fewer are computed recursively, normalised to the image of the leading coefficient , and interpolated (nmod_mpolyn_gcd_brown_smprime, described in GCDs over small finite fields). Over :
Input: nonzero with their integer contents removed (their GCD is multiplied back at the end); for the leading coefficients in lex order, which are integers. Output: , , .
- Set and .
- Take the next prime not dividing . Compute and the cofactors over , scaled so that . If , return .
- Compare the leading monomial of with that of the current : if larger, discard (unlucky) and go to 2; if smaller, discard all previous primes and set .
- Combine , , modulo with symmetric remainders, and set .
- If , go to 2.
- If and the same holds for , return , , and similarly . Otherwise go to 2.
Theorem 3 (Correctness of Brown's algorithm). If Algorithm 1 returns, its output is correct, and it returns after finitely many primes.
Proof. Each image satisfies , and so does every combination: . The coefficients of the product are bounded in absolute value by , since each coefficient is a sum of products in which every , and every , occurs at most once. By the test of step 6 these are less than , and those of are less than by step 5. Two polynomials with coefficients in that are congruent modulo are equal, so , and similarly . Hence divides and , its primitive part divides and (Gauss's lemma), and so divides . Conversely, all images used have leading monomial at most that of by Lemma 2, so the leading monomial of is that of , and a divisor of with the same leading monomial and positive leading coefficient is up to a unit, since is primitive. For termination: only finitely many primes divide or the nonzero integer that detects unluckiness (Lemma 2 applied to reduction modulo ), and once the combination uses only good primes it equals , , times -scalings, whose norms are fixed, so step 6 eventually succeeds.
The test of step 6 replaces trial division, which is the expensive final step of most modular GCD algorithms. Brown's algorithm costs about as much as a few dense multiplications of the inputs: it is the method of choice for dense inputs and for two variables, and hopeless for sparse inputs of high degree in many variables, where the dense box has entries.
Zippel's algorithm#
Zippel's algorithm [Zip1979] exploits sparsity through the shape assumption: the image of modulo a random prime has the same monomials as . The first prime gives the monomials; for the others, only the coefficients are unknown, and they are found from few evaluations by solving linear systems (sparse interpolation, Known support: transposed Vandermonde systems).
Input: , in at least two variables, primitive with respect to over ; for the lex leading coefficients. Output: , , , or failure.
- Choose a prime with and . Compute by recursive sparse interpolation over (
nmod_mpolyl_gcdp_zippel_smprime); if , return ; if its degree in exceeds the current bound, try another prime; normalise to and lift it to with symmetric coefficients. - For further primes : compute the image with the monomials of by solving for its coefficients (
nmod_mpolyl_gcds_zippel); on inconsistency go back to 1 with a new first prime. Normalise and combine with by the Chinese remainder theorem. - When no longer changes, divide by its content and test whether it divides and exactly. If so, return. If changes but its coefficients exceed a bound, go back to 1.
The result is correct because of the final divisions and the degree bound: a primitive common divisor of and whose degree in is the degree of the GCD of images, which by Lemma 2 is at least , is itself. The leading coefficient of in is in general a polynomial in , not a monomial, so the univariate images computed during sparse interpolation are only known up to scalar multiples; FLINT treats these scalars as additional unknowns of the linear systems, as proposed by de Kleine, Monagan and Wittkopf [dKMW2005].
The bound of step 3, in bits, is the bit size of the smaller of the bounds of fmpz_mpoly_factor_bound_si for the divisors of and of , which use the degrees in all variables, plus the bit size of .
Sparse interpolation with Berlekamp–Massey#
Zippel's algorithm needs one recursive sparse interpolation per variable. Hu and Monagan [HuMon2016] instead treat two main variables densely and all others at once: the coefficients of as a polynomial in are sparse polynomials in , which are recovered by the algorithm of Ben-Or and Tiwari [BenOrTiw1988] from their values at the powers of one point (Unknown support: Ben-Or–Tiwari).
Input: , in at least three variables, primitive with respect to over ; . Output: , , , or failure.
- Bound the bidegree of in from bivariate images at random points modulo a word-size prime.
- Choose Kronecker substitution degrees for (degree bounds plus one), so that the coefficients become univariate in one variable with exponents below , and a prime for which is smooth (
fmpz_next_smooth_prime), so that discrete logarithms modulo are cheap (Pohlig–Hellman [PohHel1978]). - For : evaluate for a generator , compute the bivariate GCD of the images and its cofactors (
n_polyu1n_mod_gcd_brown_smprime), scaled to have leading coefficient the image of , and feed each coefficient to a Berlekamp–Massey instance. Stop when the instances for , or for one of the cofactors, have stabilised and their roots give monomials with (discrete logarithms); check the candidate at a random point. - With the monomials known, compute images modulo further primes by solving transposed Vandermonde systems (
zip_solve), and combine them by the Chinese remainder theorem until stable. - Make the result primitive and verify by exact division.
The number of evaluations is about twice the number of terms of the largest coefficient of (or of the cofactor used), against roughly the number of terms times the number of variables for Zippel's algorithm. Using to normalise the images solves the leading coefficient problem at the price of possibly introducing a factor , removed at the end.
Hensel lifting#
The EEZ-GCD algorithm [MosYun1973; Wan1980] views the GCD problem as a factorisation problem: if for an evaluation point and is coprime to the cofactor , then is the unique lifting of with the correct leading coefficients (Lemma 1 of Multivariate Hensel lifting).
Input: , primitive with respect to ; an upper bound for . Output: , , , or failure.
- Choose (first , then random values of increasing size) with and likewise for . Compute and the cofactors , of the univariate images. If , return ; if , try another point; if , lower and try another point (the bound now has two witnesses only when two points agree).
- If equals , test whether , and symmetrically.
- Choose if , else if , else for small rationals (enumerated in Calkin–Wilf order) such that keeps its degree and its image cofactor is coprime to .
- Let . Lift the factorisation , where , are and scaled to have leading coefficients and , to a factorisation with leading coefficients and , one variable at a time with
fmpz_mpoly_hlift. On failure, try another point. - Let and verify that divides and .
Theorem 4 (Correctness of EEZ-GCD). If Algorithm 4 returns , then .
Proof. divides and by step 5, hence divides . Its degree in is , which by Lemma 2 is at least , because the evaluation preserves the degrees of and . So has degree 0 in , and as a divisor of the primitive polynomial it is a unit.
When the GCD has few terms but a dense structure in few variables, Hensel lifting is efficient, and it needs only one good evaluation point, which matters over small finite fields (GCDs over small finite fields). Its weakness is the cost of dense lifting for sparse polynomials in many variables. fmpz_mpoly_gcd does not use it; it is available as fmpz_mpoly_gcd_hensel. A last method, fmpz_mpoly_gcd_subresultant, computes the last nonzero subresultant in a well chosen main variable with Ducos' algorithm [Duc2000] and is useful only for very small inputs.
Choosing an algorithm#
After the easy cases, the inputs are converted to a lex context in the variables that occur, ordered differently for each algorithm (the variables of largest degree become the dense variables of Brown's algorithm and the main variables of the others), and the estimates of Degree bounds give costs:
- for Brown's algorithm, roughly the size of the dense boxes of , , and the cofactors, adjusted by the densities and the expected number of points before stabilisation (
mpoly_gcd_info_measure_brown); - for the Berlekamp–Massey algorithm, the number of evaluations (the maximal number of terms of a coefficient of in the two main variables) times the cost of a bivariate GCD and of evaluating and (
mpoly_gcd_info_measure_bma).
With at most two variables Brown's algorithm is used. With three or more, the Berlekamp–Massey algorithm is tried first if its estimated time is less than Brown's and either the inputs are sparse ( for the densities ) or its estimate is below 1% of Brown's; otherwise Brown's algorithm comes first. If both fail, Zippel's algorithm is tried. Each algorithm can fail (for instance when it runs out of good points, or when the exponents do not fit), never returning a wrong result, and the next one is used.
Use in FLINT#
- Driver:
fmpz_mpoly_gcd,fmpz_mpoly_gcd_cofactorsand the forced variants through_fmpz_mpoly_gcd_algo, with the bookkeeping ofmpoly_gcd_info_t(mpoly_gcd_info_limits,mpoly_gcd_info_stride,mpoly_gcd_info_set_perm,mpoly_gcd_info_measure_brown,mpoly_gcd_info_measure_bma,mpoly_gcd_info_measure_zippel,mpoly_gcd_info_measure_hensel). - Brown:
fmpz_mpolyl_gcd_brown(Algorithm 1, Theorem 3), withnmod_mpolyn_gcd_brown_smprimefor the images and the interpolation helpersfmpz_mpoly_interp_reduce_p_mpolyn,fmpz_mpoly_interp_crt_p_mpolyn; a threaded version over several primes isfmpz_mpolyl_gcd_brown_threaded_pool. - Zippel:
fmpz_mpolyl_gcd_zippel(Algorithm 2), withnmod_mpolyl_gcdp_zippel_smprimeandnmod_mpolyl_gcds_zippel. - Berlekamp–Massey:
fmpz_mpolyl_gcd_zippel2(Algorithm 3). - Hensel:
fmpz_mpolyl_gcd_hensel(Algorithm 4), withfmpz_mpoly_hlift. - Subresultants:
fmpz_mpoly_gcd_subresultant. fmpq_mpoly_gcdand friends apply these to the integer parts; the finite field versions are described in GCDs over small finite fields.
int fmpz_mpoly_gcd(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)int fmpz_mpoly_gcd_cofactors(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)int fmpz_mpoly_gcd_brown(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)int fmpz_mpoly_gcd_zippel(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)int fmpz_mpoly_gcd_zippel2(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)int fmpz_mpoly_gcd_hensel(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)int fmpz_mpoly_gcd_subresultant(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)int fmpz_mpolyl_gcd_brown(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, fmpz_mpoly_t A, fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, const mpoly_gcd_info_t Iv)int fmpz_mpolyl_gcd_zippel(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx, flint_rand_t randstate)int fmpz_mpolyl_gcd_zippel2(fmpz_mpoly_t G, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t Gamma, const fmpz_mpoly_ctx_t ctx)int fmpz_mpolyl_gcd_hensel(fmpz_mpoly_t G, slong Gdeg, fmpz_mpoly_t Abar, fmpz_mpoly_t Bbar, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx)Referenced from#
- Multivariate Hensel lifting (algorithm)
- GCDs over small finite fields (algorithm)
- Multivariate polynomials: representations and algorithms (overview)
- Monomial orderings and exponent packing (algorithm)
- Sparse interpolation (algorithm)
- fmpz_mod_mpoly.h (module)
- Greatest common divisors
- fmpz_mpoly_factor.h (module)
- fq_nmod_mpoly.h (module)
- fq_zech_mpoly.h (module)
- mpoly.h (module)
- 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
- [GCL1992] K. O. Geddes, S. R. Czapor and G. Labahn. Algorithms for computer algebra. Springer, 1992. https://doi.org/10.1007/b102438
- [GG2003] J. von zur Gathen and J. Gerhard, Modern Computer Algebra, second edition, Cambridge University Press (2003)
- [Sch-mpoly] D. Schultz. Algorithms for multivariate polynomials. Notes in the FLINT source tree, src/mpoly/doc/MPolyAlgorithms.tex.
- [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
- [dKMW2005] J. de Kleine, M. Monagan and A. Wittkopf. Algorithms for the non-monic case of the sparse modular GCD algorithm. Proceedings of ISSAC 2005, ACM, 124–131. https://doi.org/10.1145/1073884.1073903
- [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
- [BenOrTiw1988] M. Ben-Or and P. Tiwari. A deterministic algorithm for sparse multivariate polynomial interpolation. Proceedings of STOC 1988, ACM, 301–309. https://doi.org/10.1145/62212.62241
- [PohHel1978] S. C. Pohlig and M. E. Hellman, "An improved algorithm for computing logarithms over GF(p) and its cryptographic significance", IEEE Transactions on Information Theory 24 (1978), 106–110, https://doi.org/10.1109/TIT.1978.1055817
- [MosYun1973] J. Moses and D. Y. Y. Yun. The EZ GCD algorithm. Proceedings of the ACM Annual Conference 1973, 159–166. https://doi.org/10.1145/800192.805698
- [Wan1980] P. S. Wang. The EEZ-GCD algorithm. ACM SIGSAM Bulletin 14:2 (1980), 50–60. https://doi.org/10.1145/1089220.1089228
- [Duc2000] L. Ducos. Optimizations of the subresultant algorithm. Journal of Pure and Applied Algebra 145 (2000), 149–163. https://doi.org/10.1016/S0022-4049(98)00081-4
The FLINT team, “Greatest common divisors,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/multivariate/gcd.html (generated 2026-11-02).
@misc{flint-doc-algorithms-multivariate-gcd,
author = {{The FLINT team}},
title = {{Greatest common divisors}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/multivariate/gcd.html},
note = {Generated 2026-11-02}
}