rand/rngs/
xoshiro256plusplus.rs1use core::convert::Infallible;
10use rand_core::{SeedableRng, TryRng, utils};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24pub struct Xoshiro256PlusPlus {
25 s: [u64; 4],
26}
27
28impl SeedableRng for Xoshiro256PlusPlus {
29 type Seed = [u8; 32];
30
31 #[inline]
34 fn from_seed(seed: [u8; 32]) -> Xoshiro256PlusPlus {
35 let state = utils::read_words(&seed);
36 if state.iter().all(|&x| x == 0) {
39 return Self::seed_from_u64(0);
40 }
41 Xoshiro256PlusPlus { s: state }
42 }
43
44 #[inline]
48 fn seed_from_u64(mut state: u64) -> Self {
49 const PHI: u64 = 0x9e3779b97f4a7c15;
50 let mut s = [0; 4];
51 for i in s.iter_mut() {
52 state = state.wrapping_add(PHI);
53 let mut z = state;
54 z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
55 z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
56 z = z ^ (z >> 31);
57 *i = z;
58 }
59 debug_assert_ne!(s, [0; 4]);
62 Xoshiro256PlusPlus { s }
63 }
64}
65
66impl TryRng for Xoshiro256PlusPlus {
67 type Error = Infallible;
68
69 #[inline]
70 fn try_next_u32(&mut self) -> Result<u32, Infallible> {
71 self.try_next_u64().map(|val| (val >> 32) as u32)
74 }
75
76 #[inline]
77 fn try_next_u64(&mut self) -> Result<u64, Infallible> {
78 let res = self.s[0]
79 .wrapping_add(self.s[3])
80 .rotate_left(23)
81 .wrapping_add(self.s[0]);
82
83 let t = self.s[1] << 17;
84
85 self.s[2] ^= self.s[0];
86 self.s[3] ^= self.s[1];
87 self.s[1] ^= self.s[2];
88 self.s[0] ^= self.s[3];
89
90 self.s[2] ^= t;
91
92 self.s[3] = self.s[3].rotate_left(45);
93
94 Ok(res)
95 }
96
97 #[inline]
98 fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> {
99 utils::fill_bytes_via_next_word(dst, || self.try_next_u64())
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::Xoshiro256PlusPlus;
106 use rand_core::{Rng, SeedableRng};
107
108 #[test]
109 fn reference() {
110 let mut rng = Xoshiro256PlusPlus::from_seed([
111 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
112 0, 0, 0,
113 ]);
114 let expected = [
117 41943041,
118 58720359,
119 3588806011781223,
120 3591011842654386,
121 9228616714210784205,
122 9973669472204895162,
123 14011001112246962877,
124 12406186145184390807,
125 15849039046786891736,
126 10450023813501588000,
127 ];
128 for &e in &expected {
129 assert_eq!(rng.next_u64(), e);
130 }
131 }
132
133 #[test]
134 fn stable_seed_from_u64_and_from_seed() {
135 let mut rng = Xoshiro256PlusPlus::seed_from_u64(0);
138 let mut rng_from_seed_0 = Xoshiro256PlusPlus::from_seed([0; 32]);
140 let expected = [
141 5987356902031041503,
142 7051070477665621255,
143 6633766593972829180,
144 211316841551650330,
145 9136120204379184874,
146 379361710973160858,
147 15813423377499357806,
148 15596884590815070553,
149 5439680534584881407,
150 1369371744833522710,
151 ];
152 for &e in &expected {
153 assert_eq!(rng.next_u64(), e);
154 assert_eq!(rng_from_seed_0.next_u64(), e);
155 }
156 }
157}