1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 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 } }