@@ -3,44 +3,27 @@ gamma(z::Number) = _gamma(float(z))
3
3
_gamma (x:: Float32 ) = Float32 (_gamma (Float64 (x)))
4
4
5
5
function _gamma (x:: Float64 )
6
+ T = Float64
6
7
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." ))
8
9
xp1 = abs (x) + 1.0
9
- return π / sinpi (xp1) / _gammax (xp1)
10
- else
11
- return _gammax (x)
10
+ return π / (sinpi (xp1) * _gamma (xp1))
12
11
end
13
- end
14
- # only have a Float64 implementations
15
- function _gammax (x)
12
+ isfinite (x) || return x
16
13
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))
39
24
40
- return SQ2PI (T) * y * w
41
- end
42
- function small_gamma (x)
43
- T = Float64
25
+ return SQ2PI (T) * y * w
26
+ end
44
27
P = (
45
28
1.000000000000000000009e0 , 8.378004301573126728826e-1 , 3.629515436640239168939e-1 , 1.113062816019361559013e-1 ,
46
29
2.385363243461108252554e-2 , 4.092666828394035500949e-3 , 4.542931960608009155600e-4 , 4.212760487471622013093e-5
@@ -51,18 +34,26 @@ function small_gamma(x)
51
34
- 1.397148517476170440917e-5
52
35
)
53
36
54
- z = one (T)
37
+ z = 1.0
55
38
while x >= 3.0
56
- x -= one (T)
39
+ x -= 1.0
57
40
z *= x
58
41
end
59
42
while x < 2.0
60
43
z /= x
61
- x += one (T)
44
+ x += 1.0
62
45
end
63
46
64
- x -= T ( 2 )
47
+ x -= 2.0
65
48
p = evalpoly (x, P)
66
49
q = evalpoly (x, Q)
67
50
return z * p / q
68
51
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