@@ -37,9 +37,17 @@ const LANCZOS_DEN_COEFFS: [f64; LANCZOS_N] = [
3737 1.0 ,
3838] ;
3939
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+
4048fn 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 ;
4351 // evaluate the rational function lanczos_sum(x). For large
4452 // x, the obvious algorithm risks overflow, so we instead
4553 // rescale the denominator and numerator of the rational
@@ -50,8 +58,8 @@ fn lanczos_sum(x: f64) -> f64 {
5058 // this resulted in lower accuracy.
5159 if x < 5.0 {
5260 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] ) ;
5563 }
5664 } else {
5765 for i in 0 ..LANCZOS_N {
@@ -237,7 +245,8 @@ pub fn lgamma(x: f64) -> Result<f64, Error> {
237245 // absorbed the exp(-lanczos_g) term, and throwing out the lanczos_g
238246 // subtraction below; it's probably not worth it.
239247 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) ;
241250
242251 if x < 0.0 {
243252 // Use reflection formula to get value for negative x
0 commit comments