diff --git a/crates/sum_tree/src/sum_tree.rs b/crates/sum_tree/src/sum_tree.rs index 37acc4cffba5cc6c0c7794ef7bc5b93a85f45ba0..6992e0b0f36a7aa1a87a8ce9a31de1ff294e7322 100644 --- a/crates/sum_tree/src/sum_tree.rs +++ b/crates/sum_tree/src/sum_tree.rs @@ -401,7 +401,7 @@ impl SumTree { } let mut pos = D::zero(cx); - return match Self::find_recurse::<_, _, true>(cx, target, bias, &mut pos, self) { + return match Self::find_iterate::<_, _, true>(cx, target, bias, &mut pos, self) { Some((item, end)) => (pos, end, Some(item)), None => (pos.clone(), pos, None), }; @@ -427,68 +427,69 @@ impl SumTree { } let mut pos = D::zero(cx); - return match Self::find_recurse::<_, _, false>(cx, target, bias, &mut pos, self) { + return match Self::find_iterate::<_, _, false>(cx, target, bias, &mut pos, self) { Some((item, end)) => (pos, end, Some(item)), None => (pos.clone(), pos, None), }; } - fn find_recurse<'tree, 'a, D, Target, const EXACT: bool>( + fn find_iterate<'tree, 'a, D, Target, const EXACT: bool>( cx: ::Context<'a>, target: &Target, bias: Bias, position: &mut D, - this: &'tree SumTree, + mut this: &'tree SumTree, ) -> Option<(&'tree T, D)> where D: Dimension<'tree, T::Summary>, Target: SeekTarget<'tree, T::Summary, D>, { - match &*this.0 { - Node::Internal { - child_summaries, - child_trees, - .. - } => { - for (child_tree, child_summary) in child_trees.iter().zip(child_summaries) { - let child_end = position.clone().with_added_summary(child_summary, cx); - - let comparison = target.cmp(&child_end, cx); - let target_in_child = comparison == Ordering::Less - || (comparison == Ordering::Equal && bias == Bias::Left); - if target_in_child { - return Self::find_recurse::( - cx, target, bias, position, child_tree, - ); + 'iterate: loop { + match &*this.0 { + Node::Internal { + child_summaries, + child_trees, + .. + } => { + for (child_tree, child_summary) in child_trees.iter().zip(child_summaries) { + let child_end = position.clone().with_added_summary(child_summary, cx); + + let comparison = target.cmp(&child_end, cx); + let target_in_child = comparison == Ordering::Less + || (comparison == Ordering::Equal && bias == Bias::Left); + if target_in_child { + this = child_tree; + continue 'iterate; + } + *position = child_end; } - *position = child_end; } - } - Node::Leaf { - items, - item_summaries, - .. - } => { - for (item, item_summary) in items.iter().zip(item_summaries) { - let mut child_end = position.clone(); - child_end.add_summary(item_summary, cx); + Node::Leaf { + items, + item_summaries, + .. + } => { + for (item, item_summary) in items.iter().zip(item_summaries) { + let mut child_end = position.clone(); + child_end.add_summary(item_summary, cx); + + let comparison = target.cmp(&child_end, cx); + let entry_found = if EXACT { + comparison == Ordering::Equal + } else { + comparison == Ordering::Less + || (comparison == Ordering::Equal && bias == Bias::Left) + }; + if entry_found { + return Some((item, child_end)); + } - let comparison = target.cmp(&child_end, cx); - let entry_found = if EXACT { - comparison == Ordering::Equal - } else { - comparison == Ordering::Less - || (comparison == Ordering::Equal && bias == Bias::Left) - }; - if entry_found { - return Some((item, child_end)); + *position = child_end; } - - *position = child_end; } } + return None; } - None } /// A more efficient version of `Cursor::new()` + `Cursor::seek()` + `Cursor::item()` @@ -511,75 +512,72 @@ impl SumTree { } let mut pos = D::zero(cx); - return match Self::find_recurse_with_prev::<_, _, false>( - cx, target, bias, &mut pos, self, None, - ) { + return match Self::find_with_prev_iterate::<_, _, false>(cx, target, bias, &mut pos, self) { Some((prev, item, end)) => (pos, end, Some((prev, item))), None => (pos.clone(), pos, None), }; } - fn find_recurse_with_prev<'tree, 'a, D, Target, const EXACT: bool>( + fn find_with_prev_iterate<'tree, 'a, D, Target, const EXACT: bool>( cx: ::Context<'a>, target: &Target, bias: Bias, position: &mut D, - this: &'tree SumTree, - prev: Option<&'tree T>, + mut this: &'tree SumTree, ) -> Option<(Option<&'tree T>, &'tree T, D)> where D: Dimension<'tree, T::Summary>, Target: SeekTarget<'tree, T::Summary, D>, { - match &*this.0 { - Node::Internal { - child_summaries, - child_trees, - .. - } => { - let mut prev = prev; - for (child_tree, child_summary) in child_trees.iter().zip(child_summaries) { - let child_end = position.clone().with_added_summary(child_summary, cx); - - let comparison = target.cmp(&child_end, cx); - let target_in_child = comparison == Ordering::Less - || (comparison == Ordering::Equal && bias == Bias::Left); - if target_in_child { - return Self::find_recurse_with_prev::( - cx, target, bias, position, child_tree, prev, - ); + let mut prev = None; + 'iterate: loop { + match &*this.0 { + Node::Internal { + child_summaries, + child_trees, + .. + } => { + for (child_tree, child_summary) in child_trees.iter().zip(child_summaries) { + let child_end = position.clone().with_added_summary(child_summary, cx); + + let comparison = target.cmp(&child_end, cx); + let target_in_child = comparison == Ordering::Less + || (comparison == Ordering::Equal && bias == Bias::Left); + if target_in_child { + this = child_tree; + continue 'iterate; + } + prev = child_tree.last(); + *position = child_end; } - prev = child_tree.last(); - *position = child_end; } - } - Node::Leaf { - items, - item_summaries, - .. - } => { - let mut prev = prev; - for (item, item_summary) in items.iter().zip(item_summaries) { - let mut child_end = position.clone(); - child_end.add_summary(item_summary, cx); - - let comparison = target.cmp(&child_end, cx); - let entry_found = if EXACT { - comparison == Ordering::Equal - } else { - comparison == Ordering::Less - || (comparison == Ordering::Equal && bias == Bias::Left) - }; - if entry_found { - return Some((prev, item, child_end)); - } + Node::Leaf { + items, + item_summaries, + .. + } => { + for (item, item_summary) in items.iter().zip(item_summaries) { + let mut child_end = position.clone(); + child_end.add_summary(item_summary, cx); + + let comparison = target.cmp(&child_end, cx); + let entry_found = if EXACT { + comparison == Ordering::Equal + } else { + comparison == Ordering::Less + || (comparison == Ordering::Equal && bias == Bias::Left) + }; + if entry_found { + return Some((prev, item, child_end)); + } - prev = Some(item); - *position = child_end; + prev = Some(item); + *position = child_end; + } } } + return None; } - None } pub fn cursor<'a, 'b, D>(