Bivariate resultants by evaluation and interpolation
- Cost
- O((n_A + n_B) M(N) + N M(n_A) \log n_A) operations in \mathbb{F}_p for N = n_B d_A + n_A d_B + 1 points, where n_A, n_B are the degrees in the eliminated variable and d_A, d_B those in the other one.
Let A, B \in \mathbb{F}_p[x][y] have degrees n_A = \deg_y A \ge 1 and n_B = \deg_y B \ge 1 in y and degrees d_A, d_B in x. Their resultant with respect to y is the determinant of the Sylvester matrix, a polynomial R = \mathrm{Res}_y(A, B) \in \mathbb{F}_p[x]. The subresultant algorithm computes it by pseudo-remainder sequences in \mathbb{F}_p[x][y], whose intermediate coefficients have growing degree in x. When \mathbb{F}_p is large enough, it is faster to evaluate x at many points, compute univariate resultants over \mathbb{F}_p, and interpolate, as in the classical modular resultant algorithm [GG2003, §6.9]. FLINT implements this method for nmod_mpoly with fast evaluation and interpolation at structured points: a geometric progression [BS2005], or roots of unity when p is an FFT prime.
Degree bound and specialisation#
Lemma 1 (Degree bound). \deg_x R \le n_B d_A + n_A d_B.
Proof. The Sylvester matrix has n_B rows of coefficients of A (polynomials in x of degree at most d_A) and n_A rows of coefficients of B (degree at most d_B). Every term of the expansion of the determinant is a product of one entry from each row.
Hence R is determined by its values at N = n_B d_A + n_A d_B + 1 distinct points. The value at x = a must be computed from the specialisations f = A(a, y) and g = B(a, y), whose degrees may be lower than n_A and n_B when a is a root of a leading coefficient.
Lemma 2 (Specialisation). Let a \in \mathbb{F}_p, f = A(a, y), g = B(a, y), and \ell_A, \ell_B the leading coefficients of A and B in y.
- If \deg f = n_A, then R(a) = \ell_A(a)^{n_B - \deg g} \mathrm{Res}(f, g).
- If \deg g = n_B and \deg f < n_A, then R(a) = (-1)^{n_B (n_A - \deg f)} \ell_B(a)^{n_A - \deg f} \mathrm{Res}(f, g).
- If both degrees drop, R(a) = 0.
Here \mathrm{Res}(f, g) is the resultant of f and g with respect to their actual degrees, and is 0 if f or g is zero.
Proof. Evaluation commutes with the determinant, so R(a) is the determinant of the Sylvester matrix of f and g built with the formal degrees n_A and n_B. In case 1, the leading n_B - \deg g coefficients of g in that matrix are zero, and expanding along the first columns, each of which then has the single nonzero entry \ell_A(a), gives the formula. Case 2 follows from case 1 applied to \mathrm{Res}_y(B, A) = (-1)^{n_A n_B} R, with the sign of the exchange for the actual degrees. In case 3, the first column of the matrix contains only \ell_A(a) = \ell_B(a) = 0.
Algorithm#
Input: A, B with n_A \ge n_B \ge 1 and a prime p. Output: R = \mathrm{Res}_y(A, B), or failure if \mathbb{F}_p is too small.
- Set N = n_B d_A + n_A d_B + 1.
- Choose N distinct points: if FLINT has
fft_smalland p - 1 is divisible by 2^k \ge \max(N, 16) (an FFT prime), the powers of a primitive 2^k-th root of unity w; otherwise a geometric progression 1, q, q^2, \ldots, q^{N-1} with q = r^2 of order at least N, where r is the first of 2, 3, 4, \ldots that works. If p < 2N + 1, no such q exists: fail. - Evaluate each of the n_A + n_B + 2 coefficients of A and B (as polynomials in x) at the points, by FFTs or by the geometric progression algorithm [BS2005], in blocks of points sized to bound the memory.
- At each point, compute the univariate resultant of the specialisations with
_nmod_poly_resultantand apply Lemma 2. - Interpolate R from its N values, by an inverse FFT or geometric interpolation.
The evaluation of one coefficient of length at most \max(d_A, d_B) + 1 at N points of a geometric progression costs O(M(N)) operations, so step 3 costs O((n_A + n_B) M(N)), step 5 costs O(M(N)), and step 4 costs N univariate resultants of degree n_A, each O(M(n_A) \log n_A) with the half-gcd algorithm (Half-GCD) or O(n_A n_B) with Euclid's algorithm for small degrees. In the FFT case the points are split into 2^{\mathrm{depth} - m} cosets of the 2^m-th roots of unity, each evaluated by a substitution x \mapsto w^t x and one transform of length 2^m; the values come out in the order that the truncated inverse transform needs, so interpolation is a single inverse transform (or a geometric interpolation with r = \sqrt{w} when that is cheaper). Both loops over the points run in parallel on the threads set with flint_set_num_threads when the work is large enough.
Example#
Two random polynomials of degree 8 in each variable modulo the prime 10^6 + 3; nmod_mpoly_resultant takes the evaluation and interpolation path, and the result agrees with the subresultant algorithm applied to the univariate forms. The resultant reaches the degree bound of Lemma 1:
#include <flint/flint.h>
#include <flint/nmod_mpoly.h>
int main(void)
{
nmod_mpoly_ctx_t ctx;
nmod_mpoly_t a, b, r1, r2;
nmod_mpoly_univar_t ua, ub;
ulong bounds[2] = {9, 9}; /* degrees < 9 in x and in y */
flint_rand_t state;
flint_rand_init(state);
nmod_mpoly_ctx_init(ctx, 2, ORD_LEX, UWORD(1000003));
nmod_mpoly_init(a, ctx); nmod_mpoly_init(b, ctx);
nmod_mpoly_init(r1, ctx); nmod_mpoly_init(r2, ctx);
nmod_mpoly_univar_init(ua, ctx); nmod_mpoly_univar_init(ub, ctx);
nmod_mpoly_randtest_bounds(a, state, 81, bounds, ctx);
nmod_mpoly_randtest_bounds(b, state, 81, bounds, ctx);
/* eliminate y (variable 1): evaluation/interpolation in x */
nmod_mpoly_resultant(r1, a, b, 1, ctx);
/* the same resultant by subresultants over F_p[x] */
nmod_mpoly_to_univar(ua, a, 1, ctx);
nmod_mpoly_to_univar(ub, b, 1, ctx);
nmod_mpoly_univar_resultant(r2, ua, ub, ctx);
flint_printf("deg_y a = %wd, deg_x a = %wd\n", nmod_mpoly_degree_si(a, 1, ctx),
nmod_mpoly_degree_si(a, 0, ctx));
flint_printf("deg_x res = %wd (bound %wd), equal: %d\n",
nmod_mpoly_degree_si(r1, 0, ctx),
nmod_mpoly_degree_si(b, 1, ctx) * nmod_mpoly_degree_si(a, 0, ctx)
+ nmod_mpoly_degree_si(a, 1, ctx) * nmod_mpoly_degree_si(b, 0, ctx),
nmod_mpoly_equal(r1, r2, ctx));
nmod_mpoly_univar_clear(ua, ctx); nmod_mpoly_univar_clear(ub, ctx);
nmod_mpoly_clear(a, ctx); nmod_mpoly_clear(b, ctx);
nmod_mpoly_clear(r1, ctx); nmod_mpoly_clear(r2, ctx);
nmod_mpoly_ctx_clear(ctx);
flint_rand_clear(state);
return 0;
}deg_y a = 8, deg_x a = 8 deg_x res = 128 (bound 128), equal: 1
Use in FLINT#
nmod_mpoly_resultantuses the algorithm for polynomials in exactly two variables with positive degrees in the eliminated variable, after converting to dense bivariate form (nmod_mpoly_get_bpoly), when the dense boxes are not too large (at most 2^{32} entries and points, and not more than 64 times the number of terms beyond 2^{26} entries), the inputs are not tiny, andn_bpoly_mod_resultant_cutoffpredicts a gain: (n_A + 1)(n_B + 1) \ge 36, or \ge 16 with at least 4096 points. Otherwise, or if \mathbb{F}_p is too small (Algorithm 1 fails), it uses the subresultant algorithm of Ducos [Duc2000] on the univariate forms (nmod_mpoly_univar_resultant).n_bpoly_mod_resultantand_n_bpoly_mod_resultantimplement Algorithm 1 onn_bpoly_t.fmpz_mpoly_resultantuses_n_bpoly_mod_resultantmodulo many primes and combines the results by the Chinese remainder theorem (see fmpz_mpoly.h).gr_poly_resultant_multipoint, for polynomials over \mathbb{F}_p[x] in the generic rings framework, passes its arguments to_n_bpoly_mod_resultant(the memory layouts ofgr_polyovernmodand ofn_bpolycoincide).
int nmod_mpoly_resultant(nmod_mpoly_t R, const nmod_mpoly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx)int n_bpoly_mod_resultant(n_poly_t res, const n_bpoly_t A, const n_bpoly_t B, nmod_t mod)int n_bpoly_mod_resultant_cutoff(slong lenA, slong lenB, slong npoints)Referenced from#
- Multivariate polynomials: representations and algorithms (overview)
- Polynomial GCDs and resultants (overview)
fmpz_mpoly_resultantfmpz_bpoly_resultant,_fmpz_bpoly_resultant_gr_poly_resultant_multipoint,gr_poly_resultant_multipoint,_gr_poly_resultant_modular,gr_poly_resultant_modular- nmod_mpoly.h (module)
nmod_mpoly_resultantn_bpoly_mod_resultant,_n_bpoly_mod_resultant,n_bpoly_mod_resultant_cutoff
References#
- [GG2003] J. von zur Gathen and J. Gerhard, Modern Computer Algebra, second edition, Cambridge University Press (2003)
- [BS2005] A. Bostan and É. Schost. Polynomial evaluation and interpolation on special sets of points. Journal of Complexity 21 (2005), 420–446.
- [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, “Bivariate resultants by evaluation and interpolation,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/multivariate/modp-bivariate-resultant.html (generated 2026-10-20).
@misc{flint-doc-algorithms-multivariate-modp-bivariate-resultant,
author = {{The FLINT team}},
title = {{Bivariate resultants by evaluation and interpolation}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/multivariate/modp-bivariate-resultant.html},
note = {Generated 2026-10-20}
}