lib/stabilizer/src/rng.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 pub const Marsaglia = struct {
4 state: u32,
5 cached: u32 = 0,
6 byte_index: u3 = 4,
7
8 pub fn init(seed: u64) Marsaglia {
9 const folded = @as(u32, @truncate(seed)) ^ @as(u32, @truncate(seed >> 32));
10 return .{ .state = if (folded == 0) 0x6d2b_79f5 else folded };
11 }
12
13 pub fn nextU32(self: *Marsaglia) u32 {
14 var x = self.state;
15 x ^= x << 13;
16 x ^= x >> 17;
17 x ^= x << 5;
18 self.state = if (x == 0) 0x6d2b_79f5 else x;
19 return self.state;
20 }
21
22 pub fn nextU64(self: *Marsaglia) u64 {
23 return (@as(u64, self.nextU32()) << 32) | self.nextU32();
24 }
25
26 pub fn bounded(self: *Marsaglia, upper: usize) usize {
27 std.debug.assert(upper > 0);
28 return @intCast(self.nextU64() % upper);
29 }
30
31 pub fn nextByte(self: *Marsaglia) u8 {
32 if (self.byte_index >= 4) {
33 self.cached = self.nextU32();
34 self.byte_index = 0;
35 }
36 const shift: u5 = @intCast(@as(u16, self.byte_index) * 8);
37 const byte: u8 = @truncate(self.cached >> shift);
38 self.byte_index += 1;
39 return byte;
40 }
41 };