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 };