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