diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 9b8ca4b04ee28..bac500955d916 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -304,7 +304,20 @@ true function isapprox(x::Number, y::Number; atol::Real=0, rtol::Real=rtoldefault(x,y,atol), nans::Bool=false, norm::Function=abs) - x == y || (isfinite(x) && isfinite(y) && norm(x-y) <= max(atol, rtol*max(norm(x), norm(y)))) || (nans && isnan(x) && isnan(y)) + x′, y′ = promote(x, y) # to avoid integer overflow + x == y || + (isfinite(x) && isfinite(y) && norm(x-y) <= max(atol, rtol*max(norm(x′), norm(y′)))) || + (nans && isnan(x) && isnan(y)) +end + +function isapprox(x::Integer, y::Integer; + atol::Real=0, rtol::Real=rtoldefault(x,y,atol), + nans::Bool=false, norm::Function=abs) + if norm === abs && atol < 1 && rtol == 0 + return x == y + else + return norm(x - y) <= max(atol, rtol*max(norm(x), norm(y))) + end end """ diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 7e9d8021ac5df..321f1881371a3 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -209,3 +209,47 @@ end struct CustomNumber <: Number end @test !isnan(CustomNumber()) end + +@testset "isapprox and integer overflow" begin + for T in (Int8, Int16, Int32) + T === Int && continue + @test !isapprox(typemin(T), T(0)) + @test !isapprox(typemin(T), unsigned(T)(0)) + @test !isapprox(typemin(T), 0) + @test !isapprox(typemin(T), T(0), atol=0.99) + @test !isapprox(typemin(T), unsigned(T)(0), atol=0.99) + @test !isapprox(typemin(T), 0, atol=0.99) + @test_broken !isapprox(typemin(T), T(0), atol=1) + @test_broken !isapprox(typemin(T), unsigned(T)(0), atol=1) + @test !isapprox(typemin(T), 0, atol=1) + + @test !isapprox(typemin(T)+T(10), T(10)) + @test !isapprox(typemin(T)+T(10), unsigned(T)(10)) + @test !isapprox(typemin(T)+T(10), 10) + @test !isapprox(typemin(T)+T(10), T(10), atol=0.99) + @test !isapprox(typemin(T)+T(10), unsigned(T)(10), atol=0.99) + @test !isapprox(typemin(T)+T(10), 10, atol=0.99) + @test_broken !isapprox(typemin(T)+T(10), T(10), atol=1) + @test !isapprox(typemin(T)+T(10), unsigned(T)(10), atol=1) + @test !isapprox(typemin(T)+T(10), 10, atol=1) + + @test isapprox(typemin(T), 0.0, rtol=1) + end + for T in (Int, Int64, Int128) + @test !isapprox(typemin(T), T(0)) + @test !isapprox(typemin(T), unsigned(T)(0)) + @test !isapprox(typemin(T), T(0), atol=0.99) + @test !isapprox(typemin(T), unsigned(T)(0), atol=0.99) + @test_broken !isapprox(typemin(T), T(0), atol=1) + @test_broken !isapprox(typemin(T), unsigned(T)(0), atol=1) + + @test !isapprox(typemin(T)+T(10), T(10)) + @test !isapprox(typemin(T)+T(10), unsigned(T)(10)) + @test !isapprox(typemin(T)+T(10), T(10), atol=0.99) + @test !isapprox(typemin(T)+T(10), unsigned(T)(10), atol=0.99) + @test_broken !isapprox(typemin(T)+T(10), T(10), atol=1) + @test !isapprox(typemin(T)+T(10), unsigned(T)(10), atol=1) + + @test isapprox(typemin(T), 0.0, rtol=1) + end +end