#![allow(clippy::excessive_precision)]
pub const POLY: [f32; 7] = [
1.383684405e-03,
8.374815793e-03,
4.166822560e-02,
1.666642017e-01,
4.999999208e-01,
1.000000036e+00,
1.000000001e+00,
];
pub const LOG2E: f32 = 1.442_695_04;
pub const LN2_HI: f32 = 0.693_145_75;
pub const LN2_LO: f32 = 1.428_606_8e-6;
pub const LOW: f32 = -104.0;
pub const HIGH: f32 = 89.0;
pub const SCALE_BIAS: i32 = 127;
pub const MAGIC: f32 = 12_582_912.0;
pub fn sexp(x: f32) -> f32 {
let x = x.clamp(LOW, HIGH);
let kf = (x * LOG2E + MAGIC) - MAGIC;
let r = kf.mul_add(-LN2_LO, kf.mul_add(-LN2_HI, x));
let mut q = POLY[0];
for c in &POLY[1..] {
q = q.mul_add(r, *c);
}
let k = kf as i32;
let low = k >> 1;
let high = k - low;
let scale_low = f32::from_bits(((low + SCALE_BIAS) as u32) << 23);
let scale_high = f32::from_bits(((high + SCALE_BIAS) as u32) << 23);
q * scale_low * scale_high
}
routine_ew_rust!(generic;
f32,
generic_exp_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 = sexp(*px))
},
func(Exp)
);