@@ -173,7 +173,7 @@ pub fn tgamma(x: f64) -> Result<f64, Error> {
173173 q - absx
174174 } ;
175175 let z = z * LANCZOS_G / y;
176- let r = if x < 0.0 {
176+ let mut r = if x < 0.0 {
177177 let mut r = -PI / m_sinpi ( absx) / absx * y. exp ( ) / lanczos_sum ( absx) ;
178178 r -= z * r;
179179 if absx < 140.0 {
@@ -196,6 +196,7 @@ pub fn tgamma(x: f64) -> Result<f64, Error> {
196196 }
197197 r
198198 } ;
199+
199200 if r. is_infinite ( ) {
200201 return Err ( ( f64:: INFINITY , Error :: ERANGE ) . 1 ) ;
201202 } else {
@@ -241,7 +242,14 @@ pub fn lgamma(x: f64) -> Result<f64, Error> {
241242
242243 if x < 0.0 {
243244 // Use reflection formula to get value for negative x
244- r = LOG_PI - m_sinpi ( absx) . abs ( ) . ln ( ) - absx. ln ( ) - r;
245+
246+ // Calculate the sin(pi * x) value using m_sinpi
247+ let sinpi_val = m_sinpi ( absx) ;
248+
249+ // In CPython, the expression is:
250+ // r = logpi - log(fabs(m_sinpi(absx))) - log(absx) - r;
251+ // We'll match this order exactly
252+ r = LOG_PI - sinpi_val. abs ( ) . ln ( ) - absx. ln ( ) - r;
245253 }
246254 if r. is_infinite ( ) {
247255 return Err ( Error :: ERANGE ) ;
@@ -283,6 +291,60 @@ mod tests {
283291 }
284292 }
285293
294+ #[ test]
295+ fn test_specific_lgamma_value ( ) {
296+ let x = -3.8510064710745118 ;
297+ let rs_lgamma = lgamma ( x) . unwrap ( ) ;
298+
299+ pyo3:: prepare_freethreaded_python ( ) ;
300+ Python :: with_gil ( |py| {
301+ let math = PyModule :: import ( py, "math" ) . unwrap ( ) ;
302+ let py_lgamma = math
303+ . getattr ( "lgamma" )
304+ . unwrap ( )
305+ . call1 ( ( x, ) )
306+ . unwrap ( )
307+ . extract :: < f64 > ( )
308+ . unwrap ( ) ;
309+
310+ println ! ( "x = {}" , x) ;
311+ println ! ( "Python lgamma = {} ({:x})" , py_lgamma, unsafe {
312+ std:: mem:: transmute:: <f64 , u64 >( py_lgamma)
313+ } ) ;
314+ println ! ( "Rust lgamma = {} ({:x})" , rs_lgamma, unsafe {
315+ std:: mem:: transmute:: <f64 , u64 >( rs_lgamma)
316+ } ) ;
317+
318+ // Print intermediate values
319+ let absx = x. abs ( ) ;
320+ let sinpi_val = m_sinpi ( absx) ;
321+
322+ println ! ( "absx = {}" , absx) ;
323+ println ! ( "m_sinpi = {}" , sinpi_val) ;
324+
325+ // Compare with Python's sin(pi * x)
326+ let py_code = PyModule :: from_code (
327+ py,
328+ c"import math\n def sinpi(x): return math.sin(math.pi * x)\n " ,
329+ c"" ,
330+ c"" ,
331+ )
332+ . unwrap ( ) ;
333+ let py_sinpi = py_code
334+ . getattr ( "sinpi" )
335+ . unwrap ( )
336+ . call1 ( ( absx, ) )
337+ . unwrap ( )
338+ . extract :: < f64 > ( )
339+ . unwrap ( ) ;
340+ println ! ( "Python sinpi = {}" , py_sinpi) ;
341+
342+ let py_lgamma_repr = unsafe { std:: mem:: transmute :: < f64 , u64 > ( py_lgamma) } ;
343+ let rs_lgamma_repr = unsafe { std:: mem:: transmute :: < f64 , u64 > ( rs_lgamma) } ;
344+ println ! ( "Bit difference: {}" , py_lgamma_repr ^ rs_lgamma_repr) ;
345+ } ) ;
346+ }
347+
286348 proptest ! {
287349 #[ test]
288350 fn test_tgamma( x: f64 ) {
0 commit comments