use core::f64::consts::FRAC_PI_2;
use crate::soft_f64::F64;
use super::{
helpers::{k_cosf, k_sinf, rem_pio2f},
F32,
};
const S1_PIO2: F64 = f64!(1.).mul(f64!(FRAC_PI_2));
const S2_PIO2: F64 = f64!(2.).mul(f64!(FRAC_PI_2));
const S3_PIO2: F64 = f64!(3.).mul(f64!(FRAC_PI_2));
const S4_PIO2: F64 = f64!(4.).mul(f64!(FRAC_PI_2));
pub const fn sinf(x: F32) -> F32 {
let x64 = x.to_f64();
let x1p120 = F32::from_bits(0x7b800000);
let mut ix = x.to_bits();
let sign = (ix >> 31) != 0;
ix &= 0x7fffffff;
if ix <= 0x3f490fda {
if ix < 0x39800000 {
if ix < 0x00800000 {
let _ = x.div(x1p120);
} else {
let _ = x.add(x1p120);
};
return x;
}
return k_sinf(x64);
}
if ix <= 0x407b53d1 {
if ix <= 0x4016cbe3 {
if sign {
return k_cosf(x64.add(S1_PIO2)).neg();
} else {
return k_cosf(x64.sub(S1_PIO2));
}
}
return k_sinf(if sign {
x64.add(S2_PIO2).neg()
} else {
x64.sub(S2_PIO2).neg()
});
}
if ix <= 0x40e231d5 {
if ix <= 0x40afeddf {
if sign {
return k_cosf(x64.add(S3_PIO2));
} else {
return k_cosf(x64.sub(S3_PIO2)).neg();
}
}
return k_sinf(if sign {
x64.add(S4_PIO2)
} else {
x64.sub(S4_PIO2)
});
}
if ix >= 0x7f800000 {
return x.sub(x);
}
let (n, y) = rem_pio2f(x);
match n & 3 {
0 => k_sinf(y),
1 => k_cosf(y),
2 => k_sinf(y.neg()),
_ => k_cosf(y).neg(),
}
}
#[cfg(test)]
mod test {
use core::f32::consts::{FRAC_2_PI, FRAC_PI_2, FRAC_PI_3, PI};
use super::*;
#[test]
fn test_basic() {
for val in [0.0, FRAC_PI_3, FRAC_PI_2, PI, FRAC_2_PI] {
assert_eq!(F32::from_native_f32(val).sin().to_native_f32(), val.sin())
}
}
}