#[derive(Debug)]
pub struct LogVec<T> {
items: Vec<T>,
}
impl<T> LogVec<T> {
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> Default for LogVec<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Ord> LogVec<T> {
pub fn insert(&mut self, value: T) {
self.items.push(value);
let z = self.items.len().trailing_zeros();
let merge_size = 1_usize << z;
if merge_size > 1 {
let start = self.items.len() - merge_size;
let merged = &mut self.items[start..];
if merge_size <= 8 {
Self::sort_small_unchecked(merged);
} else {
merged.sort_unstable();
}
}
}
fn sort_small_unchecked(slice: &mut [T]) {
debug_assert!(slice.len() <= 8);
for i in 1..slice.len() {
for j in (1..=i).rev() {
let [left, right] = unsafe { slice.get_disjoint_unchecked_mut([j - 1, j]) };
if left <= right {
break;
}
std::mem::swap(left, right);
}
}
}
pub fn contains(&self, query: &T) -> bool {
let len = self.items.len();
if len == 0 {
return false;
}
let mut size = 1 << len.ilog2();
while size > 0 {
if len & size != 0 {
let end = len & !(size - 1);
let start = end - size;
let block = &self.items[start..end];
let (first, last) =
unsafe { (block.get_unchecked(0), block.get_unchecked(block.len() - 1)) };
if query >= first && query <= last && block.binary_search(query).is_ok() {
return true;
}
}
size >>= 1; }
false
}
pub fn delete(&mut self, query: &T) -> Option<T> {
let mut size = 1;
while size <= self.items.len() {
if self.items.len() & size != 0 {
let end = self.items.len() & !(size - 1);
let start = end - size;
if let Ok(local_idx) = self.items[start..end].binary_search(query) {
let absolute_idx = start + local_idx;
let item = self.items.remove(absolute_idx);
self.items.sort_unstable();
return Some(item);
}
}
size <<= 1;
}
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_insert_and_contains() {
let mut arr = LogVec::new();
assert!(!arr.contains(&5));
arr.insert(5);
assert!(arr.contains(&5));
assert!(!arr.contains(&3));
arr.insert(3);
arr.insert(8);
arr.insert(1);
arr.insert(10);
for &val in &[1, 3, 5, 8, 10] {
assert!(arr.contains(&val), "Should contain {}", val);
}
assert!(!arr.contains(&2));
}
#[test]
fn test_deletion() {
let mut arr = LogVec::new();
for i in 0..10 {
arr.insert(i); }
assert!(arr.contains(&5));
assert!(arr.delete(&5).is_some());
assert!(!arr.contains(&5));
for i in 0..10 {
if i != 5 {
assert!(arr.contains(&i), "Should still contain {}", i);
}
}
assert!(arr.delete(&99).is_none());
}
#[test]
fn test_large_fuzz() {
let mut arr = LogVec::new();
for i in 0..1000 {
arr.insert(i);
}
for i in 0..1000 {
assert!(arr.contains(&i));
}
for i in (0..1000).step_by(2) {
arr.delete(&i); }
for i in 0..1000 {
assert_eq!(arr.contains(&i), i % 2 != 0);
}
}
#[test]
fn test_small_sort_path_insert() {
let mut arr = LogVec::new();
let mut seed = 0x1234_5678_9ABC_DEF0u64;
for _ in 0..1024 {
seed = seed
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
arr.insert((seed % 257) as i32);
}
for v in -1..260 {
let expected = arr.items.contains(&v);
assert_eq!(arr.contains(&v), expected);
}
}
}