Skip to content

Commit b1ecd56

Browse files
committed
max and min of NaN return NaN (closes #7866) (fixes #12552)
1 parent fb503a0 commit b1ecd56

File tree

7 files changed

+41
-37
lines changed

7 files changed

+41
-37
lines changed

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ This section lists changes that do not have deprecation warnings.
3131
Library improvements
3232
--------------------
3333

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

@@ -551,6 +553,7 @@ Language tooling improvements
551553
[#11242]: https://github.com/JuliaLang/julia/issues/11242
552554
[#11688]: https://github.com/JuliaLang/julia/issues/11688
553555
[#12231]: https://github.com/JuliaLang/julia/issues/12231
556+
[#12563]: https://github.com/JuliaLang/julia/issues/12563
554557
[#12819]: https://github.com/JuliaLang/julia/issues/12819
555558
[#12872]: https://github.com/JuliaLang/julia/issues/12872
556559
[#13062]: https://github.com/JuliaLang/julia/issues/13062

base/math.jl

+5-6
Original file line numberDiff line numberDiff line change
@@ -314,16 +314,15 @@ atan2(y::Float64, x::Float64) = ccall((:atan2,libm), Float64, (Float64, Float64,
314314
atan2(y::Float32, x::Float32) = ccall((:atan2f,libm), Float32, (Float32, Float32), y, x)
315315

316316
max{T<:AbstractFloat}(x::T, y::T) = ifelse((y > x) | (signbit(y) < signbit(x)),
317-
ifelse(isnan(y), x, y), ifelse(isnan(x), y, x))
317+
ifelse(isnan(x), x, y), ifelse(isnan(y), y, x))
318318

319319

320320
min{T<:AbstractFloat}(x::T, y::T) = ifelse((y < x) | (signbit(y) > signbit(x)),
321-
ifelse(isnan(y), x, y), ifelse(isnan(x), y, x))
321+
ifelse(isnan(x), x, y), ifelse(isnan(y), y, x))
322322

323-
minmax{T<:AbstractFloat}(x::T, y::T) = ifelse(isnan(x-y), ifelse(isnan(x), (y, y), (x, x)),
324-
ifelse((y < x) | (signbit(y) > signbit(x)), (y, x),
325-
ifelse((y > x) | (signbit(y) < signbit(x)), (x, y),
326-
ifelse(x == x, (x, x), (y, y)))))
323+
minmax{T<:AbstractFloat}(x::T, y::T) =
324+
ifelse(isnan(x) | isnan(y), ifelse(isnan(x), (x,x), (y,y)),
325+
ifelse((y > x) | (signbit(x) > signbit(y)), (x,y), (y,x)))
327326

328327

329328
"""

base/mpfr.jl

+4
Original file line numberDiff line numberDiff line change
@@ -584,12 +584,16 @@ function log1p(x::BigFloat)
584584
end
585585

586586
function max(x::BigFloat, y::BigFloat)
587+
isnan(x) && return x
588+
isnan(y) && return y
587589
z = BigFloat()
588590
ccall((:mpfr_max, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &x, &y, ROUNDING_MODE[])
589591
return z
590592
end
591593

592594
function min(x::BigFloat, y::BigFloat)
595+
isnan(x) && return x
596+
isnan(y) && return y
593597
z = BigFloat()
594598
ccall((:mpfr_min, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &x, &y, ROUNDING_MODE[])
595599
return z

base/reduce.jl

+3-11
Original file line numberDiff line numberDiff line change
@@ -503,19 +503,11 @@ function extrema(itr)
503503
s = start(itr)
504504
done(itr, s) && throw(ArgumentError("collection must be non-empty"))
505505
(v, s) = next(itr, s)
506-
while v != v && !done(itr, s)
507-
(x, s) = next(itr, s)
508-
v = x
509-
end
510-
vmin = v
511-
vmax = v
506+
vmin = vmax = v
512507
while !done(itr, s)
513508
(x, s) = next(itr, s)
514-
if x > vmax
515-
vmax = x
516-
elseif x < vmin
517-
vmin = x
518-
end
509+
vmax = max(x, vmax)
510+
vmin = min(x, vmin)
519511
end
520512
return (vmin, vmax)
521513
end

test/mpfr.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,8 @@ y = BigFloat(2)
301301
@test max(x,y) == x
302302
@test min(x,y) == y
303303
y = BigFloat(NaN)
304-
@test max(x,y) == x
305-
@test min(x,y) == x
304+
@test isnan(max(x,y))
305+
@test isnan(min(x,y))
306306
@test isnan(max(y,y))
307307
@test isnan(min(y,y))
308308

test/numbers.jl

+18-12
Original file line numberDiff line numberDiff line change
@@ -54,35 +54,41 @@
5454
@test 2.0 * 3.0 == 6.
5555
@test min(1.0,1) == 1
5656

57+
const = isequal # convenient for comparing NaNs
58+
5759
# min, max and minmax
5860
@test min(1) === 1
5961
@test max(1) === 1
6062
@test minmax(1) === (1, 1)
6163
@test minmax(5, 3) == (3, 5)
6264
@test minmax(3., 5.) == (3., 5.)
6365
@test minmax(5., 3.) == (3., 5.)
64-
@test minmax(3., NaN) == (3., 3.)
65-
@test minmax(NaN, 3.) == (3., 3.)
66-
@test isequal(minmax(NaN, NaN), (NaN, NaN))
66+
@test minmax(3., NaN) (NaN, NaN)
67+
@test minmax(NaN, 3) (NaN, NaN)
68+
@test minmax(Inf, NaN) (NaN, NaN)
69+
@test minmax(NaN, Inf) (NaN, NaN)
70+
@test minmax(-Inf, NaN) (NaN, NaN)
71+
@test minmax(NaN, -Inf) (NaN, NaN)
72+
@test minmax(NaN, NaN) (NaN, NaN)
6773
@test min(-0.0,0.0) === min(0.0,-0.0)
6874
@test max(-0.0,0.0) === max(0.0,-0.0)
6975
@test minmax(-0.0,0.0) === minmax(0.0,-0.0)
7076
@test max(-3.2, 5.1) == max(5.1, -3.2) == 5.1
7177
@test min(-3.2, 5.1) == min(5.1, -3.2) == -3.2
7278
@test max(-3.2, Inf) == max(Inf, -3.2) == Inf
73-
@test max(-3.2, NaN) == max(NaN, -3.2) == -3.2
79+
@test max(-3.2, NaN) max(NaN, -3.2) NaN
7480
@test min(5.1, Inf) == min(Inf, 5.1) == 5.1
7581
@test min(5.1, -Inf) == min(-Inf, 5.1) == -Inf
76-
@test min(5.1, NaN) == min(NaN, 5.1) == 5.1
77-
@test min(5.1, -NaN) == min(-NaN, 5.1) == 5.1
82+
@test min(5.1, NaN) min(NaN, 5.1) NaN
83+
@test min(5.1, -NaN) min(-NaN, 5.1) NaN
7884
@test minmax(-3.2, 5.1) == (min(-3.2, 5.1), max(-3.2, 5.1))
7985
@test minmax(-3.2, Inf) == (min(-3.2, Inf), max(-3.2, Inf))
80-
@test minmax(-3.2, NaN) == (min(-3.2, NaN), max(-3.2, NaN))
81-
@test (max(Inf,NaN), max(-Inf,NaN), max(Inf,-NaN), max(-Inf,-NaN)) == (Inf, -Inf, Inf, -Inf)
82-
@test (max(NaN,Inf), max(NaN,-Inf), max(-NaN,Inf), max(-NaN,-Inf)) == (Inf, -Inf, Inf, -Inf)
83-
@test (min(Inf,NaN), min(-Inf,NaN), min(Inf,-NaN), min(-Inf,-NaN)) == (Inf, -Inf, Inf, -Inf)
84-
@test (min(NaN,Inf), min(NaN,-Inf), min(-NaN,Inf), min(-NaN,-Inf)) == (Inf, -Inf, Inf, -Inf)
85-
@test minmax(-Inf,NaN) == (min(-Inf,NaN), max(-Inf,NaN))
86+
@test minmax(-3.2, NaN) (min(-3.2, NaN), max(-3.2, NaN))
87+
@test (max(Inf,NaN), max(-Inf,NaN), max(Inf,-NaN), max(-Inf,-NaN)) (NaN,NaN,NaN,NaN)
88+
@test (max(NaN,Inf), max(NaN,-Inf), max(-NaN,Inf), max(-NaN,-Inf)) (NaN,NaN,NaN,NaN)
89+
@test (min(Inf,NaN), min(-Inf,NaN), min(Inf,-NaN), min(-Inf,-NaN)) (NaN,NaN,NaN,NaN)
90+
@test (min(NaN,Inf), min(NaN,-Inf), min(-NaN,Inf), min(-NaN,-Inf)) (NaN,NaN,NaN,NaN)
91+
@test minmax(-Inf,NaN) (min(-Inf,NaN), max(-Inf,NaN))
8692

8793
# fma
8894
let x = Int64(7)^7

test/reduce.jl

+6-6
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,13 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr)
144144
@test isnan(minimum([NaN]))
145145
@test isequal(extrema([NaN]), (NaN, NaN))
146146

147-
@test maximum([NaN, 2., 3.]) == 3.
148-
@test minimum([NaN, 2., 3.]) == 2.
149-
@test extrema([NaN, 2., 3.]) == (2., 3.)
147+
@test isnan(maximum([NaN, 2., 3.]))
148+
@test isnan(minimum([NaN, 2., 3.]))
149+
@test isequal(extrema([NaN, 2., 3.]), (NaN,NaN))
150150

151-
@test maximum([4., 3., NaN, 5., 2.]) == 5.
152-
@test minimum([4., 3., NaN, 5., 2.]) == 2.
153-
@test extrema([4., 3., NaN, 5., 2.]) == (2., 5.)
151+
@test isnan(maximum([4., 3., NaN, 5., 2.]))
152+
@test isnan(minimum([4., 3., NaN, 5., 2.]))
153+
@test isequal(extrema([4., 3., NaN, 5., 2.]), (NaN,NaN))
154154

155155
@test maxabs(Int[]) == 0
156156
@test_throws ArgumentError Base.minabs(Int[])

0 commit comments

Comments
 (0)