rayon/slice/
rchunks.rs

1use crate::iter::plumbing::*;
2use crate::iter::*;
3use crate::math::div_round_up;
4
5/// Parallel iterator over immutable non-overlapping chunks of a slice, starting at the end.
6#[derive(Debug)]
7pub struct RChunks<'data, T: Sync> {
8    chunk_size: usize,
9    slice: &'data [T],
10}
11
12impl<'data, T: Sync> RChunks<'data, T> {
13    pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {
14        Self { chunk_size, slice }
15    }
16}
17
18impl<'data, T: Sync> Clone for RChunks<'data, T> {
19    fn clone(&self) -> Self {
20        RChunks { ..*self }
21    }
22}
23
24impl<'data, T: Sync + 'data> ParallelIterator for RChunks<'data, T> {
25    type Item = &'data [T];
26
27    fn drive_unindexed<C>(self, consumer: C) -> C::Result
28    where
29        C: UnindexedConsumer<Self::Item>,
30    {
31        bridge(self, consumer)
32    }
33
34    fn opt_len(&self) -> Option<usize> {
35        Some(self.len())
36    }
37}
38
39impl<'data, T: Sync + 'data> IndexedParallelIterator for RChunks<'data, T> {
40    fn drive<C>(self, consumer: C) -> C::Result
41    where
42        C: Consumer<Self::Item>,
43    {
44        bridge(self, consumer)
45    }
46
47    fn len(&self) -> usize {
48        div_round_up(self.slice.len(), self.chunk_size)
49    }
50
51    fn with_producer<CB>(self, callback: CB) -> CB::Output
52    where
53        CB: ProducerCallback<Self::Item>,
54    {
55        callback.callback(RChunksProducer {
56            chunk_size: self.chunk_size,
57            slice: self.slice,
58        })
59    }
60}
61
62struct RChunksProducer<'data, T: Sync> {
63    chunk_size: usize,
64    slice: &'data [T],
65}
66
67impl<'data, T: 'data + Sync> Producer for RChunksProducer<'data, T> {
68    type Item = &'data [T];
69    type IntoIter = ::std::slice::RChunks<'data, T>;
70
71    fn into_iter(self) -> Self::IntoIter {
72        self.slice.rchunks(self.chunk_size)
73    }
74
75    fn split_at(self, index: usize) -> (Self, Self) {
76        let elem_index = self.slice.len().saturating_sub(index * self.chunk_size);
77        let (left, right) = self.slice.split_at(elem_index);
78        (
79            RChunksProducer {
80                chunk_size: self.chunk_size,
81                slice: right,
82            },
83            RChunksProducer {
84                chunk_size: self.chunk_size,
85                slice: left,
86            },
87        )
88    }
89}
90
91/// Parallel iterator over immutable non-overlapping chunks of a slice, starting at the end.
92#[derive(Debug)]
93pub struct RChunksExact<'data, T: Sync> {
94    chunk_size: usize,
95    slice: &'data [T],
96    rem: &'data [T],
97}
98
99impl<'data, T: Sync> RChunksExact<'data, T> {
100    pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {
101        let rem_len = slice.len() % chunk_size;
102        let (rem, slice) = slice.split_at(rem_len);
103        Self {
104            chunk_size,
105            slice,
106            rem,
107        }
108    }
109
110    /// Return the remainder of the original slice that is not going to be
111    /// returned by the iterator. The returned slice has at most `chunk_size-1`
112    /// elements.
113    pub fn remainder(&self) -> &'data [T] {
114        self.rem
115    }
116}
117
118impl<'data, T: Sync> Clone for RChunksExact<'data, T> {
119    fn clone(&self) -> Self {
120        RChunksExact { ..*self }
121    }
122}
123
124impl<'data, T: Sync + 'data> ParallelIterator for RChunksExact<'data, T> {
125    type Item = &'data [T];
126
127    fn drive_unindexed<C>(self, consumer: C) -> C::Result
128    where
129        C: UnindexedConsumer<Self::Item>,
130    {
131        bridge(self, consumer)
132    }
133
134    fn opt_len(&self) -> Option<usize> {
135        Some(self.len())
136    }
137}
138
139impl<'data, T: Sync + 'data> IndexedParallelIterator for RChunksExact<'data, T> {
140    fn drive<C>(self, consumer: C) -> C::Result
141    where
142        C: Consumer<Self::Item>,
143    {
144        bridge(self, consumer)
145    }
146
147    fn len(&self) -> usize {
148        self.slice.len() / self.chunk_size
149    }
150
151    fn with_producer<CB>(self, callback: CB) -> CB::Output
152    where
153        CB: ProducerCallback<Self::Item>,
154    {
155        callback.callback(RChunksExactProducer {
156            chunk_size: self.chunk_size,
157            slice: self.slice,
158        })
159    }
160}
161
162struct RChunksExactProducer<'data, T: Sync> {
163    chunk_size: usize,
164    slice: &'data [T],
165}
166
167impl<'data, T: 'data + Sync> Producer for RChunksExactProducer<'data, T> {
168    type Item = &'data [T];
169    type IntoIter = ::std::slice::RChunksExact<'data, T>;
170
171    fn into_iter(self) -> Self::IntoIter {
172        self.slice.rchunks_exact(self.chunk_size)
173    }
174
175    fn split_at(self, index: usize) -> (Self, Self) {
176        let elem_index = self.slice.len() - index * self.chunk_size;
177        let (left, right) = self.slice.split_at(elem_index);
178        (
179            RChunksExactProducer {
180                chunk_size: self.chunk_size,
181                slice: right,
182            },
183            RChunksExactProducer {
184                chunk_size: self.chunk_size,
185                slice: left,
186            },
187        )
188    }
189}
190
191/// Parallel iterator over mutable non-overlapping chunks of a slice, starting at the end.
192#[derive(Debug)]
193pub struct RChunksMut<'data, T: Send> {
194    chunk_size: usize,
195    slice: &'data mut [T],
196}
197
198impl<'data, T: Send> RChunksMut<'data, T> {
199    pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {
200        Self { chunk_size, slice }
201    }
202}
203
204impl<'data, T: Send + 'data> ParallelIterator for RChunksMut<'data, T> {
205    type Item = &'data mut [T];
206
207    fn drive_unindexed<C>(self, consumer: C) -> C::Result
208    where
209        C: UnindexedConsumer<Self::Item>,
210    {
211        bridge(self, consumer)
212    }
213
214    fn opt_len(&self) -> Option<usize> {
215        Some(self.len())
216    }
217}
218
219impl<'data, T: Send + 'data> IndexedParallelIterator for RChunksMut<'data, T> {
220    fn drive<C>(self, consumer: C) -> C::Result
221    where
222        C: Consumer<Self::Item>,
223    {
224        bridge(self, consumer)
225    }
226
227    fn len(&self) -> usize {
228        div_round_up(self.slice.len(), self.chunk_size)
229    }
230
231    fn with_producer<CB>(self, callback: CB) -> CB::Output
232    where
233        CB: ProducerCallback<Self::Item>,
234    {
235        callback.callback(RChunksMutProducer {
236            chunk_size: self.chunk_size,
237            slice: self.slice,
238        })
239    }
240}
241
242struct RChunksMutProducer<'data, T: Send> {
243    chunk_size: usize,
244    slice: &'data mut [T],
245}
246
247impl<'data, T: 'data + Send> Producer for RChunksMutProducer<'data, T> {
248    type Item = &'data mut [T];
249    type IntoIter = ::std::slice::RChunksMut<'data, T>;
250
251    fn into_iter(self) -> Self::IntoIter {
252        self.slice.rchunks_mut(self.chunk_size)
253    }
254
255    fn split_at(self, index: usize) -> (Self, Self) {
256        let elem_index = self.slice.len().saturating_sub(index * self.chunk_size);
257        let (left, right) = self.slice.split_at_mut(elem_index);
258        (
259            RChunksMutProducer {
260                chunk_size: self.chunk_size,
261                slice: right,
262            },
263            RChunksMutProducer {
264                chunk_size: self.chunk_size,
265                slice: left,
266            },
267        )
268    }
269}
270
271/// Parallel iterator over mutable non-overlapping chunks of a slice, starting at the end.
272#[derive(Debug)]
273pub struct RChunksExactMut<'data, T: Send> {
274    chunk_size: usize,
275    slice: &'data mut [T],
276    rem: &'data mut [T],
277}
278
279impl<'data, T: Send> RChunksExactMut<'data, T> {
280    pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {
281        let rem_len = slice.len() % chunk_size;
282        let (rem, slice) = slice.split_at_mut(rem_len);
283        Self {
284            chunk_size,
285            slice,
286            rem,
287        }
288    }
289
290    /// Return the remainder of the original slice that is not going to be
291    /// returned by the iterator. The returned slice has at most `chunk_size-1`
292    /// elements.
293    ///
294    /// Note that this has to consume `self` to return the original lifetime of
295    /// the data, which prevents this from actually being used as a parallel
296    /// iterator since that also consumes. This method is provided for parity
297    /// with `std::iter::RChunksExactMut`, but consider calling `remainder()` or
298    /// `take_remainder()` as alternatives.
299    pub fn into_remainder(self) -> &'data mut [T] {
300        self.rem
301    }
302
303    /// Return the remainder of the original slice that is not going to be
304    /// returned by the iterator. The returned slice has at most `chunk_size-1`
305    /// elements.
306    ///
307    /// Consider `take_remainder()` if you need access to the data with its
308    /// original lifetime, rather than borrowing through `&mut self` here.
309    pub fn remainder(&mut self) -> &mut [T] {
310        self.rem
311    }
312
313    /// Return the remainder of the original slice that is not going to be
314    /// returned by the iterator. The returned slice has at most `chunk_size-1`
315    /// elements. Subsequent calls will return an empty slice.
316    pub fn take_remainder(&mut self) -> &'data mut [T] {
317        std::mem::take(&mut self.rem)
318    }
319}
320
321impl<'data, T: Send + 'data> ParallelIterator for RChunksExactMut<'data, T> {
322    type Item = &'data mut [T];
323
324    fn drive_unindexed<C>(self, consumer: C) -> C::Result
325    where
326        C: UnindexedConsumer<Self::Item>,
327    {
328        bridge(self, consumer)
329    }
330
331    fn opt_len(&self) -> Option<usize> {
332        Some(self.len())
333    }
334}
335
336impl<'data, T: Send + 'data> IndexedParallelIterator for RChunksExactMut<'data, T> {
337    fn drive<C>(self, consumer: C) -> C::Result
338    where
339        C: Consumer<Self::Item>,
340    {
341        bridge(self, consumer)
342    }
343
344    fn len(&self) -> usize {
345        self.slice.len() / self.chunk_size
346    }
347
348    fn with_producer<CB>(self, callback: CB) -> CB::Output
349    where
350        CB: ProducerCallback<Self::Item>,
351    {
352        callback.callback(RChunksExactMutProducer {
353            chunk_size: self.chunk_size,
354            slice: self.slice,
355        })
356    }
357}
358
359struct RChunksExactMutProducer<'data, T: Send> {
360    chunk_size: usize,
361    slice: &'data mut [T],
362}
363
364impl<'data, T: 'data + Send> Producer for RChunksExactMutProducer<'data, T> {
365    type Item = &'data mut [T];
366    type IntoIter = ::std::slice::RChunksExactMut<'data, T>;
367
368    fn into_iter(self) -> Self::IntoIter {
369        self.slice.rchunks_exact_mut(self.chunk_size)
370    }
371
372    fn split_at(self, index: usize) -> (Self, Self) {
373        let elem_index = self.slice.len() - index * self.chunk_size;
374        let (left, right) = self.slice.split_at_mut(elem_index);
375        (
376            RChunksExactMutProducer {
377                chunk_size: self.chunk_size,
378                slice: right,
379            },
380            RChunksExactMutProducer {
381                chunk_size: self.chunk_size,
382                slice: left,
383            },
384        )
385    }
386}