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
20 use iter
::plumbing
::*;
23 /// Parallel iterator over a range, implemented for all integer types.
25 /// **Note:** The `zip` operation requires `IndexedParallelIterator`
26 /// which is not implemented for `u64` or `i64`.
29 /// use rayon::prelude::*;
31 /// let p = (0..25usize).into_par_iter()
33 /// .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)
34 /// .map(|(x, y)| x * y)
37 /// let s = (0..25usize).zip(0..25)
38 /// .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)
39 /// .map(|(x, y)| x * y)
44 #[derive(Debug, Clone)]
49 impl<T
> IntoParallelIterator
for Range
<T
>
50 where Iter
<T
>: ParallelIterator
52 type Item
= <Iter
<T
> as ParallelIterator
>::Item
;
55 fn into_par_iter(self) -> Self::Iter
{
60 struct IterProducer
<T
> {
64 impl<T
> IntoIterator
for IterProducer
<T
>
65 where Range
<T
>: Iterator
67 type Item
= <Range
<T
> as Iterator
>::Item
;
68 type IntoIter
= Range
<T
>;
70 fn into_iter(self) -> Self::IntoIter
{
75 macro_rules
! indexed_range_impl
{
77 impl ParallelIterator
for Iter
<$t
> {
80 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
81 where C
: UnindexedConsumer
<Self::Item
>
83 bridge(self, consumer
)
86 fn opt_len(&self) -> Option
<usize> {
91 impl IndexedParallelIterator
for Iter
<$t
> {
92 fn drive
<C
>(self, consumer
: C
) -> C
::Result
93 where C
: Consumer
<Self::Item
>
95 bridge(self, consumer
)
98 fn len(&self) -> usize {
102 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
103 where CB
: ProducerCallback
<Self::Item
>
105 callback
.callback(IterProducer { range: self.range }
)
109 impl Producer
for IterProducer
<$t
> {
111 type Item
= <Range
<$t
> as Iterator
>::Item
;
112 type IntoIter
= Range
<$t
>;
113 fn into_iter(self) -> Self::IntoIter
{
117 fn split_at(self, index
: usize) -> (Self, Self) {
118 assert
!(index
<= self.range
.len());
119 // For signed $t, the length and requested index could be greater than $t::MAX, and
120 // then `index as $t` could wrap to negative, so wrapping_add is necessary.
121 let mid
= self.range
.start
.wrapping_add(index
as $t
);
122 let left
= self.range
.start
.. mid
;
123 let right
= mid
.. self.range
.end
;
124 (IterProducer { range: left }
, IterProducer { range: right }
)
130 macro_rules
! unindexed_range_impl
{
132 impl IterProducer
<$t
> {
133 fn len(&self) -> u64 {
134 let Range { start, end }
= self.range
;
136 end
.wrapping_sub(start
) as u64
143 impl ParallelIterator
for Iter
<$t
> {
146 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
147 where C
: UnindexedConsumer
<Self::Item
>
149 bridge_unindexed(IterProducer { range: self.range }
, consumer
)
153 impl UnindexedProducer
for IterProducer
<$t
> {
156 fn split(mut self) -> (Self, Option
<Self>) {
157 let index
= self.len() / 2;
159 let mid
= self.range
.start
.wrapping_add(index
as $t
);
160 let right
= mid
.. self.range
.end
;
161 self.range
.end
= mid
;
162 (self, Some(IterProducer { range: right }
))
168 fn fold_with
<F
>(self, folder
: F
) -> F
169 where F
: Folder
<Self::Item
>
171 folder
.consume_iter(self)
177 // all Range<T> with ExactSizeIterator
178 indexed_range_impl
!{u8}
179 indexed_range_impl
!{u16}
180 indexed_range_impl
!{u32}
181 indexed_range_impl
!{usize}
182 indexed_range_impl
!{i8}
183 indexed_range_impl
!{i16}
184 indexed_range_impl
!{i32}
185 indexed_range_impl
!{isize}
187 // other Range<T> with just Iterator
188 unindexed_range_impl
!{u64}
189 unindexed_range_impl
!{i64}
193 pub fn check_range_split_at_overflow() {
194 // Note, this split index overflows i8!
195 let producer
= IterProducer { range: -100i8..100 }
;
196 let (left
, right
) = producer
.split_at(150);
197 let r1
: i32 = left
.range
.map(|i
| i
as i32).sum();
198 let r2
: i32 = right
.range
.map(|i
| i
as i32).sum();
199 assert_eq
!(r1
+ r2
, -100);