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)]
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27pub struct Xoshiro512Plus {
28 s: [u64; 8],
29}
30
31impl Xoshiro512Plus {
32 pub fn jump(&mut self) {
48 impl_jump!(
49 u64,
50 self,
51 [
52 0x33ed89b6e7a353f9,
53 0x760083d7955323be,
54 0x2837f2fbb5f22fae,
55 0x4b8c5674d309511c,
56 0xb11ac47a7ba28c25,
57 0xf1be7667092bcc1c,
58 0x53851efdb6df0aaf,
59 0x1ebbc8b23eaf25db
60 ]
61 );
62 }
63
64 pub fn long_jump(&mut self) {
70 impl_jump!(
71 u64,
72 self,
73 [
74 0x11467fef8f921d28,
75 0xa2a819f2e79c8ea8,
76 0xa8299fc284b3959a,
77 0xb4d347340ca63ee1,
78 0x1cb0940bedbff6ce,
79 0xd956c5c4fa1f8e17,
80 0x915e38fd4eda93bc,
81 0x5b3ccdfa5d7daca5
82 ]
83 );
84 }
85}
86
87impl_state_seed512!(Xoshiro512Plus);
88
89impl SeedableRng for Xoshiro512Plus {
90 type Seed = Seed512;
91
92 #[inline]
95 fn from_seed(seed: Seed512) -> Xoshiro512Plus {
96 Xoshiro512Plus {
97 s: utils::read_words(crate::common::zero_seed_fallback(&seed.0)),
98 }
99 }
100
101 fn seed_from_u64(seed: u64) -> Xoshiro512Plus {
103 from_splitmix!(seed)
104 }
105}
106
107impl TryRng for Xoshiro512Plus {
108 type Error = Infallible;
109
110 #[inline]
111 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
112 Ok((self.next_u64() >> 32) as u32)
115 }
116
117 #[inline]
118 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
119 let result_plus = self.s[0].wrapping_add(self.s[2]);
120 impl_xoshiro_large!(self);
121 Ok(result_plus)
122 }
123
124 #[inline]
125 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
126 utils::fill_bytes_via_next_word(dest, || self.try_next_u64())
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn reference() {
136 #[rustfmt::skip]
137 let mut rng = Xoshiro512Plus::from_seed(Seed512(
138 [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
139 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
140 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,
141 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0]));
142 let expected = [
145 4,
146 8,
147 4113,
148 25169936,
149 52776585412635,
150 57174648719367,
151 9223482039571869716,
152 9331471677901559830,
153 9340533895746033672,
154 14078399799840753678,
155 ];
156 for &e in &expected {
157 assert_eq!(rng.next_u64(), e);
158 }
159 }
160
161 #[test]
162 fn zero_seed_maps_to_seed_from_u64_zero() {
163 let from_zero = Xoshiro512Plus::from_seed(Seed512([0u8; 64]));
164 let from_sm0 = Xoshiro512Plus::seed_from_u64(0);
165 assert_eq!(from_zero, from_sm0);
166 }
167
168 #[test]
169 fn state_roundtrip() {
170 let rng = Xoshiro512Plus::seed_from_u64(42);
171 let clone = Xoshiro512Plus::from_seed(rng.state());
172 assert_eq!(clone, rng);
173 }
174}