Skip to content

Commit 8136181

Browse files
authored
rename lfactorial/lbinomial (#161)
Ensure consistency with #156.
1 parent 23ec9f1 commit 8136181

File tree

7 files changed

+71
-40
lines changed

7 files changed

+71
-40
lines changed

Project.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ BinDeps = "9e28174c-4ba2-5203-b857-d8d62c4213ee"
77
BinaryProvider = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
88
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
99

10+
[compat]
11+
BinaryProvider = "≥ 0.5.0"
12+
julia = "≥ 0.7.0"
13+
1014
[extras]
1115
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1216

1317
[targets]
1418
test = ["Test"]
15-
16-
[compat]
17-
BinaryProvider = "≥ 0.5.0"
18-
julia = "≥ 0.7.0"

docs/src/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ libraries.
4949
| [`loggamma(x)`](@ref SpecialFunctions.loggamma) | accurate `log(gamma(x))` for large `x` |
5050
| [`logabsgamma(x)`](@ref SpecialFunctions.logabsgamma) | accurate `log(abs(gamma(x)))` for large `x` |
5151
| [`lgamma(x)`](@ref SpecialFunctions.lgamma) | accurate `log(gamma(x))` for large `x` |
52-
| [`lfactorial(x)`](@ref SpecialFunctions.lfactorial) | accurate `log(factorial(x))` for large `x`; same as `lgamma(x+1)` for `x > 1`, zero otherwise |
52+
| [`logfactorial(x)`](@ref SpecialFunctions.logfactorial) | accurate `log(factorial(x))` for large `x`; same as `lgamma(x+1)` for `x > 1`, zero otherwise |
5353
| [`beta(x,y)`](@ref SpecialFunctions.beta) | [beta function](https://en.wikipedia.org/wiki/Beta_function) at `x,y` |
5454
| [`logbeta(x,y)`](@ref SpecialFunctions.logbeta) | accurate `log(beta(x,y))` for large `x` or `y` |
5555
| [`logabsbeta(x,y)`](@ref SpecialFunctions.logabsbeta) | accurate `log(abs(beta(x,y)))` for large `x` or `y` |
56+
| [`logabsbinomial(x,y)`](@ref SpecialFunctions.logabsbinomial) | accurate `log(abs(beta(x,y)))` for large `x` or `y` |
5657
## Installation
5758

5859
The package is available for Julia versions 0.5 and up. To install it, run

docs/src/special.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ SpecialFunctions.zeta
5151
SpecialFunctions.gamma
5252
SpecialFunctions.loggamma
5353
SpecialFunctions.logabsgamma
54-
SpecialFunctions.lfactorial
54+
SpecialFunctions.logfactorial
5555
SpecialFunctions.beta
5656
SpecialFunctions.logbeta
5757
SpecialFunctions.logabsbeta
58+
SpecialFunctions.logabsbinomial
5859
```

src/SpecialFunctions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ include("gamma.jl")
6565
include("deprecated.jl")
6666

6767
for f in (:digamma, :erf, :erfc, :erfcinv, :erfcx, :erfi, :erfinv,
68-
:eta, :gamma, :invdigamma, :lfactorial, :lgamma, :trigamma, :ellipk, :ellipe)
68+
:eta, :gamma, :invdigamma, :logfactorial, :lgamma, :trigamma, :ellipk, :ellipe)
6969
@eval $(f)(::Missing) = missing
7070
end
7171
for f in (:beta, :lbeta)

src/deprecated.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
@deprecate lgamma_r(x::Number) (loggamma(x), 1)
1010
@deprecate lbeta(x::Real, w::Real) logabsbeta(x, w)[1]
1111
@deprecate lbeta(x::Number, w::Number) logbeta(x, w)
12+
@deprecate lfact(x) logfactorial(x)
13+
@deprecate lfactorial(x) logfactorial(x)
14+
@deprecate lbinomial(x) logabsbinomial(x)[1]
15+
16+
1217

1318
function _airy(k::Integer, z::Complex{Float64})
1419
Base.depwarn("`airy(k,x)` is deprecated, use `airyai(x)`, `airyaiprime(x)`, `airybi(x)` or `airybiprime(x)` instead.",:airy)

src/gamma.jl

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ function polygamma(m::Integer, z::Number)
551551
polygamma(m, x)
552552
end
553553

554-
export gamma, loggamma, logabsgamma, beta, logbeta, logabsbeta, lfactorial
554+
export gamma, loggamma, logabsgamma, beta, logbeta, logabsbeta, logfactorial, logabsbinomial
555555

556556
## from base/special/gamma.jl
557557

@@ -584,27 +584,31 @@ logabsgamma(x::AbstractFloat) = throw(MethodError(logabsgamma, x))
584584

585585

586586
"""
587-
lfactorial(x)
587+
logfactorial(x)
588588
589589
Compute the logarithmic factorial of a nonnegative integer `x`.
590590
Equivalent to [`loggamma`](@ref) of `x + 1`, but `loggamma` extends this function
591591
to non-integer `x`.
592592
"""
593-
lfactorial(x::Integer) = x < 0 ? throw(DomainError(x, "`x` must be non-negative.")) : loggamma(x + oneunit(x))
594-
Base.@deprecate lfact lfactorial
593+
logfactorial(x::Integer) = x < 0 ? throw(DomainError(x, "`x` must be non-negative.")) : loggamma(x + oneunit(x))
595594

596595
"""
597596
logabsgamma(x)
598597
599598
Compute the logarithm of absolute value of [`gamma`](@ref) for
600-
[`Real`](@ref) `x`and returns a tuple (logabsgamma(x), sign(gamma(x))).
599+
[`Real`](@ref) `x`and returns a tuple `(log(abs(gamma(x))), sign(gamma(x)))`.
600+
601+
See also [`loggamma`](@ref).
601602
"""
602603
function logabsgamma end
603604

604605
"""
605606
loggamma(x)
606607
607-
Computes the logarithm of [`gamma`](@ref) for given `x`
608+
Computes the logarithm of [`gamma`](@ref) for given `x`. If `x` is a `Real`, then it
609+
throws a `DomainError` if `gamma(x)` is negative.
610+
611+
See also [`logabsgamma`](@ref).
608612
"""
609613
function loggamma end
610614

@@ -732,15 +736,18 @@ end
732736
"""
733737
logbeta(x, y)
734738
735-
Natural logarithm of the [`beta`](@ref)
736-
function ``\\log(|\\operatorname{B}(x,y)|)``.
739+
Natural logarithm of the [`beta`](@ref) function ``\\log(|\\operatorname{B}(x,y)|)``.
740+
741+
See also [`logabsbeta`](@ref).
737742
"""
738743
logbeta(x::Number, w::Number) = loggamma(x)+loggamma(w)-loggamma(x+w)
739744

740745
"""
741746
logabsbeta(x, y)
742747
743-
Returns a tuple of the natural logarithm of the absolute value of the [`beta`](@ref) function ``\\log(|\\operatorname{B}(x,y)|)`` and sign of the [`beta`](@ref) function .
748+
Compute the natural logarithm of the absolute value of the [`beta`](@ref) function, returning a tuple `(log(abs(beta(x,y))), sign(beta(x,y)))`
749+
750+
See also [`logbeta`](@ref).
744751
"""
745752
function logabsbeta(x::Real, w::Real)
746753
yx, sx = logabsgamma(x)
@@ -802,23 +809,37 @@ factorial(x) = Base.factorial(x) # to make SpecialFunctions.factorial work uncon
802809
factorial(x::Number) = gamma(x + 1) # fallback for x not Integer
803810

804811
"""
805-
lbinomial(n, k) = log(abs(binomial(n, k)))
812+
logabsbinomial(n, k)
806813
807814
Accurate natural logarithm of the absolute value of the [`binomial`](@ref)
808815
coefficient `binomial(n, k)` for large `n` and `k` near `n/2`.
816+
817+
Returns a tuple `(log(abs(binomial(n,k))), sign(binomial(n,k)))`.
809818
"""
810-
function lbinomial(n::T, k::T) where {T<:Integer}
819+
function logabsbinomial(n::T, k::T) where {T<:Integer}
811820
S = float(T)
812-
(k < 0) && return typemin(S)
821+
s = one(S)
813822
if n < 0
823+
# reflection formula
824+
# binomial(n,k) = (-1)^k * binomial(-n+k-1,k)
814825
n = -n + k - 1
826+
s = isodd(k) ? -s : s
827+
end
828+
if k < 0 || k > n
829+
# binomial(n,k) == 0
830+
return (typemin(S), zero(S))
831+
elseif k == 0 || k == n
832+
# binomial(n,k) == ±1
833+
return (zero(S), s)
815834
end
816-
k > n && return typemin(S)
817-
(k == 0 || k == n) && return zero(S)
818-
(k == 1) && return log(abs(n))
819835
if k > (n>>1)
820836
k = n - k
821837
end
822-
-log1p(n) - logabsbeta(n - k + one(T), k + one(T))[1]
838+
if k == 1
839+
# binomial(n,k) == ±n
840+
return (log(abs(n)), s)
841+
else
842+
return (-log1p(n) - logabsbeta(n - k + one(T), k + one(T))[1], s)
843+
end
823844
end
824-
lbinomial(n::Integer, k::Integer) = lbinomial(promote(n, k)...)
845+
logabsbinomial(n::Integer, k::Integer) = logabsbinomial(promote(n, k)...)

test/runtests.jl

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -634,12 +634,12 @@ end
634634
for x in (3.2, 2+1im, 3//2, 3.2+0.1im)
635635
@test SpecialFunctions.factorial(x) == gamma(1+x)
636636
end
637-
@test lfactorial(0) == lfactorial(1) == 0
638-
@test lfactorial(2) == loggamma(3)
639-
# Ensure that the domain of lfactorial matches that of factorial (issue #21318)
640-
@test_throws DomainError lfactorial(-3)
637+
@test logfactorial(0) == logfactorial(1) == 0
638+
@test logfactorial(2) == loggamma(3)
639+
# Ensure that the domain of logfactorial matches that of factorial (issue #21318)
640+
@test_throws DomainError logfactorial(-3)
641641
@test_throws DomainError loggamma(-4.2)
642-
@test_throws MethodError lfactorial(1.0)
642+
@test_throws MethodError logfactorial(1.0)
643643
end
644644

645645
# loggamma & logabsgamma test cases (from Wolfram Alpha)
@@ -708,21 +708,24 @@ end
708708
@test beta(big(1.0),big(1.2)) beta(1.0,1.2) rtol=4*eps()
709709
end
710710

711-
@testset "lbinomial" begin
712-
@test lbinomial(10, -1) == -Inf
713-
@test lbinomial(10, 11) == -Inf
714-
@test lbinomial(10, 0) == 0.0
715-
@test lbinomial(10, 10) == 0.0
716-
717-
@test lbinomial(10, 1) log(10)
718-
@test lbinomial(-6, 10) log(binomial(-6, 10))
719-
@test lbinomial(-6, 11) log(abs(binomial(-6, 11)))
720-
@test lbinomial.(200, 0:200) log.(binomial.(BigInt(200), (0:200)))
711+
@testset "logabsbinomial" begin
712+
@test logabsbinomial(10, -1) == (-Inf, 0.0)
713+
@test logabsbinomial(10, 11) == (-Inf, 0.0)
714+
@test logabsbinomial(10, 0) == ( 0.0, 1.0)
715+
@test logabsbinomial(10, 10) == ( 0.0, 1.0)
716+
717+
@test logabsbinomial(10, 1)[1] log(10)
718+
@test logabsbinomial(10, 1)[2] == 1.0
719+
@test logabsbinomial(-6, 10)[1] log(binomial(-6, 10))
720+
@test logabsbinomial(-6, 10)[2] == 1.0
721+
@test logabsbinomial(-6, 11)[1] log(abs(binomial(-6, 11)))
722+
@test logabsbinomial(-6, 11)[2] == -1.0
723+
@test first.(logabsbinomial.(200, 0:200)) log.(binomial.(BigInt(200), (0:200)))
721724
end
722725

723726
@testset "missing data" begin
724727
for f in (digamma, erf, erfc, erfcinv, erfcx, erfi, erfinv, eta, gamma,
725-
invdigamma, lfactorial, trigamma)
728+
invdigamma, logfactorial, trigamma)
726729
@test f(missing) === missing
727730
end
728731
@test beta(1.0, missing) === missing

0 commit comments

Comments
 (0)