From 2a323b86779577463d341f21991cf433412ea94a Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Fri, 6 Nov 2020 21:37:23 +0100 Subject: [PATCH] Implemented 'copied' operation --- asparit/src/core/iterator.rs | 30 ++++ asparit/src/inner/copied.rs | 275 +++++++++++++++++++++++++++++++++++ asparit/src/inner/mod.rs | 1 + 3 files changed, 306 insertions(+) create mode 100644 asparit/src/inner/copied.rs diff --git a/asparit/src/core/iterator.rs b/asparit/src/core/iterator.rs index 9765431..d362a30 100644 --- a/asparit/src/core/iterator.rs +++ b/asparit/src/core/iterator.rs @@ -6,6 +6,7 @@ use crate::{ inner::{ cloned::Cloned, collect::Collect, + copied::Copied, for_each::ForEach, map::Map, map_init::MapInit, @@ -405,6 +406,35 @@ pub trait ParallelIterator<'a>: Sized + Send { Cloned::new(self) } + /// Creates an iterator which copies all of its elements. This may be + /// useful when you have an iterator over `&T`, but you need `T`, and + /// that type implements `Copy`. See also [`cloned()`]. + /// + /// [`cloned()`]: #method.cloned + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// + /// let a = [1, 2, 3]; + /// + /// let v_copied: Vec<_> = a.par_iter().copied().collect(); + /// + /// // copied is the same as .map(|&x| x), for integers + /// let v_map: Vec<_> = a.par_iter().map(|&x| x).collect(); + /// + /// assert_eq!(v_copied, vec![1, 2, 3]); + /// assert_eq!(v_map, vec![1, 2, 3]); + /// ``` + fn copied(self) -> Copied + where + T: Copy + Send + 'a, + Self: ParallelIterator<'a, Item = &'a T>, + { + Copied::new(self) + } + /// Reduces the items in the iterator into one item using `operation`. /// The argument `identity` should be a closure that can produce /// "identity" value which may be inserted into the sequence as diff --git a/asparit/src/inner/copied.rs b/asparit/src/inner/copied.rs new file mode 100644 index 0000000..c5508f6 --- /dev/null +++ b/asparit/src/inner/copied.rs @@ -0,0 +1,275 @@ +use crate::{ + Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, + ParallelIterator, Producer, ProducerCallback, Reducer, +}; + +/* Copied */ + +pub struct Copied { + base: X, +} + +impl Copied { + pub fn new(base: X) -> Self { + Self { base } + } +} + +impl<'a, X, T> ParallelIterator<'a> for Copied +where + X: ParallelIterator<'a, Item = &'a T>, + T: Copy + Send + Sync + 'a, +{ + type Item = T; + + fn drive(self, executor: E, consumer: C) -> E::Result + where + E: Executor<'a, D>, + C: Consumer + 'a, + D: Send, + R: Reducer + Send, + { + self.base.drive(executor, CopiedConsumer { base: consumer }) + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: ProducerCallback<'a, Self::Item>, + { + self.base.with_producer(CopiedCallback { base: callback }) + } + + fn len_hint_opt(&self) -> Option { + self.base.len_hint_opt() + } +} + +impl<'a, X, T> IndexedParallelIterator<'a> for Copied +where + X: IndexedParallelIterator<'a, Item = &'a T>, + T: Copy + Send + Sync + 'a, +{ + fn drive_indexed(self, executor: E, consumer: C) -> E::Result + where + E: Executor<'a, D>, + C: Consumer + 'a, + D: Send, + R: Reducer + Send, + { + self.base + .drive_indexed(executor, CopiedConsumer { base: consumer }) + } + + fn with_producer_indexed(self, callback: CB) -> CB::Output + where + CB: IndexedProducerCallback<'a, Self::Item>, + { + self.base + .with_producer_indexed(CopiedCallback { base: callback }) + } + + fn len_hint(&self) -> usize { + self.base.len_hint() + } +} + +/* CopiedConsumer */ + +struct CopiedConsumer { + base: C, +} + +impl<'a, T, C> Consumer<&'a T> for CopiedConsumer +where + T: Copy, + C: Consumer, +{ + type Folder = CopiedFolder; + type Reducer = C::Reducer; + type Result = C::Result; + + fn split(self) -> (Self, Self, Self::Reducer) { + let (left, right, reducer) = self.base.split(); + + let left = CopiedConsumer { base: left }; + let right = CopiedConsumer { base: right }; + + (left, right, reducer) + } + + fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { + let (left, right, reducer) = self.base.split_at(index); + + let left = CopiedConsumer { base: left }; + let right = CopiedConsumer { base: right }; + + (left, right, reducer) + } + + fn into_folder(self) -> Self::Folder { + CopiedFolder { + base: self.base.into_folder(), + } + } + + fn is_full(&self) -> bool { + self.base.is_full() + } +} + +/* CopiedFolder */ + +struct CopiedFolder { + base: F, +} + +impl<'a, T, F> Folder<&'a T> for CopiedFolder +where + T: Copy + 'a, + F: Folder, +{ + type Result = F::Result; + + fn consume(mut self, item: &'a T) -> Self { + self.base = self.base.consume(*item); + + self + } + + fn consume_iter(mut self, iter: X) -> Self + where + X: IntoIterator, + { + self.base = self.base.consume_iter(iter.into_iter().copied()); + + self + } + + fn complete(self) -> Self::Result { + self.base.complete() + } + + fn is_full(&self) -> bool { + self.base.is_full() + } +} + +/* CopiedCallback */ + +struct CopiedCallback { + base: CB, +} + +impl<'a, T, CB> ProducerCallback<'a, &'a T> for CopiedCallback +where + T: Copy + 'a, + CB: ProducerCallback<'a, T>, +{ + type Output = CB::Output; + + fn callback

(self, producer: P) -> Self::Output + where + P: Producer + 'a, + { + self.base.callback(CopiedProducer { base: producer }) + } +} + +impl<'a, T, CB> IndexedProducerCallback<'a, &'a T> for CopiedCallback +where + T: Copy + 'a, + CB: IndexedProducerCallback<'a, T>, +{ + type Output = CB::Output; + + fn callback

(self, producer: P) -> Self::Output + where + P: IndexedProducer + 'a, + { + self.base.callback(CopiedProducer { base: producer }) + } +} + +/* CopiedProducer */ + +struct CopiedProducer

{ + base: P, +} + +impl<'a, T, P> Producer for CopiedProducer

+where + T: Copy + 'a, + P: Producer, +{ + type Item = T; + type IntoIter = std::iter::Copied; + + fn into_iter(self) -> Self::IntoIter { + self.base.into_iter().copied() + } + + fn split(self) -> (Self, Option) { + let (left, right) = self.base.split(); + + let left = CopiedProducer { base: left }; + let right = right.map(|right| CopiedProducer { base: right }); + + (left, right) + } + + fn splits(&self) -> Option { + self.base.splits() + } + + fn fold_with(self, folder: F) -> F + where + F: Folder, + { + self.base.fold_with(CopiedFolder { base: folder }).base + } +} + +impl<'a, T, P> IndexedProducer for CopiedProducer

+where + T: Copy + 'a, + P: IndexedProducer, +{ + type Item = T; + type IntoIter = std::iter::Copied; + + fn into_iter(self) -> Self::IntoIter { + self.base.into_iter().copied() + } + + fn len(&self) -> usize { + self.base.len() + } + + fn split_at(self, index: usize) -> (Self, Self) { + let (left, right) = self.base.split_at(index); + + let left = CopiedProducer { base: left }; + let right = CopiedProducer { base: right }; + + (left, right) + } + + fn splits(&self) -> Option { + self.base.splits() + } + + fn min_len(&self) -> Option { + self.base.min_len() + } + + fn max_len(&self) -> Option { + self.base.max_len() + } + + fn fold_with(self, folder: F) -> F + where + F: Folder, + { + self.base.fold_with(CopiedFolder { base: folder }).base + } +} diff --git a/asparit/src/inner/mod.rs b/asparit/src/inner/mod.rs index b484077..75e0f80 100644 --- a/asparit/src/inner/mod.rs +++ b/asparit/src/inner/mod.rs @@ -1,5 +1,6 @@ pub mod cloned; pub mod collect; +pub mod copied; pub mod for_each; pub mod map; pub mod map_init;