Skip to content

Commit

Permalink
Add methods for dividing triangular by diagonal matrices. (#27999)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
tpapp authored and andreasnoack committed Jul 12, 2018
1 parent e2de8c3 commit 5f19151
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
16 changes: 15 additions & 1 deletion stdlib/LinearAlgebra/src/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ ldiv!(adjD::Adjoint{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} =
ldiv!(transD::Transpose{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} =
(D = transD.parent; ldiv!(D, B))

function ldiv!(D::Diagonal, A::Union{LowerTriangular,UpperTriangular})
broadcast!(\, parent(A), D.diag, parent(A))
A
end

function rdiv!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T}
@assert !has_offset_axes(A)
dd = D.diag
Expand All @@ -354,12 +359,19 @@ function rdiv!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T}
A
end

function rdiv!(A::Union{LowerTriangular,UpperTriangular}, D::Diagonal)
broadcast!(/, parent(A), parent(A), permutedims(D.diag))
A
end

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

(/)(A::Union{StridedMatrix, AbstractTriangular}, D::Diagonal) =
rdiv!((typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A), D)

(\)(F::Factorization, D::Diagonal) =
ldiv!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))
\(adjF::Adjoint{<:Any,<:Factorization}, D::Diagonal) =
Expand Down Expand Up @@ -430,7 +442,9 @@ function ldiv!(D::Diagonal, B::StridedVecOrMat)
end
return B
end
(\)(D::Diagonal, A::AbstractMatrix) = D.diag .\ A
(\)(D::Diagonal, A::AbstractMatrix) =
ldiv!(D, (typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A))

(\)(D::Diagonal, b::AbstractVector) = D.diag .\ b
(\)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .\ Db.diag)

Expand Down
13 changes: 13 additions & 0 deletions stdlib/LinearAlgebra/test/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -460,4 +460,17 @@ end
@test Transpose(x)*D*x == (Transpose(x)*D)*x == (Transpose(x)*Array(D))*x
end

@testset "Triangular division by Diagonal #27989" begin
K = 5
for elty in (Float32, Float64, ComplexF32, ComplexF64)
U = UpperTriangular(randn(elty, K, K))
L = LowerTriangular(randn(elty, K, K))
D = Diagonal(randn(elty, K))
@test (U / D)::UpperTriangular{elty} == UpperTriangular(Matrix(U) / Matrix(D))
@test (L / D)::LowerTriangular{elty} == LowerTriangular(Matrix(L) / Matrix(D))
@test (D \ U)::UpperTriangular{elty} == UpperTriangular(Matrix(D) \ Matrix(U))
@test (D \ L)::LowerTriangular{elty} == LowerTriangular(Matrix(D) \ Matrix(L))
end
end

end # module TestDiagonal

1 comment on commit 5f19151

@fredrikekre
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please dont ping people in commit messages, or at least edit it out when squashing. Now I'll be notified whenever something happens with this commit.

Please sign in to comment.