Skip to content

Commit 123e404

Browse files
improve generic capabilities (#26)
* improve generic capabilities - add complex number tests - fix tablature - add kmax parameter to some algorithms - reorganize directory so that gauss.jl only has methods for 2F1 - unify the error checking * use log1p for 1F0 Calling float(z) closes #15.
1 parent 62ca7c6 commit 123e404

File tree

10 files changed

+690
-674
lines changed

10 files changed

+690
-674
lines changed

.codecov.yml

Lines changed: 0 additions & 1 deletion
This file was deleted.

Project.toml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
name = "HypergeometricFunctions"
22
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
3-
version = "0.2.3"
3+
version = "0.3"
44

55
[deps]
66
DualNumbers = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
77
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
88
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
9+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
910

1011
[compat]
11-
DualNumbers = "0.5, 0.6"
12-
IntervalArithmetic = "0.15, 0.16"
12+
DualNumbers = "0.5, 0.6, 0.7"
1313
SpecialFunctions = "0.7, 0.8, 0.9, 0.10"
1414
julia = "1"
15-
16-
[extras]
17-
IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253"
18-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
19-
20-
[targets]
21-
test = ["Test", "IntervalArithmetic"]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
# HypergeometricFunctions.jl
66
A Julia package for calculating hypergeometric functions
77

8-
This package implements some hypergeometric functions. In particular, the Gauss hypergeometric function is available as `_₂F₁(a,b,c,z)`, and also `_₃F₂([a1, a2, a3], [b1,b2], z)` and more general `mFn([a1,…,am], [b1,…,bn], z)`.
8+
This package implements the generalized hypergeometric function `pFq([a1,…,am], [b1,…,bn], z)`. In particular, the Gauss hypergeometric function is available as `_₂F₁(a, b, c, z)`, and also `_₃F₂([a1, a2, a3], [b1, b2], z)`.

src/HypergeometricFunctions.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
"""
22
This module calculates (generalized) hypergeometric functions:
33
4-
mFn(a;b;z) = Σ_{k=0}^∞ (a_1,k) ⋯ (a_m,k) / (b_1,k) ⋯ (b_n,k) zᵏ/k!
4+
pFq(α, β; z) = Σ_{k=0}^∞ (α_1)ₖ ⋯ (α_p)ₖ / (β_1)ₖ ⋯ (β_q)ₖ zᵏ/k!
55
"""
66
module HypergeometricFunctions
77

88
using DualNumbers, LinearAlgebra, SpecialFunctions
99

10-
export _₂F₁, _₃F₂, mFn
10+
export _₂F₁, _₃F₂, pFq
1111

12-
include("gauss.jl")
1312
include("specialfunctions.jl")
13+
include("gauss.jl")
14+
include("generalized.jl")
1415
include("drummond.jl")
1516
include("weniger.jl")
1617

src/drummond.jl

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# using Drummond's sequence transformation
33

44
# ₀F₀(;z)
5-
function drummond0F0(z::T) where T
5+
function drummond0F0(z::T; kmax::Int = 10_000) where T
66
if norm(z) < eps(real(T))
77
return one(T)
88
end
@@ -18,7 +18,7 @@ function drummond0F0(z::T) where T
1818
Dhi, Dlo = ((k+2)*ζ-1)*Dhi + k*ζ*Dlo, Dhi
1919
Thi, Tlo = Nhi/Dhi, Thi
2020
k += 1
21-
while abs(Thi-Tlo) > 10*abs(Thi)*eps(real(T)) && k < 10_000
21+
while k < kmax && errcheck(Tlo, Thi, 10eps(real(T)))
2222
Nhi, Nlo = ((k+2)*ζ-1)*Nhi + k*ζ*Nlo, Nhi
2323
Dhi, Dlo = ((k+2)*ζ-1)*Dhi + k*ζ*Dlo, Dhi
2424
Thi, Tlo = Nhi/Dhi, Thi
@@ -28,9 +28,9 @@ function drummond0F0(z::T) where T
2828
end
2929

3030
# ₁F₀(α;z)
31-
function drummond1F0::T1, z::T2) where {T1, T2}
31+
function drummond1F0::T1, z::T2; kmax::Int = 10_000) where {T1, T2}
3232
T = promote_type(T1, T2)
33-
absα = T(abs(α))
33+
absα = abs(T(α))
3434
if norm(z) < eps(real(T)) || norm(α) < eps(absα)
3535
return one(T)
3636
end
@@ -56,7 +56,7 @@ function drummond1F0(α::T1, z::T2) where {T1, T2}
5656
Nhi /= α+k+1
5757
Dhi /= α+k+1
5858
k += 1
59-
while abs(Thi-Tlo) > 10*abs(Thi)*eps(real(T)) && k < 10_000
59+
while k < kmax && errcheck(Tlo, Thi, 10eps(real(T)))
6060
Nhi, Nlo = ((k+2)*ζ-+2k+1))*Nhi + k*-1)*Nlo, Nhi
6161
Dhi, Dlo = ((k+2)*ζ-+2k+1))*Dhi + k*-1)*Dlo, Dhi
6262
Thi, Tlo = Nhi/Dhi, Thi
@@ -71,7 +71,7 @@ function drummond1F0(α::T1, z::T2) where {T1, T2}
7171
end
7272

7373
# ₀F₁(β;z)
74-
function drummond0F1::T1, z::T2) where {T1, T2}
74+
function drummond0F1::T1, z::T2; kmax::Int = 10_000) where {T1, T2}
7575
T = promote_type(T1, T2)
7676
if norm(z) < eps(real(T))
7777
return one(T)
@@ -91,7 +91,7 @@ function drummond0F1(β::T1, z::T2) where {T1, T2}
9191
Dhi, Dmid, Dlo = ((β+k+1)*(k+2)*ζ-1)*Dhi + k*+2k+2)*ζ*Dmid + k*(k-1)*ζ*Dlo, Dhi, Dmid
9292
Thi, Tmid, Tlo = Nhi/Dhi, Thi, Tmid
9393
k += 1
94-
while abs(Thi-Tmid) > 10*abs(Thi)*eps(real(T)) && abs(Tmid-Tlo) > 10*abs(Tmid)*eps(real(T)) && k < 10_000
94+
while k < kmax && errcheck(Tmid, Thi, 10eps(real(T)))
9595
Nhi, Nmid, Nlo = ((β+k+1)*(k+2)*ζ-1)*Nhi + k*+2k+2)*ζ*Nmid + k*(k-1)*ζ*Nlo, Nhi, Nmid
9696
Dhi, Dmid, Dlo = ((β+k+1)*(k+2)*ζ-1)*Dhi + k*+2k+2)*ζ*Dmid + k*(k-1)*ζ*Dlo, Dhi, Dmid
9797
Thi, Tmid, Tlo = Nhi/Dhi, Thi, Tmid
@@ -101,10 +101,10 @@ function drummond0F1(β::T1, z::T2) where {T1, T2}
101101
end
102102

103103
# ₂F₀(α,β;z)
104-
function drummond2F0::T1, β::T2, z::T3) where {T1, T2, T3}
104+
function drummond2F0::T1, β::T2, z::T3; kmax::Int = 10_000) where {T1, T2, T3}
105105
T = promote_type(T1, T2, T3)
106-
absα = T(abs(α))
107-
absβ = T(abs(β))
106+
absα = abs(T(α))
107+
absβ = abs(T(β))
108108
if norm(z) < eps(real(T)) || norm*β) < eps(absα*absβ)
109109
return one(T)
110110
end
@@ -129,7 +129,7 @@ function drummond2F0(α::T1, β::T2, z::T3) where {T1, T2, T3}
129129
Nhi /=+2)*+2)
130130
Dhi /=+2)*+2)
131131
k = 2
132-
while abs(Thi-Tmid) > 10*abs(Thi)*eps(real(T)) && abs(Tmid-Tlo) > 10*abs(Tmid)*eps(real(T)) && k < 10_000
132+
while k < kmax && errcheck(Tmid, Thi, 10eps(real(T)))
133133
Nhi, Nmid, Nlo = ((k+2)*ζ-+k+1)*+k+1)-k*+β+2k+1))*Nhi - k*+β+3k-ζ)*Nmid - k*(k-1)*Nlo, Nhi, Nmid
134134
Dhi, Dmid, Dlo = ((k+2)*ζ-+k+1)*+k+1)-k*+β+2k+1))*Dhi - k*+β+3k-ζ)*Dmid - k*(k-1)*Dlo, Dhi, Dmid
135135
Thi, Tmid, Tlo = Nhi/Dhi, Thi, Tmid
@@ -144,9 +144,9 @@ function drummond2F0(α::T1, β::T2, z::T3) where {T1, T2, T3}
144144
end
145145

146146
# ₁F₁(α,β;z)
147-
function drummond1F1::T1, β::T2, z::T3) where {T1, T2, T3}
147+
function drummond1F1::T1, β::T2, z::T3; kmax::Int = 10_000) where {T1, T2, T3}
148148
T = promote_type(T1, T2, T3)
149-
absα = T(abs(α))
149+
absα = abs(T(α))
150150
if norm(z) < eps(real(T)) || norm(α) < eps(absα)
151151
return one(T)
152152
end
@@ -180,7 +180,7 @@ function drummond1F1(α::T1, β::T2, z::T3) where {T1, T2, T3}
180180
Nhi /= α+k+1
181181
Dhi /= α+k+1
182182
k += 1
183-
while abs(Thi-Tmid) > 10*abs(Thi)*eps(real(T)) && abs(Tmid-Tlo) > 10*abs(Tmid)*eps(real(T)) && k < 10_000
183+
while k < kmax && errcheck(Tmid, Thi, 10eps(real(T)))
184184
Nhi, Nmid, Nlo = ((β+k+1)*(k+2)*ζ-+2k+1))*Nhi + k*((β+2k+2)*ζ-1)*Nmid + k*(k-1)*ζ*Nlo, Nhi, Nmid
185185
Dhi, Dmid, Dlo = ((β+k+1)*(k+2)*ζ-+2k+1))*Dhi + k*((β+2k+2)*ζ-1)*Dmid + k*(k-1)*ζ*Dlo, Dhi, Dmid
186186
Thi, Tmid, Tlo = Nhi/Dhi, Thi, Tmid
@@ -195,7 +195,7 @@ function drummond1F1(α::T1, β::T2, z::T3) where {T1, T2, T3}
195195
end
196196

197197
# ₀F₂(α,β;z)
198-
function drummond0F2::T1, β::T2, z::T3) where {T1, T2, T3}
198+
function drummond0F2::T1, β::T2, z::T3; kmax::Int = 10_000) where {T1, T2, T3}
199199
T = promote_type(T1, T2, T3)
200200
if norm(z) < eps(real(T)) || norm(α) < eps(real(T)) || norm(β) < eps(real(T))
201201
return one(T)
@@ -221,7 +221,7 @@ function drummond0F2(α::T1, β::T2, z::T3) where {T1, T2, T3}
221221
Dhi, Dmid1, Dmid2, Dlo =*(k+2)*+k+1)*+k+1)-1)*Dhi + ζ*k*((k+1)*+β+2k)++k)*+k)+α+β+3k+2)*Dmid1 + ζ*k*(k-1)*(3k+α+β+1)*Dmid2 + ζ*k*(k-1)*(k-2)*Dlo, Dhi, Dmid1, Dmid2
222222
Thi, Tmid1, Tmid2, Tlo = Nhi/Dhi, Thi, Tmid1, Tmid2
223223
k += 1
224-
while abs(Thi-Tmid1) > 10*abs(Thi)*eps(real(T)) && abs(Tmid1-Tmid2) > 10*abs(Tmid1)*eps(real(T)) && abs(Tmid2-Tlo) > 10*abs(Tmid2)*eps(real(T)) && k < 10_000
224+
while k < kmax && errcheck(Tmid1, Thi, 10eps(real(T)))
225225
Nhi, Nmid1, Nmid2, Nlo =*(k+2)*+k+1)*+k+1)-1)*Nhi + ζ*k*((k+1)*+β+2k)++k)*+k)+α+β+3k+2)*Nmid1 + ζ*k*(k-1)*(3k+α+β+1)*Nmid2 + ζ*k*(k-1)*(k-2)*Nlo, Nhi, Nmid1, Nmid2
226226
Dhi, Dmid1, Dmid2, Dlo =*(k+2)*+k+1)*+k+1)-1)*Dhi + ζ*k*((k+1)*+β+2k)++k)*+k)+α+β+3k+2)*Dmid1 + ζ*k*(k-1)*(3k+α+β+1)*Dmid2 + ζ*k*(k-1)*(k-2)*Dlo, Dhi, Dmid1, Dmid2
227227
Thi, Tmid1, Tmid2, Tlo = Nhi/Dhi, Thi, Tmid1, Tmid2
@@ -231,10 +231,10 @@ function drummond0F2(α::T1, β::T2, z::T3) where {T1, T2, T3}
231231
end
232232

233233
# ₂F₁(α,β,γ;z)
234-
function drummond2F1::T1, β::T2, γ::T3, z::T4) where {T1, T2, T3, T4}
234+
function drummond2F1::T1, β::T2, γ::T3, z::T4; kmax::Int = 10_000) where {T1, T2, T3, T4}
235235
T = promote_type(T1, T2, T3, T4)
236-
absα = T(abs(α))
237-
absβ = T(abs(β))
236+
absα = abs(T(α))
237+
absβ = abs(T(β))
238238
if norm(z) < eps(real(T)) || norm*β) < eps(absα*absβ)
239239
return one(T)
240240
end
@@ -268,7 +268,7 @@ function drummond2F1(α::T1, β::T2, γ::T3, z::T4) where {T1, T2, T3, T4}
268268
Nhi /=+k+1)*+k+1)
269269
Dhi /=+k+1)*+k+1)
270270
k += 1
271-
while abs(Thi-Tmid) > 10*abs(Thi)*eps(real(T)) && abs(Tmid-Tlo) > 10*abs(Tmid)*eps(real(T)) && k < 10_000
271+
while k < kmax && errcheck(Tmid, Thi, 10eps(real(T)))
272272
Nhi, Nmid, Nlo = ((k+2)*+k+1)*ζ-+k+1)*+k+1)-k*+β+2k+1))*Nhi + k*((γ+2k+2)*ζ-+β+3k))*Nmid + k*(k-1)*-1)*Nlo, Nhi, Nmid
273273
Dhi, Dmid, Dlo = ((k+2)*+k+1)*ζ-+k+1)*+k+1)-k*+β+2k+1))*Dhi + k*((γ+2k+2)*ζ-+β+3k))*Dmid + k*(k-1)*-1)*Dlo, Dhi, Dmid
274274
Thi, Tmid, Tlo = Nhi/Dhi, Thi, Tmid
@@ -283,9 +283,9 @@ function drummond2F1(α::T1, β::T2, γ::T3, z::T4) where {T1, T2, T3, T4}
283283
end
284284

285285
# ₘFₙ(α;β;z)
286-
function drummondpFq::AbstractVector{T1}, β::AbstractVector{T2}, z::T3) where {T1, T2, T3}
286+
function pFqdrummond::AbstractVector{T1}, β::AbstractVector{T2}, z::T3; kmax::Int = 10_000) where {T1, T2, T3}
287287
T = promote_type(T1, T2, T3)
288-
absα = T.(abs.(α))
288+
absα = abs.(T.(α))
289289
if norm(z) < eps(real(T)) || norm(prod(α)) < eps(prod(absα))
290290
return one(T)
291291
end
@@ -295,13 +295,15 @@ function drummondpFq(α::AbstractVector{T1}, β::AbstractVector{T2}, z::T3) wher
295295
r = max(p+1, q+2)
296296
C = zeros(T, r)
297297
C[1] = one(T)
298+
= zeros(T, r)
299+
Ĉ[1] = one(T)
298300
P = zeros(T, p+1)
299301
t = one(T)
300302
for j in 1:p
301303
t *= α[j]+1
302304
end
303305
P[1] = t
304-
err = one(T)
306+
err = one(real(T))
305307
for j in 1:p
306308
err *= absα[j]+1
307309
end
@@ -318,33 +320,37 @@ function drummondpFq(α::AbstractVector{T1}, β::AbstractVector{T2}, z::T3) wher
318320
D[r+1] = prod(β)*ζ/prod(α)
319321
R[r+1] = N[r+1]/D[r+1]
320322
k = 0
321-
while (abs(R[r+1]-R[r]) > 10*abs(R[r+1])*eps(real(T)) && k < 10_000) || k < r
323+
while k < r || (k < kmax && errcheck(R[r], R[r+1], 10eps(real(T))))
322324
for j in 1:r
323325
N[j] = N[j+1]
324326
D[j] = D[j+1]
325327
R[j] = R[j+1]
326328
end
327329
t1 = zero(T)
328330
for j in 0:min(k, q+1)
329-
t1 += C[j+1]*Q[j+1]*N[r-j]
331+
t1 += [j+1]*Q[j+1]*N[r-j]
330332
end
331333
if k q+1
332-
t1 += Q[k+1]
334+
if p > q
335+
t1 += Q[k+1]
336+
else
337+
t1 += Q[k+1] / T(factorial(k+1))
338+
end
333339
end
334340
t2 = zero(T)
335-
t2 += P[1]*N[r]
341+
t2 += Ĉ[1]*P[1]*N[r]
336342
for j in 1:min(k, p)
337-
t2 += C[j+1]*P[j+1]*(N[r-j+1]+N[r-j])
343+
t2 += P[j+1]*(C[j+1]*N[r-j+1] + Ĉ[j+1]*N[r-j])
338344
end
339345
N[r+1] = ζ*t1-t2
340346
t1 = zero(T)
341347
for j in 0:min(k, q+1)
342-
t1 += C[j+1]*Q[j+1]*D[r-j]
348+
t1 += [j+1]*Q[j+1]*D[r-j]
343349
end
344350
t2 = zero(T)
345-
t2 += P[1]*D[r]
351+
t2 += Ĉ[1]*P[1]*D[r]
346352
for j in 1:min(k, p)
347-
t2 += C[j+1]*P[j+1]*(D[r-j+1]+D[r-j])
353+
t2 += P[j+1]*(C[j+1]*D[r-j+1] + Ĉ[j+1]*D[r-j])
348354
end
349355
D[r+1] = ζ*t1-t2
350356
R[r+1] = N[r+1]/D[r+1]
@@ -354,14 +360,23 @@ function drummondpFq(α::AbstractVector{T1}, β::AbstractVector{T2}, z::T3) wher
354360
N[r+1] /= P[1]
355361
D[r+1] /= P[1]
356362
k += 1
357-
for j in min(k, max(p, q+1)):-1:1
358-
C[j+1] += C[j]
363+
if p > q
364+
for j in min(k, max(p, q+1)):-1:1
365+
C[j+1] += C[j]
366+
Ĉ[j+1] += Ĉ[j]
367+
end
368+
else
369+
for j in min(k, max(p, q+1)):-1:1
370+
C[j+1] = (C[j+1]*(k+1-j) + C[j])/(k+1)
371+
Ĉ[j+1] = (Ĉ[j+1]*(k-j) + Ĉ[j])/(k+1)
372+
end
373+
Ĉ[1] = Ĉ[1]*k/(k+1)
359374
end
360375
t = one(T)
361376
for j in 1:p
362377
t *= α[j]+k+1
363378
end
364-
err = one(T)
379+
err = one(real(T))
365380
for j in 1:p
366381
err *= absα[j]+k+1
367382
end

0 commit comments

Comments
 (0)