use crate::bessel::j0f::j1f_rsqrt;
use crate::exponents::core_expf;
use crate::polyeval::{f_estrin_polyeval8, f_estrin_polyeval9};
pub fn f_i2f(x: f32) -> f32 {
let ux = x.to_bits().wrapping_shl(1);
if ux >= 0xffu32 << 24 || ux == 0 {
if ux == 0 {
return 0.;
}
if x.is_infinite() {
return f32::INFINITY;
}
return x + f32::NAN; }
let xb = x.to_bits() & 0x7fff_ffff;
if xb >= 0x42b7d875u32 {
return f32::INFINITY;
}
if xb <= 0x40f80000u32 {
if xb <= 0x34000000u32 {
let dx = x as f64;
const R: f64 = 1. / 8.;
return (dx * dx * R) as f32;
}
return i2f_small(f32::from_bits(xb));
}
i2f_asympt(f32::from_bits(xb))
}
#[inline]
fn i2f_small(x: f32) -> f32 {
let dx = x as f64;
let x_sqr = dx * dx;
let p_num = f_estrin_polyeval9(
x_sqr,
f64::from_bits(0x3fc0000000000000),
f64::from_bits(0x3f831469a38d72c7),
f64::from_bits(0x3f2f453dd3dd98f4),
f64::from_bits(0x3ec8af52ee8fce9b),
f64::from_bits(0x3e5589f2cb4e0ec9),
f64::from_bits(0x3dd60fa268a4206d),
f64::from_bits(0x3d4ab3091ee18d6b),
f64::from_bits(0x3cb1efec43b15186),
f64::from_bits(0x3c050992c6e9e63f),
);
let p_den = f_estrin_polyeval8(
x_sqr,
f64::from_bits(0x3ff0000000000000),
f64::from_bits(0xbf82075d8e3f1476),
f64::from_bits(0x3f03ef86564a284b),
f64::from_bits(0xbe7c498fab4a57d8),
f64::from_bits(0x3dec162ca0f68486),
f64::from_bits(0xbd53bb6398461540),
f64::from_bits(0x3cb265215261e64a),
f64::from_bits(0xbc01cf52cc350e81),
);
let p = p_num / p_den;
(p * x_sqr) as f32
}
#[inline]
fn i2f_asympt(x: f32) -> f32 {
let dx = x as f64;
let recip = 1. / dx;
let p_num = f_estrin_polyeval9(
recip,
f64::from_bits(0x3fd9884533d45f46),
f64::from_bits(0xc02b979526807e1e),
f64::from_bits(0x406b1dd3e795bbed),
f64::from_bits(0xc09e43629031ec91),
f64::from_bits(0x40c48c03a39aec1d),
f64::from_bits(0xc0e0f022ccb8807a),
f64::from_bits(0x40f0302eeb22a776),
f64::from_bits(0xc0f02b01549d38b8),
f64::from_bits(0x40dad4e70f2bc264),
);
let p_den = f_estrin_polyeval9(
recip,
f64::from_bits(0x3ff0000000000000),
f64::from_bits(0xc0405a71a88b191c),
f64::from_bits(0x407e19f7d247d098),
f64::from_bits(0xc0aeaac6e0ca17fe),
f64::from_bits(0x40d2301702f40a98),
f64::from_bits(0xc0e7e6c6c01841b3),
f64::from_bits(0x40ed67317e9e46cc),
f64::from_bits(0xc0d13786aa1ef416),
f64::from_bits(0xc0a6c9cfe579ae22),
);
let z = p_num / p_den;
let e = core_expf(x);
let r_sqrt = j1f_rsqrt(dx);
(z * r_sqrt * e) as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_i2f() {
assert_eq!(f_i2f(0.), 0.);
assert_eq!(f_i2f(f32::INFINITY), f32::INFINITY);
assert_eq!(f_i2f(f32::NEG_INFINITY), f32::INFINITY);
assert_eq!(f_i2f(1.), 0.13574767);
assert_eq!(f_i2f(-1.), 0.13574767);
assert_eq!(f_i2f(9.432), 1314.6553);
assert_eq!(f_i2f(-9.432), 1314.6553);
}
}