Skip to content

Commit e91a47d

Browse files
authored
fix expint for negative order (#260)
1 parent f99d068 commit e91a47d

File tree

2 files changed

+27
-12
lines changed

2 files changed

+27
-12
lines changed

src/expint.jl

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,9 @@ end
286286

287287
# series about origin, general ν
288288
# https://functions.wolfram.com/GammaBetaErf/ExpIntegralE/06/01/04/01/01/0003/
289-
function En_expand_origin::Number, z::Number)
290-
if isinteger(ν)
291-
# go to special case for integer ν
292-
return En_expand_origin(Int(ν), z)
293-
end
289+
function En_expand_origin_general::Number, z::Number)
294290
gammaterm = En_safe_gamma_term(ν, z)
295-
frac = 1
291+
frac = one(real(z))
296292
sumterm = frac / (1 - ν)
297293
k, maxiter = 1, 100
298294
ϵ = 10*eps(real(sumterm))
@@ -305,21 +301,20 @@ function En_expand_origin(ν::Number, z::Number)
305301
end
306302
k += 1
307303
end
308-
309304
return gammaterm - sumterm
310305
end
311306

312-
# series about the origin, special case for integer n
307+
# series about the origin, special case for integer n > 0
313308
# https://functions.wolfram.com/GammaBetaErf/ExpIntegralE/06/01/04/01/02/0005/
314-
function En_expand_origin(n::Integer, z::Number)
309+
function En_expand_origin_posint(n::Integer, z::Number)
315310
gammaterm = 1 # (-z)^(n-1) / (n-1)!
316311
for i = 1:n-1
317312
gammaterm *= -z / i
318313
end
319314

320-
gammaterm *= digamma(n) - log(z)
321-
sumterm = float(n == 1 ? 0 : 1 / (1 - n))
322-
frac = 1
315+
frac = one(real(z))
316+
gammaterm *= digamma(oftype(frac,n)) - log(z)
317+
sumterm = n == 1 ? zero(frac) : frac / (1 - n)
323318
k, maxiter = 1, 100
324319
ϵ = 10*eps(real(sumterm))
325320
while k < maxiter
@@ -337,6 +332,14 @@ function En_expand_origin(n::Integer, z::Number)
337332
return gammaterm - sumterm
338333
end
339334

335+
function En_expand_origin::Number, z::Number)
336+
if isinteger(ν) && real(ν) > 0
337+
return En_expand_origin_posint(Integer(ν), z)
338+
else
339+
return En_expand_origin_general(ν, z)
340+
end
341+
end
342+
340343
# can find imaginary part of E_ν(x) for x on negative real axis analytically
341344
# https://functions.wolfram.com/GammaBetaErf/ExpIntegralE/04/05/01/0003/
342345
function En_imagbranchcut::Number, z::Number)

test/expint.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ using Base.MathConstants
9898
abs(ν) 50 ? (@test expint(ν, z) E) : (@test_throws ArgumentError expint(ν, z) E)
9999
end
100100
end
101+
102+
# issue #259: positive vs. negative integer order for small/larger args
103+
@test expint(-4, 0.7) 142.685471227614252544 rtol=1e-14
104+
@test expint(+4, 0.7) 0.1267808300929215658 rtol=1e-14
105+
@test expint(-4, 5.7) 0.0013051784816041558 rtol=1e-14
106+
@test expint(+4, 5.7) 0.0003585161998373381 rtol=1e-13
107+
setprecision(BigFloat, 256) do
108+
@test expint(-4, big"0.7") big"142.68547122761425254403329916322251663998829971602071820534499366398779205282" rtol=1e-76
109+
@test expint(+4, big"0.7") big"0.12678083009292156580635697928870772316601035828975150623334903100558297079388567" rtol=1e-76
110+
@test expint(-4, big"5.7") big"0.0013051784816041557674219259305064008704427556690521012788554962045721241678128274" rtol=1e-76
111+
@test expint(+4, big"5.7") big"0.00035851619983733810063957822090566023258844652925986297947736355731994111784745604432" rtol=1e-74
112+
end
101113
end
102114

103115
expinti_real(x) = invoke(expinti, Tuple{Real}, x)

0 commit comments

Comments
 (0)