Skip to content

Commit f1ff167

Browse files
committed
add array support
1 parent 372120a commit f1ff167

File tree

10 files changed

+106
-14
lines changed

10 files changed

+106
-14
lines changed

src/besseli.jl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ end
164164
165165
Modified Bessel function of the second kind of order nu, ``I_{nu}(x)``.
166166
"""
167-
besseli(nu::Real, x::Real) = _besseli(nu, float(x))
167+
besseli(nu, x::Real) = _besseli(nu, float(x))
168168

169169
_besseli(nu, x::Float16) = Float16(_besseli(nu, Float32(x)))
170170

171-
function _besseli(nu, x::T) where T <: Union{Float32, Float64}
171+
function _besseli(nu::T, x::T) where T <: Union{Float32, Float64}
172172
isinteger(nu) && return _besseli(Int(nu), x)
173173
~isfinite(x) && return x
174174
abs_nu = abs(nu)
@@ -205,6 +205,13 @@ function _besseli(nu::Integer, x::T) where T <: Union{Float32, Float64}
205205
end
206206
end
207207

208+
function _besseli(nu::AbstractRange, x::T) where T
209+
(nu[1] >= 0 && step(nu) == 1) || throw(ArgumentError("nu must be >= 0 with step(nu)=1"))
210+
out = Vector{T}(undef, length(nu))
211+
out[end-1], out[end] = _besseli(nu[end-1], x), _besseli(nu[end], x)
212+
return besselk_down_recurrence!(out, x, nu)
213+
end
214+
208215
"""
209216
besseli_positive_args(nu, x::T) where T <: Union{Float32, Float64}
210217

src/besselj.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,11 @@ end
206206
Bessel function of the first kind of order nu, ``J_{nu}(x)``.
207207
nu and x must be real where nu and x can be positive or negative.
208208
"""
209-
besselj(nu::Real, x::Real) = _besselj(nu, float(x))
209+
besselj(nu, x::Real) = _besselj(nu, float(x))
210210

211211
_besselj(nu, x::Float16) = Float16(_besselj(nu, Float32(x)))
212212

213-
function _besselj(nu, x::T) where T <: Union{Float32, Float64}
213+
function _besselj(nu::T, x::T) where T <: Union{Float32, Float64}
214214
isinteger(nu) && return _besselj(Int(nu), x)
215215
abs_nu = abs(nu)
216216
abs_x = abs(x)
@@ -255,6 +255,18 @@ function _besselj(nu::Integer, x::T) where T <: Union{Float32, Float64}
255255
end
256256
end
257257

258+
function _besselj(nu::AbstractRange, x::T) where T
259+
(nu[1] >= 0 && step(nu) == 1) || throw(ArgumentError("nu must be >= 0 with step(nu)=1"))
260+
out = Vector{T}(undef, length(nu))
261+
if nu[end] < x
262+
out[1], out[2] = _besselj(nu[1], x), _besselj(nu[2], x)
263+
return besselj_up_recurrence!(out, x, nu)
264+
else
265+
out[end-1], out[end] = _besselj(nu[end-1], x), _besselj(nu[end], x)
266+
return besselj_down_recurrence!(out, x, nu)
267+
end
268+
end
269+
258270
"""
259271
besselj_positive_args(nu, x::T) where T <: Float64
260272

src/besselk.jl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ end
187187
188188
Modified Bessel function of the second kind of order nu, ``K_{nu}(x)``.
189189
"""
190-
besselk(nu::Real, x::Real) = _besselk(nu, float(x))
190+
besselk(nu, x::Real) = _besselk(nu, float(x))
191191

192192
_besselk(nu, x::Float16) = Float16(_besselk(nu, Float32(x)))
193193

194-
function _besselk(nu, x::T) where T <: Union{Float32, Float64}
194+
function _besselk(nu::T, x::T) where T <: Union{Float32, Float64}
195195
isinteger(nu) && return _besselk(Int(nu), x)
196196
abs_nu = abs(nu)
197197
abs_x = abs(x)
@@ -216,6 +216,13 @@ function _besselk(nu::Integer, x::T) where T <: Union{Float32, Float64}
216216
end
217217
end
218218

219+
function _besselk(nu::AbstractRange, x::T) where T
220+
(nu[1] >= 0 && step(nu) == 1) || throw(ArgumentError("nu must be >= 0 with step(nu)=1"))
221+
out = Vector{T}(undef, length(nu))
222+
out[1], out[2] = _besselk(nu[1], x), _besselk(nu[2], x)
223+
return besselk_up_recurrence!(out, x, nu)
224+
end
225+
219226
"""
220227
besselk_positive_args(x::T) where T <: Union{Float32, Float64}
221228

src/bessely.jl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,11 @@ end
243243
Bessel function of the second kind of order nu, ``Y_{nu}(x)``.
244244
nu and x must be real where nu and x can be positive or negative.
245245
"""
246-
bessely(nu::Real, x::Real) = _bessely(nu, float(x))
246+
bessely(nu, x::Real) = _bessely(nu, float(x))
247247

248248
_bessely(nu, x::Float16) = Float16(_bessely(nu, Float32(x)))
249249

250-
function _bessely(nu, x::T) where T <: Union{Float32, Float64}
250+
function _bessely(nu::T, x::T) where T <: Union{Float32, Float64}
251251
isnan(nu) || isnan(x) && return NaN
252252
isinteger(nu) && return _bessely(Int(nu), x)
253253
abs_nu = abs(nu)
@@ -296,6 +296,13 @@ function _bessely(nu::Integer, x::T) where T <: Union{Float32, Float64}
296296
end
297297
end
298298

299+
function _bessely(nu::AbstractRange, x::T) where T
300+
(nu[1] >= 0 && step(nu) == 1) || throw(ArgumentError("nu must be >= 0 with step(nu)=1"))
301+
out = Vector{T}(undef, length(nu))
302+
out[1], out[2] = _bessely(nu[1], x), _bessely(nu[2], x)
303+
return besselj_up_recurrence!(out, x, nu)
304+
end
305+
299306
#####
300307
##### `bessely` for positive arguments and orders
301308
#####

src/recurrence.jl

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,29 @@
22
# outputs both (bessel(x, nu_end), bessel(x, nu_end+1)
33
# x = 0.1; k0 = besselk(0,x); k1 = besselk(1,x);
44
# besselk_up_recurrence(x, k1, k0, 1, 5) will give besselk(5, x)
5-
@inline function besselk_up_recurrence(x, jnu, jnum1, nu_start, nu_end)
5+
function besselk_up_recurrence(x, jnu, jnum1, nu_start, nu_end)
66
x2 = 2 / x
77
while nu_start < nu_end + 0.5 # avoid inexact floating points when nu isa float
88
jnum1, jnu = jnu, muladd(nu_start*x2, jnu, jnum1)
99
nu_start += 1
1010
end
1111
return jnum1, jnu
1212
end
13+
function besselk_up_recurrence!(out, x::T, nu_range) where T
14+
x2 = 2 / x
15+
k = 3
16+
for nu in nu_range[2:end-1]
17+
out[k] = muladd(nu*x2, out[k-1], out[k-2])
18+
k += 1
19+
end
20+
return out
21+
end
1322

1423
# forward recurrence relation for besselj and bessely
1524
# outputs both (bessel(x, nu_end), bessel(x, nu_end+1)
1625
# x = 0.1; y0 = bessely0(x); y1 = bessely1(x);
1726
# besselj_up_recurrence(x, y1, y0, 1, 5) will give bessely(5, x)
18-
@inline function besselj_up_recurrence(x::T, jnu, jnum1, nu_start, nu_end) where T
27+
function besselj_up_recurrence(x::T, jnu, jnum1, nu_start, nu_end) where T
1928
x2 = 2 / x
2029
while nu_start < nu_end + 0.5 # avoid inexact floating points when nu isa float
2130
jnum1, jnu = jnu, muladd(nu_start*x2, jnu, -jnum1)
@@ -27,12 +36,21 @@ end
2736
# NaN inputs need to be checked before getting to this routine
2837
return isnan(jnum1) ? (-T(Inf), -T(Inf)) : (jnum1, jnu)
2938
end
39+
function besselj_up_recurrence!(out, x::T, nu_range) where T
40+
x2 = 2 / x
41+
k = 3
42+
for nu in nu_range[2:end-1]
43+
out[k] = muladd(nu*x2, out[k-1], -out[k-2])
44+
k += 1
45+
end
46+
return out
47+
end
3048

3149
# backward recurrence relation for besselj and bessely
3250
# outputs both (bessel(x, nu_end), bessel(x, nu_end-1)
3351
# x = 0.1; j10 = besselj(10, x); j11 = besselj(11, x);
3452
# besselj_down_recurrence(x, j10, j11, 10, 1) will give besselj(1, x)
35-
@inline function besselj_down_recurrence(x, jnu, jnup1, nu_start, nu_end)
53+
function besselj_down_recurrence(x, jnu, jnup1, nu_start, nu_end)
3654
x2 = 2 / x
3755
while nu_start > nu_end - 0.5
3856
jnup1, jnu = jnu, muladd(nu_start*x2, jnu, -jnup1)
@@ -41,6 +59,16 @@ end
4159
return jnup1, jnu
4260
end
4361

62+
function besselj_down_recurrence!(out, x::T, nu_range) where T
63+
x2 = 2 / x
64+
k = length(nu_range) - 2
65+
for nu in nu_range[end-1:-1:2]
66+
out[k] = muladd(nu*x2, out[k+1], -out[k+2])
67+
k -= 1
68+
end
69+
return out
70+
end
71+
4472
#=
4573
# currently not used
4674
# backward recurrence relation for besselk and besseli
@@ -56,3 +84,12 @@ end
5684
return jnup1, jnu
5785
end
5886
=#
87+
function besselk_down_recurrence!(out, x::T, nu_range) where T
88+
x2 = 2 / x
89+
k = length(nu_range) - 2
90+
for nu in nu_range[end-1:-1:2]
91+
out[k] = muladd(nu*x2, out[k+1], out[k+2])
92+
k -= 1
93+
end
94+
return out
95+
end

test/besseli_test.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ t = [besselix(m, x) for m in m, x in x]
9494
@test t [SpecialFunctions.besselix(m, x) for m in m, x in x]
9595
@test besselix(10, Float16(1.0)) isa Float16
9696

97-
## Tests for besselk
97+
## Tests for besseli
9898

9999
## test all numbers and orders for 0<nu<100
100100
x = [0.01, 0.05, 0.1, 0.2, 0.4, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.91, 0.92, 0.93, 0.95, 0.96, 0.97, 0.98, 0.99, 0.995, 0.999, 1.0, 1.001, 1.01, 1.05, 1.1, 1.2, 1.4, 1.6, 1.8, 1.9, 2.5, 3.0, 3.5, 4.0]
@@ -106,6 +106,12 @@ for v in nu, xx in x
106106
@test isapprox(besseli(Float32(v), Float32(xx)), Float32(sf))
107107
end
108108

109+
# test nu_range
110+
@test besseli(0:50, 2.0) SpecialFunctions.besseli.(0:50, 2.0) rtol=1e-13
111+
@test besseli(0.5:1:10.5, 2.0) SpecialFunctions.besseli.(0.5:1:10.5, 2.0) rtol=1e-13
112+
113+
### need to fix method ambiguities for other functions ######
114+
109115
# test Inf
110116
@test isinf(besseli(2, Inf))
111117

test/besselj_test.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ for v in nu, xx in x
114114
@test isapprox(Bessels.besseljy_positive_args(v, xx)[1], Float64(sf), rtol=5e-11)
115115
end
116116

117+
# 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
121+
@test besselj(0.5:1:10.5, 40.0) SpecialFunctions.besselj.(0.5:1:10.5, 40.0) rtol=1e-11
122+
117123
# test Float16 and Float32
118124
@test besselj(10, Float16(1.0)) isa Float16
119125
@test besselj(10.2f0, 1.0f0) isa Float32

test/besselk_test.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ for v in nu, xx in x
126126
@test isapprox(besselk(Float32(v), Float32(xx)), Float32(sf))
127127
end
128128

129+
# test nu_range
130+
@test besselk(0:50, 2.0) SpecialFunctions.besselk.(0:50, 2.0) rtol=1e-13
131+
@test besselk(0.5:1:10.5, 12.0) SpecialFunctions.besselk.(0.5:1:10.5, 12.0) rtol=1e-13
132+
129133
# test Float16
130134
@test besselk(10, Float16(1.0)) isa Float16
131135
@test besselkx(10, Float16(1.0)) isa Float16

test/bessely_test.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ for v in nu, xx in x
9494
@test isapprox(bessely(Float32(v), Float32(xx)), Float32(sf))
9595
end
9696

97+
# test nu_range
98+
@test bessely(0:50, 2.0) SpecialFunctions.bessely.(0:50, 2.0) rtol=1e-11
99+
@test bessely(0:50, 100.0) SpecialFunctions.bessely.(0:50, 100.0) rtol=1e-11
100+
@test bessely(0.5:1:10.5, 2.0) SpecialFunctions.bessely.(0.5:1:10.5, 2.0) rtol=1e-11
101+
@test bessely(0.5:1:10.5, 40.0) SpecialFunctions.bessely.(0.5:1:10.5, 40.0) rtol=1e-11
102+
97103
# test Float16
98104
@test bessely(10, Float16(1.0)) isa Float16
99105
@test bessely(10.2f0, 1.0f0) isa Float32

test/sphericalbessel_test.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ x = NaN
8686
@test Bessels.sphericalbesselk(Float16(1.4), Float16(1.2)) isa Float16
8787
@test Bessels.sphericalbesselk(1.0f0, 1.2f0) isa Float32
8888

89-
@test Bessels.sphericalbesseli(Float16(1.4), Float16(1.2)) isa Float16
90-
@test Bessels.sphericalbesseli(1.0f0, 1.2f0) isa Float32
89+
@test Bessels.sphericalbesseli(1, Float16(1.2)) isa Float16
90+
@test Bessels.sphericalbesseli(2, 1.2f0) isa Float32
9191

9292
for x in 0.5:1.5:100.0, v in [0, 1, 2, 3, 4, 5.5, 8.2, 10]
9393
@test isapprox(Bessels.sphericalbesselj(v, x), SpecialFunctions.sphericalbesselj(v, x), rtol=1e-12)

0 commit comments

Comments
 (0)