| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- const FP_SHIFT: i32 = 16;
- const FP_MULT: f64 = 65536.0;
- const FP_HALF: f64 = 32768.0;
- const FP_FLOOR_MASK: i32 = !((1 << FP_SHIFT) - 1);
- pub trait ToFixedPoint {
- fn to_fp(&self) -> i32;
- }
- pub trait FromFixedPoint {
- fn to_f64(&self) -> f64;
- fn to_i32(&self) -> i32;
- }
- impl ToFixedPoint for f64 {
- fn to_fp(&self) -> i32 {
- (*self * FP_MULT) as i32
- }
- }
- impl ToFixedPoint for i32 {
- fn to_fp(&self) -> i32 {
- *self << FP_SHIFT
- }
- }
- impl FromFixedPoint for i32 {
- fn to_f64(&self) -> f64 {
- *self as f64 / FP_MULT
- }
- fn to_i32(&self) -> i32 {
- *self >> FP_SHIFT
- }
- }
- pub const fn add(a: i32, b: i32) -> i32 {
- a + b
- }
- pub const fn sub(a: i32, b: i32) -> i32 {
- a - b
- }
- pub const fn mul(a: i32, b: i32) -> i32 {
- ((a as i64 * b as i64) >> FP_SHIFT) as i32
- }
- pub const fn div(a: i32, b: i32) -> i32 {
- (((a as i64) << FP_SHIFT) / b as i64) as i32
- }
- pub const fn floor(a: i32) -> i32 {
- a & FP_FLOOR_MASK
- }
- #[cfg(test)]
- mod test {
- use super::*;
- #[test]
- fn f64_add() {
- let test_pairs = [
- (0.5, 0.5),
- (-0.754, 0.123)
- ];
- for (a, b) in test_pairs {
- let fp_sum = add(a.to_fp(), b.to_fp());
- float_cmp::assert_approx_eq!(f64, fp_sum.to_f64(), a + b, epsilon = 0.003, ulps = 2)
- }
- }
- #[test]
- fn f64_sub() {
- let test_pairs = [
- (0.5, 0.5),
- (-0.754, 0.123)
- ];
- for (a, b) in test_pairs {
- let fp_diff = sub(a.to_fp(), b.to_fp());
- float_cmp::assert_approx_eq!(f64, fp_diff.to_f64(), a - b, epsilon = 0.003, ulps = 2)
- }
- }
- #[test]
- fn f64_mul() {
- let test_pairs = [
- (0.5, 0.5),
- (-0.754, 0.123)
- ];
- for (a, b) in test_pairs {
- let fp_prod = mul(a.to_fp(), b.to_fp());
- float_cmp::assert_approx_eq!(f64, fp_prod.to_f64(), a * b, epsilon = 0.003, ulps = 2)
- }
- }
- #[test]
- fn f64_div() {
- let test_pairs = [
- (0.5, 0.5),
- (-0.754, 0.123)
- ];
- for (a, b) in test_pairs {
- let fp_quot = div(a.to_fp(), b.to_fp());
- float_cmp::assert_approx_eq!(f64, fp_quot.to_f64(), a / b, epsilon = 0.003, ulps = 2)
- }
- }
- }
|