mod fixed;
mod growing;
mod tiny;
use std::iter::repeat;
pub use fixed::FixedBitmapU64;
pub use growing::{DenseSet, GrowingBitmap};
use itertools::{EitherOrBoth, Itertools};
pub trait Bitmap: BitmapSlice {
fn new_all_zeros(len: usize) -> Self;
fn new_all_ones(len: usize) -> Self;
fn set(&mut self, index: usize) -> bool;
fn set_many(&mut self, indices: impl Iterator<Item = usize>) {
for item in indices {
self.set(item);
}
}
fn clear(&mut self, index: usize) -> bool;
fn clear_many(&mut self, indices: impl Iterator<Item = usize>) {
for item in indices {
self.clear(item);
}
}
fn and_with(&mut self, other: &impl BitmapSlice) -> bool;
fn clear_from(&mut self, other: &impl BitmapSlice) -> bool;
fn or_with(&mut self, other: &impl BitmapSlice) -> bool;
fn xor_with(&mut self, other: &impl BitmapSlice) -> bool;
fn is_all_ones(&self) -> bool;
fn is_superset_of(&self, other: &Self) -> bool;
}
pub trait ResizableBitmap {
fn resize(&mut self, new_size: usize);
}
pub trait BitmapSlice {
fn get(&self, index: usize) -> bool;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn count_overlapping_with(&self, other: &impl BitmapSlice) -> usize
where
Self: Sized,
{
self.anded_with(other)
.iter_data()
.map(|x| x.count_ones() as usize)
.sum::<usize>()
}
fn overlaps_with(&self, other: &impl BitmapSlice) -> bool
where
Self: Sized,
{
self.anded_with(other).iter_data().any(|x| x != 0)
}
fn is_all_zeros(&self) -> bool {
self.iter_data().all(|x| x == 0)
}
fn is_subset_of(&self, other: &impl BitmapSlice) -> bool {
self.iter_data()
.chain(repeat(0))
.zip(other.iter_data())
.all(|(subset, whole)| subset | whole == whole)
}
fn flipped(&self) -> Flipped<Self>
where
Self: Sized,
{
Flipped(self)
}
fn anded_with<'r, B: BitmapSlice>(&'r self, other: &'r B) -> AndWith<'r, Self, B>
where
Self: Sized,
{
AndWith {
a: self,
b: other,
}
}
fn xored_with<'r, B: BitmapSlice>(&'r self, other: &'r B) -> XorWith<'r, Self, B>
where
Self: Sized,
{
XorWith {
a: self,
b: other,
}
}
fn ored_with<'r, B: BitmapSlice>(&'r self, other: &'r B) -> OrWith<'r, Self, B>
where
Self: Sized,
{
OrWith {
a: self,
b: other,
}
}
fn cleared_from<'r, B: BitmapSlice>(&'r self, other: &'r B) -> ClearFrom<'r, Self, B>
where
Self: Sized,
{
ClearFrom {
a: self,
b: other,
}
}
fn iter_one_indices(&self) -> impl Iterator<Item = usize> + '_ {
self.iter_data().enumerate().flat_map(|(offset, item)| {
(0..64)
.filter(move |index| (item >> index) & 1 != 0)
.map(move |index| index + offset * 64)
})
}
fn iter(&self) -> impl Iterator<Item = bool> + '_ {
self.iter_data()
.flat_map(|val| (0..64).map(move |index| (val >> index) & 1 != 0))
}
fn count_ones(&self) -> usize {
self.iter_data().map(|x| x.count_ones() as usize).sum::<usize>()
}
fn count_zeros(&self) -> usize {
self.iter_data().map(|x| x.count_zeros() as usize).sum::<usize>() - (64 - self.len() % 64)
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_;
}
pub trait BitmapSliceMut: BitmapSlice {
fn clear(&mut self) {
self.modify(|_| 0);
}
fn copy_from(&mut self, other: &impl BitmapSlice) {
assert_eq!(self.len(), other.len());
let mut iter = other.iter_data();
self.modify(|_| iter.next().expect("Should succeed because self.len() == other.len()"));
}
fn clear_from(&mut self, other: &impl BitmapSlice) {
let mut iter = other.iter_data();
self.modify(|d| d & !iter.next().unwrap_or(0));
}
fn or_with(&mut self, other: &impl BitmapSlice) {
let mut iter = other.iter_data();
self.modify(|d| d | iter.next().unwrap_or(0));
}
fn modify(&mut self, f: impl FnMut(u64) -> u64);
}
#[derive(Copy, Clone)]
pub struct AndWith<'r, A, B> {
a: &'r A,
b: &'r B,
}
impl<A: BitmapSlice, B: BitmapSlice> BitmapSlice for AndWith<'_, A, B> {
fn get(&self, index: usize) -> bool {
self.a.get(index) && self.b.get(index)
}
fn len(&self) -> usize {
self.a.len().min(self.b.len())
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_ {
self.a.iter_data().zip(self.b.iter_data()).map(|(a, b)| a & b)
}
}
#[derive(Copy, Clone)]
pub struct OrWith<'r, A, B> {
a: &'r A,
b: &'r B,
}
impl<A: BitmapSlice, B: BitmapSlice> BitmapSlice for OrWith<'_, A, B> {
fn get(&self, index: usize) -> bool {
self.a.get(index) || self.b.get(index)
}
fn len(&self) -> usize {
self.a.len().max(self.b.len())
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_ {
self.a.iter_data().zip_longest(self.b.iter_data()).map(|v| match v {
EitherOrBoth::Both(a, b) => a | b,
EitherOrBoth::Left(x) | EitherOrBoth::Right(x) => x,
})
}
}
#[derive(Copy, Clone)]
pub struct XorWith<'r, A, B> {
a: &'r A,
b: &'r B,
}
impl<A: BitmapSlice, B: BitmapSlice> BitmapSlice for XorWith<'_, A, B> {
fn get(&self, index: usize) -> bool {
self.a.get(index) ^ self.b.get(index)
}
fn len(&self) -> usize {
self.a.len().max(self.b.len())
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_ {
self.a.iter_data().zip_longest(self.b.iter_data()).map(|v| match v {
EitherOrBoth::Both(a, b) => a ^ b,
EitherOrBoth::Left(x) | EitherOrBoth::Right(x) => x,
})
}
}
#[derive(Copy, Clone)]
pub struct ClearFrom<'r, A, B> {
a: &'r A,
b: &'r B,
}
impl<A: BitmapSlice, B: BitmapSlice> BitmapSlice for ClearFrom<'_, A, B> {
fn get(&self, index: usize) -> bool {
self.a.get(index) && !self.b.get(index)
}
fn len(&self) -> usize {
self.a.len()
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_ {
self.a
.iter_data()
.zip(self.b.iter_data().chain(repeat(0)))
.map(|(a, b)| a & !b)
}
}
#[derive(Copy, Clone)]
pub struct Flipped<'r, A>(&'r A);
impl<A: BitmapSlice> BitmapSlice for Flipped<'_, A> {
fn get(&self, index: usize) -> bool {
!self.0.get(index)
}
fn len(&self) -> usize {
self.0.len()
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_ {
let mut remaining = self.len();
self.0.iter_data().map(move |x| {
if remaining >= 64 {
remaining -= 64;
!x
} else {
!x & ((1 << remaining) - 1)
}
})
}
}
pub struct AllOnes;
pub struct AllZeros;
impl BitmapSlice for AllOnes {
fn get(&self, _index: usize) -> bool {
true
}
fn len(&self) -> usize {
usize::MAX
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_ {
repeat(u64::MAX)
}
}
impl BitmapSlice for AllZeros {
fn get(&self, _index: usize) -> bool {
false
}
fn len(&self) -> usize {
usize::MAX
}
fn iter_data(&self) -> impl Iterator<Item = u64> + '_ {
repeat(0)
}
}