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