Skip to content

Commit f74518b

Browse files
authored
Merge pull request #120 from JuliaMath/os/stabilize-Float32-functions
make float32 bessels type stable
2 parents c6e3777 + 86099dd commit f74518b

File tree

5 files changed

+46
-38
lines changed

5 files changed

+46
-38
lines changed

src/BesselFunctions/U_polynomials.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function besseljy_debye(v, x::T) where T
4040
p2 = v^2 / vmx
4141

4242
Uk_Jn, Uk_Yn = Uk_poly_Jn(p, v, p2, T(x))
43-
return coef_Jn * Uk_Jn, coef_Yn * Uk_Yn
43+
return T(coef_Jn * Uk_Jn), T(coef_Yn * Uk_Yn)
4444
end
4545

4646
# Cutoffs for besseljy_debye expansions
@@ -102,7 +102,7 @@ function hankel_debye(v, x::T) where T
102102
p2 = v^2 / vmx
103103

104104
_, Uk_Yn = Uk_poly_Hankel(p*im, v, -p2, T(x))
105-
return coef_Yn * Uk_Yn
105+
return T(coef_Yn * Uk_Yn)
106106
end
107107

108108
# Cutoffs for hankel_debye expansions

src/BesselFunctions/asymptotics.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function besseljy_large_argument(v, x::T) where T
5151
s3 = CMS *
5252
s4 = CPS *
5353

54-
return SQ2O2(S) * (s1 + s2) * b, SQ2O2(S) * (s3 - s4) * b
54+
return T(SQ2O2(S) * (s1 + s2) * b), T(SQ2O2(S) * (s3 - s4) * b)
5555
end
5656

5757
# Float64
@@ -101,11 +101,11 @@ end
101101
function _α_αp_asymptotic(v, x::Float32)
102102
v, x = Float64(v), Float64(x)
103103
if x > 4*v
104-
return _α_αp_poly_5(v, x)
104+
return Float32.(_α_αp_poly_5(v, x))
105105
elseif x > 1.8*v
106-
return _α_αp_poly_10(v, x)
106+
return Float32.(_α_αp_poly_10(v, x))
107107
else
108-
return _α_αp_poly_30(v, x)
108+
return Float32.(_α_αp_poly_30(v, x))
109109
end
110110
end
111111

src/BesselFunctions/bessely.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ function bessely_power_series(v, x::T) where T
420420
out2 = zero(S)
421421
a = (x/2)^v
422422
# check for underflow and return limit for small arguments
423-
iszero(a) && return (-T(Inf), a)
423+
iszero(a) && return (-T(Inf), T(a))
424424

425425
b = inv(a)
426426
a /= gamma(v + one(S))
@@ -434,7 +434,7 @@ function bessely_power_series(v, x::T) where T
434434
b *= -inv((-v + i + one(S)) * (i + one(S))) * t2
435435
end
436436
s, c = sincospi(v)
437-
return (out*c - out2) / s, out
437+
return T((out*c - out2) / s), T(out)
438438
end
439439
bessely_series_cutoff(v, x::Float64) = (x < 7.0) || v > 1.35*x - 4.5
440440
bessely_series_cutoff(v, x::Float32) = (x < 21.0f0) || v > 1.38f0*x - 12.5f0
@@ -484,7 +484,7 @@ function bessely_chebyshev_low_orders(v, x)
484484
x1 = 2*(x - 6)/13 - 1
485485
v1 = v - 1
486486
v2 = v
487-
a = clenshaw_chebyshev.(x1, bessely_cheb_weights)
487+
a = clenshaw_chebyshev.(x1, map(Base.Fix1(map, typeof(x1)),bessely_cheb_weights))
488488
return clenshaw_chebyshev(v1, a), clenshaw_chebyshev(v2, a)
489489
end
490490

src/BesselFunctions/hankel.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ function besseljy_positive_args(nu::Real, x::T) where T
133133

134134
# at this point x > 19.0 (for Float64) and fairly close to nu
135135
# shift nu down and use the debye expansion for Hankel function (valid x > nu) then use forward recurrence
136-
nu_shift = ceil(nu) - floor(Int, -1.5 + x + Base.Math._approx_cbrt(-411*x)) + 2
136+
nu_shift = ceil(nu) - floor(Int, -3//2 + x + Base.Math._approx_cbrt(-411*x)) + 2
137137
v2 = maximum((nu - nu_shift, modf(nu)[1] + 1))
138138

139139
Hnu = hankel_debye(v2, x)

test/hankel_test.jl

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,43 @@
33
# here we will test just a few cases of the overall hankel function
44
# focusing on negative arguments and reflection
55

6-
v, x = 1.5, 1.3
7-
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x), rtol=2e-13)
8-
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x), rtol=2e-13)
9-
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x), rtol=2e-13)
10-
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x), rtol=2e-13)
6+
@testset "$T" for T in (Float32, Float64)
7+
rtol = T == Float64 ? 2e-13 : 2e-6
8+
v, x = T(1.5), T(1.3)
9+
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x); rtol)
10+
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x); rtol)
11+
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x); rtol)
12+
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x); rtol)
13+
@inferred besselh(v, 2, x)
14+
15+
v, x = T(-2.6), T(9.2)
16+
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x); rtol)
17+
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x); rtol)
18+
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x); rtol)
19+
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x); rtol)
20+
@inferred besselh(v, 2, x)
1121

12-
v, x = -2.6, 9.2
13-
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x), rtol=2e-13)
14-
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x), rtol=2e-13)
15-
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x), rtol=2e-13)
16-
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x), rtol=2e-13)
22+
v, x = T(-4.0), T(11.4)
23+
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x); rtol)
24+
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x); rtol)
25+
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x); rtol)
26+
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x); rtol)
27+
@inferred besselh(v, 2, x)
1728

18-
v, x = -4.0, 11.4
19-
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x), rtol=2e-13)
20-
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x), rtol=2e-13)
21-
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x), rtol=2e-13)
22-
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x), rtol=2e-13)
29+
v, x = T(14.3), T(29.4)
30+
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x); rtol)
31+
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x); rtol)
32+
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x); rtol)
33+
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x); rtol)
34+
@inferred besselh(v, 2, x)
2335

24-
v, x = 14.3, 29.4
25-
@test isapprox(hankelh1(v, x), SpecialFunctions.hankelh1(v, x), rtol=2e-13)
26-
@test isapprox(hankelh2(v, x), SpecialFunctions.hankelh2(v, x), rtol=2e-13)
27-
@test isapprox(besselh(v, 1, x), SpecialFunctions.besselh(v, 1, x), rtol=2e-13)
28-
@test isapprox(besselh(v, 2, x), SpecialFunctions.besselh(v, 2, x), rtol=2e-13)
36+
@test isapprox(hankelh1(1:50, T(10)), SpecialFunctions.hankelh1.(1:50, 10.0); rtol)
37+
@test isapprox(hankelh1(T(0.5):T(25.5), T(15)), SpecialFunctions.hankelh1.(0.5:1:25.5, 15.0); rtol)
38+
@test isapprox(hankelh1(1:50, T(100)), SpecialFunctions.hankelh1.(1:50, 100.0); 2*rtol)
39+
@test isapprox(hankelh2(1:50, T(10)), SpecialFunctions.hankelh2.(1:50, 10.0); rtol)
40+
@inferred hankelh2(1:50, T(10))
2941

30-
@test isapprox(hankelh1(1:50, 10.0), SpecialFunctions.hankelh1.(1:50, 10.0), rtol=2e-13)
31-
@test isapprox(hankelh1(0.5:1:25.5, 15.0), SpecialFunctions.hankelh1.(0.5:1:25.5, 15.0), rtol=2e-13)
32-
@test isapprox(hankelh1(1:50, 100.0), SpecialFunctions.hankelh1.(1:50, 100.0), rtol=2e-13)
33-
@test isapprox(hankelh2(1:50, 10.0), SpecialFunctions.hankelh2.(1:50, 10.0), rtol=2e-13)
34-
35-
#test 2 arg version
36-
@test besselh(v, 1, x) == besselh(v, x)
37-
@test besselh(1:50, 1, 10.0) == besselh(1:50, 10.0)
42+
#test 2 arg version
43+
@test besselh(v, 1, x) == besselh(v, x)
44+
@test besselh(1:50, 1, T(10.0)) == besselh(1:50, T(10.0))
45+
end

0 commit comments

Comments
 (0)