use super::plumbing::*; use super::ParallelIterator; use std::iter::{self, Sum}; use std::marker::PhantomData; pub(super) fn sum(pi: PI) -> S where PI: ParallelIterator, S: Send + Sum + Sum, { pi.drive_unindexed(SumConsumer::new()) } fn add(left: T, right: T) -> T { iter::once(left).chain(iter::once(right)).sum() } struct SumConsumer { _marker: PhantomData<*const S>, } unsafe impl Send for SumConsumer {} impl SumConsumer { fn new() -> SumConsumer { SumConsumer { _marker: PhantomData, } } } impl Consumer for SumConsumer where S: Send + Sum + Sum, { type Folder = SumFolder; 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::().sum(), } } fn full(&self) -> bool { false } } impl UnindexedConsumer for SumConsumer where S: Send + Sum + Sum, { fn split_off_left(&self) -> Self { SumConsumer::new() } fn to_reducer(&self) -> Self::Reducer { SumConsumer::new() } } impl Reducer for SumConsumer where S: Send + Sum, { fn reduce(self, left: S, right: S) -> S { add(left, right) } } struct SumFolder { sum: S, } impl Folder for SumFolder where S: Sum + Sum, { type Result = S; fn consume(self, item: T) -> Self { SumFolder { sum: add(self.sum, iter::once(item).sum()), } } fn consume_iter(self, iter: I) -> Self where I: IntoIterator, { SumFolder { sum: add(self.sum, iter.into_iter().sum()), } } fn complete(self) -> S { self.sum } fn full(&self) -> bool { false } }