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 Sfc64 {
39 a: u64,
40 b: u64,
41 c: u64,
42 counter: u64,
43}
44
45impl Sfc64 {
46 #[must_use]
60 #[inline]
61 pub fn new(a: u64, b: u64, c: u64, rounds: Option<u64>) -> Self {
62 let mut state = Self {
63 a,
64 b,
65 c,
66 counter: 1,
67 };
68 let rounds = rounds.unwrap_or(18);
69 for _ in 0..rounds {
70 state.next_u64();
71 }
72 state
73 }
74
75 #[must_use]
96 #[inline]
97 pub fn new_u64(seed: u64, rounds: Option<u64>) -> Self {
98 let (a, b, c) = (seed, seed, seed);
99 let rounds = rounds.or(Some(12));
100 Self::new(a, b, c, rounds)
101 }
102}
103
104impl RngCore for Sfc64 {
105 #[allow(clippy::cast_possible_truncation)]
106 #[inline]
107 fn next_u32(&mut self) -> u32 {
108 self.next_u64() as u32
109 }
110
111 #[inline]
112 fn next_u64(&mut self) -> u64 {
113 const ROTATION: u32 = 24;
114 const RIGHT_SHIFT: u32 = 11;
115 const LEFT_SHIFT: u32 = 3;
116
117 let tmp = self.a.wrapping_add(self.b).wrapping_add(self.counter);
118 self.a = self.b ^ (self.b >> RIGHT_SHIFT);
119 self.b = self.c.wrapping_add(self.c << LEFT_SHIFT);
120 self.c = self.c.rotate_left(ROTATION).wrapping_add(tmp);
121 self.counter = self.counter.wrapping_add(1);
122 tmp
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 Sfc64 {
132 type Seed = [u8; 24];
133
134 #[inline]
135 fn from_seed(seed: Self::Seed) -> Self {
136 let mut s = [u64::default(); 3];
137 le::read_u64_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: [u64; 16] = [
149 0xdb90_9c81_8901_599d,
150 0x8ffd_1953_6521_6f57,
151 0xe8c4_ad5e_258a_c04a,
152 0x8f8e_f2c8_9fdb_63ca,
153 0xf986_5b01_d98d_8e2f,
154 0x4655_5871_a65d_08ba,
155 0x6686_8677_c629_8fcd,
156 0x2ce1_5a7e_6329_f57d,
157 0x0b2f_1833_ca91_ca79,
158 0x4b08_90ac_9bf4_53ca,
159 0xd128_9e0d_ecd4_f85c,
160 0x39ad_57d6_e346_b912,
161 0x98d1_7cc0_0f53_0bda,
162 0x13ac_08e9_8d77_d759,
163 0xcb06_088a_9b16_64a3,
164 0x6a00_df8e_97a8_3fa5,
165 ];
166 static EXPECTED_BYTES_1: [u8; 128] = [
167 0x9d, 0x59, 0x01, 0x89, 0x81, 0x9c, 0x90, 0xdb, 0x57, 0x6f, 0x21, 0x65, 0x53, 0x19, 0xfd,
168 0x8f, 0x4a, 0xc0, 0x8a, 0x25, 0x5e, 0xad, 0xc4, 0xe8, 0xca, 0x63, 0xdb, 0x9f, 0xc8, 0xf2,
169 0x8e, 0x8f, 0x2f, 0x8e, 0x8d, 0xd9, 0x01, 0x5b, 0x86, 0xf9, 0xba, 0x08, 0x5d, 0xa6, 0x71,
170 0x58, 0x55, 0x46, 0xcd, 0x8f, 0x29, 0xc6, 0x77, 0x86, 0x86, 0x66, 0x7d, 0xf5, 0x29, 0x63,
171 0x7e, 0x5a, 0xe1, 0x2c, 0x79, 0xca, 0x91, 0xca, 0x33, 0x18, 0x2f, 0x0b, 0xca, 0x53, 0xf4,
172 0x9b, 0xac, 0x90, 0x08, 0x4b, 0x5c, 0xf8, 0xd4, 0xec, 0x0d, 0x9e, 0x28, 0xd1, 0x12, 0xb9,
173 0x46, 0xe3, 0xd6, 0x57, 0xad, 0x39, 0xda, 0x0b, 0x53, 0x0f, 0xc0, 0x7c, 0xd1, 0x98, 0x59,
174 0xd7, 0x77, 0x8d, 0xe9, 0x08, 0xac, 0x13, 0xa3, 0x64, 0x16, 0x9b, 0x8a, 0x08, 0x06, 0xcb,
175 0xa5, 0x3f, 0xa8, 0x97, 0x8e, 0xdf, 0x00, 0x6a,
176 ];
177
178 const SEED_2: [u8; 24] = [
179 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23,
180 0x01, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
181 ];
182 static EXPECTED_2: [u64; 16] = [
183 0x6de8_9713_e3e2_d060,
184 0x7afc_0f39_1d6a_354d,
185 0x7827_56a8_00e1_098f,
186 0xb91a_7d8c_96ea_b14d,
187 0x6129_e834_d58d_bb5a,
188 0xf7ee_d803_09ca_4e5c,
189 0x1b7c_74c2_b415_d0bd,
190 0xba25_e41a_6615_5825,
191 0x5249_b3b7_0925_f9f3,
192 0x4cd8_cc40_a71d_92b5,
193 0x73b9_0774_f4ed_d216,
194 0xb8e8_17f6_3727_81fe,
195 0x470d_f4fc_f363_f4b2,
196 0x9537_2cb0_387b_c9c5,
197 0x4f3f_01b5_41b1_4300,
198 0x2edf_770d_f7dd_d1c5,
199 ];
200 static EXPECTED_BYTES_2: [u8; 128] = [
201 0x60, 0xd0, 0xe2, 0xe3, 0x13, 0x97, 0xe8, 0x6d, 0x4d, 0x35, 0x6a, 0x1d, 0x39, 0x0f, 0xfc,
202 0x7a, 0x8f, 0x09, 0xe1, 0x00, 0xa8, 0x56, 0x27, 0x78, 0x4d, 0xb1, 0xea, 0x96, 0x8c, 0x7d,
203 0x1a, 0xb9, 0x5a, 0xbb, 0x8d, 0xd5, 0x34, 0xe8, 0x29, 0x61, 0x5c, 0x4e, 0xca, 0x09, 0x03,
204 0xd8, 0xee, 0xf7, 0xbd, 0xd0, 0x15, 0xb4, 0xc2, 0x74, 0x7c, 0x1b, 0x25, 0x58, 0x15, 0x66,
205 0x1a, 0xe4, 0x25, 0xba, 0xf3, 0xf9, 0x25, 0x09, 0xb7, 0xb3, 0x49, 0x52, 0xb5, 0x92, 0x1d,
206 0xa7, 0x40, 0xcc, 0xd8, 0x4c, 0x16, 0xd2, 0xed, 0xf4, 0x74, 0x07, 0xb9, 0x73, 0xfe, 0x81,
207 0x27, 0x37, 0xf6, 0x17, 0xe8, 0xb8, 0xb2, 0xf4, 0x63, 0xf3, 0xfc, 0xf4, 0x0d, 0x47, 0xc5,
208 0xc9, 0x7b, 0x38, 0xb0, 0x2c, 0x37, 0x95, 0x00, 0x43, 0xb1, 0x41, 0xb5, 0x01, 0x3f, 0x4f,
209 0xc5, 0xd1, 0xdd, 0xf7, 0x0d, 0x77, 0xdf, 0x2e,
210 ];
211
212 #[test]
213 fn clone() {
214 let rng = Sfc64::from_seed(Default::default());
215 assert_eq!(rng.clone(), rng);
216 }
217
218 #[test]
219 fn debug() {
220 {
221 let rng = Sfc64::from_seed(Default::default());
222 assert_eq!(
223 format!("{rng:?}"),
224 "Sfc64 { a: 1074220252016367073, b: 14747097319099466665, c: 17960713684764683274, counter: 19 }"
225 );
226 }
227 {
228 let rng = Sfc64::seed_from_u64(1);
229 assert_eq!(
230 format!("{rng:?}"),
231 "Sfc64 { a: 18086042397347456770, b: 1455245525186175675, c: 11873715530299442944, counter: 19 }"
232 );
233 }
234 }
235
236 #[test]
237 fn equality() {
238 assert_eq!(
239 Sfc64::from_seed(Default::default()),
240 Sfc64::from_seed(Default::default())
241 );
242 assert_ne!(
243 Sfc64::from_seed(Default::default()),
244 Sfc64::from_seed([u8::MAX; 24])
245 );
246 }
247
248 #[test]
249 fn new() {
250 {
251 let mut rng = Sfc64::new(u64::default(), u64::default(), u64::default(), None);
252 for e in EXPECTED_1 {
253 assert_eq!(rng.next_u64(), e);
254 }
255 }
256 {
257 let mut rng = Sfc64::new(
258 0x0123_4567_89ab_cdef,
259 0x0123_4567_89ab_cdef,
260 0x0123_4567_89ab_cdef,
261 None,
262 );
263 for e in EXPECTED_2 {
264 assert_eq!(rng.next_u64(), e);
265 }
266 }
267 }
268
269 #[test]
270 fn new_u64() {
271 {
272 let expected = [
281 0x3acf_a029_e3cc_6041,
282 0xf5b6_515b_f2ee_419c,
283 0x1259_6358_94a2_9b61,
284 0x0b6a_e753_95f8_ebd6,
285 0x2256_2228_5ce3_02e2,
286 0x520d_2861_1395_cb21,
287 0xdb90_9c81_8901_599d,
288 0x8ffd_1953_6521_6f57,
289 0xe8c4_ad5e_258a_c04a,
290 0x8f8e_f2c8_9fdb_63ca,
291 0xf986_5b01_d98d_8e2f,
292 0x4655_5871_a65d_08ba,
293 0x6686_8677_c629_8fcd,
294 0x2ce1_5a7e_6329_f57d,
295 0x0b2f_1833_ca91_ca79,
296 0x4b08_90ac_9bf4_53ca,
297 ];
298
299 let mut rng = Sfc64::new_u64(u64::default(), None);
300 for e in expected {
301 assert_eq!(rng.next_u64(), e);
302 }
303 }
304 {
305 let expected = [
314 0x79d7_8afb_e043_8f43,
315 0x9633_06cd_3e6e_830e,
316 0x983b_2a24_d126_ef1b,
317 0x7d89_3205_05df_8c58,
318 0x5542_a718_fe8e_d209,
319 0x17c3_8abf_86a2_c189,
320 0x6de8_9713_e3e2_d060,
321 0x7afc_0f39_1d6a_354d,
322 0x7827_56a8_00e1_098f,
323 0xb91a_7d8c_96ea_b14d,
324 0x6129_e834_d58d_bb5a,
325 0xf7ee_d803_09ca_4e5c,
326 0x1b7c_74c2_b415_d0bd,
327 0xba25_e41a_6615_5825,
328 0x5249_b3b7_0925_f9f3,
329 0x4cd8_cc40_a71d_92b5,
330 ];
331
332 let mut rng = Sfc64::new_u64(0x0123_4567_89ab_cdef, None);
333 for e in expected {
334 assert_eq!(rng.next_u64(), e);
335 }
336 }
337 }
338
339 #[test]
340 fn next_u32() {
341 {
342 let mut rng = Sfc64::from_seed(Default::default());
343 for e in EXPECTED_1 {
344 assert_eq!(rng.next_u32(), e as u32);
345 }
346 }
347 {
348 let mut rng = Sfc64::from_seed(SEED_2);
349 for e in EXPECTED_2 {
350 assert_eq!(rng.next_u32(), e as u32);
351 }
352 }
353 }
354
355 #[test]
356 fn next_u64() {
357 {
358 let mut rng = Sfc64::from_seed(Default::default());
359 for e in EXPECTED_1 {
360 assert_eq!(rng.next_u64(), e);
361 }
362 }
363 {
364 let mut rng = Sfc64::from_seed(SEED_2);
365 for e in EXPECTED_2 {
366 assert_eq!(rng.next_u64(), e);
367 }
368 }
369 {
370 let seed = [
371 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 ];
374 let expected = [
375 0xad6f_dc72_9fee_f3c1,
376 0x2a20_433d_733f_77d5,
377 0x0310_e213_6964_7420,
378 0x331a_176b_c71d_cabc,
379 0x5311_8f35_c249_4d94,
380 0xa3a9_9de7_e77e_16bf,
381 0xa7b1_b70a_3e59_a1ff,
382 0x8e11_27b2_8667_eb3c,
383 0x3fc5_89dc_124c_f6e8,
384 0x81e0_eaaa_ceb8_1d81,
385 0x79f5_3465_2d26_2df6,
386 0x87f7_0c82_14e1_86c5,
387 0x67af_9c00_7b82_5917,
388 0x5134_aec9_998d_8629,
389 0x205a_a249_9406_8634,
390 0x1c76_2918_dba3_e139,
391 ];
392
393 let mut rng = Sfc64::from_seed(seed);
394 for e in expected {
395 assert_eq!(rng.next_u64(), e);
396 }
397 }
398 }
399
400 #[test]
401 fn fill_bytes() {
402 {
403 let mut rng = Sfc64::from_seed(Default::default());
404 let mut dst = [u8::default(); 128];
405 rng.fill_bytes(&mut dst);
406 assert_eq!(dst, EXPECTED_BYTES_1);
407 }
408 {
409 let mut rng = Sfc64::from_seed(SEED_2);
410 let mut dst = [u8::default(); 128];
411 rng.fill_bytes(&mut dst);
412 assert_eq!(dst, EXPECTED_BYTES_2);
413 }
414 }
415
416 #[test]
417 fn fill_bytes_per_chunk() {
418 {
419 let mut rng = Sfc64::from_seed(Default::default());
420 let mut dst = [u8::default(); 8];
421 for e in EXPECTED_BYTES_1.chunks_exact(dst.len()) {
422 rng.fill_bytes(&mut dst);
423 assert_eq!(dst, e);
424 }
425 }
426 {
427 let mut rng = Sfc64::from_seed(SEED_2);
428 let mut dst = [u8::default(); 8];
429 for e in EXPECTED_BYTES_2.chunks_exact(dst.len()) {
430 rng.fill_bytes(&mut dst);
431 assert_eq!(dst, e);
432 }
433 }
434 }
435
436 #[test]
437 fn seed_type() {
438 assert_eq!(
439 any::type_name::<<Sfc64 as SeedableRng>::Seed>(),
440 any::type_name::<[u8; 24]>()
441 );
442 assert_eq!(
443 mem::size_of::<<Sfc64 as SeedableRng>::Seed>(),
444 mem::size_of::<[u8; 24]>()
445 );
446 }
447
448 #[cfg(feature = "serde")]
449 #[test]
450 fn serde() {
451 let mut rng = Sfc64::from_seed(Default::default());
452
453 let json = serde_json::to_string(&rng).unwrap();
454 assert_eq!(
455 json,
456 r#"{"a":1074220252016367073,"b":14747097319099466665,"c":17960713684764683274,"counter":19}"#
457 );
458
459 let mut deserialized_rng = serde_json::from_str::<Sfc64>(&json).unwrap();
460 assert_eq!(deserialized_rng, rng);
461 assert_eq!(deserialized_rng.next_u64(), rng.next_u64());
462 }
463}