From 4fc873482d9a8e48a01c0abac22701fffcb92a88 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 20 Nov 2023 16:05:31 +0100 Subject: [PATCH 1/8] `FilterOk::next`: use `find` --- src/adaptors/mod.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index 3528e3b23..887f0db1c 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -901,17 +901,11 @@ where type Item = Result; fn next(&mut self) -> Option { - loop { - match self.iter.next() { - Some(Ok(v)) => { - if (self.f)(&v) { - return Some(Ok(v)); - } - } - Some(Err(e)) => return Some(Err(e)), - None => return None, - } - } + let f = &mut self.f; + self.iter.find(|res| match res { + Ok(t) => f(t), + _ => true, + }) } fn size_hint(&self) -> (usize, Option) { From 0969d4c74429621a717e2c17c9aac2a5cb23d56e Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 20 Nov 2023 16:05:56 +0100 Subject: [PATCH 2/8] `FilterMapOk::next`: use `find_map` --- src/adaptors/mod.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index 887f0db1c..f622bceda 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -982,17 +982,11 @@ where type Item = Result; fn next(&mut self) -> Option { - loop { - match self.iter.next() { - Some(Ok(v)) => { - if let Some(v) = (self.f)(v) { - return Some(Ok(v)); - } - } - Some(Err(e)) => return Some(Err(e)), - None => return None, - } - } + let f = &mut self.f; + self.iter.find_map(|res| match res { + Ok(t) => f(t).map(Ok), + Err(e) => Some(Err(e)), + }) } fn size_hint(&self) -> (usize, Option) { From 7df930ee1f04b4342492385554af800ad995c5c5 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 20 Nov 2023 16:18:23 +0100 Subject: [PATCH 3/8] `UniqueBy::next`: use `find` --- src/unique_impl.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/unique_impl.rs b/src/unique_impl.rs index 9b103a075..eb5c3d64d 100644 --- a/src/unique_impl.rs +++ b/src/unique_impl.rs @@ -61,13 +61,8 @@ where type Item = I::Item; fn next(&mut self) -> Option { - while let Some(v) = self.iter.next() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None + let Self { iter, used, f } = self; + iter.find(|v| used.insert(f(v), ()).is_none()) } #[inline] From 64952fc55da9d01fcdeb465e806267b06cb57b89 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 20 Nov 2023 16:19:15 +0100 Subject: [PATCH 4/8] `UniqueBy::next_back`: use `rfind` --- src/unique_impl.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/unique_impl.rs b/src/unique_impl.rs index eb5c3d64d..44f6abb17 100644 --- a/src/unique_impl.rs +++ b/src/unique_impl.rs @@ -84,13 +84,8 @@ where F: FnMut(&I::Item) -> V, { fn next_back(&mut self) -> Option { - while let Some(v) = self.iter.next_back() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None + let Self { iter, used, f } = self; + iter.rfind(|v| used.insert(f(v), ()).is_none()) } } From a1ec8fb328f83f8adca98479675b8be4bb37ec4e Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 20 Nov 2023 16:21:10 +0100 Subject: [PATCH 5/8] `Unique::next`: use `find_map` --- src/unique_impl.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/unique_impl.rs b/src/unique_impl.rs index 44f6abb17..e35392952 100644 --- a/src/unique_impl.rs +++ b/src/unique_impl.rs @@ -105,14 +105,15 @@ where type Item = I::Item; fn next(&mut self) -> Option { - while let Some(v) = self.iter.iter.next() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let UniqueBy { iter, used, .. } = &mut self.iter; + iter.find_map(|v| { + if let Entry::Vacant(entry) = used.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); } - } - None + None + }) } #[inline] From 2c5a8a82921c742dda766bb2a86e31d7dfc74a43 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 20 Nov 2023 16:21:35 +0100 Subject: [PATCH 6/8] `Unique::next_back`: use `rev().find_map` --- src/unique_impl.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/unique_impl.rs b/src/unique_impl.rs index e35392952..0f6397e48 100644 --- a/src/unique_impl.rs +++ b/src/unique_impl.rs @@ -133,14 +133,15 @@ where I::Item: Eq + Hash + Clone, { fn next_back(&mut self) -> Option { - while let Some(v) = self.iter.iter.next_back() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let UniqueBy { iter, used, .. } = &mut self.iter; + iter.rev().find_map(|v| { + if let Entry::Vacant(entry) = used.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); } - } - None + None + }) } } From e286c1b37231b730fd1a7244711d5f4953c4c0e7 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 20 Nov 2023 16:35:45 +0100 Subject: [PATCH 7/8] `partition`: use `rfind` And then no need for a named loop anymore. --- src/lib.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9a4043095..f3b6e807d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4054,18 +4054,11 @@ where { let mut split_index = 0; let mut iter = iter.into_iter(); - 'main: while let Some(front) = iter.next() { + while let Some(front) = iter.next() { if !pred(front) { - loop { - match iter.next_back() { - Some(back) => { - if pred(back) { - std::mem::swap(front, back); - break; - } - } - None => break 'main, - } + match iter.rfind(|back| pred(back)) { + Some(back) => std::mem::swap(front, back), + None => break, } } split_index += 1; From b87cc6a9b92879b888ae3a2baae5acdfe236f83c Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Wed, 13 Dec 2023 16:05:38 +0100 Subject: [PATCH 8/8] Bench `partition` --- benches/bench1.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/benches/bench1.rs b/benches/bench1.rs index 0946affe5..b01b8f360 100644 --- a/benches/bench1.rs +++ b/benches/bench1.rs @@ -1,4 +1,4 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; use itertools::free::cloned; use itertools::iproduct; use itertools::Itertools; @@ -648,6 +648,22 @@ fn step_range_10(c: &mut Criterion) { }); } +fn vec_iter_mut_partition(c: &mut Criterion) { + let data = std::iter::repeat(-1024i32..1024) + .take(256) + .flatten() + .collect_vec(); + c.bench_function("vec iter mut partition", move |b| { + b.iter_batched( + || data.clone(), + |mut data| { + black_box(itertools::partition(black_box(&mut data), |n| *n >= 0)); + }, + BatchSize::LargeInput, + ) + }); +} + fn cartesian_product_iterator(c: &mut Criterion) { let xs = vec![0; 16]; @@ -803,6 +819,7 @@ criterion_group!( step_vec_10, step_range_2, step_range_10, + vec_iter_mut_partition, cartesian_product_iterator, multi_cartesian_product_iterator, cartesian_product_nested_for,