toolbox_rs/
bit_weight_iterator.rs1use crate::{enumerative_source_coding::decode_u64, math::choose};
2
3pub struct U64BitWeightIterator {
5 weight: u64,
6 ordinal: u64,
7 max: u64,
8}
9
10impl U64BitWeightIterator {
11 pub fn with_weight(weight: u64) -> Self {
12 U64BitWeightIterator {
13 weight,
14 ordinal: 0,
15 max: choose(64u64, weight),
16 }
17 }
18}
19
20impl Iterator for U64BitWeightIterator {
21 type Item = u64;
22
23 fn next(&mut self) -> Option<Self::Item> {
24 if self.ordinal < self.max {
25 self.ordinal += 1;
26 return Some(decode_u64(self.weight, self.ordinal - 1));
27 }
28 None
29 }
30}
31
32#[cfg(test)]
33mod tests {
34 use super::U64BitWeightIterator;
35
36 #[test]
37 fn trivial_iterator_of_weight_one() {
38 let result: Vec<u64> = U64BitWeightIterator::with_weight(1).collect();
39 assert_eq!(result.len(), 64);
40 let expected: [u64; 64] = core::array::from_fn(|i| 1 << i);
41 assert_eq!(result, expected);
42 }
43
44 #[test]
45 fn trivial_iterator_of_weight_63() {
46 let result: Vec<u64> = U64BitWeightIterator::with_weight(63).collect();
47 assert_eq!(result.len(), 64);
48 let expected: [u64; 64] =
49 core::array::from_fn(|i| 0xFFFF_FFFF_FFFF_FFFF ^ (1u64 << (63 - i)));
50 assert_eq!(result, expected);
51 }
52}