lib/accy/src/kernel/library/random/block/philox.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const random = @import("../root.zig");
 2 
 3 const kernel = random.base.kernel;
 4 const wordConstant = random.block.wordConstant;
 5 
 6 pub const philox_lanes: u64 = 4;
 7 pub const philox_default_rounds: u32 = 10;
 8 pub const philox_max_rounds: u32 = 16;
 9 
10 const philox_m0: u32 = 0xD2511F53;
11 const philox_m1: u32 = 0xCD9E8D57;
12 const philox_w0: u32 = 0x9E3779B9;
13 const philox_w1: u32 = 0xBB67AE85;
14 
15 pub fn philoxBlock(rounds: u32, counter: [4]u32, key: [2]u32) [4]u32 {
16     var state = counter;
17     var bumped = key;
18     var round: u32 = 0;
19     while (round < rounds) : (round += 1) {
20         if (round > 0) {
21             bumped[0] +%= philox_w0;
22             bumped[1] +%= philox_w1;
23         }
24         const product0 = @as(u64, philox_m0) * @as(u64, state[0]);
25         const product1 = @as(u64, philox_m1) * @as(u64, state[2]);
26         const hi0: u32 = @truncate(product0 >> 32);
27         const lo0: u32 = @truncate(product0);
28         const hi1: u32 = @truncate(product1 >> 32);
29         const lo1: u32 = @truncate(product1);
30         state = .{ hi1 ^ state[1] ^ bumped[0], lo1, hi0 ^ state[3] ^ bumped[1], lo0 };
31     }
32     return state;
33 }
34 
35 pub fn philoxWords(
36     k: anytype,
37     rounds: u32,
38     counter: kernel.Value,
39     counter_fold: kernel.Value,
40     seed_lo: kernel.Value,
41     seed_hi: kernel.Value,
42 ) ![philox_lanes]kernel.Value {
43     const zero = try k.constantInt(.i32, 0);
44     const m0 = try wordConstant(k, philox_m0);
45     const m1 = try wordConstant(k, philox_m1);
46     const w0 = try wordConstant(k, philox_w0);
47     const w1 = try wordConstant(k, philox_w1);
48     var state = [philox_lanes]kernel.Value{ counter, counter_fold, zero, zero };
49     var key = [2]kernel.Value{ seed_lo, seed_hi };
50     var round: u32 = 0;
51     while (round < rounds) : (round += 1) {
52         if (round > 0) {
53             key[0] = try k.add(key[0], w0);
54             key[1] = try k.add(key[1], w1);
55         }
56         const hi0 = try k.umulhi(m0, state[0]);
57         const lo0 = try k.mul(m0, state[0]);
58         const hi1 = try k.umulhi(m1, state[2]);
59         const lo1 = try k.mul(m1, state[2]);
60         state = .{
61             try k.xor(try k.xor(hi1, state[1]), key[0]),
62             lo1,
63             try k.xor(try k.xor(hi0, state[3]), key[1]),
64             lo0,
65         };
66     }
67     return state;
68 }