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