Skip to content

Commit 596ec95

Browse files
committed
add ULPError.jl
1 parent 96b5f3d commit 596ec95

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

test/common/ULPError.jl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
module ULPError
2+
export ulp_error, ulp_error_maximum
3+
@noinline function throw_invalid()
4+
throw(ArgumentError("invalid"))
5+
end
6+
function ulp_error(accurate::AbstractFloat, approximate::AbstractFloat)
7+
if isnan(accurate)
8+
@noinline throw_invalid()
9+
end
10+
if isnan(approximate)
11+
@noinline throw_invalid()
12+
end
13+
# the ULP error is usually not required to great accuracy, so `Float32` should be precise enough
14+
zero_return = Float32(0)
15+
inf_return = Float32(Inf)
16+
if isinf(accurate) || iszero(accurate) # handle floating-point edge cases
17+
if isinf(accurate)
18+
if isinf(approximate) && (signbit(accurate) == signbit(approximate))
19+
return zero_return
20+
end
21+
return inf_return
22+
end
23+
# `iszero(accurate)`
24+
if iszero(approximate)
25+
return zero_return
26+
end
27+
return inf_return
28+
end
29+
# assuming `precision(BigFloat)` is great enough
30+
acc = if accurate isa BigFloat
31+
accurate
32+
else
33+
BigFloat(accurate)::BigFloat
34+
end
35+
err = abs(Float32((approximate - acc) / eps(approximate))::Float32)
36+
if isnan(err)
37+
@noinline throw_invalid() # unexpected
38+
end
39+
err
40+
end
41+
function ulp_error(accurate::Acc, approximate::App, x::AbstractFloat) where {Acc, App}
42+
acc = accurate(x)
43+
app = approximate(x)
44+
ulp_error(acc, app)
45+
end
46+
function ulp_error(func::Func, x::AbstractFloat) where {Func}
47+
ulp_error(func BigFloat, func, x)
48+
end
49+
function ulp_error_maximum(func::Func, iterator) where {Func}
50+
function f(x::AbstractFloat)
51+
ulp_error(func, x)
52+
end
53+
maximum(f, iterator)
54+
end
55+
end

test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ using OffsetArrays
1010
using Random
1111
using Test
1212

13+
include("common/ULPError.jl")
14+
using .ULPError
15+
1316
Random.seed!(1234)
1417

1518
include("basicfuns.jl")

0 commit comments

Comments
 (0)