|
|
|
@ -20,6 +20,40 @@ pub fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T {
|
|
|
|
|
t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Generates a random number in `0..n`.
|
|
|
|
|
#[cfg(feature = "unstable")]
|
|
|
|
|
pub fn random(n: u32) -> u32 {
|
|
|
|
|
use std::cell::Cell;
|
|
|
|
|
use std::num::Wrapping;
|
|
|
|
|
|
|
|
|
|
thread_local! {
|
|
|
|
|
static RNG: Cell<Wrapping<u32>> = {
|
|
|
|
|
// Take the address of a local value as seed.
|
|
|
|
|
let mut x = 0i32;
|
|
|
|
|
let r = &mut x;
|
|
|
|
|
let addr = r as *mut i32 as usize;
|
|
|
|
|
Cell::new(Wrapping(addr as u32))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RNG.with(|rng| {
|
|
|
|
|
// This is the 32-bit variant of Xorshift.
|
|
|
|
|
//
|
|
|
|
|
// Source: https://en.wikipedia.org/wiki/Xorshift
|
|
|
|
|
let mut x = rng.get();
|
|
|
|
|
x ^= x << 13;
|
|
|
|
|
x ^= x >> 17;
|
|
|
|
|
x ^= x << 5;
|
|
|
|
|
rng.set(x);
|
|
|
|
|
|
|
|
|
|
// This is a fast alternative to `x % n`.
|
|
|
|
|
//
|
|
|
|
|
// Author: Daniel Lemire
|
|
|
|
|
// Source: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
|
|
|
|
((u64::from(x.0)).wrapping_mul(u64::from(n)) >> 32) as u32
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Add additional context to errors
|
|
|
|
|
pub(crate) trait Context {
|
|
|
|
|
fn context(self, message: impl Fn() -> String) -> Self;
|
|
|
|
|