Skip to content

Commit c4dd7f5

Browse files
authored
minor gamma cleanups.
This should arguably should use `Base.@assume_effects :terminates_locally` but that only exists on 1.8+.
1 parent 6aa49b7 commit c4dd7f5

File tree

1 file changed

+20
-37
lines changed

1 file changed

+20
-37
lines changed

src/gamma.jl

Lines changed: 20 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,17 +34,17 @@ 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

0 commit comments

Comments
 (0)