@@ -203,15 +203,25 @@ end
203
203
return SparseArrayDOK {T} (size... )
204
204
end
205
205
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
+
206
218
# Only map the stored values of the inputs.
207
219
function map_stored! end
208
220
209
221
@interface interface:: AbstractArrayInterface function map_stored! (
210
222
f, a_dest:: AbstractArray , as:: AbstractArray...
211
223
)
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... )
215
225
return a_dest
216
226
end
217
227
@@ -221,9 +231,7 @@ function map_all! end
221
231
@interface interface:: AbstractArrayInterface function map_all! (
222
232
f, a_dest:: AbstractArray , as:: AbstractArray...
223
233
)
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... )
227
235
return a_dest
228
236
end
229
237
@@ -242,38 +250,32 @@ using ArrayLayouts: ArrayLayouts, zero!
242
250
return @interface interface map_stored! (f, a, a)
243
251
end
244
252
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
+
245
266
@interface interface:: AbstractSparseArrayInterface function Base. map! (
246
267
f, a_dest:: AbstractArray , as:: AbstractArray...
247
268
)
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)
263
277
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... )
277
279
return a_dest
278
280
end
279
281
@@ -357,9 +359,7 @@ function sparse_mul!(
357
359
β:: Number = false ;
358
360
(mul!!)= (default_mul!!),
359
361
)
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 .*= β
363
363
β′ = one (Bool)
364
364
for I1 in eachstoredindex (a1)
365
365
for I2 in eachstoredindex (a2)
0 commit comments