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);