1 //! Parallel iterator types for [ranges][std::range],
2 //! the type for values created by `a..b` expressions
4 //! You will rarely need to interact with this module directly unless you have
5 //! need to name one of the iterator types.
8 //! use rayon::prelude::*;
10 //! let r = (0..100u64).into_par_iter()
13 //! // compare result with sequential calculation
14 //! assert_eq!((0..100).sum::<u64>(), r);
17 //! [std::range]: https://doc.rust-lang.org/core/ops/struct.Range.html
19 use crate::iter
::plumbing
::*;
25 /// Parallel iterator over a range, implemented for all integer types.
27 /// **Note:** The `zip` operation requires `IndexedParallelIterator`
28 /// which is not implemented for `u64`, `i64`, `u128`, or `i128`.
31 /// use rayon::prelude::*;
33 /// let p = (0..25usize).into_par_iter()
35 /// .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)
36 /// .map(|(x, y)| x * y)
39 /// let s = (0..25usize).zip(0..25)
40 /// .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)
41 /// .map(|(x, y)| x * y)
46 #[derive(Debug, Clone)]
51 impl<T
> IntoParallelIterator
for Range
<T
>
53 Iter
<T
>: ParallelIterator
,
55 type Item
= <Iter
<T
> as ParallelIterator
>::Item
;
58 fn into_par_iter(self) -> Self::Iter
{
63 struct IterProducer
<T
> {
67 impl<T
> IntoIterator
for IterProducer
<T
>
71 type Item
= <Range
<T
> as Iterator
>::Item
;
72 type IntoIter
= Range
<T
>;
74 fn into_iter(self) -> Self::IntoIter
{
79 macro_rules
! indexed_range_impl
{
81 impl ParallelIterator
for Iter
<$t
> {
84 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
86 C
: UnindexedConsumer
<Self::Item
>,
88 bridge(self, consumer
)
91 fn opt_len(&self) -> Option
<usize> {
96 impl IndexedParallelIterator
for Iter
<$t
> {
97 fn drive
<C
>(self, consumer
: C
) -> C
::Result
99 C
: Consumer
<Self::Item
>,
101 bridge(self, consumer
)
104 fn len(&self) -> usize {
108 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
110 CB
: ProducerCallback
<Self::Item
>,
112 callback
.callback(IterProducer { range: self.range }
)
116 impl Producer
for IterProducer
<$t
> {
117 type Item
= <Range
<$t
> as Iterator
>::Item
;
118 type IntoIter
= Range
<$t
>;
119 fn into_iter(self) -> Self::IntoIter
{
123 fn split_at(self, index
: usize) -> (Self, Self) {
124 assert
!(index
<= self.range
.len());
125 // For signed $t, the length and requested index could be greater than $t::MAX, and
126 // then `index as $t` could wrap to negative, so wrapping_add is necessary.
127 let mid
= self.range
.start
.wrapping_add(index
as $t
);
128 let left
= self.range
.start
..mid
;
129 let right
= mid
..self.range
.end
;
130 (IterProducer { range: left }
, IterProducer { range: right }
)
136 trait UnindexedRangeLen
<L
> {
140 macro_rules
! unindexed_range_impl
{
141 ( $t
:ty
, $len_t
:ty
) => {
142 impl UnindexedRangeLen
<$len_t
> for Range
<$t
> {
143 fn len(&self) -> $len_t
{
144 let &Range { start, end }
= self;
146 end
.wrapping_sub(start
) as $len_t
153 impl ParallelIterator
for Iter
<$t
> {
156 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
158 C
: UnindexedConsumer
<Self::Item
>,
161 fn offset(start
: $t
) -> impl Fn(usize) -> $t
{
162 move |i
| start
.wrapping_add(i
as $t
)
165 if let Some(len
) = self.opt_len() {
166 // Drive this in indexed mode for better `collect`.
169 .map(offset(self.range
.start
))
172 bridge_unindexed(IterProducer { range: self.range }
, consumer
)
176 fn opt_len(&self) -> Option
<usize> {
177 let len
= self.range
.len();
178 if len
<= usize::MAX
as $len_t
{
186 impl UnindexedProducer
for IterProducer
<$t
> {
189 fn split(mut self) -> (Self, Option
<Self>) {
190 let index
= self.range
.len() / 2;
192 let mid
= self.range
.start
.wrapping_add(index
as $t
);
193 let right
= mid
..self.range
.end
;
194 self.range
.end
= mid
;
195 (self, Some(IterProducer { range: right }
))
201 fn fold_with
<F
>(self, folder
: F
) -> F
203 F
: Folder
<Self::Item
>,
205 folder
.consume_iter(self)
211 // all Range<T> with ExactSizeIterator
212 indexed_range_impl
! {u8}
213 indexed_range_impl
! {u16}
214 indexed_range_impl
! {u32}
215 indexed_range_impl
! {usize}
216 indexed_range_impl
! {i8}
217 indexed_range_impl
! {i16}
218 indexed_range_impl
! {i32}
219 indexed_range_impl
! {isize}
221 // other Range<T> with just Iterator
222 unindexed_range_impl
! {u64, u64}
223 unindexed_range_impl
! {i64, u64}
224 unindexed_range_impl
! {u128, u128}
225 unindexed_range_impl
! {i128, u128}
227 // char is special because of the surrogate range hole
228 macro_rules
! convert_char
{
229 ( $
self:ident
. $method
:ident ( $
( $arg
:expr
),* ) ) => {{
230 let start
= $
self.range
.start
as u32;
231 let end
= $
self.range
.end
as u32;
232 if start
< 0xD800 && 0xE000 < end
{
233 // chain the before and after surrogate range fragments
237 .map(|codepoint
| unsafe { char::from_u32_unchecked(codepoint) }
)
238 .$
method($
( $arg
),*)
240 // no surrogate range to worry about
243 .map(|codepoint
| unsafe { char::from_u32_unchecked(codepoint) }
)
244 .$
method($
( $arg
),*)
249 impl ParallelIterator
for Iter
<char> {
252 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
254 C
: UnindexedConsumer
<Self::Item
>,
256 convert_char
!(self.drive(consumer
))
259 fn opt_len(&self) -> Option
<usize> {
264 impl IndexedParallelIterator
for Iter
<char> {
265 // Split at the surrogate range first if we're allowed to
266 fn drive
<C
>(self, consumer
: C
) -> C
::Result
268 C
: Consumer
<Self::Item
>,
270 convert_char
!(self.drive(consumer
))
273 fn len(&self) -> usize {
274 // Taken from <char as Step>::steps_between
275 let start
= self.range
.start
as u32;
276 let end
= self.range
.end
as u32;
278 let mut count
= end
- start
;
279 if start
< 0xD800 && 0xE000 <= end
{
288 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
290 CB
: ProducerCallback
<Self::Item
>,
292 convert_char
!(self.with_producer(callback
))
297 fn check_range_split_at_overflow() {
298 // Note, this split index overflows i8!
299 let producer
= IterProducer { range: -100i8..100 }
;
300 let (left
, right
) = producer
.split_at(150);
301 let r1
: i32 = left
.range
.map(i32::from
).sum();
302 let r2
: i32 = right
.range
.map(i32::from
).sum();
303 assert_eq
!(r1
+ r2
, -100);
307 fn test_i128_len_doesnt_overflow() {
308 use std
::{i128, u128}
;
310 // Using parse because some versions of rust don't allow long literals
311 let octillion
: i128
= "1000000000000000000000000000".parse().unwrap();
312 let producer
= IterProducer
{
316 assert_eq
!(octillion
as u128
, producer
.range
.len());
317 assert_eq
!(octillion
as u128
, (0..octillion
).len());
318 assert_eq
!(2 * octillion
as u128
, (-octillion
..octillion
).len());
320 assert_eq
!(u128
::MAX
, (i128
::MIN
..i128
::MAX
).len());
324 fn test_u64_opt_len() {
325 use std
::{u64, usize}
;
326 assert_eq
!(Some(100), (0..100u64).into_par_iter().opt_len());
329 (0..usize::MAX
as u64).into_par_iter().opt_len()
331 if (usize::MAX
as u64) < u64::MAX
{
334 (0..(usize::MAX
as u64).wrapping_add(1))
338 assert_eq
!(None
, (0..u64::MAX
).into_par_iter().opt_len());
343 fn test_u128_opt_len() {
344 use std
::{u128, usize}
;
345 assert_eq
!(Some(100), (0..100u128).into_par_iter().opt_len());
348 (0..usize::MAX
as u128
).into_par_iter().opt_len()
350 assert_eq
!(None
, (0..1 + usize::MAX
as u128
).into_par_iter().opt_len());
351 assert_eq
!(None
, (0..u128
::MAX
).into_par_iter().opt_len());
354 // `usize as i64` can overflow, so make sure to wrap it appropriately
355 // when using the `opt_len` "indexed" mode.
357 #[cfg(target_pointer_width = "64")]
358 fn test_usize_i64_overflow() {
359 use crate::ThreadPoolBuilder
;
362 let iter
= (-2..i64::MAX
).into_par_iter();
363 assert_eq
!(iter
.opt_len(), Some(i64::MAX
as usize + 2));
365 // always run with multiple threads to split into, or this will take forever...
366 let pool
= ThreadPoolBuilder
::new().num_threads(8).build().unwrap();
367 pool
.install(|| assert_eq
!(iter
.find_last(|_
| true), Some(i64::MAX
- 1)));