diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b03400b..90bbd777 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Fixed inaccuracy in cosine implementation caused by accidentally multiplying correction term by zero. + ## [0.17.1] - 2023/10/05 ### Fixed diff --git a/agb-fixnum/src/lib.rs b/agb-fixnum/src/lib.rs index 3ba3a47f..8b0d1b0c 100644 --- a/agb-fixnum/src/lib.rs +++ b/agb-fixnum/src/lib.rs @@ -133,7 +133,7 @@ macro_rules! upcast_multiply_impl { .wrapping_mul(b_frac) .wrapping_add(b_floor.wrapping_mul(a_frac)), ) - .wrapping_add(a_frac.wrapping_mul(b_frac) >> n) + .wrapping_add(((a_frac as u32).wrapping_mul(b_frac as u32) >> n) as $T) } }; ($T: ty, $Upcast: ty) => { @@ -533,17 +533,10 @@ impl Num { /// ``` #[must_use] pub fn cos(self) -> Self { - let one: Self = I::one().into(); let mut x = self; - let four: I = 4.into(); - let two: I = 2.into(); - let sixteen: I = 16.into(); - let nine: I = 9.into(); - let forty: I = 40.into(); - - x -= one / four + (x + one / four).floor(); - x *= (x.abs() - one / two) * sixteen; - x += x * (x.abs() - one) * (nine / forty); + x -= num!(0.25) + (x + num!(0.25)).floor(); + x *= (x.abs() - num!(0.5)) * num!(16.); + x += x * (x.abs() - num!(1.)) * num!(0.225); x } @@ -1234,6 +1227,26 @@ mod tests { test_base::<11>(); } + #[test] + fn check_cos_accuracy() { + let n: Num = Num::new(1) / 32; + assert_eq!( + n.cos(), + Num::from_f64((2. * core::f64::consts::PI / 32.).cos()) + ); + } + + #[test] + fn check_16_bit_precision_i32() { + let a: Num = num!(1.923); + let b = num!(2.723); + + assert_eq!( + a * b, + Num::from_raw(((a.to_raw() as i64 * b.to_raw() as i64) >> 16) as i32) + ) + } + #[test] fn test_numbers() { // test addition