use core::mem;
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign};
use crate::bitmap::container::Container;
use crate::bitmap::Pairs;
use crate::RoaringBitmap;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
impl RoaringBitmap {
pub fn intersection_len(&self, other: &RoaringBitmap) -> u64 {
Pairs::new(&self.containers, &other.containers)
.map(|pair| match pair {
(Some(..), None) => 0,
(None, Some(..)) => 0,
(Some(lhs), Some(rhs)) => lhs.intersection_len(rhs),
(None, None) => 0,
})
.sum()
}
pub fn union_len(&self, other: &RoaringBitmap) -> u64 {
self.len().wrapping_add(other.len()).wrapping_sub(self.intersection_len(other))
}
pub fn difference_len(&self, other: &RoaringBitmap) -> u64 {
self.len() - self.intersection_len(other)
}
pub fn symmetric_difference_len(&self, other: &RoaringBitmap) -> u64 {
let intersection_len = self.intersection_len(other);
self.len()
.wrapping_add(other.len())
.wrapping_sub(intersection_len)
.wrapping_sub(intersection_len)
}
}
impl BitOr<RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn bitor(mut self, rhs: RoaringBitmap) -> RoaringBitmap {
BitOrAssign::bitor_assign(&mut self, rhs);
self
}
}
impl BitOr<&RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn bitor(mut self, rhs: &RoaringBitmap) -> RoaringBitmap {
BitOrAssign::bitor_assign(&mut self, rhs);
self
}
}
impl BitOr<RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn bitor(self, rhs: RoaringBitmap) -> RoaringBitmap {
BitOr::bitor(rhs, self)
}
}
impl BitOr<&RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn bitor(self, rhs: &RoaringBitmap) -> RoaringBitmap {
let mut containers = Vec::new();
for pair in Pairs::new(&self.containers, &rhs.containers) {
match pair {
(Some(lhs), None) => containers.push(lhs.clone()),
(None, Some(rhs)) => containers.push(rhs.clone()),
(Some(lhs), Some(rhs)) => containers.push(BitOr::bitor(lhs, rhs)),
(None, None) => break,
}
}
RoaringBitmap { containers }
}
}
impl BitOrAssign<RoaringBitmap> for RoaringBitmap {
fn bitor_assign(&mut self, mut rhs: RoaringBitmap) {
if self.len() < rhs.len() {
mem::swap(self, &mut rhs);
}
for container in rhs.containers {
let key = container.key;
match self.containers.binary_search_by_key(&key, |c| c.key) {
Err(loc) => self.containers.insert(loc, container),
Ok(loc) => BitOrAssign::bitor_assign(&mut self.containers[loc], container),
}
}
}
}
impl BitOrAssign<&RoaringBitmap> for RoaringBitmap {
fn bitor_assign(&mut self, rhs: &RoaringBitmap) {
for container in &rhs.containers {
let key = container.key;
match self.containers.binary_search_by_key(&key, |c| c.key) {
Err(loc) => self.containers.insert(loc, container.clone()),
Ok(loc) => BitOrAssign::bitor_assign(&mut self.containers[loc], container),
}
}
}
}
impl BitAnd<RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn bitand(mut self, rhs: RoaringBitmap) -> RoaringBitmap {
BitAndAssign::bitand_assign(&mut self, rhs);
self
}
}
impl BitAnd<&RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn bitand(mut self, rhs: &RoaringBitmap) -> RoaringBitmap {
BitAndAssign::bitand_assign(&mut self, rhs);
self
}
}
impl BitAnd<RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn bitand(self, rhs: RoaringBitmap) -> RoaringBitmap {
BitAnd::bitand(rhs, self)
}
}
impl BitAnd<&RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn bitand(self, rhs: &RoaringBitmap) -> RoaringBitmap {
let mut containers = Vec::new();
for pair in Pairs::new(&self.containers, &rhs.containers) {
if let (Some(lhs), Some(rhs)) = pair {
let container = BitAnd::bitand(lhs, rhs);
if !container.is_empty() {
containers.push(container);
}
}
}
RoaringBitmap { containers }
}
}
impl BitAndAssign<RoaringBitmap> for RoaringBitmap {
fn bitand_assign(&mut self, mut rhs: RoaringBitmap) {
if rhs.containers.len() < self.containers.len() {
mem::swap(self, &mut rhs);
}
self.containers.retain_mut(|cont| {
let key = cont.key;
match rhs.containers.binary_search_by_key(&key, |c| c.key) {
Ok(loc) => {
let rhs_cont = &mut rhs.containers[loc];
let rhs_cont = mem::replace(rhs_cont, Container::new(rhs_cont.key));
BitAndAssign::bitand_assign(cont, rhs_cont);
!cont.is_empty()
}
Err(_) => false,
}
})
}
}
impl BitAndAssign<&RoaringBitmap> for RoaringBitmap {
fn bitand_assign(&mut self, rhs: &RoaringBitmap) {
self.containers.retain_mut(|cont| {
let key = cont.key;
match rhs.containers.binary_search_by_key(&key, |c| c.key) {
Ok(loc) => {
BitAndAssign::bitand_assign(cont, &rhs.containers[loc]);
!cont.is_empty()
}
Err(_) => false,
}
})
}
}
impl Sub<RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn sub(mut self, rhs: RoaringBitmap) -> RoaringBitmap {
SubAssign::sub_assign(&mut self, &rhs);
self
}
}
impl Sub<&RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn sub(mut self, rhs: &RoaringBitmap) -> RoaringBitmap {
SubAssign::sub_assign(&mut self, rhs);
self
}
}
impl Sub<RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn sub(self, rhs: RoaringBitmap) -> RoaringBitmap {
Sub::sub(self, &rhs)
}
}
impl Sub<&RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn sub(self, rhs: &RoaringBitmap) -> RoaringBitmap {
let mut containers = Vec::new();
for pair in Pairs::new(&self.containers, &rhs.containers) {
match pair {
(Some(lhs), None) => containers.push(lhs.clone()),
(None, Some(_)) => (),
(Some(lhs), Some(rhs)) => {
let container = Sub::sub(lhs, rhs);
if !container.is_empty() {
containers.push(container);
}
}
(None, None) => break,
}
}
RoaringBitmap { containers }
}
}
impl SubAssign<RoaringBitmap> for RoaringBitmap {
fn sub_assign(&mut self, rhs: RoaringBitmap) {
SubAssign::sub_assign(self, &rhs)
}
}
impl SubAssign<&RoaringBitmap> for RoaringBitmap {
fn sub_assign(&mut self, rhs: &RoaringBitmap) {
self.containers.retain_mut(|cont| {
match rhs.containers.binary_search_by_key(&cont.key, |c| c.key) {
Ok(loc) => {
SubAssign::sub_assign(cont, &rhs.containers[loc]);
!cont.is_empty()
}
Err(_) => true,
}
})
}
}
impl BitXor<RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn bitxor(mut self, rhs: RoaringBitmap) -> RoaringBitmap {
BitXorAssign::bitxor_assign(&mut self, rhs);
self
}
}
impl BitXor<&RoaringBitmap> for RoaringBitmap {
type Output = RoaringBitmap;
fn bitxor(mut self, rhs: &RoaringBitmap) -> RoaringBitmap {
BitXorAssign::bitxor_assign(&mut self, rhs);
self
}
}
impl BitXor<RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn bitxor(self, rhs: RoaringBitmap) -> RoaringBitmap {
BitXor::bitxor(rhs, self)
}
}
impl BitXor<&RoaringBitmap> for &RoaringBitmap {
type Output = RoaringBitmap;
fn bitxor(self, rhs: &RoaringBitmap) -> RoaringBitmap {
let mut containers = Vec::new();
for pair in Pairs::new(&self.containers, &rhs.containers) {
match pair {
(Some(lhs), None) => containers.push(lhs.clone()),
(None, Some(rhs)) => containers.push(rhs.clone()),
(Some(lhs), Some(rhs)) => {
let container = BitXor::bitxor(lhs, rhs);
if !container.is_empty() {
containers.push(container);
}
}
(None, None) => break,
}
}
RoaringBitmap { containers }
}
}
impl BitXorAssign<RoaringBitmap> for RoaringBitmap {
fn bitxor_assign(&mut self, rhs: RoaringBitmap) {
for pair in Pairs::new(mem::take(&mut self.containers), rhs.containers) {
match pair {
(Some(mut lhs), Some(rhs)) => {
BitXorAssign::bitxor_assign(&mut lhs, rhs);
if !lhs.is_empty() {
self.containers.push(lhs);
}
}
(Some(lhs), None) => self.containers.push(lhs),
(None, Some(rhs)) => self.containers.push(rhs),
(None, None) => break,
}
}
}
}
impl BitXorAssign<&RoaringBitmap> for RoaringBitmap {
fn bitxor_assign(&mut self, rhs: &RoaringBitmap) {
for pair in Pairs::new(mem::take(&mut self.containers), &rhs.containers) {
match pair {
(Some(mut lhs), Some(rhs)) => {
BitXorAssign::bitxor_assign(&mut lhs, rhs);
if !lhs.is_empty() {
self.containers.push(lhs);
}
}
(Some(lhs), None) => self.containers.push(lhs),
(None, Some(rhs)) => self.containers.push(rhs.clone()),
(None, None) => break,
}
}
}
}
#[cfg(test)]
mod test {
use crate::{MultiOps, RoaringBitmap};
use core::convert::Infallible;
use proptest::prelude::*;
proptest! {
#[test]
fn union_len_eq_len_of_materialized_union(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary()
) {
prop_assert_eq!(a.union_len(&b), (a | b).len());
}
#[test]
fn intersection_len_eq_len_of_materialized_intersection(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary()
) {
prop_assert_eq!(a.intersection_len(&b), (a & b).len());
}
#[test]
fn difference_len_eq_len_of_materialized_difference(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary()
) {
prop_assert_eq!(a.difference_len(&b), (a - b).len());
}
#[test]
fn symmetric_difference_len_eq_len_of_materialized_symmetric_difference(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary()
) {
prop_assert_eq!(a.symmetric_difference_len(&b), (a ^ b).len());
}
#[test]
fn all_union_give_the_same_result(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary(),
c in RoaringBitmap::arbitrary()
) {
let mut ref_assign = a.clone();
ref_assign |= &b;
ref_assign |= &c;
let mut own_assign = a.clone();
own_assign |= b.clone();
own_assign |= c.clone();
let ref_inline = &a | &b | &c;
let own_inline = a.clone() | b.clone() | c.clone();
let ref_multiop = [&a, &b, &c].union();
let own_multiop = [a.clone(), b.clone(), c.clone()].union();
let ref_multiop_try = [&a, &b, &c].map(Ok::<_, Infallible>).union().unwrap();
let own_multiop_try = [a, b, c].map(Ok::<_, Infallible>).union().unwrap();
for roar in &[
own_assign,
ref_inline,
own_inline,
ref_multiop,
own_multiop,
ref_multiop_try,
own_multiop_try,
] {
prop_assert_eq!(&ref_assign, roar);
}
}
#[test]
fn all_intersection_give_the_same_result(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary(),
c in RoaringBitmap::arbitrary()
) {
let mut ref_assign = a.clone();
ref_assign &= &b;
ref_assign &= &c;
let mut own_assign = a.clone();
own_assign &= b.clone();
own_assign &= c.clone();
let ref_inline = &a & &b & &c;
let own_inline = a.clone() & b.clone() & c.clone();
let ref_multiop = [&a, &b, &c].intersection();
let own_multiop = [a.clone(), b.clone(), c.clone()].intersection();
let ref_multiop_try = [&a, &b, &c].map(Ok::<_, Infallible>).intersection().unwrap();
let own_multiop_try = [a, b, c].map(Ok::<_, Infallible>).intersection().unwrap();
for roar in &[
own_assign,
ref_inline,
own_inline,
ref_multiop,
own_multiop,
ref_multiop_try,
own_multiop_try,
] {
prop_assert_eq!(&ref_assign, roar);
}
}
#[test]
fn all_difference_give_the_same_result(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary(),
c in RoaringBitmap::arbitrary()
) {
let mut ref_assign = a.clone();
ref_assign -= &b;
ref_assign -= &c;
let mut own_assign = a.clone();
own_assign -= b.clone();
own_assign -= c.clone();
let ref_inline = &a - &b - &c;
let own_inline = a.clone() - b.clone() - c.clone();
let ref_multiop = [&a, &b, &c].difference();
let own_multiop = [a.clone(), b.clone(), c.clone()].difference();
let ref_multiop_try = [&a, &b, &c].map(Ok::<_, Infallible>).difference().unwrap();
let own_multiop_try = [a, b, c].map(Ok::<_, Infallible>).difference().unwrap();
for roar in &[
own_assign,
ref_inline,
own_inline,
ref_multiop,
own_multiop,
ref_multiop_try,
own_multiop_try,
] {
prop_assert_eq!(&ref_assign, roar);
}
}
#[test]
fn all_symmetric_difference_give_the_same_result(
a in RoaringBitmap::arbitrary(),
b in RoaringBitmap::arbitrary(),
c in RoaringBitmap::arbitrary()
) {
let mut ref_assign = a.clone();
ref_assign ^= &b;
ref_assign ^= &c;
let mut own_assign = a.clone();
own_assign ^= b.clone();
own_assign ^= c.clone();
let ref_inline = &a ^ &b ^ &c;
let own_inline = a.clone() ^ b.clone() ^ c.clone();
let ref_multiop = [&a, &b, &c].symmetric_difference();
let own_multiop = [a.clone(), b.clone(), c.clone()].symmetric_difference();
let ref_multiop_try = [&a, &b, &c]
.map(Ok::<_, Infallible>)
.symmetric_difference()
.unwrap();
let own_multiop_try = [a, b, c]
.map(Ok::<_, Infallible>)
.symmetric_difference()
.unwrap();
for roar in &[
own_assign,
ref_inline,
own_inline,
ref_multiop,
own_multiop,
ref_multiop_try,
own_multiop_try,
] {
prop_assert_eq!(&ref_assign, roar);
}
}
}
}