From 2a64c403f7820f3c7b897446cfdfde688aedc5a3 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 16 Jun 2020 23:18:01 -0700 Subject: [PATCH 1/3] Introduce keyword argument `reset` for `sum!` etc. --- base/reducedim.jl | 221 +++++++++++++++++++++++++++++++++++++++------- test/reducedim.jl | 90 ++++++++++++------- 2 files changed, 245 insertions(+), 66 deletions(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index 8b0d8327f4e39..6db5f77ff855d 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -390,14 +390,19 @@ count(A::AbstractArrayOrBroadcasted; dims=:) = count(identity, A, dims=dims) count(f, A::AbstractArrayOrBroadcasted; dims=:) = mapreduce(_bool(f), add_sum, A, dims=dims, init=0) """ - count!([f=identity,] r, A) + count!([f=identity,] r, A; [reset::Bool = true]) Count the number of elements in `A` for which `f` returns `true` over the singleton dimensions of `r`, writing the result into `r` in-place. +If `reset` is `true`, values in `r` are discarded. Otherwise, they are used as the initial +value of the accumulation. !!! compat "Julia 1.5" inplace `count!` was added in Julia 1.5. +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. + # Examples ```jldoctest julia> A = [1 2; 3 4] @@ -413,11 +418,17 @@ julia> count!(<=(2), [1; 1], A) 2-element Array{Int64,1}: 2 0 + +julia> count!(<=(2), [1; 1], A; reset = false) +2-element Array{Int64,1}: + 3 + 1 ``` """ -count!(r::AbstractArray, A::AbstractArrayOrBroadcasted; init::Bool=true) = count!(identity, r, A; init=init) -count!(f, r::AbstractArray, A::AbstractArrayOrBroadcasted; init::Bool=true) = - mapreducedim!(_bool(f), add_sum, initarray!(r, add_sum, init, A), A) +count!(r::AbstractArray, A::AbstractArrayOrBroadcasted; kw...) = + count!(identity, r, A; kw...) +count!(f, r::AbstractArray, A::AbstractArrayOrBroadcasted; kw...) = + mapreducedim!(_bool(f), add_sum, initarray!(r, add_sum, _kw_reset(kw), A), A) """ sum(A::AbstractArray; dims) @@ -444,9 +455,14 @@ julia> sum(A, dims=2) sum(A::AbstractArray; dims) """ - sum!(r, A) + sum!(r, A; [reset::Bool = true]) Sum elements of `A` over the singleton dimensions of `r`, and write results to `r`. +If `reset` is `true`, values in `r` are discarded. Otherwise, they are used as the initial +value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. # Examples ```jldoctest @@ -463,6 +479,10 @@ julia> sum!([1; 1], A) julia> sum!([1 1], A) 1×2 Array{Int64,2}: 4 6 + +julia> sum!([1 1], A; reset = false) +1×2 Array{Int64,2}: + 5 7 ``` """ sum!(r, A) @@ -492,9 +512,14 @@ julia> prod(A, dims=2) prod(A::AbstractArray; dims) """ - prod!(r, A) + prod!(r, A; [reset::Bool = true]) Multiply elements of `A` over the singleton dimensions of `r`, and write results to `r`. +If `reset` is `true`, values in `r` are discarded. Otherwise, they are used as the initial +value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. # Examples ```jldoctest @@ -503,14 +528,18 @@ julia> A = [1 2; 3 4] 1 2 3 4 -julia> prod!([1; 1], A) +julia> prod!([0; 0], A) 2-element Array{Int64,1}: 2 12 -julia> prod!([1 1], A) +julia> prod!([0 0], A) 1×2 Array{Int64,2}: 3 8 + +julia> prod!([0 0], A; reset = true) +1×2 Array{Int64,2}: + 0 0 ``` """ prod!(r, A) @@ -542,9 +571,14 @@ julia> maximum(A, dims=2) maximum(A::AbstractArray; dims) """ - maximum!(r, A) + maximum!(r, A; [reset::Bool = true]) Compute the maximum value of `A` over the singleton dimensions of `r`, and write results to `r`. +If `reset` is `true`, values in `r` are discarded. Otherwise, they are used as the initial +value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. # Examples ```jldoctest @@ -553,12 +587,20 @@ julia> A = [1 2; 3 4] 1 2 3 4 -julia> maximum!([1; 1], A) +julia> maximum!([4; 5], A) 2-element Array{Int64,1}: 2 4 -julia> maximum!([1 1], A) +julia> maximum!([4 5], A) +1×2 Array{Int64,2}: + 3 4 + +julia> maximum!([4 5], A; reset = false) # initial values "win" +1×2 Array{Int64,2}: + 4 5 + +julia> maximum!([1 1], A; reset = false) 1×2 Array{Int64,2}: 3 4 ``` @@ -592,9 +634,14 @@ julia> minimum(A, dims=2) minimum(A::AbstractArray; dims) """ - minimum!(r, A) + minimum!(r, A; [reset::Bool = true]) Compute the minimum value of `A` over the singleton dimensions of `r`, and write results to `r`. +If `reset` is `true`, values in `r` are discarded. Otherwise, they are used as the initial +value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. # Examples ```jldoctest @@ -603,12 +650,20 @@ julia> A = [1 2; 3 4] 1 2 3 4 -julia> minimum!([1; 1], A) +julia> minimum!([0; 1], A) 2-element Array{Int64,1}: 1 3 -julia> minimum!([1 1], A) +julia> minimum!([0 1], A) +1×2 Array{Int64,2}: + 1 2 + +julia> minimum!([0 1], A; reset = false) # initial values "win" +1×2 Array{Int64,2}: + 0 1 + +julia> minimum!([4, 4], A; reset = false) 1×2 Array{Int64,2}: 1 2 ``` @@ -640,9 +695,14 @@ julia> all(A, dims=2) all(A::AbstractArray; dims) """ - all!(r, A) + all!(r, A; [reset::Bool = true]) Test whether all values in `A` along the singleton dimensions of `r` are `true`, and write results to `r`. +If `reset` is `true`, values in `r` are discarded. Otherwise, they are used as the initial +value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. # Examples ```jldoctest @@ -651,14 +711,18 @@ julia> A = [true false; true false] 1 0 1 0 -julia> all!([1; 1], A) -2-element Array{Int64,1}: +julia> all!([false; false], A) # initial values are ignored +2-element Array{Bool,1}: 0 0 -julia> all!([1 1], A) -1×2 Array{Int64,2}: +julia> all!([false false], A) # initial values are ignored +1×2 Array{Bool,2}: 1 0 + +julia> all!([false false], A; reset = false) # initial values are used +1×2 Array{Bool,2}: + 0 0 ``` """ all!(r, A) @@ -688,10 +752,15 @@ julia> any(A, dims=2) any(::AbstractArray; dims) """ - any!(r, A) + any!(r, A; [reset::Bool = true]) Test whether any values in `A` along the singleton dimensions of `r` are `true`, and write results to `r`. +If `reset` is `true`, values in `r` are discarded. Otherwise, they are used as the initial +value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. # Examples ```jldoctest @@ -700,14 +769,18 @@ julia> A = [true false; true false] 1 0 1 0 -julia> any!([1; 1], A) -2-element Array{Int64,1}: +julia> any!([true; true], A) # initial values are ignored +2-element Array{Bool,1}: 1 1 -julia> any!([1 1], A) -1×2 Array{Int64,2}: +julia> any!([true true], A) # initial values are ignored +1×2 Array{Bool,2}: 1 0 + +julia> any!([true true], A; reset = false) # initial values are used +1×2 Array{Bool,2}: + 1 1 ``` """ any!(r, A) @@ -732,15 +805,39 @@ all(a::AbstractArray; dims=:) = _all(a, dims) all(f::Function, a::AbstractArray; dims=:) = _all(f, a, dims) _all(a, ::Colon) = _all(identity, a, :) +""" + _kw_reset((init = bool,)) -> bool + _kw_reset((reset = bool,)) -> bool + +Extract a keyword argument `reset` from the keyword arguments. Throw an error +if unsupported. For backward compatibility, allow `init` as an alias. +""" +_kw_reset(kw::Iterators.Pairs) = _kw_reset(kw.data) +_kw_reset(::NamedTuple{(), Tuple{}}) = true +_kw_reset(kw::NamedTuple{(:reset,), Tuple{Bool}}) = kw.reset +_kw_reset(kw::NamedTuple{(:init,), Tuple{Bool}}) = kw.init + +function _kw_reset(kw::NamedTuple) + if haskey(kw, :reset) && haskey(kw, :init) + throw(ArgumentError( + "keyword arguments `reset` and `init` cannot be specified " * + "at the same time; use `reset` in Julia >= 1.6", + )) + else + throw(ArgumentError("unknown keyword arguments or unsupported type: $kw")) + end +end + for (fname, op) in [(:sum, :add_sum), (:prod, :mul_prod), (:maximum, :max), (:minimum, :min), (:all, :&), (:any, :|)] fname! = Symbol(fname, '!') _fname = Symbol('_', fname) @eval begin - $(fname!)(f::Function, r::AbstractArray, A::AbstractArray; init::Bool=true) = - mapreducedim!(f, $(op), initarray!(r, $(op), init, A), A) - $(fname!)(r::AbstractArray, A::AbstractArray; init::Bool=true) = $(fname!)(identity, r, A; init=init) + $(fname!)(f::Function, r::AbstractArray, A::AbstractArray; kw...) = + mapreducedim!(f, $(op), initarray!(r, $(op), _kw_reset(kw), A), A) + $(fname!)(r::AbstractArray, A::AbstractArray; kw...) = + $(fname!)(identity, r, A; kw...) $(_fname)(A, dims; kw...) = $(_fname)(identity, A, dims; kw...) $(_fname)(f, A, dims; kw...) = mapreduce(f, $(op), A; dims=dims, kw...) @@ -801,15 +898,44 @@ function findminmax!(f, Rval, Rind, A::AbstractArray{T,N}) where {T,N} end """ - findmin!(rval, rind, A) -> (minval, index) + findmin!(rval, rind, A; [reset::Bool = true]) -> (minval, index) Find the minimum of `A` and the corresponding linear index along singleton dimensions of `rval` and `rind`, and store the results in `rval` and `rind`. `NaN` is treated as less than all other values. +If `reset` is `true`, values in `rval` and `rind` are discarded. Otherwise, they are used +as the initial value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. + +# Examples +```jldoctest +julia> A = [1.0 2; 3 4] +2×2 Array{Float64,2}: + 1.0 2.0 + 3.0 4.0 + +julia> findmin!([0.0; 0.0], [CartesianIndex(-1, -1); CartesianIndex(-1, -1)], A) +([1.0; 3.0], CartesianIndex{2}[CartesianIndex(1, 1); CartesianIndex(2, 1)]) + +julia> findmin!([0.0 0.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A) +([1.0 2.0], CartesianIndex{2}[CartesianIndex(1, 1) CartesianIndex(1, 2)]) + +julia> findmin!([0.0 0.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A; reset = false) +([0.0 0.0], CartesianIndex{2}[CartesianIndex(-1, -1) CartesianIndex(-1, -1)]) +``` """ function findmin!(rval::AbstractArray, rind::AbstractArray, A::AbstractArray; - init::Bool=true) - findminmax!(isless, init && !isempty(A) ? fill!(rval, first(A)) : rval, fill!(rind,zero(eltype(keys(A)))), A) + kw...) + if haskey(kw, :init) # backward compatibility + _kw_reset(kw) && !isempty(A) && fill!(rval, first(A)) + fill!(rind, zero(eltype(keys(A)))) + elseif _kw_reset(kw) + fill!(rval, first(A)) + fill!(rind, zero(eltype(keys(A)))) + end + return findminmax!(isless, rval, rind, A) end """ @@ -850,15 +976,44 @@ end isgreater(a, b) = isless(b,a) """ - findmax!(rval, rind, A) -> (maxval, index) + findmax!(rval, rind, A; [reset::Bool = true]) -> (maxval, index) Find the maximum of `A` and the corresponding linear index along singleton dimensions of `rval` and `rind`, and store the results in `rval` and `rind`. `NaN` is treated as greater than all other values. +If `reset` is `true`, values in `rval` and `rind` are discarded. Otherwise, they are used +as the initial value of the accumulation. + +!!! compat "Julia 1.6" + keyword argument `reset` is added in Julia 1.6. + +# Examples +```jldoctest +julia> A = [1.0 2; 3 4] +2×2 Array{Float64,2}: + 1.0 2.0 + 3.0 4.0 + +julia> findmax!([5.0; 5.0], [CartesianIndex(-1, -1); CartesianIndex(-1, -1)], A) +([2.0; 4.0], CartesianIndex{2}[CartesianIndex(1, 2); CartesianIndex(2, 2)]) + +julia> findmin!([5.0 5.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A) +([3.0 4.0], CartesianIndex{2}[CartesianIndex(2, 1) CartesianIndex(2, 2)]) + +julia> findmax!([5.0 5.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A; reset = false) +([5.0 5.0], CartesianIndex{2}[CartesianIndex(-1, -1) CartesianIndex(-1, -1)]) +``` """ function findmax!(rval::AbstractArray, rind::AbstractArray, A::AbstractArray; - init::Bool=true) - findminmax!(isgreater, init && !isempty(A) ? fill!(rval, first(A)) : rval, fill!(rind,zero(eltype(keys(A)))), A) + kw...) + if haskey(kw, :init) # backward compatibility + _kw_reset(kw) && !isempty(A) && fill!(rval, first(A)) + fill!(rind, zero(eltype(keys(A)))) + elseif _kw_reset(kw) + fill!(rval, first(A)) + fill!(rind, zero(eltype(keys(A)))) + end + return findminmax!(isgreater, rval, rind, A) end """ diff --git a/test/reducedim.jl b/test/reducedim.jl index e51a075496f1c..213a2950c5853 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -38,29 +38,35 @@ safe_minabs(A::Array{T}, region) where {T} = safe_mapslices(minimum, abs.(A), re @test minimum!(abs, r, Areduc) ≈ safe_minabs(Areduc, region) @test count!(!, r, Breduc) ≈ safe_count(.!Breduc, region) - # With init=false + # With reset=false r2 = similar(r) fill!(r, 1) - @test sum!(r, Areduc, init=false) ≈ safe_sum(Areduc, region) .+ 1 + @test sum!(r, Areduc, reset=false) ≈ safe_sum(Areduc, region) .+ 1 fill!(r, 2.2) - @test prod!(r, Areduc, init=false) ≈ safe_prod(Areduc, region)*2.2 + @test prod!(r, Areduc, reset=false) ≈ safe_prod(Areduc, region)*2.2 fill!(r, 1.8) - @test maximum!(r, Areduc, init=false) ≈ fill!(r2, 1.8) + @test maximum!(r, Areduc, reset=false) ≈ fill!(r2, 1.8) fill!(r, -0.2) - @test minimum!(r, Areduc, init=false) ≈ fill!(r2, -0.2) + @test minimum!(r, Areduc, reset=false) ≈ fill!(r2, -0.2) fill!(r, 1) - @test count!(r, Breduc, init=false) ≈ safe_count(Breduc, region) .+ 1 + @test count!(r, Breduc, reset=false) ≈ safe_count(Breduc, region) .+ 1 fill!(r, 8.1) - @test sum!(abs, r, Areduc, init=false) ≈ safe_sumabs(Areduc, region) .+ 8.1 + @test sum!(abs, r, Areduc, reset=false) ≈ safe_sumabs(Areduc, region) .+ 8.1 fill!(r, 8.1) - @test sum!(abs2, r, Areduc, init=false) ≈ safe_sumabs2(Areduc, region) .+ 8.1 + @test sum!(abs2, r, Areduc, reset=false) ≈ safe_sumabs2(Areduc, region) .+ 8.1 fill!(r, 1.5) - @test maximum!(abs, r, Areduc, init=false) ≈ fill!(r2, 1.5) + @test maximum!(abs, r, Areduc, reset=false) ≈ fill!(r2, 1.5) fill!(r, -1.5) - @test minimum!(abs, r, Areduc, init=false) ≈ fill!(r2, -1.5) + @test minimum!(abs, r, Areduc, reset=false) ≈ fill!(r2, -1.5) + fill!(r, 1) + @test count!(!, r, Breduc, reset=false) ≈ safe_count(.!Breduc, region) .+ 1 + + # Backward compatibility: fill!(r, 1) - @test count!(!, r, Breduc, init=false) ≈ safe_count(.!Breduc, region) .+ 1 + @test sum!(r, Areduc, init=false) ≈ safe_sum(Areduc, region) .+ 1 + fill!(r, 1) + @test count!(r, Breduc, init=false) ≈ safe_count(Breduc, region) .+ 1 @test @inferred(sum(Areduc, dims=region)) ≈ safe_sum(Areduc, region) @test @inferred(prod(Areduc, dims=region)) ≈ safe_prod(Areduc, region) @@ -92,22 +98,22 @@ r = fill(NaN, map(length, Base.reduced_indices(axes(Breduc), 1))) @test sum(abs2, Breduc, dims=1) ≈ safe_sumabs2(Breduc, 1) fill!(r, 4.2) -@test sum!(r, Breduc, init=false) ≈ safe_sum(Breduc, 1) .+ 4.2 +@test sum!(r, Breduc, reset=false) ≈ safe_sum(Breduc, 1) .+ 4.2 fill!(r, -6.3) -@test sum!(abs, r, Breduc, init=false) ≈ safe_sumabs(Breduc, 1) .- 6.3 +@test sum!(abs, r, Breduc, reset=false) ≈ safe_sumabs(Breduc, 1) .- 6.3 fill!(r, -1.1) -@test sum!(abs2, r, Breduc, init=false) ≈ safe_sumabs2(Breduc, 1) .- 1.1 +@test sum!(abs2, r, Breduc, reset=false) ≈ safe_sumabs2(Breduc, 1) .- 1.1 # Small arrays with init=false let A = reshape(1:15, 3, 5) R = fill(1, 3) - @test sum!(R, A, init=false) == [36,41,46] + @test sum!(R, A, reset=false) == [36,41,46] R = fill(1, 1, 5) - @test sum!(R, A, init=false) == [7 16 25 34 43] + @test sum!(R, A, reset=false) == [7 16 25 34 43] end let R = [2] A = reshape(1:6, 3, 2) - @test prod!(R, A, init=false) == [1440] + @test prod!(R, A, reset=false) == [1440] # min/max @test reduce(max, A, dims=1) == [3 6] @@ -193,7 +199,7 @@ for (tup, rval, rind) in [((1,), [1.0 2.0 4.0], [CartesianIndex(1,1) CartesianIn @test findmin!(similar(rval), similar(rind), A) == (rval, rind) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) end for (tup, rval, rind) in [((1,), [5.0 5.0 6.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(1,3)]), @@ -203,7 +209,25 @@ for (tup, rval, rind) in [((1,), [5.0 5.0 6.0], [CartesianIndex(2,1) CartesianIn @test findmax!(similar(rval), similar(rind), A) == (rval, rind) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) +end + +@testset "findmin! and findmax! with reset = false" begin + A = [1.0 5.0 6.0; + 5.0 2.0 4.0] + rind = [CartesianIndex(-1, -1), CartesianIndex(-1, -1)] + @test findmin!([0.0, 0.0], copy(rind), A; reset=false) == ([0.0, 0.0], rind) + @test findmax!([9.0, 9.0], copy(rind), A; reset=false) == ([9.0, 9.0], rind) + # Backward compatibility (`init` is ignored if `A` is non-empty): + @test findmin!([0.0, 0.0], copy(rind), A; init = false) == + ([1.0, 2.0], [CartesianIndex(1, 1), CartesianIndex(2, 2)]) + @test findmax!([9.0, 9.0], copy(rind), A; init=false) == + ([6.0, 5.0], [CartesianIndex(1, 3), CartesianIndex(2, 1)]) + # Backward compatibility (indices are filled with zeros if `A` is empty): + @test findmin!([0.0, 0.0], copy(rind), A[:, 1:0]; init=false) == + ([0.0, 0.0], zero(rind)) + @test findmax!([9.0, 9.0], copy(rind), A[:, 1:0]; init=false) == + ([9.0, 9.0], zero(rind)) end #issue #23209 @@ -217,7 +241,7 @@ for (tup, rval, rind) in [((1,), [NaN 2.0 4.0], [CartesianIndex(2,1) CartesianIn @test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) @test isequal(Base.reducedim!(min, copy(rval), A), rval) end @@ -228,7 +252,7 @@ for (tup, rval, rind) in [((1,), [NaN 3.0 6.0], [CartesianIndex(2,1) CartesianIn @test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) @test isequal(Base.reducedim!(max, copy(rval), A), rval) end @@ -252,7 +276,7 @@ for (tup, rval, rind) in [((1,), [NaN NaN 4.0], [CartesianIndex(2,1) CartesianIn @test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) end for (tup, rval, rind) in [((1,), [NaN NaN 6.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(1,3)]), @@ -262,7 +286,7 @@ for (tup, rval, rind) in [((1,), [NaN NaN 6.0], [CartesianIndex(2,1) CartesianIn @test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) end A = [Inf -Inf Inf -Inf; @@ -274,7 +298,7 @@ for (tup, rval, rind) in [((1,), [Inf -Inf -Inf -Inf], [CartesianIndex(1,1) Cart @test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) end for (tup, rval, rind) in [((1,), [Inf Inf Inf -Inf], [CartesianIndex(1,1) CartesianIndex(2,2) CartesianIndex(1,3) CartesianIndex(1,4)]), @@ -284,7 +308,7 @@ for (tup, rval, rind) in [((1,), [Inf Inf Inf -Inf], [CartesianIndex(1,1) Cartes @test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) end A = [BigInt(10)] @@ -293,7 +317,7 @@ for (tup, rval, rind) in [((2,), [BigInt(10)], [1])] @test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) end for (tup, rval, rind) in [((2,), [BigInt(10)], [1])] @@ -301,7 +325,7 @@ for (tup, rval, rind) in [((2,), [BigInt(10)], [1])] @test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) end A = [BigInt(-10)] @@ -310,7 +334,7 @@ for (tup, rval, rind) in [((2,), [BigInt(-10)], [1])] @test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) end for (tup, rval, rind) in [((2,), [BigInt(-10)], [1])] @@ -318,7 +342,7 @@ for (tup, rval, rind) in [((2,), [BigInt(-10)], [1])] @test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) end A = [BigInt(10) BigInt(-10)] @@ -327,7 +351,7 @@ for (tup, rval, rind) in [((2,), reshape([BigInt(-10)], 1, 1), reshape([Cartesia @test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) end for (tup, rval, rind) in [((2,), reshape([BigInt(10)], 1, 1), reshape([CartesianIndex(1,1)], 1, 1))] @@ -335,7 +359,7 @@ for (tup, rval, rind) in [((2,), reshape([BigInt(10)], 1, 1), reshape([Cartesian @test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) end A = ["a", "b"] @@ -344,7 +368,7 @@ for (tup, rval, rind) in [((1,), ["a"], [1])] @test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(minimum(A, dims=tup), rval) @test isequal(minimum!(similar(rval), A), rval) - @test isequal(minimum!(copy(rval), A, init=false), rval) + @test isequal(minimum!(copy(rval), A, reset=false), rval) end for (tup, rval, rind) in [((1,), ["b"], [2])] @@ -352,7 +376,7 @@ for (tup, rval, rind) in [((1,), ["b"], [2])] @test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind)) @test isequal(maximum(A, dims=tup), rval) @test isequal(maximum!(similar(rval), A), rval) - @test isequal(maximum!(copy(rval), A, init=false), rval) + @test isequal(maximum!(copy(rval), A, reset=false), rval) end # issue #6672 From d91156e48a57453cf73b9935a1c9b46ce517c519 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 17 Jun 2020 12:56:14 -0700 Subject: [PATCH 2/3] Fix findmin! and findmax! for empty case --- base/reducedim.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index 6db5f77ff855d..289c205bca70f 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -932,7 +932,7 @@ function findmin!(rval::AbstractArray, rind::AbstractArray, A::AbstractArray; _kw_reset(kw) && !isempty(A) && fill!(rval, first(A)) fill!(rind, zero(eltype(keys(A)))) elseif _kw_reset(kw) - fill!(rval, first(A)) + !isempty(A) && fill!(rval, first(A)) fill!(rind, zero(eltype(keys(A)))) end return findminmax!(isless, rval, rind, A) @@ -1010,7 +1010,7 @@ function findmax!(rval::AbstractArray, rind::AbstractArray, A::AbstractArray; _kw_reset(kw) && !isempty(A) && fill!(rval, first(A)) fill!(rind, zero(eltype(keys(A)))) elseif _kw_reset(kw) - fill!(rval, first(A)) + !isempty(A) && fill!(rval, first(A)) fill!(rind, zero(eltype(keys(A)))) end return findminmax!(isgreater, rval, rind, A) From 3bbc2568283198e72f68591694f72477b03bb969 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 17 Jun 2020 18:26:18 -0700 Subject: [PATCH 3/3] Fix doctests --- base/reducedim.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index 289c205bca70f..8237c3b7be101 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -537,7 +537,7 @@ julia> prod!([0 0], A) 1×2 Array{Int64,2}: 3 8 -julia> prod!([0 0], A; reset = true) +julia> prod!([0 0], A; reset = false) 1×2 Array{Int64,2}: 0 0 ``` @@ -663,7 +663,7 @@ julia> minimum!([0 1], A; reset = false) # initial values "win" 1×2 Array{Int64,2}: 0 1 -julia> minimum!([4, 4], A; reset = false) +julia> minimum!([4 4], A; reset = false) 1×2 Array{Int64,2}: 1 2 ``` @@ -917,7 +917,7 @@ julia> A = [1.0 2; 3 4] 3.0 4.0 julia> findmin!([0.0; 0.0], [CartesianIndex(-1, -1); CartesianIndex(-1, -1)], A) -([1.0; 3.0], CartesianIndex{2}[CartesianIndex(1, 1); CartesianIndex(2, 1)]) +([1.0, 3.0], CartesianIndex{2}[CartesianIndex(1, 1), CartesianIndex(2, 1)]) julia> findmin!([0.0 0.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A) ([1.0 2.0], CartesianIndex{2}[CartesianIndex(1, 1) CartesianIndex(1, 2)]) @@ -995,9 +995,9 @@ julia> A = [1.0 2; 3 4] 3.0 4.0 julia> findmax!([5.0; 5.0], [CartesianIndex(-1, -1); CartesianIndex(-1, -1)], A) -([2.0; 4.0], CartesianIndex{2}[CartesianIndex(1, 2); CartesianIndex(2, 2)]) +([2.0, 4.0], CartesianIndex{2}[CartesianIndex(1, 2), CartesianIndex(2, 2)]) -julia> findmin!([5.0 5.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A) +julia> findmax!([5.0 5.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A) ([3.0 4.0], CartesianIndex{2}[CartesianIndex(2, 1) CartesianIndex(2, 2)]) julia> findmax!([5.0 5.0], [CartesianIndex(-1, -1) CartesianIndex(-1, -1)], A; reset = false)