igneum/proto-cuda/packs/igneum-hourly/program.metal
igneum-labs ff263245ac Igneum: design docs, Metal lottery-hash prototype, CUDA test pack, finality simulation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 15:06:01 +00:00

109 lines
4.9 KiB
Metal

#include <metal_stdlib>
using namespace metal;
#define MASK 0x0fffffffu
constant uint SEEDW[8] = { 0x6bdee811u, 0x8f488bbeu, 0xc5cdece7u, 0x210af22du, 0x2f687b65u, 0x17471eeeu, 0xee16e284u, 0xfc9eb8f9u };
inline uint splitmix32(uint x) {
x ^= x >> 16; x *= 0x7feb352du;
x ^= x >> 15; x *= 0x846ca68bu;
x ^= x >> 16;
return x;
}
inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31
inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }
inline uint ds_elem(uint i, uint d0, uint d1) {
uint x = i ^ d0;
x *= 0x9E3779B1u; x ^= x >> 15;
x += d1;
x *= 0x85EBCA77u; x ^= x >> 13;
x *= 0xC2B2AE3Du; x ^= x >> 16;
return x;
}
kernel void igneum_hash(device const uint* dataset [[buffer(0)]],
device ulong* out [[buffer(1)]],
constant uint& baseNonce [[buffer(2)]],
uint gid [[thread_position_in_grid]]) {
uint nonce = baseNonce + gid;
uint r0, r1, r2, r3, r4, r5, r6, r7;
{ uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; }
{ uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; }
{ uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; }
{ uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; }
{ uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; }
{ uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; }
{ uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; }
{ uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; }
for (uint it = 0u; it < 8u; ++it) {
uint sel = r0;
r6 = r6 ^ dataset[r5 & MASK]; // 0
r3 = r3 ^ r7; // 1
r6 = mulhi(r6, r2); // 2
r1 = r1 + r0 + select(0x1eb46b1cu, 0x43f8f369u, ((sel >> 0u) & 1u) != 0u); // 3
r3 = r3 ^ dataset[r0 & MASK]; // 4
r5 = r5 | r7; // 5
r4 = r4 ^ dataset[r6 & MASK]; // 6
r4 = rotl_imm(r4, 21u); // 7
r6 = r6 ^ dataset[r3 & MASK]; // 8
r6 = r6 ^ dataset[r1 & MASK]; // 9
r0 = r0 ^ simd_shuffle_xor(r3, (ushort)8); // 10
r2 = r2 ^ r3; // 11
r2 = r2 + r7 + select(0x3a1ce85eu, 0xc26c7c2au, ((sel >> 19u) & 1u) != 0u); // 12
r4 = r4 ^ dataset[r3 & MASK]; // 13
r7 = r7 ^ dataset[r1 & MASK]; // 14
r2 = mulhi(r2, r3); // 15
r5 = r5 ^ dataset[r2 & MASK]; // 16
r5 = r5 ^ dataset[r1 & MASK]; // 17
r4 = r4 ^ dataset[r7 & MASK]; // 18
r2 = rotr_var(r2, r1); // 19
r7 = r7 ^ dataset[r0 & MASK]; // 20
r4 = r4 ^ dataset[r6 & MASK]; // 21
r7 = rotl_imm(r7, 25u); // 22
r3 = r3 + r5 + select(0x942b819bu, 0x98ae0055u, ((sel >> 15u) & 1u) != 0u); // 23
r3 = mulhi(r3, r4); // 24
r6 = r6 ^ r1; // 25
r1 = rotl_imm(r1, 31u); // 26
r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // 27
r6 = r6 - r5; // 28
r6 = rotr_var(r6, r3); // 29
r0 = r0 ^ simd_shuffle_xor(r4, (ushort)4); // 30
r4 = rotl_imm(r4, 30u); // 31
r2 = r2 - r1; // 32
r5 = r5 | r4; // 33
r7 = r6 * r3 + r7; // 34
r5 = r5 * r0; // 35
r5 = r5 - r3; // 36
r2 = r2 + r7 + select(0x473ecfd5u, 0x6b5970b5u, ((sel >> 5u) & 1u) != 0u); // 37
r2 = r2 ^ dataset[r7 & MASK]; // 38
r2 = rotr_var(r2, r6); // 39
r0 = r0 ^ r5; // 40
r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // 41
r1 = r1 * r6; // 42
r0 = r4 * r1 + r0; // 43
r1 = r1 + r4 + select(0x04e78f3bu, 0x4a502c22u, ((sel >> 20u) & 1u) != 0u); // 44
r6 = r2 * r7 + r6; // 45
r1 = r1 ^ r0; // 46
r5 = r5 ^ dataset[r7 & MASK]; // 47
r0 = r0 | r4; // 48
r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // 49
r7 = r7 + r0 + select(0x0a3df170u, 0x6fabf9ceu, ((sel >> 17u) & 1u) != 0u); // 50
r6 = r6 ^ r3; // 51
r1 = r1 + r2 + select(0xc99bce6fu, 0xad344ca0u, ((sel >> 21u) & 1u) != 0u); // 52
r6 = r6 * r7; // 53
r3 = mulhi(r3, r4); // 54
r7 = r7 * r1; // 55
r7 = r7 ^ r1; // 56
r2 = r2 * r7; // 57
r2 = r2 ^ dataset[r1 & MASK]; // 58
r7 = r4 * r5 + r7; // 59
r2 = r2 ^ dataset[r7 & MASK]; // 60
r0 = r2 * r3 + r0; // 61
r1 = mulhi(r1, r5); // 62
r7 = r7 + r3 + select(0xc23e27c9u, 0x05e4fc1du, ((sel >> 24u) & 1u) != 0u); // 63
}
uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u);
uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u);
out[gid] = ((ulong)hi << 32) | (ulong)lo;
}