#![allow(clippy::excessive_precision)]
pub const POLY: [f32; 9] = [
7.0376836292e-2,
-1.1514610310e-1,
1.1676998740e-1,
-1.2420140846e-1,
1.4249322787e-1,
-1.6668057665e-1,
2.0000714765e-1,
-2.4999993993e-1,
3.3333331174e-1,
];
pub const LN2_HI: f32 = 0.693_359_375;
pub const LN2_LO: f32 = -2.121_944_4e-4;
pub const SPLIT: f32 = std::f32::consts::SQRT_2;
pub const SUBNORMAL_SCALE: f32 = 16_777_216.0;
pub const SUBNORMAL_SHIFT: i32 = 24;
pub fn sln(x: f32) -> f32 {
let subnormal = x < f32::MIN_POSITIVE;
let scaled = if subnormal { x * SUBNORMAL_SCALE } else { x };
let bits = scaled.to_bits();
let mut e = ((bits >> 23) & 0xff) as i32 - 127;
if subnormal {
e -= SUBNORMAL_SHIFT;
}
let mut m = f32::from_bits((bits & 0x007fffff) | 0x3f800000);
if m > SPLIT {
m *= 0.5;
e += 1;
}
let f = m - 1.0;
let f2 = f * f;
let mut p = POLY[0];
for c in &POLY[1..] {
p = p.mul_add(f, *c);
}
let e = e as f32;
let y = p * f2 * f;
let y = e.mul_add(LN2_LO, y);
let y = (-0.5f32).mul_add(f2, y) + f;
let y = e.mul_add(LN2_HI, y);
if x <= 0.0 || x.is_nan() {
if x == 0.0 { f32::NEG_INFINITY } else { f32::NAN }
} else if x.is_infinite() {
f32::INFINITY
} else {
y
}
}
routine_ew_rust!(generic;
f32,
generic_ln_f32_4n,
4,
4,
fn run(x: &mut [f32], _: ()) {
debug_assert!(x.len() % Self::nr() == 0);
debug_assert!(x.as_ptr() as usize % Self::alignment_bytes() == 0);
x.iter_mut().for_each(|px| *px = sln(*px))
},
func(Ln)
);