1use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
2
3use crate::bounds::Bounded;
4use crate::ops::checked::*;
5use crate::ops::saturating::Saturating;
6use crate::{Num, NumCast};
7
8/// Generic trait for primitive integers.
9///
10/// The `PrimInt` trait is an abstraction over the builtin primitive integer types (e.g., `u8`,
11/// `u32`, `isize`, `i128`, ...). It inherits the basic numeric traits and extends them with
12/// bitwise operators and non-wrapping arithmetic.
13///
14/// The trait explicitly inherits `Copy`, `Eq`, `Ord`, and `Sized`. The intention is that all
15/// types implementing this trait behave like primitive types that are passed by value by default
16/// and behave like builtin integers. Furthermore, the types are expected to expose the integer
17/// value in binary representation and support bitwise operators. The standard bitwise operations
18/// (e.g., bitwise-and, bitwise-or, right-shift, left-shift) are inherited and the trait extends
19/// these with introspective queries (e.g., `PrimInt::count_ones()`, `PrimInt::leading_zeros()`),
20/// bitwise combinators (e.g., `PrimInt::rotate_left()`), and endianness converters (e.g.,
21/// `PrimInt::to_be()`).
22///
23/// All `PrimInt` types are expected to be fixed-width binary integers. The width can be queried
24/// via `T::zero().count_zeros()`. The trait currently lacks a way to query the width at
25/// compile-time.
26///
27/// While a default implementation for all builtin primitive integers is provided, the trait is in
28/// no way restricted to these. Other integer types that fulfil the requirements are free to
29/// implement the trait was well.
30///
31/// This trait and many of the method names originate in the unstable `core::num::Int` trait from
32/// the rust standard library. The original trait was never stabilized and thus removed from the
33/// standard library.
34pub trait PrimInt:
35 Sized
36 + Copy
37 + Num
38 + NumCast
39 + Bounded
40 + PartialOrd
41 + Ord
42 + Eq
43 + Not<Output = Self>
44 + BitAnd<Output = Self>
45 + BitOr<Output = Self>
46 + BitXor<Output = Self>
47 + Shl<usize, Output = Self>
48 + Shr<usize, Output = Self>
49 + CheckedAdd<Output = Self>
50 + CheckedSub<Output = Self>
51 + CheckedMul<Output = Self>
52 + CheckedDiv<Output = Self>
53 + Saturating
54{
55 /// Returns the number of ones in the binary representation of `self`.
56 ///
57 /// # Examples
58 ///
59 /// ```
60 /// use num_traits::PrimInt;
61 ///
62 /// let n = 0b01001100u8;
63 ///
64 /// assert_eq!(n.count_ones(), 3);
65 /// ```
66 fn count_ones(self) -> u32;
67
68 /// Returns the number of zeros in the binary representation of `self`.
69 ///
70 /// # Examples
71 ///
72 /// ```
73 /// use num_traits::PrimInt;
74 ///
75 /// let n = 0b01001100u8;
76 ///
77 /// assert_eq!(n.count_zeros(), 5);
78 /// ```
79 fn count_zeros(self) -> u32;
80
81 /// Returns the number of leading ones in the binary representation
82 /// of `self`.
83 ///
84 /// # Examples
85 ///
86 /// ```
87 /// use num_traits::PrimInt;
88 ///
89 /// let n = 0xF00Du16;
90 ///
91 /// assert_eq!(n.leading_ones(), 4);
92 /// ```
93 fn leading_ones(self) -> u32 {
94 (!self).leading_zeros()
95 }
96
97 /// Returns the number of leading zeros in the binary representation
98 /// of `self`.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use num_traits::PrimInt;
104 ///
105 /// let n = 0b0101000u16;
106 ///
107 /// assert_eq!(n.leading_zeros(), 10);
108 /// ```
109 fn leading_zeros(self) -> u32;
110
111 /// Returns the number of trailing ones in the binary representation
112 /// of `self`.
113 ///
114 /// # Examples
115 ///
116 /// ```
117 /// use num_traits::PrimInt;
118 ///
119 /// let n = 0xBEEFu16;
120 ///
121 /// assert_eq!(n.trailing_ones(), 4);
122 /// ```
123 fn trailing_ones(self) -> u32 {
124 (!self).trailing_zeros()
125 }
126
127 /// Returns the number of trailing zeros in the binary representation
128 /// of `self`.
129 ///
130 /// # Examples
131 ///
132 /// ```
133 /// use num_traits::PrimInt;
134 ///
135 /// let n = 0b0101000u16;
136 ///
137 /// assert_eq!(n.trailing_zeros(), 3);
138 /// ```
139 fn trailing_zeros(self) -> u32;
140
141 /// Shifts the bits to the left by a specified amount, `n`, wrapping
142 /// the truncated bits to the end of the resulting integer.
143 ///
144 /// # Examples
145 ///
146 /// ```
147 /// use num_traits::PrimInt;
148 ///
149 /// let n = 0x0123456789ABCDEFu64;
150 /// let m = 0x3456789ABCDEF012u64;
151 ///
152 /// assert_eq!(n.rotate_left(12), m);
153 /// ```
154 fn rotate_left(self, n: u32) -> Self;
155
156 /// Shifts the bits to the right by a specified amount, `n`, wrapping
157 /// the truncated bits to the beginning of the resulting integer.
158 ///
159 /// # Examples
160 ///
161 /// ```
162 /// use num_traits::PrimInt;
163 ///
164 /// let n = 0x0123456789ABCDEFu64;
165 /// let m = 0xDEF0123456789ABCu64;
166 ///
167 /// assert_eq!(n.rotate_right(12), m);
168 /// ```
169 fn rotate_right(self, n: u32) -> Self;
170
171 /// Shifts the bits to the left by a specified amount, `n`, filling
172 /// zeros in the least significant bits.
173 ///
174 /// This is bitwise equivalent to signed `Shl`.
175 ///
176 /// # Examples
177 ///
178 /// ```
179 /// use num_traits::PrimInt;
180 ///
181 /// let n = 0x0123456789ABCDEFu64;
182 /// let m = 0x3456789ABCDEF000u64;
183 ///
184 /// assert_eq!(n.signed_shl(12), m);
185 /// ```
186 fn signed_shl(self, n: u32) -> Self;
187
188 /// Shifts the bits to the right by a specified amount, `n`, copying
189 /// the "sign bit" in the most significant bits even for unsigned types.
190 ///
191 /// This is bitwise equivalent to signed `Shr`.
192 ///
193 /// # Examples
194 ///
195 /// ```
196 /// use num_traits::PrimInt;
197 ///
198 /// let n = 0xFEDCBA9876543210u64;
199 /// let m = 0xFFFFEDCBA9876543u64;
200 ///
201 /// assert_eq!(n.signed_shr(12), m);
202 /// ```
203 fn signed_shr(self, n: u32) -> Self;
204
205 /// Shifts the bits to the left by a specified amount, `n`, filling
206 /// zeros in the least significant bits.
207 ///
208 /// This is bitwise equivalent to unsigned `Shl`.
209 ///
210 /// # Examples
211 ///
212 /// ```
213 /// use num_traits::PrimInt;
214 ///
215 /// let n = 0x0123456789ABCDEFi64;
216 /// let m = 0x3456789ABCDEF000i64;
217 ///
218 /// assert_eq!(n.unsigned_shl(12), m);
219 /// ```
220 fn unsigned_shl(self, n: u32) -> Self;
221
222 /// Shifts the bits to the right by a specified amount, `n`, filling
223 /// zeros in the most significant bits.
224 ///
225 /// This is bitwise equivalent to unsigned `Shr`.
226 ///
227 /// # Examples
228 ///
229 /// ```
230 /// use num_traits::PrimInt;
231 ///
232 /// let n = -8i8; // 0b11111000
233 /// let m = 62i8; // 0b00111110
234 ///
235 /// assert_eq!(n.unsigned_shr(2), m);
236 /// ```
237 fn unsigned_shr(self, n: u32) -> Self;
238
239 /// Reverses the byte order of the integer.
240 ///
241 /// # Examples
242 ///
243 /// ```
244 /// use num_traits::PrimInt;
245 ///
246 /// let n = 0x0123456789ABCDEFu64;
247 /// let m = 0xEFCDAB8967452301u64;
248 ///
249 /// assert_eq!(n.swap_bytes(), m);
250 /// ```
251 fn swap_bytes(self) -> Self;
252
253 /// Reverses the order of bits in the integer.
254 ///
255 /// The least significant bit becomes the most significant bit, second least-significant bit
256 /// becomes second most-significant bit, etc.
257 ///
258 /// # Examples
259 ///
260 /// ```
261 /// use num_traits::PrimInt;
262 ///
263 /// let n = 0x12345678u32;
264 /// let m = 0x1e6a2c48u32;
265 ///
266 /// assert_eq!(n.reverse_bits(), m);
267 /// assert_eq!(0u32.reverse_bits(), 0);
268 /// ```
269 fn reverse_bits(self) -> Self {
270 reverse_bits_fallback(self)
271 }
272
273 /// Convert an integer from big endian to the target's endianness.
274 ///
275 /// On big endian this is a no-op. On little endian the bytes are swapped.
276 ///
277 /// # Examples
278 ///
279 /// ```
280 /// use num_traits::PrimInt;
281 ///
282 /// let n = 0x0123456789ABCDEFu64;
283 ///
284 /// if cfg!(target_endian = "big") {
285 /// assert_eq!(u64::from_be(n), n)
286 /// } else {
287 /// assert_eq!(u64::from_be(n), n.swap_bytes())
288 /// }
289 /// ```
290 fn from_be(x: Self) -> Self;
291
292 /// Convert an integer from little endian to the target's endianness.
293 ///
294 /// On little endian this is a no-op. On big endian the bytes are swapped.
295 ///
296 /// # Examples
297 ///
298 /// ```
299 /// use num_traits::PrimInt;
300 ///
301 /// let n = 0x0123456789ABCDEFu64;
302 ///
303 /// if cfg!(target_endian = "little") {
304 /// assert_eq!(u64::from_le(n), n)
305 /// } else {
306 /// assert_eq!(u64::from_le(n), n.swap_bytes())
307 /// }
308 /// ```
309 fn from_le(x: Self) -> Self;
310
311 /// Convert `self` to big endian from the target's endianness.
312 ///
313 /// On big endian this is a no-op. On little endian the bytes are swapped.
314 ///
315 /// # Examples
316 ///
317 /// ```
318 /// use num_traits::PrimInt;
319 ///
320 /// let n = 0x0123456789ABCDEFu64;
321 ///
322 /// if cfg!(target_endian = "big") {
323 /// assert_eq!(n.to_be(), n)
324 /// } else {
325 /// assert_eq!(n.to_be(), n.swap_bytes())
326 /// }
327 /// ```
328 fn to_be(self) -> Self;
329
330 /// Convert `self` to little endian from the target's endianness.
331 ///
332 /// On little endian this is a no-op. On big endian the bytes are swapped.
333 ///
334 /// # Examples
335 ///
336 /// ```
337 /// use num_traits::PrimInt;
338 ///
339 /// let n = 0x0123456789ABCDEFu64;
340 ///
341 /// if cfg!(target_endian = "little") {
342 /// assert_eq!(n.to_le(), n)
343 /// } else {
344 /// assert_eq!(n.to_le(), n.swap_bytes())
345 /// }
346 /// ```
347 fn to_le(self) -> Self;
348
349 /// Raises self to the power of `exp`, using exponentiation by squaring.
350 ///
351 /// # Examples
352 ///
353 /// ```
354 /// use num_traits::PrimInt;
355 ///
356 /// assert_eq!(2i32.pow(4), 16);
357 /// ```
358 fn pow(self, exp: u32) -> Self;
359}
360
361fn one_per_byte<P: PrimInt>() -> P {
362 // i8, u8: return 0x01
363 // i16, u16: return 0x0101 = (0x01 << 8) | 0x01
364 // i32, u32: return 0x01010101 = (0x0101 << 16) | 0x0101
365 // ...
366 let mut ret: P = P::one();
367 let mut shift: usize = 8;
368 let mut b: u32 = ret.count_zeros() >> 3;
369 while b != 0 {
370 ret = (ret << shift) | ret;
371 shift <<= 1;
372 b >>= 1;
373 }
374 ret
375}
376
377fn reverse_bits_fallback<P: PrimInt>(i: P) -> P {
378 let rep_01: P = one_per_byte();
379 let rep_03: P = (rep_01 << 1) | rep_01;
380 let rep_05: P = (rep_01 << 2) | rep_01;
381 let rep_0f: P = (rep_03 << 2) | rep_03;
382 let rep_33: P = (rep_03 << 4) | rep_03;
383 let rep_55: P = (rep_05 << 4) | rep_05;
384
385 // code above only used to determine rep_0f, rep_33, rep_55;
386 // optimizer should be able to do it in compile time
387 let mut ret: P = i.swap_bytes();
388 ret = ((ret & rep_0f) << 4) | ((ret >> 4) & rep_0f);
389 ret = ((ret & rep_33) << 2) | ((ret >> 2) & rep_33);
390 ret = ((ret & rep_55) << 1) | ((ret >> 1) & rep_55);
391 ret
392}
393
394macro_rules! prim_int_impl {
395 ($T:ty, $S:ty, $U:ty) => {
396 impl PrimInt for $T {
397 #[inline]
398 fn count_ones(self) -> u32 {
399 <$T>::count_ones(self)
400 }
401
402 #[inline]
403 fn count_zeros(self) -> u32 {
404 <$T>::count_zeros(self)
405 }
406
407 #[cfg(has_leading_trailing_ones)]
408 #[inline]
409 fn leading_ones(self) -> u32 {
410 <$T>::leading_ones(self)
411 }
412
413 #[inline]
414 fn leading_zeros(self) -> u32 {
415 <$T>::leading_zeros(self)
416 }
417
418 #[cfg(has_leading_trailing_ones)]
419 #[inline]
420 fn trailing_ones(self) -> u32 {
421 <$T>::trailing_ones(self)
422 }
423
424 #[inline]
425 fn trailing_zeros(self) -> u32 {
426 <$T>::trailing_zeros(self)
427 }
428
429 #[inline]
430 fn rotate_left(self, n: u32) -> Self {
431 <$T>::rotate_left(self, n)
432 }
433
434 #[inline]
435 fn rotate_right(self, n: u32) -> Self {
436 <$T>::rotate_right(self, n)
437 }
438
439 #[inline]
440 fn signed_shl(self, n: u32) -> Self {
441 ((self as $S) << n) as $T
442 }
443
444 #[inline]
445 fn signed_shr(self, n: u32) -> Self {
446 ((self as $S) >> n) as $T
447 }
448
449 #[inline]
450 fn unsigned_shl(self, n: u32) -> Self {
451 ((self as $U) << n) as $T
452 }
453
454 #[inline]
455 fn unsigned_shr(self, n: u32) -> Self {
456 ((self as $U) >> n) as $T
457 }
458
459 #[inline]
460 fn swap_bytes(self) -> Self {
461 <$T>::swap_bytes(self)
462 }
463
464 #[cfg(has_reverse_bits)]
465 #[inline]
466 fn reverse_bits(self) -> Self {
467 <$T>::reverse_bits(self)
468 }
469
470 #[inline]
471 fn from_be(x: Self) -> Self {
472 <$T>::from_be(x)
473 }
474
475 #[inline]
476 fn from_le(x: Self) -> Self {
477 <$T>::from_le(x)
478 }
479
480 #[inline]
481 fn to_be(self) -> Self {
482 <$T>::to_be(self)
483 }
484
485 #[inline]
486 fn to_le(self) -> Self {
487 <$T>::to_le(self)
488 }
489
490 #[inline]
491 fn pow(self, exp: u32) -> Self {
492 <$T>::pow(self, exp)
493 }
494 }
495 };
496}
497
498// prim_int_impl!(type, signed, unsigned);
499prim_int_impl!(u8, i8, u8);
500prim_int_impl!(u16, i16, u16);
501prim_int_impl!(u32, i32, u32);
502prim_int_impl!(u64, i64, u64);
503prim_int_impl!(u128, i128, u128);
504prim_int_impl!(usize, isize, usize);
505prim_int_impl!(i8, i8, u8);
506prim_int_impl!(i16, i16, u16);
507prim_int_impl!(i32, i32, u32);
508prim_int_impl!(i64, i64, u64);
509prim_int_impl!(i128, i128, u128);
510prim_int_impl!(isize, isize, usize);
511
512#[cfg(test)]
513mod tests {
514 use crate::int::PrimInt;
515
516 #[test]
517 pub fn reverse_bits() {
518 use core::{i16, i32, i64, i8};
519
520 assert_eq!(
521 PrimInt::reverse_bits(0x0123_4567_89ab_cdefu64),
522 0xf7b3_d591_e6a2_c480
523 );
524
525 assert_eq!(PrimInt::reverse_bits(0i8), 0);
526 assert_eq!(PrimInt::reverse_bits(-1i8), -1);
527 assert_eq!(PrimInt::reverse_bits(1i8), i8::MIN);
528 assert_eq!(PrimInt::reverse_bits(i8::MIN), 1);
529 assert_eq!(PrimInt::reverse_bits(-2i8), i8::MAX);
530 assert_eq!(PrimInt::reverse_bits(i8::MAX), -2);
531
532 assert_eq!(PrimInt::reverse_bits(0i16), 0);
533 assert_eq!(PrimInt::reverse_bits(-1i16), -1);
534 assert_eq!(PrimInt::reverse_bits(1i16), i16::MIN);
535 assert_eq!(PrimInt::reverse_bits(i16::MIN), 1);
536 assert_eq!(PrimInt::reverse_bits(-2i16), i16::MAX);
537 assert_eq!(PrimInt::reverse_bits(i16::MAX), -2);
538
539 assert_eq!(PrimInt::reverse_bits(0i32), 0);
540 assert_eq!(PrimInt::reverse_bits(-1i32), -1);
541 assert_eq!(PrimInt::reverse_bits(1i32), i32::MIN);
542 assert_eq!(PrimInt::reverse_bits(i32::MIN), 1);
543 assert_eq!(PrimInt::reverse_bits(-2i32), i32::MAX);
544 assert_eq!(PrimInt::reverse_bits(i32::MAX), -2);
545
546 assert_eq!(PrimInt::reverse_bits(0i64), 0);
547 assert_eq!(PrimInt::reverse_bits(-1i64), -1);
548 assert_eq!(PrimInt::reverse_bits(1i64), i64::MIN);
549 assert_eq!(PrimInt::reverse_bits(i64::MIN), 1);
550 assert_eq!(PrimInt::reverse_bits(-2i64), i64::MAX);
551 assert_eq!(PrimInt::reverse_bits(i64::MAX), -2);
552 }
553
554 #[test]
555 pub fn reverse_bits_i128() {
556 use core::i128;
557
558 assert_eq!(PrimInt::reverse_bits(0i128), 0);
559 assert_eq!(PrimInt::reverse_bits(-1i128), -1);
560 assert_eq!(PrimInt::reverse_bits(1i128), i128::MIN);
561 assert_eq!(PrimInt::reverse_bits(i128::MIN), 1);
562 assert_eq!(PrimInt::reverse_bits(-2i128), i128::MAX);
563 assert_eq!(PrimInt::reverse_bits(i128::MAX), -2);
564 }
565}
566