From fe0866f5322649d98b9a66f64d09063cd3e4710a Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 15:48:22 -0500 Subject: [PATCH 01/15] add `nans` keyword to isapprox --- base/floatfuncs.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index f34f6875c7b6e..ecb8f3733de68 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -170,10 +170,11 @@ end # isapprox: approximate equality of numbers """ - isapprox(x, y; rtol::Real=sqrt(eps), atol::Real=0) + isapprox(x, y; rtol::Real=sqrt(eps), atol::Real=0, nans::Bool=false) Inexact equality comparison: `true` if `norm(x-y) <= atol + rtol*max(norm(x), norm(y))`. The -default `atol` is zero and the default `rtol` depends on the types of `x` and `y`. +default `atol` is zero and the default `rtol` depends on the types of `x` and `y`. The default +`nans` is false, meaning `isapprox(NaN,NaN) == false`; call with `nans=true` to have `isapprox(NaN,NaN) == true`. For real or complex floating-point values, `rtol` defaults to `sqrt(eps(typeof(real(x-y))))`. This corresponds to requiring equality of about half of the @@ -188,8 +189,8 @@ approximately equal component-wise. The binary operator `≈` is equivalent to `isapprox` with the default arguments, and `x ≉ y` is equivalent to `!isapprox(x,y)`. """ -function isapprox(x::Number, y::Number; rtol::Real=rtoldefault(x,y), atol::Real=0) - x == y || (isfinite(x) && isfinite(y) && abs(x-y) <= atol + rtol*max(abs(x), abs(y))) +function isapprox(x::Number, y::Number; rtol::Real=rtoldefault(x,y), atol::Real=0, nans::Bool=false) + x == y || (isfinite(x) && isfinite(y) && abs(x-y) <= atol + rtol*max(abs(x), abs(y))) || (nans && (isnan(x) & isnan(y))) end const ≈ = isapprox From bc14714228d73d68010ab879f7f4f9917a26a42d Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 15:59:46 -0500 Subject: [PATCH 02/15] test isapprox with nans --- test/floatfuncs.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 94a751ad447ce..fdd3325456bab 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -68,3 +68,10 @@ for elty in (Float32,Float64) @test round.(elty2,A) == fill(round(elty2,x),(10,10,10)) end end + +# isapprox +for nan in (Float16,Float32,Float64) + nan = elty(NaN) + @test isapprox(nan, nan) == false + @test isapprox(nan, nan, nans=true) == true7 +end From b8d1ae09386efc79b3ea4ae196e5194c7e596409 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 16:55:19 -0500 Subject: [PATCH 03/15] fix typo --- test/floatfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index fdd3325456bab..594adb57d161b 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -73,5 +73,5 @@ end for nan in (Float16,Float32,Float64) nan = elty(NaN) @test isapprox(nan, nan) == false - @test isapprox(nan, nan, nans=true) == true7 + @test isapprox(nan, nan, nans=true) == true end From 734344d4278fbd7f665de1414c3c0ebb96646bd2 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 17:05:58 -0500 Subject: [PATCH 04/15] isapprox with `nans` keyword --- base/linalg/uniformscaling.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 546b4fd6ae5bd..069f90507a5ec 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -166,7 +166,8 @@ broadcast(::typeof(/), J::UniformScaling,x::Number) = UniformScaling(J.λ/x) ==(J1::UniformScaling,J2::UniformScaling) = (J1.λ == J2.λ) isapprox{T<:Number,S<:Number}(J1::UniformScaling{T}, J2::UniformScaling{S}; - rtol::Real=Base.rtoldefault(T,S), atol::Real=0) = isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol) + rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) = + isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans) function copy!(A::AbstractMatrix, J::UniformScaling) size(A,1)==size(A,2) || throw(DimensionMismatch("a UniformScaling can only be copied to a square matrix")) From 93f91b2f456fa593a556f9cb6f5acd2a1d039bfa Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 17:14:25 -0500 Subject: [PATCH 05/15] isapprox with `nans` keyword --- base/linalg/generic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index dff7113069929..fe49a356ab7bd 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -1216,13 +1216,13 @@ promote_leaf_eltypes(x::Union{AbstractArray,Tuple}) = mapreduce(promote_leaf_elt # `a ≈ a` is `true`. function isapprox(x::AbstractArray, y::AbstractArray; rtol::Real=Base.rtoldefault(promote_leaf_eltypes(x),promote_leaf_eltypes(y)), - atol::Real=0, norm::Function=vecnorm) + atol::Real=0, nans::Bool=false, norm::Function=vecnorm) d = norm(x - y) if isfinite(d) return d <= atol + rtol*max(norm(x), norm(y)) else # Fall back to a component-wise approximate comparison - return all(ab -> isapprox(ab[1], ab[2]; rtol=rtol, atol=atol), zip(x, y)) + return all(ab -> isapprox(ab[1], ab[2]; rtol=rtol, atol=atol, nans=nans), zip(x, y)) end end From d745d4bf7e2677c49853aaeb2473b8d9b485394d Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 17:20:32 -0500 Subject: [PATCH 06/15] add tests for isapprox([nan],[nan]) --- test/floatfuncs.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 594adb57d161b..2582a156316dc 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -71,7 +71,10 @@ end # isapprox for nan in (Float16,Float32,Float64) - nan = elty(NaN) + nan = elty(NaN) + half = elty(0.5) @test isapprox(nan, nan) == false @test isapprox(nan, nan, nans=true) == true + @test isapprox([half, nan, half], [half, nan, half]) == false + @test isapprox([half, nan, half], [half, nan, half], nans=true) == true end From 05542af560251d0654358f34a81e44464cd7223b Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 17:38:45 -0500 Subject: [PATCH 07/15] fix bad name --- test/floatfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 2582a156316dc..946f55b36d745 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -70,7 +70,7 @@ for elty in (Float32,Float64) end # isapprox -for nan in (Float16,Float32,Float64) +for elty in (Float16,Float32,Float64) nan = elty(NaN) half = elty(0.5) @test isapprox(nan, nan) == false From 67b8def531a127ae80819fd038151a12502b3a96 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 18:35:32 -0500 Subject: [PATCH 08/15] move isapprox tests into floatapprox.jl --- test/floatfuncs.jl | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 946f55b36d745..94a751ad447ce 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -68,13 +68,3 @@ for elty in (Float32,Float64) @test round.(elty2,A) == fill(round(elty2,x),(10,10,10)) end end - -# isapprox -for elty in (Float16,Float32,Float64) - nan = elty(NaN) - half = elty(0.5) - @test isapprox(nan, nan) == false - @test isapprox(nan, nan, nans=true) == true - @test isapprox([half, nan, half], [half, nan, half]) == false - @test isapprox([half, nan, half], [half, nan, half], nans=true) == true -end From d9611df202b8052ae2429b368b3b4635b916d2f2 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 18:42:06 -0500 Subject: [PATCH 09/15] issue #19936 --- test/floatapprox.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/floatapprox.jl b/test/floatapprox.jl index fe76153082173..0ff7fd61dcd78 100644 --- a/test/floatapprox.jl +++ b/test/floatapprox.jl @@ -59,3 +59,13 @@ @test [0,1] ≈ [1e-9, 1] @test [0,Inf] ≈ [0,Inf] @test [0,Inf] ≉ [0,-Inf] + +# issue #19936 +for elty in (Float16,Float32,Float64) + nan = elty(NaN) + half = elty(0.5) + @test !isapprox(nan, nan) + @test isapprox(nan, nan, nans=true) + @test !isapprox([half, nan, half], [half, nan, half]) + @test isapprox([half, nan, half], [half, nan, half], nans=true) +end From ed1a291cbac719ecd28a2adb97dbdd015d3bd038 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 22:02:44 -0500 Subject: [PATCH 10/15] fixes trailing whitespace? --- base/linalg/uniformscaling.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 069f90507a5ec..32d5231ae7aab 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -166,7 +166,7 @@ broadcast(::typeof(/), J::UniformScaling,x::Number) = UniformScaling(J.λ/x) ==(J1::UniformScaling,J2::UniformScaling) = (J1.λ == J2.λ) isapprox{T<:Number,S<:Number}(J1::UniformScaling{T}, J2::UniformScaling{S}; - rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) = + rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) = isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans) function copy!(A::AbstractMatrix, J::UniformScaling) From 78796c8bbde67114acc582dc6a511462329e55a3 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 22:09:15 -0500 Subject: [PATCH 11/15] quash whitespace error --- base/linalg/uniformscaling.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 32d5231ae7aab..2a62ab1d80517 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -165,9 +165,10 @@ broadcast(::typeof(/), J::UniformScaling,x::Number) = UniformScaling(J.λ/x) ==(J1::UniformScaling,J2::UniformScaling) = (J1.λ == J2.λ) -isapprox{T<:Number,S<:Number}(J1::UniformScaling{T}, J2::UniformScaling{S}; - rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) = +function isapprox{T<:Number,S<:Number}(J1::UniformScaling{T}, J2::UniformScaling{S}; + rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans) +end function copy!(A::AbstractMatrix, J::UniformScaling) size(A,1)==size(A,2) || throw(DimensionMismatch("a UniformScaling can only be copied to a square matrix")) From 21c6cba6bb41256615b3098cbea91aa47cdd09ac Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 22:13:54 -0500 Subject: [PATCH 12/15] isapprox description readability --- base/floatfuncs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index ecb8f3733de68..b281b3f169658 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -173,8 +173,8 @@ end isapprox(x, y; rtol::Real=sqrt(eps), atol::Real=0, nans::Bool=false) Inexact equality comparison: `true` if `norm(x-y) <= atol + rtol*max(norm(x), norm(y))`. The -default `atol` is zero and the default `rtol` depends on the types of `x` and `y`. The default -`nans` is false, meaning `isapprox(NaN,NaN) == false`; call with `nans=true` to have `isapprox(NaN,NaN) == true`. +default `atol` is zero and the default `rtol` depends on the types of `x` and `y`. The keyword +argument `nans` determines whether or not NaN values are considered equal (defaults to false). For real or complex floating-point values, `rtol` defaults to `sqrt(eps(typeof(real(x-y))))`. This corresponds to requiring equality of about half of the From 5fb491bb4e0f8bb49f6aff18aa447d842b37f510 Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 22:14:55 -0500 Subject: [PATCH 13/15] change isapprox nan test short-circuiting --- base/floatfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index b281b3f169658..adb7bb20d1025 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -190,7 +190,7 @@ The binary operator `≈` is equivalent to `isapprox` with the default arguments is equivalent to `!isapprox(x,y)`. """ function isapprox(x::Number, y::Number; rtol::Real=rtoldefault(x,y), atol::Real=0, nans::Bool=false) - x == y || (isfinite(x) && isfinite(y) && abs(x-y) <= atol + rtol*max(abs(x), abs(y))) || (nans && (isnan(x) & isnan(y))) + x == y || (isfinite(x) && isfinite(y) && abs(x-y) <= atol + rtol*max(abs(x), abs(y))) || (nans && isnan(x) && isnan(y)) end const ≈ = isapprox From cfe5db65bed5c5c9922c3818ee2cd274ac620dfc Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 22:23:09 -0500 Subject: [PATCH 14/15] remove trailing whitespace --- test/floatapprox.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/floatapprox.jl b/test/floatapprox.jl index 0ff7fd61dcd78..ab432de6f71d8 100644 --- a/test/floatapprox.jl +++ b/test/floatapprox.jl @@ -60,7 +60,7 @@ @test [0,Inf] ≈ [0,Inf] @test [0,Inf] ≉ [0,-Inf] -# issue #19936 +# issue #19936 for elty in (Float16,Float32,Float64) nan = elty(NaN) half = elty(0.5) From 6b28ca858e3f5ff1b4a6206f8dbd58c91e9d639b Mon Sep 17 00:00:00 2001 From: Jeffrey Sarnoff Date: Fri, 13 Jan 2017 22:43:33 -0500 Subject: [PATCH 15/15] vanquish trailing whitespace --- base/linalg/uniformscaling.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 2a62ab1d80517..583ec9435a6f5 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -168,7 +168,7 @@ broadcast(::typeof(/), J::UniformScaling,x::Number) = UniformScaling(J.λ/x) function isapprox{T<:Number,S<:Number}(J1::UniformScaling{T}, J2::UniformScaling{S}; rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans) -end +end function copy!(A::AbstractMatrix, J::UniformScaling) size(A,1)==size(A,2) || throw(DimensionMismatch("a UniformScaling can only be copied to a square matrix"))