use super::scalar::DetF32;
impl DetF32 {
#[inline(never)]
pub fn sin(self) -> Self {
let x = self.rem_2pi();
let x2 = x * x;
let x3 = x2 * x;
let x5 = x3 * x2;
let x7 = x5 * x2;
let x9 = x7 * x2;
x - x3 * Self::from_bits(0x3e2aaaab) + x5 * Self::from_bits(0x3c088889) - x7 * Self::from_bits(0x39500d01) + x9 * Self::from_bits(0x3638ef1d) }
#[inline(never)]
pub fn cos(self) -> Self {
let x = self.rem_2pi();
let x2 = x * x;
let x4 = x2 * x2;
let x6 = x4 * x2;
let x8 = x6 * x2;
Self::ONE
- x2 * Self::HALF + x4 * Self::from_bits(0x3d2aaaab) - x6 * Self::from_bits(0x3a93f27e) + x8 * Self::from_bits(0x37d00d01) }
fn rem_2pi(self) -> Self {
let two_pi = DetF32::from_f32(std::f32::consts::TAU); let inv_two_pi = DetF32::from_f32(1.0 / std::f32::consts::TAU);
let n = (self * inv_two_pi).floor();
self - n * two_pi
}
#[inline(never)]
fn floor(self) -> Self {
let val = self.to_f32();
let truncated = val as i32 as f32;
if val >= 0.0 || val == truncated {
Self::from_f32(truncated)
} else {
Self::from_f32(truncated - 1.0)
}
}
#[inline(never)]
pub fn atan2(y: Self, x: Self) -> Self {
if x == Self::ZERO && y == Self::ZERO {
return Self::ZERO;
}
let abs_x = x.abs();
let abs_y = y.abs();
let (a, b, swap) = if abs_y > abs_x {
(abs_x, abs_y, true)
} else {
(abs_y, abs_x, false)
};
let t = a / b;
let t2 = t * t;
let mut angle = t
* (Self::ONE
- t2 * (Self::from_bits(0x3eaaaaab) - t2 * (Self::from_bits(0x3e4ccccd) - t2 * Self::from_bits(0x3e124925))));
if swap {
angle = Self::from_bits(0x3fc90fdb) - angle; }
if x.to_bits() & 0x80000000 != 0 {
angle = Self::PI - angle;
}
if y.to_bits() & 0x80000000 != 0 {
angle = -angle;
}
angle
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sin_cos_identity() {
let angle = DetF32::from_bits(0x3f490fdb); let s = angle.sin();
let c = angle.cos();
let sum = s * s + c * c;
assert!((sum - DetF32::ONE).abs() < DetF32::from_f32(1e-4));
}
#[test]
fn test_trig_exact_bits() {
let angle = DetF32::from_bits(0x3f490fdb);
let result1 = angle.sin();
let result2 = angle.sin();
assert_eq!(result1.to_bits(), result2.to_bits());
}
}