1 use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
2 
3 use crate::bounds::Bounded;
4 use crate::ops::checked::*;
5 use crate::ops::saturating::Saturating;
6 use 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.
34 pub 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     /// ```
count_ones(self) -> u3266     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     /// ```
count_zeros(self) -> u3279     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     /// ```
leading_ones(self) -> u3293     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     /// ```
leading_zeros(self) -> u32109     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     /// ```
trailing_ones(self) -> u32123     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     /// ```
trailing_zeros(self) -> u32139     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     /// ```
rotate_left(self, n: u32) -> Self154     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     /// ```
rotate_right(self, n: u32) -> Self169     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     /// ```
signed_shl(self, n: u32) -> Self186     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     /// ```
signed_shr(self, n: u32) -> Self203     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     /// ```
unsigned_shl(self, n: u32) -> Self220     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     /// ```
unsigned_shr(self, n: u32) -> Self237     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     /// ```
swap_bytes(self) -> Self251     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     /// ```
reverse_bits(self) -> Self269     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     /// ```
from_be(x: Self) -> Self290     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     /// ```
from_le(x: Self) -> Self309     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     /// ```
to_be(self) -> Self328     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     /// ```
to_le(self) -> Self347     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     /// ```
pow(self, exp: u32) -> Self358     fn pow(self, exp: u32) -> Self;
359 }
360 
one_per_byte<P: PrimInt>() -> P361 fn 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::one();
367     let mut shift = 8;
368     let mut b = ret.count_zeros() >> 3;
369     while b != 0 {
370         ret = (ret << shift) | ret;
371         shift <<= 1;
372         b >>= 1;
373     }
374     ret
375 }
376 
reverse_bits_fallback<P: PrimInt>(i: P) -> P377 fn reverse_bits_fallback<P: PrimInt>(i: P) -> P {
378     let rep_01: P = one_per_byte();
379     let rep_03 = (rep_01 << 1) | rep_01;
380     let rep_05 = (rep_01 << 2) | rep_01;
381     let rep_0f = (rep_03 << 2) | rep_03;
382     let rep_33 = (rep_03 << 4) | rep_03;
383     let rep_55 = (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 = 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 
394 macro_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             #[inline]
408             fn leading_ones(self) -> u32 {
409                 <$T>::leading_ones(self)
410             }
411 
412             #[inline]
413             fn leading_zeros(self) -> u32 {
414                 <$T>::leading_zeros(self)
415             }
416 
417             #[inline]
418             fn trailing_ones(self) -> u32 {
419                 <$T>::trailing_ones(self)
420             }
421 
422             #[inline]
423             fn trailing_zeros(self) -> u32 {
424                 <$T>::trailing_zeros(self)
425             }
426 
427             #[inline]
428             fn rotate_left(self, n: u32) -> Self {
429                 <$T>::rotate_left(self, n)
430             }
431 
432             #[inline]
433             fn rotate_right(self, n: u32) -> Self {
434                 <$T>::rotate_right(self, n)
435             }
436 
437             #[inline]
438             fn signed_shl(self, n: u32) -> Self {
439                 ((self as $S) << n) as $T
440             }
441 
442             #[inline]
443             fn signed_shr(self, n: u32) -> Self {
444                 ((self as $S) >> n) as $T
445             }
446 
447             #[inline]
448             fn unsigned_shl(self, n: u32) -> Self {
449                 ((self as $U) << n) as $T
450             }
451 
452             #[inline]
453             fn unsigned_shr(self, n: u32) -> Self {
454                 ((self as $U) >> n) as $T
455             }
456 
457             #[inline]
458             fn swap_bytes(self) -> Self {
459                 <$T>::swap_bytes(self)
460             }
461 
462             #[inline]
463             fn reverse_bits(self) -> Self {
464                 <$T>::reverse_bits(self)
465             }
466 
467             #[inline]
468             fn from_be(x: Self) -> Self {
469                 <$T>::from_be(x)
470             }
471 
472             #[inline]
473             fn from_le(x: Self) -> Self {
474                 <$T>::from_le(x)
475             }
476 
477             #[inline]
478             fn to_be(self) -> Self {
479                 <$T>::to_be(self)
480             }
481 
482             #[inline]
483             fn to_le(self) -> Self {
484                 <$T>::to_le(self)
485             }
486 
487             #[inline]
488             fn pow(self, exp: u32) -> Self {
489                 <$T>::pow(self, exp)
490             }
491         }
492     };
493 }
494 
495 // prim_int_impl!(type, signed, unsigned);
496 prim_int_impl!(u8, i8, u8);
497 prim_int_impl!(u16, i16, u16);
498 prim_int_impl!(u32, i32, u32);
499 prim_int_impl!(u64, i64, u64);
500 prim_int_impl!(u128, i128, u128);
501 prim_int_impl!(usize, isize, usize);
502 prim_int_impl!(i8, i8, u8);
503 prim_int_impl!(i16, i16, u16);
504 prim_int_impl!(i32, i32, u32);
505 prim_int_impl!(i64, i64, u64);
506 prim_int_impl!(i128, i128, u128);
507 prim_int_impl!(isize, isize, usize);
508 
509 #[cfg(test)]
510 mod tests {
511     use crate::int::PrimInt;
512 
513     #[test]
reverse_bits()514     pub fn reverse_bits() {
515         use core::{i16, i32, i64, i8};
516 
517         assert_eq!(
518             PrimInt::reverse_bits(0x0123_4567_89ab_cdefu64),
519             0xf7b3_d591_e6a2_c480
520         );
521 
522         assert_eq!(PrimInt::reverse_bits(0i8), 0);
523         assert_eq!(PrimInt::reverse_bits(-1i8), -1);
524         assert_eq!(PrimInt::reverse_bits(1i8), i8::MIN);
525         assert_eq!(PrimInt::reverse_bits(i8::MIN), 1);
526         assert_eq!(PrimInt::reverse_bits(-2i8), i8::MAX);
527         assert_eq!(PrimInt::reverse_bits(i8::MAX), -2);
528 
529         assert_eq!(PrimInt::reverse_bits(0i16), 0);
530         assert_eq!(PrimInt::reverse_bits(-1i16), -1);
531         assert_eq!(PrimInt::reverse_bits(1i16), i16::MIN);
532         assert_eq!(PrimInt::reverse_bits(i16::MIN), 1);
533         assert_eq!(PrimInt::reverse_bits(-2i16), i16::MAX);
534         assert_eq!(PrimInt::reverse_bits(i16::MAX), -2);
535 
536         assert_eq!(PrimInt::reverse_bits(0i32), 0);
537         assert_eq!(PrimInt::reverse_bits(-1i32), -1);
538         assert_eq!(PrimInt::reverse_bits(1i32), i32::MIN);
539         assert_eq!(PrimInt::reverse_bits(i32::MIN), 1);
540         assert_eq!(PrimInt::reverse_bits(-2i32), i32::MAX);
541         assert_eq!(PrimInt::reverse_bits(i32::MAX), -2);
542 
543         assert_eq!(PrimInt::reverse_bits(0i64), 0);
544         assert_eq!(PrimInt::reverse_bits(-1i64), -1);
545         assert_eq!(PrimInt::reverse_bits(1i64), i64::MIN);
546         assert_eq!(PrimInt::reverse_bits(i64::MIN), 1);
547         assert_eq!(PrimInt::reverse_bits(-2i64), i64::MAX);
548         assert_eq!(PrimInt::reverse_bits(i64::MAX), -2);
549     }
550 
551     #[test]
reverse_bits_i128()552     pub fn reverse_bits_i128() {
553         use core::i128;
554 
555         assert_eq!(PrimInt::reverse_bits(0i128), 0);
556         assert_eq!(PrimInt::reverse_bits(-1i128), -1);
557         assert_eq!(PrimInt::reverse_bits(1i128), i128::MIN);
558         assert_eq!(PrimInt::reverse_bits(i128::MIN), 1);
559         assert_eq!(PrimInt::reverse_bits(-2i128), i128::MAX);
560         assert_eq!(PrimInt::reverse_bits(i128::MAX), -2);
561     }
562 }
563