Skip to content

Commit

Permalink
Add ParallelSliceMut::par_split_inclusive_mut
Browse files Browse the repository at this point in the history
  • Loading branch information
cuviper committed Jan 26, 2024
1 parent 100f79e commit 06b546c
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/iter/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,26 @@ fn check_slice_split_mut() {
assert_eq!(v, [1, 40, 30, 1, 60, 1]);
}

#[test]
fn check_slice_split_inclusive_mut() {
let mut v1: Vec<_> = (0..1000).collect();
let mut v2 = v1.clone();
for m in 1..100 {
let a: Vec<_> = v1.split_inclusive_mut(|x| x % m == 0).collect();
let b: Vec<_> = v2.par_split_inclusive_mut(|x| x % m == 0).collect();
assert_eq!(a, b);
}

// same as std::slice::split_inclusive_mut() example
let mut v = [10, 40, 30, 20, 60, 50];
v.par_split_inclusive_mut(|num| num % 3 == 0)
.for_each(|group| {
let terminator_idx = group.len() - 1;
group[terminator_idx] = 1;
});
assert_eq!(v, [10, 40, 1, 20, 1, 1]);
}

#[test]
fn check_chunks() {
let a: Vec<i32> = vec![1, 5, 10, 4, 100, 3, 1000, 2, 10000, 1];
Expand Down
53 changes: 53 additions & 0 deletions src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,28 @@ pub trait ParallelSliceMut<T: Send> {
}
}

/// Returns a parallel iterator over mutable subslices separated by elements
/// that match the separator, including the matched part as a terminator.
///
/// # Examples
///
/// ```
/// use rayon::prelude::*;
/// let mut array = [1, 2, 3, 0, 2, 4, 8, 0, 3, 6, 9];
/// array.par_split_inclusive_mut(|i| *i == 0)
/// .for_each(|slice| slice.reverse());
/// assert_eq!(array, [0, 3, 2, 1, 0, 8, 4, 2, 9, 6, 3]);
/// ```
fn par_split_inclusive_mut<P>(&mut self, separator: P) -> SplitInclusiveMut<'_, T, P>
where
P: Fn(&T) -> bool + Sync + Send,
{
SplitInclusiveMut {
slice: self.as_parallel_slice_mut(),
separator,
}
}

/// Returns a parallel iterator over at most `chunk_size` elements of
/// `self` at a time. The chunks are mutable and do not overlap.
///
Expand Down Expand Up @@ -1074,6 +1096,37 @@ where
}
}

/// Parallel iterator over mutable slices separated by a predicate,
/// including the matched part as a terminator.
pub struct SplitInclusiveMut<'data, T, P> {
slice: &'data mut [T],
separator: P,
}

impl<'data, T: Debug, P> Debug for SplitInclusiveMut<'data, T, P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SplitInclusiveMut")
.field("slice", &self.slice)
.finish()
}
}

impl<'data, T, P> ParallelIterator for SplitInclusiveMut<'data, T, P>
where
P: Fn(&T) -> bool + Sync + Send,
T: Send,
{
type Item = &'data mut [T];

fn drive_unindexed<C>(self, consumer: C) -> C::Result
where
C: UnindexedConsumer<Self::Item>,
{
let producer = SplitInclusiveProducer::new_incl(self.slice, &self.separator);
bridge_unindexed(producer, consumer)
}
}

/// Implement support for `SplitProducer`.
impl<'data, T, P> Fissile<P> for &'data mut [T]
where
Expand Down
1 change: 1 addition & 0 deletions tests/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ fn debug_vec() {
check(v.par_split(|x| x % 3 == 0));
check(v.par_split_inclusive(|x| x % 3 == 0));
check(v.par_split_mut(|x| x % 3 == 0));
check(v.par_split_inclusive_mut(|x| x % 3 == 0));
check(v.par_drain(..));
check(v.into_par_iter());
}
Expand Down

0 comments on commit 06b546c

Please sign in to comment.