Skip to content

Commit dde82c2

Browse files
authored
expint: fixes for #263 (#268)
* Fix branch cut * use logabsgamma * Remove local var * complex nu branch cut test
1 parent 9116108 commit dde82c2

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

src/expint.jl

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,10 @@ end
344344
# https://functions.wolfram.com/GammaBetaErf/ExpIntegralE/04/05/01/0003/
345345
function En_imagbranchcut::Number, z::Number)
346346
a = real(z)
347-
e1 = exp(π*imag(ν))
347+
e1 = exp(oftype(a, π) * imag(ν))
348348
e2 = Complex(cospi(real(ν)), -sinpi(real(ν)))
349-
impart = π * im * e1 * e2 * exp((ν-1)*log(complex(a)) - loggamma(ν))
350-
impart *= signbit(imag(z)) ? -1 : 1
351-
return imag(impart) * im # get rid of any real error
349+
lgamma, lgammasign = ν isa Real ? logabsgamma(ν) : (loggamma(ν), 1)
350+
return -2 * lgammasign * e1 * π * e2 * exp((ν-1)*log(complex(a)) - lgamma) * im
352351
end
353352

354353
"""
@@ -375,7 +374,8 @@ function expint(ν::Number, z::Number, niter::Int=1000)
375374
end
376375

377376
if z == 0
378-
return oftype(z, real(ν) > 0 ? 1/-1) : Inf)
377+
typ = typeof(real(z))
378+
return oftype(z, real(ν) > 0 ? one(typ)/-1) : convert(typ, Inf))
379379
end
380380

381381
if ν == 0
@@ -394,8 +394,8 @@ function expint(ν::Number, z::Number, niter::Int=1000)
394394
return En_expand_origin(ν, z)
395395
end
396396

397-
if z isa Real
398-
return first(z > 0 ? En_cf(ν, z, niter) : En_cf_nogamma(ν, z, niter))
397+
if z isa Real || real(z) > 0
398+
return first(real(z) > 0 ? En_cf(ν, z, niter) : En_cf_nogamma(ν, z, niter))
399399
else
400400
# Procedure for z near the negative real axis based on
401401
# (without looking at the accompanying source code):
@@ -434,12 +434,22 @@ function expint(ν::Number, z::Number, niter::Int=1000)
434434
z₀ += Δ
435435
end
436436

437-
# more exact imaginary part available for non-integer ν
437+
En = doconj ? conj(E_start) : E_start
438+
439+
# handle branch cut
438440
if imz == 0
439-
E_start = real(E_start) + En_imagbranchcut(ν, z)
441+
bc = En_imagbranchcut(ν, z)
442+
bit = !signbit(imag(z))
443+
sign = bit ? 1 : -1
444+
if isreal(ν)
445+
# can separate real/im in case of real ν
446+
return real(En) - sign * imag(bc)/2 * im
447+
else
448+
return bit ? En : En + bc
449+
end
450+
else
451+
return En
440452
end
441-
442-
return doconj ? conj(E_start) : E_start
443453
end
444454
throw("unreachable")
445455
end

test/expint.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ using Base.MathConstants
7676
@test expint(-2, -3.3) -4.745485121488663825992363318400378114254141655964565963
7777
@test expint(-2, -3.3) isa Real
7878

79+
@test expint(-2.1+3im, 4.2 +0im) 0.003387565626497080536855067510744646235748203589175196673362104 - 0.003355838600814825542988272289126728631565803782052141768321840im
80+
@test expint(-4.3, -10+0.0im) -1505.2167858114105916067190408869152177781925766866637213104 + 0.00015439438628349460776476190593323691084185406009267711345841im
81+
@test expint(-4.3, -10-0.0im) -1505.2167858114105916067190408869152177781925766866637213104 - 0.00015439438628349460776476190593323691084185406009267711345841im
82+
@test expint(-4.3+2im, -10+0.0im) -1473.52621376586428327992147406861600035297263354271049988247182 - 210.712752794950368400059514411922967744944073260391136148642008im
83+
@test expint(-4.3+2im, -10-0.0im) -1473.47816311715810169554659685200228583538709701122499753349598 - 210.761182017526309473296237005277228612276963738826032570499367im
84+
7985
@test isnan(expint(NaN))
8086
@test isnan(expint(NaN+NaN*im))
8187
@test isnan(expint(NaN, 1.0))

0 commit comments

Comments
 (0)