@@ -203,15 +203,25 @@ end
203203 return SparseArrayDOK {T} (size... )
204204end
205205
206+ # map over a specified subset of indices of the inputs.
207+ function map_indices! end
208+
209+ @interface interface:: AbstractArrayInterface function map_indices! (
210+ indices, f, a_dest:: AbstractArray , as:: AbstractArray...
211+ )
212+ for I in indices
213+ a_dest[I] = f (map (a -> a[I], as)... )
214+ end
215+ return a_dest
216+ end
217+
206218# Only map the stored values of the inputs.
207219function map_stored! end
208220
209221@interface interface:: AbstractArrayInterface function map_stored! (
210222 f, a_dest:: AbstractArray , as:: AbstractArray...
211223)
212- for I in eachstoredindex (as... )
213- a_dest[I] = f (map (a -> a[I], as)... )
214- end
224+ @interface interface map_indices! (eachstoredindex (as... ), f, a_dest, as... )
215225 return a_dest
216226end
217227
@@ -221,9 +231,7 @@ function map_all! end
221231@interface interface:: AbstractArrayInterface function map_all! (
222232 f, a_dest:: AbstractArray , as:: AbstractArray...
223233)
224- for I in eachindex (as... )
225- a_dest[I] = map (f, map (a -> a[I], as)... )
226- end
234+ @interface interface map_indices! (eachindex (as... ), f, a_dest, as... )
227235 return a_dest
228236end
229237
@@ -242,38 +250,32 @@ using ArrayLayouts: ArrayLayouts, zero!
242250 return @interface interface map_stored! (f, a, a)
243251end
244252
253+ # Determines if a function preserves the stored values
254+ # of the destination sparse array.
255+ # The current code may be inefficient since it actually
256+ # accesses an unstored element, which in the case of a
257+ # sparse array of arrays can allocate an array.
258+ # Sparse arrays could be expected to define a cheap
259+ # unstored element allocator, for example
260+ # `get_prototypical_unstored(a::AbstractArray)`.
261+ function preserves_unstored (f, a_dest:: AbstractArray , as:: AbstractArray... )
262+ I = first (eachindex (as... ))
263+ return iszero (f (map (a -> getunstoredindex (a, I), as)... ))
264+ end
265+
245266@interface interface:: AbstractSparseArrayInterface function Base. map! (
246267 f, a_dest:: AbstractArray , as:: AbstractArray...
247268)
248- # TODO : Define a function `preserves_unstored(a_dest, f, as...)`
249- # to determine if a function preserves the stored values
250- # of the destination sparse array.
251- # The current code may be inefficient since it actually
252- # accesses an unstored element, which in the case of a
253- # sparse array of arrays can allocate an array.
254- # Sparse arrays could be expected to define a cheap
255- # unstored element allocator, for example
256- # `get_prototypical_unstored(a::AbstractArray)`.
257- I = first (eachindex (as... ))
258- preserves_unstored = iszero (f (map (a -> getunstoredindex (a, I), as)... ))
259- if ! preserves_unstored
260- # Doesn't preserve unstored values, loop over all elements.
261- @interface interface map_all! (f, a_dest, as... )
262- return a_dest
269+ indices = if ! preserves_unstored (f, a_dest, as... )
270+ eachindex (a_dest)
271+ elseif any (a -> a_dest != = a, as)
272+ as = map (a -> Base. unalias (a_dest, a), as)
273+ @interface interface zero! (a_dest)
274+ eachstoredindex (as... )
275+ else
276+ eachstoredindex (a_dest)
263277 end
264- # First zero out the destination.
265- # TODO : Make this more nuanced, skip when possible, for
266- # example if the sparsity of the destination is a subset of
267- # the sparsity of the sources, i.e.:
268- # ```julia
269- # if eachstoredindex(as...) ∉ eachstoredindex(a_dest)
270- # zero!(a_dest)
271- # end
272- # ```
273- # This is the safest thing to do in general, for example
274- # if the destination is dense but the sources are sparse.
275- @interface interface zero! (a_dest)
276- @interface interface map_stored! (f, a_dest, as... )
278+ @interface interface map_indices! (indices, f, a_dest, as... )
277279 return a_dest
278280end
279281
@@ -357,9 +359,7 @@ function sparse_mul!(
357359 β:: Number = false ;
358360 (mul!!)= (default_mul!!),
359361)
360- # TODO : Change to: `a_dest .*= β`
361- # once https://github.com/ITensor/SparseArraysBase.jl/issues/19 is fixed.
362- storedvalues (a_dest) .*= β
362+ a_dest .*= β
363363 β′ = one (Bool)
364364 for I1 in eachstoredindex (a1)
365365 for I2 in eachstoredindex (a2)
0 commit comments