|
93 | 93 | """
|
94 | 94 | isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y)))
|
95 | 95 |
|
96 |
| -For FixedPoint numbers, the default criterion is that `x` and `y` differ by no more than `eps`, the separation between adjacent fixed-point numbers. |
| 96 | +For FixedPoint numbers, the default criterion is that `x` and `y` differ by no |
| 97 | +more than `eps`, the separation between adjacent fixed-point numbers. |
97 | 98 | """
|
98 |
| -function isapprox(x::T, y::T; rtol=0, atol=max(eps(x), eps(y))) where {T <: FixedPoint} |
99 |
| - maxdiff = T(atol+rtol*max(abs(x), abs(y))) |
100 |
| - rx, ry, rd = reinterpret(x), reinterpret(y), reinterpret(maxdiff) |
101 |
| - abs(signed(widen1(rx))-signed(widen1(ry))) <= rd |
| 99 | +@inline function isapprox(x::X, y::X; rtol=0, atol=eps(X)) where {X <: FixedPoint} |
| 100 | + n, m = minmax(x, y) # m >= n |
| 101 | + if rtol == zero(rtol) |
| 102 | + _isapprox_atol(m, n, atol) |
| 103 | + elseif atol == zero(atol) |
| 104 | + _isapprox_rtol(m, n, rtol) |
| 105 | + else |
| 106 | + _isapprox_atol(m, n, atol) | _isapprox_rtol(m, n, rtol) |
| 107 | + end |
102 | 108 | end
|
103 | 109 | function isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y)))
|
104 | 110 | isapprox(promote(x, y)...; rtol=rtol, atol=atol)
|
105 | 111 | end
|
| 112 | +function _isapprox_atol(m::X, n::X, atol::X) where {X <: FixedPoint} |
| 113 | + unsigned(m.i - n.i) <= unsigned(max(atol, zero(X)).i) |
| 114 | +end |
| 115 | +function _isapprox_atol(m::X, n::X, atol) where {X <: FixedPoint} |
| 116 | + unsigned(m.i - n.i) <= div(atol, eps(X)) |
| 117 | +end |
| 118 | +function _isapprox_rtol(m::X, n::X, rtol) where {X <: FixedPoint} |
| 119 | + unsigned(m.i - n.i) <= rtol * max(unsigned(abs(m.i)), unsigned(abs(n.i))) |
| 120 | +end |
106 | 121 |
|
107 | 122 | # predicates
|
108 | 123 | isinteger(x::FixedPoint) = x == trunc(x) # TODO: use floor(x) when dropping support for Fixed{Int8,8}
|
|
0 commit comments