1macro_rules! define {
7 (
8 @ord
9 $lhs:ident,
10 $rhs:ident,
11 low_type => $lo_t:ty,
12 high_type => $hi_t:ty,
13 op1 => $op1:tt ,
14 op2 => $op2:tt $(,)?
15 ) => {{
16 let lhs = $lhs.to_ne_wide();
18 let rhs = $rhs.to_ne_wide();
19
20 let mut i = Self::WIDE - 1;
21 let lhs_0 = ne_index!(lhs[i]) as $hi_t;
22 let rhs_0 = ne_index!(rhs[i]) as $hi_t;
23 let mut is_ord = lhs_0 $op1 rhs_0;
24 let mut is_eq = lhs_0 == rhs_0;
25
26 while i > 0 && !is_ord && is_eq {
27 i -= 1;
28 let lhs_i = ne_index!(lhs[i]) as $lo_t;
29 let rhs_i = ne_index!(rhs[i]) as $lo_t;
30 is_ord = if i == 0 {
32 lhs_i $op2 rhs_i
33 } else {
34 lhs_i $op1 rhs_i
35 };
36 is_eq = lhs_i == rhs_i;
37 }
38 is_ord
39 }};
40
41 (
42 low_type => $lo_t:ty,
43 high_type => $hi_t:ty $(,)?
44 ) => {
45 #[inline(always)]
47 const fn eq_branchless(self, rhs: Self) -> bool {
48 let lhs = self.to_ne_wide();
49 let rhs = rhs.to_ne_wide();
50 let mut is_eq = true;
51 let mut i = 0;
52 while i < Self::WIDE {
53 is_eq &= (lhs[i] == rhs[i]);
55 i += 1;
56 }
57 is_eq
58 }
59
60 #[inline(always)]
62 pub const fn eq_branched(self, rhs: Self) -> bool {
63 let lhs = self.to_ne_wide();
64 let rhs = rhs.to_ne_wide();
65 let mut is_eq = true;
66 let mut i = 0;
67 while i < Self::WIDE && is_eq {
68 is_eq &= (lhs[i] == rhs[i]);
69 i += 1;
70 }
71 is_eq
72 }
73
74 #[inline(always)]
76 pub const fn eq_const(self, rhs: Self) -> bool {
77 if Self::BITS < 4096 {
78 self.eq_branchless(rhs)
79 } else {
80 self.eq_branched(rhs)
81 }
82 }
83
84 #[inline(always)]
90 #[must_use]
91 pub const fn lt_const(self, rhs: Self) -> bool {
92 $crate::shared::ord::define!(
93 @ord
94 self,
95 rhs,
96 low_type => $lo_t,
97 high_type => $hi_t,
98 op1 => <,
99 op2 => <,
100 )
101 }
102
103 #[must_use]
105 #[inline(always)]
106 pub const fn le_const(self, rhs: Self) -> bool {
107 $crate::shared::ord::define!(
108 @ord
109 self,
110 rhs,
111 low_type => $lo_t,
112 high_type => $hi_t,
113 op1 => <,
114 op2 => <=,
115 )
116 }
117
118 #[inline(always)]
120 pub const fn gt_const(self, rhs: Self) -> bool {
121 !self.le_const(rhs)
122 }
123
124 #[inline(always)]
126 pub const fn ge_const(self, rhs: Self) -> bool {
127 !self.lt_const(rhs)
128 }
129
130 #[inline(always)]
132 pub const fn cmp_const(self, rhs: Self) -> core::cmp::Ordering {
133 let lhs = self.to_ne_wide();
134 let rhs = rhs.to_ne_wide();
135
136 let mut i = Self::WIDE - 1;
137 let lhs_0 = ne_index!(lhs[i]) as $hi_t;
138 let rhs_0 = ne_index!(rhs[i]) as $hi_t;
139 let mut is_eq = lhs_0 == rhs_0;
140 let mut is_lt = lhs_0 < rhs_0;
141 let mut is_gt = lhs_0 > rhs_0;
142
143 while i > 0 && !is_lt && !is_gt && is_eq {
144 i -= 1;
145 let lhs_i = ne_index!(lhs[i]) as $lo_t;
146 let rhs_i = ne_index!(rhs[i]) as $lo_t;
147 is_eq = lhs_i == rhs_i;
148 is_lt = lhs_i < rhs_i;
149 is_gt = lhs_i > rhs_i;
150 }
151
152 if is_lt {
153 core::cmp::Ordering::Less
154 } else if is_gt {
155 core::cmp::Ordering::Greater
156 } else {
157 core::cmp::Ordering::Equal
158 }
159 }
160 };
161}
162
163pub(crate) use define;
164
165macro_rules! traits {
166 ($t:ty $(,)?) => {
167 impl core::cmp::Ord for $t {
168 #[inline(always)]
169 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
170 self.cmp_const(*other)
171 }
172 }
173
174 impl core::cmp::PartialOrd for $t {
175 #[inline(always)]
176 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
177 Some(self.cmp(other))
178 }
179
180 #[inline(always)]
181 fn lt(&self, other: &Self) -> bool {
182 self.lt_const(*other)
183 }
184
185 #[inline(always)]
186 fn le(&self, other: &Self) -> bool {
187 self.le_const(*other)
188 }
189
190 #[inline(always)]
191 fn gt(&self, other: &Self) -> bool {
192 self.gt_const(*other)
193 }
194
195 #[inline(always)]
196 fn ge(&self, other: &Self) -> bool {
197 self.ge_const(*other)
198 }
199 }
200 };
201}
202
203pub(crate) use traits;