FLINT3.7.0-dev
Module · 34 functions

fmpz_mod_poly_factor.h

#include <flint/fmpz_mod_poly_factor.h>

This module factors polynomials over the prime field \mathbb{F}_p represented as fmpz_mod_poly_t (for primes of any size), tests them for irreducibility and squarefreeness, and finds their roots, over \mathbb{F}_p and also over \mathbb{Z}/n\mathbb{Z} for composite n with known factorisation. It mirrors nmod_poly_factor, and as there, the factorisation, irreducibility and root-finding functions are wrappers around the generic finite-field code of gr_poly (gr_poly_factor_finite_field, gr_poly_is_irreducible, gr_poly_roots_finite_field). For moduli below 2^{\mathtt{FLINT\_BITS}}, nmod_poly_factor is faster.

A complete factorisation consists of a squarefree factorisation and, for each squarefree part, the Kaltofen–Shoup algorithm (baby-step giant-step distinct-degree factorisation with modular composition, and equal-degree splitting), except for polynomials of very small degree, where the Cantor–Zassenhaus algorithm is used; see Factoring polynomials over a prime field for the rule.

Types and conventions#

A polynomial in factored form. The structure has the fields poly (an array of alloc polynomials, of which the first num are used), exp (an array of alloc exponents of type slong), num and alloc. Entry i for 0 \le i < \mathit{num} stands for \mathtt{poly[i]}^{\mathtt{exp[i]}}. An fmpz_mod_poly_factor_t is an array of one fmpz_mod_poly_factor_struct, so it is passed by reference.

Memory management#

Initialises fac as the empty factorisation, without allocating memory.

Frees the memory used by fac, including all allocated polynomials.

Changes the space of fac to exactly alloc factors. For alloc = 0 the factorisation is cleared and reinitialised as empty. If alloc is smaller than the number of factors, the factors beyond the first alloc are discarded.

Ensures that fac has space for at least len factors. If it has to grow, it grows to at least twice its previous allocation.

Basic manipulation#

Sets res to a copy of fac.

Set the output to the factor of index i, 0 \le i < \mathit{num}. The exponent is exp[i]. fmpz_mod_poly_factor_get_fmpz_mod_poly is an older name, with a non-const factorisation argument.

Multiplies the factorisation by \mathit{poly}^{\mathit{exp}}: if poly is equal to one of the factors, exp is added to its exponent, otherwise a copy of poly is appended with exponent exp. Constant polynomials are ignored. The search is linear in the number of factors.

Multiplies res by the factorisation fac, by inserting each factor of fac with fmpz_mod_poly_factor_insert. res and fac must be distinct objects.

Multiplies every exponent of fac by exp, which raises the factored polynomial to the power exp.

Input and output#

void fmpz_mod_poly_factor_print_pretty(const fmpz_mod_poly_factor_t fac, const char * var, const fmpz_mod_ctx_t ctx)

Print the factors to standard output, one per line, as the polynomial followed by ^ and the exponent, in the formats of fmpz_mod_poly_print and of fmpz_mod_poly_print_pretty with the variable name var.

Factorisation#

Sets res to the factorisation of f into monic irreducible polynomials, with multiplicities. The leading coefficient of f is not returned. A constant f gives the empty factorisation.

More

The following example factors x^{15} - 1 modulo the Mersenne prime p = 2^{127} - 1. Since p \equiv 7 \pmod{15}, the multiplicative order of p modulo 15 is 4, so the cyclotomic factor \Phi_{15} of degree 8 splits into two factors of degree 4, \Phi_5 stays irreducible (the order of p modulo 5 is 4) and \Phi_3 splits into two linear factors, which with x - 1 gives three roots. The factors are not sorted by degree, so the example sorts the degrees before printing them.

Examplefmpz_mod_poly_factor_cyclotomic.cchecked by make checkdoc
#include <stdlib.h>
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_mod.h>
#include <flint/fmpz_mod_poly.h>
#include <flint/fmpz_mod_poly_factor.h>

static int cmp(const void * a, const void * b)
{
    slong x = *(const slong *) a, y = *(const slong *) b;
    return (x > y) - (x < y);
}

int main(void)
{
    fmpz_t p;
    fmpz_mod_ctx_t ctx;
    fmpz_mod_poly_t f;
    fmpz_mod_poly_factor_t fac;
    slong i, deg[16];

    fmpz_init(p);
    fmpz_ui_pow_ui(p, 2, 127);
    fmpz_sub_ui(p, p, 1);                     /* p = 2^127 - 1 = 7 mod 15 */
    fmpz_mod_ctx_init(ctx, p);
    fmpz_mod_poly_init(f, ctx);
    fmpz_mod_poly_factor_init(fac, ctx);

    fmpz_mod_poly_set_coeff_ui(f, 15, 1, ctx);
    fmpz_mod_poly_set_coeff_si(f, 0, -1, ctx);      /* x^15 - 1 */

    fmpz_mod_poly_factor(fac, f, ctx);
    for (i = 0; i < fac->num; i++)
        deg[i] = fmpz_mod_poly_degree(fac->poly + i, ctx);
    qsort(deg, fac->num, sizeof(slong), cmp);
    flint_printf("degrees of the factors:");
    for (i = 0; i < fac->num; i++)
        flint_printf(" %wd", deg[i]);
    flint_printf("\n");

    fmpz_mod_poly_roots(fac, f, 0, ctx);
    flint_printf("number of roots: %wd\n", fac->num);

    fmpz_mod_poly_factor_clear(fac, ctx);
    fmpz_mod_poly_clear(f, ctx);
    fmpz_mod_ctx_clear(ctx);
    fmpz_clear(p);
    return 0;
}
Output
degrees of the factors: 1 1 1 4 4 4
number of roots: 3

Like fmpz_mod_poly_factor, but split the squarefree factors with the Cantor–Zassenhaus algorithm, Berlekamp's algorithm or the Kaltofen–Shoup algorithm respectively (deflation is still applied). The output is overwritten.

Sets res to the squarefree factorisation of f: monic squarefree polynomials g_i, pairwise coprime and with distinct exponents e_i, such that f = c \prod_i g_i^{e_i} with c the leading coefficient of f. A constant f gives the empty factorisation. This is gr_poly_factor_squarefree; see Squarefree factorisation.

Distinct-degree factorisation of a squarefree polynomial poly of degree at least 1, which need not be monic. Appends to res monic polynomials f_1, \ldots, f_k, each with exponent 1, such that f_j is the product of all monic irreducible factors of poly of one degree d_j, and writes d_j to (*degs)[j - 1]. The array *degs must have room for \deg(\mathit{poly}) entries; the d_j are distinct but not sorted. If poly is not squarefree the output is meaningless.

More

Equal-degree factorisation: pol must be squarefree and a product of irreducible polynomials of degree d, and d must divide \deg(\mathit{pol}). Appends the monic irreducible factors of pol, each with exponent 1, to factors. This is gr_poly_factor_equal_deg; see Equal-degree factorisation. An exception is raised if d does not divide the degree.

Irreducibility and squarefreeness#

Returns whether f is irreducible over \mathbb{F}_p. As a special case, constant polynomials, including zero, are considered irreducible. This is gr_poly_is_irreducible, which uses the distinct-degree test for degree below 600 and a filter for small factors followed by Rabin's test for larger degrees; see Irreducibility testing over finite fields.

Return whether f is irreducible, using the distinct-degree test (gr_poly_is_irreducible_ddf) or Rabin's test with the Frobenius powers computed by modular composition (gr_poly_is_irreducible_rabin). Constants are considered irreducible.

Rabin's irreducibility test for a possibly composite modulus n: either sets fac to 1 and returns whether f is irreducible (when n is prime), or sets fac to a nontrivial factor of n, met as a non-invertible leading coefficient, and returns an unspecified value.

More
int _fmpz_mod_poly_is_squarefree(const fmpz * f, slong len, const fmpz_mod_ctx_t ctx)

Return whether f (given as (f, len) in the underscore version, with any \mathit{len} \ge 0) is squarefree, by testing whether \gcd(f, f') = 1 (gr_poly_is_squarefree). Nonzero constants are squarefree; as a special case, the zero polynomial is not.

int _fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz * f, slong len, const fmpz_mod_ctx_t ctx)

Squarefreeness test for a possibly composite modulus n: either sets fac to 1 and returns whether f is squarefree, or sets fac to a nontrivial factor of n and returns 0.

Roots#

void fmpz_mod_poly_roots(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_mod_ctx_t ctx)

Sets r to the linear factors x - a for the distinct roots a \in \mathbb{F}_p of the nonzero polynomial f. If with_multiplicity is nonzero, the exponent of x - a is the multiplicity of a as a root of f, otherwise it is 1. The modulus must be prime. A zero f causes an exception. This is gr_poly_roots_finite_field; see Roots of polynomials over finite fields.

int fmpz_mod_poly_roots_factored(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_factor_t n, const fmpz_mod_ctx_t ctx)

Set the output to the linear factors x - a for the distinct roots a \in \mathbb{Z}/n\mathbb{Z} of the nonzero polynomial f, where the fmpz_factor_t holds the prime factorisation of the modulus n (not checked). If the multiplicity flag is nonzero, the exponent of x - a is the largest e such that (x - a)^e divides f in (\mathbb{Z}/n\mathbb{Z})[x], otherwise it is 1. Return 1 on success and 0 if the roots were not computed because there are too many of them. A zero f causes an exception.

More
Cite this page

The FLINT team, “fmpz_mod_poly_factor.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz_mod_poly_factor/index.html (generated 2026-10-20).