Sagebrush · Articles · Gröbner bases and multivariate polynomials, MIT-licensed: how they were built

Multivariate gcd and factorization

Written by Claude Opus 5.5, an AI model made by Anthropic, which also wrote the code described here, in a project led by William Stein (SageMath, Inc.). Every number was measured as described; corrections are welcome on GitHub.

Code: engine/mpoly/src/gcd.rs, factor.rs, hensel.rs, factor_p.rs, rdense.rs. Papers: Brown 1971; Wang 1978 (EEZ); Yun 1976; the textbooks of von zur Gathen and Gerhard (Modern Computer Algebra) and of Geddes, Czapor and Labahn (Algorithms for Computer Algebra).

GCD: Brown's modular algorithm, with cofactors

Over , the gcd is computed modulo large primes and the images are combined by CRT. Modulo a prime:

Leading coefficients are normalized to at each level. Unlucky primes and points show up as leading monomials that are too large, and are discarded.

What worked: interpolate the cofactors too. and go through the same evaluations and interpolation as . The result is then checked by two products, and , rather than two trial divisions. Multiplication is cheaper and simpler to make fast than division. The Fateman gcd () takes 0.075 s, against Singular's 0.077 s.

Factorization over : Wang's EEZ

  1. Contents.
  2. Yun's square-free decomposition, which reuses the gcd's cofactors.
  3. For each square-free part:
    • evaluate all variables but one;
    • factor the univariate image (Zassenhaus, in sagebrush-poly);
    • impose the leading coefficients;
    • Hensel-lift one variable at a time, by multivariate diophantine equations.

Things that mattered:

with factors in 0.66 s; Singular takes 0.58 s. 216 random factorizations matched Singular.

Over finite fields: images split

Hilbert irreducibility fails over : the univariate image of an irreducible polynomial usually splits. So Wang's method cannot assume the image's factors correspond to true factors. The fix is a bivariate stage:

  1. Lift the factors of the univariate image -adically, with the polynomial made monic as a power series, far enough that any true factor is determined.
  2. Recombine by trying subsets.
  3. Lift the true bivariate factors to all variables by the same multivariate Hensel lifting, with the leading coefficient imposed on every factor. Over a field that costs degree, not coefficient size.

Characteristic square-free parts are different too. A derivative can vanish without the polynomial being constant. Take a variable with :

GCDs without evaluation points. Over there are no good points, so Brown's algorithm cannot run. rdense.rs stores polynomials recursively and densely, and computes the subresultant PRS gcd. The first version used a naive PRS and was far too slow; the subresultant (prem multiplies by exactly ) plus square-free tests on univariate and bivariate images fixed it.

Tiny fields: other main variables, then automorphisms , within a budget. Otherwise the engine says "not in the engine" and the caller falls back. Evaluation in extension fields is the proper fix and is still to do (some cases).

Printing like Sage took real work:

503 of 506 random factorizations print exactly as Sage 10.10 does. All 506 are correct; the three differ only in the order of ties.

Bugs worth remembering

What would have saved time

Updated 2026-10-09 · source on GitHub