| ... | @@ -19,12 +19,13 @@ const debug = std.debug; | ... | @@ -19,12 +19,13 @@ const debug = std.debug; |
| 19 | const assert = std.debug.assert; | 19 | const assert = std.debug.assert; |
| 20 | const testing = std.testing; | 20 | const testing = std.testing; |
| 21 | const htest = @import("test.zig"); | 21 | const htest = @import("test.zig"); |
| | 22 | const Vector = std.meta.Vector; |
| 22 | | 23 | |
| 23 | pub const State = struct { | 24 | pub const State = struct { |
| 24 | pub const BLOCKBYTES = 48; | 25 | pub const BLOCKBYTES = 48; |
| 25 | pub const RATE = 16; | 26 | pub const RATE = 16; |
| 26 | | 27 | |
| 27 | data: [BLOCKBYTES / 4]u32, | 28 | data: [BLOCKBYTES / 4]u32 align(16), |
| 28 | | 29 | |
| 29 | const Self = @This(); | 30 | const Self = @This(); |
| 30 | | 31 | |
| ... | @@ -103,7 +104,57 @@ pub const State = struct { | ... | @@ -103,7 +104,57 @@ pub const State = struct { |
| 103 | } | 104 | } |
| 104 | } | 105 | } |
| 105 | | 106 | |
| 106 | pub const permute = if (std.builtin.mode == .ReleaseSmall) permute_small else permute_unrolled; | 107 | const Lane = Vector(4, u32); |
| | 108 | |
| | 109 | inline fn shift(x: Lane, comptime n: comptime_int) Lane { |
| | 110 | return x << @splat(4, @as(u5, n)); |
| | 111 | } |
| | 112 | |
| | 113 | inline fn rot(x: Lane, comptime n: comptime_int) Lane { |
| | 114 | return (x << @splat(4, @as(u5, n))) | (x >> @splat(4, @as(u5, 32 - n))); |
| | 115 | } |
| | 116 | |
| | 117 | fn permute_vectorized(self: *Self) void { |
| | 118 | const state = &self.data; |
| | 119 | var x = Lane{ state[0], state[1], state[2], state[3] }; |
| | 120 | var y = Lane{ state[4], state[5], state[6], state[7] }; |
| | 121 | var z = Lane{ state[8], state[9], state[10], state[11] }; |
| | 122 | var round = @as(u32, 24); |
| | 123 | while (round > 0) : (round -= 1) { |
| | 124 | x = rot(x, 24); |
| | 125 | y = rot(y, 9); |
| | 126 | const newz = x ^ shift(z, 1) ^ shift(y & z, 2); |
| | 127 | const newy = y ^ x ^ shift(x | z, 1); |
| | 128 | const newx = z ^ y ^ shift(x & y, 3); |
| | 129 | x = newx; |
| | 130 | y = newy; |
| | 131 | z = newz; |
| | 132 | switch (round & 3) { |
| | 133 | 0 => { |
| | 134 | x = @shuffle(u32, x, undefined, [_]i32{ 1, 0, 3, 2 }); |
| | 135 | x[0] ^= round | 0x9e377900; |
| | 136 | }, |
| | 137 | 2 => { |
| | 138 | x = @shuffle(u32, x, undefined, [_]i32{ 2, 3, 0, 1 }); |
| | 139 | }, |
| | 140 | else => {}, |
| | 141 | } |
| | 142 | } |
| | 143 | comptime var i: usize = 0; |
| | 144 | inline while (i < 4) : (i += 1) { |
| | 145 | state[0 + i] = x[i]; |
| | 146 | state[4 + i] = y[i]; |
| | 147 | state[8 + i] = z[i]; |
| | 148 | } |
| | 149 | } |
| | 150 | |
| | 151 | pub const permute = if (std.Target.current.cpu.arch == .x86_64) impl: { |
| | 152 | break :impl permute_vectorized; |
| | 153 | } else if (std.builtin.mode == .ReleaseSmall) impl: { |
| | 154 | break :impl permute_small; |
| | 155 | } else impl: { |
| | 156 | break :impl permute_unrolled; |
| | 157 | }; |
| 107 | | 158 | |
| 108 | pub fn squeeze(self: *Self, out: []u8) void { | 159 | pub fn squeeze(self: *Self, out: []u8) void { |
| 109 | var i = @as(usize, 0); | 160 | var i = @as(usize, 0); |