@@ -40,6 +40,7 @@ const AdjOrTransSparseVectorUnion{Tv,Ti} = LinearAlgebra.AdjOrTrans{Tv, <:Sparse
4040
4141# ## Basic properties
4242
43+ length (x:: SparseVector ) = getfield (x, :n )
4344size (x:: SparseVector ) = (getfield (x, :n ),)
4445count (f, x:: SparseVector ) = count (f, nonzeros (x)) + f (zero (eltype (x)))* (length (x) - nnz (x))
4546
@@ -1075,20 +1076,27 @@ const _Annotated_SparseConcatArrays = Union{_Triangular_SparseConcatArrays, _Sym
10751076const _SparseConcatGroup = Union{_DenseConcatGroup, _SparseConcatArrays, _Annotated_SparseConcatArrays}
10761077
10771078# Concatenations involving un/annotated sparse/special matrices/vectors should yield sparse arrays
1079+
1080+ # the output array type is determined by the first element of the to be concatenated objects
1081+ # if this is a Number, the output would be dense by the fallback abstractarray.jl code (see cat_similar)
1082+ # so make sure that if that happens, the "array" is sparse (if more sparse arrays are involved, of course)
1083+ _sparse (x:: Number ) = sparsevec ([1 ], [x], 1 )
1084+ _sparse (A) = _makesparse (A)
10781085_makesparse (x:: Number ) = x
1079- _makesparse (x:: AbstractArray ) = SparseMatrixCSC (issparse (x) ? x : sparse (x))
1086+ _makesparse (x:: AbstractVector ) = convert (SparseVector, issparse (x) ? x : sparse (x)):: SparseVector
1087+ _makesparse (x:: AbstractMatrix ) = convert (SparseMatrixCSC, issparse (x) ? x : sparse (x)):: SparseMatrixCSC
10801088
10811089function Base. _cat (dims, Xin:: _SparseConcatGroup... )
1082- X = map (_makesparse, Xin)
1090+ X = ( _sparse ( first (Xin)), map (_makesparse, Base . tail ( Xin)) ... )
10831091 T = promote_eltype (Xin... )
10841092 Base. cat_t (T, X... ; dims= dims)
10851093end
10861094function hcat (Xin:: _SparseConcatGroup... )
1087- X = map (_makesparse, Xin)
1095+ X = ( _sparse ( first (Xin)), map (_makesparse, Base . tail ( Xin)) ... )
10881096 return cat (X... , dims= Val (2 ))
10891097end
10901098function vcat (Xin:: _SparseConcatGroup... )
1091- X = map (_makesparse, Xin)
1099+ X = ( _sparse ( first (Xin)), map (_makesparse, Base . tail ( Xin)) ... )
10921100 return cat (X... , dims= Val (1 ))
10931101end
10941102hvcat (rows:: Tuple{Vararg{Int}} , X:: _SparseConcatGroup... ) =
@@ -1122,9 +1130,9 @@ Concatenate along dimension 2. Return a SparseMatrixCSC object.
11221130 the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl
11231131 automatically yielded sparse output even in the absence of any SparseArray argument.
11241132"""
1125- sparse_hcat (Xin:: Union{AbstractVecOrMat,Number} ...) = cat (map (_makesparse, Xin)... , dims= Val (2 ))
1133+ sparse_hcat (Xin:: Union{AbstractVecOrMat,Number} ...) = cat (_sparse ( first (Xin)), map (_makesparse, Base . tail ( Xin) )... , dims= Val (2 ))
11261134function sparse_hcat (X:: Union{AbstractVecOrMat,UniformScaling,Number} ...)
1127- LinearAlgebra. _hcat (X ... ; array_type = SparseMatrixCSC)
1135+ LinearAlgebra. _hcat (_sparse ( first (X)), map (_makesparse, Base . tail (X)) ... ; array_type = SparseMatrixCSC)
11281136end
11291137
11301138"""
@@ -1137,9 +1145,9 @@ Concatenate along dimension 1. Return a SparseMatrixCSC object.
11371145 the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl
11381146 automatically yielded sparse output even in the absence of any SparseArray argument.
11391147"""
1140- sparse_vcat (Xin:: Union{AbstractVecOrMat,Number} ...) = cat (map (_makesparse, Xin)... , dims= Val (1 ))
1148+ sparse_vcat (Xin:: Union{AbstractVecOrMat,Number} ...) = cat (_sparse ( first (Xin)), map (_makesparse, Base . tail ( Xin) )... , dims= Val (1 ))
11411149function sparse_vcat (X:: Union{AbstractVecOrMat,UniformScaling,Number} ...)
1142- LinearAlgebra. _vcat (X ... ; array_type = SparseMatrixCSC)
1150+ LinearAlgebra. _vcat (_sparse ( first (X)), map (_makesparse, Base . tail (X)) ... ; array_type = SparseMatrixCSC)
11431151end
11441152
11451153"""
@@ -1155,10 +1163,10 @@ arguments to concatenate in each block row.
11551163 automatically yielded sparse output even in the absence of any SparseArray argument.
11561164"""
11571165function sparse_hvcat (rows:: Tuple{Vararg{Int}} , Xin:: Union{AbstractVecOrMat,Number} ...)
1158- hvcat (rows, map (_makesparse, Xin)... )
1166+ hvcat (rows, _sparse ( first (Xin)), map (_makesparse, Base . tail ( Xin) )... )
11591167end
11601168function sparse_hvcat (rows:: Tuple{Vararg{Int}} , X:: Union{AbstractVecOrMat,UniformScaling,Number} ...)
1161- LinearAlgebra. _hvcat (rows, X ... ; array_type = SparseMatrixCSC)
1169+ LinearAlgebra. _hvcat (rows, _sparse ( first (X)), map (_makesparse, Base . tail (X)) ... ; array_type = SparseMatrixCSC)
11621170end
11631171
11641172# ## math functions
@@ -1434,7 +1442,12 @@ for (fun, comp, word) in ((:findmin, :(<), "minimum"), (:findmax, :(>), "maximum
14341442 # we try to avoid findfirst(iszero, x)
14351443 sindex = findfirst (iszero, nzvals) # first stored zero, if any
14361444 zindex = findfirst (i -> i < nzinds[i], eachindex (nzinds)) # first non-stored zero
1437- index = isnothing (sindex) ? zindex : min (sindex, zindex)
1445+ index = if isnothing (sindex)
1446+ # non-stored zero are contiguous and at the end
1447+ isnothing (zindex) && last (nzinds) < lastindex (x) ? last (nzinds) + 1 : zindex
1448+ else
1449+ min (sindex, zindex)
1450+ end
14381451 return zeroval, index
14391452 end
14401453end
@@ -2120,8 +2133,8 @@ function subvector_shifter!(R::AbstractVector, V::AbstractVector, start::Integer
21202133 end
21212134 end
21222135 # ...but rowval should be sorted within columns
2123- circshift! (@view (R[start: fin]), split- start+ 1 )
2124- circshift! (@view (V[start: fin]), split- start+ 1 )
2136+ circshift! (@view (R[start: fin]), (CIRCSHIFT_WRONG_DIRECTION ? ( + ) : ( - ))( split- start+ 1 ) )
2137+ circshift! (@view (V[start: fin]), (CIRCSHIFT_WRONG_DIRECTION ? ( + ) : ( - ))( split- start+ 1 ) )
21252138end
21262139
21272140function circshift! (O:: SparseVector , X:: SparseVector , (r,):: Base.DimsInteger{1} )
0 commit comments