fixnum_approx_eq/
macros.rs

1/// Assertion that two values are approximately equal
2/// up to some absolute tolerance (constant value)
3#[macro_export]
4macro_rules! assert_approx_eq_abs {
5    ($left:expr, $right:expr, $tolerance:expr $(,)?) => {{
6        assert!(
7            $crate::comparisons::are_approx_eq_abs($left, $right, $tolerance).unwrap(),
8            "{:?} != {:?} with absolute tolerance {:?}",
9            $left,
10            $right,
11            $tolerance
12        );
13    }};
14}
15
16/// Assertion that two values are approximately equal
17/// up to some relative tolerance (percentage of their magnitude `a.abs() + b.abs()`)
18#[macro_export]
19macro_rules! assert_approx_eq_rel {
20    ($left:expr, $right:expr, $tolerance_percentage:expr $(,)?) => {{
21        assert!(
22            $crate::comparisons::are_approx_eq_rel($left, $right, $tolerance_percentage).unwrap(),
23            "{:?} != {:?} with relative tolerance (%) {:?}",
24            $left,
25            $right,
26            $tolerance_percentage
27        );
28    }};
29}
30
31/// Assertion if two numbers `left` and `right` are equal up to some tolerance.
32///
33/// See details in [crate::comparisons::are_approx_eq].
34#[macro_export]
35macro_rules! assert_approx_eq {
36    ($left:expr, $right:expr, $abs_tolerance:expr, $rel_percentage:expr $(,)?) => {{
37        assert!(
38            $crate::comparisons::are_approx_eq($left, $right, $abs_tolerance, $rel_percentage)
39                .unwrap(),
40            "{:?} != {:?} with absolute tolerance {:?} and relative tolerance (%) {:?}",
41            $left,
42            $right,
43            $abs_tolerance,
44            $rel_percentage,
45        );
46    }};
47}
48
49#[cfg(test)]
50mod tests {
51    use fixnum::typenum::U18;
52    use fixnum::{fixnum, FixedPoint};
53
54    #[test]
55    fn assert_approx_eq_works() {
56        assert_approx_eq!(
57            FixedPoint::<i128, U18>::from(fixnum!(0.99, 18)),
58            FixedPoint::<i128, U18>::from(fixnum!(1.01, 18)),
59            FixedPoint::<i128, U18>::from(fixnum!(0.02, 18)),
60            FixedPoint::<i128, U18>::from(fixnum!(0.01, 18))
61        );
62        assert_approx_eq!(
63            FixedPoint::<i128, U18>::from_bits(100000000000000),
64            FixedPoint::<i128, U18>::from_bits(100000000000002),
65            FixedPoint::<i128, U18>::from_bits(2),
66            FixedPoint::<i128, U18>::from(fixnum!(0.0000000000001, 18)),
67        );
68        assert_approx_eq!(
69            FixedPoint::<i128, U18>::try_from(49f64).unwrap(),
70            FixedPoint::<i128, U18>::try_from(51f64).unwrap(),
71            FixedPoint::<i128, U18>::try_from(2.01f64).unwrap(),
72            FixedPoint::<i128, U18>::try_from(0.02f64).unwrap()
73        );
74    }
75
76    #[test]
77    #[should_panic]
78    fn assert_approx_eq_fails_u128() {
79        assert_approx_eq!(
80            FixedPoint::<i128, U18>::from(fixnum!(0.99, 18)),
81            FixedPoint::<i128, U18>::from(fixnum!(1.01001, 18)),
82            FixedPoint::<i128, U18>::from(fixnum!(0.02, 18)),
83            FixedPoint::<i128, U18>::from(fixnum!(0.01, 18))
84        );
85    }
86
87    #[test]
88    #[should_panic]
89    fn assert_approx_eq_fails_fixed() {
90        assert_approx_eq!(
91            FixedPoint::<i128, U18>::from_bits(100000000000000),
92            FixedPoint::<i128, U18>::from_bits(100000000000003),
93            FixedPoint::<i128, U18>::from_bits(2),
94            FixedPoint::<i128, U18>::from(fixnum!(0.000000000000005, 18)),
95        );
96    }
97
98    #[test]
99    #[should_panic]
100    fn assert_approx_eq_fails_f64() {
101        // both fail
102        assert_approx_eq!(
103            FixedPoint::<i128, U18>::try_from(49f64).unwrap(),
104            FixedPoint::<i128, U18>::try_from(51.1f64).unwrap(),
105            FixedPoint::<i128, U18>::try_from(2f64).unwrap(),
106            FixedPoint::<i128, U18>::try_from(0.02f64).unwrap()
107        );
108    }
109
110    #[test]
111    fn assert_approx_eq_abs_works() {
112        assert_approx_eq_abs!(
113            FixedPoint::<i128, U18>::from(fixnum!(0.99, 18)),
114            FixedPoint::<i128, U18>::from(fixnum!(1.01, 18)),
115            FixedPoint::<i128, U18>::from(fixnum!(0.02, 18))
116        );
117        assert_approx_eq_abs!(
118            FixedPoint::<i128, U18>::from_bits(100000000000000),
119            FixedPoint::<i128, U18>::from_bits(100000000000002),
120            FixedPoint::<i128, U18>::from_bits(2),
121        );
122        assert_approx_eq_abs!(
123            FixedPoint::<i128, U18>::try_from(49f64).unwrap(),
124            FixedPoint::<i128, U18>::try_from(51f64).unwrap(),
125            FixedPoint::<i128, U18>::try_from(2.01f64).unwrap()
126        );
127    }
128
129    #[test]
130    fn assert_approx_eq_rel_works() {
131        assert_approx_eq_rel!(
132            FixedPoint::<i128, U18>::from(fixnum!(0.99, 18)),
133            FixedPoint::<i128, U18>::from(fixnum!(1.01, 18)),
134            FixedPoint::<i128, U18>::from(fixnum!(0.01, 18))
135        );
136        assert_approx_eq_rel!(
137            FixedPoint::<i128, U18>::from_bits(100000000000000),
138            FixedPoint::<i128, U18>::from_bits(100000000000002),
139            FixedPoint::<i128, U18>::from(fixnum!(0.0000000000001, 18)),
140        );
141        assert_approx_eq_rel!(
142            FixedPoint::<i128, U18>::try_from(49f64).unwrap(),
143            FixedPoint::<i128, U18>::try_from(51f64).unwrap(),
144            FixedPoint::<i128, U18>::try_from(0.02f64).unwrap()
145        );
146    }
147}