From beefedaf2b3586e6aa0e638660f20397f69336ff Mon Sep 17 00:00:00 2001 From: timofey Date: Mon, 29 May 2023 17:21:47 +0000 Subject: [PATCH] better tree interfaces --- src/flow/binary.rs | 3 +- src/rcore/point.rs | 6 +++ src/rstd/collections/avl.rs | 1 + src/rstd/collections/avl/binary.rs | 6 +++ src/rstd/collections/avl/bounds.rs | 85 +++++++++++++++++++++--------- 5 files changed, 74 insertions(+), 27 deletions(-) diff --git a/src/flow/binary.rs b/src/flow/binary.rs index a330f32..726f516 100644 --- a/src/flow/binary.rs +++ b/src/flow/binary.rs @@ -25,13 +25,14 @@ pub trait BinaryTrees<'a>: 'a { fn comparator(&self) -> &Self::Comparator; fn split(&self, node: &Self::Node) -> Split<'a, Self>; - fn tree_of(&self, node: Self::Node) -> TreeRc<'a, Self>; + fn tree_of(&self, node: Self::Node) -> BTWrap<'a, Self, TreeRc<'a, Self>>; fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, NodeRc<'a, Self>>; fn equal(&self, rhs: &Self::Reference, lhs: &Self::Reference) -> bool; fn refer(&self, tree: &Self::Tree) -> Option>; } pub trait BinaryTreesMutable<'a>: BinaryTrees<'a> { + fn empty(&self) -> Self::Tree; fn join_key( &self, tl: Self::Tree, diff --git a/src/rcore/point.rs b/src/rcore/point.rs index 519874c..fb2c593 100644 --- a/src/rcore/point.rs +++ b/src/rcore/point.rs @@ -10,6 +10,12 @@ pub struct Point<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { pub origin: Rc>, } +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> PartialEq for Point<'a, Ctx, A> { + fn eq(&self, other: &Self) -> bool { + self.point == other.point + } +} + impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Clone for Point<'a, Ctx, A> { fn clone(&self) -> Self { Self { diff --git a/src/rstd/collections/avl.rs b/src/rstd/collections/avl.rs index a3f7009..ebae195 100644 --- a/src/rstd/collections/avl.rs +++ b/src/rstd/collections/avl.rs @@ -1,5 +1,6 @@ pub mod binary; pub mod bounds; +pub mod context; use std::{error::Error, fmt::Display, rc::Rc}; diff --git a/src/rstd/collections/avl/binary.rs b/src/rstd/collections/avl/binary.rs index 5f87af8..cb44ffe 100644 --- a/src/rstd/collections/avl/binary.rs +++ b/src/rstd/collections/avl/binary.rs @@ -7,6 +7,12 @@ pub struct AvlReference<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { parent_height: u64, } +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> PartialEq for AvlReference<'a, Ctx, A> { + fn eq(&self, other: &Self) -> bool { + self.node == other.node && self.parent_height == other.parent_height + } +} + pub type AvlResult<'a, Ctx, A, T> = Result>>>; pub type AvlNodeResult<'a, Ctx, A> = AvlResult<'a, Ctx, A, AvlNode<'a, Ctx, A>>; diff --git a/src/rstd/collections/avl/bounds.rs b/src/rstd/collections/avl/bounds.rs index 6f7bad1..bfc929d 100644 --- a/src/rstd/collections/avl/bounds.rs +++ b/src/rstd/collections/avl/bounds.rs @@ -51,7 +51,9 @@ pub struct BoundTree<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { } pub struct BoundNode<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { - node: AvlNode<'a, Ctx, A>, + l: BoundTree<'a, Ctx, A>, + r: BoundTree<'a, Ctx, A>, + key: Rc, bounds: Bounds, } @@ -116,13 +118,30 @@ impl Bounds { } Self::new(l.l, r.r, comparator) } + + pub fn equal_bound( + lhs: &Option>, + rhs: &Option>, + comparator: &impl Comparator, + ) -> bool { + match (lhs, rhs) { + (None, None) => true, + (Some(kl), Some(kr)) => matches!(comparator.pick_smaller(kl, kr), Comparison::E), + _ => false, + } + } + + pub fn equal(lhs: &Self, rhs: &Self, comparator: &impl Comparator) -> bool { + Self::equal_bound(&lhs.l, &rhs.l, comparator) + && Self::equal_bound(&lhs.r, &rhs.r, comparator) + } } pub type BoundSplit<'a, Ctx, A> = (BoundTree<'a, Ctx, A>, BoundTree<'a, Ctx, A>, Rc); impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundNode<'a, Ctx, A> { pub fn into_tree(self) -> BoundTreeResult<'a, Ctx, A> { - let tree = self.node.into_tree()?; + let tree = AvlNode::new(self.l.tree, self.r.tree, self.key)?.into_tree()?; let bounds = self.bounds; Ok(BoundTree { tree, bounds }) } @@ -133,27 +152,12 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundNode<'a, Ctx, A> { key: Rc, comparator: &impl Comparator, ) -> BoundNodeResult<'a, Ctx, A> { - let bounds = Bounds::join(l.bounds, r.bounds, &key, comparator)?; - let node = AvlNode::new(l.tree, r.tree, key)?; - Ok(Self { node, bounds }) + let bounds = Bounds::join(l.bounds.clone(), r.bounds.clone(), &key, comparator)?; + Ok(Self { l, r, key, bounds }) } - pub fn split( - &self, - comparator: &impl Comparator, - ) -> Result, BoundsError> { - let (bl, br) = self.bounds.clone().split(&self.node.key, comparator)?; - Ok(( - BoundTree { - tree: self.node.l.clone(), - bounds: bl, - }, - BoundTree { - tree: self.node.r.clone(), - bounds: br, - }, - self.node.key.clone(), - )) + pub fn split(&self) -> BoundSplit<'a, Ctx, A> { + (self.l.clone(), self.r.clone(), self.key.clone()) } } @@ -172,16 +176,25 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundTree<'a, Ctx, A> { } } -type BoundResolutionError<'a, Ctx, A> = +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Clone for BoundTree<'a, Ctx, A> { + fn clone(&self) -> Self { + Self { + tree: self.tree.clone(), + bounds: self.bounds.clone(), + } + } +} + +pub type BoundResolutionError<'a, Ctx, A> = ResolutionError<>::LookupError, BoundErrorA<'a, Ctx, A>>; -type BoundResolutionResult<'a, Ctx, A> = +pub type BoundResolutionResult<'a, Ctx, A> = Result, BoundResolutionError<'a, Ctx, A>>; -type BoundResolution<'a, Ctx, A> = Wrapped<'a, Ctx, BoundResolutionResult<'a, Ctx, A>>; +pub type BoundResolution<'a, Ctx, A> = Wrapped<'a, Ctx, BoundResolutionResult<'a, Ctx, A>>; impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundReference<'a, Ctx, A> { - pub fn resolve(&self) -> BoundResolution<'a, Ctx, A> { + pub fn resolve(&self, comparator: Rc>) -> BoundResolution<'a, Ctx, A> { let bounds = self.bounds.clone(); ::fmap( move |resolution| { @@ -192,9 +205,29 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> BoundReference<'a, Ctx, A> { })? .as_ref() .clone(); - Ok(BoundNode { node, bounds }) + let (bl, br) = bounds + .clone() + .split(&node.key, comparator.as_ref()) + .map_err(BoundError::Bounds) + .map_err(ResolutionError::Parse)?; + Ok(BoundNode { + l: BoundTree { + tree: node.l, + bounds: bl, + }, + r: BoundTree { + tree: node.r, + bounds: br, + }, + key: node.key, + bounds, + }) }, self.reference.resolve(), ) } + + pub fn equal(lhs: &Self, rhs: &Self, comparator: &impl Comparator) -> bool { + lhs.reference == rhs.reference && Bounds::equal(&lhs.bounds, &rhs.bounds, comparator) + } }