Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LinearAlgebra] Add isdiag/isposdef for Diagonal and UniformScaling #29638

Merged
merged 10 commits into from
Oct 16, 2018
1 change: 1 addition & 0 deletions stdlib/LinearAlgebra/src/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ factorize(D::Diagonal) = D
real(D::Diagonal) = Diagonal(real(D.diag))
imag(D::Diagonal) = Diagonal(imag(D.diag))

isdiag(D::Diagonal) = true
Copy link
Contributor

@mcognetta mcognetta Oct 15, 2018

Choose a reason for hiding this comment

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

Sorry, one more thing. This fails when we have a block diagonal matrix in which not all blocks are diagonal.

MWE:

julia> D=Diagonal([[1 0; 0 1], [1 0; 1 1]])
2×2 Diagonal{Array{Int64,2},Array{Array{Int64,2},1}}:
 [1 0; 0 1]      ⋅     
     ⋅       [1 0; 1 1]

julia> isdiag(D)
true

I believe it should be
isdiag(D::Diagonal) = all(isdiag, D.diag)
isdiag(D::Diagonal{<:Number}) = true

But I am not so sure on what it means to be a matrix of matrices so maybe @fredrikekre can correct me.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see, I only had the Number case in mind. I'll fix this.

Copy link
Member Author

Choose a reason for hiding this comment

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

... and add a test.

istriu(D::Diagonal) = true
istril(D::Diagonal) = true
function triu!(D::Diagonal,k::Integer=0)
Expand Down
2 changes: 2 additions & 0 deletions stdlib/LinearAlgebra/src/uniformscaling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ oneunit(J::UniformScaling{T}) where {T} = oneunit(UniformScaling{T})
zero(::Type{UniformScaling{T}}) where {T} = UniformScaling(zero(T))
zero(J::UniformScaling{T}) where {T} = zero(UniformScaling{T})

isdiag(::UniformScaling) = true
istriu(::UniformScaling) = true
istril(::UniformScaling) = true
issymmetric(::UniformScaling) = true
ishermitian(J::UniformScaling) = isreal(J.λ)
isposdef(J::UniformScaling) = isposdef(J.λ)

(+)(J::UniformScaling, x::Number) = J.λ + x
(+)(x::Number, J::UniformScaling) = x + J.λ
Expand Down
1 change: 1 addition & 0 deletions stdlib/LinearAlgebra/test/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Random.seed!(1)
@test D[1,2] == 0

@test issymmetric(D)
@test isdiag(D)
@test istriu(D)
@test istril(D)
if elty <: Real
Expand Down
5 changes: 4 additions & 1 deletion stdlib/LinearAlgebra/test/uniformscaling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@ end
@test conj(UniformScaling(1.0+1.0im))::UniformScaling{Complex{Float64}} == UniformScaling(1.0-1.0im)
end

@testset "istriu, istril, issymmetric, ishermitian, isapprox" begin
@testset "isdiag, istriu, istril, issymmetric, ishermitian, isposdef, isapprox" begin
@test isdiag(I)
@test istriu(I)
@test istril(I)
@test issymmetric(I)
@test issymmetric(UniformScaling(complex(1.0,1.0)))
@test ishermitian(I)
@test !ishermitian(UniformScaling(complex(1.0,1.0)))
@test isposdef(I)
@test !isposdef(-I)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe test these for complex-valued UniformScalings as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I think that's what @mcognetta's suggestion above does, I believe. This is now included.

@test UniformScaling(4.00000000000001) ≈ UniformScaling(4.0)
@test UniformScaling(4.32) ≈ UniformScaling(4.3) rtol=0.1 atol=0.01
@test UniformScaling(4.32) ≈ 4.3 * [1 0; 0 1] rtol=0.1 atol=0.01
Expand Down