Factoring polynomials over the integers
- Cost
- Zassenhaus recombination tries up to subsets of the modular factors; van Hoeij's algorithm with gradual feeding runs in time polynomial in the degree and the coefficient size, and in practice its cost is dominated by the modular factorisation and the Hensel lifting.
Factoring a polynomial means writing it as with and distinct primitive irreducible of positive degree. By Gauss' lemma this is the same as factoring over , up to the content. All practical methods follow the plan of Zassenhaus [Zas1969]: factor modulo a small prime , which is easy (Factoring polynomials over finite fields), lift the modular factorisation to one modulo a large power (Hensel lifting), and find out which products of modular factors are true factors. The last step, the recombination, is the difficult one: a polynomial with modular factors has candidate subsets. Lenstra, Lenstra and Lovász showed that factoring is possible in polynomial time [LLL1982], but their algorithm was not competitive. Van Hoeij [vHo2002] turned the recombination into a knapsack problem solved by lattice reduction, which is fast in practice and, with the refinements of Belabas, van Hoeij, Klüners and Steel [BHKS2009], van Hoeij and Novocin [vHN2010], and Hart, van Hoeij and Novocin [HvHN2011], provably polynomial. The implementation in FLINT is due to Novocin and Hart and follows [HvHN2011] and [Nov2008].
Throughout, has degree and leading coefficient , and is the Euclidean norm of its coefficient vector.
Reductions#
fmpz_poly_factor first reduces to the factorisation of squarefree primitive polynomials with nonzero constant term:
- The content is removed, with the sign of . Polynomials of degree at most 3 are handled directly: a quadratic splits if and only if its discriminant is a square, and a cubic is reducible if and only if it has a rational root, which
_fmpz_poly_factor_cubiclocates from real and 2-adic approximations of the roots (Cubics). - The factor is split off.
- If with , the polynomial of degree is factored, and the inflation of each irreducible factor of is handled separately (Deflation and Capelli's theorem).
- Otherwise
fmpz_poly_factor_squarefreecomputes the squarefree factorisation by Yun's algorithm [Yun1976] (Squarefree factorisation), with the GCDs of GCDs of polynomials over Z, and each is factored by_fmpz_poly_factor_zassenhaus.
Deflation and Capelli's theorem#
If is irreducible, need not be: is irreducible but is not. For prime exponents, Capelli's theorem decides the question [Sch2000].
Theorem 1 (Capelli). Let be irreducible, a root of , and a prime. Then is irreducible over if and only if is not a -th power in .
FLINT applies the prime case along a chain with . A witness that is not a -th power is a prime and a residue field of above in which the image of is not a -th power, which by Euler's criterion means when . _fmpz_poly_factor_inflation_is_irreducible_capelli searches for a witness with a budget linear in ; if it finds one, is irreducible, and otherwise is factored by the general algorithm at degree , which is still smaller than factoring from scratch.
Cubics#
_fmpz_poly_factor_cubic looks for rational roots instead of factoring modulo a prime, by a method from Schultz's notes [Sch-mpoly]. Let with . With ,
and a rational root of the monic is an integer. Each integer root of gives the factor of . The integer roots of are found as follows (the cases and are immediate).
- Small primes. If and are odd, has no root, so is irreducible. If has no root modulo one of the primes , is irreducible; this is tested at once by computing modulo the product of these primes, which fits in a word.
- Discriminant. Let , so that the discriminant of is . If , the roots are and the double root . If , has one real root, by Cardano's formula; it is computed with integer square and cube roots, and the three integers around the approximation are tested.
- Three real roots (, hence ). With the equation becomes , so all roots satisfy . After a test modulo the primes , the roots are computed in the 2-adic integers to a precision with , reduced to the symmetric range, and tested exactly.
For the 2-adic roots write and with odd, so that . The Newton polygon of at 2 gives three cases.
- : with , , which has no root modulo 2; has no root in , and is irreducible.
- : all roots have valuation , so if there is none in . Otherwise gives , which is modulo 2 with an irreducible quadratic factor, so there is exactly one root in , found by Hensel lifting.
: with and , , which has the simple root modulo 2. Newton iteration, doubling the precision at each step, lifts the factorisation
that is, . The roots of the quadratic have valuation . If is odd, is the only root in . If is even, the other roots are
with a 2-adic square root (an odd 2-adic integer is a square if and only if it is modulo 8). The square root loses precision, so and are lifted further when the result is not precise enough.
Once an integer root has been found, the other roots are those of , rational if and only if is a square. The method costs a bounded number of integer square and cube roots and 2-adic Newton iterations on numbers of the size of the coefficients, so it is much faster than the general algorithm for cubics with large coefficients.
The modular factorisation#
Let be squarefree and primitive with . A prime is admissible if , and is squarefree; all but finitely many primes are, since is squarefree when divides neither nor the discriminant. For an admissible prime,
with distinct monic irreducible , and every irreducible factor of in reduces to for a subset , the subsets of distinct factors being disjoint. In particular has at most irreducible factors, and it is irreducible if .
_fmpz_poly_factor_zassenhaus factors modulo the first three admissible primes, starting from 2, and keeps the one with the fewest factors, since the cost of recombination grows with . The factor degrees modulo all three primes are combined: a true factor of degree is a product of modular factors of total degree modulo each prime, so must be a subset sum of the modular degrees for all three. The zassenhaus_prune functions maintain the set of such degrees; if it contains no degree strictly between 0 and , the polynomial is irreducible, and otherwise subsets of an impossible degree are skipped during recombination. By Chebotarev's density theorem, the factor degrees modulo a random prime are the cycle lengths of a random element of the Galois group, so for a polynomial with Galois group , the typical case, is about on average.
Bounds and precision#
Recombination recovers a factor from its image modulo , which requires a bound for its coefficients.
Theorem 2 (Mignotte). If divides in , then for all
fmpz_poly_factor_mignotte computes , the maximum of this bound over with rounded up, of and of , so that every proper factor of has coefficients bounded by (the extreme coefficients of a factor divide those of ).
Lemma 3 (Recovering a factor). Let be a primitive divisor of with positive leading coefficient, let with monic , and suppose that . If , then is the primitive part of the polynomial with coefficients in that is congruent to modulo .
Proof. The polynomial has integer coefficients, because , and it is congruent to modulo , since is invertible modulo . Its coefficients are bounded by in absolute value, so it is equal to , and its primitive part is .
The Zassenhaus algorithm therefore lifts to the least with .
Zassenhaus recombination#
Input: squarefree primitive , monic with , where .
Output: the irreducible factors of .
- , , .
- While : for each with and a possible total degree, let be the primitive part of the symmetric residue of modulo ; if , output and set and . Then .
- Output if .
Theorem 4. Algorithm 1 outputs the irreducible factors of .
Proof. Every irreducible factor of corresponds to a subset of , and the subsets of distinct factors partition . A factor found for a subset divides ; if it were reducible, its irreducible factors would correspond to proper subsets of , which were tried earlier and would have been removed from . So every output is irreducible. Since , the bound applies to the factors of , and ; by Lemma 3 (with and in place of and ) the factor of with subset is found when is tried. When all subsets of size at most have been tried, is irreducible, since a reducible would have a factor with at most half of the remaining modular factors.
The number of subsets tried is at most , and each test is a trial division, made cheap by fmpz_poly_divides, which first compares the constant coefficients and the values at 1. This is fast when is small, the typical case, and hopeless when is large. FLINT uses Zassenhaus recombination for .
Van Hoeij's algorithm#
Van Hoeij's idea [vHo2002] is to represent subsets by indicator vectors and to find the vectors of the true factors as short vectors of a lattice. Let be monic with , and for let .
Logarithmic derivatives#
The map turns products into sums:
The coefficients of the logarithmic derivative (CLD) are the coefficients of the polynomials , which have degree less than and are well defined modulo , since divides there. If is a true factor of , then , and its coefficients are much smaller than : on , over the roots of , and splitting the coefficients of at index gives the bound computed by fmpz_poly_CLD_bound [HvHN2011]: with and any , the coefficient of in is at most
which is minimised numerically over . For the lowest and highest coefficients , let be the coefficient of in reduced into (_fmpz_poly_factor_CLD_mat). If is the indicator vector of a true factor , then is small. The low coefficients are computed with fmpz_poly_mullow and fmpz_poly_divlow_smodp, the high ones with fmpz_poly_mulhigh_n and fmpz_poly_divhigh_smodp, so that only coefficients of each product are needed.
The knapsack lattice#
For a set of CLD columns, let be the lattice spanned by the rows of
with each column of scaled down so that the values produced by true factors become small. The vector of a true factor then has length at most about , while a random 0-1 combination produces entries of the size of . The vectors of the true factors span a sublattice whose rank is the number of irreducible factors, and the reduced echelon basis of consists of the indicator vectors of the factors, a 0-1 basis. Lattice reduction finds a basis of a lattice of decreasing rank, by the following lemma.
Lemma 5 (Short vectors after reduction). Let be a basis of a lattice with Gram–Schmidt vectors , and suppose for all . Then every lattice vector of norm at most lies in the span of .
Proof. Write with integers and . The component of orthogonal to is , so . If , then , so .
After each LLL reduction, fmpz_lll_with_removal_ulll drops the final basis vectors whose Gram–Schmidt norm exceeds the bound (LLL with removals, with the truncation strategy Truncation: ULLL); by the lemma, survives. Each new column of CLD data can only lower the rank of , and enough columns at enough precision make [vHo2002], [HvHN2011].
Input: squarefree primitive of degree and its factorisation modulo an admissible prime into monic factors.
Output: the irreducible factors of .
- Choose an initial precision (see below) and lift the factors to precision . Set with .
- If the first columns of define a partition of , form the corresponding products; if they all divide , output them and stop.
- Compute the CLD data for low and high coefficients, leaving out coefficients whose CLD bound is too large compared to .
- For each new column, taken alternately from the low and the high end: append it to , keeping only the bits of the entries above the CLD bound (
fmpz_mat_next_col_van_hoeij); if this makes the matrix worth reducing, run LLL with removal, and go to step 2. - When the columns are used up, double (up to about ); when all coefficients have been used, double the precision , continue the Hensel lift, and go to step 2.
The test in step 2 is fmpz_poly_factor_van_hoeij_check_if_solved: it reads a partition from the echelon form of the first columns (fmpz_mat_col_partition), forms the products of the lifted factors in each part, multiplied by and reduced modulo , and checks that their primitive parts divide , first modulo 2 and then over . Since the answer is verified by division, the output is always correct; the bounds only ensure that the algorithm makes progress and terminates.
Gradual feeding, adding one column at a time, keeps each LLL call on a matrix whose new column has only a few more bits than the reduced basis, which is what makes the total work polynomial [vHN2010], [HvHN2011]. The starting precision is about the least with
where is the bit size of the smaller of the CLD bounds of the lowest and the highest coefficient, but not more than the Zassenhaus precision. This is usually far below the Mignotte bound and enough for the first few columns to determine the factorisation; otherwise the precision is doubled and the Hensel lift continued with _fmpz_poly_hensel_continue_lift. The first rounds use (or 50 for ) coefficients from each end instead of 10 when .
Complexity#
For a polynomial of degree with -bit coefficients, the Mignotte precision is bits, and the Hensel lift to that precision costs operations on integers of that size (Hensel lifting). Zassenhaus recombination adds up to trial divisions. Van Hoeij's algorithm with gradual feeding runs in time polynomial in and [HvHN2011], and usually needs much less than the Mignotte precision; the LLL work is small unless is large and there are many factors of similar degree. The classical worst cases of the Zassenhaus algorithm, such as the Swinnerton-Dyer polynomials of degree , which have factors modulo every prime, are easy: proving , of degree 128, irreducible takes about 0.1 seconds on the x86-64 machine used for this documentation.
Use in FLINT#
fmpz_poly_factorperforms the reductions of Reductions and calls_fmpz_poly_factor_zassenhauswith cutoff 8 and van Hoeij's algorithm enabled;fmpz_poly_factor_zassenhaususes only the Zassenhaus recombination._fmpz_poly_factor_zassenhauschooses the prime, lifts withfmpz_poly_hensel_lift_onceto the Mignotte precision and callsfmpz_poly_factor_zassenhaus_recombination_with_prune, or callsfmpz_poly_factor_van_hoeijwhen .fmpz_poly_factor_van_hoeijuses_fmpz_poly_hensel_start_lift,_fmpz_poly_hensel_continue_lift,_fmpz_poly_factor_CLD_mat,fmpz_mat_next_col_van_hoeij,fmpz_lll_with_removal_ulll(with and ; see Lattice reduction (LLL)) andfmpz_poly_factor_van_hoeij_check_if_solved.fmpz_poly_factor_squarefree,fmpz_poly_factor_mignotte,fmpz_poly_CLD_bound,_fmpz_poly_factor_inflation_is_irreducible_capelli,_fmpz_poly_factor_quadraticand_fmpz_poly_factor_cubicprovide the remaining steps.- Multivariate polynomials over are factored by
fmpz_mpoly_factor, which reduces to univariate factorisations of this kind (Multivariate polynomials: representations and algorithms); polynomials over number fields and finite fields have their own modules.
void fmpz_poly_factor(fmpz_poly_factor_t fac, const fmpz_poly_t G)void fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t fac, const fmpz_poly_t G)void _fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t final_fac, slong exp, const fmpz_poly_t f, slong cutoff, int use_van_hoeij)void fmpz_poly_factor_van_hoeij(fmpz_poly_factor_t final_fac, const nmod_poly_factor_t fac, const fmpz_poly_t f, slong exp, ulong p)void fmpz_poly_factor_squarefree(fmpz_poly_factor_t fac, const fmpz_poly_t F)void fmpz_poly_factor_zassenhaus_recombination_with_prune(fmpz_poly_factor_t final_fac, const fmpz_poly_factor_t lifted_fac, const fmpz_poly_t F, const fmpz_t P, slong exp, const zassenhaus_prune_t Z)int _fmpz_poly_factor_inflation_is_irreducible_capelli(const fmpz_poly_t T, ulong p)Referenced from#
- Arithmetic with algebraic numbers (algorithm)
- Algebraic numbers by minimal polynomial and isolating ball (algorithm)
- Lattice reduction (LLL) (algorithm)
- Factorisation (algorithm)
- Factoring polynomials over finite fields (algorithm)
- GCDs of polynomials over Z (algorithm)
- Hensel lifting (algorithm)
- Polynomial arithmetic over generic rings and its specialisations (overview)
- Squarefree factorisation (algorithm)
- Getting started with fmpz_poly
fmpz_poly_CLD_bound- Factoring polynomials over the integers
- fmpz_poly_factor.h (module)
_fmpz_poly_factor_quadratic,_fmpz_poly_factor_cubic
References#
- [Zas1969] H. Zassenhaus. On Hensel factorization, I. Journal of Number Theory 1 (1969), 291–311. https://doi.org/10.1016/0022-314X(69)90047-X
- [LLL1982] A. K. Lenstra, H. W. Lenstra, Jr. and L. Lovász, "Factoring polynomials with rational coefficients", Mathematische Annalen 261 (1982), 515–534. https://doi.org/10.1007/BF01457454
- [vHo2002] M. van Hoeij. Factoring polynomials and the knapsack problem. Journal of Number Theory 95 (2002), 167–189. https://doi.org/10.1006/jnth.2001.2763
- [BHKS2009] K. Belabas, M. van Hoeij, J. Klüners and A. Steel. Factoring polynomials over global fields. Journal de Théorie des Nombres de Bordeaux 21 (2009), 15–39. https://doi.org/10.5802/jtnb.655
- [vHN2010] M. van Hoeij and A. Novocin, "Gradual sub-lattice reduction and a new complexity for factoring polynomials", LATIN 2010, Lecture Notes in Computer Science 6034 (2010), 539–553. https://doi.org/10.1007/978-3-642-12200-2_47
- [HvHN2011] W. Hart, M. van Hoeij and A. Novocin. Practical polynomial factoring in polynomial time. ISSAC 2011, 163–170. https://doi.org/10.1145/1993886.1993915
- [Nov2008] A. Novocin. Factoring univariate polynomials over the rationals. PhD thesis, Florida State University, 2008.
- [Yun1976] D. Y. Y. Yun. On square-free decomposition algorithms. Proceedings of the 1976 ACM Symposium on Symbolic and Algebraic Computation (SYMSAC '76), 26–35. https://doi.org/10.1145/800205.806320
- [Sch2000] A. Schinzel. Polynomials with Special Regard to Reducibility. Cambridge University Press, 2000. https://doi.org/10.1017/CBO9780511542916
- [Sch-mpoly] D. Schultz. Algorithms for multivariate polynomials. Notes in the FLINT source tree, src/mpoly/doc/MPolyAlgorithms.tex.
- [Mig1974] M. Mignotte. An inequality about factors of polynomials. Mathematics of Computation 28 (1974), 1153–1157. https://doi.org/10.1090/S0025-5718-1974-0354624-3
- [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996
The FLINT team, “Factoring polynomials over the integers,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/polynomials/factoring-integers.html (generated 2026-11-02).
@misc{flint-doc-algorithms-polynomials-factoring-integers,
author = {{The FLINT team}},
title = {{Factoring polynomials over the integers}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/polynomials/factoring-integers.html},
note = {Generated 2026-11-02}
}