# GLIDER at scale — a soup census over the readable engine. # # 2^d chunks of 64 random 4x4 toroidal soups; each soup runs g generations # and contributes its population to a checksum, and the chunks join up a # balanced fork tree, exactly the shape of the official game-of-life bench # but over GLIDER's readable rows-and-cells engine. `batch!` hands the whole # tree to the GPU; plain `batch` spreads it over the CPU cores. import Base import ./life.bend as L def bit(+b: U32, +k: U32) -> U32: U32.and(U32.shrn(b, U32.to_nat(k)), 1) def row4(+b: U32, +r: U32) -> List<&2, U32>: +r4 = U32.mul(r, 4) [bit(b, r4), bit(b, U32.add(r4, 1)), bit(b, U32.add(r4, 2)), bit(b, U32.add(r4, 3))] def soup(+ix: U32) -> L.Board: +b = U32.and(U32.mul(ix, 2654435761), 65535) L.B{[row4(b, 0), row4(b, 1), row4(b, 2), row4(b, 3)]} def sim(+ix: U32, +g: Nat) -> U32: L.total(L.steps(g, soup(ix))) def chunk(+j: Nat, +i: U32, +g: Nat, +acc: U32) -> U32: match j: case 0n: acc case 1n+p: chunk(p, i, g, U32.mul(U32.add(acc, sim(U32.add(i, U32.from_nat(p)), g)), 2654435761)) def batch(+d: Nat, +i: U32, +g: Nat) -> U32: match d: case 0n: chunk(64n, i, g, 0) case 1n+p: a b = batch(p, i, g) batch(p, U32.add(i, U32.shln(64, p)), g) U32.mul(U32.add(a, b), 2654435761) def size() -> Nat: 10n def gens() -> Nat: 8n def main() -> IO(Unit): do IO: IO.print(U32.show(batch!(size(), 0, gens())))