use crate::polyeval::f_polyeval6;
pub fn f_sqrt1pm1f(x: f32) -> f32 {
let ix = x.to_bits();
let ux = ix.wrapping_shl(1);
if ux >= 0xffu32 << 24 || ux <= 0x68000000u32 {
if ux == 0 {
return 0.;
}
if ux.wrapping_shl(8) == 0 {
return if x.is_sign_negative() {
f32::NAN
} else {
f32::INFINITY
};
}
if ux <= 0x68000000u32 {
#[cfg(any(
all(
any(target_arch = "x86", target_arch = "x86_64"),
target_feature = "fma"
),
target_arch = "aarch64"
))]
{
use crate::common::f_fmlaf;
return f_fmlaf(-0.25 * x, 0.25 * x, x * 0.5);
}
#[cfg(not(any(
all(
any(target_arch = "x86", target_arch = "x86_64"),
target_feature = "fma"
),
target_arch = "aarch64"
)))]
{
use crate::common::f_fmla;
let dx = x as f64;
return f_fmla(-0.25 * dx, 0.25 * dx, dx * 0.5) as f32;
}
}
return f32::NAN; }
if (ix >> 31) != 0 && ux >= 0x7f00_0000 {
if ux == 0x7f00_0000u32 {
return -1.;
}
return f32::NAN;
}
if ux <= 0x78eb_851eu32 {
const C: [u64; 6] = [
0x3fe0000000000034,
0xbfc00000000002ee,
0x3faffffffc0d541c,
0xbfa3fffffa546ce5,
0x3f9c016d2be05c25,
0xbf95016d1ae9e058,
];
let dx = x as f64;
let p = f_polyeval6(
dx,
f64::from_bits(C[0]),
f64::from_bits(C[1]),
f64::from_bits(C[2]),
f64::from_bits(C[3]),
f64::from_bits(C[4]),
f64::from_bits(C[5]),
) * dx;
return p as f32;
}
let dx = x as f64;
((dx + 1.).sqrt() - 1.) as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sqrt1pm1f() {
assert_eq!(f_sqrt1pm1f(-0.9), -0.6837722);
assert_eq!(f_sqrt1pm1f(24.), 4.);
assert_eq!(f_sqrt1pm1f(-0.75), -0.5);
assert_eq!(f_sqrt1pm1f(8.), 2.);
assert_eq!(f_sqrt1pm1f(9.), 2.1622777);
assert_eq!(f_sqrt1pm1f(12.31), 2.6482873);
assert_eq!(f_sqrt1pm1f(0.005231), 0.0026120886);
assert_eq!(f_sqrt1pm1f(0.00000000005231), 2.6155e-11);
assert_eq!(f_sqrt1pm1f(-0.00000000005231), -2.6155e-11);
assert_eq!(f_sqrt1pm1f(0.), 0.);
assert_eq!(f_sqrt1pm1f(-0.), 0.);
assert_eq!(f_sqrt1pm1f(f32::INFINITY), f32::INFINITY);
assert!(f_sqrt1pm1f(f32::NEG_INFINITY).is_nan());
assert!(f_sqrt1pm1f(f32::NAN).is_nan());
assert!(f_sqrt1pm1f(-1.0001).is_nan());
}
}