Skip to content

Commit 9c62620

Browse files
authored
Merge pull request #24 from heltonmc/large_arg_bessely
Output both bessely and besselj for large arguments
2 parents d685966 + 3b3c2e9 commit 9c62620

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

src/asymptotics.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
function besseljy_large_argument(v, x::T) where T
2+
# gives both (besselj, bessely) for x > 1.6*v
3+
α, αp = _α_αp_asymptotic(v, x)
4+
b = SQ2OPI(T) / sqrt(αp * x)
5+
6+
# we need to calculate sin(x - v*pi/2 - pi/4) and cos(x - v*pi/2 - pi/4)
7+
# For improved accuracy this is expanded using the formula for sin(x+y+z)
8+
9+
S, C = sincos(PIO2(T) * v)
10+
Sα, Cα = sincos(α)
11+
12+
CMS = C - S
13+
CPS = C + S
14+
15+
s1 = CMS *
16+
s2 = CPS *
17+
18+
s3 = CMS *
19+
s4 = CPS *
20+
21+
return SQ2O2(T) * (s1 + s2) * b, SQ2O2(T) * (s3 - s4) * b
22+
end
23+
124
function _α_αp_asymptotic(v, x::Float64)
225
if x > 5*v
326
return _α_αp_poly_10(v, x)

src/besselj.jl

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ function _besselj(nu, x)
163163
x < 4.0 && return besselj_small_arguments_orders(nu, x)
164164

165165
large_arg_cutoff = 1.65*nu
166-
(x > large_arg_cutoff && x > 20.0) && return besselj_large_argument(nu, x)
166+
(x > large_arg_cutoff && x > 20.0) && return besseljy_large_argument(nu, x)[1]
167167

168168

169169
debye_cutoff = 2.0 + 1.00035*x + Base.Math._approx_cbrt(302.681*Float64(x))
@@ -190,8 +190,8 @@ function _besselj(nu, x)
190190
if (debye_diff > large_arg_diff && x > 20.0)
191191
nu_shift = ceil(Int, large_arg_diff)
192192
v2 = nu - nu_shift
193-
jnu = besselj_large_argument(v2, x)
194-
jnum1 = besselj_large_argument(v2 - 1, x)
193+
jnu = besseljy_large_argument(v2, x)[1]
194+
jnum1 = besseljy_large_argument(v2 - 1, x)[1]
195195
return besselj_up_recurrence(x, jnu, jnum1, v2, nu)[2]
196196
else
197197
nu_shift = ceil(Int, debye_diff)
@@ -203,20 +203,6 @@ function _besselj(nu, x)
203203
end
204204
end
205205

206-
# for moderate size arguments of x and v this has relative errors ~9e-15
207-
# for large arguments relative errors ~1e-13
208-
function besselj_large_argument(v, x::T) where T
209-
α, αp = _α_αp_asymptotic(v, x)
210-
b = SQ2OPI(T) / sqrt(αp * x)
211-
212-
S, C = sincos(PIO2(T)*v)
213-
Sα, Cα = sincos(α)
214-
s1 = (C - S) *
215-
s2 = (C + S) *
216-
217-
return SQ2O2(T) * (s1 + s2) * b
218-
end
219-
220206
# generally can only use for x < 4.0
221207
# this needs a better way to sum these as it produces large errors
222208
# only valid in non-oscillatory regime (v>1/2, 0<t<sqrt(v^2 - 0.25))

test/bessely_test.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,7 @@ y1_32 = bessely1.(Float32.(x))
6464
# test that Inf inputs go to zero
6565
@test bessely1(Inf32) == zero(Float32)
6666
@test bessely1(Inf64) == zero(Float64)
67+
68+
69+
# briefly test the large argument is working
70+
@test Bessels.besseljy_large_argument(10.0, 100.0)[2] SpecialFunctions.bessely(10.0, 100.0)

0 commit comments

Comments
 (0)