oarust 0.8.6

GPU-first semantic computing engine written in Rust
// OA donor Keccak-f[1600], adapted to uint2 lanes so the kernel does not
// require Vulkan shaderInt64.

static const uint RC_LO[24] = {
	0x00000001u, 0x00008082u, 0x0000808au, 0x80008000u,
	0x0000808bu, 0x80000001u, 0x80008081u, 0x00008009u,
	0x0000008au, 0x00000088u, 0x80008009u, 0x8000000au,
	0x8000808bu, 0x0000008bu, 0x00008089u, 0x00008003u,
	0x00008002u, 0x00000080u, 0x0000800au, 0x8000000au,
	0x80008081u, 0x00008080u, 0x80000001u, 0x80008008u
};

static const uint RC_HI[24] = {
	0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u,
	0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u,
	0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
	0x00000000u, 0x80000000u, 0x80000000u, 0x80000000u,
	0x80000000u, 0x80000000u, 0x00000000u, 0x80000000u,
	0x80000000u, 0x80000000u, 0x00000000u, 0x80000000u
};

static const uint ROT[25] = {
	0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43,
	25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14
};

uint2 rotl64(uint2 value, uint shift) {
	if (shift == 0) return value;
	if (shift >= 32) {
		value = uint2(value.y, value.x);
		shift -= 32;
	}
	if (shift == 0) return value;
	return uint2(
		(value.x << shift) | (value.y >> (32 - shift)),
		(value.y << shift) | (value.x >> (32 - shift))
	);
}

void keccak_f1600_u32(inout uint2 state[25]) {
	for (uint round = 0; round < 24; ++round) {
		uint2 columns[5];
		for (uint i = 0; i < 5; ++i) {
			columns[i] = state[i] ^ state[5 + i] ^ state[10 + i] ^ state[15 + i] ^ state[20 + i];
		}
		uint2 differences[5];
		for (uint i = 0; i < 5; ++i) {
			differences[i] = columns[(i + 4) % 5] ^ rotl64(columns[(i + 1) % 5], 1);
		}
		for (uint i = 0; i < 25; ++i) state[i] ^= differences[i % 5];

		uint2 rotated[25];
		for (uint i = 0; i < 25; ++i) {
			uint x = i % 5;
			uint y = i / 5;
			rotated[5 * ((2 * x + 3 * y) % 5) + y] = rotl64(state[i], ROT[i]);
		}
		for (uint y = 0; y < 5; ++y) {
			uint base = y * 5;
			state[base] = rotated[base] ^ (~rotated[base + 1] & rotated[base + 2]);
			state[base + 1] = rotated[base + 1] ^ (~rotated[base + 2] & rotated[base + 3]);
			state[base + 2] = rotated[base + 2] ^ (~rotated[base + 3] & rotated[base + 4]);
			state[base + 3] = rotated[base + 3] ^ (~rotated[base + 4] & rotated[base]);
			state[base + 4] = rotated[base + 4] ^ (~rotated[base] & rotated[base + 1]);
		}
		state[0] ^= uint2(RC_LO[round], RC_HI[round]);
	}
}