@@ -169,26 +169,19 @@ function En_cf_nogamma(ν::Number, z::Number, n::Int=1000)
169
169
scale = sqrt (floatmax (real (A)))
170
170
171
171
# two recurrence steps / loop
172
- iters = 0
172
+ iters = 1
173
173
for i = 2 : n
174
174
iters += 1
175
175
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
182
178
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
189
180
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
192
185
193
186
# rescale
194
187
if fastabs (A) > scale
@@ -221,18 +214,14 @@ function En_cf_gamma(ν::Number, z::Number, n::Int=1000)
221
214
ϵ = 10 * eps (real (B))
222
215
scale = sqrt (floatmax (real (A)))
223
216
224
- iters = 0
217
+ iters = 1
225
218
j = 1
226
219
for i = 2 : n
227
220
iters += 1
228
221
229
- A′ = A
230
222
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
236
225
237
226
conv = abs (Aprev* B - A* Bprev) < ϵ* abs (B* Bprev)
238
227
conv && break
@@ -458,21 +447,25 @@ function _expint(ν::Number, z::Number, niter::Int=1000, ::Val{expscaled}=Val{fa
458
447
# 16(2), 169–177. https://doi.org/10.1145/78928.78933
459
448
doconj = imag (z) < 0
460
449
rez, imz = real (z), abs (imag (z))
450
+ zorig = z
461
451
z = doconj ? conj (z) : z
462
452
ν = doconj ? conj (ν) : ν
463
453
464
- quick_niter, nmax = 50 , 45
454
+ quick_niter = niter >> 4
465
455
# start with small imaginary part if exactly on negative real axis
466
456
imstart = (imz == 0 ) ? abs (z)* sqrt (eps (typeof (real (z)))) : imz
467
457
z₀ = rez + imstart* im
468
458
g_start, cf_start, i, _ = En_cf (ν, z₀, quick_niter)
469
459
E_start = g_start + En_safeexpmult (- z₀, cf_start)
470
460
isnan (E_start) && return E_start
471
- if imz > 0 && i < nmax
461
+ if imz > 0 && i < quick_niter
472
462
# didn't need to take any steps
463
+ if expscaled
464
+ E_start = En_safeexpmult (z₀, g_start) + cf_start
465
+ end
473
466
return doconj ? conj (E_start) : E_start
474
467
end
475
- while i > nmax
468
+ while i == quick_niter
476
469
# double imaginary part until in region with fast convergence
477
470
imstart *= 2
478
471
z₀ = rez + imstart* im
@@ -504,7 +497,7 @@ function _expint(ν::Number, z::Number, niter::Int=1000, ::Val{expscaled}=Val{fa
504
497
En = bit ? En : En + bc
505
498
end
506
499
end
507
- return expscaled ? exp (z) * En : En
500
+ return expscaled ? En_safeexpmult (zorig, En) : En
508
501
end
509
502
end
510
503
0 commit comments