Skip to content

Commit 5f19151

Browse files
tpappandreasnoack
authored andcommitted
Add methods for dividing triangular by diagonal matrices. (#27999)
* Add methods for dividing triangular by diagonal matrices. Fixes #27989. * Simplified tests. suggested by @fredrikekre * Test for element types instead, fix bug. For broadcasting, tranpose should be used instead of adjoint. * Matrix diagonal division through ldiv!/rdiv!. Removed previous direct implementations for upper/lower triangular, added ldiv!/rdiv! methods. Use reshape instead of transpose. * Fix ldiv! to \, use permutedims, restrict signature.
1 parent e2de8c3 commit 5f19151

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

stdlib/LinearAlgebra/src/diagonal.jl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,11 @@ ldiv!(adjD::Adjoint{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} =
335335
ldiv!(transD::Transpose{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} =
336336
(D = transD.parent; ldiv!(D, B))
337337

338+
function ldiv!(D::Diagonal, A::Union{LowerTriangular,UpperTriangular})
339+
broadcast!(\, parent(A), D.diag, parent(A))
340+
A
341+
end
342+
338343
function rdiv!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T}
339344
@assert !has_offset_axes(A)
340345
dd = D.diag
@@ -354,12 +359,19 @@ function rdiv!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T}
354359
A
355360
end
356361

362+
function rdiv!(A::Union{LowerTriangular,UpperTriangular}, D::Diagonal)
363+
broadcast!(/, parent(A), parent(A), permutedims(D.diag))
364+
A
365+
end
357366

358367
rdiv!(A::AbstractMatrix{T}, adjD::Adjoint{<:Any,<:Diagonal{T}}) where {T} =
359368
(D = adjD.parent; rdiv!(A, conj(D)))
360369
rdiv!(A::AbstractMatrix{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} =
361370
(D = transD.parent; rdiv!(A, D))
362371

372+
(/)(A::Union{StridedMatrix, AbstractTriangular}, D::Diagonal) =
373+
rdiv!((typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A), D)
374+
363375
(\)(F::Factorization, D::Diagonal) =
364376
ldiv!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))
365377
\(adjF::Adjoint{<:Any,<:Factorization}, D::Diagonal) =
@@ -430,7 +442,9 @@ function ldiv!(D::Diagonal, B::StridedVecOrMat)
430442
end
431443
return B
432444
end
433-
(\)(D::Diagonal, A::AbstractMatrix) = D.diag .\ A
445+
(\)(D::Diagonal, A::AbstractMatrix) =
446+
ldiv!(D, (typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A))
447+
434448
(\)(D::Diagonal, b::AbstractVector) = D.diag .\ b
435449
(\)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .\ Db.diag)
436450

stdlib/LinearAlgebra/test/diagonal.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,4 +460,17 @@ end
460460
@test Transpose(x)*D*x == (Transpose(x)*D)*x == (Transpose(x)*Array(D))*x
461461
end
462462

463+
@testset "Triangular division by Diagonal #27989" begin
464+
K = 5
465+
for elty in (Float32, Float64, ComplexF32, ComplexF64)
466+
U = UpperTriangular(randn(elty, K, K))
467+
L = LowerTriangular(randn(elty, K, K))
468+
D = Diagonal(randn(elty, K))
469+
@test (U / D)::UpperTriangular{elty} == UpperTriangular(Matrix(U) / Matrix(D))
470+
@test (L / D)::LowerTriangular{elty} == LowerTriangular(Matrix(L) / Matrix(D))
471+
@test (D \ U)::UpperTriangular{elty} == UpperTriangular(Matrix(D) \ Matrix(U))
472+
@test (D \ L)::LowerTriangular{elty} == LowerTriangular(Matrix(D) \ Matrix(L))
473+
end
474+
end
475+
463476
end # module TestDiagonal

0 commit comments

Comments
 (0)