use crate::consts::{FRAC_PI_2, PI, TAU};
use crate::round::absf;
#[inline]
pub fn sinf(x: f32) -> f32 {
let x = normalize_angle(x);
if x >= 0.0 {
sin_approx(x)
} else {
-sin_approx(-x)
}
}
#[inline]
pub fn cosf(x: f32) -> f32 {
sinf(x + FRAC_PI_2)
}
#[inline]
pub fn tanf(x: f32) -> f32 {
let c = cosf(x);
if absf(c) < 1e-10 {
if c >= 0.0 {
f32::MAX
} else {
f32::MIN
}
} else {
sinf(x) / c
}
}
fn sin_approx(x: f32) -> f32 {
let x = if x > PI { x - PI } else { x };
let num = 16.0 * x * (PI - x);
let den = 5.0 * PI * PI - 4.0 * x * (PI - x);
let result = num / den;
if x > PI {
-result
} else {
result
}
}
#[inline]
fn normalize_angle(x: f32) -> f32 {
let mut x = x;
if x >= -PI && x <= PI {
return x;
}
x = x - ((x / TAU) as i32 as f32) * TAU;
if x > PI {
x - TAU
} else if x < -PI {
x + TAU
} else {
x
}
}
#[inline]
pub fn asinf(x: f32) -> f32 {
let x = if x < -1.0 {
-1.0
} else if x > 1.0 {
1.0
} else {
x
};
let x2 = x * x;
let x3 = x2 * x;
x + x3 * (1.0 / 6.0 + x2 * (3.0 / 40.0 + x2 * (15.0 / 336.0)))
}
#[inline]
pub fn acosf(x: f32) -> f32 {
FRAC_PI_2 - asinf(x)
}
#[inline]
pub fn atanf(x: f32) -> f32 {
if absf(x) > 1.0 {
let sign = if x > 0.0 { 1.0 } else { -1.0 };
return sign * FRAC_PI_2 - atanf(1.0 / x);
}
let x2 = x * x;
let x3 = x2 * x;
let x5 = x3 * x2;
let x7 = x5 * x2;
x - x3 / 3.0 + x5 / 5.0 - x7 / 7.0
}
#[inline]
pub fn atan2f(y: f32, x: f32) -> f32 {
if x == 0.0 {
if y > 0.0 {
return FRAC_PI_2;
} else if y < 0.0 {
return -FRAC_PI_2;
} else {
return 0.0;
}
}
let atan = atanf(y / x);
if x > 0.0 {
atan
} else if y >= 0.0 {
atan + PI
} else {
atan - PI
}
}
#[inline]
pub fn sincosf(x: f32) -> (f32, f32) {
let s = sinf(x);
let c = cosf(x);
(s, c)
}