auto merge of #5769 : gifnksm/rust/range_step, r=bstrie
`uint::range_step` or `int::range_step` causes overflow or underflow as following. code: ```rust fn main() { for uint::range_step(3, 0, -2) |n| { println(fmt!("%u", n)); } } ``` output: ``` 3 1 18446744073709551615 18446744073709551613 ... ``` This commit fixes this behavior as follows. ``` 3 1 ```
This commit is contained in:
commit
412a07055c
2 changed files with 49 additions and 10 deletions
|
@ -107,11 +107,15 @@ pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) {
|
||||||
} else if step > 0 { // ascending
|
} else if step > 0 { // ascending
|
||||||
while i < stop {
|
while i < stop {
|
||||||
if !it(i) { break }
|
if !it(i) { break }
|
||||||
|
// avoiding overflow. break if i + step > max_value
|
||||||
|
if i > max_value - step { break; }
|
||||||
i += step;
|
i += step;
|
||||||
}
|
}
|
||||||
} else { // descending
|
} else { // descending
|
||||||
while i > stop {
|
while i > stop {
|
||||||
if !it(i) { break }
|
if !it(i) { break }
|
||||||
|
// avoiding underflow. break if i + step < min_value
|
||||||
|
if i < min_value - step { break; }
|
||||||
i += step;
|
i += step;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,10 +425,26 @@ pub fn test_ranges() {
|
||||||
for range_step(36,30,-2) |i| {
|
for range_step(36,30,-2) |i| {
|
||||||
l.push(i);
|
l.push(i);
|
||||||
}
|
}
|
||||||
assert!(l == ~[0,1,2,
|
for range_step(max_value - 2, max_value, 2) |i| {
|
||||||
13,12,11,
|
l.push(i);
|
||||||
20,22,24,
|
}
|
||||||
36,34,32]);
|
for range_step(max_value - 3, max_value, 2) |i| {
|
||||||
|
l.push(i);
|
||||||
|
}
|
||||||
|
for range_step(min_value + 2, min_value, -2) |i| {
|
||||||
|
l.push(i);
|
||||||
|
}
|
||||||
|
for range_step(min_value + 3, min_value, -2) |i| {
|
||||||
|
l.push(i);
|
||||||
|
}
|
||||||
|
assert_eq!(l, ~[0,1,2,
|
||||||
|
13,12,11,
|
||||||
|
20,22,24,
|
||||||
|
36,34,32,
|
||||||
|
max_value-2,
|
||||||
|
max_value-3,max_value-1,
|
||||||
|
min_value+2,
|
||||||
|
min_value+3,min_value+1]);
|
||||||
|
|
||||||
// None of the `fail`s should execute.
|
// None of the `fail`s should execute.
|
||||||
for range(10,0) |_i| {
|
for range(10,0) |_i| {
|
||||||
|
|
|
@ -78,12 +78,15 @@ pub fn range_step(start: T,
|
||||||
if step >= 0 {
|
if step >= 0 {
|
||||||
while i < stop {
|
while i < stop {
|
||||||
if !it(i) { break }
|
if !it(i) { break }
|
||||||
|
// avoiding overflow. break if i + step > max_value
|
||||||
|
if i > max_value - (step as T) { break; }
|
||||||
i += step as T;
|
i += step as T;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
while i > stop {
|
while i > stop {
|
||||||
if !it(i) { break }
|
if !it(i) { break }
|
||||||
|
// avoiding underflow. break if i + step < min_value
|
||||||
|
if i < min_value + ((-step) as T) { break; }
|
||||||
i -= -step as T;
|
i -= -step as T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,11 +374,27 @@ pub fn test_ranges() {
|
||||||
for range_step(36,30,-2) |i| {
|
for range_step(36,30,-2) |i| {
|
||||||
l.push(i);
|
l.push(i);
|
||||||
}
|
}
|
||||||
|
for range_step(max_value - 2, max_value, 2) |i| {
|
||||||
|
l.push(i);
|
||||||
|
}
|
||||||
|
for range_step(max_value - 3, max_value, 2) |i| {
|
||||||
|
l.push(i);
|
||||||
|
}
|
||||||
|
for range_step(min_value + 2, min_value, -2) |i| {
|
||||||
|
l.push(i);
|
||||||
|
}
|
||||||
|
for range_step(min_value + 3, min_value, -2) |i| {
|
||||||
|
l.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
assert!(l == ~[0,1,2,
|
assert_eq!(l, ~[0,1,2,
|
||||||
13,12,11,
|
13,12,11,
|
||||||
20,22,24,
|
20,22,24,
|
||||||
36,34,32]);
|
36,34,32,
|
||||||
|
max_value-2,
|
||||||
|
max_value-3,max_value-1,
|
||||||
|
min_value+2,
|
||||||
|
min_value+3,min_value+1]);
|
||||||
|
|
||||||
// None of the `fail`s should execute.
|
// None of the `fail`s should execute.
|
||||||
for range(0,0) |_i| {
|
for range(0,0) |_i| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue