From b73afe5572d2b0edb3024aab84a3bb01b989e957 Mon Sep 17 00:00:00 2001 From: Philippe Cholet <44676486+Philippe-Cholet@users.noreply.github.com> Date: Fri, 22 Sep 2023 23:38:42 +0200 Subject: [PATCH 1/3] `Powerset::fold` Reset between `&mut Combinations::fold` calls. --- src/powerset.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/powerset.rs b/src/powerset.rs index 811cfce7f..d0eae99a3 100644 --- a/src/powerset.rs +++ b/src/powerset.rs @@ -74,6 +74,24 @@ where let (n, combs_count) = self.combs.n_and_count(); combs_count + remaining_for(n, k).unwrap() } + + fn fold(self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let mut it = self.combs; + if it.k() == 0 { + init = it.by_ref().fold(init, &mut f); + it.reset(1); + } + init = it.by_ref().fold(init, &mut f); + // n is now known for sure because k >= 1 and all k-combinations have been generated. + for k in it.k() + 1..=it.n() { + it.reset(k); + init = it.by_ref().fold(init, &mut f); + } + init + } } impl FusedIterator for Powerset From 9644b606769b7ca06483a11c34d8efe6afe7f329 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Thu, 28 Sep 2023 19:11:27 +0200 Subject: [PATCH 2/3] Bench `Powerset::fold` --- benches/powerset.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/benches/powerset.rs b/benches/powerset.rs index f5862a416..018333d31 100644 --- a/benches/powerset.rs +++ b/benches/powerset.rs @@ -20,6 +20,17 @@ fn powerset_n(c: &mut Criterion, n: usize) { }); } +fn powerset_n_fold(c: &mut Criterion, n: usize) { + let id = format!("powerset {} fold", n); + c.bench_function(id.as_str(), move |b| { + b.iter(|| { + for _ in 0..calc_iters(n) { + (0..n).powerset().fold(0, |s, elt| s + black_box(elt).len()); + } + }) + }); +} + fn powerset_0(c: &mut Criterion) { powerset_n(c, 0); } @@ -44,6 +55,30 @@ fn powerset_12(c: &mut Criterion) { powerset_n(c, 12); } +fn powerset_0_fold(c: &mut Criterion) { + powerset_n_fold(c, 0); +} + +fn powerset_1_fold(c: &mut Criterion) { + powerset_n_fold(c, 1); +} + +fn powerset_2_fold(c: &mut Criterion) { + powerset_n_fold(c, 2); +} + +fn powerset_4_fold(c: &mut Criterion) { + powerset_n_fold(c, 4); +} + +fn powerset_8_fold(c: &mut Criterion) { + powerset_n_fold(c, 8); +} + +fn powerset_12_fold(c: &mut Criterion) { + powerset_n_fold(c, 12); +} + criterion_group!( benches, powerset_0, @@ -52,5 +87,11 @@ criterion_group!( powerset_4, powerset_8, powerset_12, + powerset_0_fold, + powerset_1_fold, + powerset_2_fold, + powerset_4_fold, + powerset_8_fold, + powerset_12_fold, ); criterion_main!(benches); From ac196496f9c12e2959afb76d82fa766dac404fd1 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Thu, 28 Sep 2023 21:14:20 +0200 Subject: [PATCH 3/3] Test powerset specializations Truncated to be fast enough. --- tests/specializations.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/specializations.rs b/tests/specializations.rs index efc8ba6ef..e9bfb5ccb 100644 --- a/tests/specializations.rs +++ b/tests/specializations.rs @@ -75,6 +75,12 @@ quickcheck! { fn intersperse(v: Vec) -> () { test_specializations(&v.into_iter().intersperse(0)); } + + fn powerset(a: Vec) -> () { + let mut a = a; + a.truncate(6); + test_specializations(&a.iter().powerset()) + } } quickcheck! {