godot_core/builtin/math/
approx_eq.rs

1/*
2 * Copyright (c) godot-rust; Bromeon and contributors.
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 */
7
8// TODO(bromeon): test this against Godot's own is_equal_approx() implementation for equality-comparable built-in types (excl Callable/Rid/...)
9
10/// Approximate equality-comparison of geometric types.
11///
12/// The implementation is specific to the type. It's mostly used for gdext-internal tests, but you may use it for your own code.
13/// Note that we give no guarantees about precision, and implementation can change at any time.
14///
15/// We currently also do not guarantee that this gives the same results as Godot's own `is_equal_approx()` function; although this may
16/// be the goal in the future.
17pub trait ApproxEq: PartialEq {
18    fn approx_eq(&self, other: &Self) -> bool;
19}
20
21/// Asserts that two values are approximately equal
22///
23/// For comparison, this uses `ApproxEq::approx_eq` by default, or the provided `fn = ...` function.
24#[macro_export]
25macro_rules! assert_eq_approx {
26    ($actual:expr, $expected:expr, fn = $func:expr $(,)?) => {
27        match ($actual, $expected) {
28            (a, b) => assert!(($func)(&a, &b), "\n  left: {:?},\n right: {:?}", $actual, $expected)
29        }
30    };
31    ($actual:expr, $expected:expr, fn = $func:expr, $($t:tt)+) => {
32        match ($actual, $expected) {
33            (a, b) => assert!(($func)(&a, &b), "\n  left: {:?},\n right: {:?}{}", $actual, $expected, format_args!($($t)+) )
34        }
35    };
36    ($actual:expr, $expected:expr $(,)?) => {
37        match ($actual, $expected) {
38             (a, b) => assert!($crate::builtin::math::ApproxEq::approx_eq(&a, &b), "\n  left: {:?},\n right: {:?}", $actual, $expected),
39            // (a, b) => $crate::assert_eq_approx!($actual, $expected, fn = $crate::builtin::ApproxEq::approx_eq),
40        }
41    };
42    ($actual:expr, $expected:expr, $($t:tt)+) => {
43        match ($actual, $expected) {
44            (a, b) => assert!($crate::builtin::math::ApproxEq::approx_eq(&a, &b), "\n  left: {:?},\n right: {:?},\n{}", $actual, $expected, format_args!($($t)+)),
45            // (a, b) => $crate::assert_eq_approx!($actual, $expected, fn = $crate::builtin::ApproxEq::approx_eq, $($t)+),
46        }
47    };
48}
49
50/// Asserts that two values are not approximately equal, using the provided
51/// `func` for equality checking.
52#[macro_export]
53macro_rules! assert_ne_approx {
54    ($actual:expr, $expected:expr, fn = $func:expr $(, $($t:tt)* )?) => {
55        #[allow(clippy::redundant_closure_call)]
56        {
57            $crate::assert_eq_approx!($actual, $expected, fn = |a,b| !($func)(a, b) $(, $($t)* )?)
58        }
59    };
60
61    ($actual:expr, $expected:expr $(, $($t:tt)* )?) => {
62        #[allow(clippy::redundant_closure_call)]
63        {
64            $crate::assert_eq_approx!($actual, $expected, fn = |a, b| !$crate::builtin::math::ApproxEq::approx_eq(a, b) $(, $($t)* )?)
65        }
66    };
67}