@@ -169,26 +169,19 @@ function En_cf_nogamma(ν::Number, z::Number, n::Int=1000)
169169 scale = sqrt (floatmax (real (A)))
170170
171171 # two recurrence steps / loop
172- iters = 0
172+ iters = 1
173173 for i = 2 : n
174174 iters += 1
175175
176- A′ = A
177- A = z* A + (i- 1 ) * Aprev
178- Aprev = A′
179- B′ = B
180- B = z* B + (i- 1 ) * Bprev
181- Bprev = B′
176+ A, Aprev = z* A + (i- 1 ) * Aprev, A
177+ B, Bprev = z* B + (i- 1 ) * Bprev, B
182178
183- A′ = A
184- A = A + (ν+ i- 1 ) * Aprev
185- Aprev = A′
186- B′ = B
187- B = B + (ν+ i- 1 ) * Bprev
188- Bprev = B′
179+ (isinf (A) | isinf (B)) && return Aprev/ Bprev, iters- 1
189180
190- conv = abs (Aprev* B - A* Bprev) < ϵ* abs (B* Bprev)
191- conv && i > 4 && break
181+ A, Aprev = A + (ν+ i- 1 ) * Aprev, A
182+ B, Bprev = B + (ν+ i- 1 ) * Bprev, B
183+
184+ i > 4 && abs (Aprev* B - A* Bprev) < ϵ* abs (B* Bprev) && break
192185
193186 # rescale
194187 if fastabs (A) > scale
@@ -221,18 +214,14 @@ function En_cf_gamma(ν::Number, z::Number, n::Int=1000)
221214 ϵ = 10 * eps (real (B))
222215 scale = sqrt (floatmax (real (A)))
223216
224- iters = 0
217+ iters = 1
225218 j = 1
226219 for i = 2 : n
227220 iters += 1
228221
229- A′ = A
230222 term = iseven (i) ? - (i÷ 2 - 1 - ν)* z : z* (i÷ 2 )
231- A = (i - ν)* A + term * Aprev
232- Aprev = A′
233- B′ = B
234- B = (i - ν)* B + term * Bprev
235- Bprev = B′
223+ A, Aprev = (i - ν)* A + term * Aprev, A
224+ B, Bprev = (i - ν)* B + term * Bprev, B
236225
237226 conv = abs (Aprev* B - A* Bprev) < ϵ* abs (B* Bprev)
238227 conv && break
@@ -458,21 +447,25 @@ function _expint(ν::Number, z::Number, niter::Int=1000, ::Val{expscaled}=Val{fa
458447 # 16(2), 169–177. https://doi.org/10.1145/78928.78933
459448 doconj = imag (z) < 0
460449 rez, imz = real (z), abs (imag (z))
450+ zorig = z
461451 z = doconj ? conj (z) : z
462452 ν = doconj ? conj (ν) : ν
463453
464- quick_niter, nmax = 50 , 45
454+ quick_niter = niter >> 4
465455 # start with small imaginary part if exactly on negative real axis
466456 imstart = (imz == 0 ) ? abs (z)* sqrt (eps (typeof (real (z)))) : imz
467457 z₀ = rez + imstart* im
468458 g_start, cf_start, i, _ = En_cf (ν, z₀, quick_niter)
469459 E_start = g_start + En_safeexpmult (- z₀, cf_start)
470460 isnan (E_start) && return E_start
471- if imz > 0 && i < nmax
461+ if imz > 0 && i < quick_niter
472462 # didn't need to take any steps
463+ if expscaled
464+ E_start = En_safeexpmult (z₀, g_start) + cf_start
465+ end
473466 return doconj ? conj (E_start) : E_start
474467 end
475- while i > nmax
468+ while i == quick_niter
476469 # double imaginary part until in region with fast convergence
477470 imstart *= 2
478471 z₀ = rez + imstart* im
@@ -504,7 +497,7 @@ function _expint(ν::Number, z::Number, niter::Int=1000, ::Val{expscaled}=Val{fa
504497 En = bit ? En : En + bc
505498 end
506499 end
507- return expscaled ? exp (z) * En : En
500+ return expscaled ? En_safeexpmult (zorig, En) : En
508501 end
509502end
510503
0 commit comments