• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
2 
3 use bounds::Bounded;
4 use ops::checked::*;
5 use ops::saturating::Saturating;
6 use {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 zeros in the binary representation
82     /// of `self`.
83     ///
84     /// # Examples
85     ///
86     /// ```
87     /// use num_traits::PrimInt;
88     ///
89     /// let n = 0b0101000u16;
90     ///
91     /// assert_eq!(n.leading_zeros(), 10);
92     /// ```
leading_zeros(self) -> u3293     fn leading_zeros(self) -> u32;
94 
95     /// Returns the number of trailing zeros in the binary representation
96     /// of `self`.
97     ///
98     /// # Examples
99     ///
100     /// ```
101     /// use num_traits::PrimInt;
102     ///
103     /// let n = 0b0101000u16;
104     ///
105     /// assert_eq!(n.trailing_zeros(), 3);
106     /// ```
trailing_zeros(self) -> u32107     fn trailing_zeros(self) -> u32;
108 
109     /// Shifts the bits to the left by a specified amount, `n`, wrapping
110     /// the truncated bits to the end of the resulting integer.
111     ///
112     /// # Examples
113     ///
114     /// ```
115     /// use num_traits::PrimInt;
116     ///
117     /// let n = 0x0123456789ABCDEFu64;
118     /// let m = 0x3456789ABCDEF012u64;
119     ///
120     /// assert_eq!(n.rotate_left(12), m);
121     /// ```
rotate_left(self, n: u32) -> Self122     fn rotate_left(self, n: u32) -> Self;
123 
124     /// Shifts the bits to the right by a specified amount, `n`, wrapping
125     /// the truncated bits to the beginning of the resulting integer.
126     ///
127     /// # Examples
128     ///
129     /// ```
130     /// use num_traits::PrimInt;
131     ///
132     /// let n = 0x0123456789ABCDEFu64;
133     /// let m = 0xDEF0123456789ABCu64;
134     ///
135     /// assert_eq!(n.rotate_right(12), m);
136     /// ```
rotate_right(self, n: u32) -> Self137     fn rotate_right(self, n: u32) -> Self;
138 
139     /// Shifts the bits to the left by a specified amount, `n`, filling
140     /// zeros in the least significant bits.
141     ///
142     /// This is bitwise equivalent to signed `Shl`.
143     ///
144     /// # Examples
145     ///
146     /// ```
147     /// use num_traits::PrimInt;
148     ///
149     /// let n = 0x0123456789ABCDEFu64;
150     /// let m = 0x3456789ABCDEF000u64;
151     ///
152     /// assert_eq!(n.signed_shl(12), m);
153     /// ```
signed_shl(self, n: u32) -> Self154     fn signed_shl(self, n: u32) -> Self;
155 
156     /// Shifts the bits to the right by a specified amount, `n`, copying
157     /// the "sign bit" in the most significant bits even for unsigned types.
158     ///
159     /// This is bitwise equivalent to signed `Shr`.
160     ///
161     /// # Examples
162     ///
163     /// ```
164     /// use num_traits::PrimInt;
165     ///
166     /// let n = 0xFEDCBA9876543210u64;
167     /// let m = 0xFFFFEDCBA9876543u64;
168     ///
169     /// assert_eq!(n.signed_shr(12), m);
170     /// ```
signed_shr(self, n: u32) -> Self171     fn signed_shr(self, n: u32) -> Self;
172 
173     /// Shifts the bits to the left by a specified amount, `n`, filling
174     /// zeros in the least significant bits.
175     ///
176     /// This is bitwise equivalent to unsigned `Shl`.
177     ///
178     /// # Examples
179     ///
180     /// ```
181     /// use num_traits::PrimInt;
182     ///
183     /// let n = 0x0123456789ABCDEFi64;
184     /// let m = 0x3456789ABCDEF000i64;
185     ///
186     /// assert_eq!(n.unsigned_shl(12), m);
187     /// ```
unsigned_shl(self, n: u32) -> Self188     fn unsigned_shl(self, n: u32) -> Self;
189 
190     /// Shifts the bits to the right by a specified amount, `n`, filling
191     /// zeros in the most significant bits.
192     ///
193     /// This is bitwise equivalent to unsigned `Shr`.
194     ///
195     /// # Examples
196     ///
197     /// ```
198     /// use num_traits::PrimInt;
199     ///
200     /// let n = -8i8; // 0b11111000
201     /// let m = 62i8; // 0b00111110
202     ///
203     /// assert_eq!(n.unsigned_shr(2), m);
204     /// ```
unsigned_shr(self, n: u32) -> Self205     fn unsigned_shr(self, n: u32) -> Self;
206 
207     /// Reverses the byte order of the integer.
208     ///
209     /// # Examples
210     ///
211     /// ```
212     /// use num_traits::PrimInt;
213     ///
214     /// let n = 0x0123456789ABCDEFu64;
215     /// let m = 0xEFCDAB8967452301u64;
216     ///
217     /// assert_eq!(n.swap_bytes(), m);
218     /// ```
swap_bytes(self) -> Self219     fn swap_bytes(self) -> Self;
220 
221     /// Convert an integer from big endian to the target's endianness.
222     ///
223     /// On big endian this is a no-op. On little endian the bytes are swapped.
224     ///
225     /// # Examples
226     ///
227     /// ```
228     /// use num_traits::PrimInt;
229     ///
230     /// let n = 0x0123456789ABCDEFu64;
231     ///
232     /// if cfg!(target_endian = "big") {
233     ///     assert_eq!(u64::from_be(n), n)
234     /// } else {
235     ///     assert_eq!(u64::from_be(n), n.swap_bytes())
236     /// }
237     /// ```
from_be(x: Self) -> Self238     fn from_be(x: Self) -> Self;
239 
240     /// Convert an integer from little endian to the target's endianness.
241     ///
242     /// On little endian this is a no-op. On big endian the bytes are swapped.
243     ///
244     /// # Examples
245     ///
246     /// ```
247     /// use num_traits::PrimInt;
248     ///
249     /// let n = 0x0123456789ABCDEFu64;
250     ///
251     /// if cfg!(target_endian = "little") {
252     ///     assert_eq!(u64::from_le(n), n)
253     /// } else {
254     ///     assert_eq!(u64::from_le(n), n.swap_bytes())
255     /// }
256     /// ```
from_le(x: Self) -> Self257     fn from_le(x: Self) -> Self;
258 
259     /// Convert `self` to big endian from the target's endianness.
260     ///
261     /// On big endian this is a no-op. On little endian the bytes are swapped.
262     ///
263     /// # Examples
264     ///
265     /// ```
266     /// use num_traits::PrimInt;
267     ///
268     /// let n = 0x0123456789ABCDEFu64;
269     ///
270     /// if cfg!(target_endian = "big") {
271     ///     assert_eq!(n.to_be(), n)
272     /// } else {
273     ///     assert_eq!(n.to_be(), n.swap_bytes())
274     /// }
275     /// ```
to_be(self) -> Self276     fn to_be(self) -> Self;
277 
278     /// Convert `self` to little endian from the target's endianness.
279     ///
280     /// On little endian this is a no-op. On big endian the bytes are swapped.
281     ///
282     /// # Examples
283     ///
284     /// ```
285     /// use num_traits::PrimInt;
286     ///
287     /// let n = 0x0123456789ABCDEFu64;
288     ///
289     /// if cfg!(target_endian = "little") {
290     ///     assert_eq!(n.to_le(), n)
291     /// } else {
292     ///     assert_eq!(n.to_le(), n.swap_bytes())
293     /// }
294     /// ```
to_le(self) -> Self295     fn to_le(self) -> Self;
296 
297     /// Raises self to the power of `exp`, using exponentiation by squaring.
298     ///
299     /// # Examples
300     ///
301     /// ```
302     /// use num_traits::PrimInt;
303     ///
304     /// assert_eq!(2i32.pow(4), 16);
305     /// ```
pow(self, exp: u32) -> Self306     fn pow(self, exp: u32) -> Self;
307 }
308 
309 macro_rules! prim_int_impl {
310     ($T:ty, $S:ty, $U:ty) => {
311         impl PrimInt for $T {
312             #[inline]
313             fn count_ones(self) -> u32 {
314                 <$T>::count_ones(self)
315             }
316 
317             #[inline]
318             fn count_zeros(self) -> u32 {
319                 <$T>::count_zeros(self)
320             }
321 
322             #[inline]
323             fn leading_zeros(self) -> u32 {
324                 <$T>::leading_zeros(self)
325             }
326 
327             #[inline]
328             fn trailing_zeros(self) -> u32 {
329                 <$T>::trailing_zeros(self)
330             }
331 
332             #[inline]
333             fn rotate_left(self, n: u32) -> Self {
334                 <$T>::rotate_left(self, n)
335             }
336 
337             #[inline]
338             fn rotate_right(self, n: u32) -> Self {
339                 <$T>::rotate_right(self, n)
340             }
341 
342             #[inline]
343             fn signed_shl(self, n: u32) -> Self {
344                 ((self as $S) << n) as $T
345             }
346 
347             #[inline]
348             fn signed_shr(self, n: u32) -> Self {
349                 ((self as $S) >> n) as $T
350             }
351 
352             #[inline]
353             fn unsigned_shl(self, n: u32) -> Self {
354                 ((self as $U) << n) as $T
355             }
356 
357             #[inline]
358             fn unsigned_shr(self, n: u32) -> Self {
359                 ((self as $U) >> n) as $T
360             }
361 
362             #[inline]
363             fn swap_bytes(self) -> Self {
364                 <$T>::swap_bytes(self)
365             }
366 
367             #[inline]
368             fn from_be(x: Self) -> Self {
369                 <$T>::from_be(x)
370             }
371 
372             #[inline]
373             fn from_le(x: Self) -> Self {
374                 <$T>::from_le(x)
375             }
376 
377             #[inline]
378             fn to_be(self) -> Self {
379                 <$T>::to_be(self)
380             }
381 
382             #[inline]
383             fn to_le(self) -> Self {
384                 <$T>::to_le(self)
385             }
386 
387             #[inline]
388             fn pow(self, exp: u32) -> Self {
389                 <$T>::pow(self, exp)
390             }
391         }
392     };
393 }
394 
395 // prim_int_impl!(type, signed, unsigned);
396 prim_int_impl!(u8, i8, u8);
397 prim_int_impl!(u16, i16, u16);
398 prim_int_impl!(u32, i32, u32);
399 prim_int_impl!(u64, i64, u64);
400 #[cfg(has_i128)]
401 prim_int_impl!(u128, i128, u128);
402 prim_int_impl!(usize, isize, usize);
403 prim_int_impl!(i8, i8, u8);
404 prim_int_impl!(i16, i16, u16);
405 prim_int_impl!(i32, i32, u32);
406 prim_int_impl!(i64, i64, u64);
407 #[cfg(has_i128)]
408 prim_int_impl!(i128, i128, u128);
409 prim_int_impl!(isize, isize, usize);
410