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