use crate::common::f_fmla;
use crate::sin_cosf::ArgumentReducerPi;
use crate::tangent::evalf::tanpif_eval;
#[inline]
pub fn f_cotpif(x: f32) -> f32 {
let ix = x.to_bits();
let e = ix & (0xff << 23);
if e > (150 << 23) {
if e == (0xff << 23) {
if (ix.wrapping_shl(9)) == 0 {
return f32::NAN;
}
return x + x; }
return f32::INFINITY;
}
let argument_reduction = ArgumentReducerPi { x: x as f64 };
let (y, k) = argument_reduction.reduce();
if y == 0.0 {
let km = (k.abs() & 31) as i32;
match km {
0 => return f32::copysign(f32::INFINITY, x), 16 => return 0.0f32.copysign(x), 8 => return f32::copysign(1.0, x), 24 => return -f32::copysign(1.0, x), _ => {}
}
}
let ax = ix & 0x7fff_ffff;
if ax < 0x3bc49ba6u32 {
let dx = x as f64;
let dx_sqr = dx * dx;
const ONE_OVER_PI: f64 = f64::from_bits(0x3fd45f306dc9c883);
let r = f_fmla(
dx_sqr,
f64::from_bits(0xbfe60c8539c1dc14),
f64::from_bits(0xbff0c152382d7366),
);
let rcp = 1. / dx;
return f_fmla(rcp, ONE_OVER_PI, r * dx) as f32;
}
let rs = tanpif_eval(y, k);
let num = rs.tan_y + rs.tan_k;
let den = f_fmla(rs.tan_y, -rs.tan_k, 1.);
(den / num) as f32
}
#[inline]
pub(crate) fn cotpif_core(x: f64) -> f64 {
let argument_reduction = ArgumentReducerPi { x };
let (y, k) = argument_reduction.reduce();
let rs = tanpif_eval(y, k);
let num = rs.tan_y + rs.tan_k;
let den = f_fmla(rs.tan_y, -rs.tan_k, 1.);
den / num
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cotpif() {
assert_eq!(f_cotpif(0.00046277765), 687.82416);
assert_eq!(f_cotpif(2.3588752e-6), 134941.39);
assert_eq!(f_cotpif(10775313000000000000000000000000.), f32::INFINITY);
assert_eq!(f_cotpif(5.5625), -0.19891237);
assert_eq!(f_cotpif(-29.75), 1.0);
assert_eq!(f_cotpif(-21.5625), 0.19891237);
assert_eq!(f_cotpif(-15.611655), 0.3659073);
assert_eq!(f_cotpif(115.30706), 0.693186);
assert_eq!(f_cotpif(0.), f32::INFINITY);
assert!(f_cotpif(f32::INFINITY).is_nan());
assert!(f_cotpif(f32::NAN).is_nan());
}
}