Skip to content

Commit 6d9e7ac

Browse files
committed
rand_xorshift reorganisation, courtesy of @newpavlov
This copies changes from the separate small-rngs repo
1 parent 31b437a commit 6d9e7ac

File tree

5 files changed

+193
-216
lines changed

5 files changed

+193
-216
lines changed

rand_xorshift/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ authors = ["The Rand Project Developers", "The Rust Project Developers"]
55
license = "MIT/Apache-2.0"
66
readme = "README.md"
77
repository = "https://github.com/rust-random/rand"
8-
documentation = "https://docs.rs/rand_isaac"
9-
homepage = "https://crates.io/crates/rand_isaac"
8+
documentation = "https://docs.rs/rand_xorshift"
9+
homepage = "https://crates.io/crates/rand_xorshift"
1010
description = """
1111
Xorshift random number generator
1212
"""

rand_xorshift/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ requirements, use a more secure one such as `StdRng` or `OsRng`.
1919

2020
Documentation:
2121
[master branch](https://rust-random.github.io/rand/rand_xorshift/index.html),
22-
[by release](https://docs.rs/rand_isaac)
22+
[by release](https://docs.rs/rand_xorshift)
2323

2424
[Changelog](CHANGELOG.md)
2525

rand_xorshift/src/lib.rs

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,110 @@
1414

1515
#![deny(missing_docs)]
1616
#![deny(missing_debug_implementations)]
17-
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
1817

19-
#![cfg_attr(not(all(feature="serde1", test)), no_std)]
18+
#![no_std]
2019

2120
extern crate rand_core;
2221

2322
#[cfg(feature="serde1")] extern crate serde;
2423
#[cfg(feature="serde1")] #[macro_use] extern crate serde_derive;
2524

26-
// To test serialization we need bincode and the standard library
27-
#[cfg(all(feature="serde1", test))] extern crate bincode;
28-
#[cfg(all(feature="serde1", test))] extern crate std as core;
25+
use core::num::Wrapping as w;
26+
use core::{fmt, slice};
27+
use rand_core::{RngCore, SeedableRng, Error, impls, le};
2928

30-
mod xorshift;
29+
/// An Xorshift random number generator.
30+
///
31+
/// The Xorshift[^1] algorithm is not suitable for cryptographic purposes
32+
/// but is very fast. If you do not know for sure that it fits your
33+
/// requirements, use a more secure one such as `StdRng` or `OsRng`.
34+
///
35+
/// [^1]: Marsaglia, George (July 2003).
36+
/// ["Xorshift RNGs"](https://www.jstatsoft.org/v08/i14/paper).
37+
/// *Journal of Statistical Software*. Vol. 8 (Issue 14).
38+
#[derive(Clone)]
39+
#[cfg_attr(feature="serde1", derive(Serialize,Deserialize))]
40+
pub struct XorShiftRng {
41+
x: w<u32>,
42+
y: w<u32>,
43+
z: w<u32>,
44+
w: w<u32>,
45+
}
3146

32-
pub use self::xorshift::XorShiftRng;
47+
// Custom Debug implementation that does not expose the internal state
48+
impl fmt::Debug for XorShiftRng {
49+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50+
write!(f, "XorShiftRng {{}}")
51+
}
52+
}
53+
54+
impl RngCore for XorShiftRng {
55+
#[inline]
56+
fn next_u32(&mut self) -> u32 {
57+
let x = self.x;
58+
let t = x ^ (x << 11);
59+
self.x = self.y;
60+
self.y = self.z;
61+
self.z = self.w;
62+
let w_ = self.w;
63+
self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
64+
self.w.0
65+
}
66+
67+
#[inline]
68+
fn next_u64(&mut self) -> u64 {
69+
impls::next_u64_via_u32(self)
70+
}
71+
72+
#[inline]
73+
fn fill_bytes(&mut self, dest: &mut [u8]) {
74+
impls::fill_bytes_via_next(self, dest)
75+
}
76+
77+
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
78+
Ok(self.fill_bytes(dest))
79+
}
80+
}
81+
82+
impl SeedableRng for XorShiftRng {
83+
type Seed = [u8; 16];
84+
85+
fn from_seed(seed: Self::Seed) -> Self {
86+
let mut seed_u32 = [0u32; 4];
87+
le::read_u32_into(&seed, &mut seed_u32);
88+
89+
// Xorshift cannot be seeded with 0 and we cannot return an Error, but
90+
// also do not wish to panic (because a random seed can legitimately be
91+
// 0); our only option is therefore to use a preset value.
92+
if seed_u32.iter().all(|&x| x == 0) {
93+
seed_u32 = [0xBAD_5EED, 0xBAD_5EED, 0xBAD_5EED, 0xBAD_5EED];
94+
}
95+
96+
XorShiftRng {
97+
x: w(seed_u32[0]),
98+
y: w(seed_u32[1]),
99+
z: w(seed_u32[2]),
100+
w: w(seed_u32[3]),
101+
}
102+
}
103+
104+
fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
105+
let mut seed_u32 = [0u32; 4];
106+
loop {
107+
unsafe {
108+
let ptr = seed_u32.as_mut_ptr() as *mut u8;
109+
110+
let slice = slice::from_raw_parts_mut(ptr, 4 * 4);
111+
rng.try_fill_bytes(slice)?;
112+
}
113+
if !seed_u32.iter().all(|&x| x == 0) { break; }
114+
}
115+
116+
Ok(XorShiftRng {
117+
x: w(seed_u32[0]),
118+
y: w(seed_u32[1]),
119+
z: w(seed_u32[2]),
120+
w: w(seed_u32[3]),
121+
})
122+
}
123+
}

rand_xorshift/src/xorshift.rs

Lines changed: 0 additions & 206 deletions
This file was deleted.

0 commit comments

Comments
 (0)