arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/merkle/mmr/bit.rs
src/merkle/mmr/bit.rsRaw
 1/// Iterate over the bits of a `usize` and yields the bit positions for the true bits.
 2pub struct TrueBitPositionIterator {
 3    value: usize,
 4}
 5
 6impl TrueBitPositionIterator {
 7    pub fn new(value: usize) -> TrueBitPositionIterator {
 8        TrueBitPositionIterator { value }
 9    }
10}
11
12impl Iterator for TrueBitPositionIterator {
13    type Item = u32;
14
15    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
16        // trailing_zeros is computed with the intrinsic cttz. [Rust 1.67.0] x86 uses the `bsf`
17        // instruction. AArch64 uses the `rbit clz` instructions.
18        let zeros = self.value.trailing_zeros();
19
20        if zeros == usize::BITS {
21            None
22        } else {
23            let bit_position = zeros;
24            let mask = 1 << bit_position;
25            self.value ^= mask;
26            Some(bit_position)
27        }
28    }
29}
30
31impl DoubleEndedIterator for TrueBitPositionIterator {
32    fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
33        // trailing_zeros is computed with the intrinsic ctlz. [Rust 1.67.0] x86 uses the `bsr`
34        // instruction. AArch64 uses the `clz` instruction.
35        let zeros = self.value.leading_zeros();
36
37        if zeros == usize::BITS {
38            None
39        } else {
40            let bit_position = usize::BITS - zeros - 1;
41            let mask = 1 << bit_position;
42            self.value ^= mask;
43            Some(bit_position)
44        }
45    }
46}