Skip to content

Commit e6f0ac3

Browse files
authored
Merge pull request #48 from cgeoga/master
Asymptotic expansion for large arg and small-ish order
2 parents 8eb7c77 + f5728a8 commit e6f0ac3

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/besselk.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ function besselk_positive_args(nu, x::T) where T <: Union{Float32, Float64}
232232
# check if nu is a half-integer:
233233
(isinteger(nu-1/2) && !debye_cut) && return sphericalbesselk(nu-1/2, x)*SQRT_PID2(T)*sqrt(x)
234234

235+
# check if the standard asymptotic expansion can be used:
236+
besselk_asexp_cutoff(nu, x) && return besselk_large_argument(nu, x)
237+
235238
# use uniform debye expansion if x or nu is large
236239
debye_cut && return besselk_large_orders(nu, x)
237240

@@ -431,3 +434,36 @@ end
431434
besselk_power_series_cutoff(nu, x::Float64) = x < 2.0 || nu > 1.6x - 1.0
432435
besselk_power_series_cutoff(nu, x::Float32) = x < 10.0f0 || nu > 1.65f0*x - 8.0f0
433436

437+
438+
"""
439+
besselk_asymptoticexp(v, x, order)
440+
441+
Computes the asymptotic expansion of K_ν w.r.t. argument. Accurate for large x, and faster than uniform asymptotic expansion for small to small-ish orders. The default order of the expansion in `Bessels.besselk` is 10.
442+
"""
443+
besselk_asexp_cutoff(nu, x::T) where T = (nu < 20.0) && (x > ASEXP_CUTOFF(T))
444+
445+
function besselk_large_argument(v, x::T) where T
446+
a = exp(-x / 2)
447+
coef = a * sqrt(pi / 2x)
448+
return T(_besselk_large_argument(v, x) * coef * a)
449+
end
450+
451+
besselk_large_argument_scaled(v, x::T) where T = T(_besselk_large_argument(v, x) * sqrt(pi / 2x))
452+
453+
function _besselk_large_argument(v, x::T) where T
454+
MaxIter = 5000
455+
S = promote_type(T, Float64)
456+
v, x = S(v), S(x)
457+
458+
fv2 = 4 * v^2
459+
term = one(S)
460+
res = term
461+
s = term
462+
for i in 1:MaxIter
463+
offset = muladd(2, i, -1)
464+
term *= muladd(offset, -offset, fv2) / (8 * x * i)
465+
res = muladd(term, s, res)
466+
abs(term) <= eps(T) && break
467+
end
468+
return res
469+
end

src/constants.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,6 @@ const Q3_k1(::Type{Float64}) = (
287287

288288
const SQRT_PID2(::Type{Float64}) = 1.2533141373155003
289289
const SQRT_PID2(::Type{Float32}) = 1.2533141f0
290+
291+
const ASEXP_CUTOFF(::Type{Float64}) = 35.0
292+
const ASEXP_CUTOFF(::Type{Float32}) = 35.0f0 # temporary

0 commit comments

Comments
 (0)