Skip to content

Commit

Permalink
Add norm kwarg to isapprox (#35883)
Browse files Browse the repository at this point in the history
Fixes #13132
  • Loading branch information
sloede authored May 14, 2020
1 parent 08861c7 commit e58bc72
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 11 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ New library features
Standard library changes
------------------------
* The `nextprod` function now accepts tuples and other array types for its first argument ([#35791]).
* The function `isapprox(x,y)` now accepts the `norm` keyword argument also for numeric (i.e., non-array) arguments `x` and `y` ([#35883]).

#### LinearAlgebra

Expand Down
15 changes: 8 additions & 7 deletions base/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ end

# isapprox: approximate equality of numbers
"""
isapprox(x, y; rtol::Real=atol>0 ? 0 : √eps, atol::Real=0, nans::Bool=false, norm::Function)
isapprox(x, y; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps, nans::Bool=false[, norm::Function])
Inexact equality comparison: `true` if `norm(x-y) <= max(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 keyword
Expand All @@ -234,10 +234,9 @@ the square root of [`eps`](@ref) of the type of `x` or `y`, whichever is bigger
This corresponds to requiring equality of about half of the significand digits. Otherwise,
e.g. for integer arguments or if an `atol > 0` is supplied, `rtol` defaults to zero.
`x` and `y` may also be arrays of numbers, in which case `norm` defaults to the usual
`norm` function in LinearAlgebra, but
may be changed by passing a `norm::Function` keyword argument. (For numbers, `norm` is the
same thing as `abs`.) When `x` and `y` are arrays, if `norm(x-y)` is not finite (i.e. `±Inf`
The `norm` keyword defaults to `abs` for numeric `(x,y)` and to `LinearAlgebra.norm` for
arrays (where an alternative `norm` choice is sometimes useful).
When `x` and `y` are arrays, if `norm(x-y)` is not finite (i.e. `±Inf`
or `NaN`), the comparison falls back to checking whether all elements of `x` and `y` are
approximately equal component-wise.
Expand Down Expand Up @@ -273,8 +272,10 @@ julia> isapprox(1e-10, 0, atol=1e-8)
true
```
"""
function isapprox(x::Number, y::Number; atol::Real=0, rtol::Real=rtoldefault(x,y,atol), nans::Bool=false)
x == y || (isfinite(x) && isfinite(y) && abs(x-y) <= max(atol, rtol*max(abs(x), abs(y)))) || (nans && isnan(x) && isnan(y))
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))
end

"""
Expand Down
14 changes: 10 additions & 4 deletions test/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -670,10 +670,16 @@ end
@test exp10(Float16(1.0)) === Float16(exp10(1.0))
end

# #22742: updated isapprox semantics
@test !isapprox(1.0, 1.0+1e-12, atol=1e-14)
@test isapprox(1.0, 1.0+0.5*sqrt(eps(1.0)))
@test !isapprox(1.0, 1.0+1.5*sqrt(eps(1.0)), atol=sqrt(eps(1.0)))
@testset "isapprox" begin
# #22742: updated isapprox semantics
@test !isapprox(1.0, 1.0+1e-12, atol=1e-14)
@test isapprox(1.0, 1.0+0.5*sqrt(eps(1.0)))
@test !isapprox(1.0, 1.0+1.5*sqrt(eps(1.0)), atol=sqrt(eps(1.0)))

# #13132: Use of `norm` kwarg for scalar arguments
@test isapprox(1, 1+1.0e-12, norm=abs)
@test !isapprox(1, 1+1.0e-12, norm=x->1)
end

# test AbstractFloat fallback pr22716
struct Float22716{T<:AbstractFloat} <: AbstractFloat
Expand Down

0 comments on commit e58bc72

Please sign in to comment.