Bivariate resultants by evaluation and interpolation
- Cost
- operations in for points, where are the degrees in the eliminated variable and those in the other one.
Let have degrees and in and degrees , in . Their resultant with respect to is the determinant of the Sylvester matrix, a polynomial . The subresultant algorithm computes it by pseudo-remainder sequences in , whose intermediate coefficients have growing degree in . When is large enough, it is faster to evaluate at many points, compute univariate resultants over , 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 is an FFT prime.
Degree bound and specialisation#
Lemma 1 (Degree bound). .
Proof. The Sylvester matrix has rows of coefficients of (polynomials in of degree at most ) and rows of coefficients of (degree at most ). Every term of the expansion of the determinant is a product of one entry from each row.
Hence is determined by its values at distinct points. The value at must be computed from the specialisations and , whose degrees may be lower than and when is a root of a leading coefficient.
Lemma 2 (Specialisation). Let , , , and , the leading coefficients of and in .
- If , then .
- If and , then .
- If both degrees drop, .
Here is the resultant of and with respect to their actual degrees, and is 0 if or is zero.
Proof. Evaluation commutes with the determinant, so is the determinant of the Sylvester matrix of and built with the formal degrees and . In case 1, the leading coefficients of in that matrix are zero, and expanding along the first columns, each of which then has the single nonzero entry , gives the formula. Case 2 follows from case 1 applied to , with the sign of the exchange for the actual degrees. In case 3, the first column of the matrix contains only .
Algorithm#
Input: with and a prime . Output: , or failure if is too small.
- Set .
- Choose distinct points: if FLINT has
fft_smalland is divisible by (an FFT prime), the powers of a primitive -th root of unity ; otherwise a geometric progression with of order at least , where is the first of that works. If , no such exists: fail. - Evaluate each of the coefficients of and (as polynomials in ) 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 from its values, by an inverse FFT or geometric interpolation.
The evaluation of one coefficient of length at most at points of a geometric progression costs operations, so step 3 costs , step 5 costs , and step 4 costs univariate resultants of degree , each with the half-gcd algorithm (Half-GCD) or with Euclid's algorithm for small degrees. In the FFT case the points are split into cosets of the -th roots of unity, each evaluated by a substitution and one transform of length ; 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 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 ; 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 single-word exponents and 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 entries and points, and not more than 64 times the number of terms beyond entries), the inputs are not tiny, andn_bpoly_mod_resultant_cutoffpredicts a gain: , or with at least 4096 points. Otherwise, or if 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 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-11-02).
@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-11-02}
}