Skip to content

Commit 135473e

Browse files
committed
support underflow Jnu, Inu
1 parent 1a77816 commit 135473e

File tree

4 files changed

+57
-7
lines changed

4 files changed

+57
-7
lines changed

src/besseli.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,34 @@ function _besseli(nu::AbstractRange, x::T) where T
213213
return besselk_down_recurrence!(out, x, nu)
214214
end
215215

216+
function _besseli(nu::AbstractRange, x::T) where T
217+
(nu[1] >= 0 && step(nu) == 1) || throw(ArgumentError("nu must be >= 0 with step(nu)=1"))
218+
len = length(nu)
219+
isone(len) && return [besseli(nu[1], x)]
220+
out = zeros(T, len)
221+
k = len
222+
inu = zero(T)
223+
while abs(inu) < floatmin(T)
224+
if besseli_underflow_check(nu[k], x)
225+
inu = zero(T)
226+
else
227+
inu = _besseli(nu[k], x)
228+
end
229+
out[k] = inu
230+
k -= 1
231+
k < 1 && break
232+
end
233+
if k > 1
234+
out[k] = _besseli(nu[k], x)
235+
out[1:k+1] = besselk_down_recurrence!(out[1:k+1], x, nu[1:k+1])
236+
return out
237+
else
238+
return out
239+
end
240+
end
241+
242+
besseli_underflow_check(nu, x::T) where T = nu > 140 + T(1.45)*x + 53*Base.Math._approx_cbrt(x)
243+
216244
"""
217245
besseli_positive_args(nu, x::T) where T <: Union{Float32, Float64}
218246

src/besselj.jl

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,38 @@ end
257257

258258
function _besselj(nu::AbstractRange, x::T) where T
259259
(nu[1] >= 0 && step(nu) == 1) || throw(ArgumentError("nu must be >= 0 with step(nu)=1"))
260-
out = Vector{T}(undef, length(nu))
260+
len = length(nu)
261+
isone(len) && return [besselj(nu[1], x)]
262+
263+
out = zeros(T, len)
261264
if nu[end] < x
262265
out[1], out[2] = _besselj(nu[1], x), _besselj(nu[2], x)
263266
return besselj_up_recurrence!(out, x, nu)
264267
else
265-
out[end-1], out[end] = _besselj(nu[end-1], x), _besselj(nu[end], x)
266-
return besselj_down_recurrence!(out, x, nu)
268+
k = len
269+
jn = zero(T)
270+
while abs(jn) < floatmin(T)
271+
if besselj_underflow_check(nu[k], x)
272+
jn = zero(T)
273+
else
274+
jn = _besselj(nu[k], x)
275+
end
276+
out[k] = jn
277+
k -= 1
278+
k < 1 && break
279+
end
280+
if k > 1
281+
out[k] = _besselj(nu[k], x)
282+
out[1:k+1] = besselj_down_recurrence!(out[1:k+1], x, nu[1:k+1])
283+
return out
284+
else
285+
return out
286+
end
267287
end
268288
end
269289

290+
besselj_underflow_check(nu, x::T) where T = nu > 100 + T(1.01)*x + 85*Base.Math._approx_cbrt(x)
291+
270292
"""
271293
besselj_positive_args(nu, x::T) where T <: Float64
272294

test/besseli_test.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ for v in nu, xx in x
107107
end
108108

109109
# test nu_range
110-
@test besseli(0:50, 2.0) SpecialFunctions.besseli.(0:50, 2.0) rtol=1e-13
110+
@test besseli(0:250, 2.0) SpecialFunctions.besseli.(0:250, 2.0) rtol=1e-13
111111
@test besseli(0.5:1:10.5, 2.0) SpecialFunctions.besseli.(0.5:1:10.5, 2.0) rtol=1e-13
112112

113113
### need to fix method ambiguities for other functions ######

test/besselj_test.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,9 @@ for v in nu, xx in x
115115
end
116116

117117
# test nu_range
118-
@test besselj(0:50, 2.0) SpecialFunctions.besselj.(0:50, 2.0) rtol=1e-11
119-
@test besselj(0:50, 100.0) SpecialFunctions.besselj.(0:50, 100.0) rtol=1e-11
120-
@test besselj(0.5:1:10.5, 2.0) SpecialFunctions.besselj.(0.5:1:10.5, 2.0) rtol=1e-11
118+
@test besselj(0:250, 2.0) SpecialFunctions.besselj.(0:250, 2.0) rtol=1e-11
119+
@test besselj(0:95, 100.0) SpecialFunctions.besselj.(0:95, 100.0) rtol=1e-11
120+
@test besselj(0.5:1:150.5, 2.0) SpecialFunctions.besselj.(0.5:1:150.5, 2.0) rtol=1e-11
121121
@test besselj(0.5:1:10.5, 40.0) SpecialFunctions.besselj.(0.5:1:10.5, 40.0) rtol=1e-11
122122

123123
# test Float16 and Float32

0 commit comments

Comments
 (0)