diff --git a/crates/utils/benches/interval_map.rs b/crates/utils/benches/interval_map.rs index 398f156b5..02953eb97 100644 --- a/crates/utils/benches/interval_map.rs +++ b/crates/utils/benches/interval_map.rs @@ -1,3 +1,4 @@ +#![cfg(bench)] #![feature(test)] extern crate test; @@ -7,7 +8,7 @@ use std::hint::black_box; use test::Bencher; -use utils::array_interval_map::{Interval, IntervalMap}; +use utils::interval_map::{Interval, IntervalMap}; struct Rng { state: u32, diff --git a/crates/utils/src/array_interval_map/mod.rs b/crates/utils/src/array_interval_map/mod.rs deleted file mode 100644 index 257561e6a..000000000 --- a/crates/utils/src/array_interval_map/mod.rs +++ /dev/null @@ -1,988 +0,0 @@ -#![allow(clippy::shadow_unrelated)] - -use petgraph::graph::{DefaultIx, IndexType, NodeIndex}; - -#[cfg(test)] -mod tests; - -/// An interval-value map, which support operations on dynamic sets of intervals. -#[derive(Debug)] -pub struct IntervalMap { - /// Vector that stores nodes - nodes: Vec>, - /// Root of the interval tree - root: NodeIndex, - /// Number of elements in the map - len: usize, -} - -impl IntervalMap -where - T: Clone + Ord, - Ix: IndexType, -{ - /// Creates a new `IntervalMap` with estimated capacity. - #[inline] - #[must_use] - pub fn with_capacity(capacity: usize) -> Self { - let mut nodes = vec![Self::new_sentinel()]; - nodes.reserve(capacity); - IntervalMap { - nodes, - root: Self::sentinel(), - len: 0, - } - } - - /// Inserts a interval-value pair into the map. - /// - /// # Panics - /// - /// This method panics when the tree is at the maximum number of nodes for its index - #[inline] - pub fn insert(&mut self, interval: Interval, value: V) -> Option { - let node = Self::new_node(interval, value); - let node_idx = NodeIndex::new(self.nodes.len()); - // check for max capacity, except if we use usize - assert!( - ::max().index() == !0 || NodeIndex::end() != node_idx, - "Reached maximum number of nodes" - ); - self.nodes.push(node); - self.insert_inner(node_idx) - } - - /// Removes a interval from the map, returning the value at the interval if the interval - /// was previously in the map. - #[inline] - pub fn remove(&mut self, interval: &Interval) -> Option { - if let Some(node_idx) = self.search_exact(interval) { - self.remove_inner(node_idx); - let mut node = self.nodes.swap_remove(node_idx.index()); - let old = NodeIndex::::new(self.nodes.len()); - self.update_idx(old, node_idx); - return node.value.take(); - } - None - } - - /// Checks if an interval in the map overlaps with the given interval. - #[inline] - pub fn overlap(&self, interval: &Interval) -> bool { - let node_idx = self.search(interval); - !self.nref(node_idx, Node::is_sentinel) - } - - /// Finds all intervals in the map that overlaps with the given interval. - #[inline] - pub fn find_all_overlap(&self, interval: &Interval) -> Vec<&Interval> { - self.find_all_overlap_inner(self.root, interval) - } - - /// Returns a reference to the value corresponding to the key. - #[inline] - pub fn get(&self, interval: &Interval) -> Option<&V> { - self.search_exact(interval) - .map(|idx| self.nref(idx, Node::value)) - } - - /// Returns a reference to the value corresponding to the key. - #[inline] - pub fn get_mut(&mut self, interval: &Interval) -> Option<&mut V> { - self.search_exact(interval) - .map(|idx| self.nmut(idx, Node::value_mut)) - } - - /// Gets an iterator over the entries of the map, sorted by key. - #[inline] - #[must_use] - pub fn iter(&self) -> Iter<'_, T, V, Ix> { - Iter { - map_ref: self, - stack: None, - } - } - - /// Gets the given key's corresponding entry in the map for in-place manipulation. - #[inline] - pub fn entry(&mut self, interval: Interval) -> Entry<'_, T, V, Ix> { - match self.search_exact(&interval) { - Some(node) => Entry::Occupied(OccupiedEntry { - map_ref: self, - node, - }), - None => Entry::Vacant(VacantEntry { - map_ref: self, - interval, - }), - } - } - - /// Returns the number of elements in the map. - #[inline] - #[must_use] - pub fn len(&self) -> usize { - self.len - } - - /// Returns `true` if the map contains no elements. - #[inline] - #[must_use] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } -} - -impl IntervalMap -where - T: Clone + Ord, -{ - /// Creates an empty `IntervalMap` - #[must_use] - #[inline] - pub fn new() -> Self { - Self { - nodes: vec![Self::new_sentinel()], - root: Self::sentinel(), - len: 0, - } - } -} - -impl Default for IntervalMap -where - T: Clone + Ord, -{ - #[inline] - fn default() -> Self { - Self::with_capacity(0) - } -} - -impl IntervalMap -where - T: Clone + Ord, - Ix: IndexType, -{ - /// Creates a new sentinel node - fn new_sentinel() -> Node { - Node { - interval: None, - value: None, - max: None, - left: None, - right: None, - parent: None, - color: Color::Black, - } - } - - /// Creates a new tree node - fn new_node(interval: Interval, value: V) -> Node { - Node { - max: Some(interval.high.clone()), - interval: Some(interval), - value: Some(value), - left: Some(Self::sentinel()), - right: Some(Self::sentinel()), - parent: Some(Self::sentinel()), - color: Color::Red, - } - } - - /// Gets the sentinel node index - fn sentinel() -> NodeIndex { - NodeIndex::new(0) - } -} - -impl IntervalMap -where - T: Ord + Clone, - Ix: IndexType, -{ - /// Inserts a node into the tree. - fn insert_inner(&mut self, z: NodeIndex) -> Option { - let mut y = Self::sentinel(); - let mut x = self.root; - - while !self.nref(x, Node::is_sentinel) { - y = x; - if self.nref(z, Node::interval) == self.nref(y, Node::interval) { - let zval = self.nmut(z, Node::take_value); - let old_value = self.nmut(y, Node::set_value(zval)); - return Some(old_value); - } - if self.nref(z, Node::interval) < self.nref(x, Node::interval) { - x = self.nref(x, Node::left); - } else { - x = self.nref(x, Node::right); - } - } - self.nmut(z, Node::set_parent(y)); - if self.nref(y, Node::is_sentinel) { - self.root = z; - } else { - if self.nref(z, Node::interval) < self.nref(y, Node::interval) { - self.nmut(y, Node::set_left(z)); - } else { - self.nmut(y, Node::set_right(z)); - } - self.update_max_bottom_up(y); - } - self.nmut(z, Node::set_color(Color::Red)); - - self.insert_fixup(z); - - self.len = self.len.wrapping_add(1); - None - } - - /// Removes a node from the tree. - fn remove_inner(&mut self, z: NodeIndex) { - let mut y = z; - let mut y_orig_color = self.nref(y, Node::color); - let x; - if self.left_ref(z, Node::is_sentinel) { - x = self.nref(z, Node::right); - self.transplant(z, x); - } else if self.right_ref(z, Node::is_sentinel) { - x = self.nref(z, Node::left); - self.transplant(z, x); - } else { - y = self.tree_minimum(self.nref(z, Node::right)); - y_orig_color = self.nref(y, Node::color); - x = self.nref(y, Node::right); - if self.nref(y, Node::parent) == z { - self.nmut(x, Node::set_parent(y)); - } else { - self.transplant(y, x); - self.nmut(y, Node::set_right(self.nref(z, Node::right))); - self.right_mut(y, Node::set_parent(y)); - } - self.transplant(z, y); - self.nmut(y, Node::set_left(self.nref(z, Node::left))); - self.left_mut(y, Node::set_parent(y)); - self.nmut(y, Node::set_color(self.nref(z, Node::color))); - - self.update_max_bottom_up(y); - } - - if matches!(y_orig_color, Color::Black) { - self.remove_fixup(x); - } - - self.len = self.len.wrapping_sub(1); - } - - /// Finds all intervals in the map that overlaps with the given interval. - fn find_all_overlap_inner( - &self, - x: NodeIndex, - interval: &Interval, - ) -> Vec<&Interval> { - let mut list = vec![]; - if self.nref(x, Node::interval).overlap(interval) { - list.push(self.nref(x, Node::interval)); - } - if self - .left_ref(x, Node::sentinel) - .map(Node::max) - .is_some_and(|lm| lm >= &interval.low) - { - list.extend(self.find_all_overlap_inner(self.nref(x, Node::left), interval)); - } - if self - .right_ref(x, Node::sentinel) - .map(|r| IntervalRef::new(&self.nref(x, Node::interval).low, r.max())) - .is_some_and(|i| i.overlap(interval)) - { - list.extend(self.find_all_overlap_inner(self.nref(x, Node::right), interval)); - } - list - } - - /// Search for an interval that overlaps with the given interval. - fn search(&self, interval: &Interval) -> NodeIndex { - let mut x = self.root; - while self - .nref(x, Node::sentinel) - .map(Node::interval) - .is_some_and(|xi| !xi.overlap(interval)) - { - if self - .left_ref(x, Node::sentinel) - .map(Node::max) - .is_some_and(|lm| lm > &interval.low) - { - x = self.nref(x, Node::left); - } else { - x = self.nref(x, Node::right); - } - } - x - } - - /// Search for the node with exact the given interval - fn search_exact(&self, interval: &Interval) -> Option> { - let mut x = self.root; - while !self.nref(x, Node::is_sentinel) { - if self.nref(x, Node::interval) == interval { - return Some(x); - } - if self.nref(x, Node::max) < &interval.high { - return None; - } - if self.nref(x, Node::interval) > interval { - x = self.nref(x, Node::left); - } else { - x = self.nref(x, Node::right); - } - } - None - } - - /// Restores red-black tree properties after an insert. - fn insert_fixup(&mut self, mut z: NodeIndex) { - while self.parent_ref(z, Node::is_red) { - if self.grand_parent_ref(z, Node::is_sentinel) { - break; - } - if self.is_left_child(self.nref(z, Node::parent)) { - let y = self.grand_parent_ref(z, Node::right); - if self.nref(y, Node::is_red) { - self.parent_mut(z, Node::set_color(Color::Black)); - self.nmut(y, Node::set_color(Color::Black)); - self.grand_parent_mut(z, Node::set_color(Color::Red)); - z = self.parent_ref(z, Node::parent); - } else { - if self.is_right_child(z) { - z = self.nref(z, Node::parent); - self.left_rotate(z); - } - self.parent_mut(z, Node::set_color(Color::Black)); - self.grand_parent_mut(z, Node::set_color(Color::Red)); - self.right_rotate(self.parent_ref(z, Node::parent)); - } - } else { - let y = self.grand_parent_ref(z, Node::left); - if self.nref(y, Node::is_red) { - self.parent_mut(z, Node::set_color(Color::Black)); - self.nmut(y, Node::set_color(Color::Black)); - self.grand_parent_mut(z, Node::set_color(Color::Red)); - z = self.parent_ref(z, Node::parent); - } else { - if self.is_left_child(z) { - z = self.nref(z, Node::parent); - self.right_rotate(z); - } - self.parent_mut(z, Node::set_color(Color::Black)); - self.grand_parent_mut(z, Node::set_color(Color::Red)); - self.left_rotate(self.parent_ref(z, Node::parent)); - } - } - } - self.nmut(self.root, Node::set_color(Color::Black)); - } - - /// Restores red-black tree properties after a remove. - fn remove_fixup(&mut self, mut x: NodeIndex) { - while x != self.root && self.nref(x, Node::is_black) { - let mut w; - if self.is_left_child(x) { - w = self.parent_ref(x, Node::right); - if self.nref(w, Node::is_red) { - self.nmut(w, Node::set_color(Color::Black)); - self.parent_mut(x, Node::set_color(Color::Red)); - self.left_rotate(self.nref(x, Node::parent)); - w = self.parent_ref(x, Node::right); - } - if self.nref(w, Node::is_sentinel) { - break; - } - if self.left_ref(w, Node::is_black) && self.right_ref(w, Node::is_black) { - self.nmut(w, Node::set_color(Color::Red)); - x = self.nref(x, Node::parent); - } else { - if self.right_ref(w, Node::is_black) { - self.left_mut(w, Node::set_color(Color::Black)); - self.nmut(w, Node::set_color(Color::Red)); - self.right_rotate(w); - w = self.parent_ref(x, Node::right); - } - self.nmut(w, Node::set_color(self.parent_ref(x, Node::color))); - self.parent_mut(x, Node::set_color(Color::Black)); - self.right_mut(w, Node::set_color(Color::Black)); - self.left_rotate(self.nref(x, Node::parent)); - x = self.root; - } - } else { - w = self.parent_ref(x, Node::left); - if self.nref(w, Node::is_red) { - self.nmut(w, Node::set_color(Color::Black)); - self.parent_mut(x, Node::set_color(Color::Red)); - self.right_rotate(self.nref(x, Node::parent)); - w = self.parent_ref(x, Node::left); - } - if self.nref(w, Node::is_sentinel) { - break; - } - if self.right_ref(w, Node::is_black) && self.left_ref(w, Node::is_black) { - self.nmut(w, Node::set_color(Color::Red)); - x = self.nref(x, Node::parent); - } else { - if self.left_ref(w, Node::is_black) { - self.right_mut(w, Node::set_color(Color::Black)); - self.nmut(w, Node::set_color(Color::Red)); - self.left_rotate(w); - w = self.parent_ref(x, Node::left); - } - self.nmut(w, Node::set_color(self.parent_ref(x, Node::color))); - self.parent_mut(x, Node::set_color(Color::Black)); - self.left_mut(w, Node::set_color(Color::Black)); - self.right_rotate(self.nref(x, Node::parent)); - x = self.root; - } - } - } - self.nmut(x, Node::set_color(Color::Black)); - } - - /// Binary tree left rotate. - fn left_rotate(&mut self, x: NodeIndex) { - if self.right_ref(x, Node::is_sentinel) { - return; - } - let y = self.nref(x, Node::right); - self.nmut(x, Node::set_right(self.nref(y, Node::left))); - if !self.left_ref(y, Node::is_sentinel) { - self.left_mut(y, Node::set_parent(x)); - } - - self.replace_parent(x, y); - self.nmut(y, Node::set_left(x)); - - self.rotate_update_max(x, y); - } - - /// Binary tree right rotate. - fn right_rotate(&mut self, x: NodeIndex) { - if self.left_ref(x, Node::is_sentinel) { - return; - } - let y = self.nref(x, Node::left); - self.nmut(x, Node::set_left(self.nref(y, Node::right))); - if !self.right_ref(y, Node::is_sentinel) { - self.right_mut(y, Node::set_parent(x)); - } - - self.replace_parent(x, y); - self.nmut(y, Node::set_right(x)); - - self.rotate_update_max(x, y); - } - - /// Replaces parent during a rotation. - fn replace_parent(&mut self, x: NodeIndex, y: NodeIndex) { - self.nmut(y, Node::set_parent(self.nref(x, Node::parent))); - if self.parent_ref(x, Node::is_sentinel) { - self.root = y; - } else if self.is_left_child(x) { - self.parent_mut(x, Node::set_left(y)); - } else { - self.parent_mut(x, Node::set_right(y)); - } - self.nmut(x, Node::set_parent(y)); - } - - /// Updates the max value after a rotation. - fn rotate_update_max(&mut self, x: NodeIndex, y: NodeIndex) { - self.nmut(y, Node::set_max(self.nref(x, Node::max_owned))); - let mut max = &self.nref(x, Node::interval).high; - if let Some(lmax) = self.left_ref(x, Node::sentinel).map(Node::max) { - max = max.max(lmax); - } - if let Some(rmax) = self.right_ref(x, Node::sentinel).map(Node::max) { - max = max.max(rmax); - } - self.nmut(x, Node::set_max(max.clone())); - } - - /// Updates the max value towards the root - fn update_max_bottom_up(&mut self, x: NodeIndex) { - let mut p = x; - while !self.nref(p, Node::is_sentinel) { - self.nmut(p, Node::set_max(self.nref(p, Node::interval).high.clone())); - self.max_from(p, self.nref(p, Node::left)); - self.max_from(p, self.nref(p, Node::right)); - p = self.nref(p, Node::parent); - } - } - - /// Updates a nodes value from a child node. - fn max_from(&mut self, x: NodeIndex, c: NodeIndex) { - if let Some(cmax) = self.nref(c, Node::sentinel).map(Node::max) { - let max = self.nref(x, Node::max).max(cmax).clone(); - self.nmut(x, Node::set_max(max)); - } - } - - /// Finds the node with the minimum interval. - fn tree_minimum(&self, mut x: NodeIndex) -> NodeIndex { - while !self.left_ref(x, Node::is_sentinel) { - x = self.nref(x, Node::left); - } - x - } - - /// Replaces one subtree as a child of its parent with another subtree. - fn transplant(&mut self, u: NodeIndex, v: NodeIndex) { - if self.parent_ref(u, Node::is_sentinel) { - self.root = v; - } else { - if self.is_left_child(u) { - self.parent_mut(u, Node::set_left(v)); - } else { - self.parent_mut(u, Node::set_right(v)); - } - self.update_max_bottom_up(self.nref(u, Node::parent)); - } - self.nmut(v, Node::set_parent(self.nref(u, Node::parent))); - } - - /// Checks if a node is a left child of its parent. - fn is_left_child(&self, node: NodeIndex) -> bool { - self.parent_ref(node, Node::left) == node - } - - /// Checks if a node is a right child of its parent. - fn is_right_child(&self, node: NodeIndex) -> bool { - self.parent_ref(node, Node::right) == node - } - - /// Updates nodes index after remove - fn update_idx(&mut self, old: NodeIndex, new: NodeIndex) { - if self.root == old { - self.root = new; - } - if self.nodes.get(new.index()).is_some() { - if !self.parent_ref(new, Node::is_sentinel) { - if self.parent_ref(new, Node::left) == old { - self.parent_mut(new, Node::set_left(new)); - } else { - self.parent_mut(new, Node::set_right(new)); - } - } - self.left_mut(new, Node::set_parent(new)); - self.right_mut(new, Node::set_parent(new)); - } - } -} - -#[allow(clippy::missing_docs_in_private_items)] -#[allow(clippy::indexing_slicing)] -impl<'a, T, V, Ix> IntervalMap -where - Ix: IndexType, -{ - fn nref(&'a self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a Node) -> R, - { - op(&self.nodes[node.index()]) - } - - fn nmut(&'a mut self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a mut Node) -> R, - { - op(&mut self.nodes[node.index()]) - } - - fn left_ref(&'a self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a Node) -> R, - { - let idx = self.nodes[node.index()].left().index(); - op(&self.nodes[idx]) - } - - fn right_ref(&'a self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a Node) -> R, - { - let idx = self.nodes[node.index()].right().index(); - op(&self.nodes[idx]) - } - - fn parent_ref(&'a self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a Node) -> R, - { - let idx = self.nodes[node.index()].parent().index(); - op(&self.nodes[idx]) - } - - fn grand_parent_ref(&'a self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a Node) -> R, - { - let parent_idx = self.nodes[node.index()].parent().index(); - let grand_parent_idx = self.nodes[parent_idx].parent().index(); - op(&self.nodes[grand_parent_idx]) - } - - fn left_mut(&'a mut self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a mut Node) -> R, - { - let idx = self.nodes[node.index()].left().index(); - op(&mut self.nodes[idx]) - } - - fn right_mut(&'a mut self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a mut Node) -> R, - { - let idx = self.nodes[node.index()].right().index(); - op(&mut self.nodes[idx]) - } - - fn parent_mut(&'a mut self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a mut Node) -> R, - { - let idx = self.nodes[node.index()].parent().index(); - op(&mut self.nodes[idx]) - } - - fn grand_parent_mut(&'a mut self, node: NodeIndex, op: F) -> R - where - R: 'a, - F: FnOnce(&'a mut Node) -> R, - { - let parent_idx = self.nodes[node.index()].parent().index(); - let grand_parent_idx = self.nodes[parent_idx].parent().index(); - op(&mut self.nodes[grand_parent_idx]) - } -} - -/// An iterator over the entries of a `IntervalMap`. -#[allow(missing_debug_implementations)] -pub struct Iter<'a, T, V, Ix> { - /// Reference to the map - map_ref: &'a IntervalMap, - /// Stack for iteration - stack: Option>>, -} - -impl Iter<'_, T, V, Ix> -where - Ix: IndexType, -{ - /// Initiliazes the stack - fn init_stack(&mut self) { - self.stack = Some(Self::left_tree(self.map_ref, self.map_ref.root)); - } - - /// Pushes x and x's left sub tree to stack. - fn left_tree(map_ref: &IntervalMap, mut x: NodeIndex) -> Vec> { - let mut nodes = vec![]; - while !map_ref.nref(x, Node::is_sentinel) { - nodes.push(x); - x = map_ref.nref(x, Node::left); - } - nodes - } -} - -impl<'a, T, V, Ix> Iterator for Iter<'a, T, V, Ix> -where - Ix: IndexType, -{ - type Item = (&'a Interval, &'a V); - - #[allow(clippy::unwrap_used, clippy::unwrap_in_result)] - #[inline] - fn next(&mut self) -> Option { - if self.stack.is_none() { - self.init_stack(); - } - let stack = self.stack.as_mut().unwrap(); - if stack.is_empty() { - return None; - } - let x = stack.pop().unwrap(); - stack.extend(Self::left_tree( - self.map_ref, - self.map_ref.nref(x, Node::right), - )); - Some(self.map_ref.nref(x, |x| (x.interval(), x.value()))) - } -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -#[allow(missing_debug_implementations, clippy::exhaustive_enums)] -pub enum Entry<'a, T, V, Ix> { - /// An occupied entry. - Occupied(OccupiedEntry<'a, T, V, Ix>), - /// A vacant entry. - Vacant(VacantEntry<'a, T, V, Ix>), -} - -/// A view into an occupied entry in a `IntervalMap`. -/// It is part of the [`Entry`] enum. -#[allow(missing_debug_implementations)] -pub struct OccupiedEntry<'a, T, V, Ix> { - /// Reference to the map - map_ref: &'a mut IntervalMap, - /// The entry node - node: NodeIndex, -} - -/// A view into a vacant entry in a `IntervalMap`. -/// It is part of the [`Entry`] enum. -#[allow(missing_debug_implementations)] -pub struct VacantEntry<'a, T, V, Ix> { - /// Mutable reference to the map - map_ref: &'a mut IntervalMap, - /// The interval of this entry - interval: Interval, -} - -impl<'a, T, V, Ix> Entry<'a, T, V, Ix> -where - T: Ord + Clone, - Ix: IndexType, -{ - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - #[inline] - pub fn or_insert(self, default: V) -> &'a mut V { - match self { - Entry::Occupied(entry) => entry.map_ref.nmut(entry.node, Node::value_mut), - Entry::Vacant(entry) => { - let _ignore = entry.map_ref.insert(entry.interval, default); - let entry_idx = NodeIndex::new(entry.map_ref.len().wrapping_sub(1)); - entry.map_ref.nmut(entry_idx, Node::value_mut) - } - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Panics - /// - /// This method panics when the node is a sentinel node - #[allow(clippy::unwrap_used)] - #[inline] - #[must_use] - pub fn and_modify(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - match self { - Entry::Occupied(entry) => { - f(entry.map_ref.nmut(entry.node, Node::value_mut)); - Self::Occupied(entry) - } - Entry::Vacant(entry) => Self::Vacant(entry), - } - } -} - -// TODO: better typed `Node` -/// Node of the interval tree -#[derive(Debug)] -pub struct Node { - /// Left children - left: Option>, - /// Right children - right: Option>, - /// Parent - parent: Option>, - /// Color of the node - color: Color, - - /// Interval of the node - interval: Option>, - /// Max value of the sub-tree of the node - max: Option, - /// Value of the node - value: Option, -} - -#[allow(clippy::missing_docs_in_private_items)] -#[allow(clippy::unwrap_used)] -impl Node -where - Ix: IndexType, -{ - fn color(&self) -> Color { - self.color - } - - fn interval(&self) -> &Interval { - self.interval.as_ref().unwrap() - } - - fn max(&self) -> &T { - self.max.as_ref().unwrap() - } - - fn max_owned(&self) -> T - where - T: Clone, - { - self.max().clone() - } - - fn left(&self) -> NodeIndex { - self.left.unwrap() - } - - fn right(&self) -> NodeIndex { - self.right.unwrap() - } - - fn parent(&self) -> NodeIndex { - self.parent.unwrap() - } - - fn is_sentinel(&self) -> bool { - self.interval.is_none() - } - - fn sentinel(&self) -> Option<&Self> { - self.interval.is_some().then_some(self) - } - - fn is_black(&self) -> bool { - matches!(self.color, Color::Black) - } - - fn is_red(&self) -> bool { - matches!(self.color, Color::Red) - } - - fn value(&self) -> &V { - self.value.as_ref().unwrap() - } - - fn value_mut(&mut self) -> &mut V { - self.value.as_mut().unwrap() - } - - fn take_value(&mut self) -> V { - self.value.take().unwrap() - } - - fn set_value(value: V) -> impl FnOnce(&mut Node) -> V { - move |node: &mut Node| node.value.replace(value).unwrap() - } - - fn set_color(color: Color) -> impl FnOnce(&mut Node) { - move |node: &mut Node| { - node.color = color; - } - } - - fn set_max(max: T) -> impl FnOnce(&mut Node) { - move |node: &mut Node| { - let _ignore = node.max.replace(max); - } - } - - fn set_left(left: NodeIndex) -> impl FnOnce(&mut Node) { - move |node: &mut Node| { - let _ignore = node.left.replace(left); - } - } - - fn set_right(right: NodeIndex) -> impl FnOnce(&mut Node) { - move |node: &mut Node| { - let _ignore = node.right.replace(right); - } - } - - fn set_parent(parent: NodeIndex) -> impl FnOnce(&mut Node) { - move |node: &mut Node| { - let _ignore = node.parent.replace(parent); - } - } -} - -/// The Interval stored in `IntervalMap` -/// Represents the interval [low, high) -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Interval { - /// Low value - low: T, - /// high value - high: T, -} - -impl Interval { - /// Creates a new `Interval` - /// - /// # Panics - /// - /// This method panics when low is greater than high - #[inline] - pub fn new(low: T, high: T) -> Self { - assert!(low < high, "invalid range"); - Self { low, high } - } - - /// Checks if self overlaps with other interval - #[inline] - pub fn overlap(&self, other: &Self) -> bool { - self.high > other.low && other.high > self.low - } -} - -/// Reference type of `Interval` -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -struct IntervalRef<'a, T> { - /// Low value - low: &'a T, - /// high value - high: &'a T, -} - -impl<'a, T: Ord> IntervalRef<'a, T> { - /// Creates a new `IntervalRef` - /// - /// # Panics - /// - /// This method panics when low is greater than high - #[inline] - fn new(low: &'a T, high: &'a T) -> Self { - assert!(low < high, "invalid range"); - Self { low, high } - } - - /// Checks if self overlaps with a `Interval` - fn overlap(&self, other: &Interval) -> bool { - self.high > &other.low && &other.high > self.low - } -} - -/// The color of the node -#[derive(Debug, Clone, Copy)] -enum Color { - /// Red node - Red, - /// Black node - Black, -} diff --git a/crates/utils/src/array_interval_map/tests.rs b/crates/utils/src/array_interval_map/tests.rs deleted file mode 100644 index c449b4121..000000000 --- a/crates/utils/src/array_interval_map/tests.rs +++ /dev/null @@ -1,305 +0,0 @@ -use std::collections::HashSet; - -use rand::{rngs::StdRng, Rng, SeedableRng}; - -use super::*; - -struct IntervalGenerator { - rng: StdRng, - unique: HashSet>, - limit: i32, -} - -impl IntervalGenerator { - fn new(seed: [u8; 32]) -> Self { - const LIMIT: i32 = 1000; - Self { - rng: SeedableRng::from_seed(seed), - unique: HashSet::new(), - limit: LIMIT, - } - } - - fn next(&mut self) -> Interval { - let low = self.rng.gen_range(0..self.limit - 1); - let high = self.rng.gen_range((low + 1)..self.limit); - Interval::new(low, high) - } - - fn next_unique(&mut self) -> Interval { - let mut interval = self.next(); - while self.unique.contains(&interval) { - interval = self.next(); - } - self.unique.insert(interval.clone()); - interval - } - - fn next_with_range(&mut self, range: i32) -> Interval { - let low = self.rng.gen_range(0..self.limit - 1); - let high = self - .rng - .gen_range((low + 1)..self.limit.min(low + 1 + range)); - Interval::new(low, high) - } -} - -impl IntervalMap { - fn check_max(&self) { - let _ignore = self.check_max_inner(self.root); - } - - fn check_max_inner(&self, x: NodeIndex) -> i32 { - if self.nref(x, Node::is_sentinel) { - return 0; - } - let l_max = self.check_max_inner(self.nref(x, Node::left)); - let r_max = self.check_max_inner(self.nref(x, Node::right)); - let max = self.nref(x, |x| x.interval().high.max(l_max).max(r_max)); - assert_eq!(self.nref(x, Node::max_owned), max); - max - } - - /// 1. Every node is either red or black. - /// 2. The root is black. - /// 3. Every leaf (NIL) is black. - /// 4. If a node is red, then both its children are black. - /// 5. For each node, all simple paths from the node to descendant leaves contain the - /// same number of black nodes. - fn check_rb_properties(&self) { - assert!(matches!(self.nref(self.root, Node::color), Color::Black)); - self.check_children_color(self.root); - self.check_black_height(self.root); - } - - fn check_children_color(&self, x: NodeIndex) { - if self.nref(x, Node::is_sentinel) { - return; - } - self.check_children_color(self.nref(x, Node::left)); - self.check_children_color(self.nref(x, Node::right)); - if self.nref(x, Node::is_red) { - assert!(matches!(self.left_ref(x, Node::color), Color::Black)); - assert!(matches!(self.right_ref(x, Node::color), Color::Black)); - } - } - - fn check_black_height(&self, x: NodeIndex) -> usize { - if self.nref(x, Node::is_sentinel) { - return 0; - } - let lefth = self.check_black_height(self.nref(x, Node::left)); - let righth = self.check_black_height(self.nref(x, Node::right)); - assert_eq!(lefth, righth); - if self.nref(x, Node::is_black) { - return lefth + 1; - } - lefth - } -} - -fn with_map_and_generator(test_fn: impl FnOnce(IntervalMap, IntervalGenerator) + Clone) { - let seeds = vec![[0; 32], [1; 32], [2; 32]]; - for seed in seeds { - let gen = IntervalGenerator::new(seed); - let map = IntervalMap::new(); - test_fn.clone()(map, gen); - } -} - -#[test] -fn rb_properties() { - with_map_and_generator(|mut map, mut gen| { - let intervals: Vec<_> = std::iter::repeat_with(|| gen.next_unique()) - .take(1000) - .collect(); - for i in intervals.clone() { - let _ignore = map.insert(i, ()); - } - map.check_rb_properties(); - }); -} - -#[test] -#[should_panic] -fn invalid_range() { - let _interval = Interval::new(3, 1); -} - -#[test] -fn insert_equal_interval() { - let mut map = IntervalMap::new(); - map.insert(Interval::new(1, 3), 1); - assert_eq!(map.insert(Interval::new(1, 3), 2), Some(1)); - assert_eq!(map.insert(Interval::new(1, 3), 3), Some(2)); -} - -#[test] -fn map_len() { - with_map_and_generator(|mut map, mut gen| { - let intervals: Vec<_> = std::iter::repeat_with(|| gen.next_unique()) - .take(100) - .collect(); - for i in intervals.clone() { - let _ignore = map.insert(i, ()); - } - assert_eq!(map.len(), 100); - for i in intervals { - let _ignore = map.remove(&i); - } - assert_eq!(map.len(), 0); - }); -} - -#[test] -fn check_overlap_simple() { - let mut map = IntervalMap::new(); - map.insert(Interval::new(1, 3), ()); - map.insert(Interval::new(6, 7), ()); - map.insert(Interval::new(9, 11), ()); - assert!(map.overlap(&Interval::new(2, 5))); - assert!(map.overlap(&Interval::new(1, 17))); - assert!(!map.overlap(&Interval::new(4, 5))); - assert!(!map.overlap(&Interval::new(20, 23))); -} - -#[test] -fn check_overlap() { - with_map_and_generator(|mut map, mut gen| { - let intervals: Vec<_> = std::iter::repeat_with(|| gen.next_with_range(10)) - .take(100) - .collect(); - for i in intervals.clone() { - let _ignore = map.insert(i, ()); - } - let to_check: Vec<_> = std::iter::repeat_with(|| gen.next_with_range(10)) - .take(1000) - .collect(); - let expects: Vec<_> = to_check - .iter() - .map(|ci| intervals.iter().any(|i| ci.overlap(i))) - .collect(); - - for (ci, expect) in to_check.into_iter().zip(expects.into_iter()) { - assert_eq!(map.overlap(&ci), expect); - } - }); -} - -#[test] -fn check_max() { - with_map_and_generator(|mut map, mut gen| { - let intervals: Vec<_> = std::iter::repeat_with(|| gen.next_unique()) - .take(1000) - .collect(); - for i in intervals.clone() { - let _ignore = map.insert(i, ()); - map.check_max(); - } - assert_eq!(map.len(), 1000); - for i in intervals { - let _ignore = map.remove(&i); - map.check_max(); - } - }); -} - -#[test] -fn remove_non_exist_interval() { - with_map_and_generator(|mut map, mut gen| { - let intervals: Vec<_> = std::iter::repeat_with(|| gen.next_unique()) - .take(1000) - .collect(); - for i in intervals { - let _ignore = map.insert(i, ()); - } - assert_eq!(map.len(), 1000); - let to_remove: Vec<_> = std::iter::repeat_with(|| gen.next_unique()) - .take(1000) - .collect(); - for i in to_remove { - let _ignore = map.remove(&i); - } - assert_eq!(map.len(), 1000); - }); -} - -#[test] -fn find_all_overlap_simple() { - let mut map = IntervalMap::new(); - map.insert(Interval::new(1, 3), ()); - map.insert(Interval::new(2, 4), ()); - map.insert(Interval::new(6, 7), ()); - map.insert(Interval::new(7, 11), ()); - assert_eq!(map.find_all_overlap(&Interval::new(2, 7)).len(), 3); - map.remove(&Interval::new(1, 3)); - assert_eq!(map.find_all_overlap(&Interval::new(2, 7)).len(), 2); -} - -#[test] -fn find_all_overlap() { - with_map_and_generator(|mut map, mut gen| { - let intervals: Vec<_> = std::iter::repeat_with(|| gen.next_unique()) - .take(1000) - .collect(); - for i in intervals.clone() { - let _ignore = map.insert(i, ()); - } - let to_find: Vec<_> = std::iter::repeat_with(|| gen.next()).take(1000).collect(); - - let expects: Vec> = to_find - .iter() - .map(|ti| intervals.iter().filter(|i| ti.overlap(i)).collect()) - .collect(); - - for (ti, mut expect) in to_find.into_iter().zip(expects.into_iter()) { - let mut result = map.find_all_overlap(&ti); - expect.sort_unstable(); - result.sort_unstable(); - assert_eq!(expect.len(), result.len()); - for (e, r) in expect.into_iter().zip(result.into_iter()) { - assert_eq!(e, r); - } - } - }); -} - -#[test] -fn entry_modify() { - let mut map = IntervalMap::new(); - map.insert(Interval::new(1, 3), 1); - map.insert(Interval::new(2, 4), 2); - map.insert(Interval::new(6, 7), 3); - map.insert(Interval::new(7, 11), 4); - let _ignore = map.entry(Interval::new(6, 7)).and_modify(|v| *v += 1); - assert_eq!(map.get(&Interval::new(1, 3)), Some(&1)); - assert_eq!(map.get(&Interval::new(2, 4)), Some(&2)); - assert_eq!(map.get(&Interval::new(6, 7)), Some(&4)); - assert_eq!(map.get(&Interval::new(7, 11)), Some(&4)); - assert_eq!(map.get(&Interval::new(5, 17)), None); - map.entry(Interval::new(3, 5)) - .and_modify(|v| *v += 1) - .or_insert(0); - let _ignore = map.get_mut(&Interval::new(3, 5)).map(|v| *v += 1); - assert_eq!(map.get(&Interval::new(3, 5)), Some(&1)); -} - -#[test] -fn iterate_through_map() { - with_map_and_generator(|mut map, mut gen| { - let mut intervals: Vec<_> = std::iter::repeat_with(|| gen.next_unique()) - .enumerate() - .take(1000) - .collect(); - for (v, i) in intervals.clone() { - let _ignore = map.insert(i, v); - } - intervals.sort_unstable_by(|a, b| a.1.cmp(&b.1)); - - #[allow(clippy::pattern_type_mismatch)] - for ((ei, ev), (v, i)) in map.iter().zip(intervals.iter()) { - assert_eq!(ei, i); - assert_eq!(ev, v); - } - }); -} diff --git a/crates/utils/src/interval_map/mod.rs b/crates/utils/src/interval_map/mod.rs index 40bc541d2..257561e6a 100644 --- a/crates/utils/src/interval_map/mod.rs +++ b/crates/utils/src/interval_map/mod.rs @@ -1,63 +1,67 @@ +#![allow(clippy::shadow_unrelated)] + +use petgraph::graph::{DefaultIx, IndexType, NodeIndex}; + #[cfg(test)] mod tests; -use std::{cell::RefCell, ops::Deref, rc::Rc}; - /// An interval-value map, which support operations on dynamic sets of intervals. -pub struct IntervalMap { +#[derive(Debug)] +pub struct IntervalMap { + /// Vector that stores nodes + nodes: Vec>, /// Root of the interval tree - root: NodeRef, - /// Sentinel node, used to simplify boundary checks - sentinel: NodeRef, + root: NodeIndex, /// Number of elements in the map len: usize, } -impl IntervalMap +impl IntervalMap where - T: Ord + Clone, + T: Clone + Ord, + Ix: IndexType, { - /// Creates an empty `IntervalMap` - #[must_use] + /// Creates a new `IntervalMap` with estimated capacity. #[inline] - pub fn new() -> Self { - let sentinel = Self::new_sentinel(); - Self { - root: sentinel.clone_rc(), - sentinel, + #[must_use] + pub fn with_capacity(capacity: usize) -> Self { + let mut nodes = vec![Self::new_sentinel()]; + nodes.reserve(capacity); + IntervalMap { + nodes, + root: Self::sentinel(), len: 0, } } /// Inserts a interval-value pair into the map. + /// + /// # Panics + /// + /// This method panics when the tree is at the maximum number of nodes for its index #[inline] pub fn insert(&mut self, interval: Interval, value: V) -> Option { - let z = self.new_node(interval, value); - self.insert_inner(z) - } - - /// Gets the given key's corresponding entry in the map for in-place manipulation. - #[inline] - pub fn entry(&mut self, interval: Interval) -> Entry<'_, T, V> { - match self.search_exact(&interval) { - Some(node) => Entry::Occupied(OccupiedEntry { - _map_ref: self, - node, - }), - None => Entry::Vacant(VacantEntry { - map_ref: self, - interval, - }), - } + let node = Self::new_node(interval, value); + let node_idx = NodeIndex::new(self.nodes.len()); + // check for max capacity, except if we use usize + assert!( + ::max().index() == !0 || NodeIndex::end() != node_idx, + "Reached maximum number of nodes" + ); + self.nodes.push(node); + self.insert_inner(node_idx) } /// Removes a interval from the map, returning the value at the interval if the interval /// was previously in the map. #[inline] pub fn remove(&mut self, interval: &Interval) -> Option { - if let Some(node) = self.search_exact(interval) { - self.remove_inner(&node); - return Some(node.take_value()); + if let Some(node_idx) = self.search_exact(interval) { + self.remove_inner(node_idx); + let mut node = self.nodes.swap_remove(node_idx.index()); + let old = NodeIndex::::new(self.nodes.len()); + self.update_idx(old, node_idx); + return node.value.take(); } None } @@ -65,14 +69,53 @@ where /// Checks if an interval in the map overlaps with the given interval. #[inline] pub fn overlap(&self, interval: &Interval) -> bool { - let node = self.search(interval); - !node.is_sentinel() + let node_idx = self.search(interval); + !self.nref(node_idx, Node::is_sentinel) } /// Finds all intervals in the map that overlaps with the given interval. #[inline] - pub fn find_all_overlap(&self, interval: &Interval) -> Vec> { - Self::find_all_overlap_inner(&self.root, interval) + pub fn find_all_overlap(&self, interval: &Interval) -> Vec<&Interval> { + self.find_all_overlap_inner(self.root, interval) + } + + /// Returns a reference to the value corresponding to the key. + #[inline] + pub fn get(&self, interval: &Interval) -> Option<&V> { + self.search_exact(interval) + .map(|idx| self.nref(idx, Node::value)) + } + + /// Returns a reference to the value corresponding to the key. + #[inline] + pub fn get_mut(&mut self, interval: &Interval) -> Option<&mut V> { + self.search_exact(interval) + .map(|idx| self.nmut(idx, Node::value_mut)) + } + + /// Gets an iterator over the entries of the map, sorted by key. + #[inline] + #[must_use] + pub fn iter(&self) -> Iter<'_, T, V, Ix> { + Iter { + map_ref: self, + stack: None, + } + } + + /// Gets the given key's corresponding entry in the map for in-place manipulation. + #[inline] + pub fn entry(&mut self, interval: Interval) -> Entry<'_, T, V, Ix> { + match self.search_exact(&interval) { + Some(node) => Entry::Occupied(OccupiedEntry { + map_ref: self, + node, + }), + None => Entry::Vacant(VacantEntry { + map_ref: self, + interval, + }), + } } /// Returns the number of elements in the map. @@ -86,39 +129,43 @@ where #[inline] #[must_use] pub fn is_empty(&self) -> bool { - self.len == 0 + self.len() == 0 } } -impl IntervalMap { - // TODO: lazy evaluation - /// Gets an iterator over the entries of the map, sorted by key. - #[inline] +impl IntervalMap +where + T: Clone + Ord, +{ + /// Creates an empty `IntervalMap` #[must_use] - pub fn iter(&self) -> Iter<'_, T, V> { - Iter { - map_ref: self, - stack: Iter::left_tree(self.root.clone_rc()), + #[inline] + pub fn new() -> Self { + Self { + nodes: vec![Self::new_sentinel()], + root: Self::sentinel(), + len: 0, } } } impl Default for IntervalMap where - T: Ord + Clone, + T: Clone + Ord, { #[inline] fn default() -> Self { - Self::new() + Self::with_capacity(0) } } -impl IntervalMap +impl IntervalMap where - T: Clone, + T: Clone + Ord, + Ix: IndexType, { /// Creates a new sentinel node - fn new_sentinel() -> NodeRef { + fn new_sentinel() -> Node { Node { interval: None, value: None, @@ -128,90 +175,97 @@ where parent: None, color: Color::Black, } - .into_ref() } /// Creates a new tree node - fn new_node(&self, interval: Interval, value: V) -> NodeRef { + fn new_node(interval: Interval, value: V) -> Node { Node { max: Some(interval.high.clone()), interval: Some(interval), value: Some(value), - left: Some(self.sentinel.clone_rc()), - right: Some(self.sentinel.clone_rc()), - parent: Some(self.sentinel.clone_rc()), + left: Some(Self::sentinel()), + right: Some(Self::sentinel()), + parent: Some(Self::sentinel()), color: Color::Red, } - .into_ref() + } + + /// Gets the sentinel node index + fn sentinel() -> NodeIndex { + NodeIndex::new(0) } } -impl IntervalMap +impl IntervalMap where T: Ord + Clone, + Ix: IndexType, { /// Inserts a node into the tree. - fn insert_inner(&mut self, z: NodeRef) -> Option { - let mut y = self.sentinel.clone_rc(); - let mut x = self.root.clone_rc(); - while !x.is_sentinel() { - y = x.clone_rc(); - if z.interval(|zi| y.interval(|yi| zi == yi)) { - let old_value = y.set_value(z.take_value()); + fn insert_inner(&mut self, z: NodeIndex) -> Option { + let mut y = Self::sentinel(); + let mut x = self.root; + + while !self.nref(x, Node::is_sentinel) { + y = x; + if self.nref(z, Node::interval) == self.nref(y, Node::interval) { + let zval = self.nmut(z, Node::take_value); + let old_value = self.nmut(y, Node::set_value(zval)); return Some(old_value); } - if z.interval(|zi| x.interval(|xi| zi < xi)) { - x = x.left_owned(); + if self.nref(z, Node::interval) < self.nref(x, Node::interval) { + x = self.nref(x, Node::left); } else { - x = x.right_owned(); + x = self.nref(x, Node::right); } } - z.set_parent(y.clone_rc()); - if y.is_sentinel() { - self.root = z.clone_rc(); + self.nmut(z, Node::set_parent(y)); + if self.nref(y, Node::is_sentinel) { + self.root = z; } else { - if z.interval(|zi| y.interval(|yi| zi < yi)) { - y.set_left(z.clone_rc()); + if self.nref(z, Node::interval) < self.nref(y, Node::interval) { + self.nmut(y, Node::set_left(z)); } else { - y.set_right(z.clone_rc()); + self.nmut(y, Node::set_right(z)); } - Self::update_max_bottom_up(&y); + self.update_max_bottom_up(y); } - z.set_color(Color::Red); + self.nmut(z, Node::set_color(Color::Red)); - self.insert_fixup(z.clone_rc()); + self.insert_fixup(z); self.len = self.len.wrapping_add(1); None } /// Removes a node from the tree. - fn remove_inner(&mut self, z: &NodeRef) { - let mut y = z.clone_rc(); - let mut y_orig_color = y.color(); + fn remove_inner(&mut self, z: NodeIndex) { + let mut y = z; + let mut y_orig_color = self.nref(y, Node::color); let x; - if z.left(NodeRef::is_sentinel) { - x = z.right_owned(); - self.transplant(z, &x); - } else if z.right(NodeRef::is_sentinel) { - x = z.left_owned(); - self.transplant(z, &x); + if self.left_ref(z, Node::is_sentinel) { + x = self.nref(z, Node::right); + self.transplant(z, x); + } else if self.right_ref(z, Node::is_sentinel) { + x = self.nref(z, Node::left); + self.transplant(z, x); } else { - y = Self::tree_minimum(z.right_owned()); - y_orig_color = y.color(); - x = y.right_owned(); - if y.parent(|p| p == z) { - x.set_parent(y.clone_rc()); + y = self.tree_minimum(self.nref(z, Node::right)); + y_orig_color = self.nref(y, Node::color); + x = self.nref(y, Node::right); + if self.nref(y, Node::parent) == z { + self.nmut(x, Node::set_parent(y)); } else { - self.transplant(&y, &x); - y.set_right(z.right_owned()); - y.right(|r| r.set_parent(y.clone_rc())); + self.transplant(y, x); + self.nmut(y, Node::set_right(self.nref(z, Node::right))); + self.right_mut(y, Node::set_parent(y)); } - self.transplant(z, &y); - y.set_left(z.left_owned()); - y.left(|l| l.set_parent(y.clone_rc())); - y.set_color(z.color()); - Self::update_max_bottom_up(&y); + self.transplant(z, y); + self.nmut(y, Node::set_left(self.nref(z, Node::left))); + self.left_mut(y, Node::set_parent(y)); + self.nmut(y, Node::set_color(self.nref(z, Node::color))); + + self.update_max_bottom_up(y); } if matches!(y_orig_color, Color::Black) { @@ -222,570 +276,650 @@ where } /// Finds all intervals in the map that overlaps with the given interval. - fn find_all_overlap_inner(x: &NodeRef, i: &Interval) -> Vec> { + fn find_all_overlap_inner( + &self, + x: NodeIndex, + interval: &Interval, + ) -> Vec<&Interval> { let mut list = vec![]; - if x.interval(|xi| xi.overlap(i)) { - list.push(x.interval(Clone::clone)); - } - if !x.left(NodeRef::is_sentinel) && x.left(|l| l.max(|m| *m > i.low)) { - list.extend(Self::find_all_overlap_inner(&x.left_owned(), i)); - } - if !x.right(NodeRef::is_sentinel) - && Interval::new( - x.interval(|xi| xi.low.clone()), - x.right(|r| r.max(Clone::clone)), - ) - .overlap(i) + if self.nref(x, Node::interval).overlap(interval) { + list.push(self.nref(x, Node::interval)); + } + if self + .left_ref(x, Node::sentinel) + .map(Node::max) + .is_some_and(|lm| lm >= &interval.low) { - list.extend(Self::find_all_overlap_inner(&x.right_owned(), i)); + list.extend(self.find_all_overlap_inner(self.nref(x, Node::left), interval)); + } + if self + .right_ref(x, Node::sentinel) + .map(|r| IntervalRef::new(&self.nref(x, Node::interval).low, r.max())) + .is_some_and(|i| i.overlap(interval)) + { + list.extend(self.find_all_overlap_inner(self.nref(x, Node::right), interval)); } list } /// Search for an interval that overlaps with the given interval. - fn search(&self, interval: &Interval) -> NodeRef { - let mut x = self.root.clone_rc(); - while !x.is_sentinel() && x.interval(|xi| !xi.overlap(interval)) { - if !x.left(NodeRef::is_sentinel) && x.left(|l| l.max(|lm| lm > &interval.low)) { - x = x.left_owned(); + fn search(&self, interval: &Interval) -> NodeIndex { + let mut x = self.root; + while self + .nref(x, Node::sentinel) + .map(Node::interval) + .is_some_and(|xi| !xi.overlap(interval)) + { + if self + .left_ref(x, Node::sentinel) + .map(Node::max) + .is_some_and(|lm| lm > &interval.low) + { + x = self.nref(x, Node::left); } else { - x = x.right_owned(); + x = self.nref(x, Node::right); } } x } /// Search for the node with exact the given interval - fn search_exact(&self, interval: &Interval) -> Option> { - let mut x = self.root.clone_rc(); - while !x.is_sentinel() { - if x.interval(|xi| xi == interval) { + fn search_exact(&self, interval: &Interval) -> Option> { + let mut x = self.root; + while !self.nref(x, Node::is_sentinel) { + if self.nref(x, Node::interval) == interval { return Some(x); } - if x.max(|max| max < &interval.high) { + if self.nref(x, Node::max) < &interval.high { return None; } - if x.interval(|xi| xi > interval) { - x = x.left_owned(); + if self.nref(x, Node::interval) > interval { + x = self.nref(x, Node::left); } else { - x = x.right_owned(); + x = self.nref(x, Node::right); } } None } /// Restores red-black tree properties after an insert. - fn insert_fixup(&mut self, mut z: NodeRef) { - while z.parent(NodeRef::is_red) { - if z.grand_parent(NodeRef::is_sentinel) { + fn insert_fixup(&mut self, mut z: NodeIndex) { + while self.parent_ref(z, Node::is_red) { + if self.grand_parent_ref(z, Node::is_sentinel) { break; } - if z.parent(Self::is_left_child) { - let y = z.grand_parent(NodeRef::right_owned); - if y.is_red() { - z.parent(NodeRef::set_color_fn(Color::Black)); - y.set_color(Color::Black); - z.grand_parent(NodeRef::set_color_fn(Color::Red)); - z = z.grand_parent_owned(); + if self.is_left_child(self.nref(z, Node::parent)) { + let y = self.grand_parent_ref(z, Node::right); + if self.nref(y, Node::is_red) { + self.parent_mut(z, Node::set_color(Color::Black)); + self.nmut(y, Node::set_color(Color::Black)); + self.grand_parent_mut(z, Node::set_color(Color::Red)); + z = self.parent_ref(z, Node::parent); } else { - if Self::is_right_child(&z) { - z = z.parent_owned(); - self.left_rotate(&z); + if self.is_right_child(z) { + z = self.nref(z, Node::parent); + self.left_rotate(z); } - z.parent(NodeRef::set_color_fn(Color::Black)); - z.grand_parent(NodeRef::set_color_fn(Color::Red)); - z.grand_parent(|gp| self.right_rotate(gp)); + self.parent_mut(z, Node::set_color(Color::Black)); + self.grand_parent_mut(z, Node::set_color(Color::Red)); + self.right_rotate(self.parent_ref(z, Node::parent)); } } else { - let y = z.grand_parent(NodeRef::left_owned); - if y.is_red() { - z.parent(NodeRef::set_color_fn(Color::Black)); - y.set_color(Color::Black); - z.grand_parent(NodeRef::set_color_fn(Color::Red)); - z = z.grand_parent_owned(); + let y = self.grand_parent_ref(z, Node::left); + if self.nref(y, Node::is_red) { + self.parent_mut(z, Node::set_color(Color::Black)); + self.nmut(y, Node::set_color(Color::Black)); + self.grand_parent_mut(z, Node::set_color(Color::Red)); + z = self.parent_ref(z, Node::parent); } else { - if Self::is_left_child(&z) { - z = z.parent_owned(); - self.right_rotate(&z); + if self.is_left_child(z) { + z = self.nref(z, Node::parent); + self.right_rotate(z); } - z.parent(NodeRef::set_color_fn(Color::Black)); - z.grand_parent(NodeRef::set_color_fn(Color::Red)); - z.grand_parent(|gp| self.left_rotate(gp)); + self.parent_mut(z, Node::set_color(Color::Black)); + self.grand_parent_mut(z, Node::set_color(Color::Red)); + self.left_rotate(self.parent_ref(z, Node::parent)); } } } - self.root.set_color(Color::Black); + self.nmut(self.root, Node::set_color(Color::Black)); } /// Restores red-black tree properties after a remove. - fn remove_fixup(&mut self, mut x: NodeRef) { - while x != self.root && x.is_black() { + fn remove_fixup(&mut self, mut x: NodeIndex) { + while x != self.root && self.nref(x, Node::is_black) { let mut w; - if Self::is_left_child(&x) { - w = x.parent(NodeRef::right_owned); - if w.is_red() { - w.set_color(Color::Black); - x.parent(NodeRef::set_color_fn(Color::Red)); - x.parent(|p| self.left_rotate(p)); - w = x.parent(NodeRef::right_owned); + if self.is_left_child(x) { + w = self.parent_ref(x, Node::right); + if self.nref(w, Node::is_red) { + self.nmut(w, Node::set_color(Color::Black)); + self.parent_mut(x, Node::set_color(Color::Red)); + self.left_rotate(self.nref(x, Node::parent)); + w = self.parent_ref(x, Node::right); } - if w.is_sentinel() { + if self.nref(w, Node::is_sentinel) { break; } - if w.left(NodeRef::is_black) && w.right(NodeRef::is_black) { - w.set_color(Color::Red); - x = x.parent_owned(); + if self.left_ref(w, Node::is_black) && self.right_ref(w, Node::is_black) { + self.nmut(w, Node::set_color(Color::Red)); + x = self.nref(x, Node::parent); } else { - if w.right(NodeRef::is_black) { - w.left(NodeRef::set_color_fn(Color::Black)); - w.set_color(Color::Red); - self.right_rotate(&w); - w = x.parent(NodeRef::right_owned); + if self.right_ref(w, Node::is_black) { + self.left_mut(w, Node::set_color(Color::Black)); + self.nmut(w, Node::set_color(Color::Red)); + self.right_rotate(w); + w = self.parent_ref(x, Node::right); } - w.set_color(x.parent(NodeRef::color)); - x.parent(NodeRef::set_color_fn(Color::Black)); - w.right(NodeRef::set_color_fn(Color::Black)); - x.parent(|p| self.left_rotate(p)); - x = self.root.clone_rc(); + self.nmut(w, Node::set_color(self.parent_ref(x, Node::color))); + self.parent_mut(x, Node::set_color(Color::Black)); + self.right_mut(w, Node::set_color(Color::Black)); + self.left_rotate(self.nref(x, Node::parent)); + x = self.root; } } else { - w = x.parent(NodeRef::left_owned); - if w.is_red() { - w.set_color(Color::Black); - x.parent(NodeRef::set_color_fn(Color::Red)); - x.parent(|p| self.right_rotate(p)); - w = x.parent(NodeRef::left_owned); + w = self.parent_ref(x, Node::left); + if self.nref(w, Node::is_red) { + self.nmut(w, Node::set_color(Color::Black)); + self.parent_mut(x, Node::set_color(Color::Red)); + self.right_rotate(self.nref(x, Node::parent)); + w = self.parent_ref(x, Node::left); } - if w.is_sentinel() { + if self.nref(w, Node::is_sentinel) { break; } - if w.left(NodeRef::is_black) && w.right(NodeRef::is_black) { - w.set_color(Color::Red); - x = x.parent_owned(); + if self.right_ref(w, Node::is_black) && self.left_ref(w, Node::is_black) { + self.nmut(w, Node::set_color(Color::Red)); + x = self.nref(x, Node::parent); } else { - if w.left(NodeRef::is_black) { - w.right(NodeRef::set_color_fn(Color::Black)); - w.set_color(Color::Red); - self.left_rotate(&w); - w = x.parent(NodeRef::left_owned); + if self.left_ref(w, Node::is_black) { + self.right_mut(w, Node::set_color(Color::Black)); + self.nmut(w, Node::set_color(Color::Red)); + self.left_rotate(w); + w = self.parent_ref(x, Node::left); } - w.set_color(x.parent(NodeRef::color)); - x.parent(NodeRef::set_color_fn(Color::Black)); - w.left(NodeRef::set_color_fn(Color::Black)); - x.parent(|p| self.right_rotate(p)); - x = self.root.clone_rc(); + self.nmut(w, Node::set_color(self.parent_ref(x, Node::color))); + self.parent_mut(x, Node::set_color(Color::Black)); + self.left_mut(w, Node::set_color(Color::Black)); + self.right_rotate(self.nref(x, Node::parent)); + x = self.root; } } } - x.set_color(Color::Black); + self.nmut(x, Node::set_color(Color::Black)); } /// Binary tree left rotate. - fn left_rotate(&mut self, x: &NodeRef) { - if x.right(NodeRef::is_sentinel) { + fn left_rotate(&mut self, x: NodeIndex) { + if self.right_ref(x, Node::is_sentinel) { return; } - let y = x.right_owned(); - x.set_right(y.left_owned()); - if !y.left(NodeRef::is_sentinel) { - y.left(|l| l.set_parent(x.clone_rc())); + let y = self.nref(x, Node::right); + self.nmut(x, Node::set_right(self.nref(y, Node::left))); + if !self.left_ref(y, Node::is_sentinel) { + self.left_mut(y, Node::set_parent(x)); } - self.replace_parent(x, &y); - y.set_left(x.clone_rc()); + self.replace_parent(x, y); + self.nmut(y, Node::set_left(x)); - Self::rotate_update_max(x, &y); + self.rotate_update_max(x, y); } /// Binary tree right rotate. - fn right_rotate(&mut self, x: &NodeRef) { - if x.left(NodeRef::is_sentinel) { + fn right_rotate(&mut self, x: NodeIndex) { + if self.left_ref(x, Node::is_sentinel) { return; } - let y = x.left_owned(); - x.set_left(y.right_owned()); - if !y.right(NodeRef::is_sentinel) { - y.right(|r| r.set_parent(x.clone_rc())); + let y = self.nref(x, Node::left); + self.nmut(x, Node::set_left(self.nref(y, Node::right))); + if !self.right_ref(y, Node::is_sentinel) { + self.right_mut(y, Node::set_parent(x)); } - self.replace_parent(x, &y); - y.set_right(x.clone_rc()); + self.replace_parent(x, y); + self.nmut(y, Node::set_right(x)); - Self::rotate_update_max(x, &y); + self.rotate_update_max(x, y); } /// Replaces parent during a rotation. - fn replace_parent(&mut self, x: &NodeRef, y: &NodeRef) { - y.set_parent(x.parent_owned()); - if x.parent(NodeRef::is_sentinel) { - self.root = y.clone_rc(); - } else if x.parent(|p| p.left(|l| l.eq(x))) { - x.parent(|p| p.set_left(y.clone_rc())); + fn replace_parent(&mut self, x: NodeIndex, y: NodeIndex) { + self.nmut(y, Node::set_parent(self.nref(x, Node::parent))); + if self.parent_ref(x, Node::is_sentinel) { + self.root = y; + } else if self.is_left_child(x) { + self.parent_mut(x, Node::set_left(y)); } else { - x.parent(|p| p.set_right(y.clone_rc())); + self.parent_mut(x, Node::set_right(y)); } - x.set_parent(y.clone_rc()); + self.nmut(x, Node::set_parent(y)); } /// Updates the max value after a rotation. - fn rotate_update_max(x: &NodeRef, y: &NodeRef) { - y.set_max(x.max_owned()); - let mut max = x.interval(|i| i.high.clone()); - if !x.left(NodeRef::is_sentinel) { - max = max.max(x.left(NodeRef::max_owned)); + fn rotate_update_max(&mut self, x: NodeIndex, y: NodeIndex) { + self.nmut(y, Node::set_max(self.nref(x, Node::max_owned))); + let mut max = &self.nref(x, Node::interval).high; + if let Some(lmax) = self.left_ref(x, Node::sentinel).map(Node::max) { + max = max.max(lmax); } - if !x.right(NodeRef::is_sentinel) { - max = max.max(x.right(NodeRef::max_owned)); + if let Some(rmax) = self.right_ref(x, Node::sentinel).map(Node::max) { + max = max.max(rmax); } - x.set_max(max); + self.nmut(x, Node::set_max(max.clone())); } /// Updates the max value towards the root - fn update_max_bottom_up(x: &NodeRef) { - let mut p = x.clone_rc(); - while !p.is_sentinel() { - p.set_max(p.interval(|i| i.high.clone())); - Self::max_from(&p, &p.left_owned()); - Self::max_from(&p, &p.right_owned()); - p = p.parent_owned(); + fn update_max_bottom_up(&mut self, x: NodeIndex) { + let mut p = x; + while !self.nref(p, Node::is_sentinel) { + self.nmut(p, Node::set_max(self.nref(p, Node::interval).high.clone())); + self.max_from(p, self.nref(p, Node::left)); + self.max_from(p, self.nref(p, Node::right)); + p = self.nref(p, Node::parent); } } /// Updates a nodes value from a child node. - fn max_from(x: &NodeRef, c: &NodeRef) { - if !c.is_sentinel() && x.max(|xm| c.max(|cm| xm < cm)) { - x.set_max(c.max_owned()); + fn max_from(&mut self, x: NodeIndex, c: NodeIndex) { + if let Some(cmax) = self.nref(c, Node::sentinel).map(Node::max) { + let max = self.nref(x, Node::max).max(cmax).clone(); + self.nmut(x, Node::set_max(max)); } } /// Finds the node with the minimum interval. - fn tree_minimum(mut x: NodeRef) -> NodeRef { - loop { - let left = x.left_owned(); - if left.is_sentinel() { - return x; - } - x = left; + fn tree_minimum(&self, mut x: NodeIndex) -> NodeIndex { + while !self.left_ref(x, Node::is_sentinel) { + x = self.nref(x, Node::left); } + x } /// Replaces one subtree as a child of its parent with another subtree. - fn transplant(&mut self, u: &NodeRef, v: &NodeRef) { - if u.parent(NodeRef::is_sentinel) { - self.root = v.clone_rc(); + fn transplant(&mut self, u: NodeIndex, v: NodeIndex) { + if self.parent_ref(u, Node::is_sentinel) { + self.root = v; } else { - if u.parent(|p| p.left(|l| l == u)) { - u.parent(|p| p.set_left(v.clone_rc())); + if self.is_left_child(u) { + self.parent_mut(u, Node::set_left(v)); } else { - u.parent(|p| p.set_right(v.clone_rc())); + self.parent_mut(u, Node::set_right(v)); } - u.parent(Self::update_max_bottom_up); + self.update_max_bottom_up(self.nref(u, Node::parent)); } - v.set_parent(u.parent_owned()); + self.nmut(v, Node::set_parent(self.nref(u, Node::parent))); } /// Checks if a node is a left child of its parent. - fn is_left_child(node: &NodeRef) -> bool { - node.parent(|p| p.left(|l| l.eq(node))) + fn is_left_child(&self, node: NodeIndex) -> bool { + self.parent_ref(node, Node::left) == node } /// Checks if a node is a right child of its parent. - fn is_right_child(node: &NodeRef) -> bool { - node.parent(|p| p.right(|r| r.eq(node))) - } -} - -impl std::fmt::Debug for IntervalMap { - #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("IntervalMap") - .field("len", &self.len) - .finish() + fn is_right_child(&self, node: NodeIndex) -> bool { + self.parent_ref(node, Node::right) == node } -} -impl Drop for IntervalMap { - #[inline] - fn drop(&mut self) { - // Removes circular references. - for entry in self.iter() { - drop(entry.node.borrow_mut().parent.take()); + /// Updates nodes index after remove + fn update_idx(&mut self, old: NodeIndex, new: NodeIndex) { + if self.root == old { + self.root = new; + } + if self.nodes.get(new.index()).is_some() { + if !self.parent_ref(new, Node::is_sentinel) { + if self.parent_ref(new, Node::left) == old { + self.parent_mut(new, Node::set_left(new)); + } else { + self.parent_mut(new, Node::set_right(new)); + } + } + self.left_mut(new, Node::set_parent(new)); + self.right_mut(new, Node::set_parent(new)); } } } -// TODO: better typed `Node` -/// Node of the interval tree -struct Node { - /// Interval of the node - interval: Option>, - /// Value of the node - value: Option, - /// Max value of the sub-tree of the node - max: Option, - - /// Left children - left: Option>, - /// Right children - right: Option>, - /// Parent - parent: Option>, - /// Color of the node - color: Color, -} - -#[allow(clippy::missing_docs_in_private_items, clippy::unwrap_used)] -impl Node { - fn into_ref(self) -> NodeRef { - NodeRef(Rc::new(RefCell::new(self))) - } - - fn color(&self) -> Color { - self.color - } - - fn interval(&self) -> &Interval { - self.interval.as_ref().unwrap() +#[allow(clippy::missing_docs_in_private_items)] +#[allow(clippy::indexing_slicing)] +impl<'a, T, V, Ix> IntervalMap +where + Ix: IndexType, +{ + fn nref(&'a self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a Node) -> R, + { + op(&self.nodes[node.index()]) } - fn value(&self) -> &V { - self.value.as_ref().unwrap() + fn nmut(&'a mut self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a mut Node) -> R, + { + op(&mut self.nodes[node.index()]) } - fn max(&self) -> &T { - self.max.as_ref().unwrap() + fn left_ref(&'a self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a Node) -> R, + { + let idx = self.nodes[node.index()].left().index(); + op(&self.nodes[idx]) } - fn left(&self) -> &NodeRef { - self.left.as_ref().unwrap() + fn right_ref(&'a self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a Node) -> R, + { + let idx = self.nodes[node.index()].right().index(); + op(&self.nodes[idx]) } - fn right(&self) -> &NodeRef { - self.right.as_ref().unwrap() + fn parent_ref(&'a self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a Node) -> R, + { + let idx = self.nodes[node.index()].parent().index(); + op(&self.nodes[idx]) } - fn parent(&self) -> &NodeRef { - self.parent.as_ref().unwrap() + fn grand_parent_ref(&'a self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a Node) -> R, + { + let parent_idx = self.nodes[node.index()].parent().index(); + let grand_parent_idx = self.nodes[parent_idx].parent().index(); + op(&self.nodes[grand_parent_idx]) } - fn left_owned(&self) -> NodeRef { - self.left.as_ref().unwrap().clone_rc() + fn left_mut(&'a mut self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a mut Node) -> R, + { + let idx = self.nodes[node.index()].left().index(); + op(&mut self.nodes[idx]) } - fn right_owned(&self) -> NodeRef { - self.right.as_ref().unwrap().clone_rc() + fn right_mut(&'a mut self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a mut Node) -> R, + { + let idx = self.nodes[node.index()].right().index(); + op(&mut self.nodes[idx]) } - fn parent_owned(&self) -> NodeRef { - self.parent.as_ref().unwrap().clone_rc() + fn parent_mut(&'a mut self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a mut Node) -> R, + { + let idx = self.nodes[node.index()].parent().index(); + op(&mut self.nodes[idx]) } - fn set_color(&mut self, color: Color) { - self.color = color; + fn grand_parent_mut(&'a mut self, node: NodeIndex, op: F) -> R + where + R: 'a, + F: FnOnce(&'a mut Node) -> R, + { + let parent_idx = self.nodes[node.index()].parent().index(); + let grand_parent_idx = self.nodes[parent_idx].parent().index(); + op(&mut self.nodes[grand_parent_idx]) } } -/// `RefCell` reference to `Node` -struct NodeRef(Rc>>); - -impl Deref for NodeRef { - type Target = Rc>>; +/// An iterator over the entries of a `IntervalMap`. +#[allow(missing_debug_implementations)] +pub struct Iter<'a, T, V, Ix> { + /// Reference to the map + map_ref: &'a IntervalMap, + /// Stack for iteration + stack: Option>>, +} - fn deref(&self) -> &Self::Target { - &self.0 +impl Iter<'_, T, V, Ix> +where + Ix: IndexType, +{ + /// Initiliazes the stack + fn init_stack(&mut self) { + self.stack = Some(Self::left_tree(self.map_ref, self.map_ref.root)); } -} -impl PartialEq for NodeRef { - fn eq(&self, other: &Self) -> bool { - Rc::ptr_eq(self, other) + /// Pushes x and x's left sub tree to stack. + fn left_tree(map_ref: &IntervalMap, mut x: NodeIndex) -> Vec> { + let mut nodes = vec![]; + while !map_ref.nref(x, Node::is_sentinel) { + nodes.push(x); + x = map_ref.nref(x, Node::left); + } + nodes } } -impl Eq for NodeRef {} +impl<'a, T, V, Ix> Iterator for Iter<'a, T, V, Ix> +where + Ix: IndexType, +{ + type Item = (&'a Interval, &'a V); -#[allow(clippy::missing_docs_in_private_items)] -impl NodeRef { - fn clone_rc(&self) -> Self { - Self(Rc::clone(self)) + #[allow(clippy::unwrap_used, clippy::unwrap_in_result)] + #[inline] + fn next(&mut self) -> Option { + if self.stack.is_none() { + self.init_stack(); + } + let stack = self.stack.as_mut().unwrap(); + if stack.is_empty() { + return None; + } + let x = stack.pop().unwrap(); + stack.extend(Self::left_tree( + self.map_ref, + self.map_ref.nref(x, Node::right), + )); + Some(self.map_ref.nref(x, |x| (x.interval(), x.value()))) } } -#[allow(clippy::missing_docs_in_private_items, clippy::unwrap_used)] -impl NodeRef { - fn is_sentinel(&self) -> bool { - self.borrow().interval.is_none() - } +/// A view into a single entry in a map, which may either be vacant or occupied. +#[allow(missing_debug_implementations, clippy::exhaustive_enums)] +pub enum Entry<'a, T, V, Ix> { + /// An occupied entry. + Occupied(OccupiedEntry<'a, T, V, Ix>), + /// A vacant entry. + Vacant(VacantEntry<'a, T, V, Ix>), +} - fn is_black(&self) -> bool { - matches!(self.borrow().color, Color::Black) - } +/// A view into an occupied entry in a `IntervalMap`. +/// It is part of the [`Entry`] enum. +#[allow(missing_debug_implementations)] +pub struct OccupiedEntry<'a, T, V, Ix> { + /// Reference to the map + map_ref: &'a mut IntervalMap, + /// The entry node + node: NodeIndex, +} - fn is_red(&self) -> bool { - matches!(self.borrow().color, Color::Red) - } +/// A view into a vacant entry in a `IntervalMap`. +/// It is part of the [`Entry`] enum. +#[allow(missing_debug_implementations)] +pub struct VacantEntry<'a, T, V, Ix> { + /// Mutable reference to the map + map_ref: &'a mut IntervalMap, + /// The interval of this entry + interval: Interval, +} - fn color(&self) -> Color { - self.borrow().color() +impl<'a, T, V, Ix> Entry<'a, T, V, Ix> +where + T: Ord + Clone, + Ix: IndexType, +{ + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + #[inline] + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Entry::Occupied(entry) => entry.map_ref.nmut(entry.node, Node::value_mut), + Entry::Vacant(entry) => { + let _ignore = entry.map_ref.insert(entry.interval, default); + let entry_idx = NodeIndex::new(entry.map_ref.len().wrapping_sub(1)); + entry.map_ref.nmut(entry_idx, Node::value_mut) + } + } } - fn max_owned(&self) -> T + /// Provides in-place mutable access to an occupied entry before any + /// potential inserts into the map. + /// + /// # Panics + /// + /// This method panics when the node is a sentinel node + #[allow(clippy::unwrap_used)] + #[inline] + #[must_use] + pub fn and_modify(self, f: F) -> Self where - T: Clone, + F: FnOnce(&mut V), { - self.borrow().max().clone() + match self { + Entry::Occupied(entry) => { + f(entry.map_ref.nmut(entry.node, Node::value_mut)); + Self::Occupied(entry) + } + Entry::Vacant(entry) => Self::Vacant(entry), + } } +} - fn left_owned(&self) -> NodeRef { - self.borrow().left_owned() - } +// TODO: better typed `Node` +/// Node of the interval tree +#[derive(Debug)] +pub struct Node { + /// Left children + left: Option>, + /// Right children + right: Option>, + /// Parent + parent: Option>, + /// Color of the node + color: Color, - fn right_owned(&self) -> NodeRef { - self.borrow().right_owned() - } + /// Interval of the node + interval: Option>, + /// Max value of the sub-tree of the node + max: Option, + /// Value of the node + value: Option, +} - fn parent_owned(&self) -> NodeRef { - self.borrow().parent_owned() +#[allow(clippy::missing_docs_in_private_items)] +#[allow(clippy::unwrap_used)] +impl Node +where + Ix: IndexType, +{ + fn color(&self) -> Color { + self.color } - fn grand_parent_owned(&self) -> NodeRef { - self.borrow().parent().parent_owned() + fn interval(&self) -> &Interval { + self.interval.as_ref().unwrap() } - fn take_value(self) -> V { - self.borrow_mut().value.take().unwrap() + fn max(&self) -> &T { + self.max.as_ref().unwrap() } - fn set_value(&self, new_value: V) -> V { - self.borrow_mut().value.replace(new_value).unwrap() + fn max_owned(&self) -> T + where + T: Clone, + { + self.max().clone() } - fn set_color(&self, color: Color) { - self.borrow_mut().set_color(color); + fn left(&self) -> NodeIndex { + self.left.unwrap() } - fn set_color_fn(color: Color) -> impl FnOnce(&NodeRef) { - move |node: &NodeRef| { - node.borrow_mut().set_color(color); - } + fn right(&self) -> NodeIndex { + self.right.unwrap() } - fn set_right(&self, node: NodeRef) { - let _ignore = self.borrow_mut().right.replace(node); + fn parent(&self) -> NodeIndex { + self.parent.unwrap() } - fn set_max(&self, max: T) { - let _ignore = self.borrow_mut().max.replace(max); + fn is_sentinel(&self) -> bool { + self.interval.is_none() } - fn set_left(&self, node: NodeRef) { - let _ignore = self.borrow_mut().left.replace(node); + fn sentinel(&self) -> Option<&Self> { + self.interval.is_some().then_some(self) } - fn set_parent(&self, node: NodeRef) { - let _ignore = self.borrow_mut().parent.replace(node); + fn is_black(&self) -> bool { + matches!(self.color, Color::Black) } -} -#[allow(clippy::missing_docs_in_private_items)] -impl NodeRef { - fn max(&self, op: F) -> R - where - F: FnOnce(&T) -> R, - { - op(self.borrow().max()) + fn is_red(&self) -> bool { + matches!(self.color, Color::Red) } - fn interval(&self, op: F) -> R - where - F: FnOnce(&Interval) -> R, - { - op(self.borrow().interval()) + fn value(&self) -> &V { + self.value.as_ref().unwrap() } - fn value(&self, op: F) -> R - where - F: FnOnce(&V) -> R, - { - op(self.borrow().value()) + fn value_mut(&mut self) -> &mut V { + self.value.as_mut().unwrap() } - fn left(&self, op: F) -> R - where - F: FnOnce(&NodeRef) -> R, - { - op(self.borrow().left()) + fn take_value(&mut self) -> V { + self.value.take().unwrap() } - fn right(&self, op: F) -> R - where - F: FnOnce(&NodeRef) -> R, - { - op(self.borrow().right()) + fn set_value(value: V) -> impl FnOnce(&mut Node) -> V { + move |node: &mut Node| node.value.replace(value).unwrap() } - fn parent(&self, op: F) -> R - where - F: FnOnce(&NodeRef) -> R, - { - op(self.borrow().parent()) + fn set_color(color: Color) -> impl FnOnce(&mut Node) { + move |node: &mut Node| { + node.color = color; + } } - fn grand_parent(&self, op: F) -> R - where - F: FnOnce(&NodeRef) -> R, - { - let mut grand_parent = self.borrow().parent().borrow().parent_owned(); - op(&mut grand_parent) + fn set_max(max: T) -> impl FnOnce(&mut Node) { + move |node: &mut Node| { + let _ignore = node.max.replace(max); + } } -} - -/// An iterator over the entries of a `IntervalMap`. -#[allow(missing_debug_implementations)] -pub struct Iter<'a, T, V> { - /// Reference to the map - map_ref: &'a IntervalMap, - /// Stack for iteration - stack: Vec>, -} -impl Iter<'_, T, V> { - /// Pushes x and x's left sub tree to stack. - fn left_tree(mut x: NodeRef) -> Vec> { - let mut nodes = vec![]; - while !x.is_sentinel() { - nodes.push(x.clone_rc()); - x = x.left_owned(); + fn set_left(left: NodeIndex) -> impl FnOnce(&mut Node) { + move |node: &mut Node| { + let _ignore = node.left.replace(left); } - nodes } -} -impl<'a, T, V> Iterator for Iter<'a, T, V> { - type Item = OccupiedEntry<'a, T, V>; - - #[allow(clippy::unwrap_used, clippy::unwrap_in_result)] - #[inline] - fn next(&mut self) -> Option { - if self.stack.is_empty() { - return None; + fn set_right(right: NodeIndex) -> impl FnOnce(&mut Node) { + move |node: &mut Node| { + let _ignore = node.right.replace(right); } - let x = self.stack.pop().unwrap(); - self.stack.extend(Self::left_tree(x.right_owned())); - Some(OccupiedEntry { - _map_ref: self.map_ref, - node: x, - }) } -} -/// The color of the node -#[derive(Debug, Clone, Copy)] -enum Color { - /// Red node - Red, - /// Black node - Black, + fn set_parent(parent: NodeIndex) -> impl FnOnce(&mut Node) { + move |node: &mut Node| { + let _ignore = node.parent.replace(parent); + } + } } /// The Interval stored in `IntervalMap` @@ -811,92 +945,44 @@ impl Interval { } /// Checks if self overlaps with other interval - fn overlap(&self, other: &Self) -> bool { + #[inline] + pub fn overlap(&self, other: &Self) -> bool { self.high > other.low && other.high > self.low } } -/// A view into a single entry in a map, which may either be vacant or occupied. -#[allow(missing_debug_implementations, clippy::exhaustive_enums)] -pub enum Entry<'a, T, V> { - /// An occupied entry. - Occupied(OccupiedEntry<'a, T, V>), - /// A vacant entry. - Vacant(VacantEntry<'a, T, V>), -} - -/// A view into an occupied entry in a `IntervalMap`. -/// It is part of the [`Entry`] enum. -#[allow(missing_debug_implementations)] -pub struct OccupiedEntry<'a, T, V> { - /// Reference to the map - _map_ref: &'a IntervalMap, - /// The entry node - node: NodeRef, -} - -/// A view into a vacant entry in a `IntervalMap`. -/// It is part of the [`Entry`] enum. -#[allow(missing_debug_implementations)] -pub struct VacantEntry<'a, T, V> { - /// Mutable reference to the map - map_ref: &'a mut IntervalMap, - /// The interval of this entry - interval: Interval, +/// Reference type of `Interval` +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct IntervalRef<'a, T> { + /// Low value + low: &'a T, + /// high value + high: &'a T, } -impl Entry<'_, T, V> -where - T: Ord + Clone, -{ - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - #[inline] - pub fn or_insert(self, default: V) { - if let Entry::Vacant(entry) = self { - let _ignore = entry.map_ref.insert(entry.interval, default); - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. +impl<'a, T: Ord> IntervalRef<'a, T> { + /// Creates a new `IntervalRef` /// /// # Panics /// - /// This method panics when the node is a sentinel node - #[allow(clippy::unwrap_used)] + /// This method panics when low is greater than high #[inline] - #[must_use] - pub fn and_modify(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - match self { - Entry::Occupied(entry) => { - f(entry.node.borrow_mut().value.as_mut().unwrap()); - Self::Occupied(entry) - } - Entry::Vacant(entry) => Self::Vacant(entry), - } + fn new(low: &'a T, high: &'a T) -> Self { + assert!(low < high, "invalid range"); + Self { low, high } } -} -impl OccupiedEntry<'_, T, V> { - /// Maps on the interval of this entry - #[inline] - pub fn map_interval(&self, op: F) -> R - where - F: FnOnce(&Interval) -> R, - { - self.node.interval(op) + /// Checks if self overlaps with a `Interval` + fn overlap(&self, other: &Interval) -> bool { + self.high > &other.low && &other.high > self.low } +} - /// Maps on the value of this entry - #[inline] - pub fn map_value(&self, op: F) -> R - where - F: FnOnce(&V) -> R, - { - self.node.value(op) - } +/// The color of the node +#[derive(Debug, Clone, Copy)] +enum Color { + /// Red node + Red, + /// Black node + Black, } diff --git a/crates/utils/src/interval_map/tests.rs b/crates/utils/src/interval_map/tests.rs index e87aee749..c449b4121 100644 --- a/crates/utils/src/interval_map/tests.rs +++ b/crates/utils/src/interval_map/tests.rs @@ -46,17 +46,17 @@ impl IntervalGenerator { impl IntervalMap { fn check_max(&self) { - let _ignore = Self::check_max_inner(&self.root); + let _ignore = self.check_max_inner(self.root); } - fn check_max_inner(x: &NodeRef) -> i32 { - if x.is_sentinel() { + fn check_max_inner(&self, x: NodeIndex) -> i32 { + if self.nref(x, Node::is_sentinel) { return 0; } - let l_max = Self::check_max_inner(&x.left_owned()); - let r_max = Self::check_max_inner(&x.right_owned()); - let max = x.interval(|i| i.high.max(l_max).max(r_max)); - assert_eq!(x.max_owned(), max); + let l_max = self.check_max_inner(self.nref(x, Node::left)); + let r_max = self.check_max_inner(self.nref(x, Node::right)); + let max = self.nref(x, |x| x.interval().high.max(l_max).max(r_max)); + assert_eq!(self.nref(x, Node::max_owned), max); max } @@ -67,31 +67,31 @@ impl IntervalMap { /// 5. For each node, all simple paths from the node to descendant leaves contain the /// same number of black nodes. fn check_rb_properties(&self) { - assert!(matches!(self.root.color(), Color::Black)); - Self::check_children_color(&self.root); - Self::check_black_height(&self.root); + assert!(matches!(self.nref(self.root, Node::color), Color::Black)); + self.check_children_color(self.root); + self.check_black_height(self.root); } - fn check_children_color(x: &NodeRef) { - if x.is_sentinel() { + fn check_children_color(&self, x: NodeIndex) { + if self.nref(x, Node::is_sentinel) { return; } - Self::check_children_color(&x.left_owned()); - Self::check_children_color(&x.right_owned()); - if x.is_red() { - assert!(x.left(|l| matches!(l.color(), Color::Black))); - assert!(x.right(|r| matches!(r.color(), Color::Black))); + self.check_children_color(self.nref(x, Node::left)); + self.check_children_color(self.nref(x, Node::right)); + if self.nref(x, Node::is_red) { + assert!(matches!(self.left_ref(x, Node::color), Color::Black)); + assert!(matches!(self.right_ref(x, Node::color), Color::Black)); } } - fn check_black_height(x: &NodeRef) -> usize { - if x.is_sentinel() { + fn check_black_height(&self, x: NodeIndex) -> usize { + if self.nref(x, Node::is_sentinel) { return 0; } - let lefth = Self::check_black_height(&x.left_owned()); - let righth = Self::check_black_height(&x.right_owned()); + let lefth = self.check_black_height(self.nref(x, Node::left)); + let righth = self.check_black_height(self.nref(x, Node::right)); assert_eq!(lefth, righth); - if x.is_black() { + if self.nref(x, Node::is_black) { return lefth + 1; } lefth @@ -257,7 +257,7 @@ fn find_all_overlap() { expect.sort_unstable(); result.sort_unstable(); assert_eq!(expect.len(), result.len()); - for (e, r) in expect.into_iter().zip(result.iter()) { + for (e, r) in expect.into_iter().zip(result.into_iter()) { assert_eq!(e, r); } } @@ -267,20 +267,21 @@ fn find_all_overlap() { #[test] fn entry_modify() { let mut map = IntervalMap::new(); - map.insert(Interval::new(1, 3), 0); - map.insert(Interval::new(2, 4), 0); - map.insert(Interval::new(6, 7), 0); - map.insert(Interval::new(7, 11), 0); + map.insert(Interval::new(1, 3), 1); + map.insert(Interval::new(2, 4), 2); + map.insert(Interval::new(6, 7), 3); + map.insert(Interval::new(7, 11), 4); let _ignore = map.entry(Interval::new(6, 7)).and_modify(|v| *v += 1); - let _ignore = map - .entry(Interval::new(6, 7)) - .and_modify(|v| assert_eq!(*v, 1)); + assert_eq!(map.get(&Interval::new(1, 3)), Some(&1)); + assert_eq!(map.get(&Interval::new(2, 4)), Some(&2)); + assert_eq!(map.get(&Interval::new(6, 7)), Some(&4)); + assert_eq!(map.get(&Interval::new(7, 11)), Some(&4)); + assert_eq!(map.get(&Interval::new(5, 17)), None); map.entry(Interval::new(3, 5)) .and_modify(|v| *v += 1) .or_insert(0); - let _ignore = map - .entry(Interval::new(3, 5)) - .and_modify(|v| assert_eq!(*v, 0)); + let _ignore = map.get_mut(&Interval::new(3, 5)).map(|v| *v += 1); + assert_eq!(map.get(&Interval::new(3, 5)), Some(&1)); } #[test] @@ -296,9 +297,9 @@ fn iterate_through_map() { intervals.sort_unstable_by(|a, b| a.1.cmp(&b.1)); #[allow(clippy::pattern_type_mismatch)] - for (entry, (v, i)) in map.iter().zip(intervals.iter()) { - entry.map_interval(|ei| assert_eq!(ei, i)); - entry.map_value(|ev| assert_eq!(ev, v)); + for ((ei, ev), (v, i)) in map.iter().zip(intervals.iter()) { + assert_eq!(ei, i); + assert_eq!(ev, v); } }); } diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 61a6404df..9df453778 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -176,10 +176,10 @@ pub struct ClientTlsConfig; #[non_exhaustive] pub struct ServerTlsConfig; -/// Interval tree implementation -pub mod array_interval_map; /// configuration pub mod config; +/// Interval tree implementation +pub mod interval_map; /// utils for metrics pub mod metrics; /// utils of `parking_lot` lock