celestial_core/
test_helpers.rs1#[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}