Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move [l]gamma, [l]beta and lfact to SpecialFunctions.jl #27473

Merged
merged 1 commit into from
Jun 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,9 @@ Deprecated or removed

* `setrounding` has been deprecated for `Float32` and `Float64`, as the behaviour was too unreliable ([#26935]).

* `gamma`, `lgamma`, `beta`, `lbeta` and `lfact` have been moved to
[SpecialFunctions.jl](https://github.com/JuliaMath/SpecialFunctions.jl) ([#27459], [#27473]).

* `atan2` is now a 2-argument method of `atan` ([#27248]).

Command-line option changes
Expand Down
8 changes: 0 additions & 8 deletions base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ else
factorial(n::Union{Int8,UInt8,Int16,UInt16,Int32,UInt32}) = factorial(Int64(n))
end

function gamma(n::Union{Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64})
n < 0 && throw(DomainError(n, "`n` must not be negative."))
n == 0 && return Inf
n <= 2 && return 1.0
n > 20 && return gamma(Float64(n))
@inbounds return Float64(_fact_table64[n-1])
end


# Basic functions for working with permutations

Expand Down
13 changes: 13 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,19 @@ end
@deprecate_moved varm "StatsBase"
@deprecate_moved linreg "StatsBase"

# ?? more special functions to SpecialFunctions.jl
@deprecate_moved gamma "SpecialFunctions"
@deprecate_moved lgamma "SpecialFunctions"
@deprecate_moved beta "SpecialFunctions"
@deprecate_moved lbeta "SpecialFunctions"
@deprecate_moved lfact "SpecialFunctions"
function factorial(x::Number)
error("""factorial(x::Number) has been moved to the package SpecialFunctions.jl.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense to me. Why would we move one method and not the whole function? With this, SpecialFunctions will need to commit type piracy to define that method.

Copy link
Member Author

@fredrikekre fredrikekre Jun 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right; https://github.com/JuliaMath/SpecialFunctions.jl/pull/92/files#diff-f839a13f2df5472f7fd840f52ce84e16R757
Do we care though? It's not like SpecialFunctions define this function for a more narrow type, so this could not possibly break anything, since before using SpecialFunctions something like factorial(2.5) would be an error, and behaviour of factorial(::Integer) does not change when loading SpecialFunctions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to me. This allows people to do using SpecialFunctions in the same REPL session and have it work, which seems far superior to not being able to do so.

Run `Pkg.add("SpecialFunctions")` to install it, restart Julia,
and then run `using SpecialFunctions` to load it.
""")
end

# issue #27093
# in src/jlfrontend.scm a call to `@deprecate` is generated for per-module `eval(m, x)`
@eval Core Main.Base.@deprecate(eval(e), Core.eval(Main, e))
Expand Down
7 changes: 0 additions & 7 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ export
floor,
fma,
frexp,
gamma,
gcd,
gcdx,
hypot,
Expand All @@ -284,8 +283,6 @@ export
ldexp,
leading_ones,
leading_zeros,
lfact,
lgamma,
log,
log10,
log1p,
Expand Down Expand Up @@ -348,10 +345,6 @@ export
≈,
≉,

# specfun
beta,
lbeta,

# arrays
axes,
broadcast!,
Expand Down
5 changes: 2 additions & 3 deletions base/fastmath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ const fast_op =
:exp => :exp_fast,
:expm1 => :expm1_fast,
:hypot => :hypot_fast,
:lgamma => :lgamma_fast,
:log10 => :log10_fast,
:log1p => :log1p_fast,
:log2 => :log2_fast,
Expand Down Expand Up @@ -276,7 +275,7 @@ sqrt_fast(x::FloatTypes) = sqrt_llvm(x)
const libm = Base.libm_name

for f in (:acosh, :asinh, :atanh, :cbrt, :cos,
:cosh, :exp2, :expm1, :lgamma, :log10, :log1p, :log2,
:cosh, :exp2, :expm1, :log10, :log1p, :log2,
:log, :sin, :sinh, :tan, :tanh)
f_fast = fast_op[f]
@eval begin
Expand Down Expand Up @@ -377,7 +376,7 @@ end
# fall-back implementations and type promotion

for f in (:acos, :acosh, :angle, :asin, :asinh, :atan, :atanh, :cbrt,
:cis, :cos, :cosh, :exp10, :exp2, :exp, :expm1, :lgamma,
:cis, :cos, :cosh, :exp10, :exp2, :exp, :expm1,
:log10, :log1p, :log2, :log, :sin, :sinh, :sqrt, :tan,
:tanh)
f_fast = fast_op[f]
Expand Down
21 changes: 21 additions & 0 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,27 @@ function isqrt(x::Union{Int64,UInt64,Int128,UInt128})
s*s > x ? s-1 : s
end

"""
factorial(n::Integer)

Factorial of `n`. If `n` is an [`Integer`](@ref), the factorial is computed as an
integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small,
but you can use `factorial(big(n))` to compute the result exactly in arbitrary precision.

# Examples
```jldoctest
julia> factorial(6)
720

julia> factorial(21)
ERROR: OverflowError: 21 is too large to look up in the table
Stacktrace:
[...]

julia> factorial(big(21))
51090942171709440000
```
"""
function factorial(n::Integer)
n < 0 && throw(DomainError(n, "`n` must be nonnegative."))
f::typeof(n*n) = 1
Expand Down
9 changes: 4 additions & 5 deletions base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export sin, cos, sincos, tan, sinh, cosh, tanh, asin, acos, atan,
rad2deg, deg2rad,
log, log2, log10, log1p, exponent, exp, exp2, exp10, expm1,
cbrt, sqrt, significand,
lgamma, hypot, gamma, lfact, max, min, minmax, ldexp, frexp,
hypot, max, min, minmax, ldexp, frexp,
clamp, clamp!, modf, ^, mod2pi, rem2pi,
beta, lbeta, @evalpoly
@evalpoly

import .Base: log, exp, sin, cos, tan, sinh, cosh, tanh, asin,
acos, atan, asinh, acosh, atanh, sqrt, log2, log10,
Expand Down Expand Up @@ -484,7 +484,7 @@ Stacktrace:
```
"""
log1p(x)
for f in (:log2, :log10, :lgamma)
for f in (:log2, :log10)
@eval begin
@inline ($f)(x::Float64) = nan_dom_err(ccall(($(string(f)), libm), Float64, (Float64,), x), x)
@inline ($f)(x::Float32) = nan_dom_err(ccall(($(string(f, "f")), libm), Float32, (Float32,), x), x)
Expand Down Expand Up @@ -1037,15 +1037,14 @@ include("special/exp.jl")
include("special/exp10.jl")
include("special/hyperbolic.jl")
include("special/trig.jl")
include("special/gamma.jl")
include("special/rem_pio2.jl")
include("special/log.jl")

# `missing` definitions for functions in this module
for f in (:(acos), :(acosh), :(asin), :(asinh), :(atan), :(atanh),
:(sin), :(sinh), :(cos), :(cosh), :(tan), :(tanh),
:(exp), :(exp2), :(expm1), :(log), :(log10), :(log1p),
:(log2), :(exponent), :(sqrt), :(gamma), :(lgamma))
:(log2), :(exponent), :(sqrt))
@eval $(f)(::Missing) = missing
end

Expand Down
25 changes: 3 additions & 22 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@ import
isfinite, isinf, isnan, ldexp, log, log2, log10, max, min, mod, modf,
nextfloat, prevfloat, promote_rule, rem, rem2pi, round, show, float,
sum, sqrt, string, print, trunc, precision, exp10, expm1,
gamma, lgamma, log1p,
log1p,
eps, signbit, sin, cos, sincos, tan, sec, csc, cot, acos, asin, atan,
cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh,
cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding,
setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero,
isone, big, beta, RefValue
isone, big, RefValue

import .Base.Rounding: rounding_raw, setrounding_raw

import .Base.GMP: ClongMax, CulongMax, CdoubleMax, Limb

import .Base.Math.lgamma_r

import .Base.FastMath.sincos_fast

version() = VersionNumber(unsafe_string(ccall((:mpfr_get_version,:libmpfr), Ptr{Cchar}, ())))
Expand Down Expand Up @@ -655,7 +653,7 @@ function sum(arr::AbstractArray{BigFloat})
end

# Functions for which NaN results are converted to DomainError, following Base
for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :atanh, :gamma)
for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :atanh)
@eval begin
function ($f)(x::BigFloat)
isnan(x) && return x
Expand All @@ -667,28 +665,11 @@ for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :at
end
end

# log of absolute value of gamma function
const lgamma_signp = Ref{Cint}()
function lgamma(x::BigFloat)
z = BigFloat()
ccall((:mpfr_lgamma,:libmpfr), Cint, (Ref{BigFloat}, Ref{Cint}, Ref{BigFloat}, Int32), z, lgamma_signp, x, ROUNDING_MODE[])
return z
end

lgamma_r(x::BigFloat) = (lgamma(x), lgamma_signp[])

function atan(y::BigFloat, x::BigFloat)
z = BigFloat()
ccall((:mpfr_atan2, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, y, x, ROUNDING_MODE[])
return z
end
if version() >= v"4.0.0"
function beta(y::BigFloat, x::BigFloat)
z = BigFloat()
ccall((:mpfr_beta, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Int32), z, y, x, ROUNDING_MODE[])
return z
end
end

# Utility functions
==(x::BigFloat, y::BigFloat) = ccall((:mpfr_equal_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0
Expand Down
27 changes: 0 additions & 27 deletions base/number.jl
Original file line number Diff line number Diff line change
Expand Up @@ -321,33 +321,6 @@ oneunit(::Type{T}) where {T} = T(one(T))

_default_type(::Type{Number}) = Int

"""
factorial(n)

Factorial of `n`. If `n` is an [`Integer`](@ref), the factorial is computed as an
integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small,
but you can use `factorial(big(n))` to compute the result exactly in arbitrary precision.
If `n` is not an `Integer`, `factorial(n)` is equivalent to [`gamma(n+1)`](@ref).

# Examples
```jldoctest
julia> factorial(6)
720

julia> factorial(21)
ERROR: OverflowError: 21 is too large to look up in the table
Stacktrace:
[...]

julia> factorial(21.0)
5.109094217170944e19

julia> factorial(big(21))
51090942171709440000
```
"""
factorial(x::Number) = gamma(x + 1) # fallback for x not Integer

"""
big(T::Type)

Expand Down
Loading