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 Xoshiro512StarStar {
27 s: [u64; 8],
28}
29
30impl Xoshiro512StarStar {
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!(Xoshiro512StarStar);
87
88impl SeedableRng for Xoshiro512StarStar {
89 type Seed = Seed512;
90
91 #[inline]
94 fn from_seed(seed: Seed512) -> Xoshiro512StarStar {
95 Xoshiro512StarStar {
96 s: utils::read_words(crate::common::zero_seed_fallback(&seed.0)),
97 }
98 }
99
100 fn seed_from_u64(seed: u64) -> Xoshiro512StarStar {
102 from_splitmix!(seed)
103 }
104}
105
106impl TryRng for Xoshiro512StarStar {
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_starstar = starstar_u64!(self.s[1]);
119 impl_xoshiro_large!(self);
120 Ok(result_starstar)
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 #[rustfmt::skip]
135 fn reference() {
136 let mut rng = Xoshiro512StarStar::from_seed(Seed512(
137 [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
138 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
139 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,
140 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0]));
141 let expected = [
144 11520,
145 0,
146 23040,
147 23667840,
148 144955163520,
149 303992986974289920,
150 25332796375735680,
151 296904390158016,
152 13911081092387501979,
153 15304787717237593024,
154 ];
155 for &e in &expected {
156 assert_eq!(rng.next_u64(), e);
157 }
158 }
159
160 #[test]
161 fn zero_seed_maps_to_seed_from_u64_zero() {
162 let from_zero = Xoshiro512StarStar::from_seed(Seed512([0u8; 64]));
163 let from_sm0 = Xoshiro512StarStar::seed_from_u64(0);
164 assert_eq!(from_zero, from_sm0);
165 }
166
167 #[test]
168 fn state_roundtrip() {
169 let rng = Xoshiro512StarStar::seed_from_u64(42);
170 let clone = Xoshiro512StarStar::from_seed(rng.state());
171 assert_eq!(clone, rng);
172 }
173}