float_cmp/
macros.rs

1
2#[macro_export]
3macro_rules! approx_eq {
4    ($typ:ty, $lhs:expr, $rhs:expr) => {
5        {
6            let m = <$typ as $crate::ApproxEq>::Margin::default();
7            <$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, m)
8        }
9    };
10    ($typ:ty, $lhs:expr, $rhs:expr $(, $set:ident = $val:expr)*) => {
11        {
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 => core::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 => core::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!(f64, 1000000_f64, 1000000.0000000003_f64, ulps=3) );
122    assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, epsilon=0.0000000004) );
123    assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0000000004, 0)) );
124    assert!( approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0, 3)) );
125
126    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64);
127    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, ulps=3);
128    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, epsilon=0.0000000004);
129    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0000000004, 0));
130    assert_approx_eq!(f64, 1000000_f64, 1000000.0000000003_f64, (0.0, 3));
131}
132
133#[test]
134fn test_macro_3() {
135    use crate::F32Margin;
136
137    let a: f32 = 0.15 + 0.15 + 0.15;
138    let b: f32 = 0.1 + 0.1 + 0.25;
139    assert!( approx_eq!(f32, a, b, F32Margin { epsilon: 0.0, ulps: 2 }) );
140    assert!( approx_eq!(f32, a, b, F32Margin::default()) );
141
142    assert_approx_eq!(f32, a, b, F32Margin { epsilon: 0.0, ulps: 2 });
143    assert_approx_eq!(f32, a, b, F32Margin::default());
144}
145
146#[test]
147#[should_panic]
148fn test_macro_4() {
149    let a: f32 = 0.15 + 0.15 + 0.15;
150    let b: f32 = 1.0;
151
152    assert_approx_eq!(f32, a, b);
153}
154
155#[test]
156#[should_panic]
157fn test_macro_5() {
158    let a: f32 = 0.15 + 0.15 + 0.15;
159    let b: f32 = 1.0;
160
161    assert_approx_eq!(f32, a, b, ulps = 2);
162}
163
164#[test]
165#[should_panic]
166fn test_macro_6() {
167    let a: f32 = 0.15 + 0.15 + 0.15;
168    let b: f32 = 1.0;
169
170    assert_approx_eq!(f32, a, b, epsilon = 0.00000003);
171}
172
173#[test]
174#[should_panic]
175fn test_macro_7() {
176    let a: f32 = 0.15 + 0.15 + 0.15;
177    let b: f32 = 1.0;
178
179    assert_approx_eq!(f32, a, b, epsilon = 0.00000003, ulps = 2);
180}
181
182#[test]
183#[should_panic]
184fn test_macro_8() {
185    let a: f32 = 0.15 + 0.15 + 0.15;
186    let b: f32 = 1.0;
187
188    assert_approx_eq!(f32, a, b, (0.0, 2));
189}