Skip to content

Commit bcd5662

Browse files
authored
BigFloat erfcx (#77)
Fixes #75
1 parent 8574f13 commit bcd5662

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/erf.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,31 @@ function erfcinv(y::Float32)
281281
end
282282

283283
erfcinv(x::Integer) = erfcinv(float(x))
284+
285+
# MPFR has an open TODO item for this function
286+
# until then, we use [DLMF 7.12.1](https://dlmf.nist.gov/7.12.1) for the tail
287+
function erfcx(x::BigFloat)
288+
if x <= (Clong == Int32 ? 0x1p15 : 0x1p30)
289+
# any larger gives internal overflow
290+
return exp(x^2)*erfc(x)
291+
elseif !isfinite(x)
292+
return 1/x
293+
else
294+
# asymptotic series
295+
# starts to diverge at iteration i = 2^30 or 2^60
296+
# final term will be < Γ(2*i+1)/(2^i * Γ(i+1)) / (2^(i+1))
297+
# so good to (lgamma(2*i+1) - lgamma(i+1))/log(2) - 2*i - 1
298+
# ≈ 3.07e10 or 6.75e19 bits
299+
# which is larger than the memory of the respective machines
300+
ϵ = eps(BigFloat)/4
301+
v = 1/(2*x*x)
302+
k = 1
303+
s = w = -k*v
304+
while abs(w) > ϵ
305+
k += 2
306+
w *= -k*v
307+
s += w
308+
end
309+
return (1+s)/(x*sqrt(oftype(x,pi)))
310+
end
311+
end

test/runtests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ relerrc(z, x) = max(relerr(real(z),real(x)), relerr(imag(z),imag(x)))
6161

6262
@test SF.erfinv(one(Int)) == SF.erfinv(1.0)
6363
@test SF.erfcinv(one(Int)) == SF.erfcinv(1.0)
64+
65+
@test SF.erfcx(1.8) SF.erfcx(big(1.8)) rtol=4*eps()
66+
@test SF.erfcx(1.8e8) SF.erfcx(big(1.8e8)) rtol=4*eps()
67+
@test SF.erfcx(1.8e88) SF.erfcx(big(1.8e88)) rtol=4*eps()
6468
end
6569

6670
@testset "sine and cosine integrals" begin

0 commit comments

Comments
 (0)