From de837c0ec5671baf59faae4036a89ca7e082cbad Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 7 Nov 2020 21:13:31 +0100 Subject: [PATCH] Implemented 'max' and 'max_by' operation --- asparit/src/core/iterator.rs | 55 ++++++++++++++++++++++++++++++ asparit/src/inner/max.rs | 65 ++++++++++++++++++++++++++++++++++++ asparit/src/inner/mod.rs | 1 + 3 files changed, 121 insertions(+) create mode 100644 asparit/src/inner/max.rs diff --git a/asparit/src/core/iterator.rs b/asparit/src/core/iterator.rs index c77bdcd..ce495b0 100644 --- a/asparit/src/core/iterator.rs +++ b/asparit/src/core/iterator.rs @@ -20,6 +20,7 @@ use crate::{ map::Map, map_init::MapInit, map_with::MapWith, + max::{Max, MaxBy}, min::{Min, MinBy}, product::Product, reduce::{Reduce, ReduceWith}, @@ -1139,6 +1140,60 @@ pub trait ParallelIterator<'a>: Sized + Send { MinBy::new(self, operation) } + /// Computes the maximum of all the items in the iterator. If the + /// iterator is empty, `None` is returned; otherwise, `Some(max)` + /// is returned. + /// + /// Note that the order in which the items will be reduced is not + /// specified, so if the `Ord` impl is not truly associative, then + /// the results are not deterministic. + /// + /// Basically equivalent to `self.reduce_with(|a, b| cmp::max(a, b))`. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// + /// let a = [45, 74, 32]; + /// + /// assert_eq!(a.par_iter().max(), Some(&74)); + /// + /// let b: [i32; 0] = []; + /// + /// assert_eq!(b.par_iter().max(), None); + /// ``` + fn max(self) -> Max + where + Self::Item: Ord, + { + Max::new(self) + } + + /// Computes the maximum of all the items in the iterator with respect to + /// the given comparison function. If the iterator is empty, `None` is + /// returned; otherwise, `Some(min)` is returned. + /// + /// Note that the order in which the items will be reduced is not + /// specified, so if the comparison function is not associative, then + /// the results are not deterministic. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// + /// let a = [-3_i32, 77, 53, 240, -1]; + /// + /// assert_eq!(a.par_iter().max_by(|x, y| x.abs().cmp(&y.abs())), Some(&240)); + /// ``` + fn max_by(self, operation: O) -> MaxBy + where + O: Fn(&Self::Item, &Self::Item) -> Ordering + Clone + Send + Sync + 'a, + { + MaxBy::new(self, operation) + } + /// Creates a fresh collection containing all the elements produced /// by this parallel iterator. /// diff --git a/asparit/src/inner/max.rs b/asparit/src/inner/max.rs new file mode 100644 index 0000000..df7d5f1 --- /dev/null +++ b/asparit/src/inner/max.rs @@ -0,0 +1,65 @@ +use std::cmp::{max, Ord, Ordering}; + +use crate::{Driver, Executor, ParallelIterator}; + +/* Max */ + +pub struct Max { + iterator: X, +} + +impl Max { + pub fn new(iterator: X) -> Self { + Self { iterator } + } +} + +impl<'a, X, T> Driver<'a, Option> for Max +where + X: ParallelIterator<'a, Item = T>, + T: Send + Ord + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, Option>, + { + self.iterator.reduce_with(max).exec_with(executor) + } +} + +/* MaxBy */ + +pub struct MaxBy { + iterator: X, + operation: O, +} + +impl MaxBy { + pub fn new(iterator: X, operation: O) -> Self { + Self { + iterator, + operation, + } + } +} + +impl<'a, X, O, T> Driver<'a, Option> for MaxBy +where + X: ParallelIterator<'a, Item = T>, + O: Fn(&T, &T) -> Ordering + Clone + Send + Sync + 'a, + T: Send + Ord + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, Option>, + { + let operation = self.operation; + + self.iterator + .reduce_with(move |a, b| match operation(&a, &b) { + Ordering::Greater => b, + _ => a, + }) + .exec_with(executor) + } +} diff --git a/asparit/src/inner/mod.rs b/asparit/src/inner/mod.rs index 5ffc150..f671984 100644 --- a/asparit/src/inner/mod.rs +++ b/asparit/src/inner/mod.rs @@ -11,6 +11,7 @@ pub mod inspect; pub mod map; pub mod map_init; pub mod map_with; +pub mod max; pub mod min; pub mod noop; pub mod product;