Skip to content

Commit 8ebb0f2

Browse files
authored
Merge pull request #8 from heltonmc/asymptotic-expansion
Asymptotic expansion for large orders. Besselk(nu, x)
2 parents e5dfe6c + ef12079 commit 8ebb0f2

File tree

10 files changed

+309
-39
lines changed

10 files changed

+309
-39
lines changed

src/Bessels.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export besselj
77
export bessely0
88
export bessely1
99

10+
export besseli
11+
export besselix
1012
export besseli0
1113
export besseli0x
1214
export besseli1
@@ -32,7 +34,8 @@ include("Float128/bessely.jl")
3234
include("Float128/constants.jl")
3335

3436
include("math_constants.jl")
35-
#include("parse.jl")
37+
include("U_polynomials.jl")
38+
include("recurrence.jl")
3639
#include("hankel.jl")
3740

3841
end

src/U_polynomials.jl

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
function Uk_poly_Kn(p, v, p2, ::Type{Float32})
2+
u0 = one(p)
3+
u1 = 1 / 24 * evalpoly(p2, (3, -5))
4+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
5+
u3 = 1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
6+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
7+
return evalpoly(-p/v, (u0, u1, u2, u3, u4))
8+
end
9+
function Uk_poly_Kn(p, v, p2, ::Type{T}) where T <: Float64
10+
u0 = one(T)
11+
u1 = 1 / 24 * evalpoly(p2, (3, -5))
12+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
13+
u3 = 1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
14+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
15+
u5 = 1 / 6688604160 * evalpoly(p2, (1519035525, -49286948607, 284499769554, -614135872350, 566098157625, -188699385875))
16+
u6 = 1 / 4815794995200 * evalpoly(p2, (2757049477875, -127577298354750, 1050760774457901, -3369032068261860,5104696716244125, -3685299006138750, 1023694168371875))
17+
return evalpoly(-p/v, (u0, u1, u2, u3, u4, u5, u6))
18+
end
19+
function Uk_poly_In(p, v, p2, ::Type{T}) where T <: Float64
20+
u0 = one(T)
21+
u1 = -1 / 24 * evalpoly(p2, (3, -5))
22+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
23+
u3 = -1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
24+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
25+
u5 = -1 / 6688604160 * evalpoly(p2, (1519035525, -49286948607, 284499769554, -614135872350, 566098157625, -188699385875))
26+
u6 = 1 / 4815794995200 * evalpoly(p2, (2757049477875, -127577298354750, 1050760774457901, -3369032068261860,5104696716244125, -3685299006138750, 1023694168371875))
27+
return evalpoly(-p/v, (u0, u1, u2, u3, u4, u5, u6))
28+
end
29+
function Uk_poly_In(p, v, p2, ::Type{Float32})
30+
u0 = one(p)
31+
u1 = -1 / 24 * evalpoly(p2, (3, -5))
32+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
33+
u3 = -1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
34+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
35+
return evalpoly(-p/v, (u0, u1, u2, u3, u4))
36+
end
37+
38+
#=
39+
function Uk_poly_Kn(p, v, p2, ::Type{T}) where T <: BigFloat
40+
u0 = one(T)
41+
u1 = 1 / 24 * evalpoly(p2, (3, -5))
42+
u2 = 1 / 1152 * evalpoly(p2, (81, -462, 385))
43+
u3 = 1 / 414720 * evalpoly(p2, (30375, -369603, 765765, -425425))
44+
u4 = 1 / 39813120 * evalpoly(p2, (4465125, -94121676, 349922430, -446185740, 185910725))
45+
u5 = 1 / 6688604160 * evalpoly(p2, (1519035525, -49286948607, 284499769554, -614135872350, 566098157625, -188699385875))
46+
u6 = 1 / 4815794995200 * evalpoly(p2, (2757049477875, -127577298354750, 1050760774457901, -3369032068261860,5104696716244125, -3685299006138750, 1023694168371875))
47+
u7 = 1 / 115579079884800 * evalpoly(p2, (199689155040375, -12493049053044375, 138799253740521843, -613221795981706275, 1347119637570231525, -1570320948552481125, 931766432052080625, -221849150488590625))
48+
u8 = 1 / 22191183337881600 * evalpoly(p2, (134790179652253125, -10960565081605263000, 157768535329832893644, -914113758588905038248, 2711772922412520971550, -4513690624987320777000, 4272845805510421639500, -2152114239059719935000, 448357133137441653125))
49+
u9 = 1 / 263631258054033408000 * evalpoly(p2, (6427469716717690265625, -659033454841709672064375, 11921080954211358275362500, -87432034049652400520788332, 334380732677827878090447630, -741743213039573443221773250, 992115946599792610768672500, -790370708270219620781737500, 345821892003106984030190625, -64041091111686478524109375))
50+
u10 = 1 / 88580102706155225088000 * evalpoly(p2, (9745329584487361980740625, -1230031256571145165088463750, 27299183373230345667273718125, -246750339886026017414509498824, 1177120360439828012193658602930, -3327704366990695147540934069220, 5876803711285273203043452095250, -6564241639632418015173104205000, 4513386761946134740461797128125, -1745632061522350031610173343750, 290938676920391671935028890625))
51+
return evalpoly(-p/v, (u0, u1, u2, u3, u4, u5, u6, u7, u8, u9, u10))
52+
end
53+
54+
55+
u0 = one(x)
56+
u1 = p / 24 * (3 - 5*p^2) * -1 / v
57+
u2 = p^2 / 1152 * (81 - 462*p^2 + 385*p^4) / v^2
58+
u3 = p^3 / 414720 * (30375 - 369603 * p^2 + 765765*p^4 - 425425*p^6) * -1 / v^3
59+
u4 = p^4 / 39813120 * (4465125 - 94121676*p^2 + 349922430*p^4 - 446185740*p^6 + 185910725*p^8) / v^4
60+
u5 = p^5 / 6688604160 * (-188699385875*p^10 + 566098157625*p^8 - 614135872350*p^6 + 284499769554*p^4 - 49286948607*p^2 + 1519035525) * -1 / v^5
61+
u6 = p^6 / 4815794995200 * (1023694168371875*p^12 - 3685299006138750*p^10 + 5104696716244125*p^8 - 3369032068261860*p^6 + 1050760774457901*p^4 - 127577298354750*p^2 + 2757049477875) * 1 / v^6
62+
u7 = p^7 / 115579079884800 * (-221849150488590625*p^14 + 931766432052080625*p^12 - 1570320948552481125*p^10 + 1347119637570231525*p^8 - 613221795981706275*p^6 + 138799253740521843*p^4 - 12493049053044375*p^2 + 199689155040375) * -1 / v^7
63+
u8 = p^8 / 22191183337881600 * (448357133137441653125*p^16 - 2152114239059719935000*p^14 + 4272845805510421639500*p^12 - 4513690624987320777000*p^10 + 2711772922412520971550*p^8 - 914113758588905038248*p^6 + 157768535329832893644*p^4 - 10960565081605263000*p^2 + 134790179652253125) * 1 / v^8
64+
u9 = p^9 / 263631258054033408000 * (-64041091111686478524109375*p^18 + 345821892003106984030190625*p^16 - 790370708270219620781737500*p^14 + 992115946599792610768672500*p^12 - 741743213039573443221773250*p^10 + 334380732677827878090447630*p^8 - 87432034049652400520788332*p^6 + 11921080954211358275362500*p^4 - 659033454841709672064375*p^2 + 6427469716717690265625) * -1 / v^9
65+
u10 = p^10 / 88580102706155225088000 * (290938676920391671935028890625*p^20 - 1745632061522350031610173343750*p^18 + 4513386761946134740461797128125*p^16 - 6564241639632418015173104205000*p^14 + 5876803711285273203043452095250*p^12 - 3327704366990695147540934069220*p^10 + 1177120360439828012193658602930*p^8 - 246750339886026017414509498824*p^6 + 27299183373230345667273718125*p^4 - 1230031256571145165088463750*p^2 + 9745329584487361980740625) * 1 / v^10
66+
u11 = p^11 / 27636992044320430227456000 * (-1363312191078326248171914924296875*p^22 + 8997860461116953237934638500359375*p^20 - 25963913760458280822131901737878125*p^18 + 42936745153513007436411401865860625*p^16 - 44801790321820682384740638703320750*p^14 + 30589806122850866110941936529264950*p^12 - 13704902022868787041097596217578170*p^10
67+
+ 3926191452593448964331218647028194*p^8 - 676389476843440422173605288596087*p^6 + 62011003282542082472252466220875*p^4 - 2321657500166464779660536015625*p^2 + 15237265774872558064250728125) * -1 / v^11
68+
u12 = p^12 / 39797268543821419527536640000 * (32426380464797989812768996474401171875*p^24 - 233469939346545526651936774615688437500*p^22 + 743739612850105971846901081692858843750*p^20 - 1378260730939829908037976894025628887500*p^18 + 1642838631056253395899341314188134178125*p^16 - 1314368459332124683504418467809129387000*p^14
69+
+ 714528665351965363868467348116538170900*p^12 - 261201165596865827608687437905740780920*p^10 + 62055079517573388459132793029571876461*p^8 - 8958590476947726766450604043798559500*p^6 + 692277766674325563109617997687563750*p^4 - 21882222767154197351962677311437500*p^2 + 120907703923613748239829527671875) * 1 / v^12
70+
u13 = p^13 / 955134445051714068660879360000 * (-14020668045586884672121117629431460546875*p^26 + 109361210755577700442544717509565392265625*p^24 - 381190503845282445953419057314665534156250*p^22 + 782463969315283937856703223178540650343750*p^20
71+
- 1049095945162229046324321461816274931715625*p^18 + 962926533925253374359704288384340809260875*p^16 - 616410216242554698436702353237166008656700*p^14 + 274983827478138958623041508409195988431140*p^12 - 83924867223075156862785921508524155665245*p^10
72+
+ 16843538631795795357786827345307534156063*p^8 - 2069933923586966756183324291232117362250*p^6 + 136735019134677724428035696765082813750*p^4 - 3698121486504259988094897605296209375*p^2 + 17438611142828905996129258798828125) * -1 / v^13
73+
u14 = p^14 / 45846453362482275295722209280000 * (13133360053559028970728309756597440972265625*p^28 - 110320224449895843354117801955418504167031250*p^26 + 417630985812040040477569028872405152769921875*p^24
74+
- 940627071986145750405920450097257805227812500*p^22 + 1401302601668131482630653233972052729323190625*p^20 - 1451823699927947602004297385351260623500372750*p^18 + 1070439683260179398514645952824098811025619475*p^16
75+
- 564850830044980230366140582063618983657685400*p^14 + 211477117385619365164298957821904115470535555*p^12 - 54857705817658080981995319669299096598482382*p^10 + 9440449669103391509091075981237243128469201*p^8
76+
- 1000503839668383458999731491914516564625300*p^6 + 57170953417612444837142230812990944671875*p^4 - 1338184074771428116079233795614103631250*p^2 + 5448320367052402487647812713291015625) * 1 / v^14
77+
u15 = p^15 / 9820310310243703368343697227776000000 * (- 59115551939078562227317999668652486368337724609375*p^30 + 532039967451707060045861997017872377315039521484375*p^28 - 2173722139119126857509156976742601742357422740234375*p^26
78+
+ 5329871927856528282113994744458999865006055974609375*p^24 - 8735135969643867540297524795790262235822823374296875*p^22 + 10085018700249896522602267572484630409640764997271875*p^20 - 8420533422834140468835467666391400380550043688871875*p^18
79+
+ 5136561256208409671660362298619778869859994724706875*p^16 - 2284251621937242886581917667066122422330060024456125*p^14 + 730367145705123976114617970888707594104468177381925*p^12 - 163359140754958502896104062604202934925448173291477*p^10
80+
+ 24403480234538299231733883413666768614198435948125*p^8 - 2254933495791765108580529087615802250458013685625*p^6 + 112597271053778779753048514469995937998172890625*p^4 - 2303431987527333128955769182299845911305390625*p^2 + 8178936810213560828419581728001773291015625) * -1 / v^15
81+
82+
=#

src/besseli.jl

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# Scaled modified Bessel functions of the first kind of order zero and one
55
# besseli0x, besselix
66
#
7+
# (Scaled) Modified Bessel functions of the first kind of order nu
8+
# besseli, besselix
9+
#
710
# Calculation of besseli0 is done in two branches using polynomial approximations [1]
811
#
912
# Branch 1: x < 7.75
@@ -35,11 +38,18 @@
3538
#
3639
# Horner's scheme is then used to evaluate all polynomials.
3740
# ArbNumerics.jl is used as the reference bessel implementations with 75 digits.
41+
#
42+
# Calculation of besseli and besselkx can be done with downward recursion starting with
43+
# besseli_{nu+1} and besseli_{nu}. Higher orders are determined by a uniform asymptotic
44+
# expansion similar to besselk (see notes there) using Equation 10.41.3 [3].
45+
#
3846
#
3947
# [1] "Rational Approximations for the Modified Bessel Function of the First Kind
4048
# - I0(x) for Computations with Double Precision" by Pavel Holoborodko
4149
# [2] "Rational Approximations for the Modified Bessel Function of the First Kind
42-
# - I1(x) for Computations with Double Precision" by Pavel Holoborodko
50+
# - I1(x) for Computations with Double Precision" by Pavel Holoborodko
51+
# [3] https://dlmf.nist.gov/10.41
52+
4353
"""
4454
besseli0(x::T) where T <: Union{Float32, Float64}
4555
@@ -56,6 +66,7 @@ function besseli0(x::T) where T <: Union{Float32, Float64}
5666
return a * s
5767
end
5868
end
69+
5970
"""
6071
besseli0x(x::T) where T <: Union{Float32, Float64}
6172
@@ -73,6 +84,7 @@ function besseli0x(x::T) where T <: Union{Float32, Float64}
7384
return evalpoly(inv(x), besseli0_large_coefs(T)) / sqrt(x)
7485
end
7586
end
87+
7688
"""
7789
besseli1(x::T) where T <: Union{Float32, Float64}
7890
@@ -94,6 +106,7 @@ function besseli1(x::T) where T <: Union{Float32, Float64}
94106
end
95107
return z
96108
end
109+
97110
"""
98111
besseli1x(x::T) where T <: Union{Float32, Float64}
99112
@@ -116,3 +129,67 @@ function besseli1x(x::T) where T <: Union{Float32, Float64}
116129
end
117130
return z
118131
end
132+
133+
"""
134+
besseli(nu, x::T) where T <: Union{Float32, Float64}
135+
136+
Modified Bessel function of the first kind of order nu, ``I_{nu}(x)``.
137+
Nu must be real.
138+
"""
139+
function besseli(nu, x::T) where T <: Union{Float32, Float64, BigFloat}
140+
nu == 0 && return besseli0(x)
141+
nu == 1 && return besseli1(x)
142+
143+
branch = 30
144+
if nu < branch
145+
inp1 = besseli_large_orders(branch + 1, x)
146+
in = besseli_large_orders(branch, x)
147+
return down_recurrence(x, in, inp1, nu, branch)
148+
else
149+
return besseli_large_orders(nu, x)
150+
end
151+
end
152+
153+
"""
154+
besselix(nu, x::T) where T <: Union{Float32, Float64}
155+
156+
Scaled modified Bessel function of the first kind of order nu, ``I_{nu}(x)*e^{-x}``.
157+
Nu must be real.
158+
"""
159+
function besselix(nu, x::T) where T <: Union{Float32, Float64, BigFloat}
160+
nu == 0 && return besseli0x(x)
161+
nu == 1 && return besseli1x(x)
162+
163+
branch = 30
164+
if nu < branch
165+
inp1 = besseli_large_orders_scaled(branch + 1, x)
166+
in = besseli_large_orders_scaled(branch, x)
167+
return down_recurrence(x, in, inp1, nu, branch)
168+
else
169+
return besseli_large_orders_scaled(nu, x)
170+
end
171+
end
172+
function besseli_large_orders(v, x::T) where T <: Union{Float32, Float64, BigFloat}
173+
S = promote_type(T, Float64)
174+
x = S(x)
175+
z = x / v
176+
zs = hypot(1, z)
177+
n = zs + log(z) - log1p(zs)
178+
coef = SQ1O2PI(S) * sqrt(inv(v)) * exp(v*n) / sqrt(zs)
179+
p = inv(zs)
180+
p2 = v^2/fma(max(v,x), max(v,x), min(v,x)^2)
181+
182+
return T(coef*Uk_poly_In(p, v, p2, T))
183+
end
184+
function besseli_large_orders_scaled(v, x::T) where T <: Union{Float32, Float64, BigFloat}
185+
S = promote_type(T, Float64)
186+
x = S(x)
187+
z = x / v
188+
zs = hypot(1, z)
189+
n = zs + log(z) - log1p(zs)
190+
coef = SQ1O2PI(S) * sqrt(inv(v)) * exp(v*n - x) / sqrt(zs)
191+
p = inv(zs)
192+
p2 = v^2/fma(max(v,x), max(v,x), min(v,x)^2)
193+
194+
return T(coef*Uk_poly_In(p, v, p2, T))
195+
end

src/besselk.jl

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,36 @@
4141
# K_{nu+1} = (2*nu/x)*K_{nu} + K_{nu-1}
4242
#
4343
# When nu is large, a large amount of recurrence is necesary.
44-
# At this point as nu -> Inf it is more efficient to use a uniform expansion.
45-
# The boundary of the expansion depends on the accuracy required.
46-
# For more information see [4]. This approach is not yet implemented, so recurrence
47-
# is used for all values of nu.
48-
#
49-
#
44+
# We consider uniform asymptotic expansion for large orders to more efficiently
45+
# compute besselk(nu, x) when nu is larger than 100 (Let's double check this cutoff)
46+
# The boundary should be carefully determined for accuracy and machine roundoff.
47+
# We use 10.41.4 from the Digital Library of Math Functions [5].
48+
# This is also 9.7.8 in Abramowitz and Stegun [6].
49+
# K_{nu}(nu*z) = sqrt(pi / 2nu) *exp(-nu*n)/(1+z^2)^1/4 * sum((-1^k)U_k(p) /nu^k)) for k=0 -> infty
50+
# The U polynomials are the most tricky. They are listed up to order 4 in Table 9.39
51+
# of [6]. For Float32, >=4 U polynomials are usually necessary. For Float64 values,
52+
# >= 8 orders are needed. However, this largely depends on the cutoff of order you need.
53+
# For moderatelly sized orders (nu=50), might need 11-12 orders to reach good enough accuracy
54+
# in double precision.
55+
#
56+
# However, calculation of these higher order U polynomials are tedious. These have been hand
57+
# calculated and somewhat crosschecked with symbolic math. There could be errors. They are listed
58+
# in src/U_polynomials.jl as a reference as higher orders are impossible to find while being needed for any meaningfully accurate calculation.
59+
# For large orders these formulas will converge much faster than using upward recurrence.
60+
#
61+
#
5062
# [1] "Rational Approximations for the Modified Bessel Function of the Second Kind
5163
# - K0(x) for Computations with Double Precision" by Pavel Holoborodko
5264
# [2] "Rational Approximations for the Modified Bessel Function of the Second Kind
5365
# - K1(x) for Computations with Double Precision" by Pavel Holoborodko
5466
# [3] https://github.com/boostorg/math/tree/develop/include/boost/math/special_functions/detail
55-
# [4] "Computation of Bessel Functions of Complex Argument and Large ORder" by Donald E. Amos
67+
# [4] "Computation of Bessel Functions of Complex Argument and Large Order" by Donald E. Amos
5668
# Sandia National Laboratories
69+
# [5] https://dlmf.nist.gov/10.41
70+
# [6] Abramowitz, Milton, and Irene A. Stegun, eds. Handbook of mathematical functions with formulas, graphs, and mathematical tables.
71+
# Vol. 55. US Government printing office, 1964.
5772
#
73+
5874
"""
5975
besselk0(x::T) where T <: Union{Float32, Float64}
6076
@@ -130,46 +146,61 @@ function besselk1x(x::T) where T <: Union{Float32, Float64}
130146
end
131147
end
132148
#=
133-
Recurrence is used for all values of nu. If besselk0(x) or besselk1(0) is equal to zero
149+
If besselk0(x) or besselk1(0) is equal to zero
134150
this will underflow and always return zero even if besselk(x, nu)
135151
is larger than the smallest representing floating point value.
136152
In other words, for large values of x and small to moderate values of nu,
137153
this routine will underflow to zero.
138154
For small to medium values of x and large values of nu this will overflow and return Inf.
139-
140-
In the future, a more efficient algorithm for large nu should be incorporated.
141155
=#
142156
"""
143157
besselk(x::T) where T <: Union{Float32, Float64}
144158
145159
Modified Bessel function of the second kind of order nu, ``K_{nu}(x)``.
146160
"""
147-
function besselk(nu::Int, x::T) where T <: Union{Float32, Float64}
148-
return three_term_recurrence(x, besselk0(x), besselk1(x), nu)
161+
function besselk(nu, x::T) where T <: Union{Float32, Float64, BigFloat}
162+
T == Float32 ? branch = 20 : branch = 50
163+
if nu < branch
164+
return up_recurrence(x, besselk0(x), besselk1(x), nu)
165+
else
166+
return besselk_large_orders(nu, x)
167+
end
149168
end
169+
150170
"""
151171
besselk(x::T) where T <: Union{Float32, Float64}
152172
153173
Scaled modified Bessel function of the second kind of order nu, ``K_{nu}(x)*e^{x}``.
154174
"""
155175
function besselkx(nu::Int, x::T) where T <: Union{Float32, Float64}
156-
return three_term_recurrence(x, besselk0x(x), besselk1x(x), nu)
176+
T == Float32 ? branch = 20 : branch = 50
177+
if nu < branch
178+
return up_recurrence(x, besselk0x(x), besselk1x(x), nu)
179+
else
180+
return besselk_large_orders_scaled(nu, x)
181+
end
157182
end
183+
function besselk_large_orders(v, x::T) where T <: Union{Float32, Float64, BigFloat}
184+
S = promote_type(T, Float64)
185+
x = S(x)
186+
z = x / v
187+
zs = hypot(1, z)
188+
n = zs + log(z) - log1p(zs)
189+
coef = SQPIO2(S) * sqrt(inv(v)) * exp(-v*n) / sqrt(zs)
190+
p = inv(zs)
191+
p2 = v^2/fma(max(v,x), max(v,x), min(v,x)^2)
158192

159-
@inline function three_term_recurrence(x, k0, k1, nu)
160-
nu == 0 && return k0
161-
nu == 1 && return k1
162-
163-
# this prevents us from looping through large values of nu when the loop will always return zero
164-
(iszero(k0) || iszero(k1)) && return zero(x)
165-
166-
k2 = k0
167-
x2 = 2 / x
168-
for n in 1:nu-1
169-
a = x2 * n
170-
k2 = muladd(a, k1, k0)
171-
k0 = k1
172-
k1 = k2
173-
end
174-
return k2
193+
return T(coef*Uk_poly_Kn(p, v, p2, T))
175194
end
195+
function besselk_large_orders_scaled(v, x::T) where T <: Union{Float32, Float64, BigFloat}
196+
S = promote_type(T, Float64)
197+
x = S(x)
198+
z = x / v
199+
zs = hypot(1, z)
200+
n = zs + log(z) - log1p(zs)
201+
coef = SQPIO2(S) * sqrt(inv(v)) * exp(-v*n + x) / sqrt(zs)
202+
p = inv(zs)
203+
p2 = v^2/fma(max(v,x), max(v,x), min(v,x)^2)
204+
205+
return T(coef*Uk_poly_Kn(p, v, p2, T))
206+
end

src/hankel.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#= Aren't tested yet
12
function besselh(nu::Float64, k::Integer, x::AbstractFloat)
23
if k == 1
34
return complex(besselj(nu, x), bessely(nu, x))
@@ -10,3 +11,4 @@ end
1011
1112
hankelh1(nu, z) = besselh(nu, 1, z)
1213
hankelh2(nu, z) = besselh(nu, 2, z)
14+
=#

0 commit comments

Comments
 (0)