Skip to content

Commit ffffc15

Browse files
authored
Allow a tolerance in check macro (#3)
1 parent d6f8138 commit ffffc15

File tree

3 files changed

+19
-2
lines changed

3 files changed

+19
-2
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ It then tests whether the result obtained from the "safe" arguments is consisten
5050
the result obtained from `a` and `b`.
5151
If the two differ to within the precision of the "ordinary" (unsafe) result, an
5252
error is thrown.
53+
Optionally, you can supply keywords accepted by `isapprox`:
54+
55+
```julia
56+
@check foo(a) atol=1e-12
57+
```
5358

5459
Packages can specialize `CheckedArithmetic.safearg` to control how `asafe` and `bsafe`
5560
are generated. To guard against oversights, `safearg` must be explicitly defined for

src/CheckedArithmetic.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,22 @@ macro checked(expr)
9999
return esc(replace_checked!(expr))
100100
end
101101

102-
macro check(expr)
102+
macro check(expr, kws...)
103103
isexpr(expr, :call) || error("expected :call expression, got ",
104104
isa(expr, Expr) ? QuoteNode(expr.head) : typeof(expr))
105105
safeexpr = copy(expr)
106106
for i = 2:length(expr.args)
107107
safeexpr.args[i] = Expr(:call, :(CheckedArithmetic.safearg), expr.args[i])
108108
end
109+
cmpexpr = isempty(kws) ? :(val == valcmp || error(val, " is not equal to ", valcmp)) :
110+
:(isapprox(val, valcmp; $(esc(kws...))) || error(val, " is not approximately equal to ", valcmp))
109111
return quote
110112
local val = $(esc(expr))
111113
local valcmp = CheckedArithmetic.safeconvert(typeof(val), $(esc(safeexpr)))
112114
if ismissing(val) && ismissing(valcmp)
113115
val
114116
else
115-
val == valcmp || error(val, " is not equal to ", valcmp)
117+
$cmpexpr
116118
val
117119
end
118120
end
@@ -147,6 +149,8 @@ safearg_type(::Type{Float32}) = Float64
147149
safearg_type(::Type{Float16}) = Float64
148150
safearg_type(::Type{T}) where T<:Base.TwicePrecision = T
149151

152+
safearg_type(::Type{<:Rational}) = Float64
153+
150154
"""
151155
xsafe = CheckedArithmetic.safearg(x)
152156

test/runtests.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ end
7070
now()]
7171
@test @check(identity(item)) === item
7272
end
73+
74+
# Roundoff error
75+
function diff2from1(s)
76+
s2 = copy(s + s)
77+
return 1 - s2
78+
end
79+
@test_throws ErrorException @check diff2from1(1//3)
80+
@test (@check diff2from1(1//3) atol=1e-12) == 1//3
7381
end
7482

7583
@testset "acc" begin

0 commit comments

Comments
 (0)