1use core::convert::Infallible;
10use rand_core::{SeedableRng, TryRng, utils};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14#[allow(missing_copy_implementations)]
24#[derive(Debug, Clone, PartialEq, Eq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub struct SplitMix64 {
27 x: u64,
28}
29
30const PHI: u64 = 0x9e3779b97f4a7c15;
31
32impl TryRng for SplitMix64 {
33 type Error = Infallible;
34
35 #[inline]
36 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
37 self.x = self.x.wrapping_add(PHI);
38 let mut z = self.x;
39 z = (z ^ (z >> 33)).wrapping_mul(0x62A9D9ED799705F5);
44 z = (z ^ (z >> 28)).wrapping_mul(0xCB24D0A5C88C35B3);
45 Ok((z >> 32) as u32)
46 }
47
48 #[inline]
49 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
50 self.x = self.x.wrapping_add(PHI);
51 let mut z = self.x;
52 z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
53 z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
54 Ok(z ^ (z >> 31))
55 }
56
57 #[inline]
58 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
59 utils::fill_bytes_via_next_word(dest, || self.try_next_u64())
60 }
61}
62
63impl SplitMix64 {
64 pub fn state(&self) -> [u8; 8] {
70 self.x.to_le_bytes()
71 }
72}
73
74impl SeedableRng for SplitMix64 {
75 type Seed = [u8; 8];
76
77 fn from_seed(seed: [u8; 8]) -> SplitMix64 {
79 let state: [_; 1] = utils::read_words(&seed);
80 SplitMix64 { x: state[0] }
81 }
82
83 fn seed_from_u64(seed: u64) -> SplitMix64 {
85 SplitMix64::from_seed(seed.to_le_bytes())
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use rand_core::Rng;
93
94 #[test]
95 fn reference() {
96 let mut rng = SplitMix64::seed_from_u64(1477776061723855037);
97 let expected: [u64; 50] = [
100 1985237415132408290,
101 2979275885539914483,
102 13511426838097143398,
103 8488337342461049707,
104 15141737807933549159,
105 17093170987380407015,
106 16389528042912955399,
107 13177319091862933652,
108 10841969400225389492,
109 17094824097954834098,
110 3336622647361835228,
111 9678412372263018368,
112 11111587619974030187,
113 7882215801036322410,
114 5709234165213761869,
115 7799681907651786826,
116 4616320717312661886,
117 4251077652075509767,
118 7836757050122171900,
119 5054003328188417616,
120 12919285918354108358,
121 16477564761813870717,
122 5124667218451240549,
123 18099554314556827626,
124 7603784838804469118,
125 6358551455431362471,
126 3037176434532249502,
127 3217550417701719149,
128 9958699920490216947,
129 5965803675992506258,
130 12000828378049868312,
131 12720568162811471118,
132 245696019213873792,
133 8351371993958923852,
134 14378754021282935786,
135 5655432093647472106,
136 5508031680350692005,
137 8515198786865082103,
138 6287793597487164412,
139 14963046237722101617,
140 3630795823534910476,
141 8422285279403485710,
142 10554287778700714153,
143 10871906555720704584,
144 8659066966120258468,
145 9420238805069527062,
146 10338115333623340156,
147 13514802760105037173,
148 14635952304031724449,
149 15419692541594102413,
150 ];
151 for &e in expected.iter() {
152 assert_eq!(rng.next_u64(), e);
153 }
154 }
155
156 #[test]
157 fn state_roundtrip() {
158 let rng = SplitMix64::seed_from_u64(42);
159 let clone = SplitMix64::from_seed(rng.state());
160 assert_eq!(clone, rng);
161 }
162
163 #[test]
164 fn next_u32() {
165 let mut rng = SplitMix64::seed_from_u64(10);
166 let expected: [u32; 100] = [
169 3930361779, 4016923089, 4113052479, 925926767, 1755287528, 802865554, 954171070,
170 3724185978, 173676273, 1414488795, 12664133, 1784889697, 1303817078, 261610523,
171 941280008, 2571813643, 2954453492, 378291111, 2546873158, 3923319175, 645257028,
172 3881821278, 2681538690, 3037029984, 1999958137, 1853970361, 2989951788, 2126166628,
173 839962987, 3989679659, 3656977858, 684284364, 1673258011, 170979192, 3037622326,
174 1600748179, 1780764218, 1141430714, 4139736875, 3336905707, 2262051600, 3830850262,
175 2430765325, 1073032139, 1668888979, 2716938970, 4102420032, 40305196, 386350562,
176 2754480591, 622869439, 2129598760, 2306038241, 4218338739, 412298926, 3453855056,
177 3061469690, 4284292697, 994843708, 1591016681, 414726151, 1238182607, 18073498,
178 1237631493, 351884714, 2347486264, 2488990876, 802846256, 645670443, 957607012,
179 3126589776, 1966356370, 3036485766, 868696717, 2808613630, 2070968151, 1025536863,
180 1743949425, 466212687, 2994327271, 209776458, 1246125124, 3344380309, 2203947859,
181 968313105, 2805485302, 197484837, 3472483632, 3931823935, 3288490351, 4165666529,
182 3671080416, 689542830, 1272555356, 1039141475, 3984640460, 4142959054, 2252788890,
183 2459379590, 991872507,
184 ];
185 for &e in expected.iter() {
186 assert_eq!(rng.next_u32(), e);
187 }
188 }
189}