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