num_traits/
int.rs

1use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
2
3use bounds::Bounded;
4use ops::checked::*;
5use ops::saturating::Saturating;
6use {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 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    /// ```
93    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    /// ```
107    fn trailing_zeros(self) -> u32;
108
109    /// Shifts the bits to the left by a specified amount 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    /// ```
122    fn rotate_left(self, n: u32) -> Self;
123
124    /// Shifts the bits to the right by a specified amount 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    /// ```
137    fn rotate_right(self, n: u32) -> Self;
138
139    /// Shifts the bits to the left by a specified amount 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    /// ```
154    fn signed_shl(self, n: u32) -> Self;
155
156    /// Shifts the bits to the right by a specified amount 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    /// ```
171    fn signed_shr(self, n: u32) -> Self;
172
173    /// Shifts the bits to the left by a specified amount 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    /// ```
188    fn unsigned_shl(self, n: u32) -> Self;
189
190    /// Shifts the bits to the right by a specified amount 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    /// ```
205    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    /// ```
219    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    /// ```
238    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    /// ```
257    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    /// ```
276    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    /// ```
295    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    /// ```
306    fn pow(self, exp: u32) -> Self;
307}
308
309macro_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);
396prim_int_impl!(u8, i8, u8);
397prim_int_impl!(u16, i16, u16);
398prim_int_impl!(u32, i32, u32);
399prim_int_impl!(u64, i64, u64);
400#[cfg(has_i128)]
401prim_int_impl!(u128, i128, u128);
402prim_int_impl!(usize, isize, usize);
403prim_int_impl!(i8, i8, u8);
404prim_int_impl!(i16, i16, u16);
405prim_int_impl!(i32, i32, u32);
406prim_int_impl!(i64, i64, u64);
407#[cfg(has_i128)]
408prim_int_impl!(i128, i128, u128);
409prim_int_impl!(isize, isize, usize);