Skip to content

Commit 5c1b7a6

Browse files
committed
Special half-integer branch for besselk.
1 parent 0302204 commit 5c1b7a6

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

src/besselk.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ function besselk_positive_args(nu, x::T) where T <: Union{Float32, Float64}
226226
# dispatch to avoid uniform expansion when nu = 0
227227
iszero(nu) && return besselk0(x)
228228

229+
# check if nu is a half-integer:
230+
isinteger(nu-1/2) && return besselk_vhalfint(nu, x)
231+
229232
# use uniform debye expansion if x or nu is large
230233
besselik_debye_cutoff(nu, x) && return besselk_large_orders(nu, x)
231234

@@ -424,3 +427,23 @@ function besselk_power_series(v, x::T) where T
424427
end
425428
besselk_power_series_cutoff(nu, x::Float64) = x < 2.0 || nu > 1.6x - 1.0
426429
besselk_power_series_cutoff(nu, x::Float32) = x < 10.0f0 || nu > 1.65f0*x - 8.0f0
430+
431+
432+
"""
433+
besselk_vhalfint(nu, x::T) where T <: {Float32, Float64}
434+
435+
Computes `K_{ν}(x)` when `v + 1/2` is an integer using the fact that the
436+
asymptotic expansion actually terminates and is exact for those specific `v` values.
437+
"""
438+
function besselk_vhalfint(v, x::T) where T
439+
v = abs(v)
440+
invx = inv(x)
441+
b0 = b1 = SQRT_PID2(T)*sqrt(invx)*exp(-x)
442+
twodx = 2*invx
443+
_v = T(1/2)
444+
while _v < v
445+
b0, b1 = b1, muladd(b1, twodx*_v, b0)
446+
_v += one(T)
447+
end
448+
b1
449+
end

src/constants.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,6 @@ const Q3_k1(::Type{Float64}) = (
284284
2.88448064302447607e1, 2.27912927104139732e0,
285285
2.50358186953478678e-2
286286
)
287+
288+
const SQRT_PID2(::Type{Float64}) = 1.2533141373155003
289+
const SQRT_PID2(::Type{Float32}) = 1.2533141f0

test/besselk_test.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ k1x_32 = besselk1x.(Float32.(x))
6767
@test besselk(100, 3.9) SpecialFunctions.besselk(100, 3.9)
6868
@test besselk(100, 234.0) SpecialFunctions.besselk(100, 234.0)
6969

70+
# test half-integer orders:
71+
for v in (-3/2, -1/2, 1/2, 3/2, 5/2, 7/2, 9/2)
72+
@test besselk(v, 7.0) SpecialFunctions.besselk(v, 7.0)
73+
@test besselk(Float32(v), Float32(7.0)) SpecialFunctions.besselk(Float32(v), Float32(7.0))
74+
end
75+
7076
# test small arguments and order
7177
m = 0:40; x = [1e-6; 1e-4; 1e-3; 1e-2; 0.1; 1.0:2.0:500.0]
7278
for m in m, x in x

0 commit comments

Comments
 (0)