devela/code/util/asserts/
dynamic.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// devela::code::util::asserts
//
//! Additional assertion macros
//

/// Asserts the equality of a series of expressions.
///
/// Similar to [`assert_eq`] but supports more than 2 terms to test for equality.
///
/// # Panics
// TODO
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! assert_eq_all {
    ($first:expr, $($rest:expr),+ $(,)?) => {{
        let first_val = &$first;
        $(
            let rest_val = &$rest;
            assert!(
                first_val == rest_val,
                "Assertion failed: ({}) is not equal to ({})\n  left: {}\n right: {}",
                stringify!($first),
                stringify!($rest),
                first_val,
                rest_val,
            );
        )+
    }};
}
#[doc(inline)]
pub use assert_eq_all;

/// Asserts the approximate equality of a series of expressions within `tolerance`.
///
/// This macro should work with any numeric type that supports comparison and
/// subtraction, including signed and unsigned integers and floating-point numbers.
///
/// The given `$tolerance` must be a non-negative number.
///
/// # Panics
// TODO
///
/// # Examples
/// The following examples compile:
/// ```
/// # use devela::assert_approx_eq_all;
/// assert_approx_eq_all![tolerance: 0.01, 1.0, 1.001, 0.999]; // up to 0.01 away from 1.0
/// assert_approx_eq_all![tolerance: 1_u32, 4, 3, 5]; // up to 1 away from 4
///
/// assert_approx_eq_all![tolerance: 0.01, -1.0, -1.001, -0.999];
/// assert_approx_eq_all![tolerance: 1_i32, -4, -3, -5];
/// assert_approx_eq_all![tolerance: 0_i32, 3, 3];
/// ```
/// The following examples panic:
/// ```should_panic
/// # use devela::assert_approx_eq_all;
/// assert_approx_eq_all![tolerance: 0.01, 1.0, 1.001, 0.989]; // |0.989 - 1.0| > |0.01|
/// ```
/// ```should_panic
/// # use devela::assert_approx_eq_all;
/// assert_approx_eq_all![tolerance: 1_u32, 4, 3, 5, 6]; // |6 - 4| > |1|
/// ```
/// ```should_panic
/// # use devela::assert_approx_eq_all;
/// assert_approx_eq_all![tolerance: 1_u32, 3, 4, 5]; // |5 - 3| > |1|
/// ```
/// ```should_panic
/// # use devela::assert_approx_eq_all;
/// assert_approx_eq_all![tolerance: -0.01, 1.0, 1.001, 0.999]; // tolerance: -0.01 < 0
/// ```
/// ```should_panic
/// # use devela::assert_approx_eq_all;
/// assert_approx_eq_all![tolerance: -1_i32, 4, 3, 5]; // tolerance: -1 < 0
/// ```
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! assert_approx_eq_all {
    (tolerance: $tolerance:expr, $first:expr, $($rest:expr),+ $(,)?) => {{
        let first_val = $first;
        $(
            let rest_val = $rest;
            // Calculate the absolute difference without relying on `abs`:
            let difference = if first_val > rest_val {
                first_val - rest_val
            } else {
                rest_val - first_val
            };
            assert!(
                difference <= $tolerance,
                "Assertion failed: ({}) is not approximately equal to ({})
      left: {}\n     right: {}\n tolerance: {}",
                stringify!($first), stringify!($rest), first_val, rest_val, $tolerance,
            );
        )+
    }};
}
#[doc(inline)]
pub use assert_approx_eq_all;