@@ -37,9 +37,17 @@ const LANCZOS_DEN_COEFFS: [f64; LANCZOS_N] = [
37
37
1.0 ,
38
38
] ;
39
39
40
+ fn mul_add ( a : f64 , b : f64 , c : f64 ) -> f64 {
41
+ if cfg ! ( feature = "mul_add" ) {
42
+ a. mul_add ( b, c)
43
+ } else {
44
+ a * b + c
45
+ }
46
+ }
47
+
40
48
fn lanczos_sum ( x : f64 ) -> f64 {
41
- let mut num = 0.0 ;
42
- let mut den = 0.0 ;
49
+ let mut num = 0.0f64 ;
50
+ let mut den = 0.0f64 ;
43
51
// evaluate the rational function lanczos_sum(x). For large
44
52
// x, the obvious algorithm risks overflow, so we instead
45
53
// rescale the denominator and numerator of the rational
@@ -50,8 +58,8 @@ fn lanczos_sum(x: f64) -> f64 {
50
58
// this resulted in lower accuracy.
51
59
if x < 5.0 {
52
60
for i in ( 0 ..LANCZOS_N ) . rev ( ) {
53
- num = num * x + LANCZOS_NUM_COEFFS [ i] ;
54
- den = den * x + LANCZOS_DEN_COEFFS [ i] ;
61
+ num = mul_add ( num, x , LANCZOS_NUM_COEFFS [ i] ) ;
62
+ den = mul_add ( den, x , LANCZOS_DEN_COEFFS [ i] ) ;
55
63
}
56
64
} else {
57
65
for i in 0 ..LANCZOS_N {
@@ -237,7 +245,8 @@ pub fn lgamma(x: f64) -> Result<f64, Error> {
237
245
// absorbed the exp(-lanczos_g) term, and throwing out the lanczos_g
238
246
// subtraction below; it's probably not worth it.
239
247
let mut r = lanczos_sum ( absx) . ln ( ) - LANCZOS_G ;
240
- r += ( absx - 0.5 ) * ( ( absx + LANCZOS_G - 0.5 ) . ln ( ) - 1.0 ) ;
248
+ let t = absx - 0.5 ;
249
+ r = mul_add ( t, ( absx + LANCZOS_G - 0.5 ) . ln ( ) - 1.0 , r) ;
241
250
242
251
if x < 0.0 {
243
252
// Use reflection formula to get value for negative x
0 commit comments