1 use super::plumbing::*;
2 use super::ParallelIterator;
3 
4 use std::iter::{self, Sum};
5 use std::marker::PhantomData;
6 
sum<PI, S>(pi: PI) -> S where PI: ParallelIterator, S: Send + Sum<PI::Item> + Sum,7 pub(super) fn sum<PI, S>(pi: PI) -> S
8 where
9     PI: ParallelIterator,
10     S: Send + Sum<PI::Item> + Sum,
11 {
12     pi.drive_unindexed(SumConsumer::new())
13 }
14 
add<T: Sum>(left: T, right: T) -> T15 fn add<T: Sum>(left: T, right: T) -> T {
16     [left, right].into_iter().sum()
17 }
18 
19 struct SumConsumer<S: Send> {
20     _marker: PhantomData<*const S>,
21 }
22 
23 unsafe impl<S: Send> Send for SumConsumer<S> {}
24 
25 impl<S: Send> SumConsumer<S> {
new() -> SumConsumer<S>26     fn new() -> SumConsumer<S> {
27         SumConsumer {
28             _marker: PhantomData,
29         }
30     }
31 }
32 
33 impl<S, T> Consumer<T> for SumConsumer<S>
34 where
35     S: Send + Sum<T> + Sum,
36 {
37     type Folder = SumFolder<S>;
38     type Reducer = Self;
39     type Result = S;
40 
split_at(self, _index: usize) -> (Self, Self, Self)41     fn split_at(self, _index: usize) -> (Self, Self, Self) {
42         (SumConsumer::new(), SumConsumer::new(), SumConsumer::new())
43     }
44 
into_folder(self) -> Self::Folder45     fn into_folder(self) -> Self::Folder {
46         SumFolder {
47             sum: iter::empty::<T>().sum(),
48         }
49     }
50 
full(&self) -> bool51     fn full(&self) -> bool {
52         false
53     }
54 }
55 
56 impl<S, T> UnindexedConsumer<T> for SumConsumer<S>
57 where
58     S: Send + Sum<T> + Sum,
59 {
split_off_left(&self) -> Self60     fn split_off_left(&self) -> Self {
61         SumConsumer::new()
62     }
63 
to_reducer(&self) -> Self::Reducer64     fn to_reducer(&self) -> Self::Reducer {
65         SumConsumer::new()
66     }
67 }
68 
69 impl<S> Reducer<S> for SumConsumer<S>
70 where
71     S: Send + Sum,
72 {
reduce(self, left: S, right: S) -> S73     fn reduce(self, left: S, right: S) -> S {
74         add(left, right)
75     }
76 }
77 
78 struct SumFolder<S> {
79     sum: S,
80 }
81 
82 impl<S, T> Folder<T> for SumFolder<S>
83 where
84     S: Sum<T> + Sum,
85 {
86     type Result = S;
87 
consume(self, item: T) -> Self88     fn consume(self, item: T) -> Self {
89         SumFolder {
90             sum: add(self.sum, iter::once(item).sum()),
91         }
92     }
93 
consume_iter<I>(self, iter: I) -> Self where I: IntoIterator<Item = T>,94     fn consume_iter<I>(self, iter: I) -> Self
95     where
96         I: IntoIterator<Item = T>,
97     {
98         SumFolder {
99             sum: add(self.sum, iter.into_iter().sum()),
100         }
101     }
102 
complete(self) -> S103     fn complete(self) -> S {
104         self.sum
105     }
106 
full(&self) -> bool107     fn full(&self) -> bool {
108         false
109     }
110 }
111