@@ -4,7 +4,7 @@ module FixedPointNumbers
44
55using 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
5669isinteger {T,f} (x:: FixedPoint{T,f} ) = (x. i& (1 << f- 1 )) == 0
@@ -113,6 +126,17 @@ for T in tuple(Fixed16, UF...)
113126 end
114127end
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.
118142scaledual (Tdual:: Type , x) = one (Tdual), x
0 commit comments