Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

keccakP1600timesN

Apply Keccak-p[1600,12] to N states using SIMD

kangarootwelve.keccakP1600timesN
fn keccakP1600timesN(comptime N: usize, states: *[5][5]@Vector(N, u64)) void

File

lib/std/crypto/kangarootwelve.zig:219

Code

fn keccakP1600timesN(comptime N: usize, states: *[5][5]@Vector(N, u64)) void {
    @setEvalBranchQuota(10000);

    // Pre-computed rotation offsets for rho-pi step
    const rho_offsets = comptime blk: {
        var offsets: [24]u6 = undefined;
        var px: usize = 1;
        var py: usize = 0;
        for (0..24) |t| {
            const rot_amount = ((t + 1) * (t + 2) / 2) % 64;
            offsets[t] = @intCast(rot_amount);
            const temp_x = py;
            py = (2 * px + 3 * py) % 5;
            px = temp_x;
        }
        break :blk offsets;
    };

    var round: usize = 0;
    while (round < 12) : (round += 2) {
        inline for (0..2) |i| {
            // θ (theta)
            var C: [5]@Vector(N, u64) = undefined;
            inline for (0..5) |x| {
                C[x] = states[x][0] ^ states[x][1] ^ states[x][2] ^ states[x][3] ^ states[x][4];
            }

            var D: [5]@Vector(N, u64) = undefined;
            inline for (0..5) |x| {
                D[x] = C[(x + 4) % 5] ^ rol64Vec(N, C[(x + 1) % 5], 1);
            }

            // Apply D to all lanes
            inline for (0..5) |x| {
                states[x][0] ^= D[x];
                states[x][1] ^= D[x];
                states[x][2] ^= D[x];
                states[x][3] ^= D[x];
                states[x][4] ^= D[x];
            }

            // ρ (rho) and π (pi) - optimized with pre-computed offsets
            var current = states[1][0];
            var px: usize = 1;
            var py: usize = 0;
            inline for (rho_offsets) |rot| {
                const next_y = (2 * px + 3 * py) % 5;
                const next = states[py][next_y];
                states[py][next_y] = rol64Vec(N, current, rot);
                current = next;
                px = py;
                py = next_y;
            }

            // χ (chi) - optimized with better register usage
            inline for (0..5) |y| {
                const t0 = states[0][y];
                const t1 = states[1][y];
                const t2 = states[2][y];
                const t3 = states[3][y];
                const t4 = states[4][y];

                states[0][y] = t0 ^ (~t1 & t2);
                states[1][y] = t1 ^ (~t2 & t3);
                states[2][y] = t2 ^ (~t3 & t4);
                states[3][y] = t3 ^ (~t4 & t0);
                states[4][y] = t4 ^ (~t0 & t1);
            }

            // ι (iota)
            const rc_splat: @Vector(N, u64) = @splat(RC[round + i]);
            states[0][0] ^= rc_splat;
        }
    }
}