use crate::common::f_fmla;
use crate::polyeval::f_polyeval4;
use crate::sin_cosf::sincosf_eval::sincosf_eval;
pub fn f_cosm1f(x: f32) -> f32 {
let x_abs = x.to_bits() & 0x7fff_ffffu32;
let x = f32::from_bits(x_abs);
if x_abs <= 0x3e49_0fdbu32 {
let xd = x as f64;
if x_abs < 0x3980_0000u32 {
let x_sqr = xd * xd;
const R: f64 = 1. / 2.;
return (-x_sqr * R) as f32;
}
let x2 = xd * xd;
let p = f_polyeval4(
x2,
f64::from_bits(0xbfe0000000000000),
f64::from_bits(0x3fa55555554ed21a),
f64::from_bits(0xbf56c16b981a61d0),
f64::from_bits(0x3ef9fc205e761f45),
);
return (p * x2) as f32;
}
if x_abs >= 0x7f80_0000u32 {
return x + f32::NAN;
}
let x_abs = (x * 0.5).to_bits();
let xd = f32::from_bits(x_abs) as f64;
let rs = sincosf_eval(xd, x_abs);
let sin_x_over_2 = f_fmla(rs.sin_y, rs.cos_k, f_fmla(rs.cosm1_y, rs.sin_k, rs.sin_k));
let sin_sqr = sin_x_over_2 * sin_x_over_2;
let cosm1x = -2. * sin_sqr;
cosm1x as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn f_cosm1f_test() {
assert_eq!(f_cosm1f(0.00015928394), -1.2685687e-8);
assert_eq!(f_cosm1f(0.0), 0.0);
assert_eq!(f_cosm1f(std::f32::consts::PI), -2.);
assert_eq!(f_cosm1f(0.5), -0.122417435);
assert_eq!(f_cosm1f(0.7), -0.2351578);
assert_eq!(f_cosm1f(1.7), -1.1288445);
assert!(f_cosm1f(f32::INFINITY).is_nan());
assert!(f_cosm1f(f32::NEG_INFINITY).is_nan());
assert!(f_cosm1f(f32::NAN).is_nan());
assert_eq!(f_cosm1f(0.0002480338), -3.076038e-8);
}
}