Skip to content

Commit 2ff2caf

Browse files
committed
add float32 versions
1 parent 89cd49d commit 2ff2caf

File tree

2 files changed

+115
-7
lines changed

2 files changed

+115
-7
lines changed

src/besselk.jl

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@
8484
# + 16843538631795795357786827345307534156063*p^8 - 2069933923586966756183324291232117362250*p^6 + 136735019134677724428035696765082813750*p^4 - 3698121486504259988094897605296209375*p^2 + 17438611142828905996129258798828125) * -1 / v^13
8585
#
8686
# For large orders these formulas will converge much faster than using upward recurrence.
87-
# If using up to the fifth U polynomial, it requires evaluation of a 15 degree polynomial.
88-
# For tenth U polynomial, it requires evaluation of a 30 degree polynomial.
8987
#
9088
#
9189
# [1] "Rational Approximations for the Modified Bessel Function of the Second Kind
@@ -186,13 +184,20 @@ For small to medium values of x and large values of nu this will overflow and re
186184
187185
Modified Bessel function of the second kind of order nu, ``K_{nu}(x)``.
188186
"""
189-
function besselk(nu::Int, x::T) where T <: Union{Float32, Float64}
190-
if nu < 100
187+
function besselk(nu::Int, x::T) where T <: Float64
188+
if nu < 50
191189
return three_term_recurrence(x, besselk0(x), besselk1(x), nu)
192190
else
193191
return besselk_large_orders(BigFloat(nu), BigFloat(x))
194192
end
195193
end
194+
function besselk(nu::Int, x::T) where T <: Float32
195+
if nu < 20
196+
return three_term_recurrence(x, besselk0(x), besselk1(x), nu)
197+
else
198+
return k4(nu, x)
199+
end
200+
end
196201
"""
197202
besselk(x::T) where T <: Union{Float32, Float64}
198203
@@ -220,7 +225,71 @@ end
220225
return k2
221226
end
222227

228+
function k4(v, x::T) where T <: Float32
229+
x = Float64(x)
230+
z = x / v
231+
zs = sqrt(1 + z^2)
232+
n = zs + log(z / (1 + zs))
233+
coef = exp(-v * n) * sqrt(pi / (2*v)) / sqrt(zs)
234+
p = inv(zs)
235+
p2 = p*p
236+
u0 = one(Float64)
237+
u1 = 1 / 24 * evalpoly(p2, (3, -5))
238+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
239+
u3 = 1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
240+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
241+
return Float32(coef*evalpoly(-p/v, (u0, u1, u2, u3, u4)))
242+
end
243+
244+
function besselk_large_orders(v, x::T) where T <: AbstractFloat
245+
x = Float64(x)
246+
z = x / v
247+
zs = sqrt(1 + z^2)
248+
n = zs + log(z / (1 + zs))
249+
coef = exp(-v * n) * sqrt(pi / (2*v)) / sqrt(zs)
250+
p = inv(zs)
251+
p2 = p*p
252+
u0 = one(Float64)
253+
u1 = 1 / 24 * evalpoly(p2, (3, -5))
254+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
255+
u3 = 1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
256+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
257+
u5 = 1 / 6688604160 * evalpoly(p2, (1519035525, -49286948607, 284499769554, -614135872350, 566098157625, -188699385875))
258+
u6 = 1 / 4815794995200 * evalpoly(p2, (2757049477875, -127577298354750, 1050760774457901, -3369032068261860,5104696716244125, -3685299006138750, 1023694168371875))
259+
u7 = 1 / 115579079884800 * evalpoly(p2, (199689155040375, -12493049053044375, 138799253740521843, -613221795981706275, 1347119637570231525, -1570320948552481125, 931766432052080625, -221849150488590625))
260+
u8 = 1 / 22191183337881600 * evalpoly(p2, (134790179652253125, -10960565081605263000, 157768535329832893644, -914113758588905038248, 2711772922412520971550, -4513690624987320777000, 4272845805510421639500, -2152114239059719935000, 448357133137441653125))
261+
return coef*evalpoly(-p/v, (u0, u1, u2, u3, u4, u5, u6, u7, u8))
262+
end
263+
264+
#=
265+
function besselk_large_orders(v, x::T) where T <: AbstractFloat
266+
x = Float64(x)
267+
z = x / v
268+
zs = sqrt(1 + z^2)
269+
n = zs + log(z / (1 + zs))
270+
coef = exp(-v * n) * sqrt(pi / (2*v)) / sqrt(zs)
271+
p = inv(zs)
272+
p2 = p*p
273+
u0 = one(Float64)
274+
u1 = 1 / 24 * evalpoly(p2, (3, -5))
275+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
276+
u3 = 1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
277+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
278+
u5 = 1 / 6688604160 * evalpoly(p2, (1519035525, -49286948607, 284499769554, -614135872350, 566098157625, -188699385875))
279+
u6 = 1 / 4815794995200 * evalpoly(p2, (2757049477875, -127577298354750, 1050760774457901, -3369032068261860,5104696716244125, -3685299006138750, 1023694168371875))
280+
u7 = 1 / 115579079884800 * evalpoly(p2, (199689155040375, -12493049053044375, 138799253740521843, -613221795981706275, 1347119637570231525, -1570320948552481125, 931766432052080625, -221849150488590625))
281+
u8 = 1 / 22191183337881600 * evalpoly(p2, (134790179652253125, -10960565081605263000, 157768535329832893644, -914113758588905038248, 2711772922412520971550, -4513690624987320777000, 4272845805510421639500, -2152114239059719935000, 448357133137441653125))
282+
u9 = 1 / 263631258054033408000 * evalpoly(p2, (6427469716717690265625, -659033454841709672064375, 11921080954211358275362500, -87432034049652400520788332, 334380732677827878090447630, -741743213039573443221773250, 992115946599792610768672500, -790370708270219620781737500, 345821892003106984030190625, -64041091111686478524109375))
283+
u10 = 1 / 88580102706155225088000 * evalpoly(p2, (9745329584487361980740625, -1230031256571145165088463750, 27299183373230345667273718125, -246750339886026017414509498824, 1177120360439828012193658602930, -3327704366990695147540934069220, 5876803711285273203043452095250, -6564241639632418015173104205000, 4513386761946134740461797128125, -1745632061522350031610173343750, 290938676920391671935028890625))
284+
285+
return coef*evalpoly(-p/v, (u0, u1, u2, u3, u4, u5, u6, u7, u8, u9, u10))
286+
end
287+
288+
=#
289+
290+
223291

292+
#=
224293
function besselk_large_orders(v, x::T) where T <: AbstractFloat
225294
z = x / v
226295
zs = sqrt(1 + z^2)
@@ -248,12 +317,39 @@ function besselk_large_orders(v, x::T) where T <: AbstractFloat
248317
u13 = p^13 / 955134445051714068660879360000 * (-14020668045586884672121117629431460546875*p^26 + 109361210755577700442544717509565392265625*p^24 - 381190503845282445953419057314665534156250*p^22 + 782463969315283937856703223178540650343750*p^20
249318
- 1049095945162229046324321461816274931715625*p^18 + 962926533925253374359704288384340809260875*p^16 - 616410216242554698436702353237166008656700*p^14 + 274983827478138958623041508409195988431140*p^12 - 83924867223075156862785921508524155665245*p^10
250319
+ 16843538631795795357786827345307534156063*p^8 - 2069933923586966756183324291232117362250*p^6 + 136735019134677724428035696765082813750*p^4 - 3698121486504259988094897605296209375*p^2 + 17438611142828905996129258798828125) * -1 / v^13
251-
252-
320+
u14 = p^14 / 45846453362482275295722209280000 * (13133360053559028970728309756597440972265625*p^28 - 110320224449895843354117801955418504167031250*p^26 + 417630985812040040477569028872405152769921875*p^24
321+
- 940627071986145750405920450097257805227812500*p^22 + 1401302601668131482630653233972052729323190625*p^20 - 1451823699927947602004297385351260623500372750*p^18 + 1070439683260179398514645952824098811025619475*p^16
322+
- 564850830044980230366140582063618983657685400*p^14 + 211477117385619365164298957821904115470535555*p^12 - 54857705817658080981995319669299096598482382*p^10 + 9440449669103391509091075981237243128469201*p^8
323+
- 1000503839668383458999731491914516564625300*p^6 + 57170953417612444837142230812990944671875*p^4 - 1338184074771428116079233795614103631250*p^2 + 5448320367052402487647812713291015625) * 1 / v^14
324+
u15 = p^15 / 9820310310243703368343697227776000000 * (- 59115551939078562227317999668652486368337724609375*p^30 + 532039967451707060045861997017872377315039521484375*p^28 - 2173722139119126857509156976742601742357422740234375*p^26
325+
+ 5329871927856528282113994744458999865006055974609375*p^24 - 8735135969643867540297524795790262235822823374296875*p^22 + 10085018700249896522602267572484630409640764997271875*p^20 - 8420533422834140468835467666391400380550043688871875*p^18
326+
+ 5136561256208409671660362298619778869859994724706875*p^16 - 2284251621937242886581917667066122422330060024456125*p^14 + 730367145705123976114617970888707594104468177381925*p^12 - 163359140754958502896104062604202934925448173291477*p^10
327+
+ 24403480234538299231733883413666768614198435948125*p^8 - 2254933495791765108580529087615802250458013685625*p^6 + 112597271053778779753048514469995937998172890625*p^4 - 2303431987527333128955769182299845911305390625*p^2 + 8178936810213560828419581728001773291015625) * -1 / v^15
328+
253329
254-
out1 = ((u13 + u12 + u11 + u10 + u9) + u8) + u7
330+
out1 = ((u15 + u14 + u13 + u12 + u11 + u10 + u9) + u8) + u7
255331
out2 = ((out1 + u6 + u5) + u4) + u3
256332
out = ((out2 + u2) + u1) + u0
257333
258334
return coef*out
259335
end
336+
337+
338+
339+
340+
u11 = 1 / 27636992044320430227456000 * (-1363312191078326248171914924296875*p^22 + 8997860461116953237934638500359375*p^20 - 25963913760458280822131901737878125*p^18 + 42936745153513007436411401865860625*p^16 - 44801790321820682384740638703320750*p^14 + 30589806122850866110941936529264950*p^12 - 13704902022868787041097596217578170*p^10
341+
+ 3926191452593448964331218647028194*p^8 - 676389476843440422173605288596087*p^6 + 62011003282542082472252466220875*p^4 - 2321657500166464779660536015625*p^2 + 15237265774872558064250728125) * -1 / v^11
342+
u12 = 1 / 39797268543821419527536640000 * (32426380464797989812768996474401171875*p^24 - 233469939346545526651936774615688437500*p^22 + 743739612850105971846901081692858843750*p^20 - 1378260730939829908037976894025628887500*p^18 + 1642838631056253395899341314188134178125*p^16 - 1314368459332124683504418467809129387000*p^14
343+
+ 714528665351965363868467348116538170900*p^12 - 261201165596865827608687437905740780920*p^10 + 62055079517573388459132793029571876461*p^8 - 8958590476947726766450604043798559500*p^6 + 692277766674325563109617997687563750*p^4 - 21882222767154197351962677311437500*p^2 + 120907703923613748239829527671875) * 1 / v^12
344+
u13 = 1 / 955134445051714068660879360000 * (-14020668045586884672121117629431460546875*p^26 + 109361210755577700442544717509565392265625*p^24 - 381190503845282445953419057314665534156250*p^22 + 782463969315283937856703223178540650343750*p^20
345+
- 1049095945162229046324321461816274931715625*p^18 + 962926533925253374359704288384340809260875*p^16 - 616410216242554698436702353237166008656700*p^14 + 274983827478138958623041508409195988431140*p^12 - 83924867223075156862785921508524155665245*p^10
346+
+ 16843538631795795357786827345307534156063*p^8 - 2069933923586966756183324291232117362250*p^6 + 136735019134677724428035696765082813750*p^4 - 3698121486504259988094897605296209375*p^2 + 17438611142828905996129258798828125) * -1 / v^13
347+
u14 = 1 / 45846453362482275295722209280000 * (13133360053559028970728309756597440972265625*p^28 - 110320224449895843354117801955418504167031250*p^26 + 417630985812040040477569028872405152769921875*p^24
348+
- 940627071986145750405920450097257805227812500*p^22 + 1401302601668131482630653233972052729323190625*p^20 - 1451823699927947602004297385351260623500372750*p^18 + 1070439683260179398514645952824098811025619475*p^16
349+
- 564850830044980230366140582063618983657685400*p^14 + 211477117385619365164298957821904115470535555*p^12 - 54857705817658080981995319669299096598482382*p^10 + 9440449669103391509091075981237243128469201*p^8
350+
- 1000503839668383458999731491914516564625300*p^6 + 57170953417612444837142230812990944671875*p^4 - 1338184074771428116079233795614103631250*p^2 + 5448320367052402487647812713291015625) * 1 / v^14
351+
u15 = 1 / 9820310310243703368343697227776000000 * (- 59115551939078562227317999668652486368337724609375*p^30 + 532039967451707060045861997017872377315039521484375*p^28 - 2173722139119126857509156976742601742357422740234375*p^26
352+
+ 5329871927856528282113994744458999865006055974609375*p^24 - 8735135969643867540297524795790262235822823374296875*p^22 + 10085018700249896522602267572484630409640764997271875*p^20 - 8420533422834140468835467666391400380550043688871875*p^18
353+
+ 5136561256208409671660362298619778869859994724706875*p^16 - 2284251621937242886581917667066122422330060024456125*p^14 + 730367145705123976114617970888707594104468177381925*p^12 - 163359140754958502896104062604202934925448173291477*p^10
354+
+ 24403480234538299231733883413666768614198435948125*p^8 - 2254933495791765108580529087615802250458013685625*p^6 + 112597271053778779753048514469995937998172890625*p^4 - 2303431987527333128955769182299845911305390625*p^2 + 8178936810213560828419581728001773291015625) * -1 / v^15
355+
=#

test/besselk_test.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ m = 200:5:1000; x = 400.0:10.0:1200.0
8181
t = Float64.([besselk(m, x) for m in m, x in x])
8282
@test t [SpecialFunctions.besselk(m, x) for m in m, x in x]
8383

84+
# Float 32 tests for aysmptotic expansion
85+
m = 20:5:200; x = 5.0f0:2.0f0:400.0f0
86+
t = [besselk(m, x) for m in m, x in x]
87+
@test t[10] isa Float32
88+
@test t Float32.([SpecialFunctions.besselk(m, x) for m in m, x in x])
89+
90+
# test for low values and medium orders
91+
m = 20:5:50; x = [1f-3, 1f-2, 1f-1, 1f0, 1.5f0, 2.0f0, 4.0f0]
92+
t = [besselk(m, x) for m in m, x in x]
93+
@test t[5] isa Float32
94+
@test t Float32.([SpecialFunctions.besselk(m, x) for m in m, x in x])
95+
8496
@test iszero(besselk(20, 1000.0))
8597
#@test isinf(besselk(250, 5.0))
8698

0 commit comments

Comments
 (0)