1 use super::plumbing::*;
2 use super::ParallelIterator;
3 
4 use std::iter::{self, Product};
5 use std::marker::PhantomData;
6 
product<PI, P>(pi: PI) -> P where PI: ParallelIterator, P: Send + Product<PI::Item> + Product,7 pub(super) fn product<PI, P>(pi: PI) -> P
8 where
9     PI: ParallelIterator,
10     P: Send + Product<PI::Item> + Product,
11 {
12     pi.drive_unindexed(ProductConsumer::new())
13 }
14 
mul<T: Product>(left: T, right: T) -> T15 fn mul<T: Product>(left: T, right: T) -> T {
16     iter::once(left).chain(iter::once(right)).product()
17 }
18 
19 struct ProductConsumer<P: Send> {
20     _marker: PhantomData<*const P>,
21 }
22 
23 unsafe impl<P: Send> Send for ProductConsumer<P> {}
24 
25 impl<P: Send> ProductConsumer<P> {
new() -> ProductConsumer<P>26     fn new() -> ProductConsumer<P> {
27         ProductConsumer {
28             _marker: PhantomData,
29         }
30     }
31 }
32 
33 impl<P, T> Consumer<T> for ProductConsumer<P>
34 where
35     P: Send + Product<T> + Product,
36 {
37     type Folder = ProductFolder<P>;
38     type Reducer = Self;
39     type Result = P;
40 
split_at(self, _index: usize) -> (Self, Self, Self)41     fn split_at(self, _index: usize) -> (Self, Self, Self) {
42         (
43             ProductConsumer::new(),
44             ProductConsumer::new(),
45             ProductConsumer::new(),
46         )
47     }
48 
into_folder(self) -> Self::Folder49     fn into_folder(self) -> Self::Folder {
50         ProductFolder {
51             product: iter::empty::<T>().product(),
52         }
53     }
54 
full(&self) -> bool55     fn full(&self) -> bool {
56         false
57     }
58 }
59 
60 impl<P, T> UnindexedConsumer<T> for ProductConsumer<P>
61 where
62     P: Send + Product<T> + Product,
63 {
split_off_left(&self) -> Self64     fn split_off_left(&self) -> Self {
65         ProductConsumer::new()
66     }
67 
to_reducer(&self) -> Self::Reducer68     fn to_reducer(&self) -> Self::Reducer {
69         ProductConsumer::new()
70     }
71 }
72 
73 impl<P> Reducer<P> for ProductConsumer<P>
74 where
75     P: Send + Product,
76 {
reduce(self, left: P, right: P) -> P77     fn reduce(self, left: P, right: P) -> P {
78         mul(left, right)
79     }
80 }
81 
82 struct ProductFolder<P> {
83     product: P,
84 }
85 
86 impl<P, T> Folder<T> for ProductFolder<P>
87 where
88     P: Product<T> + Product,
89 {
90     type Result = P;
91 
consume(self, item: T) -> Self92     fn consume(self, item: T) -> Self {
93         ProductFolder {
94             product: mul(self.product, iter::once(item).product()),
95         }
96     }
97 
consume_iter<I>(self, iter: I) -> Self where I: IntoIterator<Item = T>,98     fn consume_iter<I>(self, iter: I) -> Self
99     where
100         I: IntoIterator<Item = T>,
101     {
102         ProductFolder {
103             product: mul(self.product, iter.into_iter().product()),
104         }
105     }
106 
complete(self) -> P107     fn complete(self) -> P {
108         self.product
109     }
110 
full(&self) -> bool111     fn full(&self) -> bool {
112         false
113     }
114 }
115