FLINT3.7.0-dev
Algorithm

Division, exact division and square roots

Cost
Heap division O(ℓBℓQlog⁡ℓB)O(\ell_B \ell_Q \log \ell_B) monomial comparisons and ℓBℓQ\ell_B \ell_Q coefficient multiplications for a quotient with ℓQ\ell_Q terms, O(ℓB)O(\ell_B) extra memory; heap square root O(ℓQ2log⁡ℓQ)O(\ell_Q^2 \log \ell_Q).

Division in R[x0,…,xn−1]R[x_0, \ldots, x_{n-1}] is defined with respect to the monomial ordering of the context (Monomial orderings). Its main uses in FLINT are exact division, to compute A/BA/B when BB divides AA or to decide whether it does, which is needed throughout the GCD and factoring code; and division with remainder, which is the reduction step of Gröbner basis computations [Buc1965; CLO2015]. The heap algorithms of Monagan and Pearce [MonPea2007; MonPea2011] compute the quotient term by term, in the time of the multiplication QBQB, without forming intermediate remainders.

Division with remainder#

Over a field KK, division of AA by B≠0B \ne 0 produces QQ and RR with A=QB+RA = QB + R and no term of RR divisible by lm⁡(B)\operatorname{lm}(B):

Algorithm 1: Division with remainder

Input: A,B∈K[x]A, B \in K[x], B≠0B \ne 0. Output: Q,RQ, R with A=QB+RA = QB + R, no monomial of RR divisible by lm⁡(B)\operatorname{lm}(B).

  1. Set Q=R=0Q = R = 0 and P=AP = A.
  2. While P≠0P \ne 0: let cxμ=lt⁡(P)c x^\mu = \operatorname{lt}(P). If lm⁡(B)\operatorname{lm}(B) divides xμx^\mu, set t=(c/lc⁡(B)) xμ/lm⁡(B)t = (c/\operatorname{lc}(B)) \, x^\mu / \operatorname{lm}(B), Q←Q+tQ \gets Q + t and P←P−tBP \gets P - tB; otherwise R←R+cxμR \gets R + c x^\mu and P←P−cxμP \gets P - c x^\mu.

Each step removes the leading term of PP and adds only smaller ones, so the algorithm terminates because the ordering is a well-order, and A=QB+R+PA = QB + R + P is invariant. Quotient and remainder are unique [CLO2015, §2.3]. With several divisors B0,…,Bk−1B_0, \ldots, B_{k-1} (*_divrem_ideal) the first BiB_i whose leading monomial divides xμx^\mu is used; the remainder then depends on the order of the BiB_i unless they form a Gröbner basis.

Over Z\mathbb{Z} the quotient c/lc⁡(B)c/\operatorname{lc}(B) is generally not an integer. FLINT offers two variants, described with examples on Division:

  • fmpz_mpoly_divrem uses the floor division c=qlc⁡(B)+rc = q \operatorname{lc}(B) + r, takes qq as quotient coefficient and moves rxμr x^\mu to the remainder;
  • fmpz_mpoly_quasidivrem keeps a scale ss and, when lc⁡(B)∤c\operatorname{lc}(B) \nmid c, multiplies PP, QQ, RR and ss by u=∣lc⁡(B)∣/gcd⁡(c,lc⁡(B))u = |\operatorname{lc}(B)| / \gcd(c, \operatorname{lc}(B)) before continuing.

Lemma 1 (Quasi-division). fmpz_mpoly_quasidivrem returns s>0s > 0, QQ and RR with sA=QB+RsA = QB + R and no monomial of RR divisible by lm⁡(B)\operatorname{lm}(B); ss divides ∣lc⁡(B)∣m|\operatorname{lc}(B)|^{m}, where mm is the number of terms of QQ. Over Q\mathbb{Q}, Q/sQ/s and R/sR/s are the quotient and remainder of Algorithm 1.

Proof. The invariant sA=QB+R+PsA = QB + R + P holds initially and is preserved by the scaling (all four quantities are multiplied by uu) and by the steps of Algorithm 1, which after scaling divide exactly. A scaling happens at most once per quotient term and multiplies ss by a divisor of ∣lc⁡(B)∣|\operatorname{lc}(B)|. Dividing sA=QB+RsA = QB + R by ss gives a decomposition with the property of the remainder, which is unique.

Heap division#

In Algorithm 1, P=A−QkBP = A - Q_k B after kk quotient terms q0,…,qk−1q_0, \ldots, q_{k-1}. Its leading term is all that is needed, so instead of storing PP, the algorithm merges the terms of AA with the products −qjbi-q_j b_i, i≥1i \ge 1, in a heap ordered by monomial, exactly like the heap multiplication of Algorithm 1 of Sparse and dense multiplication applied to (B−lt⁡(B))×Q(B - \operatorname{lt}(B)) \times Q while QQ is still being computed. (The products qjb0q_j b_0 cancel the leading terms by construction and are never formed.)

Algorithm 2: Heap division

Input: AA, BB with ℓA\ell_A, ℓB\ell_B terms. Output: QQ and RR as in Algorithm 1.

  1. Put the first term of AA into the heap.
  2. While the heap is not empty: pop all entries with the largest monomial xμx^\mu and add their coefficients (aa for a term of AA, −biqj-b_i q_j for a product) into an accumulator cc; reinsert successors (the next term of AA; the products (i+1,j)(i + 1, j) and (i,j+1)(i, j + 1) by the rule of the multiplication heap).
  3. If c≠0c \ne 0: if lm⁡(B)∣xμ\operatorname{lm}(B) \mid x^\mu, the next quotient term is qk=(c/lc⁡(B)) xμ/lm⁡(B)q_k = (c / \operatorname{lc}(B)) \, x^{\mu} / \operatorname{lm}(B), and the product (1,k)(1, k) becomes available; otherwise cxμc x^\mu is a term of RR.

The product (1,k)(1, k) for a new quotient term must be inserted only when the row of qkq_k is allowed to start; Monagan and Pearce keep a counter ss of rows waiting for the newest quotient term and insert it lazily, which keeps the invariant of Lemma 1 of Sparse and dense multiplication and the bound on the heap size.

Theorem 2 (Heap division). Algorithm 2 computes QQ and RR using at most ℓA+(ℓB−1)ℓQ\ell_A + (\ell_B - 1)\ell_Q heap insertions on a heap with at most ℓB\ell_B entries, hence O((ℓA+ℓBℓQ)log⁡ℓB)O((\ell_A + \ell_B \ell_Q) \log \ell_B) monomial comparisons, and O(ℓB)O(\ell_B) memory besides AA, QQ and RR.

Proof. The terms entering the heap are the terms of AA, one at a time, and the products biqjb_i q_j, i≥1i \ge 1; the latter are in rows indexed by ii, each with at most one entry in the heap as in the multiplication. The monomial popped is the leading monomial of P=A−QkB−RkP = A - Q_kB - R_k, so the steps coincide with those of Algorithm 1.

This divisor heap is the variant of [MonPea2011] suited to divisors with few terms, the common case in exact division (ℓB≤ℓQ\ell_B \le \ell_Q for most GCD and factoring applications). Coefficients are accumulated in three words when the sizes permit, as in multiplication.

Exact division#

When BB is expected to divide AA, the remainder is not wanted and the division can stop at the first sign of inexactness.

Lemma 3 (Early termination). If BB divides AA with quotient QQ, then in Algorithm 2:

  1. every leading monomial xμx^\mu of PP is divisible by lm⁡(B)\operatorname{lm}(B), and every accumulated coefficient is divisible by lc⁡(B)\operatorname{lc}(B);
  2. every such xμx^\mu is at least the last monomial of AA;
  3. the monomials of QQ fit in the exponent fields of AA;
  4. deg⁡xiB≤deg⁡xiA\deg_{x_i} B \le \deg_{x_i} A for each ii.

Proof. If B∣AB \mid A, the remainder is zero, so no term goes to RR, which is (1). If xμ=lm⁡(B)xνx^\mu = \operatorname{lm}(B) x^\nu with xνx^\nu a monomial of QQ, then xμ≥tm⁡(B)xν≥tm⁡(B)tm⁡(Q)=tm⁡(A)x^\mu \ge \operatorname{tm}(B) x^\nu \ge \operatorname{tm}(B) \operatorname{tm}(Q) = \operatorname{tm}(A), where tm is the last (trailing) monomial, which is (2). Every monomial of QQ divides a monomial of A=QBA = QB in the sense that deg⁡xiQ≤deg⁡xiA\deg_{x_i} Q \le \deg_{x_i} A (degrees add in an integral domain), which gives (3) and (4).

fmpz_mpoly_divides tests (4) before starting, computes in the packing width of AA and returns 0 as soon as one of (1)–(3) fails, using the packed divisibility test for (1) and the overflow test for (3). Since in typical uses most trial divisions that fail do so on the first few terms, this is much faster than computing a remainder. fmpz_mpoly_divexact assumes divisibility.

Parallel exact division#

Monagan and Pearce [MonPea2010] parallelise exact division although the quotient terms are produced sequentially: worker threads compute the products biqjb_i q_j for ranges of the terms of AA (cut at monomials chosen with mpoly_divides_select_exps) as soon as the quotient terms they need exist, and subtract them from their range; the thread owning the current leading range divides and publishes new quotient terms. FLINT uses this in fmpz_mpoly_divides_heap_threaded (and the nmod_mpoly analogue) when AA has more than 1024 terms, threads are available, and the platform has a strongly ordered memory model (FLINT_KNOW_STRONG_ORDER), which the lock-free publication of quotient terms requires.

Dense array division#

fmpz_mpoly_divides_array and fmpz_mpoly_divrem_array run Algorithm 1 on a dense array of coefficients indexed by the exponents, in lex or degree slices as for array multiplication. They are not selected automatically by fmpz_mpoly_divides and fmpz_mpoly_divrem.

Square roots#

If A=Q2A = Q^2 with Q=∑jqjxνjQ = \sum_{j} q_j x^{\nu_j} sorted, then lt⁡(A)=q02x2ν0\operatorname{lt}(A) = q_0^2 x^{2\nu_0}, and for k≥1k \ge 1 the coefficient of xν0+νkx^{\nu_0 + \nu_k} in A−(q0xν0+⋯+qk−1xνk−1)2A - (q_0 x^{\nu_0} + \cdots + q_{k-1} x^{\nu_{k-1}})^2 is 2q0qk2 q_0 q_k, its leading term. So the terms of QQ can be computed one by one like the quotient terms of a division by 2q0xν02 q_0 x^{\nu_0}, with a heap supplying the products 2qiqj2 q_i q_j, 0<i<j0 < i < j, of the partial square root. FLINT's fmpz_mpoly_sqrt_heap and nmod_mpoly_sqrt_heap do this, accumulating the cross products once and doubling.

A polynomial that is not a square is usually recognised quickly:

Lemma 4 (Certificates of non-squareness). Let A∈Z[x]A \in \mathbb{Z}[x] be nonzero. AA is not a square in Z[x]\mathbb{Z}[x] if one of the following holds:

  1. some deg⁡xiA\deg_{x_i} A, or for a degree ordering the total degree of AA, is odd;
  2. lc⁡(A)\operatorname{lc}(A) is not a square, or lm⁡(A)\operatorname{lm}(A) is not a square monomial;
  3. in the computation above, a monomial xμx^\mu of the remainder is not divisible by xν0x^{\nu_0}, the coefficient is not divisible by 2q02q_0, or xμx^\mu is smaller than xν0⋅tm⁡(A)x^{\nu_0} \cdot \sqrt{\operatorname{tm}(A)};
  4. there are a prime pp and α∈Fpn\alpha \in \mathbb{F}_p^n with A(α) mod pA(\alpha) \bmod p a quadratic non-residue, that is, with Jacobi symbol (A(α)p)=−1\bigl(\frac{A(\alpha)}{p}\bigr) = -1.

Proof. Degrees, leading terms and trailing terms of Q2Q^2 are twice, squares of, and squares of those of QQ, in an integral domain. (3) is (1) and (2) of Lemma 3 for the division by 2q0xν02 q_0 x^{\nu_0}. For (4), A=Q2A = Q^2 implies A(α)=Q(α)2A(\alpha) = Q(\alpha)^2 in Fp\mathbb{F}_p.

mpoly_is_proved_not_square implements (1); fmpz_mpoly_sqrt_heap checks (2) and (3) as it goes and, when the partial square root becomes longer than AA, tries (4) at a few random points modulo word-size primes before continuing. fmpz_mpoly_is_square returns as soon as the square root is determined.

Generic and specialised implementations#

The generic versions in gr_mpoly work for any coefficient ring: gr_mpoly_divides (with a direct method for monomial divisors, and gr_mpoly_divides_heap or gr_mpoly_divides_heap_threaded in integral domains), gr_mpoly_divrem_heap and gr_mpoly_divrem_ideal for division with remainder (typically over fields), gr_mpoly_quasidivrem_heap and gr_mpoly_quasidivrem_ideal_heap for pseudo-division, and the weak variants gr_mpoly_divrem_weak and gr_mpoly_divrem_ideal_weak, which divide coefficients with remainder when an exact division is impossible, like fmpz_mpoly_divrem over Z\mathbb{Z}. The specialised modules implement the same algorithms with packed coefficient accumulation:

Referenced from#

References#

  • [Buc1965] B. Buchberger. Ein Algorithmus zum Auffinden der Basiselemente des Restklassenringes nach einem nulldimensionalen Polynomideal. PhD thesis, University of Innsbruck, 1965.
  • [CLO2015] D. Cox, J. Little and D. O'Shea. Ideals, Varieties, and Algorithms, fourth edition. Undergraduate Texts in Mathematics, Springer, 2015. https://doi.org/10.1007/978-3-319-16721-3
  • [MonPea2007] M. Monagan and R. Pearce. Polynomial division using dynamic arrays, heaps, and packed exponent vectors. Computer Algebra in Scientific Computing (CASC 2007), Lecture Notes in Computer Science 4770, Springer, 2007, 295–315. https://doi.org/10.1007/978-3-540-75187-8_23
  • [MonPea2011] M. Monagan and R. Pearce. Sparse polynomial division using a heap. Journal of Symbolic Computation 46:7 (2011), 807–822. https://doi.org/10.1016/j.jsc.2010.08.014
  • [MonPea2010] M. Monagan and R. Pearce. Parallel sparse polynomial division using heaps. Proceedings of PASCO 2010, ACM, 105–111. https://doi.org/10.1145/1837210.1837227
Cite this page

The FLINT team, “Division, exact division and square roots,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/multivariate/division.html (generated 2026-11-02).