w
This commit is contained in:
parent
03ddaa09f2
commit
caa90775f9
89 changed files with 7126 additions and 0 deletions
62
tests/pixel-contract.mjs
Normal file
62
tests/pixel-contract.mjs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import '../kernels.js';
|
||||
|
||||
const K = globalThis.MANDEL_KERNELS;
|
||||
const decode = b64 => Uint8Array.from(atob(b64), c => c.charCodeAt(0));
|
||||
|
||||
function instantiate() {
|
||||
for (const [name, payload] of [['simd', K.WASM_SIMD_B64], ['scalar', K.WASM_SCALAR_B64]]) {
|
||||
try {
|
||||
const instance = new WebAssembly.Instance(new WebAssembly.Module(decode(payload)), {});
|
||||
return { name, ex: instance.exports };
|
||||
} catch {}
|
||||
}
|
||||
throw new Error('Neither shallow WASM backend could be instantiated.');
|
||||
}
|
||||
|
||||
function jsPixel(cre, cim, span, width, height, x, y, iter) {
|
||||
const scale = span / width;
|
||||
// Match the public ABI operation order: JavaScript shifts the center once,
|
||||
// then the kernel applies the historical integer-grid formula. The
|
||||
// algebraically equivalent single expression can round differently at a
|
||||
// chaotic boundary and is not a useful backend-equivalence oracle.
|
||||
const shiftedRe = cre + scale * 0.5;
|
||||
const shiftedIm = cim - scale * 0.5;
|
||||
const cr = shiftedRe + scale * (x - width * 0.5);
|
||||
const ci = shiftedIm + scale * (height * 0.5 - y);
|
||||
let zr = 0, zi = 0, zr2 = 0, zi2 = 0, n = 0;
|
||||
while (n < iter && zr2 + zi2 <= 4) {
|
||||
zi = 2 * zr * zi + ci;
|
||||
zr = zr2 - zi2 + cr;
|
||||
zr2 = zr * zr;
|
||||
zi2 = zi * zi;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
const backend = instantiate();
|
||||
const scenes = [
|
||||
{ cre: -0.5, cim: 0, span: 3.4, width: 31, height: 19, iter: 350 },
|
||||
{ cre: -0.743643887037151, cim: 0.13182590420533, span: 4e-4, width: 37, height: 23, iter: 700 }
|
||||
];
|
||||
|
||||
let samples = 0;
|
||||
let mismatches = 0;
|
||||
const mismatchDetails = [];
|
||||
for (const s of scenes) {
|
||||
const scale = s.span / s.width;
|
||||
const npx = backend.ex.render_rows(s.cre + scale * 0.5, s.cim - scale * 0.5, s.span, s.width, s.height, 0, s.height, s.iter);
|
||||
const counts = new Uint32Array(backend.ex.memory.buffer, backend.ex.counts_ptr(), npx);
|
||||
for (let y = 0; y < s.height; y++) for (let x = 0; x < s.width; x++) {
|
||||
samples++;
|
||||
const wasmCount = counts[y * s.width + x];
|
||||
const jsCount = jsPixel(s.cre, s.cim, s.span, s.width, s.height, x, y, s.iter);
|
||||
if (wasmCount !== jsCount) {
|
||||
mismatches++;
|
||||
if (mismatchDetails.length < 12) mismatchDetails.push({ scene: scenes.indexOf(s), x, y, wasmCount, jsCount });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mismatches) throw new Error(`Pixel contract mismatch: ${mismatches}/${samples} ${JSON.stringify(mismatchDetails)}`);
|
||||
console.log(JSON.stringify({ status: 'pass', backend: backend.name, samples, mismatches, contract: '(x+0.5,y+0.5)' }));
|
||||
Loading…
Add table
Add a link
Reference in a new issue