1use rand_core::{RngCore, SeedableRng, impls, le};
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11#[derive(Clone, Debug, Eq, PartialEq)]
37#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
38pub struct Sfc32 {
39 a: u32,
40 b: u32,
41 c: u32,
42 counter: u32,
43}
44
45impl Sfc32 {
46 #[must_use]
60 #[inline]
61 pub fn new(a: u32, b: u32, c: u32, rounds: Option<u32>) -> Self {
62 let mut state = Self {
63 a,
64 b,
65 c,
66 counter: 1,
67 };
68 let rounds = rounds.unwrap_or(15);
69 for _ in 0..rounds {
70 state.next_u32();
71 }
72 state
73 }
74
75 #[allow(clippy::cast_possible_truncation)]
76 #[must_use]
97 #[inline]
98 pub fn new_u64(seed: u64, rounds: Option<u32>) -> Self {
99 let (a, b, c) = (0, seed as u32, (seed >> u32::BITS) as u32);
100 let rounds = rounds.or(Some(12));
101 Self::new(a, b, c, rounds)
102 }
103}
104
105impl RngCore for Sfc32 {
106 #[inline]
107 fn next_u32(&mut self) -> u32 {
108 const ROTATION: u32 = 21;
109 const RIGHT_SHIFT: u32 = 9;
110 const LEFT_SHIFT: u32 = 3;
111
112 let tmp = self.a.wrapping_add(self.b).wrapping_add(self.counter);
113 self.a = self.b ^ (self.b >> RIGHT_SHIFT);
114 self.b = self.c.wrapping_add(self.c << LEFT_SHIFT);
115 self.c = self.c.rotate_left(ROTATION).wrapping_add(tmp);
116 self.counter = self.counter.wrapping_add(1);
117 tmp
118 }
119
120 #[inline]
121 fn next_u64(&mut self) -> u64 {
122 impls::next_u64_via_u32(self)
123 }
124
125 #[inline]
126 fn fill_bytes(&mut self, dst: &mut [u8]) {
127 impls::fill_bytes_via_next(self, dst);
128 }
129}
130
131impl SeedableRng for Sfc32 {
132 type Seed = [u8; 12];
133
134 #[inline]
135 fn from_seed(seed: Self::Seed) -> Self {
136 let mut s = [u32::default(); 3];
137 le::read_u32_into(&seed, &mut s);
138 Self::new(s[0], s[1], s[2], None)
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use core::{any, mem};
145
146 use super::*;
147
148 static EXPECTED_1: [u32; 16] = [
149 0xfb52_c520,
150 0x3880_2be1,
151 0x9482_79e6,
152 0xec4b_f1d9,
153 0x7cb0_a909,
154 0xfad8_b4a8,
155 0x3ca4_b808,
156 0x3821_b4c5,
157 0x5e70_23ca,
158 0x50f2_6bf7,
159 0xf1e1_b0a2,
160 0x6163_032f,
161 0x3bf3_c9a4,
162 0x6db6_c5e0,
163 0x5733_1c8c,
164 0x2aaf_9993,
165 ];
166 static EXPECTED_BYTES_1: [u8; 64] = [
167 0x20, 0xc5, 0x52, 0xfb, 0xe1, 0x2b, 0x80, 0x38, 0xe6, 0x79, 0x82, 0x94, 0xd9, 0xf1, 0x4b,
168 0xec, 0x09, 0xa9, 0xb0, 0x7c, 0xa8, 0xb4, 0xd8, 0xfa, 0x08, 0xb8, 0xa4, 0x3c, 0xc5, 0xb4,
169 0x21, 0x38, 0xca, 0x23, 0x70, 0x5e, 0xf7, 0x6b, 0xf2, 0x50, 0xa2, 0xb0, 0xe1, 0xf1, 0x2f,
170 0x03, 0x63, 0x61, 0xa4, 0xc9, 0xf3, 0x3b, 0xe0, 0xc5, 0xb6, 0x6d, 0x8c, 0x1c, 0x33, 0x57,
171 0x93, 0x99, 0xaf, 0x2a,
172 ];
173
174 const SEED_2: [u8; 12] = [
175 0x00, 0x00, 0x00, 0x00, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
176 ];
177 static EXPECTED_2: [u32; 16] = [
178 0x35e0_5b54,
179 0x4c62_7ca1,
180 0x33a0_43e2,
181 0xb611_3c67,
182 0x7cab_9699,
183 0x4a52_efeb,
184 0x5936_797f,
185 0x139e_2b9f,
186 0xc7df_3db1,
187 0x61ce_1717,
188 0x5581_e344,
189 0xbc30_16ea,
190 0xa6bf_d381,
191 0xcfed_5524,
192 0x8a34_536c,
193 0x3e3f_a43b,
194 ];
195 static EXPECTED_BYTES_2: [u8; 64] = [
196 0x54, 0x5b, 0xe0, 0x35, 0xa1, 0x7c, 0x62, 0x4c, 0xe2, 0x43, 0xa0, 0x33, 0x67, 0x3c, 0x11,
197 0xb6, 0x99, 0x96, 0xab, 0x7c, 0xeb, 0xef, 0x52, 0x4a, 0x7f, 0x79, 0x36, 0x59, 0x9f, 0x2b,
198 0x9e, 0x13, 0xb1, 0x3d, 0xdf, 0xc7, 0x17, 0x17, 0xce, 0x61, 0x44, 0xe3, 0x81, 0x55, 0xea,
199 0x16, 0x30, 0xbc, 0x81, 0xd3, 0xbf, 0xa6, 0x24, 0x55, 0xed, 0xcf, 0x6c, 0x53, 0x34, 0x8a,
200 0x3b, 0xa4, 0x3f, 0x3e,
201 ];
202
203 #[test]
204 fn clone() {
205 let rng = Sfc32::from_seed(Default::default());
206 assert_eq!(rng.clone(), rng);
207 }
208
209 #[test]
210 fn debug() {
211 {
212 let rng = Sfc32::from_seed(Default::default());
213 assert_eq!(
214 format!("{rng:?}"),
215 "Sfc32 { a: 3033783054, b: 1182722562, c: 4269119441, counter: 16 }"
216 );
217 }
218 {
219 let rng = Sfc32::seed_from_u64(1);
220 assert_eq!(
221 format!("{rng:?}"),
222 "Sfc32 { a: 163349985, b: 1519831815, c: 3040613532, counter: 16 }"
223 );
224 }
225 }
226
227 #[test]
228 fn equality() {
229 assert_eq!(
230 Sfc32::from_seed(Default::default()),
231 Sfc32::from_seed(Default::default())
232 );
233 assert_ne!(
234 Sfc32::from_seed(Default::default()),
235 Sfc32::from_seed([u8::MAX; 12])
236 );
237 }
238
239 #[test]
240 fn new() {
241 {
242 let mut rng = Sfc32::new(u32::default(), u32::default(), u32::default(), None);
243 for e in EXPECTED_1 {
244 assert_eq!(rng.next_u32(), e);
245 }
246 }
247 {
248 let mut rng = Sfc32::new(u32::default(), 0x89ab_cdef, 0x0123_4567, None);
249 for e in EXPECTED_2 {
250 assert_eq!(rng.next_u32(), e);
251 }
252 }
253 }
254
255 #[test]
256 fn new_u64() {
257 {
258 let expected = [
267 0x5146_76c3,
268 0x08a8_09df,
269 0x3034_9d2b,
270 0xfb52_c520,
271 0x3880_2be1,
272 0x9482_79e6,
273 0xec4b_f1d9,
274 0x7cb0_a909,
275 0xfad8_b4a8,
276 0x3ca4_b808,
277 0x3821_b4c5,
278 0x5e70_23ca,
279 0x50f2_6bf7,
280 0xf1e1_b0a2,
281 0x6163_032f,
282 0x3bf3_c9a4,
283 ];
284
285 let mut rng = Sfc32::new_u64(u64::default(), None);
286 for e in expected {
287 assert_eq!(rng.next_u32(), e);
288 }
289 }
290 {
291 let expected = [
300 0x8471_2d97,
301 0xf5a3_d9c8,
302 0x5cd0_a295,
303 0x35e0_5b54,
304 0x4c62_7ca1,
305 0x33a0_43e2,
306 0xb611_3c67,
307 0x7cab_9699,
308 0x4a52_efeb,
309 0x5936_797f,
310 0x139e_2b9f,
311 0xc7df_3db1,
312 0x61ce_1717,
313 0x5581_e344,
314 0xbc30_16ea,
315 0xa6bf_d381,
316 ];
317
318 let mut rng = Sfc32::new_u64(0x0123_4567_89ab_cdef, None);
319 for e in expected {
320 assert_eq!(rng.next_u32(), e);
321 }
322 }
323 }
324
325 #[test]
326 fn next_u32() {
327 {
328 let mut rng = Sfc32::from_seed(Default::default());
329 for e in EXPECTED_1 {
330 assert_eq!(rng.next_u32(), e);
331 }
332 }
333 {
334 let mut rng = Sfc32::from_seed(SEED_2);
335 for e in EXPECTED_2 {
336 assert_eq!(rng.next_u32(), e);
337 }
338 }
339 {
340 let seed = [
341 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
342 ];
343 let expected = [
344 0x03b8_0bb8,
345 0xa87d_bc7e,
346 0x1787_178c,
347 0x4c7b_7234,
348 0xc65d_ade2,
349 0x2c69_2349,
350 0xf52c_2153,
351 0xdf09_8072,
352 0x9d49_b03c,
353 0x9562_381a,
354 0xc9b4_1738,
355 0x64b7_5e54,
356 0x36ce_9b32,
357 0xf106_947e,
358 0x0afc_726b,
359 0x549b_bc87,
360 ];
361
362 let mut rng = Sfc32::from_seed(seed);
363 for e in expected {
364 assert_eq!(rng.next_u32(), e);
365 }
366 }
367 }
368
369 #[test]
370 fn next_u64() {
371 {
372 let mut rng = Sfc32::from_seed(Default::default());
373 for e in EXPECTED_1.map(u64::from).chunks_exact(2) {
374 assert_eq!(rng.next_u64(), (e[1] << u32::BITS) | e[0]);
375 }
376 }
377 {
378 let mut rng = Sfc32::from_seed(SEED_2);
379 for e in EXPECTED_2.map(u64::from).chunks_exact(2) {
380 assert_eq!(rng.next_u64(), (e[1] << u32::BITS) | e[0]);
381 }
382 }
383 }
384
385 #[test]
386 fn fill_bytes() {
387 {
388 let mut rng = Sfc32::from_seed(Default::default());
389 let mut dst = [u8::default(); 64];
390 rng.fill_bytes(&mut dst);
391 assert_eq!(dst, EXPECTED_BYTES_1);
392 }
393 {
394 let mut rng = Sfc32::from_seed(SEED_2);
395 let mut dst = [u8::default(); 64];
396 rng.fill_bytes(&mut dst);
397 assert_eq!(dst, EXPECTED_BYTES_2);
398 }
399 }
400
401 #[test]
402 fn fill_bytes_per_chunk() {
403 {
404 let mut rng = Sfc32::from_seed(Default::default());
405 let mut dst = [u8::default(); 4];
406 for e in EXPECTED_BYTES_1.chunks_exact(dst.len()) {
407 rng.fill_bytes(&mut dst);
408 assert_eq!(dst, e);
409 }
410 }
411 {
412 let mut rng = Sfc32::from_seed(SEED_2);
413 let mut dst = [u8::default(); 4];
414 for e in EXPECTED_BYTES_2.chunks_exact(dst.len()) {
415 rng.fill_bytes(&mut dst);
416 assert_eq!(dst, e);
417 }
418 }
419 }
420
421 #[test]
422 fn seed_type() {
423 assert_eq!(
424 any::type_name::<<Sfc32 as SeedableRng>::Seed>(),
425 any::type_name::<[u8; 12]>()
426 );
427 assert_eq!(
428 mem::size_of::<<Sfc32 as SeedableRng>::Seed>(),
429 mem::size_of::<[u8; 12]>()
430 );
431 }
432
433 #[cfg(feature = "serde")]
434 #[test]
435 fn serde() {
436 let mut rng = Sfc32::from_seed(Default::default());
437
438 let json = serde_json::to_string(&rng).unwrap();
439 assert_eq!(
440 json,
441 r#"{"a":3033783054,"b":1182722562,"c":4269119441,"counter":16}"#
442 );
443
444 let mut deserialized_rng = serde_json::from_str::<Sfc32>(&json).unwrap();
445 assert_eq!(deserialized_rng, rng);
446 assert_eq!(deserialized_rng.next_u32(), rng.next_u32());
447 }
448}