Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add isapprox for arrays, with ≈ and ≉ synonyms #12472

Merged
merged 1 commit into from
Aug 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ Library improvements

* The `MathConst` type has been renamed `Irrational` ([#11922]).

* `isapprox` now has simpler and more sensible default tolerances ([#12393]).
* `isapprox` now has simpler and more sensible default tolerances ([#12393]), supports arrays, and has synonyms `≈` ([U+2248](http://www.fileformat.info/info/unicode/char/2248/index.htm), LaTeX `\approx`) and `≉` ([U+2249](http://www.fileformat.info/info/unicode/char/2249/index.htm), LaTeX `\napprox`) for `isapprox` and `!isapprox`, respectively ([#12472]).

* Numbers

Expand Down Expand Up @@ -1563,11 +1563,13 @@ Too numerous to mention.
[#11891]: https://github.com/JuliaLang/julia/issues/11891
[#11922]: https://github.com/JuliaLang/julia/issues/11922
[#11985]: https://github.com/JuliaLang/julia/issues/11985
[#12025]: https://github.com/JuliaLang/julia/issues/12025
[#12031]: https://github.com/JuliaLang/julia/issues/12031
[#12034]: https://github.com/JuliaLang/julia/issues/12034
[#12087]: https://github.com/JuliaLang/julia/issues/12087
[#12137]: https://github.com/JuliaLang/julia/issues/12137
[#12162]: https://github.com/JuliaLang/julia/issues/12162
[#12393]: https://github.com/JuliaLang/julia/issues/12393
[#12458]: https://github.com/JuliaLang/julia/issues/12458
[#12472]: https://github.com/JuliaLang/julia/issues/12472
[#12491]: https://github.com/JuliaLang/julia/issues/12491
11 changes: 9 additions & 2 deletions base/docs/helpdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2935,11 +2935,18 @@ cis
doc"""
```rst
::
isapprox(x::Number, y::Number; rtol::Real=sqrt(eps), atol::Real=0)
isapprox(x, y; rtol::Real=sqrt(eps), atol::Real=0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

signature may need to be updated to match this in the RST docs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed.


Inexact equality comparison: ``true`` if ``abs(x-y) <= atol + rtol*max(abs(x), abs(y))``. The default ``atol`` is zero and the default ``rtol`` depends on the types of ``x`` and ``y``.
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``.

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 significand digits. For other types, ``rtol`` defaults to zero.

``x`` and ``y`` may also be arrays of numbers, in which case ``norm``
defaults to ``vecnorm`` but may be changed by passing a
``norm::Function`` keyword argument. (For numbers, ``norm`` is the
same thing as ``abs``.)

The binary operator ``≈`` is equivalent to ``isapprox`` with the default arguments, and ``x ≉ y`` is equivalent to ``!isapprox(x,y)``.
```
"""
isapprox
Expand Down
2 changes: 2 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ export
zero,
√,
∛,
≈,
≉,

# specfun
airy,
Expand Down
8 changes: 6 additions & 2 deletions base/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,14 @@ for f in (:round, :ceil, :floor, :trunc)
end

# isapprox: approximate equality of numbers
isapprox(x::Number, y::Number; rtol::Real=rtoldefault(x,y), atol::Real=0) =
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)))
end

const ≈ = isapprox
≉(x,y) = !(x ≈ y)

# default tolerance arguments
rtoldefault{T<:AbstractFloat}(::Type{T}) = sqrt(eps(T))
rtoldefault{T<:Real}(::Type{T}) = 0
rtoldefault{T<:Number,S<:Number}(x::T, y::S) = rtoldefault(promote_type(real(T),real(S)))
rtoldefault{T<:Number,S<:Number}(x::Union(T,Type{T}), y::Union(S,Type{S})) = rtoldefault(promote_type(real(T),real(S)))
3 changes: 2 additions & 1 deletion base/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module LinAlg
importall Base
importall ..Base.Operators
import Base: USE_BLAS64, size, copy, copy_transpose!, power_by_squaring,
print_matrix, transpose!, unsafe_getindex, unsafe_setindex!
print_matrix, transpose!, unsafe_getindex, unsafe_setindex!,
isapprox

export
# Modules
Expand Down
5 changes: 5 additions & 0 deletions base/linalg/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,8 @@ det(x::Number) = x
logdet(A::AbstractMatrix) = logdet(lufact(A))
logabsdet(A::AbstractMatrix) = logabsdet(lufact(A))

# isapprox: approximate equality of arrays [like isapprox(Number,Number)]
function isapprox{T<:Number,S<:Number}(x::AbstractArray{T}, y::AbstractArray{S}; rtol::Real=Base.rtoldefault(T,S), atol::Real=0, norm::Function=vecnorm)
d = norm(x - y)
return isfinite(d) ? d <= atol + rtol*max(norm(x), norm(y)) : x == y
end
39 changes: 26 additions & 13 deletions test/floatapprox.jl
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license

# Floating point numbers - basic tests
@test isapprox(4.00000000000001, 4.0)
@test isapprox(5.0,4.999999999999993)
@test !isapprox(4.000000002, 4.00300002)
@test 4.000000000000014.0
@test 5.04.999999999999993
@test 4.0000000024.00300002

# Other tolerance levels
@test isapprox(4.32, 4.3; rtol=0.1, atol=0.01)
@test isapprox(1.001, 1.002; rtol=0.001, atol=0.0001)
@test !isapprox(4.5, 4.9; rtol=0.001, atol=0.001)

# Complex numbers
@test isapprox(1.0 + 1.0im, 1.0 + 1.00000000000001im)
@test isapprox(0.9999999999999 + 1.0im, 1.0 + 1.000000000000001im)
@test 1.0 + 1.0im1.0 + 1.00000000000001im
@test 0.9999999999999 + 1.0im1.0 + 1.000000000000001im
@test isapprox(0.9999 + 1.0im, 1.0 + 1.1im; rtol = 0.0001, atol=1.1)

# Complex <-> reals
@test isapprox(1.0 + 0im, 1.0000000000001)
@test 1.0 + 0im1.0000000000001
@test isapprox(0.9999999999999, 1.0 + 0im)
@test !isapprox(1.0+1im, 1.000000000000001)

# Comparing NaNs
@test !isapprox(4.0,NaN)
@test !isapprox(NaN,4.0)
@test !isapprox(complex(2.3,NaN), complex(NaN,2.3))
@test !isapprox(NaN, NaN)
@test !isapprox(complex(NaN,NaN), complex(NaN,NaN))
@test !isapprox(complex(NaN,2.3), complex(NaN,2.3))
@test !isapprox(complex(2.3,NaN), complex(2.3,NaN))
@test 4.0 ≉ NaN
@test NaN ≉ 4.0
@test complex(2.3,NaN) ≉ complex(NaN,2.3)
@test NaN ≉ NaN
@test complex(NaN,NaN) ≉ complex(NaN,NaN)
@test complex(NaN,2.3) ≉ complex(NaN,2.3)
@test complex(2.3,NaN) ≉ complex(2.3,NaN)

# Comparing Infs
@test Inf ≈ Inf
@test Inf ≉ 1
@test Inf ≉ -Inf
@test complex(0.0,Inf) ≈ complex(0.0,Inf)
@test complex(0.0,Inf) ≉ complex(0.0,-Inf)

# Tests for integers and rationals
@test isapprox(4,4)
Expand All @@ -46,3 +53,9 @@

# issue #12375:
@test !isapprox(1e17, 1)

# Tests for arrays:
@test [1,2,3] ≈ [1,2,3+1e-9]
@test [0,1] ≈ [1e-9, 1]
@test [0,Inf] ≈ [0,Inf]
@test [0,Inf] ≉ [0,-Inf]