1 | use super::plumbing::*; |
2 | use super::ParallelIterator; |
3 | |
4 | use std::iter::{self, Product}; |
5 | use std::marker::PhantomData; |
6 | |
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 | |
15 | fn mul<T: Product>(left: T, right: T) -> T { |
16 | [left, right].into_iter().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> { |
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 | |
41 | fn split_at(self, _index: usize) -> (Self, Self, Self) { |
42 | ( |
43 | ProductConsumer::new(), |
44 | ProductConsumer::new(), |
45 | ProductConsumer::new(), |
46 | ) |
47 | } |
48 | |
49 | fn into_folder(self) -> Self::Folder { |
50 | ProductFolder { |
51 | product: iter::empty::<T>().product(), |
52 | } |
53 | } |
54 | |
55 | 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 | { |
64 | fn split_off_left(&self) -> Self { |
65 | ProductConsumer::new() |
66 | } |
67 | |
68 | 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 | { |
77 | 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 | |
92 | fn consume(self, item: T) -> Self { |
93 | ProductFolder { |
94 | product: mul(self.product, iter::once(item).product()), |
95 | } |
96 | } |
97 | |
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 | |
107 | fn complete(self) -> P { |
108 | self.product |
109 | } |
110 | |
111 | fn full(&self) -> bool { |
112 | false |
113 | } |
114 | } |
115 | |