blob: e7fadd1f5d53602aeb8629492059af872f619c3c [file] [log] [blame]
#[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),
]
};
}