Skip to content

Commit

Permalink
max and min of NaN return NaN (closes JuliaLang#7866) (fixes JuliaLan…
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengj committed Sep 14, 2016
1 parent fb503a0 commit afe7b8e
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 39 deletions.
4 changes: 2 additions & 2 deletions NEWS.md
Expand Up @@ -31,8 +31,7 @@ This section lists changes that do not have deprecation warnings.
Library improvements
--------------------

Compiler/Runtime improvements
-----------------------------
* `max`, `min`, and related functions (`minmax`, `maximum`, `minimum`, `extrema`) now return `NaN` for `NaN` arguments ([#12563]).

Deprecated or removed
---------------------
Expand Down Expand Up @@ -551,6 +550,7 @@ Language tooling improvements
[#11242]: https://github.com/JuliaLang/julia/issues/11242
[#11688]: https://github.com/JuliaLang/julia/issues/11688
[#12231]: https://github.com/JuliaLang/julia/issues/12231
[#12563]: https://github.com/JuliaLang/julia/issues/12563
[#12819]: https://github.com/JuliaLang/julia/issues/12819
[#12872]: https://github.com/JuliaLang/julia/issues/12872
[#13062]: https://github.com/JuliaLang/julia/issues/13062
Expand Down
11 changes: 5 additions & 6 deletions base/math.jl
Expand Up @@ -314,16 +314,15 @@ atan2(y::Float64, x::Float64) = ccall((:atan2,libm), Float64, (Float64, Float64,
atan2(y::Float32, x::Float32) = ccall((:atan2f,libm), Float32, (Float32, Float32), y, x)

max{T<:AbstractFloat}(x::T, y::T) = ifelse((y > x) | (signbit(y) < signbit(x)),
ifelse(isnan(y), x, y), ifelse(isnan(x), y, x))
ifelse(isnan(x), x, y), ifelse(isnan(y), y, x))


min{T<:AbstractFloat}(x::T, y::T) = ifelse((y < x) | (signbit(y) > signbit(x)),
ifelse(isnan(y), x, y), ifelse(isnan(x), y, x))
ifelse(isnan(x), x, y), ifelse(isnan(y), y, x))

minmax{T<:AbstractFloat}(x::T, y::T) = ifelse(isnan(x-y), ifelse(isnan(x), (y, y), (x, x)),
ifelse((y < x) | (signbit(y) > signbit(x)), (y, x),
ifelse((y > x) | (signbit(y) < signbit(x)), (x, y),
ifelse(x == x, (x, x), (y, y)))))
minmax{T<:AbstractFloat}(x::T, y::T) =
ifelse(isnan(x) | isnan(y), ifelse(isnan(x), (x,x), (y,y)),
ifelse((y > x) | (signbit(x) > signbit(y)), (x,y), (y,x)))


"""
Expand Down
4 changes: 4 additions & 0 deletions base/mpfr.jl
Expand Up @@ -584,12 +584,16 @@ function log1p(x::BigFloat)
end

function max(x::BigFloat, y::BigFloat)
isnan(x) && return x
isnan(y) && return y
z = BigFloat()
ccall((:mpfr_max, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &x, &y, ROUNDING_MODE[])
return z
end

function min(x::BigFloat, y::BigFloat)
isnan(x) && return x
isnan(y) && return y
z = BigFloat()
ccall((:mpfr_min, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &x, &y, ROUNDING_MODE[])
return z
Expand Down
14 changes: 3 additions & 11 deletions base/reduce.jl
Expand Up @@ -503,19 +503,11 @@ function extrema(itr)
s = start(itr)
done(itr, s) && throw(ArgumentError("collection must be non-empty"))
(v, s) = next(itr, s)
while v != v && !done(itr, s)
(x, s) = next(itr, s)
v = x
end
vmin = v
vmax = v
vmin = vmax = v
while !done(itr, s)
(x, s) = next(itr, s)
if x > vmax
vmax = x
elseif x < vmin
vmin = x
end
vmax = max(x, vmax)
vmin = min(x, vmin)
end
return (vmin, vmax)
end
Expand Down
4 changes: 2 additions & 2 deletions test/mpfr.jl
Expand Up @@ -301,8 +301,8 @@ y = BigFloat(2)
@test max(x,y) == x
@test min(x,y) == y
y = BigFloat(NaN)
@test max(x,y) == x
@test min(x,y) == x
@test isnan(max(x,y))
@test isnan(min(x,y))
@test isnan(max(y,y))
@test isnan(min(y,y))

Expand Down
30 changes: 18 additions & 12 deletions test/numbers.jl
Expand Up @@ -54,35 +54,41 @@
@test 2.0 * 3.0 == 6.
@test min(1.0,1) == 1

const = isequal # convenient for comparing NaNs

# min, max and minmax
@test min(1) === 1
@test max(1) === 1
@test minmax(1) === (1, 1)
@test minmax(5, 3) == (3, 5)
@test minmax(3., 5.) == (3., 5.)
@test minmax(5., 3.) == (3., 5.)
@test minmax(3., NaN) == (3., 3.)
@test minmax(NaN, 3.) == (3., 3.)
@test isequal(minmax(NaN, NaN), (NaN, NaN))
@test minmax(3., NaN) (NaN, NaN)
@test minmax(NaN, 3) (NaN, NaN)
@test minmax(Inf, NaN) (NaN, NaN)
@test minmax(NaN, Inf) (NaN, NaN)
@test minmax(-Inf, NaN) (NaN, NaN)
@test minmax(NaN, -Inf) (NaN, NaN)
@test minmax(NaN, NaN) (NaN, NaN)
@test min(-0.0,0.0) === min(0.0,-0.0)
@test max(-0.0,0.0) === max(0.0,-0.0)
@test minmax(-0.0,0.0) === minmax(0.0,-0.0)
@test max(-3.2, 5.1) == max(5.1, -3.2) == 5.1
@test min(-3.2, 5.1) == min(5.1, -3.2) == -3.2
@test max(-3.2, Inf) == max(Inf, -3.2) == Inf
@test max(-3.2, NaN) == max(NaN, -3.2) == -3.2
@test max(-3.2, NaN) max(NaN, -3.2) NaN
@test min(5.1, Inf) == min(Inf, 5.1) == 5.1
@test min(5.1, -Inf) == min(-Inf, 5.1) == -Inf
@test min(5.1, NaN) == min(NaN, 5.1) == 5.1
@test min(5.1, -NaN) == min(-NaN, 5.1) == 5.1
@test min(5.1, NaN) min(NaN, 5.1) NaN
@test min(5.1, -NaN) min(-NaN, 5.1) NaN
@test minmax(-3.2, 5.1) == (min(-3.2, 5.1), max(-3.2, 5.1))
@test minmax(-3.2, Inf) == (min(-3.2, Inf), max(-3.2, Inf))
@test minmax(-3.2, NaN) == (min(-3.2, NaN), max(-3.2, NaN))
@test (max(Inf,NaN), max(-Inf,NaN), max(Inf,-NaN), max(-Inf,-NaN)) == (Inf, -Inf, Inf, -Inf)
@test (max(NaN,Inf), max(NaN,-Inf), max(-NaN,Inf), max(-NaN,-Inf)) == (Inf, -Inf, Inf, -Inf)
@test (min(Inf,NaN), min(-Inf,NaN), min(Inf,-NaN), min(-Inf,-NaN)) == (Inf, -Inf, Inf, -Inf)
@test (min(NaN,Inf), min(NaN,-Inf), min(-NaN,Inf), min(-NaN,-Inf)) == (Inf, -Inf, Inf, -Inf)
@test minmax(-Inf,NaN) == (min(-Inf,NaN), max(-Inf,NaN))
@test minmax(-3.2, NaN) (min(-3.2, NaN), max(-3.2, NaN))
@test (max(Inf,NaN), max(-Inf,NaN), max(Inf,-NaN), max(-Inf,-NaN)) (NaN,NaN,NaN,NaN)
@test (max(NaN,Inf), max(NaN,-Inf), max(-NaN,Inf), max(-NaN,-Inf)) (NaN,NaN,NaN,NaN)
@test (min(Inf,NaN), min(-Inf,NaN), min(Inf,-NaN), min(-Inf,-NaN)) (NaN,NaN,NaN,NaN)
@test (min(NaN,Inf), min(NaN,-Inf), min(-NaN,Inf), min(-NaN,-Inf)) (NaN,NaN,NaN,NaN)
@test minmax(-Inf,NaN) (min(-Inf,NaN), max(-Inf,NaN))

# fma
let x = Int64(7)^7
Expand Down
12 changes: 6 additions & 6 deletions test/reduce.jl
Expand Up @@ -144,13 +144,13 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr)
@test isnan(minimum([NaN]))
@test isequal(extrema([NaN]), (NaN, NaN))

@test maximum([NaN, 2., 3.]) == 3.
@test minimum([NaN, 2., 3.]) == 2.
@test extrema([NaN, 2., 3.]) == (2., 3.)
@test isnan(maximum([NaN, 2., 3.]))
@test isnan(minimum([NaN, 2., 3.]))
@test isequal(extrema([NaN, 2., 3.]), (NaN,NaN))

@test maximum([4., 3., NaN, 5., 2.]) == 5.
@test minimum([4., 3., NaN, 5., 2.]) == 2.
@test extrema([4., 3., NaN, 5., 2.]) == (2., 5.)
@test isnan(maximum([4., 3., NaN, 5., 2.]))
@test isnan(minimum([4., 3., NaN, 5., 2.]))
@test isequal(extrema([4., 3., NaN, 5., 2.]), (NaN,NaN))

@test maxabs(Int[]) == 0
@test_throws ArgumentError Base.minabs(Int[])
Expand Down

0 comments on commit afe7b8e

Please sign in to comment.