use std::iter::{empty, once}; use std::marker::PhantomData; use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer}; /* Product */ pub struct Product { iterator: X, marker: PhantomData

, } impl Product { pub fn new(iterator: X) -> Self { Self { iterator, marker: PhantomData, } } } impl<'a, X, P> Driver<'a, P> for Product where X: ParallelIterator<'a>, P: std::iter::Product + std::iter::Product + Send + 'a, { fn exec_with(self, executor: E) -> E::Result where E: Executor<'a, P>, { let iterator = self.iterator; let consumer = ProductConsumer(PhantomData); iterator.drive(executor, consumer) } } /* ProductConsumer */ pub struct ProductConsumer

(PhantomData

); impl Consumer for ProductConsumer

where P: std::iter::Product + std::iter::Product + Send, { type Folder = ProductFolder

; type Reducer = ProductReducer

; type Result = P; fn split(self) -> (Self, Self, Self::Reducer) { let left = self; let right = ProductConsumer(PhantomData); (left, right, ProductReducer(PhantomData)) } fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) { let left = self; let right = ProductConsumer(PhantomData); (left, right, ProductReducer(PhantomData)) } fn into_folder(self) -> Self::Folder { ProductFolder { product: empty::().product(), } } } /* ProductFolder */ pub struct ProductFolder

{ product: P, } impl Folder for ProductFolder

where P: std::iter::Product + std::iter::Product + Send, { type Result = P; fn consume(mut self, item: I) -> Self { self.product = mul(self.product, once(item).product()); self } fn consume_iter(mut self, iter: X) -> Self where X: IntoIterator, { self.product = mul(self.product, iter.into_iter().product()); self } fn complete(self) -> Self::Result { self.product } } /* ProductReducer */ pub struct ProductReducer

(PhantomData

); impl

Reducer

for ProductReducer

where P: std::iter::Product + Send, { fn reduce(self, left: P, right: P) -> P { mul(left, right) } } fn mul(left: T, right: T) -> T where T: std::iter::Product, { once(left).chain(once(right)).product() }