rayon/iter/
product.rs

1use super::plumbing::*;
2use super::ParallelIterator;
3
4use std::iter::{self, Product};
5use std::marker::PhantomData;
6
7pub(super) fn product<PI, P>(pi: PI) -> P
8where
9    PI: ParallelIterator,
10    P: Send + Product<PI::Item> + Product,
11{
12    pi.drive_unindexed(ProductConsumer::new())
13}
14
15fn mul<T: Product>(left: T, right: T) -> T {
16    [left, right].into_iter().product()
17}
18
19struct ProductConsumer<P: Send> {
20    _marker: PhantomData<*const P>,
21}
22
23unsafe impl<P: Send> Send for ProductConsumer<P> {}
24
25impl<P: Send> ProductConsumer<P> {
26    fn new() -> ProductConsumer<P> {
27        ProductConsumer {
28            _marker: PhantomData,
29        }
30    }
31}
32
33impl<P, T> Consumer<T> for ProductConsumer<P>
34where
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
60impl<P, T> UnindexedConsumer<T> for ProductConsumer<P>
61where
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
73impl<P> Reducer<P> for ProductConsumer<P>
74where
75    P: Send + Product,
76{
77    fn reduce(self, left: P, right: P) -> P {
78        mul(left, right)
79    }
80}
81
82struct ProductFolder<P> {
83    product: P,
84}
85
86impl<P, T> Folder<T> for ProductFolder<P>
87where
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}