use crate::polyeval::f_estrin_polyeval7;
pub fn f_log1pmxf(x: f32) -> f32 {
let ux = x.to_bits().wrapping_shl(1);
if ux >= 0xffu32 << 24 || ux == 0 {
if ux == 0 {
return x;
}
if x.is_infinite() {
return f32::NAN;
}
return x + f32::NAN;
}
let ax = x.to_bits() & 0x7fff_ffffu32;
let xd = x as f64;
if ax > 0x3c80_0000u32 {
if x == -1. {
return f32::NEG_INFINITY;
}
let x1p = xd + 1.;
if x1p <= 0. {
if x1p == 0. {
return f32::NEG_INFINITY;
}
return f32::NAN;
}
return (crate::logs::log1pf::core_logf(x1p) - xd) as f32;
}
let xd_sqr = xd * xd;
let p = f_estrin_polyeval7(
xd,
f64::from_bits(0xbfe0000000000000),
f64::from_bits(0x3fd55555555561c8),
f64::from_bits(0xbfd0000000000f5a),
f64::from_bits(0x3fc999998d26deab),
f64::from_bits(0xbfc555554878739c),
f64::from_bits(0x3fc24ab2e3c10eca),
f64::from_bits(0xbfc0017973fafec4),
) * xd_sqr;
p as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_log1pmxfm() {
assert_eq!(f_log1pmxf(-0.0000014305108), -1.0231815e-12);
assert_eq!(f_log1pmxf(0.0), 0.0);
assert_eq!(f_log1pmxf(2.0), -0.9013877);
assert_eq!(f_log1pmxf(-0.7), -0.50397277);
assert_eq!(
f_log1pmxf(-0.0000000000043243),
-0.000000000000000000000009349785
);
assert!(f_log1pmxf(f32::INFINITY).is_nan());
assert!(f_log1pmxf(f32::NAN).is_nan());
assert!(f_log1pmxf(f32::NEG_INFINITY).is_nan());
assert!(f_log1pmxf(-2.0).is_nan());
}
}