|
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