#![deny(missing_docs, missing_copy_implementations, missing_debug_implementations)]
#[cfg(test)]
mod tests;
mod store;
pub use store::{Iter as Blocks, IntoIter as IntoBlocks};
use std::{cmp, fmt, iter, ops, usize};
use std::iter::FromIterator;
use store::BlockStore;
pub type Id = usize;
pub type Block = u32;
pub const BITS: usize = 32;
#[inline]
fn mask(bit: usize) -> Block {
(1 as Block) << bit
}
#[inline]
fn ceil_div(n: usize, k: usize) -> usize {
if n % k == 0 { n / k } else { n / k + 1 }
}
#[inline]
fn pop_lsb(n: &mut Block) -> usize {
let idx = n.trailing_zeros() as usize;
*n &= *n - 1;
idx
}
pub struct IdSet {
blocks: BlockStore,
len: usize,
}
impl IdSet {
#[inline]
pub fn new() -> Self {
IdSet {
blocks: BlockStore::new(),
len: 0,
}
}
#[inline]
pub fn new_filled(n: usize) -> Self {
let (nwords, nbits) = (n / BITS, n % BITS);
let blocks: BlockStore = if nbits != 0 {
iter::repeat(!0)
.take(nwords)
.chain(iter::once(mask(nbits) - 1))
.collect()
} else {
iter::repeat(!0).take(nwords).collect()
};
IdSet { blocks, len: n }
}
#[inline]
pub fn with_capacity(n: usize) -> Self {
IdSet {
blocks: BlockStore::with_capacity(ceil_div(n, BITS)),
len: 0,
}
}
#[cfg(test)]
fn from_bytes(bytes: &[Block]) -> Self {
let blocks = BlockStore::from_iter(bytes);
let len = bytes
.iter()
.map(|&word| word.count_ones() as usize)
.sum();
IdSet { blocks, len }
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn capacity(&self) -> usize {
self.blocks.capacity().saturating_mul(BITS)
}
#[inline]
pub fn reserve(&mut self, cap: usize) {
self.blocks.reserve(ceil_div(cap, BITS));
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.blocks.shrink_to_fit();
}
#[inline]
pub fn clear(&mut self) {
self.blocks.clear();
self.len = 0;
}
#[inline]
pub fn insert(&mut self, id: Id) -> bool {
let (word, bit) = (id / BITS, id % BITS);
let mask = mask(bit);
if word < self.blocks.len() {
if (self.blocks[word] & mask) == 0 {
self.blocks[word] |= mask;
self.len += 1;
true
} else {
false
}
} else {
self.blocks.resize(word + 1);
self.blocks[word] = mask;
self.len += 1;
true
}
}
#[inline]
pub fn remove(&mut self, id: Id) -> bool {
let (word, bit) = (id / BITS, id % BITS);
let mask = mask(bit);
if word < self.blocks.len() {
if (self.blocks[word] & mask) != 0 {
self.blocks[word] &= !mask;
self.len -= 1;
true
} else {
false
}
} else {
false
}
}
#[inline]
pub fn contains(&self, id: Id) -> bool {
let (word, bit) = (id / BITS, id % BITS);
if word < self.blocks.len() {
(self.blocks[word] & mask(bit)) != 0
} else {
false
}
}
#[inline]
pub fn retain<F: FnMut(Id) -> bool>(&mut self, mut pred: F) {
let mut idx = 0;
for word in self.blocks.iter_mut() {
let mut block = *word;
while block != 0 {
let id = idx + block.trailing_zeros() as usize;
let mask = block - 1;
if !pred(id) {
self.len -= 1;
*word &= mask;
}
block &= mask;
}
idx += BITS;
}
}
#[inline]
pub fn as_blocks(&self) -> &[Block] {
&self.blocks
}
#[inline]
pub fn iter(&self) -> Iter {
Iter {
inner: IdIter::new(self.blocks.iter()),
len: self.len,
}
}
#[inline]
pub fn blocks(&self) -> Blocks {
self.blocks.iter()
}
#[inline]
pub fn into_blocks(self) -> IntoBlocks {
self.blocks.into_iter()
}
#[inline]
pub fn union<I>(&self, other: I) -> BlockIter<Union<Blocks, I::Blocks>>
where I: IntoBlockIterator
{
self | other
}
#[inline]
pub fn intersection<I>(&self, other: I) -> BlockIter<Intersection<Blocks, I::Blocks>>
where I: IntoBlockIterator
{
self & other
}
#[inline]
pub fn difference<I>(&self, other: I) -> BlockIter<Difference<Blocks, I::Blocks>>
where I: IntoBlockIterator
{
self - other
}
#[inline]
pub fn symmetric_difference<I>(&self,
other: I)
-> BlockIter<SymmetricDifference<Blocks, I::Blocks>>
where I: IntoBlockIterator
{
self ^ other
}
#[inline]
pub fn into_union<I>(self, other: I) -> BlockIter<Union<IntoBlocks, I::Blocks>>
where I: IntoBlockIterator
{
self | other
}
#[inline]
pub fn into_intersection<I>(self, other: I) -> BlockIter<Intersection<IntoBlocks, I::Blocks>>
where I: IntoBlockIterator
{
self & other
}
#[inline]
pub fn into_difference<I>(self, other: I) -> BlockIter<Difference<IntoBlocks, I::Blocks>>
where I: IntoBlockIterator
{
self - other
}
#[inline]
pub fn into_symmetric_difference<I>(self,
other: I)
-> BlockIter<SymmetricDifference<IntoBlocks, I::Blocks>>
where I: IntoBlockIterator
{
self ^ other
}
#[inline]
pub fn inplace_union<I>(&mut self, other: I)
where I: IntoBlockIterator
{
*self |= other
}
#[inline]
pub fn inplace_intersection<I>(&mut self, other: I)
where I: IntoBlockIterator
{
*self &= other
}
#[inline]
pub fn inplace_difference<I>(&mut self, other: I)
where I: IntoBlockIterator
{
*self -= other
}
#[inline]
pub fn inplace_symmetric_difference<I>(&mut self, other: I)
where I: IntoBlockIterator
{
*self ^= other
}
#[inline]
pub fn is_disjoint(&self, other: &Self) -> bool {
self.len().saturating_add(other.len()) < cmp::max(self.capacity(), other.capacity()) &&
self.intersection(other).into_iter().count() == 0
}
#[inline]
pub fn is_superset(&self, other: &Self) -> bool {
!other.is_subset(self)
}
#[inline]
pub fn is_subset(&self, other: &Self) -> bool {
self.len() <= other.len() && self.difference(other).into_iter().count() == 0
}
}
impl Clone for IdSet {
#[inline]
fn clone(&self) -> Self {
IdSet {
blocks: self.blocks.clone(),
len: self.len,
}
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.blocks.clone_from(&source.blocks);
self.len = source.len;
}
}
impl fmt::Debug for IdSet {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{")?;
let mut iter = self.iter();
if let Some(id) = iter.next() {
write!(f, "{:?}", id)?;
for id in iter {
write!(f, ", {:?}", id)?;
}
}
write!(f, "}}")
}
}
impl Default for IdSet {
#[inline]
fn default() -> Self {
IdSet::new()
}
}
impl Eq for IdSet {}
impl PartialEq for IdSet {
fn eq(&self, other: &Self) -> bool {
if self.len != other.len {
return false;
}
let (mut lhs, mut rhs) = (self.blocks.iter(), other.blocks.iter());
loop {
match (lhs.next(), rhs.next()) {
(Some(l), Some(r)) => {
if l != r {
return false;
}
}
(None, None) => return true,
(Some(l), None) => return l == 0 && lhs.all(|block| block == 0),
(None, Some(r)) => return r == 0 && rhs.all(|block| block == 0),
}
}
}
}
impl Extend<Id> for IdSet {
#[inline]
fn extend<I: IntoIterator<Item = Id>>(&mut self, iter: I) {
for id in iter {
self.insert(id);
}
}
}
impl FromIterator<Id> for IdSet {
#[inline]
fn from_iter<I: IntoIterator<Item = Id>>(iter: I) -> Self {
let mut set = IdSet::new();
for id in iter {
set.insert(id);
}
set
}
}
impl<'a> IntoIterator for &'a IdSet {
type Item = Id;
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Clone, Debug)]
pub struct Iter<'a> {
inner: IdIter<Blocks<'a>>,
len: usize,
}
impl<'a> Iterator for Iter<'a> {
type Item = Id;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let id = self.inner.next();
if id.is_some() {
self.len -= 1;
}
id
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a> ExactSizeIterator for Iter<'a> {
#[inline]
fn len(&self) -> usize {
self.len
}
}
impl IntoIterator for IdSet {
type Item = Id;
type IntoIter = IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
let len = self.len;
IntoIter {
inner: IdIter::new(self.blocks.into_iter()),
len,
}
}
}
#[derive(Clone, Debug)]
pub struct IntoIter {
inner: IdIter<IntoBlocks>,
len: usize,
}
impl Iterator for IntoIter {
type Item = Id;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let id = self.inner.next();
if id.is_some() {
self.len -= 1;
}
id
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl ExactSizeIterator for IntoIter {
#[inline]
fn len(&self) -> usize {
self.len
}
}
#[derive(Clone, Debug)]
pub struct IdIter<B> {
blocks: B,
word: Block,
idx: usize,
}
impl<B> IdIter<B>
where B: ExactSizeIterator<Item = Block>
{
pub fn new<I: IntoBlockIterator<Blocks = B>>(iter: I) -> Self {
let mut blocks = iter.into_block_iter().into_inner();
let word = blocks.next().unwrap_or(0);
IdIter {
blocks,
word,
idx: 0,
}
}
}
impl<B> Iterator for IdIter<B>
where B: ExactSizeIterator<Item = Block>
{
type Item = Id;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while self.word == 0 {
match self.blocks.next() {
Some(word) => self.word = word,
None => return None,
}
self.idx += BITS;
}
Some(self.idx + pop_lsb(&mut self.word))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let ones = self.word.count_ones() as usize;
(ones, Some(self.blocks.len().saturating_mul(BITS).saturating_add(ones)))
}
}
#[derive(Clone, Debug)]
pub struct BlockIter<B> {
inner: B,
}
impl<B> BlockIter<B> {
pub fn into_inner(self) -> B {
self.inner
}
}
impl<B> BlockIter<B>
where B: ExactSizeIterator<Item = Block>
{
pub fn new(inner: B) -> Self {
BlockIter { inner }
}
#[inline]
pub fn collect<T>(self) -> T
where T: iter::FromIterator<Id>
{
self.into_iter().collect()
}
#[inline]
pub fn into_set(self) -> IdSet {
let mut len = 0;
let blocks = self.inner.inspect(|&block| len += block.count_ones() as usize).collect();
IdSet {
blocks, len,
}
}
#[inline]
pub fn union<I>(self, other: I) -> BlockIter<Union<B, I::Blocks>>
where I: IntoBlockIterator
{
self | other
}
#[inline]
pub fn intersection<I>(self, other: I) -> BlockIter<Intersection<B, I::Blocks>>
where I: IntoBlockIterator
{
self & other
}
#[inline]
pub fn difference<I>(self, other: I) -> BlockIter<Difference<B, I::Blocks>>
where I: IntoBlockIterator
{
self - other
}
#[inline]
pub fn symmetric_difference<I>(self, other: I) -> BlockIter<SymmetricDifference<B, I::Blocks>>
where I: IntoBlockIterator
{
self ^ other
}
}
impl<B> IntoIterator for BlockIter<B>
where B: ExactSizeIterator<Item = Block>
{
type Item = Id;
type IntoIter = IdIter<B>;
fn into_iter(self) -> Self::IntoIter {
IdIter::new(self.inner)
}
}
pub trait IntoBlockIterator {
type Blocks: ExactSizeIterator<Item = Block>;
fn into_block_iter(self) -> BlockIter<Self::Blocks>;
}
impl<B> IntoBlockIterator for B
where B: ExactSizeIterator<Item = Block>
{
type Blocks = B;
fn into_block_iter(self) -> BlockIter<Self::Blocks> {
BlockIter { inner: self }
}
}
impl<B> IntoBlockIterator for BlockIter<B>
where B: ExactSizeIterator<Item = Block>
{
type Blocks = B;
#[inline]
fn into_block_iter(self) -> BlockIter<Self::Blocks> {
self
}
}
impl<'a> IntoBlockIterator for &'a IdSet {
type Blocks = Blocks<'a>;
#[inline]
fn into_block_iter(self) -> BlockIter<Self::Blocks> {
self.blocks().into_block_iter()
}
}
impl IntoBlockIterator for IdSet {
type Blocks = IntoBlocks;
#[inline]
fn into_block_iter(self) -> BlockIter<Self::Blocks> {
self.into_blocks().into_block_iter()
}
}
impl<B, I> ops::BitAnd<I> for BlockIter<B>
where B: ExactSizeIterator<Item = Block>,
I: IntoBlockIterator
{
type Output = BlockIter<Intersection<B, I::Blocks>>;
#[inline]
fn bitand(self, other: I) -> Self::Output {
BlockIter {
inner: Intersection {
left: self.inner,
right: other.into_block_iter().inner,
},
}
}
}
impl<B, I> ops::BitOr<I> for BlockIter<B>
where B: ExactSizeIterator<Item = Block>,
I: IntoBlockIterator
{
type Output = BlockIter<Union<B, I::Blocks>>;
#[inline]
fn bitor(self, other: I) -> Self::Output {
BlockIter {
inner: Union {
left: self.inner,
right: other.into_block_iter().inner,
},
}
}
}
impl<B, I> ops::BitXor<I> for BlockIter<B>
where B: ExactSizeIterator<Item = Block>,
I: IntoBlockIterator
{
type Output = BlockIter<SymmetricDifference<B, I::Blocks>>;
#[inline]
fn bitxor(self, other: I) -> Self::Output {
BlockIter {
inner: SymmetricDifference {
left: self.inner,
right: other.into_block_iter().inner,
},
}
}
}
impl<B, I> ops::Sub<I> for BlockIter<B>
where B: ExactSizeIterator<Item = Block>,
I: IntoBlockIterator
{
type Output = BlockIter<Difference<B, I::Blocks>>;
#[inline]
fn sub(self, other: I) -> Self::Output {
BlockIter {
inner: Difference {
left: self.inner,
right: other.into_block_iter().inner,
},
}
}
}
impl<'a, I> ops::BitAnd<I> for &'a IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<Intersection<Blocks<'a>, I::Blocks>>;
#[inline]
fn bitand(self, other: I) -> Self::Output {
self.into_block_iter() & other
}
}
impl<'a, I> ops::BitOr<I> for &'a IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<Union<Blocks<'a>, I::Blocks>>;
#[inline]
fn bitor(self, other: I) -> Self::Output {
self.into_block_iter() | other
}
}
impl<'a, I> ops::BitXor<I> for &'a IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<SymmetricDifference<Blocks<'a>, I::Blocks>>;
#[inline]
fn bitxor(self, other: I) -> Self::Output {
self.into_block_iter() ^ other
}
}
impl<'a, I> ops::Sub<I> for &'a IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<Difference<Blocks<'a>, I::Blocks>>;
#[inline]
fn sub(self, other: I) -> Self::Output {
self.into_block_iter() - other
}
}
impl<I> ops::BitAnd<I> for IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<Intersection<IntoBlocks, I::Blocks>>;
#[inline]
fn bitand(self, other: I) -> Self::Output {
self.into_block_iter() & other
}
}
impl<I> ops::BitOr<I> for IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<Union<IntoBlocks, I::Blocks>>;
#[inline]
fn bitor(self, other: I) -> Self::Output {
self.into_block_iter() | other
}
}
impl<I> ops::BitXor<I> for IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<SymmetricDifference<IntoBlocks, I::Blocks>>;
#[inline]
fn bitxor(self, other: I) -> Self::Output {
self.into_block_iter() ^ other
}
}
impl<I> ops::Sub<I> for IdSet
where I: IntoBlockIterator
{
type Output = BlockIter<Difference<IntoBlocks, I::Blocks>>;
#[inline]
fn sub(self, other: I) -> Self::Output {
self.into_block_iter() - other
}
}
impl<I> ops::BitAndAssign<I> for IdSet
where I: IntoBlockIterator
{
#[inline]
fn bitand_assign(&mut self, other: I) {
let blocks = other.into_block_iter().into_inner();
if blocks.len() < self.blocks.len() {
for block in self.blocks.drain(blocks.len()) {
self.len -= block.count_ones() as usize;
}
}
for (lblock, rblock) in self.blocks.iter_mut().zip(blocks) {
self.len -= (*lblock & !rblock).count_ones() as usize;
*lblock &= rblock;
}
}
}
impl<I> ops::BitOrAssign<I> for IdSet
where I: IntoBlockIterator
{
#[inline]
fn bitor_assign(&mut self, other: I) {
let mut blocks = other.into_block_iter().into_inner();
for lblock in self.blocks.iter_mut() {
if let Some(rblock) = blocks.next() {
self.len += (rblock & !*lblock).count_ones() as usize;
*lblock |= rblock;
} else {
return;
}
}
let len = &mut self.len;
self.blocks
.extend(blocks.inspect(|block| *len += block.count_ones() as usize));
}
}
impl<I> ops::BitXorAssign<I> for IdSet
where I: IntoBlockIterator
{
#[inline]
fn bitxor_assign(&mut self, other: I) {
let mut blocks = other.into_block_iter().into_inner();
for lblock in self.blocks.iter_mut() {
if let Some(rblock) = blocks.next() {
self.len -= lblock.count_ones() as usize;
*lblock ^= rblock;
self.len += lblock.count_ones() as usize;
} else {
return;
}
}
let len = &mut self.len;
self.blocks
.extend(blocks.inspect(|block| *len += block.count_ones() as usize));
}
}
impl<I> ops::SubAssign<I> for IdSet
where I: IntoBlockIterator
{
#[inline]
fn sub_assign(&mut self, other: I) {
for (lblock, rblock) in self.blocks
.iter_mut()
.zip(other.into_block_iter().into_inner()) {
self.len -= (*lblock & rblock).count_ones() as usize;
*lblock &= !rblock;
}
}
}
#[derive(Clone, Debug)]
pub struct Intersection<L, R> {
left: L,
right: R,
}
impl<L, R> Iterator for Intersection<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
type Item = Block;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let (Some(l), Some(r)) = (self.left.next(), self.right.next()) {
Some(l & r)
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<L, R> ExactSizeIterator for Intersection<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
#[inline]
fn len(&self) -> usize {
cmp::min(self.left.len(), self.right.len())
}
}
#[derive(Clone, Debug)]
pub struct Union<L, R> {
left: L,
right: R,
}
impl<L, R> Iterator for Union<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
type Item = Block;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match (self.left.next(), self.right.next()) {
(Some(l), Some(r)) => Some(l | r),
(Some(l), None) => Some(l),
(None, Some(r)) => Some(r),
(None, None) => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<L, R> ExactSizeIterator for Union<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
#[inline]
fn len(&self) -> usize {
cmp::max(self.left.len(), self.right.len())
}
}
#[derive(Clone, Debug)]
pub struct SymmetricDifference<L, R> {
left: L,
right: R,
}
impl<L, R> Iterator for SymmetricDifference<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
type Item = Block;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match (self.left.next(), self.right.next()) {
(Some(l), Some(r)) => Some(l ^ r),
(Some(l), None) => Some(l),
(None, Some(r)) => Some(r),
(None, None) => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<L, R> ExactSizeIterator for SymmetricDifference<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
#[inline]
fn len(&self) -> usize {
cmp::max(self.left.len(), self.right.len())
}
}
#[derive(Clone, Debug)]
pub struct Difference<L, R> {
left: L,
right: R,
}
impl<L, R> Iterator for Difference<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
type Item = Block;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.left
.next()
.map(|l| l & !self.right.next().unwrap_or(0))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<L, R> ExactSizeIterator for Difference<L, R>
where L: ExactSizeIterator<Item = Block>,
R: ExactSizeIterator<Item = Block>
{
#[inline]
fn len(&self) -> usize {
self.left.len()
}
}