1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! External iterators for generic mathematics
12 #![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
13 html_favicon_url
= "https://rust-num.github.io/num/favicon.ico",
14 html_root_url
= "https://rust-num.github.io/num/",
15 html_playground_url
= "http://play.integer32.com/")]
17 extern crate num_traits
as traits
;
18 extern crate num_integer
as integer
;
21 use traits
::{Zero, One, CheckedAdd, ToPrimitive}
;
22 use std
::ops
::{Add, Sub}
;
24 /// An iterator over the range [start, stop)
32 /// Returns an iterator over the given range [start, stop) (that is, starting
33 /// at start (inclusive), and ending at stop (exclusive)).
38 /// let array = [0, 1, 2, 3, 4];
40 /// for i in num_iter::range(0, 5) {
41 /// println!("{}", i);
42 /// assert_eq!(i, array[i]);
46 pub fn range
<A
>(start
: A
, stop
: A
) -> Range
<A
>
47 where A
: Add
<A
, Output
= A
> + PartialOrd
+ Clone
+ One
49 Range{state: start, stop: stop, one: One::one()}
52 // FIXME: rust-lang/rust#10414: Unfortunate type bound
53 impl<A
> Iterator
for Range
<A
>
54 where A
: Add
<A
, Output
= A
> + PartialOrd
+ Clone
+ ToPrimitive
59 fn next(&mut self) -> Option
<A
> {
60 if self.state
< self.stop
{
61 let result
= self.state
.clone();
62 self.state
= self.state
.clone() + self.one
.clone();
70 fn size_hint(&self) -> (usize, Option
<usize>) {
71 // This first checks if the elements are representable as i64. If they aren't, try u64 (to
72 // handle cases like range(huge, huger)). We don't use usize/int because the difference of
73 // the i64/u64 might lie within their range.
74 let bound
= match self.state
.to_i64() {
76 let sz
= self.stop
.to_i64().map(|b
| b
.checked_sub(a
));
78 Some(Some(bound
)) => bound
.to_usize(),
82 None
=> match self.state
.to_u64() {
84 let sz
= self.stop
.to_u64().map(|b
| b
.checked_sub(a
));
86 Some(Some(bound
)) => bound
.to_usize(),
95 Some(b
) => (b
, Some(b
)),
96 // Standard fallback for unbounded/unrepresentable bounds
102 /// `Integer` is required to ensure the range will be the same regardless of
103 /// the direction it is consumed.
104 impl<A
> DoubleEndedIterator
for Range
<A
>
105 where A
: Integer
+ Clone
+ ToPrimitive
108 fn next_back(&mut self) -> Option
<A
> {
109 if self.stop
> self.state
{
110 self.stop
= self.stop
.clone() - self.one
.clone();
111 Some(self.stop
.clone())
118 /// An iterator over the range [start, stop]
120 pub struct RangeInclusive
<A
> {
125 /// Return an iterator over the range [start, stop]
127 pub fn range_inclusive
<A
>(start
: A
, stop
: A
) -> RangeInclusive
<A
>
128 where A
: Add
<A
, Output
= A
> + PartialOrd
+ Clone
+ One
130 RangeInclusive{range: range(start, stop), done: false}
133 impl<A
> Iterator
for RangeInclusive
<A
>
134 where A
: Add
<A
, Output
= A
> + PartialOrd
+ Clone
+ ToPrimitive
139 fn next(&mut self) -> Option
<A
> {
140 match self.range
.next() {
143 if !self.done
&& self.range
.state
== self.range
.stop
{
145 Some(self.range
.stop
.clone())
154 fn size_hint(&self) -> (usize, Option
<usize>) {
155 let (lo
, hi
) = self.range
.size_hint();
159 let lo
= lo
.saturating_add(1);
161 Some(x
) => x
.checked_add(1),
169 impl<A
> DoubleEndedIterator
for RangeInclusive
<A
>
170 where A
: Sub
<A
, Output
= A
> + Integer
+ Clone
+ ToPrimitive
173 fn next_back(&mut self) -> Option
<A
> {
174 if self.range
.stop
> self.range
.state
{
175 let result
= self.range
.stop
.clone();
176 self.range
.stop
= self.range
.stop
.clone() - self.range
.one
.clone();
178 } else if !self.done
&& self.range
.state
== self.range
.stop
{
180 Some(self.range
.stop
.clone())
187 /// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
189 pub struct RangeStep
<A
> {
196 /// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
198 pub fn range_step
<A
>(start
: A
, stop
: A
, step
: A
) -> RangeStep
<A
>
199 where A
: CheckedAdd
+ PartialOrd
+ Clone
+ Zero
201 let rev
= step
< Zero
::zero();
202 RangeStep{state: start, stop: stop, step: step, rev: rev}
205 impl<A
> Iterator
for RangeStep
<A
>
206 where A
: CheckedAdd
+ PartialOrd
+ Clone
211 fn next(&mut self) -> Option
<A
> {
212 if (self.rev
&& self.state
> self.stop
) || (!self.rev
&& self.state
< self.stop
) {
213 let result
= self.state
.clone();
214 match self.state
.checked_add(&self.step
) {
215 Some(x
) => self.state
= x
,
216 None
=> self.state
= self.stop
.clone()
225 /// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
227 pub struct RangeStepInclusive
<A
> {
235 /// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
237 pub fn range_step_inclusive
<A
>(start
: A
, stop
: A
, step
: A
) -> RangeStepInclusive
<A
>
238 where A
: CheckedAdd
+ PartialOrd
+ Clone
+ Zero
240 let rev
= step
< Zero
::zero();
241 RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false}
244 impl<A
> Iterator
for RangeStepInclusive
<A
>
245 where A
: CheckedAdd
+ PartialOrd
+ Clone
+ PartialEq
250 fn next(&mut self) -> Option
<A
> {
251 if !self.done
&& ((self.rev
&& self.state
>= self.stop
) ||
252 (!self.rev
&& self.state
<= self.stop
)) {
253 let result
= self.state
.clone();
254 match self.state
.checked_add(&self.step
) {
255 Some(x
) => self.state
= x
,
256 None
=> self.done
= true
268 use std
::ops
::{Add, Mul}
;
269 use std
::cmp
::Ordering
;
270 use traits
::{One, ToPrimitive}
;
274 /// A mock type to check Range when ToPrimitive returns None
277 impl ToPrimitive
for Foo
{
278 fn to_i64(&self) -> Option
<i64> { None }
279 fn to_u64(&self) -> Option
<u64> { None }
282 impl Add
<Foo
> for Foo
{
285 fn add(self, _
: Foo
) -> Foo
{
290 impl PartialEq
for Foo
{
291 fn eq(&self, _
: &Foo
) -> bool
{
296 impl PartialOrd
for Foo
{
297 fn partial_cmp(&self, _
: &Foo
) -> Option
<Ordering
> {
303 fn clone(&self) -> Foo
{
308 impl Mul
<Foo
> for Foo
{
311 fn mul(self, _
: Foo
) -> Foo
{
322 assert
!(super::range(0, 5).collect
::<Vec
<isize>>() == vec
![0, 1, 2, 3, 4]);
323 assert
!(super::range(-10, -1).collect
::<Vec
<isize>>() ==
324 vec
![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
325 assert
!(super::range(0, 5).rev().collect
::<Vec
<isize>>() == vec
![4, 3, 2, 1, 0]);
326 assert_eq
!(super::range(200, -5).count(), 0);
327 assert_eq
!(super::range(200, -5).rev().count(), 0);
328 assert_eq
!(super::range(200, 200).count(), 0);
329 assert_eq
!(super::range(200, 200).rev().count(), 0);
331 assert_eq
!(super::range(0, 100).size_hint(), (100, Some(100)));
332 // this test is only meaningful when sizeof usize < sizeof u64
333 assert_eq
!(super::range(usize::MAX
- 1, usize::MAX
).size_hint(), (1, Some(1)));
334 assert_eq
!(super::range(-10, -1).size_hint(), (9, Some(9)));
338 fn test_range_inclusive() {
339 assert
!(super::range_inclusive(0, 5).collect
::<Vec
<isize>>() ==
340 vec
![0, 1, 2, 3, 4, 5]);
341 assert
!(super::range_inclusive(0, 5).rev().collect
::<Vec
<isize>>() ==
342 vec
![5, 4, 3, 2, 1, 0]);
343 assert_eq
!(super::range_inclusive(200, -5).count(), 0);
344 assert_eq
!(super::range_inclusive(200, -5).rev().count(), 0);
345 assert
!(super::range_inclusive(200, 200).collect
::<Vec
<isize>>() == vec
![200]);
346 assert
!(super::range_inclusive(200, 200).rev().collect
::<Vec
<isize>>() == vec
![200]);
350 fn test_range_step() {
351 assert
!(super::range_step(0, 20, 5).collect
::<Vec
<isize>>() ==
353 assert
!(super::range_step(20, 0, -5).collect
::<Vec
<isize>>() ==
354 vec
![20, 15, 10, 5]);
355 assert
!(super::range_step(20, 0, -6).collect
::<Vec
<isize>>() ==
357 assert
!(super::range_step(200u8, 255, 50).collect
::<Vec
<u8>>() ==
359 assert
!(super::range_step(200, -5, 1).collect
::<Vec
<isize>>() == vec
![]);
360 assert
!(super::range_step(200, 200, 1).collect
::<Vec
<isize>>() == vec
![]);
364 fn test_range_step_inclusive() {
365 assert
!(super::range_step_inclusive(0, 20, 5).collect
::<Vec
<isize>>() ==
366 vec
![0, 5, 10, 15, 20]);
367 assert
!(super::range_step_inclusive(20, 0, -5).collect
::<Vec
<isize>>() ==
368 vec
![20, 15, 10, 5, 0]);
369 assert
!(super::range_step_inclusive(20, 0, -6).collect
::<Vec
<isize>>() ==
371 assert
!(super::range_step_inclusive(200u8, 255, 50).collect
::<Vec
<u8>>() ==
373 assert
!(super::range_step_inclusive(200, -5, 1).collect
::<Vec
<isize>>() ==
375 assert
!(super::range_step_inclusive(200, 200, 1).collect
::<Vec
<isize>>() ==