From 8d3b328ea5a2b18222b8e23c6a6c9a0887392851 Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Sat, 9 Oct 2021 22:28:08 -0500 Subject: [PATCH 1/7] add path for empty structured matrices in sparse constructors --- stdlib/SparseArrays/src/sparsematrix.jl | 2 ++ stdlib/SparseArrays/test/sparse.jl | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index ea8a8f0b442e2..2d4e835ec3727 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -563,6 +563,7 @@ SparseMatrixCSC(M::Matrix) = sparse(M) SparseMatrixCSC(T::Tridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::Tridiagonal) where {Tv,Ti} m = length(T.d) + m == 0 && return SparseMatrixCSC{Tv,Ti}(zeros(Tv, 0, 0)) colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 @@ -593,6 +594,7 @@ end SparseMatrixCSC(T::SymTridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::SymTridiagonal) where {Tv,Ti} m = length(T.dv) + m == 0 && return SparseMatrixCSC{Tv,Ti}(zeros(Tv, 0, 0)) colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 128bb4735f063..2fe2121f52a33 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1699,6 +1699,16 @@ end @test S == S2 end +@testset "Sparse construction with empty structured matrices" begin + empty = sparse(zeros(0, 0)) + + @test sparse(Diagonal(zeros(0, 0))) == empty + @test sparse(Bidiagonal(zeros(0, 0), :U)) == empty + @test sparse(Bidiagonal(zeros(0, 0), :L)) == empty + @test sparse(SymTridiagonal(zeros(0, 0))) == empty + @test sparse(Tridiagonal(zeros(0, 0))) == empty +end + @testset "error conditions for reshape, and dropdims" begin local A = sprand(Bool, 5, 5, 0.2) @test_throws DimensionMismatch reshape(A,(20, 2)) From 67a66383a7394a2f376971a91618a439918e8a85 Mon Sep 17 00:00:00 2001 From: Marco Date: Sun, 10 Oct 2021 08:27:46 -0500 Subject: [PATCH 2/7] Update stdlib/SparseArrays/test/sparse.jl Co-authored-by: Daniel Karrasch --- stdlib/SparseArrays/test/sparse.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 2fe2121f52a33..d38115b1376ea 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1700,7 +1700,7 @@ end end @testset "Sparse construction with empty structured matrices" begin - empty = sparse(zeros(0, 0)) + empty = spzeros(0, 0) @test sparse(Diagonal(zeros(0, 0))) == empty @test sparse(Bidiagonal(zeros(0, 0), :U)) == empty From 9729d897ef88ef7df70649e219c6abeb47fe5db8 Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Tue, 12 Oct 2021 21:29:33 -0500 Subject: [PATCH 3/7] 1x1 tests --- stdlib/SparseArrays/src/sparsematrix.jl | 4 +++- stdlib/SparseArrays/test/sparse.jl | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 2d4e835ec3727..6883c25a48050 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -564,6 +564,7 @@ SparseMatrixCSC(T::Tridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::Tridiagonal) where {Tv,Ti} m = length(T.d) m == 0 && return SparseMatrixCSC{Tv,Ti}(zeros(Tv, 0, 0)) + m == 1 && return SparseMatrixCSC{Tv,Ti}(fill(T[1,1], (1,1))) colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 @@ -595,7 +596,8 @@ SparseMatrixCSC(T::SymTridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::SymTridiagonal) where {Tv,Ti} m = length(T.dv) m == 0 && return SparseMatrixCSC{Tv,Ti}(zeros(Tv, 0, 0)) - + m == 1 && return SparseMatrixCSC{Tv,Ti}(fill(T[1,1], (1,1))) + colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 @inbounds for i=1:m-1 diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index d38115b1376ea..764a61bd8e3c8 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1699,7 +1699,7 @@ end @test S == S2 end -@testset "Sparse construction with empty structured matrices" begin +@testset "Sparse construction with empty/1x1 structured matrices" begin empty = spzeros(0, 0) @test sparse(Diagonal(zeros(0, 0))) == empty @@ -1707,6 +1707,17 @@ end @test sparse(Bidiagonal(zeros(0, 0), :L)) == empty @test sparse(SymTridiagonal(zeros(0, 0))) == empty @test sparse(Tridiagonal(zeros(0, 0))) == empty + + one_by_one = rand(1,1) + sp_one_by_one = sparse(one_by_one) + + @test sparse(Diagonal(one_by_one)) == sp_one_by_one + @test sparse(Bidiagonal(one_by_one, :U)) == sp_one_by_one + @test sparse(Bidiagonal(one_by_one, :L)) == sp_one_by_one + @test sparse(Tridiagonal(one_by_one)) == sp_one_by_one + + s = SymTridiagonal(rand(1), rand(0)) + @test sparse(s) == s end @testset "error conditions for reshape, and dropdims" begin From 850436b57a6cd19d3a94b34974431f89882b3d5d Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Tue, 12 Oct 2021 21:51:56 -0500 Subject: [PATCH 4/7] reduce allocations --- stdlib/SparseArrays/src/sparsematrix.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 6883c25a48050..797ac0db20fed 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -563,7 +563,7 @@ SparseMatrixCSC(M::Matrix) = sparse(M) SparseMatrixCSC(T::Tridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::Tridiagonal) where {Tv,Ti} m = length(T.d) - m == 0 && return SparseMatrixCSC{Tv,Ti}(zeros(Tv, 0, 0)) + m == 0 && return SparseMatrixCSC{Tv,Ti}(0, 0, ones(Ti, 1), Ti[], Tv[]) m == 1 && return SparseMatrixCSC{Tv,Ti}(fill(T[1,1], (1,1))) colptr = Vector{Ti}(undef, m+1) @@ -595,9 +595,9 @@ end SparseMatrixCSC(T::SymTridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::SymTridiagonal) where {Tv,Ti} m = length(T.dv) - m == 0 && return SparseMatrixCSC{Tv,Ti}(zeros(Tv, 0, 0)) + m == 0 && return SparseMatrixCSC{Tv,Ti}(0, 0, ones(Ti, 1), Ti[], Tv[]) m == 1 && return SparseMatrixCSC{Tv,Ti}(fill(T[1,1], (1,1))) - + colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 @inbounds for i=1:m-1 @@ -627,7 +627,7 @@ end SparseMatrixCSC(B::Bidiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(B) function SparseMatrixCSC{Tv,Ti}(B::Bidiagonal) where {Tv,Ti} m = length(B.dv) - m == 0 && return SparseMatrixCSC{Tv,Ti}(zeros(Tv, 0, 0)) + m == 0 && return SparseMatrixCSC{Tv,Ti}(0, 0, ones(Ti, 1), Ti[], Tv[]) colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 From 11cdb16597e551d13e6725743bfd4d3be443fc73 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 13 Oct 2021 21:44:32 -0700 Subject: [PATCH 5/7] Update sparsematrix.jl --- stdlib/SparseArrays/src/sparsematrix.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 797ac0db20fed..2ea35de3fbcb0 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -656,7 +656,7 @@ end SparseMatrixCSC(D::Diagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(D) function SparseMatrixCSC{Tv,Ti}(D::Diagonal) where {Tv,Ti} m = length(D.diag) - return SparseMatrixCSC(m, m, Vector(1:(m+1)), Vector(1:m), Vector{Tv}(D.diag)) + return SparseMatrixCSC(m, m, Vector(Ti(1):Ti(m+1)), Vector(Ti(1):Ti(m)), Vector{Tv}(D.diag)) end SparseMatrixCSC(M::AbstractMatrix{Tv}) where {Tv} = SparseMatrixCSC{Tv,Int}(M) SparseMatrixCSC{Tv}(M::AbstractMatrix{Tv}) where {Tv} = SparseMatrixCSC{Tv,Int}(M) From df9d74e109dd0df0158a761b39b598452844b7e3 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 13 Oct 2021 23:46:26 -0500 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: Daniel Karrasch --- stdlib/SparseArrays/src/sparsematrix.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 2ea35de3fbcb0..da08e8a72981c 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -564,7 +564,7 @@ SparseMatrixCSC(T::Tridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::Tridiagonal) where {Tv,Ti} m = length(T.d) m == 0 && return SparseMatrixCSC{Tv,Ti}(0, 0, ones(Ti, 1), Ti[], Tv[]) - m == 1 && return SparseMatrixCSC{Tv,Ti}(fill(T[1,1], (1,1))) + m == 1 && return SparseMatrixCSC{Tv,Ti}(1, 1, Ti[1, 2], Ti[1], Tv[T.d[1]]) colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 @@ -596,7 +596,7 @@ SparseMatrixCSC(T::SymTridiagonal{Tv}) where Tv = SparseMatrixCSC{Tv,Int}(T) function SparseMatrixCSC{Tv,Ti}(T::SymTridiagonal) where {Tv,Ti} m = length(T.dv) m == 0 && return SparseMatrixCSC{Tv,Ti}(0, 0, ones(Ti, 1), Ti[], Tv[]) - m == 1 && return SparseMatrixCSC{Tv,Ti}(fill(T[1,1], (1,1))) + m == 1 && return SparseMatrixCSC{Tv,Ti}(1, 1, Ti[1, 2], Ti[1], Tv[T.dv[1]]) colptr = Vector{Ti}(undef, m+1) colptr[1] = 1 From 06adc305896f3266222fc52339db077f34dcf7f3 Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Wed, 13 Oct 2021 23:55:25 -0500 Subject: [PATCH 7/7] add test for SparseMatrixCSC{Tv, Ti}(::Diagonal) --- stdlib/SparseArrays/test/sparse.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 764a61bd8e3c8..ff955e967b433 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1697,6 +1697,12 @@ end S2 = SparseMatrixCSC(D) @test Array(D) == Array(S) == Array(S2) @test S == S2 + + # An issue discovered in #42574 where + # SparseMatrixCSC{Tv, Ti}(::Diagonal) ignored Ti + D = Diagonal(rand(3)) + S = SparseMatrixCSC{Float64, Int8}(D) + @test S isa SparseMatrixCSC{Float64, Int8} end @testset "Sparse construction with empty/1x1 structured matrices" begin