diff --git a/docs/src/functions_list.md b/docs/src/functions_list.md index 56d36c45..f1839de3 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 +Base.binomial SpecialFunctions.jinc SpecialFunctions.ellipk SpecialFunctions.ellipe diff --git a/docs/src/functions_overview.md b/docs/src/functions_overview.md index 7566623f..4f1ab0aa 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 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 a86ea640..8fbcff0f 100644 --- a/src/gamma.jl +++ b/src/gamma.jl @@ -926,3 +926,16 @@ function logabsbinomial(n::T, k::T) where {T<:Integer} end end logabsbinomial(n::Integer, k::Integer) = logabsbinomial(promote(n, k)...) + +""" + binomial(x, y) + +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) + +See also [`beta(a,b)`](@ref SpecialFunctions.beta). +""" +Base.binomial(x::Number, y::Number) = inv((x+1) * beta(x-y+1, y+1)) diff --git a/test/gamma.jl b/test/gamma.jl index d3c4f681..23d52198 100644 --- a/test/gamma.jl +++ b/test/gamma.jl @@ -267,3 +267,44 @@ 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) + @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 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 + + + # 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