Skip to content

Commit c34f7bd

Browse files
committed
fix
1 parent d991c6e commit c34f7bd

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

src/gamma.rs

Lines changed: 64 additions & 2 deletions
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) {

0 commit comments

Comments
 (0)