schur_full/schur_vals select DiagonalAlgorithm for Diagonal inputs, but no such implementation exists, so both throw a MethodError.
Reproduction
On MatrixAlgebraKit v0.6.9, Julia 1.12.6:
julia> using LinearAlgebra, MatrixAlgebraKit
julia> D = Diagonal([2.0, 3.0, 5.0]);
julia> MatrixAlgebraKit.select_algorithm(MatrixAlgebraKit.schur_full!, D, nothing)
DiagonalAlgorithm{@NamedTuple{}}(NamedTuple())
julia> schur_full(D)
ERROR: MethodError: no method matching schur_full!(::Diagonal{Float64, Vector{Float64}}, ::Tuple{Diagonal{Float64, Vector{Float64}}, Matrix{Float64}, Vector{ComplexF64}}, ::DiagonalAlgorithm{@NamedTuple{}})
julia> schur_vals(D)
ERROR: MethodError: no method matching schur_vals!(...)
julia> eig_full(D) # control: works
Cause
Schur reuses eig's algorithm selection, which routes Diagonal to DiagonalAlgorithm:
src/interface/schur.jl:44-48 — default_algorithm(::typeof(schur_full!), ::Type{A}; kwargs...) = default_eig_algorithm(A; kwargs...), for both schur_full! and schur_vals!
src/interface/eig.jl:167-169 — default_eig_algorithm(::Type{T}) where {T <: Diagonal} = DiagonalAlgorithm(; kwargs...)
But src/implementations/schur.jl only implements QRIteration (lines 92 and 97). There is no DiagonalAlgorithm method, nor check_input/initialize_output for it — the existing ones at lines 7-38 are ::AbstractAlgorithm, so selection succeeds and dispatch then fails.
eig, eigh, svd, qr and lq all have DiagonalAlgorithm implementations; schur appears to be the one that was missed.
Suggested fix
Add the diagonal case to src/implementations/schur.jl. A diagonal matrix is already in Schur form, so T = A, Z = I, vals = complex.(diagview(A)) — mirroring eigh_full!(A::Diagonal, DV, ::DiagonalAlgorithm) at src/implementations/eigh.jl:179. Unlike eigh, no sorting is implied by the Schur interface.
Alternatively, give schur its own default_schur_algorithm instead of reusing default_eig_algorithm, so Diagonal no longer selects an unimplemented algorithm. That turns the MethodError into a clearer one but still leaves schur_full(::Diagonal) unsupported.
Happy to open a PR for whichever direction you prefer.
Note: src/interface/schur.jl:23 already carries # TODO: is this useful? Is there any difference with simply eig_vals? above schur_vals. If the answer is to drop schur_vals, that covers half of this.
Downstream impact
This reaches TensorKit.DiagonalTensorMap, which forwards to select_algorithm like every other factorization:
julia> using TensorKit
julia> d = DiagonalTensorMap(randn(4), Vect[Z2Irrep](0 => 2, 1 => 2));
julia> schur_full(d) # MethodError; eig_full(d) and svd_compact(d) are fine
Found via JET.report_package(TensorKit).
schur_full/schur_valsselectDiagonalAlgorithmforDiagonalinputs, but no such implementation exists, so both throw aMethodError.Reproduction
On MatrixAlgebraKit v0.6.9, Julia 1.12.6:
Cause
Schur reuses eig's algorithm selection, which routes
DiagonaltoDiagonalAlgorithm:src/interface/schur.jl:44-48—default_algorithm(::typeof(schur_full!), ::Type{A}; kwargs...) = default_eig_algorithm(A; kwargs...), for bothschur_full!andschur_vals!src/interface/eig.jl:167-169—default_eig_algorithm(::Type{T}) where {T <: Diagonal} = DiagonalAlgorithm(; kwargs...)But
src/implementations/schur.jlonly implementsQRIteration(lines 92 and 97). There is noDiagonalAlgorithmmethod, norcheck_input/initialize_outputfor it — the existing ones at lines 7-38 are::AbstractAlgorithm, so selection succeeds and dispatch then fails.eig,eigh,svd,qrandlqall haveDiagonalAlgorithmimplementations; schur appears to be the one that was missed.Suggested fix
Add the diagonal case to
src/implementations/schur.jl. A diagonal matrix is already in Schur form, soT = A,Z = I,vals = complex.(diagview(A))— mirroringeigh_full!(A::Diagonal, DV, ::DiagonalAlgorithm)atsrc/implementations/eigh.jl:179. Unlikeeigh, no sorting is implied by the Schur interface.Alternatively, give schur its own
default_schur_algorithminstead of reusingdefault_eig_algorithm, soDiagonalno longer selects an unimplemented algorithm. That turns theMethodErrorinto a clearer one but still leavesschur_full(::Diagonal)unsupported.Happy to open a PR for whichever direction you prefer.
Note:
src/interface/schur.jl:23already carries# TODO: is this useful? Is there any difference with simply eig_vals?aboveschur_vals. If the answer is to dropschur_vals, that covers half of this.Downstream impact
This reaches
TensorKit.DiagonalTensorMap, which forwards toselect_algorithmlike every other factorization:Found via
JET.report_package(TensorKit).