use crate::common::f_fmla;
use crate::hyperbolic::asinhf::log_eval;
use crate::polyeval::f_polyeval6;
#[inline]
pub fn f_atanhf(x: f32) -> f32 {
let x_abs = x.to_bits() & 0x7fff_ffff;
if x_abs >= 0x3F80_0000u32 {
if x.is_nan() {
return x;
}
return if x_abs == 0x3F80_0000u32 {
if x.is_sign_positive() {
f32::INFINITY
} else {
f32::NEG_INFINITY
}
} else {
f32::NAN
};
}
if x_abs <= 0x3dcc_0000u32 {
if x_abs <= 0x3280_0000u32 {
return if x_abs == 0 {
x
} else {
(x as f64 + f64::from_bits(0x3fd5555555555555) * x as f64 * x as f64 * x as f64)
as f32
};
}
let xdbl = x as f64;
let x2 = xdbl * xdbl;
let pe = f_polyeval6(
x2,
0.0,
f64::from_bits(0x3fd5555555555555),
f64::from_bits(0x3fc999999999999a),
f64::from_bits(0x3fc2492492492492),
f64::from_bits(0x3fbc71c71c71c71c),
f64::from_bits(0x3fb745d1745d1746),
);
return f_fmla(xdbl, pe, xdbl) as f32;
}
let xdbl = x as f64;
(0.5 * log_eval((xdbl + 1.0) / (xdbl - 1.0))) as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_atanhf() {
assert_eq!(f_atanhf(0.0), 0.0);
assert_eq!(f_atanhf(1.0), f32::INFINITY);
assert!(f_atanhf(-1.5).is_nan());
assert_eq!(f_atanhf(0.25), 0.25541282);
assert_eq!(f_atanhf(0.124121), 0.12476436);
}
}