Skip to content

Commit

Permalink
fix maximum on generic orders (#30441)
Browse files Browse the repository at this point in the history
Close #30436
Address the non-numeric values case that is visible only with long arrays reported in #30320
  • Loading branch information
jw3126 authored and ViralBShah committed Dec 20, 2018
1 parent 99efc91 commit 744ead4
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
16 changes: 10 additions & 6 deletions base/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -452,18 +452,22 @@ julia> prod(1:20)
prod(a) = mapreduce(identity, mul_prod, a)

## maximum & minimum
function _fast(::typeof(max),x,y)
_fast(::typeof(min),x,y) = min(x,y)
_fast(::typeof(max),x,y) = max(x,y)
function _fast(::typeof(max), x::AbstractFloat, y::AbstractFloat)
ifelse(isnan(x),
x,
ifelse(x > y, x, y))
end

function _fast(::typeof(min),x,y)
function _fast(::typeof(min),x::AbstractFloat, y::AbstractFloat)
ifelse(isnan(x),
x,
ifelse(x < y, x, y))
end

_isnan(x) = false
_isnan(x::Real) = isnan(x)
isbadzero(::typeof(max), x::AbstractFloat) = (x == zero(x)) & signbit(x)
isbadzero(::typeof(min), x::AbstractFloat) = (x == zero(x)) & !signbit(x)
isbadzero(op, x) = false
Expand All @@ -479,10 +483,10 @@ function mapreduce_impl(f, op::Union{typeof(max), typeof(min)},
start = first
stop = start + chunk_len - 4
while stop <= last
isnan(v1) && return v1
isnan(v2) && return v2
isnan(v3) && return v3
isnan(v4) && return v4
_isnan(v1) && return v1
_isnan(v2) && return v2
_isnan(v3) && return v3
_isnan(v4) && return v4
@inbounds for i in start:4:stop
v1 = _fast(op, v1, f(A[i+1]))
v2 = _fast(op, v2, f(A[i+2]))
Expand Down
11 changes: 10 additions & 1 deletion stdlib/Test/src/Test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export @testset
# Legacy approximate testing functions, yet to be included
export @inferred
export detect_ambiguities, detect_unbound_args
export GenericString, GenericSet, GenericDict, GenericArray
export GenericString, GenericSet, GenericDict, GenericArray, GenericOrder
export TestSetException

import Distributed: myid
Expand Down Expand Up @@ -1546,6 +1546,15 @@ end
GenericArray{T}(args...) where {T} = GenericArray(Array{T}(args...))
GenericArray{T,N}(args...) where {T,N} = GenericArray(Array{T,N}(args...))

"""
The `GenericOrder` can be used to test APIs for their support
of generic ordered types.
"""
struct GenericOrder{T}
val::T
end
Base.isless(x::GenericOrder, y::GenericOrder) = isless(x.val,y.val)

Base.keys(a::GenericArray) = keys(a.a)
Base.axes(a::GenericArray) = axes(a.a)
Base.length(a::GenericArray) = length(a.a)
Expand Down
11 changes: 11 additions & 0 deletions test/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,17 @@ end
end
end

@testset "maximum works on generic order #30320" begin
for n in [1:20;1500]
arr = randn(n)
@test GenericOrder(maximum(arr)) === maximum(map(GenericOrder, arr))
@test GenericOrder(minimum(arr)) === minimum(map(GenericOrder, arr))
f = x -> x
@test GenericOrder(maximum(f,arr)) === maximum(f,map(GenericOrder, arr))
@test GenericOrder(minimum(f,arr)) === minimum(f,map(GenericOrder, arr))
end
end

@test isnan(maximum([NaN]))
@test isnan(minimum([NaN]))
@test isequal(extrema([NaN]), (NaN, NaN))
Expand Down

0 comments on commit 744ead4

Please sign in to comment.