1 //! Parallel iterator types for [slices][std::slice]
3 //! You will rarely need to interact with this module directly unless you need
4 //! to name one of the iterator types.
6 //! [std::slice]: https://doc.rust-lang.org/stable/std/slice/
13 use self::mergesort
::par_mergesort
;
14 use self::quicksort
::par_quicksort
;
15 use crate::iter
::plumbing
::*;
17 use crate::split_producer
::*;
19 use std
::cmp
::Ordering
;
20 use std
::fmt
::{self, Debug}
;
22 use super::math
::div_round_up
;
24 /// Parallel extensions for slices.
25 pub trait ParallelSlice
<T
: Sync
> {
26 /// Returns a plain slice, which is used to implement the rest of the
28 fn as_parallel_slice(&self) -> &[T
];
30 /// Returns a parallel iterator over subslices separated by elements that
31 /// match the separator.
36 /// use rayon::prelude::*;
37 /// let smallest = [1, 2, 3, 0, 2, 4, 8, 0, 3, 6, 9]
38 /// .par_split(|i| *i == 0)
39 /// .map(|numbers| numbers.iter().min().unwrap())
41 /// assert_eq!(Some(&1), smallest);
43 fn par_split
<P
>(&self, separator
: P
) -> Split
<'_
, T
, P
>
45 P
: Fn(&T
) -> bool
+ Sync
+ Send
,
48 slice
: self.as_parallel_slice(),
53 /// Returns a parallel iterator over all contiguous windows of length
54 /// `window_size`. The windows overlap.
59 /// use rayon::prelude::*;
60 /// let windows: Vec<_> = [1, 2, 3].par_windows(2).collect();
61 /// assert_eq!(vec![[1, 2], [2, 3]], windows);
63 fn par_windows(&self, window_size
: usize) -> Windows
<'_
, T
> {
66 slice
: self.as_parallel_slice(),
70 /// Returns a parallel iterator over at most `chunk_size` elements of
71 /// `self` at a time. The chunks do not overlap.
73 /// If the number of elements in the iterator is not divisible by
74 /// `chunk_size`, the last chunk may be shorter than `chunk_size`. All
75 /// other chunks will have that exact length.
80 /// use rayon::prelude::*;
81 /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_chunks(2).collect();
82 /// assert_eq!(chunks, vec![&[1, 2][..], &[3, 4], &[5]]);
84 fn par_chunks(&self, chunk_size
: usize) -> Chunks
<'_
, T
> {
85 assert
!(chunk_size
!= 0, "chunk_size must not be zero");
88 slice
: self.as_parallel_slice(),
92 /// Returns a parallel iterator over `chunk_size` elements of
93 /// `self` at a time. The chunks do not overlap.
95 /// If `chunk_size` does not divide the length of the slice, then the
96 /// last up to `chunk_size-1` elements will be omitted and can be
97 /// retrieved from the remainder function of the iterator.
102 /// use rayon::prelude::*;
103 /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_chunks_exact(2).collect();
104 /// assert_eq!(chunks, vec![&[1, 2][..], &[3, 4]]);
106 fn par_chunks_exact(&self, chunk_size
: usize) -> ChunksExact
<'_
, T
> {
107 assert
!(chunk_size
!= 0, "chunk_size must not be zero");
108 let slice
= self.as_parallel_slice();
109 let rem
= slice
.len() % chunk_size
;
110 let len
= slice
.len() - rem
;
111 let (fst
, snd
) = slice
.split_at(len
);
120 impl<T
: Sync
> ParallelSlice
<T
> for [T
] {
122 fn as_parallel_slice(&self) -> &[T
] {
127 /// Parallel extensions for mutable slices.
128 pub trait ParallelSliceMut
<T
: Send
> {
129 /// Returns a plain mutable slice, which is used to implement the rest of
130 /// the parallel methods.
131 fn as_parallel_slice_mut(&mut self) -> &mut [T
];
133 /// Returns a parallel iterator over mutable subslices separated by
134 /// elements that match the separator.
139 /// use rayon::prelude::*;
140 /// let mut array = [1, 2, 3, 0, 2, 4, 8, 0, 3, 6, 9];
141 /// array.par_split_mut(|i| *i == 0)
142 /// .for_each(|slice| slice.reverse());
143 /// assert_eq!(array, [3, 2, 1, 0, 8, 4, 2, 0, 9, 6, 3]);
145 fn par_split_mut
<P
>(&mut self, separator
: P
) -> SplitMut
<'_
, T
, P
>
147 P
: Fn(&T
) -> bool
+ Sync
+ Send
,
150 slice
: self.as_parallel_slice_mut(),
155 /// Returns a parallel iterator over at most `chunk_size` elements of
156 /// `self` at a time. The chunks are mutable and do not overlap.
158 /// If the number of elements in the iterator is not divisible by
159 /// `chunk_size`, the last chunk may be shorter than `chunk_size`. All
160 /// other chunks will have that exact length.
165 /// use rayon::prelude::*;
166 /// let mut array = [1, 2, 3, 4, 5];
167 /// array.par_chunks_mut(2)
168 /// .for_each(|slice| slice.reverse());
169 /// assert_eq!(array, [2, 1, 4, 3, 5]);
171 fn par_chunks_mut(&mut self, chunk_size
: usize) -> ChunksMut
<'_
, T
> {
172 assert
!(chunk_size
!= 0, "chunk_size must not be zero");
175 slice
: self.as_parallel_slice_mut(),
179 /// Returns a parallel iterator over `chunk_size` elements of
180 /// `self` at a time. The chunks are mutable and do not overlap.
182 /// If `chunk_size` does not divide the length of the slice, then the
183 /// last up to `chunk_size-1` elements will be omitted and can be
184 /// retrieved from the remainder function of the iterator.
189 /// use rayon::prelude::*;
190 /// let mut array = [1, 2, 3, 4, 5];
191 /// array.par_chunks_exact_mut(3)
192 /// .for_each(|slice| slice.reverse());
193 /// assert_eq!(array, [3, 2, 1, 4, 5]);
195 fn par_chunks_exact_mut(&mut self, chunk_size
: usize) -> ChunksExactMut
<'_
, T
> {
196 assert
!(chunk_size
!= 0, "chunk_size must not be zero");
197 let slice
= self.as_parallel_slice_mut();
198 let rem
= slice
.len() % chunk_size
;
199 let len
= slice
.len() - rem
;
200 let (fst
, snd
) = slice
.split_at_mut(len
);
208 /// Sorts the slice in parallel.
210 /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
212 /// When applicable, unstable sorting is preferred because it is generally faster than stable
213 /// sorting and it doesn't allocate auxiliary memory.
214 /// See [`par_sort_unstable`](#method.par_sort_unstable).
216 /// # Current implementation
218 /// The current algorithm is an adaptive merge sort inspired by
219 /// [timsort](https://en.wikipedia.org/wiki/Timsort).
220 /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of
221 /// two or more sorted sequences concatenated one after another.
223 /// Also, it allocates temporary storage the same size as `self`, but for very short slices a
224 /// non-allocating insertion sort is used instead.
226 /// In order to sort the slice in parallel, the slice is first divided into smaller chunks and
227 /// all chunks are sorted in parallel. Then, adjacent chunks that together form non-descending
228 /// or descending runs are concatenated. Finally, the remaining chunks are merged together using
229 /// parallel subdivision of chunks and parallel merge operation.
234 /// use rayon::prelude::*;
236 /// let mut v = [-5, 4, 1, -3, 2];
239 /// assert_eq!(v, [-5, -3, 1, 2, 4]);
241 fn par_sort(&mut self)
245 par_mergesort(self.as_parallel_slice_mut(), T
::lt
);
248 /// Sorts the slice in parallel with a comparator function.
250 /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
252 /// When applicable, unstable sorting is preferred because it is generally faster than stable
253 /// sorting and it doesn't allocate auxiliary memory.
254 /// See [`par_sort_unstable_by`](#method.par_sort_unstable_by).
256 /// # Current implementation
258 /// The current algorithm is an adaptive merge sort inspired by
259 /// [timsort](https://en.wikipedia.org/wiki/Timsort).
260 /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of
261 /// two or more sorted sequences concatenated one after another.
263 /// Also, it allocates temporary storage the same size as `self`, but for very short slices a
264 /// non-allocating insertion sort is used instead.
266 /// In order to sort the slice in parallel, the slice is first divided into smaller chunks and
267 /// all chunks are sorted in parallel. Then, adjacent chunks that together form non-descending
268 /// or descending runs are concatenated. Finally, the remaining chunks are merged together using
269 /// parallel subdivision of chunks and parallel merge operation.
274 /// use rayon::prelude::*;
276 /// let mut v = [5, 4, 1, 3, 2];
277 /// v.par_sort_by(|a, b| a.cmp(b));
278 /// assert_eq!(v, [1, 2, 3, 4, 5]);
280 /// // reverse sorting
281 /// v.par_sort_by(|a, b| b.cmp(a));
282 /// assert_eq!(v, [5, 4, 3, 2, 1]);
284 fn par_sort_by
<F
>(&mut self, compare
: F
)
286 F
: Fn(&T
, &T
) -> Ordering
+ Sync
,
288 par_mergesort(self.as_parallel_slice_mut(), |a
, b
| {
289 compare(a
, b
) == Ordering
::Less
293 /// Sorts the slice in parallel with a key extraction function.
295 /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
297 /// When applicable, unstable sorting is preferred because it is generally faster than stable
298 /// sorting and it doesn't allocate auxiliary memory.
299 /// See [`par_sort_unstable_by_key`](#method.par_sort_unstable_by_key).
301 /// # Current implementation
303 /// The current algorithm is an adaptive merge sort inspired by
304 /// [timsort](https://en.wikipedia.org/wiki/Timsort).
305 /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of
306 /// two or more sorted sequences concatenated one after another.
308 /// Also, it allocates temporary storage the same size as `self`, but for very short slices a
309 /// non-allocating insertion sort is used instead.
311 /// In order to sort the slice in parallel, the slice is first divided into smaller chunks and
312 /// all chunks are sorted in parallel. Then, adjacent chunks that together form non-descending
313 /// or descending runs are concatenated. Finally, the remaining chunks are merged together using
314 /// parallel subdivision of chunks and parallel merge operation.
319 /// use rayon::prelude::*;
321 /// let mut v = [-5i32, 4, 1, -3, 2];
323 /// v.par_sort_by_key(|k| k.abs());
324 /// assert_eq!(v, [1, 2, -3, 4, -5]);
326 fn par_sort_by_key
<B
, F
>(&mut self, f
: F
)
329 F
: Fn(&T
) -> B
+ Sync
,
331 par_mergesort(self.as_parallel_slice_mut(), |a
, b
| f(a
).lt(&f(b
)));
334 /// Sorts the slice in parallel, but may not preserve the order of equal elements.
336 /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
337 /// and `O(n log n)` worst-case.
339 /// # Current implementation
341 /// The current algorithm is based on Orson Peters' [pattern-defeating quicksort][pdqsort],
342 /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
343 /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
344 /// heapsort on degenerate inputs.
346 /// It is generally faster than stable sorting, except in a few special cases, e.g. when the
347 /// slice consists of several concatenated sorted sequences.
349 /// All quicksorts work in two stages: partitioning into two halves followed by recursive
350 /// calls. The partitioning phase is sequential, but the two recursive calls are performed in
353 /// [pdqsort]: https://github.com/orlp/pdqsort
358 /// use rayon::prelude::*;
360 /// let mut v = [-5, 4, 1, -3, 2];
362 /// v.par_sort_unstable();
363 /// assert_eq!(v, [-5, -3, 1, 2, 4]);
365 fn par_sort_unstable(&mut self)
369 par_quicksort(self.as_parallel_slice_mut(), T
::lt
);
372 /// Sorts the slice in parallel with a comparator function, but may not preserve the order of
375 /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
376 /// and `O(n log n)` worst-case.
378 /// # Current implementation
380 /// The current algorithm is based on Orson Peters' [pattern-defeating quicksort][pdqsort],
381 /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
382 /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
383 /// heapsort on degenerate inputs.
385 /// It is generally faster than stable sorting, except in a few special cases, e.g. when the
386 /// slice consists of several concatenated sorted sequences.
388 /// All quicksorts work in two stages: partitioning into two halves followed by recursive
389 /// calls. The partitioning phase is sequential, but the two recursive calls are performed in
392 /// [pdqsort]: https://github.com/orlp/pdqsort
397 /// use rayon::prelude::*;
399 /// let mut v = [5, 4, 1, 3, 2];
400 /// v.par_sort_unstable_by(|a, b| a.cmp(b));
401 /// assert_eq!(v, [1, 2, 3, 4, 5]);
403 /// // reverse sorting
404 /// v.par_sort_unstable_by(|a, b| b.cmp(a));
405 /// assert_eq!(v, [5, 4, 3, 2, 1]);
407 fn par_sort_unstable_by
<F
>(&mut self, compare
: F
)
409 F
: Fn(&T
, &T
) -> Ordering
+ Sync
,
411 par_quicksort(self.as_parallel_slice_mut(), |a
, b
| {
412 compare(a
, b
) == Ordering
::Less
416 /// Sorts the slice in parallel with a key extraction function, but may not preserve the order
417 /// of equal elements.
419 /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
420 /// and `O(n log n)` worst-case.
422 /// # Current implementation
424 /// The current algorithm is based on Orson Peters' [pattern-defeating quicksort][pdqsort],
425 /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
426 /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
427 /// heapsort on degenerate inputs.
429 /// It is generally faster than stable sorting, except in a few special cases, e.g. when the
430 /// slice consists of several concatenated sorted sequences.
432 /// All quicksorts work in two stages: partitioning into two halves followed by recursive
433 /// calls. The partitioning phase is sequential, but the two recursive calls are performed in
436 /// [pdqsort]: https://github.com/orlp/pdqsort
441 /// use rayon::prelude::*;
443 /// let mut v = [-5i32, 4, 1, -3, 2];
445 /// v.par_sort_unstable_by_key(|k| k.abs());
446 /// assert_eq!(v, [1, 2, -3, 4, -5]);
448 fn par_sort_unstable_by_key
<B
, F
>(&mut self, f
: F
)
451 F
: Fn(&T
) -> B
+ Sync
,
453 par_quicksort(self.as_parallel_slice_mut(), |a
, b
| f(a
).lt(&f(b
)));
457 impl<T
: Send
> ParallelSliceMut
<T
> for [T
] {
459 fn as_parallel_slice_mut(&mut self) -> &mut [T
] {
464 impl<'data
, T
: Sync
+ 'data
> IntoParallelIterator
for &'data
[T
] {
465 type Item
= &'data T
;
466 type Iter
= Iter
<'data
, T
>;
468 fn into_par_iter(self) -> Self::Iter
{
473 impl<'data
, T
: Sync
+ 'data
> IntoParallelIterator
for &'data Vec
<T
> {
474 type Item
= &'data T
;
475 type Iter
= Iter
<'data
, T
>;
477 fn into_par_iter(self) -> Self::Iter
{
482 impl<'data
, T
: Send
+ 'data
> IntoParallelIterator
for &'data
mut [T
] {
483 type Item
= &'data
mut T
;
484 type Iter
= IterMut
<'data
, T
>;
486 fn into_par_iter(self) -> Self::Iter
{
487 IterMut { slice: self }
491 impl<'data
, T
: Send
+ 'data
> IntoParallelIterator
for &'data
mut Vec
<T
> {
492 type Item
= &'data
mut T
;
493 type Iter
= IterMut
<'data
, T
>;
495 fn into_par_iter(self) -> Self::Iter
{
496 IterMut { slice: self }
500 /// Parallel iterator over immutable items in a slice
502 pub struct Iter
<'data
, T
: Sync
> {
506 impl<'data
, T
: Sync
> Clone
for Iter
<'data
, T
> {
507 fn clone(&self) -> Self {
512 impl<'data
, T
: Sync
+ 'data
> ParallelIterator
for Iter
<'data
, T
> {
513 type Item
= &'data T
;
515 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
517 C
: UnindexedConsumer
<Self::Item
>,
519 bridge(self, consumer
)
522 fn opt_len(&self) -> Option
<usize> {
527 impl<'data
, T
: Sync
+ 'data
> IndexedParallelIterator
for Iter
<'data
, T
> {
528 fn drive
<C
>(self, consumer
: C
) -> C
::Result
530 C
: Consumer
<Self::Item
>,
532 bridge(self, consumer
)
535 fn len(&self) -> usize {
539 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
541 CB
: ProducerCallback
<Self::Item
>,
543 callback
.callback(IterProducer { slice: self.slice }
)
547 struct IterProducer
<'data
, T
: Sync
> {
551 impl<'data
, T
: 'data
+ Sync
> Producer
for IterProducer
<'data
, T
> {
552 type Item
= &'data T
;
553 type IntoIter
= ::std
::slice
::Iter
<'data
, T
>;
555 fn into_iter(self) -> Self::IntoIter
{
559 fn split_at(self, index
: usize) -> (Self, Self) {
560 let (left
, right
) = self.slice
.split_at(index
);
561 (IterProducer { slice: left }
, IterProducer { slice: right }
)
565 /// Parallel iterator over immutable non-overlapping chunks of a slice
567 pub struct Chunks
<'data
, T
: Sync
> {
572 impl<'data
, T
: Sync
> Clone
for Chunks
<'data
, T
> {
573 fn clone(&self) -> Self {
578 impl<'data
, T
: Sync
+ 'data
> ParallelIterator
for Chunks
<'data
, T
> {
579 type Item
= &'data
[T
];
581 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
583 C
: UnindexedConsumer
<Self::Item
>,
585 bridge(self, consumer
)
588 fn opt_len(&self) -> Option
<usize> {
593 impl<'data
, T
: Sync
+ 'data
> IndexedParallelIterator
for Chunks
<'data
, T
> {
594 fn drive
<C
>(self, consumer
: C
) -> C
::Result
596 C
: Consumer
<Self::Item
>,
598 bridge(self, consumer
)
601 fn len(&self) -> usize {
602 div_round_up(self.slice
.len(), self.chunk_size
)
605 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
607 CB
: ProducerCallback
<Self::Item
>,
609 callback
.callback(ChunksProducer
{
610 chunk_size
: self.chunk_size
,
616 struct ChunksProducer
<'data
, T
: Sync
> {
621 impl<'data
, T
: 'data
+ Sync
> Producer
for ChunksProducer
<'data
, T
> {
622 type Item
= &'data
[T
];
623 type IntoIter
= ::std
::slice
::Chunks
<'data
, T
>;
625 fn into_iter(self) -> Self::IntoIter
{
626 self.slice
.chunks(self.chunk_size
)
629 fn split_at(self, index
: usize) -> (Self, Self) {
630 let elem_index
= cmp
::min(index
* self.chunk_size
, self.slice
.len());
631 let (left
, right
) = self.slice
.split_at(elem_index
);
634 chunk_size
: self.chunk_size
,
638 chunk_size
: self.chunk_size
,
645 /// Parallel iterator over immutable non-overlapping chunks of a slice
647 pub struct ChunksExact
<'data
, T
: Sync
> {
653 impl<'data
, T
: Sync
> ChunksExact
<'data
, T
> {
654 /// Return the remainder of the original slice that is not going to be
655 /// returned by the iterator. The returned slice has at most `chunk_size-1`
657 pub fn remainder(&self) -> &'data
[T
] {
662 impl<'data
, T
: Sync
> Clone
for ChunksExact
<'data
, T
> {
663 fn clone(&self) -> Self {
664 ChunksExact { ..*self }
668 impl<'data
, T
: Sync
+ 'data
> ParallelIterator
for ChunksExact
<'data
, T
> {
669 type Item
= &'data
[T
];
671 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
673 C
: UnindexedConsumer
<Self::Item
>,
675 bridge(self, consumer
)
678 fn opt_len(&self) -> Option
<usize> {
683 impl<'data
, T
: Sync
+ 'data
> IndexedParallelIterator
for ChunksExact
<'data
, T
> {
684 fn drive
<C
>(self, consumer
: C
) -> C
::Result
686 C
: Consumer
<Self::Item
>,
688 bridge(self, consumer
)
691 fn len(&self) -> usize {
692 self.slice
.len() / self.chunk_size
695 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
697 CB
: ProducerCallback
<Self::Item
>,
699 callback
.callback(ChunksExactProducer
{
700 chunk_size
: self.chunk_size
,
706 struct ChunksExactProducer
<'data
, T
: Sync
> {
711 impl<'data
, T
: 'data
+ Sync
> Producer
for ChunksExactProducer
<'data
, T
> {
712 type Item
= &'data
[T
];
713 type IntoIter
= ::std
::slice
::ChunksExact
<'data
, T
>;
715 fn into_iter(self) -> Self::IntoIter
{
716 self.slice
.chunks_exact(self.chunk_size
)
719 fn split_at(self, index
: usize) -> (Self, Self) {
720 let elem_index
= index
* self.chunk_size
;
721 let (left
, right
) = self.slice
.split_at(elem_index
);
723 ChunksExactProducer
{
724 chunk_size
: self.chunk_size
,
727 ChunksExactProducer
{
728 chunk_size
: self.chunk_size
,
735 /// Parallel iterator over immutable overlapping windows of a slice
737 pub struct Windows
<'data
, T
: Sync
> {
742 impl<'data
, T
: Sync
> Clone
for Windows
<'data
, T
> {
743 fn clone(&self) -> Self {
748 impl<'data
, T
: Sync
+ 'data
> ParallelIterator
for Windows
<'data
, T
> {
749 type Item
= &'data
[T
];
751 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
753 C
: UnindexedConsumer
<Self::Item
>,
755 bridge(self, consumer
)
758 fn opt_len(&self) -> Option
<usize> {
763 impl<'data
, T
: Sync
+ 'data
> IndexedParallelIterator
for Windows
<'data
, T
> {
764 fn drive
<C
>(self, consumer
: C
) -> C
::Result
766 C
: Consumer
<Self::Item
>,
768 bridge(self, consumer
)
771 fn len(&self) -> usize {
772 assert
!(self.window_size
>= 1);
773 self.slice
.len().saturating_sub(self.window_size
- 1)
776 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
778 CB
: ProducerCallback
<Self::Item
>,
780 callback
.callback(WindowsProducer
{
781 window_size
: self.window_size
,
787 struct WindowsProducer
<'data
, T
: Sync
> {
792 impl<'data
, T
: 'data
+ Sync
> Producer
for WindowsProducer
<'data
, T
> {
793 type Item
= &'data
[T
];
794 type IntoIter
= ::std
::slice
::Windows
<'data
, T
>;
796 fn into_iter(self) -> Self::IntoIter
{
797 self.slice
.windows(self.window_size
)
800 fn split_at(self, index
: usize) -> (Self, Self) {
801 let left_index
= cmp
::min(self.slice
.len(), index
+ (self.window_size
- 1));
802 let left
= &self.slice
[..left_index
];
803 let right
= &self.slice
[index
..];
806 window_size
: self.window_size
,
810 window_size
: self.window_size
,
817 /// Parallel iterator over mutable items in a slice
819 pub struct IterMut
<'data
, T
: Send
> {
820 slice
: &'data
mut [T
],
823 impl<'data
, T
: Send
+ 'data
> ParallelIterator
for IterMut
<'data
, T
> {
824 type Item
= &'data
mut T
;
826 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
828 C
: UnindexedConsumer
<Self::Item
>,
830 bridge(self, consumer
)
833 fn opt_len(&self) -> Option
<usize> {
838 impl<'data
, T
: Send
+ 'data
> IndexedParallelIterator
for IterMut
<'data
, T
> {
839 fn drive
<C
>(self, consumer
: C
) -> C
::Result
841 C
: Consumer
<Self::Item
>,
843 bridge(self, consumer
)
846 fn len(&self) -> usize {
850 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
852 CB
: ProducerCallback
<Self::Item
>,
854 callback
.callback(IterMutProducer { slice: self.slice }
)
858 struct IterMutProducer
<'data
, T
: Send
> {
859 slice
: &'data
mut [T
],
862 impl<'data
, T
: 'data
+ Send
> Producer
for IterMutProducer
<'data
, T
> {
863 type Item
= &'data
mut T
;
864 type IntoIter
= ::std
::slice
::IterMut
<'data
, T
>;
866 fn into_iter(self) -> Self::IntoIter
{
867 self.slice
.iter_mut()
870 fn split_at(self, index
: usize) -> (Self, Self) {
871 let (left
, right
) = self.slice
.split_at_mut(index
);
873 IterMutProducer { slice: left }
,
874 IterMutProducer { slice: right }
,
879 /// Parallel iterator over mutable non-overlapping chunks of a slice
881 pub struct ChunksMut
<'data
, T
: Send
> {
883 slice
: &'data
mut [T
],
886 impl<'data
, T
: Send
+ 'data
> ParallelIterator
for ChunksMut
<'data
, T
> {
887 type Item
= &'data
mut [T
];
889 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
891 C
: UnindexedConsumer
<Self::Item
>,
893 bridge(self, consumer
)
896 fn opt_len(&self) -> Option
<usize> {
901 impl<'data
, T
: Send
+ 'data
> IndexedParallelIterator
for ChunksMut
<'data
, T
> {
902 fn drive
<C
>(self, consumer
: C
) -> C
::Result
904 C
: Consumer
<Self::Item
>,
906 bridge(self, consumer
)
909 fn len(&self) -> usize {
910 div_round_up(self.slice
.len(), self.chunk_size
)
913 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
915 CB
: ProducerCallback
<Self::Item
>,
917 callback
.callback(ChunksMutProducer
{
918 chunk_size
: self.chunk_size
,
924 struct ChunksMutProducer
<'data
, T
: Send
> {
926 slice
: &'data
mut [T
],
929 impl<'data
, T
: 'data
+ Send
> Producer
for ChunksMutProducer
<'data
, T
> {
930 type Item
= &'data
mut [T
];
931 type IntoIter
= ::std
::slice
::ChunksMut
<'data
, T
>;
933 fn into_iter(self) -> Self::IntoIter
{
934 self.slice
.chunks_mut(self.chunk_size
)
937 fn split_at(self, index
: usize) -> (Self, Self) {
938 let elem_index
= cmp
::min(index
* self.chunk_size
, self.slice
.len());
939 let (left
, right
) = self.slice
.split_at_mut(elem_index
);
942 chunk_size
: self.chunk_size
,
946 chunk_size
: self.chunk_size
,
953 /// Parallel iterator over mutable non-overlapping chunks of a slice
955 pub struct ChunksExactMut
<'data
, T
: Send
> {
957 slice
: &'data
mut [T
],
961 impl<'data
, T
: Send
> ChunksExactMut
<'data
, T
> {
962 /// Return the remainder of the original slice that is not going to be
963 /// returned by the iterator. The returned slice has at most `chunk_size-1`
966 /// Note that this has to consume `self` to return the original lifetime of
967 /// the data, which prevents this from actually being used as a parallel
968 /// iterator since that also consumes. This method is provided for parity
969 /// with `std::iter::ChunksExactMut`, but consider calling `remainder()` or
970 /// `take_remainder()` as alternatives.
971 pub fn into_remainder(self) -> &'data
mut [T
] {
975 /// Return the remainder of the original slice that is not going to be
976 /// returned by the iterator. The returned slice has at most `chunk_size-1`
979 /// Consider `take_remainder()` if you need access to the data with its
980 /// original lifetime, rather than borrowing through `&mut self` here.
981 pub fn remainder(&mut self) -> &mut [T
] {
985 /// Return the remainder of the original slice that is not going to be
986 /// returned by the iterator. The returned slice has at most `chunk_size-1`
987 /// elements. Subsequent calls will return an empty slice.
988 pub fn take_remainder(&mut self) -> &'data
mut [T
] {
989 std
::mem
::replace(&mut self.rem
, &mut [])
993 impl<'data
, T
: Send
+ 'data
> ParallelIterator
for ChunksExactMut
<'data
, T
> {
994 type Item
= &'data
mut [T
];
996 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
998 C
: UnindexedConsumer
<Self::Item
>,
1000 bridge(self, consumer
)
1003 fn opt_len(&self) -> Option
<usize> {
1008 impl<'data
, T
: Send
+ 'data
> IndexedParallelIterator
for ChunksExactMut
<'data
, T
> {
1009 fn drive
<C
>(self, consumer
: C
) -> C
::Result
1011 C
: Consumer
<Self::Item
>,
1013 bridge(self, consumer
)
1016 fn len(&self) -> usize {
1017 self.slice
.len() / self.chunk_size
1020 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
1022 CB
: ProducerCallback
<Self::Item
>,
1024 callback
.callback(ChunksExactMutProducer
{
1025 chunk_size
: self.chunk_size
,
1031 struct ChunksExactMutProducer
<'data
, T
: Send
> {
1033 slice
: &'data
mut [T
],
1036 impl<'data
, T
: 'data
+ Send
> Producer
for ChunksExactMutProducer
<'data
, T
> {
1037 type Item
= &'data
mut [T
];
1038 type IntoIter
= ::std
::slice
::ChunksExactMut
<'data
, T
>;
1040 fn into_iter(self) -> Self::IntoIter
{
1041 self.slice
.chunks_exact_mut(self.chunk_size
)
1044 fn split_at(self, index
: usize) -> (Self, Self) {
1045 let elem_index
= index
* self.chunk_size
;
1046 let (left
, right
) = self.slice
.split_at_mut(elem_index
);
1048 ChunksExactMutProducer
{
1049 chunk_size
: self.chunk_size
,
1052 ChunksExactMutProducer
{
1053 chunk_size
: self.chunk_size
,
1060 /// Parallel iterator over slices separated by a predicate
1061 pub struct Split
<'data
, T
, P
> {
1066 impl<'data
, T
, P
: Clone
> Clone
for Split
<'data
, T
, P
> {
1067 fn clone(&self) -> Self {
1069 separator
: self.separator
.clone(),
1075 impl<'data
, T
: Debug
, P
> Debug
for Split
<'data
, T
, P
> {
1076 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1077 f
.debug_struct("Split").field("slice", &self.slice
).finish()
1081 impl<'data
, T
, P
> ParallelIterator
for Split
<'data
, T
, P
>
1083 P
: Fn(&T
) -> bool
+ Sync
+ Send
,
1086 type Item
= &'data
[T
];
1088 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
1090 C
: UnindexedConsumer
<Self::Item
>,
1092 let producer
= SplitProducer
::new(self.slice
, &self.separator
);
1093 bridge_unindexed(producer
, consumer
)
1097 /// Implement support for `SplitProducer`.
1098 impl<'data
, T
, P
> Fissile
<P
> for &'data
[T
]
1102 fn length(&self) -> usize {
1106 fn midpoint(&self, end
: usize) -> usize {
1110 fn find(&self, separator
: &P
, start
: usize, end
: usize) -> Option
<usize> {
1111 self[start
..end
].iter().position(separator
)
1114 fn rfind(&self, separator
: &P
, end
: usize) -> Option
<usize> {
1115 self[..end
].iter().rposition(separator
)
1118 fn split_once(self, index
: usize) -> (Self, Self) {
1119 let (left
, right
) = self.split_at(index
);
1120 (left
, &right
[1..]) // skip the separator
1123 fn fold_splits
<F
>(self, separator
: &P
, folder
: F
, skip_last
: bool
) -> F
1128 let mut split
= self.split(separator
);
1132 folder
.consume_iter(split
)
1136 /// Parallel iterator over mutable slices separated by a predicate
1137 pub struct SplitMut
<'data
, T
, P
> {
1138 slice
: &'data
mut [T
],
1142 impl<'data
, T
: Debug
, P
> Debug
for SplitMut
<'data
, T
, P
> {
1143 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1144 f
.debug_struct("SplitMut")
1145 .field("slice", &self.slice
)
1150 impl<'data
, T
, P
> ParallelIterator
for SplitMut
<'data
, T
, P
>
1152 P
: Fn(&T
) -> bool
+ Sync
+ Send
,
1155 type Item
= &'data
mut [T
];
1157 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
1159 C
: UnindexedConsumer
<Self::Item
>,
1161 let producer
= SplitProducer
::new(self.slice
, &self.separator
);
1162 bridge_unindexed(producer
, consumer
)
1166 /// Implement support for `SplitProducer`.
1167 impl<'data
, T
, P
> Fissile
<P
> for &'data
mut [T
]
1171 fn length(&self) -> usize {
1175 fn midpoint(&self, end
: usize) -> usize {
1179 fn find(&self, separator
: &P
, start
: usize, end
: usize) -> Option
<usize> {
1180 self[start
..end
].iter().position(separator
)
1183 fn rfind(&self, separator
: &P
, end
: usize) -> Option
<usize> {
1184 self[..end
].iter().rposition(separator
)
1187 fn split_once(self, index
: usize) -> (Self, Self) {
1188 let (left
, right
) = self.split_at_mut(index
);
1189 (left
, &mut right
[1..]) // skip the separator
1192 fn fold_splits
<F
>(self, separator
: &P
, folder
: F
, skip_last
: bool
) -> F
1197 let mut split
= self.split_mut(separator
);
1201 folder
.consume_iter(split
)