use core::mem::transmute;
#[inline(always)]
pub fn abs(value: f32) -> f32 {
unsafe { transmute::<u32, f32>(transmute::<f32, u32>(value) & 0x7fffffff) }
}
#[inline(always)]
pub fn is_negative(value: f32) -> bool {
unsafe { transmute::<f32, u32>(value) >= 0x80000000 }
}
#[inline(always)]
pub fn is_positive(value: f32) -> bool {
unsafe { transmute::<f32, u32>(value) < 0x80000000 }
}
#[inline(always)]
pub fn flipsign(value: f32) -> f32 {
unsafe { transmute::<u32, f32>(transmute::<f32, u32>(value) ^ 0x80000000) }
}
#[inline(always)]
pub fn copysign(value: f32, sign: f32) -> f32 {
unsafe {
transmute::<u32, f32>(
(transmute::<f32, u32>(value) & 0x7fffffff) | (transmute::<f32, u32>(sign) & 0x80000000),
)
}
}
pub fn atan(mut x: f32) -> f32 {
const ATAN_HI: [f32; 4] = [
4.6364760399e-01,
7.8539812565e-01,
9.8279368877e-01,
1.5707962513e+00,
];
const ATAN_LO: [f32; 4] = [
5.0121582440e-09,
3.7748947079e-08,
3.4473217170e-08,
7.5497894159e-08,
];
const A_T: [f32; 5] =
[3.3333328366e-01, -1.9999158382e-01, 1.4253635705e-01, -1.0648017377e-01, 6.1687607318e-02];
let x1p_120 = f32::from_bits(0x03800000);
let z: f32;
let mut ix = x.to_bits();
let sign = (ix >> 31) != 0;
ix &= 0x7fffffff;
if ix >= 0x4c800000 {
if x.is_nan() {
return x;
}
z = ATAN_HI[3] + x1p_120;
return if sign {
-z
} else {
z
};
}
let id = if ix < 0x3ee00000 {
if ix < 0x39800000 {
return x;
}
-1
} else {
x = abs(x);
if ix < 0x3f980000 {
if ix < 0x3f300000 {
x = (2. * x - 1.) / (2. + x);
0
} else {
x = (x - 1.) / (x + 1.);
1
}
} else if ix < 0x401c0000 {
x = (x - 1.5) / (1. + 1.5 * x);
2
} else {
x = -1. / x;
3
}
};
z = x * x;
let w = z * z;
let s1 = z * (A_T[0] + w * (A_T[2] + w * A_T[4]));
let s2 = w * (A_T[1] + w * A_T[3]);
if id < 0 {
return x - x * (s1 + s2);
}
let id = id as usize;
let z = ATAN_HI[id] - ((x * (s1 + s2) - ATAN_LO[id]) - x);
if sign {
-z
} else {
z
}
}