Skip to content

Commit

Permalink
Revert "Remove approximation that is now slower than accurate calcula…
Browse files Browse the repository at this point in the history
…tion"

This reverts commit 856ad28.
  • Loading branch information
jongiddy committed Jun 9, 2020
1 parent ae79ebe commit ca0f9c6
Showing 1 changed file with 13 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/distributions/uniform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ where Borrowed: SampleUniform
///
/// For simplicity, we use the same generic struct `UniformInt<X>` for all
/// integer types `X`. This gives us only one field type, `X`; to store unsigned
/// values of this size, we use the fact that these conversions are no-ops.
/// values of this size, we take use the fact that these conversions are no-ops.
///
/// For a closed range, the number of possible numbers we should generate is
/// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of
Expand Down Expand Up @@ -438,9 +438,18 @@ macro_rules! uniform_int_impl {
let high = *high_b.borrow();
assert!(low < high, "UniformSampler::sample_single: low >= high");
let range = high.wrapping_sub(low) as $unsigned as $u_large;
let unsigned_max = ::core::$u_large::MAX;
let ints_to_reject = (unsigned_max - range + 1) % range;
let zone = unsigned_max - ints_to_reject;
let zone = if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned {
// Using a modulus is faster than the approximation for
// i8 and i16. I suppose we trade the cost of one
// modulus for near-perfect branch prediction.
let unsigned_max: $u_large = ::core::$u_large::MAX;
let ints_to_reject = (unsigned_max - range + 1) % range;
unsigned_max - ints_to_reject
} else {
// conservative but fast approximation. `- 1` is necessary to allow the
// same comparison without bias.
(range << range.leading_zeros()).wrapping_sub(1)
};

loop {
let v: $u_large = rng.gen();
Expand Down

0 comments on commit ca0f9c6

Please sign in to comment.