Skip to content

Commit 325cb5b

Browse files
authored
Merge pull request #62 from JuliaMath/oscardssmith-gamma-cleanup
minor `gamma` cleanups.
2 parents 6aa49b7 + c264d27 commit 325cb5b

File tree

1 file changed

+28
-37
lines changed

1 file changed

+28
-37
lines changed

src/gamma.jl

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,27 @@ gamma(z::Number) = _gamma(float(z))
33
_gamma(x::Float32) = Float32(_gamma(Float64(x)))
44

55
function _gamma(x::Float64)
6+
T = Float64
67
if x < 0
7-
isinteger(x) && throw(DomainError(x, "NaN result for non-NaN input."))
8+
(isinteger(x) || x==-Inf) && throw(DomainError(x, "NaN result for non-NaN input."))
89
xp1 = abs(x) + 1.0
9-
return π / sinpi(xp1) / _gammax(xp1)
10-
else
11-
return _gammax(x)
10+
return π / (sinpi(xp1) * _gamma(xp1))
1211
end
13-
end
14-
# only have a Float64 implementations
15-
function _gammax(x)
12+
isfinite(x) || return x
1613
if x > 11.5
17-
return large_gamma(x)
18-
elseif x <= 11.5
19-
return small_gamma(x)
20-
elseif isnan(x)
21-
return x
22-
end
23-
end
24-
function large_gamma(x)
25-
isinf(x) && return x
26-
T = Float64
27-
w = inv(x)
28-
s = (
29-
8.333333333333331800504e-2, 3.472222222230075327854e-3, -2.681327161876304418288e-3, -2.294719747873185405699e-4,
30-
7.840334842744753003862e-4, 6.989332260623193171870e-5, -5.950237554056330156018e-4, -2.363848809501759061727e-5,
31-
7.147391378143610789273e-4
32-
)
33-
w = w * evalpoly(w, s) + one(T)
34-
# lose precision on following block
35-
y = exp((x))
36-
# avoid overflow
37-
v = x^(0.5 * x - 0.25)
38-
y = v * (v / y)
14+
w = inv(x)
15+
s = (
16+
8.333333333333331800504e-2, 3.472222222230075327854e-3, -2.681327161876304418288e-3, -2.294719747873185405699e-4,
17+
7.840334842744753003862e-4, 6.989332260623193171870e-5, -5.950237554056330156018e-4, -2.363848809501759061727e-5,
18+
7.147391378143610789273e-4
19+
)
20+
w = muladd(w, evalpoly(w, s), 1.0)
21+
# avoid overflow
22+
v = x ^ muladd(0.5, x, -0.25)
23+
y = v * (v / exp(x))
3924

40-
return SQ2PI(T) * y * w
41-
end
42-
function small_gamma(x)
43-
T = Float64
25+
return SQ2PI(T) * y * w
26+
end
4427
P = (
4528
1.000000000000000000009e0, 8.378004301573126728826e-1, 3.629515436640239168939e-1, 1.113062816019361559013e-1,
4629
2.385363243461108252554e-2, 4.092666828394035500949e-3, 4.542931960608009155600e-4, 4.212760487471622013093e-5
@@ -51,18 +34,26 @@ function small_gamma(x)
5134
-1.397148517476170440917e-5
5235
)
5336

54-
z = one(T)
37+
z = 1.0
5538
while x >= 3.0
56-
x -= one(T)
39+
x -= 1.0
5740
z *= x
5841
end
5942
while x < 2.0
6043
z /= x
61-
x += one(T)
44+
x += 1.0
6245
end
6346

64-
x -= T(2)
47+
x -= 2.0
6548
p = evalpoly(x, P)
6649
q = evalpoly(x, Q)
6750
return z * p / q
6851
end
52+
53+
54+
function gamma(n::Integer)
55+
n < 0 && throw(DomainError(n, "`n` must not be negative."))
56+
n == 0 && return Inf*float(n)
57+
n > 20 && return gamma(float(n))
58+
@inbounds return Float64(factorial(n-1))
59+
end

0 commit comments

Comments
 (0)