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 Dxsm;
134
135impl Output<u16, u8> for Dxsm {
136 #[inline]
137 fn output(s: u16) -> u8 {
138 let mut h = (s >> 8) as u8;
139 h ^= h >> 4;
140 h = h.wrapping_mul(0x1d);
141 h ^= h >> 6;
142 h.wrapping_mul(s as u8 | 1)
143 }
144}
145
146impl Output<u32, u16> for Dxsm {
147 #[inline]
148 fn output(s: u32) -> u16 {
149 let mut h = (s >> 16) as u16;
150 h ^= h >> 8;
151 h = h.wrapping_mul(0x77b5);
152 h ^= h >> 12;
153 h.wrapping_mul(s as u16 | 1)
154 }
155}
156
157impl Output<u64, u32> for Dxsm {
158 #[inline]
159 fn output(s: u64) -> u32 {
160 let mut h = (s >> 32) as u32;
161 h ^= h >> 16;
162 h = h.wrapping_mul(0x4c957f2d);
163 h ^= h >> 24;
164 h.wrapping_mul(s as u32 | 1)
165 }
166}
167
168impl Output<u128, u64> for Dxsm {
169 #[inline]
170 fn output(s: u128) -> u64 {
171 let mut h = (s >> 64) as u64;
172 h ^= h >> 32;
173 h = h.wrapping_mul(0xda942042e4dd58b5);
174 h ^= h >> 48;
175 h.wrapping_mul(s as u64 | 1)
176 }
177}
178
179#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
181pub struct XslRr;
182
183impl Output<u64, u32> for XslRr {
184 #[inline]
185 fn output(s: u64) -> u32 {
186 let xsl = s ^ (s >> 32);
187 (xsl as u32).rotate_right((s >> 59) as u32)
188 }
189}
190
191impl Output<u128, u64> for XslRr {
192 #[inline]
193 fn output(s: u128) -> u64 {
194 let xsl = s ^ (s >> 64);
195 (xsl as u64).rotate_right((s >> 122) as u32)
196 }
197}
198
199#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
201pub struct XslRrRr;
202
203impl Output<u64, u64> for XslRrRr {
204 #[inline]
205 fn output(s: u64) -> u64 {
206 let xsl = s ^ (s >> 32);
207 let l = (xsl as u32).rotate_right((s >> 59) as u32);
208 let h = ((xsl >> 32) as u32).rotate_right(l & 0b11111);
209 u64::from(l) | (u64::from(h) << 32)
210 }
211}
212
213impl Output<u128, u128> for XslRrRr {
214 #[inline]
215 fn output(s: u128) -> u128 {
216 let xsl = s ^ (s >> 64);
217 let l = (xsl as u64).rotate_right((s >> 122) as u32);
218 let h = ((xsl >> 64) as u64).rotate_right((l & 0b111111) as u32);
219 u128::from(l) | (u128::from(h) << 64)
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use crate::DefaultCheapLcgParameters;
226
227 #[test]
228 #[ignore]
229 fn xsh_rs() {
230 const NAME: &str = "XshRs";
231
232 #[allow(clippy::cast_possible_wrap, clippy::int_plus_one)]
233 fn print(bits: u32, x_bits: u32) {
234 let spare = bits - x_bits;
235
236 let op = if spare as i32 - 5 >= 64 {
237 5
238 } else if spare as i32 - 4 >= 32 {
239 4
240 } else if spare as i32 - 3 >= 16 {
241 3
242 } else if spare as i32 - 2 >= 4 {
243 2
244 } else if spare as i32 - 1 >= 1 {
245 1
246 } else {
247 0
248 };
249
250 let mask = (1 << op) - 1;
251 let max_rand_shift = mask;
252 let top_spare = op;
253 let bottom_spare = spare - top_spare;
254 let x_shift = top_spare + (x_bits + max_rand_shift) / 2;
255
256 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
257 println!(" #[inline]");
258 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
259 println!(" let xsh = s ^ (s >> {x_shift});");
260 println!(
261 " (xsh >> ({} + (s >> {}))) as u{x_bits}",
262 bottom_spare - max_rand_shift,
263 bits - op
264 );
265 println!(" }}");
266 println!("}}");
267 println!();
268 }
269
270 println!("/// high xorshift, followed by a random shift");
271 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
272 println!("pub struct {NAME};");
273 println!();
274
275 print(16, 8);
276 print(32, 16);
277 print(64, 32);
278 print(128, 64);
279 }
280
281 #[test]
282 #[ignore]
283 fn xsh_rr() {
284 const NAME: &str = "XshRr";
285
286 fn print(bits: u32, x_bits: u32) {
287 let spare = bits - x_bits;
288
289 let wanted_op = if x_bits >= 128 {
290 7
291 } else if x_bits >= 64 {
292 6
293 } else if x_bits >= 32 {
294 5
295 } else if x_bits >= 16 {
296 4
297 } else {
298 3
299 };
300
301 let op = if spare >= wanted_op { wanted_op } else { spare };
302 let amplifier = wanted_op - op;
303 assert!(amplifier == 0);
304 let top_spare = op;
305 let bottom_spare = spare - top_spare;
306 let x_shift = (top_spare + x_bits) / 2;
307
308 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
309 println!(" #[inline]");
310 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
311 println!(" let xsh = ((s ^ (s >> {x_shift})) >> {bottom_spare}) as u{x_bits};");
312 println!(" xsh.rotate_right((s >> {}) as u32)", bits - op);
313 println!(" }}");
314 println!("}}");
315 println!();
316 }
317
318 println!("/// high xorshift, followed by a random shift");
319 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
320 println!("pub struct {NAME};");
321 println!();
322
323 print(16, 8);
324 print(32, 16);
325 print(64, 32);
326 print(128, 64);
327 }
328
329 fn multiplier(bits: u32) -> String {
330 const M: u128 = 0xf69019274d7f699caef17502108ef2d9;
331
332 match bits {
333 8 => format!("0x{:02x}", M as u8),
334 16 => format!("0x{:04x}", M as u16),
335 32 => format!("0x{:08x}", M as u32),
336 64 => format!("0x{:016x}", M as u64),
337 128 => format!("0x{M:032x}"),
338 _ => panic!()
339 }
340 }
341
342 #[test]
343 #[ignore]
344 fn rxs_m_xs() {
345 const NAME: &str = "RxsMXs";
346
347 fn print(bits: u32, x_bits: u32) {
348 let op = if x_bits >= 128 {
349 6
350 } else if x_bits >= 64 {
351 5
352 } else if x_bits >= 32 {
353 4
354 } else if x_bits >= 16 {
355 3
356 } else {
357 2
358 };
359
360 let shift = bits - x_bits;
361 assert!(shift == 0);
362
363 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
364 println!(" #[inline]");
365 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
366 println!(" let shift = {} + (s >> {});", op, bits - op);
367 println!(" let rxs = s ^ (s >> shift);");
368 println!(" let m = rxs.wrapping_mul({});", multiplier(bits));
369 println!(" m ^ (m >> {})", (x_bits * 2).div_ceil(3));
370 println!(" }}");
371 println!("}}");
372 println!();
373 }
374
375 println!("/// random xorshift, mcg multiply, fixed xorshift");
376 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
377 println!("pub struct {NAME};");
378 println!();
379
380 print(8, 8);
381 print(16, 16);
382 print(32, 32);
383 print(64, 64);
384 print(128, 128);
385 }
386
387 #[test]
388 #[ignore]
389 fn dxsm() {
390 const NAME: &str = "Dxsm";
391
392 fn print(bits: u32, x_bits: u32) {
393 assert!(x_bits == bits / 2);
394
395 let multiplier = match bits {
396 16 => format!("0x{:02x}", DefaultCheapLcgParameters::<u16>::multiplier() as u8),
397 32 => format!("0x{:04x}", DefaultCheapLcgParameters::<u32>::multiplier() as u16),
398 64 => {
399 format!("0x{:08x}", DefaultCheapLcgParameters::<u64>::multiplier() as u32)
400 }
401 128 => {
402 format!("0x{:016x}", DefaultCheapLcgParameters::<u128>::multiplier() as u64)
403 }
404 _ => panic!()
405 };
406
407 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
408 println!(" #[inline]");
409 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
410 println!(" let mut h = (s >> {}) as u{x_bits};", x_bits);
411 println!(" h ^= h >> {};", x_bits / 2);
412 println!(" h = h.wrapping_mul({multiplier});");
413 println!(" h ^= h >> {};", (x_bits / 4) * 3);
414 println!(" h.wrapping_mul(s as u{x_bits} | 1)");
415 println!(" }}");
416 println!("}}");
417 println!();
418 }
419
420 println!("/// double xorshift multiply");
421 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
422 println!("pub struct {NAME};");
423 println!();
424
425 print(16, 8);
426 print(32, 16);
427 print(64, 32);
428 print(128, 64);
429 }
430
431 #[test]
432 #[ignore]
433 fn xsl_rr() {
434 const NAME: &str = "XslRr";
435
436 fn print(bits: u32, x_bits: u32) {
437 let spare = bits - x_bits;
438
439 let wanted_op = if x_bits >= 128 {
440 7
441 } else if x_bits >= 64 {
442 6
443 } else if x_bits >= 32 {
444 5
445 } else if x_bits >= 16 {
446 4
447 } else {
448 3
449 };
450
451 let op = if spare >= wanted_op { wanted_op } else { spare };
452 let amplifier = wanted_op - op;
453 assert!(amplifier == 0);
454 let top_spare = spare;
455 let bottom_spare = spare - top_spare;
456 assert!(bottom_spare == 0);
457 let x_shift = (top_spare + x_bits) / 2;
458
459 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
460 println!(" #[inline]");
461 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
462 println!(" let xsl = s ^ (s >> {x_shift});");
463 println!(" (xsl as u{x_bits}).rotate_right((s >> {}) as u32)", bits - op);
464 println!(" }}");
465 println!("}}");
466 println!();
467 }
468
469 println!("/// fixed xorshift (to low bits), random rotate");
470 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
471 println!("pub struct {NAME};");
472 println!();
473
474 print(64, 32);
475 print(128, 64);
476 }
477
478 #[test]
479 #[ignore]
480 fn xsl_rr_rr() {
481 const NAME: &str = "XslRrRr";
482
483 fn print(bits: u32, x_bits: u32) {
484 assert!(bits == x_bits);
485 let spare = bits - bits / 2;
486
487 let wanted_op = if bits / 2 >= 128 {
488 7
489 } else if bits / 2 >= 64 {
490 6
491 } else if bits / 2 >= 32 {
492 5
493 } else if bits / 2 >= 16 {
494 4
495 } else {
496 3
497 };
498
499 let op = if spare >= wanted_op { wanted_op } else { spare };
500 let amplifier = wanted_op - op;
501 assert!(amplifier == 0);
502 let top_spare = spare;
503 let x_shift = (top_spare + bits / 2) / 2;
504
505 println!("impl Output<u{bits}, u{x_bits}> for {NAME} {{");
506 println!(" #[inline]");
507 println!(" fn output(s: u{bits}) -> u{x_bits} {{");
508 println!(" let xsl = s ^ (s >> {x_shift});");
509 println!(" let l = (xsl as u{}).rotate_right((s >> {}) as u32);", bits / 2, bits - op);
510 println!(
511 " let h = ((xsl >> {top_spare}) as u{}).rotate_right((l & 0b{:b}) as u32);",
512 bits / 2,
513 (1 << op) - 1
514 );
515 println!(" u{x_bits}::from(l) | (u{x_bits}::from(h) << {top_spare})");
516 println!(" }}");
517 println!("}}");
518 println!();
519 }
520
521 println!("/// fixed xorshift (to low bits), random rotate (both parts)");
522 println!("#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]");
523 println!("pub struct {NAME};");
524 println!();
525
526 print(64, 64);
527 print(128, 128);
528 }
529}