4
4
5
5
import Base: sort!, findall, copy!
6
6
import LinearAlgebra: promote_to_array_type, promote_to_arrays_
7
- using LinearAlgebra: adj_or_trans
7
+
8
+ using LinearAlgebra: adj_or_trans, _SpecialArrays, _DenseConcatGroup
8
9
9
10
# ## The SparseVector
10
11
@@ -1175,10 +1176,24 @@ function _absspvec_vcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti}
1175
1176
SparseVector (len, rnzind, rnzval)
1176
1177
end
1177
1178
1179
+ hcat (Xin:: Union{Vector, AbstractSparseVector} ...) = hcat (map (sparse, Xin)... )
1180
+ vcat (Xin:: Union{Vector, AbstractSparseVector} ...) = vcat (map (sparse, Xin)... )
1181
+
1178
1182
# ## Concatenation of un/annotated sparse/special/dense vectors/matrices
1179
- # by type-pirating and subverting the Base.cat design by making these a subtype of the normal methods for it
1180
- # and re-defining all of it here. See https://github.com/JuliaLang/julia/issues/2326
1181
- # for what would have been a more principled way of doing this.
1183
+
1184
+ const _SparseArrays = Union{AbstractSparseVector,
1185
+ AbstractSparseMatrixCSC,
1186
+ Adjoint{<: Any ,<: AbstractSparseVector },
1187
+ Transpose{<: Any ,<: AbstractSparseVector }}
1188
+ const _SparseConcatArrays = Union{_SpecialArrays, _SparseArrays}
1189
+
1190
+ const _Symmetric_SparseConcatArrays = Symmetric{<: Any ,<: _SparseConcatArrays }
1191
+ const _Hermitian_SparseConcatArrays = Hermitian{<: Any ,<: _SparseConcatArrays }
1192
+ const _Triangular_SparseConcatArrays = UpperOrLowerTriangular{<: Any ,<: _SparseConcatArrays }
1193
+ const _Annotated_SparseConcatArrays = Union{_Triangular_SparseConcatArrays, _Symmetric_SparseConcatArrays, _Hermitian_SparseConcatArrays}
1194
+ # It's important that _SparseConcatGroup is a larger union than _DenseConcatGroup to make
1195
+ # sparse cat-methods less specific and to kick in only if there is some sparse array present
1196
+ const _SparseConcatGroup = Union{_DenseConcatGroup, _SparseConcatArrays, _Annotated_SparseConcatArrays}
1182
1197
1183
1198
# Concatenations involving un/annotated sparse/special matrices/vectors should yield sparse arrays
1184
1199
@@ -1190,55 +1205,23 @@ _sparse(A) = _makesparse(A)
1190
1205
_makesparse (x:: Number ) = x
1191
1206
_makesparse (x:: AbstractVector ) = convert (SparseVector, issparse (x) ? x : sparse (x)):: SparseVector
1192
1207
_makesparse (x:: AbstractMatrix ) = convert (SparseMatrixCSC, issparse (x) ? x : sparse (x)):: SparseMatrixCSC
1193
- anysparse () = false
1194
- anysparse (X) = X isa AbstractArray && issparse (X)
1195
- anysparse (X, Xs... ) = anysparse (X) || anysparse (Xs... )
1196
-
1197
- function hcat (X:: Union{Vector, AbstractSparseVector} ...)
1198
- if anysparse (X... )
1199
- X = map (sparse, X)
1200
- end
1201
- return cat (X... ; dims= Val (2 ))
1202
- end
1203
- function vcat (X:: Union{Vector, AbstractSparseVector} ...)
1204
- if anysparse (X... )
1205
- X = map (sparse, X)
1206
- end
1207
- return cat (X... ; dims= Val (1 ))
1208
- end
1209
-
1210
- # type-pirate the Base.cat design by making this a subtype of the existing method for it
1211
- # in future versions of Julia (v1.10+), in which https://github.com/JuliaLang/julia/issues/2326 is not fixed yet, the <:Number constraint could be relaxed
1212
- # but see also https://github.com/JuliaSparse/SparseArrays.jl/issues/71
1213
- const _SparseConcatGroup = Union{AbstractVecOrMat{<: Number },Number}
1214
1208
1215
1209
# `@constprop :aggressive` allows `dims` to be propagated as constant improving return type inference
1216
- Base. @constprop :aggressive function Base. _cat (dims, X:: _SparseConcatGroup... )
1217
- T = promote_eltype (X... )
1218
- if anysparse (X... )
1219
- X = (_sparse (first (X)), map (_makesparse, Base. tail (X))... )
1220
- end
1210
+ Base. @constprop :aggressive function Base. _cat (dims, Xin:: _SparseConcatGroup... )
1211
+ X = (_sparse (first (Xin)), map (_makesparse, Base. tail (Xin))... )
1212
+ T = promote_eltype (Xin... )
1221
1213
return Base. _cat_t (dims, T, X... )
1222
1214
end
1223
- function hcat (X:: _SparseConcatGroup... )
1224
- if anysparse (X... )
1225
- X = (_sparse (first (X)), map (_makesparse, Base. tail (X))... )
1226
- end
1215
+ function hcat (Xin:: _SparseConcatGroup... )
1216
+ X = (_sparse (first (Xin)), map (_makesparse, Base. tail (Xin))... )
1227
1217
return cat (X... , dims= Val (2 ))
1228
1218
end
1229
- function vcat (X:: _SparseConcatGroup... )
1230
- if anysparse (X... )
1231
- X = (_sparse (first (X)), map (_makesparse, Base. tail (X))... )
1232
- end
1219
+ function vcat (Xin:: _SparseConcatGroup... )
1220
+ X = (_sparse (first (Xin)), map (_makesparse, Base. tail (Xin))... )
1233
1221
return cat (X... , dims= Val (1 ))
1234
1222
end
1235
- function hvcat (rows:: Tuple{Vararg{Int}} , X:: _SparseConcatGroup... )
1236
- if anysparse (X... )
1237
- vcat (_hvcat_rows (rows, X... )... )
1238
- else
1239
- typed_hvcat (promote_eltypeof (X... ), rows, X... )
1240
- end
1241
- end
1223
+ hvcat (rows:: Tuple{Vararg{Int}} , X:: _SparseConcatGroup... ) =
1224
+ vcat (_hvcat_rows (rows, X... )... )
1242
1225
function _hvcat_rows ((row1, rows... ):: Tuple{Vararg{Int}} , X:: _SparseConcatGroup... )
1243
1226
if row1 ≤ 0
1244
1227
throw (ArgumentError (" length of block row must be positive, got $row1 " ))
@@ -1255,7 +1238,7 @@ end
1255
1238
_hvcat_rows (:: Tuple{} , X:: _SparseConcatGroup... ) = ()
1256
1239
1257
1240
# make sure UniformScaling objects are converted to sparse matrices for concatenation
1258
- promote_to_array_type (A:: Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}} ) = anysparse (A ... ) ? SparseMatrixCSC : Matrix
1241
+ promote_to_array_type (A:: Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}} ) = SparseMatrixCSC
1259
1242
promote_to_arrays_ (n:: Int , :: Type{SparseMatrixCSC} , J:: UniformScaling ) = sparse (J, n, n)
1260
1243
1261
1244
"""
0 commit comments