@@ -997,16 +997,14 @@ julia> sparse(Is, Js, Vs)
997
997
⋅ ⋅ 3
998
998
```
999
999
"""
1000
- sparse (I:: AbstractVector{Ti} , J:: AbstractVector{Ti} , V:: AbstractVector{Tv} , m:: Integer , n:: Integer , combine) where {Tv,Ti<: Integer } =
1001
- _sparse (I, J, V, m, n, combine)
1002
-
1003
- function _sparse (I:: AbstractVector{Ti} , J:: AbstractVector{Ti} , V:: Union{Tv,AbstractVector{Tv}} , m:: Integer , n:: Integer , combine) where {Tv,Ti<: Integer }
1000
+ function sparse (I:: AbstractVector{Ti} , J:: AbstractVector{Ti} , V:: AbstractVector{Tv} , m:: Integer , n:: Integer , combine) where {Tv,Ti<: Integer }
1004
1001
require_one_based_indexing (I, J, V)
1005
1002
coolen = length (I)
1006
- length (J) == coolen || throw (ArgumentError (" J (= $(length (J)) ) need length == length(I) = $coolen " ))
1007
- only_sparsity_pattern = (V isa Tv && iszero (V)) # We can use an optimised version if we only care about the sparsity pattern (and not the values)
1008
- only_sparsity_pattern || length (V) == coolen || throw (ArgumentError (" V (= $(length (V)) ) need length == length(I) = $coolen " ))
1009
-
1003
+ if length (J) != coolen || length (V) != coolen
1004
+ throw (ArgumentError (string (" the first three arguments' lengths must match, " ,
1005
+ " length(I) (=$(length (I)) ) == length(J) (= $(length (J)) ) == length(V) (= " ,
1006
+ " $(length (V)) )" )))
1007
+ end
1010
1008
if Base. hastypemax (Ti) && coolen >= typemax (Ti)
1011
1009
throw (ArgumentError (" the index type $Ti cannot hold $coolen elements; use a larger index type" ))
1012
1010
end
@@ -1023,7 +1021,7 @@ function _sparse(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::Union{Tv,Abstr
1023
1021
# Allocate storage for CSR form
1024
1022
csrrowptr = Vector {Ti} (undef, m+ 1 )
1025
1023
csrcolval = Vector {Ti} (undef, coolen)
1026
- csrnzval = Vector {Tv} (undef, only_sparsity_pattern ? 0 : coolen)
1024
+ csrnzval = Vector {Tv} (undef, coolen)
1027
1025
1028
1026
# Allocate storage for the CSC form's column pointers and a necessary workspace
1029
1027
csccolptr = Vector {Ti} (undef, n+ 1 )
@@ -1091,15 +1089,21 @@ F. Gustavson, "Two fast algorithms for sparse matrices: multiplication and permu
1091
1089
transposition," ACM TOMS 4(3), 250-269 (1978) inspired this method's use of a pair of
1092
1090
counting sorts.
1093
1091
"""
1094
- function sparse! (I:: AbstractVector{Ti} , J:: AbstractVector{Ti} , V:: Union{Tv, AbstractVector{Tv}} ,
1092
+ function sparse! (I:: AbstractVector{Ti} , J:: AbstractVector{Ti} , V:: AbstractVector{Tv} ,
1095
1093
m:: Integer , n:: Integer , combine, klasttouch:: Vector{Tj} ,
1096
1094
csrrowptr:: Vector{Tj} , csrcolval:: Vector{Ti} , csrnzval:: Vector{Tv} ,
1097
1095
csccolptr:: Vector{Ti} , cscrowval:: Vector{Ti} , cscnzval:: Vector{Tv} ) where {Tv,Ti<: Integer ,Tj<: Integer }
1098
1096
1099
1097
require_one_based_indexing (I, J, V)
1100
1098
sparse_check_Ti (m, n, Ti)
1101
1099
sparse_check_length (" I" , I, 0 , Tj)
1102
- only_sparsity_pattern = (V isa Tv && iszero (V)) # We can use an optimised version if we only care about the sparsity pattern (and not the values)
1100
+
1101
+ # This method is also used internally by spzeros! to build the sparsity pattern without
1102
+ # caring about the values. This is communicated by passing combine=nothing and in this
1103
+ # case V and csrnzval should *not* be accessed. When called from spzeros! they will both
1104
+ # alias cscnzval, which will be resized and filled with zero(Tv).
1105
+ only_sparsity_pattern = combine === nothing
1106
+
1103
1107
# Compute the CSR form's row counts and store them shifted forward by one in csrrowptr
1104
1108
fill! (csrrowptr, Tj (0 ))
1105
1109
coolen = length (I)
@@ -1168,11 +1172,9 @@ function sparse!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::Union{Tv,Abstr
1168
1172
end
1169
1173
writek += Tj (1 )
1170
1174
csccolptr[j+ 1 ] += Ti (1 )
1171
- else
1175
+ elseif ! only_sparsity_pattern
1172
1176
klt = klasttouch[j]
1173
- if ! only_sparsity_pattern
1174
- csrnzval[klt] = combine (csrnzval[klt], csrnzval[readk])
1175
- end
1177
+ csrnzval[klt] = combine (csrnzval[klt], csrnzval[readk])
1176
1178
end
1177
1179
end
1178
1180
newcsrrowptri = writek
@@ -2031,14 +2033,49 @@ Create a sparse matrix `S` of dimensions `m x n` with structural zeros at `S[I[k
2031
2033
This method can be used to construct the sparsity pattern of the matrix, and is more
2032
2034
efficient than using e.g. `sparse(I, J, zeros(length(I)))`.
2033
2035
2036
+ For additional documentation and an expert driver, see `SparseArrays.spzeros!`.
2037
+
2034
2038
!!! compat "Julia 1.10"
2035
2039
This methods requires Julia version 1.10 or later.
2036
2040
"""
2037
2041
spzeros (I:: AbstractVector , J:: AbstractVector ) = spzeros (Float64, I, J)
2038
2042
spzeros (I:: AbstractVector , J:: AbstractVector , m:: Integer , n:: Integer ) = spzeros (Float64, I, J, m, n)
2039
2043
spzeros (:: Type{Tv} , I:: AbstractVector , J:: AbstractVector ) where {Tv} = spzeros (Tv, I, J, dimlub (I), dimlub (J))
2040
- spzeros (:: Type{Tv} , I:: AbstractVector , J:: AbstractVector , m:: Integer , n:: Integer ) where {Tv} =
2041
- _sparse (I, J, zero (Tv), Int (m), Int (n), + )
2044
+ function spzeros (:: Type{Tv} , I:: AbstractVector , J:: AbstractVector , m:: Integer , n:: Integer ) where {Tv}
2045
+ return spzeros (Tv, AbstractVector {Int} (I), AbstractVector {Int} (J), m, n)
2046
+ end
2047
+ function spzeros (:: Type{Tv} , I:: AbstractVector{Ti} , J:: AbstractVector{Ti} , m:: Integer , n:: Integer ) where {Tv, Ti<: Integer }
2048
+ if length (I) != length (J)
2049
+ throw (ArgumentError (" length(I) = $(length (I)) does not match length(J) = $(length (J)) " ))
2050
+ end
2051
+ klasttouch = Vector {Ti} (undef, n)
2052
+ csrrowptr = Vector {Ti} (undef, m+ 1 )
2053
+ csrcolval = Vector {Ti} (undef, length (I))
2054
+ return spzeros! (Tv, I, J, m, n, klasttouch, csrrowptr, csrcolval)
2055
+ end
2056
+
2057
+ """
2058
+ spzeros!(::Type{Tv}, I::AbstractVector{Ti}, J::AbstractVector{Ti}, m::Integer, n::Integer,
2059
+ klasttouch::Vector{Ti}, csrrowptr::Vector{Ti}, csrcolval::Vector{Ti},
2060
+ [csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}]) where {Tv,Ti<:Integer}
2061
+
2062
+ Parent of and expert driver for `spzeros(I, J)` allowing user to provide preallocated
2063
+ storage for intermediate objects. This method is to `spzeros` what `SparseArrays.sparse!` is
2064
+ to `sparse`. See documentation for `SparseArrays.sparse!` for details and required buffer
2065
+ lengths.
2066
+
2067
+ !!! compat "Julia 1.10"
2068
+ This methods requires Julia version 1.10 or later.
2069
+ """
2070
+ function spzeros! (:: Type{Tv} , I:: AbstractVector{Ti} , J:: AbstractVector{Ti} , m:: Integer , n:: Integer ,
2071
+ klasttouch:: Vector{Ti} , csrrowptr:: Vector{Ti} , csrcolval:: Vector{Ti} ,
2072
+ csccolptr:: Vector{Ti} = Ti[], cscrowval:: Vector{Ti} = Ti[], cscnzval:: Vector{Tv} = Tv[]
2073
+ ) where {Tv, Ti<: Integer }
2074
+ # We can pass V = csrnzval = cscnzval since V and csrnzval are unused in sparse! if used
2075
+ # to only build the sparsity pattern (which is indicated by passing combine=nothing).
2076
+ return sparse! (I, J, cscnzval, m, n, nothing , klasttouch,
2077
+ csrrowptr, csrcolval, cscnzval, csccolptr, cscrowval, cscnzval)
2078
+ end
2042
2079
2043
2080
import Base. _one
2044
2081
function Base. _one (unit:: T , S:: AbstractSparseMatrixCSC ) where T
0 commit comments