diff --git a/src/hessenberg.jl b/src/hessenberg.jl index 056b97e3..442e8aa2 100644 --- a/src/hessenberg.jl +++ b/src/hessenberg.jl @@ -177,6 +177,29 @@ function \(U::UnitUpperTriangular, H::UpperHessenberg) UpperHessenberg(HH) end +function (\)(H::Union{UpperHessenberg,AdjOrTrans{<:Any,<:UpperHessenberg}}, B::AbstractVecOrMat) + TFB = typeof(oneunit(eltype(H)) \ oneunit(eltype(B))) + return ldiv!(H, copy_similar(B, TFB)) +end + +function (/)(B::AbstractMatrix, H::Union{UpperHessenberg,AdjOrTrans{<:Any,<:UpperHessenberg}}) + TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(H))) + return rdiv!(copy_similar(B, TFB), H) +end + +ldiv!(H::AdjOrTrans{<:Any,<:UpperHessenberg}, B::AbstractVecOrMat) = + (rdiv!(wrapperop(H)(B), parent(H)); B) +rdiv!(B::AbstractVecOrMat, H::AdjOrTrans{<:Any,<:UpperHessenberg}) = + (ldiv!(parent(H), wrapperop(H)(B)); B) + +# fix method ambiguities for right division, from adjtrans.jl: +/(u::AdjointAbsVec, A::UpperHessenberg) = adjoint(adjoint(A) \ u.parent) +/(u::TransposeAbsVec, A::UpperHessenberg) = transpose(transpose(A) \ u.parent) +/(u::AdjointAbsVec, A::Adjoint{<:Any,<:UpperHessenberg}) = adjoint(adjoint(A) \ u.parent) +/(u::TransposeAbsVec, A::Transpose{<:Any,<:UpperHessenberg}) = transpose(transpose(A) \ u.parent) +/(u::AdjointAbsVec, A::Transpose{<:Any,<:UpperHessenberg}) = adjoint(conj(A.parent) \ u.parent) # technically should be adjoint(copy(adjoint(copy(A))) \ u.parent) +/(u::TransposeAbsVec, A::Adjoint{<:Any,<:UpperHessenberg}) = transpose(conj(A.parent) \ u.parent) + # Solving (H+µI)x = b: we can do this in O(m²) time and O(m) memory # (in-place in x) by the RQ algorithm from: # diff --git a/test/hessenberg.jl b/test/hessenberg.jl index 91f6d155..69a91020 100644 --- a/test/hessenberg.jl +++ b/test/hessenberg.jl @@ -66,6 +66,13 @@ let n = 10 H = UpperHessenberg(Areal) @test Array(Hc + H) == Array(Hc) + Array(H) @test Array(Hc - H) == Array(Hc) - Array(H) + @testset "ldiv and rdiv" begin + for b in (b_, B_), H in (H, Hc, H', Hc', transpose(Hc)) + @test H * (H \ b) ≈ b + @test (b' / H) * H ≈ (Matrix(b') / H) * H ≈ b' + @test (transpose(b) / H) * H ≈ (Matrix(transpose(b)) / H) * H ≈ transpose(b) + end + end @testset "Preserve UpperHessenberg shape (issue #39388)" begin H = UpperHessenberg(Areal) A = rand(n,n)