Skip to content

Commit 2e58cfb

Browse files
authored
Merge pull request #13 from SenseLabsDE/fix-overflow
Fix overflow when using large raster sizes
2 parents 08c1d83 + 3dc78d4 commit 2e58cfb

File tree

5 files changed

+58
-53
lines changed

5 files changed

+58
-53
lines changed

benches/bench.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ fn bench_contourbuilder_isobands_volcano_without_xy_step_xy_origin(b: &mut Bench
9090
.iter()
9191
.map(|x| x.as_f64().unwrap())
9292
.collect();
93-
let h = raw_data["height"].as_u64().unwrap() as u32;
94-
let w = raw_data["width"].as_u64().unwrap() as u32;
93+
let h = raw_data["height"].as_u64().unwrap() as usize;
94+
let w = raw_data["width"].as_u64().unwrap() as usize;
9595

9696
b.iter(|| {
9797
black_box(
@@ -118,8 +118,8 @@ fn bench_contourbuilder_isobands_pot_pop_fr_without_xy_step_xy_origin(b: &mut Be
118118
.iter()
119119
.map(|x| x.as_f64().unwrap())
120120
.collect();
121-
let h = raw_data["height"].as_u64().unwrap() as u32;
122-
let w = raw_data["width"].as_u64().unwrap() as u32;
121+
let h = raw_data["height"].as_u64().unwrap() as usize;
122+
let w = raw_data["width"].as_u64().unwrap() as usize;
123123

124124
b.iter(|| {
125125
black_box(

examples/ex.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ fn main() {
2121
}
2222
})
2323
.collect();
24-
let h = raw_data["height"].as_u64().unwrap() as u32;
25-
let w = raw_data["width"].as_u64().unwrap() as u32;
24+
let h = raw_data["height"].as_u64().unwrap() as usize;
25+
let w = raw_data["width"].as_u64().unwrap() as usize;
2626

2727
let x_origin = -6.144721171428571;
2828
let y_origin = 51.78171334283718;
@@ -75,8 +75,8 @@ fn main() {
7575
}
7676
})
7777
.collect();
78-
let h = raw_data["height"].as_u64().unwrap() as u32;
79-
let w = raw_data["width"].as_u64().unwrap() as u32;
78+
let h = raw_data["height"].as_u64().unwrap() as usize;
79+
let w = raw_data["width"].as_u64().unwrap() as usize;
8080

8181
let contours = ContourBuilder::new(w, h, true)
8282
.isobands(

src/area.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
use crate::{Float, Pt};
22

3-
pub fn area(ring: &[Pt]) -> Float {
3+
#[allow(clippy::unnecessary_cast)]
4+
// Note that we need to disable the clippy warning about unnecessary casts
5+
// because of the "f32" optional feature (and because we want to ensure we always
6+
// use "f64" in this function, both in the default feature and in the "f32" feature).
7+
pub fn area(ring: &[Pt]) -> f64 {
48
let n = ring.len();
5-
let mut area = ring[n - 1].y * ring[0].x - ring[n - 1].x * ring[0].y;
9+
let mut area =
10+
ring[n - 1].y as f64 * ring[0].x as f64 - ring[n - 1].x as f64 * ring[0].y as f64;
611
for i in 1..n {
7-
area += ring[i - 1].y * ring[i].x - ring[i - 1].x * ring[i].y;
12+
area += ring[i - 1].y as f64 * ring[i].x as f64 - ring[i - 1].x as f64 * ring[i].y as f64;
813
}
914
// Note that in the shoelace formula you need to divide this result by 2 to get the actual area.
1015
// Here we skip this division because we only use this area formula to calculate the winding

src/contourbuilder.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use rustc_hash::FxHashMap;
1212
/// [`contour_rings`]: fn.contour_rings.html
1313
pub struct ContourBuilder {
1414
/// The number of columns in the grid
15-
dx: u32,
15+
dx: usize,
1616
/// The number of rows in the grid
17-
dy: u32,
17+
dy: usize,
1818
/// Whether to smooth the contours
1919
smooth: bool,
2020
/// The horizontal coordinate for the origin of the grid.
@@ -38,7 +38,7 @@ impl ContourBuilder {
3838
/// * `dx` - The number of columns in the grid.
3939
/// * `dy` - The number of rows in the grid.
4040
/// * `smooth` - Whether or not the generated rings will be smoothed using linear interpolation.
41-
pub fn new(dx: u32, dy: u32, smooth: bool) -> Self {
41+
pub fn new(dx: usize, dy: usize, smooth: bool) -> Self {
4242
ContourBuilder {
4343
dx,
4444
dy,
@@ -83,18 +83,18 @@ impl ContourBuilder {
8383
.map(|point| {
8484
let x = point.x;
8585
let y = point.y;
86-
let xt = x.trunc() as u32;
87-
let yt = y.trunc() as u32;
86+
let xt = x.trunc() as usize;
87+
let yt = y.trunc() as usize;
8888
let mut v0;
89-
let ix = (yt * dx + xt) as usize;
89+
let ix = yt * dx + xt;
9090
if ix < len_values {
9191
let v1 = values[ix];
9292
if x > 0.0 && x < (dx as Float) && (xt as Float - x).abs() < Float::EPSILON {
93-
v0 = values[(yt * dx + xt - 1) as usize];
93+
v0 = values[yt * dx + xt - 1];
9494
point.x = x + (value - v0) / (v1 - v0) - 0.5;
9595
}
9696
if y > 0.0 && y < (dy as Float) && (yt as Float - y).abs() < Float::EPSILON {
97-
v0 = values[((yt - 1) * dx + xt) as usize];
97+
v0 = values[(yt - 1) * dx + xt];
9898
point.y = y + (value - v0) / (v1 - v0) - 0.5;
9999
}
100100
}
@@ -112,7 +112,7 @@ impl ContourBuilder {
112112
/// * `values` - The slice of values to be used.
113113
/// * `thresholds` - The slice of thresholds values to be used.
114114
pub fn lines(&self, values: &[Float], thresholds: &[Float]) -> Result<Vec<Line>> {
115-
if values.len() as u32 != self.dx * self.dy {
115+
if values.len() != self.dx * self.dy {
116116
return Err(new_error(ErrorKind::BadDimension));
117117
}
118118
let mut isoring = IsoRingBuilder::new(self.dx, self.dy);
@@ -163,7 +163,7 @@ impl ContourBuilder {
163163
/// * `values` - The slice of values to be used.
164164
/// * `thresholds` - The slice of thresholds values to be used.
165165
pub fn contours(&self, values: &[Float], thresholds: &[Float]) -> Result<Vec<Contour>> {
166-
if values.len() as u32 != self.dx * self.dy {
166+
if values.len() != self.dx * self.dy {
167167
return Err(new_error(ErrorKind::BadDimension));
168168
}
169169
let mut isoring = IsoRingBuilder::new(self.dx, self.dy);
@@ -232,7 +232,7 @@ impl ContourBuilder {
232232
// We will compute rings as previously, but we will
233233
// iterate over the contours in pairs and use the paths from the lower threshold
234234
// and the path from the upper threshold to create the isoband.
235-
if values.len() as u32 != self.dx * self.dy {
235+
if values.len() != self.dx * self.dy {
236236
return Err(new_error(ErrorKind::BadDimension));
237237
}
238238
if thresholds.len() < 2 {

src/isoringbuilder.rs

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ struct Fragment {
4949
/// * `threshold` - The threshold value.
5050
/// * `dx` - The number of columns in the grid.
5151
/// * `dy` - The number of rows in the grid.
52-
pub fn contour_rings(values: &[Float], threshold: Float, dx: u32, dy: u32) -> Result<Vec<Ring>> {
52+
pub fn contour_rings(
53+
values: &[Float],
54+
threshold: Float,
55+
dx: usize,
56+
dy: usize,
57+
) -> Result<Vec<Ring>> {
5358
let mut isoring = IsoRingBuilder::new(dx, dy);
5459
isoring.compute(values, threshold)
5560
}
@@ -59,8 +64,8 @@ pub struct IsoRingBuilder {
5964
fragment_by_start: FxHashMap<usize, usize>,
6065
fragment_by_end: FxHashMap<usize, usize>,
6166
f: Slab<Fragment>,
62-
dx: u32,
63-
dy: u32,
67+
dx: usize,
68+
dy: usize,
6469
is_empty: bool,
6570
}
6671

@@ -70,7 +75,7 @@ impl IsoRingBuilder {
7075
///
7176
/// * `dx` - The number of columns in the grid.
7277
/// * `dy` - The number of rows in the grid.
73-
pub fn new(dx: u32, dy: u32) -> Self {
78+
pub fn new(dx: usize, dy: usize) -> Self {
7479
IsoRingBuilder {
7580
fragment_by_start: FxHashMap::default(),
7681
fragment_by_end: FxHashMap::default(),
@@ -103,8 +108,8 @@ impl IsoRingBuilder {
103108
self.clear();
104109
}
105110
let mut result = Vec::new();
106-
let dx = self.dx as i32;
107-
let dy = self.dy as i32;
111+
let dx = self.dx as i64;
112+
let dy = self.dy as i64;
108113
let mut x = -1;
109114
let mut y = -1;
110115
let mut t0;
@@ -113,68 +118,63 @@ impl IsoRingBuilder {
113118
let mut t3;
114119

115120
// Special case for the first row (y = -1, t2 = t3 = 0).
116-
t1 = (values[0] >= threshold) as u32;
117-
case_stitch!((t1 << 1) as usize, x, y, &mut result);
121+
t1 = (values[0] >= threshold) as usize;
122+
case_stitch!(t1 << 1, x, y, &mut result);
118123
x += 1;
119124
while x < dx - 1 {
120125
t0 = t1;
121-
t1 = (values[(x + 1) as usize] >= threshold) as u32;
122-
case_stitch!((t0 | t1 << 1) as usize, x, y, &mut result);
126+
t1 = (values[(x + 1) as usize] >= threshold) as usize;
127+
case_stitch!(t0 | t1 << 1, x, y, &mut result);
123128
x += 1;
124129
}
125-
case_stitch!(t1 as usize, x, y, &mut result);
130+
case_stitch!(t1, x, y, &mut result);
126131

127132
// General case for the intermediate rows.
128133
y += 1;
129134
while y < dy - 1 {
130135
x = -1;
131-
t1 = (values[(y * dx + dx) as usize] >= threshold) as u32;
132-
t2 = (values[(y * dx) as usize] >= threshold) as u32;
133-
case_stitch!((t1 << 1 | t2 << 2) as usize, x, y, &mut result);
136+
t1 = (values[(y * dx + dx) as usize] >= threshold) as usize;
137+
t2 = (values[(y * dx) as usize] >= threshold) as usize;
138+
case_stitch!(t1 << 1 | t2 << 2, x, y, &mut result);
134139
x += 1;
135140
while x < dx - 1 {
136141
t0 = t1;
137-
t1 = (values[(y * dx + dx + x + 1) as usize] >= threshold) as u32;
142+
t1 = (values[(y * dx + dx + x + 1) as usize] >= threshold) as usize;
138143
t3 = t2;
139-
t2 = (values[(y * dx + x + 1) as usize] >= threshold) as u32;
140-
case_stitch!(
141-
(t0 | t1 << 1 | t2 << 2 | t3 << 3) as usize,
142-
x,
143-
y,
144-
&mut result
145-
);
144+
t2 = (values[(y * dx + x + 1) as usize] >= threshold) as usize;
145+
case_stitch!(t0 | t1 << 1 | t2 << 2 | t3 << 3, x, y, &mut result);
146146
x += 1;
147147
}
148-
case_stitch!((t1 | t2 << 3) as usize, x, y, &mut result);
148+
case_stitch!(t1 | t2 << 3, x, y, &mut result);
149149
y += 1;
150150
}
151151

152152
// Special case for the last row (y = dy - 1, t0 = t1 = 0).
153153
x = -1;
154-
t2 = (values[(y * dx) as usize] >= threshold) as u32;
155-
case_stitch!((t2 << 2) as usize, x, y, &mut result);
154+
t2 = (values[(y * dx) as usize] >= threshold) as usize;
155+
case_stitch!(t2 << 2, x, y, &mut result);
156156
x += 1;
157157
while x < dx - 1 {
158158
t3 = t2;
159-
t2 = (values[(y * dx + x + 1) as usize] >= threshold) as u32;
160-
case_stitch!((t2 << 2 | t3 << 3) as usize, x, y, &mut result);
159+
t2 = (values[(y * dx + x + 1) as usize] >= threshold) as usize;
160+
case_stitch!(t2 << 2 | t3 << 3, x, y, &mut result);
161161
x += 1;
162162
}
163-
case_stitch!((t2 << 3) as usize, x, y, &mut result);
163+
case_stitch!(t2 << 3, x, y, &mut result);
164164
self.is_empty = false;
165165
Ok(result)
166166
}
167167

168168
fn index(&self, point: &Pt) -> usize {
169-
(point.x * 2.0 + point.y * (self.dx as Float + 1.) * 4.) as usize
169+
(point.x as usize) * 2 + (point.y as usize) * (self.dx + 1usize) * 4
170170
}
171171

172172
// Stitchs segments to rings.
173173
fn stitch(
174174
&mut self,
175175
line: &[Vec<Float>],
176-
x: i32,
177-
y: i32,
176+
x: i64,
177+
y: i64,
178178
result: &mut Vec<Ring>,
179179
) -> Result<()> {
180180
let start = Pt {

0 commit comments

Comments
 (0)