use crate::flow::comparator::*; use crate::flow::traversible::*; use crate::func::fail::*; fn and(_l: (), _r: ()) {} struct SubsetContext<'a, T: MonadFail<'a, ()>, A: 'a, D: 'a + PartialEq> { comparator: &'a dyn Comparator, n_subset: Arc>, n_superset: Arc>, k_l: Option, k_r: Option, t_superl: Arc>, t_superr: Arc>, k_super: A, } impl<'a, T: 'a + MonadFail<'a, ()>, A: 'a + Send + Clone, D: 'a + PartialEq> SubsetContext<'a, T, A, D> { fn on_l(self, (t_subl, t_subr, k_sub): Split<'a, T, A, D>) -> T::F<()> { T::la2( algorithms::contains::t_contains(self.comparator, self.t_superl.clone(), k_sub.clone()), T::la2( t_subset_of_t( self.comparator, t_subl, self.t_superl, self.k_l, Some(k_sub.clone()), ), t_subset_of_t( self.comparator, t_subr, self.n_superset.to_tree(), Some(k_sub), self.k_r, ), and, ), and, ) } fn on_e(self, (t_subl, t_subr, k_sub): Split<'a, T, A, D>) -> T::F<()> { T::la2( t_subset_of_t( self.comparator, t_subl, self.t_superl, self.k_l, Some(k_sub.clone()), ), t_subset_of_t( self.comparator, t_subr, self.t_superr, Some(k_sub), self.k_r, ), and, ) } fn on_r(self, (t_subl, t_subr, k_sub): Split<'a, T, A, D>) -> T::F<()> { T::la2( algorithms::contains::t_contains(self.comparator, self.t_superr.clone(), k_sub.clone()), T::la2( t_subset_of_t( self.comparator, t_subl, self.n_superset.to_tree(), self.k_l, Some(k_sub.clone()), ), t_subset_of_t( self.comparator, t_subr, self.t_superr, Some(k_sub), self.k_r, ), and, ), and, ) } fn test_unoptimised(self) -> T::F<()> { let split = self.n_subset.split(); match self.comparator.compare(&split.2, &self.k_super) { Comparison::L => self.on_l(split), Comparison::E => self.on_e(split), Comparison::R => self.on_r(split), } } fn outside_l(&self) -> bool { outside_l(self.comparator, &self.k_l, &self.k_super) } fn outside_r(&self) -> bool { outside_r(self.comparator, &self.k_r, &self.k_super) } fn test_r_only(self) -> T::F<()> { t_subset_of_t( self.comparator, self.n_subset.to_tree(), self.t_superr, self.k_l, self.k_r, ) } fn test_l_only(self) -> T::F<()> { t_subset_of_t( self.comparator, self.n_subset.to_tree(), self.t_superl, self.k_l, self.k_r, ) } fn test_optimised(self) -> T::F<()> { if self.outside_l() { self.test_r_only() } else if self.outside_r() { self.test_l_only() } else { self.test_unoptimised() } } } fn outside_l(comparator: &dyn Comparator, k_l: &Option, k_super: &A) -> bool { if let Some(a_l) = k_l { comparator.compare(a_l, k_super) == Comparison::R } else { false } } fn outside_r(comparator: &dyn Comparator, k_r: &Option, k_super: &A) -> bool { if let Some(a_r) = k_r { comparator.compare(a_r, k_super) == Comparison::L } else { false } } pub fn n_subset_of_n<'a, T: MonadFail<'a, ()>, A: 'a + Send + Clone, D: 'a + PartialEq>( comparator: &'a dyn Comparator, n_subset: Arc>, n_superset: Arc>, k_l: Option, k_r: Option, ) -> T::F<()> { let (t_superl, t_superr, k_super) = n_superset.split(); SubsetContext { comparator, n_subset, n_superset, k_l, k_r, t_superl, t_superr, k_super, } .test_optimised() } pub fn r_subset_of_r_unoptimised< 'a, T: MonadFail<'a, ()>, A: 'a + Send + Clone, D: 'a + PartialEq, >( comparator: &'a dyn Comparator, r_subset: Arc>, r_superset: Arc>, k_l: Option, k_r: Option, ) -> T::F<()> { T::bind2( r_subset.resolve(), r_superset.resolve(), move |n_subset, n_superset| n_subset_of_n(comparator, n_subset, n_superset, k_l, k_r), ) } fn r_subset_of_r_optimised<'a, T: MonadFail<'a, ()>, A: 'a + Send + Clone, D: 'a + PartialEq>( r_subset: Arc>, r_superset: Arc>, comparator: &'a dyn Comparator, k_l: Option, k_r: Option, ) -> >::F<()> { if r_subset.data() == r_superset.data() { T::pure(()) } else { r_subset_of_r_unoptimised(comparator, r_subset, r_superset, k_l, k_r) } } pub fn t_subset_of_t<'a, T: MonadFail<'a, ()>, A: 'a + Send + Clone, D: 'a + PartialEq>( comparator: &'a dyn Comparator, t_subset: Arc>, t_superset: Arc>, k_l: Option, k_r: Option, ) -> T::F<()> { match (t_subset.refer(), t_superset.refer()) { (None, _) => T::pure(()), (Some(_), None) => T::fail(()), (Some(r_subset), Some(r_superset)) => { r_subset_of_r_optimised(r_subset, r_superset, comparator, k_l, k_r) } } }