-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitwise.rs
45 lines (38 loc) · 1.8 KB
/
bitwise.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use super::core;
/// Computes bit reversal by going bit by bit and setting the reverse position bit for the output.
pub trait BitwiseReverse {
/// Swaps the bits such that bit i is now bit N-i, where N is the length of the T in bits.
fn swap_bits(self) -> Self;
}
macro_rules! doit_bitwise { ($($ty:ty),*) => ($(
impl BitwiseReverse for $ty {
// This algorithm uses the reverse variable as a like a stack to reverse the value.
// The lesser significant bits are pushed onto the reverse variable and then the variable
// is shifted down to make room for more significant bits. This algorithm has a shortcut,
// that if there aren't anymore 1s to push onto the reverse variable the algorithm ends
// early and shift the reverse to the correct position.
#[inline]
fn swap_bits(self) -> $ty {
let mut v = self;
// By initializing the reversal to value, we have already loaded the largest
// significant bit into the correct location.
let mut r = self;
// Compute how many bits are left to shift at the end of the algorithm.
let mut s = 8 * core::mem::size_of::<$ty>() - 1;
v >>= 1;
while v != 0 { // Quit early if there are no more 1s to shift in
r <<= 1; // Make room for the next significant bit
r |= v & 1; // Add the bit to the reverse variable
v >>= 1; // Go to the next significant bit
s -= 1; // Decrement the leftover bit count
}
// Shift the reversal to the correct position and return the reversal
r << s
}
})*)
}
doit_bitwise!(u8, u16, u32, u64, usize);
#[cfg(feature = "u128")]
doit_bitwise!(u128);
doit_signed!(BitwiseReverse);
test_suite!();