From ceb44f8d26edcc53f33eeb86be92aafb584b4307 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Sat, 29 Mar 2014 19:23:01 +0100 Subject: [PATCH] num: bitwise reflection methods Let Bitwise provide a reflect() method for reversed binary representation. This is a binary primitive used in several algorithms, eg. CRC checksums. Signed-off-by: Luca Bruno --- src/libstd/num/i16.rs | 10 ++++++++++ src/libstd/num/i32.rs | 10 ++++++++++ src/libstd/num/i64.rs | 10 ++++++++++ src/libstd/num/i8.rs | 10 ++++++++++ src/libstd/num/int.rs | 8 ++++++++ src/libstd/num/int_macros.rs | 7 +++++++ src/libstd/num/mod.rs | 12 ++++++++++++ src/libstd/num/uint_macros.rs | 12 ++++++++++++ 8 files changed, 79 insertions(+) diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index 42710a8b459d0..bc7febd961595 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -39,6 +39,16 @@ impl Bitwise for i16 { /// of the number. #[inline] fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } } + + /// Returns the bitwise reflected representation of the number. + fn reflect(&self) -> i16 { + let mut r = 0; + for i in range(0, 16) { + let digit = (*self >> i) & 1; + r = r | (digit << (15-i)); + } + return r; + } } impl CheckedAdd for i16 { diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 69d4b0639f732..49b6419d3dbce 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -39,6 +39,16 @@ impl Bitwise for i32 { /// of the number. #[inline] fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } } + + /// Returns the bitwise reflected representation of the number. + fn reflect(&self) -> i32 { + let mut r = 0; + for i in range(0, 32) { + let digit = (*self >> i) & 1; + r = r | (digit << (31-i)); + } + return r; + } } impl CheckedAdd for i32 { diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index 1f7066c25db3b..352d23ca2758e 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -40,6 +40,16 @@ impl Bitwise for i64 { /// Counts the number of trailing zeros. #[inline] fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } } + + /// Returns the bitwise reflected representation of the number. + fn reflect(&self) -> i64 { + let mut r = 0; + for i in range(0, 64) { + let digit = (*self >> i) & 1; + r = r | (digit << (63-i)); + } + return r; + } } impl CheckedAdd for i64 { diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 061ffddf2312e..7d00e213e791a 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -39,6 +39,16 @@ impl Bitwise for i8 { /// of the number. #[inline] fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } } + + /// Returns the bitwise reflected representation of the number. + fn reflect(&self) -> i8 { + let mut r = 0; + for i in range(0, 8) { + let digit = (*self >> i) & 1; + r = r | (digit << (7-i)); + } + return r; + } } impl CheckedAdd for i8 { diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 66b204ee8bdc7..da34e5c9f3ec2 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -41,6 +41,10 @@ impl Bitwise for int { /// of the number. #[inline] fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int } + + /// Returns the bitwise reflected representation of the number. + #[inline] + fn reflect(&self) -> int { (*self as i32).reflect() as int } } #[cfg(target_word_size = "64")] @@ -58,6 +62,10 @@ impl Bitwise for int { /// of the number. #[inline] fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int } + + /// Returns the bitwise reflected representation of the number. + #[inline] + fn reflect(&self) -> int { (*self as i64).reflect() as int } } #[cfg(target_word_size = "32")] diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 1d2c38f22bb17..5079f241ad854 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -374,6 +374,13 @@ mod tests { assert_eq!((0b1111001 as $T).count_zeros(), BITS as $T - 5); } + #[test] + fn test_bitwise_reflect() { + assert_eq!((0b01011001 as $T).reflect(), (0b10011010 as $T) << (BITS - 8)); + assert_eq!((0b01000011 as $T).reflect(), (0b11000010 as $T) << (BITS - 8)); + assert_eq!((0b11110011 as $T).reflect(), (0b11001111 as $T) << (BITS - 8)); + } + #[test] fn test_from_str() { assert_eq!(from_str::<$T>("0"), Some(0 as $T)); diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index feff0e7e6c0e5..fa11555157d18 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -271,6 +271,18 @@ pub trait Bitwise: Bounded /// assert_eq!(n.trailing_zeros(), 3); /// ``` fn trailing_zeros(&self) -> Self; + + /// Returns the bitwise reflected representation of the number. + /// + /// # Example + /// + /// ```rust + /// use std::num::Bitwise; + /// + /// let n = 0b11010001u8; + /// assert_eq!(n.reflect(), 0b10001011u8); + /// ``` + fn reflect(&self) -> Self; } /// Specifies the available operations common to all of Rust's core numeric primitives. diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index ece30e72e0682..be0fa3d8dd2a0 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -223,6 +223,11 @@ impl Bitwise for $T { fn trailing_zeros(&self) -> $T { (*self as $T_SIGNED).trailing_zeros() as $T } + + /// Returns the bitwise reflected representation of the number. + fn reflect(&self) -> $T { + (*self as $T_SIGNED).reflect() as $T + } } #[cfg(test)] @@ -272,6 +277,13 @@ mod tests { assert_eq!((0b1111001 as $T).count_zeros(), BITS as $T - 5); } + #[test] + fn test_bitwise_reflect() { + assert_eq!((0b01011001 as $T).reflect(), (0b10011010 as $T) << (BITS - 8)); + assert_eq!((0b01000011 as $T).reflect(), (0b11000010 as $T) << (BITS - 8)); + assert_eq!((0b11110011 as $T).reflect(), (0b11001111 as $T) << (BITS - 8)); + } + #[test] pub fn test_to_str() { assert_eq!((0 as $T).to_str_radix(10u), ~"0");