utils/bit.rs
1//! Bit manipulation helpers.
2
3use crate::number::UnsignedInteger;
4
5/// Iterator which yields all the set or unset bits in a provided number.
6pub struct BitIterator<T: UnsignedInteger> {
7 n: T,
8}
9
10impl<T: UnsignedInteger> BitIterator<T> {
11 /// Returns an iterator that yields the positions and values of all the set bits in the provided
12 /// number.
13 ///
14 /// # Examples
15 /// ```
16 /// # use utils::bit::BitIterator;
17 /// assert_eq!(
18 /// BitIterator::ones(0b1001_1101u8).collect::<Vec<(u32, u8)>>(),
19 /// vec![
20 /// (0, 1),
21 /// (2, 4),
22 /// (3, 8),
23 /// (4, 16),
24 /// (7, 128),
25 /// ],
26 /// );
27 /// ```
28 pub fn ones(n: T) -> Self {
29 BitIterator { n }
30 }
31
32 /// Returns an iterator that yields the positions and values of all the unset bits in the
33 /// provided number.
34 ///
35 /// # Examples
36 /// ```
37 /// # use utils::bit::BitIterator;
38 /// assert_eq!(
39 /// BitIterator::zeroes(0b1001_1101u8).collect::<Vec<(u32, u8)>>(),
40 /// vec![
41 /// (1, 2),
42 /// (5, 32),
43 /// (6, 64),
44 /// ],
45 /// );
46 /// ```
47 pub fn zeroes(n: T) -> Self {
48 BitIterator { n: !n }
49 }
50}
51
52impl<T: UnsignedInteger> Iterator for BitIterator<T> {
53 type Item = (u32, T);
54
55 #[inline]
56 fn next(&mut self) -> Option<Self::Item> {
57 if self.n == T::ZERO {
58 None
59 } else {
60 let position = self.n.trailing_zeros();
61 let value = T::ONE << position;
62 self.n &= !value;
63 Some((position, value))
64 }
65 }
66}
67
68/// Computes the population count for each bit position across 8 input masks.
69///
70/// Returns four masks `[bit0, bit1, bit2, bit3]` that encode, per bit position, the 4-bit count
71/// of how many of the 8 inputs have that bit set.
72///
73/// For example, if a given bit is set in 5 inputs, then that bit would be set in `bit0` and `bit2`.
74/// If a given bit is set in all 8 inputs, then that bit would only be set in `bit3`.
75///
76/// # Examples
77/// ```
78/// # use utils::bit::bitwise_count8;
79/// let [bit0, bit1, bit2, bit3] = bitwise_count8::<u16>(&[
80/// 0b100000000,
81/// 0b110000000,
82/// 0b111000000,
83/// 0b111100000,
84/// 0b111110000,
85/// 0b111111000,
86/// 0b111111100,
87/// 0b111111110,
88/// ]);
89/// assert_eq!(bit0, 0b010101010);
90/// assert_eq!(bit1, 0b011001100);
91/// assert_eq!(bit2, 0b011110000);
92/// assert_eq!(bit3, 0b100000000);
93/// ```
94///
95/// ```
96/// # use utils::bit::bitwise_count8;
97/// let [bit0, bit1, bit2, bit3] = bitwise_count8::<u64>(&[
98/// 0b00111000_01001000_10000111_11111111_10111000_11100010_00110010_01010011,
99/// 0b01110000_00100111_01011101_11011000_10001100_00011000_10100101_00110010,
100/// 0b00000101_11010011_10110011_10000000_00000000_11110110_00000101_11111010,
101/// 0b01101001_01001100_00111001_01101100_00110111_00101011_00010101_10011101,
102/// 0b00011100_11101111_00111111_01101011_00011101_01011110_11101101_10101101,
103/// 0b10111100_11101111_00001001_10100100_01010110_10101011_01011000_11111100,
104/// 0b11110110_00010001_11101111_00101101_01110111_10000011_11110110_10101011,
105/// 0b01110001_01100010_01111101_01001000_01011001_10110100_11100110_11100000,
106/// ]);
107/// assert_eq!(bit0, 0b00000011_10000011_11110100_01100001_01100110_11100101_00100010_00011100);
108/// assert_eq!(bit1, 0b10110001_11010000_11001000_00011011_11110010_01000111_00001110_10100100);
109/// assert_eq!(bit2, 0b01111100_01101111_00111110_11101100_00011101_10111010_11110101_11111011);
110/// assert_eq!(bit3, 0b00000000_00000000_00000001_00000000_00000000_00000000_00000000_00000000);
111/// ```
112#[inline]
113#[must_use]
114pub fn bitwise_count8<T: UnsignedInteger>(m: &[T; 8]) -> [T; 4] {
115 let (s1, c1) = carry_save_adder(m[0], m[1], m[2]);
116 let (s2, c2) = carry_save_adder(m[3], m[4], m[5]);
117 let (s3, c3) = carry_save_adder(m[6], m[7], T::ZERO);
118 let (s4, c4) = carry_save_adder(c1, c2, c3);
119 let (bit0, c5) = carry_save_adder(s1, s2, s3);
120 let (bit1, c6) = carry_save_adder(s4, c5, T::ZERO);
121 let (bit2, bit3) = carry_save_adder(c4, c6, T::ZERO);
122 [bit0, bit1, bit2, bit3]
123}
124
125#[inline]
126#[must_use]
127fn carry_save_adder<T: UnsignedInteger>(a: T, b: T, c: T) -> (T, T) {
128 let sum_ab = a ^ b;
129 let carry_ab = a & b;
130 let sum_abc = sum_ab ^ c;
131 let carry_abc = carry_ab | (sum_ab & c);
132 (sum_abc, carry_abc)
133}