From 6ca85cd73f475d465885d29b3cd7a39a93953c8e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 2 Nov 2023 16:11:01 -0400 Subject: [PATCH] Reland "add more methods and tests for reductions over empty arrays" Refs #29919 Refs #52003 This reverts commit 2a842146ac6ee0a7f505d56b4c1f77274d7f0628. --- base/reduce.jl | 9 ++++++--- test/reduce.jl | 23 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index c4020faf4c85f..4b870b21c4e84 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -338,7 +338,8 @@ reduce_empty(::typeof(*), ::Type{T}) where {T} = one(T) reduce_empty(::typeof(*), ::Type{<:AbstractChar}) = "" reduce_empty(::typeof(&), ::Type{Bool}) = true reduce_empty(::typeof(|), ::Type{Bool}) = false - +reduce_empty(::typeof(max), T) = typemin(T) +reduce_empty(::typeof(min), T) = typemax(T) reduce_empty(::typeof(add_sum), ::Type{T}) where {T} = reduce_empty(+, T) reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:BitSignedSmall} = zero(Int) reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:BitUnsignedSmall} = zero(UInt) @@ -362,8 +363,10 @@ mapreduce_empty(::typeof(identity), op, T) = reduce_empty(op, T) mapreduce_empty(::typeof(abs), op, T) = abs(reduce_empty(op, T)) mapreduce_empty(::typeof(abs2), op, T) = abs2(reduce_empty(op, T)) -mapreduce_empty(f::typeof(abs), ::typeof(max), T) = abs(zero(T)) -mapreduce_empty(f::typeof(abs2), ::typeof(max), T) = abs2(zero(T)) +mapreduce_empty(::typeof(abs), ::typeof(max), T) = abs(zero(T)) +mapreduce_empty(::typeof(abs), ::typeof(min), T) = typemax(abs(zero(T))) +mapreduce_empty(::typeof(abs2), ::typeof(max), T) = abs2(zero(T)) +mapreduce_empty(::typeof(abs2), ::typeof(min), T) = typemax(abs2(zero(T))) # For backward compatibility: mapreduce_empty_iter(f, op, itr, ItrEltype) = diff --git a/test/reduce.jl b/test/reduce.jl index f5140c8a34bd9..7dc163a257ba8 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -91,6 +91,10 @@ end @test mapreduce(abs2, *, Float64[]) === 1.0 @test mapreduce(abs2, max, Float64[]) === 0.0 @test mapreduce(abs, max, Float64[]) === 0.0 +@test mapreduce(abs2, min, Float64[]) === Inf +@test mapreduce(abs, min, Float64[]) === Inf +@test_throws ArgumentError mapreduce(abs2, &, Float64[]) +@test_throws ArgumentError mapreduce(abs2, |, Float64[]) @test_throws "reducing over an empty collection is not allowed" mapreduce(abs2, &, Float64[]) @test_throws str -> !occursin("Closest candidates are", str) mapreduce(abs2, &, Float64[]) @test_throws "reducing over an empty collection is not allowed" mapreduce(abs2, |, Float64[]) @@ -246,8 +250,8 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr) # maximum & minimum & extrema -@test_throws "reducing over an empty" maximum(Int[]) -@test_throws "reducing over an empty" minimum(Int[]) +@test maximum(Int[]) === typemin(Int) +@test minimum(Int[]) === typemax(Int) @test_throws "reducing over an empty" extrema(Int[]) @test maximum(Int[]; init=-1) == -1 @@ -258,6 +262,21 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr) @test minimum(sin, []; init=1) == 1 @test extrema(sin, []; init=(1, -1)) == (1, -1) +@test maximum(Float64[]) === -Inf +@test minimum(Float64[]) === +Inf + +@test maximum(Float32[]) === -Inf32 +@test minimum(Float32[]) === +Inf32 + +@test maximum(abs, Int[]) === 0 +@test minimum(abs, Int[]) === typemax(Int) + +@test maximum(abs, Float64[]) === 0.0 +@test minimum(abs, Float64[]) === +Inf + +@test maximum(abs, Float32[]) === 0.0f0 +@test minimum(abs, Float32[]) === +Inf32 + @test maximum(5) == 5 @test minimum(5) == 5 @test extrema(5) == (5, 5)