Apply Keccak-p[1600,12] to a single state (byte representation)
fn keccakP(state: *[200]u8) void
fn keccakP(state: *[200]u8) void {
@setEvalBranchQuota(10000);
var lanes: [5][5]u64 = undefined;
// Load state into lanes
inline for (0..5) |x| {
inline for (0..5) |y| {
lanes[x][y] = load64(state[8 * (x + 5 * y) ..]);
}
}
// Apply 12 rounds
var round: usize = 0;
while (round < 12) : (round += 2) {
inline for (0..2) |i| {
// θ
var C: [5]u64 = undefined;
inline for (0..5) |x| {
C[x] = lanes[x][0] ^ lanes[x][1] ^ lanes[x][2] ^ lanes[x][3] ^ lanes[x][4];
}
var D: [5]u64 = undefined;
inline for (0..5) |x| {
D[x] = C[(x + 4) % 5] ^ std.math.rotl(u64, C[(x + 1) % 5], 1);
}
inline for (0..5) |x| {
inline for (0..5) |y| {
lanes[x][y] ^= D[x];
}
}
// ρ and π
var current = lanes[1][0];
var px: usize = 1;
var py: usize = 0;
inline for (0..24) |t| {
const temp = lanes[py][(2 * px + 3 * py) % 5];
const rot_amount = ((t + 1) * (t + 2) / 2) % 64;
lanes[py][(2 * px + 3 * py) % 5] = std.math.rotl(u64, current, @as(u6, @intCast(rot_amount)));
current = temp;
const temp_x = py;
py = (2 * px + 3 * py) % 5;
px = temp_x;
}
// χ
inline for (0..5) |y| {
const T = [5]u64{ lanes[0][y], lanes[1][y], lanes[2][y], lanes[3][y], lanes[4][y] };
inline for (0..5) |x| {
lanes[x][y] = T[x] ^ (~T[(x + 1) % 5] & T[(x + 2) % 5]);
}
}
// ι
lanes[0][0] ^= RC[round + i];
}
}
// Store lanes back to state
inline for (0..5) |x| {
inline for (0..5) |y| {
store64(lanes[x][y], state[8 * (x + 5 * y) ..]);
}
}
}