use crate::{local_prelude::*, BitSet};
#[derive(Clone)]
struct BlockIter<T, B: BitBlock> {
head: B,
head_offset: usize,
tail: T,
}
impl<T, B: BitBlock> BlockIter<T, B>
where
T: Iterator<Item = B>,
{
fn from_blocks(mut blocks: T) -> Self {
let h = blocks.next().unwrap_or(B::zero());
BlockIter {
tail: blocks,
head: h,
head_offset: 0,
}
}
}
#[allow(clippy::multiple_inherent_impl)]
impl<B: BitBlock> BitSet<B> {
#[inline]
pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, B> {
fn or<B: BitBlock>(w1: B, w2: B) -> B {
w1 | w2
}
Union(BlockIter::from_blocks(TwoBitPositions {
set: self.bit_vec.blocks(),
other: other.bit_vec.blocks(),
merge: or,
}))
}
#[inline]
pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, B> {
fn bitand<B: BitBlock>(w1: B, w2: B) -> B {
w1 & w2
}
let min = cmp::min(self.bit_vec.len(), other.bit_vec.len());
Intersection {
iter: BlockIter::from_blocks(TwoBitPositions {
set: self.bit_vec.blocks(),
other: other.bit_vec.blocks(),
merge: bitand,
}),
n: min,
}
}
#[inline]
pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, B> {
fn diff<B: BitBlock>(w1: B, w2: B) -> B {
w1 & !w2
}
Difference(BlockIter::from_blocks(TwoBitPositions {
set: self.bit_vec.blocks(),
other: other.bit_vec.blocks(),
merge: diff,
}))
}
#[inline]
pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, B> {
fn bitxor<B: BitBlock>(w1: B, w2: B) -> B {
w1 ^ w2
}
SymmetricDifference(BlockIter::from_blocks(TwoBitPositions {
set: self.bit_vec.blocks(),
other: other.bit_vec.blocks(),
merge: bitxor,
}))
}
#[inline]
pub fn iter(&self) -> Iter<'_, B> {
Iter(BlockIter::from_blocks(self.bit_vec.blocks()))
}
}
#[derive(Clone)]
struct TwoBitPositions<'a, B: 'a + BitBlock> {
set: Blocks<'a, B>,
other: Blocks<'a, B>,
merge: fn(B, B) -> B,
}
#[derive(Clone)]
pub struct Iter<'a, B: 'a + BitBlock>(BlockIter<Blocks<'a, B>, B>);
#[derive(Clone)]
pub struct Union<'a, B: 'a + BitBlock>(BlockIter<TwoBitPositions<'a, B>, B>);
#[derive(Clone)]
pub struct Intersection<'a, B: 'a + BitBlock> {
iter: BlockIter<TwoBitPositions<'a, B>, B>,
n: usize,
}
#[derive(Clone)]
pub struct Difference<'a, B: 'a + BitBlock>(BlockIter<TwoBitPositions<'a, B>, B>);
#[derive(Clone)]
pub struct SymmetricDifference<'a, B: 'a + BitBlock>(BlockIter<TwoBitPositions<'a, B>, B>);
impl<T, B: BitBlock> Iterator for BlockIter<T, B>
where
T: Iterator<Item = B>,
{
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
while self.head == B::zero() {
match self.tail.next() {
Some(w) => self.head = w,
None => return None,
}
self.head_offset += B::bits();
}
let k = (self.head & (!self.head + B::one())) - B::one();
self.head = self.head & (self.head - B::one());
Some(self.head_offset + B::count_ones(k))
}
fn count(self) -> usize {
self.head.count_ones() + self.tail.map(|block| block.count_ones()).sum::<usize>()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.tail.size_hint() {
(_, Some(h)) => (0, Some((1 + h) * B::bits())),
_ => (0, None),
}
}
}
impl<B: BitBlock> Iterator for TwoBitPositions<'_, B> {
type Item = B;
fn next(&mut self) -> Option<Self::Item> {
match (self.set.next(), self.other.next()) {
(Some(a), Some(b)) => Some((self.merge)(a, b)),
(Some(a), None) => Some((self.merge)(a, B::zero())),
(None, Some(b)) => Some((self.merge)(B::zero(), b)),
_ => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (first_lower_bound, first_upper_bound) = self.set.size_hint();
let (second_lower_bound, second_upper_bound) = self.other.size_hint();
let upper_bound = first_upper_bound.zip(second_upper_bound);
let get_max = |(a, b)| cmp::max(a, b);
(
cmp::max(first_lower_bound, second_lower_bound),
upper_bound.map(get_max),
)
}
}
impl<B: BitBlock> Iterator for Iter<'_, B> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn count(self) -> usize {
self.0.count()
}
}
impl<B: BitBlock> Iterator for Union<'_, B> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn count(self) -> usize {
self.0.count()
}
}
impl<B: BitBlock> Iterator for Intersection<'_, B> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
if self.n != 0 {
self.n -= 1;
self.iter.next()
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.n))
}
#[inline]
fn count(self) -> usize {
self.iter.count()
}
}
impl<B: BitBlock> Iterator for Difference<'_, B> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn count(self) -> usize {
self.0.count()
}
}
impl<B: BitBlock> Iterator for SymmetricDifference<'_, B> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn count(self) -> usize {
self.0.count()
}
}
impl<'a, B: BitBlock> IntoIterator for &'a BitSet<B> {
type Item = usize;
type IntoIter = Iter<'a, B>;
fn into_iter(self) -> Iter<'a, B> {
self.iter()
}
}