| #[macro_export] |
| macro_rules! glam_test { |
| ($name:ident, $block:block) => { |
| #[cfg_attr(not(target_arch = "wasm32"), test)] |
| #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] |
| fn $name() { |
| $block |
| } |
| }; |
| } |
| |
| #[macro_export] |
| macro_rules! should_panic { |
| ($block:block) => {{ |
| #[cfg(all(feature = "std", not(target_arch = "wasm32")))] |
| assert!(std::panic::catch_unwind(|| $block).is_err()); |
| }}; |
| } |
| |
| #[macro_export] |
| macro_rules! should_glam_assert { |
| ($block:block) => {{ |
| #[cfg(any(feature = "glam-assert", feature = "debug-glam-assert"))] |
| should_panic!($block); |
| }}; |
| } |
| |
| #[macro_export] |
| macro_rules! assert_approx_eq { |
| ($a:expr, $b:expr) => {{ |
| #[allow(unused_imports)] |
| use $crate::support::FloatCompare; |
| let eps = core::f32::EPSILON; |
| let (a, b) = (&$a, &$b); |
| assert!( |
| a.approx_eq(b, eps), |
| "assertion failed: `(left !== right)` \ |
| (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)", |
| *a, |
| *b, |
| eps, |
| a.abs_diff(b) |
| ); |
| }}; |
| ($a:expr, $b:expr, $eps:expr) => {{ |
| use $crate::support::FloatCompare; |
| let (a, b) = (&$a, &$b); |
| let eps = $eps; |
| assert!( |
| a.approx_eq(b, $eps), |
| "assertion failed: `(left !== right)` \ |
| (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)", |
| *a, |
| *b, |
| eps, |
| a.abs_diff(b) |
| ); |
| }}; |
| ($a:expr, $b:expr, $eps:expr, $ctx:expr) => {{ |
| use $crate::support::FloatCompare; |
| let (a, b) = (&$a, &$b); |
| let eps = $eps; |
| assert!( |
| a.approx_eq(b, $eps), |
| "assertion failed: `(left !== right)` \ |
| (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`), \ |
| additional context: {}", |
| *a, |
| *b, |
| eps, |
| a.abs_diff(b), |
| $ctx |
| ); |
| }}; |
| } |
| |
| /// Test vector normalization for float vector |
| #[macro_export] |
| macro_rules! impl_vec_float_normalize_tests { |
| ($t:ident, $vec:ident) => { |
| use core::$t::MAX; |
| use core::$t::MIN_POSITIVE; |
| |
| /// Works for vec2, vec3, vec4 |
| fn from_x_y(x: $t, y: $t) -> $vec { |
| let mut v = $vec::ZERO; |
| v.x = x; |
| v.y = y; |
| v |
| } |
| |
| glam_test!(test_normalize, { |
| assert_eq!(from_x_y(-42.0, 0.0).normalize(), from_x_y(-1.0, 0.0)); |
| assert_eq!(from_x_y(MAX.sqrt(), 0.0).normalize(), from_x_y(1.0, 0.0)); |
| // assert_eq!(from_x_y(MAX, 0.0).normalize(), from_x_y(1.0, 0.0)); // normalize fails for huge vectors and returns zero |
| |
| // We expect not to be able to normalize small numbers: |
| should_glam_assert!({ from_x_y(0.0, 0.0).normalize() }); |
| should_glam_assert!({ from_x_y(MIN_POSITIVE, 0.0).normalize() }); |
| |
| // We expect not to be able to normalize non-finite vectors: |
| should_glam_assert!({ from_x_y(INFINITY, 0.0).normalize() }); |
| should_glam_assert!({ from_x_y(NAN, 0.0).normalize() }); |
| }); |
| |
| #[cfg(not(any(feature = "debug-glam-assert", feature = "glam-assert")))] |
| glam_test!(test_normalize_no_glam_assert, { |
| // We expect not to be able to normalize small numbers: |
| assert!(!from_x_y(0.0, 0.0).normalize().is_finite()); |
| assert!(!from_x_y(MIN_POSITIVE, 0.0).normalize().is_finite()); |
| |
| // We expect not to be able to normalize non-finite vectors: |
| assert!(!from_x_y(INFINITY, 0.0).normalize().is_finite()); |
| assert!(!from_x_y(NAN, 0.0).normalize().is_finite()); |
| }); |
| |
| glam_test!(test_try_normalize, { |
| assert_eq!( |
| from_x_y(-42.0, 0.0).try_normalize(), |
| Some(from_x_y(-1.0, 0.0)) |
| ); |
| assert_eq!( |
| from_x_y(MAX.sqrt(), 0.0).try_normalize(), |
| Some(from_x_y(1.0, 0.0)) |
| ); |
| |
| // We expect `try_normalize` to return None when inputs are very small: |
| assert_eq!(from_x_y(0.0, 0.0).try_normalize(), None); |
| assert_eq!(from_x_y(MIN_POSITIVE, 0.0).try_normalize(), None); |
| |
| // We expect `try_normalize` to return None when inputs are non-finite: |
| assert_eq!(from_x_y(INFINITY, 0.0).try_normalize(), None); |
| assert_eq!(from_x_y(NAN, 0.0).try_normalize(), None); |
| |
| // We expect `try_normalize` to return None when inputs are very large: |
| assert_eq!(from_x_y(MAX, 0.0).try_normalize(), None); |
| assert_eq!(from_x_y(MAX, MAX).try_normalize(), None); |
| }); |
| |
| glam_test!(test_normalize_or_zero, { |
| assert_eq!( |
| from_x_y(-42.0, 0.0).normalize_or_zero(), |
| from_x_y(-1.0, 0.0) |
| ); |
| assert_eq!( |
| from_x_y(MAX.sqrt(), 0.0).normalize_or_zero(), |
| from_x_y(1.0, 0.0) |
| ); |
| |
| // We expect `normalize_or_zero` to return zero when inputs are very small: |
| assert_eq!(from_x_y(0.0, 0.0).normalize_or_zero(), $vec::ZERO); |
| assert_eq!(from_x_y(MIN_POSITIVE, 0.0).normalize_or_zero(), $vec::ZERO); |
| |
| // We expect `normalize_or_zero` to return zero when inputs are non-finite: |
| assert_eq!(from_x_y(INFINITY, 0.0).normalize_or_zero(), $vec::ZERO); |
| assert_eq!(from_x_y(NAN, 0.0).normalize_or_zero(), $vec::ZERO); |
| |
| // We expect `normalize_or_zero` to return zero when inputs are very large: |
| assert_eq!(from_x_y(MAX, 0.0).normalize_or_zero(), $vec::ZERO); |
| assert_eq!(from_x_y(MAX, MAX).normalize_or_zero(), $vec::ZERO); |
| }); |
| }; |
| } |
| |
| /// Useful test vectors |
| #[macro_export] |
| macro_rules! vec3_float_test_vectors { |
| ($vec3:ident) => { |
| [ |
| $vec3::X, |
| $vec3::Y, |
| $vec3::Z, |
| -$vec3::X, |
| -$vec3::Y, |
| -$vec3::Z, |
| $vec3::new(1.0, 1e-3, 0.0), |
| $vec3::new(1.0, 1e-4, 0.0), |
| $vec3::new(1.0, 1e-5, 0.0), |
| $vec3::new(1.0, 1e-6, 0.0), |
| $vec3::new(1.0, 1e-7, 0.0), |
| $vec3::new(1.0, 1e-14, 0.0), |
| $vec3::new(1.0, 1e-15, 0.0), |
| $vec3::new(1.0, 1e-16, 0.0), |
| $vec3::new(0.1, 0.2, 0.3), |
| $vec3::new(0.2, 0.3, 0.4), |
| $vec3::new(4.0, -5.0, 6.0), |
| $vec3::new(-2.0, 0.5, -1.0), |
| // Pathalogical cases from <https://graphics.pixar.com/library/OrthonormalB/paper.pdf>: |
| $vec3::new(0.00038527316, 0.00038460016, -0.99999988079), |
| $vec3::new(-0.00019813581, -0.00008946839, -0.99999988079), |
| ] |
| }; |
| } |
| |
| #[macro_export] |
| macro_rules! vec2_float_test_vectors { |
| ($vec2:ident) => { |
| [ |
| $vec2::X, |
| $vec2::Y, |
| -$vec2::X, |
| -$vec2::Y, |
| $vec2::new(1.0, 1e-3), |
| $vec2::new(1.0, 1e-4), |
| $vec2::new(1.0, 1e-5), |
| $vec2::new(1.0, 1e-6), |
| $vec2::new(1.0, 1e-7), |
| $vec2::new(1.0, 1e-14), |
| $vec2::new(1.0, 1e-15), |
| $vec2::new(1.0, 1e-16), |
| $vec2::new(0.1, 0.2), |
| $vec2::new(0.2, 0.3), |
| $vec2::new(4.0, -5.0), |
| $vec2::new(-2.0, 0.5), |
| // Pathalogical cases from <https://graphics.pixar.com/library/OrthonormalB/paper.pdf>: |
| $vec2::new(0.00038527316, 0.00038460016), |
| $vec2::new(-0.00019813581, -0.00008946839), |
| ] |
| }; |
| } |