From 5363f350887b1e5b5dd21a86f88c8af9d7fea6da Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:25 +0200 Subject: Merging upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/rayon/src/iter/chunks.rs | 50 ++++--- vendor/rayon/src/iter/filter.rs | 2 +- vendor/rayon/src/iter/filter_map.rs | 2 +- vendor/rayon/src/iter/find.rs | 2 +- vendor/rayon/src/iter/fold_chunks.rs | 236 ++++++++++++++++++++++++++++++ vendor/rayon/src/iter/fold_chunks_with.rs | 231 +++++++++++++++++++++++++++++ vendor/rayon/src/iter/inspect.rs | 2 +- vendor/rayon/src/iter/interleave.rs | 18 +-- vendor/rayon/src/iter/map.rs | 2 +- vendor/rayon/src/iter/mod.rs | 123 +++++++++++++--- vendor/rayon/src/iter/plumbing/README.md | 2 +- vendor/rayon/src/iter/step_by.rs | 1 - vendor/rayon/src/iter/test.rs | 21 ++- vendor/rayon/src/iter/try_fold.rs | 3 +- vendor/rayon/src/iter/try_reduce.rs | 3 +- vendor/rayon/src/iter/try_reduce_with.rs | 3 +- vendor/rayon/src/iter/update.rs | 2 +- 17 files changed, 624 insertions(+), 79 deletions(-) create mode 100644 vendor/rayon/src/iter/fold_chunks.rs create mode 100644 vendor/rayon/src/iter/fold_chunks_with.rs (limited to 'vendor/rayon/src/iter') diff --git a/vendor/rayon/src/iter/chunks.rs b/vendor/rayon/src/iter/chunks.rs index be5f84cc7..ec48278d0 100644 --- a/vendor/rayon/src/iter/chunks.rs +++ b/vendor/rayon/src/iter/chunks.rs @@ -90,38 +90,46 @@ where where P: Producer, { - self.callback.callback(ChunkProducer { - chunk_size: self.size, - len: self.len, - base, - }) + let producer = ChunkProducer::new(self.size, self.len, base, Vec::from_iter); + self.callback.callback(producer) } } } } -struct ChunkProducer

-where - P: Producer, -{ +pub(super) struct ChunkProducer { chunk_size: usize, len: usize, base: P, + map: F, } -impl

Producer for ChunkProducer

+impl ChunkProducer { + pub(super) fn new(chunk_size: usize, len: usize, base: P, map: F) -> Self { + Self { + chunk_size, + len, + base, + map, + } + } +} + +impl Producer for ChunkProducer where P: Producer, + F: Fn(P::IntoIter) -> T + Send + Clone, { - type Item = Vec; - type IntoIter = ChunkSeq

; + type Item = T; + type IntoIter = std::iter::Map, F>; fn into_iter(self) -> Self::IntoIter { - ChunkSeq { + let chunks = ChunkSeq { chunk_size: self.chunk_size, len: self.len, inner: if self.len > 0 { Some(self.base) } else { None }, - } + }; + chunks.map(self.map) } fn split_at(self, index: usize) -> (Self, Self) { @@ -132,11 +140,13 @@ where chunk_size: self.chunk_size, len: elem_index, base: left, + map: self.map.clone(), }, ChunkProducer { chunk_size: self.chunk_size, len: self.len - elem_index, base: right, + map: self.map, }, ) } @@ -150,7 +160,7 @@ where } } -struct ChunkSeq

{ +pub(super) struct ChunkSeq

{ chunk_size: usize, len: usize, inner: Option

, @@ -160,7 +170,7 @@ impl

Iterator for ChunkSeq

where P: Producer, { - type Item = Vec; + type Item = P::IntoIter; fn next(&mut self) -> Option { let producer = self.inner.take()?; @@ -168,11 +178,11 @@ where let (left, right) = producer.split_at(self.chunk_size); self.inner = Some(right); self.len -= self.chunk_size; - Some(left.into_iter().collect()) + Some(left.into_iter()) } else { debug_assert!(self.len > 0); self.len = 0; - Some(producer.into_iter().collect()) + Some(producer.into_iter()) } } @@ -206,11 +216,11 @@ where let (left, right) = producer.split_at(self.len - size); self.inner = Some(left); self.len -= size; - Some(right.into_iter().collect()) + Some(right.into_iter()) } else { debug_assert!(self.len > 0); self.len = 0; - Some(producer.into_iter().collect()) + Some(producer.into_iter()) } } } diff --git a/vendor/rayon/src/iter/filter.rs b/vendor/rayon/src/iter/filter.rs index 38627f7c0..e1b74ba52 100644 --- a/vendor/rayon/src/iter/filter.rs +++ b/vendor/rayon/src/iter/filter.rs @@ -97,7 +97,7 @@ where P: Fn(&T) -> bool + Sync, { fn split_off_left(&self) -> Self { - FilterConsumer::new(self.base.split_off_left(), &self.filter_op) + FilterConsumer::new(self.base.split_off_left(), self.filter_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/filter_map.rs b/vendor/rayon/src/iter/filter_map.rs index f19c38563..db1c7e3f0 100644 --- a/vendor/rayon/src/iter/filter_map.rs +++ b/vendor/rayon/src/iter/filter_map.rs @@ -98,7 +98,7 @@ where P: Fn(T) -> Option + Sync + 'p, { fn split_off_left(&self) -> Self { - FilterMapConsumer::new(self.base.split_off_left(), &self.filter_op) + FilterMapConsumer::new(self.base.split_off_left(), self.filter_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/find.rs b/vendor/rayon/src/iter/find.rs index 971db2b3c..b16ee8446 100644 --- a/vendor/rayon/src/iter/find.rs +++ b/vendor/rayon/src/iter/find.rs @@ -94,7 +94,7 @@ where self.item = iter .into_iter() // stop iterating if another thread has found something - .take_while(not_full(&self.found)) + .take_while(not_full(self.found)) .find(self.find_op); if self.item.is_some() { self.found.store(true, Ordering::Relaxed) diff --git a/vendor/rayon/src/iter/fold_chunks.rs b/vendor/rayon/src/iter/fold_chunks.rs new file mode 100644 index 000000000..185fb1a65 --- /dev/null +++ b/vendor/rayon/src/iter/fold_chunks.rs @@ -0,0 +1,236 @@ +use std::fmt::{self, Debug}; + +use super::chunks::ChunkProducer; +use super::plumbing::*; +use super::*; +use crate::math::div_round_up; + +/// `FoldChunks` is an iterator that groups elements of an underlying iterator and applies a +/// function over them, producing a single value for each group. +/// +/// This struct is created by the [`fold_chunks()`] method on [`IndexedParallelIterator`] +/// +/// [`fold_chunks()`]: trait.IndexedParallelIterator.html#method.fold_chunks +/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] +pub struct FoldChunks +where + I: IndexedParallelIterator, +{ + base: I, + chunk_size: usize, + fold_op: F, + identity: ID, +} + +impl Debug for FoldChunks { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Fold") + .field("base", &self.base) + .field("chunk_size", &self.chunk_size) + .finish() + } +} + +impl FoldChunks +where + I: IndexedParallelIterator, + ID: Fn() -> U + Send + Sync, + F: Fn(U, I::Item) -> U + Send + Sync, + U: Send, +{ + /// Creates a new `FoldChunks` iterator + pub(super) fn new(base: I, chunk_size: usize, identity: ID, fold_op: F) -> Self { + FoldChunks { + base, + chunk_size, + identity, + fold_op, + } + } +} + +impl ParallelIterator for FoldChunks +where + I: IndexedParallelIterator, + ID: Fn() -> U + Send + Sync, + F: Fn(U, I::Item) -> U + Send + Sync, + U: Send, +{ + type Item = U; + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: Consumer, + { + bridge(self, consumer) + } + + fn opt_len(&self) -> Option { + Some(self.len()) + } +} + +impl IndexedParallelIterator for FoldChunks +where + I: IndexedParallelIterator, + ID: Fn() -> U + Send + Sync, + F: Fn(U, I::Item) -> U + Send + Sync, + U: Send, +{ + fn len(&self) -> usize { + div_round_up(self.base.len(), self.chunk_size) + } + + fn drive(self, consumer: C) -> C::Result + where + C: Consumer, + { + bridge(self, consumer) + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: ProducerCallback, + { + let len = self.base.len(); + return self.base.with_producer(Callback { + chunk_size: self.chunk_size, + len, + identity: self.identity, + fold_op: self.fold_op, + callback, + }); + + struct Callback { + chunk_size: usize, + len: usize, + identity: ID, + fold_op: F, + callback: CB, + } + + impl ProducerCallback for Callback + where + CB: ProducerCallback, + ID: Fn() -> U + Send + Sync, + F: Fn(U, T) -> U + Send + Sync, + { + type Output = CB::Output; + + fn callback

(self, base: P) -> CB::Output + where + P: Producer, + { + let identity = &self.identity; + let fold_op = &self.fold_op; + let fold_iter = move |iter: P::IntoIter| iter.fold(identity(), fold_op); + let producer = ChunkProducer::new(self.chunk_size, self.len, base, fold_iter); + self.callback.callback(producer) + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::ops::Add; + + #[test] + fn check_fold_chunks() { + let words = "bishbashbosh!" + .chars() + .collect::>() + .into_par_iter() + .fold_chunks(4, String::new, |mut s, c| { + s.push(c); + s + }) + .collect::>(); + + assert_eq!(words, vec!["bish", "bash", "bosh", "!"]); + } + + // 'closure' values for tests below + fn id() -> i32 { + 0 + } + fn sum(x: T, y: U) -> T + where + T: Add, + { + x + y + } + + #[test] + #[should_panic(expected = "chunk_size must not be zero")] + fn check_fold_chunks_zero_size() { + let _: Vec = vec![1, 2, 3] + .into_par_iter() + .fold_chunks(0, id, sum) + .collect(); + } + + #[test] + fn check_fold_chunks_even_size() { + assert_eq!( + vec![1 + 2 + 3, 4 + 5 + 6, 7 + 8 + 9], + (1..10) + .into_par_iter() + .fold_chunks(3, id, sum) + .collect::>() + ); + } + + #[test] + fn check_fold_chunks_empty() { + let v: Vec = vec![]; + let expected: Vec = vec![]; + assert_eq!( + expected, + v.into_par_iter() + .fold_chunks(2, id, sum) + .collect::>() + ); + } + + #[test] + fn check_fold_chunks_len() { + assert_eq!(4, (0..8).into_par_iter().fold_chunks(2, id, sum).len()); + assert_eq!(3, (0..9).into_par_iter().fold_chunks(3, id, sum).len()); + assert_eq!(3, (0..8).into_par_iter().fold_chunks(3, id, sum).len()); + assert_eq!(1, (&[1]).par_iter().fold_chunks(3, id, sum).len()); + assert_eq!(0, (0..0).into_par_iter().fold_chunks(3, id, sum).len()); + } + + #[test] + fn check_fold_chunks_uneven() { + let cases: Vec<(Vec, usize, Vec)> = vec![ + ((0..5).collect(), 3, vec![0 + 1 + 2, 3 + 4]), + (vec![1], 5, vec![1]), + ((0..4).collect(), 3, vec![0 + 1 + 2, 3]), + ]; + + for (i, (v, n, expected)) in cases.into_iter().enumerate() { + let mut res: Vec = vec![]; + v.par_iter() + .fold_chunks(n, || 0, sum) + .collect_into_vec(&mut res); + assert_eq!(expected, res, "Case {} failed", i); + + res.truncate(0); + v.into_par_iter() + .fold_chunks(n, || 0, sum) + .rev() + .collect_into_vec(&mut res); + assert_eq!( + expected.into_iter().rev().collect::>(), + res, + "Case {} reversed failed", + i + ); + } + } +} diff --git a/vendor/rayon/src/iter/fold_chunks_with.rs b/vendor/rayon/src/iter/fold_chunks_with.rs new file mode 100644 index 000000000..af120aec4 --- /dev/null +++ b/vendor/rayon/src/iter/fold_chunks_with.rs @@ -0,0 +1,231 @@ +use std::fmt::{self, Debug}; + +use super::chunks::ChunkProducer; +use super::plumbing::*; +use super::*; +use crate::math::div_round_up; + +/// `FoldChunksWith` is an iterator that groups elements of an underlying iterator and applies a +/// function over them, producing a single value for each group. +/// +/// This struct is created by the [`fold_chunks_with()`] method on [`IndexedParallelIterator`] +/// +/// [`fold_chunks_with()`]: trait.IndexedParallelIterator.html#method.fold_chunks +/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] +pub struct FoldChunksWith +where + I: IndexedParallelIterator, +{ + base: I, + chunk_size: usize, + item: U, + fold_op: F, +} + +impl Debug for FoldChunksWith { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Fold") + .field("base", &self.base) + .field("chunk_size", &self.chunk_size) + .field("item", &self.item) + .finish() + } +} + +impl FoldChunksWith +where + I: IndexedParallelIterator, + U: Send + Clone, + F: Fn(U, I::Item) -> U + Send + Sync, +{ + /// Creates a new `FoldChunksWith` iterator + pub(super) fn new(base: I, chunk_size: usize, item: U, fold_op: F) -> Self { + FoldChunksWith { + base, + chunk_size, + item, + fold_op, + } + } +} + +impl ParallelIterator for FoldChunksWith +where + I: IndexedParallelIterator, + U: Send + Clone, + F: Fn(U, I::Item) -> U + Send + Sync, +{ + type Item = U; + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: Consumer, + { + bridge(self, consumer) + } + + fn opt_len(&self) -> Option { + Some(self.len()) + } +} + +impl IndexedParallelIterator for FoldChunksWith +where + I: IndexedParallelIterator, + U: Send + Clone, + F: Fn(U, I::Item) -> U + Send + Sync, +{ + fn len(&self) -> usize { + div_round_up(self.base.len(), self.chunk_size) + } + + fn drive(self, consumer: C) -> C::Result + where + C: Consumer, + { + bridge(self, consumer) + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: ProducerCallback, + { + let len = self.base.len(); + return self.base.with_producer(Callback { + chunk_size: self.chunk_size, + len, + item: self.item, + fold_op: self.fold_op, + callback, + }); + + struct Callback { + chunk_size: usize, + len: usize, + item: T, + fold_op: F, + callback: CB, + } + + impl ProducerCallback for Callback + where + CB: ProducerCallback, + U: Send + Clone, + F: Fn(U, T) -> U + Send + Sync, + { + type Output = CB::Output; + + fn callback

(self, base: P) -> CB::Output + where + P: Producer, + { + let item = self.item; + let fold_op = &self.fold_op; + let fold_iter = move |iter: P::IntoIter| iter.fold(item.clone(), fold_op); + let producer = ChunkProducer::new(self.chunk_size, self.len, base, fold_iter); + self.callback.callback(producer) + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::ops::Add; + + #[test] + fn check_fold_chunks_with() { + let words = "bishbashbosh!" + .chars() + .collect::>() + .into_par_iter() + .fold_chunks_with(4, String::new(), |mut s, c| { + s.push(c); + s + }) + .collect::>(); + + assert_eq!(words, vec!["bish", "bash", "bosh", "!"]); + } + + // 'closure' value for tests below + fn sum(x: T, y: U) -> T + where + T: Add, + { + x + y + } + + #[test] + #[should_panic(expected = "chunk_size must not be zero")] + fn check_fold_chunks_zero_size() { + let _: Vec = vec![1, 2, 3] + .into_par_iter() + .fold_chunks_with(0, 0, sum) + .collect(); + } + + #[test] + fn check_fold_chunks_even_size() { + assert_eq!( + vec![1 + 2 + 3, 4 + 5 + 6, 7 + 8 + 9], + (1..10) + .into_par_iter() + .fold_chunks_with(3, 0, sum) + .collect::>() + ); + } + + #[test] + fn check_fold_chunks_with_empty() { + let v: Vec = vec![]; + let expected: Vec = vec![]; + assert_eq!( + expected, + v.into_par_iter() + .fold_chunks_with(2, 0, sum) + .collect::>() + ); + } + + #[test] + fn check_fold_chunks_len() { + assert_eq!(4, (0..8).into_par_iter().fold_chunks_with(2, 0, sum).len()); + assert_eq!(3, (0..9).into_par_iter().fold_chunks_with(3, 0, sum).len()); + assert_eq!(3, (0..8).into_par_iter().fold_chunks_with(3, 0, sum).len()); + assert_eq!(1, (&[1]).par_iter().fold_chunks_with(3, 0, sum).len()); + assert_eq!(0, (0..0).into_par_iter().fold_chunks_with(3, 0, sum).len()); + } + + #[test] + fn check_fold_chunks_uneven() { + let cases: Vec<(Vec, usize, Vec)> = vec![ + ((0..5).collect(), 3, vec![0 + 1 + 2, 3 + 4]), + (vec![1], 5, vec![1]), + ((0..4).collect(), 3, vec![0 + 1 + 2, 3]), + ]; + + for (i, (v, n, expected)) in cases.into_iter().enumerate() { + let mut res: Vec = vec![]; + v.par_iter() + .fold_chunks_with(n, 0, sum) + .collect_into_vec(&mut res); + assert_eq!(expected, res, "Case {} failed", i); + + res.truncate(0); + v.into_par_iter() + .fold_chunks_with(n, 0, sum) + .rev() + .collect_into_vec(&mut res); + assert_eq!( + expected.into_iter().rev().collect::>(), + res, + "Case {} reversed failed", + i + ); + } + } +} diff --git a/vendor/rayon/src/iter/inspect.rs b/vendor/rayon/src/iter/inspect.rs index 9b1cd094d..c50ca022d 100644 --- a/vendor/rayon/src/iter/inspect.rs +++ b/vendor/rayon/src/iter/inspect.rs @@ -209,7 +209,7 @@ where F: Fn(&T) + Sync, { fn split_off_left(&self) -> Self { - InspectConsumer::new(self.base.split_off_left(), &self.inspect_op) + InspectConsumer::new(self.base.split_off_left(), self.inspect_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/interleave.rs b/vendor/rayon/src/iter/interleave.rs index b5d43d53d..3cacc49f9 100644 --- a/vendor/rayon/src/iter/interleave.rs +++ b/vendor/rayon/src/iter/interleave.rs @@ -310,16 +310,16 @@ where { #[inline] fn next_back(&mut self) -> Option { - if self.i.len() == self.j.len() { - if self.i_next { - self.i.next_back() - } else { - self.j.next_back() + match self.i.len().cmp(&self.j.len()) { + Ordering::Less => self.j.next_back(), + Ordering::Equal => { + if self.i_next { + self.i.next_back() + } else { + self.j.next_back() + } } - } else if self.i.len() < self.j.len() { - self.j.next_back() - } else { - self.i.next_back() + Ordering::Greater => self.i.next_back(), } } } diff --git a/vendor/rayon/src/iter/map.rs b/vendor/rayon/src/iter/map.rs index f2a35ff8c..da14d4082 100644 --- a/vendor/rayon/src/iter/map.rs +++ b/vendor/rayon/src/iter/map.rs @@ -213,7 +213,7 @@ where R: Send, { fn split_off_left(&self) -> Self { - MapConsumer::new(self.base.split_off_left(), &self.map_op) + MapConsumer::new(self.base.split_off_left(), self.map_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/mod.rs b/vendor/rayon/src/iter/mod.rs index 89e96fcef..98c93267f 100644 --- a/vendor/rayon/src/iter/mod.rs +++ b/vendor/rayon/src/iter/mod.rs @@ -119,6 +119,8 @@ mod flat_map_iter; mod flatten; mod flatten_iter; mod fold; +mod fold_chunks; +mod fold_chunks_with; mod for_each; mod from_par_iter; mod inspect; @@ -140,6 +142,7 @@ mod repeat; mod rev; mod skip; mod splitter; +mod step_by; mod sum; mod take; mod try_fold; @@ -165,6 +168,8 @@ pub use self::{ flatten::Flatten, flatten_iter::FlattenIter, fold::{Fold, FoldWith}, + fold_chunks::FoldChunks, + fold_chunks_with::FoldChunksWith, inspect::Inspect, interleave::Interleave, interleave_shortest::InterleaveShortest, @@ -181,6 +186,7 @@ pub use self::{ rev::Rev, skip::Skip, splitter::{split, Split}, + step_by::StepBy, take::Take, try_fold::{TryFold, TryFoldWith}, update::Update, @@ -189,10 +195,6 @@ pub use self::{ zip_eq::ZipEq, }; -mod step_by; -#[cfg(has_step_by_rev)] -pub use self::step_by::StepBy; - /// `IntoParallelIterator` implements the conversion to a [`ParallelIterator`]. /// /// By implementing `IntoParallelIterator` for a type, you define how it will @@ -1124,7 +1126,7 @@ pub trait ParallelIterator: Sized + Send { /// multiple sums. The number of results is nondeterministic, as /// is the point where the breaks occur. /// - /// So if did the same parallel fold (`fold(0, |a,b| a+b)`) on + /// So if we did the same parallel fold (`fold(0, |a,b| a+b)`) on /// our example list, we might wind up with a sequence of two numbers, /// like so: /// @@ -2241,6 +2243,8 @@ impl IntoParallelIterator for T { /// those points. /// /// **Note:** Not implemented for `u64`, `i64`, `u128`, or `i128` ranges +// Waiting for `ExactSizeIterator::is_empty` to be stabilized. See rust-lang/rust#35428 +#[allow(clippy::len_without_is_empty)] pub trait IndexedParallelIterator: ParallelIterator { /// Collects the results of the iterator into the specified /// vector. The vector is always truncated before execution @@ -2339,13 +2343,18 @@ pub trait IndexedParallelIterator: ParallelIterator { /// // we should never get here /// assert_eq!(1, zipped.len()); /// ``` + #[track_caller] fn zip_eq(self, zip_op: Z) -> ZipEq where Z: IntoParallelIterator, Z::Iter: IndexedParallelIterator, { let zip_op_iter = zip_op.into_par_iter(); - assert_eq!(self.len(), zip_op_iter.len()); + assert_eq!( + self.len(), + zip_op_iter.len(), + "iterators must have the same length" + ); ZipEq::new(self, zip_op_iter) } @@ -2415,6 +2424,89 @@ pub trait IndexedParallelIterator: ParallelIterator { Chunks::new(self, chunk_size) } + /// Splits an iterator into fixed-size chunks, performing a sequential [`fold()`] on + /// each chunk. + /// + /// Returns an iterator that produces a folded result for each chunk of items + /// produced by this iterator. + /// + /// This works essentially like: + /// + /// ```text + /// iter.chunks(chunk_size) + /// .map(|chunk| + /// chunk.into_iter() + /// .fold(identity, fold_op) + /// ) + /// ``` + /// + /// except there is no per-chunk allocation overhead. + /// + /// [`fold()`]: std::iter::Iterator#method.fold + /// + /// **Panics** if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// let nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + /// let chunk_sums = nums.into_par_iter().fold_chunks(2, || 0, |a, n| a + n).collect::>(); + /// assert_eq!(chunk_sums, vec![3, 7, 11, 15, 19]); + /// ``` + #[track_caller] + fn fold_chunks( + self, + chunk_size: usize, + identity: ID, + fold_op: F, + ) -> FoldChunks + where + ID: Fn() -> T + Send + Sync, + F: Fn(T, Self::Item) -> T + Send + Sync, + T: Send, + { + assert!(chunk_size != 0, "chunk_size must not be zero"); + FoldChunks::new(self, chunk_size, identity, fold_op) + } + + /// Splits an iterator into fixed-size chunks, performing a sequential [`fold()`] on + /// each chunk. + /// + /// Returns an iterator that produces a folded result for each chunk of items + /// produced by this iterator. + /// + /// This works essentially like `fold_chunks(chunk_size, || init.clone(), fold_op)`, + /// except it doesn't require the `init` type to be `Sync`, nor any other form of + /// added synchronization. + /// + /// [`fold()`]: std::iter::Iterator#method.fold + /// + /// **Panics** if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// let nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + /// let chunk_sums = nums.into_par_iter().fold_chunks_with(2, 0, |a, n| a + n).collect::>(); + /// assert_eq!(chunk_sums, vec![3, 7, 11, 15, 19]); + /// ``` + #[track_caller] + fn fold_chunks_with( + self, + chunk_size: usize, + init: T, + fold_op: F, + ) -> FoldChunksWith + where + T: Send + Clone, + F: Fn(T, Self::Item) -> T + Send + Sync, + { + assert!(chunk_size != 0, "chunk_size must not be zero"); + FoldChunksWith::new(self, chunk_size, init, fold_op) + } + /// Lexicographically compares the elements of this `ParallelIterator` with those of /// another. /// @@ -2601,11 +2693,6 @@ pub trait IndexedParallelIterator: ParallelIterator { /// /// assert_eq!(result, [3, 6, 9]) /// ``` - /// - /// # Compatibility - /// - /// This method is only available on Rust 1.38 or greater. - #[cfg(has_step_by_rev)] fn step_by(self, step: usize) -> StepBy { StepBy::new(self, step) } @@ -3146,20 +3233,9 @@ pub trait ParallelDrainRange { /// stable clone of the standard library's `Try` trait, as yet unstable. mod private { use std::convert::Infallible; + use std::ops::ControlFlow::{self, Break, Continue}; use std::task::Poll; - #[cfg(has_control_flow)] - pub(crate) use std::ops::ControlFlow; - - #[cfg(not(has_control_flow))] - #[allow(missing_debug_implementations)] - pub enum ControlFlow { - Continue(C), - Break(B), - } - - use self::ControlFlow::{Break, Continue}; - /// Clone of `std::ops::Try`. /// /// Implementing this trait is not permitted outside of `rayon`. @@ -3176,7 +3252,6 @@ mod private { fn branch(self) -> ControlFlow; } - #[cfg(has_control_flow)] impl Try for ControlFlow { private_impl! {} diff --git a/vendor/rayon/src/iter/plumbing/README.md b/vendor/rayon/src/iter/plumbing/README.md index cd94eae30..dbee36ba0 100644 --- a/vendor/rayon/src/iter/plumbing/README.md +++ b/vendor/rayon/src/iter/plumbing/README.md @@ -124,7 +124,7 @@ implement `IndexedParallelIterator`. The `bridge` function will then connect the consumer, which is handling the `flat_map` and `for_each`, with the producer, which is -handling the `zip` and its preecessors. It will split down until the +handling the `zip` and its predecessors. It will split down until the chunks seem reasonably small, then pull items from the producer and feed them to the consumer. diff --git a/vendor/rayon/src/iter/step_by.rs b/vendor/rayon/src/iter/step_by.rs index 863de3cf0..94b8334e8 100644 --- a/vendor/rayon/src/iter/step_by.rs +++ b/vendor/rayon/src/iter/step_by.rs @@ -1,4 +1,3 @@ -#![cfg(has_step_by_rev)] use std::cmp::min; use super::plumbing::*; diff --git a/vendor/rayon/src/iter/test.rs b/vendor/rayon/src/iter/test.rs index bc5106bec..94323d79d 100644 --- a/vendor/rayon/src/iter/test.rs +++ b/vendor/rayon/src/iter/test.rs @@ -117,13 +117,10 @@ fn fold_map_reduce() { let r1 = (0_i32..32) .into_par_iter() .with_max_len(1) - .fold( - || vec![], - |mut v, e| { - v.push(e); - v - }, - ) + .fold(Vec::new, |mut v, e| { + v.push(e); + v + }) .map(|v| vec![v]) .reduce_with(|mut v_a, v_b| { v_a.extend(v_b); @@ -394,7 +391,7 @@ fn check_slice_mut_indexed() { #[test] fn check_vec_indexed() { let a = vec![1, 2, 3]; - is_indexed(a.clone().into_par_iter()); + is_indexed(a.into_par_iter()); } #[test] @@ -1371,10 +1368,10 @@ fn check_find_is_present() { let counter = AtomicUsize::new(0); let value: Option = (0_i32..2048).into_par_iter().find_any(|&p| { counter.fetch_add(1, Ordering::SeqCst); - p >= 1024 && p < 1096 + (1024..1096).contains(&p) }); let q = value.unwrap(); - assert!(q >= 1024 && q < 1096); + assert!((1024..1096).contains(&q)); assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one } @@ -1892,7 +1889,7 @@ fn check_either() { // try an indexed iterator let left: E = Either::Left(v.clone().into_par_iter()); - assert!(left.enumerate().eq(v.clone().into_par_iter().enumerate())); + assert!(left.enumerate().eq(v.into_par_iter().enumerate())); } #[test] @@ -2063,7 +2060,7 @@ fn check_chunks_len() { assert_eq!(4, (0..8).into_par_iter().chunks(2).len()); assert_eq!(3, (0..9).into_par_iter().chunks(3).len()); assert_eq!(3, (0..8).into_par_iter().chunks(3).len()); - assert_eq!(1, (&[1]).par_iter().chunks(3).len()); + assert_eq!(1, [1].par_iter().chunks(3).len()); assert_eq!(0, (0..0).into_par_iter().chunks(3).len()); } diff --git a/vendor/rayon/src/iter/try_fold.rs b/vendor/rayon/src/iter/try_fold.rs index c1881d10f..6d1048d75 100644 --- a/vendor/rayon/src/iter/try_fold.rs +++ b/vendor/rayon/src/iter/try_fold.rs @@ -2,10 +2,9 @@ use super::plumbing::*; use super::ParallelIterator; use super::Try; -use super::private::ControlFlow::{self, Break, Continue}; - use std::fmt::{self, Debug}; use std::marker::PhantomData; +use std::ops::ControlFlow::{self, Break, Continue}; impl TryFold where diff --git a/vendor/rayon/src/iter/try_reduce.rs b/vendor/rayon/src/iter/try_reduce.rs index 7bf6cc4a5..35a724c94 100644 --- a/vendor/rayon/src/iter/try_reduce.rs +++ b/vendor/rayon/src/iter/try_reduce.rs @@ -2,8 +2,7 @@ use super::plumbing::*; use super::ParallelIterator; use super::Try; -use super::private::ControlFlow::{self, Break, Continue}; - +use std::ops::ControlFlow::{self, Break, Continue}; use std::sync::atomic::{AtomicBool, Ordering}; pub(super) fn try_reduce(pi: PI, identity: ID, reduce_op: R) -> T diff --git a/vendor/rayon/src/iter/try_reduce_with.rs b/vendor/rayon/src/iter/try_reduce_with.rs index 9fe34d61d..cd7c83e27 100644 --- a/vendor/rayon/src/iter/try_reduce_with.rs +++ b/vendor/rayon/src/iter/try_reduce_with.rs @@ -2,8 +2,7 @@ use super::plumbing::*; use super::ParallelIterator; use super::Try; -use super::private::ControlFlow::{self, Break, Continue}; - +use std::ops::ControlFlow::{self, Break, Continue}; use std::sync::atomic::{AtomicBool, Ordering}; pub(super) fn try_reduce_with(pi: PI, reduce_op: R) -> Option diff --git a/vendor/rayon/src/iter/update.rs b/vendor/rayon/src/iter/update.rs index 373a4d772..c693ac8d6 100644 --- a/vendor/rayon/src/iter/update.rs +++ b/vendor/rayon/src/iter/update.rs @@ -210,7 +210,7 @@ where F: Fn(&mut T) + Send + Sync, { fn split_off_left(&self) -> Self { - UpdateConsumer::new(self.base.split_off_left(), &self.update_op) + UpdateConsumer::new(self.base.split_off_left(), self.update_op) } fn to_reducer(&self) -> Self::Reducer { -- cgit v1.2.3