• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #[macro_export]
2 macro_rules! glam_test {
3     ($name:ident, $block:block) => {
4         #[cfg_attr(not(target_arch = "wasm32"), test)]
5         #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
6         fn $name() {
7             $block
8         }
9     };
10 }
11 
12 #[macro_export]
13 macro_rules! should_panic {
14     ($block:block) => {{
15         #[cfg(all(feature = "std", panic = "unwind"))]
16         assert!(std::panic::catch_unwind(|| $block).is_err());
17     }};
18 }
19 
20 #[macro_export]
21 macro_rules! should_glam_assert {
22     ($block:block) => {{
23         #[cfg(any(feature = "glam-assert", feature = "debug-glam-assert"))]
24         should_panic!($block);
25     }};
26 }
27 
28 #[macro_export]
29 macro_rules! assert_approx_eq {
30     ($a:expr, $b:expr) => {{
31         #[allow(unused_imports)]
32         use $crate::support::FloatCompare;
33         let eps = f32::EPSILON;
34         let (a, b) = (&$a, &$b);
35         assert!(
36             a.approx_eq(b, eps),
37             "assertion failed: `(left !== right)` \
38              (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)",
39             *a,
40             *b,
41             eps,
42             a.abs_diff(b)
43         );
44     }};
45     ($a:expr, $b:expr, $eps:expr) => {{
46         use $crate::support::FloatCompare;
47         let (a, b) = (&$a, &$b);
48         let eps = $eps;
49         assert!(
50             a.approx_eq(b, $eps),
51             "assertion failed: `(left !== right)` \
52              (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)",
53             *a,
54             *b,
55             eps,
56             a.abs_diff(b)
57         );
58     }};
59     ($a:expr, $b:expr, $eps:expr, $ctx:expr) => {{
60         use $crate::support::FloatCompare;
61         let (a, b) = (&$a, &$b);
62         let eps = $eps;
63         assert!(
64             a.approx_eq(b, $eps),
65             "assertion failed: `(left !== right)` \
66              (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`), \
67              additional context: {}",
68             *a,
69             *b,
70             eps,
71             a.abs_diff(b),
72             $ctx
73         );
74     }};
75 }
76 
77 /// Test vector normalization for float vector
78 #[macro_export]
79 macro_rules! impl_vec_float_normalize_tests {
80     ($t:ident, $vec:ident) => {
81         /// Works for vec2, vec3, vec4
82         fn from_x_y(x: $t, y: $t) -> $vec {
83             let mut v = $vec::ZERO;
84             v.x = x;
85             v.y = y;
86             v
87         }
88 
89         glam_test!(test_normalize, {
90             assert_eq!(from_x_y(-42.0, 0.0).normalize(), from_x_y(-1.0, 0.0));
91             assert_eq!(
92                 from_x_y($t::MAX.sqrt(), 0.0).normalize(),
93                 from_x_y(1.0, 0.0)
94             );
95             // assert_eq!(from_x_y($t::MAX, 0.0).normalize(), from_x_y(1.0, 0.0)); // normalize fails for huge vectors and returns zero
96 
97             // We expect not to be able to normalize small numbers:
98             should_glam_assert!({ from_x_y(0.0, 0.0).normalize() });
99             should_glam_assert!({ from_x_y($t::MIN_POSITIVE, 0.0).normalize() });
100 
101             // We expect not to be able to normalize non-finite vectors:
102             should_glam_assert!({ from_x_y($t::INFINITY, 0.0).normalize() });
103             should_glam_assert!({ from_x_y($t::NAN, 0.0).normalize() });
104         });
105 
106         #[cfg(not(any(feature = "debug-glam-assert", feature = "glam-assert")))]
107         glam_test!(test_normalize_no_glam_assert, {
108             // We expect not to be able to normalize small numbers:
109             assert!(!from_x_y(0.0, 0.0).normalize().is_finite());
110             assert!(!from_x_y($t::MIN_POSITIVE, 0.0).normalize().is_finite());
111 
112             // We expect not to be able to normalize non-finite vectors:
113             assert!(!from_x_y($t::INFINITY, 0.0).normalize().is_finite());
114             assert!(!from_x_y($t::NAN, 0.0).normalize().is_finite());
115         });
116 
117         glam_test!(test_try_normalize, {
118             assert_eq!(
119                 from_x_y(-42.0, 0.0).try_normalize(),
120                 Some(from_x_y(-1.0, 0.0))
121             );
122             assert_eq!(
123                 from_x_y($t::MAX.sqrt(), 0.0).try_normalize(),
124                 Some(from_x_y(1.0, 0.0))
125             );
126 
127             // We expect `try_normalize` to return None when inputs are very small:
128             assert_eq!(from_x_y(0.0, 0.0).try_normalize(), None);
129             assert_eq!(from_x_y($t::MIN_POSITIVE, 0.0).try_normalize(), None);
130 
131             // We expect `try_normalize` to return None when inputs are non-finite:
132             assert_eq!(from_x_y($t::INFINITY, 0.0).try_normalize(), None);
133             assert_eq!(from_x_y($t::NAN, 0.0).try_normalize(), None);
134 
135             // We expect `try_normalize` to return None when inputs are very large:
136             assert_eq!(from_x_y($t::MAX, 0.0).try_normalize(), None);
137             assert_eq!(from_x_y($t::MAX, $t::MAX).try_normalize(), None);
138         });
139 
140         glam_test!(test_normalize_or, {
141             assert_eq!(
142                 from_x_y(-42.0, 0.0).normalize_or($vec::Y),
143                 from_x_y(-1.0, 0.0)
144             );
145             assert_eq!(
146                 from_x_y($t::MAX.sqrt(), 0.0).normalize_or($vec::Y),
147                 from_x_y(1.0, 0.0)
148             );
149 
150             // We expect `normalize_or` to return the fallback value when inputs are very small:
151             assert_eq!(from_x_y(0.0, 0.0).normalize_or($vec::Y), $vec::Y);
152             assert_eq!(
153                 from_x_y($t::MIN_POSITIVE, 0.0).normalize_or($vec::Y),
154                 $vec::Y
155             );
156 
157             // We expect `normalize` to return zero when inputs are non-finite:
158             assert_eq!(from_x_y($t::INFINITY, 0.0).normalize_or($vec::Y), $vec::Y);
159             assert_eq!(from_x_y($t::NAN, 0.0).normalize_or($vec::Y), $vec::Y);
160 
161             // We expect `normalize` to return zero when inputs are very large:
162             assert_eq!(from_x_y($t::MAX, 0.0).normalize_or($vec::Y), $vec::Y);
163             assert_eq!(from_x_y($t::MAX, $t::MAX).normalize_or($vec::Y), $vec::Y);
164         });
165 
166         glam_test!(test_normalize_or_zero, {
167             assert_eq!(
168                 from_x_y(-42.0, 0.0).normalize_or_zero(),
169                 from_x_y(-1.0, 0.0)
170             );
171             assert_eq!(
172                 from_x_y($t::MAX.sqrt(), 0.0).normalize_or_zero(),
173                 from_x_y(1.0, 0.0)
174             );
175 
176             // We expect `normalize_or_zero` to return zero when inputs are very small:
177             assert_eq!(from_x_y(0.0, 0.0).normalize_or_zero(), $vec::ZERO);
178             assert_eq!(
179                 from_x_y($t::MIN_POSITIVE, 0.0).normalize_or_zero(),
180                 $vec::ZERO
181             );
182 
183             // We expect `normalize_or_zero` to return zero when inputs are non-finite:
184             assert_eq!(from_x_y($t::INFINITY, 0.0).normalize_or_zero(), $vec::ZERO);
185             assert_eq!(from_x_y($t::NAN, 0.0).normalize_or_zero(), $vec::ZERO);
186 
187             // We expect `normalize_or_zero` to return zero when inputs are very large:
188             assert_eq!(from_x_y($t::MAX, 0.0).normalize_or_zero(), $vec::ZERO);
189             assert_eq!(from_x_y($t::MAX, $t::MAX).normalize_or_zero(), $vec::ZERO);
190         });
191     };
192 }
193 
194 /// Useful test vectors
195 #[macro_export]
196 macro_rules! vec3_float_test_vectors {
197     ($vec3:ident) => {
198         [
199             $vec3::X,
200             $vec3::Y,
201             $vec3::Z,
202             -$vec3::X,
203             -$vec3::Y,
204             -$vec3::Z,
205             $vec3::new(1.0, 1e-3, 0.0),
206             $vec3::new(1.0, 1e-4, 0.0),
207             $vec3::new(1.0, 1e-5, 0.0),
208             $vec3::new(1.0, 1e-6, 0.0),
209             $vec3::new(1.0, 1e-7, 0.0),
210             $vec3::new(1.0, 1e-14, 0.0),
211             $vec3::new(1.0, 1e-15, 0.0),
212             $vec3::new(1.0, 1e-16, 0.0),
213             $vec3::new(0.1, 0.2, 0.3),
214             $vec3::new(0.2, 0.3, 0.4),
215             $vec3::new(4.0, -5.0, 6.0),
216             $vec3::new(-2.0, 0.5, -1.0),
217             // Pathological cases from <https://graphics.pixar.com/library/OrthonormalB/paper.pdf>:
218             $vec3::new(0.00038527316, 0.00038460016, -0.99999988079),
219             $vec3::new(-0.00019813581, -0.00008946839, -0.99999988079),
220         ]
221     };
222 }
223 
224 #[macro_export]
225 macro_rules! vec2_float_test_vectors {
226     ($vec2:ident) => {
227         [
228             $vec2::X,
229             $vec2::Y,
230             -$vec2::X,
231             -$vec2::Y,
232             $vec2::new(1.0, 1e-3),
233             $vec2::new(1.0, 1e-4),
234             $vec2::new(1.0, 1e-5),
235             $vec2::new(1.0, 1e-6),
236             $vec2::new(1.0, 1e-7),
237             $vec2::new(1.0, 1e-14),
238             $vec2::new(1.0, 1e-15),
239             $vec2::new(1.0, 1e-16),
240             $vec2::new(0.1, 0.2),
241             $vec2::new(0.2, 0.3),
242             $vec2::new(4.0, -5.0),
243             $vec2::new(-2.0, 0.5),
244             // Pathological cases from <https://graphics.pixar.com/library/OrthonormalB/paper.pdf>:
245             $vec2::new(0.00038527316, 0.00038460016),
246             $vec2::new(-0.00019813581, -0.00008946839),
247         ]
248     };
249 }
250 
251 #[macro_export]
252 macro_rules! test_matrix_minor {
253     ($n:expr, $minor:expr, $input:expr, $i:expr, $j:expr) => {
254         let mut yy = 0;
255         for y in 0..$n {
256             if y != $j {
257                 let mut xx = 0;
258                 for x in 0..$n {
259                     if x != $i {
260                         assert_eq!($minor.col(xx)[yy], $input.col(x)[y]);
261                         xx += 1;
262                     }
263                 }
264                 yy += 1;
265             }
266         }
267     };
268 }
269