Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mitigate in-place reducedim alias bug #45821

Closed
wants to merge 12 commits into from
20 changes: 19 additions & 1 deletion base/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,9 @@ Sum elements of `A` over the singleton dimensions of `r`, and write results to `
Note that since the sum! function is intended to operate without making any allocations,
the target should not alias with the source.

!!! warning
Incorrect result may occur when `r` is alias or `view` of `A`.

# Examples
```jldoctest
julia> A = [1 2; 3 4]
Expand Down Expand Up @@ -601,6 +604,9 @@ prod(f, A::AbstractArray; dims)

Multiply elements of `A` over the singleton dimensions of `r`, and write results to `r`.

!!! warning
Incorrect result may occur when `r` is alias or `view` of `A`.

# Examples
```jldoctest
julia> A = [1 2; 3 4]
Expand Down Expand Up @@ -895,6 +901,9 @@ all(::Function, ::AbstractArray; dims)

Test whether all values in `A` along the singleton dimensions of `r` are `true`, and write results to `r`.

!!! warning
Incorrect result may occur when `r` is alias or `view` of `A`.

# Examples
```jldoctest
julia> A = [true false; true false]
Expand Down Expand Up @@ -968,6 +977,9 @@ any(::Function, ::AbstractArray; dims)
Test whether any values in `A` along the singleton dimensions of `r` are `true`, and write
results to `r`.

!!! warning
Incorrect result may occur when `r` is alias or `view` of `A`.

# Examples
```jldoctest
julia> A = [true false; true false]
Expand Down Expand Up @@ -1019,7 +1031,13 @@ for (fname, op) in [(:sum, :add_sum), (:prod, :mul_prod),
@eval begin
$(fname!)(f::Function, r::AbstractArray, A::AbstractArray; init::Bool=true) =
mapreducedim!($mapf, $(op), initarray!(r, $mapf, $(op), init, A), A)
$(fname!)(r::AbstractArray, A::AbstractArray; init::Bool=true) = $(fname!)(identity, r, A; init=init)
@inline function $(fname!)(r::AbstractArray, A::AbstractArray; init::Bool=true)
if size(r) == size(A) && init
copyto!(r, A)
return r
end
$(fname!)(identity, r, A; init=init)
end

$(_fname)(A, dims; kw...) = $(_fname)(identity, A, dims; kw...)
$(_fname)(f, A, dims; kw...) = mapreduce($mapf, $(op), A; dims=dims, kw...)
Expand Down
12 changes: 12 additions & 0 deletions test/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ safe_minabs(A::Array{T}, region) where {T} = safe_mapslices(minimum, abs.(A), re
)
end

@testset "test in-place reductions with alias" begin
a = rand(3)
b = copy(a)
@test sum!(a, a) == b
@test prod!(a, a) == b

c = rand(Bool, 5)
d = copy(c)
@test all!(c, c) == d
@test any!(c, c) == d
end

# Combining dims and init
A = Array{Int}(undef, 0, 3)
@test_throws "reducing over an empty collection is not allowed" maximum(A; dims=1)
Expand Down