1use core::convert::Infallible;
10use rand_core::{Rng, SeedableRng, TryRng, utils};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14use crate::Seed512;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub struct Xoshiro512PlusPlus {
27 s: [u64; 8],
28}
29
30impl Xoshiro512PlusPlus {
31 pub fn jump(&mut self) {
47 impl_jump!(
48 u64,
49 self,
50 [
51 0x33ed89b6e7a353f9,
52 0x760083d7955323be,
53 0x2837f2fbb5f22fae,
54 0x4b8c5674d309511c,
55 0xb11ac47a7ba28c25,
56 0xf1be7667092bcc1c,
57 0x53851efdb6df0aaf,
58 0x1ebbc8b23eaf25db
59 ]
60 );
61 }
62
63 pub fn long_jump(&mut self) {
69 impl_jump!(
70 u64,
71 self,
72 [
73 0x11467fef8f921d28,
74 0xa2a819f2e79c8ea8,
75 0xa8299fc284b3959a,
76 0xb4d347340ca63ee1,
77 0x1cb0940bedbff6ce,
78 0xd956c5c4fa1f8e17,
79 0x915e38fd4eda93bc,
80 0x5b3ccdfa5d7daca5
81 ]
82 );
83 }
84}
85
86impl_state_seed512!(Xoshiro512PlusPlus);
87
88impl SeedableRng for Xoshiro512PlusPlus {
89 type Seed = Seed512;
90
91 #[inline]
94 fn from_seed(seed: Seed512) -> Xoshiro512PlusPlus {
95 Xoshiro512PlusPlus {
96 s: utils::read_words(crate::common::zero_seed_fallback(&seed.0)),
97 }
98 }
99
100 fn seed_from_u64(seed: u64) -> Xoshiro512PlusPlus {
102 from_splitmix!(seed)
103 }
104}
105
106impl TryRng for Xoshiro512PlusPlus {
107 type Error = Infallible;
108
109 #[inline]
110 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
111 Ok((self.next_u64() >> 32) as u32)
114 }
115
116 #[inline]
117 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
118 let result_plusplus = plusplus_u64!(self.s[2], self.s[0], 17);
119 impl_xoshiro_large!(self);
120 Ok(result_plusplus)
121 }
122
123 #[inline]
124 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
125 utils::fill_bytes_via_next_word(dest, || self.try_next_u64())
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn reference() {
135 let mut rng = Xoshiro512PlusPlus::from_seed(Seed512([
136 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,
137 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0,
138 0, 0, 0, 0, 0, 0,
139 ]));
140 let expected = [
143 524291,
144 1048578,
145 539099140,
146 3299073855497,
147 6917532603230064654,
148 7494048333530275843,
149 14418333309547923463,
150 10960079161595355914,
151 18279570946505382726,
152 10209173166699159237,
153 ];
154 for &e in &expected {
155 assert_eq!(rng.next_u64(), e);
156 }
157 }
158
159 #[test]
160 fn zero_seed_maps_to_seed_from_u64_zero() {
161 let from_zero = Xoshiro512PlusPlus::from_seed(Seed512([0u8; 64]));
162 let from_sm0 = Xoshiro512PlusPlus::seed_from_u64(0);
163 assert_eq!(from_zero, from_sm0);
164 }
165
166 #[test]
167 fn state_roundtrip() {
168 let rng = Xoshiro512PlusPlus::seed_from_u64(42);
169 let clone = Xoshiro512PlusPlus::from_seed(rng.state());
170 assert_eq!(clone, rng);
171 }
172}