The QR algorithm for eigenvalues
- Cost
- operations: about for the Hessenberg reduction and per QR step, with steps in practice; about twice as much with eigenvectors.
The eigenvalues of a matrix are the roots of its characteristic polynomial, but computing them as such is numerically hopeless: the roots of a polynomial are far more sensitive to its coefficients than the eigenvalues are to the entries of the matrix. Floating-point eigensolvers instead transform the matrix by unitary similarities, which do not change the eigenvalues and do not amplify rounding errors, until it is triangular. The QR algorithm of Francis and Kublanovskaya, with the refinements of the following sections, does this in operations and is backward stable: the computed Schur form is the exact Schur form of a matrix with for the unit roundoff and a modest constant [GVL1996, §7.5]. It is the algorithm of LAPACK's zgeev, and of gr_mat_eig_qr and acb_mat_approx_eig_qr in FLINT; the implementation follows mpmath's eigen.py (by Timo Hartmann), with the plane rotations of LAPACK.
Throughout, is an complex matrix, its conjugate transpose, and the working precision, .
Reduction to Hessenberg form#
A matrix is upper Hessenberg if for . Every matrix is unitarily similar to a Hessenberg matrix , which Householder reflections compute in operations, each reflection zeroing one column below its subdiagonal and being applied from both sides. The Hessenberg form is preserved by the QR iteration and makes each of its steps cost instead of .
gr_mat_hessenberg_reduce works from the last row upwards and stores each reflector in the row it zeroes (rather than in the column, as LAPACK's zgehd2), so that both applications of a reflector are unit-stride vector operations, dot products and _gr_vec_addmul_scalar calls on rows, which floating-point rings implement with SIMD code. The reflectors stay below the subdiagonal; gr_mat_hessenberg_expand_q accumulates them into when eigenvectors are wanted.
The shifted QR iteration#
A QR step with shift factors and replaces by . If is close to an eigenvalue , the last subdiagonal entry is reduced by a factor of about , where is the next closest eigenvalue; with the shifts below the convergence is quadratic (cubic for normal matrices), so that a few steps per eigenvalue suffice.
The step is computed implicitly: the plane rotation that maps the first column of to a multiple of is applied to from both sides, which creates a nonzero entry (the bulge) below the subdiagonal, and rotations chase the bulge down and out of the matrix. By the implicit Q theorem the result equals the explicit step. Each rotation has a real cosine and , as in LAPACK's zlartg: the diagonal of each transformation is then exactly real, which a ring can exploit in its vec_apply_2x2 method (a quarter of the real multiplications of a general complex rotation are saved).
The shift is the Wilkinson shift, the eigenvalue of the trailing block of the active part closest to its last diagonal entry. Since it can stall on special matrices (permutation-like structures, for which it is exactly symmetric between two eigenvalues), exceptional shifts are used after 10, 20 and 29 steps without deflation: the last subdiagonal entry, its absolute value and the norm of the matrix, cycling every 30 steps.
Deflation#
When a subdiagonal entry becomes negligible, it is set to zero, which splits into two Hessenberg blocks whose eigenvalues can be computed separately. The test is
with by default and the right-hand side replaced by when the diagonal entries are smaller than that, so that small eigenvalues do not prevent deflation. The iteration works on the trailing block until a block of size one or two has converged, then on the remaining leading part. Since the ring's arithmetic only approximates the precision it reports, a tolerance given by the caller should not be much smaller than : the iteration may otherwise fail to converge.
The eigenvalues are the diagonal entries of the resulting upper triangular matrix (a complex Schur form). In a real ring all shifts are real, so the iteration converges only if all eigenvalues are real; the double-shift variant with diagonal blocks for complex conjugate pairs (LAPACK's dhseqr) is not implemented.
Eigenvectors#
The right eigenvector of for the eigenvalue has , for and
and the eigenvector of is ; left eigenvectors are computed likewise from the rows. As in LAPACK's ztrevc, a difference smaller than a threshold is replaced by , so that repeated eigenvalues give finite (though not independent) eigenvectors, and the partial vector is scaled down whenever its largest entry exceeds , against overflow. The threshold is as in acb_mat_approx_eig_qr, or, in a ring with a bounded exponent range where this underflows (the formats of dfloat), : a perturbation at the level of the backward error.
The eigenvectors are accurate when the eigenvalues are well separated relative to the norm; for nearly multiple eigenvalues the individual eigenvectors are ill-conditioned, although the invariant subspace they span may be well-conditioned.
Schur reordering#
Adjacent diagonal entries of a complex Schur form can be exchanged by one plane rotation: the eigenvector of for is , and the rotation whose first column is this vector, normalised, moves to the top. The rotation is applied to the rows and columns of and to , the exchanged diagonal entries are set exactly, and the new subdiagonal entry, which is zero up to rounding, is set to zero. A sequence of exchanges moves any eigenvalue to any position (LAPACK's ztrexc), which serves to compute invariant subspaces for selected eigenvalues and is the building block of aggressive early deflation in multishift QR algorithms.
Accuracy and precision#
By backward stability, the computed eigenvalues are the exact eigenvalues of with , so a simple eigenvalue with left and right eigenvectors is computed with an error of about , the condition number times the backward error (for a normal matrix, and the error is ). An eigenvalue of multiplicity in a Jordan block is perturbed by about . In arbitrary precision the remedy for ill-conditioning is simply to raise ; the certification methods (Eigenvalue enclosures) tell whether it suffices.
In the multi-double formats of dfloat the operations are accurate to a few units in the last place of their bits rather than correctly rounded, and the computed eigenvalues of random matrices are typically one to three bits less accurate than with acf at the same precision; acb_mat_approx_eig_qr therefore asks for a few bits of margin before using them (Floating-point backends for the approximate functions).
Use in FLINT#
gr_mat_eig_qrand the functions it is built from (gr_mat_hessenberg_reduce,gr_mat_hessenberg_expand_q,gr_mat_hessenberg_qr_step,gr_mat_hessenberg_qr,gr_mat_eig_triu_r,gr_mat_eig_triu_l,gr_mat_schur_reorder), over any ring of approximate complex numbers; see Numerical eigenvalues.acb_mat_approx_eig_qrisgr_mat_eig_qroverdfloatornfloat_complexwhen the precision and the entries allow it, and overacf_totherwise; its results feed the certified eigenvalue functions ofacb_mat(Eigenvalue enclosures).- The plane rotations are the ring method
_gr_vec_apply_2x2; the complexdfloatrings implement it with SIMD code, where it takes about three quarters of the time of the eigensolver.
Referenced from#
- Eigenvalue enclosures (algorithm)
- Numerical eigenvalues
References#
- [GVL1996] G. H. Golub and C. F. Van Loan, Matrix Computations, third edition, Johns Hopkins University Press (1996).
The FLINT team, “The QR algorithm for eigenvalues,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/linear-algebra/qr-eigenvalues.html (generated 2026-11-07).
@misc{flint-doc-algorithms-linear-algebra-qr-eigenvalues,
author = {{The FLINT team}},
title = {{The QR algorithm for eigenvalues}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/linear-algebra/qr-eigenvalues.html},
note = {Generated 2026-11-07}
}