use crate::common::{is_integer, is_odd_integer};
use crate::gamma::lgamma::lgamma_core;
pub fn f_lgamma_r(x: f64) -> (f64, i32) {
let xb = x.to_bits().wrapping_shl(1);
if xb >= 0x7ffu64 << 53 || xb == 0 {
if x.is_nan() {
return (f64::NAN, 1);
}
if xb == 0 {
return (f64::INFINITY, 1 - 2 * ((x.to_bits() >> 63) as i32));
}
if xb.wrapping_shl(11) == 0 {
return (f64::INFINITY, 1);
}
}
if is_integer(x) {
if x == 2. || x == 1. {
return (0., 1);
}
if x.is_sign_negative() {
let is_odd = (!is_odd_integer(x)) as i32;
return (f64::INFINITY, 1 - (is_odd << 1));
}
}
let (r, sign_gam) = lgamma_core(x);
(r.to_f64(), sign_gam)
}
#[cfg(test)]
mod tests {
use crate::f_lgamma_r;
#[test]
fn test_lgamma_rf() {
assert_eq!(f_lgamma_r(-0.), (f64::INFINITY, -1));
assert_eq!(f_lgamma_r(f64::NEG_INFINITY), (f64::INFINITY, 1));
assert_eq!(f_lgamma_r(f64::INFINITY), (f64::INFINITY, 1));
assert_eq!(f_lgamma_r(0.), (f64::INFINITY, 1));
assert_eq!(f_lgamma_r(5.), (3.1780538303479458, 1));
assert_eq!(f_lgamma_r(-4.5), (-2.813084081769316, -1));
assert_eq!(f_lgamma_r(-2.0015738), (5.759666328573806, -1));
}
}