Skip to content

Commit 10b396a

Browse files
committed
Implement isapprox for FixedPoint
By default it asks whether two FixedPoints are within eps of each other. Handy in testing.
1 parent d41a0a1 commit 10b396a

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

src/FixedPointNumbers.jl

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module FixedPointNumbers
44

55
using Base: reducedim_initarray
66

7-
import Base: ==, <, <=, -, +, *, /, ~,
7+
import Base: ==, <, <=, -, +, *, /, ~, isapprox,
88
convert, promote_rule, show, showcompact, isinteger, abs, decompose,
99
isnan, isinf, isfinite,
1010
zero, one, typemin, typemax, realmin, realmax, eps, sizeof, reinterpret,
@@ -51,6 +51,19 @@ reinterpret(x::FixedPoint) = x.i
5151
=={T <: FixedPoint}(x::T, y::T) = x.i == y.i
5252
<{T <: FixedPoint}(x::T, y::T) = x.i < y.i
5353
<={T <: FixedPoint}(x::T, y::T) = x.i <= y.i
54+
"""
55+
isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y)))
56+
57+
For FixedPoint numbers, the default criterion is that `x` and `y` differ by no more than `eps`, the separation between adjacent fixed-point numbers.
58+
"""
59+
function isapprox{T<:FixedPoint}(x::T, y::T; rtol=0, atol=max(eps(x), eps(y)))
60+
maxdiff = T(atol+rtol*max(abs(x), abs(y)))
61+
rx, ry, rd = reinterpret(x), reinterpret(y), reinterpret(maxdiff)
62+
abs(signed(widen1(rx))-signed(widen1(ry))) <= rd
63+
end
64+
function isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y)))
65+
isapprox(promote(x, y)...; rtol=rtol, atol=atol)
66+
end
5467

5568
# predicates
5669
isinteger{T,f}(x::FixedPoint{T,f}) = (x.i&(1<<f-1)) == 0
@@ -113,6 +126,17 @@ for T in tuple(Fixed16, UF...)
113126
end
114127
end
115128

129+
for f in (:div, :fld, :fld1)
130+
@eval begin
131+
$f{T<:FixedPoint}(x::T, y::T) = $f(reinterpret(x),reinterpret(y))
132+
end
133+
end
134+
for f in (:rem, :mod, :mod1, :rem1, :min, :max)
135+
@eval begin
136+
$f{T<:FixedPoint}(x::T, y::T) = T($f(reinterpret(x),reinterpret(y)),0)
137+
end
138+
end
139+
116140
# When multiplying by a float, reduce two multiplies to one.
117141
# Particularly useful for arrays.
118142
scaledual(Tdual::Type, x) = one(Tdual), x

src/ufixed.jl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ convert{Ti<:Integer}(::Type{Rational{Ti}}, x::UFixed) = convert(Ti, reinterpret(
8080
convert(::Type{Rational}, x::UFixed) = reinterpret(x)//rawone(x)
8181

8282
# Traits
83-
eps{T<:UFixed}(::Type{T}) = T(one(rawtype(T)),0)
84-
eps{T<:UFixed}(::T) = eps(T)
85-
sizeof{T<:UFixed}(::Type{T}) = sizeof(rawtype(T))
8683
abs(x::UFixed) = x
8784

8885
(-){T<:UFixed}(x::T) = T(-reinterpret(x), 0)
@@ -126,16 +123,6 @@ isinf(x::UFixed) = false
126123
bswap{f}(x::UFixed{UInt8,f}) = x
127124
bswap(x::UFixed) = typeof(x)(bswap(reinterpret(x)),0)
128125

129-
for f in (:div, :fld, :fld1)
130-
@eval begin
131-
$f{T<:UFixed}(x::T, y::T) = $f(reinterpret(x),reinterpret(y))
132-
end
133-
end
134-
for f in (:rem, :mod, :mod1, :rem1, :min, :max)
135-
@eval begin
136-
$f{T<:UFixed}(x::T, y::T) = T($f(reinterpret(x),reinterpret(y)),0)
137-
end
138-
end
139126
function minmax{T<:UFixed}(x::T, y::T)
140127
a, b = minmax(reinterpret(x), reinterpret(y))
141128
T(a,0), T(b,0)

test/fixed.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ end
7878
@test ( 65.2 % T).i == round(Int, 65.2*512) % Int16
7979
@test (-67.2 % T).i == round(Int, -67.2*512) % Int16
8080

81+
for T in [Fixed{Int8,7}, Fixed{Int16,8}, Fixed{Int16,10}]
82+
testapprox(T) # defined in ufixed.jl
83+
end
84+
8185
# reductions
8286
F8 = Fixed{Int8,8}
8387
a = F8[0.498, 0.1]

test/ufixed.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ for T in (FixedPointNumbers.UF..., UF2...)
172172
testtrunc(eps(T))
173173
end
174174

175+
function testapprox{T}(::Type{T})
176+
for x = typemin(T):eps(T):typemax(T)-eps(T)
177+
y = x+eps(T)
178+
@test x y
179+
@test y x
180+
@test !(x y+eps(T))
181+
end
182+
end
183+
for T in FixedPointNumbers.UF
184+
testapprox(T)
185+
end
186+
175187
@test !(UFixed8(0.5) < UFixed8(0.5))
176188
@test UFixed8(0.5) <= UFixed8(0.5)
177189

0 commit comments

Comments
 (0)