FLINT3.7.0-dev
Module · 32 functions

fq_poly_factor.h

#include <flint/fq_poly_factor.h>

This module factors polynomials over a finite field \mathbb{F}_q in the representation of fq.h into irreducible factors, tests irreducibility and squarefreeness, and finds roots. All algorithms are those of the generic module gr_poly.h, which this module wraps: squarefree factorisation, distinct-degree factorisation, equal-degree splitting, and the complete algorithms of Cantor and Zassenhaus [CanZas1981], Berlekamp [Ber1970] and Kaltofen and Shoup [KalSho1998]. The interface is generated from fq_poly_factor_templates.h and is the same for fq_nmod_poly_factor and fq_zech_poly_factor; fq_default_poly_factor provides it for any finite field.

AlgorithmFactoring polynomials over finite fieldsSquarefree, distinct-degree and equal-degree factorisation over \mathbb{F}_q; the Cantor–Zassenhaus, Berlekamp and Kaltofen–Shoup algorithms, the baby-step giant-step distinct-degree factorisation with modular composition, the trace and minimal-polynomial splittings, and how the generic implementation in gr_poly chooses between them.

Factorisation structure#

A factorisation: an array poly of alloc initialised polynomials and an array exp of exponents, of which the first num pairs are used. The factored polynomial is the product of poly[i]^exp[i] (times a leading coefficient that is returned separately). fq_poly_factor_t is an array of one structure.

Initialises fac as an empty factorisation, with room for 5 factors.

Frees the memory used by fac.

fq_poly_factor_realloc changes the allocation to alloc factors (clearing factors beyond it; alloc = 0 reinitialises fac). fq_poly_factor_fit_length ensures room for len factors, at least doubling the allocation when it grows.

Sets res to a copy of fac.

void fq_poly_factor_insert(fq_poly_factor_t fac, const fq_poly_t poly, slong exp, const fq_ctx_t ctx)

Multiplies the factorisation by poly^exp: if poly is already one of the factors, exp is added to its exponent, otherwise poly is appended with exponent exp. Constant polynomials are ignored.

Inserts all factors of fac into res with fq_poly_factor_insert.

Multiplies all exponents by exp, raising the factored polynomial to the power exp.

Sets z to the factor of index i, 0 \le i < \mathit{num}.

void fq_poly_factor_print_pretty(const fq_poly_factor_t fac, const char * var, const fq_ctx_t ctx)

Print the factors to stdout, one per line, each followed by ^ and its exponent, in the format of fq_poly_print, respectively of fq_poly_print_pretty with the variable name var.

Squarefree and irreducible polynomials#

int _fq_poly_is_squarefree(const fq_struct * f, slong len, const fq_ctx_t ctx)
int fq_poly_is_squarefree(const fq_poly_t f, const fq_ctx_t ctx)

Return whether f is squarefree, that is, not divisible by the square of a polynomial of positive degree. Polynomials of length at most 2 other than 0 are squarefree, and 0 is not. This is a wrapper of gr_poly_is_squarefree, which computes \gcd(f, f') and handles p-th powers.

Sets res to a squarefree factorisation of f: pairwise coprime monic squarefree polynomials g_i with distinct exponents e_i such that f = c \prod g_i^{e_i}, where c is the leading coefficient of f. Previous contents of res are discarded; for f of length at most 1 the factorisation is empty.

int fq_poly_is_irreducible(const fq_poly_t f, const fq_ctx_t ctx)

Return whether f is irreducible. Unlike gr_poly_is_irreducible, these functions return 1 for all polynomials of length at most 2, including constants and zero.

More

Factorisation#

void fq_poly_factor(fq_poly_factor_t result, fq_t leading_coeff, const fq_poly_t input, const fq_ctx_t ctx)

Factors input as c \prod g_i^{e_i} with distinct monic irreducible g_i: sets result to the factors and exponents (discarding previous contents) and leading_coeff to c. For the zero polynomial c = 0 and the factorisation is empty; for a constant, c is the constant.

More
void fq_poly_factor_with_cantor_zassenhaus(fq_poly_factor_t result, fq_t leading_coeff, const fq_poly_t input, const fq_ctx_t ctx)
void fq_poly_factor_with_berlekamp(fq_poly_factor_t result, fq_t leading_coeff, const fq_poly_t input, const fq_ctx_t ctx)
void fq_poly_factor_with_kaltofen_shoup(fq_poly_factor_t result, fq_t leading_coeff, const fq_poly_t input, const fq_ctx_t ctx)

As fq_poly_factor, but factoring the squarefree parts with the Cantor–Zassenhaus algorithm (distinct-degree factorisation followed by equal-degree splitting), Berlekamp's algorithm (a basis of the kernel of the Frobenius map minus the identity, followed by random splitting), or the Kaltofen–Shoup algorithm (distinct-degree factorisation with baby-step giant-step Frobenius computations by modular composition).

As the _with_ functions, without returning the leading coefficient: the output is the factorisation of the monic polynomial f / c. Previous contents of the output are discarded.

void fq_poly_factor_distinct_deg(fq_poly_factor_t res, const fq_poly_t poly, slong * const * degs, const fq_ctx_t ctx)

Distinct-degree factorisation of the squarefree polynomial poly: appends to res, with exponent 1, polynomials g_1, g_2, \ldots such that \operatorname{monic}(\mathit{poly}) = \prod g_i and each g_i is the product of all irreducible factors of degree d_i, and writes the degrees d_i to (*degs)[0], (*degs)[1], .... The caller must provide room for \deg(\mathit{poly}) entries in *degs. The result is undefined if poly is not squarefree. This is a wrapper of gr_poly_factor_distinct_deg.

void fq_poly_factor_equal_deg(fq_poly_factor_t factors, const fq_poly_t pol, slong d, const fq_ctx_t ctx)

Equal-degree factorisation: appends to factors, with exponent 1, the irreducible factors of pol, which must be a monic squarefree product of irreducible polynomials of degree d. The factors are found by random splitting (Cantor–Zassenhaus), using an internal random state.

void fq_poly_factor_split_single(fq_poly_t linfactor, const fq_poly_t input, const fq_ctx_t ctx)

Sets linfactor to one monic linear factor x - a of input, which must split into linear factors (not necessarily distinct). If input has degree 1 it is copied. Throws FLINT_ERROR if no root is found. This is the step used by fq_embed_gens to find a root of a defining polynomial in an extension field.

void fq_poly_iterated_frobenius_preinv(fq_poly_t * rop, slong n, const fq_poly_t v, const fq_poly_t vinv, const fq_ctx_t ctx)

Sets rop[i] to x^{q^i} \bmod v for 0 \le i < n, where vinv is the inverse of the reversal of v (see fq_poly_reverse and fq_poly_inv_series). The array rop must contain n initialised polynomials. If FQ_POLY_ITERATED_FROBENIUS_CUTOFF returns 1, the powers after the first are computed by modular composition with a precomputed Brent–Kung matrix (x^{q^{i}} = x^{q^{i-1}}(x^q)), otherwise by exponentiation.

Returns 1 if fq_poly_iterated_frobenius_preinv should use modular composition for a modulus of length length, which is the case if \log_2 q < 3(\lfloor \sqrt{\mathit{length}} \rfloor + 1). (FQ_NMOD_POLY_ITERATED_FROBENIUS_CUTOFF and FQ_ZECH_POLY_ITERATED_FROBENIUS_CUTOFF use 2 \log_2 q instead.)

Roots#

void fq_poly_roots(fq_poly_factor_t r, const fq_poly_t f, int with_multiplicity, const fq_ctx_t ctx)

Sets r to the roots of the nonzero polynomial f in \mathbb{F}_q, stored as the monic linear factors x - a. If with_multiplicity is nonzero, the exponents are the multiplicities of the roots; otherwise they are 1. Previous contents of r are discarded. This is a wrapper of gr_poly_roots_finite_field, which splits \gcd(f, x^q - x) by equal-degree factorisation; see Roots of polynomials over finite fields.

Example#

Factoring x^8 - 1 over \mathbb{F}_3, where it has the two roots \pm 1 and three irreducible quadratic factors, and over \mathbb{F}_{3^2}, whose multiplicative group of order 8 consists of the roots of x^8 - 1, so that the polynomial splits into linear factors:

Examplefq_poly_factor_cyclotomic.cchecked by make checkdoc
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fq.h>
#include <flint/fq_poly.h>
#include <flint/fq_poly_factor.h>

void factor_x8_minus_1(slong d)
{
    fmpz_t p;
    fq_ctx_t ctx;
    fq_poly_t f;
    fq_poly_factor_t fac;
    fq_t c;
    slong i, deg[20] = { 0 };

    fmpz_init_set_ui(p, 3);
    fq_ctx_init(ctx, p, d, "a");
    fq_poly_init(f, ctx);
    fq_poly_factor_init(fac, ctx);
    fq_init(c, ctx);

    fq_one(c, ctx);
    fq_poly_set_coeff(f, 8, c, ctx);
    fq_neg(c, c, ctx);
    fq_poly_set_coeff(f, 0, c, ctx);              /* x^8 - 1 */

    fq_poly_factor(fac, c, f, ctx);
    for (i = 0; i < fac->num; i++)
        deg[fq_poly_degree(fac->poly + i, ctx)]++;
    flint_printf("GF(3^%wd): %wd factors, of degree", d, fac->num);
    for (i = 1; i < 20; i++)
        if (deg[i] != 0)
            flint_printf(" %wd (%wd times)", i, deg[i]);
    flint_printf("\n");

    fq_poly_roots(fac, f, 1, ctx);
    flint_printf("GF(3^%wd): %wd roots\n", d, fac->num);

    fq_clear(c, ctx);
    fq_poly_factor_clear(fac, ctx);
    fq_poly_clear(f, ctx);
    fq_ctx_clear(ctx);
    fmpz_clear(p);
}

int main(void)
{
    factor_x8_minus_1(1);
    factor_x8_minus_1(2);
    return 0;
}
Output
GF(3^1): 5 factors, of degree 1 (2 times) 2 (3 times)
GF(3^1): 2 roots
GF(3^2): 8 factors, of degree 1 (8 times)
GF(3^2): 8 roots

References#

  • [CanZas1981] D. G. Cantor and H. Zassenhaus. A new algorithm for factoring polynomials over finite fields. Mathematics of Computation 36 (1981), 587–592. https://doi.org/10.1090/S0025-5718-1981-0606517-5
  • [Ber1970] E. R. Berlekamp. Factoring polynomials over large finite fields. Mathematics of Computation 24 (1970), 713–735.
  • [KalSho1998] E. Kaltofen and V. Shoup, "Subquadratic-time factoring of polynomials over finite fields", Mathematics of Computation 67 (1998), 1179-1197. https://doi.org/10.1090/S0025-5718-98-00944-2
Cite this page

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