use crate::{local_prelude::*, BitSet}; #[derive(Clone)] struct BlockIter { head: B, head_offset: usize, tail: T, } impl BlockIter where T: Iterator, { 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 BitSet { /// Iterator over each usize stored in `self` union `other`. /// See [`union_with`] for an efficient in-place version. /// /// # Examples /// /// ``` /// use bit_set::BitSet; /// /// let a = BitSet::from_bytes(&[0b01101000]); /// let b = BitSet::from_bytes(&[0b10100000]); /// /// // Print 0, 1, 2, 4 in arbitrary order /// for x in a.union(&b) { /// println!("{}", x); /// } /// ``` /// /// [`union_with`]: Self::union_with #[inline] pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, B> { fn or(w1: B, w2: B) -> B { w1 | w2 } Union(BlockIter::from_blocks(TwoBitPositions { set: self.bit_vec.blocks(), other: other.bit_vec.blocks(), merge: or, })) } /// Iterator over each usize stored in `self` intersect `other`. /// See [`intersect_with`] for an efficient in-place version. /// /// # Examples /// /// ``` /// use bit_set::BitSet; /// /// let a = BitSet::from_bytes(&[0b01101000]); /// let b = BitSet::from_bytes(&[0b10100000]); /// /// // Print 2 /// for x in a.intersection(&b) { /// println!("{}", x); /// } /// ``` /// /// [`intersect_with`]: Self::intersect_with #[inline] pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, B> { fn bitand(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, } } /// Iterator over each usize stored in the `self` setminus `other`. /// See [`difference_with`] for an efficient in-place version. /// /// # Examples /// /// ``` /// use bit_set::BitSet; /// /// let a = BitSet::from_bytes(&[0b01101000]); /// let b = BitSet::from_bytes(&[0b10100000]); /// /// // Print 1, 4 in arbitrary order /// for x in a.difference(&b) { /// println!("{}", x); /// } /// /// // Note that difference is not symmetric, /// // and `b - a` means something else. /// // This prints 0 /// for x in b.difference(&a) { /// println!("{}", x); /// } /// ``` /// /// [`difference_with`]: Self::difference_with #[inline] pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, B> { fn diff(w1: B, w2: B) -> B { w1 & !w2 } Difference(BlockIter::from_blocks(TwoBitPositions { set: self.bit_vec.blocks(), other: other.bit_vec.blocks(), merge: diff, })) } /// Iterator over each usize stored in the symmetric difference of `self` and `other`. /// See [`symmetric_difference_with`] for an efficient in-place version. /// /// # Examples /// /// ``` /// use bit_set::BitSet; /// /// let a = BitSet::from_bytes(&[0b01101000]); /// let b = BitSet::from_bytes(&[0b10100000]); /// /// // Print 0, 1, 4 in arbitrary order /// for x in a.symmetric_difference(&b) { /// println!("{}", x); /// } /// ``` /// /// [`symmetric_difference_with`]: Self::symmetric_difference_with #[inline] pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, B> { fn bitxor(w1: B, w2: B) -> B { w1 ^ w2 } SymmetricDifference(BlockIter::from_blocks(TwoBitPositions { set: self.bit_vec.blocks(), other: other.bit_vec.blocks(), merge: bitxor, })) } /// Iterator over each usize stored in the `BitSet`. /// /// # Examples /// /// ``` /// use bit_set::BitSet; /// /// let s = BitSet::from_bytes(&[0b01001010]); /// /// // Print 1, 4, 6 in arbitrary order /// for x in s.iter() { /// println!("{}", x); /// } /// ``` #[inline] pub fn iter(&self) -> Iter<'_, B> { Iter(BlockIter::from_blocks(self.bit_vec.blocks())) } } /// An iterator combining two `BitSet` iterators. #[derive(Clone)] struct TwoBitPositions<'a, B: 'a + BitBlock> { set: Blocks<'a, B>, other: Blocks<'a, B>, merge: fn(B, B) -> B, } /// An iterator for `BitSet`. #[derive(Clone)] pub struct Iter<'a, B: 'a + BitBlock>(BlockIter, B>); #[derive(Clone)] pub struct Union<'a, B: 'a + BitBlock>(BlockIter, B>); #[derive(Clone)] pub struct Intersection<'a, B: 'a + BitBlock> { iter: BlockIter, B>, // as an optimization, we compute the maximum possible // number of elements in the intersection, and count it // down as we return elements. If we reach zero, we can // stop. n: usize, } #[derive(Clone)] pub struct Difference<'a, B: 'a + BitBlock>(BlockIter, B>); #[derive(Clone)] pub struct SymmetricDifference<'a, B: 'a + BitBlock>(BlockIter, B>); impl Iterator for BlockIter where T: Iterator, { type Item = usize; fn next(&mut self) -> Option { while self.head == B::zero() { match self.tail.next() { Some(w) => self.head = w, None => return None, } self.head_offset += B::bits(); } // from the current block, isolate the // LSB and subtract 1, producing k: // a block with a number of set bits // equal to the index of the LSB let k = (self.head & (!self.head + B::one())) - B::one(); // update block, removing the LSB self.head = self.head & (self.head - B::one()); // return offset + (index of LSB) Some(self.head_offset + B::count_ones(k)) } fn count(self) -> usize { self.head.count_ones() + self.tail.map(|block| block.count_ones()).sum::() } #[inline] fn size_hint(&self) -> (usize, Option) { match self.tail.size_hint() { (_, Some(h)) => (0, Some((1 + h) * B::bits())), _ => (0, None), } } } impl Iterator for TwoBitPositions<'_, B> { type Item = B; fn next(&mut self) -> Option { 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) { 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 Iterator for Iter<'_, B> { type Item = usize; #[inline] fn next(&mut self) -> Option { self.0.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn count(self) -> usize { self.0.count() } } impl Iterator for Union<'_, B> { type Item = usize; #[inline] fn next(&mut self) -> Option { self.0.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn count(self) -> usize { self.0.count() } } impl Iterator for Intersection<'_, B> { type Item = usize; #[inline] fn next(&mut self) -> Option { if self.n != 0 { self.n -= 1; self.iter.next() } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { // We could invoke self.iter.size_hint() and incorporate that into the hint. // In practice, that does not seem worthwhile because the lower bound will // always be zero and the upper bound could only possibly less then n in a // partially iterated iterator. However, it makes little sense ask for size_hint // in a partially iterated iterator, so it did not seem worthwhile. (0, Some(self.n)) } #[inline] fn count(self) -> usize { self.iter.count() } } impl Iterator for Difference<'_, B> { type Item = usize; #[inline] fn next(&mut self) -> Option { self.0.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn count(self) -> usize { self.0.count() } } impl Iterator for SymmetricDifference<'_, B> { type Item = usize; #[inline] fn next(&mut self) -> Option { self.0.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn count(self) -> usize { self.0.count() } } impl<'a, B: BitBlock> IntoIterator for &'a BitSet { type Item = usize; type IntoIter = Iter<'a, B>; fn into_iter(self) -> Iter<'a, B> { self.iter() } }