Fix cos term (#498)

One of the finer cosine terms was not correct. By using the num macro
(not available at the time of this functions initial writing) we can
avoid issues of incorrect constants.

Fixes #497

- [x] Changelog updated
This commit is contained in:
Corwin 2023-10-10 20:14:51 +01:00 committed by GitHub
commit cd6e8d1346
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 11 deletions

View file

@ -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

View file

@ -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<I: FixedWidthSignedInteger, const N: usize> Num<I, N> {
/// ```
#[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<i32, 8> = 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<i32, 16> = 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