FLINT3.7.0-dev

Eigenvalues and eigenvectors

Synopsis#include <flint/acb_mat.h>
int acb_mat_approx_eig_qr(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, const mag_t tol, slong maxiter, slong prec)source

Computes floating-point approximations of the nn eigenvalues of the n×nn \times n matrix AA (in no particular order) in E, and optionally of the corresponding left eigenvectors in the rows of L and right eigenvectors in the columns of R (either may be NULL), without error bounds. Returns nonzero if the QR iteration converged numerically; this is only a heuristic, and the output may be accurate even if zero is returned.

The matrix is reduced to Hessenberg form by Householder reflections and the eigenvalues are computed by the implicitly shifted QR algorithm, working on the midpoints at prec bits. tol (default 2−prec/(100n)2^{-\mathit{prec}} / (100n) if NULL) is the tolerance for negligible subdiagonal entries, and maxiter (default 14n+prec/1014n + \mathit{prec}/10 if 0 or negative) bounds the number of iterations. The eigenvectors are computed from the triangular Schur form by back-substitution and transformed back with the accumulated unitary transformation.

void acb_mat_eig_global_enclosure(mag_t eps, const acb_mat_t A, acb_srcptr E, const acb_mat_t R, slong prec)source

Given approximations EE of the eigenvalues and RR of the right eigenvectors of the n×nn \times n matrix AA, computes ε\varepsilon such that every eigenvalue of AA lies within distance ε\varepsilon of some λ^k∈E\hat\lambda_k \in E, by Theorem 1 of [Miy2010], an extension of the Bauer–Fike theorem. If ∥YR−I∥∞≥1\|YR - I\|_\infty \ge 1 for the approximate inverse YY of RR, eps is set to infinity.

The union of the disks {z:∣z−λ^k∣≤ε}\{z : |z - \hat\lambda_k| \le \varepsilon\} encloses the spectrum, but a single disk need not contain exactly one eigenvalue; when the approximations are good, the disks usually correspond to the eigenvalues one to one. The bound is

ε=∥Y(AR−RD)∥∞1−∥YR−I∥∞,\varepsilon = \frac{\|Y(AR - RD)\|_\infty}{1 - \|YR - I\|_\infty},

with D=diag⁡(E)D = \operatorname{diag}(E) and Y≈R−1Y \approx R^{-1}. It certifies regions of the complex plane (half-planes, disks, annuli) that contain the whole spectrum, cheaply and without assumptions on AA.

void acb_mat_eig_enclosure_rump(acb_t lambda, acb_mat_t J, acb_mat_t R, const acb_mat_t A, const acb_t lambda_approx, const acb_mat_t R_approx, slong prec)source

Given an approximate eigenvalue lambda_approx of AA and an n×kn \times k matrix R_approx of approximate eigenvectors (a basis of the invariant subspace of a presumed cluster of kk eigenvalues), computes a ball lambda that contains at least kk eigenvalues of AA (counted with multiplicity) and an n×kn \times k matrix R that contains a basis of the corresponding invariant subspace. If J is not NULL, it is set to a k×kk \times k matrix J≈λIJ \approx \lambda I such that AR−RJAR - RJ contains zero; the Jordan form of AA then has a k×kk \times k block equal to the Jordan form of a matrix in JJ. For k=1k = 1, AR−RλAR - R \lambda contains zero. On failure, the outputs are set to indeterminate values.

The algorithm is that of Section 13.4 of [Rum2010] (the INTLAB function verifyeig): with a preconditioner R0≈((A−λ~I)UUT−X~VT)−1R_0 \approx ((A - \tilde\lambda I) U U^T - \tilde X V^T)^{-1}, where the rows selected by VV (for k=1k = 1 the row of X~\tilde X of largest absolute value, otherwise the last kk rows) are frozen, a fixed point iteration with ε\varepsilon-inflation is run for at most 5+b5 + b steps, where bb is the bit length of prec, until the image of the candidate set lies in its interior, as Rump's theorem requires (each entry is tested with acb_contains_interior). See Eigenvalue enclosures.

int acb_mat_eig_simple_rump(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec)source
int acb_mat_eig_simple_vdhoeven_mourrain(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec)source
int acb_mat_eig_simple(acb_ptr E, acb_mat_t L, acb_mat_t R, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec)source

Attempt to prove that the n×nn \times n matrix AA has nn simple eigenvalues, given approximations of the eigenvalues and right eigenvectors. Return 1 on success, writing pairwise disjoint enclosures of the eigenvalues to E (in no particular order), and if L or R is not NULL, enclosures of the corresponding left eigenvectors (rows of L) and right eigenvectors (columns of R), normalised so that L=R−1L = R^{-1}, which gives a diagonalisation LAR=DLAR = D. Return 0 otherwise.

The rump version certifies the eigenpairs one by one with acb_mat_eig_enclosure_rump and fails as soon as an enclosure overlaps a previous one; LL is obtained by inverting RR; the cost is O(n4)O(n^4). The vdhoeven_mourrain version certifies all eigenpairs at once with the algorithm of [HM2017] at a cost of O(n3)O(n^3), and is the default. These functions do not try to compute clusters; use acb_mat_eig_multiple for matrices that may have multiple or clustered eigenvalues.

int acb_mat_eig_multiple_rump(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec)source
int acb_mat_eig_multiple(acb_ptr E, const acb_mat_t A, acb_srcptr E_approx, const acb_mat_t R_approx, slong prec)source

Compute enclosures of all nn eigenvalues of AA with multiplicities, given approximations of the eigenvalues and right eigenvectors. On success (return value 1), the nn entries of E are either disjoint or identical, identical entries are consecutive, and a run of kk identical entries is a ball that contains exactly kk eigenvalues (a cluster that could not be separated at this precision) and is disjoint from the other n−kn - k eigenvalues. Return 0 otherwise.

The rump version groups the approximate eigenvalues that lie within M2−3prec/4M 2^{-3\mathit{prec}/4} of each other, where MM is the largest approximate eigenvalue (and, in a second attempt, within M2−prec/2M 2^{-\mathit{prec}/2}), validates each group with acb_mat_eig_enclosure_rump and checks that the enclosures are disjoint; for mm clusters it costs O(mn3)O(m n^3). The default acb_mat_eig_multiple first tries acb_mat_eig_simple_vdhoeven_mourrain and falls back to the rump version.

Computing certified eigenvalues of a complex matrix AA in FLINT takes two steps. First, acb_mat_approx_eig_qr computes floating-point approximations of the eigenvalues and eigenvectors by the QR algorithm, without error bounds. Then one of the certification functions turns these approximations into rigorous enclosures:

  • acb_mat_eig_simple proves that AA has nn distinct eigenvalues and returns disjoint enclosures of them, together with enclosures of the left and right eigenvectors if wanted;
  • acb_mat_eig_multiple allows multiple or clustered eigenvalues and returns enclosures with multiplicities;
  • acb_mat_eig_global_enclosure returns a single radius ε\varepsilon such that every eigenvalue lies within ε\varepsilon of one of the approximations, which is the cheapest way to certify statements about the whole spectrum;
  • acb_mat_eig_enclosure_rump certifies one eigenvalue (or one cluster) and its eigenvector (or invariant subspace).

The certification functions accept approximations from any source, and their output is valid whatever the quality of the approximations; poor approximations only make them fail or give wide enclosures. For a real matrix, convert it with acb_mat_set_arb_mat first.

AlgorithmEigenvalue enclosuresHow acb_mat computes rigorous enclosures of the eigenvalues and eigenvectors of complex matrices by certifying floating-point approximations from the QR algorithm, with a global perturbation bound, a Gershgorin test after an approximate diagonalisation, and Rump's fixed-point method for eigenvalue clusters.

Approximation by the QR algorithm#

acb_mat_approx_eig_qr(E, L, R, A, tol, maxiter, prec) works on the midpoint matrix at prec bits: Householder reduction to Hessenberg form, then the implicitly shifted QR iteration until the subdiagonal entries are below tol (by default 2−prec/(100n)2^{-\mathit{prec}}/(100n) relative to their neighbours) or maxiter iterations (by default 14n+prec/1014n + \mathit{prec}/10) have been done, and finally back-substitution in the triangular Schur form for the eigenvectors. The return value only says whether the iteration converged numerically. The cost is O(n3)O(n^3) operations at prec bits.

Certification#

All eigenvalues, simple. acb_mat_eig_simple uses by default the algorithm of van der Hoeven and Mourrain [HM2017]: with TT the midpoint of the approximate eigenvector matrix, it computes D=T−1ATD = T^{-1} A T in ball arithmetic (by acb_mat_solve), splits it into its diagonal Δ\Delta and off-diagonal part HH, and checks with the separation σ=min⁡i≠j∣δi−δj∣\sigma = \min_{i \ne j} |\delta_i - \delta_j| and μ=∥Δ∥∞\mu = \|\Delta\|_\infty that ∥H∥∞\|H\|_\infty is small enough compared to σ\sigma and μ\mu for a perturbation argument to apply. The eigenvalues are then the diagonal entries of DD inflated by ∥H∥∞\|H\|_\infty, and enclosures of the eigenvectors follow from a correction of TT. The cost is O(n3)O(n^3). The alternative acb_mat_eig_simple_rump certifies the eigenpairs one by one with acb_mat_eig_enclosure_rump at a cost of O(n4)O(n^4). Both fail (return 0) if two enclosures overlap, which happens for multiple eigenvalues and for eigenvalues closer than the attainable accuracy.

Clusters. acb_mat_eig_multiple first tries acb_mat_eig_simple_vdhoeven_mourrain; if that fails, it groups approximate eigenvalues that agree to about 3/43/4 (and then 1/21/2) of the precision into clusters, certifies each cluster of size kk with acb_mat_eig_enclosure_rump (a ball containing at least kk eigenvalues), and succeeds if the cluster enclosures are pairwise disjoint, since they then contain exactly kk eigenvalues each. The output repeats each cluster enclosure kk times.

One eigenpair or cluster. acb_mat_eig_enclosure_rump follows Section 13.4 of [Rum2010]: the eigenproblem AX=XλAX = X\lambda (or AX=XMAX = XM for a cluster) is written as a fixed point problem for the correction to the approximation, in which kk rows of the eigenvector are frozen to normalise it; a preconditioned fixed point iteration with ε\varepsilon-inflation looks for a set of corrections that is mapped into itself, which proves the existence of an eigenvalue (or of kk eigenvalues) in the resulting enclosure. For a cluster, the output matrix JJ satisfies AR−RJ∋0AR - RJ \ni 0, so that the Jordan structure of the cluster is that of a matrix in JJ.

The whole spectrum. acb_mat_eig_global_enclosure implements Theorem 1 of Miyajima [Miy2010]: with DD the diagonal matrix of approximate eigenvalues, RR the approximate eigenvectors and Y≈R−1Y \approx R^{-1}, every eigenvalue of AA lies within

ε=∥Y(AR−RD)∥∞1−∥YR−I∥∞\varepsilon = \frac{\|Y(AR - RD)\|_\infty}{1 - \|YR - I\|_\infty}

of a diagonal entry of DD, provided that ∥YR−I∥∞<1\|YR - I\|_\infty < 1. This generalises the Bauer–Fike theorem to approximate eigenvectors. It needs only a few matrix products, but it cannot tell which disk contains how many eigenvalues.

The algorithms and proofs are in Eigenvalue enclosures.

Practical advice#

  • Compute the approximations at the same precision as the certification, or a little higher; the certification cannot produce enclosures much tighter than the approximations are accurate.
  • If certification fails, increase the precision. If it keeps failing, the matrix may have multiple eigenvalues (use acb_mat_eig_multiple) or be defective (non-diagonalisable), in which case only cluster enclosures exist, and their width is about ε1/m\varepsilon^{1/m} for a Jordan block of size mm and an input accuracy ε\varepsilon.
  • Badly scaled matrices may need balancing first, and a similarity transformation by a random matrix sometimes helps when an algorithm fails to converge on a well-scaled matrix.
  • The left eigenvectors computed by acb_mat_eig_simple are normalised so that L=R−1L = R^{-1}, which gives a certified diagonalisation LAR=DLAR = D.

Examples#

A 4×44 \times 4 nonsymmetric matrix with four real eigenvalues. The global enclosure gives a tiny radius for the spectrum as a whole; acb_mat_eig_simple isolates the eigenvalues individually (their imaginary parts are only known to be small: certification in complex arithmetic cannot prove that an eigenvalue is real):

Exampleacb_mat_eig_simple.cchecked by make checkdoc
#include <flint/acb.h>
#include <flint/acb_mat.h>

int main(void)
{
    acb_mat_t A, L, R;
    acb_ptr E, F;
    mag_t eps;
    slong i, j, n = 4, prec = 64;

    acb_mat_init(A, n, n);
    acb_mat_init(L, n, n);
    acb_mat_init(R, n, n);
    E = _acb_vec_init(n);
    F = _acb_vec_init(n);
    mag_init(eps);

    /* the Hilbert matrix with the top right entry replaced by -1 */
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
        {
            acb_set_ui(acb_mat_entry(A, i, j), i + j + 1);
            acb_inv(acb_mat_entry(A, i, j), acb_mat_entry(A, i, j), prec);
        }
    acb_set_si(acb_mat_entry(A, 0, n - 1), -1);

    acb_mat_approx_eig_qr(E, NULL, R, A, NULL, 0, prec);

    acb_mat_eig_global_enclosure(eps, A, E, R, prec);
    flint_printf("global enclosure radius: ");
    mag_printd(eps, 3);
    flint_printf("\n");

    if (acb_mat_eig_simple(F, L, R, A, E, R, prec))
    {
        _acb_vec_sort_pretty(F, n);
        for (i = 0; i < n; i++)
        {
            acb_printn(F + i, 12, 0);
            flint_printf("\n");
        }
    }

    acb_mat_clear(A);
    acb_mat_clear(L);
    acb_mat_clear(R);
    _acb_vec_clear(E, n);
    _acb_vec_clear(F, n);
    mag_clear(eps);
    return 0;
}
Output
global enclosure radius: 3.24e-18
[-0.0392285082075 +/- 2.44e-14] + [+/- 1.32e-16]*I
[-0.00114669579895 +/- 3.57e-15] + [+/- 1.33e-16]*I
[0.558734852147 +/- 1.64e-13] + [+/- 1.36e-16]*I
[1.15783082805 +/- 1.11e-13] + [+/- 1.39e-16]*I

The matrix A=Tdiag⁡(1,1,2)T−1A = T \operatorname{diag}(1, 1, 2) T^{-1} below has the double eigenvalue 1. acb_mat_eig_simple fails, and acb_mat_eig_multiple returns the cluster enclosure twice:

Exampleacb_mat_eig_multiple.cchecked by make checkdoc
#include <flint/fmpq.h>
#include <flint/fmpq_mat.h>
#include <flint/acb.h>
#include <flint/acb_mat.h>

int main(void)
{
    fmpq_mat_t T, Tinv, D, Q;
    acb_mat_t A, R;
    acb_ptr E, F;
    slong i, n = 3, prec = 64;

    fmpq_mat_init(T, n, n);
    fmpq_mat_init(Tinv, n, n);
    fmpq_mat_init(D, n, n);
    fmpq_mat_init(Q, n, n);
    acb_mat_init(A, n, n);
    acb_mat_init(R, n, n);
    E = _acb_vec_init(n);
    F = _acb_vec_init(n);

    /* A = T diag(1, 1, 2) T^-1 has the double eigenvalue 1 */
    fmpq_set_si(fmpq_mat_entry(T, 0, 0), 1, 1);
    fmpq_set_si(fmpq_mat_entry(T, 0, 1), 1, 1);
    fmpq_set_si(fmpq_mat_entry(T, 1, 1), 1, 1);
    fmpq_set_si(fmpq_mat_entry(T, 1, 2), 1, 1);
    fmpq_set_si(fmpq_mat_entry(T, 2, 0), 1, 1);
    fmpq_set_si(fmpq_mat_entry(T, 2, 2), 1, 1);
    fmpq_set_si(fmpq_mat_entry(D, 0, 0), 1, 1);
    fmpq_set_si(fmpq_mat_entry(D, 1, 1), 1, 1);
    fmpq_set_si(fmpq_mat_entry(D, 2, 2), 2, 1);
    fmpq_mat_inv(Tinv, T);
    fmpq_mat_mul(Q, T, D);
    fmpq_mat_mul(Q, Q, Tinv);
    acb_mat_set_fmpq_mat(A, Q, prec);

    acb_mat_approx_eig_qr(E, NULL, R, A, NULL, 0, prec);

    flint_printf("simple: %d\n", acb_mat_eig_simple(F, NULL, NULL, A, E, R, prec));
    flint_printf("multiple: %d\n", acb_mat_eig_multiple(F, A, E, R, prec));
    for (i = 0; i < n; i++)
    {
        acb_printn(F + i, 10, 0);
        flint_printf("\n");
    }

    fmpq_mat_clear(T);
    fmpq_mat_clear(Tinv);
    fmpq_mat_clear(D);
    fmpq_mat_clear(Q);
    acb_mat_clear(A);
    acb_mat_clear(R);
    _acb_vec_clear(E, n);
    _acb_vec_clear(F, n);
    return 0;
}
Output
simple: 0
multiple: 1
[1.000000000 +/- 4.41e-19] + [+/- 2.17e-19]*I
[1.000000000 +/- 4.41e-19] + [+/- 2.17e-19]*I
[2.000000000 +/- 3.26e-18] + [+/- 1.63e-18]*I

Since this matrix is diagonalisable, the cluster enclosure is about as tight as the enclosure of a simple eigenvalue; for a Jordan block, it would be much wider.

References#

  • [Miy2010] S. Miyajima, "Fast enclosure for all eigenvalues in generalized eigenvalue problems", Journal of Computational and Applied Mathematics, 233 (2010), 2994-3004, https://doi.org/10.1016/j.cam.2009.11.048
  • [Rum2010] S. M. Rump, "Verification methods: Rigorous results using floating-point arithmetic", Acta Numerica 19 (2010), 287-449.
  • [HM2017] J. van der Hoeven and B. Mourrain. "Efficient certification of numeric solutions to eigenproblems", MACIS 2017, 81-94, (2017), https://hal.archives-ouvertes.fr/hal-01579079
Cite this page

The FLINT team, “Eigenvalues and eigenvectors (acb_mat.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/acb_mat/eigenvalues.html (generated 2026-11-02).