diff options
| author | Brendan Zabarauskas <bjzaba@yahoo.com.au> | 2014-06-16 11:25:47 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-06-18 17:01:34 -0700 |
| commit | ff9f92ce5224f5e27b8dc39ffc02eb9481f7cff1 (patch) | |
| tree | f56ac5a3288101c49c4cc5c2e85b18dd4c2c6ff7 /src/libcore | |
| parent | 4c0f8f49f6fe860efa268efa2f4fa0b5f00a4b07 (diff) | |
| download | rust-ff9f92ce5224f5e27b8dc39ffc02eb9481f7cff1.tar.gz rust-ff9f92ce5224f5e27b8dc39ffc02eb9481f7cff1.zip | |
Merge the Bitwise and ByteOrder traits into the Int trait
This reduces the complexity of the trait hierarchy.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/mem.rs | 220 | ||||
| -rw-r--r-- | src/libcore/num/int_macros.rs | 69 | ||||
| -rw-r--r-- | src/libcore/num/mod.rs | 305 | ||||
| -rw-r--r-- | src/libcore/num/uint_macros.rs | 69 |
4 files changed, 318 insertions, 345 deletions
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index b64ee9bf4f7..eab344ac7a7 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -13,10 +13,9 @@ //! This module contains functions for querying the size and alignment of //! types, initializing and manipulating memory. -use clone::Clone; -use ptr; use intrinsics; -use intrinsics::{bswap16, bswap32, bswap64}; +use num::Int; +use ptr; pub use intrinsics::transmute; @@ -170,155 +169,6 @@ pub unsafe fn move_val_init<T>(dst: &mut T, src: T) { ptr::write(dst, src) } -/// A type that can have its bytes re-ordered. -pub trait ByteOrder: Clone { - /// Reverses the byte order of the value. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xEFCDAB8967452301u64; - /// - /// assert_eq!(n.swap_bytes(), m); - /// ``` - fn swap_bytes(&self) -> Self; - - /// Convert a value from big endian to the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(ByteOrder::from_big_endian(n), n) - /// } else { - /// assert_eq!(ByteOrder::from_big_endian(n), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn from_big_endian(x: Self) -> Self { - if cfg!(target_endian = "big") { x } else { x.swap_bytes() } - } - - /// Convert a value from little endian to the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(ByteOrder::from_little_endian(n), n) - /// } else { - /// assert_eq!(ByteOrder::from_little_endian(n), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn from_little_endian(x: Self) -> Self { - if cfg!(target_endian = "little") { x } else { x.swap_bytes() } - } - - /// Convert the value to big endian from the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_big_endian(), n) - /// } else { - /// assert_eq!(n.to_big_endian(), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn to_big_endian(&self) -> Self { - if cfg!(target_endian = "big") { self.clone() } else { self.swap_bytes() } - } - - /// Convert the value to little endian from the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_little_endian(), n) - /// } else { - /// assert_eq!(n.to_little_endian(), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn to_little_endian(&self) -> Self { - if cfg!(target_endian = "little") { self.clone() } else { self.swap_bytes() } - } -} - -impl ByteOrder for u8 { - #[inline] - fn swap_bytes(&self) -> u8 { - *self // swapping a single byte does nothing - } -} - -impl ByteOrder for u16 { - #[inline] - fn swap_bytes(&self) -> u16 { - unsafe { intrinsics::bswap16(*self) } - } -} - -impl ByteOrder for u32 { - #[inline] - fn swap_bytes(&self) -> u32 { - unsafe { intrinsics::bswap32(*self) } - } -} - -impl ByteOrder for u64 { - #[inline] - fn swap_bytes(&self) -> u64 { - unsafe { intrinsics::bswap64(*self) } - } -} - -#[cfg(target_word_size = "32")] -impl ByteOrder for uint { - #[inline] - fn swap_bytes(&self) -> uint { - (*self as u32).swap_bytes() as uint - } -} - -#[cfg(target_word_size = "64")] -impl ByteOrder for uint { - #[inline] - fn swap_bytes(&self) -> uint { - (*self as u64).swap_bytes() as uint - } -} - /// Convert an u16 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. @@ -366,42 +216,42 @@ pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le16(x: u16) -> u16 { ByteOrder::from_little_endian(x) } +pub fn from_le16(x: u16) -> u16 { Int::from_little_endian(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le32(x: u32) -> u32 { ByteOrder::from_little_endian(x) } +pub fn from_le32(x: u32) -> u32 { Int::from_little_endian(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le64(x: u64) -> u64 { ByteOrder::from_little_endian(x) } +pub fn from_le64(x: u64) -> u64 { Int::from_little_endian(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be16(x: u16) -> u16 { ByteOrder::from_big_endian(x) } +pub fn from_be16(x: u16) -> u16 { Int::from_big_endian(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) } +pub fn from_be32(x: u32) -> u32 { Int::from_big_endian(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) } +pub fn from_be64(x: u64) -> u64 { Int::from_big_endian(x) } /// Swap the values at two mutable locations of the same type, without /// deinitialising or copying either one. @@ -642,60 +492,6 @@ mod tests { assert!(Vec::from_slice([76u8]) == transmute("L".to_string())); } } - - macro_rules! test_byte_order { - ($T:ident) => { - mod $T { - use mem::ByteOrder; - - static A: $T = 0b0101100; - static B: $T = 0b0100001; - static C: $T = 0b1111001; - - static _0: $T = 0; - static _1: $T = !0; - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_little_endian() { - assert_eq!(ByteOrder::from_little_endian(A.to_little_endian()), A); - assert_eq!(ByteOrder::from_little_endian(B.to_little_endian()), B); - assert_eq!(ByteOrder::from_little_endian(C.to_little_endian()), C); - assert_eq!(ByteOrder::from_little_endian(_0), _0); - assert_eq!(ByteOrder::from_little_endian(_1), _1); - assert_eq!(_0.to_little_endian(), _0); - assert_eq!(_1.to_little_endian(), _1); - } - - #[test] - fn test_big_endian() { - assert_eq!(ByteOrder::from_big_endian(A.to_big_endian()), A); - assert_eq!(ByteOrder::from_big_endian(B.to_big_endian()), B); - assert_eq!(ByteOrder::from_big_endian(C.to_big_endian()), C); - assert_eq!(ByteOrder::from_big_endian(_0), _0); - assert_eq!(ByteOrder::from_big_endian(_1), _1); - assert_eq!(_0.to_big_endian(), _0); - assert_eq!(_1.to_big_endian(), _1); - } - } - } - } - - test_byte_order!(u8) - test_byte_order!(u16) - test_byte_order!(u32) - test_byte_order!(u64) - test_byte_order!(uint) } // FIXME #13642 (these benchmarks should be in another place) diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 8a1bd66aa1a..84744b3f5d7 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -35,7 +35,6 @@ mod tests { use int; use num; - use num::Bitwise; use num::CheckedDiv; #[test] @@ -90,7 +89,7 @@ mod tests { } #[test] - fn test_bitwise() { + fn test_bitwise_operators() { assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); @@ -99,34 +98,74 @@ mod tests { assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not()); } + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + #[test] fn test_count_ones() { - assert!((0b0101100 as $T).count_ones() == 3); - assert!((0b0100001 as $T).count_ones() == 2); - assert!((0b1111001 as $T).count_ones() == 5); + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); } #[test] fn test_count_zeros() { - assert!((0b0101100 as $T).count_zeros() == BITS as $T - 3); - assert!((0b0100001 as $T).count_zeros() == BITS as $T - 2); - assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); } #[test] fn test_rotate() { - let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); - let n: $T = 0b0100001; assert_eq!(n.rotate_left(3).rotate_left(2).rotate_right(5), n); - let n: $T = 0b1111001; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behaviour. See #10183. - let n: $T = 0; assert_eq!(n.rotate_left(124), n); - let n: $T = -1; assert_eq!(n.rotate_left(124), n); - let n: $T = 0; assert_eq!(n.rotate_right(124), n); - let n: $T = -1; assert_eq!(n.rotate_right(124), n); + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(Int::from_little_endian(A.to_little_endian()), A); + assert_eq!(Int::from_little_endian(B.to_little_endian()), B); + assert_eq!(Int::from_little_endian(C.to_little_endian()), C); + assert_eq!(Int::from_little_endian(_0), _0); + assert_eq!(Int::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(Int::from_big_endian(A.to_big_endian()), A); + assert_eq!(Int::from_big_endian(B.to_big_endian()), B); + assert_eq!(Int::from_big_endian(C.to_big_endian()), C); + assert_eq!(Int::from_big_endian(_0), _0); + assert_eq!(Int::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); } #[test] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 696abc05ed2..ed0c24e7fa0 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -376,193 +376,292 @@ bounded_impl!(i64, i64::MIN, i64::MAX) bounded_impl!(f32, f32::MIN_VALUE, f32::MAX_VALUE) bounded_impl!(f64, f64::MIN_VALUE, f64::MAX_VALUE) -/// Numbers with a fixed binary representation. -pub trait Bitwise: Bounded - + Not<Self> - + BitAnd<Self,Self> - + BitOr<Self,Self> - + BitXor<Self,Self> - + Shl<Self,Self> - + Shr<Self,Self> { - /// Returns the number of ones in the binary representation of the number. +/// Specifies the available operations common to all of Rust's core numeric primitives. +/// These may not always make sense from a purely mathematical point of view, but +/// may be useful for systems programming. +pub trait Primitive: Copy + + Clone + + Num + + NumCast + + PartialOrd + + Bounded {} + +trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) + +/// A collection of traits relevant to primitive signed and unsigned integers +pub trait Int: Primitive + + CheckedAdd + + CheckedSub + + CheckedMul + + CheckedDiv + + Bounded + + Not<Self> + + BitAnd<Self,Self> + + BitOr<Self,Self> + + BitXor<Self,Self> + + Shl<Self,Self> + + Shr<Self,Self> { + /// Returns the number of ones in the binary representation of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b01001100u8; + /// /// assert_eq!(n.count_ones(), 3); /// ``` - fn count_ones(&self) -> Self; + fn count_ones(self) -> Self; - /// Returns the number of zeros in the binary representation of the number. + /// Returns the number of zeros in the binary representation of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b01001100u8; + /// /// assert_eq!(n.count_zeros(), 5); /// ``` #[inline] - fn count_zeros(&self) -> Self { - (!*self).count_ones() + fn count_zeros(self) -> Self { + (!self).count_ones() } /// Returns the number of leading zeros in the in the binary representation - /// of the number. + /// of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b0101000u16; + /// /// assert_eq!(n.leading_zeros(), 10); /// ``` - fn leading_zeros(&self) -> Self; + fn leading_zeros(self) -> Self; /// Returns the number of trailing zeros in the in the binary representation - /// of the number. + /// of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b0101000u16; + /// /// assert_eq!(n.trailing_zeros(), 3); /// ``` - fn trailing_zeros(&self) -> Self; + fn trailing_zeros(self) -> Self; - /// Shifts the bits to the left by a specified amount amount, `r`, wrapping - /// the truncated bits to the end of the resulting value. + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0x3456789ABCDEF012u64; + /// /// assert_eq!(n.rotate_left(12), m); /// ``` - fn rotate_left(&self, r: uint) -> Self; + fn rotate_left(self, n: uint) -> Self; - /// Shifts the bits to the right by a specified amount amount, `r`, wrapping - /// the truncated bits to the beginning of the resulting value. + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0xDEF0123456789ABCu64; + /// /// assert_eq!(n.rotate_right(12), m); /// ``` - fn rotate_right(&self, r: uint) -> Self; + fn rotate_right(self, n: uint) -> Self; + + /// Reverses the byte order of the integer. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + fn swap_bytes(self) -> Self; + + /// Convert a integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_big_endian(n), n) + /// } else { + /// assert_eq!(Int::from_big_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_big_endian(x: Self) -> Self { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert a integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_little_endian(n), n) + /// } else { + /// assert_eq!(Int::from_little_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_little_endian(x: Self) -> Self { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert the integer to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_big_endian(), n) + /// } else { + /// assert_eq!(n.to_big_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_big_endian(self) -> Self { + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert the integer to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_little_endian(), n) + /// } else { + /// assert_eq!(n.to_little_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_little_endian(self) -> Self { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } } -macro_rules! bitwise_impl { - ($t:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { - impl Bitwise for $t { +macro_rules! int_impl { + ($T:ty, $BITS:expr, $ctpop:path, $ctlz:path, $cttz:path, $bswap:path) => { + impl Int for $T { #[inline] - fn count_ones(&self) -> $t { unsafe { $co(*self) } } + fn count_ones(self) -> $T { unsafe { $ctpop(self) } } #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self) } } + fn leading_zeros(self) -> $T { unsafe { $ctlz(self) } } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*self) } } + fn trailing_zeros(self) -> $T { unsafe { $cttz(self) } } #[inline] - fn rotate_left(&self, r: uint) -> $t { - // Protect against undefined behaviour for overlong bit shifts - let r = r % $bits; - (*self << r) | (*self >> ($bits - r)) + fn rotate_left(self, n: uint) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> ($BITS - n)) } #[inline] - fn rotate_right(&self, r: uint) -> $t { - // Protect against undefined behaviour for overlong bit shifts - let r = r % $bits; - (*self >> r) | (*self << ($bits - r)) + fn rotate_right(self, n: uint) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << ($BITS - n)) } + + #[inline] + fn swap_bytes(self) -> $T { unsafe { $bswap(self) } } } } } -macro_rules! bitwise_cast_impl { - ($t:ty, $t_cast:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { - impl Bitwise for $t { +/// Swapping a single byte is a no-op. This is marked as `unsafe` for +/// consistency with the other `bswap` intrinsics. +unsafe fn bswap8(x: u8) -> u8 { x } + +int_impl!(u8, 8, + intrinsics::ctpop8, + intrinsics::ctlz8, + intrinsics::cttz8, + bswap8) + +int_impl!(u16, 16, + intrinsics::ctpop16, + intrinsics::ctlz16, + intrinsics::cttz16, + intrinsics::bswap16) + +int_impl!(u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32) + +int_impl!(u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64) + +macro_rules! int_cast_impl { + ($T:ty, $U:ty) => { + impl Int for $T { #[inline] - fn count_ones(&self) -> $t { unsafe { $co(*self as $t_cast) as $t } } + fn count_ones(self) -> $T { (self as $U).count_ones() as $T } #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self as $t_cast) as $t } } + fn leading_zeros(self) -> $T { (self as $U).leading_zeros() as $T } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*self as $t_cast) as $t } } + fn trailing_zeros(self) -> $T { (self as $U).trailing_zeros() as $T } #[inline] - fn rotate_left(&self, r: uint) -> $t { - // cast to prevent the sign bit from being corrupted - (*self as $t_cast).rotate_left(r) as $t - } + fn rotate_left(self, n: uint) -> $T { (self as $U).rotate_left(n) as $T } #[inline] - fn rotate_right(&self, r: uint) -> $t { - // cast to prevent the sign bit from being corrupted - (*self as $t_cast).rotate_right(r) as $t - } + fn rotate_right(self, n: uint) -> $T { (self as $U).rotate_right(n) as $T } + + #[inline] + fn swap_bytes(self) -> $T { (self as $U).swap_bytes() as $T } } } } -#[cfg(target_word_size = "32")] -bitwise_cast_impl!(uint, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -#[cfg(target_word_size = "64")] -bitwise_cast_impl!(uint, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -bitwise_impl!(u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) -bitwise_impl!(u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) -bitwise_impl!(u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -bitwise_impl!(u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -#[cfg(target_word_size = "32")] -bitwise_cast_impl!(int, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -#[cfg(target_word_size = "64")] -bitwise_cast_impl!(int, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -bitwise_cast_impl!(i8, u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) -bitwise_cast_impl!(i16, u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) -bitwise_cast_impl!(i32, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -bitwise_cast_impl!(i64, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -/// Specifies the available operations common to all of Rust's core numeric primitives. -/// These may not always make sense from a purely mathematical point of view, but -/// may be useful for systems programming. -pub trait Primitive: Copy - + Clone - + Num - + NumCast - + PartialOrd - + Bounded {} - -trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) - -/// A collection of traits relevant to primitive signed and unsigned integers -pub trait Int: Primitive - + Bitwise - + CheckedAdd - + CheckedSub - + CheckedMul - + CheckedDiv {} +int_cast_impl!(i8, u8) +int_cast_impl!(i16, u16) +int_cast_impl!(i32, u32) +int_cast_impl!(i64, u64) -trait_impl!(Int for uint u8 u16 u32 u64 int i8 i16 i32 i64) +#[cfg(target_word_size = "32")] int_cast_impl!(uint, u32) +#[cfg(target_word_size = "64")] int_cast_impl!(uint, u64) +#[cfg(target_word_size = "32")] int_cast_impl!(int, u32) +#[cfg(target_word_size = "64")] int_cast_impl!(int, u64) /// Returns the smallest power of 2 greater than or equal to `n`. #[inline] diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 8548b141053..1fe3c4cf1f1 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -26,7 +26,6 @@ mod tests { use num; use num::CheckedDiv; - use num::Bitwise; #[test] fn test_overflows() { @@ -41,7 +40,7 @@ mod tests { } #[test] - fn test_bitwise() { + fn test_bitwise_operators() { assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); @@ -50,34 +49,74 @@ mod tests { assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); } + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + #[test] fn test_count_ones() { - assert!((0b0101100 as $T).count_ones() == 3); - assert!((0b0100001 as $T).count_ones() == 2); - assert!((0b1111001 as $T).count_ones() == 5); + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); } #[test] fn test_count_zeros() { - assert!((0b0101100 as $T).count_zeros() == BITS as $T - 3); - assert!((0b0100001 as $T).count_zeros() == BITS as $T - 2); - assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); } #[test] fn test_rotate() { - let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); - let n: $T = 0b0100001; assert_eq!(n.rotate_left(3).rotate_left(2).rotate_right(5), n); - let n: $T = 0b1111001; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behaviour. See #10183. - let n: $T = 0; assert_eq!(n.rotate_left(124), n); - let n: $T = MAX; assert_eq!(n.rotate_left(124), n); - let n: $T = 0; assert_eq!(n.rotate_right(124), n); - let n: $T = MAX; assert_eq!(n.rotate_right(124), n); + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(Int::from_little_endian(A.to_little_endian()), A); + assert_eq!(Int::from_little_endian(B.to_little_endian()), B); + assert_eq!(Int::from_little_endian(C.to_little_endian()), C); + assert_eq!(Int::from_little_endian(_0), _0); + assert_eq!(Int::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(Int::from_big_endian(A.to_big_endian()), A); + assert_eq!(Int::from_big_endian(B.to_big_endian()), B); + assert_eq!(Int::from_big_endian(C.to_big_endian()), C); + assert_eq!(Int::from_big_endian(_0), _0); + assert_eq!(Int::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); } #[test] |
