Path: blob/main/cranelift/bitset/src/scalar.rs
1692 views
//! Scalar bitsets.12use core::mem::size_of;3use core::ops::{Add, BitAnd, BitOr, Not, Shl, Shr, Sub};45/// A small bitset built on top of a single primitive integer type.6///7/// # Example8///9/// ```10/// use cranelift_bitset::ScalarBitSet;11///12/// // Create a new bitset backed with a `u32`.13/// let mut bitset = ScalarBitSet::<u32>::new();14///15/// // Bitsets are initially empty.16/// assert!(bitset.is_empty());17/// assert_eq!(bitset.len(), 0);18///19/// // Insert into the bitset.20/// bitset.insert(4);21/// bitset.insert(5);22/// bitset.insert(6);23///24/// // Now the bitset is not empty.25/// assert_eq!(bitset.len(), 3);26/// assert!(!bitset.is_empty());27/// assert!(bitset.contains(4));28/// assert!(bitset.contains(5));29/// assert!(bitset.contains(6));30///31/// // Remove an element from the bitset.32/// let was_present = bitset.remove(6);33/// assert!(was_present);34/// assert!(!bitset.contains(6));35/// assert_eq!(bitset.len(), 2);36///37/// // Can iterate over the elements in the set.38/// let elems: Vec<_> = bitset.iter().collect();39/// assert_eq!(elems, [4, 5]);40/// ```41#[derive(Clone, Copy, PartialEq, Eq)]42#[cfg_attr(43feature = "enable-serde",44derive(serde_derive::Serialize, serde_derive::Deserialize)45)]46pub struct ScalarBitSet<T>(pub T);4748impl<T> core::fmt::Debug for ScalarBitSet<T>49where50T: ScalarBitSetStorage,51{52fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {53let mut s = f.debug_struct(core::any::type_name::<Self>());54for i in 0..Self::capacity() {55use alloc::string::ToString;56s.field(&i.to_string(), &self.contains(i));57}58s.finish()59}60}6162impl<T> Default for ScalarBitSet<T>63where64T: ScalarBitSetStorage,65{66#[inline]67fn default() -> Self {68Self::new()69}70}7172impl<T> ScalarBitSet<T>73where74T: ScalarBitSetStorage,75{76/// Create a new, empty bitset.77///78/// # Example79///80/// ```81/// use cranelift_bitset::ScalarBitSet;82///83/// let bitset = ScalarBitSet::<u64>::new();84///85/// assert!(bitset.is_empty());86/// ```87#[inline]88pub fn new() -> Self {89Self(T::from(0))90}9192/// Construct a bitset with the half-open range `[lo, hi)` inserted.93///94/// # Example95///96/// ```97/// use cranelift_bitset::ScalarBitSet;98///99/// let bitset = ScalarBitSet::<u64>::from_range(3, 6);100///101/// assert_eq!(bitset.len(), 3);102///103/// assert!(bitset.contains(3));104/// assert!(bitset.contains(4));105/// assert!(bitset.contains(5));106/// ```107///108/// # Panics109///110/// Panics if `lo > hi` or if `hi > Self::capacity()`.111///112/// ```should_panic113/// use cranelift_bitset::ScalarBitSet;114///115/// // The lower bound may not be larger than the upper bound.116/// let bitset = ScalarBitSet::<u64>::from_range(6, 3);117/// ```118///119/// ```should_panic120/// use cranelift_bitset::ScalarBitSet;121///122/// // The bounds must fit within the backing scalar type.123/// let bitset = ScalarBitSet::<u64>::from_range(3, 69);124/// ```125#[inline]126pub fn from_range(lo: u8, hi: u8) -> Self {127assert!(lo <= hi);128assert!(hi <= Self::capacity());129130let one = T::from(1);131132// We can't just do (one << hi) - one here as the shift may overflow133let hi_rng = if hi >= 1 {134(one << (hi - 1)) + ((one << (hi - 1)) - one)135} else {136T::from(0)137};138139let lo_rng = (one << lo) - one;140141Self(hi_rng - lo_rng)142}143144/// The maximum number of bits that can be stored in this bitset.145///146/// If you need more bits than this, use a147/// [`CompoundBitSet`][crate::CompoundBitSet] instead of a `ScalarBitSet`.148///149/// # Example150///151/// ```152/// use cranelift_bitset::ScalarBitSet;153///154/// assert_eq!(ScalarBitSet::<u8>::capacity(), 8);155/// assert_eq!(ScalarBitSet::<u64>::capacity(), 64);156/// ```157#[inline]158pub fn capacity() -> u8 {159u8::try_from(size_of::<T>()).unwrap() * 8160}161162/// Get the number of elements in this set.163///164/// # Example165///166/// ```167/// use cranelift_bitset::ScalarBitSet;168///169/// let mut bitset = ScalarBitSet::<u64>::new();170///171/// assert_eq!(bitset.len(), 0);172///173/// bitset.insert(24);174/// bitset.insert(13);175/// bitset.insert(36);176///177/// assert_eq!(bitset.len(), 3);178/// ```179#[inline]180pub fn len(&self) -> u8 {181self.0.count_ones()182}183184/// Is this bitset empty?185///186/// # Example187///188/// ```189/// use cranelift_bitset::ScalarBitSet;190///191/// let mut bitset = ScalarBitSet::<u16>::new();192///193/// assert!(bitset.is_empty());194///195/// bitset.insert(10);196///197/// assert!(!bitset.is_empty());198/// ```199#[inline]200pub fn is_empty(&self) -> bool {201self.0 == T::from(0)202}203204/// Check whether this bitset contains `i`.205///206/// # Example207///208/// ```209/// use cranelift_bitset::ScalarBitSet;210///211/// let mut bitset = ScalarBitSet::<u8>::new();212///213/// assert!(!bitset.contains(7));214///215/// bitset.insert(7);216///217/// assert!(bitset.contains(7));218/// ```219///220/// # Panics221///222/// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].223///224/// ```should_panic225/// use cranelift_bitset::ScalarBitSet;226///227/// let mut bitset = ScalarBitSet::<u8>::new();228///229/// // A `ScalarBitSet<u8>` can only hold the elements `0..=7`, so `8` is230/// // out of bounds and will trigger a panic.231/// bitset.contains(8);232/// ```233#[inline]234pub fn contains(&self, i: u8) -> bool {235assert!(i < Self::capacity());236self.0 & (T::from(1) << i) != T::from(0)237}238239/// Insert `i` into this bitset.240///241/// Returns whether the value was newly inserted. That is:242///243/// * If the set did not previously contain `i` then `true` is returned.244///245/// * If the set already contained `i` then `false` is returned.246///247/// # Example248///249/// ```250/// use cranelift_bitset::ScalarBitSet;251///252/// let mut bitset = ScalarBitSet::<u8>::new();253///254/// // When an element is inserted that was not already present in the set,255/// // then `true` is returned.256/// let is_new = bitset.insert(7);257/// assert!(is_new);258///259/// // The element is now present in the set.260/// assert!(bitset.contains(7));261///262/// // And when the element is already in the set, `false` is returned from263/// // `insert`.264/// let is_new = bitset.insert(7);265/// assert!(!is_new);266/// ```267///268/// # Panics269///270/// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].271///272/// ```should_panic273/// use cranelift_bitset::ScalarBitSet;274///275/// let mut bitset = ScalarBitSet::<u32>::new();276///277/// // A `ScalarBitSet<u32>` can only hold the elements `0..=31`, so `42` is278/// // out of bounds and will trigger a panic.279/// bitset.insert(42);280/// ```281#[inline]282pub fn insert(&mut self, i: u8) -> bool {283let is_new = !self.contains(i);284self.0 = self.0 | (T::from(1) << i);285is_new286}287288/// Remove `i` from this bitset.289///290/// Returns whether `i` was previously in this set or not.291///292/// # Example293///294/// ```295/// use cranelift_bitset::ScalarBitSet;296///297/// let mut bitset = ScalarBitSet::<u128>::new();298///299/// // Removing an element that was not present in the set returns `false`.300/// let was_present = bitset.remove(100);301/// assert!(!was_present);302///303/// // And when the element was in the set, `true` is returned.304/// bitset.insert(100);305/// let was_present = bitset.remove(100);306/// assert!(was_present);307/// ```308///309/// # Panics310///311/// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].312///313/// ```should_panic314/// use cranelift_bitset::ScalarBitSet;315///316/// let mut bitset = ScalarBitSet::<u16>::new();317///318/// // A `ScalarBitSet<u16>` can only hold the elements `0..=15`, so `20` is319/// // out of bounds and will trigger a panic.320/// bitset.remove(20);321/// ```322#[inline]323pub fn remove(&mut self, i: u8) -> bool {324let was_present = self.contains(i);325self.0 = self.0 & !(T::from(1) << i);326was_present327}328329/// Remove all entries from this bitset.330///331/// # Example332///333/// ```334/// use cranelift_bitset::ScalarBitSet;335///336/// let mut bitset = ScalarBitSet::<u32>::new();337///338/// bitset.insert(10);339/// bitset.insert(20);340/// bitset.insert(30);341///342/// bitset.clear();343///344/// assert!(bitset.is_empty());345/// ```346#[inline]347pub fn clear(&mut self) {348self.0 = T::from(0);349}350351/// Remove and return the smallest value in the bitset.352///353/// # Example354///355/// ```356/// use cranelift_bitset::ScalarBitSet;357///358/// let mut bitset = ScalarBitSet::<u64>::new();359///360/// bitset.insert(0);361/// bitset.insert(24);362/// bitset.insert(13);363/// bitset.insert(36);364///365/// assert_eq!(bitset.pop_min(), Some(0));366/// assert_eq!(bitset.pop_min(), Some(13));367/// assert_eq!(bitset.pop_min(), Some(24));368/// assert_eq!(bitset.pop_min(), Some(36));369/// assert_eq!(bitset.pop_min(), None);370/// ```371#[inline]372pub fn pop_min(&mut self) -> Option<u8> {373let min = self.min()?;374self.remove(min);375Some(min)376}377378/// Remove and return the largest value in the bitset.379///380/// # Example381///382/// ```383/// use cranelift_bitset::ScalarBitSet;384///385/// let mut bitset = ScalarBitSet::<u64>::new();386///387/// bitset.insert(0);388/// bitset.insert(24);389/// bitset.insert(13);390/// bitset.insert(36);391///392/// assert_eq!(bitset.pop_max(), Some(36));393/// assert_eq!(bitset.pop_max(), Some(24));394/// assert_eq!(bitset.pop_max(), Some(13));395/// assert_eq!(bitset.pop_max(), Some(0));396/// assert_eq!(bitset.pop_max(), None);397/// ```398#[inline]399pub fn pop_max(&mut self) -> Option<u8> {400let max = self.max()?;401self.remove(max);402Some(max)403}404405/// Return the smallest number contained in this bitset or `None` if this406/// bitset is empty.407///408/// # Example409///410/// ```411/// use cranelift_bitset::ScalarBitSet;412///413/// let mut bitset = ScalarBitSet::<u64>::new();414///415/// // When the bitset is empty, `min` returns `None`.416/// assert_eq!(bitset.min(), None);417///418/// bitset.insert(28);419/// bitset.insert(1);420/// bitset.insert(63);421///422/// // When the bitset is not empty, it returns the smallest element.423/// assert_eq!(bitset.min(), Some(1));424/// ```425#[inline]426pub fn min(&self) -> Option<u8> {427if self.0 == T::from(0) {428None429} else {430Some(self.0.trailing_zeros())431}432}433434/// Return the largest number contained in the bitset or None if this bitset435/// is empty436///437/// # Example438///439/// ```440/// use cranelift_bitset::ScalarBitSet;441///442/// let mut bitset = ScalarBitSet::<u64>::new();443///444/// // When the bitset is empty, `max` returns `None`.445/// assert_eq!(bitset.max(), None);446///447/// bitset.insert(0);448/// bitset.insert(36);449/// bitset.insert(49);450///451/// // When the bitset is not empty, it returns the smallest element.452/// assert_eq!(bitset.max(), Some(49));453/// ```454#[inline]455pub fn max(&self) -> Option<u8> {456if self.0 == T::from(0) {457None458} else {459let leading_zeroes = self.0.leading_zeros();460Some(Self::capacity() - leading_zeroes - 1)461}462}463464/// Iterate over the items in this set.465///466/// Items are always yielded in sorted order.467///468/// # Example469///470/// ```471/// use cranelift_bitset::ScalarBitSet;472///473/// let mut bitset = ScalarBitSet::<u64>::new();474///475/// bitset.insert(19);476/// bitset.insert(3);477/// bitset.insert(63);478/// bitset.insert(0);479///480/// assert_eq!(481/// bitset.iter().collect::<Vec<_>>(),482/// [0, 3, 19, 63],483/// );484/// ```485#[inline]486pub fn iter(self) -> Iter<T> {487Iter { bitset: self }488}489}490491impl<T> IntoIterator for ScalarBitSet<T>492where493T: ScalarBitSetStorage,494{495type Item = u8;496497type IntoIter = Iter<T>;498499#[inline]500fn into_iter(self) -> Self::IntoIter {501self.iter()502}503}504505impl<'a, T> IntoIterator for &'a ScalarBitSet<T>506where507T: ScalarBitSetStorage,508{509type Item = u8;510511type IntoIter = Iter<T>;512513#[inline]514fn into_iter(self) -> Self::IntoIter {515self.iter()516}517}518519impl<T: ScalarBitSetStorage> From<T> for ScalarBitSet<T> {520fn from(bits: T) -> Self {521Self(bits)522}523}524525/// A trait implemented by all integers that can be used as the backing storage526/// for a [`ScalarBitSet`].527///528/// You shouldn't have to implement this yourself, it is already implemented for529/// `u{8,16,32,64,128}` and if you need more bits than that, then use530/// [`CompoundBitSet`][crate::CompoundBitSet] instead.531pub trait ScalarBitSetStorage:532Default533+ From<u8>534+ Shl<u8, Output = Self>535+ Shr<u8, Output = Self>536+ BitAnd<Output = Self>537+ BitOr<Output = Self>538+ Not<Output = Self>539+ Sub<Output = Self>540+ Add<Output = Self>541+ PartialEq542+ Copy543{544/// Count the number of leading zeros.545fn leading_zeros(self) -> u8;546547/// Count the number of trailing zeros.548fn trailing_zeros(self) -> u8;549550/// Count the number of bits set in this integer.551fn count_ones(self) -> u8;552}553554macro_rules! impl_storage {555( $int:ty ) => {556impl ScalarBitSetStorage for $int {557#[inline]558fn leading_zeros(self) -> u8 {559u8::try_from(self.leading_zeros()).unwrap()560}561562#[inline]563fn trailing_zeros(self) -> u8 {564u8::try_from(self.trailing_zeros()).unwrap()565}566567#[inline]568fn count_ones(self) -> u8 {569u8::try_from(self.count_ones()).unwrap()570}571}572};573}574575impl_storage!(u8);576impl_storage!(u16);577impl_storage!(u32);578impl_storage!(u64);579impl_storage!(u128);580impl_storage!(usize);581582/// An iterator over the elements in a [`ScalarBitSet`].583pub struct Iter<T> {584bitset: ScalarBitSet<T>,585}586587impl<T> Iterator for Iter<T>588where589T: ScalarBitSetStorage,590{591type Item = u8;592593#[inline]594fn next(&mut self) -> Option<u8> {595self.bitset.pop_min()596}597}598599impl<T> DoubleEndedIterator for Iter<T>600where601T: ScalarBitSetStorage,602{603#[inline]604fn next_back(&mut self) -> Option<Self::Item> {605self.bitset.pop_max()606}607}608609impl<T> ExactSizeIterator for Iter<T>610where611T: ScalarBitSetStorage,612{613#[inline]614fn len(&self) -> usize {615usize::from(self.bitset.len())616}617}618619#[cfg(feature = "arbitrary")]620impl<'a, T> arbitrary::Arbitrary<'a> for ScalarBitSet<T>621where622T: ScalarBitSetStorage + arbitrary::Arbitrary<'a>,623{624fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {625T::arbitrary(u).map(Self)626}627}628629630