fixedbitset

repository·master·Indexed 41 days ago

https://github.com/petgraph/fixedbitset

A high-performance, fixed-size bitset container for Rust, optimized for set operations and minimal memory overhead. Version 0.5.7 provides efficient management of bit sets with support for union, intersection, and difference operations, SIMD acceleration on AVX builds, and iterators for set and cleared bits.

Tokens
3.2K
Snippets
9
Records
14
Agent score
2%

What's inside fixedbitset

  1. Overview of fixedbitset

    master
    fixedbitset is a simple, fixed-size bitset container for Rust. It provides an efficient way to manage sets of bits, offering various set operations (union, intersection, difference, etc.), iterators for both set bits (ones) and cleared bits (zeros), and support for SIMD acceleration on AVX builds. It is designed to have minimal stack overhead, comparable to a Vec.
  2. Use IndexRange for bitset range operations

    master

    The IndexRange<T> trait allows you to use standard Rust range syntax (e.g., .., a.., ..b, or a..b) in operations that require defining a range of indices. The trait provides methods to retrieve the start (inclusive) and end (exclusive) bounds of the range.

    Supported range types via the IndexRange trait:

    • RangeFull (..): Both start() and end() return None.
    • RangeFrom<T> (a..): start() returns Some(a), end() returns None.
    • RangeTo<T> (..b): start() returns None, end() returns Some(b).
    • Range<T> (a..b): start() returns Some(a), end() returns Some(b).
    use core::ops::{Range, RangeFrom, RangeFull, RangeTo};
    
    // Example of how the trait behaves with different range syntaxes:
    let full = ..;
    let from = 5..;
    let to = ..10;
    let both = 5..10;
    
    // The trait provides access to bounds:
    // full.start() -> None, full.end() -> None
    // from.start() -> Some(5), from.end() -> None
    // to.start() -> None, to.end() -> Some(10)
    // both.start() -> Some(5), both.end() -> Some(10)
  3. Modify bits in a FixedBitSet

    master

    Use the following methods to manipulate individual bits or ranges of bits:

    Individual Bits

    • insert(bit): Enables the bit at the specified index. Panics if the index is out of bounds.
    • remove(bit): Disables the bit at the specified index. Panics if the index is out of bounds.
    • set(bit, enabled): Sets the bit to true or false. Panics if the index is out of bounds.
    • toggle(bit): Inverts the state of the bit. Panics if the index is out of bounds.
    • put(bit): Enables the bit and returns its previous value. Panics if the index is out of bounds.
    • copy_bit(from, to): Copies the state of from to to. Panics if to is out of bounds.

    Ranges

    • insert_range(range): Enables all bits in the specified range.
    • remove_range(range): Disables all bits in the specified range.
    • toggle_range(range): Inverts all bits in the specified range.
    • set_range(range, enabled): Sets all bits in the range to the provided enabled state.

    Performance Note

    For performance-critical code where you have already verified bounds, use the _unchecked variants (e.g., insert_unchecked, remove_unchecked, set_unchecked, toggle_unchecked, contains_unchecked, copy_bit_unchecked). These methods are unsafe and will cause undefined behavior if the index is out of bounds.

    let mut bitset = FixedBitSet::with_capacity(10);
    
    bitset.insert(2);
    bitset.remove(5);
    bitset.set(3, true);
    bitset.toggle(0);
    
    // Range operations
    bitset.insert_range(1..5);
    bitset.remove_range(0..2);
  4. Iterate over bits in a FixedBitSet

    master

    You can iterate over the bits of a FixedBitSet using the following methods:

    • ones(): Returns an iterator over the indices of all enabled (1) bits. This is a borrowed iterator.
    • into_ones(): Consumes the FixedBitSet and returns an iterator over the indices of all enabled (1) bits.
    • zeroes(): Returns an iterator over the indices of all disabled (0) bits. This is a borrowed iterator.
    let mut bitset = FixedBitSet::with_capacity(10);
    bitset.insert(1);
    bitset.insert(5);
    
    // Iterate over set bits
    for bit in bitset.ones() {
        println!("Set bit: {}", bit);
    }
    
    // Iterate over unset bits
    for bit in bitset.zeroes() {
        println!("Unset bit: {}", bit);
    }
  5. Perform set operations between FixedBitSets

    master

    You can perform set operations using either lazy iterators or in-place mutations.

    Lazy Iterators (Non-mutating)

    These methods return iterators that yield indices of the resulting set:

    • intersection(&other): Elements in both sets.
    • union(&other): Elements in either set.
    • difference(&other): Elements in self but not in other.
    • symmetric_difference(&other): Elements in one set but not both.

    In-place Mutation

    These methods modify self directly:

    • union_with(&other): Performs a union. May increase self capacity.
    • intersect_with(&other): Performs an intersection. Capacity remains the same.
    • difference_with(&other): Performs a difference. Capacity remains the same.
    • symmetric_difference_with(&other): Performs a symmetric difference. May increase self capacity.

    Fast Counting

    If you only need the count of the resulting set without iterating, use these optimized methods which avoid allocations and mutations:

    • union_count(&other)
    • intersection_count(&other)
    • difference_count(&other)
    • symmetric_difference_count(&other)

    Additionally, is_disjoint(&other) returns true if the intersection is empty.

    let mut a = FixedBitSet::with_capacity(10);
    a.insert(1);
    a.insert(2);
    
    let mut b = FixedBitSet::with_capacity(10);
    b.insert(2);
    b.insert(3);
    
    // In-place union
    a.union_with(&b);
    
    // Fast counting
    let count = a.intersection_count(&b);
    
    // Check if disjoint
    let disjoint = a.is_disjoint(&b);
  6. Iterate over set differences, intersections, unions, and symmetric differences

    master

    The FixedBitSet API provides several methods to create iterators representing set operations between two sets. These iterators yield the bit positions (usize) of the elements in the resulting set.

    • difference(&self, other: &FixedBitSet) -> Difference: Elements in self but not in other.
    • intersection(&self, other: &FixedBitSet) -> Intersection: Elements present in both self and other.
    • union(&self, other: &FixedBitSet) -> Union: Elements present in either self or other.
    • symmetric_difference(&self, other: &FixedBitSet) -> SymmetricDifference: Elements present in one of the sets, but not both.
  7. Query bitset state and contents

    master

    Use these methods to inspect the state of a FixedBitSet:

    • len(): Returns the total number of bits (both set and unset).
    • is_empty(): Returns true if the bitset has zero length.
    • is_clear(): Returns true if all bits in the bitset are unset (0).
    • is_full(): Returns true if all bits in the bitset are set (1).
    • contains(bit): Returns true if the bit at the index is enabled. Returns false if the index is outside the capacity.
    • minimum(): Returns Some(index) of the lowest set bit, or None if no bits are set.
    • maximum(): Returns Some(index) of the highest set bit, or None if no bits are set.
    • count_ones(range): Returns the number of set bits in the specified range.
    • count_zeroes(range): Returns the number of unset bits in the specified range.
    • contains_all_in_range(range): Returns true if every bit in the range is set.
    • contains_any_in_range(range): Returns true if at least one bit in the range is set.
    let mut bitset = FixedBitSet::with_capacity(10);
    bitset.insert(2);
    bitset.insert(8);
    
    assert_eq!(bitset.len(), 10);
    assert_eq!(bitset.minimum(), Some(2));
    assert_eq!(bitset.maximum(), Some(8));
    assert_eq!(bitset.contains(2), true);
    assert_eq!(bitset.count_ones(0..10), 2);
  8. Iterate over set bits using ones() and zeroes()

    master

    To traverse the indices of bits within a single FixedBitSet:

    • ones(&self) -> Ones: An iterator producing the indices of all bits set to true.
    • zeroes(&self) -> Zeroes: An iterator producing the indices of all bits set to false (up to the set length).
  9. Create a FixedBitSet from an iterator

    master

    You can construct a FixedBitSet from an iterator of bit indices using FromIterator. This will create a set where only the indices provided by the iterator are set to true.

    let indices = vec![1, 3, 5];
    let bitset: FixedBitSet = indices.into_iter().collect();
  10. Compare sets using is_subset and is_superset

    master

    You can check the relationship between two FixedBitSet instances using subset and superset logic:

    • is_subset(&self, other: &FixedBitSet) -> bool: Returns true if other contains at least all the values in self.
    • is_superset(&self, other: &FixedBitSet) -> bool: Returns true if self contains at least all the values in other.
  11. Grow the capacity of a FixedBitSet

    master

    The FixedBitSet has a fixed capacity, but you can increase it using the grow method. When you grow the bitset, all new bits are initialized to zero.

    • grow(bits): Increases the capacity to at least bits. If bits is less than or equal to the current length, no action is taken.
    • grow_and_insert(bits): A specialized method that grows the capacity to accommodate a new bit at the specified index and inserts it in a single operation. This is more efficient than calling grow followed by insert.
    let mut bitset = FixedBitSet::with_capacity(5);
    bitset.grow(10);
    assert_eq!(bitset.len(), 10);
    
    // Grow and insert in one step
    bitset.grow_and_insert(15);
    assert_eq!(bitset.len(), 16); // Grows to accommodate index 15
  12. Access bits via indexing

    master

    You can check if a specific bit is enabled using the Index trait. Note that indexing a FixedBitSet with a value outside its current capacity will not panic; it will simply return false because bits outside the capacity are always considered disabled.

    let is_set = my_bitset[5]; // Returns true if bit 5 is enabled, false otherwise