diff --git a/src/higherorderfns.jl b/src/higherorderfns.jl index 04166135..4a6d269b 100644 --- a/src/higherorderfns.jl +++ b/src/higherorderfns.jl @@ -1387,6 +1387,12 @@ _densifysparse(x) = x _sparsifystructured(M::AbstractMatrix) = _isdenselike(M) ? _fullystored(M) : SparseMatrixCSC(M) _sparsifystructured(V::AbstractVector) = _isdenselike(V) ? _fullystored(V) : SparseVector(V) _sparsifystructured(S::SparseVecOrMat) = S +# stores the whole diagonal, as for the other banded types: a kernel that read a `-0.0` there +# as a structural zero would lose its sign +function _sparsifystructured(D::Diagonal) + n = size(D, 1) + return SparseMatrixCSC(n, n, collect(1:(n + 1)), collect(1:n), copyto!(Vector{eltype(D)}(undef, n), D.diag)) +end _sparsifystructured(S::SparseViewOfColumns) = copy(S) _sparsifystructured(x) = x diff --git a/test/higherorderfns.jl b/test/higherorderfns.jl index f64a71a7..7779345e 100644 --- a/test/higherorderfns.jl +++ b/test/higherorderfns.jl @@ -857,6 +857,8 @@ end # wrappers and banded matrices count as sparse arguments @test cos.(S')::Matrix{Float64} == cos.(fS') @test isequal((S[1:2, :] ./ Diagonal([1.0, 2.0]))::Matrix{Float64}, fS[1:2, :] ./ Diagonal([1.0, 2.0])) + # a `-0.0` on the diagonal keeps its sign + @test isequal(Array(sparse(ones(2, 2)) ./ Diagonal([-0.0, 1.0])), ones(2, 2) ./ Diagonal([-0.0, 1.0])) # `map` and a sparse destination keep the result sparse @test map(cos, S)::SparseMatrixCSC == cos.(fS) @test broadcast!(cos, similar(S), S)::SparseMatrixCSC == cos.(fS)