Skip to content

Commit dc2fabd

Browse files
authored
Add Xoshiro256++ random number generator (EbTech#21)
1 parent 64f3755 commit dc2fabd

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

src/graph/connectivity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl ConnectivityData {
4545
///
4646
/// Multiple-edges and self-loops are correctly handled.
4747
pub struct ConnectivityGraph<'a> {
48-
// Immutable graph, frozen for the lifetime of the ConnectivityGraph object.
48+
/// Immutable graph, frozen for the lifetime of the ConnectivityGraph object.
4949
pub graph: &'a Graph,
5050
/// ID of a vertex's CC, SCC or 2ECC, whichever applies. Range 1 to num_cc.
5151
pub cc: Vec<usize>,

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! Algorithms Cookbook in Rust.
2+
23
pub mod caching;
34
pub mod graph;
45
pub mod math;
56
pub mod order;
67
pub mod range_query;
8+
pub mod rng;
79
pub mod scanner;
810
pub mod string_proc;

src/rng.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//! Pseudorandom number generators (PRNGs).
2+
3+
/// A simple and efficient random number generator.
4+
pub type SmallRng = Xoshiro256PlusPlus;
5+
6+
/// A xoshiro256++ random number generator.
7+
///
8+
/// This is a simplified version of the `SmallRng` implementation from the
9+
/// excellent `rand` crate, keeping only essential features.
10+
///
11+
/// The xoshiro256++ algorithm is not suitable for cryptographic purposes, but
12+
/// is very fast and has excellent statistical properties.
13+
///
14+
/// * Source: [Docs.rs](https://docs.rs/rand/0.8.4/src/rand/rngs/xoshiro256plusplus.rs.html)
15+
/// * Theory: [Xorshift - Wikipedia](https://en.wikipedia.org/wiki/Xorshift)
16+
#[derive(Debug, Clone, PartialEq, Eq)]
17+
pub struct Xoshiro256PlusPlus {
18+
s: [u64; 4],
19+
}
20+
21+
impl Xoshiro256PlusPlus {
22+
/// Construct a new RNG from a 64-bit seed.
23+
pub fn new(mut state: u64) -> Self {
24+
const PHI: u64 = 0x9e3779b97f4a7c15;
25+
let mut seed = <[u64; 4]>::default();
26+
for chunk in &mut seed {
27+
state = state.wrapping_add(PHI);
28+
let mut z = state;
29+
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
30+
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
31+
z = z ^ (z >> 31);
32+
*chunk = z;
33+
}
34+
Self { s: seed }
35+
}
36+
37+
/// Generate a random `u32`.
38+
#[inline]
39+
pub fn next_u32(&mut self) -> u32 {
40+
(self.next_u64() >> 32) as u32
41+
}
42+
43+
/// Generate a random `u64`.
44+
#[inline]
45+
pub fn next_u64(&mut self) -> u64 {
46+
let result_plusplus = self.s[0]
47+
.wrapping_add(self.s[3])
48+
.rotate_left(23)
49+
.wrapping_add(self.s[0]);
50+
51+
let t = self.s[1] << 17;
52+
53+
self.s[2] ^= self.s[0];
54+
self.s[3] ^= self.s[1];
55+
self.s[1] ^= self.s[2];
56+
self.s[0] ^= self.s[3];
57+
58+
self.s[2] ^= t;
59+
60+
self.s[3] = self.s[3].rotate_left(45);
61+
62+
result_plusplus
63+
}
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
use super::*;
69+
70+
#[test]
71+
fn test_xoshiro256plusplus() {
72+
let mut rng = Xoshiro256PlusPlus::new(42);
73+
assert_eq!(rng.next_u64(), 15021278609987233951);
74+
assert_eq!(rng.next_u64(), 5881210131331364753);
75+
assert_eq!(rng.next_u64(), 18149643915985481100);
76+
assert_eq!(rng.next_u64(), 12933668939759105464);
77+
assert_eq!(rng.next_u64(), 14637574242682825331);
78+
assert_eq!(rng.next_u64(), 10848501901068131965);
79+
assert_eq!(rng.next_u64(), 2312344417745909078);
80+
assert_eq!(rng.next_u64(), 11162538943635311430);
81+
}
82+
83+
#[test]
84+
fn reference() {
85+
let mut rng = Xoshiro256PlusPlus { s: [1, 2, 3, 4] };
86+
// These values were produced with the reference implementation:
87+
// http://xoshiro.di.unimi.it/xoshiro256plusplus.c
88+
let expected = [
89+
41943041,
90+
58720359,
91+
3588806011781223,
92+
3591011842654386,
93+
9228616714210784205,
94+
9973669472204895162,
95+
14011001112246962877,
96+
12406186145184390807,
97+
15849039046786891736,
98+
10450023813501588000,
99+
];
100+
for &e in &expected {
101+
assert_eq!(rng.next_u64(), e);
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy