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}
190