Polynomial GCD and Resultant
Overview
Polynomial GCD is the backbone of factorization, square-free decomposition, rational-function reduction, and intersection of algebraic curves. Over a field ($\mathbb{Q}[x]$, $\mathrm{GF}(p)[x]$, etc.) the Euclidean algorithm applies directly, but over $\mathbb{Z}[x]$ special care is required to prevent intermediate coefficient explosion.
Related API: gcd(p, q),
intPolyGcd, resultant, discriminant, sylvesterMatrix.
Euclidean Algorithm and Coefficient Growth
The Euclidean algorithm over a field reads identically to the integer case:
$$r_0 = f,\; r_1 = g,\; r_{i+1} = r_{i-1} \bmod r_i, \;\gcd(f, g) = r_k \;(r_{k+1} = 0).$$
This works fine over $\mathbb{Q}[x]$, but running a naive pseudo-remainder sequence over $\mathbb{Z}[x]$ causes intermediate coefficients to grow explosively. Knuth's classical example, $f = x^8 + x^6 - 3x^4 - 3x^3 + 8x^2 + 2x - 5$ and $g = 3x^6 + 5x^4 - 4x^2 - 9x + 21$, produces 5-digit intermediate coefficients even though the GCD is the constant 1. In general, intermediate coefficient bit-lengths grow exponentially in the degree.
This is why $\mathbb{Z}[x]$ GCD uses either the subresultant PRS or modular GCD instead of a plain pseudo-remainder sequence.
Subresultant PRS
The subresultant pseudo-remainder sequence (SR-PRS), formalized by Collins (1967) and Brown (1971), computes GCDs over $\mathbb{Z}[x]$ without exponential coefficient growth.
Idea
Pseudo-remainders $r_{i+1} = \mathrm{prem}(r_{i-1}, r_i)$ carry powers of the leading coefficient and are too large. At each step the SR-PRS divides through by an explicit common factor $\beta_i$:
$$r_{i+1} = \frac{\mathrm{prem}(r_{i-1}, r_i)}{\beta_i}.$$
$\beta_i$ has a closed form involving the previous leading coefficient $\ell_i$ and the degree drop (typically $\beta_i = -\ell_{i-1} \cdot \psi_i^{\delta_i}$). Dividing by this factor keeps the result integral while bounding intermediate coefficient bit-lengths polynomially in the input size.
sangi implementation
intPolyGcd(a, b) is implemented with the SR-PRS.
pseudoRemainder(f, g) is exposed as the building block (the raw pseudo-remainder).
At the final step the content GCD and primitive part are combined to produce the $\mathbb{Z}[x]$ GCD.
Complexity: classical SR-PRS is around $O(n^2 M(n L))$ where $n$ is the degree, $L$ the coefficient bit-length, and $M$ the cost of multi-precision multiplication.
Related article: Polynomial GCD — systematic treatment of Euclidean / SR-PRS / modular methods.
Sylvester Matrix and Resultant
For $f = \sum_{i=0}^n a_i x^i$ and $g = \sum_{i=0}^m b_i x^i$, the Sylvester matrix is the $(m + n) \times (m + n)$ matrix whose upper block stacks $f$'s coefficients shifted across $m$ rows and whose lower block stacks $g$'s coefficients across $n$ rows:
$$\mathrm{Syl}(f, g) = \begin{pmatrix} a_n & a_{n-1} & \cdots & a_0 & & \\ & a_n & a_{n-1} & \cdots & a_0 & \\ & & \ddots & & & \ddots \\ b_m & b_{m-1} & \cdots & b_0 & & \\ & b_m & b_{m-1} & \cdots & b_0 & \\ & & \ddots & & & \ddots \\ \end{pmatrix}.$$
The resultant $\mathrm{Res}(f, g)$ is its determinant:
$$\mathrm{Res}(f, g) = \det \mathrm{Syl}(f, g).$$
Properties
- $\mathrm{Res}(f, g) = 0 \;\Leftrightarrow\; f$ and $g$ share a root in the algebraic closure $\;\Leftrightarrow\; \deg \gcd(f, g) \geq 1$.
- $\mathrm{Res}(f, g) = a_n^m \prod_i g(\alpha_i) = (-1)^{nm} b_m^n \prod_j f(\beta_j)$ where $\alpha_i$ are the roots of $f$ and $\beta_j$ of $g$.
- If $f, g \in \mathbb{Z}[x]$ then $\mathrm{Res}(f, g) \in \mathbb{Z}$ — it is a polynomial in the coefficients only.
Computation
Expanding $\det \mathrm{Syl}$ directly costs $O((n+m)^3)$ and bloats further when coefficients are large.
Asymptotically, reading the resultant off the SR-PRS as a by-product is cheaper ($O((n+m)^2 \cdot$ multi-precision coefficient cost$)$): divide the leading coefficient of the last non-zero remainder by the running product of $\beta_i$.
sangi's current resultant(f, g) constructs the Sylvester matrix and evaluates its determinant via Gauss elimination ($O((n+m)^3)$); switching to the SR-PRS-fused path is on the roadmap.
Related article: Resultant
Discriminant
The discriminant of $f$ is defined via the resultant with its derivative:
$$\mathrm{Disc}(f) = \frac{(-1)^{n(n-1)/2}}{a_n} \mathrm{Res}(f, f').$$
It generalizes the familiar quadratic discriminant $b^2 - 4ac$.
Properties and uses
- $\mathrm{Disc}(f) = 0 \;\Leftrightarrow\; f$ has a repeated root in its algebraic closure.
- The sign of $\mathrm{Disc}(f)$ can reveal partial parity information about the number of real roots.
- A single resultant computation decides whether $f$ is square-free as a factorization pre-check.
sangi's discriminant(f) internally calls resultant(f, derivative(f)), then applies the sign and division by $a_n$.
// disc(x^2 - 2) = 8
Polynomial<int> f = {-2, 0, 1};
std::cout << discriminant(f) << std::endl; // 8
Half-GCD (HGCD)
The classical Euclidean / SR-PRS performs $O(n)$ iterations (one per degree drop), each costing $O(n M(n L))$, for a total of $O(n^2 M(n L))$. Half-GCD compresses these into $O(\log n)$ rounds via divide-and-conquer.
Idea
Look only at the high half of the coefficients of $(r_0, r_1)$ and recursively compute a unimodular transformation matrix $\begin{pmatrix} a & b \\ c & d \end{pmatrix}$ that advances the remainder sequence by roughly half the degree. The transformation captures the relation $(r_0, r_1) \to (r_k, r_{k+1})$ with $k \approx n/2$, yielding the GCD and Bezout coefficients in $O(M(n) \log n)$ time.
Complexity: $O(M(n) \log n)$ where $M(n)$ is the cost of polynomial multiplication.
Half-GCD outperforms classical GCD significantly once the degree exceeds a few thousand and FFT-based multiplication becomes effective. sangi's current GCD is SR-PRS-centered; Half-GCD is a planned optional path for larger inputs.
Modular GCD (Brown-Collins)
Compute the GCD over $\mathbb{Z}[x]$ by computing GCDs over $\mathrm{GF}(p)[x]$ for several primes $p_1, p_2, \ldots$ and lifting via the Chinese Remainder Theorem. Due to Brown (1971) and Collins.
Steps
- Pick a prime $p$ not dividing $\mathrm{lc}(f)$ or $\mathrm{lc}(g)$.
- Compute $\gcd_p(f, g)$ over $\mathrm{GF}(p)[x]$ via the Euclidean algorithm ($O(n^2)$ in $\mathrm{GF}(p)$).
- Repeat for several primes, combining via CRT.
- Stop when the recovered integer coefficients stabilize below the Mignotte bound.
Pros and pitfalls
- No coefficient explosion: every $\mathrm{GF}(p)$ computation stays bounded by $p$.
- Easy to parallelize: the per-prime computations are independent.
- Unlucky primes: a small fraction of primes drop the degree spuriously and must be discarded; the probability is low.
Modular GCD beats SR-PRS when both the coefficient bit-length $L$ and the degree $n$ are large, and is the standard choice in mainstream CAS.
sangi's intPolyGcd currently centers on SR-PRS; modular GCD is a planned extension.
Approximate GCD (floating-point)
With double coefficients, exact common factors rarely exist (any small perturbation makes inputs coprime).
Approximate GCD extracts an "essential" common factor within a tolerance $\epsilon$.
sangi's approximateGCD(p, q, tol) follows a two-stage strategy:
- Estimate $\deg \gcd$ from the numerical rank of the Sylvester matrix, truncating singular values below $\epsilon$.
- Reconstruct the GCD of that degree by linear least squares.
Signal-processing applications also use methods such as Karmarkar-Lakshman or ApaTools; sangi favors implementation simplicity (rank estimation + LS reconstruction).
Design Decisions
Why SR-PRS as the default
The typical sangi workload (factorization pre-processing, Yun's square-free decomposition, resultant computation) has $n \lesssim 100$ and $L \lesssim 64$, where SR-PRS's small constant outweighs the setup overhead of Half-GCD (FFT) and modular GCD (multiple prime selection, CRT). SR-PRS delivers the best implementation-complexity-versus-performance balance for this range.
Current path and planned SR-PRS switch
Direct expansion of the Sylvester determinant (Gauss elimination) costs $O((n+m)^3)$ and tends to inflate coefficients in $\mathbb{Z}$.
Reading the resultant off the SR-PRS as a by-product would fold GCD and resultant computations into a single pass, with a better asymptotic in the multi-precision regime.
sangi's current resultant favors implementation simplicity and uses the Sylvester-plus-determinant path; a future release will switch to the SR-PRS-fused route for improved multi-precision performance.
References
- Brown, W. S. (1971). "On Euclid's algorithm and the computation of polynomial greatest common divisors". Journal of the ACM, 18(4), 478–504.
- Collins, G. E. (1967). "Subresultants and reduced polynomial remainder sequences". Journal of the ACM, 14(1), 128–142.
- Knuth, D. E. The Art of Computer Programming, Volume 2: Seminumerical Algorithms. 3rd ed. Addison-Wesley, 1997.
- von zur Gathen, J. and Gerhard, J. Modern Computer Algebra. 3rd ed. Cambridge University Press, 2013.