float_cmp/
macros.rs

1#[macro_export]
2macro_rules! approx_eq {
3    ($typ:ty, $lhs:expr, $rhs:expr) => {
4        {
5            let m = <$typ as $crate::ApproxEq>::Margin::default();
6            <$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, m)
7        }
8    };
9    ($typ:ty, $lhs:expr, $rhs:expr $(, $set:ident = $val:expr)*) => {
10        {
11            use $crate::FloatMargin;
12            let m = <$typ as $crate::ApproxEq>::Margin::zero()$(.$set($val))*;
13            <$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, m)
14        }
15    };
16    ($typ:ty, $lhs:expr, $rhs:expr, $marg:expr) => {
17        {
18            <$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, $marg)
19        }
20    };
21}
22
23#[macro_export]
24macro_rules! assert_approx_eq {
25    ($typ:ty, $lhs:expr, $rhs:expr) => {
26        {
27            match (&$lhs, &$rhs) {
28                (left_val, right_val) => {
29                    if !$crate::approx_eq!($typ, *left_val, *right_val) {
30                        panic!(
31                            r#"assertion failed: `(left approx_eq right)`
32  left: `{:?}`,
33 right: `{:?}`"#,
34                            left_val, right_val,
35                        )
36                    }
37                }
38            }
39        }
40    };
41    ($typ:ty, $lhs:expr, $rhs:expr $(, $set:ident = $val:expr)*) => {
42        {
43            match (&$lhs, &$rhs) {
44                (left_val, right_val) => {
45                    if !$crate::approx_eq!($typ, *left_val, *right_val $(, $set = $val)*) {
46                        panic!(
47                            r#"assertion failed: `(left approx_eq right)`
48  left: `{:?}`,
49 right: `{:?}`"#,
50                            left_val, right_val,
51                        )
52                    }
53                }
54            }
55        }
56    };
57    ($typ:ty, $lhs:expr, $rhs:expr, $marg:expr) => {
58        {
59            match (&$lhs, &$rhs) {
60                (left_val, right_val) => {
61                    if !$crate::approx_eq!($typ, *left_val, *right_val, $marg) {
62                        panic!(
63                            r#"assertion failed: `(left approx_eq right)`
64  left: `{:?}`,
65 right: `{:?}`"#,
66                            left_val, right_val,
67                        )
68                    }
69                }
70            }
71        }
72    };
73}
74
75// Until saturating_abs() comes out of nightly, we have to code it ourselves.
76macro_rules! saturating_abs_i32 {
77    ($val:expr) => {
78        if $val.is_negative() {
79            match $val.checked_neg() {
80                Some(v) => v,
81                None => i32::MAX,
82            }
83        } else {
84            $val
85        }
86    };
87}
88macro_rules! saturating_abs_i64 {
89    ($val:expr) => {
90        if $val.is_negative() {
91            match $val.checked_neg() {
92                Some(v) => v,
93                None => i64::MAX,
94            }
95        } else {
96            $val
97        }
98    };
99}
100
101#[test]
102fn test_macro() {
103    let a: f32 = 0.15 + 0.15 + 0.15;
104    let b: f32 = 0.1 + 0.1 + 0.25;
105    assert!(approx_eq!(f32, a, b)); // uses the default
106    assert!(approx_eq!(f32, a, b, ulps = 2));
107    assert!(approx_eq!(f32, a, b, epsilon = 0.00000003));
108    assert!(approx_eq!(f32, a, b, epsilon = 0.00000003, ulps = 2));
109    assert!(approx_eq!(f32, a, b, (0.0, 2)));
110
111    assert_approx_eq!(f32, a, b); // uses the default
112    assert_approx_eq!(f32, a, b, ulps = 2);
113    assert_approx_eq!(f32, a, b, epsilon = 0.00000003);
114    assert_approx_eq!(f32, a, b, epsilon = 0.00000003, ulps = 2);
115    assert_approx_eq!(f32, a, b, (0.0, 2));
116}
117
118#[test]
119fn test_macro_2() {
120    assert!(approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64));
121    assert!(approx_eq!(
122        f64,
123        1000000_f64,
124        1000000.0000000003_f64,
125        ulps = 3
126    ));
127    assert!(approx_eq!(
128        f64,
129        1000000_f64,
130        1000000.0000000003_f64,
131        epsilon = 0.0000000004
132    ));
133    assert!(approx_eq!(
134        f64,
135        1000000_f64,
136        1000000.0000000003_f64,
137        (0.0000000004, 0)
138    ));
139    assert!(approx_eq!(
140        f64,
141        1000000_f64,
142        1000000.0000000003_f64,
143        (0.0, 3)
144    ));
145
146    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64);
147    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, ulps = 3);
148    assert_approx_eq!(
149        f64,
150        1000000_f64,
151        1000000.0000000003_f64,
152        epsilon = 0.0000000004
153    );
154    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0000000004, 0));
155    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0, 3));
156}
157
158#[test]
159fn test_macro_3() {
160    use crate::F32Margin;
161
162    let a: f32 = 0.15 + 0.15 + 0.15;
163    let b: f32 = 0.1 + 0.1 + 0.25;
164    assert!(approx_eq!(
165        f32,
166        a,
167        b,
168        F32Margin {
169            epsilon: 0.0,
170            ulps: 2
171        }
172    ));
173    assert!(approx_eq!(f32, a, b, F32Margin::default()));
174
175    assert_approx_eq!(
176        f32,
177        a,
178        b,
179        F32Margin {
180            epsilon: 0.0,
181            ulps: 2
182        }
183    );
184    assert_approx_eq!(f32, a, b, F32Margin::default());
185}
186
187#[test]
188#[should_panic]
189fn test_macro_4() {
190    let a: f32 = 0.15 + 0.15 + 0.15;
191    let b: f32 = 1.0;
192
193    assert_approx_eq!(f32, a, b);
194}
195
196#[test]
197#[should_panic]
198fn test_macro_5() {
199    let a: f32 = 0.15 + 0.15 + 0.15;
200    let b: f32 = 1.0;
201
202    assert_approx_eq!(f32, a, b, ulps = 2);
203}
204
205#[test]
206#[should_panic]
207fn test_macro_6() {
208    let a: f32 = 0.15 + 0.15 + 0.15;
209    let b: f32 = 1.0;
210
211    assert_approx_eq!(f32, a, b, epsilon = 0.00000003);
212}
213
214#[test]
215#[should_panic]
216fn test_macro_7() {
217    let a: f32 = 0.15 + 0.15 + 0.15;
218    let b: f32 = 1.0;
219
220    assert_approx_eq!(f32, a, b, epsilon = 0.00000003, ulps = 2);
221}
222
223#[test]
224#[should_panic]
225fn test_macro_8() {
226    let a: f32 = 0.15 + 0.15 + 0.15;
227    let b: f32 = 1.0;
228
229    assert_approx_eq!(f32, a, b, (0.0, 2));
230}