Skip to content

Commit

Permalink
Airy function cleanup (#18050)
Browse files Browse the repository at this point in the history
This rearranges the different airy functions, deprecating `airy`, `airyx` and `airyprime` in favour of the more specific variants (`airyai`, `airyaiprime`, etc.), and clarifies the docs of each remaining function. Fixes #17032.
  • Loading branch information
simonbyrne authored and tkelman committed Dec 29, 2016
1 parent f583495 commit e73c556
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 90 deletions.
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ Deprecated or removed
`maxabs` and `minabs` have similarly been deprecated in favor of `maximum(abs, x)` and `minimum(abs, x)`.
Likewise for the in-place counterparts of these functions ([#19598]).

* `airy`, `airyx` and `airyprime` have been deprecated in favor of more specific
functions (`airyai`, `airybi`, `airyaiprime`, `airybiprimex`, `airyaix`, `airybix`,
`airyaiprimex`, `airybiprimex`) ([#18050]).

Julia v0.5.0 Release Notes
==========================

Expand Down Expand Up @@ -778,6 +782,7 @@ Language tooling improvements
[#17668]: https://github.com/JuliaLang/julia/issues/17668
[#17758]: https://github.com/JuliaLang/julia/issues/17758
[#17785]: https://github.com/JuliaLang/julia/issues/17785
[#18050]: https://github.com/JuliaLang/julia/issues/18050
[#18330]: https://github.com/JuliaLang/julia/issues/18330
[#18339]: https://github.com/JuliaLang/julia/issues/18339
[#18346]: https://github.com/JuliaLang/julia/issues/18346
Expand Down
66 changes: 63 additions & 3 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -879,8 +879,8 @@ for f in (
# base/special/erf.jl
:erfcx, :erfi, :dawson,
# base/special/bessel.jl
:airyprime, :airyai, :airyaiprime, :airybi, :airybiprime,
:airy, :airyx, :besselj0, :besselj1, :bessely0, :bessely1,
:airyai, :airyaiprime, :airybi, :airybiprime,
:besselj0, :besselj1, :bessely0, :bessely1,
# base/math.jl
:cbrt, :sinh, :cosh, :tanh, :atan, :asinh, :exp, :erf, :erfc, :exp2,
:expm1, :exp10, :sin, :cos, :tan, :asin, :acos, :acosh, :atanh,
Expand Down Expand Up @@ -943,7 +943,7 @@ for f in (
# base/special/gamma.jl
:polygamma, :zeta, :beta, :lbeta,
# base/special/bessel.jl
:airy, :airyx, :besseli, :besselix, :besselj, :besseljx,
:besseli, :besselix, :besselj, :besseljx,
:besselk, :besselkx, :bessely, :besselyx, :besselh,
:besselhx, :hankelh1, :hankelh2, :hankelh1x, :hankelh2x,
# base/math.jl
Expand Down Expand Up @@ -1146,6 +1146,66 @@ for (dep, f, op) in [(:sumabs!, :sum!, :abs),
end
end

@deprecate airy(z::Number) airyai(z)
@deprecate airyx(z::Number) airyaix(z)
@deprecate airyprime(z::Number) airyaiprime(z)
@deprecate airy{T<:Number}(x::AbstractArray{T}) airyai.(x)
@deprecate airyx{T<:Number}(x::AbstractArray{T}) airyaix.(x)
@deprecate airyprime{T<:Number}(x::AbstractArray{T}) airyprime.(x)

function _airy(k::Integer, z::Complex128)
depwarn("`airy(k,x)` is deprecated, use `airyai(x)`, `airyaiprime(x)`, `airybi(x)` or `airybiprime(x)` instead.",:airy)
id = Int32(k==1 || k==3)
if k == 0 || k == 1
return _airy(z, id, Int32(1))
elseif k == 2 || k == 3
return _biry(z, id, Int32(1))
else
throw(ArgumentError("k must be between 0 and 3"))
end
end
function _airyx(k::Integer, z::Complex128)
depwarn("`airyx(k,x)` is deprecated, use `airyaix(x)`, `airyaiprimex(x)`, `airybix(x)` or `airybiprimex(x)` instead.",:airyx)
id = Int32(k==1 || k==3)
if k == 0 || k == 1
return _airy(z, id, Int32(2))
elseif k == 2 || k == 3
return _biry(z, id, Int32(2))
else
throw(ArgumentError("k must be between 0 and 3"))
end
end

for afn in (:airy,:airyx)
_afn = Symbol("_"*string(afn))
suf = string(afn)[5:end]
@eval begin
function $afn(k::Integer, z::Complex128)
depwarn("`$afn(k,x)` is deprecated, use `airyai$suf(x)`, `airyaiprime$suf(x)`, `airybi$suf(x)` or `airybiprime$suf(x)` instead.",$(QuoteNode(afn)))
$_afn(k,z)
end

$afn(k::Integer, z::Complex) = $afn(k, float(z))
$afn{T<:AbstractFloat}(k::Integer, z::Complex{T}) = throw(MethodError($afn,(k,z)))
$afn(k::Integer, z::Complex64) = Complex64($afn(k, Complex128(z)))
$afn(k::Integer, x::Real) = $afn(k, float(x))
$afn(k::Integer, x::AbstractFloat) = real($afn(k, complex(x)))

function $afn{T<:Number}(k::Number, x::AbstractArray{T})
depwarn("`$afn(k::Number,x::AbstractArray)` is deprecated, use `airyai$suf.(x)`, `airyaiprime$suf.(x)`, `airybi$suf.(x)` or `airybiprime$suf.(x)` instead.",$(QuoteNode(afn)))
$_afn.(k,x)
end
function $afn{S<:Number}(k::AbstractArray{S}, x::Number)
depwarn("`$afn(k::AbstractArray,x::AbstractArray)` is deprecated, use `airyai$suf.(x)`, `airyaiprime$suf.(x)`, `airybi$suf.(x)` or `airybiprime$suf.(x)` instead.",$(QuoteNode(afn)))
$_afn.(k,x)
end
function $afn{S<:Number,T<:Number}(k::AbstractArray{S}, x::AbstractArray{T})
depwarn("`$afn(k::AbstractArray,x::AbstractArray)` is deprecated, use `airyai$suf.(x)`, `airyaiprime$suf.(x)`, `airybi$suf.(x)` or `airybiprime$suf.(x)` instead.",$(QuoteNode(afn)))
$_afn.(k,x)
end
end
end

# Deprecate vectorized xor in favor of compact broadcast syntax
@deprecate xor(a::Bool, B::BitArray) xor.(a, B)
@deprecate xor(A::BitArray, b::Bool) xor.(A, b)
Expand Down
7 changes: 4 additions & 3 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -430,13 +430,14 @@ export
,

# specfun
airy,
airyai,
airyaiprime,
airybi,
airybiprime,
airyprime,
airyx,
airyaix,
airyaiprimex,
airybix,
airybiprimex,
besselh,
besselhx,
besseli,
Expand Down
3 changes: 2 additions & 1 deletion base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export sin, cos, tan, sinh, cosh, tanh, asin, acos, atan,
significand,
lgamma, hypot, gamma, lfact, max, min, minmax, ldexp, frexp,
clamp, clamp!, modf, ^, mod2pi,
airy, airyai, airyprime, airyaiprime, airybi, airybiprime, airyx,
airyai, airyaiprime, airybi, airybiprime,
airyaix, airyaiprimex, airybix, airybiprimex,
besselj0, besselj1, besselj, besseljx,
bessely0, bessely1, bessely, besselyx,
hankelh1, hankelh2, hankelh1x, hankelh2x,
Expand Down
1 change: 0 additions & 1 deletion base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,6 @@ function airyai(x::BigFloat)
ccall((:mpfr_ai, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Int32), &z, &x, ROUNDING_MODE[])
return z
end
airy(x::BigFloat) = airyai(x)

function ldexp(x::BigFloat, n::Clong)
z = BigFloat()
Expand Down
104 changes: 50 additions & 54 deletions base/special/bessel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ type AmosException <: Exception
end

## Airy functions

let
const ai::Array{Float64,1} = Array{Float64}(2)
const ae::Array{Int32,1} = Array{Int32}(2)
Expand Down Expand Up @@ -40,88 +39,85 @@ let
end
end

"""
airy(k,x)

The `k`th derivative of the Airy function ``\\operatorname{Ai}(x)``.
"""
function airy(k::Integer, z::Complex128)
id = Int32(k==1 || k==3)
if k == 0 || k == 1
return _airy(z, id, Int32(1))
elseif k == 2 || k == 3
return _biry(z, id, Int32(1))
else
throw(ArgumentError("k must be between 0 and 3"))
end
end
airyai(x)
Airy function of the first kind ``\\operatorname{Ai}(x)``.
"""
airyprime(x)
function airyai end
airyai(z::Complex128) = _airy(z, Int32(0), Int32(1))

Airy function derivative ``\\operatorname{Ai}'(x)``.
"""
airyprime(z) = airy(1,z)
airyaiprime(x)
Derivative of the Airy function of the first kind ``\\operatorname{Ai}'(x)``.
"""
airyai(x)
function airyaiprime end
airyaiprime(z::Complex128) = _airy(z, Int32(1), Int32(1))

Airy function ``\\operatorname{Ai}(x)``.
"""
airyai(z) = airy(0,z)
airybi(x)
Airy function of the second kind ``\\operatorname{Bi}(x)``.
"""
airyaiprime(x)
function airybi end
airybi(z::Complex128) = _biry(z, Int32(0), Int32(1))

Airy function derivative ``\\operatorname{Ai}'(x)``.
"""
airyaiprime(z) = airy(1,z)
airybiprime(x)
Derivative of the Airy function of the second kind ``\\operatorname{Bi}'(x)``.
"""
airybi(x)
function airybiprime end
airybiprime(z::Complex128) = _biry(z, Int32(1), Int32(1))

Airy function ``\\operatorname{Bi}(x)``.
"""
airybi(z) = airy(2,z)
airyaix(x)
Scaled Airy function of the first kind ``\\operatorname{Ai}(x) e^{\\frac{2}{3} x \\sqrt{x}}``.
"""
airybiprime(x)
function airyaix end
airyaix(z::Complex128) = _airy(z, Int32(0), Int32(2))

Airy function derivative ``\\operatorname{Bi}'(x)``.
"""
airybiprime(z) = airy(3,z)
airyaiprimex(x)
function airyx(k::Integer, z::Complex128)
id = Int32(k==1 || k==3)
if k == 0 || k == 1
return _airy(z, id, Int32(2))
elseif k == 2 || k == 3
return _biry(z, id, Int32(2))
else
throw(ArgumentError("k must be between 0 and 3"))
end
end
Scaled derivative of the Airy function of the first kind ``\\operatorname{Ai}'(x) e^{\\frac{2}{3} x \\sqrt{x}}``.
"""
function airyaiprimex end
airyaiprimex(z::Complex128) = _airy(z, Int32(1), Int32(2))

for afn in (:airy,:airyx)
@eval begin
$afn(k::Integer, z::Complex) = $afn(k, float(z))
$afn{T<:AbstractFloat}(k::Integer, z::Complex{T}) = throw(MethodError($afn,(k,z)))
$afn(k::Integer, z::Complex64) = Complex64($afn(k, Complex128(z)))
"""
airybix(x)
$afn(k::Integer, x::Real) = $afn(k, float(x))
$afn(k::Integer, x::AbstractFloat) = real($afn(k, complex(x)))
Scaled Airy function of the second kind ``\\operatorname{Bi}(x) e^{- \\left| \\operatorname{Re} \\left( \\frac{2}{3} x \\sqrt{x} \\right) \\right|}``.
"""
function airybix end
airybix(z::Complex128) = _biry(z, Int32(0), Int32(2))

$afn(z) = $afn(0,z)
end
end
"""
airyx(k,x)
airybiprimex(x)
scaled `k`th derivative of the Airy function, return ``\\operatorname{Ai}(x) e^{\\frac{2}{3} x \\sqrt{x}}``
for `k == 0 || k == 1`, and ``\\operatorname{Ai}(x) e^{- \\left| \\operatorname{Re} \\left( \\frac{2}{3} x \\sqrt{x} \\right) \\right|}``
for `k == 2 || k == 3`.
Scaled derivative of the Airy function of the second kind ``\\operatorname{Bi}'(x) e^{- \\left| \\operatorname{Re} \\left( \\frac{2}{3} x \\sqrt{x} \\right) \\right|}``.
"""
function airyx(k,x) end
function airybiprimex end
airybiprimex(z::Complex128) = _biry(z, Int32(1), Int32(2))

for afn in (:airyai, :airyaiprime, :airybi, :airybiprime,
:airyaix, :airyaiprimex, :airybix, :airybiprimex)
@eval begin
$afn(z::Complex) = $afn(float(z))
$afn{T<:AbstractFloat}(z::Complex{T}) = throw(MethodError($afn,(z,)))
$afn(z::Complex64) = Complex64($afn(Complex128(z)))
end
if afn in (:airyaix, :airyaiprimex)
@eval $afn(x::Real) = x < 0 ? throw(DomainError()) : real($afn(complex(float(x))))
else
@eval $afn(x::Real) = real($afn(complex(float(x))))
end

end

## Bessel functions

Expand Down
10 changes: 5 additions & 5 deletions doc/src/manual/mathematical-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,11 @@ asind acosd atand acotd asecd acscd
| [`lbeta(x,y)`](@ref) | accurate `log(beta(x,y))` for large `x` or `y` |
| [`eta(x)`](@ref) | [Dirichlet eta function](https://en.wikipedia.org/wiki/Dirichlet_eta_function) at `x` |
| [`zeta(x)`](@ref) | [Riemann zeta function](https://en.wikipedia.org/wiki/Riemann_zeta_function) at `x` |
| [`airy(z)`](@ref), [`airyai(z)`](@ref), `airy(0,z)` | [Airy Ai function](https://en.wikipedia.org/wiki/Airy_function) at `z` |
| [`airyprime(z)`](@ref), [`airyaiprime(z)`](@ref), `airy(1,z)` | derivative of the Airy Ai function at `z` |
| [`airybi(z)`](@ref), `airy(2,z)` | [Airy Bi function](https://en.wikipedia.org/wiki/Airy_function) at `z` |
| [`airybiprime(z)`](@ref), `airy(3,z)` | derivative of the Airy Bi function at `z` |
| [`airyx(z)`](@ref), `airyx(k,z)` | scaled Airy AI function and `k` th derivatives at `z` |
| [`airyai(z)`](@ref) | [Airy Ai function](https://en.wikipedia.org/wiki/Airy_function) at `z` |
| [`airyaiprime(z)`](@ref) | derivative of the Airy Ai function at `z` |
| [`airybi(z)`](@ref) | [Airy Bi function](https://en.wikipedia.org/wiki/Airy_function) at `z` |
| [`airybiprime(z)`](@ref) | derivative of the Airy Bi function at `z` |
| [`airyaix(z)`](@ref), [`airyaiprimex(z)`](@ref), [`airybix(z)`](@ref), [`airybiprimex(z)`](@ref) | scaled Airy AI function and `k` th derivatives at `z` |
| [`besselj(nu,z)`](@ref) | [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind of order `nu` at `z` |
| [`besselj0(z)`](@ref) | `besselj(0,z)` |
| [`besselj1(z)`](@ref) | `besselj(1,z)` |
Expand Down
7 changes: 4 additions & 3 deletions doc/src/stdlib/math.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,14 @@ Base.Math.digamma
Base.Math.invdigamma
Base.Math.trigamma
Base.Math.polygamma
Base.Math.airy
Base.Math.airyai
Base.Math.airyprime
Base.Math.airyaiprime
Base.Math.airyaix
Base.Math.airyaiprimex
Base.Math.airybi
Base.Math.airybiprime
Base.Math.airyx
Base.Math.airybix
Base.Math.airybiprimex
Base.Math.besselj0
Base.Math.besselj1
Base.Math.besselj
Expand Down
53 changes: 33 additions & 20 deletions test/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -394,26 +394,39 @@ end
end

@testset "airy" begin
@test airy(1.8) airyai(1.8)
@test airyprime(1.8) -0.0685247801186109345638
@test airyaiprime(1.8) airyprime(1.8)
@test airybi(1.8) 2.595869356743906290060
@test airybiprime(1.8) 2.98554005084659907283
@test_throws Base.Math.AmosException airy(200im)
@test_throws Base.Math.AmosException airyai(200im)
@test_throws Base.Math.AmosException airybi(200)
@test_throws ArgumentError airy(5,one(Complex128))
z = 1.8 + 1.0im
for elty in [Complex64,Complex128]
@test airy(convert(elty,1.8)) 0.0470362168668458052247
z = convert(elty,z)
@test airyx(z) airyx(0,z)
@test airyx(0, z) airy(0, z) * exp(2/3 * z * sqrt(z))
@test airyx(1, z) airy(1, z) * exp(2/3 * z * sqrt(z))
@test airyx(2, z) airy(2, z) * exp(-abs(real(2/3 * z * sqrt(z))))
@test airyx(3, z) airy(3, z) * exp(-abs(real(2/3 * z * sqrt(z))))
@test_throws ArgumentError airyx(5,z)
end
@test_throws MethodError airy(complex(big(1.0)))

for T in [Float32, Float64, Complex64,Complex128]
@test airyai(T(1.8)) 0.0470362168668458052247
@test airyaiprime(T(1.8)) -0.0685247801186109345638
@test airybi(T(1.8)) 2.595869356743906290060
@test airybiprime(T(1.8)) 2.98554005084659907283
end
for T in [Complex64, Complex128]
z = convert(T,1.8 + 1.0im)
@test airyaix(z) airyai(z) * exp(2/3 * z * sqrt(z))
@test airyaiprimex(z) airyaiprime(z) * exp(2/3 * z * sqrt(z))
@test airybix(z) airybi(z) * exp(-abs(real(2/3 * z * sqrt(z))))
@test airybiprimex(z) airybiprime(z) * exp(-abs(real(2/3 * z * sqrt(z))))
end
@test_throws MethodError airyai(complex(big(1.0)))

for x = -3:3
@test airyai(x) airyai(complex(x))
@test airyaiprime(x) airyaiprime(complex(x))
@test airybi(x) airybi(complex(x))
@test airybiprime(x) airybiprime(complex(x))
if x >= 0
@test airyaix(x) airyaix(complex(x))
@test airyaiprimex(x) airyaiprimex(complex(x))
else
@test_throws DomainError airyaix(x)
@test_throws DomainError airyaiprimex(x)
end
@test airybix(x) airybix(complex(x))
@test airybiprimex(x) airybiprimex(complex(x))
end
end

@testset "bessel functions" begin
Expand Down Expand Up @@ -926,7 +939,7 @@ end
@testset "vectorization of 2-arg functions" begin
binary_math_functions = [
copysign, flipsign, log, atan2, hypot, max, min,
airy, airyx, besselh, hankelh1, hankelh2, hankelh1x, hankelh2x,
besselh, hankelh1, hankelh2, hankelh1x, hankelh2x,
besseli, besselix, besselj, besseljx, besselk, besselkx, bessely, besselyx,
polygamma, zeta, beta, lbeta,
]
Expand Down

0 comments on commit e73c556

Please sign in to comment.