1 | |
2 | #[macro_export ] |
3 | macro_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 ] |
24 | macro_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. |
76 | macro_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 | } |
88 | macro_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 ] |
102 | fn 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 ] |
119 | fn 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 ] |
134 | fn 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 ] |
148 | fn 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 ] |
157 | fn 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 ] |
166 | fn 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 ] |
175 | fn 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 ] |
184 | fn 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 | } |
190 | |