diff --git a/asparit/src/core/iterator.rs b/asparit/src/core/iterator.rs index e943396..025cc60 100644 --- a/asparit/src/core/iterator.rs +++ b/asparit/src/core/iterator.rs @@ -15,7 +15,7 @@ use crate::{ count::Count, filter::Filter, filter_map::FilterMap, - find::{Find, FindMap, FindMatch}, + find::{All, Any, Find, FindMap, FindMatch}, flatten::{FlatMapIter, FlattenIter}, fold::{Fold, FoldWith}, for_each::ForEach, @@ -155,7 +155,7 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn for_each_with(self, init: T, operation: O) -> Collect, ()> where - O: Fn(&mut T, Self::Item) + Clone + Send + Sync + 'a, + O: Fn(&mut T, Self::Item) + Clone + Send + 'a, T: Clone + Send + 'a, { self.map_with(init, operation).collect() @@ -189,8 +189,8 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn for_each_init(self, init: S, operation: O) -> Collect, ()> where - O: Fn(&mut T, Self::Item) + Clone + Sync + Send + 'a, - S: Fn() -> T + Clone + Sync + Send + 'a, + O: Fn(&mut T, Self::Item) + Clone + Send + 'a, + S: Fn() -> T + Clone + Send + 'a, { self.map_init(init, operation).collect() } @@ -217,7 +217,7 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn try_for_each(self, operation: O) -> TryForEach where - O: Fn(Self::Item) -> T + Clone + Sync + Send, + O: Fn(Self::Item) -> T + Clone + Send, T: Try + Send, { TryForEach::new(self, operation) @@ -253,7 +253,7 @@ pub trait ParallelIterator<'a>: Sized + Send { fn try_for_each_with(self, init: S, operation: O) -> TryForEachWith where S: Clone + Send + 'a, - O: Fn(&mut S, Self::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut S, Self::Item) -> T + Clone + Send + 'a, T: Try + Send + 'a, { TryForEachWith::new(self, init, operation) @@ -290,8 +290,8 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn try_for_each_init(self, init: S, operation: O) -> TryForEachInit where - O: Fn(&mut U, Self::Item) -> T + Clone + Sync + Send + 'a, - S: Fn() -> U + Clone + Send + Sync + 'a, + O: Fn(&mut U, Self::Item) -> T + Clone + Send + 'a, + S: Fn() -> U + Clone + Send + 'a, T: Try + Send + 'a, { TryForEachInit::new(self, init, operation) @@ -328,7 +328,7 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn map(self, operation: O) -> Map where - O: Fn(Self::Item) -> T + Sync + Send, + O: Fn(Self::Item) -> T + Clone + Send, T: Send, { Map::new(self, operation) @@ -366,7 +366,7 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn map_with(self, init: S, operation: O) -> MapWith where - O: Fn(&mut S, Self::Item) -> T + Clone + Sync + Send, + O: Fn(&mut S, Self::Item) -> T + Clone + Send, S: Send + Clone, T: Send, { @@ -403,8 +403,8 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn map_init(self, init: S, operation: O) -> MapInit where - O: Fn(&mut U, Self::Item) -> T + Sync + Send, - S: Fn() -> U + Sync + Send, + O: Fn(&mut U, Self::Item) -> T + Send, + S: Fn() -> U + Send, T: Send, { MapInit::new(self, init, operation) @@ -707,7 +707,7 @@ pub trait ParallelIterator<'a>: Sized + Send { /// [associative]: https://en.wikipedia.org/wiki/Associative_property fn reduce_with(self, operation: O) -> ReduceWith where - O: Fn(Self::Item, Self::Item) -> Self::Item + Sync + Send + 'a, + O: Fn(Self::Item, Self::Item) -> Self::Item + Clone + Send + 'a, { ReduceWith::new(self, operation) } @@ -745,9 +745,9 @@ pub trait ParallelIterator<'a>: Sized + Send { /// ``` fn try_reduce(self, identity: S, operation: O) -> TryReduce where - S: Fn() -> T + Sync + Send, - O: Fn(T, T) -> Self::Item + Sync + Send, Self::Item: Try, + S: Fn() -> T + Clone + Send + 'a, + O: Fn(T, T) -> Self::Item + Clone + Send + 'a, { TryReduce::new(self, identity, operation) } @@ -790,7 +790,7 @@ pub trait ParallelIterator<'a>: Sized + Send { fn try_reduce_with(self, operation: O) -> TryReduceWith where Self::Item: Try, - O: Fn(T, T) -> Self::Item + Sync + Send + 'a, + O: Fn(T, T) -> Self::Item + Clone + Send + 'a, { TryReduceWith::new(self, operation) } @@ -1452,6 +1452,52 @@ pub trait ParallelIterator<'a>: Sized + Send { FindMap::new(self, operation, FindMatch::Last) } + /// Searches for **some** item in the parallel iterator that + /// matches the given operation, and if so returns true. Once + /// a match is found, we'll attempt to stop process the rest + /// of the items. Proving that there's no match, returning false, + /// does require visiting every item. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// + /// let a = [0, 12, 3, 4, 0, 23, 0]; + /// + /// let is_valid = a.par_iter().any(|&x| x > 10); + /// + /// assert!(is_valid); + /// ``` + fn any(self, operation: O) -> Any + where + O: Fn(Self::Item) -> bool + Clone + Send + 'a, + { + Any::new(self, operation) + } + + /// Tests that every item in the parallel iterator matches the given + /// operation, and if so returns true. If a counter-example is found, + /// we'll attempt to stop processing more items, then return false. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// + /// let a = [0, 12, 3, 4, 0, 23, 0]; + /// + /// let is_valid = a.par_iter().all(|&x| x > 10); + /// + /// assert!(!is_valid); + /// ``` + fn all(self, operation: O) -> All + where + O: Fn(Self::Item) -> bool + Clone + Send + 'a, + { + All::new(self, operation) + } + /// Creates a fresh collection containing all the elements produced /// by this parallel iterator. /// diff --git a/asparit/src/inner/find.rs b/asparit/src/inner/find.rs index 43fc8a1..58f9a8a 100644 --- a/asparit/src/inner/find.rs +++ b/asparit/src/inner/find.rs @@ -88,6 +88,82 @@ where } } +/* Any */ + +pub struct Any { + iterator: X, + operation: O, +} + +impl Any { + pub fn new(iterator: X, operation: O) -> Self { + Self { + iterator, + operation, + } + } +} + +impl<'a, X, O> Driver<'a, bool, Option> for Any +where + X: ParallelIterator<'a>, + O: Fn(X::Item) -> bool + Clone + Send + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, bool, Option>, + { + let executor = executor.into_inner(); + + let ret = Find::new( + self.iterator.map(self.operation), + bool::clone, + FindMatch::Any, + ) + .exec_with(executor); + + E::map(ret, |x| x.is_some()) + } +} + +/* All */ + +pub struct All { + iterator: X, + operation: O, +} + +impl All { + pub fn new(iterator: X, operation: O) -> Self { + Self { + iterator, + operation, + } + } +} + +impl<'a, X, O> Driver<'a, bool, Option> for All +where + X: ParallelIterator<'a>, + O: Fn(X::Item) -> bool + Clone + Send + 'a, +{ + fn exec_with(self, executor: E) -> E::Result + where + E: Executor<'a, bool, Option>, + { + let executor = executor.into_inner(); + + let ret = Find::new( + self.iterator.map(self.operation), + |x: &bool| !x, + FindMatch::Any, + ) + .exec_with(executor); + + E::map(ret, |x| x.is_some()) + } +} + /* FindConsumer */ struct FindConsumer { diff --git a/asparit/src/inner/map.rs b/asparit/src/inner/map.rs index 4d2a50c..09cbac1 100644 --- a/asparit/src/inner/map.rs +++ b/asparit/src/inner/map.rs @@ -19,7 +19,7 @@ impl Map { impl<'a, X, O, T> ParallelIterator<'a> for Map where X: ParallelIterator<'a>, - O: Fn(X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(X::Item) -> T + Clone + Send + 'a, T: Send + 'a, { type Item = O::Output; @@ -54,7 +54,7 @@ where impl<'a, X, O, T> IndexedParallelIterator<'a> for Map where X: IndexedParallelIterator<'a>, - O: Fn(X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(X::Item) -> T + Clone + Send + 'a, T: Send + 'a, { fn drive_indexed(self, executor: E, consumer: C) -> E::Result @@ -94,7 +94,7 @@ struct MapCallback { impl<'a, I, O, T, CB> ProducerCallback<'a, I> for MapCallback where CB: ProducerCallback<'a, T>, - O: Fn(I) -> T + Clone + Sync + Send + 'a, + O: Fn(I) -> T + Clone + Send + 'a, T: Send, { type Output = CB::Output; @@ -115,7 +115,7 @@ where impl<'a, I, O, T, CB> IndexedProducerCallback<'a, I> for MapCallback where CB: IndexedProducerCallback<'a, T>, - O: Fn(I) -> T + Clone + Sync + Send + 'a, + O: Fn(I) -> T + Clone + Send + 'a, T: Send, { type Output = CB::Output; @@ -143,7 +143,7 @@ struct MapProducer { impl Producer for MapProducer where P: Producer, - O: Fn(P::Item) -> T + Clone + Sync + Send, + O: Fn(P::Item) -> T + Clone + Send, T: Send, { type Item = O::Output; @@ -185,7 +185,7 @@ where impl IndexedProducer for MapProducer where P: IndexedProducer, - O: Fn(P::Item) -> T + Clone + Sync + Send, + O: Fn(P::Item) -> T + Clone + Send, T: Send, { type Item = O::Output; @@ -255,7 +255,7 @@ impl MapConsumer { impl Consumer for MapConsumer where C: Consumer, - O: Fn(I) -> T + Clone + Send + Sync, + O: Fn(I) -> T + Clone + Send, T: Send, { type Folder = MapFolder; diff --git a/asparit/src/inner/map_init.rs b/asparit/src/inner/map_init.rs index 3503142..39fc95a 100644 --- a/asparit/src/inner/map_init.rs +++ b/asparit/src/inner/map_init.rs @@ -26,7 +26,7 @@ impl MapInit { impl<'a, X, O, T, S, U> ParallelIterator<'a> for MapInit where X: ParallelIterator<'a>, - O: Fn(&mut U, X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut U, X::Item) -> T + Clone + Send + 'a, T: Send + 'a, S: Fn() -> U + Clone + Send + 'a, { @@ -63,7 +63,7 @@ where impl<'a, X, O, T, S, U> IndexedParallelIterator<'a> for MapInit where X: IndexedParallelIterator<'a>, - O: Fn(&mut U, X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut U, X::Item) -> T + Clone + Send + 'a, T: Send + 'a, S: Fn() -> U + Clone + Send + 'a, { @@ -106,7 +106,7 @@ struct MapInitCallback { impl<'a, I, S, O, T, U, CB> ProducerCallback<'a, I> for MapInitCallback where CB: ProducerCallback<'a, T>, - O: Fn(&mut U, I) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut U, I) -> T + Clone + Send + 'a, T: Send, S: Fn() -> U + Clone + Send + 'a, { @@ -129,7 +129,7 @@ where impl<'a, I, S, O, T, U, CB> IndexedProducerCallback<'a, I> for MapInitCallback where CB: IndexedProducerCallback<'a, T>, - O: Fn(&mut U, I) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut U, I) -> T + Clone + Send + 'a, T: Send, S: Fn() -> U + Clone + Send + 'a, { @@ -160,7 +160,7 @@ struct MapInitProducer { impl Producer for MapInitProducer where P: Producer, - O: Fn(&mut U, P::Item) -> T + Clone + Sync + Send, + O: Fn(&mut U, P::Item) -> T + Clone + Send, T: Send, S: Fn() -> U + Clone + Send, { @@ -211,7 +211,7 @@ where impl IndexedProducer for MapInitProducer where P: IndexedProducer, - O: Fn(&mut U, P::Item) -> T + Clone + Sync + Send, + O: Fn(&mut U, P::Item) -> T + Clone + Send, T: Send, S: Fn() -> U + Clone + Send, { @@ -294,7 +294,7 @@ impl MapInitConsumer { impl Consumer for MapInitConsumer where C: Consumer, - O: Fn(&mut U, I) -> T + Clone + Send + Sync, + O: Fn(&mut U, I) -> T + Clone + Send, T: Send, S: Fn() -> U + Clone + Send, { diff --git a/asparit/src/inner/map_with.rs b/asparit/src/inner/map_with.rs index 13d582e..908751d 100644 --- a/asparit/src/inner/map_with.rs +++ b/asparit/src/inner/map_with.rs @@ -24,7 +24,7 @@ impl MapWith { impl<'a, X, O, T, S> ParallelIterator<'a> for MapWith where X: ParallelIterator<'a>, - O: Fn(&mut S, X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut S, X::Item) -> T + Clone + Send + 'a, T: Send + 'a, S: Clone + Send + 'a, { @@ -61,7 +61,7 @@ where impl<'a, X, O, T, S> IndexedParallelIterator<'a> for MapWith where X: IndexedParallelIterator<'a>, - O: Fn(&mut S, X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut S, X::Item) -> T + Clone + Send + 'a, T: Send + 'a, S: Clone + Send + 'a, { @@ -104,7 +104,7 @@ struct MapWithCallback { impl<'a, I, S, O, T, CB> ProducerCallback<'a, I> for MapWithCallback where CB: ProducerCallback<'a, T>, - O: Fn(&mut S, I) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut S, I) -> T + Clone + Send + 'a, T: Send, S: Clone + Send + 'a, { @@ -127,7 +127,7 @@ where impl<'a, I, S, O, T, CB> IndexedProducerCallback<'a, I> for MapWithCallback where CB: IndexedProducerCallback<'a, T>, - O: Fn(&mut S, I) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut S, I) -> T + Clone + Send + 'a, T: Send, S: Clone + Send + 'a, { @@ -158,7 +158,7 @@ struct MapWithProducer { impl Producer for MapWithProducer where P: Producer, - O: Fn(&mut S, P::Item) -> T + Clone + Sync + Send, + O: Fn(&mut S, P::Item) -> T + Clone + Send, T: Send, S: Clone + Send, { @@ -209,7 +209,7 @@ where impl IndexedProducer for MapWithProducer where P: IndexedProducer, - O: Fn(&mut S, P::Item) -> T + Clone + Sync + Send, + O: Fn(&mut S, P::Item) -> T + Clone + Send, T: Send, S: Clone + Send, { @@ -337,7 +337,7 @@ impl MapWithConsumer { impl Consumer for MapWithConsumer where C: Consumer, - O: Fn(&mut S, I) -> T + Clone + Send + Sync, + O: Fn(&mut S, I) -> T + Clone + Send, T: Send, S: Clone + Send, { diff --git a/asparit/src/inner/try_for_each.rs b/asparit/src/inner/try_for_each.rs index bc7a3f7..a79276d 100644 --- a/asparit/src/inner/try_for_each.rs +++ b/asparit/src/inner/try_for_each.rs @@ -19,7 +19,7 @@ impl TryForEach { impl<'a, X, O, T> Driver<'a, T> for TryForEach where X: ParallelIterator<'a>, - O: Fn(X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(X::Item) -> T + Clone + Send + 'a, T: Try + Send + 'a, { fn exec_with(self, executor: E) -> E::Result @@ -64,7 +64,7 @@ impl<'a, X, S, O, T> Driver<'a, T> for TryForEachWith where X: ParallelIterator<'a>, S: Clone + Send + 'a, - O: Fn(&mut S, X::Item) -> T + Clone + Sync + Send + 'a, + O: Fn(&mut S, X::Item) -> T + Clone + Send + 'a, T: Try + Send + 'a, { fn exec_with(self, executor: E) -> E::Result @@ -109,8 +109,8 @@ impl TryForEachInit { impl<'a, X, S, O, T, U> Driver<'a, T> for TryForEachInit where X: ParallelIterator<'a>, - S: Fn() -> U + Clone + Send + Sync + 'a, - O: Fn(&mut U, X::Item) -> T + Clone + Sync + Send + 'a, + S: Fn() -> U + Clone + Send + 'a, + O: Fn(&mut U, X::Item) -> T + Clone + Send + 'a, T: Try + Send + 'a, { fn exec_with(self, executor: E) -> E::Result