uwd/utils.rs
1/// Randomly shuffles the elements of a mutable slice in-place using a pseudo-random
2/// number generator seeded by the CPU's timestamp counter (`rdtsc`).
3///
4/// The shuffling algorithm is a variant of the Fisher-Yates shuffle.
5///
6/// # Arguments
7///
8/// * `list` — A mutable slice of elements to be shuffled.
9pub fn shuffle<T>(list: &mut [T]) {
10 let mut seed = rdtsc();
11 for i in (1..list.len()).rev() {
12 seed = seed.wrapping_mul(1103515245).wrapping_add(12345);
13 let j = seed as usize % (i + 1);
14 list.swap(i, j);
15 }
16}
17
18/// Reads the CPU's time-stamp counter using the `rdtsc` instruction, which returns the
19/// number of cycles since the last reset.
20///
21/// This can be used as a fast, low-quality entropy source for seeding simple randomization routines.
22///
23/// # Returns
24///
25/// * The 64-bit timestamp value combining the contents of EDX:EAX registers.
26#[inline(always)]
27fn rdtsc() -> u64 {
28 unsafe {
29 let mut low: u32;
30 let mut high: u32;
31 core::arch::asm!("rdtsc", out("eax") low, out("edx") high);
32 ((high as u64) << 32) | (low as u64)
33 }
34}