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}