Skip to content

Commit

Permalink
Update erf.jl
Browse files Browse the repository at this point in the history
Followup to #372. This manages to remove a one of the branches by pushing the domain split further, and makes `erfcinv` use the better version I found for erfinv in the original PR.
  • Loading branch information
oscardssmith authored May 7, 2024
1 parent c400278 commit b3581b6
Showing 1 changed file with 17 additions and 28 deletions.
45 changes: 17 additions & 28 deletions src/erf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -366,29 +366,16 @@ function _erfinv(x::Float16)
# Perform calculations with `Float32`
x32 = Float32(x)
a32 = Float32(a)
if a32 <= 0.75f0
# Simpler and more accurate alternative to Table 7 in Blair et al.
# Ref: https://github.com/JuliaMath/SpecialFunctions.jl/pull/372#discussion_r1592832735
t = muladd(-6.73815f1, x32, 1f0) / muladd(-4.18798f0, x32, 4.54263f0)
y = copysign(muladd(0.88622695f0, x32, t), x32)
elseif a32 <= 0.9375f0 # Table 26 in Blair et al.
t = x32^2 - 0.87890625f0
y = x32 * @horner(t, 0.10178_950f1,
-0.32827_601f1) /
@horner(t, 0.72455_99f0,
-0.33871_553f1,
0.1f1)
if a32 <= 0.895f0
t = muladd(-0.664556f0, x32, 1f0) / muladd(-4.14539f0, x32, 4.53331f0)
y = muladd(0.88622695f0, x32, t)
else
# Simpler alternative to Table 47 in Blair et al.
# because of the reduced accuracy requirement
# (it turns out that this branch only covers 128 values).
# Note that the use of log(1-x) rather than log1p is intentional since it will be
# slightly faster and 1-x is exact.
# Ref: https://github.com/JuliaMath/SpecialFunctions.jl/pull/372#discussion_r1592710586
t = sqrt(-log(1-a32))
y = copysign(@horner(t, -0.429159f0, 1.04868f0), x32)
# Note that the use of log(1-x) rather than log1p is intentional since
# it will be slightly faster and 1-x is exact.
t = @fastmath sqrt(-log(1-a32))
y = 1f0 + (t - 1.35934f0) / muladd(-0.12807f0, x32, 1.08437f0)

Check warning on line 376 in src/erf.jl

View check run for this annotation

Codecov / codecov/patch

src/erf.jl#L375-L376

Added lines #L375 - L376 were not covered by tests
end
return Float16(y)
return Float16(copysign(y, x32))
end
end

Expand Down Expand Up @@ -520,13 +507,15 @@ function _erfcinv(y::Float16)
return Inf16
end
throw(DomainError(y, "`y` must be nonnegative."))
else # Table 47 in Blair et al.
t = 1.0f0 / sqrt(-log(Float32(y)))
x = @horner(t, 0.98650_088f0,
0.92601_777f0) /
(t * @horner(t, 0.98424_719f0,
0.10074_7432f0,
0.1f0))
else
# Simpler alternative to Table 47 in Blair et al.
# because of the reduced accuracy requirement
# (it turns out that this branch only covers 128 values).
# Note that the use of log(1-x) rather than log1p is intentional since it will be
# slightly faster and 1-x is exact.
# Ref: https://github.com/JuliaMath/SpecialFunctions.jl/pull/372#discussion_r1592710586
t = @fastmath sqrt(-log(Float32(y)))
x = @horner(t, -0.429159f0, 1.04868f0)

Check warning on line 518 in src/erf.jl

View check run for this annotation

Codecov / codecov/patch

src/erf.jl#L517-L518

Added lines #L517 - L518 were not covered by tests
return Float16(x)
end
end
Expand Down

0 comments on commit b3581b6

Please sign in to comment.