Skip to content

Commit b613749

Browse files
committed
seq module: make gen_range usage stable across platforms
1 parent fb7bb9f commit b613749

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

src/seq/mod.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,13 @@ pub trait IteratorRandom: Iterator + Sized {
200200
let mut result = None;
201201

202202
if upper == Some(lower) {
203-
return if lower == 0 { None } else { self.nth(rng.gen_range(0, lower)) };
203+
return if lower == 0 { None } else { self.nth(gen_index(rng, lower)) };
204204
}
205205

206206
// Continue until the iterator is exhausted
207207
loop {
208208
if lower > 1 {
209-
let ix = rng.gen_range(0, lower + consumed);
209+
let ix = gen_index(rng, lower + consumed);
210210
let skip;
211211
if ix < lower {
212212
result = self.nth(ix);
@@ -267,7 +267,7 @@ pub trait IteratorRandom: Iterator + Sized {
267267

268268
// Continue, since the iterator was not exhausted
269269
for (i, elem) in self.enumerate() {
270-
let k = rng.gen_range(0, i + 1 + amount);
270+
let k = gen_index(rng, i + 1 + amount);
271271
if let Some(slot) = buf.get_mut(k) {
272272
*slot = elem;
273273
}
@@ -300,7 +300,7 @@ pub trait IteratorRandom: Iterator + Sized {
300300
// If the iterator stops once, then so do we.
301301
if reservoir.len() == amount {
302302
for (i, elem) in self.enumerate() {
303-
let k = rng.gen_range(0, i + 1 + amount);
303+
let k = gen_index(rng, i + 1 + amount);
304304
if let Some(slot) = reservoir.get_mut(k) {
305305
*slot = elem;
306306
}
@@ -323,7 +323,7 @@ impl<T> SliceRandom for [T] {
323323
if self.is_empty() {
324324
None
325325
} else {
326-
Some(&self[rng.gen_range(0, self.len())])
326+
Some(&self[gen_index(rng, self.len())])
327327
}
328328
}
329329

@@ -333,7 +333,7 @@ impl<T> SliceRandom for [T] {
333333
None
334334
} else {
335335
let len = self.len();
336-
Some(&mut self[rng.gen_range(0, len)])
336+
Some(&mut self[gen_index(rng, len)])
337337
}
338338
}
339339

@@ -390,7 +390,7 @@ impl<T> SliceRandom for [T] {
390390
where R: Rng + ?Sized {
391391
for i in (1..self.len()).rev() {
392392
// invariant: elements with index > i have been locked in place.
393-
self.swap(i, rng.gen_range(0, i + 1));
393+
self.swap(i, gen_index(rng, i + 1));
394394
}
395395
}
396396

@@ -408,7 +408,7 @@ impl<T> SliceRandom for [T] {
408408

409409
for i in (end..len).rev() {
410410
// invariant: elements with index > i have been locked in place.
411-
self.swap(i, rng.gen_range(0, i + 1));
411+
self.swap(i, gen_index(rng, i + 1));
412412
}
413413
let r = self.split_at_mut(end);
414414
(r.1, r.0)
@@ -451,6 +451,19 @@ impl<'a, S: Index<usize, Output = T> + ?Sized + 'a, T: 'a> ExactSizeIterator
451451
}
452452

453453

454+
// Sample a number uniformly between 0 and `ubound`. Uses 32-bit sampling where
455+
// possible, primarily in order to produce the same output on 32-bit and 64-bit
456+
// platforms.
457+
#[inline]
458+
fn gen_index<R: Rng + ?Sized>(rng: &mut R, ubound: usize) -> usize {
459+
if ubound <= (core::u32::MAX as usize) {
460+
rng.gen_range(0, ubound as u32) as usize
461+
} else {
462+
rng.gen_range(0, ubound)
463+
}
464+
}
465+
466+
454467
#[cfg(test)]
455468
mod test {
456469
use super::*;

0 commit comments

Comments
 (0)