blob: 2d959016caf43b4a45b7c4dc92095561903cdb0d [file] [log] [blame] [edit]
//! Scalar bitsets.
use core::mem::size_of;
use core::ops::{Add, BitAnd, BitOr, Not, Shl, Shr, Sub};
/// A small bitset built on top of a single primitive integer type.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// // Create a new bitset backed with a `u32`.
/// let mut bitset = ScalarBitSet::<u32>::new();
///
/// // Bitsets are initially empty.
/// assert!(bitset.is_empty());
/// assert_eq!(bitset.len(), 0);
///
/// // Insert into the bitset.
/// bitset.insert(4);
/// bitset.insert(5);
/// bitset.insert(6);
///
/// // Now the bitset is not empty.
/// assert_eq!(bitset.len(), 3);
/// assert!(!bitset.is_empty());
/// assert!(bitset.contains(4));
/// assert!(bitset.contains(5));
/// assert!(bitset.contains(6));
///
/// // Remove an element from the bitset.
/// let was_present = bitset.remove(6);
/// assert!(was_present);
/// assert!(!bitset.contains(6));
/// assert_eq!(bitset.len(), 2);
///
/// // Can iterate over the elements in the set.
/// let elems: Vec<_> = bitset.iter().collect();
/// assert_eq!(elems, [4, 5]);
/// ```
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(
feature = "enable-serde",
derive(serde_derive::Serialize, serde_derive::Deserialize)
)]
pub struct ScalarBitSet<T>(pub T);
impl<T> core::fmt::Debug for ScalarBitSet<T>
where
T: ScalarBitSetStorage,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut s = f.debug_struct(core::any::type_name::<Self>());
for i in 0..Self::capacity() {
use alloc::string::ToString;
let i = u8::try_from(i).unwrap();
s.field(&i.to_string(), &self.contains(i));
}
s.finish()
}
}
impl<T> Default for ScalarBitSet<T>
where
T: ScalarBitSetStorage,
{
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T> ScalarBitSet<T>
where
T: ScalarBitSetStorage,
{
/// Create a new, empty bitset.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let bitset = ScalarBitSet::<u64>::new();
///
/// assert!(bitset.is_empty());
/// ```
#[inline]
pub fn new() -> Self {
Self(T::from(0))
}
/// Construct a bitset with the half-open range `[lo, hi)` inserted.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let bitset = ScalarBitSet::<u64>::from_range(3, 6);
///
/// assert_eq!(bitset.len(), 3);
///
/// assert!(bitset.contains(3));
/// assert!(bitset.contains(4));
/// assert!(bitset.contains(5));
/// ```
///
/// # Panics
///
/// Panics if `lo > hi` or if `hi > Self::capacity()`.
///
/// ```should_panic
/// use cranelift_bitset::ScalarBitSet;
///
/// // The lower bound may not be larger than the upper bound.
/// let bitset = ScalarBitSet::<u64>::from_range(6, 3);
/// ```
///
/// ```should_panic
/// use cranelift_bitset::ScalarBitSet;
///
/// // The bounds must fit within the backing scalar type.
/// let bitset = ScalarBitSet::<u64>::from_range(3, 69);
/// ```
#[inline]
pub fn from_range(lo: u8, hi: u8) -> Self {
assert!(lo <= hi);
assert!(hi <= Self::capacity());
let one = T::from(1);
// We can't just do (one << hi) - one here as the shift may overflow
let hi_rng = if hi >= 1 {
(one << (hi - 1)) + ((one << (hi - 1)) - one)
} else {
T::from(0)
};
let lo_rng = (one << lo) - one;
Self(hi_rng - lo_rng)
}
/// The maximum number of bits that can be stored in this bitset.
///
/// If you need more bits than this, use a
/// [`CompoundBitSet`][crate::CompoundBitSet] instead of a `ScalarBitSet`.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// assert_eq!(ScalarBitSet::<u8>::capacity(), 8);
/// assert_eq!(ScalarBitSet::<u64>::capacity(), 64);
/// ```
#[inline]
pub fn capacity() -> u8 {
u8::try_from(size_of::<T>()).unwrap() * 8
}
/// Get the number of elements in this set.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u64>::new();
///
/// assert_eq!(bitset.len(), 0);
///
/// bitset.insert(24);
/// bitset.insert(13);
/// bitset.insert(36);
///
/// assert_eq!(bitset.len(), 3);
/// ```
#[inline]
pub fn len(&self) -> u8 {
self.0.count_ones()
}
/// Is this bitset empty?
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u16>::new();
///
/// assert!(bitset.is_empty());
///
/// bitset.insert(10);
///
/// assert!(!bitset.is_empty());
/// ```
#[inline]
pub fn is_empty(&self) -> bool {
self.0 == T::from(0)
}
/// Check whether this bitset contains `i`.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u8>::new();
///
/// assert!(!bitset.contains(7));
///
/// bitset.insert(7);
///
/// assert!(bitset.contains(7));
/// ```
///
/// # Panics
///
/// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].
///
/// ```should_panic
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u8>::new();
///
/// // A `ScalarBitSet<u8>` can only hold the elements `0..=7`, so `8` is
/// // out of bounds and will trigger a panic.
/// bitset.contains(8);
/// ```
#[inline]
pub fn contains(&self, i: u8) -> bool {
assert!(i < Self::capacity());
self.0 & (T::from(1) << i) != T::from(0)
}
/// Insert `i` into this bitset.
///
/// Returns whether the value was newly inserted. That is:
///
/// * If the set did not previously contain `i` then `true` is returned.
///
/// * If the set already contained `i` then `false` is returned.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u8>::new();
///
/// // When an element is inserted that was not already present in the set,
/// // then `true` is returned.
/// let is_new = bitset.insert(7);
/// assert!(is_new);
///
/// // The element is now present in the set.
/// assert!(bitset.contains(7));
///
/// // And when the element is already in the set, `false` is returned from
/// // `insert`.
/// let is_new = bitset.insert(7);
/// assert!(!is_new);
/// ```
///
/// # Panics
///
/// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].
///
/// ```should_panic
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u32>::new();
///
/// // A `ScalarBitSet<u32>` can only hold the elements `0..=31`, so `42` is
/// // out of bounds and will trigger a panic.
/// bitset.insert(42);
/// ```
#[inline]
pub fn insert(&mut self, i: u8) -> bool {
let is_new = !self.contains(i);
self.0 = self.0 | (T::from(1) << i);
is_new
}
/// Remove `i` from this bitset.
///
/// Returns whether `i` was previously in this set or not.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u128>::new();
///
/// // Removing an element that was not present in the set returns `false`.
/// let was_present = bitset.remove(100);
/// assert!(!was_present);
///
/// // And when the element was in the set, `true` is returned.
/// bitset.insert(100);
/// let was_present = bitset.remove(100);
/// assert!(was_present);
/// ```
///
/// # Panics
///
/// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].
///
/// ```should_panic
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u16>::new();
///
/// // A `ScalarBitSet<u16>` can only hold the elements `0..=15`, so `20` is
/// // out of bounds and will trigger a panic.
/// bitset.remove(20);
/// ```
#[inline]
pub fn remove(&mut self, i: u8) -> bool {
let was_present = self.contains(i);
self.0 = self.0 & !(T::from(1) << i);
was_present
}
/// Remove all entries from this bitset.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u32>::new();
///
/// bitset.insert(10);
/// bitset.insert(20);
/// bitset.insert(30);
///
/// bitset.clear();
///
/// assert!(bitset.is_empty());
/// ```
#[inline]
pub fn clear(&mut self) {
self.0 = T::from(0);
}
/// Remove and return the largest value in the bitset.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u64>::new();
///
/// bitset.insert(0);
/// bitset.insert(24);
/// bitset.insert(13);
/// bitset.insert(36);
///
/// assert_eq!(bitset.pop(), Some(36));
/// assert_eq!(bitset.pop(), Some(24));
/// assert_eq!(bitset.pop(), Some(13));
/// assert_eq!(bitset.pop(), Some(0));
/// assert_eq!(bitset.pop(), None);
/// ```
#[inline]
pub fn pop(&mut self) -> Option<u8> {
let max = self.max()?;
self.remove(max);
Some(max)
}
/// Return the smallest number contained in this bitset or `None` if this
/// bitset is empty.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u64>::new();
///
/// // When the bitset is empty, `min` returns `None`.
/// assert_eq!(bitset.min(), None);
///
/// bitset.insert(28);
/// bitset.insert(1);
/// bitset.insert(63);
///
/// // When the bitset is not empty, it returns the smallest element.
/// assert_eq!(bitset.min(), Some(1));
/// ```
#[inline]
pub fn min(&self) -> Option<u8> {
if self.0 == T::from(0) {
None
} else {
Some(self.0.trailing_zeros())
}
}
/// Return the largest number contained in the bitset or None if this bitset
/// is empty
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u64>::new();
///
/// // When the bitset is empty, `max` returns `None`.
/// assert_eq!(bitset.max(), None);
///
/// bitset.insert(0);
/// bitset.insert(36);
/// bitset.insert(49);
///
/// // When the bitset is not empty, it returns the smallest element.
/// assert_eq!(bitset.max(), Some(49));
/// ```
#[inline]
pub fn max(&self) -> Option<u8> {
if self.0 == T::from(0) {
None
} else {
let leading_zeroes = self.0.leading_zeros();
Some(Self::capacity() - leading_zeroes - 1)
}
}
/// Iterate over the items in this set.
///
/// Items are always yielded in sorted order.
///
/// # Example
///
/// ```
/// use cranelift_bitset::ScalarBitSet;
///
/// let mut bitset = ScalarBitSet::<u64>::new();
///
/// bitset.insert(19);
/// bitset.insert(3);
/// bitset.insert(63);
/// bitset.insert(0);
///
/// assert_eq!(
/// bitset.iter().collect::<Vec<_>>(),
/// [0, 3, 19, 63],
/// );
/// ```
#[inline]
pub fn iter(&self) -> Iter<T> {
Iter {
value: self.0,
index: 0,
}
}
}
impl<T> IntoIterator for ScalarBitSet<T>
where
T: ScalarBitSetStorage,
{
type Item = u8;
type IntoIter = Iter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a ScalarBitSet<T>
where
T: ScalarBitSetStorage,
{
type Item = u8;
type IntoIter = Iter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
/// A trait implemented by all integers that can be used as the backing storage
/// for a [`ScalarBitSet`].
///
/// You shouldn't have to implement this yourself, it is already implemented for
/// `u{8,16,32,64,128}` and if you need more bits than that, then use
/// [`CompoundBitSet`][crate::CompoundBitSet] instead.
pub trait ScalarBitSetStorage:
Default
+ From<u8>
+ Shl<u8, Output = Self>
+ Shr<u8, Output = Self>
+ BitAnd<Output = Self>
+ BitOr<Output = Self>
+ Not<Output = Self>
+ Sub<Output = Self>
+ Add<Output = Self>
+ PartialEq
+ Copy
{
/// Count the number of leading zeros.
fn leading_zeros(self) -> u8;
/// Count the number of trailing zeros.
fn trailing_zeros(self) -> u8;
/// Count the number of bits set in this integer.
fn count_ones(self) -> u8;
}
macro_rules! impl_storage {
( $int:ty ) => {
impl ScalarBitSetStorage for $int {
fn leading_zeros(self) -> u8 {
u8::try_from(self.leading_zeros()).unwrap()
}
fn trailing_zeros(self) -> u8 {
u8::try_from(self.trailing_zeros()).unwrap()
}
fn count_ones(self) -> u8 {
u8::try_from(self.count_ones()).unwrap()
}
}
};
}
impl_storage!(u8);
impl_storage!(u16);
impl_storage!(u32);
impl_storage!(u64);
impl_storage!(u128);
impl_storage!(usize);
/// An iterator over the elements in a [`ScalarBitSet`].
pub struct Iter<T> {
value: T,
index: u8,
}
impl<T> Iterator for Iter<T>
where
T: ScalarBitSetStorage,
{
type Item = u8;
#[inline]
fn next(&mut self) -> Option<u8> {
if self.value == T::from(0) {
None
} else {
let trailing_zeros = self.value.trailing_zeros();
let elem = self.index + trailing_zeros;
self.index += trailing_zeros + 1;
self.value = self.value >> (trailing_zeros + 1);
Some(elem)
}
}
}