# Base.factorial: Extending and overwriting functions in SpecialFunctions

The `Base.factorial` function supplies the following methods

``````julia> methods(factorial)
# 7 methods for generic function "factorial":
[1] factorial(n::UInt128) in Base at combinatorics.jl:26
[2] factorial(n::Int128) in Base at combinatorics.jl:25
[3] factorial(x::BigFloat) in Base.MPFR at mpfr.jl:639
[4] factorial(x::BigInt) in Base.GMP at gmp.jl:639
[5] factorial(n::Union{Int64, UInt64}) in Base at combinatorics.jl:27
[6] factorial(n::Union{Int16, Int32, Int8, UInt16, UInt32, UInt8}) in Base at combinatorics.jl:33
[7] factorial(n::Integer) in Base at intfuncs.jl:889
``````

Currently that function is extended to `x::Number` using the `gamma` function within the `SpecialFunctions` module as such

``````# this trickery is needed while the deprecated method in Base exists
@static if !hasmethod(Base.factorial, Tuple{Number})
import Base: factorial
end
factorial(x) = Base.factorial(x) # to make SpecialFunctions.factorial work unconditionally
factorial(x::Number) = gamma(x + 1) # fallback for x not Integer
``````

It seems like that `Base.factorial` is deprecated according to the comments?

The problem arises now because the implementation `Base.factorial(x::BigFloat)` is checking that `isinteger(x)` which does not really make any sense. Iād like to extend it to any `BigFloat` by calling the `gamma` function.

Is it possible to extend `Base.factorial` in the following way:

• for `x::Integer` call `Base.factorial`
• else call `SpecialFunctions.gamma`
• especially, overwrite `Base.factorial(x::BigFloat)`

I tried a straight forward implementation like such

``````# this trickery is needed while the deprecated method in Base exists
@static if !hasmethod(Base.factorial, Tuple{Number})
import Base: factorial
end
factorial(x::Integer) = Base.factorial(x)   # to make SpecialFunctions.factorial work unconditionally
factorial(x::Number)  = gamma(x + 1)        # fallback for x not Integer
``````

This approach throws the following error

``````julia> using SpecialFunctions
[ Info: Precompiling SpecialFunctions [276daf66-3868-5448-9aa4-cd146d93841b]
WARNING: Method definition factorial(Integer) in module Base at intfuncs.jl:889 overwritten in module SpecialFunctions at <HOME>/.julia/environments/SpecialFunctions-dev/dev/SpecialFunctions/src/gamma.jl:891.
** incremental compilation may be fatally broken for this module **
``````

This in relation to issue #233.

1 Like

That is technically type piracy and should not be part of a solution. IMO in the long run, it would be best to move all methods either into or out of `Base` ā piling hacks on hacks will continue to backfire.