Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 71 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::{
vec,
vec::Vec,
vec::{Vec, IntoIter as VecIntoIter},
};

#[cfg(not(feature = "std"))]
Expand All @@ -34,6 +34,8 @@ use std::fmt::{Display, Error, Formatter, Binary};
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Index};
use std::cmp::{Ord, Ordering};
use std::iter::{Chain, FromIterator};
#[cfg(feature = "std")]
use std::vec::IntoIter as VecIntoIter;
pub use range::IndexRange;

const BITS: usize = 32;
Expand Down Expand Up @@ -312,6 +314,21 @@ impl FixedBitSet
}
}

/// Iterates over all enabled bits, taking ownership of the set.
///
/// Iterator element is the index of the `1` bit, type `usize`.
#[inline]
pub fn into_ones(self) -> IntoOnes {
let mut remaining_blocks = self.data.into_iter();
let current_block = remaining_blocks.next().unwrap_or(0);
IntoOnes {
current_bit_idx: 0,
current_block_idx: 0,
current_block,
remaining_blocks
}
}

/// Returns a lazy iterator over the intersection of two `FixedBitSet`s
pub fn intersection<'a>(&'a self, other: &'a FixedBitSet) -> Intersection<'a>
{
Expand Down Expand Up @@ -631,6 +648,55 @@ impl<'a> Iterator for Ones<'a> {
}
}

/// An iterator producing the indices of the set bit in a set.
///
/// This struct is created by the [`FixedBitSet::into_ones`] method.
pub struct IntoOnes {
current_bit_idx: usize,
current_block_idx: usize,
remaining_blocks: VecIntoIter<Block>,
current_block: Block
}

impl Iterator for IntoOnes {
type Item = usize; // the bit position of the '1'

#[inline]
fn next(&mut self) -> Option<Self::Item> {
let mut block = self.current_block;
let mut idx = self.current_bit_idx;

loop {
loop {
if (block & 1) == 1 {
self.current_block = block >> 1;
self.current_bit_idx = idx + 1;
return Some(idx);
}
// reordering the two lines below makes a huge (2x) difference in performance!
block = block >> 1;
idx += 1;
if block == 0 {
break;
}
}

// go to next block
match self.remaining_blocks.next() {
Some(next_block) => {
self.current_block_idx += 1;
idx = self.current_block_idx * BITS;
block = next_block;
}
None => {
// last block => done
return None;
}
}
}
}
}

impl Clone for FixedBitSet
{
#[inline]
Expand Down Expand Up @@ -927,6 +993,10 @@ fn ones() {
let ones: Vec<_> = fb.ones().collect();

assert_eq!(vec![7, 11, 12, 35, 40, 50, 77, 95, 99], ones);

let ones: Vec<_> = fb.into_ones().collect();

assert_eq!(vec![7, 11, 12, 35, 40, 50, 77, 95, 99], ones);
}

#[test]
Expand Down