From 66e75608808dce3d042a682dac2cecf3cce8ddaa Mon Sep 17 00:00:00 2001 From: PaulXiCao <> Date: Wed, 13 Jan 2021 21:56:13 +0100 Subject: [PATCH 1/6] function definition --- src/SpecialFunctions.jl | 1 + src/gamma.jl | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/SpecialFunctions.jl b/src/SpecialFunctions.jl index 528d25c5..e57ff7b2 100644 --- a/src/SpecialFunctions.jl +++ b/src/SpecialFunctions.jl @@ -29,6 +29,7 @@ export bessely0, bessely1, besselyx, + binomial, jinc, dawson, ellipk, diff --git a/src/gamma.jl b/src/gamma.jl index a86ea640..d9ea67da 100644 --- a/src/gamma.jl +++ b/src/gamma.jl @@ -926,3 +926,12 @@ function logabsbinomial(n::T, k::T) where {T<:Integer} end end logabsbinomial(n::Integer, k::Integer) = logabsbinomial(promote(n, k)...) + + +# this trickery is needed while the deprecated method in Base exists +@static if !hasmethod(Base.binomial, Tuple{Number, Number}) + import Base: binomial +end +binomial(n, k) = Base.binomial(n, k) # to make SpecialFunctions.binomial work unconditionally + +binomial(x::Number, y::Number) = inv((x+1) * beta(x-y+1, y+1)) From bb0620789e43968c1bd41903c47af6b3668f8493 Mon Sep 17 00:00:00 2001 From: PaulXiCao <> Date: Wed, 13 Jan 2021 21:56:42 +0100 Subject: [PATCH 2/6] WIP documentation --- docs/src/functions_list.md | 1 + docs/src/functions_overview.md | 1 + src/gamma.jl | 10 ++++++++++ 3 files changed, 12 insertions(+) diff --git a/docs/src/functions_list.md b/docs/src/functions_list.md index 56d36c45..08c97269 100644 --- a/docs/src/functions_list.md +++ b/docs/src/functions_list.md @@ -51,6 +51,7 @@ SpecialFunctions.besseli SpecialFunctions.besselix SpecialFunctions.besselk SpecialFunctions.besselkx +SpecialFunctions.binomial SpecialFunctions.jinc SpecialFunctions.ellipk SpecialFunctions.ellipe diff --git a/docs/src/functions_overview.md b/docs/src/functions_overview.md index 7566623f..321b9974 100644 --- a/docs/src/functions_overview.md +++ b/docs/src/functions_overview.md @@ -22,6 +22,7 @@ Here the *Special Functions* are listed according to the structure of [NIST Digi | [`logbeta(x,y)`](@ref SpecialFunctions.logbeta) | accurate `log(beta(x,y))` for large `x` or `y` | | [`logabsbeta(x,y)`](@ref SpecialFunctions.logabsbeta) | accurate `log(abs(beta(x,y)))` for large `x` or `y` | | [`logabsbinomial(x,y)`](@ref SpecialFunctions.logabsbinomial) | accurate `log(abs(binomial(n,k)))` for large `n` and `k` near `n/2` | +| [`binomial(x,y)`](@ref SpecialFunctions.binomial) | generalized binomial coefficient ``{ x \choose y}`` for ``x,y \in \mathbb{C}``| ## [Exponential and Trigonometric Integrals](https://dlmf.nist.gov/6) diff --git a/src/gamma.jl b/src/gamma.jl index d9ea67da..79fe0c53 100644 --- a/src/gamma.jl +++ b/src/gamma.jl @@ -934,4 +934,14 @@ logabsbinomial(n::Integer, k::Integer) = logabsbinomial(promote(n, k)...) end binomial(n, k) = Base.binomial(n, k) # to make SpecialFunctions.binomial work unconditionally +""" + binomial(x, y) + +Generalized binomial coefficient +``{x \\choose y} = \\frac{1}{(x+1) \\Beta(x-y+1,y+1)}``. + +External links: [Wikipedia](https://en.wikipedia.org/wiki/Binomial_coefficient#Two_real_or_complex_valued_arguments) + +See also [`beta(a,b)`](@ref SpecialFunctions.beta). +""" binomial(x::Number, y::Number) = inv((x+1) * beta(x-y+1, y+1)) From c89743a1a827514a5fa92c045c13593369b5f306 Mon Sep 17 00:00:00 2001 From: PaulXiCao <> Date: Fri, 15 Jan 2021 23:56:34 +0100 Subject: [PATCH 3/6] extending Base.binomial --- src/SpecialFunctions.jl | 1 - src/gamma.jl | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/SpecialFunctions.jl b/src/SpecialFunctions.jl index e57ff7b2..528d25c5 100644 --- a/src/SpecialFunctions.jl +++ b/src/SpecialFunctions.jl @@ -29,7 +29,6 @@ export bessely0, bessely1, besselyx, - binomial, jinc, dawson, ellipk, diff --git a/src/gamma.jl b/src/gamma.jl index 79fe0c53..dd89ea0e 100644 --- a/src/gamma.jl +++ b/src/gamma.jl @@ -927,13 +927,6 @@ function logabsbinomial(n::T, k::T) where {T<:Integer} end logabsbinomial(n::Integer, k::Integer) = logabsbinomial(promote(n, k)...) - -# this trickery is needed while the deprecated method in Base exists -@static if !hasmethod(Base.binomial, Tuple{Number, Number}) - import Base: binomial -end -binomial(n, k) = Base.binomial(n, k) # to make SpecialFunctions.binomial work unconditionally - """ binomial(x, y) @@ -944,4 +937,4 @@ External links: [Wikipedia](https://en.wikipedia.org/wiki/Binomial_coefficient#T See also [`beta(a,b)`](@ref SpecialFunctions.beta). """ -binomial(x::Number, y::Number) = inv((x+1) * beta(x-y+1, y+1)) +Base.binomial(x::Number, y::Number) = inv((x+1) * beta(x-y+1, y+1)) From dc96e3f5669e7ac2d120a76008fbf6f4c671815b Mon Sep 17 00:00:00 2001 From: PaulXiCao <> Date: Sat, 16 Jan 2021 00:29:03 +0100 Subject: [PATCH 4/6] roadmap for tests --- test/gamma.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/gamma.jl b/test/gamma.jl index d3c4f681..f26f0c7c 100644 --- a/test/gamma.jl +++ b/test/gamma.jl @@ -267,3 +267,14 @@ end @test beta(big(1.0),big(1.2)) ≈ beta(1.0,1.2) rtol=4*eps() end + +@testset "binomial" begin + # type stability tests + # (combinations of real/complex/integer arguments of sizes 16/32/63/Big lead to correct data types) + + # check some specific, real/complex arguments + + # check some Big arguments + + # compare integer arguments type casted to complex wrt integer arguments +end From be2f509e2e77ae636c845de227a502ead67cc2a8 Mon Sep 17 00:00:00 2001 From: PaulXiCao <> Date: Sat, 16 Jan 2021 15:39:51 +0100 Subject: [PATCH 5/6] tests --- test/gamma.jl | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/test/gamma.jl b/test/gamma.jl index f26f0c7c..23d52198 100644 --- a/test/gamma.jl +++ b/test/gamma.jl @@ -271,10 +271,40 @@ end @testset "binomial" begin # type stability tests # (combinations of real/complex/integer arguments of sizes 16/32/63/Big lead to correct data types) + @testset "type stability" begin + for F in [Float16, Float32, Float64] + @test F == typeof(binomial( F( 2), F( 2))) + @test Complex{F} == typeof(binomial(Complex{F}(2), Complex{F}(2))) + end + @test BigFloat == typeof(binomial(BigFloat( 2), BigFloat( 2))) + end - # check some specific, real/complex arguments + # check some specific, real/complex argument combinations. results from WolframAlpha + @testset "some specific real/complex arguments" begin + @test binomial( 3.5, 2.3 ) ≈ 3.93413299580028 + @test binomial(-3.5, 2.3 ) ≈ 5.64332481819944 + @test binomial( 3.5, -2.3 ) ≈ 0.00703726043773 + @test binomial(-3.5, -2.3 ) ≈ 0.04879062507380 + @test binomial( 3.5, 2.3+2im) ≈ 14.10920342060363-014.53780610795795im + @test binomial( 3.5-1im, 2.3 ) ≈ 3.16723141606959-003.29657673089314im + @test binomial( 3.5-1im, 2.3+3im) ≈ 143.19825764420579-258.14796666889352im + end + + # check some Big arguments. results from WolframAlpha + @testset "Big arguments" begin + @test binomial(BigFloat(" 1.2222222222222222222222222222222222222222"), BigFloat("2.0")) ≈ + BigFloat(" 0.1358024691358024691358024691358024691358") + @test binomial(BigFloat(" 0.1234567890123456789012345678901234567890"), BigFloat("3.4567890123456789012345678901234567890123")) ≈ + BigFloat("-0.0658640218674615803572225658583379621360") + end - # check some Big arguments # compare integer arguments type casted to complex wrt integer arguments + @testset "comparison of integer arguments" begin + for n = 0:10, k = 0:n + @test binomial(n, k) ≈ binomial(complex(n), k ) + @test binomial(n, k) ≈ binomial( n, complex(k)) + @test binomial(n, k) ≈ binomial(complex(n), complex(k)) + end + end end From 7cc46b5e6499ceffb53a0dc670017f2f94609215 Mon Sep 17 00:00:00 2001 From: PaulXiCao <> Date: Sat, 16 Jan 2021 15:40:34 +0100 Subject: [PATCH 6/6] documentation --- docs/src/functions_list.md | 2 +- docs/src/functions_overview.md | 2 +- src/gamma.jl | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/src/functions_list.md b/docs/src/functions_list.md index 08c97269..f1839de3 100644 --- a/docs/src/functions_list.md +++ b/docs/src/functions_list.md @@ -51,7 +51,7 @@ SpecialFunctions.besseli SpecialFunctions.besselix SpecialFunctions.besselk SpecialFunctions.besselkx -SpecialFunctions.binomial +Base.binomial SpecialFunctions.jinc SpecialFunctions.ellipk SpecialFunctions.ellipe diff --git a/docs/src/functions_overview.md b/docs/src/functions_overview.md index 321b9974..4f1ab0aa 100644 --- a/docs/src/functions_overview.md +++ b/docs/src/functions_overview.md @@ -22,7 +22,7 @@ Here the *Special Functions* are listed according to the structure of [NIST Digi | [`logbeta(x,y)`](@ref SpecialFunctions.logbeta) | accurate `log(beta(x,y))` for large `x` or `y` | | [`logabsbeta(x,y)`](@ref SpecialFunctions.logabsbeta) | accurate `log(abs(beta(x,y)))` for large `x` or `y` | | [`logabsbinomial(x,y)`](@ref SpecialFunctions.logabsbinomial) | accurate `log(abs(binomial(n,k)))` for large `n` and `k` near `n/2` | -| [`binomial(x,y)`](@ref SpecialFunctions.binomial) | generalized binomial coefficient ``{ x \choose y}`` for ``x,y \in \mathbb{C}``| +| [`binomial(x,y)`](@ref Base.binomial) | generalized binomial coefficient ``{ x \choose y}`` for ``x,y \in \mathbb{C}``| ## [Exponential and Trigonometric Integrals](https://dlmf.nist.gov/6) diff --git a/src/gamma.jl b/src/gamma.jl index dd89ea0e..8fbcff0f 100644 --- a/src/gamma.jl +++ b/src/gamma.jl @@ -930,8 +930,9 @@ logabsbinomial(n::Integer, k::Integer) = logabsbinomial(promote(n, k)...) """ binomial(x, y) -Generalized binomial coefficient -``{x \\choose y} = \\frac{1}{(x+1) \\Beta(x-y+1,y+1)}``. +Generalized binomial coefficient for complex arguments +``{x \\choose y} = \\frac{1}{(x+1) \\Beta(x-y+1,y+1)}`` +for ``x, y \\ \\mathbb{C}``. External links: [Wikipedia](https://en.wikipedia.org/wiki/Binomial_coefficient#Two_real_or_complex_valued_arguments)