Skip to content

Commit 41163f3

Browse files
committed
fix
1 parent 20a6f44 commit 41163f3

File tree

2 files changed

+67
-5
lines changed

2 files changed

+67
-5
lines changed

src/gamma.rs

+66-4
Original file line numberDiff line numberDiff line change
@@ -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\ndef 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) {
@@ -300,9 +362,9 @@ mod tests {
300362
};
301363
let py_gamma_repr = unsafe { std::mem::transmute::<f64, i64>(py_gamma) };
302364
let rs_gamma_repr = unsafe { std::mem::transmute::<f64, i64>(rs_gamma) };
303-
// assert_eq!(py_gamma_repr, rs_gamma_repr, "x = {x}, py_gamma = {py_gamma}, rs_gamma = {rs_gamma}");
365+
assert_eq!(py_gamma_repr, rs_gamma_repr, "x = {x}, py_gamma = {py_gamma}, rs_gamma = {rs_gamma}");
304366
// allow 1 bit error for now
305-
assert!((py_gamma_repr - rs_gamma_repr).abs() <= 1, "x = {x} diff: {}, py_gamma = {py_gamma} ({py_gamma_repr:x}), rs_gamma = {rs_gamma} ({rs_gamma_repr:x})", py_gamma_repr ^ rs_gamma_repr);
367+
// assert!((py_gamma_repr - rs_gamma_repr).abs() <= 1, "x = {x} diff: {}, py_gamma = {py_gamma} ({py_gamma_repr:x}), rs_gamma = {rs_gamma} ({rs_gamma_repr:x})", py_gamma_repr ^ rs_gamma_repr);
306368
});
307369
}
308370

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ mod err;
22
mod gamma;
33

44
pub use err::Error;
5-
pub use gamma::{tgamma as gamma, lgamma};
5+
pub use gamma::{lgamma, tgamma as gamma};

0 commit comments

Comments
 (0)