use super::{fma_internal, ln, log1p, sqrt, two_sum};
#[inline(always)]
pub fn asinh(x: f64) -> f64 {
let ux = x.to_bits();
let e = ((ux >> 52) & 0x7ff) as i32;
let sign = (ux >> 63) != 0;
let mut ax = f64::from_bits(ux & 0x7fff_ffff_ffff_ffffu64);
if e >= 0x3ff + 26 {
ax = ln(ax) + core::f64::consts::LN_2;
} else if e > 0x3ff {
ax = ln(2.0 * ax + 1.0 / (sqrt(ax * ax + 1.0) + ax));
} else if e >= 0x3ff - 26 {
let z = fma_internal(ax, ax, 0.0);
let s = sqrt(z + 1.0);
let t = z / (s + 1.0);
let (sum_hi, sum_lo) = two_sum(ax, t);
ax = log1p(sum_hi) + sum_lo / (1.0 + sum_hi);
} else {
return x;
}
if sign { -ax } else { ax }
}