Skip to content

Commit

Permalink
Make general concatenations (cat) of combinations of sparse matrice…
Browse files Browse the repository at this point in the history
…s with sparse matrices or dense matrices/vectors yield sparse arrays (fixes JuliaLang#17680).
  • Loading branch information
Sacha0 authored and mfasi committed Sep 5, 2016
1 parent ba20966 commit 788e01e
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 11 deletions.
2 changes: 1 addition & 1 deletion base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ function cat_t(catdims, typeC::Type, X...)
end
end

C = similar(isa(X[1],AbstractArray) ? full(X[1]) : [X[1]], typeC, tuple(dimsC...))
C = similar(isa(X[1],AbstractArray) ? X[1] : [X[1]], typeC, tuple(dimsC...))
if length(catdims)>1
fill!(C,0)
end
Expand Down
3 changes: 3 additions & 0 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,9 @@ hvcat{T}(rows::Tuple{Vararg{Int}}, xs::Vector{T}...) = typed_hvcat(T, rows, xs..
hvcat(rows::Tuple{Vararg{Int}}, xs::Matrix...) = typed_hvcat(promote_eltype(xs...), rows, xs...)
hvcat{T}(rows::Tuple{Vararg{Int}}, xs::Matrix{T}...) = typed_hvcat(T, rows, xs...)

cat(catdims, xs::Union{Matrix,Vector}...) = Base.cat_t(catdims, promote_eltype(xs...), xs...)
cat{T}(catdims, xs::Union{Matrix{T},Vector{T}}...) = Base.cat_t(catdims, T, xs...)

## find ##

# returns the index of the next non-zero element, or 0 if all zeros
Expand Down
4 changes: 2 additions & 2 deletions base/sparse/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh,
tand, tanh, trace, transpose!, tril!, triu!, trunc, vecnorm, abs, abs2,
broadcast, ceil, complex, cond, conj, convert, copy, copy!, ctranspose, diagm,
exp, expm1, factorize, find, findmax, findmin, findnz, float, full, getindex,
hcat, hvcat, imag, indmax, ishermitian, kron, length, log, log1p, max, min,
vcat, hcat, hvcat, cat, imag, indmax, ishermitian, kron, length, log, log1p, max, min,
maximum, minimum, norm, one, promote_eltype, real, reinterpret, reshape, rot180,
rotl90, rotr90, round, scale!, setindex!, similar, size, transpose, tril,
triu, vcat, vec, permute!
triu, vec, permute!

import Base.Broadcast: broadcast_shape

Expand Down
6 changes: 6 additions & 0 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3253,6 +3253,12 @@ function hvcat(rows::Tuple{Vararg{Int}}, X::Union{Vector, Matrix, SparseMatrixCS
vcat(tmp_rows...)
end

function cat(catdims, Xin::Union{Vector, Matrix, SparseMatrixCSC}...)
X = SparseMatrixCSC[issparse(x) ? x : sparse(x) for x in Xin]
T = promote_eltype(Xin...)
Base.cat_t(catdims, T, X...)
end

"""
blkdiag(A...)
Expand Down
32 changes: 24 additions & 8 deletions test/sparsedir/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1554,14 +1554,30 @@ end
@inferred sprand(1, 1, 1.0, rand, Float64)
@inferred sprand(1, 1, 1.0, x->round(Int,rand(x)*100))

# dense sparse concatenation -> sparse return type
@test issparse([sprand(10,10,.1) rand(10,10)])
@test issparse([sprand(10,10,.1); rand(10,10)])
@test issparse([sprand(10,10,.1) rand(10,10); rand(10,10) rand(10,10)])
# ---
@test !issparse([rand(10,10) rand(10,10)])
@test !issparse([rand(10,10); rand(10,10)])
@test !issparse([rand(10,10) rand(10,10); rand(10,10) rand(10,10)])
# Test that concatenations of combinations of sparse matrices with sparse matrices or dense
# matrices/vectors yield sparse arrays
let
N = 4
densevec = ones(N)
densemat = diagm(ones(N))
spmat = spdiagm(ones(N))
# Test that concatenations of pairs of sparse matrices yield sparse arrays
@test issparse(vcat(spmat, spmat))
@test issparse(hcat(spmat, spmat))
@test issparse(hvcat((2,), spmat, spmat))
@test issparse(cat((1,2), spmat, spmat))
# Test that concatenations of a sparse matrice with a dense matrix/vector yield sparse arrays
@test issparse(vcat(spmat, densemat))
@test issparse(vcat(densemat, spmat))
for densearg in (densevec, densemat)
@test issparse(hcat(spmat, densearg))
@test issparse(hcat(densearg, spmat))
@test issparse(hvcat((2,), spmat, densearg))
@test issparse(hvcat((2,), densearg, spmat))
@test issparse(cat((1,2), spmat, densearg))
@test issparse(cat((1,2), densearg, spmat))
end
end

# issue #14816
let m = 5
Expand Down

0 comments on commit 788e01e

Please sign in to comment.