GenericSchur

GenericSchur is a Julia package for eigen-analysis of dense real and complex matrices of generic numeric type, i.e. those not supported by the LAPACK-based routines in the standard LinearAlgebra library. Examples are BigFloat, Float128, and DoubleFloat.

Normally, the schur!, eigvals!, and eigen! functions in the LinearAlgebra standard library are overloaded here, and may be accessed through the usual schur, eigvals, and eigen wrappers.

Type piracy

Most users will enjoy the convenience of the functions from LinearAlgebra, but these piratical methods may be omitted; see Preferences for details.

Complex Schur decomposition

The Schur decomposition is the workhorse for eigensystem analysis of dense non-symmetric matrices.

This package provides a full Schur decomposition of complex square matrices:

A::StridedMatrix{C} where {C <: Complex} == Z * T * adjoint(Z)

where T is upper-triangular and Z is unitary, both with the same element type as A.

A = your_matrix_generator() .+ 0im # in case you start with a real matrix
S = schur(A)

The result S is a LinearAlgebra.Schur object, with the properties T, Z=vectors, and values.

The unexported gschur and gschur! functions are available for types normally handled by the LAPACK wrappers in LinearAlgebra.

The algorithm is essentially the unblocked, serial, single-shift Francis (QR) scheme used in the complex LAPACK routines. Scaling is enabled for balancing, but currently permutation (which would reduce the work) is not.

Hermitian matrices

The Schur decomposition of a Hermitian (or real symmetric) matrix is identical to diagonalization, i.e. the upper-triangular factor is diagonal. This package provides such decompositions for real-symmetric and complex-Hermitian matrices via eigen! etc. In these cases, an alg argument may be used to select a LinearAlgebra.QRIteration or LinearAlgebra.DivideAndConquer algorithm. The divide-and-conquer scheme takes a long time to compile, but execution is significantly faster than QR iteration for large matrices.

Real decompositions

A quasi-triangular "real Schur" decomposition of real matrices is also provided:

A::StridedMatrix{R} where {R <: Real} == Z * T * transpose(Z)

where T is quasi-upper-triangular and Z is orthogonal, both with the same element type as A. This is what you get by invoking the above-mentioned functions with matrix arguments whose element type T <: Real. By default, the result is in standard form, so pair-blocks (and therefore rank-2 invariant subspaces) should be fully resolved. (This differs from the original version in GenericLinearAlgebra.jl.)

If the optional keyword standardized is set to false in gschur, a non-standard (but less expensive) form is produced.

Eigenvectors

Right and left eigenvectors are available from Schur factorizations, using

S = schur(A)
VR = eigvecs(S)
VL = eigvecs(S,left=true)

The results are currently unreliable if the Frobenius norm of A is extremely small or large, so scale if necessary (also see Balancing, below).

Balancing

The accuracy of eigenvalues and eigenvectors may be improved for some matrices by use of a similarity transform which reduces the matrix norm. This is done by default in the eigen! method, and may also be handled explicitly via the balance! function provided here:

Ab, B = balance!(copy(A))
S = schur(Ab)
v = eigvecs(S)
lmul!(B, v) # to get the eigenvectors of A

More details are in the function docstring. Although the balancing function also does permutations to isolate trivial subspaces, the Schur routines do not yet exploit this opportunity for reduced workload.

Generalized problems

The generalized Schur decomposition is provided [via schur(A,B), or ggschur!(A,B)], for real and complex element types. No specific implementations are currently provided for Hermitian/Symmetric problems.

Right and left eigenvectors are available for generalized problems, via eigvecs(S::GeneralizedSchur).

Reordering

An invariant (viz. deflating) subspace may be extracted via methods of the LinearAlgebra.ordschur function; see the documentation in the LinearAlgebra stdlib. This package provides this for ordinary and generalized Schur factorizations, both real and complex element types.

Preferences

The runtime behavior can be adjusted by use of package Preferences.

Type piracy

The piracy preference may be set to "true" (the default) or "false" to determine whether methods are added to functions such as LinearAlgebra.schur!.

Acknowledgements

This package includes translations from LAPACK code, and incorporates or elaborates several methods from Andreas Noack's GenericLinearAlgebra.jl package.