diff --git a/benches/bench1.rs b/benches/bench1.rs index 664191ab4..84caf88bc 100644 --- a/benches/bench1.rs +++ b/benches/bench1.rs @@ -855,6 +855,17 @@ fn with_position_fold(c: &mut Criterion) { }); } +fn tuple_combinations_fold(c: &mut Criterion) { + let v = black_box((0..64).collect_vec()); + c.bench_function("tuple_combinations fold", move |b| { + b.iter(|| { + v.iter() + .tuple_combinations() + .fold(0, |acc, (a, b, c, d)| acc + *a * *c - *b * *d) + }) + }); +} + criterion_group!( benches, slice_iter, @@ -903,6 +914,7 @@ criterion_group!( permutations_range, permutations_slice, with_position_fold, + tuple_combinations_fold, while_some, ); criterion_main!(benches); diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index 18c864ad1..3aa49d224 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -650,6 +650,13 @@ where fn count(self) -> usize { self.iter.count() } + + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } } impl FusedIterator for TupleCombinations @@ -684,6 +691,13 @@ impl Iterator for Tuple1Combination { fn count(self) -> usize { self.iter.count() } + + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.iter.map(|x| (x,)).fold(init, f) + } } impl HasCombination for (I::Item,) { @@ -717,19 +731,19 @@ macro_rules! impl_tuple_combination { impl Iterator for $C where I: Iterator + Clone, - I::Item: Clone + A: Clone, { type Item = (A, $(ignore_ident!($X, A)),*); fn next(&mut self) -> Option { - if let Some(($($X),*,)) = self.c.next() { + if let Some(($($X,)*)) = self.c.next() { let z = self.item.clone().unwrap(); Some((z, $($X),*)) } else { self.item = self.iter.next(); self.item.clone().and_then(|z| { self.c = self.iter.clone().into(); - self.c.next().map(|($($X),*,)| (z, $($X),*)) + self.c.next().map(|($($X,)*)| (z, $($X),*)) }) } } @@ -747,6 +761,25 @@ macro_rules! impl_tuple_combination { let n = self.iter.count(); checked_binomial(n, K).unwrap() + self.c.count() } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let Self { c, item, mut iter } = self; + if let Some(z) = item.as_ref() { + init = c + .map(|($($X,)*)| (z.clone(), $($X),*)) + .fold(init, &mut f); + } + while let Some(z) = iter.next() { + let c: $P = iter.clone().into(); + init = c + .map(|($($X,)*)| (z.clone(), $($X),*)) + .fold(init, &mut f); + } + init + } } impl HasCombination for (A, $(ignore_ident!($X, A)),*)