use std::ops::{BitAnd, BitOr, BitXor, Not};
use {BitSet, BitSetLike};
#[derive(Debug)]
pub struct BitSetAnd<A: BitSetLike, B: BitSetLike>(pub A, pub B);
impl<A: BitSetLike, B: BitSetLike> BitSetLike for BitSetAnd<A, B> {
#[inline]
fn layer3(&self) -> usize {
self.0.layer3() & self.1.layer3()
}
#[inline]
fn layer2(&self, i: usize) -> usize {
self.0.layer2(i) & self.1.layer2(i)
}
#[inline]
fn layer1(&self, i: usize) -> usize {
self.0.layer1(i) & self.1.layer1(i)
}
#[inline]
fn layer0(&self, i: usize) -> usize {
self.0.layer0(i) & self.1.layer0(i)
}
}
#[derive(Debug)]
pub struct BitSetOr<A: BitSetLike, B: BitSetLike>(pub A, pub B);
impl<A: BitSetLike, B: BitSetLike> BitSetLike for BitSetOr<A, B> {
#[inline]
fn layer3(&self) -> usize {
self.0.layer3() | self.1.layer3()
}
#[inline]
fn layer2(&self, i: usize) -> usize {
self.0.layer2(i) | self.1.layer2(i)
}
#[inline]
fn layer1(&self, i: usize) -> usize {
self.0.layer1(i) | self.1.layer1(i)
}
#[inline]
fn layer0(&self, i: usize) -> usize {
self.0.layer0(i) | self.1.layer0(i)
}
}
#[derive(Debug)]
pub struct BitSetNot<A: BitSetLike>(pub A);
impl<A: BitSetLike> BitSetLike for BitSetNot<A> {
#[inline]
fn layer3(&self) -> usize {
!0
}
#[inline]
fn layer2(&self, _: usize) -> usize {
!0
}
#[inline]
fn layer1(&self, _: usize) -> usize {
!0
}
#[inline]
fn layer0(&self, i: usize) -> usize {
!self.0.layer0(i)
}
}
#[derive(Debug)]
pub struct BitSetXor<A: BitSetLike, B: BitSetLike>(pub A, pub B);
impl<A: BitSetLike, B: BitSetLike> BitSetLike for BitSetXor<A, B> {
#[inline]
fn layer3(&self) -> usize {
let xor = BitSetAnd(BitSetOr(&self.0, &self.1), BitSetNot(BitSetAnd(&self.0, &self.1)));
xor.layer3()
}
#[inline]
fn layer2(&self, id: usize) -> usize {
let xor = BitSetAnd(BitSetOr(&self.0, &self.1), BitSetNot(BitSetAnd(&self.0, &self.1)));
xor.layer2(id)
}
#[inline]
fn layer1(&self, id: usize) -> usize {
let xor = BitSetAnd(BitSetOr(&self.0, &self.1), BitSetNot(BitSetAnd(&self.0, &self.1)));
xor.layer1(id)
}
#[inline]
fn layer0(&self, id: usize) -> usize {
let xor = BitSetAnd(BitSetOr(&self.0, &self.1), BitSetNot(BitSetAnd(&self.0, &self.1)));
xor.layer0(id)
}
}
macro_rules! operator {
( impl < ( $( $lifetime:tt )* ) ( $( $arg:ident ),* ) > for $bitset:ty ) => {
impl<$( $lifetime, )* $( $arg ),*> Not for $bitset
where $( $arg: BitSetLike ),*
{
type Output = BitSetNot<Self>;
fn not(self) -> Self::Output {
BitSetNot(self)
}
}
impl<$( $lifetime, )* $( $arg, )* T> BitAnd<T> for $bitset
where T: BitSetLike,
$( $arg: BitSetLike ),*
{
type Output = BitSetAnd<Self, T>;
fn bitand(self, rhs: T) -> Self::Output {
BitSetAnd(self, rhs)
}
}
impl<$( $lifetime, )* $( $arg, )* T> BitOr<T> for $bitset
where T: BitSetLike,
$( $arg: BitSetLike ),*
{
type Output = BitSetOr<Self, T>;
fn bitor(self, rhs: T) -> Self::Output {
BitSetOr(self, rhs)
}
}
impl<$( $lifetime, )* $( $arg, )* T> BitXor<T> for $bitset
where T: BitSetLike,
$( $arg: BitSetLike ),*
{
type Output = BitSetXor<Self, T>;
fn bitxor(self, rhs: T) -> Self::Output {
BitSetXor(self, rhs)
}
}
}
}
operator!(impl<()()> for BitSet);
operator!(impl<('a)()> for &'a BitSet);
operator!(impl<()(A)> for BitSetNot<A>);
operator!(impl<('a)(A)> for &'a BitSetNot<A>);
operator!(impl<()(A, B)> for BitSetAnd<A, B>);
operator!(impl<('a)(A, B)> for &'a BitSetAnd<A, B>);
operator!(impl<()(A, B)> for BitSetOr<A, B>);
operator!(impl<('a)(A, B)> for &'a BitSetOr<A, B>);
operator!(impl<()(A, B)> for BitSetXor<A, B>);
operator!(impl<('a)(A, B)> for &'a BitSetXor<A, B>);
#[cfg(test)]
mod tests {
use {Index, BitSet, BitSetLike, BitSetXor};
#[test]
fn operators() {
let mut bitset = BitSet::new();
bitset.add(1);
bitset.add(3);
bitset.add(5);
bitset.add(15);
bitset.add(200);
bitset.add(50001);
let mut other = BitSet::new();
other.add(1);
other.add(3);
other.add(50000);
other.add(50001);
{
let not = &bitset & !&bitset;
assert_eq!(not.iter().count(), 0);
}
{
let either = &bitset | &other;
let collected = either.iter().collect::<Vec<Index>>();
assert_eq!(collected, vec![1, 3, 5, 15, 200, 50000, 50001]);
let either_sanity = bitset.clone() | other.clone();
assert_eq!(collected, either_sanity.iter().collect::<Vec<Index>>());
}
{
let same = &bitset & &other;
let collected = same.iter().collect::<Vec<Index>>();
assert_eq!(collected, vec![1, 3, 50001]);
let same_sanity = bitset.clone() & other.clone();
assert_eq!(collected, same_sanity.iter().collect::<Vec<Index>>());
}
{
let exclusive = &bitset ^ &other;
let collected = exclusive.iter().collect::<Vec<Index>>();
assert_eq!(collected, vec![5, 15, 200, 50000]);
let exclusive_sanity = bitset.clone() ^ other.clone();
assert_eq!(collected, exclusive_sanity.iter().collect::<Vec<Index>>());
}
}
#[test]
fn xor() {
let mut bitset = BitSet::new();
bitset.add(2);
bitset.add(3);
bitset.add(50000);
let mut other = BitSet::new();
other.add(1);
other.add(3);
other.add(50000);
other.add(50001);
{
let xor = BitSetXor(&bitset, &other);
let collected = xor.iter().collect::<Vec<Index>>();
assert_eq!(collected, vec![1, 2, 50001]);
}
}
}