use crate::constants::*;
use crate::arithmetic::fp_mul_i_fast;
use crate::error::SolMathError;
pub(crate) fn sin_core(x: i128) -> Result<i128, SolMathError> {
let t = fp_mul_i_fast(x, x);
let mut r = SIN_C11;
r = fp_mul_i_fast(r, t) + SIN_C9;
r = fp_mul_i_fast(r, t) + SIN_C7;
r = fp_mul_i_fast(r, t) + SIN_C5;
r = fp_mul_i_fast(r, t) + SIN_C3;
r = fp_mul_i_fast(r, t) + SIN_C1;
Ok(fp_mul_i_fast(r, x))
}
pub(crate) fn cos_core(x: i128) -> Result<i128, SolMathError> {
let t = fp_mul_i_fast(x, x);
let mut r = COS_C10;
r = fp_mul_i_fast(r, t) + COS_C8;
r = fp_mul_i_fast(r, t) + COS_C6;
r = fp_mul_i_fast(r, t) + COS_C4;
r = fp_mul_i_fast(r, t) + COS_C2;
r = fp_mul_i_fast(r, t) + COS_C0;
Ok(r)
}
pub(crate) fn reduce_mod_2pi(x: i128) -> i128 {
let mut r = x.rem_euclid(TWO_PI_SCALE);
if r > PI_SCALE {
r -= TWO_PI_SCALE;
}
r
}
pub fn sin_fixed(x: i128) -> Result<i128, SolMathError> {
let mut xx = reduce_mod_2pi(x);
let sign = if xx < 0 {
xx = -xx;
-1i128
} else {
1i128
};
if xx > PI_OVER_2_SCALE {
xx = PI_SCALE - xx;
}
if xx > PI_OVER_4_SCALE {
Ok(cos_core(PI_OVER_2_SCALE - xx)? * sign)
} else {
Ok(sin_core(xx)? * sign)
}
}
pub fn cos_fixed(x: i128) -> Result<i128, SolMathError> {
let mut xx = reduce_mod_2pi(x);
xx = if xx < 0 { -xx } else { xx };
let cos_sign = if xx > PI_OVER_2_SCALE {
xx = PI_SCALE - xx;
-1i128
} else {
1i128
};
if xx > PI_OVER_4_SCALE {
Ok(sin_core(PI_OVER_2_SCALE - xx)? * cos_sign)
} else {
Ok(cos_core(xx)? * cos_sign)
}
}
pub fn sincos_fixed(x: i128) -> Result<(i128, i128), SolMathError> {
let mut xx = reduce_mod_2pi(x);
let sin_sign = if xx < 0 {
xx = -xx;
-1i128
} else {
1i128
};
let cos_sign = if xx > PI_OVER_2_SCALE {
xx = PI_SCALE - xx;
-1i128
} else {
1i128
};
if xx > PI_OVER_4_SCALE {
let y = PI_OVER_2_SCALE - xx;
Ok((cos_core(y)? * sin_sign, sin_core(y)? * cos_sign))
} else {
Ok((sin_core(xx)? * sin_sign, cos_core(xx)? * cos_sign))
}
}