Characteristic and minimal polynomials
#include <flint/fmpz_mat.h>void fmpz_mat_charpoly(fmpz_poly_t cp, const fmpz_mat_t mat)sourcevoid _fmpz_mat_charpoly(fmpz * cp, const fmpz_mat_t mat)sourcevoid fmpz_mat_charpoly_berkowitz(fmpz_poly_t cp, const fmpz_mat_t mat)sourcevoid _fmpz_mat_charpoly_berkowitz(fmpz * cp, const fmpz_mat_t mat)sourcevoid fmpz_mat_charpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat)sourcevoid _fmpz_mat_charpoly_modular(fmpz * cp, const fmpz_mat_t mat)sourceSets cp to the characteristic polynomial of the square matrix = mat. The underscore versions write the coefficients to cp. Only fmpz_mat_charpoly checks that the matrix is square, and throws otherwise.
fmpz_mat_charpoly_berkowitz is a wrapper of _gr_mat_charpoly_berkowitz, division-free with operations on integers. fmpz_mat_charpoly_modular computes the characteristic polynomial modulo enough 63-bit primes to exceed twice the bound of fmpz_mat_charpoly_bound, in parallel, and combines the results by the Chinese remainder theorem; the result is proven. fmpz_mat_charpoly uses explicit formulas for , Berkowitz's algorithm for and when is smaller than the bit length of the bit size of the entries, and the modular algorithm otherwise. See Characteristic and minimal polynomials.
void fmpz_mat_minpoly(fmpz_poly_t cp, const fmpz_mat_t mat)sourceslong _fmpz_mat_minpoly(fmpz * cp, const fmpz_mat_t mat)sourcevoid fmpz_mat_minpoly_modular(fmpz_poly_t cp, const fmpz_mat_t mat)sourceslong _fmpz_mat_minpoly_modular(fmpz * cp, const fmpz_mat_t mat)sourceSets cp to the minimal polynomial of the square matrix mat. The underscore versions write the coefficients to cp, which needs space for of them, and return the length. fmpz_mat_minpoly throws if mat is not square; the others assume it.
All four use the multimodular algorithm: minimal polynomials modulo 63-bit primes (nmod_mat_minpoly_with_gens) are combined by the Chinese remainder theorem until the result stabilises, primes giving a smaller degree are discarded, and the candidate is accepted when for every Krylov generator recorded modulo the primes, which proves that is the minimal polynomial. A coefficient bound from [Dum2007] caps the number of primes. See Characteristic and minimal polynomials.
fmpz_mat_charpoly computes the characteristic polynomial of a square integer matrix, and fmpz_mat_minpoly its minimal polynomial, the monic polynomial of least degree with . Both have integer coefficients, and divides . For all but tiny matrices both are computed modulo word-size primes and reconstructed by the Chinese remainder theorem; the results are always proven.
Characteristic polynomial#
fmpz_mat_charpoly chooses the method from the dimension and the bit size of the largest entry:
| Condition | Method |
|---|---|
| explicit formulas | |
| , or | fmpz_mat_charpoly_berkowitz |
| otherwise | fmpz_mat_charpoly_modular |
fmpz_mat_charpoly_berkowitz is a wrapper of the generic _gr_mat_charpoly_berkowitz, which uses additions and multiplications and no divisions (Berkowitz's algorithm); its intermediate results are coefficients of characteristic polynomials of submatrices, so their size stays controlled.
fmpz_mat_charpoly_modular computes the bound of fmpz_mat_charpoly_bound on the absolute values of the coefficients, chooses primes above , reduces modulo all of them at once with fmpz_mat_multi_mod_ui, computes the characteristic polynomials modulo the primes in parallel with nmod_mat_charpoly ( or operations each), and reconstructs the coefficients in the symmetric range with _fmpz_vec_multi_CRT_ui. Since the number of primes is fixed by the a priori bound, there is no early termination. With , about characteristic polynomials modulo primes are needed, each costing word operations, so the total is word operations, plus the multimodular reduction and reconstruction.
The bound: the coefficient of is the sum of the principal minors of , each of which is at most the product of the largest row norms (and of the largest column norms) by Hadamard's inequality.
Minimal polynomial#
fmpz_mat_minpoly and fmpz_mat_minpoly_modular compute minimal polynomials modulo primes above with nmod_mat_minpoly_with_gens, which also records which standard basis vectors were used as generators of Krylov subspaces. For each prime:
- if the degree modulo is smaller than the degree seen before, is discarded: the minimal polynomial modulo divides the reduction of , so a smaller degree identifies a bad prime;
- if it is larger, all previous primes were bad and are discarded;
- otherwise the coefficients are combined by the Chinese remainder theorem.
When the reconstruction is unchanged by a new prime, the candidate is tested: is checked exactly for every recorded generator , by matrix-vector products. The Krylov spaces of these generators span (they span ), so the test proves ; and , the degree modulo a prime, is at most . Hence . A bound on the coefficients of [Dum2007], from a bound on the spectral radius obtained with ovals of Cassini, caps the number of primes.
Related functions#
nmod_mat_charpolyandnmod_mat_minpolywork modulo a word-size modulus.fmpq_mat_charpolyandfmpq_mat_minpolyscale a rational matrix to an integer matrix by the common denominator of its entries, call these functions, and rescale the coefficient of by .fmpz_poly_factorfactors the result, for example to find the rational eigenvalues.
Example#
A matrix with a repeated eigenvalue structure: the characteristic polynomial has degree 10 while the minimal polynomial has degree 4. The Berkowitz and modular algorithms agree:
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_poly.h>
#include <flint/fmpz_mat.h>
int main(void)
{
fmpz_mat_t A;
fmpz_poly_t c, c2, m;
slong i, n = 10;
fmpz_mat_init(A, n, n);
fmpz_poly_init(c);
fmpz_poly_init(c2);
fmpz_poly_init(m);
/* block diagonal: eigenvalue 2 (blocks of sizes 2, 2, 1),
eigenvalue -1 (blocks of sizes 2, 1, 1, 1) */
for (i = 0; i < 5; i++)
fmpz_set_si(fmpz_mat_entry(A, i, i), 2);
for (i = 5; i < 10; i++)
fmpz_set_si(fmpz_mat_entry(A, i, i), -1);
fmpz_one(fmpz_mat_entry(A, 0, 1));
fmpz_one(fmpz_mat_entry(A, 2, 3));
fmpz_one(fmpz_mat_entry(A, 5, 6));
/* conjugate by a unimodular matrix to hide the structure */
{
fmpz_mat_t U, Ui, T;
fmpz_t den;
flint_rand_t state;
flint_rand_init(state);
fmpz_init(den);
fmpz_mat_init(U, n, n);
fmpz_mat_init(Ui, n, n);
fmpz_mat_init(T, n, n);
fmpz_mat_one(U);
fmpz_mat_randops(U, state, 30);
fmpz_mat_inv(Ui, den, U); /* den = +-1 */
fmpz_mat_mul(T, U, A);
fmpz_mat_mul(A, T, Ui);
fmpz_mat_scalar_divexact_fmpz(A, A, den);
fmpz_mat_clear(U);
fmpz_mat_clear(Ui);
fmpz_mat_clear(T);
fmpz_clear(den);
flint_rand_clear(state);
}
fmpz_mat_charpoly(c, A);
flint_printf("charpoly: %{fmpz_poly}\n", c);
fmpz_mat_charpoly_berkowitz(c2, A);
flint_printf("berkowitz agrees: %d\n", fmpz_poly_equal(c, c2));
fmpz_mat_charpoly_modular(c2, A);
flint_printf("modular agrees: %d\n", fmpz_poly_equal(c, c2));
fmpz_mat_minpoly(m, A);
flint_printf("minpoly: %{fmpz_poly}\n", m);
fmpz_mat_clear(A);
fmpz_poly_clear(c);
fmpz_poly_clear(c2);
fmpz_poly_clear(m);
return 0;
}charpoly: x^10 - 5 * x^9 + 30 * x^7 - 15 * x^6 - 81 * x^5 + 30 * x^4 + 120 * x^3 - 80 * x - 32 berkowitz agrees: 1 modular agrees: 1 minpoly: x^4 - 2 * x^3 - 3 * x^2 + 4 * x + 4
The characteristic polynomial is and the minimal polynomial , the exponents being the sizes of the largest Jordan blocks.
Guides#
References#
- [Dum2007] J.-G. Dumas, "Bounds on the coefficients of the characteristic and minimal polynomials", Journal of Inequalities in Pure and Applied Mathematics 8:2 (2007), article 31.
The FLINT team, “Characteristic and minimal polynomials (fmpz_mat.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz_mat/charpoly.html (generated 2026-11-02).
@misc{flint-doc-fmpz-mat-charpoly,
author = {{The FLINT team}},
title = {{Characteristic and minimal polynomials (fmpz\_mat.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/fmpz_mat/charpoly.html},
note = {Generated 2026-11-02}
}