rustfmt src/librand
This commit is contained in:
parent
747d951e88
commit
76b69e365b
@ -27,15 +27,15 @@ const CHACHA_ROUNDS: usize = 20; // Cryptographically secure from 8 upwards as o
|
||||
/// Salsa20*](http://cr.yp.to/chacha.html)
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ChaChaRng {
|
||||
buffer: [u32; STATE_WORDS], // Internal buffer of output
|
||||
state: [u32; STATE_WORDS], // Initial state
|
||||
index: usize, // Index into state
|
||||
buffer: [u32; STATE_WORDS], // Internal buffer of output
|
||||
state: [u32; STATE_WORDS], // Initial state
|
||||
index: usize, // Index into state
|
||||
}
|
||||
|
||||
static EMPTY: ChaChaRng = ChaChaRng {
|
||||
buffer: [0; STATE_WORDS],
|
||||
state: [0; STATE_WORDS],
|
||||
index: STATE_WORDS
|
||||
buffer: [0; STATE_WORDS],
|
||||
state: [0; STATE_WORDS],
|
||||
index: STATE_WORDS,
|
||||
};
|
||||
|
||||
|
||||
@ -95,9 +95,9 @@ impl ChaChaRng {
|
||||
/// associated with a particular nonce can call this function with
|
||||
/// arguments `0, desired_nonce`.
|
||||
pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
|
||||
self.state[12] = (counter_low >> 0) as u32;
|
||||
self.state[12] = (counter_low >> 0) as u32;
|
||||
self.state[13] = (counter_low >> 32) as u32;
|
||||
self.state[14] = (counter_high >> 0) as u32;
|
||||
self.state[14] = (counter_high >> 0) as u32;
|
||||
self.state[15] = (counter_high >> 32) as u32;
|
||||
self.index = STATE_WORDS; // force recomputation
|
||||
}
|
||||
@ -127,7 +127,7 @@ impl ChaChaRng {
|
||||
self.state[3] = 0x6B206574;
|
||||
|
||||
for i in 0..KEY_WORDS {
|
||||
self.state[4+i] = key[i];
|
||||
self.state[4 + i] = key[i];
|
||||
}
|
||||
|
||||
self.state[12] = 0;
|
||||
@ -144,11 +144,17 @@ impl ChaChaRng {
|
||||
self.index = 0;
|
||||
// update 128-bit counter
|
||||
self.state[12] += 1;
|
||||
if self.state[12] != 0 { return };
|
||||
if self.state[12] != 0 {
|
||||
return;
|
||||
}
|
||||
self.state[13] += 1;
|
||||
if self.state[13] != 0 { return };
|
||||
if self.state[13] != 0 {
|
||||
return;
|
||||
}
|
||||
self.state[14] += 1;
|
||||
if self.state[14] != 0 { return };
|
||||
if self.state[14] != 0 {
|
||||
return;
|
||||
}
|
||||
self.state[15] += 1;
|
||||
}
|
||||
}
|
||||
@ -172,7 +178,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
|
||||
// reset state
|
||||
self.init(&[0; KEY_WORDS]);
|
||||
// set key in place
|
||||
let key = &mut self.state[4 .. 4+KEY_WORDS];
|
||||
let key = &mut self.state[4..4 + KEY_WORDS];
|
||||
for (k, s) in key.iter_mut().zip(seed) {
|
||||
*k = *s;
|
||||
}
|
||||
@ -191,7 +197,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
|
||||
|
||||
impl Rand for ChaChaRng {
|
||||
fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
|
||||
let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS];
|
||||
let mut key: [u32; KEY_WORDS] = [0; KEY_WORDS];
|
||||
for word in &mut key {
|
||||
*word = other.gen();
|
||||
}
|
||||
@ -219,7 +225,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rng_seeded() {
|
||||
let seed : &[_] = &[0,1,2,3,4,5,6,7];
|
||||
let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
|
||||
let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
|
||||
let mut rb: ChaChaRng = SeedableRng::from_seed(seed);
|
||||
assert!(order::equals(ra.gen_ascii_chars().take(100),
|
||||
@ -242,30 +248,54 @@ mod tests {
|
||||
fn test_rng_true_values() {
|
||||
// Test vectors 1 and 2 from
|
||||
// http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
|
||||
let seed : &[_] = &[0; 8];
|
||||
let seed: &[_] = &[0; 8];
|
||||
let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
|
||||
|
||||
let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
|
||||
assert_eq!(v,
|
||||
vec!(0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653,
|
||||
0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b,
|
||||
0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8,
|
||||
0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2));
|
||||
vec!(0xade0b876,
|
||||
0x903df1a0,
|
||||
0xe56a5d40,
|
||||
0x28bd8653,
|
||||
0xb819d2bd,
|
||||
0x1aed8da0,
|
||||
0xccef36a8,
|
||||
0xc70d778b,
|
||||
0x7c5941da,
|
||||
0x8d485751,
|
||||
0x3fe02477,
|
||||
0x374ad8b8,
|
||||
0xf4b8436a,
|
||||
0x1ca11815,
|
||||
0x69b687c3,
|
||||
0x8665eeb2));
|
||||
|
||||
let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
|
||||
assert_eq!(v,
|
||||
vec!(0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73,
|
||||
0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32,
|
||||
0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874,
|
||||
0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b));
|
||||
vec!(0xbee7079f,
|
||||
0x7a385155,
|
||||
0x7c97ba98,
|
||||
0x0d082d73,
|
||||
0xa0290fcb,
|
||||
0x6965e348,
|
||||
0x3e53c612,
|
||||
0xed7aee32,
|
||||
0x7621b729,
|
||||
0x434ee69c,
|
||||
0xb03371d5,
|
||||
0xd539d874,
|
||||
0x281fed31,
|
||||
0x45fb0a51,
|
||||
0x1f0ae1ac,
|
||||
0x6f4d794b));
|
||||
|
||||
|
||||
let seed : &[_] = &[0,1,2,3,4,5,6,7];
|
||||
let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
|
||||
let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
|
||||
|
||||
// Store the 17*i-th 32-bit word,
|
||||
// i.e., the i-th word of the i-th 16-word block
|
||||
let mut v : Vec<u32> = Vec::new();
|
||||
let mut v: Vec<u32> = Vec::new();
|
||||
for _ in 0..16 {
|
||||
v.push(ra.next_u32());
|
||||
for _ in 0..16 {
|
||||
@ -274,15 +304,27 @@ mod tests {
|
||||
}
|
||||
|
||||
assert_eq!(v,
|
||||
vec!(0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036,
|
||||
0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384,
|
||||
0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
|
||||
0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4));
|
||||
vec!(0xf225c81a,
|
||||
0x6ab1be57,
|
||||
0x04d42951,
|
||||
0x70858036,
|
||||
0x49884684,
|
||||
0x64efec72,
|
||||
0x4be2d186,
|
||||
0x3615b384,
|
||||
0x11cfa18e,
|
||||
0xd3c50049,
|
||||
0x75c775f6,
|
||||
0x434c6530,
|
||||
0x2c5bad8f,
|
||||
0x898881dc,
|
||||
0x5f1c86d9,
|
||||
0xc1f8e7f4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rng_clone() {
|
||||
let seed : &[_] = &[0; 8];
|
||||
let seed: &[_] = &[0; 8];
|
||||
let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
|
||||
let mut clone = rng.clone();
|
||||
for _ in 0..16 {
|
||||
|
@ -35,20 +35,22 @@ pub struct Exp1(pub f64);
|
||||
// This could be done via `-rng.gen::<f64>().ln()` but that is slower.
|
||||
impl Rand for Exp1 {
|
||||
#[inline]
|
||||
fn rand<R:Rng>(rng: &mut R) -> Exp1 {
|
||||
fn rand<R: Rng>(rng: &mut R) -> Exp1 {
|
||||
#[inline]
|
||||
fn pdf(x: f64) -> f64 {
|
||||
(-x).exp()
|
||||
}
|
||||
#[inline]
|
||||
fn zero_case<R:Rng>(rng: &mut R, _u: f64) -> f64 {
|
||||
fn zero_case<R: Rng>(rng: &mut R, _u: f64) -> f64 {
|
||||
ziggurat_tables::ZIG_EXP_R - rng.gen::<f64>().ln()
|
||||
}
|
||||
|
||||
Exp1(ziggurat(rng, false,
|
||||
Exp1(ziggurat(rng,
|
||||
false,
|
||||
&ziggurat_tables::ZIG_EXP_X,
|
||||
&ziggurat_tables::ZIG_EXP_F,
|
||||
pdf, zero_case))
|
||||
pdf,
|
||||
zero_case))
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +61,7 @@ impl Rand for Exp1 {
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Exp {
|
||||
/// `lambda` stored as `1/lambda`, since this is what we scale by.
|
||||
lambda_inverse: f64
|
||||
lambda_inverse: f64,
|
||||
}
|
||||
|
||||
impl Exp {
|
||||
@ -72,7 +74,9 @@ impl Exp {
|
||||
}
|
||||
|
||||
impl Sample<f64> for Exp {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
impl IndependentSample<f64> for Exp {
|
||||
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
|
||||
|
@ -46,7 +46,7 @@ pub struct Gamma {
|
||||
enum GammaRepr {
|
||||
Large(GammaLargeShape),
|
||||
One(Exp),
|
||||
Small(GammaSmallShape)
|
||||
Small(GammaSmallShape),
|
||||
}
|
||||
|
||||
// These two helpers could be made public, but saving the
|
||||
@ -65,7 +65,7 @@ enum GammaRepr {
|
||||
/// shape parameters.
|
||||
struct GammaSmallShape {
|
||||
inv_shape: f64,
|
||||
large_shape: GammaLargeShape
|
||||
large_shape: GammaLargeShape,
|
||||
}
|
||||
|
||||
/// Gamma distribution where the shape parameter is larger than 1.
|
||||
@ -75,7 +75,7 @@ struct GammaSmallShape {
|
||||
struct GammaLargeShape {
|
||||
scale: f64,
|
||||
c: f64,
|
||||
d: f64
|
||||
d: f64,
|
||||
}
|
||||
|
||||
impl Gamma {
|
||||
@ -88,9 +88,9 @@ impl Gamma {
|
||||
assert!(scale > 0.0, "Gamma::new called with scale <= 0");
|
||||
|
||||
let repr = match shape {
|
||||
1.0 => One(Exp::new(1.0 / scale)),
|
||||
1.0 => One(Exp::new(1.0 / scale)),
|
||||
0.0 ... 1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
|
||||
_ => Large(GammaLargeShape::new_raw(shape, scale))
|
||||
_ => Large(GammaLargeShape::new_raw(shape, scale)),
|
||||
};
|
||||
Gamma { repr: repr }
|
||||
}
|
||||
@ -100,7 +100,7 @@ impl GammaSmallShape {
|
||||
fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
|
||||
GammaSmallShape {
|
||||
inv_shape: 1. / shape,
|
||||
large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
|
||||
large_shape: GammaLargeShape::new_raw(shape + 1.0, scale),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,19 +111,25 @@ impl GammaLargeShape {
|
||||
GammaLargeShape {
|
||||
scale: scale,
|
||||
c: 1. / (9. * d).sqrt(),
|
||||
d: d
|
||||
d: d,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sample<f64> for Gamma {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
impl Sample<f64> for GammaSmallShape {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
impl Sample<f64> for GammaLargeShape {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
|
||||
impl IndependentSample<f64> for Gamma {
|
||||
@ -148,7 +154,7 @@ impl IndependentSample<f64> for GammaLargeShape {
|
||||
let StandardNormal(x) = rng.gen::<StandardNormal>();
|
||||
let v_cbrt = 1.0 + self.c * x;
|
||||
if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
let v = v_cbrt * v_cbrt * v_cbrt;
|
||||
@ -156,8 +162,8 @@ impl IndependentSample<f64> for GammaLargeShape {
|
||||
|
||||
let x_sqr = x * x;
|
||||
if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
|
||||
u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
|
||||
return self.d * v * self.scale
|
||||
u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
|
||||
return self.d * v * self.scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -196,7 +202,9 @@ impl ChiSquared {
|
||||
}
|
||||
}
|
||||
impl Sample<f64> for ChiSquared {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
impl IndependentSample<f64> for ChiSquared {
|
||||
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
|
||||
@ -206,7 +214,7 @@ impl IndependentSample<f64> for ChiSquared {
|
||||
let StandardNormal(norm) = rng.gen::<StandardNormal>();
|
||||
norm * norm
|
||||
}
|
||||
DoFAnythingElse(ref g) => g.ind_sample(rng)
|
||||
DoFAnythingElse(ref g) => g.ind_sample(rng),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -234,12 +242,14 @@ impl FisherF {
|
||||
FisherF {
|
||||
numer: ChiSquared::new(m),
|
||||
denom: ChiSquared::new(n),
|
||||
dof_ratio: n / m
|
||||
dof_ratio: n / m,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Sample<f64> for FisherF {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
impl IndependentSample<f64> for FisherF {
|
||||
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
|
||||
@ -251,7 +261,7 @@ impl IndependentSample<f64> for FisherF {
|
||||
/// freedom.
|
||||
pub struct StudentT {
|
||||
chi: ChiSquared,
|
||||
dof: f64
|
||||
dof: f64,
|
||||
}
|
||||
|
||||
impl StudentT {
|
||||
@ -261,12 +271,14 @@ impl StudentT {
|
||||
assert!(n > 0.0, "StudentT::new called with `n <= 0`");
|
||||
StudentT {
|
||||
chi: ChiSquared::new(n),
|
||||
dof: n
|
||||
dof: n,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Sample<f64> for StudentT {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
impl IndependentSample<f64> for StudentT {
|
||||
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
|
||||
|
@ -54,7 +54,9 @@ pub trait IndependentSample<Support>: Sample<Support> {
|
||||
|
||||
/// A wrapper for generating types that implement `Rand` via the
|
||||
/// `Sample` & `IndependentSample` traits.
|
||||
pub struct RandSample<Sup> { _marker: PhantomData<Sup> }
|
||||
pub struct RandSample<Sup> {
|
||||
_marker: PhantomData<Sup>,
|
||||
}
|
||||
|
||||
impl<Sup> RandSample<Sup> {
|
||||
pub fn new() -> RandSample<Sup> {
|
||||
@ -63,7 +65,9 @@ impl<Sup> RandSample<Sup> {
|
||||
}
|
||||
|
||||
impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
|
||||
@ -89,9 +93,9 @@ pub struct Weighted<T> {
|
||||
/// `IndependentSample` traits. Note that `&T` is (cheaply) `Clone` for
|
||||
/// all `T`, as is `usize`, so one can store references or indices into
|
||||
/// another vector.
|
||||
pub struct WeightedChoice<'a, T:'a> {
|
||||
pub struct WeightedChoice<'a, T: 'a> {
|
||||
items: &'a mut [Weighted<T>],
|
||||
weight_range: Range<usize>
|
||||
weight_range: Range<usize>,
|
||||
}
|
||||
|
||||
impl<'a, T: Clone> WeightedChoice<'a, T> {
|
||||
@ -103,7 +107,8 @@ impl<'a, T: Clone> WeightedChoice<'a, T> {
|
||||
/// - the total weight is larger than a `usize` can contain.
|
||||
pub fn new(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> {
|
||||
// strictly speaking, this is subsumed by the total weight == 0 case
|
||||
assert!(!items.is_empty(), "WeightedChoice::new called with no items");
|
||||
assert!(!items.is_empty(),
|
||||
"WeightedChoice::new called with no items");
|
||||
|
||||
let mut running_total = 0_usize;
|
||||
|
||||
@ -113,25 +118,28 @@ impl<'a, T: Clone> WeightedChoice<'a, T> {
|
||||
for item in &mut *items {
|
||||
running_total = match running_total.checked_add(item.weight) {
|
||||
Some(n) => n,
|
||||
None => panic!("WeightedChoice::new called with a total weight \
|
||||
larger than a usize can contain")
|
||||
None => panic!("WeightedChoice::new called with a total weight larger than a \
|
||||
usize can contain"),
|
||||
};
|
||||
|
||||
item.weight = running_total;
|
||||
}
|
||||
assert!(running_total != 0, "WeightedChoice::new called with a total weight of 0");
|
||||
assert!(running_total != 0,
|
||||
"WeightedChoice::new called with a total weight of 0");
|
||||
|
||||
WeightedChoice {
|
||||
items: items,
|
||||
// we're likely to be generating numbers in this range
|
||||
// relatively often, so might as well cache it
|
||||
weight_range: Range::new(0, running_total)
|
||||
weight_range: Range::new(0, running_total),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone> Sample<T> for WeightedChoice<'a, T> {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> T { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> T {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
|
||||
@ -191,18 +199,19 @@ mod ziggurat_tables;
|
||||
/// * `pdf`: the probability density function
|
||||
/// * `zero_case`: manual sampling from the tail when we chose the
|
||||
/// bottom box (i.e. i == 0)
|
||||
|
||||
// the perf improvement (25-50%) is definitely worth the extra code
|
||||
// size from force-inlining.
|
||||
#[inline(always)]
|
||||
fn ziggurat<R: Rng, P, Z>(
|
||||
rng: &mut R,
|
||||
symmetric: bool,
|
||||
x_tab: ziggurat_tables::ZigTable,
|
||||
f_tab: ziggurat_tables::ZigTable,
|
||||
mut pdf: P,
|
||||
mut zero_case: Z)
|
||||
-> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 {
|
||||
fn ziggurat<R: Rng, P, Z>(rng: &mut R,
|
||||
symmetric: bool,
|
||||
x_tab: ziggurat_tables::ZigTable,
|
||||
f_tab: ziggurat_tables::ZigTable,
|
||||
mut pdf: P,
|
||||
mut zero_case: Z)
|
||||
-> f64
|
||||
where P: FnMut(f64) -> f64,
|
||||
Z: FnMut(&mut R, f64) -> f64
|
||||
{
|
||||
const SCALE: f64 = (1u64 << 53) as f64;
|
||||
loop {
|
||||
// reimplement the f64 generation as an optimisation suggested
|
||||
@ -224,10 +233,18 @@ fn ziggurat<R: Rng, P, Z>(
|
||||
|
||||
// u is either U(-1, 1) or U(0, 1) depending on if this is a
|
||||
// symmetric distribution or not.
|
||||
let u = if symmetric {2.0 * f - 1.0} else {f};
|
||||
let u = if symmetric {
|
||||
2.0 * f - 1.0
|
||||
} else {
|
||||
f
|
||||
};
|
||||
let x = u * x_tab[i];
|
||||
|
||||
let test_x = if symmetric { x.abs() } else {x};
|
||||
let test_x = if symmetric {
|
||||
x.abs()
|
||||
} else {
|
||||
x
|
||||
};
|
||||
|
||||
// algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i])
|
||||
if test_x < x_tab[i + 1] {
|
||||
@ -259,7 +276,9 @@ mod tests {
|
||||
}
|
||||
|
||||
// 0, 1, 2, 3, ...
|
||||
struct CountingRng { i: u32 }
|
||||
struct CountingRng {
|
||||
i: u32,
|
||||
}
|
||||
impl Rng for CountingRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
self.i += 1;
|
||||
@ -298,54 +317,133 @@ mod tests {
|
||||
}}
|
||||
}
|
||||
|
||||
t!(vec!(Weighted { weight: 1, item: 10}), [10]);
|
||||
t!(vec!(Weighted {
|
||||
weight: 1,
|
||||
item: 10,
|
||||
}),
|
||||
[10]);
|
||||
|
||||
// skip some
|
||||
t!(vec!(Weighted { weight: 0, item: 20},
|
||||
Weighted { weight: 2, item: 21},
|
||||
Weighted { weight: 0, item: 22},
|
||||
Weighted { weight: 1, item: 23}),
|
||||
[21,21, 23]);
|
||||
t!(vec!(Weighted {
|
||||
weight: 0,
|
||||
item: 20,
|
||||
},
|
||||
Weighted {
|
||||
weight: 2,
|
||||
item: 21,
|
||||
},
|
||||
Weighted {
|
||||
weight: 0,
|
||||
item: 22,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 23,
|
||||
}),
|
||||
[21, 21, 23]);
|
||||
|
||||
// different weights
|
||||
t!(vec!(Weighted { weight: 4, item: 30},
|
||||
Weighted { weight: 3, item: 31}),
|
||||
[30,30,30,30, 31,31,31]);
|
||||
t!(vec!(Weighted {
|
||||
weight: 4,
|
||||
item: 30,
|
||||
},
|
||||
Weighted {
|
||||
weight: 3,
|
||||
item: 31,
|
||||
}),
|
||||
[30, 30, 30, 30, 31, 31, 31]);
|
||||
|
||||
// check that we're binary searching
|
||||
// correctly with some vectors of odd
|
||||
// length.
|
||||
t!(vec!(Weighted { weight: 1, item: 40},
|
||||
Weighted { weight: 1, item: 41},
|
||||
Weighted { weight: 1, item: 42},
|
||||
Weighted { weight: 1, item: 43},
|
||||
Weighted { weight: 1, item: 44}),
|
||||
t!(vec!(Weighted {
|
||||
weight: 1,
|
||||
item: 40,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 41,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 42,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 43,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 44,
|
||||
}),
|
||||
[40, 41, 42, 43, 44]);
|
||||
t!(vec!(Weighted { weight: 1, item: 50},
|
||||
Weighted { weight: 1, item: 51},
|
||||
Weighted { weight: 1, item: 52},
|
||||
Weighted { weight: 1, item: 53},
|
||||
Weighted { weight: 1, item: 54},
|
||||
Weighted { weight: 1, item: 55},
|
||||
Weighted { weight: 1, item: 56}),
|
||||
t!(vec!(Weighted {
|
||||
weight: 1,
|
||||
item: 50,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 51,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 52,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 53,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 54,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 55,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 56,
|
||||
}),
|
||||
[50, 51, 52, 53, 54, 55, 56]);
|
||||
}
|
||||
|
||||
#[test] #[should_panic]
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_weighted_choice_no_items() {
|
||||
WeightedChoice::<isize>::new(&mut []);
|
||||
}
|
||||
#[test] #[should_panic]
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_weighted_choice_zero_weight() {
|
||||
WeightedChoice::new(&mut [Weighted { weight: 0, item: 0},
|
||||
Weighted { weight: 0, item: 1}]);
|
||||
WeightedChoice::new(&mut [Weighted {
|
||||
weight: 0,
|
||||
item: 0,
|
||||
},
|
||||
Weighted {
|
||||
weight: 0,
|
||||
item: 1,
|
||||
}]);
|
||||
}
|
||||
#[test] #[should_panic]
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_weighted_choice_weight_overflows() {
|
||||
let x = (!0) as usize / 2; // x + x + 2 is the overflow
|
||||
WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
|
||||
Weighted { weight: 1, item: 1 },
|
||||
Weighted { weight: x, item: 2 },
|
||||
Weighted { weight: 1, item: 3 }]);
|
||||
WeightedChoice::new(&mut [Weighted {
|
||||
weight: x,
|
||||
item: 0,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 1,
|
||||
},
|
||||
Weighted {
|
||||
weight: x,
|
||||
item: 2,
|
||||
},
|
||||
Weighted {
|
||||
weight: 1,
|
||||
item: 3,
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ use distributions::{Sample, IndependentSample};
|
||||
pub struct Range<X> {
|
||||
low: X,
|
||||
range: X,
|
||||
accept_zone: X
|
||||
accept_zone: X,
|
||||
}
|
||||
|
||||
impl<X: SampleRange + PartialOrd> Range<X> {
|
||||
@ -46,7 +46,9 @@ impl<X: SampleRange + PartialOrd> Range<X> {
|
||||
|
||||
impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
|
||||
#[inline]
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup {
|
||||
self.ind_sample(rng)
|
||||
}
|
||||
}
|
||||
impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
|
||||
fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
|
||||
@ -148,7 +150,7 @@ float_impl! { f64 }
|
||||
mod tests {
|
||||
use std::prelude::v1::*;
|
||||
use distributions::{Sample, IndependentSample};
|
||||
use super::Range as Range;
|
||||
use super::Range;
|
||||
|
||||
#[should_panic]
|
||||
#[test]
|
||||
@ -182,8 +184,7 @@ mod tests {
|
||||
)*
|
||||
}}
|
||||
}
|
||||
t!(i8, i16, i32, i64, isize,
|
||||
u8, u16, u32, u64, usize)
|
||||
t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -48,7 +48,9 @@ static EMPTY: IsaacRng = IsaacRng {
|
||||
cnt: 0,
|
||||
rsl: [w(0); RAND_SIZE_USIZE],
|
||||
mem: [w(0); RAND_SIZE_USIZE],
|
||||
a: w(0), b: w(0), c: w(0),
|
||||
a: w(0),
|
||||
b: w(0),
|
||||
c: w(0),
|
||||
};
|
||||
|
||||
impl IsaacRng {
|
||||
@ -113,10 +115,14 @@ impl IsaacRng {
|
||||
} else {
|
||||
for i in (0..RAND_SIZE_USIZE).step_by(8) {
|
||||
mix!();
|
||||
self.mem[i ]=a; self.mem[i+1]=b;
|
||||
self.mem[i+2]=c; self.mem[i+3]=d;
|
||||
self.mem[i+4]=e; self.mem[i+5]=f;
|
||||
self.mem[i+6]=g; self.mem[i+7]=h;
|
||||
self.mem[i] = a;
|
||||
self.mem[i + 1] = b;
|
||||
self.mem[i + 2] = c;
|
||||
self.mem[i + 3] = d;
|
||||
self.mem[i + 4] = e;
|
||||
self.mem[i + 5] = f;
|
||||
self.mem[i + 6] = g;
|
||||
self.mem[i + 7] = h;
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +296,9 @@ static EMPTY_64: Isaac64Rng = Isaac64Rng {
|
||||
cnt: 0,
|
||||
rsl: [w(0); RAND_SIZE_64],
|
||||
mem: [w(0); RAND_SIZE_64],
|
||||
a: w(0), b: w(0), c: w(0),
|
||||
a: w(0),
|
||||
b: w(0),
|
||||
c: w(0),
|
||||
};
|
||||
|
||||
impl Isaac64Rng {
|
||||
@ -311,8 +319,14 @@ impl Isaac64Rng {
|
||||
let mut $var = w(0x9e3779b97f4a7c13);
|
||||
)
|
||||
}
|
||||
init!(a); init!(b); init!(c); init!(d);
|
||||
init!(e); init!(f); init!(g); init!(h);
|
||||
init!(a);
|
||||
init!(b);
|
||||
init!(c);
|
||||
init!(d);
|
||||
init!(e);
|
||||
init!(f);
|
||||
init!(g);
|
||||
init!(h);
|
||||
|
||||
macro_rules! mix {
|
||||
() => {{
|
||||
@ -353,10 +367,14 @@ impl Isaac64Rng {
|
||||
} else {
|
||||
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
|
||||
mix!();
|
||||
self.mem[i ]=a; self.mem[i+1]=b;
|
||||
self.mem[i+2]=c; self.mem[i+3]=d;
|
||||
self.mem[i+4]=e; self.mem[i+5]=f;
|
||||
self.mem[i+6]=g; self.mem[i+7]=h;
|
||||
self.mem[i] = a;
|
||||
self.mem[i + 1] = b;
|
||||
self.mem[i + 2] = c;
|
||||
self.mem[i + 3] = d;
|
||||
self.mem[i + 4] = e;
|
||||
self.mem[i + 5] = f;
|
||||
self.mem[i + 6] = g;
|
||||
self.mem[i + 7] = h;
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,7 +388,7 @@ impl Isaac64Rng {
|
||||
let mut a = self.a;
|
||||
let mut b = self.b + self.c;
|
||||
const MIDPOINT: usize = RAND_SIZE_64 / 2;
|
||||
const MP_VEC: [(usize, usize); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
|
||||
const MP_VEC: [(usize, usize); 2] = [(0, MIDPOINT), (MIDPOINT, 0)];
|
||||
macro_rules! ind {
|
||||
($x:expr) => {
|
||||
*self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1))
|
||||
@ -579,18 +597,36 @@ mod tests {
|
||||
// Regression test that isaac is actually using the above vector
|
||||
let v = (0..10).map(|_| ra.next_u32()).collect::<Vec<_>>();
|
||||
assert_eq!(v,
|
||||
vec!(2558573138, 873787463, 263499565, 2103644246, 3595684709,
|
||||
4203127393, 264982119, 2765226902, 2737944514, 3900253796));
|
||||
vec!(2558573138,
|
||||
873787463,
|
||||
263499565,
|
||||
2103644246,
|
||||
3595684709,
|
||||
4203127393,
|
||||
264982119,
|
||||
2765226902,
|
||||
2737944514,
|
||||
3900253796));
|
||||
|
||||
let seed: &[_] = &[12345, 67890, 54321, 9876];
|
||||
let mut rb: IsaacRng = SeedableRng::from_seed(seed);
|
||||
// skip forward to the 10000th number
|
||||
for _ in 0..10000 { rb.next_u32(); }
|
||||
for _ in 0..10000 {
|
||||
rb.next_u32();
|
||||
}
|
||||
|
||||
let v = (0..10).map(|_| rb.next_u32()).collect::<Vec<_>>();
|
||||
assert_eq!(v,
|
||||
vec!(3676831399, 3183332890, 2834741178, 3854698763, 2717568474,
|
||||
1576568959, 3507990155, 179069555, 141456972, 2478885421));
|
||||
vec!(3676831399,
|
||||
3183332890,
|
||||
2834741178,
|
||||
3854698763,
|
||||
2717568474,
|
||||
1576568959,
|
||||
3507990155,
|
||||
179069555,
|
||||
141456972,
|
||||
2478885421));
|
||||
}
|
||||
#[test]
|
||||
fn test_rng_64_true_values() {
|
||||
@ -599,21 +635,35 @@ mod tests {
|
||||
// Regression test that isaac is actually using the above vector
|
||||
let v = (0..10).map(|_| ra.next_u64()).collect::<Vec<_>>();
|
||||
assert_eq!(v,
|
||||
vec!(547121783600835980, 14377643087320773276, 17351601304698403469,
|
||||
1238879483818134882, 11952566807690396487, 13970131091560099343,
|
||||
4469761996653280935, 15552757044682284409, 6860251611068737823,
|
||||
vec!(547121783600835980,
|
||||
14377643087320773276,
|
||||
17351601304698403469,
|
||||
1238879483818134882,
|
||||
11952566807690396487,
|
||||
13970131091560099343,
|
||||
4469761996653280935,
|
||||
15552757044682284409,
|
||||
6860251611068737823,
|
||||
13722198873481261842));
|
||||
|
||||
let seed: &[_] = &[12345, 67890, 54321, 9876];
|
||||
let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
|
||||
// skip forward to the 10000th number
|
||||
for _ in 0..10000 { rb.next_u64(); }
|
||||
for _ in 0..10000 {
|
||||
rb.next_u64();
|
||||
}
|
||||
|
||||
let v = (0..10).map(|_| rb.next_u64()).collect::<Vec<_>>();
|
||||
assert_eq!(v,
|
||||
vec!(18143823860592706164, 8491801882678285927, 2699425367717515619,
|
||||
17196852593171130876, 2606123525235546165, 15790932315217671084,
|
||||
596345674630742204, 9947027391921273664, 11788097613744130851,
|
||||
vec!(18143823860592706164,
|
||||
8491801882678285927,
|
||||
2699425367717515619,
|
||||
17196852593171130876,
|
||||
2606123525235546165,
|
||||
15790932315217671084,
|
||||
596345674630742204,
|
||||
9947027391921273664,
|
||||
11788097613744130851,
|
||||
10391409374914919106));
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,12 @@
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
#[cfg(test)] #[macro_use] extern crate std;
|
||||
#[cfg(test)] #[macro_use] extern crate log;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use core::f64;
|
||||
use core::intrinsics;
|
||||
@ -217,7 +221,10 @@ pub trait Rng : Sized {
|
||||
/// Return an iterator that will yield an infinite number of randomly
|
||||
/// generated items.
|
||||
fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
|
||||
Generator { rng: self, _marker: PhantomData }
|
||||
Generator {
|
||||
rng: self,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a random value in the range [`low`, `high`).
|
||||
@ -272,9 +279,9 @@ pub trait Rng : Sized {
|
||||
/// Iterator which will generate a stream of random items.
|
||||
///
|
||||
/// This iterator is created via the `gen_iter` method on `Rng`.
|
||||
pub struct Generator<'a, T, R:'a> {
|
||||
pub struct Generator<'a, T, R: 'a> {
|
||||
rng: &'a mut R,
|
||||
_marker: PhantomData<T>
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
|
||||
@ -288,7 +295,7 @@ impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
|
||||
/// Iterator which will continuously generate random ascii characters.
|
||||
///
|
||||
/// This iterator is created via the `gen_ascii_chars` method on `Rng`.
|
||||
pub struct AsciiGenerator<'a, R:'a> {
|
||||
pub struct AsciiGenerator<'a, R: 'a> {
|
||||
rng: &'a mut R,
|
||||
}
|
||||
|
||||
@ -384,7 +391,7 @@ impl SeedableRng<[u32; 4]> for XorShiftRng {
|
||||
x: seed[0],
|
||||
y: seed[1],
|
||||
z: seed[2],
|
||||
w: seed[3]
|
||||
w: seed[3],
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -396,7 +403,12 @@ impl Rand for XorShiftRng {
|
||||
tuple = rng.gen();
|
||||
}
|
||||
let (x, y, z, w) = tuple;
|
||||
XorShiftRng { x: x, y: y, z: z, w: w }
|
||||
XorShiftRng {
|
||||
x: x,
|
||||
y: y,
|
||||
z: z,
|
||||
w: w,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,7 +432,9 @@ pub struct Closed01<F>(pub F);
|
||||
mod test {
|
||||
use std::__rand as rand;
|
||||
|
||||
pub struct MyRng<R> { inner: R }
|
||||
pub struct MyRng<R> {
|
||||
inner: R,
|
||||
}
|
||||
|
||||
impl<R: rand::Rng> ::Rng for MyRng<R> {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
|
@ -14,7 +14,7 @@ use core::char;
|
||||
use core::isize;
|
||||
use core::usize;
|
||||
|
||||
use {Rand,Rng};
|
||||
use {Rand, Rng};
|
||||
|
||||
impl Rand for isize {
|
||||
#[inline]
|
||||
@ -185,7 +185,9 @@ macro_rules! tuple_impl {
|
||||
|
||||
impl Rand for () {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(_: &mut R) -> () { () }
|
||||
fn rand<R: Rng>(_: &mut R) -> () {
|
||||
()
|
||||
}
|
||||
}
|
||||
tuple_impl!{A}
|
||||
tuple_impl!{A, B}
|
||||
|
@ -35,12 +35,12 @@ impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
|
||||
/// * `rng`: the random number generator to use.
|
||||
/// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
|
||||
/// * `reseeder`: the reseeding object to use.
|
||||
pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
|
||||
pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng<R, Rsdr> {
|
||||
ReseedingRng {
|
||||
rng: rng,
|
||||
generation_threshold: generation_threshold,
|
||||
bytes_generated: 0,
|
||||
reseeder: reseeder
|
||||
reseeder: reseeder,
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
|
||||
rng: SeedableRng::from_seed(seed),
|
||||
generation_threshold: DEFAULT_GENERATION_THRESHOLD,
|
||||
bytes_generated: 0,
|
||||
reseeder: rsdr
|
||||
reseeder: rsdr,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,7 +114,9 @@ impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Default for ReseedWithDefault {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn default() -> ReseedWithDefault { ReseedWithDefault }
|
||||
fn default() -> ReseedWithDefault {
|
||||
ReseedWithDefault
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -126,7 +128,7 @@ mod tests {
|
||||
use {SeedableRng, Rng};
|
||||
|
||||
struct Counter {
|
||||
i: u32
|
||||
i: u32,
|
||||
}
|
||||
|
||||
impl Rng for Counter {
|
||||
@ -153,7 +155,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_reseeding() {
|
||||
let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);
|
||||
let mut rs = ReseedingRng::new(Counter { i: 0 }, 400, ReseedWithDefault);
|
||||
|
||||
let mut i = 0;
|
||||
for _ in 0..1000 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user