1use core::convert::Infallible;
10use rand_core::{Rng, 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 Xoshiro128PlusPlus {
25 s: [u32; 4],
26}
27
28impl Xoshiro128PlusPlus {
29 pub fn jump(&mut self) {
45 impl_jump!(u32, self, [0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b]);
46 }
47
48 pub fn long_jump(&mut self) {
54 impl_jump!(u32, self, [0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662]);
55 }
56}
57
58impl_state_array_of_four!(Xoshiro128PlusPlus, u32);
59
60impl SeedableRng for Xoshiro128PlusPlus {
61 type Seed = [u8; 16];
62
63 #[inline]
66 fn from_seed(seed: [u8; 16]) -> Xoshiro128PlusPlus {
67 Xoshiro128PlusPlus {
68 s: utils::read_words(crate::common::zero_seed_fallback(&seed)),
69 }
70 }
71
72 fn seed_from_u64(seed: u64) -> Xoshiro128PlusPlus {
74 from_splitmix!(seed)
75 }
76}
77
78impl TryRng for Xoshiro128PlusPlus {
79 type Error = Infallible;
80
81 #[inline]
82 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
83 let result_starstar = plusplus_u32!(self.s[0], self.s[3]);
84 impl_xoshiro_u32!(self);
85 Ok(result_starstar)
86 }
87
88 #[inline]
89 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
90 utils::next_u64_via_u32(self)
91 }
92
93 #[inline]
94 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
95 utils::fill_bytes_via_next_word(dest, || self.try_next_u32())
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn reference() {
105 let mut rng =
106 Xoshiro128PlusPlus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]);
107 let expected = [
110 641, 1573767, 3222811527, 3517856514, 836907274, 4247214768, 3867114732, 1355841295,
111 495546011, 621204420,
112 ];
113 for &e in &expected {
114 assert_eq!(rng.next_u32(), e);
115 }
116 }
117
118 #[test]
119 fn test_jump() {
120 let mut rng =
121 Xoshiro128PlusPlus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]);
122 rng.jump();
123 assert_eq!(rng.s[0], 2843103750);
126 assert_eq!(rng.s[1], 2038079848);
127 assert_eq!(rng.s[2], 1533207345);
128 assert_eq!(rng.s[3], 44816753);
129 }
130
131 #[test]
132 fn test_long_jump() {
133 let mut rng =
134 Xoshiro128PlusPlus::from_seed([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]);
135 rng.long_jump();
136 assert_eq!(rng.s[0], 1611968294);
139 assert_eq!(rng.s[1], 2125834322);
140 assert_eq!(rng.s[2], 966769569);
141 assert_eq!(rng.s[3], 3193880526);
142 }
143
144 #[test]
145 fn zero_seed_maps_to_seed_from_u64_zero() {
146 let from_zero = Xoshiro128PlusPlus::from_seed([0u8; 16]);
147 let from_sm0 = Xoshiro128PlusPlus::seed_from_u64(0);
148 assert_eq!(from_zero, from_sm0);
149 }
150
151 #[test]
152 fn state_roundtrip() {
153 let rng = Xoshiro128PlusPlus::seed_from_u64(42);
154 let clone = Xoshiro128PlusPlus::from_seed(rng.state());
155 assert_eq!(clone, rng);
156 }
157}