# prngs — every catalogued generator, as one WebAssembly module

This package is the whole catalog compiled once: a single `prng.wasm`
carrying every implemented generator (all ~4,000 entries, ~100 distinct kinds),
addressable by index or by catalog id. It is built and verified in CI on every
run and published as the `prng-wasm-<sha>` pipeline artifact.

Verified means: `scripts/check_wasm.py` draws from **every** entry through this
module and through the native C binary and requires identical output. A build
that compiles but computes something different does not ship.

## Contents

| file | purpose |
|---|---|
| `prng.wasm` | the module (~540 KiB) |
| `prng.js` | Emscripten loader; exports `createPrng()`; works from a `<script>` tag and from node `require` |
| `ids.json` | `[{i, id, kind, category}, …]` — handle `i` is the registry index |
| `meta.json` | per-handle metrics for the page: family, period, seed space, output bits, outputs-to-predict, relevance, description |
| `index.html` | dependency-free demo: search a generator, seed it, see draws and a lattice plot |

## Use on a website

```html
<script src="prng.js"></script>
<script>
createPrng().then(M => {
  const find = M.cwrap("prng_wasm_find", "number", ["string"]);
  const h = find("lcg_randu_ibm");           // handle, -1 if unknown
  M._prng_wasm_seed(h, 42, 0);               // seed = hi<<32 | lo, as two uint32
  const v = M._prng_wasm_next_u32(h) >>> 0;  // >>> 0 makes it unsigned in JS
});
</script>
```

## API (all exported as `Module._name`)

| function | notes |
|---|---|
| `prng_wasm_count()` | number of generators (== entries in `ids.json`) |
| `prng_wasm_id(i)` | id string for handle `i`; use `cwrap(…, "string", ["number"])` |
| `prng_wasm_find(id)` | handle for an id, `-1` if unknown; use `cwrap(…, "number", ["string"])` |
| `prng_wasm_seed(i, lo, hi)` | seed with the 64-bit value `hi<<32 \| lo`; returns 1, or 0 for a bad handle |
| `prng_wasm_next_u32(i)` | one 32-bit draw (apply `>>> 0` in JS) |
| `prng_wasm_next_u64(i)` | low 32 bits; the high 32 bits are then in `prng_wasm_last_hi()` |
| `prng_wasm_fill_u32(i, ptr, n)` | write `n` draws into a `malloc`'d buffer in one call; read them back via `new Uint32Array(M.HEAPU32.buffer, ptr, n)` |

Seeds and 64-bit results cross the boundary as uint32 pairs so nothing here
depends on WASM BigInt support.

## Node

```js
const createPrng = require("./prng.js");
createPrng().then(M => { console.log(M._prng_wasm_count()); });
```

`dump.js` next to this file prints draws in the same format as the native
`stream` binary and is what the CI comparison uses.

## Building

```
source /opt/emsdk/emsdk_env.sh
bash dev/c/wasm/build.sh          # -> dev/c/wasm/dist/
python3 scripts/check_wasm.py     # proves it matches native, every entry
```

The build is the same sources the native `stream` binary links, minus the
`main()`s, compiled with `emcc -O2` through `wasm_api.c`, the JS-facing surface.
