use crate::AndNot;
use smallvec::SmallVec;
use std::cmp::Ordering;
use std::iter::FromIterator;
use std::ops::{BitAnd, BitOr};
use std::{fmt, slice};
const DEFAULT_SPARSE_ALLOC: usize = 2;
#[cfg(target_arch = "x86_64")]
const AVG_RANGE_COMP_REQ: usize = 12;
#[cfg(target_arch = "aarch64")]
const AVG_RANGE_COMP_REQ: usize = 5;
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
const AVG_RANGE_COMP_REQ: usize = 14;
const FAST_PATH_BST_RATIO: usize = 8;
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename = "R")]
struct IDLRange {
#[serde(rename = "r")]
pub range: u64,
#[serde(rename = "m")]
pub mask: u64,
}
impl fmt::Debug for IDLRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"IDLRange {{ range: {}, mask: {:x} }}",
self.range, self.mask
)
}
}
impl Ord for IDLRange {
fn cmp(&self, other: &Self) -> Ordering {
self.range.cmp(&other.range)
}
}
impl PartialOrd for IDLRange {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for IDLRange {
fn eq(&self, other: &Self) -> bool {
self.range == other.range
}
}
impl Eq for IDLRange {}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[serde(rename = "S")]
enum IDLState {
#[serde(rename = "s")]
Sparse(SmallVec<[u64; DEFAULT_SPARSE_ALLOC]>),
#[serde(rename = "c")]
Compressed(Vec<IDLRange>),
}
impl IDLState {
fn shrink_to_fit(&mut self) {
match self {
IDLState::Sparse(svec) => svec.shrink_to_fit(),
IDLState::Compressed(vec) => vec.shrink_to_fit(),
}
}
fn sparse_bitand_fast_path(smol: &[u64], lrg: &[u64]) -> Self {
let mut nlist = SmallVec::with_capacity(smol.len());
let mut idx_min = 0;
smol.iter().for_each(|id| {
let (_, partition) = lrg.split_at(idx_min);
if let Ok(idx) = partition.binary_search(id) {
debug_assert!(Ok(idx + idx_min) == lrg.binary_search(id));
let idx = idx + idx_min;
nlist.push(*id);
debug_assert!(idx >= idx_min);
idx_min = idx;
}
});
nlist.shrink_to_fit();
IDLState::Sparse(nlist)
}
fn sparse_bitor_fast_path(smol: &[u64], lrg: &[u64]) -> Self {
let mut nlist = SmallVec::with_capacity(lrg.len() + smol.len());
nlist.extend_from_slice(lrg);
let mut idx_min = 0;
smol.iter().for_each(|id| {
let (_, partition) = nlist.split_at(idx_min);
if let Err(idx) = partition.binary_search(id) {
debug_assert!(Err(idx + idx_min) == nlist.binary_search(id));
let idx = idx + idx_min;
nlist.insert(idx, *id);
debug_assert!(idx >= idx_min);
if idx != 0 {
idx_min = idx - 1;
}
}
});
nlist.shrink_to_fit();
IDLState::Sparse(nlist)
}
}
impl fmt::Display for IDLBitRange {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.state {
IDLState::Sparse(list) => write!(
f,
"IDLBitRange (sparse values) {:?} (data) <optimised out>",
list.len()
),
IDLState::Compressed(list) => write!(
f,
"IDLBitRange (compressed ranges) {:?} (decompressed) <optimised out>",
list.len()
),
}
}
}
impl fmt::Debug for IDLBitRange {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.state {
IDLState::Sparse(list) => {
write!(f, "IDLBitRange (sparse values) {:?} (data) [ ", list.len())?;
}
IDLState::Compressed(list) => {
write!(f, "IDLBitRange (compressed) {:?} (decompressed) [ ", list)?;
}
}
for id in self {
write!(f, "{}, ", id)?;
}
write!(f, "]")
}
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename = "IDLV2")]
pub struct IDLBitRange {
#[serde(rename = "t")]
state: IDLState,
}
impl IDLRange {
fn new(range: u64, mask: u64) -> Self {
IDLRange { range, mask }
}
#[inline(always)]
fn push_id(&mut self, value: u64) {
self.mask ^= 1 << value;
}
}
impl Default for IDLBitRange {
fn default() -> Self {
IDLBitRange {
state: IDLState::Sparse(SmallVec::with_capacity(0)),
}
}
}
impl PartialEq for IDLBitRange {
fn eq(&self, other: &Self) -> bool {
let x = self & other;
debug_assert!(other.len() == self.len() && other.len() == x.len());
x.len() == other.len()
}
}
impl IDLBitRange {
pub fn new() -> Self {
Self::default()
}
pub fn from_u64(id: u64) -> Self {
IDLBitRange {
state: IDLState::Sparse(smallvec![id]),
}
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn is_sparse(&self) -> bool {
matches!(self.state, IDLState::Sparse(_))
}
pub fn is_compressed(&self) -> bool {
matches!(self.state, IDLState::Compressed(_))
}
#[inline(always)]
pub fn len(&self) -> usize {
match &self.state {
IDLState::Sparse(list) => list.len(),
IDLState::Compressed(list) => list
.iter()
.fold(0, |acc, i| (i.mask.count_ones() as usize) + acc),
}
}
fn len_ranges(&self) -> usize {
match &self.state {
IDLState::Sparse(_list) => 0,
IDLState::Compressed(list) => list.len(),
}
}
#[inline(always)]
pub fn below_threshold(&self, threshold: usize) -> bool {
match &self.state {
IDLState::Sparse(list) => list.len() < threshold,
IDLState::Compressed(list) => {
let mut ic: usize = 0;
for i in list.iter() {
ic += i.mask.count_ones() as usize;
if ic >= threshold {
return false;
}
}
true
}
}
}
#[inline(always)]
pub fn sum(&self) -> u64 {
match &self.state {
IDLState::Sparse(list) => list.iter().fold(0, |acc, x| x + acc),
IDLState::Compressed(list) => IDLBitRangeIterComp::new(list).fold(0, |acc, x| x + acc),
}
}
pub fn contains(&self, id: u64) -> bool {
match &self.state {
IDLState::Sparse(list) => list.as_slice().binary_search(&id).is_ok(),
IDLState::Compressed(list) => {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
let mask = 1 << bvalue;
if let Ok(idx) = list.binary_search_by(|v| v.range.cmp(&range)) {
let existing = unsafe { list.get_unchecked(idx) };
(existing.mask & mask) > 0
} else {
false
}
}
}
}
pub unsafe fn push_id(&mut self, id: u64) {
match &mut self.state {
IDLState::Sparse(list) => {
list.push(id);
}
IDLState::Compressed(list) => {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
if let Some(last) = list.last_mut() {
debug_assert!(id >= last.range);
if last.range == range {
(*last).push_id(bvalue);
return;
}
}
list.push(IDLRange::new(range, 1 << bvalue));
}
} }
pub fn insert_id(&mut self, id: u64) {
match &mut self.state {
IDLState::Sparse(list) => {
let r = list.binary_search(&id);
if let Err(idx) = r {
list.insert(idx, id);
}
}
IDLState::Compressed(list) => {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
let candidate = IDLRange::new(range, 1 << bvalue);
let r = list.binary_search(&candidate);
match r {
Ok(idx) => {
let existing = list.get_mut(idx).unwrap();
existing.mask |= candidate.mask;
}
Err(idx) => {
list.insert(idx, candidate);
}
};
}
}
}
pub fn remove_id(&mut self, id: u64) {
match &mut self.state {
IDLState::Sparse(list) => {
let r = list.binary_search(&id);
if let Ok(idx) = r {
list.remove(idx);
};
}
IDLState::Compressed(list) => {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
let candidate = IDLRange::new(range, 1 << bvalue);
if let Ok(idx) = list.binary_search(&candidate) {
let existing = list.get_mut(idx).unwrap();
existing.mask &= !candidate.mask;
if existing.mask == 0 {
list.remove(idx);
}
}
}
} }
pub fn compress(&mut self) {
if self.is_compressed() {
return;
}
let mut prev_state = IDLState::Compressed(Vec::with_capacity(0));
std::mem::swap(&mut prev_state, &mut self.state);
match prev_state {
IDLState::Sparse(list) => list.into_iter().for_each(|i| unsafe {
self.push_id(i);
}),
IDLState::Compressed(_) => panic!("Unexpected state!"),
}
}
pub fn maybe_compress(&mut self) -> bool {
let maybe_state = if let IDLState::Sparse(list) = &self.state {
if list.len() < AVG_RANGE_COMP_REQ {
None
} else {
let mut maybe = IDLBitRange {
state: IDLState::Compressed(Vec::with_capacity(0)),
};
list.iter().for_each(|id| unsafe { maybe.push_id(*id) });
if maybe.len_ranges() > 0
&& (maybe.len() / maybe.len_ranges()) >= AVG_RANGE_COMP_REQ
{
let IDLBitRange { mut state } = maybe;
state.shrink_to_fit();
Some(state)
} else {
None
}
}
} else {
None
};
if let Some(mut new_state) = maybe_state {
std::mem::swap(&mut self.state, &mut new_state);
true
} else {
false
}
}
#[inline(always)]
fn bitand_inner(&self, rhs: &Self) -> Self {
match (&self.state, &rhs.state) {
(IDLState::Sparse(lhs), IDLState::Sparse(rhs)) => {
let state = if !lhs.is_empty() && (rhs.len() / lhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitand_fast_path(lhs.as_slice(), rhs.as_slice())
} else if !rhs.is_empty() && (lhs.len() / rhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitand_fast_path(rhs.as_slice(), lhs.as_slice())
} else {
let x = if rhs.len() > lhs.len() {
rhs.len()
} else {
lhs.len()
};
let mut nlist = SmallVec::with_capacity(x);
let mut liter = lhs.iter();
let mut riter = rhs.iter();
let mut lnext = liter.next();
let mut rnext = riter.next();
while lnext.is_some() && rnext.is_some() {
let l = lnext.unwrap();
let r = rnext.unwrap();
match l.cmp(r) {
Ordering::Equal => {
nlist.push(*l);
lnext = liter.next();
rnext = riter.next();
}
Ordering::Less => {
lnext = liter.next();
}
Ordering::Greater => {
rnext = riter.next();
}
}
}
nlist.shrink_to_fit();
IDLState::Sparse(nlist)
};
IDLBitRange { state }
}
(IDLState::Sparse(sparselist), IDLState::Compressed(list))
| (IDLState::Compressed(list), IDLState::Sparse(sparselist)) => {
let mut nlist = SmallVec::with_capacity(sparselist.len());
let mut idx_min = 0;
sparselist.iter().for_each(|id| {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
let mask = 1 << bvalue;
let (_, partition) = list.split_at(idx_min);
if let Ok(idx) = partition.binary_search_by(|v| v.range.cmp(&range)) {
debug_assert!(
Ok(idx + idx_min) == list.binary_search_by(|v| v.range.cmp(&range))
);
let idx = idx + idx_min;
let existing = unsafe { list.get_unchecked(idx) };
if (existing.mask & mask) > 0 {
nlist.push(*id);
}
debug_assert!(idx >= idx_min);
idx_min = idx;
}
});
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Sparse(nlist),
}
}
(IDLState::Compressed(list1), IDLState::Compressed(list2)) => {
let mut nlist = Vec::with_capacity(0);
let mut liter = list1.iter();
let mut riter = list2.iter();
let mut lnextrange = liter.next();
let mut rnextrange = riter.next();
while lnextrange.is_some() && rnextrange.is_some() {
let l = lnextrange.unwrap();
let r = rnextrange.unwrap();
match l.range.cmp(&r.range) {
Ordering::Equal => {
let mask = l.mask & r.mask;
if mask > 0 {
let newrange = IDLRange::new(l.range, mask);
nlist.push(newrange);
}
lnextrange = liter.next();
rnextrange = riter.next();
}
Ordering::Less => {
lnextrange = liter.next();
}
Ordering::Greater => {
rnextrange = riter.next();
}
}
}
if nlist.is_empty() {
IDLBitRange::new()
} else {
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Compressed(nlist),
}
}
}
}
}
#[inline(always)]
fn bitor_inner(&self, rhs: &Self) -> Self {
match (&self.state, &rhs.state) {
(IDLState::Sparse(lhs), IDLState::Sparse(rhs)) => {
let state = if !lhs.is_empty() && (rhs.len() / lhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitor_fast_path(lhs.as_slice(), rhs.as_slice())
} else if !rhs.is_empty() && (lhs.len() / rhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitor_fast_path(rhs.as_slice(), lhs.as_slice())
} else {
let mut nlist = SmallVec::with_capacity(lhs.len() + rhs.len());
let mut liter = lhs.iter();
let mut riter = rhs.iter();
let mut lnext = liter.next();
let mut rnext = riter.next();
while lnext.is_some() && rnext.is_some() {
let l = lnext.unwrap();
let r = rnext.unwrap();
let n = match l.cmp(r) {
Ordering::Equal => {
lnext = liter.next();
rnext = riter.next();
l
}
Ordering::Less => {
lnext = liter.next();
l
}
Ordering::Greater => {
rnext = riter.next();
r
}
};
nlist.push(*n);
}
while lnext.is_some() {
let l = lnext.unwrap();
nlist.push(*l);
lnext = liter.next();
}
while rnext.is_some() {
let r = rnext.unwrap();
nlist.push(*r);
rnext = riter.next();
}
nlist.shrink_to_fit();
IDLState::Sparse(nlist)
};
IDLBitRange { state }
}
(IDLState::Sparse(sparselist), IDLState::Compressed(list))
| (IDLState::Compressed(list), IDLState::Sparse(sparselist)) => {
let mut list = list.clone();
let mut idx_min = 0;
sparselist.iter().for_each(|id| {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
let candidate = IDLRange::new(range, 1 << bvalue);
let (_, partition) = list.split_at(idx_min);
let r = partition.binary_search(&candidate);
match r {
Ok(idx) => {
debug_assert!(Ok(idx + idx_min) == list.binary_search(&candidate));
let idx = idx + idx_min;
let existing = list.get_mut(idx).unwrap();
existing.mask |= candidate.mask;
debug_assert!(idx >= idx_min);
idx_min = idx;
}
Err(idx) => {
debug_assert!(Err(idx + idx_min) == list.binary_search(&candidate));
let idx = idx + idx_min;
list.insert(idx, candidate);
debug_assert!(idx >= idx_min);
if idx != 0 {
idx_min = idx - 1;
}
}
};
});
list.shrink_to_fit();
IDLBitRange {
state: IDLState::Compressed(list),
}
}
(IDLState::Compressed(list1), IDLState::Compressed(list2)) => {
let llen = list1.len();
let rlen = list2.len();
let mut nlist = Vec::with_capacity(llen + rlen);
let mut liter = list1.iter();
let mut riter = list2.iter();
let mut lnextrange = liter.next();
let mut rnextrange = riter.next();
while lnextrange.is_some() && rnextrange.is_some() {
let l = lnextrange.unwrap();
let r = rnextrange.unwrap();
let (range, mask) = match l.range.cmp(&r.range) {
Ordering::Equal => {
lnextrange = liter.next();
rnextrange = riter.next();
(l.range, l.mask | r.mask)
}
Ordering::Less => {
lnextrange = liter.next();
(l.range, l.mask)
}
Ordering::Greater => {
rnextrange = riter.next();
(r.range, r.mask)
}
};
let newrange = IDLRange::new(range, mask);
nlist.push(newrange);
}
while lnextrange.is_some() {
let l = lnextrange.unwrap();
let newrange = IDLRange::new(l.range, l.mask);
nlist.push(newrange);
lnextrange = liter.next();
}
while rnextrange.is_some() {
let r = rnextrange.unwrap();
let newrange = IDLRange::new(r.range, r.mask);
nlist.push(newrange);
rnextrange = riter.next();
}
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Compressed(nlist),
}
}
} }
#[inline(always)]
fn bitandnot_inner(&self, rhs: &Self) -> Self {
match (&self.state, &rhs.state) {
(IDLState::Sparse(lhs), IDLState::Sparse(rhs)) => {
let mut nlist = SmallVec::with_capacity(lhs.len());
let mut liter = lhs.iter();
let mut riter = rhs.iter();
let mut lnext = liter.next();
let mut rnext = riter.next();
while lnext.is_some() && rnext.is_some() {
let l = lnext.unwrap();
let r = rnext.unwrap();
match l.cmp(r) {
Ordering::Equal => {
lnext = liter.next();
rnext = riter.next();
}
Ordering::Less => {
nlist.push(*l);
lnext = liter.next();
}
Ordering::Greater => {
rnext = riter.next();
}
}
}
while lnext.is_some() {
nlist.push(*lnext.unwrap());
lnext = liter.next();
}
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Sparse(nlist),
}
}
(IDLState::Sparse(sparselist), IDLState::Compressed(list)) => {
let mut nlist = SmallVec::with_capacity(sparselist.len());
let mut idx_min = 0;
sparselist.iter().for_each(|id| {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
let mask = 1 << bvalue;
let (_, partition) = list.split_at(idx_min);
match partition.binary_search_by(|v| v.range.cmp(&range)) {
Ok(idx) => {
debug_assert!(
Ok(idx + idx_min) == list.binary_search_by(|v| v.range.cmp(&range))
);
let idx = idx + idx_min;
let existing = unsafe { list.get_unchecked(idx) };
if (existing.mask & mask) == 0 {
nlist.push(*id);
}
debug_assert!(idx >= idx_min);
idx_min = idx;
}
Err(idx) => {
debug_assert!(
Err(idx + idx_min)
== list.binary_search_by(|v| v.range.cmp(&range))
);
let idx = idx + idx_min;
nlist.push(*id);
if idx != 0 {
idx_min = idx - 1;
}
}
}
});
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Sparse(nlist),
}
}
(IDLState::Compressed(list), IDLState::Sparse(sparselist)) => {
let mut nlist = list.clone();
let mut idx_min = 0;
sparselist.iter().for_each(|id| {
let bvalue: u64 = id % 64;
let range: u64 = id - bvalue;
let candidate = IDLRange::new(range, 1 << bvalue);
let (_, partition) = nlist.split_at(idx_min);
if let Ok(idx) = partition.binary_search(&candidate) {
debug_assert!(Ok(idx + idx_min) == nlist.binary_search(&candidate));
let idx = idx + idx_min;
let existing = nlist.get_mut(idx).unwrap();
existing.mask &= !candidate.mask;
if existing.mask == 0 {
nlist.remove(idx);
}
debug_assert!(idx >= idx_min);
idx_min = idx;
}
});
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Compressed(nlist),
}
}
(IDLState::Compressed(list1), IDLState::Compressed(list2)) => {
let mut nlist = Vec::with_capacity(list1.len());
let mut liter = list1.iter();
let mut riter = list2.iter();
let mut lnextrange = liter.next();
let mut rnextrange = riter.next();
while lnextrange.is_some() && rnextrange.is_some() {
let l = lnextrange.unwrap();
let r = rnextrange.unwrap();
match l.range.cmp(&r.range) {
Ordering::Equal => {
let mask = l.mask & (!r.mask);
if mask > 0 {
let newrange = IDLRange::new(l.range, mask);
nlist.push(newrange);
}
lnextrange = liter.next();
rnextrange = riter.next();
}
Ordering::Less => {
nlist.push(l.clone());
lnextrange = liter.next();
}
Ordering::Greater => {
rnextrange = riter.next();
}
}
}
while lnextrange.is_some() {
let l = lnextrange.unwrap();
let newrange = IDLRange::new(l.range, l.mask);
nlist.push(newrange);
lnextrange = liter.next();
}
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Compressed(nlist),
}
}
} }
}
impl FromIterator<u64> for IDLBitRange {
fn from_iter<I: IntoIterator<Item = u64>>(iter: I) -> Self {
let iter = iter.into_iter();
let (lower_bound, _) = iter.size_hint();
let mut new_sparse = IDLBitRange {
state: IDLState::Sparse(SmallVec::with_capacity(lower_bound)),
};
let mut max_seen = 0;
iter.for_each(|i| {
if i >= max_seen {
unsafe {
new_sparse.push_id(i);
}
max_seen = i;
} else {
new_sparse.insert_id(i);
}
});
if !new_sparse.maybe_compress() {
new_sparse.state.shrink_to_fit();
}
new_sparse
}
}
impl BitAnd for &IDLBitRange {
type Output = IDLBitRange;
fn bitand(self, rhs: &IDLBitRange) -> IDLBitRange {
self.bitand_inner(rhs)
}
}
impl BitAnd for IDLBitRange {
type Output = IDLBitRange;
fn bitand(self, rhs: IDLBitRange) -> IDLBitRange {
self.bitand_inner(&rhs)
}
}
impl BitOr for &IDLBitRange {
type Output = IDLBitRange;
fn bitor(self, rhs: &IDLBitRange) -> IDLBitRange {
self.bitor_inner(rhs)
}
}
impl BitOr for IDLBitRange {
type Output = IDLBitRange;
fn bitor(self, rhs: Self) -> IDLBitRange {
self.bitor_inner(&rhs)
}
}
impl AndNot for IDLBitRange {
type Output = IDLBitRange;
fn andnot(self, rhs: Self) -> IDLBitRange {
self.bitandnot_inner(&rhs)
}
}
impl AndNot for &IDLBitRange {
type Output = IDLBitRange;
fn andnot(self, rhs: &IDLBitRange) -> IDLBitRange {
self.bitandnot_inner(rhs)
}
}
#[derive(Debug)]
pub struct IDLBitRangeIterComp<'a> {
rangeiter: slice::Iter<'a, IDLRange>,
currange: Option<&'a IDLRange>,
curbit: u64,
}
impl<'a> Iterator for IDLBitRangeIterComp<'a> {
type Item = u64;
fn next(&mut self) -> Option<u64> {
while self.currange.is_some() {
let range = self.currange.unwrap();
while self.curbit < 64 {
let m: u64 = 1 << self.curbit;
let candidate: u64 = range.mask & m;
if candidate > 0 {
let result = Some(self.curbit + range.range);
self.curbit += 1;
return result;
}
self.curbit += 1;
}
self.currange = self.rangeiter.next();
self.curbit = 0;
}
None
}
}
impl<'a> IDLBitRangeIterComp<'a> {
fn new(data: &'a [IDLRange]) -> Self {
let mut rangeiter = data.iter();
let currange = rangeiter.next();
IDLBitRangeIterComp {
rangeiter,
currange,
curbit: 0,
}
}
}
#[derive(Debug)]
pub enum IDLBitRangeIter<'a> {
Sparse(slice::Iter<'a, u64>),
Compressed(IDLBitRangeIterComp<'a>),
}
impl<'a> Iterator for IDLBitRangeIter<'a> {
type Item = u64;
fn next(&mut self) -> Option<u64> {
match self {
IDLBitRangeIter::Sparse(i) => i.next().copied(),
IDLBitRangeIter::Compressed(i) => i.next(),
}
}
}
impl<'a> IntoIterator for &'a IDLBitRange {
type Item = u64;
type IntoIter = IDLBitRangeIter<'a>;
fn into_iter(self) -> IDLBitRangeIter<'a> {
match &self.state {
IDLState::Sparse(list) => IDLBitRangeIter::Sparse((list).into_iter()),
IDLState::Compressed(list) => {
let mut liter = (list).iter();
let nrange = liter.next();
IDLBitRangeIter::Compressed(IDLBitRangeIterComp {
rangeiter: liter,
currange: nrange,
curbit: 0,
})
}
}
}
}
#[cfg(test)]
mod tests {
use super::IDLBitRange;
use super::IDLState;
use super::AVG_RANGE_COMP_REQ;
use crate::AndNot;
use std::iter::FromIterator;
#[test]
fn test_struct_size() {
let ibrsize = std::mem::size_of::<IDLBitRange>();
eprintln!("Struct size {:?}", ibrsize);
assert!(ibrsize <= 64);
}
#[test]
fn test_empty() {
let idl_a = IDLBitRange::new();
assert!(idl_a.is_empty());
assert!(idl_a.len() == 0);
}
#[test]
fn test_push_id_contains() {
let mut idl_a = IDLBitRange::new();
unsafe { idl_a.push_id(0) };
assert!(idl_a.contains(0));
assert!(idl_a.len() == 1);
unsafe { idl_a.push_id(1) };
assert!(idl_a.contains(0));
assert!(idl_a.contains(1));
assert!(idl_a.is_sparse());
assert!(idl_a.len() == 2);
unsafe { idl_a.push_id(2) };
assert!(idl_a.contains(0));
assert!(idl_a.contains(1));
assert!(idl_a.contains(2));
assert!(idl_a.is_sparse());
assert!(idl_a.len() == 3);
unsafe { idl_a.push_id(128) };
assert!(idl_a.contains(0));
assert!(idl_a.contains(1));
assert!(idl_a.contains(2));
assert!(idl_a.contains(128));
assert!(idl_a.is_sparse());
assert!(idl_a.len() == 4);
}
#[test]
fn test_from_iter() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let idl_b = IDLBitRange::from_iter(vec![64, 68, 2, 1]);
let idl_c = IDLBitRange::from_iter(vec![68, 64, 1, 2]);
let idl_d = IDLBitRange::from_iter(vec![2, 1, 68, 64]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
assert_eq!(idl_a, idl_expect);
assert_eq!(idl_b, idl_expect);
assert_eq!(idl_c, idl_expect);
assert_eq!(idl_d, idl_expect);
}
#[test]
fn test_sparse_remove_id() {
let mut idl_a = IDLBitRange::new();
idl_a.remove_id(100);
assert!(idl_a.len() == 0);
let mut idl_a = IDLBitRange::from_iter(vec![100]);
idl_a.remove_id(100);
assert!(idl_a.len() == 0);
let mut idl_a = IDLBitRange::from_iter(vec![100, 101]);
idl_a.remove_id(101);
assert!(idl_a.len() == 1);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let idl_expect = IDLBitRange::from_iter(vec![2, 64, 68]);
idl_a.remove_id(1);
assert_eq!(idl_a, idl_expect);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let idl_expect = IDLBitRange::from_iter(vec![1, 64, 68]);
idl_a.remove_id(2);
assert_eq!(idl_a, idl_expect);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 68]);
idl_a.remove_id(64);
assert_eq!(idl_a, idl_expect);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 64]);
idl_a.remove_id(68);
assert_eq!(idl_a, idl_expect);
}
#[test]
fn test_compressed_remove_id() {
let mut idl_a = IDLBitRange::new();
idl_a.compress();
assert!(idl_a.is_compressed());
idl_a.remove_id(100);
assert!(idl_a.len() == 0);
let mut idl_a = IDLBitRange::from_iter(vec![100]);
idl_a.compress();
idl_a.remove_id(100);
assert!(idl_a.len() == 0);
let mut idl_a = IDLBitRange::from_iter(vec![100, 101]);
idl_a.compress();
idl_a.remove_id(101);
assert!(idl_a.len() == 1);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let mut idl_expect = IDLBitRange::from_iter(vec![2, 64, 68]);
idl_a.compress();
idl_expect.compress();
idl_a.remove_id(1);
assert_eq!(idl_a, idl_expect);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 64, 68]);
idl_a.compress();
idl_expect.compress();
idl_a.remove_id(2);
assert_eq!(idl_a, idl_expect);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 68]);
idl_a.compress();
idl_expect.compress();
idl_a.remove_id(64);
assert_eq!(idl_a, idl_expect);
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 64, 68]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 64]);
idl_a.compress();
idl_expect.compress();
idl_a.remove_id(68);
assert_eq!(idl_a, idl_expect);
}
#[test]
fn test_range_intersection_1() {
let idl_a = IDLBitRange::new();
let idl_b = IDLBitRange::new();
let idl_expect = IDLBitRange::new();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_2() {
let idl_a = IDLBitRange::new();
let idl_b = IDLBitRange::from_iter(vec![2]);
let idl_expect = IDLBitRange::new();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
let idl_a = IDLBitRange::from_iter(vec![2]);
let idl_b = IDLBitRange::new();
let idl_expect = IDLBitRange::new();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_3() {
let idl_a = IDLBitRange::from_iter(vec![2]);
let idl_b = IDLBitRange::from_iter(vec![2]);
let idl_expect = IDLBitRange::from_iter(vec![2]);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
let idl_a = IDLBitRange::from_iter(vec![2]);
let idl_b = IDLBitRange::from_iter(vec![128]);
let idl_expect = IDLBitRange::new();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_4() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3]);
let idl_b = IDLBitRange::from_iter(vec![2]);
let idl_expect = IDLBitRange::from_iter(vec![2]);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
let idl_a = IDLBitRange::from_iter(vec![2]);
let idl_b = IDLBitRange::from_iter(vec![1, 2, 3]);
let idl_expect = IDLBitRange::from_iter(vec![2]);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
let idl_a = IDLBitRange::from_iter(vec![128]);
let idl_b = IDLBitRange::from_iter(vec![1, 2, 3]);
let idl_expect = IDLBitRange::new();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
let idl_a = IDLBitRange::from_iter(vec![64, 66]);
let idl_b = IDLBitRange::from_iter(vec![1, 2, 60, 62, 64, 69]);
let idl_expect = IDLBitRange::from_iter(vec![64]);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_5() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3]);
let idl_b = IDLBitRange::from_iter(vec![4, 67]);
let idl_expect = IDLBitRange::new();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_6() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 35, 64, 65, 128, 150]);
let idl_b = IDLBitRange::from_iter(vec![2, 3, 8, 35, 64, 128, 130, 150, 152, 180]);
let idl_expect = IDLBitRange::from_iter(vec![2, 3, 35, 64, 128, 150]);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_7() {
let idl_a = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
let idl_b = IDLBitRange::from_iter(1..1024);
let idl_expect = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_8() {
let idl_a = IDLBitRange::from_iter(1..204800);
let idl_b = IDLBitRange::from_iter(102400..307200);
let idl_expect = IDLBitRange::from_iter(102400..204800);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_intersection_9() {
let idl_a = IDLBitRange::from_iter(vec![307199]);
let idl_b = IDLBitRange::from_iter(102400..307200);
let idl_expect = IDLBitRange::from_iter(vec![307199]);
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_compressed_intersection() {
let mut idl_a = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
let mut idl_b = IDLBitRange::from_iter(1..1024);
let mut idl_expect = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
idl_a.compress();
idl_b.compress();
idl_expect.compress();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_compressed_intersection() {
let mut idl_a = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
let idl_b = IDLBitRange::from_iter(1..1024);
let mut idl_expect = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
idl_a.compress();
idl_expect.compress();
let idl_result = idl_a & idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_union_1() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3]);
let idl_b = IDLBitRange::from_iter(vec![2]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 3]);
let idl_result = idl_a | idl_b;
eprintln!("{:?}, {:?}", idl_result, idl_expect);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_union_2() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3]);
let idl_b = IDLBitRange::from_iter(vec![4, 67]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 4, 67]);
let idl_result = idl_a | idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_union_3() {
let idl_a = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
let idl_b = IDLBitRange::from_iter(1..1024);
let idl_expect = IDLBitRange::from_iter(1..1024);
let idl_result = idl_a | idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_union_compressed() {
let mut idl_a = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
let mut idl_b = IDLBitRange::from_iter(1..1024);
let mut idl_expect = IDLBitRange::from_iter(1..1024);
idl_a.compress();
idl_b.compress();
idl_expect.compress();
let idl_result = idl_a | idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_union_compressed() {
let mut idl_a = IDLBitRange::from_iter(vec![
2, 3, 8, 35, 64, 128, 130, 150, 152, 180, 256, 800, 900,
]);
let idl_b = IDLBitRange::from_iter(1..1024);
let idl_expect = IDLBitRange::from_iter(1..1024);
idl_a.compress();
let idl_result = idl_a | idl_b;
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_not_1() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let idl_b = IDLBitRange::from_iter(vec![3, 4]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 5, 6]);
if AVG_RANGE_COMP_REQ <= 5 {
idl_expect.compress();
};
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_not_2() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let idl_b = IDLBitRange::from_iter(vec![10]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_not_3() {
let idl_a = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
let idl_b = IDLBitRange::from_iter(vec![1]);
let idl_expect = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_not_4() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 64, 65, 66]);
let idl_b = IDLBitRange::from_iter(vec![65]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 64, 66]);
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_not_1() {
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let mut idl_b = IDLBitRange::from_iter(vec![3, 4]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 5, 6]);
idl_a.compress();
idl_b.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_not_2() {
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let mut idl_b = IDLBitRange::from_iter(vec![10]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
idl_a.compress();
idl_b.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_not_3() {
let mut idl_a = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
let mut idl_b = IDLBitRange::from_iter(vec![1]);
let mut idl_expect = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
idl_a.compress();
idl_b.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_not_4() {
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 64, 65, 66]);
let mut idl_b = IDLBitRange::from_iter(vec![65]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 64, 66]);
idl_a.compress();
idl_b.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_comp_not_1() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let mut idl_b = IDLBitRange::from_iter(vec![3, 4]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 5, 6]);
idl_b.compress();
if AVG_RANGE_COMP_REQ <= 5 {
idl_expect.compress();
};
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_comp_not_2() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let mut idl_b = IDLBitRange::from_iter(vec![10]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
idl_b.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_comp_not_3() {
let idl_a = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
let mut idl_b = IDLBitRange::from_iter(vec![1]);
let idl_expect = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
idl_b.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_sparse_comp_not_4() {
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 64, 65, 66]);
let mut idl_b = IDLBitRange::from_iter(vec![65]);
let idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 64, 66]);
idl_b.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
let idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 64, 65, 66]);
let mut idl_b = IDLBitRange::from_iter(vec![65, 80]);
idl_b.compress();
let mut idl_expect = IDLBitRange::from_iter(vec![80]);
idl_expect.compress();
let idl_result = idl_b.andnot(idl_a);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_sparse_not_1() {
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let idl_b = IDLBitRange::from_iter(vec![3, 4]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 5, 6]);
idl_a.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_sparse_not_2() {
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
let idl_b = IDLBitRange::from_iter(vec![10]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 4, 5, 6]);
idl_a.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_sparse_not_3() {
let mut idl_a = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
let idl_b = IDLBitRange::from_iter(vec![1]);
let mut idl_expect = IDLBitRange::from_iter(vec![2, 3, 4, 5, 6]);
idl_a.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_range_comp_sparse_not_4() {
let mut idl_a = IDLBitRange::from_iter(vec![1, 2, 3, 64, 65, 66]);
let idl_b = IDLBitRange::from_iter(vec![65]);
let mut idl_expect = IDLBitRange::from_iter(vec![1, 2, 3, 64, 66]);
idl_a.compress();
idl_expect.compress();
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}
#[test]
fn test_sizeof_idlstate() {
let sz = std::mem::size_of::<IDLState>();
eprintln!("{}", sz);
}
}