Skip to content

Commit a9d0c40

Browse files
committed
Refactor aliasing logic
1 parent 0ae32a5 commit a9d0c40

File tree

1 file changed

+24
-29
lines changed

1 file changed

+24
-29
lines changed

src/abstractsparsearrayinterface.jl

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ end
207207
function map_indices! end
208208

209209
@interface interface::AbstractArrayInterface function map_indices!(
210-
f, a_dest::AbstractArray, indices, as::AbstractArray...
210+
indices, f, a_dest::AbstractArray, as::AbstractArray...
211211
)
212212
for I in indices
213213
a_dest[I] = f(map(a -> a[I], as)...)
@@ -221,7 +221,7 @@ function map_stored! end
221221
@interface interface::AbstractArrayInterface function map_stored!(
222222
f, a_dest::AbstractArray, as::AbstractArray...
223223
)
224-
@interface interface map_indices!(f, a_dest, eachstoredindex(as...), as...)
224+
@interface interface map_indices!(eachstoredindex(as...), f, a_dest, as...)
225225
return a_dest
226226
end
227227

@@ -231,7 +231,7 @@ function map_all! end
231231
@interface interface::AbstractArrayInterface function map_all!(
232232
f, a_dest::AbstractArray, as::AbstractArray...
233233
)
234-
@interface interface map_indices!(f, a_dest, eachindex(as...), as...)
234+
@interface interface map_indices!(eachindex(as...), f, a_dest, as...)
235235
return a_dest
236236
end
237237

@@ -250,37 +250,32 @@ using ArrayLayouts: ArrayLayouts, zero!
250250
return @interface interface map_stored!(f, a, a)
251251
end
252252

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+
253266
@interface interface::AbstractSparseArrayInterface function Base.map!(
254267
f, a_dest::AbstractArray, as::AbstractArray...
255268
)
256-
# TODO: Define a function `preserves_unstored(a_dest, f, as...)`
257-
# to determine if a function preserves the stored values
258-
# of the destination sparse array.
259-
# The current code may be inefficient since it actually
260-
# accesses an unstored element, which in the case of a
261-
# sparse array of arrays can allocate an array.
262-
# Sparse arrays could be expected to define a cheap
263-
# unstored element allocator, for example
264-
# `get_prototypical_unstored(a::AbstractArray)`.
265-
I = first(eachindex(as...))
266-
preserves_unstored = iszero(f(map(a -> getunstoredindex(a, I), as)...))
267-
if !preserves_unstored
268-
# Doesn't preserve unstored values, loop over all elements.
269-
@interface interface map_all!(f, a_dest, as...)
270-
return a_dest
271-
end
272-
# Unalias the inputs from the destination
273-
# to make sure the inputs aren't overwritten incorrectly.
274-
# See: https://github.com/JuliaLang/julia/blob/v1.11.2/base/broadcast.jl#L935-L948
275-
as = map(a -> a_dest === a ? a : Base.unalias(a_dest, a), as)
276-
indices_stored = eachstoredindex(as...)
277-
if eachstoredindex(a_dest) indices_stored
278-
# If not all indices being mapped over are stored in the destination,
279-
# zero out the destination. An extreme example of this is when
280-
# the sources are sparse but the destination is dense.
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)
281273
@interface interface zero!(a_dest)
274+
eachstoredindex(as...)
275+
else
276+
eachstoredindex(a_dest)
282277
end
283-
@interface interface map_indices!(f, a_dest, indices_stored, as...)
278+
@interface interface map_indices!(indices, f, a_dest, as...)
284279
return a_dest
285280
end
286281

0 commit comments

Comments
 (0)