|
1 | 1 | module ULPError |
2 | 2 | export ulp_error, ulp_error_maximum |
3 | | - @noinline function throw_invalid() |
4 | | - throw(ArgumentError("invalid")) |
5 | | - end |
6 | 3 | function ulp_error(accurate::AbstractFloat, approximate::AbstractFloat) |
7 | 4 | # the ULP error is usually not required to great accuracy, so `Float32` should be precise enough |
8 | | - zero_return = Float32(0) |
9 | | - inf_return = Float32(Inf) |
10 | | - let accur_is_nan = isnan(accurate), approx_is_nan = isnan(approximate) |
| 5 | + zero_return = 0f0 |
| 6 | + inf_return = Inf32 |
| 7 | + # handle floating-point edge cases |
| 8 | + if !(isfinite(accurate) && isfinite(approximate)) |
| 9 | + accur_is_nan = isnan(accurate) |
| 10 | + approx_is_nan = isnan(approximate) |
11 | 11 | if accur_is_nan || approx_is_nan |
12 | | - if accur_is_nan === approx_is_nan |
13 | | - return zero_return |
| 12 | + return if accur_is_nan === approx_is_nan |
| 13 | + zero_return |
| 14 | + else |
| 15 | + inf_return |
14 | 16 | end |
15 | | - return inf_return |
16 | 17 | end |
17 | | - end |
18 | | - if isinf(accurate) || iszero(accurate) # handle floating-point edge cases |
19 | | - if isinf(accurate) |
20 | | - if isinf(approximate) && (signbit(accurate) == signbit(approximate)) |
21 | | - return zero_return |
| 18 | + if isinf(approximate) |
| 19 | + return if isinf(accurate) && (signbit(accurate) == signbit(approximate)) |
| 20 | + zero_return |
| 21 | + else |
| 22 | + inf_return |
22 | 23 | end |
23 | | - return inf_return |
24 | 24 | end |
25 | | - # `iszero(accurate)` |
26 | | - if iszero(approximate) |
27 | | - return zero_return |
28 | | - end |
29 | | - return inf_return |
30 | 25 | end |
31 | 26 | # assuming `precision(BigFloat)` is great enough |
32 | 27 | acc = if accurate isa BigFloat |
33 | 28 | accurate |
34 | 29 | else |
35 | 30 | BigFloat(accurate)::BigFloat |
36 | 31 | end |
37 | | - err = abs(Float32((approximate - acc) / eps(approximate))::Float32) |
38 | | - if isnan(err) |
39 | | - @noinline throw_invalid() # unexpected |
40 | | - end |
41 | | - err |
| 32 | + abs(Float32((approximate - acc) / eps(approximate))::Float32) |
42 | 33 | end |
43 | 34 | function ulp_error(accurate::Acc, approximate::App, x::AbstractFloat) where {Acc, App} |
44 | 35 | acc = accurate(x) |
|
0 commit comments