@@ -11,22 +11,20 @@ fn stirling(x f64) (f64, f64) {
1111 if x > 200 {
1212 return inf (1 ), 1.0
1313 }
14- sqrt_two_pi := 2.506628274631000502417
15- max_stirling := 143.01608
1614 mut w := 1.0 / x
1715 w = 1.0 + w * ((((gamma_s[0 ] * w + gamma_s[1 ]) * w + gamma_s[2 ]) * w + gamma_s[3 ]) * w +
1816 gamma_s[4 ])
1917 mut y1 := exp (x)
2018 mut y2 := 1.0
21- if x > max_stirling { // avoid Pow() overflow
19+ if x > 143.01608 { // avoid Pow() overflow, the constant is max_stirling
2220 v := pow (x, 0.5 * x - 0.25 )
2321 y1_ := y1
2422 y1 = v
2523 y2 = v / y1_
2624 } else {
2725 y1 = pow (x, x - 0.5 ) / y1
2826 }
29- return y1 , f64 (sqrt_two_pi ) * w * y2
27+ return y1 , f64 (2.506628274631000502417 ) * w * y2 // the constant is sqrt_two_pi
3028}
3129
3230// gamma returns the gamma function of x.
@@ -40,7 +38,6 @@ fn stirling(x f64) (f64, f64) {
4038// gamma(nan) = nan
4139pub fn gamma (a f64 ) f64 {
4240 mut x := a
43- euler := 0.57721566490153286060651209008240243104215933593992 // A001620
4441 if is_neg_int (x) || is_inf (x, - 1 ) || is_nan (x) {
4542 return nan ()
4643 }
@@ -92,18 +89,14 @@ pub fn gamma(a f64) f64 {
9289 }
9390 for x < 0 {
9491 if x > - 1 e- 09 {
95- unsafe {
96- goto small
97- }
92+ return gamma_too_small (x, z)
9893 }
9994 z = z / x
10095 x = x + 1
10196 }
10297 for x < 2 {
10398 if x < 1 e- 09 {
104- unsafe {
105- goto small
106- }
99+ return gamma_too_small (x, z)
107100 }
108101 z = z / x
109102 x = x + 1
@@ -116,13 +109,14 @@ pub fn gamma(a f64) f64 {
116109 gamma_p[4 ]) * x + gamma_p[5 ]) * x + gamma_p[6 ]
117110 q = ((((((x * gamma_q[0 ] + gamma_q[1 ]) * x + gamma_q[2 ]) * x + gamma_q[3 ]) * x +
118111 gamma_q[4 ]) * x + gamma_q[5 ]) * x + gamma_q[6 ]) * x + gamma_q[7 ]
119- if true {
120- return z * p / q
121- }
122- small:
112+ return z * p / q
113+ }
114+
115+ fn gamma_too_small (x f64 , z f64 ) f64 {
123116 if x == 0 {
124117 return inf (1 )
125118 }
119+ euler := 0.57721566490153286060651209008240243104215933593992 // A001620
126120 return z / ((1.0 + euler * x) * x)
127121}
128122
@@ -142,14 +136,6 @@ pub fn log_gamma(x f64) f64 {
142136// log_gamma_sign returns the natural logarithm and sign (-1 or +1) of Gamma(x)
143137pub fn log_gamma_sign (a f64 ) (f64 , int ) {
144138 mut x := a
145- ymin := 1.461632144968362245
146- tiny := exp2 (- 70 )
147- two52 := exp2 (52 ) // 0x4330000000000000 ~4.5036e+15
148- two58 := exp2 (58 ) // 0x4390000000000000 ~2.8823e+17
149- tc := 1.46163214496836224576e+00 // 0x3FF762D86356BE3F
150- tf := - 1.21486290535849611461e-01 // 0xBFBF19B9BCC38A42
151- // tt := -(tail of tf)
152- tt := - 3.63867699703950536541e-18 // 0xBC50C7CAA48A971F
153139 mut sign := 1
154140 if is_nan (x) {
155141 return x, sign
@@ -165,15 +151,15 @@ pub fn log_gamma_sign(a f64) (f64, int) {
165151 x = - x
166152 neg = true
167153 }
168- if x < tiny { // if |x| < 2**-70, return -log(|x|)
154+ if x < exp2 ( - 70 ) { // if |x| < 2**-70, return -log(|x|)
169155 if neg {
170156 sign = - 1
171157 }
172158 return - log (x), sign
173159 }
174160 mut nadj := 0.0
175161 if neg {
176- if x > = two 52 {
162+ if x > = exp2 ( 52 ) { // the constant is 0x4330000000000000 ~4.5036e+15
177163 // x| >= 2**52, must be -integer
178164 return inf (1 ), sign
179165 }
@@ -190,6 +176,8 @@ pub fn log_gamma_sign(a f64) (f64, int) {
190176 if x == 1 || x == 2 { // purge off 1 and 2
191177 return 0.0 , sign
192178 } else if x < 2 { // use lgamma(x) = lgamma(x+1) - log(x)
179+ ymin := 1.461632144968362245
180+ tc := 1.46163214496836224576e+00 // 0x3FF762D86356BE3F
193181 mut y := 0.0
194182 mut i := 0
195183 if x < = 0.9 {
@@ -234,6 +222,9 @@ pub fn log_gamma_sign(a f64) (f64, int) {
234222 w * lgamma_t[13 ])))
235223 gamma_p3 := lgamma_t[2 ] + w * (lgamma_t[5 ] + w * (lgamma_t[8 ] + w * (lgamma_t[11 ] +
236224 w * lgamma_t[14 ])))
225+ tf := - 1.21486290535849611461e-01 // 0xBFBF19B9BCC38A42
226+ // tt := -(tail of tf)
227+ tt := - 3.63867699703950536541e-18 // 0xBC50C7CAA48A971F
237228 p := z * gamma_p1 - (tt - w * (gamma_p2 + y * gamma_p3 ))
238229 lgamma + = (tf + p)
239230 } else if i == 2 {
@@ -278,7 +269,7 @@ pub fn log_gamma_sign(a f64) (f64, int) {
278269 z * = (y + 2 )
279270 lgamma + = log (z)
280271 }
281- } else if x < two 58 { // 8 <= x < 2**58
272+ } else if x < exp2 ( 58 ) { // 8 <= x < 2**58, which is 0x4390000000000000 ~2.8823e+17
282273 t := log (x)
283274 z := 1.0 / x
284275 y := z * z
@@ -297,8 +288,6 @@ pub fn log_gamma_sign(a f64) (f64, int) {
297288// sin_pi(x) is a helper function for negative x
298289fn sin_pi (x_ f64 ) f64 {
299290 mut x := x_
300- two52 := exp2 (52 ) // 0x4330000000000000 ~4.5036e+15
301- two53 := exp2 (53 ) // 0x4340000000000000 ~9.0072e+15
302291 if x < 0.25 {
303292 return - sin (pi * x)
304293 }
@@ -309,10 +298,11 @@ fn sin_pi(x_ f64) f64 {
309298 x = mod (x, 2 )
310299 n = int (x * 4 )
311300 } else {
312- if x > = two 53 { // x must be even
301+ if x > = exp2 ( 53 ) { // x must be even; the constant is 0x4340000000000000 ~9.0072e+15
313302 x = 0
314303 n = 0
315304 } else {
305+ two52 := exp2 (52 ) // 0x4330000000000000 ~4.5036e+15
316306 if x < two52 {
317307 z = x + two52 // exact
318308 }
0 commit comments