Roots and squarefree factorisation
#include <flint/ca_poly.h>int ca_poly_factor_squarefree(ca_t c, ca_poly_vec_t fac, ulong * exp, const ca_poly_t F, ca_ctx_t ctx)sourceComputes the squarefree factorisation , where the are monic, squarefree, pairwise coprime and nonconstant and . Sets c to the leading coefficient, fac to the vector of the and the first entries of exp to the , and returns 1. Returns 0 if F is not proper or if a GCD computation fails. The array exp must have room for entries.
Sets res to the monic squarefree part of poly and returns 1, or returns 0 if a GCD computation fails.
void _ca_poly_set_roots(ca_ptr poly, ca_srcptr roots, const ulong * exp, slong len, ca_ctx_t ctx)sourceSets poly to the monic polynomial with the roots in roots (of length len, or the length of the vector) and the multiplicities in exp. The product is computed by binary splitting. The underscore version writes coefficients.
Attempts to compute all complex roots of poly. On success, returns 1, sets roots to the distinct roots in no particular order and exp to their multiplicities. Returns 0 on failure, leaving the outputs unspecified. See Roots and squarefree factorisation.
The non-underscore version computes the squarefree factorisation and then the roots of each factor; exp must have room for entries. The underscore version assumes a squarefree polynomial, which is not checked, and writes roots. Roots of factors with rational coefficients are computed as algebraic numbers with qqbar_roots_fmpz_poly; other factors are solved by the formulas for degree 1, 2 and 3. The computation fails if the leading coefficient is not proved nonzero, if the squarefree factorisation fails, or if a factor of degree 4 or higher has non-rational coefficients.
ca_poly_roots computes the roots of a polynomial with exact coefficients, as exact numbers, together with their multiplicities. This is possible only when the roots can be expressed in the forms that ca_t supports, and the function says when it fails rather than returning approximations. ca_mat_eigenvalues is built on it.
Method#
The polynomial must have a leading coefficient that is proved nonzero. ca_poly_roots first computes the squarefree factorisation with ca_poly_factor_squarefree, which implements Yun's algorithm [Yun1976]: with , the polynomials and are updated by , , , and the successive are the squarefree factors of multiplicity . Every GCD needs zero tests of leading coefficients (see ca_poly_gcd), so this step can fail. Each squarefree factor is then solved:
- after removing the factor if the constant terms are proved zero, a factor of degree 1 gives its root by a division;
- a factor whose coefficients are all rational is solved exactly over with
qqbar_roots_fmpz_poly, which factors it over and isolates the roots of each irreducible factor (see Roots of polynomials and eigenvalues); the roots becomeca_tnumbers withca_set_qqbar, so they are elements of number fields generated by them; - other factors of degree 2 and 3 are solved by the quadratic and cubic formulas, which introduce square roots, cube roots and the root of unity ;
- other factors of degree 4 or higher make the computation fail.
The roots are returned in no particular order. To build a polynomial from given roots, use ca_poly_set_roots, which multiplies the linear factors by binary splitting.
Example#
The roots of are found with their multiplicities. The quintic , which is not solvable by radicals, still has exact roots since its coefficients are rational: they are algebraic numbers of degree 5. The polynomial cannot be solved.
#include <flint/ca_poly.h>
int main(void)
{
ca_ctx_t ctx;
ca_poly_t f, g;
ca_vec_t roots;
ca_t c;
ulong exp[5];
slong i;
ca_ctx_init(ctx);
ca_poly_init(f, ctx);
ca_poly_init(g, ctx);
ca_vec_init(roots, 0, ctx);
ca_init(c, ctx);
/* f = (x^2 + 1)^2 (x - pi) */
ca_poly_x(f, ctx);
ca_poly_mul(f, f, f, ctx);
ca_one(c, ctx);
ca_poly_set_coeff_ca(f, 0, c, ctx);
ca_poly_mul(f, f, f, ctx);
ca_poly_x(g, ctx);
ca_pi(c, ctx);
ca_neg(c, c, ctx);
ca_poly_set_coeff_ca(g, 0, c, ctx);
ca_poly_mul(f, f, g, ctx);
if (ca_poly_roots(roots, exp, f, ctx))
{
for (i = 0; i < ca_vec_length(roots, ctx); i++)
{
flint_printf("multiplicity %wu: ", exp[i]);
ca_print(ca_vec_entry(roots, i), ctx);
flint_printf("\n");
}
}
/* x^5 - x - 1 has a nonsolvable Galois group, but rational coefficients */
ca_poly_zero(g, ctx);
ca_one(c, ctx);
ca_poly_set_coeff_ca(g, 5, c, ctx);
ca_neg_one(c, ctx);
ca_poly_set_coeff_ca(g, 1, c, ctx);
ca_poly_set_coeff_ca(g, 0, c, ctx);
flint_printf("x^5 - x - 1: %d\n", ca_poly_roots(roots, exp, g, ctx));
ca_printn(ca_vec_entry(roots, 0), 10, ctx); flint_printf("\n");
/* x^4 - pi has no exact roots that ca_poly_roots can find */
ca_pi(c, ctx);
ca_neg(c, c, ctx);
ca_poly_zero(g, ctx);
ca_poly_set_coeff_ca(g, 0, c, ctx);
ca_one(c, ctx);
ca_poly_set_coeff_ca(g, 4, c, ctx);
flint_printf("x^4 - pi: %d\n", ca_poly_roots(roots, exp, g, ctx));
ca_poly_clear(f, ctx);
ca_poly_clear(g, ctx);
ca_vec_clear(roots, ctx);
ca_clear(c, ctx);
ca_ctx_clear(ctx);
return 0;
}multiplicity 1: 3.14159 {a where a = 3.14159 [Pi]}
multiplicity 2: 1.00000*I {a where a = I [a^2+1=0]}
multiplicity 2: -1.00000*I {-a where a = I [a^2+1=0]}
x^5 - x - 1: 1
1.167303978
x^4 - pi: 0Guides#
- Using ca (
ca)
References#
- [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
The FLINT team, “Roots and squarefree factorisation (ca_poly.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/ca_poly/roots.html (generated 2026-11-02).
@misc{flint-doc-ca-poly-roots,
author = {{The FLINT team}},
title = {{Roots and squarefree factorisation (ca\_poly.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/ca_poly/roots.html},
note = {Generated 2026-11-02}
}