fixedbitset_utils/
lib.rs

1//! A bunch of utility stuffs that I use when working with bitsets in Rust
2
3use std::{iter::Cloned, slice::Iter, cmp::Ordering};
4
5use fixedbitset::FixedBitSet;
6
7type BitSet = FixedBitSet;
8
9/// This structure defines an iterator capable of iterating over the 1-bits of
10/// a fixed bitset. It uses word representation of the items in the set, so it
11/// should be more efficient to use than a crude iteration over the elements of
12/// the set.
13///
14/// # Example
15/// ```
16/// # use fixedbitset::FixedBitSet;
17/// # use bitset_fixed_utils::BitSetIter;
18///
19/// let mut bit_set = FixedBitSet::with_capacity(5);
20/// bit_set.set(1, true);
21/// bit_set.set(2, true);
22/// bit_set.set(4, true);
23///
24/// // Successively prints 1, 2, 4
25/// for x in BitSetIter::new(&bit_set) {
26///     println!("{}", x);
27/// }
28/// ```
29///
30pub struct BitSetIter<'a> {
31    /// An iterator over the buffer of words of the bitset
32    iter: Cloned<Iter<'a, u32>>,
33    /// The current word (or none if we exhausted all iterations)
34    word: Option<u32>,
35    /// The value of position 0 in the current word
36    base: usize,
37    /// An offset in the current word
38    offset: usize,
39}
40impl BitSetIter<'_> {
41    /// This method creates an iterator for the given bitset from an immutable
42    /// reference to that bitset.
43    pub fn new(bs: &BitSet) -> BitSetIter {
44        let mut iter = bs.as_slice().iter().cloned();
45        let word = iter.next();
46        BitSetIter {iter, word, base: 0, offset: 0}
47    }
48}
49/// `BitSetIter` is an iterator over the one bits of the bitset. As such, it
50/// implements the standard `Iterator` trait.
51impl Iterator for BitSetIter<'_> {
52    type Item = usize;
53
54    /// Returns the nex element from the iteration, or None, if there are no more
55    /// elements to iterate upon.
56    fn next(&mut self) -> Option<Self::Item> {
57        while let Some(w) = self.word {
58            if w == 0 || self.offset >= 32 {
59                self.word   = self.iter.next();
60                self.base  += 32;
61                self.offset = 0;
62            } else {
63                let mut mask = 1_u32 << self.offset as u32;
64                while (w & mask) == 0 && self.offset < 32 {
65                    mask <<= 1;
66                    self.offset += 1;
67                }
68                if self.offset < 32 {
69                    let ret = Some(self.base + self.offset);
70                    self.offset += 1;
71                    return ret;
72                }
73            }
74        }
75        None
76    }
77}
78
79/// A totally ordered Bitset wrapper. Useful to implement tie break mechanisms.
80/// This wrapper orders the bitsets according to the lexical order of their
81/// underlying bits.
82///
83/// # Note:
84/// This implementation uses the underlying _words_ representation of the
85/// bitsets to perform several comparisons at once. Hence, using a `LexBitSet`
86/// should be more efficient than trying to establish the total ordering
87/// yourself with a loop on the 1-bits of the two sets.
88///
89/// # Example
90/// ```
91/// # use fixedbitset::FixedBitSet;
92/// # use bitset_fixed_utils::LexBitSet;
93///
94/// let mut a = FixedBitSet::with_capacity(5);
95/// let mut b = FixedBitSet::with_capacity(5);
96///
97/// a.set(2, true);  // bits 0..2 match for a and b
98/// b.set(2, true);
99///
100/// a.set(3, false); // a and b diverge on bit 3
101/// b.set(3, true);  // and a has a 0 bit in that pos
102///
103/// a.set(4, true);  // anything that remains after
104/// b.set(4, false); // the firs lexicographical difference is ignored
105///
106/// assert!(LexBitSet(&a) < LexBitSet(&b));
107/// ```
108///
109#[derive(Debug)]
110pub struct LexBitSet<'a>(pub &'a BitSet);
111
112/// The `LexBitSet` implements a total order on bitsets. As such, it must
113/// implement the standard trait `Ord`.
114///
115/// # Note:
116/// This implementation uses the underlying _words_ representation of the
117/// bitsets to perform several comparisons at once. Hence, using a `LexBitSet`
118/// should be more efficient than trying to establish the total ordering
119/// yourself with a loop on the 1-bits of the two sets.
120impl Ord for LexBitSet<'_> {
121    fn cmp(&self, other: &Self) -> Ordering {
122        let mut x = self.0.as_slice().iter().cloned();
123        let mut y = other.0.as_slice().iter().cloned();
124        let end   = x.len().max(y.len());
125
126        for _ in 0..end {
127            let xi = x.next().unwrap_or(0);
128            let yi = y.next().unwrap_or(0);
129            if xi != yi {
130                let mut mask = 1_u32;
131                for _ in 0..32 {
132                    let bit_x = xi & mask;
133                    let bit_y = yi & mask;
134                    if bit_x != bit_y {
135                        return bit_x.cmp(&bit_y);
136                    }
137                    mask <<= 1;
138                }
139            }
140        }
141        Ordering::Equal
142    }
143}
144
145/// Because it is a total order, `LexBitSet` must also be a partial order.
146/// Hence, it must implement the standard trait `PartialOrd`.
147impl PartialOrd for LexBitSet<'_> {
148    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
149        Some(self.cmp(other))
150    }
151}
152
153/// Because `LexBitSet` defines a total order, it makes sense to consider that
154/// it also defines an equivalence relation. As such, it implements the standard
155/// `Eq` and `PartialEq` traits.
156impl Eq for LexBitSet<'_> {}
157
158/// Having `LexBitSet` to implement `PartialEq` means that it _at least_ defines
159/// a partial equivalence relation.
160impl PartialEq for LexBitSet<'_> {
161    fn eq(&self, other: &Self) -> bool {
162        self.0 == other.0 || self.cmp(other) == Ordering::Equal
163    }
164}
165
166
167#[cfg(test)]
168/// These tests validate the behavior of the bitset iterator `BitSetIter`.
169mod tests_bitset_iter {
170    use crate::{BitSetIter, BitSet};
171
172    #[test]
173    fn bsiter_collect() {
174        let mut bit_set = BitSet::with_capacity(5);
175        bit_set.set(1, true);
176        bit_set.set(2, true);
177        bit_set.set(4, true);
178
179        let iter  = BitSetIter::new(&bit_set);
180        let items = iter.collect::<Vec<usize>>();
181
182        assert_eq!(items, vec![1, 2, 4]);
183    }
184    #[test]
185    fn bsiter_next_normal_case() {
186        let mut bit_set = BitSet::with_capacity(5);
187        bit_set.set(1, true);
188        bit_set.set(2, true);
189        bit_set.set(4, true);
190
191        let mut iter = BitSetIter::new(&bit_set);
192        assert_eq!(Some(1), iter.next());
193        assert_eq!(Some(2), iter.next());
194        assert_eq!(Some(4), iter.next());
195        assert_eq!(None   , iter.next());
196    }
197    #[test]
198    fn bsiter_no_items() {
199        let bit_set = BitSet::with_capacity(5);
200        let mut iter    = BitSetIter::new(&bit_set);
201
202        assert_eq!(None, iter.next());
203        assert_eq!(None, iter.next());
204        assert_eq!(None, iter.next());
205    }
206    #[test]
207    fn bsiter_mutiple_words() {
208        let mut bit_set = BitSet::with_capacity(128);
209        bit_set.set(  1, true);
210        bit_set.set( 50, true);
211        bit_set.set( 66, true);
212        bit_set.set(100, true);
213
214        let mut iter = BitSetIter::new(&bit_set);
215        assert_eq!(Some(  1), iter.next());
216        assert_eq!(Some( 50), iter.next());
217        assert_eq!(Some( 66), iter.next());
218        assert_eq!(Some(100), iter.next());
219        assert_eq!(None     , iter.next());
220    }
221}
222#[cfg(test)]
223/// These tests validate the behavior of the lexicographically ordered bitsets
224/// `LexBitSet`.
225mod tests_lexbitset {
226    use crate::{LexBitSet, BitSet};
227
228    #[test]
229    fn same_size_less_than() {
230        let mut a = BitSet::with_capacity(200);
231        let mut b = BitSet::with_capacity(200);
232
233        a.set(2, true);  // bits 0..2 match for a and b
234        b.set(2, true);
235
236        a.set(3, false); // a and b diverge on bit 3
237        b.set(3, true);  // and a has a 0 bit in that pos
238
239        a.set(4, true);  // anything that remains after
240        b.set(4, false); // the firs lexicographical difference is ignored
241
242        a.set(150, true);
243        b.set(150, true);
244
245        assert!(LexBitSet(&a) <= LexBitSet(&b));
246        assert!(LexBitSet(&a) <  LexBitSet(&b));
247    }
248    #[test]
249    fn same_size_greater_than() {
250        let mut a = BitSet::with_capacity(200);
251        let mut b = BitSet::with_capacity(200);
252
253        a.set(2, true);  // bits 0..2 match for a and b
254        b.set(2, true);
255
256        a.set(3, false); // a and b diverge on bit 3
257        b.set(3, true);  // and a has a 0 bit in that pos
258
259        a.set(4, true);  // anything that remains after
260        b.set(4, false); // the firs lexicographical difference is ignored
261
262        a.set(150, true);
263        b.set(150, true);
264
265        assert!(LexBitSet(&b) >= LexBitSet(&a));
266        assert!(LexBitSet(&b) >  LexBitSet(&a));
267    }
268    #[test]
269    fn same_size_equal() {
270        let mut a = BitSet::with_capacity(200);
271        let mut b = BitSet::with_capacity(200);
272
273        a.set(2, true);  // bits 0..2 match for a and b
274        b.set(2, true);
275
276        a.set(150, true);
277        b.set(150, true);
278
279        assert!(LexBitSet(&a) >= LexBitSet(&b));
280        assert!(LexBitSet(&b) >= LexBitSet(&a));
281
282        assert_eq!(LexBitSet(&a), LexBitSet(&b));
283        assert_eq!(LexBitSet(&a), LexBitSet(&a));
284        assert_eq!(LexBitSet(&b), LexBitSet(&b));
285    }
286
287    #[test]
288    /// For different sized bitsets, it behaves as though they were padded with
289    /// trailing zeroes.
290    fn different_sizes_considered_padded_with_zeroes() {
291        let mut a = BitSet::with_capacity(20);
292        let mut b = BitSet::with_capacity(200);
293
294        a.set(2, true);  // bits 0..2 match for a and b
295        b.set(2, true);
296
297        assert_eq!(LexBitSet(&a), LexBitSet(&b));
298
299        b.set(150, true);
300        assert!(LexBitSet(&a) <= LexBitSet(&b));
301        assert!(LexBitSet(&a) <  LexBitSet(&b));
302    }
303}