aboutsummaryrefslogtreecommitdiff
path: root/src/iter/sum.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/iter/sum.rs')
-rw-r--r--src/iter/sum.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/iter/sum.rs b/src/iter/sum.rs
new file mode 100644
index 0000000..a73e0bf
--- /dev/null
+++ b/src/iter/sum.rs
@@ -0,0 +1,110 @@
+use super::plumbing::*;
+use super::ParallelIterator;
+
+use std::iter::{self, Sum};
+use std::marker::PhantomData;
+
+pub(super) fn sum<PI, S>(pi: PI) -> S
+where
+ PI: ParallelIterator,
+ S: Send + Sum<PI::Item> + Sum,
+{
+ pi.drive_unindexed(SumConsumer::new())
+}
+
+fn add<T: Sum>(left: T, right: T) -> T {
+ iter::once(left).chain(iter::once(right)).sum()
+}
+
+struct SumConsumer<S: Send> {
+ _marker: PhantomData<*const S>,
+}
+
+unsafe impl<S: Send> Send for SumConsumer<S> {}
+
+impl<S: Send> SumConsumer<S> {
+ fn new() -> SumConsumer<S> {
+ SumConsumer {
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<S, T> Consumer<T> for SumConsumer<S>
+where
+ S: Send + Sum<T> + Sum,
+{
+ type Folder = SumFolder<S>;
+ type Reducer = Self;
+ type Result = S;
+
+ fn split_at(self, _index: usize) -> (Self, Self, Self) {
+ (SumConsumer::new(), SumConsumer::new(), SumConsumer::new())
+ }
+
+ fn into_folder(self) -> Self::Folder {
+ SumFolder {
+ sum: iter::empty::<T>().sum(),
+ }
+ }
+
+ fn full(&self) -> bool {
+ false
+ }
+}
+
+impl<S, T> UnindexedConsumer<T> for SumConsumer<S>
+where
+ S: Send + Sum<T> + Sum,
+{
+ fn split_off_left(&self) -> Self {
+ SumConsumer::new()
+ }
+
+ fn to_reducer(&self) -> Self::Reducer {
+ SumConsumer::new()
+ }
+}
+
+impl<S> Reducer<S> for SumConsumer<S>
+where
+ S: Send + Sum,
+{
+ fn reduce(self, left: S, right: S) -> S {
+ add(left, right)
+ }
+}
+
+struct SumFolder<S> {
+ sum: S,
+}
+
+impl<S, T> Folder<T> for SumFolder<S>
+where
+ S: Sum<T> + Sum,
+{
+ type Result = S;
+
+ fn consume(self, item: T) -> Self {
+ SumFolder {
+ sum: add(self.sum, iter::once(item).sum()),
+ }
+ }
+
+ fn consume_iter<I>(self, iter: I) -> Self
+ where
+ I: IntoIterator<Item = T>,
+ {
+ SumFolder {
+ sum: add(self.sum, iter.into_iter().sum()),
+ }
+ }
+
+ fn complete(self) -> S {
+ self.sum
+ }
+
+ fn full(&self) -> bool {
+ false
+ }
+}