Skip to content

Commit 48dd874

Browse files
Make _₂F₁ inferred for Float32 inputs by promoting the arguments. (#43)
* Make _₂F₁ inferred for Float32 inputs by promoting the arguments. * Bump the version number * Update test/runtests.jl Co-authored-by: David Widmann <devmotion@users.noreply.github.com> Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
1 parent e1916f4 commit 48dd874

File tree

4 files changed

+70
-17
lines changed

4 files changed

+70
-17
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "HypergeometricFunctions"
22
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
3-
version = "0.3.5"
3+
version = "0.3.6"
44

55
[deps]
66
DualNumbers = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"

src/gauss.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@ function _₂F₁(a, b, c, z)
1414
if isequal(a+b, 0) # 31. 15.4.11 & 15.4.12
1515
return cosnasinsqrt(2b, z)
1616
elseif isequal(a+b, 1) # 32. 15.4.13 & 15.4.14
17-
return cosnasinsqrt(1-2b, z)*exp(-0.5log1p(-z))
17+
return cosnasinsqrt(1-2b, z)*exp(-log1p(-z)/2)
1818
elseif isequal(b-a, 0.5) # 15.4.7 & 15.4.8
1919
return expnlog1pcoshatanhsqrt(-2a, z)
2020
end
2121
elseif isequal(c, 1.5)
2222
if abeqcd(a, b, 0.5) # 13. 15.4.4 & 15.4.5
2323
return sqrtasinsqrt(z)
2424
elseif abeqcd(a, b, 1) # 14.
25-
return sqrtasinsqrt(z)*exp(-0.5log1p(-z))
25+
return sqrtasinsqrt(z)*exp(-log1p(-z)/2)
2626
elseif abeqcd(a, b, 0.5, 1) # 15. 15.4.2 & 15.4.3
2727
return sqrtatanhsqrt(z)
2828
elseif isequal(a+b, 1) # 29. 15.4.15 & 15.4.16
2929
return sinnasinsqrt(1-2b, z)
3030
elseif isequal(a+b, 2) # 30.
31-
return sinnasinsqrt(2-2b, z)*exp(-0.5log1p(-z))
31+
return sinnasinsqrt(2-2b, z)*exp(-log1p(-z)/2)
3232
elseif isequal(b-a, 0.5) # 4. 15.4.9 & 15.4.10
3333
return expnlog1psinhatanhsqrt(1-2a, z)
3434
end

src/specialfunctions.jl

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,8 @@ function G(z::Union{Float64, ComplexF64, Dual128, DualComplex256}, ϵ::Union{Flo
220220
end
221221
end
222222

223-
G(z::Number, ϵ::Number) = ϵ == 0 ? digamma(z)/unsafe_gamma(z) : (inv(unsafe_gamma(z))-inv(unsafe_gamma(z+ϵ)))/ϵ
224-
223+
G(z::T, ϵ::T) where {T<:Number} = ϵ == 0 ? digamma(z)/unsafe_gamma(z) : (inv(unsafe_gamma(z))-inv(unsafe_gamma(z+ϵ)))/ϵ
224+
G(z::Number, ϵ::Number) = G(promote(z, ϵ)...)
225225

226226
"""
227227
Compute the function ((z+ϵ)ₘ-(z)ₘ)/ϵ
@@ -271,9 +271,35 @@ G(z::AbstractVector{BigFloat}, ϵ::BigFloat) = BigFloat[G(zi, ϵ) for zi in z]
271271

272272
# Transformation formula w = 1-z
273273

274-
reconeα₀(a, b, c, m::Int, ϵ) = ϵ == 0 ? (-1)^m*gamma(m)*gamma(c)/(gamma(a+m)*gamma(b+m)) : gamma(c)/*gamma(1-m-ϵ)*gamma(a+m+ϵ)*gamma(b+m+ϵ))
275-
reconeβ₀(a, b, c, w, m::Int, ϵ) = abs(ϵ) > 0.1 ? ( pochhammer(float(a), m)*pochhammer(b, m)/(gamma(1-ϵ)*gamma(a+m+ϵ)*gamma(b+m+ϵ)*gamma(m+1)) - w^ϵ/(gamma(a)*gamma(b)*gamma(m+1+ϵ)) )*gamma(c)*w^m/ϵ : ( (G(1.0, -ϵ)/gamma(m+1)+G(m+1.0, ϵ))/(gamma(a+m+ϵ)*gamma(b+m+ϵ)) - (G(float(a)+m, ϵ)/gamma(b+m+ϵ)+G(float(b)+m, ϵ)/gamma(a+m))/gamma(m+1+ϵ) - E(log(w), ϵ)/(gamma(a+m)*gamma(b+m)*gamma(m+1+ϵ)) )*gamma(c)*pochhammer(float(a), m)*pochhammer(b, m)*w^m
276-
reconeγ₀(a, b, c, w, m::Int, ϵ) = gamma(c)*pochhammer(float(a), m)*pochhammer(b, m)*w^m/(gamma(a+m+ϵ)*gamma(b+m+ϵ)*gamma(m+1)*gamma(1-ϵ))
274+
function reconeα₀(a, b, c, m::Int, ϵ)
275+
_a, _b, _c, _ϵ = promote(a, b, c, ϵ)
276+
return _reconeα₀(_a, _b, _c, m, _ϵ)
277+
end
278+
function _reconeα₀(a::T, b::T, c::T, m::Int, ϵ::T) where {T}
279+
if ϵ == 0
280+
return (-1)^m*gamma(real(T)(m))*gamma(c)/(gamma(a+m)*gamma(b+m))
281+
else
282+
return gamma(c)/*gamma(1-m-ϵ)*gamma(a+m+ϵ)*gamma(b+m+ϵ))
283+
end
284+
end
285+
function reconeβ₀(a, b, c, w, m::Int, ϵ)
286+
_a, _b, _c, _, _ϵ = promote(a, b, c, real(w), ϵ)
287+
_w, _ = promote(w, zero(_a))
288+
return _reconeβ₀(_a, _b, _c, _w, m, _ϵ)
289+
end
290+
function _reconeβ₀(a::T, b::T, c::T, w::Number, m::Int, ϵ::T) where {T}
291+
if abs(ϵ) > 0.1
292+
return ( pochhammer(a, m)*pochhammer(b, m)/(gamma(1-ϵ)*gamma(a+m+ϵ)*gamma(b+m+ϵ)*gamma(real(T)(m)+1)) - w^ϵ/(gamma(a)*gamma(b)*gamma(m+1+ϵ)) )*gamma(c)*w^m/ϵ
293+
else
294+
return ( (G(1, -ϵ)/gamma(real(T)(m)+1)+G(m+1, ϵ))/(gamma(a+m+ϵ)*gamma(b+m+ϵ)) - (G(a+m, ϵ)/gamma(b+m+ϵ)+G(float(b)+m, ϵ)/gamma(a+m))/gamma(m+1+ϵ) - E(log(w), ϵ)/(gamma(a+m)*gamma(b+m)*gamma(m+1+ϵ)) )*gamma(c)*pochhammer(a, m)*pochhammer(b, m)*w^m
295+
end
296+
end
297+
function reconeγ₀(a, b, c, w, m::Int, ϵ)
298+
_a, _b, _c, _, _ϵ = promote(a, b, c, real(w), ϵ)
299+
_w, _ = promote(w, zero(_a))
300+
return _reconeγ₀(_a, _b, _c, _w, m, _ϵ)
301+
end
302+
_reconeγ₀(a::T, b::T, c::T, w::Number, m::Int, ϵ::T) where {T} = gamma(c)*pochhammer(a, m)*pochhammer(b, m)*w^m/(gamma(a+m+ϵ)*gamma(b+m+ϵ)*gamma(real(T)(m)+1)*gamma(1-ϵ))
277303

278304
function Aone(a, b, c, w, m::Int, ϵ)
279305
αₙ = reconeα₀(a, b, c, m, ϵ)*one(w)
@@ -306,14 +332,38 @@ end
306332

307333
# Transformation formula w = 1/z
308334

309-
recInfα₀(a, b, c, m::Int, ϵ) = ϵ == 0 ? (-1)^m*gamma(m)*gamma(c)/(gamma(a+m)*gamma(c-a)) : gamma(c)/*gamma(1-m-ϵ)*gamma(a+m+ϵ)*gamma(c-a))
310-
recInfβ₀(a, b, c, w, m::Int, ϵ) = abs(ϵ) > 0.1 ?
311-
( pochhammer(float(a), m)*pochhammer(float(1-c+a), m)/(gamma(1-ϵ)*gamma(a+m+ϵ)*gamma(c-a)*gamma(m+1)) -
312-
(-w)^ϵ*pochhammer(float(1-c+a)+ϵ, m)/(gamma(a)*gamma(c-a-ϵ)*gamma(m+1+ϵ)) )*gamma(c)*w^m/ϵ :
313-
( (pochhammer(float(1-c+a)+ϵ, m)*G(1.0, -ϵ)-P(1-c+a, ϵ, m)/gamma(1-ϵ))/(gamma(c-a)*gamma(a+m+ϵ)*gamma(m+1)) +
314-
pochhammer(float(1-c+a)+ϵ, m)*( (G(m+1.0, ϵ)/gamma(a+m+ϵ) - G(float(a)+m, ϵ)/gamma(m+1+ϵ))/gamma(c-a) -
315-
(G(float(c-a), -ϵ) - E(-log(-w), -ϵ)/gamma(c-a-ϵ))/(gamma(m+1+ϵ)*gamma(a+m)) ) )*gamma(c)*pochhammer(float(a), m)*w^m
316-
recInfγ₀(a, b, c, w, m::Int, ϵ) = gamma(c)*pochhammer(float(a), m)*pochhammer(float(1-c+a), m)*w^m/(gamma(a+m+ϵ)*gamma(c-a)*gamma(m+1)*gamma(1-ϵ))
335+
function recInfα₀(a, b, c, m::Int, ϵ)
336+
_a, _b, _c, _ϵ = promote(a, b, c, ϵ)
337+
return _recInfα₀(_a, _b, _c, m, _ϵ)
338+
end
339+
function _recInfα₀(a::T, b::T, c::T, m::Int, ϵ::T) where {T}
340+
if ϵ == 0
341+
return (-1)^m*gamma(real(T)(m))*gamma(c)/(gamma(a+m)*gamma(c-a))
342+
else
343+
return gamma(c)/*gamma(1-m-ϵ)*gamma(a+m+ϵ)*gamma(c-a))
344+
end
345+
end
346+
function recInfβ₀(a, b, c, w, m::Int, ϵ)
347+
_a, _b, _c, _, _ϵ = promote(a, b, c, real(w), ϵ)
348+
_w, _ = promote(w, zero(_a))
349+
return _recInfβ₀(_a, _b, _c, _w, m, _ϵ)
350+
end
351+
function _recInfβ₀(a::T, b::T, c::T, w::Number, m::Int, ϵ::T) where {T}
352+
if abs(ϵ) > 0.1
353+
return ( pochhammer(a, m)*pochhammer(1-c+a, m)/(gamma(1-ϵ)*gamma(a+m+ϵ)*gamma(c-a)*gamma(real(T)(m)+1)) -
354+
(-w)^ϵ*pochhammer(1-c+a+ϵ, m)/(gamma(a)*gamma(c-a-ϵ)*gamma(m+1+ϵ)) )*gamma(c)*w^m/ϵ
355+
else
356+
return ( (pochhammer(1-c+a+ϵ, m)*G(1, -ϵ)-P(1-c+a, ϵ, m)/gamma(1-ϵ))/(gamma(c-a)*gamma(a+m+ϵ)*gamma(real(T)(m)+1)) +
357+
pochhammer(1-c+a+ϵ, m)*( (G(m+1, ϵ)/gamma(a+m+ϵ) - G(a+m, ϵ)/gamma(m+1+ϵ))/gamma(c-a) -
358+
(G(c-a, -ϵ) - E(-log(-w), -ϵ)/gamma(c-a-ϵ))/(gamma(m+1+ϵ)*gamma(a+m)) ) )*gamma(c)*pochhammer(a, m)*w^m
359+
end
360+
end
361+
function recInfγ₀(a, b, c, w, m::Int, ϵ)
362+
_a, _b, _c, _, _ϵ = promote(a, b, c, real(w), ϵ)
363+
_w, _ = promote(w, zero(_a))
364+
return _recInfγ₀(_a, _b, _c, _w, m, _ϵ)
365+
end
366+
_recInfγ₀(a::T, b::T, c::T, w::Number, m::Int, ϵ::T) where {T} = gamma(c)*pochhammer(a, m)*pochhammer(1-c+a, m)*w^m/(gamma(a+m+ϵ)*gamma(c-a)*gamma(real(T)(m)+1)*gamma(1-ϵ))
317367

318368
function AInf(a, b, c, w, m::Int, ϵ)
319369
αₙ = recInfα₀(a, b, c, m, ϵ)*one(w)

test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ const NumberType = Float64
3333
j += 1
3434
end
3535
end
36+
@testset "Test that _₂F₁ is inferred for Float32 arguments" begin
37+
@test @inferred(_₂F₁(0.3f0, 0.7f0, 1.3f0, 0.1f0)) Float32(_₂F₁(0.3, 0.7, 1.3, 0.1))
38+
end
3639
end
3740

3841

0 commit comments

Comments
 (0)