From 60df99ff4edc4422e29397bd8539b1da6931f204 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Wed, 18 Nov 2020 23:32:44 +0100 Subject: [PATCH] Implemented 'cmp', 'partial_cmp', 'eq', 'ne', 'lt', 'le', 'gt' and 'ge' operation --- asparit/src/core/executor.rs | 2 + asparit/src/core/iterator.rs | 125 +++++++++++++++++++ asparit/src/executor/sequential.rs | 4 + asparit/src/executor/tokio.rs | 4 + asparit/src/iter/cmp.rs | 187 +++++++++++++++++++++++++++++ asparit/src/iter/find.rs | 6 +- asparit/src/iter/mod.rs | 10 +- 7 files changed, 330 insertions(+), 8 deletions(-) create mode 100644 asparit/src/iter/cmp.rs diff --git a/asparit/src/core/executor.rs b/asparit/src/core/executor.rs index b42eeca..c90cfa6 100644 --- a/asparit/src/core/executor.rs +++ b/asparit/src/core/executor.rs @@ -23,6 +23,8 @@ where C: Consumer + 'a, R: Reducer + Send + 'a; + fn ready(self, value: T1) -> Self::Result; + fn split(self) -> (Self, Self); fn join(left: Self::Result, right: Self::Result, reducer: R) -> Self::Result diff --git a/asparit/src/core/iterator.rs b/asparit/src/core/iterator.rs index 265e045..3217a6e 100644 --- a/asparit/src/core/iterator.rs +++ b/asparit/src/core/iterator.rs @@ -10,6 +10,7 @@ use crate::{ chain::Chain, chunks::Chunks, cloned::Cloned, + cmp::{Cmp, Compare, Equal, PartialCmp}, collect::Collect, copied::Copied, count::Count, @@ -1916,6 +1917,130 @@ pub trait IndexedParallelIterator<'a>: ParallelIterator<'a> { Chunks::new(self, chunk_size) } + /// Lexicographically compares the elements of this `ParallelIterator` with those of + /// another. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// use std::cmp::Ordering::*; + /// + /// let x = vec![1, 2, 3]; + /// assert_eq!(x.par_iter().cmp(&vec![1, 3, 0]), Less); + /// assert_eq!(x.par_iter().cmp(&vec![1, 2, 3]), Equal); + /// assert_eq!(x.par_iter().cmp(&vec![1, 2]), Greater); + /// ``` + fn cmp(self, other: X) -> Cmp + where + X: IntoParallelIterator<'a, Item = Self::Item>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: Ord, + { + Cmp::new(self, other.into_par_iter()) + } + + /// Lexicographically compares the elements of this `ParallelIterator` with those of + /// another. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// use std::cmp::Ordering::*; + /// use std::f64::NAN; + /// + /// let x = vec![1.0, 2.0, 3.0]; + /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, 3.0, 0.0]), Some(Less)); + /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, 2.0, 3.0]), Some(Equal)); + /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, 2.0]), Some(Greater)); + /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, NAN]), None); + /// ``` + fn partial_cmp(self, other: X) -> PartialCmp + where + X: IntoParallelIterator<'a>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: PartialOrd, + { + PartialCmp::new(self, other.into_par_iter()) + } + + /// Determines if the elements of this `ParallelIterator` + /// are equal to those of another + fn eq(self, other: X) -> Equal + where + X: IntoParallelIterator<'a>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: PartialEq, + { + Equal::new(self, other.into_par_iter(), true) + } + + /// Determines if the elements of this `ParallelIterator` + /// are unequal to those of another + fn ne(self, other: X) -> Equal + where + X: IntoParallelIterator<'a>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: PartialEq, + { + Equal::new(self, other.into_par_iter(), false) + } + + /// Determines if the elements of this `ParallelIterator` + /// are lexicographically less than those of another. + fn lt(self, other: X) -> Compare + where + X: IntoParallelIterator<'a>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: PartialOrd, + { + Compare::new(self, other.into_par_iter(), Ordering::Less, None) + } + + /// Determines if the elements of this `ParallelIterator` + /// are less or equal to those of another. + fn le(self, other: X) -> Compare + where + X: IntoParallelIterator<'a>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: PartialOrd, + { + Compare::new( + self, + other.into_par_iter(), + Ordering::Less, + Some(Ordering::Equal), + ) + } + + /// Determines if the elements of this `ParallelIterator` + /// are lexicographically greater than those of another. + fn gt(self, other: X) -> Compare + where + X: IntoParallelIterator<'a>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: PartialOrd, + { + Compare::new(self, other.into_par_iter(), Ordering::Greater, None) + } + + /// Determines if the elements of this `ParallelIterator` + /// are less or equal to those of another. + fn ge(self, other: X) -> Compare + where + X: IntoParallelIterator<'a>, + X::Iter: IndexedParallelIterator<'a>, + Self::Item: PartialOrd, + { + Compare::new( + self, + other.into_par_iter(), + Ordering::Greater, + Some(Ordering::Equal), + ) + } + /// Creates an iterator that yields the first `n` elements. /// /// # Examples diff --git a/asparit/src/executor/sequential.rs b/asparit/src/executor/sequential.rs index 4b20844..2ef8b80 100644 --- a/asparit/src/executor/sequential.rs +++ b/asparit/src/executor/sequential.rs @@ -38,6 +38,10 @@ where } } + fn ready(self, value: T1) -> Self::Result { + value + } + fn split(self) -> (Self, Self) { (Self, Self) } diff --git a/asparit/src/executor/tokio.rs b/asparit/src/executor/tokio.rs index c4789dc..3e3090c 100644 --- a/asparit/src/executor/tokio.rs +++ b/asparit/src/executor/tokio.rs @@ -62,6 +62,10 @@ where exec_indexed(splitter, producer, consumer) } + fn ready(self, value: T1) -> Self::Result { + async move { value }.boxed() + } + fn split(self) -> (Self, Self) { let mut left = self; let right = Self { diff --git a/asparit/src/iter/cmp.rs b/asparit/src/iter/cmp.rs new file mode 100644 index 0000000..6f8a165 --- /dev/null +++ b/asparit/src/iter/cmp.rs @@ -0,0 +1,187 @@ +use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; + +use crate::{Driver, Executor, IndexedParallelIterator, ParallelIterator, WithIndexedProducer}; + +/* Cmp */ + +pub struct Cmp { + iterator_a: XA, + iterator_b: XB, +} + +impl Cmp { + pub fn new(iterator_a: XA, iterator_b: XB) -> Self { + Self { + iterator_a, + iterator_b, + } + } +} + +impl<'a, XA, XB, I> Driver<'a, Ordering, Option> for Cmp +where + XA: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + XB: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + I: Ord + Send + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, Ordering, Option>, + { + let Self { + iterator_a, + iterator_b, + } = self; + + let len_a = iterator_a.len_hint(); + let len_b = iterator_b.len_hint(); + let ord_len = len_a.cmp(&len_b); + + let executor = executor.into_inner(); + let inner = iterator_a + .zip(iterator_b) + .map(|(a, b)| Ord::cmp(&a, &b)) + .find_first(|ord| ord != &Ordering::Equal) + .exec_with(executor); + + E::map(inner, move |inner| inner.unwrap_or(ord_len)) + } +} + +/* PartialCmp */ + +pub struct PartialCmp { + iterator_a: XA, + iterator_b: XB, +} + +impl PartialCmp { + pub fn new(iterator_a: XA, iterator_b: XB) -> Self { + Self { + iterator_a, + iterator_b, + } + } +} + +impl<'a, XA, XB, I> Driver<'a, Option, Option>> for PartialCmp +where + XA: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + XB: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + I: PartialOrd + Send + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, Option, Option>>, + { + let Self { + iterator_a, + iterator_b, + } = self; + + let len_a = iterator_a.len_hint(); + let len_b = iterator_b.len_hint(); + let ord_len = len_a.cmp(&len_b); + + let executor = executor.into_inner(); + let inner = iterator_a + .zip(iterator_b) + .map(|(a, b)| PartialOrd::partial_cmp(&a, &b)) + .find_first(|ord| ord != &Some(Ordering::Equal)) + .exec_with(executor); + + E::map(inner, move |inner| inner.unwrap_or(Some(ord_len))) + } +} + +/* Equal */ + +pub struct Equal { + iterator_a: XA, + iterator_b: XB, + expected: bool, +} + +impl Equal { + pub fn new(iterator_a: XA, iterator_b: XB, expected: bool) -> Self { + Self { + iterator_a, + iterator_b, + expected, + } + } +} + +impl<'a, XA, XB, I> Driver<'a, bool, Option> for Equal +where + XA: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + XB: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + I: PartialEq + Send + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, bool, Option>, + { + let Self { + iterator_a, + iterator_b, + expected, + } = self; + + let len_a = iterator_a.len_hint(); + let len_b = iterator_b.len_hint(); + + if (len_a == len_b) ^ expected { + return executor.ready(false); + } + + iterator_a + .zip(iterator_b) + .all(move |(x, y)| dbg!(PartialEq::eq(&x, &y)) == expected) + .exec_with(executor) + } +} + +/* Compare */ + +pub struct Compare { + iterator_a: XA, + iterator_b: XB, + ord: Ordering, + ord_opt: Option, +} + +impl Compare { + pub fn new(iterator_a: XA, iterator_b: XB, ord: Ordering, ord_opt: Option) -> Self { + Self { + iterator_a, + iterator_b, + ord, + ord_opt, + } + } +} + +impl<'a, XA, XB, I> Driver<'a, bool, Option, Option>> for Compare +where + XA: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + XB: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, + I: PartialOrd + Send + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, bool, Option, Option>>, + { + let Self { + iterator_a, + iterator_b, + ord, + ord_opt, + } = self; + + let executor = executor.into_inner(); + let inner = PartialCmp::new(iterator_a, iterator_b).exec_with(executor); + + E::map(inner, move |inner| inner == Some(ord) || inner == ord_opt) + } +} diff --git a/asparit/src/iter/find.rs b/asparit/src/iter/find.rs index e5a1917..2208b57 100644 --- a/asparit/src/iter/find.rs +++ b/asparit/src/iter/find.rs @@ -160,7 +160,7 @@ where ) .exec_with(executor); - E::map(ret, |x| x.is_some()) + E::map(ret, |x| x.is_none()) } } @@ -265,8 +265,8 @@ where loop { let boundary = match self.find_match { FindMatch::Any if found > 0 => return self, - FindMatch::First if found < self.lower_bound => return self, - FindMatch::Last if found > self.upper_bound => return self, + FindMatch::First if found != 0 && found < self.lower_bound => return self, + FindMatch::Last if found != 0 && found > self.upper_bound => return self, FindMatch::Any => self.lower_bound, FindMatch::First => self.lower_bound, FindMatch::Last => self.upper_bound, diff --git a/asparit/src/iter/mod.rs b/asparit/src/iter/mod.rs index 6443634..722196a 100644 --- a/asparit/src/iter/mod.rs +++ b/asparit/src/iter/mod.rs @@ -1,6 +1,7 @@ pub mod chain; pub mod chunks; pub mod cloned; +pub mod cmp; pub mod collect; pub mod copied; pub mod count; @@ -40,15 +41,14 @@ mod tests { #[tokio::test(flavor = "multi_thread")] async fn test_for_each() { - vec![0usize, 1, 2, 3, 4, 5, 6, 7, 8, 9] + let x = vec![0usize, 1, 2, 3, 4] .into_par_iter() .with_splits(1) - .chunks(4) - .for_each(|x| { - dbg!(x); - }) + .lt(vec![0usize, 1, 2, 3, 4, 5]) .exec() .await; + + dbg!(x); } #[tokio::test]