Skip to main content

celestial_core/
test_helpers.rs

1#[inline]
2pub fn f64_to_ordered_u64(x: f64) -> u64 {
3    let bits = x.to_bits();
4    if bits & 0x8000_0000_0000_0000 != 0 {
5        !bits
6    } else {
7        bits | 0x8000_0000_0000_0000
8    }
9}
10
11#[inline]
12pub fn ulp_diff(a: f64, b: f64) -> u64 {
13    let ua = f64_to_ordered_u64(a);
14    let ub = f64_to_ordered_u64(b);
15    ua.abs_diff(ub)
16}
17
18#[track_caller]
19pub fn assert_ulp_le(a: f64, b: f64, max_ulp: u64, ctx: &str) {
20    if a == 0.0 && b == 0.0 {
21        return;
22    }
23    assert!(
24        a.is_finite() && b.is_finite(),
25        "non-finite value in {}",
26        ctx
27    );
28    let d = ulp_diff(a, b);
29    assert!(
30        d <= max_ulp,
31        "{}: ULP={} exceeds {}, a={} (0x{:016x}) b={} (0x{:016x})",
32        ctx,
33        d,
34        max_ulp,
35        a,
36        a.to_bits(),
37        b,
38        b.to_bits()
39    );
40}
41
42#[track_caller]
43pub fn assert_float_eq(a: f64, b: f64, max_ulp: u64) {
44    if a == 0.0 && b == 0.0 {
45        return;
46    }
47    assert!(a.is_finite() && b.is_finite());
48    let d = ulp_diff(a, b);
49    assert!(
50        d <= max_ulp,
51        "ULP={} exceeds {}, a={} (0x{:016x}) b={} (0x{:016x})",
52        d,
53        max_ulp,
54        a,
55        a.to_bits(),
56        b,
57        b.to_bits()
58    );
59}
60
61#[macro_export]
62macro_rules! assert_ulp_lt {
63    ($a:expr, $b:expr, $max_ulp:expr) => {
64        $crate::test_helpers::assert_ulp_le(
65            $a,
66            $b,
67            $max_ulp,
68            &format!(
69                "ULP check failed: {} vs {} (max_ulp={})",
70                stringify!($a),
71                stringify!($b),
72                $max_ulp
73            ),
74        )
75    };
76    ($a:expr, $b:expr, $max_ulp:expr, $($arg:tt)*) => {
77        $crate::test_helpers::assert_ulp_le($a, $b, $max_ulp, &format!($($arg)*))
78    };
79}