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

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const random = @import("../root.zig");
 2 
 3 const std = random.base.std;
 4 const kernel = random.base.kernel;
 5 
 6 pub const squares_lanes: u64 = 1;
 7 pub const squares_default_key: u64 = 0x123456789abcdef0;
 8 
 9 pub fn squaresBlock(counter: u64, key: u64) u32 {
10     var x = counter *% key;
11     const y = x;
12     const z = y +% key;
13     x = x *% x +% y;
14     x = std.math.rotr(u64, x, 32);
15     x = x *% x +% z;
16     x = std.math.rotr(u64, x, 32);
17     x = x *% x +% y;
18     x = std.math.rotr(u64, x, 32);
19     return @truncate((x *% x +% z) >> 32);
20 }
21 
22 pub fn zeroExtendWord(k: anytype, word: kernel.Value) !kernel.Value {
23     const wide = try k.cast(word, .i64);
24     const mask = try k.constantInt(.i64, 0xFFFFFFFF);
25     return k.and_(wide, mask);
26 }
27 
28 pub fn rotateWide32(k: anytype, value: kernel.Value) !kernel.Value {
29     const half = try k.constantInt(.i64, 32);
30     const low = try k.ushr(value, half);
31     const high = try k.shl(value, half);
32     return k.or_(low, high);
33 }
34 
35 pub fn squaresWord(
36     k: anytype,
37     counter: kernel.Value,
38     key: kernel.Value,
39 ) !kernel.Value {
40     var x = try k.mul(counter, key);
41     const y = x;
42     const z = try k.add(y, key);
43     x = try k.add(try k.mul(x, x), y);
44     x = try rotateWide32(k, x);
45     x = try k.add(try k.mul(x, x), z);
46     x = try rotateWide32(k, x);
47     x = try k.add(try k.mul(x, x), y);
48     x = try rotateWide32(k, x);
49     const final = try k.add(try k.mul(x, x), z);
50     const half = try k.constantInt(.i64, 32);
51     const high = try k.ushr(final, half);
52     return k.cast(high, .i32);
53 }
54 
55 pub fn squaresKeyValue(k: anytype, key_lo: kernel.Value, key_hi: kernel.Value) !kernel.Value {
56     const lo = try zeroExtendWord(k, key_lo);
57     const hi = try zeroExtendWord(k, key_hi);
58     const half = try k.constantInt(.i64, 32);
59     return k.or_(try k.shl(hi, half), lo);
60 }