Skip to content

Commit dc35516

Browse files
oscardssmithantoine-levitt
authored andcommitted
minor speedup and accuracy improvement for atanh (JuliaLang#39267)
When `x` is not small, the numeric stability given by `log1p` and the rest of the complicated stuff actually just increases error and reduces speed. Also the small x and infinity case are just extra branches that already fall out of the remaining branches. The `<.5` branch is still both slower and has a higher max error (1.4 ULP vs .8 for the other branch), so if anyone can think of anything to improve it, I'm all ears. This PR is only a 20% speed improvement, but it's also a simplification so I think it's worthwhile.
1 parent 2d0bc79 commit dc35516

File tree

1 file changed

+9
-21
lines changed

1 file changed

+9
-21
lines changed

base/special/hyperbolic.jl

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,10 @@ function atanh(x::T) where T <: Union{Float32, Float64}
243243
# Method
244244
# 1.Reduced x to positive by atanh(-x) = -atanh(x)
245245
# 2. Find the branch and the expression to calculate and return it
246-
# a) 0 <= x < 2^-28
247-
# return x
248-
# b) 2^-28 <= x < 0.5
249-
# return 0.5*log1p(2x+2x*x/(1-x))
250-
# c) 0.5 <= x < 1
251-
# return 0.5*log1p(2x/1-x)
252-
# d) x = 1
253-
# return Inf
246+
# a) 0 <= x < 0.5
247+
# return 0.5*log1p(2x/(1-x))
248+
# b) 0.5 <= x <= 1
249+
# return 0.5*log((x+1)/(1-x))
254250
# Special cases:
255251
# if |x| > 1 throw DomainError
256252
isnan(x) && return x
@@ -260,20 +256,12 @@ function atanh(x::T) where T <: Union{Float32, Float64}
260256
if absx > 1
261257
atanh_domain_error(x)
262258
end
263-
if absx < T(2)^-28
264-
# in a)
265-
return x
266-
end
267259
if absx < T(0.5)
260+
# in a)
261+
t = log1p(T(2)*absx/(T(1)-absx))
262+
else
268263
# in b)
269-
t = absx+absx
270-
t = T(0.5)*log1p(t+t*absx/(T(1)-absx))
271-
elseif absx < T(1)
272-
# in c)
273-
t = T(0.5)*log1p((absx + absx)/(T(1)-absx))
274-
elseif absx == T(1)
275-
# in d)
276-
return copysign(T(Inf), x)
264+
t = log((T(1)+absx)/(T(1)-absx))
277265
end
278-
return copysign(t, x)
266+
return T(0.5)*copysign(t, x)
279267
end

0 commit comments

Comments
 (0)