]> git.lizzy.rs Git - rust.git/blob - library/portable-simd/crates/test_helpers/src/biteq.rs
Auto merge of #89167 - workingjubilee:use-simd, r=MarkSimulacrum
[rust.git] / library / portable-simd / crates / test_helpers / src / biteq.rs
1 //! Compare numeric types by exact bit value.
2
3 pub trait BitEq {
4     fn biteq(&self, other: &Self) -> bool;
5     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result;
6 }
7
8 impl BitEq for bool {
9     fn biteq(&self, other: &Self) -> bool {
10         self == other
11     }
12
13     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
14         write!(f, "{:?}", self)
15     }
16 }
17
18 macro_rules! impl_integer_biteq {
19     { $($type:ty),* } => {
20         $(
21         impl BitEq for $type {
22             fn biteq(&self, other: &Self) -> bool {
23                 self == other
24             }
25
26             fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
27                 write!(f, "{:?} ({:x})", self, self)
28             }
29         }
30         )*
31     };
32 }
33
34 impl_integer_biteq! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize }
35
36 macro_rules! impl_float_biteq {
37     { $($type:ty),* } => {
38         $(
39         impl BitEq for $type {
40             fn biteq(&self, other: &Self) -> bool {
41                 if self.is_nan() && other.is_nan() {
42                     true // exact nan bits don't matter
43                 } else {
44                     self.to_bits() == other.to_bits()
45                 }
46             }
47
48             fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
49                 write!(f, "{:?} ({:x})", self, self.to_bits())
50             }
51         }
52         )*
53     };
54 }
55
56 impl_float_biteq! { f32, f64 }
57
58 impl<T: BitEq, const N: usize> BitEq for [T; N] {
59     fn biteq(&self, other: &Self) -> bool {
60         self.iter()
61             .zip(other.iter())
62             .fold(true, |value, (left, right)| value && left.biteq(right))
63     }
64
65     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
66         #[repr(transparent)]
67         struct Wrapper<'a, T: BitEq>(&'a T);
68
69         impl<T: BitEq> core::fmt::Debug for Wrapper<'_, T> {
70             fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
71                 self.0.fmt(f)
72             }
73         }
74
75         f.debug_list()
76             .entries(self.iter().map(|x| Wrapper(x)))
77             .finish()
78     }
79 }
80
81 #[doc(hidden)]
82 pub struct BitEqWrapper<'a, T>(pub &'a T);
83
84 impl<T: BitEq> PartialEq for BitEqWrapper<'_, T> {
85     fn eq(&self, other: &Self) -> bool {
86         self.0.biteq(other.0)
87     }
88 }
89
90 impl<T: BitEq> core::fmt::Debug for BitEqWrapper<'_, T> {
91     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
92         self.0.fmt(f)
93     }
94 }
95
96 #[macro_export]
97 macro_rules! prop_assert_biteq {
98     { $a:expr, $b:expr $(,)? } => {
99         {
100             use $crate::biteq::BitEqWrapper;
101             let a = $a;
102             let b = $b;
103             proptest::prop_assert_eq!(BitEqWrapper(&a), BitEqWrapper(&b));
104         }
105     }
106 }