Next Generation WASM Microkernel Operating System
wasm
os
rust
microkernel
1// Copyright 2025 Jonas Kruckenberg
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! Very small, fast, non-cryptographic random number generator.
9//!
10//! This random number generator implements the `xorshift64+` algorithm, generating random numbers
11//! adding two 32-bit `xorshift` sequences together.
12
13#![cfg_attr(not(test), no_std)]
14
15/// Fast, non-cryptographic random number generator.
16///
17/// Implement `xorshift64+`: 2 32-bit `xorshift` sequences added together.
18/// Shift triplet `[17,7,16]` was calculated as indicated in Marsaglia's
19/// `Xorshift` paper: <https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf>
20/// This generator passes the SmallCrush suite, part of TestU01 framework:
21/// <http://simul.iro.umontreal.ca/testu01/tu01.html>
22#[derive(Clone, Copy, Debug)]
23pub struct FastRand {
24 one: u32,
25 two: u32,
26}
27
28impl FastRand {
29 /// Initializes a new, thread-local, fast random number generator from the provided seed.
30 pub fn from_seed(seed: u64) -> FastRand {
31 let one = (seed >> 32_u64) as u32;
32 #[expect(
33 clippy::cast_possible_truncation,
34 reason = "we actually want to truncate here"
35 )]
36 let mut two = seed as u32;
37
38 if two == 0 {
39 // This value cannot be zero
40 two = 1;
41 }
42
43 FastRand { one, two }
44 }
45
46 /// Generate a random `u32` between `0` and `n`.
47 pub fn fastrand_n(&mut self, n: u32) -> u32 {
48 // This is similar to fastrand() % n, but faster.
49 // See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
50 let mul = u64::from(self.fastrand()).wrapping_mul(u64::from(n));
51 (mul >> 32) as u32
52 }
53
54 /// Generate a random `u32` number.
55 pub fn fastrand(&mut self) -> u32 {
56 let mut s1 = self.one;
57 let s0 = self.two;
58
59 s1 ^= s1 << 17_u32;
60 s1 = s1 ^ s0 ^ s1 >> 7_u32 ^ s0 >> 16_u32;
61
62 self.one = s0;
63 self.two = s1;
64
65 s0.wrapping_add(s1)
66 }
67}