cranelift_bitset/
compound.rs

1//! Compound bit sets.
2
3use crate::scalar::{self, ScalarBitSet};
4use alloc::boxed::Box;
5use core::{cmp, iter, mem};
6
7/// A large bit set backed by dynamically-sized storage.
8///
9/// # Example
10///
11/// ```
12/// use cranelift_bitset::CompoundBitSet;
13///
14/// // Create a new bitset.
15/// let mut bitset = CompoundBitSet::new();
16///
17/// // Bitsets are initially empty.
18/// assert!(bitset.is_empty());
19/// assert_eq!(bitset.len(), 0);
20///
21/// // Insert into the bitset.
22/// bitset.insert(444);
23/// bitset.insert(555);
24/// bitset.insert(666);
25///
26/// // Now the bitset is not empty.
27/// assert_eq!(bitset.len(), 3);
28/// assert!(!bitset.is_empty());
29/// assert!(bitset.contains(444));
30/// assert!(bitset.contains(555));
31/// assert!(bitset.contains(666));
32///
33/// // Remove an element from the bitset.
34/// let was_present = bitset.remove(666);
35/// assert!(was_present);
36/// assert!(!bitset.contains(666));
37/// assert_eq!(bitset.len(), 2);
38///
39/// // Can iterate over the elements in the set.
40/// let elems: Vec<_> = bitset.iter().collect();
41/// assert_eq!(elems, [444, 555]);
42/// ```
43#[derive(Clone, Default, PartialEq, Eq)]
44#[cfg_attr(
45    feature = "enable-serde",
46    derive(serde_derive::Serialize, serde_derive::Deserialize)
47)]
48pub struct CompoundBitSet {
49    elems: Box<[ScalarBitSet<usize>]>,
50    max: Option<u32>,
51}
52
53impl core::fmt::Debug for CompoundBitSet {
54    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55        write!(f, "CompoundBitSet ")?;
56        f.debug_set().entries(self.iter()).finish()
57    }
58}
59
60const BITS_PER_WORD: usize = mem::size_of::<usize>() * 8;
61
62impl CompoundBitSet {
63    /// Construct a new, empty bit set.
64    ///
65    /// # Example
66    ///
67    /// ```
68    /// use cranelift_bitset::CompoundBitSet;
69    ///
70    /// let bitset = CompoundBitSet::new();
71    ///
72    /// assert!(bitset.is_empty());
73    /// ```
74    #[inline]
75    pub fn new() -> Self {
76        CompoundBitSet::default()
77    }
78
79    /// Construct a new, empty bit set with space reserved to store any element
80    /// `x` such that `x < capacity`.
81    ///
82    /// The actual capacity reserved may be greater than that requested.
83    ///
84    /// # Example
85    ///
86    /// ```
87    /// use cranelift_bitset::CompoundBitSet;
88    ///
89    /// let bitset = CompoundBitSet::with_capacity(4096);
90    ///
91    /// assert!(bitset.is_empty());
92    /// assert!(bitset.capacity() >= 4096);
93    /// ```
94    #[inline]
95    pub fn with_capacity(capacity: usize) -> Self {
96        let mut bitset = Self::new();
97        bitset.ensure_capacity(capacity);
98        bitset
99    }
100
101    /// Get the number of elements in this bitset.
102    ///
103    /// # Example
104    ///
105    /// ```
106    /// use cranelift_bitset::CompoundBitSet;
107    ///
108    /// let mut bitset = CompoundBitSet::new();
109    ///
110    /// assert_eq!(bitset.len(), 0);
111    ///
112    /// bitset.insert(24);
113    /// bitset.insert(130);
114    /// bitset.insert(3600);
115    ///
116    /// assert_eq!(bitset.len(), 3);
117    /// ```
118    #[inline]
119    pub fn len(&self) -> usize {
120        self.elems.iter().map(|sub| usize::from(sub.len())).sum()
121    }
122
123    /// Get `n + 1` where `n` is the largest value that can be stored inside
124    /// this set without growing the backing storage.
125    ///
126    /// That is, this set can store any value `x` such that `x <
127    /// bitset.capacity()` without growing the backing storage.
128    ///
129    /// # Example
130    ///
131    /// ```
132    /// use cranelift_bitset::CompoundBitSet;
133    ///
134    /// let mut bitset = CompoundBitSet::new();
135    ///
136    /// // New bitsets have zero capacity -- they allocate lazily.
137    /// assert_eq!(bitset.capacity(), 0);
138    ///
139    /// // Insert into the bitset, growing its capacity.
140    /// bitset.insert(999);
141    ///
142    /// // The bitset must now have capacity for at least `999` elements,
143    /// // perhaps more.
144    /// assert!(bitset.capacity() >= 999);
145    ///```
146    pub fn capacity(&self) -> usize {
147        self.elems.len() * BITS_PER_WORD
148    }
149
150    /// Is this bitset empty?
151    ///
152    /// # Example
153    ///
154    /// ```
155    /// use cranelift_bitset::CompoundBitSet;
156    ///
157    /// let mut bitset = CompoundBitSet::new();
158    ///
159    /// assert!(bitset.is_empty());
160    ///
161    /// bitset.insert(1234);
162    ///
163    /// assert!(!bitset.is_empty());
164    /// ```
165    #[inline]
166    pub fn is_empty(&self) -> bool {
167        self.len() == 0
168    }
169
170    /// Convert an element `i` into the `word` that can be used to index into
171    /// `self.elems` and the `bit` that can be tested in the
172    /// `ScalarBitSet<usize>` at `self.elems[word]`.
173    #[inline]
174    fn word_and_bit(i: usize) -> (usize, u8) {
175        let word = i / BITS_PER_WORD;
176        let bit = i % BITS_PER_WORD;
177        let bit = u8::try_from(bit).unwrap();
178        (word, bit)
179    }
180
181    /// The opposite of `word_and_bit`: convert the pair of an index into
182    /// `self.elems` and associated bit index into a set element.
183    #[inline]
184    fn elem(word: usize, bit: u8) -> usize {
185        let bit = usize::from(bit);
186        debug_assert!(bit < BITS_PER_WORD);
187        word * BITS_PER_WORD + bit
188    }
189
190    /// Is `i` contained in this bitset?
191    ///
192    /// # Example
193    ///
194    /// ```
195    /// use cranelift_bitset::CompoundBitSet;
196    ///
197    /// let mut bitset = CompoundBitSet::new();
198    ///
199    /// assert!(!bitset.contains(666));
200    ///
201    /// bitset.insert(666);
202    ///
203    /// assert!(bitset.contains(666));
204    /// ```
205    #[inline]
206    pub fn contains(&self, i: usize) -> bool {
207        let (word, bit) = Self::word_and_bit(i);
208        if word < self.elems.len() {
209            self.elems[word].contains(bit)
210        } else {
211            false
212        }
213    }
214
215    /// Ensure there is space in this bitset for the values `0..n`, growing the
216    /// backing storage if necessary.
217    ///
218    /// After calling `bitset.ensure_capacity(n)`, inserting any element `i`
219    /// where `i < n` is guaranteed to succeed without growing the bitset's
220    /// backing storage.
221    ///
222    /// # Example
223    ///
224    /// ```
225    /// # use cranelift_bitset::CompoundBitSet;
226    /// # let mut bitset = CompoundBitSet::new();
227    /// // We are going to do a series of inserts where `1000` will be the
228    /// // maximum value inserted. Make sure that our bitset has capacity for
229    /// // these elements once up front, to avoid growing the backing storage
230    /// // multiple times incrementally.
231    /// bitset.ensure_capacity(1001);
232    ///
233    /// for i in 0..=1000 {
234    ///     if i % 2 == 0 {
235    ///         // Inserting this value should not require growing the backing
236    ///         // storage.
237    ///         assert!(bitset.capacity() > i);
238    ///         bitset.insert(i);
239    ///     }
240    /// }
241    /// ```
242    #[inline]
243    pub fn ensure_capacity(&mut self, n: usize) {
244        let (word, _bit) = Self::word_and_bit(n);
245        if word >= self.elems.len() {
246            assert!(word < usize::try_from(isize::MAX).unwrap());
247
248            let delta = word - self.elems.len();
249            let to_grow = delta + 1;
250
251            // Amortize the cost of growing.
252            let to_grow = cmp::max(to_grow, self.elems.len() * 2);
253            // Don't make ridiculously small allocations.
254            let to_grow = cmp::max(to_grow, 4);
255
256            let new_elems = self
257                .elems
258                .iter()
259                .copied()
260                .chain(iter::repeat(ScalarBitSet::new()).take(to_grow))
261                .collect::<Box<[_]>>();
262            self.elems = new_elems;
263        }
264    }
265
266    /// Insert `i` into this bitset.
267    ///
268    /// Returns whether the value was newly inserted. That is:
269    ///
270    /// * If the set did not previously contain `i` then `true` is returned.
271    ///
272    /// * If the set already contained `i` then `false` is returned.
273    ///
274    /// # Example
275    ///
276    /// ```
277    /// use cranelift_bitset::CompoundBitSet;
278    ///
279    /// let mut bitset = CompoundBitSet::new();
280    ///
281    /// // When an element is inserted that was not already present in the set,
282    /// // then `true` is returned.
283    /// let is_new = bitset.insert(1234);
284    /// assert!(is_new);
285    ///
286    /// // The element is now present in the set.
287    /// assert!(bitset.contains(1234));
288    ///
289    /// // And when the element is already in the set, `false` is returned from
290    /// // `insert`.
291    /// let is_new = bitset.insert(1234);
292    /// assert!(!is_new);
293    /// ```
294    #[inline]
295    pub fn insert(&mut self, i: usize) -> bool {
296        self.ensure_capacity(i + 1);
297
298        let (word, bit) = Self::word_and_bit(i);
299        let is_new = self.elems[word].insert(bit);
300
301        let i = u32::try_from(i).unwrap();
302        self.max = self.max.map(|max| cmp::max(max, i)).or(Some(i));
303
304        is_new
305    }
306
307    /// Remove `i` from this bitset.
308    ///
309    /// Returns whether `i` was previously in this set or not.
310    ///
311    /// # Example
312    ///
313    /// ```
314    /// use cranelift_bitset::CompoundBitSet;
315    ///
316    /// let mut bitset = CompoundBitSet::new();
317    ///
318    /// // Removing an element that was not present in the set returns `false`.
319    /// let was_present = bitset.remove(456);
320    /// assert!(!was_present);
321    ///
322    /// // And when the element was in the set, `true` is returned.
323    /// bitset.insert(456);
324    /// let was_present = bitset.remove(456);
325    /// assert!(was_present);
326    /// ```
327    #[inline]
328    pub fn remove(&mut self, i: usize) -> bool {
329        let (word, bit) = Self::word_and_bit(i);
330        if word < self.elems.len() {
331            let sub = &mut self.elems[word];
332            let was_present = sub.remove(bit);
333            if was_present && self.max() == Some(i) {
334                self.update_max(word);
335            }
336            was_present
337        } else {
338            false
339        }
340    }
341
342    /// Update the `self.max` field, based on the old word index of `self.max`.
343    fn update_max(&mut self, word_of_old_max: usize) {
344        self.max = self.elems[0..word_of_old_max + 1]
345            .iter()
346            .enumerate()
347            .rev()
348            .filter_map(|(word, sub)| {
349                let bit = sub.max()?;
350                Some(u32::try_from(Self::elem(word, bit)).unwrap())
351            })
352            .next();
353    }
354
355    /// Get the largest value in this set, or `None` if this set is empty.
356    ///
357    /// # Example
358    ///
359    /// ```
360    /// use cranelift_bitset::CompoundBitSet;
361    ///
362    /// let mut bitset = CompoundBitSet::new();
363    ///
364    /// // Returns `None` if the bitset is empty.
365    /// assert!(bitset.max().is_none());
366    ///
367    /// bitset.insert(123);
368    /// bitset.insert(987);
369    /// bitset.insert(999);
370    ///
371    /// // Otherwise, it returns the largest value in the set.
372    /// assert_eq!(bitset.max(), Some(999));
373    /// ```
374    #[inline]
375    pub fn max(&self) -> Option<usize> {
376        self.max.map(|m| usize::try_from(m).unwrap())
377    }
378
379    /// Removes and returns the largest value in this set.
380    ///
381    /// Returns `None` if this set is empty.
382    ///
383    /// # Example
384    ///
385    /// ```
386    /// use cranelift_bitset::CompoundBitSet;
387    ///
388    /// let mut bitset = CompoundBitSet::new();
389    ///
390    /// bitset.insert(111);
391    /// bitset.insert(222);
392    /// bitset.insert(333);
393    /// bitset.insert(444);
394    /// bitset.insert(555);
395    ///
396    /// assert_eq!(bitset.pop(), Some(555));
397    /// assert_eq!(bitset.pop(), Some(444));
398    /// assert_eq!(bitset.pop(), Some(333));
399    /// assert_eq!(bitset.pop(), Some(222));
400    /// assert_eq!(bitset.pop(), Some(111));
401    /// assert_eq!(bitset.pop(), None);
402    /// ```
403    #[inline]
404    pub fn pop(&mut self) -> Option<usize> {
405        let max = self.max()?;
406        self.remove(max);
407        Some(max)
408    }
409
410    /// Remove all elements from this bitset.
411    ///
412    /// # Example
413    ///
414    /// ```
415    /// use cranelift_bitset::CompoundBitSet;
416    ///
417    /// let mut bitset = CompoundBitSet::new();
418    ///
419    /// bitset.insert(100);
420    /// bitset.insert(200);
421    /// bitset.insert(300);
422    ///
423    /// bitset.clear();
424    ///
425    /// assert!(bitset.is_empty());
426    /// ```
427    #[inline]
428    pub fn clear(&mut self) {
429        let max = match self.max() {
430            Some(max) => max,
431            None => return,
432        };
433        let (word, _bit) = Self::word_and_bit(max);
434        debug_assert!(self.elems[word + 1..].iter().all(|sub| sub.is_empty()));
435        for sub in &mut self.elems[..=word] {
436            *sub = ScalarBitSet::new();
437        }
438        self.max = None;
439    }
440
441    /// Iterate over the elements in this bitset.
442    ///
443    /// The elements are always yielded in sorted order.
444    ///
445    /// # Example
446    ///
447    /// ```
448    /// use cranelift_bitset::CompoundBitSet;
449    ///
450    /// let mut bitset = CompoundBitSet::new();
451    ///
452    /// bitset.insert(0);
453    /// bitset.insert(4096);
454    /// bitset.insert(123);
455    /// bitset.insert(456);
456    /// bitset.insert(789);
457    ///
458    /// assert_eq!(
459    ///     bitset.iter().collect::<Vec<_>>(),
460    ///     [0, 123, 456, 789, 4096],
461    /// );
462    /// ```
463    #[inline]
464    pub fn iter(&self) -> Iter<'_> {
465        Iter {
466            bitset: self,
467            word: 0,
468            sub: None,
469        }
470    }
471}
472
473impl<'a> IntoIterator for &'a CompoundBitSet {
474    type Item = usize;
475
476    type IntoIter = Iter<'a>;
477
478    #[inline]
479    fn into_iter(self) -> Self::IntoIter {
480        self.iter()
481    }
482}
483
484/// An iterator over the elements in a [`CompoundBitSet`].
485pub struct Iter<'a> {
486    bitset: &'a CompoundBitSet,
487    word: usize,
488    sub: Option<scalar::Iter<usize>>,
489}
490
491impl Iterator for Iter<'_> {
492    type Item = usize;
493
494    #[inline]
495    fn next(&mut self) -> Option<usize> {
496        loop {
497            if let Some(sub) = &mut self.sub {
498                if let Some(bit) = sub.next() {
499                    return Some(CompoundBitSet::elem(self.word, bit));
500                } else {
501                    self.word += 1;
502                }
503            }
504
505            self.sub = Some(self.bitset.elems.get(self.word)?.iter());
506        }
507    }
508}