11use crate :: Error ;
22// use std::f64::consts::PI;
33
4-
54// Import C library functions properly
65unsafe extern "C" {
76 fn exp ( x : f64 ) -> f64 ;
@@ -197,7 +196,7 @@ pub fn tgamma(x: f64) -> Result<f64, Error> {
197196 let lanczos = lanczos_sum ( absx) ;
198197 let mut r = term3 / lanczos;
199198 r -= z * r;
200-
199+
201200 if absx < 140.0 {
202201 unsafe { r / pow ( y, absx - 0.5 ) }
203202 } else {
@@ -211,7 +210,7 @@ pub fn tgamma(x: f64) -> Result<f64, Error> {
211210 let exp_y = unsafe { exp ( y) } ;
212211 let mut r = lanczos / exp_y;
213212 r += z * r;
214-
213+
215214 if absx < 140.0 {
216215 unsafe { r * pow ( y, absx - 0.5 ) }
217216 } else {
@@ -261,19 +260,19 @@ pub fn lgamma(x: f64) -> Result<f64, Error> {
261260 // Using C's math functions through libc to match CPython
262261 let lanczos_sum_val = lanczos_sum ( absx) ;
263262 let log_lanczos = unsafe { log ( lanczos_sum_val) } ;
264-
263+
265264 // Subtract lanczos_g as a separate step
266265 let mut r = log_lanczos - LANCZOS_G ;
267-
266+
268267 // Calculate (absx - 0.5) term
269268 let factor = absx - 0.5 ;
270-
269+
271270 // Calculate log term
272271 let log_term = unsafe { log ( absx + LANCZOS_G - 0.5 ) } ;
273-
272+
274273 // Calculate the multiplication and subtraction
275274 let step2 = factor * ( log_term - 1.0 ) ;
276-
275+
277276 // Combine the results
278277 r += step2;
279278
@@ -283,11 +282,11 @@ pub fn lgamma(x: f64) -> Result<f64, Error> {
283282 let abs_sinpi = unsafe { fabs ( sinpi_val) } ;
284283 let log_abs_sinpi = unsafe { log ( abs_sinpi) } ;
285284 let log_absx = unsafe { log ( absx) } ;
286-
285+
287286 // Combine in exactly the same order as CPython
288287 r = LOG_PI - log_abs_sinpi - log_absx - r;
289288 }
290-
289+
291290 if r. is_infinite ( ) {
292291 return Err ( Error :: ERANGE ) ;
293292 }
@@ -328,9 +327,73 @@ mod tests {
328327 }
329328 }
330329
330+ #[ test]
331+ fn test_literal ( ) {
332+ // Verify single constants
333+ assert_eq ! ( PI , 3.141592653589793238462643383279502884197 ) ;
334+ assert_eq ! ( LOG_PI , 1.144729885849400174143427351353058711647 ) ;
335+ assert_eq ! ( LANCZOS_G , 6.024680040776729583740234375 ) ;
336+ assert_eq ! ( LANCZOS_G_MINUS_HALF , 5.524680040776729583740234375 ) ;
337+
338+ // Verify LANCZOS_NUM_COEFFS
339+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 0 ] , 23531376880.410759 ) ;
340+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 1 ] , 42919803642.649101 ) ;
341+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 2 ] , 35711959237.355667 ) ;
342+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 3 ] , 17921034426.037209 ) ;
343+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 4 ] , 6039542586.3520279 ) ;
344+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 5 ] , 1439720407.3117216 ) ;
345+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 6 ] , 248874557.86205417 ) ;
346+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 7 ] , 31426415.585400194 ) ;
347+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 8 ] , 2876370.6289353725 ) ;
348+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 9 ] , 186056.26539522348 ) ;
349+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 10 ] , 8071.6720023658163 ) ;
350+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 11 ] , 210.82427775157936 ) ;
351+ assert_eq ! ( LANCZOS_NUM_COEFFS [ 12 ] , 2.5066282746310002 ) ;
352+
353+ // Verify LANCZOS_DEN_COEFFS
354+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 0 ] , 0.0 ) ;
355+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 1 ] , 39916800.0 ) ;
356+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 2 ] , 120543840.0 ) ;
357+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 3 ] , 150917976.0 ) ;
358+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 4 ] , 105258076.0 ) ;
359+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 5 ] , 45995730.0 ) ;
360+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 6 ] , 13339535.0 ) ;
361+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 7 ] , 2637558.0 ) ;
362+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 8 ] , 357423.0 ) ;
363+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 9 ] , 32670.0 ) ;
364+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 10 ] , 1925.0 ) ;
365+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 11 ] , 66.0 ) ;
366+ assert_eq ! ( LANCZOS_DEN_COEFFS [ 12 ] , 1.0 ) ;
367+
368+ // Verify GAMMA_INTEGRAL
369+ assert_eq ! ( GAMMA_INTEGRAL [ 0 ] , 1.0 ) ;
370+ assert_eq ! ( GAMMA_INTEGRAL [ 1 ] , 1.0 ) ;
371+ assert_eq ! ( GAMMA_INTEGRAL [ 2 ] , 2.0 ) ;
372+ assert_eq ! ( GAMMA_INTEGRAL [ 3 ] , 6.0 ) ;
373+ assert_eq ! ( GAMMA_INTEGRAL [ 4 ] , 24.0 ) ;
374+ assert_eq ! ( GAMMA_INTEGRAL [ 5 ] , 120.0 ) ;
375+ assert_eq ! ( GAMMA_INTEGRAL [ 6 ] , 720.0 ) ;
376+ assert_eq ! ( GAMMA_INTEGRAL [ 7 ] , 5040.0 ) ;
377+ assert_eq ! ( GAMMA_INTEGRAL [ 8 ] , 40320.0 ) ;
378+ assert_eq ! ( GAMMA_INTEGRAL [ 9 ] , 362880.0 ) ;
379+ assert_eq ! ( GAMMA_INTEGRAL [ 10 ] , 3628800.0 ) ;
380+ assert_eq ! ( GAMMA_INTEGRAL [ 11 ] , 39916800.0 ) ;
381+ assert_eq ! ( GAMMA_INTEGRAL [ 12 ] , 479001600.0 ) ;
382+ assert_eq ! ( GAMMA_INTEGRAL [ 13 ] , 6227020800.0 ) ;
383+ assert_eq ! ( GAMMA_INTEGRAL [ 14 ] , 87178291200.0 ) ;
384+ assert_eq ! ( GAMMA_INTEGRAL [ 15 ] , 1307674368000.0 ) ;
385+ assert_eq ! ( GAMMA_INTEGRAL [ 16 ] , 20922789888000.0 ) ;
386+ assert_eq ! ( GAMMA_INTEGRAL [ 17 ] , 355687428096000.0 ) ;
387+ assert_eq ! ( GAMMA_INTEGRAL [ 18 ] , 6402373705728000.0 ) ;
388+ assert_eq ! ( GAMMA_INTEGRAL [ 19 ] , 1.21645100408832e+17 ) ;
389+ assert_eq ! ( GAMMA_INTEGRAL [ 20 ] , 2.43290200817664e+18 ) ;
390+ assert_eq ! ( GAMMA_INTEGRAL [ 21 ] , 5.109094217170944e+19 ) ;
391+ assert_eq ! ( GAMMA_INTEGRAL [ 22 ] , 1.1240007277776077e+21 ) ;
392+ }
393+
331394 #[ test]
332395 fn test_specific_lgamma_value ( ) {
333- let x = - 3.8510064710745118 ;
396+ let x = 0.003585187864492183 ;
334397 let rs_lgamma = lgamma ( x) . unwrap ( ) ;
335398
336399 pyo3:: prepare_freethreaded_python ( ) ;
@@ -385,6 +448,42 @@ mod tests {
385448 }
386449
387450 proptest ! {
451+ #[ test]
452+ fn test_sinpi( x: f64 ) {
453+ if !x. is_finite( ) {
454+ return Ok ( ( ) ) ;
455+ }
456+ eprintln!( "x = {x}" ) ;
457+
458+ pyo3:: prepare_freethreaded_python( ) ;
459+ Python :: with_gil( |py| {
460+ // Create Python function for comparing sinpi
461+ let py_code = PyModule :: from_code(
462+ py,
463+ c"import math\n def sinpi(x): return math.sin(math.pi * x)" ,
464+ c"" ,
465+ c"" ,
466+ )
467+ . unwrap( ) ;
468+
469+ // Get results from both implementations
470+ let rs_sinpi = m_sinpi( x) ;
471+ let py_sinpi = py_code
472+ . getattr( "sinpi" )
473+ . unwrap( )
474+ . call1( ( x, ) )
475+ . unwrap( )
476+ . extract:: <f64 >( )
477+ . unwrap( ) ;
478+
479+ // Check if they're close enough
480+ // Get bit representation for detailed comparison
481+ let rs_bits = unsafe { std:: mem:: transmute:: <f64 , i64 >( rs_sinpi) } ;
482+ let py_bits = unsafe { std:: mem:: transmute:: <f64 , i64 >( py_sinpi) } ;
483+ assert_eq!( rs_bits, py_bits) ;
484+ } ) ;
485+ }
486+
388487 #[ test]
389488 fn test_tgamma( x: f64 ) {
390489 let rs_gamma = tgamma( x) ;
0 commit comments