1pub trait Output<S, O> {
2 fn output(s: S) -> O;
3}
4
5#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub struct XshRs;
8
9impl Output<u16, u8> for XshRs {
10 #[inline]
11 fn output(s: u16) -> u8 {
12 let xsh = s ^ (s >> 7);
13 (xsh >> (3 + (s >> 14))) as u8
14 }
15}
16
17impl Output<u32, u16> for XshRs {
18 #[inline]
19 fn output(s: u32) -> u16 {
20 let xsh = s ^ (s >> 11);
21 (xsh >> (11 + (s >> 30))) as u16
22 }
23}
24
25impl Output<u64, u32> for XshRs {
26 #[inline]
27 fn output(s: u64) -> u32 {
28 let xsh = s ^ (s >> 22);
29 (xsh >> (22 + (s >> 61))) as u32
30 }
31}
32
33impl Output<u128, u64> for XshRs {
34 #[inline]
35 fn output(s: u128) -> u64 {
36 let xsh = s ^ (s >> 43);
37 (xsh >> (45 + (s >> 124))) as u64
38 }
39}
40
41#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
43pub struct XshRr;
44
45impl Output<u16, u8> for XshRr {
46 #[inline]
47 fn output(s: u16) -> u8 {
48 let xsh = ((s ^ (s >> 5)) >> 5) as u8;
49 xsh.rotate_right((s >> 13).into())
50 }
51}
52
53impl Output<u32, u16> for XshRr {
54 #[inline]
55 fn output(s: u32) -> u16 {
56 let xsh = ((s ^ (s >> 10)) >> 12) as u16;
57 xsh.rotate_right(s >> 28)
58 }
59}
60
61impl Output<u64, u32> for XshRr {
62 #[inline]
63 fn output(s: u64) -> u32 {
64 let xsh = ((s ^ (s >> 18)) >> 27) as u32;
65 xsh.rotate_right((s >> 59) as u32)
66 }
67}
68
69impl Output<u128, u64> for XshRr {
70 #[inline]
71 fn output(s: u128) -> u64 {
72 let xsh = ((s ^ (s >> 35)) >> 58) as u64;
73 xsh.rotate_right((s >> 122) as u32)
74 }
75}
76
77#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
79pub struct RxsMXs;
80
81impl Output<u8, u8> for RxsMXs {
82 #[inline]
83 fn output(s: u8) -> u8 {
84 let shift = 2 + (s >> 6);
85 let rxs = s ^ (s >> shift);
86 let m = rxs.wrapping_mul(0xd9);
87 m ^ (m >> 6)
88 }
89}
90
91impl Output<u16, u16> for RxsMXs {
92 #[inline]
93 fn output(s: u16) -> u16 {
94 let shift = 3 + (s >> 13);
95 let rxs = s ^ (s >> shift);
96 let m = rxs.wrapping_mul(0xf2d9);
97 m ^ (m >> 11)
98 }
99}
100
101impl Output<u32, u32> for RxsMXs {
102 #[inline]
103 fn output(s: u32) -> u32 {
104 let shift = 4 + (s >> 28);
105 let rxs = s ^ (s >> shift);
106 let m = rxs.wrapping_mul(0x108ef2d9);
107 m ^ (m >> 22)
108 }
109}
110
111impl Output<u64, u64> for RxsMXs {
112 #[inline]
113 fn output(s: u64) -> u64 {
114 let shift = 5 + (s >> 59);
115 let rxs = s ^ (s >> shift);
116 let m = rxs.wrapping_mul(0xaef17502108ef2d9);
117 m ^ (m >> 43)
118 }
119}
120
121impl Output<u128, u128> for RxsMXs {
122 #[inline]
123 fn output(s: u128) -> u128 {
124 let shift = 6 + (s >> 122);
125 let rxs = s ^ (s >> shift);
126 let m = rxs.wrapping_mul(0xf69019274d7f699caef17502108ef2d9);
127 m ^ (m >> 86)
128 }
129}
130
131#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
133pub struct RxsM;
134
135impl Output<u16, u8> for RxsM {
136 #[inline]
137 fn output(s: u16) -> u8 {
138 let shift = 2 + (s >> 14);
139 let rxs = s ^ (s >> shift);
140 (rxs.wrapping_mul(0xf2d9) >> 8) as u8
141 }
142}
143
144impl Output<u32, u16> for RxsM {
145 #[inline]
146 fn output(s: u32) -> u16 {
147 let shift = 3 + (s >> 29);
148 let rxs = s ^ (s >> shift);
149 (rxs.wrapping_mul(0x108ef2d9) >> 16) as u16
150 }
151}
152
153impl Output<u64, u32> for RxsM {
154 #[inline]
155 fn output(s: u64) -> u32 {
156 let shift = 4 + (s >> 60);
157 let rxs = s ^ (s >> shift);
158 (rxs.wrapping_mul(0xaef17502108ef2d9) >> 32) as u32
159 }
160}
161
162impl Output<u128, u64> for RxsM {
163 #[inline]
164 fn output(s: u128) -> u64 {
165 let shift = 5 + (s >> 123);
166 let rxs = s ^ (s >> shift);
167 (rxs.wrapping_mul(0xf69019274d7f699caef17502108ef2d9) >> 64) as u64
168 }
169}
170
171#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
173pub struct Dxsm;
174
175impl Output<u16, u8> for Dxsm {
176 #[inline]
177 fn output(s: u16) -> u8 {
178 let mut h = (s >> 8) as u8;
179 h ^= h >> 4;
180 h = h.wrapping_mul(0x1d);
181 h ^= h >> 6;
182 h.wrapping_mul(s as u8 | 1)
183 }
184}
185
186impl Output<u32, u16> for Dxsm {
187 #[inline]
188 fn output(s: u32) -> u16 {
189 let mut h = (s >> 16) as u16;
190 h ^= h >> 8;
191 h = h.wrapping_mul(0x77b5);
192 h ^= h >> 12;
193 h.wrapping_mul(s as u16 | 1)
194 }
195}
196
197impl Output<u64, u32> for Dxsm {
198 #[inline]
199 fn output(s: u64) -> u32 {
200 let mut h = (s >> 32) as u32;
201 h ^= h >> 16;
202 h = h.wrapping_mul(0x4c957f2d);
203 h ^= h >> 24;
204 h.wrapping_mul(s as u32 | 1)
205 }
206}
207
208impl Output<u128, u64> for Dxsm {
209 #[inline]
210 fn output(s: u128) -> u64 {
211 let mut h = (s >> 64) as u64;
212 h ^= h >> 32;
213 h = h.wrapping_mul(0xda942042e4dd58b5);
214 h ^= h >> 48;
215 h.wrapping_mul(s as u64 | 1)
216 }
217}
218
219#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
221pub struct XslRr;
222
223impl Output<u64, u32> for XslRr {
224 #[inline]
225 fn output(s: u64) -> u32 {
226 let xsl = s ^ (s >> 32);
227 (xsl as u32).rotate_right((s >> 59) as u32)
228 }
229}
230
231impl Output<u128, u64> for XslRr {
232 #[inline]
233 fn output(s: u128) -> u64 {
234 let xsl = s ^ (s >> 64);
235 (xsl as u64).rotate_right((s >> 122) as u32)
236 }
237}
238
239#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
241pub struct XslRrRr;
242
243impl Output<u64, u64> for XslRrRr {
244 #[inline]
245 fn output(s: u64) -> u64 {
246 let xsl = s ^ (s >> 32);
247 let l = (xsl as u32).rotate_right((s >> 59) as u32);
248 let h = ((xsl >> 32) as u32).rotate_right(l & 0b11111);
249 u64::from(l) | (u64::from(h) << 32)
250 }
251}
252
253impl Output<u128, u128> for XslRrRr {
254 #[inline]
255 fn output(s: u128) -> u128 {
256 let xsl = s ^ (s >> 64);
257 let l = (xsl as u64).rotate_right((s >> 122) as u32);
258 let h = ((xsl >> 64) as u64).rotate_right((l & 0b111111) as u32);
259 u128::from(l) | (u128::from(h) << 64)
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use crate::DefaultCheapLcgParameters;
266
267 #[test]
268 #[ignore]
269 fn xsh_rs() {
270 const NAME: &str = "XshRs";
271
272 #[allow(clippy::cast_possible_wrap, clippy::int_plus_one)]
273 fn print(bits: u32, x_bits: u32) {
274 let spare = bits - x_bits;
275
276 let op = if spare as i32 - 5 >= 64 {
277 5
278 } else if spare as i32 - 4 >= 32 {
279 4
280 } else if spare as i32 - 3 >= 16 {
281 3
282 } else if spare as i32 - 2 >= 4 {
283 2
284 } else if spare as i32 - 1 >= 1 {
285 1
286 } else {
287 0
288 };
289
290 let mask = (1 << op) - 1;
291 let max_rand_shift = mask;
292 let top_spare = op;
293 let bottom_spare = spare - top_spare;
294 let x_shift = top_spare + (x_bits + max_rand_shift) / 2;
295
296 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
297 println!(" #[inline]");
298 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
299 println!(" let xsh = s ^ (s >> {x_shift});");
300 println!(
301 " (xsh >> ({} + (s >> {}))) as u{x_bits}",
302 bottom_spare - max_rand_shift,
303 bits - op
304 );
305 println!(" }}");
306 println!("}}");
307 println!();
308 }
309
310 println!("/// high xorshift, followed by a random shift");
311 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
312 println!("pub struct {NAME};");
313 println!();
314
315 print(16, 8);
316 print(32, 16);
317 print(64, 32);
318 print(128, 64);
319 }
320
321 #[test]
322 #[ignore]
323 fn xsh_rr() {
324 const NAME: &str = "XshRr";
325
326 fn print(bits: u32, x_bits: u32) {
327 let spare = bits - x_bits;
328
329 let wanted_op = if x_bits >= 128 {
330 7
331 } else if x_bits >= 64 {
332 6
333 } else if x_bits >= 32 {
334 5
335 } else if x_bits >= 16 {
336 4
337 } else {
338 3
339 };
340
341 let op = if spare >= wanted_op { wanted_op } else { spare };
342 let amplifier = wanted_op - op;
343 assert!(amplifier == 0);
344 let top_spare = op;
345 let bottom_spare = spare - top_spare;
346 let x_shift = (top_spare + x_bits) / 2;
347
348 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
349 println!(" #[inline]");
350 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
351 println!(" let xsh = ((s ^ (s >> {x_shift})) >> {bottom_spare}) as u{x_bits};");
352 println!(" xsh.rotate_right((s >> {}) as u32)", bits - op);
353 println!(" }}");
354 println!("}}");
355 println!();
356 }
357
358 println!("/// high xorshift, followed by a random shift");
359 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
360 println!("pub struct {NAME};");
361 println!();
362
363 print(16, 8);
364 print(32, 16);
365 print(64, 32);
366 print(128, 64);
367 }
368
369 fn multiplier(bits: u32) -> String {
370 const M: u128 = 0xf69019274d7f699caef17502108ef2d9;
371
372 match bits {
373 8 => format!("0x{:02x}", M as u8),
374 16 => format!("0x{:04x}", M as u16),
375 32 => format!("0x{:08x}", M as u32),
376 64 => format!("0x{:016x}", M as u64),
377 128 => format!("0x{M:032x}"),
378 _ => panic!()
379 }
380 }
381
382 #[test]
383 #[ignore]
384 fn rxs_m_xs() {
385 const NAME: &str = "RxsMXs";
386
387 fn print(bits: u32, x_bits: u32) {
388 let op = if x_bits >= 128 {
389 6
390 } else if x_bits >= 64 {
391 5
392 } else if x_bits >= 32 {
393 4
394 } else if x_bits >= 16 {
395 3
396 } else {
397 2
398 };
399
400 let shift = bits - x_bits;
401 assert!(shift == 0);
402
403 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
404 println!(" #[inline]");
405 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
406 println!(" let shift = {} + (s >> {});", op, bits - op);
407 println!(" let rxs = s ^ (s >> shift);");
408 println!(" let m = rxs.wrapping_mul({});", multiplier(bits));
409 println!(" m ^ (m >> {})", (x_bits * 2).div_ceil(3));
410 println!(" }}");
411 println!("}}");
412 println!();
413 }
414
415 println!("/// random xorshift, mcg multiply, fixed xorshift");
416 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
417 println!("pub struct {NAME};");
418 println!();
419
420 print(8, 8);
421 print(16, 16);
422 print(32, 32);
423 print(64, 64);
424 print(128, 128);
425 }
426
427 #[test]
428 #[ignore]
429 fn rxs_m() {
430 const NAME: &str = "RxsM";
431
432 fn print(bits: u32, x_bits: u32) {
433 let op = if x_bits >= 128 {
434 6
435 } else if x_bits >= 64 {
436 5
437 } else if x_bits >= 32 {
438 4
439 } else if x_bits >= 16 {
440 3
441 } else {
442 2
443 };
444
445 let shift = bits - x_bits;
446
447 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
448 println!(" #[inline]");
449 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
450 println!(" let shift = {} + (s >> {});", op, bits - op);
451 println!(" let rxs = s ^ (s >> shift);");
452 println!(" (rxs.wrapping_mul({}) >> {shift}) as u{x_bits}", multiplier(bits));
453 println!(" }}");
454 println!("}}");
455 println!();
456 }
457
458 println!("/// random xorshift, mcg multiply");
459 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
460 println!("pub struct {NAME};");
461 println!();
462
463 print(16, 8);
464 print(32, 16);
465 print(64, 32);
466 print(128, 64);
467 }
468
469 #[test]
470 #[ignore]
471 fn dxsm() {
472 const NAME: &str = "Dxsm";
473
474 fn print(bits: u32, x_bits: u32) {
475 assert!(x_bits == bits / 2);
476
477 let multiplier = match bits {
478 16 => format!("0x{:02x}", DefaultCheapLcgParameters::<u16>::multiplier() as u8),
479 32 => format!("0x{:04x}", DefaultCheapLcgParameters::<u32>::multiplier() as u16),
480 64 => {
481 format!("0x{:08x}", DefaultCheapLcgParameters::<u64>::multiplier() as u32)
482 }
483 128 => {
484 format!("0x{:016x}", DefaultCheapLcgParameters::<u128>::multiplier() as u64)
485 }
486 _ => panic!()
487 };
488
489 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
490 println!(" #[inline]");
491 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
492 println!(" let mut h = (s >> {}) as u{x_bits};", x_bits);
493 println!(" h ^= h >> {};", x_bits / 2);
494 println!(" h = h.wrapping_mul({multiplier});");
495 println!(" h ^= h >> {};", (x_bits / 4) * 3);
496 println!(" h.wrapping_mul(s as u{x_bits} | 1)");
497 println!(" }}");
498 println!("}}");
499 println!();
500 }
501
502 println!("/// double xorshift multiply");
503 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
504 println!("pub struct {NAME};");
505 println!();
506
507 print(16, 8);
508 print(32, 16);
509 print(64, 32);
510 print(128, 64);
511 }
512
513 #[test]
514 #[ignore]
515 fn xsl_rr() {
516 const NAME: &str = "XslRr";
517
518 fn print(bits: u32, x_bits: u32) {
519 let spare = bits - x_bits;
520
521 let wanted_op = if x_bits >= 128 {
522 7
523 } else if x_bits >= 64 {
524 6
525 } else if x_bits >= 32 {
526 5
527 } else if x_bits >= 16 {
528 4
529 } else {
530 3
531 };
532
533 let op = if spare >= wanted_op { wanted_op } else { spare };
534 let amplifier = wanted_op - op;
535 assert!(amplifier == 0);
536 let top_spare = spare;
537 let bottom_spare = spare - top_spare;
538 assert!(bottom_spare == 0);
539 let x_shift = (top_spare + x_bits) / 2;
540
541 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
542 println!(" #[inline]");
543 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
544 println!(" let xsl = s ^ (s >> {x_shift});");
545 println!(" (xsl as u{x_bits}).rotate_right((s >> {}) as u32)", bits - op);
546 println!(" }}");
547 println!("}}");
548 println!();
549 }
550
551 println!("/// fixed xorshift (to low bits), random rotate");
552 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
553 println!("pub struct {NAME};");
554 println!();
555
556 print(64, 32);
557 print(128, 64);
558 }
559
560 #[test]
561 #[ignore]
562 fn xsl_rr_rr() {
563 const NAME: &str = "XslRrRr";
564
565 fn print(bits: u32, x_bits: u32) {
566 assert!(bits == x_bits);
567 let spare = bits - bits / 2;
568
569 let wanted_op = if bits / 2 >= 128 {
570 7
571 } else if bits / 2 >= 64 {
572 6
573 } else if bits / 2 >= 32 {
574 5
575 } else if bits / 2 >= 16 {
576 4
577 } else {
578 3
579 };
580
581 let op = if spare >= wanted_op { wanted_op } else { spare };
582 let amplifier = wanted_op - op;
583 assert!(amplifier == 0);
584 let top_spare = spare;
585 let x_shift = (top_spare + bits / 2) / 2;
586
587 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
588 println!(" #[inline]");
589 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
590 println!(" let xsl = s ^ (s >> {x_shift});");
591 println!(" let l = (xsl as u{}).rotate_right((s >> {}) as u32);", bits / 2, bits - op);
592 println!(
593 " let h = ((xsl >> {top_spare}) as u{}).rotate_right((l & 0b{:b}) as u32);",
594 bits / 2,
595 (1 << op) - 1
596 );
597 println!(" u{x_bits}::from(l) | (u{x_bits}::from(h) << {top_spare})");
598 println!(" }}");
599 println!("}}");
600 println!();
601 }
602
603 println!("/// fixed xorshift (to low bits), random rotate (both parts)");
604 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
605 println!("pub struct {NAME};");
606 println!();
607
608 print(64, 64);
609 print(128, 128);
610 }
611}