Skip to content

Commit 7278cfe

Browse files
committed
add support for negative args
1 parent 00cd0ec commit 7278cfe

File tree

5 files changed

+115
-20
lines changed

5 files changed

+115
-20
lines changed

src/U_polynomials.jl

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,6 @@ Uk_poly_Kn(p, v, p2, ::Type{Float64}) = Uk_poly10(p, v, p2)[2]
9797
end
9898
end
9999

100-
function Uk_poly3(p, v, p2)
101-
u0 = 1.0
102-
u1 = evalpoly(p2, (0.125, -0.20833333333333334))
103-
u2 = evalpoly(p2, (0.0703125, -0.4010416666666667, 0.3342013888888889))
104-
u3 = evalpoly(p2, (0.0732421875, -0.8912109375, 1.8464626736111112, -1.0258125964506173))
105-
106-
Poly = (u0, u1, u2, u3)
107-
108-
return split_evalpoly(-p/v, Poly)
109-
end
110100
function Uk_poly5(p, v, p2)
111101
u0 = 1.0
112102
u1 = evalpoly(p2, (0.125, -0.20833333333333334))

src/besseli.jl

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,49 @@ end
160160
#
161161

162162
"""
163-
besseli(nu, x::T) where T <: Union{Float32, Float64}
163+
besselk(x::T) where T <: Union{Float32, Float64}
164164
165-
Modified Bessel function of the first kind of order nu, ``I_{nu}(x)``.
166-
Nu must be real.
165+
Modified Bessel function of the second kind of order nu, ``K_{nu}(x)``.
166+
"""
167+
function besseli(nu::Real, x::T) where T
168+
isinteger(nu) && return besseli(Int(nu), x)
169+
abs_nu = abs(nu)
170+
abs_x = abs(x)
171+
172+
if nu >= 0
173+
if x >= 0
174+
return besseli_positive_args(abs_nu, abs_x)
175+
else
176+
return cispi(abs_nu) * besseli_positive_args(abs_nu, abs_x)
177+
end
178+
else
179+
if x >= 0
180+
return besseli_positive_args(abs_nu, abs_x) + 2 / π * sinpi(abs_nu) * besselk_positive_args(abs_nu, abs_x)
181+
else
182+
Iv = besseli_positive_args(abs_nu, abs_x)
183+
Kv = besselk_positive_args(abs_nu, abs_x)
184+
return cispi(abs_nu) * Iv + 2 / π * sinpi(abs_nu) * (cispi(-abs_nu) * Kv - im * π * Iv)
185+
end
186+
end
187+
end
188+
function besseli(nu::Integer, x::T) where T
189+
abs_nu = abs(nu)
190+
abs_x = abs(x)
191+
sg = iseven(abs_nu) ? 1 : -1
192+
193+
if x >= 0
194+
return besseli_positive_args(abs_nu, abs_x)
195+
else
196+
return sg * besseli_positive_args(abs_nu, abs_x)
197+
end
198+
end
199+
200+
"""
201+
besseli_positive_args(nu, x::T) where T <: Union{Float32, Float64}
202+
203+
Modified Bessel function of the first kind of order nu, ``I_{nu}(x)`` for positive arguments.
167204
"""
168-
function besseli(nu, x::T) where T <: Union{Float32, Float64}
205+
function besseli_positive_args(nu, x::T) where T <: Union{Float32, Float64}
169206
iszero(nu) && return besseli0(x)
170207
isone(nu) && return besseli1(x)
171208

src/besselk.jl

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,38 @@ end
185185
186186
Modified Bessel function of the second kind of order nu, ``K_{nu}(x)``.
187187
"""
188-
function besselk(nu, x::T) where T <: Union{Float32, Float64}
189-
# check to make sure nu isn't zero
188+
function besselk(nu::Real, x::T) where T
189+
isinteger(nu) && return besselk(Int(nu), x)
190+
abs_nu = abs(nu)
191+
abs_x = abs(x)
192+
193+
if x >= 0
194+
return besselk_positive_args(abs_nu, abs_x)
195+
else
196+
return cispi(-abs_nu)*besselk_positive_args(abs_nu, abs_x) - besseli_positive_args(abs_nu, abs_x) * im * π
197+
end
198+
end
199+
function besselk(nu::Integer, x::T) where T
200+
abs_nu = abs(nu)
201+
abs_x = abs(x)
202+
sg = iseven(abs_nu) ? 1 : -1
203+
204+
if x >= 0
205+
return besselk_positive_args(abs_nu, abs_x)
206+
else
207+
return sg * besselk_positive_args(abs_nu, abs_x) - im * π * besseli_positive_args(abs_nu, abs_x)
208+
end
209+
end
210+
211+
"""
212+
besselk_positive_args(x::T) where T <: Union{Float32, Float64}
213+
214+
Modified Bessel function of the second kind of order nu, ``K_{nu}(x)`` valid for postive arguments and orders.
215+
"""
216+
function besselk_positive_args(nu, x::T) where T <: Union{Float32, Float64}
217+
iszero(x) && return T(Inf)
218+
219+
# dispatch to avoid uniform expansion when nu = 0
190220
iszero(nu) && return besselk0(x)
191221

192222
# use uniform debye expansion if x or nu is large
@@ -207,7 +237,7 @@ end
207237
Scaled modified Bessel function of the second kind of order nu, ``K_{nu}(x)*e^{x}``.
208238
"""
209239
function besselkx(nu, x::T) where T <: Union{Float32, Float64}
210-
# check to make sure nu isn't zero
240+
# dispatch to avoid uniform expansion when nu = 0
211241
iszero(nu) && return besselk0x(x)
212242

213243
# use uniform debye expansion if x or nu is large
@@ -333,11 +363,11 @@ end
333363
##### Power series for K_{nu}(x)
334364
#####
335365

336-
# Use power series form of K_v(x) which is accurate for small x (x<2) or when nu > X
366+
# Use power series form of K_v(x) which is accurate for small x (x<2) or when nu > x
337367
# We use the form as described by Equation 3.2 from reference [7].
338368
# This method was originally contributed by @cgeoga https://github.com/cgeoga/BesselK.jl/blob/main/src/besk_ser.jl
339369
# A modified form appears below. See more discussion at https://github.com/heltonmc/Bessels.jl/pull/29
340-
# This is only accurate for noninteger orders (nu) and no checks are performed.
370+
# This is only valid for noninteger orders (nu) and no checks are performed.
341371
#
342372
"""
343373
besselk_power_series(nu, x::T) where T <: Float64

test/besseli_test.jl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,22 @@ for v in nu, xx in x
102102
@test isapprox(besseli(v, xx), Float64(sf), rtol=2e-13)
103103
end
104104

105-
105+
### tests for negative arguments
106+
107+
(v, x) = 12.0, 3.2
108+
@test besseli(v,x) 7.1455266650203694069897133431E-7
109+
110+
(v, x) = -8.0, 4.2
111+
@test besseli(v,x) 0.0151395115677545706602449919627
112+
113+
(v, x) = 12.3, 8.2
114+
@test besseli(v,x) 0.113040018422133018059759059298
115+
116+
(v, x) = -12.3, 8.2
117+
@test besseli(v,x) 0.267079696793126091886043602895
118+
119+
(v, x) = -14.0, -9.9
120+
@test besseli(v,x) 0.2892290867115615816280234648
121+
122+
(v, x) = -14.6, -10.6
123+
@test besseli(v,x) -0.157582642056898598750175404443 - 0.484989503203097528858271270828*im

test/besselk_test.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,23 @@ for v in nu, xx in x
115115
sf = SpecialFunctions.besselk(v, xx)
116116
@test isapprox(besselk(v, xx), Float64(sf), rtol=2e-13)
117117
end
118+
119+
### tests for negative arguments
120+
121+
(v, x) = 12.0, 3.2
122+
@test besselk(v,x) 56331.504348755621996013084096
123+
124+
(v, x) = -8.0, 4.2
125+
@test besselk(v,x) 3.65165949039881135495282699061
126+
127+
(v, x) = 12.3, 8.2
128+
@test besselk(v,x) 0.299085139926840649406079315812
129+
130+
(v, x) = -12.3, 8.2
131+
@test besselk(v,x) 0.299085139926840649406079315812
132+
133+
(v, x) = -14.0, -9.9
134+
@test besselk(v,x) 0.100786833375605803570325345603 - 0.90863997401752715470886289641*im
135+
136+
(v, x) = -14.6, -10.6
137+
@test besselk(v,x) -0.0180385087581148387140033906859 - 1.54653251445680014758965158559*im

0 commit comments

Comments
 (0)