Skip to content

Commit 252f8a3

Browse files
committed
add mysin, mycos
1 parent f3eda54 commit 252f8a3

File tree

4 files changed

+87
-34
lines changed

4 files changed

+87
-34
lines changed

src/Bessels.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ include("Float128/constants.jl")
3636
include("math_constants.jl")
3737
include("U_polynomials.jl")
3838
include("recurrence.jl")
39+
include("misc.jl")
3940
#include("hankel.jl")
4041

4142
end

src/besselj.jl

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
# See [1] for more details and [2] for coefficients of polynomials.
1212
# For tiny arugments the power series expansion is used.
1313
#
14-
# Branch 2: 5.0 < x < 80.0
14+
# Branch 2: 5.0 < x < 75.0
1515
# besselj0 = sqrt(2/(pi*x))*(cos(x - pi/4)*R7(x) - sin(x - pi/4)*R8(x))
1616
# Hankel's asymptotic expansion is used
1717
# where R7 and R8 are rational functions (Pn(x)/Qn(x)) of degree 7 and 8 respectively
1818
# See section 4 of [3] for more details and [1] for coefficients of polynomials
1919
#
20-
# Branch 3: x >= 80.0
20+
# Branch 3: x >= 75.0
2121
# besselj0 = sqrt(2/(pi*x))*beta(x)*(cos(x - pi/4 - alpha(x))
2222
# See modified expansions given in [3]. Exact coefficients are used
2323
#
@@ -28,7 +28,7 @@
2828
# [2] Cephes Math Library Release 2.8: June, 2000 by Stephen L. Moshier
2929
# [3] Harrison, John. "Fast and accurate Bessel function computation."
3030
# 2009 19th IEEE Symposium on Computer Arithmetic. IEEE, 2009.
31-
31+
#
3232
function besselj0(x::T) where T
3333
x = abs(x)
3434
isinf(x) && return zero(x)
@@ -64,12 +64,9 @@ function besselj0(x::T) where T
6464
q = (-1/8, 25/384, -1073/5120, 375733/229376, -55384775/2359296)
6565
xn = muladd(xinv, evalpoly(x2, q), - PIO4(T))
6666

67-
# the following computes b = cos(x + xn)
68-
# but uses cos(x)*cos(xn) - sin(x)*sin(xn)
69-
# to improve accuracy when x >> xn
70-
c1 = sincos(x)
71-
c2 = sincos(xn)
72-
b = c1[2] * c2[2] - c1[1] * c2[1]
67+
# the following computes b = cos(x + xn) more accurately
68+
# see src/misc.jl
69+
b = mycos(x, xn)
7370
return a * b
7471
end
7572
end
@@ -127,12 +124,9 @@ function besselj1(x::Float64)
127124
q = (3/8, -21/128, 1899/5120, -543483/229376, 8027901/262144)
128125
xn = muladd(xinv, evalpoly(x2, q), - 3 * PIO4(T))
129126

130-
# the following computes b = cos(x + xn)
131-
# but uses cos(x)*cos(xn) - sin(x)*sin(xn)
132-
# to improve accuracy when x >> xn
133-
c1 = sincos(x)
134-
c2 = sincos(xn)
135-
b = c1[2] * c2[2] - c1[1] * c2[1]
127+
# the following computes b = cos(x + xn) more accurately
128+
# see src/misc.jl
129+
b = mycos(x, xn)
136130
return a * b
137131
end
138132
end

src/bessely.jl

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
1-
#=
2-
Cephes Math Library Release 2.8: June, 2000
3-
Copyright 1984, 1987, 2000 by Stephen L. Moshier
4-
https://github.com/jeremybarnes/cephes/blob/master/bessel/j0.c
5-
https://github.com/jeremybarnes/cephes/blob/master/bessel/j1.c
6-
=#
1+
# Bessel functions of the second kind of order zero and one
2+
# bessely0, bessely1
3+
#
4+
# Calculation of bessely0 is done in three branches using polynomial approximations
5+
#
6+
# Branch 1: x <= 5.0
7+
# bessely0 = R(x^2) + 2*log(x)*besselj0(x) / pi
8+
# where r1 and r2 are zeros of J0
9+
# and P3 and Q8 are a 3 and 8 degree polynomial respectively
10+
# Polynomial coefficients are from [1] which is based on [2]
11+
# See [1] for more details and [2] for coefficients of polynomials.
12+
# For tiny arugments the power series expansion is used.
13+
#
14+
# Branch 2: 5.0 < x < 75.0
15+
# bessely0 = sqrt(2/(pi*x))*(sin(x - pi/4)*R7(x) - cos(x - pi/4)*R8(x))
16+
# Hankel's asymptotic expansion is used
17+
# where R7 and R8 are rational functions (Pn(x)/Qn(x)) of degree 7 and 8 respectively
18+
# See section 4 of [3] for more details and [1] for coefficients of polynomials
19+
#
20+
# Branch 3: x >= 75.0
21+
# bessely0 = sqrt(2/(pi*x))*beta(x)*(sin(x - pi/4 - alpha(x))
22+
# See modified expansions given in [3]. Exact coefficients are used.
23+
#
24+
# Calculation of bessely1 is done in a similar way as bessely0.
25+
# See [3] for details on similarities.
26+
#
27+
# [1] https://github.com/deepmind/torch-cephes
28+
# [2] Cephes Math Library Release 2.8: June, 2000 by Stephen L. Moshier
29+
# [3] Harrison, John. "Fast and accurate Bessel function computation."
30+
# 2009 19th IEEE Symposium on Computer Arithmetic. IEEE, 2009.
31+
#
732
function bessely0(x::T) where T <: Union{Float32, Float64}
833
if x <= zero(x)
934
if iszero(x)
@@ -43,12 +68,9 @@ function _bessely0_compute(x::Float64)
4368
q = (-1/8, 25/384, -1073/5120, 375733/229376, -55384775/2359296)
4469
xn = muladd(xinv, evalpoly(x2, q), - PIO4(T))
4570

46-
# the following computes b = sin(x + xn)
47-
# but uses cos(x)*sin(xn) + sin(x)*cos(xn)
48-
# to improve accuracy when x >> xn
49-
c1 = sincos(x)
50-
c2 = sincos(xn)
51-
b = c1[2] * c2[1] + c1[1] * c2[2]
71+
# the following computes b = sin(x + xn) more accurately
72+
# see src/misc.jl
73+
b = mysin(x, xn)
5274
return a * b
5375
end
5476
end
@@ -110,12 +132,9 @@ function _bessely1_compute(x::Float64)
110132
q = (3/8, -21/128, 1899/5120, -543483/229376, 8027901/262144)
111133
xn = muladd(xinv, evalpoly(x2, q), - 3 * PIO4(T))
112134

113-
# the following computes b = sin(x + xn)
114-
# but uses cos(x)*sin(xn) + sin(x)*cos(xn)
115-
# to improve accuracy when x >> xn
116-
c1 = sincos(x)
117-
c2 = sincos(xn)
118-
b = c1[2] * c2[1] + c1[1] * c2[2]
135+
# the following computes b = sin(x + xn) more accurately
136+
# see src/misc.jl
137+
b = mysin(x, xn)
119138
return a * b
120139
end
121140
end
@@ -124,7 +143,7 @@ function _bessely1_compute(x::Float32)
124143
T = Float32
125144
if x <= 2.0f0
126145
z = x * x
127-
YO1 = 4.66539330185668857532f0
146+
YO1 = 4.66539330185668857532f0
128147
w = (z - YO1) * x * evalpoly(z, YP32)
129148
w += TWOOPI(Float32) * (besselj1(x) * log(x) - inv(x))
130149
return w

src/misc.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# function to more accurately compute cos(x + xn)
2+
# when x >> xn
3+
# see https://github.com/heltonmc/Bessels.jl/pull/13
4+
# written by @oscardssmith
5+
function mycos(x, xn)
6+
s = x + xn
7+
n, r = Base.Math.rem_pio2_kernel(s)
8+
lo = r.lo - ((s - x) - xn)
9+
hi = r.hi + lo
10+
y = Base.Math.DoubleFloat64(hi, r.hi-hi+lo)
11+
n = n&3
12+
if n == 0
13+
return Base.Math.cos_kernel(y)
14+
elseif n == 1
15+
return -Base.Math.sin_kernel(y)
16+
elseif n == 2
17+
return -Base.Math.cos_kernel(y)
18+
else
19+
return Base.Math.sin_kernel(y)
20+
end
21+
end
22+
# function to more accurately compute sin(x + xn)
23+
function mysin(x, xn)
24+
s = x + xn
25+
n, r = Base.Math.rem_pio2_kernel(s)
26+
lo = r.lo - ((s - x) - xn)
27+
hi = r.hi + lo
28+
y = Base.Math.DoubleFloat64(hi, r.hi-hi+lo)
29+
n = n&3
30+
if n == 0
31+
return Base.Math.sin_kernel(y)
32+
elseif n == 1
33+
return Base.Math.cos_kernel(y)
34+
elseif n == 2
35+
return -Base.Math.sin_kernel(y)
36+
else
37+
return -Base.Math.cos_kernel(y)
38+
end
39+
end

0 commit comments

Comments
 (0)