19
19
use iter:: * ;
20
20
use iter:: plumbing:: * ;
21
21
use std:: ops:: Range ;
22
+ use std:: usize;
22
23
23
24
/// Parallel iterator over a range, implemented for all integer types.
24
25
///
@@ -127,11 +128,15 @@ macro_rules! indexed_range_impl {
127
128
}
128
129
}
129
130
131
+ trait UnindexedRangeLen < L > {
132
+ fn len ( & self ) -> L ;
133
+ }
134
+
130
135
macro_rules! unindexed_range_impl {
131
136
( $t: ty, $len_t: ty ) => {
132
- impl IterProducer <$t> {
137
+ impl UnindexedRangeLen <$len_t> for Range <$t> {
133
138
fn len( & self ) -> $len_t {
134
- let Range { start, end } = self . range ;
139
+ let & Range { start, end } = self ;
135
140
if end > start {
136
141
end. wrapping_sub( start) as $len_t
137
142
} else {
@@ -146,15 +151,30 @@ macro_rules! unindexed_range_impl {
146
151
fn drive_unindexed<C >( self , consumer: C ) -> C :: Result
147
152
where C : UnindexedConsumer <Self :: Item >
148
153
{
149
- bridge_unindexed( IterProducer { range: self . range } , consumer)
154
+ if let Some ( len) = self . opt_len( ) {
155
+ ( 0 ..len) . into_par_iter( )
156
+ . map( |i| self . range. start + i as $t)
157
+ . drive_unindexed( consumer)
158
+ } else {
159
+ bridge_unindexed( IterProducer { range: self . range } , consumer)
160
+ }
161
+ }
162
+
163
+ fn opt_len( & self ) -> Option <usize > {
164
+ let len = self . range. len( ) ;
165
+ if len <= usize :: MAX as $len_t {
166
+ Some ( len as usize )
167
+ } else {
168
+ None
169
+ }
150
170
}
151
171
}
152
172
153
173
impl UnindexedProducer for IterProducer <$t> {
154
174
type Item = $t;
155
175
156
176
fn split( mut self ) -> ( Self , Option <Self >) {
157
- let index = self . len( ) / 2 ;
177
+ let index = self . range . len( ) / 2 ;
158
178
if index > 0 {
159
179
let mid = self . range. start. wrapping_add( index as $t) ;
160
180
let right = mid .. self . range. end;
@@ -203,9 +223,37 @@ pub fn check_range_split_at_overflow() {
203
223
#[ cfg( has_i128) ]
204
224
#[ test]
205
225
pub fn test_i128_len_doesnt_overflow ( ) {
226
+ use std:: { i128, u128} ;
227
+
206
228
// Using parse because some versions of rust don't allow long literals
207
- let octillion = "1000000000000000000000000000" . parse :: < i128 > ( ) . unwrap ( ) ;
229
+ let octillion: i128 = "1000000000000000000000000000" . parse ( ) . unwrap ( ) ;
208
230
let producer = IterProducer { range : 0 ..octillion } ;
209
231
210
- assert_eq ! ( octillion as u128 , producer. len( ) ) ;
232
+ assert_eq ! ( octillion as u128 , producer. range. len( ) ) ;
233
+ assert_eq ! ( octillion as u128 , ( 0 ..octillion) . len( ) ) ;
234
+ assert_eq ! ( 2 * octillion as u128 , ( -octillion..octillion) . len( ) ) ;
235
+
236
+ assert_eq ! ( u128 :: MAX , ( i128 :: MIN ..i128 :: MAX ) . len( ) ) ;
237
+
238
+ }
239
+
240
+ #[ test]
241
+ pub fn test_u64_opt_len ( ) {
242
+ use std:: { u64, usize} ;
243
+ assert_eq ! ( Some ( 100 ) , ( 0 ..100u64 ) . into_par_iter( ) . opt_len( ) ) ;
244
+ assert_eq ! ( Some ( usize :: MAX ) , ( 0 ..usize :: MAX as u64 ) . into_par_iter( ) . opt_len( ) ) ;
245
+ if ( usize:: MAX as u64 ) < u64:: MAX {
246
+ assert_eq ! ( None , ( 0 ..1 + usize :: MAX as u64 ) . into_par_iter( ) . opt_len( ) ) ;
247
+ assert_eq ! ( None , ( 0 ..u64 :: MAX ) . into_par_iter( ) . opt_len( ) ) ;
248
+ }
249
+ }
250
+
251
+ #[ cfg( has_i128) ]
252
+ #[ test]
253
+ pub fn test_u128_opt_len ( ) {
254
+ use std:: { u128, usize} ;
255
+ assert_eq ! ( Some ( 100 ) , ( 0 ..100u128 ) . into_par_iter( ) . opt_len( ) ) ;
256
+ assert_eq ! ( Some ( usize :: MAX ) , ( 0 ..usize :: MAX as u128 ) . into_par_iter( ) . opt_len( ) ) ;
257
+ assert_eq ! ( None , ( 0 ..1 + usize :: MAX as u128 ) . into_par_iter( ) . opt_len( ) ) ;
258
+ assert_eq ! ( None , ( 0 ..u128 :: MAX ) . into_par_iter( ) . opt_len( ) ) ;
211
259
}
0 commit comments