FLINT3.7.0-dev

_padic_radix_mat_charpoly_berkowitz, padic_radix_mat_charpoly_hessenberg, padic_radix_mat_charpoly_lift, padic_radix_mat_charpoly

Synopsis#include <flint/padic_radix.h>
int _padic_radix_mat_charpoly_berkowitz(padic_radix_struct * cp, const gr_mat_t mat, gr_ctx_t ctx)source
int padic_radix_mat_charpoly_hessenberg(padic_radix_struct * cp, const gr_mat_t mat, gr_ctx_t ctx)source
int padic_radix_mat_charpoly_lift(padic_radix_struct * cp, const gr_mat_t mat, gr_ctx_t ctx)source
int padic_radix_mat_charpoly(padic_radix_struct * cp, const gr_mat_t mat, gr_ctx_t ctx)source

Set cp to the characteristic polynomial χ(x)=det⁡(xI−A)\chi(x) = \det(xI - A) of the square matrix mat.

The berkowitz version is the division-free Berkowitz algorithm, with the matrix-vector products done on the matrix packed once (falling back to _gr_mat_charpoly_berkowitz for dimension at most 5, in contexts without a relative precision, and for matrices with exact nonzero entries). For integral entries known to O(pN)O(p^N) it gives every coefficient to precision about NN, which is optimal when the matrix is cyclic modulo pp but can lose many digits otherwise (dozens for the low coefficients of moderately structured matrices of dimension 16).

The hessenberg version reduces the matrix to Hessenberg form by similarity transformations with pivots of minimal valuation (so that the transformations are in GLn(Zp)\mathrm{GL}_n(\mathbb{Z}_p)), in O(n3)O(n^3) operations; it loses a few digits.

The lift version gives the optimal precision. With the matrix scaled by a power of pp to make it integral, MM the exact lift of the entries and adj⁡(xI−M)=∑kBkxk\operatorname{adj}(xI - M) = \sum_k B_k x^k, a perturbation EE with v(Eij)≥Nijv(E_{ij}) \ge N_{ij} changes ckc_k by −tr⁡(BkE)-\operatorname{tr}(B_k E) plus terms of order at least two in EE, whose coefficients (minors of xI−MxI - M) are integral. Hence ck(A)=ck(M)+O(pNk)c_k(A) = c_k(M) + O(p^{N_k}) with Nk=min⁡(2Nmin⁡,min⁡ij(Nij+v((Bk)ji)))N_k = \min(2 N_{\min}, \min_{ij} (N_{ij} + v((B_k)_{ji}))), the precision of the differential of χ\chi. The coefficients ck(M)c_k(M) are computed modulo p2Nmin⁡p^{2 N_{\min}} by the hessenberg version at a raised working precision (retried with more digits if needed, with the berkowitz version as a last resort), and the BkB_k by the recurrence Bn−1=IB_{n-1} = I, Bk−1=MBk+ckIB_{k-1} = M B_k + c_k I, modulo one word first and modulo pNmin⁡p^{N_{\min}} if valuations at that bound matter, with nn matrix products. Exact matrices give the exact characteristic polynomial (multimodular), rounded to the context precision.

The lifted entries are reduced modulo the largest working precision, so that entries of high valuation cost nothing. The working precision 2(Nmin⁡+s)2(N_{\min} + s), where psp^s is the scaling, is large when an entry has a much smaller valuation (or error term) than the others; the lift version returns GR_UNABLE when Nmin⁡+s>64(R+n)+1024N_{\min} + s > 64(R + n) + 1024, where RR is the largest relative precision of an inexact entry. For exact matrices it returns GR_UNABLE when the exact characteristic polynomial would exceed the size_limit of the context, when the entries of MM have more than 4r+2564 r + 256 digits for a finite context precision rr, or when they are dominated by powers of pp (valuations above four times the size of the units plus 256 digits), which Berkowitz's algorithm in Qp\mathbf{Q}_p handles without expanding them.

padic_radix_mat_charpoly implements the generic method. For matrices with integral entries of uniform precision NN that are cyclic modulo pp (tested with a random Krylov basis over Fp\mathbb{F}_p), the optimal precision is NN for every coefficient: the hessenberg version is tried first and accepted if it attains it (as for matrices that are generic modulo pp), and otherwise the berkowitz version, which always does, is used. Other matrices use the lift version, together with Danilevsky's algorithm (keeping the more precise result for each coefficient) where the bound 2Nmin⁡2 N_{\min} limits it, and the berkowitz version when the lift version gives up. With the context flag PADIC_RADIX_FAST_LINALG, the hessenberg version is used for all matrices.

Cite this page

The FLINT team, “_padic_radix_mat_charpoly_berkowitz, padic_radix_mat_charpoly_hessenberg, padic_radix_mat_charpoly_lift, padic_radix_mat_charpoly (padic_radix.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/padic_radix/_padic_radix_mat_charpoly_berkowitz.html (generated 2026-11-02).