Task 4 of 5
The red half alone is not a sweep — half the grid has not been touched. The black
half is the same kernel with its parity test flipped, and the ordering that matters is in
the chaining: black(red(u)). The black cells read the grid the red
half produced, so they see this sweep's reds, not last sweep's. That single fact is all
that separates Gauss-Seidel from Jacobi.
Write black(u) instead and both halves read the same old grid. The code
still runs, the answer still looks plausible, and you have written Jacobi with an extra
kernel launch — which is the most expensive way to be wrong in this module, because
nothing about the output shouts.
(x + y) % 2 === 1 update, everything else passes throughawait black(await red(u)) — the black half reads what the red half wroteCopy the red kernel and change one character:
const parity = (x + y) % 2;
if (parity !== 1) return u[y][x];
Still a number, never a boolean — the WebGL backend rejects
const isBlack = … exactly as it rejects isRed.
const afterRed = await red(guess);
const afterBoth = await black(afterRed); // NOT black(guess)
Or, in one line: await black(await red(guess)) — the inner
await is not optional, because an un-awaited kernel call hands the next
kernel a Promise instead of a grid.
This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.