diff --git a/benches/rpds_vector.rs b/benches/rpds_vector.rs index 1ab8cd0..0adef9e 100644 --- a/benches/rpds_vector.rs +++ b/benches/rpds_vector.rs @@ -91,6 +91,88 @@ fn rpds_vector_drop_last_mut(c: &mut Criterion) { }); } +fn rpds_vector_insert(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector insert", move |b| { + b.iter(|| { + let mut vector: Vector = Vector::new(); + + for i in 0..limit { + vector = vector.insert(vector.len() - i, i).unwrap(); + } + + vector + }); + }); +} + +fn rpds_vector_insert_mut(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector insert mut", move |b| { + b.iter(|| { + let mut vector: Vector = Vector::new(); + + for i in 0..limit { + vector.insert_mut(vector.len() - i, i); + } + + vector + }); + }); +} + +fn rpds_vector_remove(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector remove", move |b| { + b.iter_with_setup( + || { + let mut vector: Vector = Vector::new(); + + for i in 0..limit { + vector.push_back_mut(i); + } + + vector + }, + |mut vector| { + for i in (0..limit).rev() { + vector = vector.remove(vector.len() - i - 1).unwrap(); + } + + vector + }, + ); + }); +} + +fn rpds_vector_remove_mut(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector remove mut", move |b| { + b.iter_with_setup( + || { + let mut vector: Vector = Vector::new(); + + for i in 0..limit { + vector.push_back_mut(i); + } + + vector + }, + |mut vector| { + for i in (0..limit).rev() { + vector.remove_mut(vector.len() - i - 1); + } + + vector + }, + ); + }); +} + fn rpds_vector_get(c: &mut Criterion) { let limit = 100_000; let mut vector: Vector = Vector::new(); @@ -132,6 +214,10 @@ criterion_group!( rpds_vector_push_back_mut, rpds_vector_drop_last, rpds_vector_drop_last_mut, + rpds_vector_insert, + rpds_vector_insert_mut, + rpds_vector_remove, + rpds_vector_remove_mut, rpds_vector_get, rpds_vector_iterate ); diff --git a/benches/rpds_vector_sync.rs b/benches/rpds_vector_sync.rs index 6584573..a0c5e1c 100644 --- a/benches/rpds_vector_sync.rs +++ b/benches/rpds_vector_sync.rs @@ -91,6 +91,88 @@ fn rpds_vector_syncdrop_last_mut(c: &mut Criterion) { }); } +fn rpds_vector_syncinsert(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector sync insert", move |b| { + b.iter(|| { + let mut vector: VectorSync = VectorSync::new_sync(); + + for i in 0..limit { + vector = vector.insert(vector.len() - i, i).unwrap(); + } + + vector + }); + }); +} + +fn rpds_vector_syncinsert_mut(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector sync insert mut", move |b| { + b.iter(|| { + let mut vector: VectorSync = VectorSync::new_sync(); + + for i in 0..limit { + vector.insert_mut(vector.len() - i, i); + } + + vector + }); + }); +} + +fn rpds_vector_syncremove(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector sync remove", move |b| { + b.iter_with_setup( + || { + let mut vector: VectorSync = VectorSync::new_sync(); + + for i in 0..limit { + vector.push_back_mut(i); + } + + vector + }, + |mut vector| { + for i in (0..limit).rev() { + vector = vector.remove(vector.len() - i - 1).unwrap(); + } + + vector + }, + ); + }); +} + +fn rpds_vector_syncremove_mut(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("rpds vector sync remove mut", move |b| { + b.iter_with_setup( + || { + let mut vector: VectorSync = VectorSync::new_sync(); + + for i in 0..limit { + vector.push_back_mut(i); + } + + vector + }, + |mut vector| { + for i in (0..limit).rev() { + vector.remove_mut(vector.len() - i - 1); + } + + vector + }, + ); + }); +} + fn rpds_vector_syncget(c: &mut Criterion) { let limit = 1_000_000; let mut vector: VectorSync = VectorSync::new_sync(); @@ -132,6 +214,10 @@ criterion_group!( rpds_vector_syncpush_back_mut, rpds_vector_syncdrop_last, rpds_vector_syncdrop_last_mut, + rpds_vector_syncinsert, + rpds_vector_syncinsert_mut, + rpds_vector_syncremove, + rpds_vector_syncremove_mut, rpds_vector_syncget, rpds_vector_synciterate ); diff --git a/benches/std_vec.rs b/benches/std_vec.rs index a09e492..75be374 100644 --- a/benches/std_vec.rs +++ b/benches/std_vec.rs @@ -74,6 +74,47 @@ fn std_vec_reverse(c: &mut Criterion) { }); } +fn std_vec_insert(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("std vec insert", move |b| { + b.iter(|| { + let mut vector: Vec = Vec::new(); + + for i in 0..limit { + vector.insert(vector.len() - i, i); + } + + vector + }); + }); +} + +fn std_vec_remove(c: &mut Criterion) { + let limit = 1 << 12; + + c.bench_function("std vec remove", move |b| { + b.iter_with_setup( + || { + let mut vector: Vec = Vec::new(); + + for i in 0..limit { + vector.push(i); + } + + vector + }, + |mut vector| { + for i in (0..limit).rev() { + vector.remove(vector.len() - i - 1); + } + + vector + }, + ); + }); +} + fn std_vec_get(c: &mut Criterion) { let limit = 100_000; let mut vector: Vec = Vec::new(); @@ -108,5 +149,14 @@ fn std_vec_iterate(c: &mut Criterion) { }); } -criterion_group!(benches, std_vec_push, std_vec_pop, std_vec_reverse, std_vec_get, std_vec_iterate); +criterion_group!( + benches, + std_vec_push, + std_vec_pop, + std_vec_reverse, + std_vec_insert, + std_vec_remove, + std_vec_get, + std_vec_iterate +); criterion_main!(benches); diff --git a/src/vector/mod.rs b/src/vector/mod.rs index f3111fe..c6cc458 100644 --- a/src/vector/mod.rs +++ b/src/vector/mod.rs @@ -5,11 +5,13 @@ use alloc::borrow::Borrow; use alloc::fmt::Display; +use alloc::vec; use alloc::vec::Vec; use archery::*; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; +use core::mem; use core::ops::Index; use core::ops::IndexMut; @@ -85,6 +87,8 @@ macro_rules! vector_sync { /// | `push_back()` | Θ(log(n)) | Θ(log(n)) | /// | `drop_last()` | Θ(log(n)) | Θ(log(n)) | /// | `first()`/`last()`/`get()` | Θ(log(n)) | Θ(log(n)) | +/// | `insert()` | Θ(log(n)) | Θ(log(n)) | +/// | `remove()` | Θ(log(n)) | Θ(log(n)) | /// | `len()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(1) | Θ(1) | @@ -113,7 +117,7 @@ enum Node where P: SharedPointerKind, { - Branch(Vec, P>>), + Branch(Vec<(SharedPointer, P>, usize)>), Leaf(Vec>), } @@ -121,58 +125,41 @@ impl Node where P: SharedPointerKind, { - fn new_empty_branch() -> Node { - Node::Branch(Vec::new()) - } - fn new_empty_leaf() -> Node { Node::Leaf(Vec::new()) } - fn get usize>(&self, index: usize, height: usize, bucket: F) -> &T { - let b = bucket(index, height); - + fn get(&self, index: usize) -> &T { match self { - Node::Branch(a) => a[b].get(index, height - 1, bucket), - Node::Leaf(a) => { - debug_assert_eq!(height, 0); - a[b].as_ref() + Node::Branch(a) => { + let mut index = index; + for &(ref child, len) in a { + if index < len { + return child.get(index); + } + index -= len; + } + unreachable!() } + Node::Leaf(a) => a[index].as_ref(), } } - fn assoc usize>(&mut self, value: T, height: usize, bucket: F) { - let b = bucket(height); - + fn assoc(&mut self, value: T, index: usize) { match self { Node::Leaf(a) => { - debug_assert_eq!(height, 0, "cannot have a leaf at this height"); - - if a.len() == b { - a.push(SharedPointer::new(value)); - } else { - a[b] = SharedPointer::new(value); - } + a[index] = SharedPointer::new(value); } - Node::Branch(a) => { - debug_assert!(height > 0, "cannot have a branch at this height"); - - match a.get_mut(b) { - Some(subtree) => { - SharedPointer::make_mut(subtree).assoc(value, height - 1, bucket); - } - None => { - let mut subtree = if height > 1 { - Node::new_empty_branch() - } else { - Node::new_empty_leaf() - }; - - subtree.assoc(value, height - 1, bucket); - a.push(SharedPointer::new(subtree)); + let mut index = index; + for &mut (ref mut child, len) in a.iter_mut() { + if index < len { + SharedPointer::make_mut(child).assoc(value, index); + return; } + index -= len; } + unreachable!() } } } @@ -194,12 +181,309 @@ where } } + /// Returns the number of elements contained in the node's children. + fn len(&self) -> usize { + match self { + Node::Leaf(a) => a.len(), + Node::Branch(a) => a.iter().map(|(child, _)| child.len()).sum(), + } + } + + /// Inserts a value at the specified index in the node. If the node exceeds the length limit, + /// it splits the node and returns the additional node. + /// + /// # Arguments + /// + /// * `index` - The index at which to insert the value. + /// * `value` - The value to insert. + /// * `bucket_len_limit` - The maximum length of the node before it needs to be split. + /// + /// # Returns + /// + /// An `Option` containing the additional node if the node was split, or `None` if no split occurred. + fn insert(&mut self, index: usize, value: T, bucket_len_limit: usize) -> Option> { + match self { + Node::Leaf(values) => { + values.insert(index, SharedPointer::new(value)); + if values.len() > bucket_len_limit { + let additional_values = values.split_off(bucket_len_limit / 2); + Some(Node::Leaf(additional_values)) + } else { + None + } + } + Node::Branch(children) => { + let mut index = index; + let split_child = 'insertion: { + for (i, (child, len)) in children.iter_mut().enumerate() { + if index <= *len { + let child = SharedPointer::make_mut(child); + let split_child = + child.insert(index, value, bucket_len_limit).map(|n| (i, n)); + *len = child.len(); + break 'insertion split_child; + } + index -= *len; + } + unreachable!() + }; + + let (update_index, additional_child) = split_child?; + let &mut (ref child, ref mut len) = &mut children[update_index]; + *len = child.len(); + let child_len = additional_child.len(); + children + .insert(update_index + 1, (SharedPointer::new(additional_child), child_len)); + if children.len() > bucket_len_limit { + let additional_child = children.split_off(bucket_len_limit / 2); + Some(Node::Branch(additional_child)) + } else { + None + } + } + } + } + + fn push_back(&mut self, value: T, bucket_len_limit: usize) -> Option> { + match self { + Node::Leaf(values) => { + values.push(SharedPointer::new(value)); + if values.len() > bucket_len_limit { + let additional_values = values.split_off(bucket_len_limit / 2); + Some(Node::Leaf(additional_values)) + } else { + None + } + } + Node::Branch(children) => { + let last = children.last_mut().unwrap(); + let (last_children, last_len) = Self::pair_make_mut(last); + *last_len += 1; + let additional_child = last_children.push_back(value, bucket_len_limit); + if let Some(additional_child) = additional_child { + *last_len = last_children.len(); + let additional_child_len = additional_child.len(); + children.push((SharedPointer::new(additional_child), additional_child_len)); + if children.len() > bucket_len_limit { + let additional_child = children.split_off(bucket_len_limit / 2); + Some(Node::Branch(additional_child)) + } else { + None + } + } else { + None + } + } + } + } + + fn pair_make_mut( + v: &mut (SharedPointer, P>, usize), + ) -> (&mut Node, &mut usize) { + let (node, len) = v; + (SharedPointer::make_mut(node), len) + } + + /// Try to make the center node have at least `bucket_len_limit / 2` children by moving children from the left or right node. + /// + /// # Arguments + /// + /// * `left` - An optional mutable reference to a tuple containing a mutable reference to the left node and its length. + /// * `center` - A mutable reference to a tuple containing a mutable reference to the center node and its length. + /// * `right` - An optional mutable reference to a tuple containing a mutable reference to the right node and its length. + /// * `bucket_len_limit` - The maximum length of the node before it needs to be split. + /// + /// # Returns + /// + /// * `true` if the nodes were balanced, `false` otherwise. + fn balance( + left: Option<&mut (&mut Node, &mut usize)>, + center: &mut (&mut Node, &mut usize), + right: Option<&mut (&mut Node, &mut usize)>, + bucket_len_limit: usize, + ) -> bool { + match (left, center, right) { + (Some((left_node, left_len)), (center_node, center_len), _) + if left_node.used() > bucket_len_limit / 2 => + { + fn balance_with_left( + left: &mut Vec, + center: &mut Vec, + bucket_len_limit: usize, + ) { + let split_off_len = (left.len() - bucket_len_limit / 2).div_ceil(2); + let mut split_off_vec = left.split_off(left.len() - split_off_len); + split_off_vec.append(center); + *center = split_off_vec; + } + match (&mut *left_node, &mut *center_node) { + (Node::Leaf(left), Node::Leaf(center)) => { + balance_with_left(left, center, bucket_len_limit); + } + (Node::Branch(left), Node::Branch(center)) => { + balance_with_left(left, center, bucket_len_limit); + } + _ => unreachable!(), + } + **left_len = left_node.len(); + **center_len = center_node.len(); + true + } + (_, (center_node, center_len), Some((right_node, right_len))) + if right_node.used() > bucket_len_limit / 2 => + { + fn balance_with_right( + center: &mut Vec, + right: &mut Vec, + bucket_len_limit: usize, + ) { + let split_off_len = (right.len() - bucket_len_limit / 2).div_ceil(2); + let mut split_off_vec = right.split_off(split_off_len); + mem::swap(right, &mut split_off_vec); + center.extend(split_off_vec); + } + match (&mut *center_node, &mut *right_node) { + (Node::Leaf(center), Node::Leaf(right)) => { + balance_with_right(center, right, bucket_len_limit); + } + (Node::Branch(center), Node::Branch(right)) => { + balance_with_right(center, right, bucket_len_limit); + } + _ => unreachable!(), + } + **center_len = center_node.len(); + **right_len = right_node.len(); + true + } + _ => false, + } + } + + /// To delete the center node, move the children of the center node to the left or right node. + /// + /// # Arguments + /// + /// * `left` - An optional mutable reference to a tuple containing a mutable reference to the left node and its length. + /// * `center` - A mutable reference to a tuple containing a mutable reference to the center node and its length. + /// * `right` - An optional mutable reference to a tuple containing a mutable reference to the right node and its length. + /// * `bucket_len_limit` - The maximum length of the node before it needs to be split. + /// + /// # Panics + /// + /// This function will panic if the nodes cannot be merged within the length limit. + /// This function is called when balancing by moving elements has failed, so it will not panic. + fn drain_center( + left: Option<(&mut Node, &mut usize)>, + center: (&mut Node, &mut usize), + right: Option<(&mut Node, &mut usize)>, + bucket_len_limit: usize, + ) { + match (left, center, right) { + (Some((mut left_node, left_len)), (center_node, _), _) + if left_node.used() + center_node.used() <= bucket_len_limit => + { + match (&mut left_node, center_node) { + (Node::Leaf(left), Node::Leaf(center)) => left.append(center), + (Node::Branch(left), Node::Branch(center)) => left.append(center), + _ => unreachable!(), + } + *left_len = left_node.len(); + } + (_, (center_node, _), Some((mut right_node, right_len))) + if center_node.used() + right_node.used() <= bucket_len_limit => + { + match (center_node, &mut right_node) { + (Node::Leaf(center), Node::Leaf(right)) => { + center.append(right); + mem::swap(center, right); + } + (Node::Branch(center), Node::Branch(right)) => { + center.append(right); + mem::swap(center, right); + } + _ => unreachable!(), + } + *right_len = right_node.len(); + } + _ => unreachable!(), + } + } + + /// Removes an element at the specified index from the node. + /// + /// # Arguments + /// + /// * `index` - The index of the element to remove. + /// * `bucket_len_limit` - The maximum length of the node before it needs to be split. + /// + /// # Returns + /// + /// `true` if the node requires rebalancing after the removal, `false` otherwise. + /// + /// # Panics + /// + /// This function will panic if the index is out of bounds. + fn remove(&mut self, index: usize, bucket_len_limit: usize) -> bool { + match self { + Node::Leaf(values) => { + values.remove(index); + values.len() < bucket_len_limit / 2 + } + Node::Branch(children) => { + let mut index = index; + let (i, require_removal) = 'removal: { + for (i, (child, len)) in children.iter_mut().enumerate() { + if index < *len { + let require_removal = + SharedPointer::make_mut(child).remove(index, bucket_len_limit); + *len = child.len(); + break 'removal (i, require_removal); + } + index -= *len; + } + unreachable!() + }; + if !require_removal { + return false; + } + let (left, center, right) = match i { + 0 => { + let [center, right] = &mut children[..2] else { unreachable!() }; + (None, center, Some(right)) + } + i if i < children.len() - 1 => { + let [left, center, right] = &mut children[i - 1..=i + 1] else { + unreachable!() + }; + (Some(left), center, Some(right)) + } + _ => { + let slice_start = children.len() - 2; + let [left, center] = &mut children[slice_start..] else { unreachable!() }; + (Some(left), center, None) + } + }; + let (mut left, mut center, mut right) = ( + left.map(Self::pair_make_mut), + Self::pair_make_mut(center), + right.map(Self::pair_make_mut), + ); + if Self::balance(left.as_mut(), &mut center, right.as_mut(), bucket_len_limit) { + return false; + } + Self::drain_center(left, center, right, bucket_len_limit); + children.remove(i); + children.len() < bucket_len_limit / 2 + } + } + } + /// Drops the last element. /// /// This will return `true` if the subtree after drop becomes empty (or it already was empty). /// Note that this will prune irrelevant branches, i.e. there will be no branches without /// elements under it. - fn drop_last(&mut self) -> bool { + fn drop_last(&mut self, bucket_len_limit: usize) -> bool { if self.is_empty() { return true; } @@ -210,9 +494,21 @@ where } Node::Branch(a) => { - if SharedPointer::make_mut(a.last_mut().unwrap()).drop_last() { + let (last_node, last_len) = a.last_mut().unwrap(); + *last_len -= 1; + if SharedPointer::make_mut(last_node).drop_last(bucket_len_limit) { a.pop(); } + if a.len() >= 2 && a.last().unwrap().0.used() < bucket_len_limit / 2 { + let range_start = a.len() - 2; + let [left, center] = &mut a[range_start..] else { unreachable!() }; + let mut left = Self::pair_make_mut(left); + let mut center = Self::pair_make_mut(center); + if !Self::balance(Some(&mut left), &mut center, None, bucket_len_limit) { + Self::drain_center(Some(left), center, None, bucket_len_limit); + a.pop(); + } + } } } @@ -224,22 +520,19 @@ impl Node where P: SharedPointerKind, { - fn get_mut usize>( - &mut self, - index: usize, - height: usize, - bucket: F, - ) -> &mut T { - let b = bucket(index, height); - - match *self { - Node::Branch(ref mut a) => { - SharedPointer::make_mut(&mut a[b]).get_mut(index, height - 1, bucket) - } - Node::Leaf(ref mut a) => { - debug_assert_eq!(height, 0); - SharedPointer::make_mut(&mut a[b]) + fn get_mut(&mut self, index: usize) -> &mut T { + match self { + Node::Branch(a) => { + let mut index = index; + for &mut (ref mut child, len) in a.iter_mut() { + if index < len { + return SharedPointer::make_mut(child).get_mut(index); + } + index -= len; + } + unreachable!() } + Node::Leaf(a) => SharedPointer::make_mut(&mut a[index]), } } } @@ -261,16 +554,6 @@ mod vector_utils { pub fn degree(bits: u8) -> usize { 1 << bits } - - #[inline] - pub fn mask(bits: u8) -> usize { - degree(bits) - 1 - } - - #[inline] - pub fn bucket(bits: u8, index: usize, height: usize) -> usize { - (index >> (height * bits as usize)) & mask(bits) - } } impl VectorSync { @@ -318,11 +601,11 @@ where } #[inline] - fn height(&self) -> usize { + fn estimate_height(&self) -> usize { if self.length > 1 { let u: usize = self.length - 1; let c: usize = usize::BITS as usize - u.leading_zeros() as usize; - let b: usize = self.bits as usize; + let b: usize = self.bits as usize - 1; c / b + usize::from(c % b > 0) - 1 } else { @@ -335,9 +618,7 @@ where if index >= self.length { None } else { - Some(self.root.get(index, self.height(), |index, height| { - vector_utils::bucket(self.bits, index, height) - })) + Some(self.root.get(index)) } } @@ -362,43 +643,83 @@ where } } + #[must_use] + pub fn insert(&self, index: usize, v: T) -> Option> { + let mut new_vector = self.clone(); + + if new_vector.insert_mut(index, v) { + Some(new_vector) + } else { + None + } + } + + /// Returns `true` if the operation was successful. + pub fn insert_mut(&mut self, index: usize, v: T) -> bool { + if index > self.length { + return false; + } + + let bucket_len_limit = self.bucket_len_limit(); + self.length += 1; + let root = SharedPointer::make_mut(&mut self.root); + let Some(additional_node) = root.insert(index, v, bucket_len_limit) else { + return true; + }; + let root_len = root.len(); + let additional_node_len = additional_node.len(); + let new_root = Node::Branch(vec![ + (SharedPointer::clone(&self.root), root_len), + (SharedPointer::new(additional_node), additional_node_len), + ]); + self.root = SharedPointer::new(new_root); + + true + } + + #[must_use] + pub fn remove(&self, index: usize) -> Option> { + let mut new_vector = self.clone(); + + if new_vector.remove_mut(index) { + Some(new_vector) + } else { + None + } + } + + /// Returns `true` if the operation was successful. + pub fn remove_mut(&mut self, index: usize) -> bool { + if index >= self.length { + return false; + } + + let bucket_len_limit = self.bucket_len_limit(); + self.length -= 1; + let root = SharedPointer::make_mut(&mut self.root); + if root.remove(index, bucket_len_limit) { + if let Some(new_root) = Vector::compress_root(root) { + self.root = new_root; + } + } + + true + } + /// Sets the given index to v. /// /// # Panics /// /// This method will panic if the trie's root doesn't have capacity for the given index. fn assoc(&mut self, index: usize, v: T) { - debug_assert!( - index < self.root_max_capacity(), - "This trie's root cannot support this index" - ); - - let height = self.height(); - let bits = self.bits; - SharedPointer::make_mut(&mut self.root) - .assoc(v, height, |height| vector_utils::bucket(bits, index, height)); - let adds_item: bool = index >= self.length; - - if adds_item { - self.length += 1; - } - } + debug_assert!(index < self.len(), "This vector's root cannot support this index"); - #[inline] - fn root_max_capacity(&self) -> usize { - /* A Trie's root max capacity is - * - * degree ** (height + 1) - * = (2 ** bits) ** (height + 1) (by def. of degree) - * = 2 ** (bits * (height + 1)) - * = 1 << (bits * (height + 1)) - */ - 1 << (self.bits as usize * (self.height() + 1)) + SharedPointer::make_mut(&mut self.root).assoc(v, index); } #[inline] - fn is_root_full(&self) -> bool { - self.length == self.root_max_capacity() + fn bucket_len_limit(&self) -> usize { + vector_utils::degree(self.bits) } #[must_use] @@ -411,23 +732,19 @@ where } pub fn push_back_mut(&mut self, v: T) { - if self.is_root_full() { - let mut new_root: Node = Node::new_empty_branch(); - - match new_root { - Node::Branch(ref mut values) => values.push(SharedPointer::clone(&self.root)), - Node::Leaf(_) => unreachable!("expected a branch"), - } - - let length = self.length; - self.root = SharedPointer::new(new_root); - self.length += 1; - - self.assoc(length, v); - } else { - let length = self.length; - self.assoc(length, v); - } + let bucket_len_limit = self.bucket_len_limit(); + self.length += 1; + let root = SharedPointer::make_mut(&mut self.root); + let Some(additional_node) = root.push_back(v, bucket_len_limit) else { + return; + }; + let root_len = root.len(); + let additional_node_len = additional_node.len(); + let new_root = Node::Branch(vec![ + (SharedPointer::clone(&self.root), root_len), + (SharedPointer::new(additional_node), additional_node_len), + ]); + self.root = SharedPointer::new(new_root); } /// Compresses a root. A root is compressed if, whenever there is a branch, it has more than @@ -439,7 +756,7 @@ where match root { Node::Leaf(_) => None, - Node::Branch(a) if singleton => a.pop(), + Node::Branch(a) if singleton => a.pop().map(|(n, _)| n), Node::Branch(_) => None, } } @@ -458,9 +775,10 @@ where pub fn drop_last_mut(&mut self) -> bool { if self.length > 0 { let new_root = { + let bucket_len_limit = self.bucket_len_limit(); let root = SharedPointer::make_mut(&mut self.root); - root.drop_last(); + root.drop_last(bucket_len_limit); self.length -= 1; Vector::compress_root(root) @@ -509,13 +827,7 @@ where if index >= self.length { None } else { - let height = self.height(); - let bits = self.bits; - Some( - SharedPointer::make_mut(&mut self.root).get_mut(index, height, |index, height| { - vector_utils::bucket(bits, index, height) - }), - ) + Some(SharedPointer::make_mut(&mut self.root).get_mut(index)) } } } @@ -693,7 +1005,7 @@ where fn current_node(&self) -> &'a Node { #[allow(clippy::cast_sign_loss)] match self.node { - Node::Branch(a) => a[self.index as usize].as_ref(), + Node::Branch(a) => a[self.index as usize].0.as_ref(), Node::Leaf(_) => panic!("called current node of a branch"), } } @@ -759,7 +1071,7 @@ where if stack_field.is_none() { let mut stack: Vec> = - Vec::with_capacity(self.vector.height() + 1); + Vec::with_capacity(self.vector.estimate_height() + 1); stack.push(IterStackElement::new(self.vector.root.borrow(), backwards)); diff --git a/src/vector/test.rs b/src/vector/test.rs index 3c3e297..497eb62 100644 --- a/src/vector/test.rs +++ b/src/vector/test.rs @@ -34,19 +34,6 @@ mod node { use super::*; use pretty_assertions::assert_eq; - #[test] - fn test_new_empty_branch() { - let node: Node = Node::new_empty_branch(); - - match node { - Node::Branch(a) => { - assert_eq!(a.len(), 0); - assert_eq!(a.capacity(), 0, "Capacity of the branch array is wasteful"); - } - Node::Leaf(_) => panic!("Invalid node type"), - } - } - #[test] fn test_new_empty_leaf() { let node: Node = Node::new_empty_leaf(); @@ -63,14 +50,14 @@ mod node { #[test] fn test_drop_last_single_level() { let mut empty_leaf: Node = Node::new_empty_leaf(); - let mut empty_branch: Node = Node::new_empty_branch(); + let mut empty_branch: Node = Node::Branch(Vec::new()); let mut singleton_node: Node = vector![0].root.as_ref().clone(); let mut one_level_node: Node = vector![0, 1].root.as_ref().clone(); - assert!(empty_leaf.drop_last()); - assert!(empty_branch.drop_last()); - assert!(singleton_node.drop_last()); - assert!(!one_level_node.drop_last()); + assert!(empty_leaf.drop_last(32)); + assert!(empty_branch.drop_last(32)); + assert!(singleton_node.drop_last(32)); + assert!(!one_level_node.drop_last(32)); assert_eq!(one_level_node.used(), 1); } @@ -88,38 +75,557 @@ mod node { .clone(); let node_three_after_drop = { - let a_leaf = vec![SharedPointer::new(0), SharedPointer::new(1)]; + let a_leaf0 = vec![SharedPointer::new(0)]; + let a_leaf1 = vec![SharedPointer::new(1)]; - let leaf = Node::Leaf(a_leaf); + let leaf0 = Node::Leaf(a_leaf0); + let leaf1 = Node::Leaf(a_leaf1); - let a_branch = vec![SharedPointer::new(leaf)]; + let a_branch = vec![(SharedPointer::new(leaf0), 1), (SharedPointer::new(leaf1), 1)]; Node::Branch(a_branch) }; let node_four_after_drop = { - let a_leaf_0 = vec![SharedPointer::new(0), SharedPointer::new(1)]; + let a_leaf_0 = vec![SharedPointer::new(0)]; + let a_leaf_1 = vec![SharedPointer::new(1)]; + let a_leaf_2 = vec![SharedPointer::new(2)]; let leaf_0 = Node::Leaf(a_leaf_0); + let leaf_1 = Node::Leaf(a_leaf_1); + let leaf_2 = Node::Leaf(a_leaf_2); - let a_leaf_1 = { - let mut a = Vec::with_capacity(2); - a.push(SharedPointer::new(2)); - a - }; + let a_branch0 = vec![(SharedPointer::new(leaf_0), 1)]; + let a_branch1 = vec![(SharedPointer::new(leaf_1), 1), (SharedPointer::new(leaf_2), 1)]; - let leaf_1 = Node::Leaf(a_leaf_1); + let branch0 = Node::Branch(a_branch0); + let branch1 = Node::Branch(a_branch1); - let a_branch = vec![SharedPointer::new(leaf_0), SharedPointer::new(leaf_1)]; + let a_branch = vec![(SharedPointer::new(branch0), 1), (SharedPointer::new(branch1), 2)]; Node::Branch(a_branch) }; - assert!(!node_three.drop_last()); + let vector = Vector::::new_with_bits(1); + let limit_len = vector.bucket_len_limit(); + assert!(!node_three.drop_last(limit_len)); assert_eq!(node_three, node_three_after_drop); - assert!(!node_four.drop_last()); + assert!(!node_four.drop_last(limit_len)); assert_eq!(node_four, node_four_after_drop); } + + #[test] + fn test_insert_node_internal() { + let mut vector: Vector = Vector::new_with_bits(2) + .push_back(0) + .push_back(1) + .push_back(2) + .push_back(3) + .push_back(4); + let mut vec = vec![0, 1, 2, 3, 4]; + + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(0), + SharedPointer::new(1), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(2), + SharedPointer::new(3), + SharedPointer::new(4), + ])), + 3 + ), + ]) + ); + + // The node does not change due to the insert operation + vector.insert_mut(2, 5); + vector.insert_mut(2, 6); + vec.insert(2, 5); + vec.insert(2, 6); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(0), + SharedPointer::new(1), + SharedPointer::new(6), + SharedPointer::new(5), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(2), + SharedPointer::new(3), + SharedPointer::new(4), + ])), + 3 + ), + ]) + ); + + // The Leaf node is split by the insert operation + vector.insert_mut(0, 7); + vec.insert(0, 7); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(7), + SharedPointer::new(0), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(1), + SharedPointer::new(6), + SharedPointer::new(5), + ])), + 3 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(2), + SharedPointer::new(3), + SharedPointer::new(4), + ])), + 3 + ), + ]) + ); + + // The Leaf node is split by the insert operation + vector.insert_mut(8, 8); + vector.insert_mut(9, 9); + vec.insert(8, 8); + vec.insert(9, 9); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(7), + SharedPointer::new(0), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(1), + SharedPointer::new(6), + SharedPointer::new(5), + ])), + 3 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(2), + SharedPointer::new(3), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(4), + SharedPointer::new(8), + SharedPointer::new(9), + ])), + 3 + ), + ]) + ); + + // The Leaf node is split by the insert operation, and the Branch node is also split + vector.insert_mut(8, 10); + vector.insert_mut(8, 11); + vec.insert(8, 10); + vec.insert(8, 11); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(7), + SharedPointer::new(0), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(1), + SharedPointer::new(6), + SharedPointer::new(5), + ])), + 3 + ), + ])), + 5 + ), + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(2), + SharedPointer::new(3), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(4), + SharedPointer::new(11), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(10), + SharedPointer::new(8), + SharedPointer::new(9), + ])), + 3 + ), + ])), + 7 + ), + ]) + ); + } + + #[test] + fn test_remove_node_internal() { + let mut vector: Vector = Vector::new_with_bits(2) + .push_back(0) + .push_back(1) + .push_back(4) + .push_back(5) + .push_back(8) + .push_back(9) + .push_back(12) + .push_back(13) + .push_back(16) + .push_back(17) + .push_back(18) + .insert(2, 2) + .unwrap() + .insert(3, 3) + .unwrap() + .insert(6, 6) + .unwrap() + .insert(7, 7) + .unwrap() + .insert(10, 10) + .unwrap() + .insert(11, 11) + .unwrap() + .insert(14, 14) + .unwrap() + .insert(15, 15) + .unwrap() + .insert(19, 19) + .unwrap(); + let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]; + + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(0), + SharedPointer::new(1), + SharedPointer::new(2), + SharedPointer::new(3), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(4), + SharedPointer::new(5), + SharedPointer::new(6), + SharedPointer::new(7), + ])), + 4 + ), + ])), + 8 + ), + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(8), + SharedPointer::new(9), + SharedPointer::new(10), + SharedPointer::new(11), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(12), + SharedPointer::new(13), + SharedPointer::new(14), + SharedPointer::new(15), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(16), + SharedPointer::new(17), + SharedPointer::new(18), + SharedPointer::new(19), + ])), + 4 + ), + ])), + 12 + ), + ]) + ); + + // The element of the Leaf node moves from right to left due to the remove operation + vector.remove_mut(11); + vector.remove_mut(10); + vector.remove_mut(9); + vec.remove(11); + vec.remove(10); + vec.remove(9); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(0), + SharedPointer::new(1), + SharedPointer::new(2), + SharedPointer::new(3), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(4), + SharedPointer::new(5), + SharedPointer::new(6), + SharedPointer::new(7), + ])), + 4 + ), + ])), + 8 + ), + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(8), + SharedPointer::new(12), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(13), + SharedPointer::new(14), + SharedPointer::new(15), + ])), + 3 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(16), + SharedPointer::new(17), + SharedPointer::new(18), + SharedPointer::new(19), + ])), + 4 + ), + ])), + 9 + ), + ]) + ); + + // The element of the Leaf node moves from left to right due to the remove operation + vector.remove_mut(16); + vector.remove_mut(15); + vector.remove_mut(14); + vec.remove(16); + vec.remove(15); + vec.remove(14); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(0), + SharedPointer::new(1), + SharedPointer::new(2), + SharedPointer::new(3), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(4), + SharedPointer::new(5), + SharedPointer::new(6), + SharedPointer::new(7), + ])), + 4 + ), + ])), + 8 + ), + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(8), + SharedPointer::new(12), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(13), + SharedPointer::new(14), + ])), + 2 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(15), + SharedPointer::new(16), + ])), + 2 + ), + ])), + 6 + ), + ]) + ); + + // The Leaf node is merged with the right neighbor due to the remove operation + vector.remove_mut(8); + vec.remove(8); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(0), + SharedPointer::new(1), + SharedPointer::new(2), + SharedPointer::new(3), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(4), + SharedPointer::new(5), + SharedPointer::new(6), + SharedPointer::new(7), + ])), + 4 + ), + ])), + 8 + ), + ( + SharedPointer::new(Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(12), + SharedPointer::new(13), + SharedPointer::new(14), + ])), + 3 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(15), + SharedPointer::new(16), + ])), + 2 + ), + ])), + 5 + ), + ]) + ); + + // The Leaf node is merged with the left neighbor, and the Branch node is also merged due to the remove operation + vector.remove_mut(11); + vector.remove_mut(11); + vec.remove(11); + vec.remove(11); + assert!(vector.iter().copied().eq(vec.iter().copied())); + assert_eq!( + vector.root.as_ref(), + &Node::Branch(vec![ + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(0), + SharedPointer::new(1), + SharedPointer::new(2), + SharedPointer::new(3), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(4), + SharedPointer::new(5), + SharedPointer::new(6), + SharedPointer::new(7), + ])), + 4 + ), + ( + SharedPointer::new(Node::Leaf(vec![ + SharedPointer::new(12), + SharedPointer::new(13), + SharedPointer::new(14), + ])), + 3 + ), + ]) + ); + } } mod iter { @@ -285,48 +791,26 @@ mod internal { } #[test] - fn test_height() { - assert_eq!(dummy_vector_with_length(0).height(), 0); - assert_eq!(dummy_vector_with_length(5).height(), 0); - assert_eq!(dummy_vector_with_length(32).height(), 0); - assert_eq!(dummy_vector_with_length(33).height(), 1); - assert_eq!(dummy_vector_with_length(64).height(), 1); - assert_eq!(dummy_vector_with_length(128).height(), 1); - assert_eq!(dummy_vector_with_length(512).height(), 1); - assert_eq!(dummy_vector_with_length(1024).height(), 1); - assert_eq!(dummy_vector_with_length(1025).height(), 2); - assert_eq!(dummy_vector_with_length(32_768).height(), 2); - assert_eq!(dummy_vector_with_length(32_769).height(), 3); - assert_eq!(dummy_vector_with_length(1_048_576).height(), 3); - assert_eq!(dummy_vector_with_length(1_048_577).height(), 4); - } - - #[test] - fn test_mask() { - use vector_utils::mask; - - assert_eq!(mask(1), 0b00001); - assert_eq!(mask(2), 0b00011); - assert_eq!(mask(3), 0b00111); - assert_eq!(mask(4), 0b01111); - assert_eq!(mask(5), 0b11111); - } - - #[allow(clippy::unusual_byte_groupings)] - #[test] - fn test_bucket() { - use vector_utils::bucket; - - assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 0), 0b00001); - assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 1), 0b00010); - assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 2), 0b00011); - assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 3), 0b00100); + fn test_estimate_height() { + assert_eq!(dummy_vector_with_length(0).estimate_height(), 0); + assert_eq!(dummy_vector_with_length(5).estimate_height(), 0); + assert_eq!(dummy_vector_with_length(16).estimate_height(), 0); + assert_eq!(dummy_vector_with_length(17).estimate_height(), 1); + assert_eq!(dummy_vector_with_length(64).estimate_height(), 1); + assert_eq!(dummy_vector_with_length(128).estimate_height(), 1); + assert_eq!(dummy_vector_with_length(192).estimate_height(), 1); + assert_eq!(dummy_vector_with_length(256).estimate_height(), 1); + assert_eq!(dummy_vector_with_length(257).estimate_height(), 2); + assert_eq!(dummy_vector_with_length(4_096).estimate_height(), 2); + assert_eq!(dummy_vector_with_length(4_097).estimate_height(), 3); + assert_eq!(dummy_vector_with_length(65_536).estimate_height(), 3); + assert_eq!(dummy_vector_with_length(65_537).estimate_height(), 4); } #[test] fn test_compress_root() { let empty_leaf: Node = Node::new_empty_leaf(); - let empty_branch: Node = Node::new_empty_branch(); + let empty_branch: Node = Node::Branch(Vec::new()); let singleton_leaf: Node = vector![0].root.as_ref().clone(); let compressed_branch: Node = Vector::new_with_bits(1).push_back(0).push_back(1).push_back(3).root.as_ref().clone(); @@ -336,7 +820,7 @@ mod internal { let a_branch = { let mut a = Vec::with_capacity(2); - a.push(SharedPointer::new(leaf.clone())); + a.push((SharedPointer::new(leaf.clone()), 2)); a }; @@ -352,30 +836,6 @@ mod internal { Some(SharedPointer::new(uncompressed_branch_leaf)), ); } - - #[test] - fn test_root_max_capacity() { - assert_eq!(dummy_vector_with_length(0).root_max_capacity(), 32); - assert_eq!(dummy_vector_with_length(5).root_max_capacity(), 32); - assert_eq!(dummy_vector_with_length(32).root_max_capacity(), 32); - assert_eq!(dummy_vector_with_length(33).root_max_capacity(), 1024); - assert_eq!(dummy_vector_with_length(1024).root_max_capacity(), 1024); - assert_eq!(dummy_vector_with_length(1025).root_max_capacity(), 32_768); - assert_eq!(dummy_vector_with_length(32_768).root_max_capacity(), 32_768); - assert_eq!(dummy_vector_with_length(32_769).root_max_capacity(), 1_048_576); - } - - #[test] - fn test_is_root_full() { - assert!(!dummy_vector_with_length(0).is_root_full()); - assert!(!dummy_vector_with_length(5).is_root_full()); - assert!(dummy_vector_with_length(32).is_root_full()); - assert!(!dummy_vector_with_length(33).is_root_full()); - assert!(dummy_vector_with_length(1024).is_root_full()); - assert!(!dummy_vector_with_length(1025).is_root_full()); - assert!(dummy_vector_with_length(32_768).is_root_full()); - assert!(!dummy_vector_with_length(32_769).is_root_full()); - } } #[test] @@ -519,6 +979,52 @@ fn test_set_out_of_bounds() { assert_eq!(singleton_vector.set(1, 0), None); } +#[test] +fn test_insert() { + let limit = 4 * 4 * 4; + for base_len in 0..limit { + let mut vector: Vector = Vector::new_with_bits(2); + for i in 0..base_len { + vector.push_back_mut(i); + } + + let vec = (0..base_len).collect::>(); + + for i in 0..=base_len { + let vector = vector.insert(i as usize, i).unwrap(); + let mut vec = vec.clone(); + vec.insert(i as usize, i); + + assert!(vector.iter().copied().eq(vec)); + } + + assert!(vector.insert(base_len as usize + 1, 0).is_none()); + } +} + +#[test] +fn test_remove() { + let limit = 4 * 4 * 4; + for base_len in 1..=limit { + let mut vector: Vector = Vector::new_with_bits(2); + for i in 0..base_len { + vector.push_back_mut(i); + } + + let vec = (0..base_len).collect::>(); + + for i in 0..base_len { + let vector = vector.remove(i as usize).unwrap(); + let mut vec = vec.clone(); + vec.remove(i as usize); + + assert!(vector.iter().copied().eq(vec)); + } + + assert!(vector.remove(base_len as usize).is_none()); + } +} + #[test] fn test_get() { let limit = 32 * 32 * 32 + 1;