Skip to content

Commit 99dd324

Browse files
committed
update structure
1 parent 6a030e3 commit 99dd324

File tree

2 files changed

+59
-19
lines changed

2 files changed

+59
-19
lines changed

src/airy.jl

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
1+
# Airy functions
2+
#
3+
# airyai(x), airybi(nu, x)
4+
# airyaiprime(x), airybiprime(nu, x)
5+
#
6+
# A numerical routine to compute the airy functions and their derivatives.
7+
# These routines use their relations to other special functions using https://dlmf.nist.gov/9.6.
8+
# Specifically see (NIST 9.6.E1 - 9.6.E9) for computation from the defined bessel functions.
9+
# For negative arguments these definitions are prone to some cancellation leading to higher errors.
10+
# In the future, these could be replaced with more custom routines as they depend on a single variable.
11+
#
12+
113
"""
214
airyai(x)
315
Airy function of the first kind ``\\operatorname{Ai}(x)``.
416
"""
5-
function airyai(x::T) where T
17+
airyai(x::Real) = _airyai(float(x))
18+
19+
_airyai(x::Float16) = Float16(_airyai(Float32(x)))
20+
21+
function _airyai(x::T) where T <: Union{Float32, Float64}
22+
isnan(x) && return x
23+
x_abs = abs(x)
24+
z = 2 * x_abs^(T(3)/2) / 3
25+
626
if x > zero(T)
7-
z = 2 * x^(T(3)/2) / 3
827
return sqrt(x / 3) * besselk(one(T)/3, z) / π
928
elseif x < zero(T)
10-
x_abs = abs(x)
11-
z = 2 * x_abs^(T(3)/2) / 3
1229
Jv, Yv = besseljy_positive_args(one(T)/3, z)
1330
Jmv = (Jv - sqrt(T(3)) * Yv) / 2
14-
return sqrt(x_abs) * (Jmv + Jv) / 3
31+
return isinf(z) ? throw(DomainError(x, "airyai(x) is not defined.")) : sqrt(x_abs) * (Jmv + Jv) / 3
1532
elseif iszero(x)
1633
return T(0.3550280538878172)
1734
end
@@ -21,16 +38,21 @@ end
2138
airyaiprime(x)
2239
Derivative of the Airy function of the first kind ``\\operatorname{Ai}'(x)``.
2340
"""
24-
function airyaiprime(x::T) where T
41+
airyaiprime(x::Real) = _airyaiprime(float(x))
42+
43+
_airyaiprime(x::Float16) = Float16(_airyaiprime(Float32(x)))
44+
45+
function _airyaiprime(x::T) where T <: Union{Float32, Float64}
46+
isnan(x) && return x
47+
x_abs = abs(x)
48+
z = 2 * x_abs^(T(3)/2) / 3
49+
2550
if x > zero(T)
26-
z = 2 * x^(T(3)/2) / 3
2751
return -x * besselk(T(2)/3, z) / (sqrt(T(3)) * π)
2852
elseif x < zero(T)
29-
x_abs = abs(x)
30-
z = 2 * x_abs^(T(3)/2) / 3
3153
Jv, Yv = besseljy_positive_args(T(2)/3, z)
3254
Jmv = -(Jv + sqrt(T(3))*Yv) / 2
33-
return x_abs * (Jv - Jmv) / 3
55+
return isinf(z) ? throw(DomainError(x, "airyaiprime(x) is not defined.")) : x_abs * (Jv - Jmv) / 3
3456
elseif iszero(x)
3557
return T(-0.2588194037928068)
3658
end
@@ -40,16 +62,21 @@ end
4062
airybi(x)
4163
Airy function of the second kind ``\\operatorname{Bi}(x)``.
4264
"""
43-
function airybi(x::T) where T
65+
airybi(x::Real) = _airybi(float(x))
66+
67+
_airybi(x::Float16) = Float16(_airybi(Float32(x)))
68+
69+
function _airybi(x::T) where T <: Union{Float32, Float64}
70+
isnan(x) && return x
71+
x_abs = abs(x)
72+
z = 2 * x_abs^(T(3)/2) / 3
73+
4474
if x > zero(T)
45-
z = 2 * x^(T(3)/2) / 3
4675
return sqrt(x / 3) * (besseli(-one(T)/3, z) + besseli(one(T)/3, z))
4776
elseif x < zero(T)
48-
x_abs = abs(x)
49-
z = 2 * x_abs^(T(3)/2) / 3
5077
Jv, Yv = besseljy_positive_args(one(T)/3, z)
5178
Jmv = (Jv - sqrt(T(3)) * Yv) / 2
52-
return sqrt(x_abs/3) * (Jmv - Jv)
79+
return isinf(z) ? throw(DomainError(x, "airybi(x) is not defined.")) : sqrt(x_abs/3) * (Jmv - Jv)
5380
elseif iszero(x)
5481
return T(0.6149266274460007)
5582
end
@@ -60,15 +87,16 @@ end
6087
Derivative of the Airy function of the second kind ``\\operatorname{Bi}'(x)``.
6188
"""
6289
function airybiprime(x::T) where T
90+
isnan(x) && return x
91+
x_abs = abs(x)
92+
z = 2 * x_abs^(T(3)/2) / 3
93+
6394
if x > zero(T)
64-
z = 2 * x^(T(3)/2) / 3
6595
return x * (besseli(T(2)/3, z) + besseli(-T(2)/3, z)) / sqrt(T(3))
6696
elseif x < zero(T)
67-
x_abs = abs(x)
68-
z = 2 * x_abs^(T(3)/2) / 3
6997
Jv, Yv = besseljy_positive_args(T(2)/3, z)
7098
Jmv = -(Jv + sqrt(T(3))*Yv) / 2
71-
return x_abs * (Jv + Jmv) / sqrt(T(3))
99+
return isinf(z) ? throw(DomainError(x, "airybiprime(x) is not defined.")) : x_abs * (Jv + Jmv) / sqrt(T(3))
72100
elseif iszero(x)
73101
return T(0.4482883573538264)
74102
end

test/airy_test.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,15 @@ for x in [0.0; rand(10000)*100]
1515
@test isapprox(airybiprime(x), SpecialFunctions.airybiprime(x), rtol=1e-12)
1616
@test isapprox(airybiprime(-x), SpecialFunctions.airybiprime(-x), rtol=1e-9)
1717
end
18+
19+
# test Inf
20+
@test iszero(airyai(Inf))
21+
@test iszer(airyaiprime(Inf))
22+
@test isinf(airybi(Inf))
23+
@test isinf(airybiprime(Inf))
24+
25+
# test Float16 types
26+
@test airyai(Float16(1.2)) isa Float16
27+
@test airyaiprime(Float16(1.9)) isa Float16
28+
@test airybi(Float16(1.2)) isa Float16
29+
@test airybiprime(Float16(1.9)) isa Float16

0 commit comments

Comments
 (0)