From 28a33122008fb33bf15c92be6b6b791fe1eb025a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 19 Apr 2021 05:27:08 -0400 Subject: [PATCH] [SparseArrays] similar on sparse matrix returned uninitialized space (#40444) Co-authored-by: Klaus Crusius --- stdlib/SparseArrays/src/sparsematrix.jl | 12 ++++++------ stdlib/SparseArrays/src/sparsevector.jl | 13 ++++++------- stdlib/SparseArrays/test/sparse.jl | 14 +++++++------- stdlib/SparseArrays/test/sparsevector.jl | 12 ++++++------ 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 7bd988d881152..888db226ddd14 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -469,17 +469,17 @@ function _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew} newrowval = copyto!(similar(rowvals(S), TiNew), rowvals(S)) return SparseMatrixCSC(size(S, 1), size(S, 2), newcolptr, newrowval, similar(nonzeros(S), TvNew)) end -# parent methods for similar that preserves only storage space (for when new and old dims differ) +# parent methods for similar that preserves only storage space (for when new dims are 2-d) _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{2}) where {TvNew,TiNew} = - SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(rowvals(S), TiNew), similar(nonzeros(S), TvNew)) -# parent method for similar that allocates an empty sparse vector (when new dims are single) + SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(rowvals(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) +# parent method for similar that allocates an empty sparse vector (for when new dims are 1-d) _sparsesimilar(S::AbstractSparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{1}) where {TvNew,TiNew} = SparseVector(dims..., similar(rowvals(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) -# + # The following methods hook into the AbstractArray similar hierarchy. The first method # covers similar(A[, Tv]) calls, which preserve stored-entry structure, and the latter -# methods cover similar(A[, Tv], shape...) calls, which preserve storage space when the shape -# calls for a two-dimensional result. +# methods cover similar(A[, Tv], shape...) calls, which partially preserve +# storage space when the shape calls for a two-dimensional result. similar(S::AbstractSparseMatrixCSC{<:Any,Ti}, ::Type{TvNew}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti) similar(S::AbstractSparseMatrixCSC{<:Any,Ti}, ::Type{TvNew}, dims::Union{Dims{1},Dims{2}}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti, dims) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 09696ab1e06c8..52142553e5019 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -89,25 +89,24 @@ indtype(x::SparseVectorView) = indtype(parent(x)) # parent method for similar that preserves stored-entry structure (for when new and old dims match) _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}) where {TvNew,TiNew} = SparseVector(length(S), copyto!(similar(nonzeroinds(S), TiNew), nonzeroinds(S)), similar(nonzeros(S), TvNew)) -# parent method for similar that preserves nothing (for when old and new dims differ, and new is 1d) +# parent method for similar that preserves nothing (for when new dims are 1-d) _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{1}) where {TvNew,TiNew} = SparseVector(dims..., similar(nonzeroinds(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) -# parent method for similar that preserves storage space (for old and new dims differ, and new is 2d) +# parent method for similar that preserves storage space (for when new dims are 2-d) _sparsesimilar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Dims{2}) where {TvNew,TiNew} = - SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(nonzeroinds(S), TiNew), similar(nonzeros(S), TvNew)) + SparseMatrixCSC(dims..., fill(one(TiNew), last(dims)+1), similar(nonzeroinds(S), TiNew, 0), similar(nonzeros(S), TvNew, 0)) + # The following methods hook into the AbstractArray similar hierarchy. The first method # covers similar(A[, Tv]) calls, which preserve stored-entry structure, and the latter # methods cover similar(A[, Tv], shape...) calls, which preserve nothing if the dims -# specify a SparseVector result and storage space if the dims specify a SparseMatrixCSC result. +# specify a SparseVector or a SparseMatrixCSC result. similar(S::SparseVector{<:Any,Ti}, ::Type{TvNew}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti) similar(S::SparseVector{<:Any,Ti}, ::Type{TvNew}, dims::Union{Dims{1},Dims{2}}) where {Ti,TvNew} = _sparsesimilar(S, TvNew, Ti, dims) # The following methods cover similar(A, Tv, Ti[, shape...]) calls, which specify the # result's index type in addition to its entry type, and aren't covered by the hooks above. -# The calls without shape again preserve stored-entry structure, whereas those with -# one-dimensional shape preserve nothing, and those with two-dimensional shape -# preserve storage space. +# The calls without shape again preserve stored-entry structure but no storage space. similar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}) where{TvNew,TiNew} = _sparsesimilar(S, TvNew, TiNew) similar(S::SparseVector, ::Type{TvNew}, ::Type{TiNew}, dims::Union{Dims{1},Dims{2}}) where {TvNew,TiNew} = diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index ef5159d41031d..a622d2bc8bcc0 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2487,22 +2487,22 @@ end @test typeof(simA) == typeof(A) @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(rowvals(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) - # test similar with entry type and Dims{2} specification (preserves storage space only) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 + # test similar with entry type and Dims{2} specification (empty storage space) simA = similar(A, Float32, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32,eltype(getcolptr(A))} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(rowvals(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with entry type, index type, and Dims{2} specification (preserves storage space only) simA = similar(A, Float32, Int8, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32, Int8} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(rowvals(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with Dims{1} specification (preserves nothing) simA = similar(A, (6,)) @test typeof(simA) == SparseVector{eltype(nonzeros(A)),eltype(getcolptr(A))} diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index e141deea40517..6d29633bb04e0 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -1424,22 +1424,22 @@ end @test typeof(simA) == SparseMatrixCSC{eltype(nonzeros(A)),eltype(nonzeroinds(A))} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(nonzeroinds(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with entry type and Dims{2} specification (preserves storage space only) simA = similar(A, Float32, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32,eltype(nonzeroinds(A))} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(nonzeroinds(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 # test similar with entry type, index type, and Dims{2} specification (preserves storage space only) simA = similar(A, Float32, Int8, (6,6)) @test typeof(simA) == SparseMatrixCSC{Float32, Int8} @test size(simA) == (6,6) @test getcolptr(simA) == fill(1, 6+1) - @test length(rowvals(simA)) == length(nonzeroinds(A)) - @test length(nonzeros(simA)) == length(nonzeros(A)) + @test length(rowvals(simA)) == 0 + @test length(nonzeros(simA)) == 0 end @testset "Fast operations on full column views" begin