1
- # Adapted from Cephes Mathematical Library (MIT license https://en.smath.com/view/CephesMathLibrary/license) by Stephen L. Moshier
2
- gamma (x:: Float64 ) = _gamma (x)
3
- gamma (x:: Float32 ) = Float32 (_gamma (Float64 (x)))
4
-
5
- function _gamma (x:: Float64 )
1
+ # Float64 version adapted from Cephes Mathematical Library (MIT license https://en.smath.com/view/CephesMathLibrary/license) by Stephen L. Moshier
2
+ function gamma (_x:: Float64 )
6
3
T = Float64
4
+ x = _x
7
5
if x < 0
8
- (isinteger (x) || x== - Inf ) && throw (DomainError (x, " NaN result for non-NaN input." ))
9
- xp1 = abs (x) + 1.0
10
- return π / (sinpi (xp1) * _gamma (xp1))
6
+ s = sinpi (_x)
7
+ s == 0 && throw (DomainError (x, " NaN result for non-NaN input." ))
8
+ x = - x # Use this rather than the traditional x = 1-x to avoid roundoff.
9
+ s *= x
11
10
end
12
11
isfinite (x) || return x
13
12
if x > 11.5
14
13
w = inv (x)
15
- s = (
14
+ coefs = (1.0 ,
16
15
8.333333333333331800504e-2 , 3.472222222230075327854e-3 , - 2.681327161876304418288e-3 , - 2.294719747873185405699e-4 ,
17
16
7.840334842744753003862e-4 , 6.989332260623193171870e-5 , - 5.950237554056330156018e-4 , - 2.363848809501759061727e-5 ,
18
17
7.147391378143610789273e-4
19
18
)
20
- w = muladd (w, evalpoly (w, s), 1.0 )
19
+ w = evalpoly (w, coefs )
21
20
# avoid overflow
22
21
v = x ^ muladd (0.5 , x, - 0.25 )
23
- y = v * (v / exp (x))
22
+ res = SQ2PI (T) * v * (v / exp (x)) * w
24
23
25
- return SQ2PI (T) * y * w
24
+ if _x < 0
25
+ return π / (res * s)
26
+ else
27
+ return res
28
+ end
26
29
end
27
30
P = (
28
31
1.000000000000000000009e0 , 8.378004301573126728826e-1 , 3.629515436640239168939e-1 , 1.113062816019361559013e-1 ,
@@ -47,7 +50,50 @@ function _gamma(x::Float64)
47
50
x -= 2.0
48
51
p = evalpoly (x, P)
49
52
q = evalpoly (x, Q)
50
- return z * p / q
53
+ return _x < 0 ? π * q / (s * z * p) : z * p / q
54
+ end
55
+
56
+
57
+ function gamma (_x:: Float32 )
58
+ x = Float64 (_x)
59
+ if _x < 0
60
+ s = sinpi (x)
61
+ s == 0 && throw (DomainError (_x, " NaN result for non-NaN input." ))
62
+ x = 1 - x
63
+ end
64
+ if x < 5
65
+ z = 1.0
66
+ while x > 1
67
+ x -= 1
68
+ z *= x
69
+ end
70
+ num = evalpoly (x, (1.0 , 0.41702538904450015 , 0.24081703455575904 , 0.04071509011391178 , 0.015839573267537377 ))
71
+ den = x* evalpoly (x, (1.0 , 0.9942411061082665 , - 0.17434932941689474 , - 0.13577921102050783 , 0.03028452206514555 ))
72
+ res = z * num / den
73
+ else
74
+ x -= 1
75
+ w = evalpoly (inv (x), (2.506628299028453 , 0.20888413086840676 , 0.008736513049552962 , - 0.007022997182153692 , 0.0006787969600290756 ))
76
+ res = @fastmath sqrt (x) * exp (log (x* 1 / ℯ) * x) * w
77
+ end
78
+ return Float32 (_x < 0 ? π / (s * res) : res)
79
+ end
80
+
81
+ function gamma (_x:: Float16 )
82
+ x = Float32 (_x)
83
+ if _x < 0
84
+ s = sinpi (x)
85
+ s == 0 && throw (DomainError (_x, " NaN result for non-NaN input." ))
86
+ x = 1 - x
87
+ end
88
+ x > 14 && return Float16 (ifelse (_x > 0 , Inf32 , 0f0 ))
89
+ z = 1f0
90
+ while x > 1
91
+ x -= 1
92
+ z *= x
93
+ end
94
+ num = evalpoly (x, (1.0f0 , 0.4170254f0 , 0.24081704f0 , 0.04071509f0 , 0.015839573f0 ))
95
+ den = x* evalpoly (x, (1.0f0 , 0.9942411f0 , - 0.17434932f0 , - 0.13577922f0 , 0.030284522f0 ))
96
+ return Float16 (_x < 0 ? Float32 (π)* den / (s* z* num) : z * num / den)
51
97
end
52
98
53
99
function gamma (n:: Integer )
0 commit comments