Skip to content

Commit f786359

Browse files
authored
Merge pull request #623 from dhardy/small-rng
Update SmallRng and remove rand_xorshift crate
2 parents 2457cdb + 1d29928 commit f786359

File tree

7 files changed

+43
-26
lines changed

7 files changed

+43
-26
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ members = ["rand_core", "rand_isaac", "rand_chacha", "rand_hc128", "rand_pcg", "
3232

3333
[dependencies]
3434
rand_core = { path = "rand_core", version = "0.3", default-features = false }
35+
rand_pcg = { path = "rand_pcg", version = "0.1" }
3536
# only for deprecations and benches:
3637
rand_isaac = { path = "rand_isaac", version = "0.1" }
3738
rand_chacha = { path = "rand_chacha", version = "0.1" }

benches/generators.rs

+10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern crate rand;
1313
extern crate rand_isaac;
1414
extern crate rand_chacha;
1515
extern crate rand_hc128;
16+
extern crate rand_pcg;
1617
extern crate rand_xorshift;
1718

1819
const RAND_BENCH_N: u64 = 1000;
@@ -27,6 +28,7 @@ use rand::rngs::{OsRng, JitterRng, EntropyRng};
2728
use rand_isaac::{IsaacRng, Isaac64Rng};
2829
use rand_chacha::ChaChaRng;
2930
use rand_hc128::{Hc128Rng, Hc128Core};
31+
use rand_pcg::{Lcg64Xsh32, Mcg128Xsl64};
3032
use rand_xorshift::XorShiftRng;
3133

3234
macro_rules! gen_bytes {
@@ -47,6 +49,8 @@ macro_rules! gen_bytes {
4749
}
4850

4951
gen_bytes!(gen_bytes_xorshift, XorShiftRng::from_entropy());
52+
gen_bytes!(gen_bytes_lcg64_xsh32, Lcg64Xsh32::from_entropy());
53+
gen_bytes!(gen_bytes_mcg128_xsh64, Mcg128Xsl64::from_entropy());
5054
gen_bytes!(gen_bytes_chacha20, ChaChaRng::from_entropy());
5155
gen_bytes!(gen_bytes_hc128, Hc128Rng::from_entropy());
5256
gen_bytes!(gen_bytes_isaac, IsaacRng::from_entropy());
@@ -73,6 +77,8 @@ macro_rules! gen_uint {
7377
}
7478

7579
gen_uint!(gen_u32_xorshift, u32, XorShiftRng::from_entropy());
80+
gen_uint!(gen_u32_lcg64_xsh32, u32, Lcg64Xsh32::from_entropy());
81+
gen_uint!(gen_u32_mcg128_xsh64, u32, Mcg128Xsl64::from_entropy());
7682
gen_uint!(gen_u32_chacha20, u32, ChaChaRng::from_entropy());
7783
gen_uint!(gen_u32_hc128, u32, Hc128Rng::from_entropy());
7884
gen_uint!(gen_u32_isaac, u32, IsaacRng::from_entropy());
@@ -82,6 +88,8 @@ gen_uint!(gen_u32_small, u32, SmallRng::from_entropy());
8288
gen_uint!(gen_u32_os, u32, OsRng::new().unwrap());
8389

8490
gen_uint!(gen_u64_xorshift, u64, XorShiftRng::from_entropy());
91+
gen_uint!(gen_u64_lcg64_xsh32, u64, Lcg64Xsh32::from_entropy());
92+
gen_uint!(gen_u64_mcg128_xsh64, u64, Mcg128Xsl64::from_entropy());
8593
gen_uint!(gen_u64_chacha20, u64, ChaChaRng::from_entropy());
8694
gen_uint!(gen_u64_hc128, u64, Hc128Rng::from_entropy());
8795
gen_uint!(gen_u64_isaac, u64, IsaacRng::from_entropy());
@@ -115,6 +123,8 @@ macro_rules! init_gen {
115123
}
116124

117125
init_gen!(init_xorshift, XorShiftRng);
126+
init_gen!(init_lcg64_xsh32, Lcg64Xsh32);
127+
init_gen!(init_mcg128_xsh64, Mcg128Xsl64);
118128
init_gen!(init_hc128, Hc128Rng);
119129
init_gen!(init_isaac, IsaacRng);
120130
init_gen!(init_isaac64, Isaac64Rng);

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ extern crate rand_core;
245245
extern crate rand_isaac; // only for deprecations
246246
extern crate rand_chacha; // only for deprecations
247247
extern crate rand_hc128;
248+
extern crate rand_pcg;
248249
extern crate rand_xorshift;
249250

250251
#[cfg(feature = "log")] #[macro_use] extern crate log;

src/prng/mod.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,18 @@
4545
//!
4646
//! | name | full name | performance | memory | quality | period | features |
4747
//! |------|-----------|-------------|--------|---------|--------|----------|
48-
//! | [`XorShiftRng`] | Xorshift 32/128 | ★★★☆☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2<sup>128</sup> - 1 | — |
48+
//! | [`Pcg32`] | PCG XSH RR 64/32 (LCG) | ★★★☆☆ | 16 bytes | ★★★☆☆ | `u32` * 2<sup>64</sup> | — |
49+
//! | [`Pcg64Mcg`] | PCG XSL 128/64 (MCG) | ★★★★☆ | 16 bytes | ★★★☆☆ | `u64` * 2<sup>126</sup> | — |
50+
//! | [`XorShiftRng`] | Xorshift 32/128 | ★★★★☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2<sup>128</sup> - 1 | — |
4951
//!
5052
// Quality stars [not rendered in documentation]:
51-
// 5. reserved for crypto-level (e.g. ChaCha8, ISAAC)
52-
// 4. good performance on TestU01 and PractRand, good theory
53-
// (e.g. PCG, truncated Xorshift*)
54-
// 3. good performance on TestU01 and PractRand, but "falling through the
55-
// cracks" or insufficient theory (e.g. SFC, Xoshiro)
56-
// 2. imperfect performance on tests or other limiting properties, but not
57-
// terrible (e.g. Xoroshiro128+)
53+
// 5. proven cryptographic quality (e.g. ChaCha20)
54+
// 4. potentially cryptographic, but low margin or lack of theory (e.g. ChaCha8, ISAAC)
55+
// 3. good performance on TestU01 and PractRand, good theory
56+
// 2. imperfect performance on tests or other limiting properties, or
57+
// insufficient theory, but not terrible
5858
// 1. clear deficiencies in test results, cycle length, theory, or other
59-
// properties (e.g. Xorshift)
59+
// properties
6060
//
6161
// Performance stars [not rendered in documentation]:
6262
// Meant to give an indication of relative performance. Roughly follows a log
@@ -297,6 +297,8 @@
297297
//! [`rngs` module]: ../rngs/index.html
298298
//! [basic PRNGs]: #basic-pseudo-random-number-generators-prngs
299299
//! [CSPRNGs]: #cryptographically-secure-pseudo-random-number-generators-csprngs
300+
//! [`Pcg32`]: ../../rand_pcg/type.Pcg32.html
301+
//! [`Pcg64Mcg`]: ../../rand_pcg/type.Pcg64Mcg.html
300302
//! [`XorShiftRng`]: ../../rand_xorshift/struct.XorShiftRng.html
301303
//! [`ChaChaRng`]: ../../rand_chacha/struct.ChaChaRng.html
302304
//! [`Hc128Rng`]: ../../rand_hc128/struct.Hc128Rng.html

src/rngs/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@
4848
//!
4949
//! - [`SmallRng`] is a PRNG chosen for low memory usage, high performance and
5050
//! good statistical quality.
51-
//! The current algorithm (plain Xorshift) unfortunately performs
52-
//! poorly in statistical quality test suites (TestU01 and PractRand) and will
53-
//! be replaced in the next major release.
5451
//! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security
5552
//! (based on reviews, maturity and usage). The current algorithm is HC-128,
5653
//! which is one of the recommendations by ECRYPT's eSTREAM project.

src/rngs/small.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
//! A small fast RNG
1010
1111
use {RngCore, SeedableRng, Error};
12-
use ::rand_xorshift::XorShiftRng;
12+
13+
#[cfg(all(rust_1_26, target_pointer_width = "64"))]
14+
type Rng = ::rand_pcg::Pcg64Mcg;
15+
#[cfg(not(all(rust_1_26, target_pointer_width = "64")))]
16+
type Rng = ::rand_pcg::Pcg32;
1317

1418
/// An RNG recommended when small state, cheap initialization and good
1519
/// performance are required. The PRNG algorithm in `SmallRng` is chosen to be
@@ -20,9 +24,11 @@ use ::rand_xorshift::XorShiftRng;
2024
/// future library versions may use a different internal generator with
2125
/// different output. Further, this generator may not be portable and can
2226
/// produce different output depending on the architecture. If you require
23-
/// reproducible output, use a named RNG, for example [`XorShiftRng`].
27+
/// reproducible output, use a named RNG. Refer to the documentation on the
28+
/// [`prng` module](../prng/index.html).
2429
///
25-
/// The current algorithm used on all platforms is [Xorshift].
30+
/// The current algorithm is [`Pcg64Mcg`] on 64-bit platforms with Rust version
31+
/// 1.26 and later, or [`Pcg32`] otherwise.
2632
///
2733
/// # Examples
2834
///
@@ -61,10 +67,10 @@ use ::rand_xorshift::XorShiftRng;
6167
/// [`FromEntropy`]: ../trait.FromEntropy.html
6268
/// [`StdRng`]: struct.StdRng.html
6369
/// [`thread_rng`]: ../fn.thread_rng.html
64-
/// [Xorshift]: ../../rand_xorshift/struct.XorShiftRng.html
65-
/// [`XorShiftRng`]: ../../rand_xorshift/struct.XorShiftRng.html
70+
/// [`Pcg64Mcg`]: https://docs.rs/rand_pcg/0.1.0/rand_pcg/type.Pcg64Mcg.html
71+
/// [`Pcg32`]: https://docs.rs/rand_pcg/0.1.0/rand_pcg/type.Pcg32.html
6672
#[derive(Clone, Debug)]
67-
pub struct SmallRng(XorShiftRng);
73+
pub struct SmallRng(Rng);
6874

6975
impl RngCore for SmallRng {
7076
#[inline(always)]
@@ -87,13 +93,13 @@ impl RngCore for SmallRng {
8793
}
8894

8995
impl SeedableRng for SmallRng {
90-
type Seed = <XorShiftRng as SeedableRng>::Seed;
96+
type Seed = <Rng as SeedableRng>::Seed;
9197

9298
fn from_seed(seed: Self::Seed) -> Self {
93-
SmallRng(XorShiftRng::from_seed(seed))
99+
SmallRng(Rng::from_seed(seed))
94100
}
95101

96102
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
97-
XorShiftRng::from_rng(rng).map(SmallRng)
103+
Rng::from_rng(rng).map(SmallRng)
98104
}
99105
}

src/seq/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) ->
512512
mod test {
513513
use super::*;
514514
#[cfg(feature = "alloc")] use {Rng, SeedableRng};
515-
#[cfg(feature = "alloc")] use ::rand_xorshift::XorShiftRng;
515+
#[cfg(feature = "alloc")] use rngs::SmallRng;
516516
#[cfg(all(feature="alloc", not(feature="std")))]
517517
use alloc::vec::Vec;
518518

@@ -753,7 +753,7 @@ mod test {
753753
#[cfg(feature = "alloc")]
754754
#[allow(deprecated)]
755755
fn test_sample_slice() {
756-
let xor_rng = XorShiftRng::from_seed;
756+
let seeded_rng = SmallRng::from_seed;
757757

758758
let mut r = ::test::rng(403);
759759

@@ -764,16 +764,16 @@ mod test {
764764
r.fill(&mut seed);
765765

766766
// assert the basics work
767-
let regular = index::sample(&mut xor_rng(seed), length, amount);
767+
let regular = index::sample(&mut seeded_rng(seed), length, amount);
768768
assert_eq!(regular.len(), amount);
769769
assert!(regular.iter().all(|e| e < length));
770770

771771
// also test that sampling the slice works
772772
let vec: Vec<u32> = (0..(length as u32)).collect();
773-
let result = sample_slice(&mut xor_rng(seed), &vec, amount);
773+
let result = sample_slice(&mut seeded_rng(seed), &vec, amount);
774774
assert_eq!(result, regular.iter().map(|i| i as u32).collect::<Vec<_>>());
775775

776-
let result = sample_slice_ref(&mut xor_rng(seed), &vec, amount);
776+
let result = sample_slice_ref(&mut seeded_rng(seed), &vec, amount);
777777
assert!(result.iter().zip(regular.iter()).all(|(i,j)| **i == j as u32));
778778
}
779779
}

0 commit comments

Comments
 (0)