use super::{
approx_cos::approx_cos, approx_sin::approx_sin, reduce::reduce, Float256,
FP492,
};
use crate::{f256, HI_ABS_MASK};
impl f256 {
#[inline(always)]
#[must_use]
pub fn cos(&self) -> Self {
if self.is_special() {
if (self.bits.hi.0 & HI_ABS_MASK) > Self::MAX.bits.hi.0 {
return Self::NAN;
}
return Self::ONE;
}
let (quadrant, fx) = reduce(&self.abs());
match quadrant {
0 => Self::from(&approx_cos(&fx)),
1 => -Self::from(&approx_sin(&fx)),
2 => -Self::from(&approx_cos(&fx)),
3 => Self::from(&approx_sin(&fx)),
_ => unreachable!(),
}
}
}
#[cfg(test)]
mod cos_tests {
use core::str::FromStr;
use super::*;
use crate::consts::FRAC_PI_3;
#[test]
fn test_neg_values() {
for f in [f256::MIN, -FRAC_PI_3, f256::NEG_ONE] {
assert_eq!(f.cos(), f.abs().cos());
}
}
#[test]
fn test_very_small_value() {
let f = f256::from_sign_exp_signif(
0,
-355,
(
0x0000198008d7e326fca4eaaddac8f3a6,
0x4033b94a21af2db28e7aa2336d79615f,
),
);
let cos_f = f256::from_sign_exp_signif(
0,
-237,
(
0x00001fffffffffffffffffffffffffff,
0xffffffffffffffffffffffffffffffff,
),
);
assert_eq!(f.cos(), cos_f);
}
#[test]
fn test_some_lt_2pi() {
let f = f256::from_sign_exp_signif(
0,
-235,
(
0x00001fb29fe6c2bb05604696f175f2d5,
0xf484b7bfe311af1286402ac83b589d66,
),
);
let cos_f = f256::from_sign_exp_signif(
1,
-237,
(
0x000015d100d1d896598bcfdb27f38ee5,
0x5495ad9278b46941fc542a78cf6d980d,
),
);
assert_eq!(f.cos(), cos_f);
}
}