From 59c2501e6172e43669dcb38f5d0c54bba439bf29 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Fri, 8 Oct 2021 08:31:59 -0500 Subject: [PATCH 1/4] fix exp(NaN16) and add tests --- base/special/exp.jl | 2 +- test/math.jl | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/base/special/exp.jl b/base/special/exp.jl index 110cd93410d73..f6a3f52faeebe 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -281,7 +281,7 @@ end small_part = expb_kernel(base, r) if !(abs(x) <= SUBNORM_EXP(base, T)) x > MAX_EXP(base, T) && return Inf16 - N<=Int32(-24) && return zero(Float16) + x < MIN_EXP(base, T) && return zero(Float16) end twopk = reinterpret(T, (N+Int32(127)) << Int32(23)) return Float16(twopk*small_part) diff --git a/test/math.jl b/test/math.jl index 2960730f5dc4d..6dcfddb625f35 100644 --- a/test/math.jl +++ b/test/math.jl @@ -308,7 +308,7 @@ end end end -@testset "exp function" for T in (Float64, Float32) +@testset "exp function" for T in (Float64, Float32, Float16) @testset "$T accuracy" begin X = map(T, vcat(-10:0.0002:10, -80:0.001:80, 2.0^-27, 2.0^-28, 2.0^-14, 2.0^-13)) for x in X @@ -320,6 +320,7 @@ end @test isnan_type(T, exp(T(NaN))) @test exp(T(-Inf)) === T(0.0) @test exp(T(Inf)) === T(Inf) + @test exp(T(NaN)) === T(NaN) @test exp(T(0.0)) === T(1.0) # exact @test exp(T(5000.0)) === T(Inf) @test exp(T(-5000.0)) === T(0.0) @@ -339,10 +340,11 @@ end @test abs(y-yb) <= 1.2*eps(Float32(yb)) end end - @testset "$T edge cases" for T in (Float64, Float32) + @testset "$T edge cases" for T in (Float64, Float32, Float16) @test isnan_type(T, exp10(T(NaN))) @test exp10(T(-Inf)) === T(0.0) @test exp10(T(Inf)) === T(Inf) + @test exp(T(NaN)) === T(NaN) @test exp10(T(0.0)) === T(1.0) # exact @test exp10(T(1.0)) === T(10.0) @test exp10(T(3.0)) === T(1000.0) From 373926e509b4d3e271ca24109c10d2300174597a Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Fri, 8 Oct 2021 14:18:09 -0500 Subject: [PATCH 2/4] fix test --- test/math.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/math.jl b/test/math.jl index 6dcfddb625f35..694d47144adc6 100644 --- a/test/math.jl +++ b/test/math.jl @@ -313,7 +313,7 @@ end X = map(T, vcat(-10:0.0002:10, -80:0.001:80, 2.0^-27, 2.0^-28, 2.0^-14, 2.0^-13)) for x in X y, yb = exp(x), exp(big(x)) - @test abs(y-yb) <= 1.0*eps(T(yb)) + @test y===T(yb) || abs(y-yb) <= 1.0*eps(T(yb)) end end @testset "$T edge cases" begin @@ -332,12 +332,12 @@ end X = map(Float64, vcat(-10:0.00021:10, -35:0.0023:100, -300:0.001:300)) for x in X y, yb = exp10(x), exp10(big(x)) - @test abs(y-yb) <= 1.2*eps(Float64(yb)) + @test y===T(yb) || abs(y-yb) <= 1.2*eps(Float64(yb)) end X = map(Float32, vcat(-10:0.00021:10, -35:0.0023:35, -35:0.001:35)) for x in X y, yb = exp10(x), exp10(big(x)) - @test abs(y-yb) <= 1.2*eps(Float32(yb)) + @test y===T(yb) || abs(y-yb) <= 1.2*eps(Float32(yb)) end end @testset "$T edge cases" for T in (Float64, Float32, Float16) From 5912acef86006ef0d492715defd571ebc79566a0 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Sun, 10 Oct 2021 17:38:47 -0500 Subject: [PATCH 3/4] fix tests --- test/math.jl | 54 +++++++++++++++------------------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/test/math.jl b/test/math.jl index 694d47144adc6..8ce31d4764d55 100644 --- a/test/math.jl +++ b/test/math.jl @@ -309,48 +309,24 @@ end end @testset "exp function" for T in (Float64, Float32, Float16) - @testset "$T accuracy" begin - X = map(T, vcat(-10:0.0002:10, -80:0.001:80, 2.0^-27, 2.0^-28, 2.0^-14, 2.0^-13)) - for x in X - y, yb = exp(x), exp(big(x)) - @test y===T(yb) || abs(y-yb) <= 1.0*eps(T(yb)) - end - end - @testset "$T edge cases" begin - @test isnan_type(T, exp(T(NaN))) - @test exp(T(-Inf)) === T(0.0) - @test exp(T(Inf)) === T(Inf) - @test exp(T(NaN)) === T(NaN) - @test exp(T(0.0)) === T(1.0) # exact - @test exp(T(5000.0)) === T(Inf) - @test exp(T(-5000.0)) === T(0.0) - end -end - -@testset "exp10 function" begin - @testset "accuracy" begin - X = map(Float64, vcat(-10:0.00021:10, -35:0.0023:100, -300:0.001:300)) - for x in X - y, yb = exp10(x), exp10(big(x)) - @test y===T(yb) || abs(y-yb) <= 1.2*eps(Float64(yb)) + for func in (exp2,exp,exp10) + @testset "$T $func accuracy" begin + X = map(T, vcat(-10:0.00021:10, -300:0.001:300, 2.0^-27, 2.0^-28, 2.0^-14, 2.0^-13)) + for x in X + y, yb = func(x), func(big(x)) + @test y===T(yb) || abs(y-yb) <= 1.2*eps(T(yb)) + end end - X = map(Float32, vcat(-10:0.00021:10, -35:0.0023:35, -35:0.001:35)) - for x in X - y, yb = exp10(x), exp10(big(x)) - @test y===T(yb) || abs(y-yb) <= 1.2*eps(Float32(yb)) + @testset "$T $func edge cases" begin + @test isnan_type(T, exp(T(NaN))) + @test func(T(-Inf)) === T(0.0) + @test func(T(Inf)) === T(Inf) + @test func(T(NaN)) === T(NaN) + @test func(T(0.0)) === T(1.0) # exact + @test func(T(5000.0)) === T(Inf) + @test func(T(-5000.0)) === T(0.0) end end - @testset "$T edge cases" for T in (Float64, Float32, Float16) - @test isnan_type(T, exp10(T(NaN))) - @test exp10(T(-Inf)) === T(0.0) - @test exp10(T(Inf)) === T(Inf) - @test exp(T(NaN)) === T(NaN) - @test exp10(T(0.0)) === T(1.0) # exact - @test exp10(T(1.0)) === T(10.0) - @test exp10(T(3.0)) === T(1000.0) - @test exp10(T(5000.0)) === T(Inf) - @test exp10(T(-5000.0)) === T(0.0) - end end @testset "test abstractarray trig functions" begin From 7a5a60a5722a2209c4897a6b7f2095fea4a63d05 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Sun, 10 Oct 2021 18:15:36 -0500 Subject: [PATCH 4/4] improve tests --- test/math.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/math.jl b/test/math.jl index 8ce31d4764d55..57d7de3af36df 100644 --- a/test/math.jl +++ b/test/math.jl @@ -308,17 +308,21 @@ end end end -@testset "exp function" for T in (Float64, Float32, Float16) - for func in (exp2,exp,exp10) +@testset "exponential functions" for T in (Float64, Float32, Float16) + for (func, invfunc) in ((exp2, log2), (exp, log), (exp10, log10)) @testset "$T $func accuracy" begin - X = map(T, vcat(-10:0.00021:10, -300:0.001:300, 2.0^-27, 2.0^-28, 2.0^-14, 2.0^-13)) + minval, maxval = invfunc(floatmin(T)),prevfloat(invfunc(floatmax(T))) + # Test range and extensively test numbers near 0. + X = Iterators.flatten((minval:T(.1):maxval, + minval/100:T(.0021):maxval/100, + minval/10000:T(.000021):maxval/10000, + nextfloat(zero(T)) )) for x in X - y, yb = func(x), func(big(x)) - @test y===T(yb) || abs(y-yb) <= 1.2*eps(T(yb)) + y, yb = func(x), func(widen(x)) + @test abs(y-yb) <= 1.2*eps(T(yb)) end end @testset "$T $func edge cases" begin - @test isnan_type(T, exp(T(NaN))) @test func(T(-Inf)) === T(0.0) @test func(T(Inf)) === T(Inf) @test func(T(NaN)) === T(NaN)