Skip to content

Commit b9d0ef1

Browse files
committed
small argument fix
1 parent 3b94ce4 commit b9d0ef1

File tree

1 file changed

+15
-27
lines changed

1 file changed

+15
-27
lines changed

src/besseli.jl

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ function besselix(nu, x::T) where T <: Union{Float32, Float64}
163163

164164
branch = 60
165165
if nu < branch
166-
inp1 = besseli_large_orders_scaled(branch + 1, x)
166+
inup1 = besseli_large_orders_scaled(branch + 1, x)
167167
inu = besseli_large_orders_scaled(branch, x)
168-
return down_recurrence(x, inu, inp1, nu, branch)
168+
return down_recurrence(x, inu, inup1, nu, branch)
169169
else
170170
return besseli_large_orders_scaled(nu, x)
171171
end
@@ -199,10 +199,10 @@ function _besseli_continued_fractions(nu, x::T) where T
199199
S = promote_type(T, Float64)
200200
xx = S(x)
201201
knu, knum1 = up_recurrence(xx, besselk0(xx), besselk1(xx), nu)
202+
# if knu or knum1 is zero then besseli will likely overflow
202203
(iszero(knu) || iszero(knum1)) && return throw(DomainError(x, "Overflow error"))
203204
return 1 / (x * (knum1 + knu / steed(nu, x)))
204205
end
205-
206206
function steed(n, x::T) where T
207207
MaxIter = 1000
208208
xinv = inv(x)
@@ -213,7 +213,7 @@ function steed(n, x::T) where T
213213
b = muladd(2, n, 2) * xinv
214214
for _ in 1:MaxIter
215215
d = inv(b + d)
216-
a = muladd(b, d, -1) * a
216+
a *= muladd(b, d, -1)
217217
h = h + a
218218
b = b + xinv2
219219
abs(a / h) <= eps(T) && break
@@ -240,37 +240,25 @@ function besseli_large_argument(v, z::T) where T
240240
return res * coef * a
241241
end
242242

243-
# power series definition of besseli
244-
# fast convergence for small arguments
245-
# for large orders and small arguments there is increased roundoff error ~ 1e-14
246-
# need to investigate further if this can be mitigated
247243
function besseli_small_arguments(v, z::T) where T
244+
S = promote_type(T, Float64)
245+
x = S(z)
248246
if v < 20
249-
coef = (z / 2)^v / factorial(v)
247+
coef = (x / 2)^v / factorial(v)
250248
else
251-
coef = v*log(z / 2)
252-
coef -= _loggam(v + 1)
253-
coef = exp(coef)
249+
vinv = inv(v)
250+
coef = sqrt(vinv / (2 * π)) * MathConstants.e^(v * (log(x / (2 * v)) + 1))
251+
coef *= evalpoly(vinv, (1, -1/12, 1/288, 139/51840, -571/2488320, -163879/209018880, 5246819/75246796800, 534703531/902961561600))
254252
end
255253

256254
MaxIter = 1000
257-
out = one(T)
258-
zz = z^2 / 4
259-
a = one(T)
260-
for k in 0:MaxIter
261-
a *= zz / (k + 1) / (k + v + 1)
255+
out = one(S)
256+
zz = x^2 / 4
257+
a = one(S)
258+
for k in 1:MaxIter
259+
a *= zz / (k * (k + v))
262260
out += a
263261
a <= eps(T) && break
264262
end
265263
return coef * out
266264
end
267-
@inline function _loggam(x)
268-
xinv = inv(x)
269-
xinv2 = xinv * xinv
270-
out = (x - 0.5) * log(x) - x + 9.1893853320467274178032927e-01
271-
out += xinv * evalpoly(
272-
xinv2, (8.3333333333333333333333368e-02, -2.7777777777777777777777776e-03,
273-
7.9365079365079365079365075e-04, -5.9523809523809523809523806e-04)
274-
)
275-
return out
276-
end

0 commit comments

Comments
 (0)