compiler_builtins/int/
traits.rs1use core::ops;
2
3#[allow(dead_code)]
5pub trait MinInt:
6 Copy
7 + core::fmt::Debug
8 + ops::BitOr<Output = Self>
9 + ops::Not<Output = Self>
10 + ops::Shl<u32, Output = Self>
11{
12 type OtherSign: MinInt;
14 type UnsignedInt: MinInt;
16
17 const SIGNED: bool;
19
20 const BITS: u32;
22
23 const ZERO: Self;
24 const ONE: Self;
25 const MIN: Self;
26 const MAX: Self;
27}
28
29#[allow(dead_code)]
31pub trait Int:
32 MinInt
33 + PartialEq
34 + PartialOrd
35 + ops::AddAssign
36 + ops::SubAssign
37 + ops::BitAndAssign
38 + ops::BitOrAssign
39 + ops::BitXorAssign
40 + ops::ShlAssign<i32>
41 + ops::ShrAssign<u32>
42 + ops::Add<Output = Self>
43 + ops::Sub<Output = Self>
44 + ops::Mul<Output = Self>
45 + ops::Div<Output = Self>
46 + ops::Shr<u32, Output = Self>
47 + ops::BitXor<Output = Self>
48 + ops::BitAnd<Output = Self>
49{
50 const FUZZ_LENGTHS: [u8; 20] = make_fuzz_lengths(<Self as MinInt>::BITS);
54
55 const FUZZ_NUM: usize = {
57 let log2 = (<Self as MinInt>::BITS - 1).count_ones() as usize;
58 if log2 == 3 {
59 6
61 } else {
62 8 + (4 * (log2 - 4))
65 }
66 };
67
68 fn unsigned(self) -> Self::UnsignedInt;
69 fn from_unsigned(unsigned: Self::UnsignedInt) -> Self;
70 fn unsigned_abs(self) -> Self::UnsignedInt;
71
72 fn from_bool(b: bool) -> Self;
73
74 fn logical_shr(self, other: u32) -> Self;
76
77 fn abs_diff(self, other: Self) -> Self::UnsignedInt;
79
80 fn is_zero(self) -> bool;
82 fn wrapping_neg(self) -> Self;
83 fn wrapping_add(self, other: Self) -> Self;
84 fn wrapping_mul(self, other: Self) -> Self;
85 fn wrapping_sub(self, other: Self) -> Self;
86 fn wrapping_shl(self, other: u32) -> Self;
87 fn wrapping_shr(self, other: u32) -> Self;
88 fn rotate_left(self, other: u32) -> Self;
89 fn overflowing_add(self, other: Self) -> (Self, bool);
90 fn leading_zeros(self) -> u32;
91 fn ilog2(self) -> u32;
92}
93
94pub(crate) const fn make_fuzz_lengths(bits: u32) -> [u8; 20] {
95 let mut v = [0u8; 20];
96 v[0] = 0;
97 v[1] = 1;
98 v[2] = 2; let mut i = 3;
100
101 let mut l = 8;
106 loop {
107 if l >= ((bits / 2) as u8) {
108 break;
109 }
110 v[i] = l - 1;
112 i += 1;
113 v[i] = l;
114 i += 1;
115 l *= 2;
116 }
117
118 if bits != 8 {
119 v[i] = ((bits / 2) - 1) as u8;
121 i += 1;
122 }
123
124 let mid = i;
128 let mut j = 1;
129 loop {
130 v[i] = (bits as u8) - (v[mid - j]) - 1;
131 if j == mid {
132 break;
133 }
134 i += 1;
135 j += 1;
136 }
137 v
138}
139
140macro_rules! int_impl_common {
141 ($ty:ty) => {
142 fn from_bool(b: bool) -> Self {
143 b as $ty
144 }
145
146 fn logical_shr(self, other: u32) -> Self {
147 Self::from_unsigned(self.unsigned().wrapping_shr(other))
148 }
149
150 fn is_zero(self) -> bool {
151 self == Self::ZERO
152 }
153
154 fn wrapping_neg(self) -> Self {
155 <Self>::wrapping_neg(self)
156 }
157
158 fn wrapping_add(self, other: Self) -> Self {
159 <Self>::wrapping_add(self, other)
160 }
161
162 fn wrapping_mul(self, other: Self) -> Self {
163 <Self>::wrapping_mul(self, other)
164 }
165 fn wrapping_sub(self, other: Self) -> Self {
166 <Self>::wrapping_sub(self, other)
167 }
168
169 fn wrapping_shl(self, other: u32) -> Self {
170 <Self>::wrapping_shl(self, other)
171 }
172
173 fn wrapping_shr(self, other: u32) -> Self {
174 <Self>::wrapping_shr(self, other)
175 }
176
177 fn rotate_left(self, other: u32) -> Self {
178 <Self>::rotate_left(self, other)
179 }
180
181 fn overflowing_add(self, other: Self) -> (Self, bool) {
182 <Self>::overflowing_add(self, other)
183 }
184
185 fn leading_zeros(self) -> u32 {
186 <Self>::leading_zeros(self)
187 }
188
189 fn ilog2(self) -> u32 {
190 <Self>::ilog2(self)
191 }
192 };
193}
194
195macro_rules! int_impl {
196 ($ity:ty, $uty:ty) => {
197 impl MinInt for $uty {
198 type OtherSign = $ity;
199 type UnsignedInt = $uty;
200
201 const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
202 const SIGNED: bool = Self::MIN != Self::ZERO;
203
204 const ZERO: Self = 0;
205 const ONE: Self = 1;
206 const MIN: Self = <Self>::MIN;
207 const MAX: Self = <Self>::MAX;
208 }
209
210 impl Int for $uty {
211 fn unsigned(self) -> $uty {
212 self
213 }
214
215 #[allow(clippy::wrong_self_convention)]
217 fn from_unsigned(me: $uty) -> Self {
218 me
219 }
220
221 fn unsigned_abs(self) -> Self {
222 self
223 }
224
225 fn abs_diff(self, other: Self) -> Self {
226 self.abs_diff(other)
227 }
228
229 int_impl_common!($uty);
230 }
231
232 impl MinInt for $ity {
233 type OtherSign = $uty;
234 type UnsignedInt = $uty;
235
236 const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
237 const SIGNED: bool = Self::MIN != Self::ZERO;
238
239 const ZERO: Self = 0;
240 const ONE: Self = 1;
241 const MIN: Self = <Self>::MIN;
242 const MAX: Self = <Self>::MAX;
243 }
244
245 impl Int for $ity {
246 fn unsigned(self) -> $uty {
247 self as $uty
248 }
249
250 fn from_unsigned(me: $uty) -> Self {
251 me as $ity
252 }
253
254 fn unsigned_abs(self) -> Self::UnsignedInt {
255 self.unsigned_abs()
256 }
257
258 fn abs_diff(self, other: Self) -> $uty {
259 self.abs_diff(other)
260 }
261
262 int_impl_common!($ity);
263 }
264 };
265}
266
267int_impl!(isize, usize);
268int_impl!(i8, u8);
269int_impl!(i16, u16);
270int_impl!(i32, u32);
271int_impl!(i64, u64);
272int_impl!(i128, u128);
273
274pub trait DInt: MinInt {
277 type H: HInt<D = Self>;
279
280 fn lo(self) -> Self::H;
282 fn hi(self) -> Self::H;
284 fn lo_hi(self) -> (Self::H, Self::H) {
286 (self.lo(), self.hi())
287 }
288 fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self {
290 lo.zero_widen() | hi.widen_hi()
291 }
292}
293
294pub trait HInt: Int {
297 type D: DInt<H = Self> + MinInt;
299
300 fn widen(self) -> Self::D;
306 fn zero_widen(self) -> Self::D;
309 fn widen_hi(self) -> Self::D;
311 fn zero_widen_mul(self, rhs: Self) -> Self::D;
313 fn widen_mul(self, rhs: Self) -> Self::D;
315}
316
317macro_rules! impl_d_int {
318 ($($X:ident $D:ident),*) => {
319 $(
320 impl DInt for $D {
321 type H = $X;
322
323 fn lo(self) -> Self::H {
324 self as $X
325 }
326 fn hi(self) -> Self::H {
327 (self >> <$X as MinInt>::BITS) as $X
328 }
329 }
330 )*
331 };
332}
333
334macro_rules! impl_h_int {
335 ($($H:ident $uH:ident $X:ident),*) => {
336 $(
337 impl HInt for $H {
338 type D = $X;
339
340 fn widen(self) -> Self::D {
341 self as $X
342 }
343 fn zero_widen(self) -> Self::D {
344 (self as $uH) as $X
345 }
346 fn zero_widen_mul(self, rhs: Self) -> Self::D {
347 self.zero_widen().wrapping_mul(rhs.zero_widen())
348 }
349 fn widen_mul(self, rhs: Self) -> Self::D {
350 self.widen().wrapping_mul(rhs.widen())
351 }
352 fn widen_hi(self) -> Self::D {
353 (self as $X) << <Self as MinInt>::BITS
354 }
355 }
356 )*
357 };
358}
359
360impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128);
361impl_h_int!(
362 u8 u8 u16,
363 u16 u16 u32,
364 u32 u32 u64,
365 u64 u64 u128,
366 i8 u8 i16,
367 i16 u16 i32,
368 i32 u32 i64,
369 i64 u64 i128
370);
371
372pub trait CastInto<T: Copy>: Copy {
374 fn cast(self) -> T;
375}
376
377pub trait CastFrom<T: Copy>: Copy {
378 fn cast_from(value: T) -> Self;
379}
380
381impl<T: Copy, U: CastInto<T> + Copy> CastFrom<U> for T {
382 fn cast_from(value: U) -> Self {
383 value.cast()
384 }
385}
386
387macro_rules! cast_into {
388 ($ty:ty) => {
389 cast_into!($ty; usize, isize, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128);
390 };
391 ($ty:ty; $($into:ty),*) => {$(
392 impl CastInto<$into> for $ty {
393 fn cast(self) -> $into {
394 self as $into
395 }
396 }
397 )*};
398}
399
400cast_into!(usize);
401cast_into!(isize);
402cast_into!(u8);
403cast_into!(i8);
404cast_into!(u16);
405cast_into!(i16);
406cast_into!(u32);
407cast_into!(i32);
408cast_into!(u64);
409cast_into!(i64);
410cast_into!(u128);
411cast_into!(i128);