Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "ArrayInterface"
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
version = "2.5.1"
version = "2.6.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand All @@ -15,9 +15,10 @@ julia = "1.2"
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
SuiteSparse = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "LabelledArrays", "StaticArrays", "BandedMatrices", "BlockBandedMatrices", "SuiteSparse"]
test = ["Test", "LabelledArrays", "StaticArrays", "BandedMatrices", "BlockBandedMatrices", "SuiteSparse", "Random"]
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ A `setindex!` which is always allowed.
Return an instance of the LU factorization object with the correct type
cheaply.

## issingular(A)

Check singularity by factorization or checking zeros of structured matrices.

*Warning*: `rank` is a better choice for some matrices.

## List of things to add

- https://github.com/JuliaLang/julia/issues/22216
Expand Down
15 changes: 14 additions & 1 deletion src/ArrayInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ isstructured(::Diagonal) = true
"""
has_sparsestruct(x::AbstractArray)

determine whether `findstructralnz` accepts the parameter `x`
Determine whether `findstructralnz` accepts the parameter `x`
"""
has_sparsestruct(x) = false
has_sparsestruct(x::AbstractArray) = has_sparsestruct(typeof(x))
Expand All @@ -106,6 +106,19 @@ has_sparsestruct(x::Type{<:Bidiagonal}) = true
has_sparsestruct(x::Type{<:Tridiagonal}) = true
has_sparsestruct(x::Type{<:SymTridiagonal}) = true

"""
issingular(A::AbstractMatrix)

Determine whether a given abstract matrix is singular.
"""
issingular(A::Matrix) = !issuccess(lu(A, check=false))
issingular(A::UniformScaling) = A.λ == 0
issingular(A::Diagonal) = any(iszero,A.diag)
Copy link
Contributor

Choose a reason for hiding this comment

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

One could add here

issingular(B::Bidiagonal) = any(iszero, A.dv)
issingular(S::SymTridiagonal) = diaganyzero(iszero, ldlt(S).data)
issingular(T::Tridiagonal) = !issuccess(lu(A, check=false))

And perhaps as a fallback (which fulfills the promise of the docstring)

issingular(A::AbstractMatrix) = issingular(Matrix(A))
issingular(A::AbstractSparseMatrix) = !issuccess(lu(A, check=false))

issingular(A::Union{Hermitian,Symmetric}) = diaganyzero(bunchkaufman(A, check=false).LD)
issingular(A::Union{LowerTriangular,UpperTriangular}) = diaganyzero(A.data)
issingular(A::Union{UnitLowerTriangular,UnitUpperTriangular}) = false
diaganyzero(A) = any(iszero, view(A, diagind(A)))

"""
findstructralnz(x::AbstractArray)

Expand Down
18 changes: 18 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,21 @@ using SuiteSparse
end
@test lu_instance(1) === 1
end

using Random
using ArrayInterface: issingular
@testset "issingular" begin
for T in [Float64, ComplexF64]
R = randn(MersenneTwister(2), T, 5, 5)
S = Symmetric(R)
L = UpperTriangular(R)
U = LowerTriangular(R)
@test all(!issingular, [R, S, L, U])
R[:, 2] .= 0
@test all(issingular, [R, L, U])
@test !issingular(S)
R[2, :] .= 0
@test issingular(S)
@test all(!issingular, [UnitLowerTriangular(R), UnitUpperTriangular(R)])
end
end