diff --git a/docs/codegen.md b/docs/codegen.md index 9c67d84..afff62d 100644 --- a/docs/codegen.md +++ b/docs/codegen.md @@ -46,11 +46,11 @@ The pipeline lives in `src/shinro/codegen/`; the Zig VM lives in `src/shinro/run 3. **Interpret** (`interpret`). Replay the graph on real numpy inputs as a correctness oracle. If the interpreter's output matches a live `NumpyBackend` run to float-exactness, the tracer is sound. -4. **Lower** (`lower_zig`). Walk the graph and emit Zig — a `src/shinro/runtime/` - module exposing a `shinro_step` C-ABI function with baked constants, - compiled to a `.so`. The generated graph is written to - `src/shinro/runtime/graph_data.zig`; the comptime VM that executes it is - `src/shinro/runtime/lower.zig`. +4. **Lower** (`lower_zig`). Walk the graph and emit Zig — the generated graph is + written to `src/shinro/runtime/graph_data.zig`; the comptime VM that executes + it is `src/shinro/runtime/lower.zig` (graph-agnostic, instantiated via + `Vm(Ctx)`), and `src/shinro/runtime/entry.zig` binds that graph and exposes + the `shinro_step` C-ABI function, compiled to a `.so`. ## Module map @@ -65,7 +65,7 @@ The pipeline lives in `src/shinro/codegen/`; the Zig VM lives in `src/shinro/run | `codegen/compose.py` | `compose` — merge per-component graphs into one closed-loop step graph, auto-inserting `reshape`/`clip`. | | `codegen/lower_zig.py` | Emit `src/shinro/runtime/graph_data.zig` (the graph as Zig constants) from a composed graph. | | `demos/demo_codegen.py` | Runnable demo: traces KF+LQR for the base and cartpole plants, composes, and verifies each stage against a live numpy loop. | -| `src/shinro/runtime/` (Zig) | `build.zig` (build script), `lower.zig` (comptime-unrolled VM), `linalg.zig` (shared linear-algebra kernels), `graph_data.zig` (generated graph). | +| `src/shinro/runtime/` (Zig) | `build.zig` (build script), `entry.zig` (deployment entry: binds the graph and exports `shinro_step`), `lower.zig` (graph-agnostic comptime-unrolled VM), `linalg.zig` (shared linear-algebra kernels), `graph_data.zig` (generated graph). | | `codegen/recipes.py` | The graph-recipe registry (`@register_graph` / `build_recipe`) + the shipped recipes (`closed_loop_tracking`, `policy_only`) and the two shipped default graphs (`build_base_graph` / `build_mpc_composed_graph`). | | `scripts/gen_base.py` / `scripts/gen_mpc.py` | Shims over `codegen/recipes.py` (`make zig-gen` / `make zig-mpc-gen` run them). | | `codegen/component_cli.py` | The "does my component trace?" gate (`shinro check` / `shinro trace`, plus the kept `scripts/trace_component.py` shim): inventory of registered components, inferred trace contract (`--list`), and trace + interpret-vs-live oracle check (bit-exact) for any config TOML. | diff --git a/lab-notes/daily/2026-09-28.md b/lab-notes/daily/2026-09-28.md index c77cf79..292b79c 100644 --- a/lab-notes/daily/2026-09-28.md +++ b/lab-notes/daily/2026-09-28.md @@ -104,3 +104,199 @@ Zig linalg suite **48 passed** (was 47); full VM (`zig build`) exits 0. `lower.zig`'s `matmul`/`vecmat` call sites still compile against the shipped graph. - `make lint` is unaffected (Zig runtime is outside ruff/pyrefly's surface). + +## Zig-native C-ABI tests for `lower.zig` (issue #14) + +Branch: `feat/zig-native-lower-tests` (off `main` @ 9547ada) + +### Why + +Issue #14: `lower.zig`'s C-ABI `shinro_step` had only (a) Zig unit tests for +`linalg.zig` and (b) the Python ctypes oracle (`tests/test_zig_lowering.py`, +which builds a `.so` and drives it via `ctypes`). Nothing drove the VM +natively. The blocker was that `lower.zig` hard-imports the generated +`graph_data.zig`, which `build.zig` only supplies through `-Dgraph` on the +deployed lib module. + +### What changed + +- `src/shinro/runtime/tests/lower_fixture_graph.zig` (new): hand-authored + fixture `graph_data.zig` — a 10-node graph (`inp` x, `inp` r → `cst`@`matmul` + → `add` → `clip` → named `out`; `tanh`(r) → state `out`). Mirrors the + generated `Op`/`Node` schema. +- `src/shinro/runtime/tests/lower.zig` (new): two native tests driving + `shinro_step` directly — named-output + state-output routing, and cross-tick + recurrent state feedback (state output fed back as the next tick's input). +- `src/shinro/runtime/build.zig`: a new test module rooted at `lower.zig` with + `addAnonymousImport("graph_data", tests/lower_fixture_graph.zig)`, exposed to + `tests/lower.zig` as the `lower` module; added to the `test` step. +- `src/shinro/runtime/lower.zig`: `export fn shinro_step` → `pub export fn + shinro_step` (Zig-level import visibility; the C symbol is unchanged). +- `src/shinro/runtime/README.md`: two new rows in the files table + a note on + the native test. + +### Design decisions + +- Chose the fixture-graph route over the comptime-injection refactor + (`Vm(comptime G: type)`). The fixture is ~60 lines across four files, leaves + `lower.zig` untouched apart from one visibility word, and — critically — is + **decoupled from `make zig-gen`**: the deployed graph churns (last-build-wins) + while the fixture does not, so a graph regeneration cannot silently invalidate + the test. +- The fixture must carry the **full `Op` enum**: `lower.zig`'s `switch + (node.op)` is exhaustive with no `else`, so the enum must stay in sync. That + is a deliberate loud coupling — a new VM op fails the fixture compile. +- Only the per-op tables the *present* ops read need to exist (`clip_lo`/ + `clip_hi` here); the arms of absent ops are comptime-skipped. +- Prototyping gotcha: `lower.zig`'s `@import("qp.zig")` is resolved **even when + `has_solve_qp = false`** (relative file imports are not lazily elided the way + the `solver_meta` anonymous import is). `qp.zig` sits next to `lower.zig`, so + the test module finds it — but the test module must stay rooted at + `lower.zig` for that relative import to resolve. No OSQP bake is needed. + +### Verification + +- `zig build test`: **51/51 passed** (48 linalg + 1 emosqp + 2 lower). +- `make test-zig` (zig-gen → build real `.so` → `zig build test` → + `pytest tests/test_zig_lowering.py`): **91 passed, 2 skipped** — the + `pub export` change did not disturb the ctypes oracle or the `.so` symbol. +- Prototype sanity check: a deliberately wrong expected output fails the native + test, so it genuinely executes the VM. + +### Follow-ups + +- The fixture covers the ABI plumbing + a representative op mix; full op + coverage stays with the Python oracle (`tests/test_zig_lowering.py`, + `tests/test_op_shape_matrix.py`). +- The comptime-injection refactor remains an option if arbitrary inline Zig + fixture graphs are wanted later. + +## Split the C-ABI export out of `lower.zig` into `entry.zig` + +### Why + +`lower.zig` conflated three concerns: the VM, the graph binding +(`@import("graph_data")` + `solver_meta`/`qp`), and the C-ABI surface +(`export fn shinro_step`). That coupling is what forced a graph fixture to be +wired into the *module* for every test graph. Separating the binding/export +from the VM lets the VM take the graph as a comptime parameter +(`Vm(Ctx)`), so tests — and, later, a multi-graph fixture table — inject their +own graph with no per-graph anonymous-import choreography. + +### What changed + +- `src/shinro/runtime/lower.zig` — now graph-agnostic: `pub fn Vm(comptime Ctx: + type) type` wraps the whole VM (`workspace`, `step`, and the four helpers) in + a container, with `const g = Ctx.graph;` aliasing the injected graph so the + **body is byte-for-byte unchanged** (every `g.nodes` / `g.offsets` reference + stands). The `graph_data`/`solver_meta`/`qp` imports and the `export fn` are + gone; `sm`/`qp` now come from `Ctx` (only referenced for QP graphs). +- `src/shinro/runtime/entry.zig` (new) — the deployment entry: the only file + that imports `graph_data` (plus `solver_meta`/`qp.zig` when QP), assembles + `Ctx`, and declares `pub export fn shinro_step` forwarding to + `lower.Vm(Ctx).step`. +- `src/shinro/runtime/build.zig` — lib module root `lower.zig` → `entry.zig`; + the VM test module is now an anonymous-import-free `vm_mod`, and the fixture + graph is wired to the *driver* (`tests/lower.zig`) instead. +- `src/shinro/runtime/tests/lower.zig` — binds the fixture itself + (`const Ctx = struct { pub const graph = g; … }`) and calls + `lower.Vm(Ctx).step`. +- `src/shinro/runtime/README.md` + `docs/codegen.md` — table/narrative rows for + `entry.zig` and the graph-agnostic VM. + +### Verification + +- `zig build test`: **51/51 passed** (48 linalg + 1 emosqp + 2 VM). +- `make test-zig` (real ReleaseFast `.so` + ctypes oracle + pytest): **91 + passed, 2 skipped** — the shipped KF+LQR oracle, the MPC/`.solve_qp` oracle, + and the ONNX/recurrent oracles all still match `interpret()`, so the QP path + through `entry.zig`'s conditional `solver_meta`/`qp` wiring is intact. +- Binary check: built pre-refactor HEAD in a scratch worktree and diffed the + `.so`. With `step` marked `inline` (needed so the exported wrapper compiles + to exactly the old body), the shipped **ReleaseFast `.so` is byte-identical** + to pre-refactor (`sha256 7d42e97b…`) — so production is provably unchanged, + not merely behaviorally equivalent. The Debug build differs by 32 B of + argument-spill slots on the exported wrapper (debug-info only); behavior is + oracle-verified in both modes. + +### Follow-ups + +- The multi-graph fixture table (one shared `Vm(Ctx)` driver + N generated + `(graph, vectors)` pairs) is now a pure build.zig table addition — no VM + changes, no per-graph module instances. + +## Frozen multi-graph VM fixtures (real HF policies) + +### Why + +Step 2 of the native-test work: drive `Vm(Ctx)` with a menu of real graph +types — classical, MLP, and recurrent — generated once and committed, so the +VM is regression-tested against them without any generation-time churn. + +### What changed + +- `scripts/gen_lower_fixtures.py` (new): generate-once generator. Per fixture it + lowers the composed graph, post-processes the emitted `const_blob_f32` into a + raw little-endian `.bin` re-exposed via `@embedFile` + `bytesAsSlice` (an + `align(@alignOf(f32))` copy keeps it safe for the kernel's vector weight + loads), and emits `interpret()` vectors (8 seeded samples). Deliberately NOT + wired into `make zig-gen`/CI. +- `src/shinro/runtime/tests/graphs/` (new, generated): `kf_lqr`, `toy_lstm`, + `go2` (real Unitree Go2 MLP), `drone_gru` (real eco-drone GRU) — each + `_graph.zig` + `_weights.bin` + `_data.zig`. +- `src/shinro/runtime/tests/lower_graph.zig` (new): one shared driver, compiled + once per fixture via `lower.Vm(Ctx)`. +- `build.zig`: a `graph_fixtures` table — one graph+vectors module pair and one + test per row. Adding a graph type is one row. + +### Why the compact encoding + +The real policies lower to big *Zig source* because the f32 weight blob is +written as hex literals: go2 4.1 MB, drone_gru 1.9 MB. A raw f32 `.bin` + +`@embedFile` cuts them to 736 KB / 342 KB — ~1.2 MB for all four fixtures vs +~6 MB. Compile time was never the issue (go2 builds in ~1.7 s); repo size was. + +### Verification + +- `zig build test`: **55/55** (48 linalg + 1 emosqp + 2 hand fixture + 4 frozen + graph fixtures). The 4 new tests passing validates both the compact blob + (alignment + values) and the recurrent state plumbing against `interpret()`. +- `make test-zig`: **91 passed, 2 skipped** — unchanged ctypes oracle. +- Total fixture payload: ~1.24 MB. + +### Follow-ups + +- Add a fixture = one `FI` entry in the generator + one `graph_fixtures` row. +- The fixture header records the source (HF path or recipe); no manifest is + committed (it was redundant with the graph table). + +### C-ABI coverage for the fixtures + +`TestFrozenFixturesCAbi` (tests/test_zig_lowering.py) builds a `.so` per fixture +and drives the **exported** `shinro_step` symbol via ctypes against the same +committed vectors — covering the export/port-packing surface the in-process +`Vm(Ctx).step` oracle bypasses, and the compiled path for the compact +`@embedFile` graph format. `make test-zig`: **95 passed, 2 skipped** (was 91). +Self-contained: reads only the committed fixtures (no shinro-bench, no ONNX). + +### Native QP fixture + C-ABI routing (issue #14 closure) + +Closed the last uncovered VM op (`solve_qp`). The frozen menu gains an `mpc` +fixture (KF + MPC_LTI, `has_solve_qp = true`, tol 1e-3), and the fixture driver +now routes through the **exported C-ABI `shinro_step`** instead of +`Vm(Ctx).step`: each fixture gets its own `entry` module (rooted at `entry.zig`) +so `graph_data` resolves to that fixture, and the QP one also compiles the baked +OSQP solver (include paths + C sources + `solver_meta`). `entry.zig`'s +`shinro_step` became `pub export` so the tests can call it (symbol unchanged). + +- `zig build test`: **56/56** (was 55; +the `mpc` fixture). The `.solve_qp` arm + now has a Zig-native path (entry → `Vm(Ctx)` → `qp.solve_qp` → the C bake). +- `make test-zig`: **96 passed, 2 skipped** (was 95/2 — `mpc` also passes through + the `.so` via `TestFrozenFixturesCAbi`). +- The generator now runs `zig fmt` on its output, so regeneration is a no-op + against the committed files (only a new fixture shows as a diff). + +Pitfall hit while verifying: the fixture `.so` builds land in pytest's `/tmp`; +a full `/tmp` made `zig build` fail with `DiskQuota`, which the tests surface as +**skips** (`_build_fixture_so` skips on build failure) — clear scratch dirs +before trusting a skip count. diff --git a/scripts/gen_lower_fixtures.py b/scripts/gen_lower_fixtures.py new file mode 100644 index 0000000..7e470c9 --- /dev/null +++ b/scripts/gen_lower_fixtures.py @@ -0,0 +1,240 @@ +"""Generate the Zig-native VM test fixtures (graph + compact weights + vectors). + +For each fixture this lowers a composed graph with +:func:`shinro.codegen.lower_zig.lower_zig`, then post-processes the emitted +``graph_data.zig`` to shrink the f32 weight blob: the ``const_blob_f32`` values +are written as a raw little-endian ``.bin`` and re-exposed at compile time via +``@embedFile`` + ``std.mem.bytesAsSlice`` (a ~5x reduction vs. hex literals — +the go2 MLP drops from ~4 MB to ~0.75 MB). The oracle vectors come from +:func:`shinro.codegen.interpret` on seeded random inputs, so the committed graph +and its expected outputs are generated together and stay self-consistent. + +Following the repo's "Python emits data only" doctrine, the Zig driver +(``runtime/tests/lower_graph.zig``) is handwritten once; only the graph, the +weight blob, and the vectors are emitted here. + +This is a **generate-once** step — it is NOT wired into ``make zig-gen`` or CI. +Run it deliberately, review the diff, commit. It needs the sibling +``shinro-bench`` checkout for the real HF policies (go2, drone_gru); the +``toy_lstm`` fixture lives in this repo, and ``kf_lqr`` comes from the recipe. + +Usage:: + + python3 scripts/gen_lower_fixtures.py # all fixtures + python3 scripts/gen_lower_fixtures.py --only go2 + python3 scripts/gen_lower_fixtures.py --bench-root ../shinro-bench +""" + +from __future__ import annotations + +import argparse +import re +import shutil +import struct +import subprocess +import sys +from pathlib import Path +from typing import Any + +REPO = Path(__file__).resolve().parents[1] +OUT_DIR = REPO / "src" / "shinro" / "runtime" / "tests" / "graphs" + +#: Number of seeded oracle samples per fixture, and the seed (fixed for +#: reproducibility — re-running must reproduce identical vectors). +SAMPLES = 8 +SEED = 0 +#: Non-QP oracle tolerance (same tier the ctypes oracle uses). +TOL = 1e-12 + +_ORIG_HEADER = ( + "// Generated by shinro.codegen.lower_zig — DO NOT EDIT.\n" + "// A ComposedGraph serialized as a comptime data table.\n" +) + +#: The fixture menu. ``root`` selects where ``model`` is resolved (the repo or +#: the sibling shinro-bench checkout); ``kind = "classical"`` uses a recipe. +FI = { + "kf_lqr": { + "kind": "classical", + "recipe": "build_base_graph", + "desc": "closed-loop Kalman filter + LQR (matmul/reshape/add/sub/inv/clip + recurrence)", + }, + "mpc": { + "kind": "classical", + "recipe": "build_mpc_composed_graph", + "tol": 1e-3, + "desc": "closed-loop Kalman filter + MPC_LTI (.solve_qp via the baked OSQP solver)", + }, + "toy_lstm": { + "kind": "onnx", + "root": "repo", + "model": "tests/fixtures/models/toy_lstm.onnx", + "desc": "committed toy LSTM, H=4 (fused LSTM cell + live state)", + }, + "go2": { + "kind": "onnx", + "root": "bench", + "model": "tasks/policies/models/go2/policy.onnx", + "obs_cfg": {"input_name": "obs"}, + "desc": "real Unitree Go2 velocity MLP (4xGemm + 3xElu + obs norm)", + }, + "drone_gru": { + "kind": "onnx", + "root": "bench", + "model": "tasks/policies/models/drone_gru/policy_v26rnn_dr.onnx", + "obs_cfg": {"input_name": "state"}, + "desc": "real eco-drone GRU, H=128 (fused GRU cell + live state)", + }, +} + + +def _build_composed(name: str, spec: dict[str, Any], bench_root: Path): + """Build the ComposedGraph for one fixture spec.""" + if spec["kind"] == "classical": + from shinro.codegen import recipes + + return getattr(recipes, spec["recipe"])() + root = REPO if spec["root"] == "repo" else bench_root + model = root / spec["model"] + if not model.exists(): + raise FileNotFoundError(f"{name}: model not found: {model}") + from shinro.codegen.onnx_import import import_onnx_policy + + return import_onnx_policy( + str(model), + obs_cfg=spec.get("obs_cfg"), + action_cfg={"action_space": "continuous", "deterministic": True}, + output_name=spec.get("output_name"), + ) + + +def _compact_f32_blob(name: str, graph_path: Path, header: str) -> None: + """Replace ``const_blob_f32`` hex literals with an embedded raw f32 blob. + + Graphs with no f32 weights (e.g. an all-f64 classical graph) keep their + empty blob as-is; the generated header is always replaced with ``header``. + """ + text = graph_path.read_text() + m = re.search(r"pub const const_blob_f32 = \[_\]f32\{(.*?)\};", text) + if m is None or not m.group(1).strip(): + graph_path.write_text(text.replace(_ORIG_HEADER, header)) + return + body = m.group(1) + values = [float.fromhex(tok.strip()) for tok in body.split(",") if tok.strip()] + raw = b"".join(struct.pack(" tuple[int, int, int]: + """Run the Python interpreter on seeded inputs; emit the expected vectors.""" + import numpy as np + + from shinro.codegen import interpret + from shinro.codegen.lower_zig import _zig_floats + from shinro.codegen.oracle import output_split, pack_arrays, random_inputs + + n_out, n_state = output_split(cg) + rng = np.random.default_rng(SEED) + ins, outs, states = [], [], [] + for _ in range(SAMPLES): + ports = random_inputs(cg, rng) + ins.append(pack_arrays(cg, ports)) + traced = interpret(cg.graph, ports) + outs.append(np.concatenate([np.ravel(traced[o]) for o in cg.outputs])) + if cg.state_outputs: + states.append(np.concatenate([np.ravel(traced[s]) for s in cg.state_outputs])) + else: + states.append(np.zeros(0, dtype=np.float64)) + n_in = int(ins[0].size) + in_flat = np.concatenate(ins) + out_flat = np.concatenate(outs) + state_flat = np.concatenate(states) if n_state else np.zeros(0, dtype=np.float64) + + data_path.write_text( + f"// Test vectors for `{name}` — generated by scripts/gen_lower_fixtures.py.\n" + f"// Produced by shinro.codegen.interpret on {SAMPLES} seeded inputs (seed={SEED}).\n" + f"pub const n_samples = {SAMPLES};\n" + f"pub const n_in = {n_in};\n" + f"pub const n_out = {n_out};\n" + f"pub const n_state = {n_state};\n" + f"pub const tol = {tol!r};\n" + f"pub const inputs = [_]f64{{{_zig_floats(in_flat.tolist())}}};\n" + f"pub const outputs = [_]f64{{{_zig_floats(out_flat.tolist())}}};\n" + f"pub const states = [_]f64{{{_zig_floats(state_flat.tolist())}}};\n" + ) + return n_in, n_out, n_state + + +def generate(name: str, spec: dict[str, Any], bench_root: Path, out_dir: Path) -> None: + """Generate the graph, weights, and vectors for one fixture.""" + from shinro.codegen.lower_zig import lower_zig + + cg = _build_composed(name, spec, bench_root) + if spec["kind"] == "classical": + source = f"recipes.{spec['recipe']}()" + else: + root = REPO if spec["root"] == "repo" else bench_root + source = str(root / spec["model"]) + header = ( + f"// Test fixture `{name}` — {spec['desc']}.\n" + f"// Generated by scripts/gen_lower_fixtures.py from {source} — DO NOT EDIT.\n" + ) + graph_path = out_dir / f"{name}_graph.zig" + data_path = out_dir / f"{name}_data.zig" + lower_zig(cg, str(graph_path)) + graph_path.with_name(graph_path.stem + "_manifest.json").unlink(missing_ok=True) + _compact_f32_blob(name, graph_path, header) + n_in, n_out, n_state = _emit_vectors(name, cg, data_path, spec.get("tol", TOL)) + + graph_kb = graph_path.stat().st_size / 1024 + weights = graph_path.parent / f"{name}_weights.bin" + w_kb = weights.stat().st_size / 1024 if weights.exists() else 0.0 + data_kb = data_path.stat().st_size / 1024 + print( + f"{name:10s} nodes={len(cg.graph.nodes):4d} n_in={n_in:4d} n_out={n_out:3d} " + f"n_state={n_state:4d} graph={graph_kb:8.1f}KB weights={w_kb:8.1f}KB data={data_kb:6.1f}KB" + ) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--bench-root", default=str(REPO.parent / "shinro-bench"), + help="sibling shinro-bench checkout (default: ../shinro-bench)") + parser.add_argument("--only", action="append", choices=sorted(FI), + help="generate only this fixture (repeatable)") + parser.add_argument("--out-dir", default=str(OUT_DIR), + help="output directory (default: runtime/tests/graphs)") + args = parser.parse_args() + + out_dir = Path(args.out_dir).resolve() + out_dir.mkdir(parents=True, exist_ok=True) + bench_root = Path(args.bench_root).resolve() + + names = args.only or list(FI) + for name in names: + try: + generate(name, FI[name], bench_root, out_dir) + except FileNotFoundError as exc: + print(f"ERROR: {exc}", file=sys.stderr) + return 2 + # Normalize formatting so regenerating is a no-op against the committed + # files (lower_zig's output is not necessarily zig-fmt clean). + if shutil.which("zig"): + subprocess.run(["zig", "fmt", str(out_dir)], check=False) + print(f"\nwrote fixtures to {out_dir}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/src/shinro/runtime/README.md b/src/shinro/runtime/README.md index 666061f..ac84597 100644 --- a/src/shinro/runtime/README.md +++ b/src/shinro/runtime/README.md @@ -12,14 +12,19 @@ pipeline narrative and the XLA-fidelity model. | File | Role | |------|------| -| `build.zig` | Build script. Produces `libbase.so` from `lower.zig` + `graph_data.zig`; it links the generated OSQP codegen solver **only when the graph contains `.solve_qp`**. | +| `build.zig` | Build script. Produces `libbase.so` from `entry.zig` (+ the graph-agnostic `lower.zig`); it links the generated OSQP codegen solver **only when the graph contains `.solve_qp`**. | | `build.zig.zon` | Package/dependency manifest for the Zig build. | -| `lower.zig` | The comptime VM. Exports the `shinro_step` C-ABI function: one `inline for` over the node table, dispatching each node's op with `rows`/`cols` as comptime constants. | +| `entry.zig` | The deployment entry point: the **only** file that imports `graph_data` (and, for QP graphs, `solver_meta`/`qp.zig`), binds them into the VM's context, and exports the `shinro_step` C-ABI symbol. | +| `lower.zig` | The comptime VM, graph-agnostic. `pub fn Vm(Ctx)` instantiates it over an injected graph context; its `step` runs one tick by one `inline for` over the node table, dispatching each node's op with `rows`/`cols` as comptime constants. | | `linalg.zig` | Shared linear-algebra kernels (matmul, elementwise ops, `inv`, ...) used by the VM. | | `qp.zig` | The `.solve_qp` op wrapper: drives the generated static OSQP solver (update q → solve → copy solution out). | | `graph_data.zig` | **Generated** — the graph as Zig constants (op enum, node table, offsets, `const_blob`, `has_solve_qp`). Produced by `scripts/gen_base.py` / `shinro.codegen.lower_zig`. Not hand-edited. | | `codegen/emosqp/` | **Generated** — the statically-allocated OSQP solver for the base MPC problem (no malloc, no libosqp). Emitted by `scripts/gen_emosqp_test.py`. | | `tests/linalg.zig` | Zig unit tests for the linear-algebra kernels. | +| `tests/lower.zig` | Zig-native C-ABI tests for `lower.zig`: drives `shinro_step` in-process, no `.so`/ctypes/Python. | +| `tests/lower_fixture_graph.zig` | Hand-authored fixture `graph_data.zig` (tiny node table) compiled into the `tests/lower.zig` test module. | +| `tests/lower_graph.zig` | Shared frozen-fixture oracle: one copy compiled per fixture, instantiating `Vm(Ctx)` over that fixture's graph. | +| `tests/graphs/` | **Generated** — the frozen fixtures: `_graph.zig` + `_weights.bin` (raw f32, `@embedFile`d) + `_data.zig` (expected vectors). Emitted by `scripts/gen_lower_fixtures.py` (generate-once). | | `tests/emosqp.zig` | Handwritten Zig test driving the codegen static solver, compared against the Python oracle. | | `tests/emosqp_data.zig` | **Generated** — the oracle test vectors (sample `q` + expected solution, hex floats). Emitted by `scripts/gen_emosqp_test.py`. | @@ -71,6 +76,28 @@ against the Python interpreter lives in `tests/test_zig_lowering.py` (the `.solve_qp` op is exercised by the MPC graph fixture, which traces `MPC_LTI` and compares `shinro_step` against `interpret()`). +`zig build test` also runs `tests/lower.zig`, which instantiates the VM with +`lower.Vm(Ctx).step(...)` and drives the C-ABI entry path **natively** — +directly in the test process, compiled against the committed fixture graph +`tests/lower_fixture_graph.zig` (bound by `build.zig` as the test module's +`graph_data` anonymous import). It needs no shared-library build, no ctypes, +and no Python, so a VM/ABI regression surfaces in the Zig test step alone. The +fixture is solver-free, so it pulls in no OSQP bake. + +`zig build test` additionally compiles `tests/lower_graph.zig` **once per frozen +fixture** (KF+LQR, a toy LSTM, the real Go2 MLP, the real eco-drone GRU, and a +KF+MPC `.solve_qp` graph), each calling the exported C-ABI `shinro_step` through +its own `entry` module and checking the outputs/state against `interpret()` on +the recorded vectors. The QP fixture's `entry` module also compiles the baked +OSQP solver, so `.solve_qp` is covered natively too. The +fixtures live under `tests/graphs/`: the graph is Zig constants, but the f32 +weight blob is a raw little-endian `.bin` embedded at compile time +(`@embedFile` + `bytesAsSlice`) — ~5x smaller than hex literals (the Go2 MLP is +~0.75 MB instead of ~4 MB). Regenerate them *deliberately* with +`python3 scripts/gen_lower_fixtures.py` (needs the sibling `shinro-bench` +checkout for the real policies); this is a generate-once step, deliberately not +wired into `make zig-gen` or CI, so the fixtures never churn. + ## Generated artifacts — shared paths, last build wins Three paths feed `zig build`, and all of them are **generated, single-instance, @@ -96,7 +123,7 @@ zig build --build-file src/shinro/runtime/build.zig --prefix build/ \ -Dgraph= -Dsolver_dir= ``` -- `-Dgraph` — the generated graph (default `graph_data.zig`). `lower.zig` +- `-Dgraph` — the generated graph (default `graph_data.zig`). `entry.zig` imports it as an anonymous module, so a build can consume a graph from any path (e.g. a pytest tmp dir). - `-Dsolver_dir` — the baked OSQP codegen solver tree (default diff --git a/src/shinro/runtime/build.zig b/src/shinro/runtime/build.zig index 6e3a1ee..a013af5 100644 --- a/src/shinro/runtime/build.zig +++ b/src/shinro/runtime/build.zig @@ -82,13 +82,14 @@ pub fn build(b: *std.Build) void { }); // base.so — the C-ABI graph VM the Python host dlopen-s via ctypes. - // lower.zig is the module root; @import("linalg.zig") and @import("qp.zig") - // resolve next to it, while the generated graph and the bake's n_vars - // arrive as anonymous imports selected by -Dgraph / -Dsolver_dir. The - // `.solve_qp` op compiles the codegen static solver into the library, - // but only when the lowered graph contains that op. + // entry.zig is the module root: it binds the generated graph (selected by + // -Dgraph) and the bake (selected by -Dsolver_dir) into the VM's context + // and exports shinro_step. lower.zig itself is graph-agnostic; the VM is + // instantiated through entry.zig's Ctx. The `.solve_qp` op compiles the + // codegen static solver into the library, but only when the lowered graph + // contains that op. const lib_mod = b.createModule(.{ - .root_source_file = b.path("lower.zig"), + .root_source_file = b.path("entry.zig"), .target = target, .optimize = optimize, .link_libc = true, @@ -158,6 +159,27 @@ pub fn build(b: *std.Build) void { const tests = b.addTest(.{ .root_module = test_mod }); const run_tests = b.addRunArtifact(tests); + // Zig-native C-ABI test of the VM: the graph-agnostic lower.zig exposed to + // tests/lower.zig as the `lower` module, plus the small committed fixture + // graph (tests/lower_fixture_graph.zig) as its `graph_data`. Because the VM + // now takes the graph via `Vm(Ctx)`, the test binds the fixture itself — + // nothing here is the deployed graph_data.zig, so no .so/ctypes/Python and + // no OSQP bake are needed. + const vm_mod = b.createModule(.{ + .root_source_file = b.path("lower.zig"), + .target = target, + .optimize = optimize, + }); + const lower_driver_mod = b.createModule(.{ + .root_source_file = b.path("tests/lower.zig"), + .target = target, + .optimize = optimize, + .imports = &.{.{ .name = "lower", .module = vm_mod }}, + }); + lower_driver_mod.addAnonymousImport("graph_data", .{ .root_source_file = b.path("tests/lower_fixture_graph.zig") }); + const lower_tests = b.addTest(.{ .root_module = lower_driver_mod }); + const run_lower_tests = b.addRunArtifact(lower_tests); + // OSQP codegen static solver test — compiles the generated C // (runtime/codegen/emosqp/) into the test and drives the static solver. // This remains in the test step even when the deployment graph is @@ -178,6 +200,55 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Run Zig unit tests"); test_step.dependOn(&run_tests.step); test_step.dependOn(&run_emosqp_tests.step); + test_step.dependOn(&run_lower_tests.step); + + // Frozen multi-graph oracle: one instance of tests/lower_graph.zig per + // fixture, each calling the exported C-ABI `shinro_step` for that fixture's + // graph and checking it against the committed vectors. Generated once by + // scripts/gen_lower_fixtures.py; adding a graph type is one table row. + // + // Each fixture gets its own `entry` module (rooted at entry.zig) so + // `graph_data` resolves to that fixture. A QP fixture also needs the baked + // OSQP solver compiled in (qp.zig @cImports osqp.h and links the C bake). + const graph_fixtures = .{ + .{ .name = "kf_lqr", .graph = "tests/graphs/kf_lqr_graph.zig", .data = "tests/graphs/kf_lqr_data.zig", .qp = false }, + .{ .name = "toy_lstm", .graph = "tests/graphs/toy_lstm_graph.zig", .data = "tests/graphs/toy_lstm_data.zig", .qp = false }, + .{ .name = "go2", .graph = "tests/graphs/go2_graph.zig", .data = "tests/graphs/go2_data.zig", .qp = false }, + .{ .name = "drone_gru", .graph = "tests/graphs/drone_gru_graph.zig", .data = "tests/graphs/drone_gru_data.zig", .qp = false }, + .{ .name = "mpc", .graph = "tests/graphs/mpc_graph.zig", .data = "tests/graphs/mpc_data.zig", .qp = true }, + }; + inline for (graph_fixtures) |spec| { + const entry_mod = b.createModule(.{ + .root_source_file = b.path("entry.zig"), + .target = target, + .optimize = optimize, + .link_libc = spec.qp, + }); + entry_mod.addAnonymousImport("graph_data", .{ .root_source_file = b.path(spec.graph) }); + if (spec.qp) { + entry_mod.addAnonymousImport("solver_meta", .{ .root_source_file = b.path("codegen/emosqp/solver_meta.zig") }); + entry_mod.addIncludePath(b.path("codegen/emosqp/inc/public")); + entry_mod.addIncludePath(b.path("codegen/emosqp/inc/private")); + entry_mod.addIncludePath(b.path("codegen/emosqp")); + entry_mod.addCSourceFiles(.{ .files = &default_emosqp_srcs, .flags = &.{} }); + } + const vectors_mod = b.createModule(.{ + .root_source_file = b.path(spec.data), + .target = target, + .optimize = optimize, + }); + const fixture_driver = b.createModule(.{ + .root_source_file = b.path("tests/lower_graph.zig"), + .target = target, + .optimize = optimize, + .imports = &.{ + .{ .name = "entry", .module = entry_mod }, + .{ .name = "vectors", .module = vectors_mod }, + }, + }); + const fixture_test = b.addTest(.{ .root_module = fixture_driver }); + test_step.dependOn(&b.addRunArtifact(fixture_test).step); + } // Build manifest (audit trail): a deterministic report of what this .so // contains, written next to the artifact after every build, plus a diff --git a/src/shinro/runtime/entry.zig b/src/shinro/runtime/entry.zig new file mode 100644 index 0000000..24a1a02 --- /dev/null +++ b/src/shinro/runtime/entry.zig @@ -0,0 +1,35 @@ +// runtime/entry.zig — the deployment entry point. +// +// This is the only file that binds the generated graph to the VM and the only +// one that declares the `shinro_step` C-ABI symbol. `lower.zig` holds the +// graph-agnostic VM (`Vm(Ctx)`); here we assemble the context from the graph +// selected by `-Dgraph` (plus the bake selected by `-Dsolver_dir`) and expose +// its `step` under the stable C name. +// +// Why the split: the graph binding and the ABI surface change with deployment +// (which graph, which bake), while the VM must not. Keeping the binding here +// lets the VM be compiled against any graph — tests instantiate `Vm(Ctx)` +// directly with their own fixture — and keeps every build option +// (`-Dgraph`, `-Dsolver_dir`) touching exactly one small file. + +const lower = @import("lower.zig"); +const g = @import("graph_data"); +// OSQP is deliberately conditional: the generated graph declares whether it +// contains a .solve_qp node. Non-QP graphs (LQR, PID, ...) build without the +// OSQP C sources, headers, or solver_meta module at all. +const solver_meta = if (g.has_solve_qp) @import("solver_meta") else struct {}; +const qp_mod = if (g.has_solve_qp) @import("qp.zig") else struct {}; + +/// The VM context for the deployed graph: the graph plus the (optional) bake. +pub const Ctx = struct { + pub const graph = g; + pub const sm = solver_meta; + pub const qp = qp_mod; +}; + +/// One tick of the deployed closed-loop step (see lower.zig's `Vm(Ctx).step` +/// for the buffer contract). `pub` so the Zig-native fixture tests can call the +/// real C-ABI entry directly; the exported symbol name is unchanged. +pub export fn shinro_step(inputs: [*]const f64, outputs: [*]f64, state_out: [*]f64) void { + lower.Vm(Ctx).step(inputs, outputs, state_out); +} diff --git a/src/shinro/runtime/lower.zig b/src/shinro/runtime/lower.zig index 40bcdad..873a9cf 100644 --- a/src/shinro/runtime/lower.zig +++ b/src/shinro/runtime/lower.zig @@ -1,677 +1,703 @@ -// runtime/lower.zig — comptime graph VM: walks the generated node table and +// runtime/lower.zig — comptime graph VM: walks a generated node table and // specializes one step of the closed loop at compile time. // // This is the Zig mirror of interpreter.py's dispatch loop. The graph data // (op enum, inputs, shapes) is generated by shinro.codegen.lower_zig into // graph_data.zig; the *code* here is handwritten once and never regenerated. // +// This file is graph-agnostic: it never imports graph_data.zig. The caller +// instantiates `Vm(Ctx)` with a context carrying the graph (and, for QP graphs, +// the baked solver metadata + wrapper). The deployed graph is bound in +// entry.zig, which also declares the `shinro_step` C-ABI symbol; tests bind +// their own fixtures. See `pub fn Vm` below. +// // The VM is comptime-specialized along one axis only: the outer `inline for` // over the node table unrolls every node, so each node's op and shape are // comptime constants and its slot is a fixed-size slice of one contiguous -// file-scope buffer — no heap, no runtime op dispatch. The element loops *inside* -// each node are runtime `for` loops over those comptime-known sizes. Unrolling -// them too emits one statement per element (~`buf_len` of them) and forces the -// compiler to optimize a single function of hundreds of thousands of +// container-scope buffer — no heap, no runtime op dispatch. The element loops +// *inside* each node are runtime `for` loops over those comptime-known sizes. +// Unrolling them too emits one statement per element (~`buf_len` of them) and +// forces the compiler to optimize a single function of hundreds of thousands of // instructions: minutes of compile and a `.so` that is ~2x the buffer in pure // `.text`. Runtime element loops keep compile time and code size proportional // to the node count, not the element count. // // C ABI (all flat, row-major f64 buffers; layout known to the host from the // ComposedGraph port lists): -// shinro_step(inputs, outputs, state_out) +// shinro_step(inputs, outputs, state_out) <- declared in entry.zig // - inputs: host inputs packed in cg.inputs order (e.g. y, x_ref, u_prev // followed by the estimator's state_* recurrent ports) // - outputs: packed in cg.outputs order // - state_out: packed in cg.state_outputs order (recurrent → next tick) const std = @import("std"); -// The generated graph and the bake's n_vars are anonymous imports wired by -// build.zig from -Dgraph / -Dsolver_dir (defaults: runtime/graph_data.zig and -// runtime/codegen/emosqp/solver_meta.zig). -const g = @import("graph_data"); -// OSQP is deliberately conditional: the generated graph declares whether it -// contains a .solve_qp node. Non-QP graphs (LQR, PID, ...) build without the -// OSQP C sources, headers, or solver_meta module at all. -const sm = if (g.has_solve_qp) @import("solver_meta") else struct {}; const la = @import("linalg.zig"); -const qp = if (g.has_solve_qp) @import("qp.zig") else struct {}; - -/// Per-tick workspace: every node's output slot is a slice of `workspace`, -/// addressed by `g.offsets`. Declared at file scope rather than as a local in -/// `shinro_step` so its size — `g.buf_len` f64, tens of MiB for large policies -/// — does not have to fit on the caller's stack (a stack-local copy overflows -/// the default 16 MiB stack past roughly 500k parameters). -/// -/// This is process-global mutable state, so `shinro_step` is **not reentrant -/// or thread-safe**: one call must finish before the next starts. That is the -/// deployment model (one control loop, one tick at a time) and matches the QP -/// path's statically-allocated `solver` global. The graph writes every slot -/// before it is read, so the buffer needs no initialization. -var workspace: [g.buf_len]f64 align(16) = undefined; -/// Run one tick of the closed-loop step through the generated node table. -/// -/// The C-ABI entry point (exported as `shinro_step`) that the host calls once -/// per control tick. All buffers are flat, row-major f64; their layout is -/// known to the host from the ComposedGraph port lists: -/// -/// - `inputs`: host inputs packed in `cg.inputs` order (e.g. `y`, `x_ref`, -/// `u_prev` followed by the estimator's `state_*` recurrent ports) -/// - `outputs`: packed in `cg.outputs` order -/// - `state_out`: packed in `cg.state_outputs` order (recurrent → next tick) +/// Instantiate the comptime graph VM over a context type. /// -/// The `inline for` over `g.nodes` unrolls the whole node table at compile -/// time, so every node's op and shape are comptime constants and every array -/// is a fixed-size slice of the single file-scope `workspace` — no heap, no -/// runtime op dispatch. The element loops *within* each node are runtime loops over -/// those comptime-known sizes, so code size and compile time scale with the -/// node count rather than with `buf_len`. +/// `Ctx` is a namespace (typically `struct { pub const graph = …; pub const sm = +/// …; pub const qp = …; }`) assembled by the caller. `Ctx.graph` is the +/// generated `graph_data.zig` module; `Ctx.sm` and `Ctx.qp` are the baked solver +/// metadata (`solver_meta.zig`) and the `.solve_qp` wrapper (`qp.zig`), referenced +/// only when the graph declares `has_solve_qp`. Keeping the graph out of this file +/// is what lets the VM be compiled against any graph — the deployed one is bound +/// in entry.zig, while tests bind their own fixtures. /// -/// Not reentrant or thread-safe: writes go to the shared file-scope -/// `workspace` (see its declaration). Callers run one tick at a time. -/// -/// Args: -/// inputs: Flat buffer of this tick's host inputs. -/// outputs: Flat buffer where this tick's output ports are written. -/// state_out: Flat buffer where this tick's recurrent state outputs are -/// written (fed back as state inputs next tick). -export fn shinro_step(inputs: [*]const f64, outputs: [*]f64, state_out: [*]f64) void { - @setEvalBranchQuota(1_000_000); +/// Returns: +/// A type whose `step` runs one tick and whose `workspace` is the per-tick +/// scratch (one `.bss` array sized to that graph's `buf_len`). +pub fn Vm(comptime Ctx: type) type { + const g = Ctx.graph; + // OSQP is deliberately conditional: the generated graph declares whether it + // contains a .solve_qp node. Non-QP graphs (LQR, PID, ...) never reference + // these, so a solver-free fixture can pass `struct {}` for `sm`/`qp`. + const sm = if (g.has_solve_qp) Ctx.sm else struct {}; + const qp = if (g.has_solve_qp) Ctx.qp else struct {}; - inline for (g.nodes, 0..) |node, i| { - // Const nodes own no workspace slot: their data lives in the baked blob - // and consumers read it in place (node_input_at / the contraction arms). - // Skipping them keeps buf_len to the real working set and means no slice - // is ever taken at a const node's (unused) offset. - if (node.op == .cst or node.op == .cst_f32) continue; + return struct { + /// Per-tick workspace: every node's output slot is a slice of `workspace`, + /// addressed by `g.offsets`. Declared at container scope rather than as a + /// local in `step` so its size — `g.buf_len` f64, tens of MiB for large + /// policies — does not have to fit on the caller's stack (a stack-local + /// copy overflows the default 16 MiB stack past roughly 500k parameters). + /// + /// This is process-global mutable state, so `step` is **not reentrant or + /// thread-safe**: one call must finish before the next starts. That is the + /// deployment model (one control loop, one tick at a time) and matches the + /// QP path's statically-allocated `solver` global. The graph writes every + /// slot before it is read, so the buffer needs no initialization. + var workspace: [g.buf_len]f64 align(16) = undefined; - const out = workspace[g.offsets[i]..][0 .. node.rows * node.cols]; + /// Run one tick of the closed-loop step through the generated node table. + /// + /// `inline` so entry.zig's exported wrapper compiles to exactly the + /// pre-split function body — keeping the shipped ReleaseFast `.so` + /// byte-identical to before the VM was made generic (and a solver-free + /// graph's VM identical to the old direct-export layout). + /// + /// The C-ABI payload: `shinro_step` in entry.zig forwards here. All + /// buffers are flat, row-major f64; their layout is known to the host from + /// the ComposedGraph port lists: + /// + /// - `inputs`: host inputs packed in `cg.inputs` order (e.g. `y`, `x_ref`, + /// `u_prev` followed by the estimator's `state_*` recurrent ports) + /// - `outputs`: packed in `cg.outputs` order + /// - `state_out`: packed in `cg.state_outputs` order (recurrent → next tick) + /// + /// The `inline for` over `g.nodes` unrolls the whole node table at compile + /// time, so every node's op and shape are comptime constants and every + /// array is a fixed-size slice of the single container-scope `workspace` — + /// no heap, no runtime op dispatch. The element loops *within* each node + /// are runtime loops over those comptime-known sizes, so code size and + /// compile time scale with the node count rather than with `buf_len`. + /// + /// Not reentrant or thread-safe: writes go to the shared `workspace` (see + /// its declaration). Callers run one tick at a time. + /// + /// Args: + /// inputs: Flat buffer of this tick's host inputs. + /// outputs: Flat buffer where this tick's output ports are written. + /// state_out: Flat buffer where this tick's recurrent state outputs are + /// written (fed back as state inputs next tick). + pub inline fn step(inputs: [*]const f64, outputs: [*]f64, state_out: [*]f64) void { + @setEvalBranchQuota(1_000_000); - switch (node.op) { - // Unreachable (consts are skipped above); kept for exhaustiveness. - .cst, .cst_f32 => {}, - .inp => { - for (0..node.rows * node.cols) |j| out[j] = inputs[node.aux + j]; - }, - .out => { - const src = node_input(g.nodes[0..], node, &workspace); - if (node.aux < g.n_outputs) { - for (0..node.rows * node.cols) |j| outputs[g.output_offsets[node.aux] + j] = src[j]; - } else { - for (0..node.rows * node.cols) |j| state_out[g.state_offsets[node.aux - g.n_outputs] + j] = src[j]; - } - }, - .matmul => { - const a = node_input(g.nodes[0..], node, &workspace); - const b = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const left = g.nodes[node.inputs[0]]; - const right = g.nodes[node.inputs[1]]; - if (left.vec) { - // vecmat: (k,) @ (k, n) -> (n,) — a genuinely 1-D left operand - const r = la.vecmat(left.rows, node.rows, a, b); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - } else if (right.vec) { - // matvec: (m, k) @ (k,) -> (m,) - const r = la.matvec(node.rows, right.rows, f64, a, b); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - } else { - // matmul: (m, k) @ (k, n) -> (m, n); also covers (m,1)@(1,n) (k=1) - const r = la.matmul(node.rows, left.cols, node.cols, a, b); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - } - }, - .add => ew2(g.nodes[0..], node, i, &workspace, .add), - .sub => ew2(g.nodes[0..], node, i, &workspace, .sub), - .mul => ew2(g.nodes[0..], node, i, &workspace, .mul), - .div => ew2(g.nodes[0..], node, i, &workspace, .div), - .ne => ew2(g.nodes[0..], node, i, &workspace, .ne), - .lt => ew2(g.nodes[0..], node, i, &workspace, .lt), - .pow => ew2(g.nodes[0..], node, i, &workspace, .pow), - .mod => ew2(g.nodes[0..], node, i, &workspace, .mod), - .neg => { - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| out[j] = -s[j]; - }, - .abs => { - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| out[j] = @abs(s[j]); - }, - .sign => { - // Matches np.sign: -1 / 0 / +1 (0 maps to 0, not +1). - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| { - out[j] = if (s[j] > 0.0) 1.0 else if (s[j] < 0.0) -1.0 else 0.0; - } - }, - .transpose => { - const s = node_input(g.nodes[0..], node, &workspace); - // True 2-D transpose: out (node.rows, node.cols) = src.T, so - // out[i][j] = src[j][i] — flat out[i*node.cols + j] = - // s[j*src.cols + i]. (The old form baked in the square case's - // stride symmetry and silently scrambled non-square inputs.) - for (0..node.rows) |oi| { - for (0..node.cols) |oj| out[oi * node.cols + oj] = s[oj * g.nodes[node.inputs[0]].cols + oi]; - } - }, - .inv => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.inv(node.rows, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .reshape => { - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| out[j] = s[j]; - }, - .clip => { - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| { - out[j] = std.math.clamp(s[j], g.clip_lo[node.aux + j], g.clip_hi[node.aux + j]); - } - }, - .where_op => { - const cond = node_input(g.nodes[0..], node, &workspace); - const a = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const b = node_input_at(g.nodes[0..], node.inputs[2], &workspace); - const cond_n = g.nodes[node.inputs[0]]; - const a_n = g.nodes[node.inputs[1]]; - const b_n = g.nodes[node.inputs[2]]; - for (0..node.rows) |oi| { - for (0..node.cols) |oj| { - const f = oi * node.cols + oj; - const c = cond[if (cond_n.rows * cond_n.cols == 1) 0 else f]; - const av = a[bcast_flat(a_n, a_n.vec, node.rows, node.cols, oi, oj)]; - const bv = b[bcast_flat(b_n, b_n.vec, node.rows, node.cols, oi, oj)]; - out[f] = if (c != 0.0) av else bv; - } - } - }, - .any => { - const s = node_input(g.nodes[0..], node, &workspace); - var found = false; - for (0..g.nodes[node.inputs[0]].rows * g.nodes[node.inputs[0]].cols) |j| { - if (s[j] != 0.0) found = true; - } - out[0] = if (found) 1.0 else 0.0; - }, - // deterministic-policy ops (issue #13): elementwise maps, a - // reduction (argmax), an expansion (one_hot), and shape glue - // (copy / slice). None allocate — all iterate comptime-known - // flat buffers. tanh/relu/exp preserve shape; argmax collapses - // to a scalar (stored as f64 in the buffer); one_hot expands a - // scalar index to a depth-row; copy/slice are flat copies with - // slice's `aux` holding the input offset. - .copy => { - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| out[j] = s[j]; - }, - .tanh => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.tanh(node.rows * node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .relu => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.relu(node.rows * node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .sigmoid => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.sigmoid(node.rows * node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .softmax => { - // Last-axis softmax (numpy axis=-1). A 1-D node is stored as - // rows=n, cols=1, vec=true — treat it as a single row of - // length n (rows*cols), never as n rows of length 1. - const s = node_input(g.nodes[0..], node, &workspace); - const r = if (node.vec) - la.softmax_rows(1, node.rows, s) - else - la.softmax_rows(node.rows, node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .gelu => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.gelu(node.rows * node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .elu => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.elu(node.rows * node.cols, g.elu_alpha[node.aux], s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - // .leaky_relu — x if x >= 0 else alpha*x. No linalg kernel (no exp): - // alpha is baked into g.leaky_relu_alpha (aux = table index), like - // elu's slope. At x == 0 both branches give 0. - .leaky_relu => { - const s = node_input(g.nodes[0..], node, &workspace); - const alpha = g.leaky_relu_alpha[node.aux]; - for (0..node.rows * node.cols) |j| out[j] = if (s[j] >= 0.0) s[j] else alpha * s[j]; - }, - // .layernorm — last-axis normalization (the canonical torch - // nn.LayerNorm / ONNX LayerNormalization form): per row - // (a - mean) * rstd * scale + bias with the biased variance. The - // scale/bias operands are ONNX Scale/B, one entry per normalized - // feature; eps is baked into g.layernorm_eps (aux = table index). - // A 1-D node is a single row (rows=n, cols=1, vec=true) and must be - // normalized as layernorm_rows(1, n), never as n rows of length 1. - // The comptime gate rejects a scale/bias that is not the (cols,) - // feature vector rather than reading past the operand's slot. - .layernorm => { - const a = node_input(g.nodes[0..], node, &workspace); - const scale = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const bias = node_input_at(g.nodes[0..], node.inputs[2], &workspace); - const scale_n = g.nodes[node.inputs[1]]; - const bias_n = g.nodes[node.inputs[2]]; - comptime { - const n = if (node.vec) node.rows else node.cols; - if (scale_n.rows * scale_n.cols != n) { - @compileError("layernorm: scale must have one entry per normalized feature (cols)"); - } - if (bias_n.rows * bias_n.cols != n) { - @compileError("layernorm: bias must have one entry per normalized feature (cols)"); - } - } - const r = la.layernorm_rows( - if (node.vec) 1 else node.rows, - if (node.vec) node.rows else node.cols, - a, - scale, - bias, - g.layernorm_eps[node.aux], - ); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .exp => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.elementwise_exponential(node.rows * node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - // .sqrt / .log — elementwise maps of the std builtins, so they need - // no linalg kernel (like .pow's std.math.pow). Negative sqrt / log - // operands are NaN on both engines (numpy and Zig agree). - .sqrt => { - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| out[j] = @sqrt(s[j]); - }, - .log => { - const s = node_input(g.nodes[0..], node, &workspace); - for (0..node.rows * node.cols) |j| out[j] = @log(s[j]); - }, - .sin => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.sin_vec(node.rows * node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .cos => { - const s = node_input(g.nodes[0..], node, &workspace); - const r = la.cos_vec(node.rows * node.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .argmax => { - const s = node_input(g.nodes[0..], node, &workspace); - const n_in = g.nodes[node.inputs[0]].rows * g.nodes[node.inputs[0]].cols; - const idx = la.argmax(n_in, s); - out[0] = @floatFromInt(idx); - }, - .min => { - // Minimum reduction; aux selects numpy's axis (0 = None / full, - // 1 = axis 0 down columns, 2 = axis 1 across rows). The output - // shape was fixed at trace time, so rows*cols is the exact - // element count the chosen reduction produces. - const s = node_input(g.nodes[0..], node, &workspace); - const src = g.nodes[node.inputs[0]]; - if (node.aux == 0) { - const r = la.min_all(src.rows * src.cols, s); - out[0] = r[0]; - } else if (node.aux == 1) { - const r = la.min_axis0(src.rows, src.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - } else { - const r = la.min_axis1(src.rows, src.cols, s); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - } - }, - .one_hot => { - const s = node_input(g.nodes[0..], node, &workspace); - const idx: usize = @intFromFloat(s[0]); - const r = la.onehot(node.rows, idx); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - }, - .slice => { - const s = node_input(g.nodes[0..], node, &workspace); - const src = g.nodes[node.inputs[0]]; - if (src.vec) { - // 1-D source: aux is the flat element offset. - for (0..node.rows * node.cols) |j| out[j] = s[node.aux + j]; - } else { - // 2-D source: the interpreter slices ROWS (x[start:stop] - // along axis 0), so out[i][j] = src[start + i][j]. - for (0..node.rows) |oi| { - for (0..node.cols) |oj| out[oi * node.cols + oj] = s[(node.aux + oi) * src.cols + oj]; - } - } - }, - // stack([a, b, ...]) along a new leading axis (numpy axis=0). Each - // input contributes its flat length to consecutive output rows; all - // inputs share the same shape (enforced at trace time), so the - // output flat length is n_inputs * in_len == node.rows * node.cols. - .stack => { - for (node.inputs, 0..) |inp_idx, row| { - const src = node_input_at(g.nodes[0..], inp_idx, &workspace); - const in_len = g.nodes[inp_idx].rows * g.nodes[inp_idx].cols; - for (0..in_len) |j| out[row * in_len + j] = src[j]; - } - }, - // .gemm — fused dense layer: out = alpha*(A@B') + beta*C in one - // pass (linalg.gemm). Covers the ONNX importer's Gemm: the - // contraction, the alpha/beta scales, the optional transB (torch - // nn.Linear weight layout, read by striding rather than - // materializing a transpose), and the bias add are a single kernel. - // alpha/beta are baked into g.gemm_alpha/gemm_beta; aux packs the - // table index in the upper bits and the transB flag in bit 0. A - // 1-D activation (vec) is treated as a single row (m = 1). - .gemm => { - const a = node_input(g.nodes[0..], node, &workspace); - const c = node_input_at(g.nodes[0..], node.inputs[2], &workspace); - const a_n = g.nodes[node.inputs[0]]; - const b_n = g.nodes[node.inputs[1]]; - const c_n = g.nodes[node.inputs[2]]; - const alpha = g.gemm_alpha[node.aux / 2]; - const beta = g.gemm_beta[node.aux / 2]; - const rb = node.aux % 2 == 1; - const clen = c_n.rows * c_n.cols; - const m = if (node.vec) 1 else node.rows; - const k = if (a_n.vec) a_n.rows else a_n.cols; - const n = if (node.vec) node.rows else node.cols; - // The weight operand's dtype is a comptime property of its - // source node: an f32-exact weight baked into const_blob_f32 - // selects the mixed-dtype kernel, which widens each weight to - // f64 inside the vector lane. The accumulation is still f64, so - // the result is unchanged while the weight bytes are halved. - if (b_n.op == .cst_f32) { - const b32 = g.const_blob_f32[b_n.aux..][0 .. b_n.rows * b_n.cols]; - const r = la.gemm(m, k, n, alpha, beta, rb, f32, a, b32, c, clen); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - } else { - const b = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const r = la.gemm(m, k, n, alpha, beta, rb, f64, a, b, c, clen); - for (0..node.rows * node.cols) |j| out[j] = r[j]; - } - }, - // .lstm / .gru / .rnn — one fused recurrent step each - // (linalg.lstm_cell / gru_cell / rnn_cell). Operands are - // [x, W, R, B, h_prev(, c_prev)] in ONNX layout: W is - // (ngates*H, I), R is (ngates*H, H), B is the stacked Wb ‖ Rb. - // H and I are derived at COMPTIME from the weight and activation - // node shapes, so the kernels carry no runtime shape metadata; a - // weight that is not an exact gate stack, or an output slot that - // is not the size the cell produces, is rejected at compile time - // rather than read out of bounds. gru's linear_before_reset rides - // in aux bit 0. - .lstm => { - const x = node_input(g.nodes[0..], node, &workspace); - const b = node_input_at(g.nodes[0..], node.inputs[3], &workspace); - const h_prev = node_input_at(g.nodes[0..], node.inputs[4], &workspace); - const c_prev = node_input_at(g.nodes[0..], node.inputs[5], &workspace); - const w_n = g.nodes[node.inputs[1]]; - const r_n = g.nodes[node.inputs[2]]; - const x_n = g.nodes[node.inputs[0]]; - const H = comptime w_n.rows / 4; - const I = comptime x_n.rows * x_n.cols; - comptime { - if (w_n.rows % 4 != 0) @compileError("lstm: W rows must be 4*H (i,o,f,c gate stack)"); - if (w_n.cols != I) @compileError("lstm: W (4H, I) input width must match the activation width"); - if (node.rows * node.cols != 2 * H) @compileError("lstm: output slot must be 2*H ([h_next ‖ c_next])"); - } - // W and R always share a blob (the lowerer keeps them coherent), - // so one comptime dtype choice driven by W's op serves both. - if (w_n.op == .cst_f32) { - const w32 = g.const_blob_f32[w_n.aux..][0 .. w_n.rows * w_n.cols]; - const r32 = g.const_blob_f32[r_n.aux..][0 .. r_n.rows * r_n.cols]; - const res = la.lstm_cell(H, I, f32, x, w32, r32, b, h_prev, c_prev); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } else { - const w = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const r = node_input_at(g.nodes[0..], node.inputs[2], &workspace); - const res = la.lstm_cell(H, I, f64, x, w, r, b, h_prev, c_prev); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } - }, - .gru => { - const x = node_input(g.nodes[0..], node, &workspace); - const b = node_input_at(g.nodes[0..], node.inputs[3], &workspace); - const h_prev = node_input_at(g.nodes[0..], node.inputs[4], &workspace); - const w_n = g.nodes[node.inputs[1]]; - const r_n = g.nodes[node.inputs[2]]; - const x_n = g.nodes[node.inputs[0]]; - const H = comptime w_n.rows / 3; - const I = comptime x_n.rows * x_n.cols; - const lbr = comptime (node.aux % 2 == 1); - comptime { - if (w_n.rows % 3 != 0) @compileError("gru: W rows must be 3*H (z,r,h gate stack)"); - if (w_n.cols != I) @compileError("gru: W (3H, I) input width must match the activation width"); - if (node.rows * node.cols != H) @compileError("gru: output slot must be H"); - } - if (w_n.op == .cst_f32) { - const w32 = g.const_blob_f32[w_n.aux..][0 .. w_n.rows * w_n.cols]; - const r32 = g.const_blob_f32[r_n.aux..][0 .. r_n.rows * r_n.cols]; - const res = la.gru_cell(H, I, lbr, f32, x, w32, r32, b, h_prev); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } else { - const w = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const r = node_input_at(g.nodes[0..], node.inputs[2], &workspace); - const res = la.gru_cell(H, I, lbr, f64, x, w, r, b, h_prev); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } - }, - .rnn => { - const x = node_input(g.nodes[0..], node, &workspace); - const b = node_input_at(g.nodes[0..], node.inputs[3], &workspace); - const h_prev = node_input_at(g.nodes[0..], node.inputs[4], &workspace); - const w_n = g.nodes[node.inputs[1]]; - const r_n = g.nodes[node.inputs[2]]; - const x_n = g.nodes[node.inputs[0]]; - const H = comptime w_n.rows; - const I = comptime x_n.rows * x_n.cols; - comptime { - if (w_n.cols != I) @compileError("rnn: W (H, I) input width must match the activation width"); - if (node.rows * node.cols != H) @compileError("rnn: output slot must be H"); - } - if (w_n.op == .cst_f32) { - const w32 = g.const_blob_f32[w_n.aux..][0 .. w_n.rows * w_n.cols]; - const r32 = g.const_blob_f32[r_n.aux..][0 .. r_n.rows * r_n.cols]; - const res = la.rnn_cell(H, I, f32, x, w32, r32, b, h_prev); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } else { - const w = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const r = node_input_at(g.nodes[0..], node.inputs[2], &workspace); - const res = la.rnn_cell(H, I, f64, x, w, r, b, h_prev); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } - }, - // .concat — join operands along `node.aux` (0 = leading axis, - // 1 = trailing axis of a 2-D tensor) by copying into the output - // slot. Axis 0 is a flat append because row blocks are contiguous - // in row-major order; only axis 1 needs per-row offsets. Pure - // buffer movement, so — like `.stack` — it needs no linalg kernel. - .concat => { - var off: usize = 0; // running flat offset (axis 0) - comptime var col_off: usize = 0; // per-row column offset (axis 1) - inline for (node.inputs) |inp| { - const src = node_input_at(g.nodes[0..], inp, &workspace); - const src_n = g.nodes[inp]; - if (node.aux == 0) { - const n = src_n.rows * src_n.cols; - for (0..n) |j| out[off + j] = src[j]; - off += n; - } else { - const cols = if (src_n.vec) 1 else src_n.cols; - const rows = if (node.vec) 1 else node.rows; - for (0..rows) |r| { - for (0..cols) |j| out[r * node.cols + col_off + j] = src[r * cols + j]; + inline for (g.nodes, 0..) |node, i| { + // Const nodes own no workspace slot: their data lives in the baked blob + // and consumers read it in place (node_input_at / the contraction arms). + // Skipping them keeps buf_len to the real working set and means no slice + // is ever taken at a const node's (unused) offset. + if (node.op == .cst or node.op == .cst_f32) continue; + + const out = workspace[g.offsets[i]..][0 .. node.rows * node.cols]; + + switch (node.op) { + // Unreachable (consts are skipped above); kept for exhaustiveness. + .cst, .cst_f32 => {}, + .inp => { + for (0..node.rows * node.cols) |j| out[j] = inputs[node.aux + j]; + }, + .out => { + const src = node_input(g.nodes[0..], node, &workspace); + if (node.aux < g.n_outputs) { + for (0..node.rows * node.cols) |j| outputs[g.output_offsets[node.aux] + j] = src[j]; + } else { + for (0..node.rows * node.cols) |j| state_out[g.state_offsets[node.aux - g.n_outputs] + j] = src[j]; } - col_off += cols; - } - } - }, - // .gather — index-select along `node.aux` (ONNX Gather). The index - // operand is a flat f64 buffer the kernel converts per element; - // negatives count from the end. Which kernel depends on the source - // rank: a `vec` source is a 1-D select, otherwise whole rows - // (axis 0) or whole columns (axis 1) move. - .gather => { - const x = node_input(g.nodes[0..], node, &workspace); - const idx = node_input_at(g.nodes[0..], node.inputs[1], &workspace); - const x_n = g.nodes[node.inputs[0]]; - const idx_n = g.nodes[node.inputs[1]]; - const n_idx = comptime idx_n.rows * idx_n.cols; - comptime { - if (node.aux == 1 and x_n.vec) @compileError("gather axis=1 needs a 2-D operand"); - const want = if (node.aux == 1) - x_n.rows * n_idx - else if (x_n.vec) - n_idx - else - n_idx * x_n.cols; - if (node.rows * node.cols != want) @compileError("gather: output slot size mismatch"); - } - if (node.aux == 0 and x_n.vec) { - const res = la.gather_index(n_idx, x_n.rows, x, idx); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } else if (node.aux == 0) { - const res = la.gather_rows(n_idx, x_n.cols, x_n.rows, x, idx); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } else { - const res = la.gather_cols(x_n.rows, n_idx, x_n.cols, x, idx); - for (0..node.rows * node.cols) |j| out[j] = res[j]; - } - }, - // .solve_qp — the convergence-iterative MPC op. The problem data - // (P, A, l, u) and the pre-factorized KKT matrix are baked into the - // statically-allocated `solver` global by the codegen C - // (runtime/codegen/emosqp/). Only the linear cost q changes per - // tick: it is read from the node's input slot and written in via - // osqp_update_data_vec, then the full solution lands in this - // node's output slot (u[:m] is sliced out by a downstream op). - // The node's output size must match the baked problem's n_vars — - // enforced here at compile time, so a graph lowered against the - // wrong bake refuses to build instead of silently linking a - // shape-mismatched solver. - .solve_qp => { - comptime { - if (node.rows * node.cols != sm.n_vars) { - @compileError("graph solve_qp node output size (" ++ - std.fmt.comptimePrint("{d}", .{node.rows * node.cols}) ++ - ") does not match baked solver n_vars (" ++ - std.fmt.comptimePrint("{d}", .{sm.n_vars}) ++ - ") — rebuild with the matching -Dsolver_dir"); - } + }, + .matmul => { + const a = node_input(g.nodes[0..], node, &workspace); + const b = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const left = g.nodes[node.inputs[0]]; + const right = g.nodes[node.inputs[1]]; + if (left.vec) { + // vecmat: (k,) @ (k, n) -> (n,) — a genuinely 1-D left operand + const r = la.vecmat(left.rows, node.rows, a, b); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + } else if (right.vec) { + // matvec: (m, k) @ (k,) -> (m,) + const r = la.matvec(node.rows, right.rows, f64, a, b); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + } else { + // matmul: (m, k) @ (k, n) -> (m, n); also covers (m,1)@(1,n) (k=1) + const r = la.matmul(node.rows, left.cols, node.cols, a, b); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + } + }, + .add => ew2(g.nodes[0..], node, i, &workspace, .add), + .sub => ew2(g.nodes[0..], node, i, &workspace, .sub), + .mul => ew2(g.nodes[0..], node, i, &workspace, .mul), + .div => ew2(g.nodes[0..], node, i, &workspace, .div), + .ne => ew2(g.nodes[0..], node, i, &workspace, .ne), + .lt => ew2(g.nodes[0..], node, i, &workspace, .lt), + .pow => ew2(g.nodes[0..], node, i, &workspace, .pow), + .mod => ew2(g.nodes[0..], node, i, &workspace, .mod), + .neg => { + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| out[j] = -s[j]; + }, + .abs => { + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| out[j] = @abs(s[j]); + }, + .sign => { + // Matches np.sign: -1 / 0 / +1 (0 maps to 0, not +1). + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| { + out[j] = if (s[j] > 0.0) 1.0 else if (s[j] < 0.0) -1.0 else 0.0; + } + }, + .transpose => { + const s = node_input(g.nodes[0..], node, &workspace); + // True 2-D transpose: out (node.rows, node.cols) = src.T, so + // out[i][j] = src[j][i] — flat out[i*node.cols + j] = + // s[j*src.cols + i]. (The old form baked in the square case's + // stride symmetry and silently scrambled non-square inputs.) + for (0..node.rows) |oi| { + for (0..node.cols) |oj| out[oi * node.cols + oj] = s[oj * g.nodes[node.inputs[0]].cols + oi]; + } + }, + .inv => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.inv(node.rows, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .reshape => { + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| out[j] = s[j]; + }, + .clip => { + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| { + out[j] = std.math.clamp(s[j], g.clip_lo[node.aux + j], g.clip_hi[node.aux + j]); + } + }, + .where_op => { + const cond = node_input(g.nodes[0..], node, &workspace); + const a = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const b = node_input_at(g.nodes[0..], node.inputs[2], &workspace); + const cond_n = g.nodes[node.inputs[0]]; + const a_n = g.nodes[node.inputs[1]]; + const b_n = g.nodes[node.inputs[2]]; + for (0..node.rows) |oi| { + for (0..node.cols) |oj| { + const f = oi * node.cols + oj; + const c = cond[if (cond_n.rows * cond_n.cols == 1) 0 else f]; + const av = a[bcast_flat(a_n, a_n.vec, node.rows, node.cols, oi, oj)]; + const bv = b[bcast_flat(b_n, b_n.vec, node.rows, node.cols, oi, oj)]; + out[f] = if (c != 0.0) av else bv; + } + } + }, + .any => { + const s = node_input(g.nodes[0..], node, &workspace); + var found = false; + for (0..g.nodes[node.inputs[0]].rows * g.nodes[node.inputs[0]].cols) |j| { + if (s[j] != 0.0) found = true; + } + out[0] = if (found) 1.0 else 0.0; + }, + // deterministic-policy ops (issue #13): elementwise maps, a + // reduction (argmax), an expansion (one_hot), and shape glue + // (copy / slice). None allocate — all iterate comptime-known + // flat buffers. tanh/relu/exp preserve shape; argmax collapses + // to a scalar (stored as f64 in the buffer); one_hot expands a + // scalar index to a depth-row; copy/slice are flat copies with + // slice's `aux` holding the input offset. + .copy => { + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| out[j] = s[j]; + }, + .tanh => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.tanh(node.rows * node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .relu => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.relu(node.rows * node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .sigmoid => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.sigmoid(node.rows * node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .softmax => { + // Last-axis softmax (numpy axis=-1). A 1-D node is stored as + // rows=n, cols=1, vec=true — treat it as a single row of + // length n (rows*cols), never as n rows of length 1. + const s = node_input(g.nodes[0..], node, &workspace); + const r = if (node.vec) + la.softmax_rows(1, node.rows, s) + else + la.softmax_rows(node.rows, node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .gelu => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.gelu(node.rows * node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .elu => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.elu(node.rows * node.cols, g.elu_alpha[node.aux], s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + // .leaky_relu — x if x >= 0 else alpha*x. No linalg kernel (no exp): + // alpha is baked into g.leaky_relu_alpha (aux = table index), like + // elu's slope. At x == 0 both branches give 0. + .leaky_relu => { + const s = node_input(g.nodes[0..], node, &workspace); + const alpha = g.leaky_relu_alpha[node.aux]; + for (0..node.rows * node.cols) |j| out[j] = if (s[j] >= 0.0) s[j] else alpha * s[j]; + }, + // .layernorm — last-axis normalization (the canonical torch + // nn.LayerNorm / ONNX LayerNormalization form): per row + // (a - mean) * rstd * scale + bias with the biased variance. The + // scale/bias operands are ONNX Scale/B, one entry per normalized + // feature; eps is baked into g.layernorm_eps (aux = table index). + // A 1-D node is a single row (rows=n, cols=1, vec=true) and must be + // normalized as layernorm_rows(1, n), never as n rows of length 1. + // The comptime gate rejects a scale/bias that is not the (cols,) + // feature vector rather than reading past the operand's slot. + .layernorm => { + const a = node_input(g.nodes[0..], node, &workspace); + const scale = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const bias = node_input_at(g.nodes[0..], node.inputs[2], &workspace); + const scale_n = g.nodes[node.inputs[1]]; + const bias_n = g.nodes[node.inputs[2]]; + comptime { + const n = if (node.vec) node.rows else node.cols; + if (scale_n.rows * scale_n.cols != n) { + @compileError("layernorm: scale must have one entry per normalized feature (cols)"); + } + if (bias_n.rows * bias_n.cols != n) { + @compileError("layernorm: bias must have one entry per normalized feature (cols)"); + } + } + const r = la.layernorm_rows( + if (node.vec) 1 else node.rows, + if (node.vec) node.rows else node.cols, + a, + scale, + bias, + g.layernorm_eps[node.aux], + ); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .exp => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.elementwise_exponential(node.rows * node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + // .sqrt / .log — elementwise maps of the std builtins, so they need + // no linalg kernel (like .pow's std.math.pow). Negative sqrt / log + // operands are NaN on both engines (numpy and Zig agree). + .sqrt => { + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| out[j] = @sqrt(s[j]); + }, + .log => { + const s = node_input(g.nodes[0..], node, &workspace); + for (0..node.rows * node.cols) |j| out[j] = @log(s[j]); + }, + .sin => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.sin_vec(node.rows * node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .cos => { + const s = node_input(g.nodes[0..], node, &workspace); + const r = la.cos_vec(node.rows * node.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .argmax => { + const s = node_input(g.nodes[0..], node, &workspace); + const n_in = g.nodes[node.inputs[0]].rows * g.nodes[node.inputs[0]].cols; + const idx = la.argmax(n_in, s); + out[0] = @floatFromInt(idx); + }, + .min => { + // Minimum reduction; aux selects numpy's axis (0 = None / full, + // 1 = axis 0 down columns, 2 = axis 1 across rows). The output + // shape was fixed at trace time, so rows*cols is the exact + // element count the chosen reduction produces. + const s = node_input(g.nodes[0..], node, &workspace); + const src = g.nodes[node.inputs[0]]; + if (node.aux == 0) { + const r = la.min_all(src.rows * src.cols, s); + out[0] = r[0]; + } else if (node.aux == 1) { + const r = la.min_axis0(src.rows, src.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + } else { + const r = la.min_axis1(src.rows, src.cols, s); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + } + }, + .one_hot => { + const s = node_input(g.nodes[0..], node, &workspace); + const idx: usize = @intFromFloat(s[0]); + const r = la.onehot(node.rows, idx); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + }, + .slice => { + const s = node_input(g.nodes[0..], node, &workspace); + const src = g.nodes[node.inputs[0]]; + if (src.vec) { + // 1-D source: aux is the flat element offset. + for (0..node.rows * node.cols) |j| out[j] = s[node.aux + j]; + } else { + // 2-D source: the interpreter slices ROWS (x[start:stop] + // along axis 0), so out[i][j] = src[start + i][j]. + for (0..node.rows) |oi| { + for (0..node.cols) |oj| out[oi * node.cols + oj] = s[(node.aux + oi) * src.cols + oj]; + } + } + }, + // stack([a, b, ...]) along a new leading axis (numpy axis=0). Each + // input contributes its flat length to consecutive output rows; all + // inputs share the same shape (enforced at trace time), so the + // output flat length is n_inputs * in_len == node.rows * node.cols. + .stack => { + for (node.inputs, 0..) |inp_idx, row| { + const src = node_input_at(g.nodes[0..], inp_idx, &workspace); + const in_len = g.nodes[inp_idx].rows * g.nodes[inp_idx].cols; + for (0..in_len) |j| out[row * in_len + j] = src[j]; + } + }, + // .gemm — fused dense layer: out = alpha*(A@B') + beta*C in one + // pass (linalg.gemm). Covers the ONNX importer's Gemm: the + // contraction, the alpha/beta scales, the optional transB (torch + // nn.Linear weight layout, read by striding rather than + // materializing a transpose), and the bias add are a single kernel. + // alpha/beta are baked into g.gemm_alpha/gemm_beta; aux packs the + // table index in the upper bits and the transB flag in bit 0. A + // 1-D activation (vec) is treated as a single row (m = 1). + .gemm => { + const a = node_input(g.nodes[0..], node, &workspace); + const c = node_input_at(g.nodes[0..], node.inputs[2], &workspace); + const a_n = g.nodes[node.inputs[0]]; + const b_n = g.nodes[node.inputs[1]]; + const c_n = g.nodes[node.inputs[2]]; + const alpha = g.gemm_alpha[node.aux / 2]; + const beta = g.gemm_beta[node.aux / 2]; + const rb = node.aux % 2 == 1; + const clen = c_n.rows * c_n.cols; + const m = if (node.vec) 1 else node.rows; + const k = if (a_n.vec) a_n.rows else a_n.cols; + const n = if (node.vec) node.rows else node.cols; + // The weight operand's dtype is a comptime property of its + // source node: an f32-exact weight baked into const_blob_f32 + // selects the mixed-dtype kernel, which widens each weight to + // f64 inside the vector lane. The accumulation is still f64, so + // the result is unchanged while the weight bytes are halved. + if (b_n.op == .cst_f32) { + const b32 = g.const_blob_f32[b_n.aux..][0 .. b_n.rows * b_n.cols]; + const r = la.gemm(m, k, n, alpha, beta, rb, f32, a, b32, c, clen); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + } else { + const b = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const r = la.gemm(m, k, n, alpha, beta, rb, f64, a, b, c, clen); + for (0..node.rows * node.cols) |j| out[j] = r[j]; + } + }, + // .lstm / .gru / .rnn — one fused recurrent step each + // (linalg.lstm_cell / gru_cell / rnn_cell). Operands are + // [x, W, R, B, h_prev(, c_prev)] in ONNX layout: W is + // (ngates*H, I), R is (ngates*H, H), B is the stacked Wb ‖ Rb. + // H and I are derived at COMPTIME from the weight and activation + // node shapes, so the kernels carry no runtime shape metadata; a + // weight that is not an exact gate stack, or an output slot that + // is not the size the cell produces, is rejected at compile time + // rather than read out of bounds. gru's linear_before_reset rides + // in aux bit 0. + .lstm => { + const x = node_input(g.nodes[0..], node, &workspace); + const b = node_input_at(g.nodes[0..], node.inputs[3], &workspace); + const h_prev = node_input_at(g.nodes[0..], node.inputs[4], &workspace); + const c_prev = node_input_at(g.nodes[0..], node.inputs[5], &workspace); + const w_n = g.nodes[node.inputs[1]]; + const r_n = g.nodes[node.inputs[2]]; + const x_n = g.nodes[node.inputs[0]]; + const H = comptime w_n.rows / 4; + const I = comptime x_n.rows * x_n.cols; + comptime { + if (w_n.rows % 4 != 0) @compileError("lstm: W rows must be 4*H (i,o,f,c gate stack)"); + if (w_n.cols != I) @compileError("lstm: W (4H, I) input width must match the activation width"); + if (node.rows * node.cols != 2 * H) @compileError("lstm: output slot must be 2*H ([h_next ‖ c_next])"); + } + // W and R always share a blob (the lowerer keeps them coherent), + // so one comptime dtype choice driven by W's op serves both. + if (w_n.op == .cst_f32) { + const w32 = g.const_blob_f32[w_n.aux..][0 .. w_n.rows * w_n.cols]; + const r32 = g.const_blob_f32[r_n.aux..][0 .. r_n.rows * r_n.cols]; + const res = la.lstm_cell(H, I, f32, x, w32, r32, b, h_prev, c_prev); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } else { + const w = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const r = node_input_at(g.nodes[0..], node.inputs[2], &workspace); + const res = la.lstm_cell(H, I, f64, x, w, r, b, h_prev, c_prev); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } + }, + .gru => { + const x = node_input(g.nodes[0..], node, &workspace); + const b = node_input_at(g.nodes[0..], node.inputs[3], &workspace); + const h_prev = node_input_at(g.nodes[0..], node.inputs[4], &workspace); + const w_n = g.nodes[node.inputs[1]]; + const r_n = g.nodes[node.inputs[2]]; + const x_n = g.nodes[node.inputs[0]]; + const H = comptime w_n.rows / 3; + const I = comptime x_n.rows * x_n.cols; + const lbr = comptime (node.aux % 2 == 1); + comptime { + if (w_n.rows % 3 != 0) @compileError("gru: W rows must be 3*H (z,r,h gate stack)"); + if (w_n.cols != I) @compileError("gru: W (3H, I) input width must match the activation width"); + if (node.rows * node.cols != H) @compileError("gru: output slot must be H"); + } + if (w_n.op == .cst_f32) { + const w32 = g.const_blob_f32[w_n.aux..][0 .. w_n.rows * w_n.cols]; + const r32 = g.const_blob_f32[r_n.aux..][0 .. r_n.rows * r_n.cols]; + const res = la.gru_cell(H, I, lbr, f32, x, w32, r32, b, h_prev); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } else { + const w = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const r = node_input_at(g.nodes[0..], node.inputs[2], &workspace); + const res = la.gru_cell(H, I, lbr, f64, x, w, r, b, h_prev); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } + }, + .rnn => { + const x = node_input(g.nodes[0..], node, &workspace); + const b = node_input_at(g.nodes[0..], node.inputs[3], &workspace); + const h_prev = node_input_at(g.nodes[0..], node.inputs[4], &workspace); + const w_n = g.nodes[node.inputs[1]]; + const r_n = g.nodes[node.inputs[2]]; + const x_n = g.nodes[node.inputs[0]]; + const H = comptime w_n.rows; + const I = comptime x_n.rows * x_n.cols; + comptime { + if (w_n.cols != I) @compileError("rnn: W (H, I) input width must match the activation width"); + if (node.rows * node.cols != H) @compileError("rnn: output slot must be H"); + } + if (w_n.op == .cst_f32) { + const w32 = g.const_blob_f32[w_n.aux..][0 .. w_n.rows * w_n.cols]; + const r32 = g.const_blob_f32[r_n.aux..][0 .. r_n.rows * r_n.cols]; + const res = la.rnn_cell(H, I, f32, x, w32, r32, b, h_prev); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } else { + const w = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const r = node_input_at(g.nodes[0..], node.inputs[2], &workspace); + const res = la.rnn_cell(H, I, f64, x, w, r, b, h_prev); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } + }, + // .concat — join operands along `node.aux` (0 = leading axis, + // 1 = trailing axis of a 2-D tensor) by copying into the output + // slot. Axis 0 is a flat append because row blocks are contiguous + // in row-major order; only axis 1 needs per-row offsets. Pure + // buffer movement, so — like `.stack` — it needs no linalg kernel. + .concat => { + var off: usize = 0; // running flat offset (axis 0) + comptime var col_off: usize = 0; // per-row column offset (axis 1) + inline for (node.inputs) |inp| { + const src = node_input_at(g.nodes[0..], inp, &workspace); + const src_n = g.nodes[inp]; + if (node.aux == 0) { + const n = src_n.rows * src_n.cols; + for (0..n) |j| out[off + j] = src[j]; + off += n; + } else { + const cols = if (src_n.vec) 1 else src_n.cols; + const rows = if (node.vec) 1 else node.rows; + for (0..rows) |r| { + for (0..cols) |j| out[r * node.cols + col_off + j] = src[r * cols + j]; + } + col_off += cols; + } + } + }, + // .gather — index-select along `node.aux` (ONNX Gather). The index + // operand is a flat f64 buffer the kernel converts per element; + // negatives count from the end. Which kernel depends on the source + // rank: a `vec` source is a 1-D select, otherwise whole rows + // (axis 0) or whole columns (axis 1) move. + .gather => { + const x = node_input(g.nodes[0..], node, &workspace); + const idx = node_input_at(g.nodes[0..], node.inputs[1], &workspace); + const x_n = g.nodes[node.inputs[0]]; + const idx_n = g.nodes[node.inputs[1]]; + const n_idx = comptime idx_n.rows * idx_n.cols; + comptime { + if (node.aux == 1 and x_n.vec) @compileError("gather axis=1 needs a 2-D operand"); + const want = if (node.aux == 1) + x_n.rows * n_idx + else if (x_n.vec) + n_idx + else + n_idx * x_n.cols; + if (node.rows * node.cols != want) @compileError("gather: output slot size mismatch"); + } + if (node.aux == 0 and x_n.vec) { + const res = la.gather_index(n_idx, x_n.rows, x, idx); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } else if (node.aux == 0) { + const res = la.gather_rows(n_idx, x_n.cols, x_n.rows, x, idx); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } else { + const res = la.gather_cols(x_n.rows, n_idx, x_n.cols, x, idx); + for (0..node.rows * node.cols) |j| out[j] = res[j]; + } + }, + // .solve_qp — the convergence-iterative MPC op. The problem data + // (P, A, l, u) and the pre-factorized KKT matrix are baked into the + // statically-allocated `solver` global by the codegen C + // (runtime/codegen/emosqp/). Only the linear cost q changes per + // tick: it is read from the node's input slot and written in via + // osqp_update_data_vec, then the full solution lands in this + // node's output slot (u[:m] is sliced out by a downstream op). + // The node's output size must match the baked problem's n_vars — + // enforced here at compile time, so a graph lowered against the + // wrong bake refuses to build instead of silently linking a + // shape-mismatched solver. + .solve_qp => { + comptime { + if (node.rows * node.cols != sm.n_vars) { + @compileError("graph solve_qp node output size (" ++ + std.fmt.comptimePrint("{d}", .{node.rows * node.cols}) ++ + ") does not match baked solver n_vars (" ++ + std.fmt.comptimePrint("{d}", .{sm.n_vars}) ++ + ") — rebuild with the matching -Dsolver_dir"); + } + } + const q_vec = node_input(g.nodes[0..], node, &workspace); + qp.solve_qp(q_vec, out); + }, } - const q_vec = node_input(g.nodes[0..], node, &workspace); - qp.solve_qp(q_vec, out); - }, + } } - } -} -// --- helpers --------------------------------------------------------------- + // --- helpers --------------------------------------------------------------- -const BinOp = enum { add, sub, mul, div, ne, lt, pow, mod }; + const BinOp = enum { add, sub, mul, div, ne, lt, pow, mod }; -/// Flat index of operand element (i, j) under numpy broadcasting. -/// -/// The tracer only captures numpy-valid broadcasts, so at comptime the -/// operand shape must fall into one of: scalar, same shape, (1, m) row -/// broadcast, (n, 1) column broadcast, or a genuinely 1-D (`vec`) operand -/// right-aligned to the output's columns. The old code only handled -/// same-shape and size-1 — a (1, m)-against-(n, m) add or a scalar `where` -/// branch read out of bounds (panic in debug, garbage in release). -inline fn bcast_flat(op: g.Node, op_vec: bool, out_r: usize, out_c: usize, i: usize, j: usize) usize { - if (op.rows * op.cols == 1) return 0; // scalar broadcast - if (op_vec and op.rows == out_c) return j; // (m,) right-aligns to the last axis - if (op.rows == out_r and op.cols == out_c) return i * out_c + j; // same shape - if (op.rows == 1 and op.cols == out_c) return j; // (1, m) row broadcast - if (op.cols == 1 and op.rows == out_r) return i; // (n, 1) col broadcast - return i * out_c + j; // unreachable for numpy-valid traces -} + /// Flat index of operand element (i, j) under numpy broadcasting. + /// + /// The tracer only captures numpy-valid broadcasts, so at comptime the + /// operand shape must fall into one of: scalar, same shape, (1, m) row + /// broadcast, (n, 1) column broadcast, or a genuinely 1-D (`vec`) operand + /// right-aligned to the output's columns. The old code only handled + /// same-shape and size-1 — a (1, m)-against-(n, m) add or a scalar `where` + /// branch read out of bounds (panic in debug, garbage in release). + inline fn bcast_flat(op: g.Node, op_vec: bool, out_r: usize, out_c: usize, i: usize, j: usize) usize { + if (op.rows * op.cols == 1) return 0; // scalar broadcast + if (op_vec and op.rows == out_c) return j; // (m,) right-aligns to the last axis + if (op.rows == out_r and op.cols == out_c) return i * out_c + j; // same shape + if (op.rows == 1 and op.cols == out_c) return j; // (1, m) row broadcast + if (op.cols == 1 and op.rows == out_r) return i; // (n, 1) col broadcast + return i * out_c + j; // unreachable for numpy-valid traces + } -/// Elementwise binary op with numpy broadcasting. -/// -/// Each operand is indexed through `bcast_flat`: same shape, scalar, -/// (1, m) row, (n, 1) column, or a 1-D (`vec`) operand right-aligned to the -/// output's columns. `inline` so the comptime-known node shapes and the `op` -/// tag constant-fold into the runtime element loop (the bounds stay comptime -/// constants, but the loop itself is not unrolled). -/// -/// Args: -/// nodes: The full generated node table (for shape lookup). -/// node: The current add/sub/mul/div/ne node. -/// self_idx: The node's index in `nodes` (its buffer offset). -/// buf: The shared step buffer (written at the node's offset). -/// op: Which binary op to apply (add, sub, mul, div, ne, lt, pow). -inline fn ew2(nodes: []const g.Node, node: g.Node, self_idx: usize, buf: *[g.buf_len]f64, op: BinOp) void { - const a = node_input_at(nodes, node.inputs[0], buf); - const b = node_input_at(nodes, node.inputs[1], buf); - const a_n = nodes[node.inputs[0]]; - const b_n = nodes[node.inputs[1]]; - var out = buf.*[g.offsets[self_idx]..][0 .. node.rows * node.cols]; - for (0..node.rows) |i| { - for (0..node.cols) |j| { - const av = a[bcast_flat(a_n, a_n.vec, node.rows, node.cols, i, j)]; - const bv = b[bcast_flat(b_n, b_n.vec, node.rows, node.cols, i, j)]; - out[i * node.cols + j] = switch (op) { - .add => av + bv, - .sub => av - bv, - .mul => av * bv, - .div => av / bv, - // Inequality as a 1.0/0.0 flag — the graph's boolean repr, - // consumed by where_op downstream (e.g. PID anti-windup). - .ne => if (av != bv) 1.0 else 0.0, - // Ordered comparison as a 1.0/0.0 flag — `ne`'s sibling, the - // predicate behind threshold guards (e.g. SMC's near-zero - // |c^T g| controllability check). - .lt => if (av < bv) 1.0 else 0.0, - // numpy's power semantics (np.power); SMC raises the abs'd - // sliding variable to a fractional alpha, so no negative base. - .pow => std.math.pow(f64, av, bv), - // ONNX Mod: aux bit 0 selects C fmod (sign of the dividend, - // @rem) over Python % (sign of the divisor, @mod) — a comptime - // branch, since aux is known in the unrolled node loop. - .mod => if (node.aux == 1) @rem(av, bv) else @mod(av, bv), - }; + /// Elementwise binary op with numpy broadcasting. + /// + /// Each operand is indexed through `bcast_flat`: same shape, scalar, + /// (1, m) row, (n, 1) column, or a 1-D (`vec`) operand right-aligned to the + /// output's columns. `inline` so the comptime-known node shapes and the `op` + /// tag constant-fold into the runtime element loop (the bounds stay comptime + /// constants, but the loop itself is not unrolled). + /// + /// Args: + /// nodes: The full generated node table (for shape lookup). + /// node: The current add/sub/mul/div/ne node. + /// self_idx: The node's index in `nodes` (its buffer offset). + /// buf: The shared step buffer (written at the node's offset). + /// op: Which binary op to apply (add, sub, mul, div, ne, lt, pow). + inline fn ew2(nodes: []const g.Node, node: g.Node, self_idx: usize, buf: *[g.buf_len]f64, op: BinOp) void { + const a = node_input_at(nodes, node.inputs[0], buf); + const b = node_input_at(nodes, node.inputs[1], buf); + const a_n = nodes[node.inputs[0]]; + const b_n = nodes[node.inputs[1]]; + var out = buf.*[g.offsets[self_idx]..][0 .. node.rows * node.cols]; + for (0..node.rows) |i| { + for (0..node.cols) |j| { + const av = a[bcast_flat(a_n, a_n.vec, node.rows, node.cols, i, j)]; + const bv = b[bcast_flat(b_n, b_n.vec, node.rows, node.cols, i, j)]; + out[i * node.cols + j] = switch (op) { + .add => av + bv, + .sub => av - bv, + .mul => av * bv, + .div => av / bv, + // Inequality as a 1.0/0.0 flag — the graph's boolean repr, + // consumed by where_op downstream (e.g. PID anti-windup). + .ne => if (av != bv) 1.0 else 0.0, + // Ordered comparison as a 1.0/0.0 flag — `ne`'s sibling, the + // predicate behind threshold guards (e.g. SMC's near-zero + // |c^T g| controllability check). + .lt => if (av < bv) 1.0 else 0.0, + // numpy's power semantics (np.power); SMC raises the abs'd + // sliding variable to a fractional alpha, so no negative base. + .pow => std.math.pow(f64, av, bv), + // ONNX Mod: aux bit 0 selects C fmod (sign of the dividend, + // @rem) over Python % (sign of the divisor, @mod) — a comptime + // branch, since aux is known in the unrolled node loop. + .mod => if (node.aux == 1) @rem(av, bv) else @mod(av, bv), + }; + } + } } - } -} -/// Read a node's first input from the shared buffer. -/// -/// Args: -/// nodes: The full generated node table (for shape lookup). -/// node: The consumer node whose first input to read. -/// buf: The shared step buffer. -/// -/// Returns: -/// A fixed-length slice of `buf` covering the input node's slot. -fn node_input(nodes: []const g.Node, node: g.Node, buf: *[g.buf_len]f64) []const f64 { - return node_input_at(nodes, node.inputs[0], buf); -} + /// Read a node's first input from the shared buffer. + /// + /// Args: + /// nodes: The full generated node table (for shape lookup). + /// node: The consumer node whose first input to read. + /// buf: The shared step buffer. + /// + /// Returns: + /// A fixed-length slice of `buf` covering the input node's slot. + fn node_input(nodes: []const g.Node, node: g.Node, buf: *[g.buf_len]f64) []const f64 { + return node_input_at(nodes, node.inputs[0], buf); + } -/// Read an arbitrary node's output slot from the buffer by node index. -/// -/// Args: -/// nodes: The full generated node table (for shape lookup). -/// idx: The node index whose output to read. -/// buf: The shared step buffer. -/// -/// Returns: -/// A fixed-length slice of `buf` covering node `idx`'s `rows*cols` f64s. -fn node_input_at(nodes: []const g.Node, idx: usize, buf: *[g.buf_len]f64) []const f64 { - const n = nodes[idx]; - // .cst nodes live in the baked const_blob and are never copied into the - // workspace (their switch arm is a no-op), so read them in place. This is - // the additive fast path for policy weights; all other nodes keep the - // workspace-slot contract unchanged. - if (n.op == .cst) return g.const_blob[n.aux..][0 .. n.rows * n.cols]; - return buf.*[g.offsets[idx]..][0 .. n.rows * n.cols]; + /// Read an arbitrary node's output slot from the buffer by node index. + /// + /// Args: + /// nodes: The full generated node table (for shape lookup). + /// idx: The node index whose output to read. + /// buf: The shared step buffer. + /// + /// Returns: + /// A fixed-length slice of `buf` covering node `idx`'s `rows*cols` f64s. + fn node_input_at(nodes: []const g.Node, idx: usize, buf: *[g.buf_len]f64) []const f64 { + const n = nodes[idx]; + // .cst nodes live in the baked const_blob and are never copied into the + // workspace (their switch arm is a no-op), so read them in place. This is + // the additive fast path for policy weights; all other nodes keep the + // workspace-slot contract unchanged. + if (n.op == .cst) return g.const_blob[n.aux..][0 .. n.rows * n.cols]; + return buf.*[g.offsets[idx]..][0 .. n.rows * n.cols]; + } + }; } diff --git a/src/shinro/runtime/tests/graphs/drone_gru_data.zig b/src/shinro/runtime/tests/graphs/drone_gru_data.zig new file mode 100644 index 0000000..e968bf0 --- /dev/null +++ b/src/shinro/runtime/tests/graphs/drone_gru_data.zig @@ -0,0 +1,10 @@ +// Test vectors for `drone_gru` — generated by scripts/gen_lower_fixtures.py. +// Produced by shinro.codegen.interpret on 8 seeded inputs (seed=0). +pub const n_samples = 8; +pub const n_in = 184; +pub const n_out = 4; +pub const n_state = 128; +pub const tol = 1e-12; +pub const inputs = [_]f64{ 0x1.9bfe2762c06cfp-7, -0x1.b0e1975fba2e0p-7, 0x1.06512e9ed59f1p-4, 0x1.57bc98a03dd8dp-7, -0x1.b6d2027d6d315p-5, 0x1.2837fab0bdb1fp-5, 0x1.0b0f285640cfdp-3, 0x1.83eca305496e9p-4, -0x1.203ffce488c20p-4, -0x1.0328877b0a096p-3, -0x1.fe9620e9b2192p-5, 0x1.0ed57cfa270b6p-8, -0x1.dc2a92cf69f38p-3, -0x1.6677e007db798p-6, -0x1.fe533b537d0cap-4, -0x1.2befcc209b8c6p-4, -0x1.bddb61a62a154p-5, -0x1.031cf35770cedp-5, 0x1.51352e25a34c7p-5, 0x1.ab03732bd6a85p-4, -0x1.a52eb0aff6340p-7, 0x1.17da0a3dc06c0p-3, -0x1.1076b78cf51b3p-4, 0x1.1ff50130d86c2p-5, 0x1.720fb704f8180p-4, 0x1.340f3b3719df1p-7, -0x1.30898c00eb958p-4, -0x1.7989e92b13bedp-4, -0x1.76f81025aec04p-5, 0x1.68c48759df4e0p-6, -0x1.9d8a23bf97e0dp-4, -0x1.56b6985474568p-6, -0x1.04dfcf41d7ca3p-6, 0x1.bb0f8a3aeabc5p-5, 0x1.5fb28fc6190ddp-6, 0x1.231f0f0a4baecp-5, -0x1.0bcee6176cec5p-4, -0x1.a8b7cbe42cca0p-7, 0x1.411dc947a5bd5p-4, 0x1.31dacd860a719p-3, -0x1.01db4b83205d9p-3, 0x1.360d34f0e9b4ep-3, 0x1.13a2a227b546cp-3, 0x1.4006703666849p-4, 0x1.b148bb1672907p-6, -0x1.012a62c6164ebp-5, 0x1.2a9a465a25703p-3, 0x1.9175fdc0b112ep-3, 0x1.70f98de4539abp-3, 0x1.0d554ff04df24p-3, 0x1.24c41ab33c6ddp-5, -0x1.eeed644e14398p-4, -0x1.d30cb9bb828aap-12, 0x1.0ce462dadfe1bp-4, -0x1.07db3ed9c8ea0p-3, 0x1.43af1a1482f70p-5, 0x1.6024f363328c0p-5, 0x1.1d195e99a9affp-4, -0x1.e503c4a2ecceap-4, -0x1.0f088b2a89edbp-4, -0x1.65871aea90d85p-5, -0x1.df269edab14cap-4, 0x1.6438f87663b62p-3, -0x1.96400481433d5p-5, 0x1.0d7dee7fb54b4p-5, -0x1.a7a52fa94e31fp-6, 0x1.444b9536d8b24p-3, 0x1.0e68f12ebe9f9p-3, 0x1.036bd602fd797p-4, -0x1.c34760fb083d2p-3, 0x1.54fa224a00167p-8, 0x1.1809b1702de37p-4, 0x1.9b3900577e0d2p-4, -0x1.fa307fdcc2472p-5, 0x1.7525de8ebf985p-3, -0x1.0e6c9c7a44209p-3, -0x1.0ef63d9e88c83p-4, 0x1.7eff18fe8515bp-4, 0x1.417bfc35b2fb8p-8, 0x1.9a170a50684edp-3, 0x1.34deae29a8f2cp-6, -0x1.035b366f08a34p-4, -0x1.354cce56d77acp-5, -0x1.beeef69087e94p-4, -0x1.05ab3ce780ae1p-3, 0x1.02376f99653cdp-4, 0x1.dc174df92c0ccp-5, 0x1.09202a59cc623p-3, -0x1.351626f7bbd87p-4, 0x1.59ede07623eecp-3, -0x1.d6db242863544p-6, 0x1.427056368d234p-3, -0x1.6289c53f6d498p-5, -0x1.2d41034bc87d9p-4, 0x1.993f940bed753p-6, 0x1.a67bb1eaff0e7p-4, 0x1.07cc4fa88b9b0p-6, -0x1.dfaa4b61852ccp-5, -0x1.12ae8a46f7c28p-3, -0x1.1f0805e633dd5p-3, 0x1.9bcc3c01832cdp-5, 0x1.9562eef09eb78p-4, -0x1.0d2e258e4e42bp-6, -0x1.b80f521019b97p-4, 0x1.65991ad5a9d96p-4, -0x1.0639849ed61f9p-3, -0x1.24129becf600cp-4, 0x1.fcbce223cc42ap-5, -0x1.ccd43399823d2p-3, 0x1.3c8393d24a84cp-5, -0x1.dc7aeca145247p-5, 0x1.66167456d5c28p-7, -0x1.f01e15f004bafp-8, 0x1.4b24ebeb4b2c6p-6, 0x1.1c5534098839cp-4, -0x1.36a0d4fd6a393p-4, 0x1.230461db3a160p-3, 0x1.296873bbc666ap-4, 0x1.5997c831daf38p-4, 0x1.dd20d7650e6dfp-4, 0x1.42989c57e80a8p-4, 0x1.59bc108d5660cp-4, 0x1.ef690897bccc7p-8, -0x1.24340a7707f65p-3, -0x1.ba840a683e55dp-7, -0x1.3b3175555d0b5p-4, -0x1.2360a4c5243aep-3, 0x1.a772f51cffee4p-6, -0x1.d1c17665834c7p-5, -0x1.a5ced2640e4b2p-4, -0x1.ab36970dc294cp-4, 0x1.b7c64879d739fp-6, 0x1.25d2f5a55f9a9p-5, 0x1.0ed6dbb26649fp-3, -0x1.6cc3c27f8e501p-10, 0x1.aabcd11596275p-4, 0x1.1f2f0fe90e264p-3, 0x1.d71b9bb397f25p-4, -0x1.e46a0ba20c6c0p-3, 0x1.f744d371c5284p-4, 0x1.16377a5b2f3e6p-5, 0x1.5b274b44c1fd3p-5, 0x1.301c083b60e16p-5, 0x1.398dfe92271dap-5, 0x1.05aa045f8e641p-5, -0x1.2605938745a8ap-5, -0x1.857474ec5af39p-3, -0x1.64e44bb883784p-7, -0x1.49356486a3cffp-4, 0x1.ba6f57d1e5c65p-4, -0x1.d91d737c5aa8fp-6, 0x1.118834399eb74p-7, -0x1.5bffa43621bf8p-4, -0x1.a24d4b00b8895p-5, -0x1.2e55111b4dd43p-10, -0x1.3034703ef6263p-3, 0x1.eca47a4ea6e0cp-6, -0x1.5b93dafa829ffp-7, -0x1.e5abbba78c12dp-4, -0x1.eb2878a40f860p-3, 0x1.a44ad4b3b563fp-5, -0x1.e78fcae077ebfp-6, -0x1.b22ed20467e94p-5, -0x1.82ea6e4ce942ep-6, 0x1.7403a7600b559p-3, -0x1.466029578f1dfp-8, 0x1.1bd5811643b44p-7, -0x1.308d72319ea8ep-3, 0x1.516002ac568dap-3, 0x1.77cd968562cf3p-4, 0x1.b5043ac132ef7p-4, 0x1.386d922582168p-8, 0x1.7776389f8eb70p-4, 0x1.2fe13090e9a23p-5, 0x1.f65311f223e7cp-5, -0x1.f2b4b4f3c6f7cp-7, -0x1.2dda2d2bd8d5ap-3, 0x1.a56b3299dbfd0p-4, -0x1.8c479c9ea7ad6p-3, -0x1.891cbbe773b36p-6, -0x1.4f16f2f96d7fbp-6, -0x1.ab27cfbfba87dp-4, 0x1.f6453dbcc1ca2p-5, -0x1.48385de637c5fp-6, -0x1.65e1eda383fa0p-5, 0x1.a9dab66ba9fbcp-5, -0x1.8669de6a1a943p-5, 0x1.1c768da562306p-3, 0x1.1fe978ba5c533p-5, -0x1.8492d652c6ff0p-5, -0x1.8e2f7ac54afc3p-3, -0x1.0bd3ee498b3d3p-3, 0x1.bd2a77bafc5e8p-4, -0x1.4ba3879c5cf79p-8, -0x1.cfdf4271bcbffp-6, 0x1.5089b5d1d138dp-3, -0x1.06afc2bc6de0ep-3, -0x1.dfc557b64a822p-5, -0x1.8324d1b3beb78p-5, 0x1.e053d71b8726dp-5, -0x1.0fc8b55a56537p-4, -0x1.f6830bfb74adcp-5, -0x1.48bc0e83da40cp-3, 0x1.2abdd3fc2e9b4p-4, 0x1.4a31d6a1583e6p-4, -0x1.863f71e21f007p-5, 0x1.0b9dbd1b12ebep-6, -0x1.08bbe2920ac46p-3, -0x1.828263de30f50p-5, 0x1.1a34509df2be5p-3, 0x1.bcc33131ab584p-7, 0x1.d92995ce20f22p-3, -0x1.426f244524458p-4, 0x1.db5e766711e37p-5, -0x1.4051166b03001p-6, 0x1.cf849a5862235p-5, -0x1.7a153b1d80852p-11, -0x1.cbbbc62282872p-5, -0x1.6360362d28299p-4, 0x1.39f6504105119p-2, -0x1.fae37a33c7ccfp-8, -0x1.9d031999582e8p-3, -0x1.09aab3fe93ad8p-4, 0x1.15b99e556b0aap-4, -0x1.999b5e5a689b8p-5, 0x1.169e8fd61cfeap-3, 0x1.9a9513bf1737cp-4, -0x1.f32ee8f069fe7p-7, -0x1.82d6dc62cb174p-5, -0x1.9b9105a6acc75p-4, -0x1.1eb4cfcc0c426p-4, -0x1.2db31fa66a08dp-3, 0x1.ed521ac5b178ap-4, 0x1.45c6888ebe086p-3, -0x1.0141cfc6fe31ap-3, -0x1.e40470d7b3898p-4, -0x1.6a30f457056f3p-3, -0x1.8acb70fe91c98p-4, -0x1.3e16c164bfcb4p-2, -0x1.d3e0a142a1034p-4, 0x1.099bb7d641f2ep-3, -0x1.1b2cc89d5c8c4p-5, 0x1.5e09a6e0989b0p-4, -0x1.90903eb976a2cp-5, 0x1.6895ac6fc71a6p-3, 0x1.4666140ba53b5p-6, -0x1.38efafe59c4aep-5, 0x1.055e43adcc219p-2, -0x1.09ceae23e6177p-5, -0x1.f4368cad18b5ap-4, 0x1.4acf3160fc42ep-6, -0x1.fd04c41bf2958p-9, 0x1.b4c43bc46ef4ap-4, -0x1.798052475d131p-4, 0x1.499cafa52fe38p-4, 0x1.5d4928748769ep-4, -0x1.117c16448167fp-4, 0x1.0b757fa56b9f5p-6, -0x1.5446a8093e6a8p-4, 0x1.e06be6ffdee8ap-3, -0x1.206a6272e6a27p-4, -0x1.732898fa460f4p-5, -0x1.b491378b77342p-4, -0x1.1b8ae4776b64fp-5, -0x1.3412b1feb1d90p-11, 0x1.3a7c86aa72809p-4, -0x1.f41c543e63dd8p-5, -0x1.305f3eec6f462p-6, -0x1.2218d6731aa38p-3, -0x1.52e769675b6d8p-4, 0x1.1a31d776bef54p-2, 0x1.aa7e4318d1a2dp-4, -0x1.40123fe54cae4p-4, -0x1.11e621eb4cb92p-3, -0x1.8f99463324b77p-4, -0x1.1c4e72725c8a5p-9, 0x1.c72f1f0d93234p-9, -0x1.30e3ddbbe2e43p-4, -0x1.077d8e2ece327p-3, 0x1.234d99220f735p-3, 0x1.72054e0473ddbp-5, -0x1.32d89b6d5983ap-5, -0x1.698804c6d2748p-6, -0x1.b1ca960d60c24p-5, -0x1.2ca6ab7415d5cp-2, 0x1.7b002c3ce870ap-7, -0x1.b67eb7adb1bdfp-4, -0x1.9ab311b418055p-4, -0x1.0640611337468p-4, 0x1.2bf36678c8996p-4, -0x1.df730d21b6dccp-4, -0x1.25bda7e20c2f6p-3, 0x1.06155a5b6dd03p-4, 0x1.34fd501746211p-4, -0x1.88c77cb669c2bp-4, 0x1.ccb757643908cp-5, -0x1.ddcf81c6f09bfp-6, 0x1.eda3191ef6e7ap-6, -0x1.023ea2638c96dp-3, 0x1.55275021a3b94p-4, 0x1.ecdad89a7aaf5p-4, 0x1.04f1f87379639p-4, 0x1.c9646071b29cfp-5, -0x1.8247ee0ad2fd2p-2, 0x1.ab040a3716067p-6, -0x1.4d84509b2dcabp-9, -0x1.e1d6b6257ce94p-7, -0x1.0248e50734683p-4, 0x1.6ad703a8e5dd2p-8, 0x1.519b48b6d7ebep-5, -0x1.b030c61099fafp-6, -0x1.7b8e1d5801020p-5, 0x1.f7b508802f52fp-4, -0x1.c4c2245945a3ap-4, 0x1.a5f39a0721fb2p-4, 0x1.21b085bb2f942p-6, -0x1.49718f43f640ap-4, -0x1.db1b3900518ccp-6, -0x1.78d4523a92790p-4, 0x1.1481a52ed04b7p-4, 0x1.1d00499fa0eefp-5, -0x1.c8209f0906ccfp-5, -0x1.c377f72bfc2a2p-4, 0x1.ee54e6db4a194p-6, 0x1.88252831acf00p-4, -0x1.7504d9e2728f3p-7, 0x1.56b6e0de75fc2p-5, -0x1.340a9becdc8a3p-5, 0x1.bad25100b21adp-8, -0x1.dd3ce8753ec38p-6, 0x1.e1c236b16dd94p-6, -0x1.35338fa64f7fep-3, 0x1.07dc45af3044fp-4, -0x1.78b8ac3827e8dp-6, 0x1.25c590086f4cfp-5, -0x1.16c834d97ce4fp-5, 0x1.06709c640fec5p-5, -0x1.b7525c8a9fa68p-4, 0x1.e713e0b27385fp-4, -0x1.5ce2cc68f1aa0p-3, -0x1.a9ac16838961fp-4, 0x1.821d838947028p-6, 0x1.2b9710cb42495p-3, 0x1.c7aea042b4e8ap-6, -0x1.962c57b215631p-6, -0x1.23dbc41f43f2ap-3, -0x1.39633f7494160p-6, -0x1.04882e793e289p-9, 0x1.5a3a7c42b359bp-3, 0x1.fda51d829a7d8p-5, -0x1.392881284a9bap-3, 0x1.9f1598883a91cp-3, -0x1.43979335f7463p-5, -0x1.683a08f47cbc6p-4, 0x1.2e0b2e8e7d98bp-3, -0x1.4614505389021p-8, -0x1.2cf9e8dc244f8p-5, 0x1.66757eaeb80d4p-6, 0x1.5a110280c0eedp-4, 0x1.96ded9b3453adp-4, -0x1.19a4362ae2c2bp-3, 0x1.9949fc3d2eea2p-3, 0x1.83d5a236d9059p-4, -0x1.36a439ffdb18ep-5, -0x1.4f52b50e21df7p-4, -0x1.8ce8515f3d03bp-4, 0x1.944955b897a7ep-7, -0x1.096d6ef14fb16p-4, -0x1.394ad92a5910cp-4, 0x1.4c4a309cbc866p-4, 0x1.2aa7503c8e406p-5, -0x1.433b9722c9dacp-5, 0x1.2cbf70d473d4dp-4, 0x1.180a0540fc5e0p-3, -0x1.c04e41ad56cd8p-4, -0x1.ee377a6777564p-5, 0x1.82191059fbc8ep-4, 0x1.267a61dcb59d3p-4, 0x1.736c645c6d67ep-6, 0x1.dc20b22795efdp-4, -0x1.bdbb452c4de10p-4, -0x1.2eed6bf1dbc96p-3, -0x1.62ebe1c1ff0b3p-4, 0x1.918d7021dbc3bp-7, -0x1.4613bfa619390p-4, -0x1.8f210d99281c4p-5, -0x1.8f5c2c283606bp-4, -0x1.fc416c11aa47fp-5, -0x1.9b8f9388059cap-4, 0x1.2d073fb3667e8p-5, 0x1.45965ea164883p-4, -0x1.8994d0f8b9b8dp-5, -0x1.53959354019e5p-6, -0x1.dbfb5cb5eb0c8p-5, 0x1.b3337476c6ccfp-5, 0x1.23d19eb1df42cp-7, 0x1.467bbbb950f85p-3, -0x1.c0b49191aa478p-4, 0x1.28f648bbfaef3p-5, 0x1.6bb7bec3ccf8dp-5, -0x1.2745c85506995p-5, 0x1.de07f9ea44a24p-5, -0x1.269c0429934bep-3, 0x1.b1ee4ce2eb227p-3, -0x1.12d9c7bd5094fp-3, 0x1.78c0c8246663cp-4, -0x1.cb363bc15b49cp-4, 0x1.d766d5210f0adp-4, -0x1.3b34f64208edap-5, 0x1.038f622145f23p-6, 0x1.5d97f89ee1348p-8, 0x1.c2dc55df8ececp-4, -0x1.07696347ec634p-5, -0x1.2fd6f0ce3df36p-2, -0x1.3751f0ca2eb97p-4, 0x1.2cfe887d0d0e4p-6, -0x1.68d4e0af81849p-5, 0x1.3b519120529e6p-4, 0x1.9fe0c083ee164p-4, -0x1.e437fa8a1e054p-7, -0x1.31145209353adp-3, 0x1.1b7a1d9fcaa9fp-3, 0x1.bb9e64047181ap-4, -0x1.ea31db6c5a21cp-6, 0x1.afc7080df960cp-3, -0x1.1dcc7ca4b846cp-5, -0x1.d1c3a511556fdp-4, -0x1.fec41d0387b68p-7, 0x1.b97b0e7dcc2a8p-4, -0x1.7ffb1e3b969e5p-4, 0x1.8f9c63acd5a42p-3, -0x1.6f3796528cc39p-4, 0x1.86ee6de5cf618p-4, 0x1.be0609238958cp-5, -0x1.f8d06da19d5ecp-7, 0x1.ba96184958fa5p-4, -0x1.3328a69703f43p-3, 0x1.1607dc157af27p-3, -0x1.a15c122ba3f1cp-8, -0x1.bc5ceabac1a44p-5, 0x1.32dc97b88cefap-4, 0x1.b2227780c1170p-4, 0x1.3b4ee6be9f330p-4, 0x1.997f95ffb1344p-3, 0x1.baaa57b41c802p-4, 0x1.06dcb6685b150p-3, -0x1.ba41ac6e48084p-5, 0x1.5d0e9eefb74b5p-7, 0x1.cd32013dc744dp-5, -0x1.d11a228f35cf2p-10, 0x1.ee32fc8b85bf0p-6, 0x1.5d10a570b2573p-5, 0x1.59cd641a10050p-4, -0x1.4cf3b7245a676p-7, -0x1.1e8e3660e0f1bp-5, -0x1.534730ed8318cp-4, -0x1.6d40e95c1b77fp-4, 0x1.e03c6bfc2c0a2p-4, -0x1.14f5c356c803bp-7, 0x1.42551960e3439p-4, -0x1.09b33ac8d80a9p-3, -0x1.8cefd3fddb083p-3, -0x1.adb5304c43ad0p-4, 0x1.d5a88d49dd2cfp-4, 0x1.b57c0975e19ddp-4, 0x1.10018b058c8dcp-5, -0x1.4891a301391cfp-4, -0x1.ac9d3563460ecp-7, -0x1.e7d9cc11c6f4cp-6, -0x1.1a9a277e4eb44p-5, -0x1.009f1dfd1ae60p-2, -0x1.5f681a10220abp-4, -0x1.37797117e6a77p-6, 0x1.36907d4330d8ap-3, 0x1.075c868cfdaf2p-6, 0x1.1ee6e44be0ebbp-3, -0x1.428652b7759e4p-5, -0x1.9e0145d03462dp-6, -0x1.8f4d00418edc7p-2, 0x1.7b8f6a2d3e734p-5, 0x1.c02e46aa5adfcp-5, 0x1.6937c5816cba8p-3, -0x1.8ec1398436876p-5, 0x1.34863b151ac1bp-7, -0x1.20fbf7d31af5fp-4, -0x1.e1cb7e28d5a14p-4, -0x1.2416ca390b2dcp-4, -0x1.1a9f6f39f938bp-5, 0x1.1597fd43e9caap-3, 0x1.cfce82516f745p-13, -0x1.43cea1a5ac788p-4, 0x1.d0e7bf9dc5035p-7, 0x1.64780a6abb29dp-6, -0x1.14fc1207def1dp-4, 0x1.d444bbfce6064p-4, -0x1.82bbddc825648p-3, -0x1.5ddf1bd8a89bcp-6, 0x1.10693b427dbf3p-4, -0x1.121c692f3ea9ep-3, 0x1.27f066f323655p-5, 0x1.08c8d4c63f184p-3, 0x1.73a5c289facccp-5, -0x1.5a250ec0137b4p-3, -0x1.2a44c86cb5f37p-4, 0x1.f8c06094022f7p-4, 0x1.e8cadf051e09dp-6, -0x1.0272375ae70afp-10, 0x1.696e7890e4608p-5, 0x1.2757765e8b6b2p-4, -0x1.222ff6e2774f4p-4, -0x1.dbca9f2aaeb1ap-6, 0x1.d44ca892d4250p-7, -0x1.bd9c33d18bdccp-5, -0x1.b54b47f9d3b94p-7, 0x1.09cddbe6f15fbp-3, -0x1.8c6b44aba26aap-4, 0x1.8a949d24ed328p-3, 0x1.80e3c53f058d8p-3, -0x1.5ee992d7c9631p-3, -0x1.ce1a62bb9621cp-7, 0x1.18bba18d93f26p-5, -0x1.37a71dbbb305cp-4, -0x1.2f8bec4b3f206p-4, -0x1.84fb5c536783cp-6, 0x1.2ec470b01a317p-4, -0x1.a2e27a71f88bfp-5, 0x1.761b5d5092397p-3, 0x1.db17e96b1959cp-6, -0x1.501e62869a1fcp-7, 0x1.28cef238d737ep-3, 0x1.008657d16a173p-4, 0x1.2e850cce27a9fp-5, -0x1.0f452bee041f4p-5, 0x1.738116c5aac57p-3, 0x1.4c85a9dcfdf0dp-4, -0x1.4d44e5e351088p-6, -0x1.4302a8a92b406p-3, 0x1.31859b6f8d80ap-5, -0x1.d479d7511edddp-4, -0x1.5f6cfcb39abe4p-3, -0x1.c95ca0aa53164p-6, 0x1.cd2989828873cp-6, 0x1.06a6f3bd1f51bp-3, 0x1.cec4e1ceb1315p-6, 0x1.4a2545ee9e01ap-4, -0x1.f61f1e4c43c58p-4, -0x1.27557110f0345p-9, 0x1.970401b5d5c57p-7, 0x1.612d10c678224p-4, 0x1.7c4ebfd63eeecp-7, 0x1.4959ca2da47fbp-4, -0x1.9d0a3eff95fd0p-5, 0x1.253c95b202aabp-5, 0x1.53dbca51e907cp-5, -0x1.ffe87ba718515p-4, 0x1.1f9a3cb8d9716p-6, -0x1.0670e43395ad3p-5, -0x1.85f50bd6692f4p-3, 0x1.8890396bf5db8p-4, -0x1.286f43f89405fp-5, -0x1.5d239364f0124p-4, -0x1.35190e6e12f68p-5, 0x1.c4dad11daff7ap-7, 0x1.34d1e2807ab6dp-3, -0x1.0fdd6e017c62cp-6, 0x1.82ff085f6e334p-5, 0x1.194f1e51c9ebfp-3, 0x1.b515a808451cap-5, 0x1.b5af12afaa99dp-4, -0x1.865b5c4154ba4p-5, 0x1.3bd261c14b2fcp-4, -0x1.7bf3966cdb5f0p-8, 0x1.b8142f0bf4165p-4, -0x1.9b0ed9221205dp-4, -0x1.3f4e8e18d554ap-4, 0x1.03d612e9bce13p-3, -0x1.4143943c83673p-6, -0x1.260f80fa11c84p-5, 0x1.fc60ec6b07c84p-8, -0x1.1a6b0c7002550p-4, 0x1.10c8166e6c2f0p-3, -0x1.ffa8329a21daap-4, -0x1.ed7ac1e3da51dp-7, 0x1.1c3945d91cdefp-5, -0x1.56408d4a4a580p-7, -0x1.489df24ef2f61p-4, -0x1.63b135006721cp-4, 0x1.5c7bad55c37d9p-5, -0x1.a615b4f4369dap-4, 0x1.08b3758a1e93cp-4, -0x1.3825450ce3027p-3, -0x1.c6a46420bd34ap-5, 0x1.dbdecbbec42a2p-9, -0x1.0070d2e55fbcbp-3, 0x1.0b104b58c603ap-4, -0x1.e5fbdebf962afp-10, -0x1.a860331de0a04p-4, -0x1.37117cba7221bp-3, -0x1.40a1f8d73563bp-3, 0x1.4e74c08835376p-8, -0x1.d9d66dbb019d8p-4, -0x1.1786ffe67fad2p-3, -0x1.7ad72fc5ed3dbp-6, 0x1.d26e9e98b17bap-3, 0x1.c6b8dd5ed55c5p-6, 0x1.387dd67f05240p-4, 0x1.5c848a83175b2p-6, 0x1.40b5a17adc354p-4, -0x1.131086b780274p-3, -0x1.60ace7680b34bp-5, 0x1.ac327d5deee62p-6, -0x1.d5adb79a1106ap-10, -0x1.3a8fcb092f5e9p-6, -0x1.10be2ae91869cp-4, -0x1.a755ba661a510p-6, -0x1.3d1c8696cbd4fp-4, -0x1.effdcc7c281bcp-3, -0x1.e94549d313034p-4, 0x1.85a7a6b57a79bp-5, 0x1.3ee3ba8d8bb5dp-3, 0x1.736bd5039b81ep-3, 0x1.3d093ebfaab9bp-7, 0x1.6dee1008c25ecp-4, 0x1.73e862733051cp-4, -0x1.1b8ca2f81c469p-4, -0x1.5bbcf2a1ec5b0p-3, 0x1.94d8a54c4a1d8p-9, -0x1.68e61569b38c4p-3, -0x1.06161a4eebdd2p-5, 0x1.f22b657fad5e4p-5, -0x1.22d48a078cb12p-3, 0x1.a74d538f43d57p-9, 0x1.fbe952d2b8512p-4, 0x1.2826a929a6c7ap-5, 0x1.abe2ccc8acd38p-5, 0x1.73669fa5497e4p-4, 0x1.62e92c9ffbb8ap-3, 0x1.f02ee3316a7d0p-7, 0x1.f79a82706a207p-4, -0x1.a48a148ed3bf7p-8, -0x1.bf6be70138d4fp-5, 0x1.01e6be1b8720bp-5, -0x1.f048299ec965cp-5, -0x1.d581e879eb21dp-5, -0x1.f1dc72a70a22ap-5, -0x1.d61a560835ab8p-3, 0x1.59b360509b240p-7, -0x1.02d55f0a28226p-3, -0x1.5f7fdc41cdcbfp-7, 0x1.28f41f89ec343p-3, -0x1.aacdafdca4dc4p-5, -0x1.bc038f1eed12fp-5, 0x1.175421e0ea068p-3, 0x1.bf889f741d01fp-5, 0x1.8ffc49aadc1f8p-4, -0x1.230df8e1b1dd7p-5, 0x1.326a35d658fb4p-4, -0x1.190dfdcff4177p-4, -0x1.14e3eb25bcabbp-4, 0x1.e8717cf104698p-5, -0x1.ea2ff3048b64ap-5, 0x1.3a3635989ee6dp-4, 0x1.e9d126719d3e5p-3, -0x1.5952f441ce08ap-3, -0x1.341a58788ee1ap-4, 0x1.cacfd71c67db2p-4, -0x1.db6463aab67cap-7, 0x1.db9518541f657p-4, -0x1.9db8ea5ff1315p-4, 0x1.0f6fe917b25fep-5, -0x1.ed57cb10115ddp-7, 0x1.cbf77f33ed99dp-7, 0x1.0f400fe9adab2p-5, -0x1.f3b6f06da17bfp-4, -0x1.b7f77a91a4300p-4, 0x1.1e90af26fdeb5p-3, 0x1.e066be8caa5cap-6, 0x1.5c79c51aa3391p-7, -0x1.20d91d3875dabp-8, 0x1.241461a50bcafp-5, -0x1.d978c0932f9f8p-4, -0x1.99339bbd480a4p-4, 0x1.0b29cd4f4a879p-3, 0x1.efb2da86c47acp-7, 0x1.5c488246911f8p-4, -0x1.f028f2c6b119ap-5, 0x1.19f40f435f839p-3, 0x1.1ada213c5c0cfp-5, 0x1.8a3c90300cfb1p-5, 0x1.c184e1ff8109ap-5, -0x1.467479dc574ccp-4, -0x1.7e1981896a1dap-3, -0x1.b83d3a67a7904p-4, 0x1.4dee5b5648aebp-3, 0x1.0a614cbbf7620p-3, -0x1.1c32af1f3259cp-5, -0x1.ee4438f706612p-6, 0x1.a898012282d15p-4, -0x1.13ec38651f013p-6, -0x1.0a16a2c8f938bp-3, 0x1.032ee7db80dcdp-3, 0x1.86e799d4c6597p-5, -0x1.01ac55f8a0615p-2, -0x1.0090b9c22e609p-5, 0x1.d6c74d39cdbb7p-7, 0x1.8a3cc64b449e8p-5, 0x1.f291ab1b678e5p-7, -0x1.04665bec941fbp-4, -0x1.7b51b96a8f6c0p-7, 0x1.e300371c46b8fp-6, -0x1.b7190f929a268p-6, -0x1.30a93bdb30c2fp-5, 0x1.006d4226bad4ap-3, -0x1.83bb029099114p-4, -0x1.1e47cd3e9a981p-5, -0x1.a000ff3056d7dp-3, 0x1.bb299fc3a7a1dp-5, 0x1.5341d2cbf869dp-4, 0x1.c152069a86505p-5, 0x1.77e0ef4355feap-4, 0x1.6906e732d5e78p-5, 0x1.1896af0811a97p-5, 0x1.8441e768cbaf6p-5, -0x1.b5f548546143cp-6, 0x1.e6bd352ad7e97p-4, -0x1.1d8cdc3e83103p-5, -0x1.2b7d5b4b0700bp-3, 0x1.5c12452eab30ep-4, 0x1.7b06203b9b37cp-3, -0x1.8947245a83812p-4, -0x1.4d065ee491594p-7, -0x1.18c1cddef1031p-4, -0x1.37c617a8a65b7p-5, 0x1.2e132ca30c6abp-8, -0x1.fca50dd425787p-4, -0x1.c6e863f153b22p-6, -0x1.2c3ae9313642fp-3, -0x1.d17df905411b8p-5, -0x1.e5d06ad770a3dp-4, -0x1.b1ca902ddb385p-4, -0x1.603cda645fdc4p-3, 0x1.f372988155af7p-4, 0x1.a1056d8233aa0p-5, -0x1.88b256be523dap-3, -0x1.e8ebd178ea487p-5, -0x1.129c9520e5442p-4, -0x1.1b02be3627e08p-4, -0x1.28525dc60a96cp-3, 0x1.34ff1382f47bcp-4, -0x1.444aa727c4b3bp-5, 0x1.7f81f132edff8p-5, 0x1.af84b0cdfb4c7p-5, 0x1.19b0f278d9b32p-3, -0x1.73af935f75854p-3, 0x1.6410d287761d6p-3, 0x1.03da7654d28efp-3, 0x1.d574a631b2d24p-5, 0x1.e828e1593f8adp-3, 0x1.4fd6415ca7c24p-6, 0x1.507a4ebe333f6p-4, -0x1.2e745160ba62cp-4, 0x1.d0a1fece9b018p-4, 0x1.12f75048d07f3p-6, -0x1.719f87538b011p-5, 0x1.b18c94f3827cdp-3, -0x1.f3623ec69f28fp-6, 0x1.d096b9d27a64dp-11, -0x1.4339361f2e47cp-6, -0x1.3585d69e38fe0p-4, 0x1.b337e5d1bef52p-5, 0x1.2e73dbde88f85p-4, 0x1.224d4e3729ecdp-5, -0x1.e372491a0b2b4p-3, 0x1.9ce02586ab465p-4, -0x1.1eea4e3a8b6c9p-5, -0x1.f234c0f8ad8cfp-4, 0x1.ee352fde27b10p-5, 0x1.cd161429d9bdcp-5, -0x1.ab3e347dc91b2p-4, 0x1.fa5ad5f1a3b90p-3, -0x1.ef76896fe823dp-4, -0x1.62eb408f5e5eep-3, -0x1.d8bfa54fe2e55p-4, 0x1.22fad4af7ff38p-3, -0x1.201fa824573bcp-6, -0x1.30c9f15502eb7p-5, -0x1.975b59f23713fp-8, -0x1.e8bf014915f17p-5, -0x1.1abb5d6962583p-4, -0x1.06a45158eebc3p-4, 0x1.21fa84608114cp-4, 0x1.a1fa8e198d82ap-4, -0x1.b02a794cc00dcp-4, 0x1.87f37bdf64074p-6, 0x1.42d98505d0fb2p-4, -0x1.bb15e9c8d2210p-4, -0x1.9bb3da75aeecap-5, -0x1.a930eaad3d3aap-4, -0x1.086713c85e872p-3, 0x1.4dc8c481a9508p-7, -0x1.2d8512e09fab2p-4, 0x1.0282ae7be35e4p-4, -0x1.81a39715690dbp-9, 0x1.52063a7354513p-5, -0x1.dee056c5a5068p-6, -0x1.04184d3206548p-4, -0x1.291e237ed72bfp-7, -0x1.05f0ecea668afp-11, -0x1.211e502770f6bp-4, 0x1.5d778d1aa0115p-5, 0x1.31ce250fa6336p-4, 0x1.0300b13c8a801p-6, 0x1.5eec45667c8e6p-3, -0x1.03018d0a4bb73p-4, 0x1.aa78fb61e214ap-5, -0x1.4ed5e6833ae68p-5, 0x1.806abf1fc1a92p-6, -0x1.53f27ef158d29p-4, 0x1.c8c1293adbd94p-4, 0x1.206484d74b507p-6, 0x1.e857e59734480p-4, -0x1.034bdf2cdac97p-3, -0x1.9449a40b81c82p-5, -0x1.6d984ec2c17d1p-4, -0x1.b3c44b6f5c5a2p-5, -0x1.1bb163fd49f71p-4, -0x1.8afd108797d2bp-7, -0x1.c41f9f4ddff24p-10, -0x1.0c993159ab6edp-8, -0x1.c715ccdc6af00p-5, 0x1.3313d13caa166p-6, 0x1.66a6f07b7b500p-4, -0x1.7192734ca4c9bp-4, 0x1.74b7620f02ce8p-14, -0x1.e56e54a8dbe2fp-8, 0x1.7fad15f625c45p-5, -0x1.a280ed513516ap-8, -0x1.9aa4b7a7d0805p-10, -0x1.95f3ecd2ff547p-4, 0x1.1c79ffcab0dfcp-9, -0x1.799a98539122fp-4, 0x1.a6770500dfa12p-5, -0x1.523a515abbdebp-7, 0x1.053754033522dp-8, -0x1.6d081541dc624p-4, 0x1.4938173f9e604p-4, 0x1.1b925ffbe32b2p-4, 0x1.60e154dffc0c0p-4, 0x1.c82b2dea785c5p-3, -0x1.5830e6ef7c184p-8, 0x1.ece9eee5eedfcp-4, -0x1.95c24af241400p-7, 0x1.42d61897b0aa7p-5, 0x1.2b48cfcb87067p-5, 0x1.b181d442a8f2fp-6, 0x1.0d9f29be9daf7p-4, -0x1.f1f828572dc27p-6, 0x1.0c40f91306048p-8, 0x1.b68691db69928p-5, 0x1.65f5e1ef14c2cp-3, -0x1.59077fa7c1503p-4, -0x1.71e55dad6d3d4p-3, -0x1.8c9015e96e8fcp-5, 0x1.26ad6fee80a14p-7, 0x1.1eaeb6524c2cap-6, 0x1.2e2de2b40376cp-7, 0x1.e4788897e6470p-4, 0x1.8fca3d1ed6c53p-4, -0x1.42e1d40d02e27p-8, -0x1.80a72b33af578p-5, -0x1.1b73525eec432p-5, -0x1.23e2658e5d95ep-5, -0x1.719f470d5ac95p-6, -0x1.42142e87e3fbbp-3, -0x1.79af40736b628p-5, -0x1.5c0fcc73ced06p-5, -0x1.35762cfc57d41p-6, -0x1.a0a527eafcd82p-6, 0x1.13410e598cc8bp-4, -0x1.b3c49b76fe645p-5, -0x1.6748690e14e20p-5, 0x1.bbf4cb58bfdb8p-5, -0x1.818a3346971b9p-6, 0x1.62a3b15258f2ep-6, 0x1.1228ef572cf90p-4, 0x1.59ad6abff0c0fp-5, 0x1.99ddbc51caa6ap-6, -0x1.41d98fa513288p-6, 0x1.174dc7736496ap-4, 0x1.1f9efb69e8136p-6, -0x1.9d934bb056b3fp-5, -0x1.ee2bea4e0af7dp-7, -0x1.f2f21f7ca2a88p-4, -0x1.89da73a393370p-4, -0x1.819e9bdf78b3ep-3, -0x1.167ff90c0a8f7p-4, 0x1.11850b3694ed0p-3, -0x1.c7e02b1ac0830p-5, 0x1.4293a3d5f4363p-4, -0x1.69be51b35d390p-12, -0x1.1ef1de47164b3p-4, 0x1.121463984e0cep-3, 0x1.dcf16a7d51294p-5, -0x1.66c4cd2d980a9p-3, 0x1.aa8eef651c672p-4, -0x1.b83c0e833459dp-4, -0x1.237e848d472d1p-6, 0x1.11a8c519d771bp-4, -0x1.eb4787f59ac4ap-6, 0x1.ca51c9c7e320cp-4, 0x1.37d04a780dee0p-4, -0x1.42f1b22d85725p-3, -0x1.83049fa477f5dp-5, 0x1.ce264c7b2d492p-6, -0x1.d709f6a415b20p-5, -0x1.6258f10605f2ap-6, 0x1.479786bd331efp-4, 0x1.0381dae701b5bp-5, -0x1.7915e70ce7813p-4, 0x1.1e133826b3adep-6, -0x1.f5923fbd37ea0p-5, -0x1.f1be2781fa8fdp-4, -0x1.cedef1bd75b34p-4, 0x1.d625e02e6ddecp-6, -0x1.707df18ff5a0ep-9, 0x1.1cc88017dfaf6p-11, -0x1.d57cbad7fc727p-4, -0x1.2d59a50c92db6p-6, -0x1.a8d2e7f93463ap-4, -0x1.7b736f1d6a637p-4, -0x1.0e8b2e80b35e1p-6, -0x1.1b518054d0f09p-3, 0x1.1221c26220cb7p-4, 0x1.fd50489c29098p-3, 0x1.77de359e5d896p-5, -0x1.ab2c51f7cf702p-4, -0x1.bc4f72dc59694p-6, -0x1.3e8dbeaeea20ep-3, -0x1.3557e519de60bp-5, 0x1.9f977186a44bdp-5, 0x1.e2d2f1b1b0f27p-5, -0x1.a69a11a92190ap-4, 0x1.ea1ec7f62e0a8p-6, 0x1.d9aa2b8d2b25dp-4, 0x1.6771587f969d5p-3, -0x1.1f0bab63d50a4p-4, -0x1.61f9f06e8887fp-4, 0x1.649eadd35759cp-8, -0x1.2bd620845e3a6p-2, -0x1.b305e6d99f664p-5, -0x1.bbf723c7df7c0p-6, -0x1.784aff2d4baa9p-5, -0x1.4460929cc63e0p-3, -0x1.924f996e0cfe4p-6, -0x1.3e1950e7e3ac6p-4, 0x1.3643db055cda8p-4, -0x1.783510a4d939fp-4, -0x1.ce98217675d00p-6, -0x1.7da9710059741p-6, 0x1.d0f45aa8bee9fp-5, -0x1.04b35c8eec5d9p-2, -0x1.170a39fe3a197p-5, 0x1.37236be5e1ef5p-4, -0x1.284b8560c1545p-5, -0x1.38b7790af3a48p-3, 0x1.0b8c99e094a72p-5, 0x1.13d05ca42eee5p-5, -0x1.bb2b794f2db68p-6, -0x1.db0d64f4931dcp-4, -0x1.2f616b0b32bbdp-4, -0x1.0107824f53380p-5, -0x1.669e462349dc6p-4, -0x1.8940a586ee39ap-3, -0x1.3b1991443f06dp-4, -0x1.94a521eda2bbcp-8, -0x1.9f623413996cfp-5, -0x1.ef462f41ac01fp-8, 0x1.1221662f4c7a0p-7, 0x1.6f3cc153ef730p-4, 0x1.c357daad1696fp-3, 0x1.2bbc92a9ff119p-4, -0x1.1f9b42b03690cp-3, -0x1.101237b65fd44p-2, -0x1.35889c41d7a68p-7, 0x1.d3d9eb797c8b2p-8, -0x1.dbe73f110c405p-4, 0x1.bdb28c518f98fp-6, -0x1.3a2371cca58f8p-4, 0x1.49ddf6aad5f79p-5, -0x1.0aaa1bd6efc27p-5, 0x1.4599f25b58aecp-5, -0x1.6501a1d761bb4p-3, -0x1.67312b1c941e4p-5, -0x1.e6eb5d67e1d02p-7, -0x1.23d078d429347p-3, 0x1.8180bc6f4654bp-3, -0x1.bb00677e639eap-5, 0x1.1caa8cbec3b25p-3, -0x1.101d51378c04fp-4, -0x1.78c8e4cb9c738p-6, 0x1.e4ed1cf3f23e5p-4, 0x1.f1ca371376c0dp-6, 0x1.3aa96ed6b777ap-6, 0x1.b3b8c45003cf0p-6, -0x1.17ca049fb3addp-3, -0x1.3f1f48ddd219fp-5, -0x1.87c298861dfe0p-4, 0x1.43714983086f9p-6, -0x1.bda4ad3d5693cp-5, -0x1.20bef097db5e3p-8, -0x1.fa8b67249a0f8p-8, -0x1.dcb6c2bdf33cdp-9, -0x1.c76ffe72b20a7p-9, -0x1.0b36cd7278685p-4, -0x1.afb8341ae482fp-4, -0x1.101ecee2810eap-4, 0x1.b6e6f04f28c97p-4, 0x1.32836b06f8e49p-5, 0x1.e0d575f974675p-5, 0x1.1a9e0fd80b8f0p-3, -0x1.e3184c0964257p-4, 0x1.a1c0c628e5baap-5, -0x1.b859b0c432135p-4, -0x1.11e2a0b9fbe13p-5, 0x1.8cb07499fc068p-5, 0x1.4a9e2f6571523p-3, -0x1.405ff04cd0587p-4, -0x1.36a0dc72cd374p-7, 0x1.d998375f1195fp-4, -0x1.311cda17fddb8p-3, 0x1.28a4951398b6ap-5, -0x1.f9153a59cb374p-6, -0x1.69246b2c04ba8p-4, 0x1.e07ad97bfd6a8p-7, 0x1.e75cff0090c58p-5, -0x1.7598978fcf07cp-4, 0x1.3749a212b4fc0p-5, 0x1.1c0ca4e35e16dp-6, -0x1.fca5901b3b1adp-4, 0x1.3e2392908e039p-3, 0x1.be6c9404522b8p-4, -0x1.6039dade9f7f6p-4, -0x1.e09169b3b034ap-5, 0x1.3bb62a5a28913p-4, -0x1.95df323119a20p-5, -0x1.78c63d229e7dcp-3, 0x1.ad9f42d0315d5p-4, 0x1.cc66438f6de87p-11, 0x1.868f18423f70fp-3, 0x1.24d64a0ae631ep-5, 0x1.38ec0e645cd81p-6, 0x1.26594e2ff8391p-2, -0x1.199663c0b709ap-6, -0x1.85dd1de32437cp-4, 0x1.778499a9fa964p-6, 0x1.d1348887986ccp-4, -0x1.dd3bb3b84e71fp-4, -0x1.74067fe0e757ap-4, 0x1.70751819a7263p-5, -0x1.47687db484dd0p-2, -0x1.bf8fa961b6c0dp-4, 0x1.45d48d3db93e8p-4, -0x1.e0a84763a20ffp-5, -0x1.4d1a8f11ec479p-3, 0x1.8a5b263360a3dp-3, -0x1.20e0aa68470bcp-3, -0x1.acbdb5d9bf3dcp-5, -0x1.315775fedb347p-5, 0x1.107292a624c15p-7, -0x1.2eb2db7936c07p-5, -0x1.094e6e3a6aaf7p-7, 0x1.78cbe5aece116p-8, -0x1.1c0575582395ep-7, 0x1.31a3c4c47a2e8p-7, -0x1.e73438170748fp-3, 0x1.6951f8a776380p-5, -0x1.1fa1fab52e6dbp-3, -0x1.bbba9fca3405fp-3, 0x1.1ae669c238e4bp-3, -0x1.074606022280ap-3, 0x1.26b29230dbb01p-6, -0x1.3c70f181bf9a7p-4, -0x1.15e656cdc461ap-4, 0x1.8c35c1ab91428p-5, -0x1.ad5a5a7db9bd0p-4, 0x1.314b75cfe5a8bp-5, 0x1.37dcffb0f3499p-5, 0x1.dcf536ad33ae5p-4, -0x1.136d05d4db46ap-5, 0x1.acae1a713cbb5p-4, 0x1.6065f5697c697p-3, 0x1.44f3d90f6724ep-3, 0x1.e01d3f078be00p-5, 0x1.6ff4f3de1aea8p-5, 0x1.23c8c08b18defp-2, 0x1.c9264e918ff6cp-3, -0x1.3a01a60612a5ap-4, 0x1.7a4f6d482b24bp-4, 0x1.ed200030c3370p-5, 0x1.d99cae5eb9cf4p-8, 0x1.f65fad53517b0p-7, 0x1.8f97f3d19aae5p-5, 0x1.7ff129079d47fp-4, 0x1.666ebb0752ae8p-6, 0x1.165be8248bb8bp-5, 0x1.1d1c3f008c743p-3, 0x1.0446c3af5a484p-5, 0x1.be7b7fae892b7p-5, 0x1.959926c0848b3p-4, 0x1.4e7dfd12349b4p-3, 0x1.f6989122d4a5ap-4, 0x1.3503b5930d42ap-5, 0x1.547c1e75f4acep-6, -0x1.f530227039834p-4, 0x1.de83e8e1fe0d8p-6, -0x1.a8d321befceb7p-4, -0x1.a3725171cc81cp-4, 0x1.0a72ce0ec6e80p-4, -0x1.499241b586721p-7, 0x1.82d5824761b6bp-5, -0x1.00cdd907e6141p-4, 0x1.ec035e8cb1df7p-4, 0x1.d71cd89220718p-7, 0x1.e67e5781d3d6ap-4, 0x1.13d75a81d0237p-4, 0x1.0ebe7869736b0p-6, -0x1.880278c31282cp-5, 0x1.9cf9e31d98a34p-9, 0x1.5327313974c8dp-4, 0x1.1dc2b7333037cp-4, -0x1.e9b623235d6dcp-4, 0x1.a41e8ef43884ap-4, -0x1.5e777e532342ep-6, 0x1.4dee98deec4e9p-4, -0x1.1db0f1f35d160p-4, 0x1.0543f9801ae53p-4, -0x1.4648b687ff049p-4, 0x1.a7e06013145f8p-7, -0x1.e84ac2d3cd5ddp-6, -0x1.d3e1d0e1e4db5p-6, -0x1.d025f504f8d0ap-5, -0x1.f73f7bc989c7cp-7, -0x1.647b6356d78bcp-3, 0x1.670e23d7bf944p-4, 0x1.89e825c0dfd6cp-4, -0x1.6ab8694ae2243p-5, -0x1.1a92e11bd2cc6p-3, -0x1.08e461c63cac4p-4, 0x1.842490786ff59p-4, 0x1.00369b676dea3p-4, -0x1.ec196a08da5e0p-6, 0x1.6f861479f78fcp-4, -0x1.aa972c2c9413cp-4, -0x1.f5df2694683b7p-5, 0x1.84cc5a8970cc4p-5, -0x1.3a49eeb770328p-7, -0x1.e2b195d911e2fp-5, -0x1.013debd25e541p-2, 0x1.12ee22491e8e8p-4, 0x1.09316284f03f5p-5, -0x1.64f353807a2abp-3, 0x1.ebc96bdc1c947p-5, -0x1.78898da574464p-10, 0x1.c8d7c83ec8e92p-6, 0x1.8326b0f1084fep-4, -0x1.2f0ec12fffb5cp-4, 0x1.2446a186013c4p-4, 0x1.181b4e1ccdeb3p-4, 0x1.37eab678d19a5p-4, 0x1.4f0b32c46bfa8p-3, 0x1.0dd15aca2ff97p-4, -0x1.cc07300250a67p-5, 0x1.704f23181ad38p-3, -0x1.c58e22cfb784dp-4, -0x1.7b102bcf8969ap-5, -0x1.8b0bfaaacb578p-4, -0x1.50ba01aaca81dp-7, 0x1.bb46eaad951c4p-4, 0x1.09c95c4178801p-3, 0x1.7bb6a5c669d6dp-5, -0x1.f336919b612b5p-5, -0x1.c586a78b0903ap-5, -0x1.ee2366000e92ap-5, 0x1.8648964e34a95p-4, -0x1.735189b9a79bep-4, 0x1.621c267f15b6fp-4, -0x1.ab378e557c8ccp-9, 0x1.19e3733c4e43bp-6, 0x1.359994afb139dp-3, -0x1.8564c4902b188p-5, 0x1.54526fac398f1p-3, -0x1.20a7e95dd0ecfp-3, -0x1.51d2bdd3d112ep-4, -0x1.43412acd498a5p-3, -0x1.31e1c18ec882bp-4, 0x1.dd7f3c4fd59a2p-5, 0x1.2e2c7fcbb9537p-4, 0x1.f69ee3641aa5dp-6, 0x1.b59a7d0269f0cp-6, -0x1.e0984033f4fffp-4, -0x1.0fbc3367c49f0p-3, 0x1.f1e4b517ec19fp-6, 0x1.1407e70714741p-3, -0x1.2a4c9816bb00ep-5, -0x1.03cd0ef5067dbp-3, -0x1.3a040e36064d1p-3, -0x1.16cb8156c5e90p-4, 0x1.437d964f0d4f8p-3, -0x1.545c46fea4733p-6, -0x1.a924404aacfd8p-4, -0x1.f3474ccb5d958p-5, -0x1.8c1ebaf9415eep-5, 0x1.b32e574b3d2c0p-6, -0x1.0e57bdc4afa0ep-4, -0x1.6c84ed8dce5dfp-4, -0x1.340c09fe1c0e0p-6, 0x1.7fef4a7596b74p-5, 0x1.25b37d14e3569p-4, 0x1.c2feee90dbff5p-5, -0x1.76c80f630efa0p-5, -0x1.5b26da9d4d104p-3, -0x1.47127c7e60247p-4, 0x1.d1705f568bae7p-6, -0x1.1120e5ccd869bp-3, 0x1.9de42e86bbc4fp-6, -0x1.e34eec96dbbf8p-5, -0x1.dce8a143dbcc7p-5, 0x1.ca8cd16b5b62fp-4, 0x1.665f1d4c2351ep-6, 0x1.18a0e3078ba48p-3, -0x1.80b7d0698d5e2p-4, 0x1.cf26cec0b50efp-4, 0x1.745bfd7247530p-4, -0x1.32b0336c6115dp-2, -0x1.213ed7032247ap-7, 0x1.3bd8f99f892b7p-3, 0x1.3eb13aca71d91p-4, -0x1.6987c12e600ebp-5, -0x1.7d675dde74687p-6, -0x1.0add48b067b73p-3, 0x1.51fd57749a260p-6, -0x1.6f3ddc43f88a1p-3, -0x1.9fdea0e15376dp-4, 0x1.ca68e38b46dc8p-4, -0x1.0d8cd62d540cdp-9, -0x1.29b7f76e3feffp-5, -0x1.5b0cb07d4b3a4p-7, 0x1.18c51b3d17a0fp-2, 0x1.a8035408d450fp-4, -0x1.3db3e49bb3451p-4, 0x1.5559b0772d834p-3, -0x1.22f697b7e7bbep-7, 0x1.2efcf13b55183p-4, -0x1.e091529e4e27ap-5, -0x1.802553fd18019p-4, 0x1.4876a316f26b4p-4, -0x1.3aef9e8492218p-4, -0x1.4007247623983p-4, 0x1.6fc0bff362a8bp-4, -0x1.dbfbc4fd2c262p-4, -0x1.22a9ade9d4cf1p-3, 0x1.be823115f7320p-5, -0x1.91623de1ab69cp-3, -0x1.33e825f1865bap-4, -0x1.2b898c297222bp-5, -0x1.1384d4c3e34a0p-3, -0x1.c9aee36a13154p-4, 0x1.10bdd65178c66p-4, 0x1.df27b4dd7fad8p-6, -0x1.835d08ec7bc19p-4, 0x1.b1c12bdf7072cp-5, 0x1.3725f20e207f3p-3, -0x1.06a3a07ac7850p-3, 0x1.91722b8dc0624p-8, 0x1.94d1754a9911ap-3, 0x1.f4a984b37ce2cp-5, 0x1.4d299cab4df91p-4, -0x1.47ee1d59a22a0p-6, -0x1.46d890799b65cp-4, 0x1.d453363aac2ddp-4, 0x1.0bc4075935646p-4, -0x1.51a98f8e9dc4bp-8, -0x1.7d33f97f490a3p-5, -0x1.65ef22eec36cdp-3, 0x1.fedf9fc3f3eb4p-7, -0x1.1b5357233e47ep-4, -0x1.b00f6086d7d30p-7, 0x1.12d4de52dcf6dp-4, 0x1.4fdf8405ce3c8p-4, 0x1.2680b74c8d1dbp-4, 0x1.cdd6511dc218ap-3, 0x1.dd3b885e115a2p-4, -0x1.3197f78853308p-4, -0x1.4f2d2cffd2e52p-4, 0x1.dcce2611d090cp-3, -0x1.0fb2c9fa51ac9p-4, -0x1.213ed1471be91p-8, 0x1.6558de3e6efe3p-3, 0x1.5f4bf3f29d54bp-3, -0x1.660955db55fd0p-8, 0x1.8c6648914c809p-6, -0x1.4eded18e41ea8p-3, -0x1.740f43c35ececp-4, -0x1.2b38643ad633bp-5, -0x1.28c1824660f87p-11, -0x1.08dd37e2890e9p-5, 0x1.f3097383241c7p-7, 0x1.c110b589a809cp-3, 0x1.7c635625a0008p-5, 0x1.f9c92de2dc304p-6, 0x1.7f03bc3d05fd6p-13, -0x1.19a746890264fp-6, 0x1.f9039c9916cdap-4, -0x1.96054b6abc18cp-4, -0x1.9b7fbda90931cp-7, -0x1.c0d49211ef34dp-4, 0x1.1d81b10378ae9p-7, 0x1.861aa60751579p-7, 0x1.790a1a6cf614dp-4, 0x1.ea8fec54ee0b8p-4, 0x1.0f9755aaab4e5p-4, 0x1.4c3d1b92f2c2bp-3, 0x1.455351f46d060p-3, 0x1.025782a575c4fp-5, 0x1.31d8831020c6ap-5, -0x1.8c8cecf15cbb1p-3, 0x1.0657de236d6dbp-5, -0x1.0af1ade9b5d2dp-11, -0x1.59cdc71b97fffp-3, -0x1.6164353be0a80p-5, 0x1.88292de91bb96p-4, -0x1.fb66e71dd9302p-4, 0x1.08cbe0c61de34p-3, 0x1.84f4a253a8195p-5, -0x1.7630e875b5518p-6, -0x1.d260c830240bap-7, 0x1.53f02a114e264p-4, -0x1.252648ce8b322p-3, 0x1.a1f2b3189f83fp-3, -0x1.4d2d383ba52fep-4, -0x1.3975c39a24b39p-4, 0x1.f406d2c4ae052p-4, 0x1.439afde19b295p-4, 0x1.0f70b235c3c5fp-3, 0x1.ac6f10a72c324p-4, 0x1.3457f28e83708p-5, -0x1.05674a0580d3ap-3, -0x1.8359b75f8d09cp-5, 0x1.451f808840719p-6, -0x1.c26e47467d7d2p-10, -0x1.a468f0a07f7cdp-3, 0x1.abc9d6e383cf8p-4, 0x1.6289b8cf1b83ap-3, 0x1.2bd8c11d4a421p-3, -0x1.a0ea514c3819dp-4, 0x1.6524dc4395141p-5, -0x1.b381be26a39c7p-3, 0x1.5a1d9f8792325p-3, -0x1.8d496b249cc84p-3, 0x1.5049ed692d95bp-5, 0x1.dc3150e29bb08p-4, 0x1.087672e25e8a4p-3, 0x1.19c7d864bc9a9p-5, -0x1.23f91f0d29d49p-3, -0x1.4b88681d151f8p-7, -0x1.b79cecc9d62dfp-6, 0x1.2dc283c41fb49p-5, 0x1.9494ac5cf6fb5p-4, 0x1.0f2c049d01af2p-4, 0x1.b281cf67dfcc2p-3, 0x1.0ec434c5fd087p-4, -0x1.3e84f10750ac0p-5, 0x1.4dd1df37bdca3p-3, -0x1.01a950e85b54fp-5, 0x1.cdce200980bf8p-6, 0x1.282fc20a0ce5cp-6, -0x1.d5a75e44e2205p-3, 0x1.c58ab42bc29f2p-6, 0x1.da37ea5c6bd1dp-6, -0x1.5794acd2a3730p-6, -0x1.cef81ae78a130p-7, -0x1.070bbbdfa2b5bp-3, 0x1.0e373cba9d090p-7, 0x1.33cc9469efcc5p-3, -0x1.22703eedf8fdfp-6, -0x1.abb9b4d67eeedp-5, -0x1.f1d9fc99bd537p-5, 0x1.9d197f9f0eac0p-3, -0x1.158dca32466fbp-3, 0x1.5a17679bf599ep-4, 0x1.6d12fef983b24p-7, 0x1.89664b5e336dep-3, 0x1.0c8c128f4211fp-3, -0x1.216687a85f70fp-7, -0x1.3bb159d4f5a10p-3, 0x1.24ca4d2987753p-3, 0x1.2a9b7ad6f01c1p-3, -0x1.c4915f12c9815p-4, 0x1.313f655d68581p-4, -0x1.47fe755e87f26p-4, -0x1.3ded73e217d80p-4, -0x1.49965f1464b53p-3, 0x1.7e1e3403cd9d1p-4, 0x1.bc378113eb805p-6, 0x1.95181c2412e2fp-5, 0x1.29778499336c5p-3, 0x1.11de5febf3432p-4, 0x1.dedfb209d39d2p-5, 0x1.32e70f8a2432dp-4, -0x1.b40c72d82acd0p-4, -0x1.c3bdcd349057dp-9, -0x1.ee15b10c3454fp-4, -0x1.709aba9ee2c9cp-4, -0x1.2cdd438eb80e6p-7, 0x1.b2f2fcb35716ap-4, 0x1.a585b0de4abc2p-3, -0x1.bc7ec027255bcp-4, 0x1.1bfc0bbdd5ce3p-6, -0x1.d0b7f871ee8a2p-8, 0x1.afe952f1e565dp-5, 0x1.dd1c3477a1282p-5, 0x1.28e53a19b191ap-5, -0x1.8c27cf9ed51a9p-4, 0x1.43516f6d2cf18p-5, 0x1.6d7f3cd006a34p-4, -0x1.a491dc715b4b8p-5, 0x1.9520d02a5522cp-3, -0x1.80e1bad8b6462p-6, -0x1.03a10f1f9f46ep-4, 0x1.e59660edf6faap-6, -0x1.a608dc411b912p-6, -0x1.17ff3ae3a6928p-3, -0x1.56d79c8973a02p-9, 0x1.46ccc39e3eac8p-3, 0x1.9a1e5dca11db2p-3, -0x1.d085369a82084p-5, 0x1.72ccec1a772d8p-4, 0x1.b245c3b7b05a4p-7, 0x1.d11eaec0d23c5p-6, 0x1.038ec07a1daaap-3, 0x1.5d022cec91122p-4, 0x1.f9ad58f0a63b2p-7, -0x1.7c69e59562df8p-4, -0x1.cc61eef95e92cp-4, -0x1.a38c911281c9cp-8, 0x1.091aa239a9fbbp-5, 0x1.9c32cb44dc7fdp-5, 0x1.404b6dfec19e4p-4, 0x1.913cf212efecfp-4, -0x1.ec266d71df5a8p-3, 0x1.720c95c6cca44p-4, -0x1.ad08dc277d728p-4, 0x1.c8528e9688345p-4, 0x1.13c76ebc77a97p-5, 0x1.0246fd38e8419p-4, -0x1.bb2059f9ec350p-5, 0x1.cf188e89348b5p-6, -0x1.7e67b70287668p-3, 0x1.c09cee7fae67fp-4, -0x1.0f05e988add57p-5, -0x1.091f2fbd34a5bp-2, 0x1.b2c89e2d22177p-4, 0x1.57673bff02e07p-3, -0x1.66dcd6a0065b7p-4, 0x1.f0b9d91e6cda5p-4, -0x1.33198ea40a6cep-4, -0x1.d02ef4f10428ap-3, -0x1.252f7de80ba8bp-5, 0x1.0b2bc57119175p-5, 0x1.b59ecea6aced8p-7, 0x1.5378424027ca8p-7, 0x1.e5a8c1ff34ddap-6 }; +pub const outputs = [_]f64{ -0x1.33f9b6821d680p-1, 0x1.a5d00680e9c58p-1, -0x1.cea7db297417fp-3, 0x1.4f2eeffa548b3p-4, -0x1.9fff57e3561ecp-3, 0x1.c8c234983b835p-1, -0x1.e2cceea59ad2cp-2, 0x1.484c269bf522ep-4, -0x1.9fdbbd60d6226p-2, 0x1.bb7211db87002p-1, -0x1.4ff3a83d32c9cp-2, 0x1.7f38d809cc3e9p-3, -0x1.09c4357734666p-1, 0x1.6cf80f2895724p-1, -0x1.7a79518d0e3e4p-2, 0x1.fe7c7ebeead70p-8, -0x1.3be4da18f5d84p-1, 0x1.cb858d6dcad99p-1, -0x1.c2e05504d5faep-2, 0x1.b0094551eaec2p-4, -0x1.7b2396f788c50p-1, 0x1.7f6501f8cfe6fp-1, -0x1.984d1f733a4aep-1, 0x1.ad43d71d09b58p-4, -0x1.6a6e7d87255b6p-2, 0x1.0d3f125b0b0bap+0, -0x1.98ad7e9c5e18cp-2, 0x1.15ef0068c584ep-3, -0x1.c37f754486157p-1, 0x1.e38d9af7f3f12p-2, -0x1.1c0325448e34dp-2, 0x1.826c0db0d477cp-4 }; +pub const states = [_]f64{ -0x1.cd3646b29ba2dp-2, 0x1.1e6edaa1e4d2ep-4, 0x1.4933b69ff0031p-1, -0x1.0fa49b1c5dd11p-1, 0x1.37611f1e2a141p-1, 0x1.4ca2d660e7e62p-3, -0x1.a2eba2adba582p-4, -0x1.adfded3726516p-3, 0x1.1433252e41a0bp-3, -0x1.13a30de510833p-2, -0x1.5710f5f441ff8p-4, 0x1.c9c3fd4379c50p-2, -0x1.47e42c5b455eap-1, -0x1.f67487a778574p-1, -0x1.0182b7fd12921p-3, 0x1.024ecb9288170p-2, 0x1.318875b74fc6ep-1, 0x1.8e58462c55521p-3, 0x1.f55717b8cbb26p-4, 0x1.31bc8ea8071e9p-1, -0x1.54e3697bd81ebp-1, 0x1.d9b914549a139p-4, 0x1.46df1243a8d86p-3, -0x1.2d19729813ba8p-2, 0x1.d5bb9f34c791ap-1, -0x1.3b3c693a5daa8p-2, 0x1.a7e642371da96p-3, -0x1.dcd5eba755d76p-3, -0x1.31fec5b34c8a9p-1, 0x1.0e068d5d43724p-4, -0x1.970de53006cbbp-3, 0x1.0c6eed5bf9575p-3, 0x1.b6dad14642c54p-4, 0x1.d6ac7fbef1c08p-4, 0x1.1b02fa2be06abp-2, -0x1.47fddadbc664ep-2, -0x1.0e5a6df532a3ep-1, -0x1.3d3a0b05b25e4p-1, 0x1.aa5011df35824p-6, -0x1.75c537c0278e6p-3, 0x1.92e5b461ee618p-2, 0x1.684a77c0cc17fp-1, -0x1.f7a534517321cp-1, 0x1.0f725ceb6caeap-4, 0x1.9bcc3a69edc06p-5, 0x1.ae3cbcbac5257p-4, 0x1.4004d91dfd7b6p-2, 0x1.13788fd8e530ep-2, 0x1.6246538cbee5ap-2, 0x1.eedb5e4943d93p-5, 0x1.a656ce22f0fb9p-2, 0x1.3bd4eee61e076p-4, -0x1.fb0726b36639fp-3, 0x1.78f73258a032cp-2, -0x1.2b3bdfff8455ap-1, 0x1.2a29c18392568p-9, -0x1.a67ffa182617ap-7, -0x1.024ba5151b164p-1, 0x1.5075f738c8282p-1, 0x1.dbd505d1d3ff1p-2, 0x1.3fe506955cd99p-5, 0x1.6d5fcdf18cb5ap-1, 0x1.084b105e76ce6p-2, 0x1.91ddfda595ad2p-3, 0x1.2c075d45634a2p-6, 0x1.7d5eb696afadap-2, -0x1.d3a224c3f9740p-5, -0x1.26e65f579cb73p-1, 0x1.6b7f5b422b13fp-1, -0x1.12fc2cbfec510p-1, -0x1.24547f6e8adb6p-3, 0x1.17ee647b881aep-4, -0x1.a96df0c2078a8p-6, -0x1.18e11a96e3dd8p-1, 0x1.86459a977cf5ap-3, 0x1.846b2dd972107p-4, 0x1.371336e3ca455p-1, 0x1.a8ed39fcfe18dp-3, 0x1.0d59162802622p-4, -0x1.6306a8ba95e1ap-4, 0x1.82671bd860b57p-1, 0x1.1bface77b5eadp-1, -0x1.3367774e51624p-4, 0x1.f70ebad98f77ep-4, 0x1.63a9de052716cp-3, 0x1.4e421f52ae279p-1, -0x1.2b0042b2ec2ddp-3, 0x1.729e00a4db10cp-7, -0x1.0c34fcc5beaadp-2, 0x1.00cdcf4da53c1p-2, -0x1.c87fdacf16ee8p-3, -0x1.e6c0e2fead5c2p-2, -0x1.c9d19e936fabep-2, -0x1.867b77c22f128p-9, 0x1.4e8711aedd788p-1, -0x1.e3d3d01358ee1p-1, 0x1.57d8bb889e12fp-1, 0x1.ca79daeb1a556p-3, -0x1.56797545aa55bp-5, -0x1.d21a13e65ced8p-7, 0x1.ecada09d9b0eap-6, 0x1.f9d3129fa41a5p-9, -0x1.d5a1959e23beep-4, -0x1.e5ff40a3779a1p-5, 0x1.beafc4649a999p-2, 0x1.167f550f371f4p-2, -0x1.cfe449b0782c4p-4, 0x1.282a3de0f33e8p-2, -0x1.a997bc22f6e8cp-2, 0x1.f8e232412a12dp-4, 0x1.582875c21d403p-4, -0x1.2da0501f7a7cbp-2, 0x1.7ca0ccdc76364p-2, 0x1.7ba0ed8c2c127p-4, 0x1.e9616ec3bea8ap-2, -0x1.ff9fe651f3783p-1, 0x1.33cf934137aa2p-1, 0x1.945a5c476ecf2p-3, -0x1.662940583d528p-1, -0x1.ffef91a886f8bp-1, -0x1.034bb56ddb3f4p-2, 0x1.9df08579c33b7p-1, -0x1.93057c831a0a2p-3, 0x1.3c8cf1eeef0a3p-3, -0x1.9fb1425477efep-1, -0x1.ac3a7e7e9a216p-2, 0x1.82f16f4972190p-5, 0x1.d88f7d9ce996ep-5, -0x1.a1efe163d7fb9p-2, -0x1.1815ca6073c16p-5, 0x1.37b5941d961fdp-1, -0x1.13899020c9112p-1, 0x1.6d01d50d7f50ep-1, 0x1.90293071809d8p-3, -0x1.19419437d9115p-2, -0x1.48a5e11571440p-4, 0x1.ec1547eb848d8p-3, -0x1.688a3d51e50bcp-2, -0x1.7ddf6cb8bd7e3p-4, 0x1.79cee76b0d3a1p-2, -0x1.56ddbe8a662cep-1, -0x1.f527742170bf5p-1, -0x1.5b252f097cab6p-4, 0x1.ee98e1b00c596p-3, 0x1.170e42f753e8bp-1, 0x1.8c5cb7f1991d8p-2, 0x1.68026d6e4349fp-4, 0x1.30d09d476ab3dp-1, -0x1.5b1aaa2b3e0ddp-1, 0x1.a8ece14849685p-4, 0x1.8cdc586d1ac0bp-4, -0x1.8d2b00b6f9677p-2, 0x1.ca2bd71b09cbbp-1, -0x1.317644a18fe1ep-2, 0x1.701fb3cf5125ap-3, -0x1.3adbf1b853d2ap-3, -0x1.2824a7cf5e400p-1, -0x1.47db076def74ep-4, 0x1.1eb2434a7ca00p-12, 0x1.af169f6283eb1p-4, 0x1.16276195b69dep-3, -0x1.119c5bae56dd6p-3, 0x1.394a974d07ca7p-3, -0x1.6d483241e88dfp-2, -0x1.152edc6b2c60cp-1, -0x1.36ce00927d80cp-1, -0x1.04a0f019dbc9fp-3, -0x1.4b2fa7af7c60cp-3, 0x1.7edec64ab39c0p-2, 0x1.68c17630ec25ep-1, -0x1.f7965648fcea3p-1, 0x1.e587c548634e9p-4, -0x1.2ca6aba13b062p-2, 0x1.3d4caea05824fp-6, 0x1.31419b1c46fd9p-2, 0x1.10fa8a4463da4p-2, 0x1.17249a54b04f3p-2, 0x1.cc267472f1d66p-3, 0x1.eb344675f916dp-2, -0x1.3041525c68548p-3, 0x1.0ea0d8c32390ap-5, 0x1.d134be3a71b6dp-3, -0x1.288141aa0353fp-1, 0x1.9ddf1783fb4a5p-6, -0x1.157ea3d15af1cp-5, -0x1.b8bd397b23f95p-2, 0x1.418645c340577p-1, 0x1.f92377d1afbb9p-2, 0x1.a6a5a8cdaeef2p-4, 0x1.87f5a119f765ap-1, 0x1.fbf05c79a1876p-3, -0x1.333a09f8255c6p-3, -0x1.1357d7523ef6ap-5, 0x1.2b4198cf4ce23p-2, -0x1.2b427f430f26fp-4, -0x1.457e3862c731bp-1, 0x1.778e552424961p-1, -0x1.3c2ef388acff1p-1, -0x1.cde74cd3d432dp-6, 0x1.8fac3928289b0p-9, 0x1.1ea2b1bf50138p-3, -0x1.113cacfcae338p-1, 0x1.85912ad0f0615p-2, 0x1.d31fffb76b5b2p-4, 0x1.24916a62ca36cp-1, 0x1.0dc3f0cdf653cp-4, 0x1.6a821e88db4dap-5, -0x1.400cab1beb389p-3, 0x1.6b080e5df4644p-1, 0x1.3233fc2efd7bfp-1, 0x1.684f4d87d46a2p-5, 0x1.edadc02cd7f34p-6, 0x1.2341c09eb1b03p-3, 0x1.57f2b4bb631c8p-1, -0x1.f7f8bafa83d2ep-4, -0x1.008a06e001d0ep-4, -0x1.280de668c4d82p-2, 0x1.4b964f741bddcp-2, -0x1.e048470def38fp-3, -0x1.0252c4ff3e6ffp-1, -0x1.9ba60ed41b49ep-2, -0x1.e14efbd25ca9cp-5, 0x1.505d4560095b6p-1, -0x1.e1066388a900cp-1, 0x1.582f8575bf5d7p-1, 0x1.4c4e1526f5e33p-3, 0x1.4749a1e7e8b8ep-5, 0x1.d2db6fa34898cp-5, -0x1.a9a9d8f8f25afp-4, -0x1.b4d0fe13740bcp-5, 0x1.2330abb433729p-3, -0x1.5ae1f0ba54f00p-5, 0x1.41f0c5d8178c2p-2, 0x1.de0052d25087cp-3, -0x1.4949a295ff340p-4, 0x1.4dc5614ea6806p-3, -0x1.b546a16363d7fp-2, 0x1.59dc57a479ba2p-3, -0x1.4a77dc3ac5aa1p-4, -0x1.0ae09b515d0aep-2, 0x1.ff9c0d62226d4p-3, -0x1.63c1385f060b4p-4, 0x1.a8b8454a2ab2dp-2, -0x1.ffa86d4aa1dd5p-1, 0x1.27d1eda4e8045p-1, 0x1.ad33f7d8020e0p-3, -0x1.75766f1d02cc3p-1, -0x1.ffe84d0162ba1p-1, -0x1.5f43ca597905cp-2, 0x1.9ecd6ee897e67p-1, 0x1.6b44813b48db0p-4, 0x1.d8bae55f8967dp-4, -0x1.94b6edf853d2fp-1, -0x1.d4e5cd18ca891p-2, -0x1.e63d2841f6938p-10, -0x1.c061b8c044dc8p-5, -0x1.8ef5afe55a0f2p-2, -0x1.1abefa4d36290p-5, 0x1.3465446aa6740p-1, -0x1.154fa85834e8dp-1, 0x1.6dafdd3f933b6p-1, 0x1.0960db2bfbf54p-3, -0x1.93101a2c1389cp-3, -0x1.f6c10502322d2p-3, 0x1.b2c187b20e7f5p-3, -0x1.34a3aa2f7f9bdp-2, -0x1.c8c6fcb62570ep-5, 0x1.b113a54794df3p-2, -0x1.5225e10666090p-1, -0x1.f16f8743f1b7cp-1, -0x1.0ece2fdfe0a67p-3, 0x1.fe029dd4a758ep-3, 0x1.2544e1a8672afp-1, 0x1.1eedc86df7169p-2, 0x1.0222c0b64c080p-3, 0x1.3adfd772ed96dp-1, -0x1.420220b38df6cp-1, 0x1.314ffbeb5b89ap-3, 0x1.c9e01df1a9b46p-4, -0x1.6cb608e40bd0dp-2, 0x1.ce97e114734e7p-1, -0x1.920e81f9b2392p-3, 0x1.e1b389bdf1cd0p-3, -0x1.6edb61b8c358cp-4, -0x1.29df7172a04cdp-1, -0x1.de36a75f4cf92p-8, -0x1.aae40543445aap-3, -0x1.4dd0b7dc365d7p-4, 0x1.df62ad3d5e5cdp-4, 0x1.6377e39a52165p-4, 0x1.8b7602467a2ccp-3, -0x1.0f08601c9d6c8p-2, -0x1.20842a09120c2p-1, -0x1.4bc101f3307e2p-1, -0x1.a8c50006c001ap-4, -0x1.34738756dfb39p-3, 0x1.8bd81b114b73fp-2, 0x1.6e9858cc765afp-1, -0x1.f78acb59cf444p-1, 0x1.1b189ace66ea7p-3, -0x1.e7d9cf3bc7fe7p-6, -0x1.9772e39691350p-6, 0x1.d2ece545db19dp-3, 0x1.0a7fc6766c794p-2, 0x1.2a8625bee69cfp-2, 0x1.20cb41089fe6ep-3, 0x1.8de6bdba0d033p-2, 0x1.90bfe24b65ee3p-5, -0x1.280859280c663p-4, 0x1.142625876dbb8p-2, -0x1.47a508f31ab71p-1, 0x1.b3ab82c97d1bcp-6, 0x1.9d6775b1716f7p-5, -0x1.eb7501bcd9c6fp-2, 0x1.3c76eee4e0413p-1, 0x1.d193a8ddf964dp-2, -0x1.5bfbd9ac12e01p-5, 0x1.8221b6e16534dp-1, 0x1.d2de7e87bbbe2p-4, 0x1.5ff86026615c2p-4, 0x1.a59ce9d635f3fp-5, 0x1.57ea1aafbae91p-2, -0x1.0ab9d1383f11ep-3, -0x1.3e14991c9b10ap-1, 0x1.6582de7153253p-1, -0x1.10dc65a3bb1acp-1, 0x1.c48a09b4275cap-4, -0x1.6d585d1520324p-4, 0x1.124aeb7a0c688p-8, -0x1.97b5812cdfd84p-2, 0x1.f3b91d40abc1ep-3, 0x1.a345206ee26f6p-5, 0x1.26a10c2576665p-1, 0x1.060485af8f57cp-3, -0x1.2001ff4acaf2ep-4, -0x1.267d96b2be122p-6, 0x1.7209aa5ecef81p-1, 0x1.30528726dbb68p-1, 0x1.f1bac4a38dd53p-4, 0x1.69099fa7256fap-5, 0x1.290381b5136acp-3, 0x1.437ccdbbe3955p-1, -0x1.2b272976bbe67p-3, -0x1.00e64c00ceb0ep-6, -0x1.8a71fccbb1f56p-2, 0x1.301a8136795cbp-2, -0x1.9ada0494c9f11p-3, -0x1.f7f570471ddedp-2, -0x1.a2c71aa9a0874p-2, -0x1.8bb07a8be1072p-5, 0x1.316ef24535f34p-1, -0x1.e122b45be3d6ap-1, 0x1.50ca1cfa14277p-1, 0x1.49fe93cc0f259p-3, -0x1.a8ac47296ff14p-4, 0x1.1c10cebb98d07p-9, 0x1.2ec67c9f79bbap-4, 0x1.33cf31e7641a1p-4, 0x1.6af966c95dd59p-3, 0x1.3b58a73ac54d4p-8, 0x1.255292e221b72p-2, 0x1.34b3126d55d2ep-2, -0x1.fe416cfa6edbcp-7, 0x1.197c840092433p-2, -0x1.c7fe26af1cd50p-2, 0x1.10f6842231d4fp-2, 0x1.0a27d3535ce44p-3, -0x1.0e16f8399f59cp-2, 0x1.bc2a1aa8253a1p-4, 0x1.3b27bc2ac08ebp-5, 0x1.81d56f9b0b84bp-2, -0x1.ffae8a848cce0p-1, 0x1.1a5a37b4fa1ffp-1, 0x1.b2c545542cd59p-3, -0x1.70435d6463375p-1, -0x1.ffe7d00c6670ap-1, -0x1.e5ffa57d24a74p-3, 0x1.9adfa4bba2e64p-1, -0x1.c08139661c942p-8, 0x1.8428a5a3c4154p-3, -0x1.82a0c026d1f0bp-1, -0x1.3caee9b939bc0p-2, 0x1.d008b26fb9d42p-5, -0x1.dac185af237b3p-5, -0x1.007fbf5f7892bp-1, -0x1.5d7d7144224f2p-5, 0x1.3672a7e5ff902p-1, -0x1.1f25487ce21bep-1, 0x1.46c68215c9c38p-1, 0x1.342ae16007eb6p-3, -0x1.f59465782b55ap-3, -0x1.cfd849dc6f816p-3, 0x1.e17beb2cb8100p-4, -0x1.2c1447daa361cp-2, -0x1.7fdd7676cce80p-4, 0x1.e50a815e2995fp-2, -0x1.41e989ea7d2fdp-1, -0x1.f28e2d2d036d7p-1, -0x1.198e437bef47dp-4, 0x1.c9580da05d0c6p-3, 0x1.165da80e85be2p-1, 0x1.8d12db5d9b8e3p-2, 0x1.71c4b9a12a822p-4, 0x1.2a18cdb69e450p-1, -0x1.452db99c77656p-1, 0x1.3eaa48ecd1524p-3, 0x1.52b8e78f8c1b4p-4, -0x1.a17b4eb1319c8p-2, 0x1.df41e32b8e383p-1, -0x1.2faba394bb6d2p-2, 0x1.0007a3339dc84p-2, -0x1.2f18dc6c20830p-4, -0x1.2436c008d28dbp-1, 0x1.2f1caef938066p-6, -0x1.a1bf093e3ce94p-3, -0x1.3be8b54601ddep-8, 0x1.fb389b6702794p-4, 0x1.86cf32cb8089ep-5, 0x1.7061dbe2f8919p-3, -0x1.506ce90cca93bp-2, -0x1.0dddaf62826d8p-1, -0x1.4c6022d163d33p-1, 0x1.773867fab323bp-7, -0x1.3df97126ae704p-2, 0x1.8c132f20b8cf9p-2, 0x1.786ea2f2e25b3p-1, -0x1.f6a69bbb2d2c3p-1, 0x1.0611bd9c1b5ecp-4, 0x1.1754216349066p-3, 0x1.209dd532937d6p-4, 0x1.8653695ae70bap-2, 0x1.32383d2c70049p-2, 0x1.6769bd6586cc6p-2, 0x1.e485c38a0c17dp-4, 0x1.ceaf5bcaac975p-2, 0x1.37120a62c4ce8p-6, -0x1.64bb86e205d2ap-4, 0x1.542ba7f926287p-2, -0x1.0159bf33a80d3p-1, -0x1.3d35e35a9a93dp-3, -0x1.4b8b38cce8595p-4, -0x1.aeb947614f632p-2, 0x1.51539533757a3p-1, 0x1.f9f7c83577f5cp-2, 0x1.2e816440feec8p-5, 0x1.70f320ce70051p-1, 0x1.27579d3aae8f4p-3, 0x1.53bb7780ddea5p-3, -0x1.c1f0b9ce7b384p-5, 0x1.ee0fd2d551feep-3, -0x1.573615c0f18d6p-3, -0x1.298c3863bd390p-1, 0x1.65661c48a2483p-1, -0x1.10b940f144a27p-1, -0x1.46ccde508d57fp-8, 0x1.9cee56d0966b4p-4, -0x1.21874f0d32d42p-4, -0x1.2a53aeb83b653p-1, 0x1.3e3a2a107d153p-2, 0x1.55bef85677aedp-4, 0x1.53e330858427dp-1, 0x1.4bb1ad441d992p-4, 0x1.49617e067bfa3p-3, 0x1.71e79dc1e4b56p-5, 0x1.7856dd6198230p-1, 0x1.1bceb43ff5717p-1, 0x1.0808dfa0530c8p-4, -0x1.7e2d8040a5105p-3, 0x1.2aab6cf430c9fp-4, 0x1.5c10cdcf09c16p-1, -0x1.540c20d90f162p-3, -0x1.11151aecfb4b8p-4, -0x1.25088967ada87p-2, 0x1.a7a48883c1858p-2, -0x1.7ed2be087f7f9p-3, -0x1.02f6966242e8dp-1, -0x1.b292ad8893407p-2, -0x1.1f7134a4a72c8p-6, 0x1.32224f2a64883p-1, -0x1.e486e8c9684d2p-1, 0x1.6148c9b20302cp-1, 0x1.ed048767d72fep-4, -0x1.ce677458bee2cp-6, -0x1.de84700cb8e9fp-4, -0x1.7b3f9e5ce7025p-7, -0x1.ae6dac264467cp-5, -0x1.93437a11052c8p-6, -0x1.b901dfcfe5b1fp-7, 0x1.b3044767a8bb3p-2, 0x1.053006d31d70dp-2, -0x1.d697da7875e94p-4, 0x1.4ac3da2e6ae7ap-3, -0x1.949e6117d9a9fp-2, 0x1.5de3f8f539a08p-3, 0x1.e94b51568901ep-4, -0x1.2ae7570e2b995p-2, 0x1.2c9738c4f9604p-2, 0x1.21b377260e1e9p-5, 0x1.b093cd04b20c1p-2, -0x1.ffa8aa4d9f502p-1, 0x1.3313fb34d26d5p-1, 0x1.7285b04e75a8bp-3, -0x1.72c1f31325e83p-1, -0x1.fff007a1c5e0cp-1, -0x1.1e434381ec94fp-2, 0x1.9bd45ea833fc5p-1, -0x1.036c0b3bce273p-6, 0x1.010286e8882a1p-3, -0x1.b12ee2b4946c0p-1, -0x1.6d53cec96b18cp-2, -0x1.08fd8cacc19b7p-3, 0x1.039d7fdc2497bp-5, -0x1.dec6a1cc2a1dep-2, 0x1.8cbfd7325cf24p-6, 0x1.4341e86bf1b74p-1, -0x1.20b5586e435fep-1, 0x1.3a0553a6dbbd9p-1, 0x1.191d2f578e9dcp-3, -0x1.1d6bab0806badp-2, -0x1.a7455dcbfe22ep-3, 0x1.00e8594b9120ap-3, -0x1.250f8c392f13ap-2, -0x1.793de808edeefp-4, 0x1.9dd0dc2c824cep-2, -0x1.516b22ab152cep-1, -0x1.f476e20d243e1p-1, -0x1.0e20d7004b32ep-3, 0x1.e7d42bc9b1f69p-3, 0x1.f2efeb1bb9c40p-2, 0x1.4364c825dd328p-2, 0x1.9b0d2c6b4918ep-4, 0x1.1b5b72f6fb82ep-1, -0x1.3d5e26706788cp-1, 0x1.4eef5fef49750p-3, 0x1.6a676153bce97p-3, -0x1.c1ff2a4e5cfc3p-2, 0x1.d44faa3028398p-1, -0x1.34cc10c9aee62p-2, 0x1.1a104e5dc088fp-2, -0x1.ad4385a541bbcp-4, -0x1.2c97ff19c580ap-1, -0x1.f90825c1eaa02p-4, -0x1.cd1524479206cp-3, -0x1.66cbdce7bf9dep-4, 0x1.b65e4b0bfbb0cp-4, -0x1.1cfd40b9cfe00p-10, 0x1.ac996b6d7f5c4p-3, -0x1.105ce17658251p-2, -0x1.2106c3437a208p-1, -0x1.463f8ab2e43c7p-1, 0x1.46977109ef24dp-6, -0x1.43f66e4103f57p-3, 0x1.95303b1bff54fp-2, 0x1.72b429a1c8730p-1, -0x1.f7a6835455b45p-1, 0x1.20c85d61c4547p-3, -0x1.a280f9b8a95a1p-8, 0x1.a6fb77f9d0082p-7, 0x1.d351f64beb8aep-3, 0x1.181ba9148f2cdp-2, 0x1.3c08b4ba82647p-2, 0x1.d94ec5ca3e3d6p-4, 0x1.a1dd099628fc9p-2, 0x1.2861db1ec0c19p-5, -0x1.c7213eb5933fcp-4, 0x1.72ec338cde0e2p-2, -0x1.0a57cc30d75d5p-1, 0x1.621b6df57dd58p-5, 0x1.bb7b9b04def17p-3, -0x1.afb6f1e9d715dp-2, 0x1.573f9a2cf22cdp-1, 0x1.cfee75c78e3edp-2, 0x1.33e85a8905161p-5, 0x1.671d1f85bf560p-1, 0x1.7b360f1e111f5p-3, 0x1.4c1e762582d78p-3, -0x1.0f819df520aeep-4, 0x1.38013d6328699p-2, -0x1.fa451c10e5428p-7, -0x1.28132dae5e68fp-1, 0x1.5eda02929c682p-1, -0x1.2cdc5ebbf3e78p-1, -0x1.9f38d718f8ac4p-5, 0x1.bec01dfcfc5a8p-5, 0x1.9a5b1462ae013p-5, -0x1.d8cc53da64945p-2, 0x1.691642b97de54p-2, 0x1.5858ae8941efbp-3, 0x1.264c88ca91649p-1, 0x1.0b65a305c2f88p-4, 0x1.91d9480325a76p-5, -0x1.a1d9d4525fc65p-4, 0x1.6cd020300bb68p-1, 0x1.14626231ec0f7p-1, 0x1.7711b9246aac2p-4, -0x1.5c5acf5b958e1p-5, 0x1.58931a2b96d07p-4, 0x1.4340c9305af7ap-1, -0x1.762fa713ccf64p-4, -0x1.497b31b11c8d8p-4, -0x1.22f9c1c72026cp-2, 0x1.b159c19db36a4p-3, -0x1.29d8fc24202afp-3, -0x1.e5af16591f88ep-2, -0x1.9c8796bec8ef9p-2, -0x1.705a0186149d2p-5, 0x1.484cf9485a9e2p-1, -0x1.e68b8db324b4bp-1, 0x1.697c4bcc476e2p-1, 0x1.0246c240d8453p-2, -0x1.59b1f391ed967p-4, 0x1.25542b35ccb30p-4, -0x1.f2efb0e2bc3abp-4, -0x1.889b011907f04p-5, -0x1.79ba6518875d2p-3, -0x1.ed1afaafdfd48p-6, 0x1.8e94285d5e9dbp-2, 0x1.0f70e53957060p-2, 0x1.e7bfaf57007c0p-8, 0x1.11e57bb25d94dp-2, -0x1.b460bc8a9bdf3p-2, 0x1.b636630b93df6p-3, 0x1.c3fe37bba7f1bp-4, -0x1.3c611c7370425p-2, 0x1.4da1d88ba1548p-2, -0x1.b4446af003758p-4, 0x1.c994126b7c721p-2, -0x1.ff90011c83accp-1, 0x1.1f47c466881c1p-1, 0x1.b5c93d7c21616p-3, -0x1.6865e5e960b8cp-1, -0x1.ffefa3585d461p-1, -0x1.ba6f0a883d386p-3, 0x1.9557abe66853ap-1, -0x1.0243496ef7e56p-4, 0x1.3bcf8d8f75ca7p-3, -0x1.9479bec2efd4cp-1, -0x1.5bea582bf3306p-2, -0x1.a383360447932p-4, 0x1.ee43d954bfdadp-6, -0x1.c63b169705f7bp-2, 0x1.1d12449257b08p-7, 0x1.3aa8ea7f11164p-1, -0x1.1e295ceacb712p-1, 0x1.5f8c5de3e489dp-1, 0x1.c991624590f1bp-4, -0x1.79a40e0b679c4p-2, -0x1.b6ff62729c186p-3, 0x1.dda90a9926156p-4, -0x1.192d97d811ab3p-2, -0x1.a75a1afdbfea0p-4, 0x1.2f8a4d6cac62dp-2, -0x1.4f5d9d6e019a4p-1, -0x1.f5595872b148ap-1, -0x1.851e45663fcdcp-4, 0x1.fc14e4ad63463p-3, 0x1.067e605975e25p-1, 0x1.4f98f0577f364p-2, 0x1.50c8f0c8d947ap-4, 0x1.4ca8f10ae90cfp-1, -0x1.555ac8f768a58p-1, 0x1.745a3257a2748p-4, 0x1.19720e23d47afp-3, -0x1.c676360a91da3p-2, 0x1.da94c6f94ee39p-1, -0x1.25a175eff678fp-2, 0x1.00f899a9fac9cp-2, -0x1.b3dfb0c13bd34p-4, -0x1.2c1b51085a3d4p-1, -0x1.24cb8fca8283fp-5, -0x1.29181fa7c156ap-2, 0x1.621be2029872ap-6, 0x1.049f88a4d1ea7p-3, 0x1.2d2132501f838p-4, 0x1.0da37b3ab4f03p-2, -0x1.3d9d7931a6febp-2, -0x1.19c5cef67d512p-1, -0x1.511786395c89cp-1, -0x1.aa4b5943346c5p-4, -0x1.01234711988d3p-2, 0x1.8252f757a0d79p-2, 0x1.73ef41f9eb742p-1, -0x1.f685906f9df01p-1, 0x1.2c63a5f46a721p-3, -0x1.e3184cd90cf4dp-4, 0x1.f4de062af92e3p-5, 0x1.1ba95738d8fa2p-2, 0x1.3a747f0d87b23p-2, 0x1.3f66505a8e165p-2, 0x1.d013004e1d328p-3, 0x1.f25ff86c2cd2dp-2, -0x1.2589836e5d312p-6, 0x1.5f3d93d6dd052p-4, 0x1.c9c048b1d897dp-3, -0x1.1d8e6f6addb14p-1, -0x1.a1856e212376bp-5, -0x1.7f4bb0a7ba6fap-4, -0x1.af66d0a149fa6p-2, 0x1.5ad45e80439aap-1, 0x1.a9500ea95c9c7p-2, 0x1.a577a03a95e01p-5, 0x1.7c0acbb6a5727p-1, 0x1.14bb7d0f48d1bp-4, 0x1.db3d16b63b75bp-3, 0x1.0343672e989ccp-5, 0x1.e2cdb23008459p-3, -0x1.b956252875ab1p-4, -0x1.283e9fac13842p-1, 0x1.5fb4792ac410ap-1, -0x1.2cff00d5d58b2p-1, 0x1.9e786de460d96p-4, 0x1.79e1190fb091dp-5, 0x1.7759a9fd1fa28p-3, -0x1.0ac0543030086p-1, 0x1.395d970bef4d9p-2, 0x1.0c79f01510831p-2, 0x1.14596b9008d60p-1, 0x1.6e3c834546e70p-6, 0x1.9c7db3d7b8533p-4, -0x1.df6bf23bca0eep-5, 0x1.62ef73560ab9dp-1, 0x1.3f79c9a753c14p-1, 0x1.71f5afd2c1572p-3, -0x1.476f02795b4d2p-2, 0x1.074da2cf1f43fp-3, 0x1.46be040390e62p-1, -0x1.e52b923e1fac2p-4, -0x1.78da1b9d449bep-3, -0x1.297343d903c3ep-3, 0x1.277c129b51474p-2, -0x1.1832068b027e3p-2, -0x1.f1764094fd04ap-2, -0x1.ac0a85a903125p-2, -0x1.bc8a780afdd38p-5, 0x1.427463b2ca849p-1, -0x1.e474da819ed7dp-1, 0x1.6a5ad7420d154p-1, 0x1.00f504fb34b00p-2, -0x1.fda648df9fb8fp-3, 0x1.47044a7817ab1p-5, -0x1.1fa0b4534183cp-3, -0x1.a00ff96750d46p-5, 0x1.135201f25ae37p-3, -0x1.8b22541c29aeap-5, 0x1.4619d7457d0fep-2, 0x1.125924d770529p-2, -0x1.0805a3b64d526p-3, 0x1.d09fea1a10862p-3, -0x1.c10224d653430p-2, 0x1.390561a6dab96p-3, 0x1.9a9a622165bb8p-4, -0x1.7aa7332790d9fp-2, 0x1.fd2f401108590p-3, 0x1.b05ae35da21cdp-4, 0x1.d8316a4f6a32cp-2, -0x1.ff87e54ab703fp-1, 0x1.1ae18dbd35540p-1, 0x1.9cf558d938e8ap-3, -0x1.6646aefd51f03p-1, -0x1.ffeed57685c8dp-1, -0x1.9233c587a8411p-2, 0x1.96a30f7911a31p-1, 0x1.b0d1fc6473d74p-5, 0x1.72ddd5b94c3f6p-3, -0x1.9cb9e60d9843ep-1, -0x1.a6d8a41836140p-2, 0x1.35043485d3de6p-4, -0x1.2c94419432810p-6, -0x1.f7c43a9256e54p-2, 0x1.ee23c106884cep-5, 0x1.44214e088975bp-1, -0x1.0fb6f614f64dep-1, 0x1.733827285fb76p-1, 0x1.3975c4c5fbfc6p-3, -0x1.76425f7874891p-3, -0x1.42f850a3b6f17p-3, 0x1.44a5f6f793c16p-3, -0x1.34b3cbd2d0228p-2, -0x1.1c4be6afd9edcp-4, 0x1.4c448ff96e2dbp-2, -0x1.52cce1bf16aeep-1, -0x1.f5e00766b9352p-1, -0x1.3c3fe6680374dp-3, 0x1.c45c30d20a0e8p-3, 0x1.2a5cd393dc856p-1, 0x1.31bc3c64d332cp-2, 0x1.1ec058628439dp-3, 0x1.1c267b3c274aep-1, -0x1.4b9a737d14a1ep-1, 0x1.f32f91daafd6ap-4, 0x1.8c99c2b862770p-4, -0x1.5f25ac16dba72p-2, 0x1.d3260d14e03c2p-1, -0x1.8804313abca2bp-2, 0x1.c387e653b24f0p-3, -0x1.9180f3c96c84ap-4, -0x1.22deb4bb846b9p-1, -0x1.70fdff5470f08p-5, -0x1.72cf5e4b56c8ap-3, -0x1.1db58c773e3d1p-3, 0x1.c2c6f0a9325b9p-4, -0x1.09355ed0c65aap-3, 0x1.b95325801e3cep-3, -0x1.7262edf838fb6p-2, -0x1.0b03a01dfe242p-1, -0x1.280b10cc69486p-1, 0x1.c4fbb00030718p-6, -0x1.2c75d9e6b7826p-2, 0x1.9107289086383p-2, 0x1.6bd9cf4b2c032p-1, -0x1.f66c6c90763c2p-1, 0x1.88a4839a6e4bbp-4, -0x1.03cd0f58b0488p-3, -0x1.034dce8590d28p-3, 0x1.5327e5a961c46p-2, 0x1.80d95c080922bp-2, 0x1.3c65cec2d933ep-2, 0x1.130ddaff18028p-3, 0x1.ea5cc00c5169cp-2, 0x1.9e9565a25e0e8p-7, -0x1.e49d4b102eb6cp-8, 0x1.9c93b9418e1c6p-3, -0x1.411d948178677p-1, -0x1.fbb74416097ecp-6, 0x1.52d415ac388e4p-5, -0x1.cf0ea0f36e8cbp-2, 0x1.4b4a2de0d702bp-1, 0x1.9f9764f0fc04bp-2, -0x1.5dbf3431eb454p-9, 0x1.6f3a515ead64dp-1, 0x1.bfff34a87af0bp-3, 0x1.43d4826f7f4dcp-5, -0x1.cbd78af5e1d54p-5, 0x1.4171e9af5227fp-2, -0x1.fd4bfb446ecb4p-4, -0x1.2ee26feb9c830p-1, 0x1.7976ab0d90a6fp-1, -0x1.0705247284f9bp-1, -0x1.87bb64e56313fp-4, 0x1.2ff29b50ab996p-3, 0x1.cdebfa10929dcp-4, -0x1.3fe7a20f78854p-1, 0x1.5588ca2d80259p-3, 0x1.2c07918f8a7e5p-5, 0x1.3cc07546dec00p-1, 0x1.3036ccadc934cp-4, 0x1.b85e71c25d108p-4, -0x1.dd66d5dd5d3bbp-4, 0x1.73db131c5304ep-1, 0x1.2761af9aa956dp-1, 0x1.385edf9bac1e6p-5, 0x1.ca3b38e554c04p-4, 0x1.367ef09c05241p-3, 0x1.3de2b463cb0c7p-1, -0x1.34bdace4f981bp-3, 0x1.ce3ace48d8609p-3, -0x1.087931f3d2b44p-2, 0x1.61b6fa2c693d8p-2, -0x1.0857e0cc8a438p-3, -0x1.c41211f0c66a9p-2, -0x1.99d8e0e45302fp-2, -0x1.2e3b16c9bad33p-4, 0x1.34df75c8d6479p-1, -0x1.e3e786d5c5e31p-1, 0x1.5115a87b72860p-1, 0x1.10b2c717b3a41p-3, 0x1.3e457bf4089c1p-5, 0x1.1ef37f7831fb9p-4, -0x1.22a88009d0648p-3, -0x1.3aedd2283fa8bp-6, -0x1.87c2bca152616p-3, -0x1.fd8def8f3c0c6p-6, 0x1.9b5b7efc1f6aep-2, 0x1.d7877d201664cp-3, -0x1.50a6cef911a06p-3, 0x1.995282812caa4p-3, -0x1.cc6167939586cp-2, 0x1.85860ce5f3a7ap-5, 0x1.880554fbcc1a2p-4, -0x1.99c4c3462ef71p-3, 0x1.d735c6031af35p-4, 0x1.ddf3cb6f3b5b6p-8, 0x1.b5a3bd66a6970p-2, -0x1.ffaa84654785fp-1, 0x1.45ab3acc52142p-1, 0x1.4337730d72c0ep-3, -0x1.7453a08f0d8ecp-1, -0x1.ffec54955108bp-1, -0x1.6709e2ea4d0cfp-3, 0x1.9f6a6c7dc079ap-1, -0x1.a9cd263c74eb6p-5, 0x1.619398737a72bp-3, -0x1.a4adadc3041d2p-1, -0x1.cc8316adc40dfp-2, -0x1.c3cdbb9a79a50p-6, 0x1.4271f15afcf18p-5, -0x1.7c6fdcd90e43ep-2, 0x1.368ac60900ff2p-5, 0x1.350278ba0a96dp-1, -0x1.145abe825626bp-1, 0x1.375c7ffcc2538p-1, 0x1.bc3452d0a8995p-3, -0x1.339e2252d5ec8p-2, -0x1.efaa9f859328ep-4, 0x1.20d5af8198a3cp-3, -0x1.09a64ca551622p-2, -0x1.81da3a459902bp-4, 0x1.a8d709f57ace6p-2, -0x1.4abd46f040189p-1, -0x1.f362fe518bb2fp-1, -0x1.055f785cfa9cap-2, 0x1.3bc142f9224eep-3, 0x1.32711d4c673fbp-1, 0x1.fdceaa9b6227cp-3, 0x1.2b7b05e615f0cp-4, 0x1.440f884a24396p-1, -0x1.55cf920778e7fp-1, 0x1.bcd8ad2166125p-5, 0x1.7c06cfa0d16d3p-3, -0x1.45092acf5c24bp-2, 0x1.df85f43b4df78p-1, -0x1.0345b1435fd63p-2, 0x1.057d5557419d3p-2, -0x1.4331488b37f06p-3, -0x1.3613df412b110p-1, -0x1.ca579ea3c1b6ap-6, -0x1.e40abe84a1379p-3, 0x1.45c48325a4782p-6, -0x1.675437d9f75a0p-6, 0x1.341bf683dc453p-4, 0x1.10ecc8a7760f1p-2, -0x1.1b35ef0e31f88p-2, -0x1.150808aa3a566p-1, -0x1.3781cb2212f04p-1, 0x1.29dcf93595257p-7, -0x1.e82a34c2b6906p-4, 0x1.a2d79bf87add3p-2, 0x1.5db046fc8e38cp-1, -0x1.f5fd2bfb1f37ep-1, 0x1.808f19e4ba7e1p-3, -0x1.158dca93279d8p-3, 0x1.7755e25d6d752p-4, 0x1.2ab2966dfea86p-2, 0x1.82bb655227d48p-2, 0x1.5231436e95f80p-2, 0x1.5fdb37e2fbd97p-5, 0x1.198365611af10p-2, 0x1.eea421b028659p-5, 0x1.ca09a22d9f5c6p-4, 0x1.2072fd402402ap-2, -0x1.10b17ff6f2eb7p-1, -0x1.22ababb6c6edap-4, -0x1.5264df20887b2p-4, -0x1.11d54fc12f265p-1, 0x1.4a3797f3e78fdp-1, 0x1.d950d85d679d2p-2, -0x1.07728c1dc2145p-5, 0x1.6ff9e357fd865p-1, 0x1.97fba2b8663d6p-3, 0x1.62b5c1b227bcdp-3, 0x1.3b3524a876c7ap-6, 0x1.0c5f46c04d60dp-2, -0x1.07398c555d6aep-4, -0x1.31464ac3d71e2p-1, 0x1.5d990c20e4c69p-1, -0x1.09f8c5632d3b2p-1, 0x1.a1fe680228e19p-4, 0x1.b0865b402274ep-3, -0x1.eeae03269c881p-5, -0x1.00bd7c9ca7a50p-1, 0x1.166a8b451e12ep-2, 0x1.1af067f00cc15p-3, 0x1.23309d4d0c027p-1, 0x1.279ab2105fe94p-3, 0x1.7c167fc1cfea0p-9, 0x1.bfb2911f9e22dp-5, 0x1.6a22d682c7fc8p-1, 0x1.1cf7f5cdba925p-1, 0x1.29160151210edp-2, -0x1.819819b1526cdp-6, 0x1.7f02e6d47583cp-5, 0x1.3a0435ed463a6p-1, -0x1.d997f57ac8fbfp-3, -0x1.57f9f133dc117p-3, -0x1.149bca7cc9091p-2, 0x1.4ea70ea74f84bp-2, -0x1.f5782fcb55342p-4, -0x1.f5ba5edf35069p-2, -0x1.db21d1571692cp-2, 0x1.903d4d213f552p-4, 0x1.438b761f3ba9bp-1, -0x1.e33e55d22a2ecp-1, 0x1.6de98ff32832fp-1, 0x1.a39eac5a18559p-3, -0x1.d60516f9004cap-4, -0x1.0e0417257b8dcp-3, -0x1.a36423cc58ee6p-8, -0x1.94a00c330a40dp-5, 0x1.898191e42e37dp-5, -0x1.0be6fa75b1c8bp-8, 0x1.7e54e50e0430bp-2, 0x1.7fc8a41fbe6eep-3, 0x1.293c0f0812132p-6, 0x1.e38da2f4416a3p-3, -0x1.b0a9ac59142ecp-2, 0x1.1ba4228297489p-3, 0x1.32f12e27772cbp-3, -0x1.6ceea619a62a3p-2, 0x1.f06e5fb6a9339p-3, -0x1.7bdf4d4ef8013p-3, 0x1.8a3bb3eab23cdp-2, -0x1.ffb9b758dfc72p-1, 0x1.278ebbc3b647ep-1, 0x1.07b7e499e5791p-2, -0x1.6cf2375c85e1fp-1, -0x1.ffefcf765ccb1p-1, -0x1.1f630b02c38fcp-2, 0x1.a3eb1a50d353cp-1, -0x1.d643341448a00p-3, 0x1.817c02a54823ap-3, -0x1.8e7562ab0c72bp-1, -0x1.24e85bad41da6p-2, -0x1.d6698ccd79e8ap-8, -0x1.6509fcaddca00p-8 }; diff --git a/src/shinro/runtime/tests/graphs/drone_gru_graph.zig b/src/shinro/runtime/tests/graphs/drone_gru_graph.zig new file mode 100644 index 0000000..28f9ef7 --- /dev/null +++ b/src/shinro/runtime/tests/graphs/drone_gru_graph.zig @@ -0,0 +1,115 @@ +// Test fixture `drone_gru` — real eco-drone GRU, H=128 (fused GRU cell + live state). +// Generated by scripts/gen_lower_fixtures.py from /mnt/E/github-projects/shinro-bench/tasks/policies/models/drone_gru/policy_v26rnn_dr.onnx — DO NOT EDIT. +const std = @import("std"); + +pub const Op = enum { + cst, + cst_f32, + inp, + out, + matmul, + add, + sub, + mul, + div, + ne, + neg, + transpose, + inv, + reshape, + clip, + where_op, + any, + copy, + tanh, + relu, + exp, + argmax, + one_hot, + slice, + sin, + cos, + stack, + solve_qp, + abs, + sign, + pow, + lt, + min, + gemm, + sigmoid, + softmax, + gelu, + elu, + layernorm, + lstm, + gru, + rnn, + concat, + gather, + sqrt, + log, + mod, + leaky_relu, +}; + +pub const Node = struct { + op: Op, + inputs: []const usize, + rows: usize, + cols: usize, + aux: usize, + vec: bool, +}; + +pub const buf_len = 824; +pub const has_solve_qp = false; +pub const n_outputs = 1; + +pub const offsets = [_]usize{ + 0, 56, 56, 112, 112, 168, 296, 296, 296, 296, 424, 552, 552, 552, 552, 552, 680, 808, 808, 808, 812, 812, 816, 816, 820, +}; + +pub const nodes = [_]Node{ + .{ .op = .inp, .inputs = &.{}, .rows = 56, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 56, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .sub, .inputs = &.{ 0, 1 }, .rows = 56, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 56, .cols = 1, .aux = 56, .vec = true }, + .{ .op = .div, .inputs = &.{ 2, 3 }, .rows = 56, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 128, .cols = 1, .aux = 56, .vec = true }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 384, .cols = 56, .aux = 0, .vec = false }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 384, .cols = 128, .aux = 21504, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 768, .cols = 1, .aux = 112, .vec = true }, + .{ .op = .gru, .inputs = &.{ 4, 6, 7, 8, 5 }, .rows = 128, .cols = 1, .aux = 1, .vec = true }, + .{ .op = .out, .inputs = &.{9}, .rows = 128, .cols = 1, .aux = 1, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 880, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 881, .vec = false }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 128, .cols = 128, .aux = 70656, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 128, .cols = 1, .aux = 882, .vec = true }, + .{ .op = .gemm, .inputs = &.{ 9, 13, 14 }, .rows = 128, .cols = 1, .aux = 1, .vec = true }, + .{ .op = .relu, .inputs = &.{15}, .rows = 128, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 4, .cols = 128, .aux = 87040, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 4, .cols = 1, .aux = 1010, .vec = true }, + .{ .op = .gemm, .inputs = &.{ 16, 17, 18 }, .rows = 4, .cols = 1, .aux = 3, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 1014, .vec = false }, + .{ .op = .mul, .inputs = &.{ 19, 20 }, .rows = 4, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 1015, .vec = false }, + .{ .op = .add, .inputs = &.{ 21, 22 }, .rows = 4, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{23}, .rows = 4, .cols = 1, .aux = 0, .vec = true }, +}; + +pub const const_blob = [_]f64{ + 0x1.95a8a00000000p+2, -0x1.c609ce0000000p-8, -0x1.e36c620000000p-4, 0x1.d51ea60000000p+2, 0x1.4499220000000p-1, 0x1.1767320000000p-8, -0x1.040f4c0000000p-5, -0x1.1ae7a60000000p-8, -0x1.b24f5c0000000p-9, 0x1.53c6960000000p+0, 0x1.80194e0000000p-2, 0x1.3267a00000000p+3, 0x1.3225260000000p+3, 0x1.31f9c00000000p+3, 0x1.31c6080000000p+3, 0x1.31b1ba0000000p+3, 0x1.31d46e0000000p+3, 0x1.3211e60000000p+3, 0x1.32218c0000000p+3, 0x1.324a760000000p+3, 0x1.28aeb80000000p+3, 0x1.27c3da0000000p+3, 0x1.27a7080000000p+3, 0x1.2833100000000p+3, 0x1.28671a0000000p+3, 0x1.2832700000000p+3, 0x1.279f300000000p+3, 0x1.27b4300000000p+3, 0x1.289cf40000000p+3, 0x1.25fa120000000p+3, 0x1.24440a0000000p+3, 0x1.23650e0000000p+3, 0x1.237be40000000p+3, 0x1.2415900000000p+3, 0x1.234bb00000000p+3, 0x1.230a620000000p+3, 0x1.23f6800000000p+3, 0x1.25b82a0000000p+3, 0x1.2ad5040000000p+3, 0x1.29b7ca0000000p+3, 0x1.2928680000000p+3, 0x1.298ffe0000000p+3, 0x1.2a171c0000000p+3, 0x1.295c800000000p+3, 0x1.28dd060000000p+3, 0x1.2971ae0000000p+3, 0x1.2a95fa0000000p+3, 0x1.3298c80000000p+3, 0x1.327d420000000p+3, 0x1.3305580000000p+3, 0x1.33b85a0000000p+3, 0x1.33f4b40000000p+3, 0x1.33c0780000000p+3, 0x1.32f7ba0000000p+3, 0x1.3275820000000p+3, 0x1.326f540000000p+3, 0x1.4e78f40000000p+3, 0x1.27ff8a0000000p+1, 0x1.ee4c700000000p-1, 0x1.433f3a0000000p+3, 0x1.cfc6ac0000000p+0, 0x1.510ec60000000p+0, 0x1.3669da0000000p+0, 0x1.cded460000000p-1, 0x1.b7a1a00000000p-1, 0x1.2754500000000p+0, 0x1.f1237a0000000p-2, 0x1.b1eaa60000000p+0, 0x1.b38c380000000p+0, 0x1.b5ac760000000p+0, 0x1.b858a60000000p+0, 0x1.b950780000000p+0, 0x1.b7cc7a0000000p+0, 0x1.b533d00000000p+0, 0x1.b61b560000000p+0, 0x1.b4d1c00000000p+0, 0x1.0e121e0000000p+1, 0x1.1125140000000p+1, 0x1.10955a0000000p+1, 0x1.0da0300000000p+1, 0x1.0cc0060000000p+1, 0x1.0dd09a0000000p+1, 0x1.1111d60000000p+1, 0x1.11d2120000000p+1, 0x1.0f0c880000000p+1, 0x1.14e1dc0000000p+1, 0x1.1d380e0000000p+1, 0x1.1f71120000000p+1, 0x1.1d3ca00000000p+1, 0x1.1ad8d20000000p+1, 0x1.1df77e0000000p+1, 0x1.210a840000000p+1, 0x1.1ec4420000000p+1, 0x1.161b640000000p+1, 0x1.06c10a0000000p+1, 0x1.0a64b80000000p+1, 0x1.0a8f740000000p+1, 0x1.0791c40000000p+1, 0x1.058aa00000000p+1, 0x1.0842ae0000000p+1, 0x1.0baa220000000p+1, 0x1.0b6efc0000000p+1, 0x1.08081a0000000p+1, 0x1.bbf2b20000000p+0, 0x1.bb76ac0000000p+0, 0x1.b2c0680000000p+0, 0x1.a7d5500000000p+0, 0x1.a462320000000p+0, 0x1.a7928c0000000p+0, 0x1.b3cc1e0000000p+0, 0x1.bc80ca0000000p+0, 0x1.beb1c60000000p+0, -0x1.a79d220000000p-3, -0x1.18f58e0000000p-1, -0x1.e428860000000p-5, -0x1.d5c4120000000p-3, -0x1.e8cefc0000000p-4, -0x1.bf41920000000p-3, -0x1.8da7500000000p-4, -0x1.1ef5fc0000000p-5, -0x1.57c8800000000p-3, -0x1.f7b73c0000000p-3, -0x1.13741e0000000p-3, -0x1.b40a4e0000000p-5, -0x1.b1ef600000000p-4, -0x1.fa96b40000000p-3, -0x1.ee74e40000000p-4, -0x1.d7584c0000000p-3, -0x1.eaa1e60000000p-4, -0x1.9ffb800000000p-2, -0x1.2a62c20000000p-3, -0x1.a1d3f40000000p-3, 0x1.5071000000000p-5, -0x1.23ddb60000000p-3, -0x1.2ca2d60000000p-2, -0x1.3d34700000000p-2, -0x1.05a8260000000p-2, -0x1.3436ce0000000p-3, -0x1.40d80e0000000p-2, -0x1.7240d40000000p-3, -0x1.a2ee660000000p-3, -0x1.3214c60000000p-3, -0x1.3ae5e20000000p-2, -0x1.5844ee0000000p-2, -0x1.283f2e0000000p-2, -0x1.5e35ac0000000p-3, -0x1.d2e89e0000000p-3, -0x1.f61c8e0000000p-4, -0x1.5a78740000000p-2, -0x1.a3f1740000000p-3, -0x1.35925c0000000p-3, -0x1.a350e80000000p-3, -0x1.42adc40000000p-3, -0x1.1342720000000p-3, -0x1.3d7dd20000000p-6, -0x1.3117f20000000p-6, -0x1.1e90860000000p-3, -0x1.5b839c0000000p-2, -0x1.5df9f20000000p-3, -0x1.67f5480000000p-4, -0x1.2702860000000p-3, -0x1.2cc0800000000p-4, -0x1.1cfdcc0000000p-2, -0x1.bd24880000000p-3, -0x1.9211b40000000p-3, 0x1.1508ba0000000p-6, -0x1.020db80000000p-3, -0x1.b5346c0000000p-4, -0x1.93b4b80000000p-2, -0x1.4dd44e0000000p-2, -0x1.dddcc00000000p-5, -0x1.2f52280000000p-4, -0x1.6002020000000p-2, -0x1.8195900000000p-2, -0x1.9dd03a0000000p-5, -0x1.630c260000000p-3, -0x1.2733360000000p-2, -0x1.50304a0000000p-4, -0x1.d548ba0000000p-2, -0x1.98f46a0000000p-3, -0x1.77b9640000000p-2, -0x1.79c6ee0000000p-2, -0x1.58c6480000000p-4, -0x1.981cd80000000p-6, -0x1.63beba0000000p-4, -0x1.b84d5c0000000p-3, -0x1.2f49a80000000p-3, -0x1.1a8a440000000p-4, -0x1.c105dc0000000p-3, -0x1.90c4d20000000p-2, 0x1.7540860000000p-6, -0x1.aeb70c0000000p-3, -0x1.2c8fe80000000p-4, -0x1.810f3e0000000p-4, -0x1.a229e20000000p-3, -0x1.80339e0000000p-3, -0x1.6cbedc0000000p-2, 0x1.675a620000000p-8, -0x1.c45a860000000p-8, -0x1.5276460000000p-2, -0x1.ba4c900000000p-4, -0x1.279c720000000p-2, -0x1.293ec60000000p-2, -0x1.17f0860000000p-3, -0x1.3b33fa0000000p-4, -0x1.70585e0000000p-2, -0x1.0b01c00000000p-2, -0x1.21d90a0000000p-2, -0x1.4638760000000p-2, -0x1.5562380000000p-3, -0x1.ec81aa0000000p-3, -0x1.255c860000000p-2, -0x1.47b59c0000000p-4, -0x1.940eaa0000000p-3, -0x1.dd36de0000000p-3, -0x1.c27dc80000000p-3, -0x1.4cc1b20000000p-2, -0x1.9cd4e60000000p-3, -0x1.c20a7e0000000p-3, -0x1.49479a0000000p-3, -0x1.48a4d40000000p-2, -0x1.a72f800000000p-3, -0x1.d832d20000000p-3, -0x1.bb65680000000p-4, -0x1.cd3f900000000p-5, -0x1.f966ca0000000p-4, -0x1.6ea2c00000000p-6, -0x1.3760600000000p-2, -0x1.bb41440000000p-4, -0x1.8ebd3a0000000p-2, -0x1.3ba9800000000p-2, -0x1.7533580000000p-3, -0x1.366db00000000p-2, -0x1.0dd3fa0000000p-2, -0x1.75843a0000000p-2, -0x1.3bd49a0000000p-4, -0x1.39ae360000000p-2, -0x1.6047d40000000p-3, -0x1.e386ee0000000p-2, -0x1.ec25d60000000p-3, -0x1.da0c820000000p-5, 0x1.9f4c0c0000000p-3, -0x1.14300c0000000p-5, -0x1.4c56dc0000000p-4, -0x1.5029a00000000p-5, 0x1.377d100000000p-5, -0x1.9dddec0000000p-5, -0x1.fa73120000000p-5, -0x1.47e0da0000000p-5, -0x1.5896160000000p-5, -0x1.e0670e0000000p-6, 0x1.0aca400000000p-4, 0x1.6bc5b00000000p-6, 0x1.d058000000000p-5, -0x1.1c32fc0000000p-4, -0x1.24ac560000000p-5, 0x1.343ad80000000p-4, 0x1.87621c0000000p-3, 0x1.f80f400000000p-8, 0x1.0085b40000000p-4, 0x1.225cdc0000000p-4, 0x1.35b1da0000000p-6, 0x1.ca9bae0000000p-7, 0x1.87ca780000000p-5, 0x1.7e5c460000000p-7, 0x1.5c475a0000000p-4, 0x1.242ace0000000p-4, 0x1.51da200000000p-4, -0x1.1c501a0000000p-6, -0x1.23518e0000000p-5, 0x1.1d3c480000000p-4, 0x1.3915c60000000p-5, 0x1.b32f660000000p-4, 0x1.8a3aca0000000p-5, -0x1.6c7fc60000000p-4, -0x1.aa9df40000000p-6, 0x1.db24640000000p-5, -0x1.3bd35e0000000p-6, 0x1.ca6a920000000p-4, 0x1.f5a15a0000000p-6, -0x1.b29b200000000p-5, -0x1.220c6e0000000p-7, 0x1.f8f8e00000000p-5, -0x1.e777740000000p-7, -0x1.976b2a0000000p-4, 0x1.c36a220000000p-8, -0x1.f763060000000p-5, 0x1.56c1180000000p-4, -0x1.dde3240000000p-5, -0x1.72866c0000000p-11, -0x1.d17b300000000p-5, 0x1.29a70c0000000p-4, 0x1.7eacd80000000p-4, 0x1.a6e4ee0000000p-4, 0x1.40048c0000000p-6, 0x1.025afe0000000p-3, 0x1.1fcf780000000p-4, -0x1.482dfe0000000p-6, 0x1.b378ca0000000p-6, 0x1.356a820000000p-8, 0x1.351ede0000000p-6, -0x1.1dd2d80000000p-6, 0x1.f537dc0000000p-4, -0x1.8e990a0000000p-6, 0x1.d23dde0000000p-5, -0x1.c1e0240000000p-7, 0x1.58e04c0000000p-4, 0x1.4c71400000000p-4, 0x1.22f9cc0000000p-7, -0x1.d2bcac0000000p-5, 0x1.541a260000000p-3, 0x1.1441980000000p-4, -0x1.114a5a0000000p-5, 0x1.ac399c0000000p-4, -0x1.5d25fa0000000p-7, -0x1.a8ce9a0000000p-5, -0x1.b08f500000000p-8, 0x1.4b0ca20000000p-6, -0x1.5a071e0000000p-4, 0x1.420df80000000p-4, 0x1.be6cd00000000p-5, 0x1.b725a00000000p-5, 0x1.4e8fac0000000p-5, 0x1.580a3e0000000p-5, 0x1.1760260000000p-10, 0x1.1b29ca0000000p-7, 0x1.1b3e9c0000000p-5, 0x1.18960a0000000p-3, 0x1.5ad5260000000p-8, -0x1.0609500000000p-4, 0x1.f5599e0000000p-6, 0x1.5ca4ba0000000p-6, 0x1.d6556c0000000p-6, 0x1.b1476c0000000p-5, -0x1.99ad7c0000000p-5, 0x1.8bbd740000000p-4, 0x1.09a6180000000p-5, 0x1.e883cc0000000p-9, -0x1.7ca6120000000p-5, 0x1.20728e0000000p-4, 0x1.ce120c0000000p-4, -0x1.6ed55a0000000p-6, 0x1.f741f20000000p-6, -0x1.614ae00000000p-7, 0x1.0927300000000p-4, 0x1.2a66bc0000000p-5, -0x1.4f30f80000000p-4, -0x1.d3fbd80000000p-6, 0x1.a76a7e0000000p-4, 0x1.9f89e60000000p-6, 0x1.a264ce0000000p-4, 0x1.3855720000000p-3, 0x1.dfcf560000000p-5, 0x1.c9ba0c0000000p-4, -0x1.cfa6b40000000p-5, 0x1.ae499e0000000p-5, 0x1.43b0980000000p-4, 0x1.a8cc2a0000000p-4, -0x1.24ba900000000p-5, 0x1.1d29160000000p-5, 0x1.51f6740000000p-4, 0x1.9d6d740000000p-3, 0x1.2552040000000p-6, 0x1.270d760000000p-7, 0x1.0e87a60000000p-4, 0x1.69832e0000000p-5, 0x1.f079120000000p-3, -0x1.5557b20000000p-6, -0x1.a22bd60000000p-5, -0x1.133af60000000p-2, -0x1.2373160000000p-5, 0x1.835f840000000p-4, 0x1.a47faa0000000p-5, -0x1.3f3d960000000p-3, -0x1.af661e0000000p-5, -0x1.0549600000000p-5, 0x1.de566e0000000p-9, -0x1.30da860000000p-3, -0x1.fc9e580000000p-6, 0x1.1785720000000p-3, -0x1.1df5da0000000p-6, -0x1.4777da0000000p-4, -0x1.6ed3ce0000000p-4, 0x1.ebc97c0000000p-4, -0x1.6577ae0000000p-9, 0x1.0cf05c0000000p-5, 0x1.7a71aa0000000p-5, -0x1.c199d40000000p-6, -0x1.22317e0000000p-3, 0x1.1fe19a0000000p-6, -0x1.60fc9c0000000p-4, 0x1.5aee780000000p-3, 0x1.71f7ec0000000p-4, 0x1.1926ba0000000p-12, -0x1.381f700000000p-3, -0x1.acb3d20000000p-4, 0x1.4c98080000000p-3, -0x1.218e6a0000000p-3, 0x1.2969fe0000000p-3, -0x1.07c67c0000000p-2, 0x1.a232f60000000p-6, -0x1.12760c0000000p-4, -0x1.86383a0000000p-8, -0x1.c1f8c00000000p-5, -0x1.858cd00000000p-3, -0x1.619ac60000000p-4, -0x1.ce2af60000000p-4, -0x1.972a520000000p-6, -0x1.b0e6ea0000000p-5, -0x1.e407040000000p-13, -0x1.1bc9880000000p-4, 0x1.a53d780000000p-5, 0x1.ffa5260000000p-5, -0x1.02844c0000000p-4, -0x1.ab9b0a0000000p-6, 0x1.0f90120000000p-4, -0x1.ccdaa20000000p-6, -0x1.235d460000000p-5, 0x1.060df60000000p-3, -0x1.f0d1480000000p-5, 0x1.4435de0000000p-4, -0x1.793ac20000000p-4, 0x1.f22e1c0000000p-5, -0x1.5599b20000000p-3, -0x1.952cea0000000p-4, -0x1.ad87940000000p-7, -0x1.10961e0000000p-5, -0x1.83114e0000000p-3, -0x1.1e97880000000p-3, 0x1.4d2b020000000p-3, 0x1.7827ac0000000p-4, -0x1.12aaa20000000p-4, -0x1.a5e9300000000p-5, 0x1.0374be0000000p-6, -0x1.e796460000000p-6, -0x1.4854cc0000000p-4, 0x1.9ee60e0000000p-3, -0x1.9ca1fa0000000p-4, 0x1.46d0e40000000p-3, 0x1.de036a0000000p-4, -0x1.c407fa0000000p-4, -0x1.3e9b660000000p-4, 0x1.c194ea0000000p-8, 0x1.71d9aa0000000p-5, 0x1.d2487c0000000p-4, 0x1.9778f40000000p-5, 0x1.ef73380000000p-5, 0x1.bca6780000000p-6, 0x1.fa15960000000p-6, -0x1.93b5880000000p-5, 0x1.638fc40000000p-5, 0x1.f9b31a0000000p-4, -0x1.88d71a0000000p-5, 0x1.61e0f00000000p-4, 0x1.5f91640000000p-4, -0x1.b9d3a40000000p-4, 0x1.10acca0000000p-4, -0x1.ebd6300000000p-6, 0x1.d2306a0000000p-4, 0x1.30f37c0000000p-5, 0x1.d486cc0000000p-5, 0x1.2bb1320000000p-3, -0x1.ee2d560000000p-5, -0x1.beed680000000p-4, -0x1.c6517e0000000p-3, -0x1.d7173c0000000p-4, -0x1.8cbdea0000000p-5, 0x1.31f7ce0000000p-4, -0x1.48dcd40000000p-4, -0x1.25f85e0000000p-4, -0x1.e268500000000p-9, 0x1.f94c0e0000000p-5, -0x1.76fcaa0000000p-5, 0x1.dd91540000000p-5, 0x1.c1fb580000000p-6, 0x1.c5cfb80000000p-5, 0x1.1cffca0000000p-3, -0x1.da5aec0000000p-5, -0x1.1d4c740000000p-3, 0x1.4fab300000000p-3, 0x1.297eb60000000p-5, 0x1.543a820000000p-4, -0x1.72232e0000000p-5, -0x1.8ecc7a0000000p-3, 0x1.fb35b80000000p-3, -0x1.229bf80000000p-2, 0x1.4b54400000000p-6, -0x1.9f06980000000p-3, 0x1.02969e0000000p-3, 0x1.179ee40000000p-2, 0x1.9e09700000000p-4, 0x1.dffb8a0000000p-5, -0x1.421a9a0000000p-3, -0x1.5bdb280000000p-4, 0x1.26ec120000000p-2, -0x1.000cbc0000000p-4, -0x1.4aee8e0000000p-3, -0x1.19841c0000000p-1, -0x1.be840e0000000p-5, -0x1.0f89a60000000p-2, -0x1.a3e6b60000000p-3, -0x1.4122da0000000p-2, -0x1.c17cf00000000p-3, -0x1.6928060000000p-3, -0x1.05bc4a0000000p-2, -0x1.f0eddc0000000p-4, -0x1.9ab7be0000000p-3, -0x1.4331800000000p-3, -0x1.96ac700000000p-4, -0x1.906aa00000000p-3, -0x1.89bfc60000000p-8, -0x1.52009c0000000p-3, -0x1.3199e60000000p-4, -0x1.c550e60000000p-2, -0x1.c2b6060000000p-4, -0x1.7d17040000000p-3, -0x1.18e5760000000p-4, -0x1.30154c0000000p-3, -0x1.5ea8f00000000p-2, -0x1.a2bab80000000p-2, -0x1.a17b6c0000000p-3, -0x1.6dacee0000000p-3, -0x1.d57f300000000p-2, -0x1.d830e20000000p-3, -0x1.25bd420000000p-2, -0x1.c41a4a0000000p-4, -0x1.5e1d160000000p-2, -0x1.4153980000000p-2, -0x1.2b23140000000p-2, -0x1.be1bf00000000p-4, -0x1.ead5b20000000p-3, -0x1.9c1d160000000p-5, -0x1.f2f61e0000000p-3, -0x1.1793b80000000p-2, -0x1.04c91e0000000p-2, -0x1.02bfde0000000p-2, -0x1.6ccc040000000p-4, -0x1.63f85c0000000p-4, 0x1.3f466a0000000p-6, -0x1.4b00e80000000p-4, -0x1.05a9f40000000p-4, -0x1.d8cba00000000p-3, -0x1.5ae0f80000000p-3, -0x1.76d0c40000000p-3, -0x1.00c0200000000p-3, -0x1.d558d40000000p-4, -0x1.6551ca0000000p-2, -0x1.247dc20000000p-3, -0x1.43f1440000000p-4, -0x1.1bcc760000000p-4, -0x1.039e380000000p-2, -0x1.b170480000000p-4, -0x1.7b47da0000000p-2, -0x1.4cf9360000000p-3, -0x1.53ba800000000p-4, -0x1.27ad340000000p-5, -0x1.4ec96c0000000p-2, -0x1.673c940000000p-2, -0x1.e1c6800000000p-4, -0x1.9d07ac0000000p-3, -0x1.c8eadc0000000p-2, -0x1.ae740a0000000p-3, -0x1.f48fd20000000p-2, -0x1.1da1ec0000000p-4, -0x1.d656160000000p-2, -0x1.5c04000000000p-2, -0x1.74a59a0000000p-3, -0x1.49a0c40000000p-5, -0x1.d9000a0000000p-5, -0x1.d15a2a0000000p-3, -0x1.e4e6f20000000p-3, -0x1.a22e9c0000000p-4, -0x1.36f23c0000000p-3, -0x1.9cbe280000000p-2, -0x1.c179640000000p-8, -0x1.cb36c20000000p-3, 0x1.356adc0000000p-6, -0x1.790c360000000p-3, -0x1.07def00000000p-4, -0x1.c607f60000000p-4, -0x1.81f82c0000000p-2, -0x1.6a735c0000000p-7, -0x1.bc04980000000p-4, -0x1.fe128a0000000p-3, -0x1.a9defa0000000p-5, -0x1.31a3c60000000p-2, -0x1.33c6b60000000p-2, -0x1.e611320000000p-4, -0x1.bbb3c00000000p-4, -0x1.9405920000000p-2, -0x1.fd5d100000000p-3, -0x1.6d28d00000000p-2, -0x1.4f32060000000p-2, -0x1.2cc1940000000p-2, -0x1.fea8160000000p-3, -0x1.29e3440000000p-3, -0x1.70b4d20000000p-7, -0x1.ae466a0000000p-5, -0x1.ce82520000000p-3, -0x1.155b700000000p-3, -0x1.0fe2040000000p-2, -0x1.e721f20000000p-4, -0x1.e5ac860000000p-3, -0x1.3e63d00000000p-3, -0x1.c515a40000000p-3, -0x1.56bff60000000p-3, -0x1.18de460000000p-2, -0x1.3b08500000000p-3, 0x1.9e39160000000p-6, 0x1.a3b5c40000000p-9, 0x1.e45bc40000000p-6, -0x1.ce089c0000000p-3, -0x1.0e62ac0000000p-3, -0x1.5036d40000000p-2, -0x1.a0f2260000000p-3, -0x1.445eac0000000p-3, -0x1.90189e0000000p-2, -0x1.3e1d2c0000000p-2, -0x1.3ac30c0000000p-2, -0x1.5f12a20000000p-5, -0x1.53c5480000000p-2, -0x1.11af8c0000000p-3, -0x1.ca42c40000000p-2, -0x1.85645e0000000p-3, -0x1.8473020000000p-4, 0x1.8f91c20000000p-4, -0x1.65166c0000000p-4, -0x1.3c35da0000000p-4, 0x1.1be0600000000p-4, -0x1.3dea280000000p-6, 0x1.090ff60000000p-6, 0x1.da26d60000000p-6, -0x1.8307800000000p-5, 0x1.5504f40000000p-5, 0x1.2669e40000000p-5, -0x1.73d5ce0000000p-4, 0x1.757e9e0000000p-9, -0x1.40de200000000p-5, 0x1.53d2f00000000p-5, -0x1.0531dc0000000p-4, 0x1.1a33a80000000p-5, 0x1.a445520000000p-5, 0x1.6e3c800000000p-5, 0x1.d83d5c0000000p-6, 0x1.08d0120000000p-3, -0x1.aa0cfc0000000p-4, 0x1.4fcc140000000p-6, 0x1.403a4c0000000p-5, 0x1.03ac020000000p-3, 0x1.a2968c0000000p-6, -0x1.03b7780000000p-4, -0x1.e6dde40000000p-9, 0x1.5468740000000p-6, 0x1.8d687c0000000p-4, 0x1.bbaa600000000p-4, 0x1.4bbab60000000p-3, -0x1.8eb1500000000p-5, -0x1.46037c0000000p-7, 0x1.943a880000000p-5, -0x1.4a92d00000000p-9, 0x1.7917bc0000000p-6, 0x1.441e180000000p-4, 0x1.093ef60000000p-3, 0x1.51665e0000000p-4, -0x1.2f569a0000000p-6, -0x1.cdb70c0000000p-4, 0x1.1eb0ac0000000p-3, 0x1.43b5880000000p-4, -0x1.2ce8cc0000000p-5, -0x1.0209a00000000p-5, 0x1.7f131c0000000p-5, -0x1.ed947c0000000p-7, -0x1.150ed60000000p-4, -0x1.fe030c0000000p-5, -0x1.2c55e60000000p-5, 0x1.0587240000000p-3, 0x1.bf46180000000p-10, 0x1.ff3c080000000p-8, -0x1.80111a0000000p-4, 0x1.6d13240000000p-4, 0x1.9728b80000000p-6, 0x1.d8596c0000000p-4, -0x1.5de3b20000000p-5, 0x1.125d1c0000000p-3, 0x1.9353340000000p-5, 0x1.d944000000000p-8, 0x1.128cfe0000000p-4, 0x1.5a22c00000000p-4, 0x1.647d7c0000000p-5, 0x1.8d0f4a0000000p-4, 0x1.433ca00000000p-5, 0x1.640a020000000p-4, 0x1.7f87b20000000p-4, 0x1.8db6720000000p-5, 0x1.a4bf9a0000000p-5, 0x1.45bee60000000p-4, -0x1.1440d00000000p-4, 0x1.9097420000000p-4, -0x1.9b68280000000p-4, -0x1.6cc2c80000000p-6, 0x1.34d8180000000p-4, 0x1.1efbf00000000p-6, 0x1.e55e620000000p-5, -0x1.bde0700000000p-5, 0x1.5f484a0000000p-8, -0x1.2705e20000000p-4, -0x1.4789560000000p-6, 0x1.a881420000000p-3, 0x1.d931460000000p-4, 0x1.31fa8c0000000p-4, 0x1.6c7f6c0000000p-5, 0x1.173d560000000p-9, 0x1.ef53ca0000000p-6, -0x1.ae25a40000000p-5, 0x1.f8c82c0000000p-13, -0x1.d9709c0000000p-4, 0x1.4e53bc0000000p-5, 0x1.a744d40000000p-4, 0x1.128aa20000000p-4, 0x1.03cc820000000p-7, 0x1.2ed8ae0000000p-4, -0x1.b5bf940000000p-6, 0x1.5992300000000p-9, -0x1.24f4880000000p-6, 0x1.89c28a0000000p-5, 0x1.85f8a00000000p-4, 0x1.8800f00000000p-4, -0x1.ca17000000000p-13, -0x1.ac7e600000000p-5, 0x1.2c3a760000000p-6, 0x1.6b78ce0000000p-5, 0x1.6c861e0000000p-4, 0x1.c8d8740000000p-4, -0x1.fb11f40000000p-6, -0x1.7d46fa0000000p-5, -0x1.4b79600000000p-6, -0x1.7c10ec0000000p-9, 0x1.b5b21e0000000p-4, -0x1.d944d20000000p-7, 0x1.2fbf3a0000000p-3, 0x1.811a160000000p-4, 0x1.c408d60000000p-4, -0x1.e8efd40000000p-5, 0x1.cee1a60000000p-4, -0x1.b53f520000000p-8, 0x1.bbb0b20000000p-3, -0x1.31c4560000000p-5, -0x1.c8fc600000000p-6, 0x1.84038c0000000p-4, 0x1.5e75f80000000p-7, 0x1.0243d00000000p-3, 0x1.2f93ac0000000p-7, -0x1.ffe1080000000p-4, -0x1.bf1c7c0000000p-3, 0x1.c4db8c0000000p-8, 0x1.ea6ea00000000p-7, -0x1.4ac2220000000p-5, -0x1.a5e33c0000000p-4, 0x1.373bb40000000p-4, -0x1.8906560000000p-4, 0x1.1b0cce0000000p-4, -0x1.23c4800000000p-8, 0x1.5d62e60000000p-6, 0x1.f572f40000000p-7, 0x1.17f0840000000p-5, -0x1.3ce5500000000p-3, 0x1.f0ecce0000000p-7, -0x1.3c94920000000p-6, 0x1.273af80000000p-4, -0x1.67d0bc0000000p-5, 0x1.8880240000000p-5, -0x1.5f81ec0000000p-6, -0x1.128d2e0000000p-3, -0x1.7db91e0000000p-12, -0x1.1ed9a80000000p-3, 0x1.ee45c20000000p-4, 0x1.3b2e800000000p-3, 0x1.6bf9f40000000p-4, -0x1.1aba440000000p-4, -0x1.25ccc60000000p-4, 0x1.2b5a520000000p-4, -0x1.69f13c0000000p-4, 0x1.20f0620000000p-3, -0x1.14c6a80000000p-3, 0x1.c63cc00000000p-4, -0x1.16362a0000000p-5, 0x1.5962a80000000p-8, -0x1.154f2e0000000p-8, -0x1.d0fe7a0000000p-4, -0x1.2ad1660000000p-3, -0x1.9484460000000p-3, 0x1.0a3a1c0000000p-4, -0x1.089be20000000p-4, 0x1.bbd61c0000000p-5, -0x1.166aec0000000p-3, 0x1.6c2c8c0000000p-4, 0x1.3931540000000p-5, 0x1.a9e42e0000000p-5, 0x1.22d4560000000p-6, 0x1.6d70320000000p-4, -0x1.a904d20000000p-5, 0x1.2c9f060000000p-7, 0x1.4524a80000000p-3, 0x1.06a9800000000p-7, 0x1.4432000000000p-4, -0x1.84c3c20000000p-4, 0x1.84b3380000000p-5, -0x1.7a76b80000000p-4, -0x1.5e86220000000p-3, 0x1.8ef61a0000000p-7, -0x1.07679e0000000p-4, -0x1.0fafb40000000p-5, -0x1.13d0720000000p-4, 0x1.4f01260000000p-3, 0x1.26aa0a0000000p-3, -0x1.f084780000000p-5, -0x1.dfcd900000000p-4, -0x1.1173e40000000p-3, 0x1.3a20cc0000000p-6, 0x1.1b79b40000000p-4, 0x1.63674e0000000p-3, 0x1.a8b5580000000p-5, 0x1.2110de0000000p-3, 0x1.2013cc0000000p-4, -0x1.79f8e00000000p-5, -0x1.a7396c0000000p-3, -0x1.29a7ea0000000p-6, -0x1.6fb2040000000p-6, 0x1.0f93c80000000p-4, -0x1.725e160000000p-8, 0x1.3114400000000p-5, 0x1.03f1a00000000p-4, -0x1.ab5ca60000000p-4, 0x1.4a94400000000p-5, -0x1.78f1ce0000000p-5, 0x1.3bc23a0000000p-3, -0x1.3b8df20000000p-5, -0x1.1e520e0000000p-4, 0x1.6947340000000p-6, -0x1.c3a7700000000p-3, 0x1.035ca00000000p-3, 0x1.7242840000000p-6, 0x1.6e49da0000000p-4, -0x1.3458460000000p-6, -0x1.89e3840000000p-4, 0x1.c941300000000p-4, -0x1.024fd40000000p-5, -0x1.14df460000000p-3, -0x1.125e0a0000000p-3, -0x1.70b1180000000p-4, -0x1.e3eb980000000p-5, 0x1.0bad6a0000000p-3, -0x1.10d5520000000p-4, -0x1.a0067a0000000p-4, 0x1.2fe4360000000p-3, -0x1.84424a0000000p-5, 0x1.9ebbf00000000p-6, -0x1.a63fe80000000p-5, 0x1.8643940000000p-7, 0x1.85ac280000000p-5, 0x1.daaf0c0000000p-5, -0x1.c6fca00000000p-6, -0x1.0000e00000000p-3, 0x1.17eff80000000p-3, -0x1.5d58c60000000p-8, 0x1.048bde0000000p-3, -0x1.1ed5660000000p-4, -0x1.7144be0000000p-3, 0x1.73259c0000000p-3, -0x1.2773ee0000000p-2, 0x1.685ed40000000p-4, -0x1.05ffc00000000p-3, 0x1.3da4580000000p-3, 0x1.ad0b480000000p-3, 0x1.084fe40000000p-3, 0x1.702ff60000000p-4, -0x1.500fea0000000p-3, 0x1.3377820000000p-6, 0x1.4082b00000000p-2, 0x1.77a53a0000000p-5, 0x1.0000000000000p+0, -0x1.0000000000000p+0, 0x1.5bf08c0000000p-4, -0x1.346ab00000000p-6, 0x1.24d91a0000000p-5, 0x1.ee925c0000000p-5, 0x1.b2a42a0000000p-4, 0x1.3003c80000000p-4, 0x1.c17ad40000000p-5, -0x1.916bfc0000000p-6, 0x1.cbaaf60000000p-4, 0x1.9ec5e80000000p-4, -0x1.9c7a500000000p-5, -0x1.43f0da0000000p-5, 0x1.e30cac0000000p-5, 0x1.bf1f080000000p-6, 0x1.0e585e0000000p-5, -0x1.3d18b00000000p-6, -0x1.595b280000000p-8, 0x1.c498f00000000p-5, -0x1.22651e0000000p-6, 0x1.5a99560000000p-4, 0x1.410e340000000p-4, 0x1.ded44c0000000p-4, 0x1.795eb80000000p-4, 0x1.827c2e0000000p-4, 0x1.54be240000000p-4, 0x1.95d6f40000000p-4, 0x1.3175540000000p-6, 0x1.0698060000000p-3, 0x1.579c860000000p-5, -0x1.c5d69e0000000p-9, 0x1.e78a700000000p-6, -0x1.4d33dc0000000p-7, 0x1.4339900000000p-6, -0x1.5701320000000p-7, 0x1.fb10e20000000p-5, 0x1.44f1da0000000p-4, 0x1.0c4a200000000p-6, 0x1.07ae2c0000000p-5, 0x1.bc7c1c0000000p-6, 0x1.e896020000000p-5, 0x1.0b4a500000000p-8, 0x1.6be6f20000000p-4, -0x1.1900640000000p-5, 0x1.05646a0000000p-5, -0x1.1367700000000p-5, 0x1.2b7c900000000p-7, -0x1.7261880000000p-8, 0x1.2bc1e00000000p-5, 0x1.5a987c0000000p-4, -0x1.0b86c60000000p-5, 0x1.3017ce0000000p-5, 0x1.dcee920000000p-7, 0x1.d6dfa00000000p-7, 0x1.3237480000000p-7, 0x1.2d67a60000000p-6, 0x1.0112840000000p-8, 0x1.55acb00000000p-6, 0x1.3777020000000p-5, 0x1.8aca1c0000000p-5, 0x1.b0aeae0000000p-6, -0x1.3d63680000000p-5, -0x1.6198360000000p-7, 0x1.fa8b280000000p-9, 0x1.c16f600000000p-4, -0x1.36a3be0000000p-11, 0x1.1df5160000000p-3, -0x1.24e9280000000p-5, 0x1.1673a00000000p-3, -0x1.92c6880000000p-7, 0x1.8f2ee00000000p-5, 0x1.ccc0ca0000000p-4, -0x1.97627a0000000p-6, 0x1.0a23f00000000p-3, 0x1.0aa17a0000000p-5, 0x1.fd70120000000p-8, 0x1.a216240000000p-4, 0x1.dac0f40000000p-5, 0x1.5c68c80000000p-5, 0x1.9fc0ee0000000p-4, -0x1.e521e40000000p-8, 0x1.ba77f40000000p-7, -0x1.910c460000000p-8, -0x1.62c6080000000p-5, 0x1.0a73a20000000p-3, -0x1.4d178c0000000p-9, 0x1.0191320000000p-3, 0x1.0c57e20000000p-6, 0x1.20ee3e0000000p-3, -0x1.8132100000000p-6, 0x1.7838ec0000000p-4, 0x1.f4bf620000000p-8, 0x1.eca7900000000p-4, 0x1.54a7c20000000p-4, 0x1.08203e0000000p-4, -0x1.1998e80000000p-5, 0x1.2b416e0000000p-6, 0x1.4a5f060000000p-3, -0x1.855d300000000p-7, 0x1.834b3e0000000p-4, -0x1.3d7c6a0000000p-8, 0x1.5670240000000p-6, 0x1.05e9de0000000p-4, 0x1.4c19d80000000p-4, -0x1.e7f7ae0000000p-7, 0x1.f27d200000000p-5, 0x1.5ed2e40000000p-4, 0x1.8b8dc40000000p-7, -0x1.2e512c0000000p-5, 0x1.2d1d920000000p-3, 0x1.cc13d60000000p-4, 0x1.4838200000000p-8, 0x1.5bcc120000000p-6, 0x1.f077e20000000p-5, 0x1.a3dc960000000p-5, 0x1.9103380000000p-4, 0x1.d829a60000000p-14, -0x1.da35d60000000p-6, 0x1.25e2ee0000000p-3, -0x1.1926a60000000p-5, -0x1.8c08bc0000000p-9, 0x1.c2e6600000000p-5, 0x1.c93c000000000p-5, 0x1.1a31ea0000000p-5, 0x1.61cf000000000p-4, 0x1.93c4f60000000p-4, 0x1.65d9b20000000p-4, -0x1.e4204a0000000p-6, 0x1.25a9480000000p-5, 0x1.382a580000000p-5, -0x1.47c5580000000p-4, -0x1.090c220000000p-6, -0x1.15c8fa0000000p-5, 0x1.0000000000000p+0, 0x0.0p+0, +}; + +const _weights: [350208]u8 align(@alignOf(f32)) = @embedFile("drone_gru_weights.bin").*; +pub const const_blob_f32: []const f32 = std.mem.bytesAsSlice(f32, &_weights); +pub const clip_lo = [_]f64{}; +pub const clip_hi = [_]f64{}; +pub const gemm_alpha = [_]f64{ 0x1.0000000000000p+0, 0x1.0000000000000p+0 }; +pub const gemm_beta = [_]f64{ 0x1.0000000000000p+0, 0x1.0000000000000p+0 }; +pub const elu_alpha = [_]f64{}; +pub const leaky_relu_alpha = [_]f64{}; +pub const layernorm_eps = [_]f64{}; +pub const output_offsets = [_]usize{0}; +pub const state_offsets = [_]usize{0}; diff --git a/src/shinro/runtime/tests/graphs/drone_gru_weights.bin b/src/shinro/runtime/tests/graphs/drone_gru_weights.bin new file mode 100644 index 0000000..9ea0db2 Binary files /dev/null and b/src/shinro/runtime/tests/graphs/drone_gru_weights.bin differ diff --git a/src/shinro/runtime/tests/graphs/go2_data.zig b/src/shinro/runtime/tests/graphs/go2_data.zig new file mode 100644 index 0000000..9426664 --- /dev/null +++ b/src/shinro/runtime/tests/graphs/go2_data.zig @@ -0,0 +1,10 @@ +// Test vectors for `go2` — generated by scripts/gen_lower_fixtures.py. +// Produced by shinro.codegen.interpret on 8 seeded inputs (seed=0). +pub const n_samples = 8; +pub const n_in = 45; +pub const n_out = 12; +pub const n_state = 0; +pub const tol = 1e-12; +pub const inputs = [_]f64{ 0x1.9bfe2762c06cfp-7, -0x1.b0e1975fba2e0p-7, 0x1.06512e9ed59f1p-4, 0x1.57bc98a03dd8dp-7, -0x1.b6d2027d6d315p-5, 0x1.2837fab0bdb1fp-5, 0x1.0b0f285640cfdp-3, 0x1.83eca305496e9p-4, -0x1.203ffce488c20p-4, -0x1.0328877b0a096p-3, -0x1.fe9620e9b2192p-5, 0x1.0ed57cfa270b6p-8, -0x1.dc2a92cf69f38p-3, -0x1.6677e007db798p-6, -0x1.fe533b537d0cap-4, -0x1.2befcc209b8c6p-4, -0x1.bddb61a62a154p-5, -0x1.031cf35770cedp-5, 0x1.51352e25a34c7p-5, 0x1.ab03732bd6a85p-4, -0x1.a52eb0aff6340p-7, 0x1.17da0a3dc06c0p-3, -0x1.1076b78cf51b3p-4, 0x1.1ff50130d86c2p-5, 0x1.720fb704f8180p-4, 0x1.340f3b3719df1p-7, -0x1.30898c00eb958p-4, -0x1.7989e92b13bedp-4, -0x1.76f81025aec04p-5, 0x1.68c48759df4e0p-6, -0x1.9d8a23bf97e0dp-4, -0x1.56b6985474568p-6, -0x1.04dfcf41d7ca3p-6, 0x1.bb0f8a3aeabc5p-5, 0x1.5fb28fc6190ddp-6, 0x1.231f0f0a4baecp-5, -0x1.0bcee6176cec5p-4, -0x1.a8b7cbe42cca0p-7, 0x1.411dc947a5bd5p-4, 0x1.31dacd860a719p-3, -0x1.01db4b83205d9p-3, 0x1.360d34f0e9b4ep-3, 0x1.13a2a227b546cp-3, 0x1.4006703666849p-4, 0x1.b148bb1672907p-6, -0x1.012a62c6164ebp-5, 0x1.2a9a465a25703p-3, 0x1.9175fdc0b112ep-3, 0x1.70f98de4539abp-3, 0x1.0d554ff04df24p-3, 0x1.24c41ab33c6ddp-5, -0x1.eeed644e14398p-4, -0x1.d30cb9bb828aap-12, 0x1.0ce462dadfe1bp-4, -0x1.07db3ed9c8ea0p-3, 0x1.43af1a1482f70p-5, 0x1.6024f363328c0p-5, 0x1.1d195e99a9affp-4, -0x1.e503c4a2ecceap-4, -0x1.0f088b2a89edbp-4, -0x1.65871aea90d85p-5, -0x1.df269edab14cap-4, 0x1.6438f87663b62p-3, -0x1.96400481433d5p-5, 0x1.0d7dee7fb54b4p-5, -0x1.a7a52fa94e31fp-6, 0x1.444b9536d8b24p-3, 0x1.0e68f12ebe9f9p-3, 0x1.036bd602fd797p-4, -0x1.c34760fb083d2p-3, 0x1.54fa224a00167p-8, 0x1.1809b1702de37p-4, 0x1.9b3900577e0d2p-4, -0x1.fa307fdcc2472p-5, 0x1.7525de8ebf985p-3, -0x1.0e6c9c7a44209p-3, -0x1.0ef63d9e88c83p-4, 0x1.7eff18fe8515bp-4, 0x1.417bfc35b2fb8p-8, 0x1.9a170a50684edp-3, 0x1.34deae29a8f2cp-6, -0x1.035b366f08a34p-4, -0x1.354cce56d77acp-5, -0x1.beeef69087e94p-4, -0x1.05ab3ce780ae1p-3, 0x1.02376f99653cdp-4, 0x1.dc174df92c0ccp-5, 0x1.09202a59cc623p-3, -0x1.351626f7bbd87p-4, 0x1.59ede07623eecp-3, -0x1.d6db242863544p-6, 0x1.427056368d234p-3, -0x1.6289c53f6d498p-5, -0x1.2d41034bc87d9p-4, 0x1.993f940bed753p-6, 0x1.a67bb1eaff0e7p-4, 0x1.07cc4fa88b9b0p-6, -0x1.dfaa4b61852ccp-5, -0x1.12ae8a46f7c28p-3, -0x1.1f0805e633dd5p-3, 0x1.9bcc3c01832cdp-5, 0x1.9562eef09eb78p-4, -0x1.0d2e258e4e42bp-6, -0x1.b80f521019b97p-4, 0x1.65991ad5a9d96p-4, -0x1.0639849ed61f9p-3, -0x1.24129becf600cp-4, 0x1.fcbce223cc42ap-5, -0x1.ccd43399823d2p-3, 0x1.3c8393d24a84cp-5, -0x1.dc7aeca145247p-5, 0x1.66167456d5c28p-7, -0x1.f01e15f004bafp-8, 0x1.4b24ebeb4b2c6p-6, 0x1.1c5534098839cp-4, -0x1.36a0d4fd6a393p-4, 0x1.230461db3a160p-3, 0x1.296873bbc666ap-4, 0x1.5997c831daf38p-4, 0x1.dd20d7650e6dfp-4, 0x1.42989c57e80a8p-4, 0x1.59bc108d5660cp-4, 0x1.ef690897bccc7p-8, -0x1.24340a7707f65p-3, -0x1.ba840a683e55dp-7, -0x1.3b3175555d0b5p-4, -0x1.2360a4c5243aep-3, 0x1.a772f51cffee4p-6, -0x1.d1c17665834c7p-5, -0x1.a5ced2640e4b2p-4, -0x1.ab36970dc294cp-4, 0x1.b7c64879d739fp-6, 0x1.25d2f5a55f9a9p-5, 0x1.0ed6dbb26649fp-3, -0x1.6cc3c27f8e501p-10, 0x1.aabcd11596275p-4, 0x1.1f2f0fe90e264p-3, 0x1.d71b9bb397f25p-4, -0x1.e46a0ba20c6c0p-3, 0x1.f744d371c5284p-4, 0x1.16377a5b2f3e6p-5, 0x1.5b274b44c1fd3p-5, 0x1.301c083b60e16p-5, 0x1.398dfe92271dap-5, 0x1.05aa045f8e641p-5, -0x1.2605938745a8ap-5, -0x1.857474ec5af39p-3, -0x1.64e44bb883784p-7, -0x1.49356486a3cffp-4, 0x1.ba6f57d1e5c65p-4, -0x1.d91d737c5aa8fp-6, 0x1.118834399eb74p-7, -0x1.5bffa43621bf8p-4, -0x1.a24d4b00b8895p-5, -0x1.2e55111b4dd43p-10, -0x1.3034703ef6263p-3, 0x1.eca47a4ea6e0cp-6, -0x1.5b93dafa829ffp-7, -0x1.e5abbba78c12dp-4, -0x1.eb2878a40f860p-3, 0x1.a44ad4b3b563fp-5, -0x1.e78fcae077ebfp-6, -0x1.b22ed20467e94p-5, -0x1.82ea6e4ce942ep-6, 0x1.7403a7600b559p-3, -0x1.466029578f1dfp-8, 0x1.1bd5811643b44p-7, -0x1.308d72319ea8ep-3, 0x1.516002ac568dap-3, 0x1.77cd968562cf3p-4, 0x1.b5043ac132ef7p-4, 0x1.386d922582168p-8, 0x1.7776389f8eb70p-4, 0x1.2fe13090e9a23p-5, 0x1.f65311f223e7cp-5, -0x1.f2b4b4f3c6f7cp-7, -0x1.2dda2d2bd8d5ap-3, 0x1.a56b3299dbfd0p-4, -0x1.8c479c9ea7ad6p-3, -0x1.891cbbe773b36p-6, -0x1.4f16f2f96d7fbp-6, -0x1.ab27cfbfba87dp-4, 0x1.f6453dbcc1ca2p-5, -0x1.48385de637c5fp-6, -0x1.65e1eda383fa0p-5, 0x1.a9dab66ba9fbcp-5, -0x1.8669de6a1a943p-5, 0x1.1c768da562306p-3, 0x1.1fe978ba5c533p-5, -0x1.8492d652c6ff0p-5, -0x1.8e2f7ac54afc3p-3, -0x1.0bd3ee498b3d3p-3, 0x1.bd2a77bafc5e8p-4, -0x1.4ba3879c5cf79p-8, -0x1.cfdf4271bcbffp-6, 0x1.5089b5d1d138dp-3, -0x1.06afc2bc6de0ep-3, -0x1.dfc557b64a822p-5, -0x1.8324d1b3beb78p-5, 0x1.e053d71b8726dp-5, -0x1.0fc8b55a56537p-4, -0x1.f6830bfb74adcp-5, -0x1.48bc0e83da40cp-3, 0x1.2abdd3fc2e9b4p-4, 0x1.4a31d6a1583e6p-4, -0x1.863f71e21f007p-5, 0x1.0b9dbd1b12ebep-6, -0x1.08bbe2920ac46p-3, -0x1.828263de30f50p-5, 0x1.1a34509df2be5p-3, 0x1.bcc33131ab584p-7, 0x1.d92995ce20f22p-3, -0x1.426f244524458p-4, 0x1.db5e766711e37p-5, -0x1.4051166b03001p-6, 0x1.cf849a5862235p-5, -0x1.7a153b1d80852p-11, -0x1.cbbbc62282872p-5, -0x1.6360362d28299p-4, 0x1.39f6504105119p-2, -0x1.fae37a33c7ccfp-8, -0x1.9d031999582e8p-3, -0x1.09aab3fe93ad8p-4, 0x1.15b99e556b0aap-4, -0x1.999b5e5a689b8p-5, 0x1.169e8fd61cfeap-3, 0x1.9a9513bf1737cp-4, -0x1.f32ee8f069fe7p-7, -0x1.82d6dc62cb174p-5, -0x1.9b9105a6acc75p-4, -0x1.1eb4cfcc0c426p-4, -0x1.2db31fa66a08dp-3, 0x1.ed521ac5b178ap-4, 0x1.45c6888ebe086p-3, -0x1.0141cfc6fe31ap-3, -0x1.e40470d7b3898p-4, -0x1.6a30f457056f3p-3, -0x1.8acb70fe91c98p-4, -0x1.3e16c164bfcb4p-2, -0x1.d3e0a142a1034p-4, 0x1.099bb7d641f2ep-3, -0x1.1b2cc89d5c8c4p-5, 0x1.5e09a6e0989b0p-4, -0x1.90903eb976a2cp-5, 0x1.6895ac6fc71a6p-3, 0x1.4666140ba53b5p-6, -0x1.38efafe59c4aep-5, 0x1.055e43adcc219p-2, -0x1.09ceae23e6177p-5, -0x1.f4368cad18b5ap-4, 0x1.4acf3160fc42ep-6, -0x1.fd04c41bf2958p-9, 0x1.b4c43bc46ef4ap-4, -0x1.798052475d131p-4, 0x1.499cafa52fe38p-4, 0x1.5d4928748769ep-4, -0x1.117c16448167fp-4, 0x1.0b757fa56b9f5p-6, -0x1.5446a8093e6a8p-4, 0x1.e06be6ffdee8ap-3, -0x1.206a6272e6a27p-4, -0x1.732898fa460f4p-5, -0x1.b491378b77342p-4, -0x1.1b8ae4776b64fp-5, -0x1.3412b1feb1d90p-11, 0x1.3a7c86aa72809p-4, -0x1.f41c543e63dd8p-5, -0x1.305f3eec6f462p-6, -0x1.2218d6731aa38p-3, -0x1.52e769675b6d8p-4, 0x1.1a31d776bef54p-2, 0x1.aa7e4318d1a2dp-4, -0x1.40123fe54cae4p-4, -0x1.11e621eb4cb92p-3, -0x1.8f99463324b77p-4, -0x1.1c4e72725c8a5p-9, 0x1.c72f1f0d93234p-9, -0x1.30e3ddbbe2e43p-4, -0x1.077d8e2ece327p-3, 0x1.234d99220f735p-3, 0x1.72054e0473ddbp-5, -0x1.32d89b6d5983ap-5, -0x1.698804c6d2748p-6, -0x1.b1ca960d60c24p-5, -0x1.2ca6ab7415d5cp-2, 0x1.7b002c3ce870ap-7, -0x1.b67eb7adb1bdfp-4, -0x1.9ab311b418055p-4, -0x1.0640611337468p-4, 0x1.2bf36678c8996p-4, -0x1.df730d21b6dccp-4, -0x1.25bda7e20c2f6p-3, 0x1.06155a5b6dd03p-4, 0x1.34fd501746211p-4, -0x1.88c77cb669c2bp-4, 0x1.ccb757643908cp-5, -0x1.ddcf81c6f09bfp-6, 0x1.eda3191ef6e7ap-6, -0x1.023ea2638c96dp-3, 0x1.55275021a3b94p-4, 0x1.ecdad89a7aaf5p-4, 0x1.04f1f87379639p-4, 0x1.c9646071b29cfp-5, -0x1.8247ee0ad2fd2p-2, 0x1.ab040a3716067p-6, -0x1.4d84509b2dcabp-9, -0x1.e1d6b6257ce94p-7, -0x1.0248e50734683p-4, 0x1.6ad703a8e5dd2p-8, 0x1.519b48b6d7ebep-5, -0x1.b030c61099fafp-6, -0x1.7b8e1d5801020p-5, 0x1.f7b508802f52fp-4, -0x1.c4c2245945a3ap-4, 0x1.a5f39a0721fb2p-4, 0x1.21b085bb2f942p-6, -0x1.49718f43f640ap-4, -0x1.db1b3900518ccp-6, -0x1.78d4523a92790p-4, 0x1.1481a52ed04b7p-4, 0x1.1d00499fa0eefp-5, -0x1.c8209f0906ccfp-5, -0x1.c377f72bfc2a2p-4, 0x1.ee54e6db4a194p-6, 0x1.88252831acf00p-4, -0x1.7504d9e2728f3p-7, 0x1.56b6e0de75fc2p-5, -0x1.340a9becdc8a3p-5, 0x1.bad25100b21adp-8, -0x1.dd3ce8753ec38p-6, 0x1.e1c236b16dd94p-6, -0x1.35338fa64f7fep-3, 0x1.07dc45af3044fp-4, -0x1.78b8ac3827e8dp-6, 0x1.25c590086f4cfp-5, -0x1.16c834d97ce4fp-5, 0x1.06709c640fec5p-5, -0x1.b7525c8a9fa68p-4, 0x1.e713e0b27385fp-4, -0x1.5ce2cc68f1aa0p-3, -0x1.a9ac16838961fp-4, 0x1.821d838947028p-6, 0x1.2b9710cb42495p-3, 0x1.c7aea042b4e8ap-6, -0x1.962c57b215631p-6, -0x1.23dbc41f43f2ap-3, -0x1.39633f7494160p-6, -0x1.04882e793e289p-9, 0x1.5a3a7c42b359bp-3, 0x1.fda51d829a7d8p-5, -0x1.392881284a9bap-3, 0x1.9f1598883a91cp-3, -0x1.43979335f7463p-5, -0x1.683a08f47cbc6p-4, 0x1.2e0b2e8e7d98bp-3, -0x1.4614505389021p-8, -0x1.2cf9e8dc244f8p-5, 0x1.66757eaeb80d4p-6, 0x1.5a110280c0eedp-4, 0x1.96ded9b3453adp-4 }; +pub const outputs = [_]f64{ -0x1.6e222ae0ec137p-2, 0x1.d75cb79acd866p-2, 0x1.7d0e06515aa06p-2, -0x1.8db1d77f9c525p-4, 0x1.e82b8f6e44b76p-2, 0x1.160521cdb2cd8p+0, 0x1.b9216372d04fcp-2, 0x1.1beac37007d26p-2, 0x1.55432eb977faep-2, -0x1.97c99a4e13d70p-4, 0x1.6b8e42a518c7bp-2, 0x1.22d435b07c5e8p+0, -0x1.2dd05653f0f17p-4, 0x1.1ac43e3d3869ep-2, 0x1.4e7a59a5a8933p-2, -0x1.06f3f92c2b5aap-3, 0x1.2cf51f9f44823p-2, 0x1.fb1eb8b089691p-1, 0x1.0c5ae4da61e66p-3, 0x1.6b8b4d7856951p-2, 0x1.97c6a2322fb42p-2, 0x1.3657aef7b44aap-3, 0x1.8e058ed499f6ap-4, 0x1.e2e09366ee583p-1, -0x1.33ab3da056243p-4, 0x1.0b65fa18e9da0p-3, 0x1.1878b4bf6cf0ap-2, -0x1.07ba733a2ca2fp-2, 0x1.eb3b8b7395eb8p-2, 0x1.d8a811386a2c9p-1, 0x1.e23436735e274p-4, 0x1.f3273f9e2929ep-2, 0x1.30f1763ff7ff0p-1, 0x1.5a288f193469cp-3, 0x1.654f6f0a31db5p-3, 0x1.03d372c7e14c6p+0, -0x1.263a6cf071443p-5, 0x1.2e01f83ee7b95p-3, 0x1.6d81849e60c67p-1, -0x1.ac74ee730e290p-5, 0x1.51f482f4fc8ccp-1, 0x1.d304f13d4b180p-2, 0x1.af206e6d3ca4cp-3, 0x1.14c9791457eccp-1, 0x1.06cd2e5a89870p-1, 0x1.10c00433df25ep-2, 0x1.04a83cdbf22eep-5, 0x1.26f3e1519ec91p+0, -0x1.36265f43aae6cp-8, 0x1.30d2af8cf8448p-2, 0x1.3ff2e87efcfa7p-1, -0x1.f022b966509d1p-3, 0x1.9ffcda8a58ff8p-1, 0x1.068c21a2956c6p-1, 0x1.f5b93f340ee14p-6, 0x1.cce39620391fcp-2, 0x1.80c4a86f2d6bcp-1, 0x1.fe8a759244ab4p-4, 0x1.725c1bcfe6690p-5, 0x1.029a8ced38856p+0, -0x1.647a9f4dbd7eep-2, 0x1.adfda10381516p-2, 0x1.103be1ba249aap-1, -0x1.8fa53d6bcb2dcp-5, 0x1.5191c3725507ap-1, 0x1.1bb288ac49fd6p+0, 0x1.9ddf0ef1bd6aep-3, 0x1.bbf162f87add9p-3, 0x1.66d8b21718745p-2, 0x1.958b80b2fd16cp-4, 0x1.7f4637e8f9642p-4, 0x1.d3363d9e8d346p-1, -0x1.5e067ae4b9feap-2, 0x1.1af2229307be6p-2, 0x1.3c04512b8946dp-2, -0x1.2114361f8911cp-1, 0x1.525442c7b72d6p-1, 0x1.c50f3cd0fa3a0p-1, 0x1.94db0358a3e12p-2, 0x1.8172fce8b3aacp-1, -0x1.98228c022cae0p-4, -0x1.446341f609100p-8, 0x1.c35b7f48daff6p-3, 0x1.15e46657dc4a2p+0, -0x1.af76620de0eebp-3, 0x1.5e269596764e8p-3, 0x1.4a496f2f63f8cp-3, -0x1.3481c6ae23e97p-2, 0x1.feeee3b74738bp-2, 0x1.de658e6cb7018p-1, 0x1.4f5757ed9e3a0p-2, 0x1.b75e434f3d69ep-2, 0x1.ce7f1b1187402p-2, 0x1.7ab16d77aa374p-4, 0x1.3d0c642025e84p-3, 0x1.12f74e057b00bp+0 }; +pub const states = [_]f64{}; diff --git a/src/shinro/runtime/tests/graphs/go2_graph.zig b/src/shinro/runtime/tests/graphs/go2_graph.zig new file mode 100644 index 0000000..0973a17 --- /dev/null +++ b/src/shinro/runtime/tests/graphs/go2_graph.zig @@ -0,0 +1,116 @@ +// Test fixture `go2` — real Unitree Go2 velocity MLP (4xGemm + 3xElu + obs norm). +// Generated by scripts/gen_lower_fixtures.py from /mnt/E/github-projects/shinro-bench/tasks/policies/models/go2/policy.onnx — DO NOT EDIT. +const std = @import("std"); + +pub const Op = enum { + cst, + cst_f32, + inp, + out, + matmul, + add, + sub, + mul, + div, + ne, + neg, + transpose, + inv, + reshape, + clip, + where_op, + any, + copy, + tanh, + relu, + exp, + argmax, + one_hot, + slice, + sin, + cos, + stack, + solve_qp, + abs, + sign, + pow, + lt, + min, + gemm, + sigmoid, + softmax, + gelu, + elu, + layernorm, + lstm, + gru, + rnn, + concat, + gather, + sqrt, + log, + mod, + leaky_relu, +}; + +pub const Node = struct { + op: Op, + inputs: []const usize, + rows: usize, + cols: usize, + aux: usize, + vec: bool, +}; + +pub const buf_len = 1987; +pub const has_solve_qp = false; +pub const n_outputs = 1; + +pub const offsets = [_]usize{ + 0, 45, 45, 90, 90, 135, 135, 135, 647, 1159, 1159, 1159, 1415, 1671, 1671, 1671, 1799, 1927, 1927, 1927, 1939, 1951, 1951, 1963, 1963, 1975, +}; + +pub const nodes = [_]Node{ + .{ .op = .inp, .inputs = &.{}, .rows = 45, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 45, .aux = 0, .vec = false }, + .{ .op = .sub, .inputs = &.{ 0, 1 }, .rows = 1, .cols = 45, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 45, .aux = 45, .vec = false }, + .{ .op = .div, .inputs = &.{ 2, 3 }, .rows = 1, .cols = 45, .aux = 0, .vec = false }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 512, .cols = 45, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 512, .cols = 1, .aux = 90, .vec = true }, + .{ .op = .gemm, .inputs = &.{ 4, 5, 6 }, .rows = 1, .cols = 512, .aux = 1, .vec = false }, + .{ .op = .elu, .inputs = &.{7}, .rows = 1, .cols = 512, .aux = 0, .vec = false }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 256, .cols = 512, .aux = 23040, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 256, .cols = 1, .aux = 602, .vec = true }, + .{ .op = .gemm, .inputs = &.{ 8, 9, 10 }, .rows = 1, .cols = 256, .aux = 3, .vec = false }, + .{ .op = .elu, .inputs = &.{11}, .rows = 1, .cols = 256, .aux = 1, .vec = false }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 128, .cols = 256, .aux = 154112, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 128, .cols = 1, .aux = 858, .vec = true }, + .{ .op = .gemm, .inputs = &.{ 12, 13, 14 }, .rows = 1, .cols = 128, .aux = 5, .vec = false }, + .{ .op = .elu, .inputs = &.{15}, .rows = 1, .cols = 128, .aux = 2, .vec = false }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 12, .cols = 128, .aux = 186880, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 12, .cols = 1, .aux = 986, .vec = true }, + .{ .op = .gemm, .inputs = &.{ 16, 17, 18 }, .rows = 1, .cols = 12, .aux = 7, .vec = false }, + .{ .op = .reshape, .inputs = &.{19}, .rows = 12, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 998, .vec = false }, + .{ .op = .mul, .inputs = &.{ 20, 21 }, .rows = 12, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 999, .vec = false }, + .{ .op = .add, .inputs = &.{ 22, 23 }, .rows = 12, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{24}, .rows = 12, .cols = 1, .aux = 0, .vec = true }, +}; + +pub const const_blob = [_]f64{ + 0x1.89b0ca0000000p-11, 0x1.3259a60000000p-10, -0x1.73c9d20000000p-9, 0x1.0de4400000000p-6, 0x1.f340260000000p-10, -0x1.fed1b20000000p-1, 0x1.e819a40000000p-3, 0x1.35a76a0000000p-10, 0x1.2903360000000p-12, 0x1.0e36080000000p-5, 0x1.a7eecc0000000p-6, 0x1.1445600000000p-5, -0x1.76d6a00000000p-5, 0x1.1598de0000000p-5, 0x1.91eaf20000000p-5, 0x1.c4a0b00000000p-6, 0x1.c755c00000000p-6, 0x1.0cdf3e0000000p-4, -0x1.11798c0000000p-6, 0x1.e013540000000p-7, 0x1.f7a33a0000000p-5, -0x1.5d1ed80000000p-13, 0x1.b3fbb60000000p-8, -0x1.2ebe7e0000000p-5, -0x1.24c2900000000p-9, 0x1.c5840a0000000p-8, -0x1.2f418c0000000p-5, -0x1.94c4140000000p-10, 0x1.495ffc0000000p-9, -0x1.1b6b980000000p-5, 0x1.bd8c480000000p-12, 0x1.b950c00000000p-10, -0x1.1e25ec0000000p-5, -0x1.64f0f00000000p-6, -0x1.24ee5a0000000p-4, 0x1.2a016c0000000p-1, 0x1.ad98240000000p-6, -0x1.10d88c0000000p-5, 0x1.429c2e0000000p-1, -0x1.64c4f00000000p-5, 0x1.853b280000000p-4, 0x1.4646080000000p-1, 0x1.3e2ad20000000p-5, 0x1.816b6e0000000p-4, 0x1.40cbc80000000p-1, 0x1.86e9740000000p-1, 0x1.aa74d20000000p-2, 0x1.2050de0000000p-1, 0x1.0a308c0000000p-4, 0x1.02e50e0000000p-4, 0x1.5092480000000p-5, 0x1.bd8fc20000000p-2, 0x1.29a5880000000p-2, 0x1.14e0d20000000p-1, 0x1.9e04160000000p-4, 0x1.0380680000000p-3, 0x1.2278ee0000000p-3, 0x1.b060380000000p-4, 0x1.fbb5c80000000p-4, 0x1.193ddc0000000p-3, 0x1.74a0500000000p-4, 0x1.ce7c360000000p-4, 0x1.e2951c0000000p-4, 0x1.7c14840000000p-4, 0x1.dc75ee0000000p-4, 0x1.daa26a0000000p-4, 0x1.e1a7340000000p+0, 0x1.1e917e0000000p+1, 0x1.3ebd1c0000000p+1, 0x1.e8dc2c0000000p+0, 0x1.231cd60000000p+1, 0x1.37ba320000000p+1, 0x1.e8ac1a0000000p+0, 0x1.28d9aa0000000p+1, 0x1.42aeb20000000p+1, 0x1.e773820000000p+0, 0x1.28a5080000000p+1, 0x1.48dcb00000000p+1, 0x1.92f6d60000000p-2, 0x1.d1ea8e0000000p-2, 0x1.623e0c0000000p-1, 0x1.a477bc0000000p-2, 0x1.cd6fb00000000p-2, 0x1.655e640000000p-1, 0x1.9810040000000p-2, 0x1.b3cbb60000000p-2, 0x1.726e4e0000000p-1, 0x1.88d9de0000000p-2, 0x1.bbc5f40000000p-2, 0x1.7cf4d00000000p-1, 0x1.c3358c0000000p-10, -0x1.56b0040000000p-4, -0x1.5198460000000p-4, 0x1.f1f9ec0000000p-6, -0x1.7d6ea40000000p-5, 0x1.6e34d40000000p-3, 0x1.b27d8c0000000p-4, -0x1.4520ee0000000p-6, -0x1.004f880000000p-2, -0x1.94f6a00000000p-3, -0x1.c2bdce0000000p-5, 0x1.5d4b1e0000000p-6, -0x1.16ea000000000p-2, -0x1.a563ac0000000p-4, 0x1.5a35920000000p-6, -0x1.28608a0000000p-7, -0x1.59bc1c0000000p-3, -0x1.14e07e0000000p-5, -0x1.6336ac0000000p-4, -0x1.b3315c0000000p-3, -0x1.03042c0000000p-5, -0x1.1bac5e0000000p-3, -0x1.f1e4440000000p-4, -0x1.78b5040000000p-6, 0x1.9a26120000000p-4, 0x1.69f3fc0000000p-4, -0x1.4768240000000p-4, 0x1.b9453e0000000p-5, 0x1.0d2b5e0000000p-5, -0x1.0228ba0000000p-3, 0x1.91d7d40000000p-3, -0x1.248fda0000000p-3, -0x1.9e9ade0000000p-3, -0x1.207a720000000p-3, -0x1.23b2700000000p-3, 0x1.f57a780000000p-5, -0x1.43a5680000000p-3, -0x1.05f13e0000000p-2, -0x1.103a300000000p-3, 0x1.d390500000000p-5, -0x1.981fc80000000p-3, 0x1.3e7ad20000000p-3, -0x1.0101ca0000000p-2, -0x1.35b11e0000000p-3, -0x1.c4a6e60000000p-6, -0x1.7f93b00000000p-5, -0x1.a2ef7e0000000p-3, -0x1.7547a80000000p-3, -0x1.6560320000000p-3, -0x1.e232900000000p-3, -0x1.42403c0000000p-3, 0x1.b5fb920000000p-3, -0x1.6247920000000p-3, -0x1.05df0a0000000p-2, 0x1.ec9f820000000p-4, -0x1.1de6800000000p-3, -0x1.28bf000000000p-4, -0x1.27352e0000000p-4, -0x1.0da03a0000000p-2, 0x1.c4b64e0000000p-3, -0x1.f5cdfe0000000p-3, -0x1.e704700000000p-3, -0x1.df87560000000p-5, -0x1.fef4bc0000000p-6, 0x1.c11e0c0000000p-3, 0x1.6ee2cc0000000p-5, 0x1.abd4ec0000000p-4, 0x1.534cf40000000p-3, -0x1.0d1a6e0000000p-3, -0x1.c6efd80000000p-4, 0x1.cf62220000000p-5, -0x1.0ae57c0000000p-2, -0x1.049e200000000p-6, -0x1.1437100000000p-3, -0x1.d12d180000000p-4, -0x1.7177ca0000000p-3, -0x1.9b02bc0000000p-3, -0x1.724a180000000p-4, -0x1.5109e20000000p-3, 0x1.b6a6ac0000000p-5, -0x1.11cecc0000000p-2, -0x1.49e1d80000000p-3, -0x1.2893b80000000p-5, -0x1.e527280000000p-5, -0x1.55da0a0000000p-5, 0x1.1478f00000000p-6, -0x1.4353840000000p-4, 0x1.af18de0000000p-4, 0x1.4f0f280000000p-4, 0x1.2545920000000p-5, -0x1.d27e6c0000000p-4, 0x1.69caf00000000p-3, -0x1.6e54f00000000p-2, -0x1.2345460000000p-3, 0x1.5086f00000000p-3, -0x1.8f25e60000000p-3, 0x1.33b13e0000000p-3, -0x1.260a580000000p-4, -0x1.0565040000000p-3, 0x1.e772d00000000p-4, 0x1.4d666e0000000p-4, -0x1.2414e60000000p-6, -0x1.d49adc0000000p-5, -0x1.e79f7e0000000p-4, -0x1.a5e2920000000p-3, 0x1.8de9600000000p-5, -0x1.b669540000000p-4, -0x1.77a0860000000p-5, -0x1.e50cbe0000000p-3, -0x1.d20ffe0000000p-7, 0x1.1f354a0000000p-3, 0x1.0e1bc40000000p-5, 0x1.75ccc40000000p-4, 0x1.ddb62c0000000p-10, -0x1.bf544a0000000p-5, -0x1.b3e4160000000p-4, -0x1.253a920000000p-2, -0x1.4d495c0000000p-3, 0x1.371f380000000p-5, 0x1.5fee620000000p-3, 0x1.9879920000000p-3, -0x1.f0e42a0000000p-6, -0x1.8e8c560000000p-3, 0x1.8d23f80000000p-3, -0x1.2541080000000p-2, 0x1.28aba60000000p-3, -0x1.c7df1c0000000p-3, -0x1.8294d00000000p-5, -0x1.c1edd00000000p-6, 0x1.25cc700000000p-5, 0x1.4237ac0000000p-3, 0x1.1aad800000000p-5, -0x1.38f7be0000000p-2, 0x1.85ad600000000p-5, -0x1.56f8360000000p-3, 0x1.64d8540000000p-3, 0x1.4bad800000000p-4, 0x1.ff18ca0000000p-9, 0x1.83b5fa0000000p-6, -0x1.642e320000000p-3, -0x1.0b98b40000000p-3, -0x1.fef93a0000000p-3, -0x1.f139500000000p-5, -0x1.af45480000000p-4, -0x1.3f87560000000p-3, -0x1.45b3da0000000p-4, -0x1.611e580000000p-4, 0x1.04075c0000000p-3, -0x1.f77ffe0000000p-6, -0x1.96ff660000000p-5, -0x1.3a55c80000000p-2, -0x1.bf58fe0000000p-3, 0x1.d7f2140000000p-4, -0x1.e62a400000000p-6, -0x1.182aa80000000p-5, -0x1.a52ab60000000p-3, -0x1.380f8c0000000p-2, 0x1.a035c60000000p-3, 0x1.a6766a0000000p-3, -0x1.59ab7a0000000p-3, 0x1.f387dc0000000p-5, -0x1.4e96240000000p-2, -0x1.e0664a0000000p-3, 0x1.b05ec00000000p-8, -0x1.1fb77a0000000p-2, -0x1.f860320000000p-3, -0x1.3723c60000000p-3, -0x1.2c330a0000000p-2, -0x1.08fa920000000p-8, -0x1.1dd4380000000p-2, 0x1.63a4680000000p-6, 0x1.10784c0000000p-4, 0x1.26cc720000000p-3, -0x1.4bd5f00000000p-2, 0x1.869efe0000000p-4, 0x1.94b99a0000000p-3, 0x1.08bae20000000p-5, -0x1.3df3ae0000000p-3, 0x1.5ed9900000000p-7, -0x1.a181c80000000p-7, -0x1.891bba0000000p-3, -0x1.6059b20000000p-2, -0x1.04475a0000000p-3, 0x1.b8b36a0000000p-4, 0x1.7f52ce0000000p-4, -0x1.9dbe820000000p-4, -0x1.11d4800000000p-4, -0x1.3bb1e40000000p-3, -0x1.0262500000000p-3, 0x1.c7bf7a0000000p-6, -0x1.2bf04a0000000p-2, 0x1.362ca00000000p-4, -0x1.1e20900000000p-3, -0x1.47350a0000000p-7, -0x1.18d5ac0000000p-5, 0x1.2b02780000000p-4, 0x1.2fc6860000000p-4, -0x1.b428a00000000p-3, 0x1.b1e4060000000p-3, -0x1.e938c60000000p-3, -0x1.6524560000000p-5, 0x1.1c2bd00000000p-4, -0x1.1832e40000000p-5, 0x1.21f26e0000000p-3, 0x1.1dafb80000000p-4, 0x1.ee62480000000p-4, -0x1.f516500000000p-6, -0x1.d6a2160000000p-3, -0x1.9ab03a0000000p-7, -0x1.d4b1c00000000p-4, -0x1.c5dd480000000p-5, -0x1.db48860000000p-3, 0x1.4167520000000p-4, 0x1.5c83800000000p-4, -0x1.6ee7e40000000p-3, 0x1.3835200000000p-3, 0x1.20051e0000000p-4, -0x1.fa31660000000p-3, -0x1.660df00000000p-2, -0x1.4f82460000000p-3, 0x1.1b7be80000000p-4, -0x1.2c51ce0000000p-2, -0x1.2968aa0000000p-2, 0x1.c829be0000000p-3, -0x1.b2fb9c0000000p-3, -0x1.23ff640000000p-2, -0x1.1e1cca0000000p-5, 0x1.089f9e0000000p-2, 0x1.56da780000000p-3, 0x1.a2bcc20000000p-5, 0x1.4cb9180000000p-4, -0x1.0dc0c00000000p-2, -0x1.446d4a0000000p-2, -0x1.5dcda80000000p-5, -0x1.5262100000000p-5, 0x1.cb63500000000p-10, -0x1.0854c80000000p-5, -0x1.2e8dae0000000p-3, 0x1.351d680000000p-3, -0x1.439b8e0000000p-3, -0x1.76db0a0000000p-4, -0x1.03d7100000000p-3, -0x1.d22e040000000p-3, -0x1.c380900000000p-4, -0x1.331f2e0000000p-5, 0x1.22570e0000000p-4, -0x1.a623160000000p-3, 0x1.bf26c00000000p-3, -0x1.055a600000000p-2, -0x1.330e300000000p-2, 0x1.235cfa0000000p-5, -0x1.56d4d80000000p-2, -0x1.3596260000000p-3, 0x1.89a3960000000p-4, -0x1.07af0c0000000p-2, -0x1.1137e00000000p-5, -0x1.00c4ca0000000p-2, -0x1.fd64280000000p-4, -0x1.16b4920000000p-4, -0x1.a085540000000p-9, 0x1.8b78640000000p-3, -0x1.5718140000000p-5, 0x1.47e8d40000000p-5, -0x1.7272a00000000p-4, 0x1.0c26ee0000000p-3, -0x1.34764e0000000p-6, 0x1.0a24d00000000p-3, -0x1.f9bb340000000p-3, 0x1.3d74f80000000p-5, 0x1.415f840000000p-3, 0x1.6076220000000p-4, 0x1.ce7f780000000p-5, -0x1.0173040000000p-2, -0x1.51189e0000000p-3, -0x1.47be6c0000000p-4, -0x1.53a02e0000000p-4, -0x1.ba479c0000000p-3, -0x1.c8c6d60000000p-5, -0x1.76b7540000000p-6, -0x1.21fb440000000p-3, 0x1.28e5000000000p-4, 0x1.922d620000000p-5, -0x1.12be1e0000000p-6, 0x1.f687220000000p-5, -0x1.1db0ba0000000p-2, 0x1.12bb900000000p-3, -0x1.bd31800000000p-5, -0x1.55d4360000000p-3, -0x1.5b71140000000p-3, -0x1.7d4d2e0000000p-3, 0x1.c3cbde0000000p-3, -0x1.2752080000000p-3, -0x1.6a615e0000000p-3, -0x1.f8ceba0000000p-3, -0x1.89ec8c0000000p-3, 0x1.0ae6c20000000p-4, -0x1.4826280000000p-2, 0x1.c1a5fe0000000p-4, -0x1.0a89ca0000000p-3, -0x1.662ba00000000p-5, -0x1.4ed2040000000p-2, -0x1.6c6fc80000000p-3, 0x1.2113160000000p-3, -0x1.7b4c380000000p-4, -0x1.7221a40000000p-4, -0x1.1d183e0000000p-2, 0x1.85ec1c0000000p-3, -0x1.2deb580000000p-10, -0x1.91970c0000000p-6, 0x1.9acc6e0000000p-5, -0x1.b4239c0000000p-5, -0x1.3f55260000000p-4, -0x1.ee0e9a0000000p-3, -0x1.97d7c40000000p-4, 0x1.77a2a60000000p-3, -0x1.ff9cf40000000p-4, -0x1.1ef9a40000000p-4, -0x1.2c9b3e0000000p-7, 0x1.ec18d40000000p-3, 0x1.56008c0000000p-5, -0x1.23928a0000000p-2, -0x1.30c8600000000p-2, -0x1.253ab80000000p-3, -0x1.98070c0000000p-6, -0x1.b477880000000p-4, 0x1.56050a0000000p-3, 0x1.a0d2060000000p-10, -0x1.127c8e0000000p-2, -0x1.09792e0000000p-3, -0x1.cbb2500000000p-3, 0x1.f308600000000p-4, 0x1.32c9440000000p-8, -0x1.2b10580000000p-2, 0x1.7d454e0000000p-5, 0x1.e02d860000000p-7, -0x1.441b9c0000000p-3, -0x1.b55f040000000p-4, -0x1.42a8480000000p-3, -0x1.c280ea0000000p-3, 0x1.0327d60000000p-3, -0x1.05b5600000000p-9, -0x1.c3e78a0000000p-4, -0x1.9da0200000000p-4, -0x1.54baec0000000p-2, -0x1.e6fb5c0000000p-4, -0x1.d49bc60000000p-4, 0x1.e320700000000p-7, -0x1.d7ce020000000p-6, 0x1.8e16ee0000000p-3, -0x1.a541dc0000000p-3, 0x1.7ce5060000000p-5, -0x1.a5ca4c0000000p-3, 0x1.9b57920000000p-3, -0x1.20760e0000000p-2, -0x1.4981180000000p-3, -0x1.4287f40000000p-3, -0x1.94e79e0000000p-6, -0x1.37b3de0000000p-4, -0x1.5d85d80000000p-2, -0x1.668e1a0000000p-3, -0x1.f22f700000000p-6, 0x1.fb37680000000p-4, 0x1.0e4c680000000p-3, -0x1.6a8e860000000p-2, -0x1.3c81580000000p-3, 0x1.efb3bc0000000p-4, -0x1.99b0c20000000p-5, -0x1.978c240000000p-3, 0x1.5551fe0000000p-3, -0x1.ad62fe0000000p-3, 0x1.a08d520000000p-4, 0x1.d987420000000p-4, -0x1.b212220000000p-3, -0x1.201bbe0000000p-2, -0x1.e0822c0000000p-3, 0x1.fb9c6c0000000p-3, -0x1.1dca940000000p-2, 0x1.26ef7c0000000p-5, -0x1.8391b60000000p-3, -0x1.ba17580000000p-4, -0x1.2528c80000000p-3, -0x1.af99bc0000000p-4, -0x1.2c9e120000000p-2, -0x1.6204660000000p-4, 0x1.ec6b2e0000000p-5, -0x1.799f1e0000000p-4, -0x1.1c09600000000p-5, -0x1.2abb260000000p-4, 0x1.ac51ee0000000p-3, -0x1.92a4e00000000p-6, -0x1.4f978c0000000p-4, 0x1.cbfbc20000000p-4, -0x1.0f440a0000000p-4, -0x1.5694620000000p-3, -0x1.33b6800000000p-2, 0x1.abcb560000000p-5, 0x1.5532f00000000p-15, 0x1.3944780000000p-4, 0x1.2478fc0000000p-3, -0x1.28b3a80000000p-3, 0x1.dae6960000000p-3, 0x1.d343580000000p-4, -0x1.63355c0000000p-3, 0x1.2cc8060000000p-3, -0x1.cef8ba0000000p-4, -0x1.b982820000000p-5, -0x1.41bd500000000p-5, 0x1.6c4b160000000p-3, 0x1.11c3c40000000p-7, -0x1.e99f720000000p-4, -0x1.21bd760000000p-2, -0x1.55ebe20000000p-5, -0x1.107d960000000p-2, -0x1.64fc580000000p-5, 0x1.0e7a000000000p-6, 0x1.4470e60000000p-3, -0x1.111dbc0000000p-4, 0x1.e66d740000000p-5, -0x1.5737b20000000p-7, -0x1.4e86d00000000p-3, 0x1.65e9740000000p-4, -0x1.9b5b300000000p-3, -0x1.a6baf20000000p-4, -0x1.83939e0000000p-3, 0x1.26b9d40000000p-7, 0x1.21ee780000000p-3, 0x1.a3da720000000p-4, -0x1.8155340000000p-3, -0x1.0cbf940000000p-2, -0x1.1643ee0000000p-2, -0x1.2f484a0000000p-4, -0x1.16402c0000000p-2, -0x1.189a340000000p-4, -0x1.edde940000000p-3, 0x1.0e70620000000p-7, -0x1.a6ad3c0000000p-3, 0x1.ad20380000000p-8, 0x1.aef7260000000p-3, 0x1.4bf9740000000p-4, -0x1.fd65ee0000000p-4, -0x1.1d2a420000000p-4, 0x1.58b0900000000p-6, -0x1.8f78f80000000p-3, -0x1.6887ce0000000p-6, -0x1.8a93fe0000000p-5, -0x1.7970140000000p-4, -0x1.9a7ef40000000p-3, -0x1.887f120000000p-4, -0x1.5b176c0000000p-4, 0x1.0279ac0000000p-3, -0x1.6737480000000p-3, 0x1.26e1760000000p-13, -0x1.05359e0000000p-3, -0x1.059cc40000000p-5, 0x1.69fa120000000p-3, -0x1.d203da0000000p-5, -0x1.30ff1c0000000p-4, -0x1.0924d00000000p-2, -0x1.7dbb160000000p-4, -0x1.1da0b40000000p-3, -0x1.4283ac0000000p-6, -0x1.5d2ac20000000p-3, -0x1.43a98c0000000p-6, 0x1.2c8a5c0000000p-4, -0x1.8759ba0000000p-6, -0x1.601c520000000p-3, -0x1.1475f20000000p-4, -0x1.3e09100000000p-3, -0x1.f1c6640000000p-3, -0x1.f33c1e0000000p-5, -0x1.4412520000000p-2, -0x1.ed8b400000000p-3, -0x1.4361ea0000000p-4, -0x1.8d555a0000000p-3, 0x1.c409bc0000000p-4, -0x1.8ac00a0000000p-6, 0x1.cd37620000000p-4, -0x1.6964ac0000000p-6, -0x1.2534ce0000000p-4, -0x1.d0707c0000000p-10, 0x1.6255060000000p-4, -0x1.59f6740000000p-3, -0x1.f1b0f40000000p-5, -0x1.7e82160000000p-3, 0x1.066b2e0000000p-7, -0x1.5329cc0000000p-3, 0x1.69703c0000000p-4, -0x1.427ddc0000000p-5, -0x1.9939140000000p-5, 0x1.fa4a680000000p-5, -0x1.8940500000000p-3, -0x1.46ef340000000p-4, 0x1.53e6ca0000000p-4, 0x1.22c0240000000p-4, -0x1.518cc40000000p-2, -0x1.76152c0000000p-4, 0x1.a740880000000p-8, 0x1.767a3e0000000p-4, -0x1.2c2a580000000p-5, -0x1.234f800000000p-3, -0x1.97f0780000000p-3, -0x1.7fa1340000000p-3, -0x1.b2ec0c0000000p-3, -0x1.3e97200000000p-5, -0x1.49b6a20000000p-4, 0x1.2e9b4a0000000p-4, 0x1.be4aea0000000p-5, 0x1.15d2280000000p-5, -0x1.8e25d40000000p-6, -0x1.36acb20000000p-4, -0x1.8321cc0000000p-3, 0x1.00bb020000000p-3, -0x1.a6c6e20000000p-4, -0x1.0214980000000p-4, -0x1.57c47a0000000p-3, -0x1.3ba77a0000000p-3, -0x1.6826880000000p-4, -0x1.c8c9560000000p-3, 0x1.07b8320000000p-9, 0x1.6c1f1c0000000p-8, -0x1.3ed2860000000p-5, -0x1.37ffdc0000000p-3, 0x1.a422e00000000p-9, 0x1.80cee20000000p-10, 0x1.321d9c0000000p-7, -0x1.fbc5a00000000p-4, -0x1.9fead00000000p-4, -0x1.27fd6e0000000p-4, -0x1.017e940000000p-3, -0x1.405de40000000p-6, -0x1.ee82300000000p-5, -0x1.f33eb80000000p-4, -0x1.5951180000000p-4, -0x1.b536ee0000000p-3, -0x1.8b4f260000000p-4, 0x1.3ba9120000000p-7, -0x1.3509140000000p-4, -0x1.a9820e0000000p-5, -0x1.d263da0000000p-9, -0x1.1e9d340000000p-4, -0x1.0b652e0000000p-5, -0x1.f0fc100000000p-5, -0x1.10b3fc0000000p-4, -0x1.c7866c0000000p-5, -0x1.1281e00000000p-3, 0x1.68d5c20000000p-6, -0x1.6ba7120000000p-5, -0x1.6f20340000000p-4, -0x1.07db700000000p-4, -0x1.9d8cd40000000p-6, -0x1.e2e1440000000p-8, -0x1.1037ba0000000p-3, -0x1.53ea4c0000000p-4, 0x1.1afdc80000000p-6, -0x1.04ca880000000p-4, -0x1.65bb200000000p-5, -0x1.3d5f6c0000000p-5, -0x1.7b60be0000000p-4, -0x1.8c8cb40000000p-3, -0x1.57cee60000000p-4, -0x1.59b3ea0000000p-4, -0x1.c9e3b00000000p-3, -0x1.8e911c0000000p-4, -0x1.b2de320000000p-7, -0x1.ca87d60000000p-5, -0x1.07b8fa0000000p-3, 0x1.7a054e0000000p-9, -0x1.05ad2a0000000p-4, -0x1.0eee480000000p-5, 0x1.ab9d760000000p-7, 0x1.ed84f20000000p-7, -0x1.10c55c0000000p-5, -0x1.922a540000000p-4, -0x1.03481e0000000p-5, -0x1.39c92e0000000p-9, 0x1.bec0580000000p-6, -0x1.8db90e0000000p-8, 0x1.3b74ec0000000p-5, 0x1.713ca40000000p-6, -0x1.c9a7700000000p-6, -0x1.a26b660000000p-3, -0x1.9412fa0000000p-6, -0x1.d9121a0000000p-4, -0x1.b4ad9e0000000p-6, -0x1.0b5c8c0000000p-7, -0x1.eec0760000000p-5, -0x1.0852620000000p-3, 0x1.e0340c0000000p-6, -0x1.d6dac60000000p-4, -0x1.dd72980000000p-8, 0x1.1af7f80000000p-4, -0x1.d24ed20000000p-3, -0x1.04a8660000000p-4, -0x1.4f68760000000p-4, -0x1.55e1020000000p-3, 0x1.662fe80000000p-8, -0x1.731aee0000000p-3, -0x1.84c7100000000p-5, -0x1.2b8ecc0000000p-3, -0x1.e854620000000p-4, 0x1.b2c5e80000000p-4, -0x1.d6e4fc0000000p-6, -0x1.61143c0000000p-4, -0x1.78f6c80000000p-4, -0x1.5d67b40000000p-5, -0x1.9166a40000000p-10, -0x1.457c080000000p-3, -0x1.64a9800000000p-7, -0x1.9bbcce0000000p-4, -0x1.428b040000000p-3, -0x1.d9787e0000000p-6, -0x1.e6c4d20000000p-4, -0x1.0b679c0000000p-6, -0x1.bc6fe40000000p-5, -0x1.3ef8780000000p-5, -0x1.2521fc0000000p-3, -0x1.25997c0000000p-4, -0x1.83f0260000000p-3, 0x1.47f1e80000000p-6, 0x1.68e1760000000p-5, -0x1.27a2280000000p-3, 0x1.3bb3c00000000p-5, -0x1.c7acb60000000p-7, 0x1.63cdde0000000p-4, -0x1.09b1e20000000p-3, -0x1.79fe6a0000000p-7, -0x1.5485b00000000p-4, -0x1.7088660000000p-5, -0x1.c3815e0000000p-5, -0x1.45de120000000p-4, 0x1.719b220000000p-5, -0x1.ec0bce0000000p-3, -0x1.32f3880000000p-3, -0x1.e2d5bc0000000p-5, -0x1.9203a80000000p-3, -0x1.32059a0000000p-3, -0x1.f0e9000000000p-9, -0x1.9c28ec0000000p-4, -0x1.4a72d40000000p-3, -0x1.bb7e920000000p-7, 0x1.05d3a40000000p-4, -0x1.56331e0000000p-4, -0x1.da05740000000p-6, 0x1.9e32b00000000p-10, -0x1.03d99e0000000p-4, -0x1.46dbae0000000p-3, -0x1.444eb40000000p-4, 0x1.5f20460000000p-7, -0x1.f488180000000p-7, 0x1.072ade0000000p-6, -0x1.b2ee880000000p-5, 0x1.aa83fc0000000p-6, -0x1.39972c0000000p-4, -0x1.9078980000000p-5, -0x1.8798c80000000p-4, -0x1.4eeb420000000p-3, -0x1.7d66940000000p-3, -0x1.db20440000000p-7, -0x1.d70f160000000p-6, 0x1.1b5aec0000000p-3, -0x1.dba1e20000000p-10, -0x1.cc22ba0000000p-4, -0x1.89380a0000000p-6, 0x1.155e9a0000000p-8, -0x1.a5b7e20000000p-4, -0x1.5e42220000000p-4, 0x1.54deb60000000p-10, -0x1.9bad9c0000000p-4, -0x1.f01c560000000p-8, -0x1.f49b9a0000000p-4, 0x1.3a9a540000000p-5, -0x1.729f720000000p-4, -0x1.0dff7a0000000p-4, -0x1.dfc08c0000000p-4, -0x1.255c780000000p-5, 0x1.0beec60000000p-8, -0x1.45161e0000000p-8, -0x1.2058540000000p-3, -0x1.042f020000000p-3, -0x1.1c64780000000p-4, -0x1.307f560000000p-4, -0x1.15b8800000000p-5, 0x1.166e360000000p-6, -0x1.40ad000000000p-3, -0x1.ce0f980000000p-5, -0x1.31cf6c0000000p-4, -0x1.3c8e160000000p-4, -0x1.03f7c00000000p-3, -0x1.5fcce40000000p-4, -0x1.67d20a0000000p-5, -0x1.7a23f20000000p-4, -0x1.6ae75c0000000p-5, -0x1.24f2460000000p-9, -0x1.3f75e40000000p-7, 0x1.7405860000000p-9, -0x1.2c3ee80000000p-5, -0x1.bbd3260000000p-5, 0x1.66331a0000000p-9, 0x1.44e3ba0000000p-6, -0x1.d061de0000000p-6, -0x1.6762680000000p-8, 0x1.6f008a0000000p-7, -0x1.8b602c0000000p-2, -0x1.0b60a40000000p-7, -0x1.40c31e0000000p-5, 0x1.ff6da40000000p-11, 0x1.262ebe0000000p-11, -0x1.1213ca0000000p-7, 0x1.e6eeba0000000p-8, -0x1.1510380000000p-5, -0x1.5dfc260000000p-3, -0x1.6cfa6e0000000p-4, -0x1.c148280000000p-4, 0x1.d657160000000p-5, -0x1.6c68b00000000p-4, -0x1.8478820000000p-4, -0x1.c81ee40000000p-8, -0x1.ae2a4c0000000p-5, -0x1.3952280000000p-6, -0x1.93c6f40000000p-5, -0x1.78155a0000000p-4, 0x1.c204440000000p-6, 0x1.82a5f40000000p-9, 0x1.83d4420000000p-7, -0x1.82b9100000000p-6, -0x1.f2d6680000000p-4, -0x1.01f2580000000p-4, -0x1.562cb80000000p-5, -0x1.7c1b7c0000000p-4, 0x1.cb6b080000000p-7, -0x1.800aaa0000000p-4, -0x1.be8b000000000p-4, -0x1.55feec0000000p-6, -0x1.39f47a0000000p-5, -0x1.9ea0140000000p-5, -0x1.7d9e240000000p-4, -0x1.ed0a060000000p-6, -0x1.45aaa60000000p-4, 0x1.4312980000000p-6, -0x1.1c48d20000000p-4, -0x1.d6d3280000000p-5, -0x1.262c460000000p-3, -0x1.4cf99c0000000p-5, -0x1.c13b220000000p-4, -0x1.1302940000000p-4, -0x1.4f92da0000000p-5, -0x1.af146c0000000p-5, 0x1.41910c0000000p-7, -0x1.05e5fc0000000p-5, -0x1.877ade0000000p-4, -0x1.22d9280000000p-3, -0x1.26e2e80000000p-4, -0x1.e5b27a0000000p-6, -0x1.307f240000000p-5, 0x1.aac97c0000000p-5, 0x1.8004620000000p-6, 0x1.0bfc0a0000000p-7, -0x1.b3c0c60000000p-5, -0x1.ad656e0000000p-5, -0x1.9af51e0000000p-7, -0x1.f921340000000p-4, -0x1.61ac160000000p-5, -0x1.44c4a40000000p-5, -0x1.81c2a80000000p-5, -0x1.fec4e80000000p-5, -0x1.8cbcf00000000p-3, -0x1.9946900000000p-4, -0x1.af542c0000000p-4, 0x1.d3a6980000000p-4, -0x1.e1c0be0000000p-3, 0x1.2a53b40000000p-4, 0x1.0ebf8a0000000p-6, 0x1.26a2e60000000p-4, -0x1.eb22b60000000p-6, 0x1.37f8360000000p-5, 0x1.8e6b480000000p-3, 0x1.bda53e0000000p-6, -0x1.c30f640000000p-4, -0x1.ec69560000000p-4, 0x1.2406640000000p-6, 0x1.3169600000000p-6, 0x1.3ad6b00000000p-9, -0x1.9ea5980000000p-5, -0x1.0c13ec0000000p-4, 0x1.3cbd6c0000000p-5, -0x1.779eca0000000p-4, -0x1.fe816a0000000p-3, 0x1.469f7e0000000p-5, -0x1.1a63e00000000p-4, -0x1.5f53320000000p-2, 0x1.19285e0000000p-4, -0x1.f2a4220000000p-4, -0x1.290df80000000p-2, 0x1.4f5ad20000000p-4, 0x1.15a2160000000p-5, -0x1.5d9d7e0000000p-3, 0x1.2363220000000p-7, 0x1.2f37280000000p-4, -0x1.2eeb0a0000000p-5, -0x1.3bfed00000000p-4, 0x1.47cffa0000000p-4, -0x1.f61dec0000000p-5, -0x1.5d8c5a0000000p-4, -0x1.5662420000000p-5, -0x1.9a66560000000p-6, -0x1.f4b41a0000000p-3, -0x1.e5196a0000000p-4, -0x1.ddf2ea0000000p-4, -0x1.b83c3e0000000p-2, 0x1.0faf880000000p-4, 0x1.0cbf280000000p-3, 0x1.3e50d40000000p-5, -0x1.3dbce60000000p-3, -0x1.9ac39e0000000p-4, 0x1.1ce1500000000p-4, 0x1.6d34340000000p-5, -0x1.ebf64a0000000p-3, -0x1.3081a40000000p-5, -0x1.af35c20000000p-5, -0x1.2fd3960000000p-3, -0x1.8471f60000000p-4, 0x1.3157900000000p-5, 0x1.40eb3e0000000p-6, 0x1.33b3a20000000p-4, -0x1.1be29e0000000p-3, -0x1.204ff60000000p-6, 0x1.e1bb7a0000000p-5, -0x1.f041200000000p-4, -0x1.9e366a0000000p-2, 0x1.d68c9e0000000p-4, -0x1.3e68560000000p-4, 0x1.5c027a0000000p-4, -0x1.49cf9e0000000p-4, 0x1.1458800000000p-4, -0x1.34e7460000000p-2, -0x1.de18160000000p-3, 0x1.b93a100000000p-4, 0x1.4091e60000000p-5, -0x1.0d8ba40000000p-5, -0x1.3813b00000000p-5, -0x1.96b33e0000000p-4, -0x1.586eca0000000p-3, -0x1.9a1e3c0000000p-5, 0x1.5513420000000p-7, 0x1.6594f20000000p-4, 0x1.73e0560000000p-6, 0x1.cd7ca00000000p-5, -0x1.10849c0000000p-4, 0x1.01e7380000000p-4, -0x1.6410760000000p-2, -0x1.3335ea0000000p-2, 0x1.711c8e0000000p-3, 0x1.81cc940000000p-5, 0x1.27642e0000000p-4, -0x1.5906a40000000p-4, 0x1.f6b54a0000000p-11, -0x1.3c6b8e0000000p-3, -0x1.9549480000000p-4, 0x1.4319fe0000000p-5, 0x1.295f520000000p-6, -0x1.42b5140000000p-4, 0x1.e75df80000000p-5, -0x1.4332c60000000p-4, -0x1.d813b20000000p-8, 0x1.3485f80000000p-4, -0x1.67bf020000000p-7, 0x1.5455700000000p-6, 0x1.32aaf60000000p-3, -0x1.b9a63c0000000p-5, -0x1.2c77500000000p-3, -0x1.65063e0000000p-5, -0x1.9e52620000000p-3, -0x1.3069a80000000p-4, 0x1.6a48d00000000p-8, -0x1.2c19960000000p-4, -0x1.3390880000000p-6, -0x1.9e7c3c0000000p-4, -0x1.8dd62c0000000p-4, 0x1.13f52a0000000p-4, 0x1.62d4400000000p-7, -0x1.2632a60000000p-8, -0x1.80c7060000000p-6, 0x1.6234600000000p-4, 0x1.4ce64e0000000p-5, -0x1.4515bc0000000p-3, 0x1.29ce8c0000000p-5, 0x1.6096300000000p-5, -0x1.376be80000000p-4, 0x1.5b7fe40000000p-4, 0x1.909dec0000000p-8, -0x1.12e9fa0000000p-4, -0x1.6128520000000p-6, -0x1.fa81380000000p-5, -0x1.0c3e880000000p-3, -0x1.07b4780000000p-5, -0x1.4a75400000000p-3, 0x1.50030a0000000p-7, 0x1.a420240000000p-5, 0x1.6a431c0000000p-3, -0x1.88265c0000000p-5, 0x1.82084e0000000p-6, 0x1.09d2a00000000p-3, -0x1.4500ca0000000p-6, 0x1.4735720000000p-4, 0x1.58c89c0000000p-3, -0x1.5526e00000000p-5, 0x1.98599c0000000p-5, 0x1.9149200000000p-3, 0x1.0000000000000p+0, 0x0.0p+0, +}; + +const _weights: [753664]u8 align(@alignOf(f32)) = @embedFile("go2_weights.bin").*; +pub const const_blob_f32: []const f32 = std.mem.bytesAsSlice(f32, &_weights); +pub const clip_lo = [_]f64{}; +pub const clip_hi = [_]f64{}; +pub const gemm_alpha = [_]f64{ 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0 }; +pub const gemm_beta = [_]f64{ 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0 }; +pub const elu_alpha = [_]f64{ 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0 }; +pub const leaky_relu_alpha = [_]f64{}; +pub const layernorm_eps = [_]f64{}; +pub const output_offsets = [_]usize{0}; +pub const state_offsets = [_]usize{}; diff --git a/src/shinro/runtime/tests/graphs/go2_weights.bin b/src/shinro/runtime/tests/graphs/go2_weights.bin new file mode 100644 index 0000000..6162643 Binary files /dev/null and b/src/shinro/runtime/tests/graphs/go2_weights.bin differ diff --git a/src/shinro/runtime/tests/graphs/kf_lqr_data.zig b/src/shinro/runtime/tests/graphs/kf_lqr_data.zig new file mode 100644 index 0000000..a458a34 --- /dev/null +++ b/src/shinro/runtime/tests/graphs/kf_lqr_data.zig @@ -0,0 +1,10 @@ +// Test vectors for `kf_lqr` — generated by scripts/gen_lower_fixtures.py. +// Produced by shinro.codegen.interpret on 8 seeded inputs (seed=0). +pub const n_samples = 8; +pub const n_in = 21; +pub const n_out = 3; +pub const n_state = 15; +pub const tol = 1e-12; +pub const inputs = [_]f64{ 0x1.9bfe2762c06cfp-7, -0x1.b0e1975fba2e0p-7, 0x1.06512e9ed59f1p-4, 0x1.57bc98a03dd8dp-7, -0x1.b6d2027d6d315p-5, 0x1.2837fab0bdb1fp-5, 0x1.0b0f285640cfdp-3, 0x1.83eca305496e9p-4, -0x1.203ffce488c20p-4, -0x1.0328877b0a096p-3, -0x1.fe9620e9b2192p-5, 0x1.0ed57cfa270b6p-8, 0x1.5c480f88a478ap-3, 0x1.6b056a678de51p-6, -0x1.4fdf94a3fb86cp-7, 0x1.6b056a678de51p-6, 0x1.bfcb5a255ca3dp-4, -0x1.0f5f8b2ba07cbp-7, -0x1.4fdf94a3fb86cp-7, -0x1.0f5f8b2ba07cbp-7, 0x1.cdbbd29e32860p-4, 0x1.17da0a3dc06c0p-3, -0x1.1076b78cf51b3p-4, 0x1.1ff50130d86c2p-5, 0x1.720fb704f8180p-4, 0x1.340f3b3719df1p-7, -0x1.30898c00eb958p-4, -0x1.7989e92b13bedp-4, -0x1.76f81025aec04p-5, 0x1.68c48759df4e0p-6, -0x1.9d8a23bf97e0dp-4, -0x1.56b6985474568p-6, -0x1.04dfcf41d7ca3p-6, 0x1.aca43e61a4e02p-4, -0x1.0d96791b88d18p-10, 0x1.606787d9d6c7dp-7, -0x1.0d96791b88d18p-10, 0x1.c4f91105fdd4ep-4, 0x1.e9b7206f553c6p-9, 0x1.606787d9d6c7dp-7, 0x1.e9b7206f553c6p-9, 0x1.49e1f0affd335p-3, 0x1.13a2a227b546cp-3, 0x1.4006703666849p-4, 0x1.b148bb1672907p-6, -0x1.012a62c6164ebp-5, 0x1.2a9a465a25703p-3, 0x1.9175fdc0b112ep-3, 0x1.70f98de4539abp-3, 0x1.0d554ff04df24p-3, 0x1.24c41ab33c6ddp-5, -0x1.eeed644e14398p-4, -0x1.d30cb9bb828aap-12, 0x1.0ce462dadfe1bp-4, 0x1.eb8d4b2c889ecp-4, -0x1.0e2ee93b8a7c9p-6, 0x1.15cb8200a6aaap-7, -0x1.0e2ee93b8a7c9p-6, 0x1.f8cf576cbf0dcp-4, -0x1.6c94c0b9d4070p-11, 0x1.15cb8200a6aaap-7, -0x1.6c94c0b9d4070p-11, 0x1.2aafcd56b8c99p-3, -0x1.96400481433d5p-5, 0x1.0d7dee7fb54b4p-5, -0x1.a7a52fa94e31fp-6, 0x1.444b9536d8b24p-3, 0x1.0e68f12ebe9f9p-3, 0x1.036bd602fd797p-4, -0x1.c34760fb083d2p-3, 0x1.54fa224a00167p-8, 0x1.1809b1702de37p-4, 0x1.9b3900577e0d2p-4, -0x1.fa307fdcc2472p-5, 0x1.7525de8ebf985p-3, 0x1.0b604aee90d2ep-3, -0x1.8d85524bf8bfep-7, 0x1.57d6598b0959fp-11, -0x1.8d85524bf8bfep-7, 0x1.1fb178bc11a6ap-3, -0x1.45518cc482845p-7, 0x1.57d6598b0959fp-11, -0x1.45518cc482845p-7, 0x1.e0a0d6cb732e2p-4, -0x1.05ab3ce780ae1p-3, 0x1.02376f99653cdp-4, 0x1.dc174df92c0ccp-5, 0x1.09202a59cc623p-3, -0x1.351626f7bbd87p-4, 0x1.59ede07623eecp-3, -0x1.d6db242863544p-6, 0x1.427056368d234p-3, -0x1.6289c53f6d498p-5, -0x1.2d41034bc87d9p-4, 0x1.993f940bed753p-6, 0x1.a67bb1eaff0e7p-4, 0x1.f262efa5dce7ap-4, -0x1.2eae3f64eeb3ep-6, -0x1.7474bc8ca8f93p-8, -0x1.2eae3f64eeb3ep-6, 0x1.0e4390c55fe9ap-3, 0x1.6b3d29a6ddb0cp-8, -0x1.7474bc8ca8f93p-8, 0x1.6b3d29a6ddb0cp-8, 0x1.e934345389578p-4, -0x1.0639849ed61f9p-3, -0x1.24129becf600cp-4, 0x1.fcbce223cc42ap-5, -0x1.ccd43399823d2p-3, 0x1.3c8393d24a84cp-5, -0x1.dc7aeca145247p-5, 0x1.66167456d5c28p-7, -0x1.f01e15f004bafp-8, 0x1.4b24ebeb4b2c6p-6, 0x1.1c5534098839cp-4, -0x1.36a0d4fd6a393p-4, 0x1.230461db3a160p-3, 0x1.01f757d9d6b4fp-3, 0x1.c19bc0015aa7dp-7, -0x1.4f43c4f122443p-6, 0x1.c19bc0015aa7dp-7, 0x1.d06c904005b86p-4, -0x1.a8a1669b93196p-7, -0x1.4f43c4f122443p-6, -0x1.a8a1669b93196p-7, 0x1.02fdd8a4b91d0p-3, -0x1.2360a4c5243aep-3, 0x1.a772f51cffee4p-6, -0x1.d1c17665834c7p-5, -0x1.a5ced2640e4b2p-4, -0x1.ab36970dc294cp-4, 0x1.b7c64879d739fp-6, 0x1.25d2f5a55f9a9p-5, 0x1.0ed6dbb26649fp-3, -0x1.6cc3c27f8e501p-10, 0x1.aabcd11596275p-4, 0x1.1f2f0fe90e264p-3, 0x1.d71b9bb397f25p-4, 0x1.60a8a728f1726p-3, -0x1.10c8a37e9a4b5p-8, -0x1.2dd92c92825bcp-6, -0x1.10c8a37e9a4b5p-8, 0x1.ac99e44175ca1p-4, -0x1.db9fb440bcaa1p-8, -0x1.2dd92c92825bcp-6, -0x1.db9fb440bcaa1p-8, 0x1.1b967ab078b44p-3, -0x1.64e44bb883784p-7, -0x1.49356486a3cffp-4, 0x1.ba6f57d1e5c65p-4, -0x1.d91d737c5aa8fp-6, 0x1.118834399eb74p-7, -0x1.5bffa43621bf8p-4, -0x1.a24d4b00b8895p-5, -0x1.2e55111b4dd43p-10, -0x1.3034703ef6263p-3, 0x1.eca47a4ea6e0cp-6, -0x1.5b93dafa829ffp-7, -0x1.e5abbba78c12dp-4, 0x1.49cbaae52291cp-3, 0x1.8f5b45d358d6fp-8, 0x1.8d69a7461d258p-8, 0x1.8f5b45d358d6fp-8, 0x1.17454a13512efp-3, -0x1.b998c4f8e992ap-6, 0x1.8d69a7461d258p-8, -0x1.b998c4f8e992ap-6, 0x1.f49656f103a72p-4 }; +pub const outputs = [_]f64{ 0x1.0000000000000p-1, -0x1.0000000000000p-1, 0x1.74772ade86ad2p-5, 0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.0000000000000p+0, -0x1.0000000000000p-1, 0x1.0000000000000p-1, 0x1.0000000000000p+0, 0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.97dfe0ebcc16ap-6, 0x1.0000000000000p-1, -0x1.0000000000000p-1, 0x1.0000000000000p+0, -0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.0000000000000p+0, -0x1.0000000000000p-1, -0x1.0000000000000p-1, 0x1.af4705601e9bep-4, -0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.0000000000000p+0 }; +pub const states = [_]f64{ -0x1.25e46a4c6a98ap-5, -0x1.fbd56706849d0p-6, 0x1.136ced9be4993p-5, 0x1.05f4862e2645ep-4, 0x1.d5c026cf14de2p-9, -0x1.8fed2566b0935p-10, 0x1.d5c026cf14ddcp-9, 0x1.ba3eeb5470467p-5, -0x1.954865dccd0bbp-10, -0x1.8fed2566b0930p-10, -0x1.954865dccd0bcp-10, 0x1.c259d8b732ba3p-5, 0x1.0000000000000p-1, -0x1.0000000000000p-1, 0x1.74772ade86ad2p-5, 0x1.a89e1fde242f0p-6, -0x1.7d2f2c97a6982p-5, 0x1.51588064aa64bp-6, 0x1.b4c833111dbc4p-5, -0x1.052886e4e3f22p-12, 0x1.e6666e79ca5b0p-10, -0x1.052886e4e3f21p-12, 0x1.bfbbb12675107p-5, 0x1.4cdb111f8a8c6p-11, 0x1.e6666e79ca5b4p-10, 0x1.4cdb111f8a8c5p-11, 0x1.02292af966646p-4, 0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.0000000000000p+0, 0x1.602503cc17024p-6, 0x1.34478ecfba06cp-5, 0x1.76406518af5e0p-5, 0x1.ccc9e791e76b5p-5, -0x1.94e0eae9e6ddep-9, 0x1.79d77b95cf1a7p-10, -0x1.94e0eae9e6dd9p-9, 0x1.d230f868cef41p-5, -0x1.ef83ac4d60da7p-17, 0x1.79d77b95cf19fp-10, -0x1.ef83ac4d60d6ap-17, 0x1.f29cb9856faa4p-5, -0x1.0000000000000p-1, 0x1.0000000000000p-1, 0x1.0000000000000p+0, 0x1.2a352ea16af88p-7, 0x1.9b1e47e35b6e0p-10, 0x1.091d1c1f02ee7p-4, 0x1.ddd1df19af60cp-5, -0x1.0861651914b0cp-9, 0x1.0d84571d72246p-15, -0x1.0861651914b0ap-9, 0x1.eac659cd533ffp-5, -0x1.c96d5e121f17dp-10, 0x1.0d84571d7224bp-15, -0x1.c96d5e121f184p-10, 0x1.ca3c2d56eb37cp-5, 0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.97dfe0ebcc16ap-6, -0x1.aec5a8f7b1b84p-4, 0x1.989625fbc995ap-5, 0x1.407bd5d42b1b9p-4, 0x1.cf4035851d483p-5, -0x1.afd6a5d185785p-9, -0x1.05482708d80e3p-10, -0x1.afd6a5d185788p-9, 0x1.de6786f79f878p-5, 0x1.e41c96b070d11p-11, -0x1.05482708d80e7p-10, 0x1.e41c96b070d14p-11, 0x1.cdc3678683a05p-5, 0x1.0000000000000p-1, -0x1.0000000000000p-1, 0x1.0000000000000p+0, -0x1.4ad8de34aea80p-5, -0x1.38e4d80787f99p-4, 0x1.a7917ba039a78p-4, 0x1.d4544b815770ep-5, 0x1.3da6c9127e62cp-9, -0x1.d4699a5816f1cp-9, 0x1.3da6c9127e62cp-9, 0x1.c22f82a683a19p-5, -0x1.2814327008a44p-9, -0x1.d4699a5816f1dp-9, -0x1.2814327008a44p-9, 0x1.d535c96dc8190p-5, -0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.0000000000000p+0, -0x1.8f3b012d3a6a2p-5, 0x1.5b64a5116b12cp-4, 0x1.57780f9fab914p-6, 0x1.07b18504e793ap-4, -0x1.996610cfac45ap-11, -0x1.5d2ec8e9ecdcdp-9, -0x1.996610cfac45bp-11, 0x1.b504ae245221cp-5, -0x1.7464547606356p-10, -0x1.5d2ec8e9ecdc6p-9, -0x1.7464547606358p-10, 0x1.e78b836bd1918p-5, -0x1.0000000000000p-1, -0x1.0000000000000p-1, 0x1.af4705601e9bep-4, 0x1.7128cd189d2e4p-8, -0x1.02862870c8e73p-4, 0x1.5fa2366fc3378p-7, 0x1.0247af30ae3b6p-4, 0x1.0ea5b99d64b11p-10, 0x1.1c5092c719b03p-10, 0x1.0ea5b99d64b0cp-10, 0x1.e22b3de3f9e03p-5, -0x1.3ab81b43008fdp-8, 0x1.1c5092c719afep-10, -0x1.3ab81b43008fbp-8, 0x1.cd9f90cebdf62p-5, -0x1.0000000000000p-1, 0x1.0000000000000p-1, -0x1.0000000000000p+0 }; diff --git a/src/shinro/runtime/tests/graphs/kf_lqr_graph.zig b/src/shinro/runtime/tests/graphs/kf_lqr_graph.zig new file mode 100644 index 0000000..4322f8d --- /dev/null +++ b/src/shinro/runtime/tests/graphs/kf_lqr_graph.zig @@ -0,0 +1,138 @@ +// Test fixture `kf_lqr` — closed-loop Kalman filter + LQR (matmul/reshape/add/sub/inv/clip + recurrence). +// Generated by scripts/gen_lower_fixtures.py from recipes.build_base_graph() — DO NOT EDIT. + +pub const Op = enum { + cst, + cst_f32, + inp, + out, + matmul, + add, + sub, + mul, + div, + ne, + neg, + transpose, + inv, + reshape, + clip, + where_op, + any, + copy, + tanh, + relu, + exp, + argmax, + one_hot, + slice, + sin, + cos, + stack, + solve_qp, + abs, + sign, + pow, + lt, + min, + gemm, + sigmoid, + softmax, + gelu, + elu, + layernorm, + lstm, + gru, + rnn, + concat, + gather, + sqrt, + log, + mod, + leaky_relu, +}; + +pub const Node = struct { + op: Op, + inputs: []const usize, + rows: usize, + cols: usize, + aux: usize, + vec: bool, +}; + +pub const buf_len = 192; +pub const has_solve_qp = false; +pub const n_outputs = 1; + +pub const offsets = [_]usize{ + 0, 3, 6, 9, 12, 21, 24, 27, 27, 30, 30, 33, 36, 36, 45, 45, 54, 54, 63, 63, 72, 72, 81, 81, 90, 90, 99, 108, 117, 117, 120, 120, 123, 126, 129, 132, 135, 135, 135, 144, 153, 162, 165, 168, 168, 171, 174, 177, 180, 189, +}; + +pub const nodes = [_]Node{ + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 3, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 6, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 9, .vec = false }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 12, .vec = false }, + .{ .op = .reshape, .inputs = &.{0}, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .reshape, .inputs = &.{2}, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 7, 3 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 9, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 9, 6 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .add, .inputs = &.{ 8, 10 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 18, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 12, 4 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 27, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 13, 14 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 36, .vec = false }, + .{ .op = .add, .inputs = &.{ 15, 16 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 45, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 18, 17 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 54, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 19, 20 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 63, .vec = false }, + .{ .op = .add, .inputs = &.{ 21, 22 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 72, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 17, 24 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .inv, .inputs = &.{23}, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 25, 26 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 81, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 28, 11 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 90, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 30, 6 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .add, .inputs = &.{ 29, 31 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .sub, .inputs = &.{ 5, 32 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 27, 33 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .add, .inputs = &.{ 11, 34 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 99, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 108, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 27, 37 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .sub, .inputs = &.{ 36, 38 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 39, 17 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .reshape, .inputs = &.{35}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .sub, .inputs = &.{ 1, 41 }, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 117, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 43, 42 }, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .clip, .inputs = &.{44}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{45}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{35}, .rows = 3, .cols = 1, .aux = 1, .vec = false }, + .{ .op = .out, .inputs = &.{40}, .rows = 3, .cols = 3, .aux = 2, .vec = false }, + .{ .op = .out, .inputs = &.{45}, .rows = 3, .cols = 1, .aux = 3, .vec = true }, +}; + +pub const const_blob = [_]f64{ + 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.47ae147ae147bp-6, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-6, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-6, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.47ae147ae147bp-7, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-7, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-7, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.999999999999ap-4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.999999999999ap-4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.999999999999ap-4, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.72a8f38fccafdp+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.72a8f38fccafdp+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.1e9b2675a6625p+4, +}; + +pub const const_blob_f32 = [_]f32{}; +pub const clip_lo = [_]f64{ -0x1.0000000000000p-1, -0x1.0000000000000p-1, -0x1.0000000000000p+0 }; +pub const clip_hi = [_]f64{ 0x1.0000000000000p-1, 0x1.0000000000000p-1, 0x1.0000000000000p+0 }; +pub const gemm_alpha = [_]f64{}; +pub const gemm_beta = [_]f64{}; +pub const elu_alpha = [_]f64{}; +pub const leaky_relu_alpha = [_]f64{}; +pub const layernorm_eps = [_]f64{}; +pub const output_offsets = [_]usize{0}; +pub const state_offsets = [_]usize{ 0, 3, 12 }; diff --git a/src/shinro/runtime/tests/graphs/mpc_data.zig b/src/shinro/runtime/tests/graphs/mpc_data.zig new file mode 100644 index 0000000..61f099d --- /dev/null +++ b/src/shinro/runtime/tests/graphs/mpc_data.zig @@ -0,0 +1,10 @@ +// Test vectors for `mpc` — generated by scripts/gen_lower_fixtures.py. +// Produced by shinro.codegen.interpret on 8 seeded inputs (seed=0). +pub const n_samples = 8; +pub const n_in = 21; +pub const n_out = 3; +pub const n_state = 15; +pub const tol = 0.001; +pub const inputs = [_]f64{ 0x1.9bfe2762c06cfp-7, -0x1.b0e1975fba2e0p-7, 0x1.06512e9ed59f1p-4, 0x1.57bc98a03dd8dp-7, -0x1.b6d2027d6d315p-5, 0x1.2837fab0bdb1fp-5, 0x1.0b0f285640cfdp-3, 0x1.83eca305496e9p-4, -0x1.203ffce488c20p-4, -0x1.0328877b0a096p-3, -0x1.fe9620e9b2192p-5, 0x1.0ed57cfa270b6p-8, 0x1.5c480f88a478ap-3, 0x1.6b056a678de51p-6, -0x1.4fdf94a3fb86cp-7, 0x1.6b056a678de51p-6, 0x1.bfcb5a255ca3dp-4, -0x1.0f5f8b2ba07cbp-7, -0x1.4fdf94a3fb86cp-7, -0x1.0f5f8b2ba07cbp-7, 0x1.cdbbd29e32860p-4, 0x1.17da0a3dc06c0p-3, -0x1.1076b78cf51b3p-4, 0x1.1ff50130d86c2p-5, 0x1.720fb704f8180p-4, 0x1.340f3b3719df1p-7, -0x1.30898c00eb958p-4, -0x1.7989e92b13bedp-4, -0x1.76f81025aec04p-5, 0x1.68c48759df4e0p-6, -0x1.9d8a23bf97e0dp-4, -0x1.56b6985474568p-6, -0x1.04dfcf41d7ca3p-6, 0x1.aca43e61a4e02p-4, -0x1.0d96791b88d18p-10, 0x1.606787d9d6c7dp-7, -0x1.0d96791b88d18p-10, 0x1.c4f91105fdd4ep-4, 0x1.e9b7206f553c6p-9, 0x1.606787d9d6c7dp-7, 0x1.e9b7206f553c6p-9, 0x1.49e1f0affd335p-3, 0x1.13a2a227b546cp-3, 0x1.4006703666849p-4, 0x1.b148bb1672907p-6, -0x1.012a62c6164ebp-5, 0x1.2a9a465a25703p-3, 0x1.9175fdc0b112ep-3, 0x1.70f98de4539abp-3, 0x1.0d554ff04df24p-3, 0x1.24c41ab33c6ddp-5, -0x1.eeed644e14398p-4, -0x1.d30cb9bb828aap-12, 0x1.0ce462dadfe1bp-4, 0x1.eb8d4b2c889ecp-4, -0x1.0e2ee93b8a7c9p-6, 0x1.15cb8200a6aaap-7, -0x1.0e2ee93b8a7c9p-6, 0x1.f8cf576cbf0dcp-4, -0x1.6c94c0b9d4070p-11, 0x1.15cb8200a6aaap-7, -0x1.6c94c0b9d4070p-11, 0x1.2aafcd56b8c99p-3, -0x1.96400481433d5p-5, 0x1.0d7dee7fb54b4p-5, -0x1.a7a52fa94e31fp-6, 0x1.444b9536d8b24p-3, 0x1.0e68f12ebe9f9p-3, 0x1.036bd602fd797p-4, -0x1.c34760fb083d2p-3, 0x1.54fa224a00167p-8, 0x1.1809b1702de37p-4, 0x1.9b3900577e0d2p-4, -0x1.fa307fdcc2472p-5, 0x1.7525de8ebf985p-3, 0x1.0b604aee90d2ep-3, -0x1.8d85524bf8bfep-7, 0x1.57d6598b0959fp-11, -0x1.8d85524bf8bfep-7, 0x1.1fb178bc11a6ap-3, -0x1.45518cc482845p-7, 0x1.57d6598b0959fp-11, -0x1.45518cc482845p-7, 0x1.e0a0d6cb732e2p-4, -0x1.05ab3ce780ae1p-3, 0x1.02376f99653cdp-4, 0x1.dc174df92c0ccp-5, 0x1.09202a59cc623p-3, -0x1.351626f7bbd87p-4, 0x1.59ede07623eecp-3, -0x1.d6db242863544p-6, 0x1.427056368d234p-3, -0x1.6289c53f6d498p-5, -0x1.2d41034bc87d9p-4, 0x1.993f940bed753p-6, 0x1.a67bb1eaff0e7p-4, 0x1.f262efa5dce7ap-4, -0x1.2eae3f64eeb3ep-6, -0x1.7474bc8ca8f93p-8, -0x1.2eae3f64eeb3ep-6, 0x1.0e4390c55fe9ap-3, 0x1.6b3d29a6ddb0cp-8, -0x1.7474bc8ca8f93p-8, 0x1.6b3d29a6ddb0cp-8, 0x1.e934345389578p-4, -0x1.0639849ed61f9p-3, -0x1.24129becf600cp-4, 0x1.fcbce223cc42ap-5, -0x1.ccd43399823d2p-3, 0x1.3c8393d24a84cp-5, -0x1.dc7aeca145247p-5, 0x1.66167456d5c28p-7, -0x1.f01e15f004bafp-8, 0x1.4b24ebeb4b2c6p-6, 0x1.1c5534098839cp-4, -0x1.36a0d4fd6a393p-4, 0x1.230461db3a160p-3, 0x1.01f757d9d6b4fp-3, 0x1.c19bc0015aa7dp-7, -0x1.4f43c4f122443p-6, 0x1.c19bc0015aa7dp-7, 0x1.d06c904005b86p-4, -0x1.a8a1669b93196p-7, -0x1.4f43c4f122443p-6, -0x1.a8a1669b93196p-7, 0x1.02fdd8a4b91d0p-3, -0x1.2360a4c5243aep-3, 0x1.a772f51cffee4p-6, -0x1.d1c17665834c7p-5, -0x1.a5ced2640e4b2p-4, -0x1.ab36970dc294cp-4, 0x1.b7c64879d739fp-6, 0x1.25d2f5a55f9a9p-5, 0x1.0ed6dbb26649fp-3, -0x1.6cc3c27f8e501p-10, 0x1.aabcd11596275p-4, 0x1.1f2f0fe90e264p-3, 0x1.d71b9bb397f25p-4, 0x1.60a8a728f1726p-3, -0x1.10c8a37e9a4b5p-8, -0x1.2dd92c92825bcp-6, -0x1.10c8a37e9a4b5p-8, 0x1.ac99e44175ca1p-4, -0x1.db9fb440bcaa1p-8, -0x1.2dd92c92825bcp-6, -0x1.db9fb440bcaa1p-8, 0x1.1b967ab078b44p-3, -0x1.64e44bb883784p-7, -0x1.49356486a3cffp-4, 0x1.ba6f57d1e5c65p-4, -0x1.d91d737c5aa8fp-6, 0x1.118834399eb74p-7, -0x1.5bffa43621bf8p-4, -0x1.a24d4b00b8895p-5, -0x1.2e55111b4dd43p-10, -0x1.3034703ef6263p-3, 0x1.eca47a4ea6e0cp-6, -0x1.5b93dafa829ffp-7, -0x1.e5abbba78c12dp-4, 0x1.49cbaae52291cp-3, 0x1.8f5b45d358d6fp-8, 0x1.8d69a7461d258p-8, 0x1.8f5b45d358d6fp-8, 0x1.17454a13512efp-3, -0x1.b998c4f8e992ap-6, 0x1.8d69a7461d258p-8, -0x1.b998c4f8e992ap-6, 0x1.f49656f103a72p-4 }; +pub const outputs = [_]f64{ 0x1.ffffffffdb43bp-2, -0x1.ffffffffed69ap-2, 0x1.746132d8fc30cp-5, 0x1.ffffffffcd690p-2, 0x1.ffffffffd50e0p-2, -0x1.ffffffffe8387p-1, -0x1.ffffffffd9daap-2, 0x1.fffffffc17002p-2, 0x1.ffffffffd7428p-1, 0x1.ffffffffd2a2fp-2, 0x1.ffffffffbec40p-2, -0x1.97c7d09586146p-6, 0x1.ffffffff40d49p-2, -0x1.ffffffff954afp-2, 0x1.ffffff4a444ebp-1, -0x1.ffffffff6a84ap-2, 0x1.ffffffc9b6bdbp-2, -0x1.fffffff15b853p-1, -0x1.fffffff4c1aa0p-2, -0x1.ffffffff66827p-2, 0x1.af2d709bf2508p-4, -0x1.ffffffffe736fp-2, 0x1.ffffffffc851fp-2, -0x1.ffffffffe988dp-1 }; +pub const states = [_]f64{ -0x1.25e46a4c6a98ap-5, -0x1.fbd56706849d0p-6, 0x1.136ced9be4993p-5, 0x1.05f4862e2645ep-4, 0x1.d5c026cf14de2p-9, -0x1.8fed2566b0935p-10, 0x1.d5c026cf14ddcp-9, 0x1.ba3eeb5470467p-5, -0x1.954865dccd0bbp-10, -0x1.8fed2566b0930p-10, -0x1.954865dccd0bcp-10, 0x1.c259d8b732ba3p-5, 0x1.ffffffffdb43bp-2, -0x1.ffffffffed69ap-2, 0x1.746132d8fc30cp-5, 0x1.a89e1fde242f0p-6, -0x1.7d2f2c97a6982p-5, 0x1.51588064aa64bp-6, 0x1.b4c833111dbc4p-5, -0x1.052886e4e3f22p-12, 0x1.e6666e79ca5b0p-10, -0x1.052886e4e3f21p-12, 0x1.bfbbb12675107p-5, 0x1.4cdb111f8a8c6p-11, 0x1.e6666e79ca5b4p-10, 0x1.4cdb111f8a8c5p-11, 0x1.02292af966646p-4, 0x1.ffffffffcd690p-2, 0x1.ffffffffd50e0p-2, -0x1.ffffffffe8387p-1, 0x1.602503cc17024p-6, 0x1.34478ecfba06cp-5, 0x1.76406518af5e0p-5, 0x1.ccc9e791e76b5p-5, -0x1.94e0eae9e6ddep-9, 0x1.79d77b95cf1a7p-10, -0x1.94e0eae9e6dd9p-9, 0x1.d230f868cef41p-5, -0x1.ef83ac4d60da7p-17, 0x1.79d77b95cf19fp-10, -0x1.ef83ac4d60d6ap-17, 0x1.f29cb9856faa4p-5, -0x1.ffffffffd9daap-2, 0x1.fffffffc17002p-2, 0x1.ffffffffd7428p-1, 0x1.2a352ea16af88p-7, 0x1.9b1e47e35b6e0p-10, 0x1.091d1c1f02ee7p-4, 0x1.ddd1df19af60cp-5, -0x1.0861651914b0cp-9, 0x1.0d84571d72246p-15, -0x1.0861651914b0ap-9, 0x1.eac659cd533ffp-5, -0x1.c96d5e121f17dp-10, 0x1.0d84571d7224bp-15, -0x1.c96d5e121f184p-10, 0x1.ca3c2d56eb37cp-5, 0x1.ffffffffd2a2fp-2, 0x1.ffffffffbec40p-2, -0x1.97c7d09586146p-6, -0x1.aec5a8f7b1b84p-4, 0x1.989625fbc995ap-5, 0x1.407bd5d42b1b9p-4, 0x1.cf4035851d483p-5, -0x1.afd6a5d185785p-9, -0x1.05482708d80e3p-10, -0x1.afd6a5d185788p-9, 0x1.de6786f79f878p-5, 0x1.e41c96b070d11p-11, -0x1.05482708d80e7p-10, 0x1.e41c96b070d14p-11, 0x1.cdc3678683a05p-5, 0x1.ffffffff40d49p-2, -0x1.ffffffff954afp-2, 0x1.ffffff4a444ebp-1, -0x1.4ad8de34aea80p-5, -0x1.38e4d80787f99p-4, 0x1.a7917ba039a78p-4, 0x1.d4544b815770ep-5, 0x1.3da6c9127e62cp-9, -0x1.d4699a5816f1cp-9, 0x1.3da6c9127e62cp-9, 0x1.c22f82a683a19p-5, -0x1.2814327008a44p-9, -0x1.d4699a5816f1dp-9, -0x1.2814327008a44p-9, 0x1.d535c96dc8190p-5, -0x1.ffffffff6a84ap-2, 0x1.ffffffc9b6bdbp-2, -0x1.fffffff15b853p-1, -0x1.8f3b012d3a6a2p-5, 0x1.5b64a5116b12cp-4, 0x1.57780f9fab914p-6, 0x1.07b18504e793ap-4, -0x1.996610cfac45ap-11, -0x1.5d2ec8e9ecdcdp-9, -0x1.996610cfac45bp-11, 0x1.b504ae245221cp-5, -0x1.7464547606356p-10, -0x1.5d2ec8e9ecdc6p-9, -0x1.7464547606358p-10, 0x1.e78b836bd1918p-5, -0x1.fffffff4c1aa0p-2, -0x1.ffffffff66827p-2, 0x1.af2d709bf2508p-4, 0x1.7128cd189d2e4p-8, -0x1.02862870c8e73p-4, 0x1.5fa2366fc3378p-7, 0x1.0247af30ae3b6p-4, 0x1.0ea5b99d64b11p-10, 0x1.1c5092c719b03p-10, 0x1.0ea5b99d64b0cp-10, 0x1.e22b3de3f9e03p-5, -0x1.3ab81b43008fdp-8, 0x1.1c5092c719afep-10, -0x1.3ab81b43008fbp-8, 0x1.cd9f90cebdf62p-5, -0x1.ffffffffe736fp-2, 0x1.ffffffffc851fp-2, -0x1.ffffffffe988dp-1 }; diff --git a/src/shinro/runtime/tests/graphs/mpc_graph.zig b/src/shinro/runtime/tests/graphs/mpc_graph.zig new file mode 100644 index 0000000..3645683 --- /dev/null +++ b/src/shinro/runtime/tests/graphs/mpc_graph.zig @@ -0,0 +1,140 @@ +// Test fixture `mpc` — closed-loop Kalman filter + MPC_LTI (.solve_qp via the baked OSQP solver). +// Generated by scripts/gen_lower_fixtures.py from recipes.build_mpc_composed_graph() — DO NOT EDIT. + +pub const Op = enum { + cst, + cst_f32, + inp, + out, + matmul, + add, + sub, + mul, + div, + ne, + neg, + transpose, + inv, + reshape, + clip, + where_op, + any, + copy, + tanh, + relu, + exp, + argmax, + one_hot, + slice, + sin, + cos, + stack, + solve_qp, + abs, + sign, + pow, + lt, + min, + gemm, + sigmoid, + softmax, + gelu, + elu, + layernorm, + lstm, + gru, + rnn, + concat, + gather, + sqrt, + log, + mod, + leaky_relu, +}; + +pub const Node = struct { + op: Op, + inputs: []const usize, + rows: usize, + cols: usize, + aux: usize, + vec: bool, +}; + +pub const buf_len = 252; +pub const has_solve_qp = true; +pub const n_outputs = 1; + +pub const offsets = [_]usize{ + 0, 3, 6, 9, 12, 21, 24, 27, 27, 30, 30, 33, 36, 36, 45, 45, 54, 54, 63, 63, 72, 72, 81, 81, 90, 90, 99, 108, 117, 117, 120, 120, 123, 126, 129, 132, 135, 135, 135, 144, 153, 162, 165, 168, 168, 198, 228, 231, 234, 237, 240, 249, +}; + +pub const nodes = [_]Node{ + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 3, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 6, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 9, .vec = false }, + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 12, .vec = false }, + .{ .op = .reshape, .inputs = &.{0}, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .reshape, .inputs = &.{2}, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 7, 3 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 9, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 9, 6 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .add, .inputs = &.{ 8, 10 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 18, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 12, 4 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 27, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 13, 14 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 36, .vec = false }, + .{ .op = .add, .inputs = &.{ 15, 16 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 45, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 18, 17 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 54, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 19, 20 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 63, .vec = false }, + .{ .op = .add, .inputs = &.{ 21, 22 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 72, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 17, 24 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .inv, .inputs = &.{23}, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 25, 26 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 81, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 28, 11 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 90, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 30, 6 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .add, .inputs = &.{ 29, 31 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .sub, .inputs = &.{ 5, 32 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 27, 33 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .add, .inputs = &.{ 11, 34 }, .rows = 3, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 99, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 3, .aux = 108, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 27, 37 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .sub, .inputs = &.{ 36, 38 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 39, 17 }, .rows = 3, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .reshape, .inputs = &.{35}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .sub, .inputs = &.{ 41, 1 }, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 30, .cols = 3, .aux = 117, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 43, 42 }, .rows = 30, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .solve_qp, .inputs = &.{44}, .rows = 30, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .slice, .inputs = &.{45}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .clip, .inputs = &.{46}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{47}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{35}, .rows = 3, .cols = 1, .aux = 1, .vec = false }, + .{ .op = .out, .inputs = &.{40}, .rows = 3, .cols = 3, .aux = 2, .vec = false }, + .{ .op = .out, .inputs = &.{47}, .rows = 3, .cols = 1, .aux = 3, .vec = true }, +}; + +pub const const_blob = [_]f64{ + 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.47ae147ae147bp-6, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-6, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-6, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.47ae147ae147bp-7, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-7, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.47ae147ae147bp-7, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.999999999999ap-4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.999999999999ap-4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.999999999999ap-4, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.4000000000000p+5, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.4000000000000p+5, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.4000000000000p+4, 0x1.2000000000000p+5, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.2000000000000p+5, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.2000000000000p+4, 0x1.0000000000000p+5, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+5, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+4, 0x1.c000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.c000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.c000000000000p+3, 0x1.8000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.8000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.8000000000000p+3, 0x1.4000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.4000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.4000000000000p+3, 0x1.0000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+4, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+3, 0x1.8000000000000p+3, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.8000000000000p+3, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.8000000000000p+2, 0x1.0000000000000p+3, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+3, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+2, 0x1.0000000000000p+2, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+2, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+1, +}; + +pub const const_blob_f32 = [_]f32{}; +pub const clip_lo = [_]f64{ -0x1.0000000000000p-1, -0x1.0000000000000p-1, -0x1.0000000000000p+0 }; +pub const clip_hi = [_]f64{ 0x1.0000000000000p-1, 0x1.0000000000000p-1, 0x1.0000000000000p+0 }; +pub const gemm_alpha = [_]f64{}; +pub const gemm_beta = [_]f64{}; +pub const elu_alpha = [_]f64{}; +pub const leaky_relu_alpha = [_]f64{}; +pub const layernorm_eps = [_]f64{}; +pub const output_offsets = [_]usize{0}; +pub const state_offsets = [_]usize{ 0, 3, 12 }; diff --git a/src/shinro/runtime/tests/graphs/toy_lstm_data.zig b/src/shinro/runtime/tests/graphs/toy_lstm_data.zig new file mode 100644 index 0000000..54cb46c --- /dev/null +++ b/src/shinro/runtime/tests/graphs/toy_lstm_data.zig @@ -0,0 +1,10 @@ +// Test vectors for `toy_lstm` — generated by scripts/gen_lower_fixtures.py. +// Produced by shinro.codegen.interpret on 8 seeded inputs (seed=0). +pub const n_samples = 8; +pub const n_in = 11; +pub const n_out = 2; +pub const n_state = 8; +pub const tol = 1e-12; +pub const inputs = [_]f64{ 0x1.9bfe2762c06cfp-7, -0x1.b0e1975fba2e0p-7, 0x1.06512e9ed59f1p-4, 0x1.57bc98a03dd8dp-7, -0x1.b6d2027d6d315p-5, 0x1.2837fab0bdb1fp-5, 0x1.0b0f285640cfdp-3, 0x1.83eca305496e9p-4, -0x1.203ffce488c20p-4, -0x1.0328877b0a096p-3, -0x1.fe9620e9b2192p-5, 0x1.0ed57cfa270b6p-8, -0x1.dc2a92cf69f38p-3, -0x1.6677e007db798p-6, -0x1.fe533b537d0cap-4, -0x1.2befcc209b8c6p-4, -0x1.bddb61a62a154p-5, -0x1.031cf35770cedp-5, 0x1.51352e25a34c7p-5, 0x1.ab03732bd6a85p-4, -0x1.a52eb0aff6340p-7, 0x1.17da0a3dc06c0p-3, -0x1.1076b78cf51b3p-4, 0x1.1ff50130d86c2p-5, 0x1.720fb704f8180p-4, 0x1.340f3b3719df1p-7, -0x1.30898c00eb958p-4, -0x1.7989e92b13bedp-4, -0x1.76f81025aec04p-5, 0x1.68c48759df4e0p-6, -0x1.9d8a23bf97e0dp-4, -0x1.56b6985474568p-6, -0x1.04dfcf41d7ca3p-6, 0x1.bb0f8a3aeabc5p-5, 0x1.5fb28fc6190ddp-6, 0x1.231f0f0a4baecp-5, -0x1.0bcee6176cec5p-4, -0x1.a8b7cbe42cca0p-7, 0x1.411dc947a5bd5p-4, 0x1.31dacd860a719p-3, -0x1.01db4b83205d9p-3, 0x1.360d34f0e9b4ep-3, 0x1.13a2a227b546cp-3, 0x1.4006703666849p-4, 0x1.b148bb1672907p-6, -0x1.012a62c6164ebp-5, 0x1.2a9a465a25703p-3, 0x1.9175fdc0b112ep-3, 0x1.70f98de4539abp-3, 0x1.0d554ff04df24p-3, 0x1.24c41ab33c6ddp-5, -0x1.eeed644e14398p-4, -0x1.d30cb9bb828aap-12, 0x1.0ce462dadfe1bp-4, -0x1.07db3ed9c8ea0p-3, 0x1.43af1a1482f70p-5, 0x1.6024f363328c0p-5, 0x1.1d195e99a9affp-4, -0x1.e503c4a2ecceap-4, -0x1.0f088b2a89edbp-4, -0x1.65871aea90d85p-5, -0x1.df269edab14cap-4, 0x1.6438f87663b62p-3, -0x1.96400481433d5p-5, 0x1.0d7dee7fb54b4p-5, -0x1.a7a52fa94e31fp-6, 0x1.444b9536d8b24p-3, 0x1.0e68f12ebe9f9p-3, 0x1.036bd602fd797p-4, -0x1.c34760fb083d2p-3, 0x1.54fa224a00167p-8, 0x1.1809b1702de37p-4, 0x1.9b3900577e0d2p-4, -0x1.fa307fdcc2472p-5, 0x1.7525de8ebf985p-3, -0x1.0e6c9c7a44209p-3, -0x1.0ef63d9e88c83p-4, 0x1.7eff18fe8515bp-4, 0x1.417bfc35b2fb8p-8, 0x1.9a170a50684edp-3, 0x1.34deae29a8f2cp-6, -0x1.035b366f08a34p-4, -0x1.354cce56d77acp-5, -0x1.beeef69087e94p-4, -0x1.05ab3ce780ae1p-3, 0x1.02376f99653cdp-4, 0x1.dc174df92c0ccp-5, 0x1.09202a59cc623p-3 }; +pub const outputs = [_]f64{ 0x1.1afd8cd5059d1p-3, 0x1.a78d6b9145b0cp-4, -0x1.7fb8cb10a551dp-3, -0x1.4ec389949e33cp-3, -0x1.9f2a169f049abp-5, -0x1.4e295cacde26bp-4, 0x1.be2cad836f009p-4, 0x1.b3cd034f05089p-3, 0x1.6e266b135f57bp-3, 0x1.0b286f3e2e082p-2, -0x1.3f22e94ccded1p-6, -0x1.2aeb52e996f59p-4, 0x1.5edcf72f8fcb6p-3, 0x1.1b8aefdb58310p-2, 0x1.54d68eb29d0f4p-4, 0x1.3e9988a49b51cp-3 }; +pub const states = [_]f64{ 0x1.1afd8cd5059d1p-3, 0x1.a78d6b9145b0cp-4, 0x1.95b79e8fe2850p-4, 0x1.10682cb254633p-3, 0x1.1160b5bcbb72dp-2, 0x1.8c8ea962d7bacp-3, 0x1.73d7d734853b6p-3, 0x1.edc966fe572d2p-3, -0x1.7fb8cb10a551dp-3, -0x1.4ec389949e33cp-3, -0x1.3c1e1147823dbp-3, -0x1.01ae9f8611298p-3, -0x1.e59639cb329e0p-2, -0x1.c61a6593cc380p-2, -0x1.d32775fd85207p-2, -0x1.98ea9aa921405p-2, -0x1.9f2a169f049abp-5, -0x1.4e295cacde26bp-4, -0x1.1562d3d79a5e1p-4, -0x1.1e7fe9c099920p-4, -0x1.aa0758dfae376p-4, -0x1.5d0ec769e6598p-3, -0x1.24617cbe0ccadp-3, -0x1.31d532693bcebp-3, 0x1.be2cad836f009p-4, 0x1.b3cd034f05089p-3, 0x1.d426bb6d3e0e6p-3, 0x1.da60e98735292p-3, 0x1.a1e5ce8d4e7c4p-3, 0x1.9c34d8e8b093cp-2, 0x1.b1060938e09d1p-2, 0x1.aa9986947a061p-2, 0x1.6e266b135f57bp-3, 0x1.0b286f3e2e082p-2, 0x1.4cbe7ccff7e46p-2, 0x1.1e00544ba4a9fp-2, 0x1.418e43cbbb94dp-2, 0x1.c81e04b7da023p-2, 0x1.14b8b58c995c1p-1, 0x1.b669442989c24p-2, -0x1.3f22e94ccded1p-6, -0x1.2aeb52e996f59p-4, -0x1.e2d79386a4d50p-5, -0x1.30e53a3b164dcp-4, -0x1.48229b751a1f8p-5, -0x1.395788b4817edp-3, -0x1.ff0a0158456f0p-4, -0x1.47cd0105deadap-3, 0x1.5edcf72f8fcb6p-3, 0x1.1b8aefdb58310p-2, 0x1.937c15141aae3p-3, 0x1.fb6c2b01bb02cp-3, 0x1.438cbd0f29e51p-2, 0x1.07f86efbac0acp-1, 0x1.58bb5f9587527p-2, 0x1.a9a58f8d6beacp-2, 0x1.54d68eb29d0f4p-4, 0x1.3e9988a49b51cp-3, 0x1.5db19271a01bfp-3, 0x1.ad5aba4fab816p-3, 0x1.44448016f1e9cp-3, 0x1.2dfe75e384660p-2, 0x1.45548c0e3e688p-2, 0x1.8ca3aa13b1e56p-2 }; diff --git a/src/shinro/runtime/tests/graphs/toy_lstm_graph.zig b/src/shinro/runtime/tests/graphs/toy_lstm_graph.zig new file mode 100644 index 0000000..495380d --- /dev/null +++ b/src/shinro/runtime/tests/graphs/toy_lstm_graph.zig @@ -0,0 +1,112 @@ +// Test fixture `toy_lstm` — committed toy LSTM, H=4 (fused LSTM cell + live state). +// Generated by scripts/gen_lower_fixtures.py from /mnt/E/github-projects/shinro-python-modules/tests/fixtures/models/toy_lstm.onnx — DO NOT EDIT. +const std = @import("std"); + +pub const Op = enum { + cst, + cst_f32, + inp, + out, + matmul, + add, + sub, + mul, + div, + ne, + neg, + transpose, + inv, + reshape, + clip, + where_op, + any, + copy, + tanh, + relu, + exp, + argmax, + one_hot, + slice, + sin, + cos, + stack, + solve_qp, + abs, + sign, + pow, + lt, + min, + gemm, + sigmoid, + softmax, + gelu, + elu, + layernorm, + lstm, + gru, + rnn, + concat, + gather, + sqrt, + log, + mod, + leaky_relu, +}; + +pub const Node = struct { + op: Op, + inputs: []const usize, + rows: usize, + cols: usize, + aux: usize, + vec: bool, +}; + +pub const buf_len = 51; +pub const has_solve_qp = false; +pub const n_outputs = 1; + +pub const offsets = [_]usize{ + 0, 3, 3, 6, 9, 13, 13, 13, 13, 17, 25, 29, 37, 37, 41, 41, 43, 45, 45, 47, 47, 49, +}; + +pub const nodes = [_]Node{ + .{ .op = .inp, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .reshape, .inputs = &.{0}, .rows = 1, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .reshape, .inputs = &.{2}, .rows = 3, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 4, .cols = 1, .aux = 3, .vec = true }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 16, .cols = 3, .aux = 0, .vec = false }, + .{ .op = .cst_f32, .inputs = &.{}, .rows = 16, .cols = 4, .aux = 48, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 32, .cols = 1, .aux = 3, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 4, .cols = 1, .aux = 7, .vec = true }, + .{ .op = .lstm, .inputs = &.{ 3, 5, 6, 7, 4, 8 }, .rows = 8, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .slice, .inputs = &.{9}, .rows = 4, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{9}, .rows = 8, .cols = 1, .aux = 1, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 2, .cols = 1, .aux = 35, .vec = true }, + .{ .op = .reshape, .inputs = &.{10}, .rows = 1, .cols = 4, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 4, .cols = 2, .aux = 37, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 13, 14 }, .rows = 1, .cols = 2, .aux = 0, .vec = false }, + .{ .op = .reshape, .inputs = &.{15}, .rows = 2, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 45, .vec = false }, + .{ .op = .mul, .inputs = &.{ 16, 17 }, .rows = 2, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 1, .cols = 1, .aux = 46, .vec = false }, + .{ .op = .add, .inputs = &.{ 18, 19 }, .rows = 2, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .out, .inputs = &.{20}, .rows = 2, .cols = 1, .aux = 0, .vec = true }, +}; + +pub const const_blob = [_]f64{ + 0x1.0000000000000p+0, 0x1.0000000000000p+0, 0x1.8000000000000p+1, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x1.0000000000000p+2, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x0.0p+0, 0x1.0000000000000p+0, 0x0.0p+0, +}; + +const _weights: [448]u8 align(@alignOf(f32)) = @embedFile("toy_lstm_weights.bin").*; +pub const const_blob_f32: []const f32 = std.mem.bytesAsSlice(f32, &_weights); +pub const clip_lo = [_]f64{}; +pub const clip_hi = [_]f64{}; +pub const gemm_alpha = [_]f64{}; +pub const gemm_beta = [_]f64{}; +pub const elu_alpha = [_]f64{}; +pub const leaky_relu_alpha = [_]f64{}; +pub const layernorm_eps = [_]f64{}; +pub const output_offsets = [_]usize{0}; +pub const state_offsets = [_]usize{0}; diff --git a/src/shinro/runtime/tests/graphs/toy_lstm_weights.bin b/src/shinro/runtime/tests/graphs/toy_lstm_weights.bin new file mode 100644 index 0000000..350b51d Binary files /dev/null and b/src/shinro/runtime/tests/graphs/toy_lstm_weights.bin differ diff --git a/src/shinro/runtime/tests/lower.zig b/src/shinro/runtime/tests/lower.zig new file mode 100644 index 0000000..34eaeb1 --- /dev/null +++ b/src/shinro/runtime/tests/lower.zig @@ -0,0 +1,66 @@ +// Zig-native C-ABI tests for the comptime graph VM (runtime/lower.zig). +// +// The VM is graph-agnostic — `lower.Vm(Ctx).step(...)` runs whichever graph the +// context carries. This test binds the small committed fixture graph +// (tests/lower_fixture_graph.zig, wired by build.zig as this module's +// `graph_data`) and drives `step` directly, in-process. Unlike the Python +// ctypes oracle in tests/test_zig_lowering.py — which builds a `.so` and calls +// `shinro_step` from Python — this needs no shared-library build, no ctypes, +// and no Python, so a VM regression surfaces in the plain `zig build test` +// step alone. +// +// The production binding (the deployed graph + the `shinro_step` export) lives +// in entry.zig; this file is the test-side equivalent. +// +// Fixture semantics: x = [1, 2] -> named output [3, 5]; r -> tanh(r) on the +// recurrent state output. See the fixture header for the exact node table. + +const std = @import("std"); +const lower = @import("lower"); +const g = @import("graph_data"); + +/// The fixture's VM context: a graph, no baked QP solver. +const Ctx = struct { + pub const graph = g; + pub const sm = struct {}; + pub const qp = struct {}; +}; + +test "VM: input packing, const matmul, add, clip, named + state outputs" { + // The host packs inputs in cg.inputs order, flat and contiguous. The + // fixture's two input ports live at aux offsets 0 (x) and 2 (r), so the + // packed buffer is [x0, x1, r0, r1]. + var inputs = [_]f64{ 1, 2, 0.5, -0.5 }; + var outputs = [_]f64{ 0, 0 }; + var state = [_]f64{ 0, 0 }; + + lower.Vm(Ctx).step(&inputs, &outputs, &state); + + // y = A@x = [2, 6]; z = y + b = [3, 8]; clip into [-10, 5] -> [3, 5]. + try std.testing.expectEqualSlices(f64, &[_]f64{ 3, 5 }, &outputs); + // The second `out` node (aux >= n_outputs) routes to state_out as tanh(r). + // Both sides call std.math.tanh on the same input, so this is exact. + try std.testing.expectEqual(std.math.tanh(@as(f64, 0.5)), state[0]); + try std.testing.expectEqual(std.math.tanh(@as(f64, -0.5)), state[1]); +} + +test "VM: recurrent state output feeds back as the next tick's input" { + var inputs = [_]f64{ 1, 2, 0.5, -0.5 }; + var outputs = [_]f64{ 0, 0 }; + var state = [_]f64{ 0, 0 }; + + lower.Vm(Ctx).step(&inputs, &outputs, &state); + + // Tick 2: feed the state output back into the state input slot (aux 2/3), + // exactly as the host's control loop does between ticks. The named output + // is independent of r, so it must be unchanged. + inputs[2] = state[0]; + inputs[3] = state[1]; + var outputs2 = [_]f64{ 0, 0 }; + var state2 = [_]f64{ 0, 0 }; + lower.Vm(Ctx).step(&inputs, &outputs2, &state2); + + try std.testing.expectEqualSlices(f64, &[_]f64{ 3, 5 }, &outputs2); + try std.testing.expectEqual(std.math.tanh(std.math.tanh(@as(f64, 0.5))), state2[0]); + try std.testing.expectEqual(std.math.tanh(std.math.tanh(@as(f64, -0.5))), state2[1]); +} diff --git a/src/shinro/runtime/tests/lower_fixture_graph.zig b/src/shinro/runtime/tests/lower_fixture_graph.zig new file mode 100644 index 0000000..2b3e26a --- /dev/null +++ b/src/shinro/runtime/tests/lower_fixture_graph.zig @@ -0,0 +1,128 @@ +// Fixture `graph_data.zig` for the Zig-native lower.zig test (tests/lower.zig). +// +// The graph is injected into the VM via `Vm(Ctx)`. The deployed binding +// (entry.zig) points `Ctx.graph` at runtime/graph_data.zig; the Zig-native VM +// test (tests/lower.zig) points it at this tiny, hand-authored graph so the +// `step` path can be exercised natively — `zig build test`, no `.so`, no ctypes, +// no Python. See build.zig's VM-test module. +// +// Schema contract: the `Op` enum and `Node` struct MUST mirror +// src/shinro/runtime/graph_data.zig exactly. lower.zig `switch`es on `node.op` +// with no `else`, so the enum must stay exhaustive — adding a VM op fails this +// fixture's compile, which is deliberate (it forces the fixture to track the op +// surface). Only the constants the fixture's own ops read need to exist: the +// per-op tables (`gemm_alpha`, `elu_alpha`, `layernorm_eps`, ...) are only +// referenced from the switch arms of ops present in the node table, and those +// arms are comptime-skipped otherwise. +// +// The fixture computes, for a 2-vector x, a 2-vector recurrent input r, and +// A = [[2,0],[0,3]], b = [1,2]: +// y = A @ x (matmul; A read in place from const_blob) +// z = y + b (add) +// o = clip(z, -10, 5) → the named output port (output 0) +// r' = tanh(r) → the recurrent state output port +// so with x = [1,2] the output is [3,5] and the state is tanh([0.5,-0.5]). + +pub const Op = enum { + cst, + cst_f32, + inp, + out, + matmul, + add, + sub, + mul, + div, + ne, + neg, + transpose, + inv, + reshape, + clip, + where_op, + any, + copy, + tanh, + relu, + exp, + argmax, + one_hot, + slice, + sin, + cos, + stack, + solve_qp, + abs, + sign, + pow, + lt, + min, + gemm, + sigmoid, + softmax, + gelu, + elu, + layernorm, + lstm, + gru, + rnn, + concat, + gather, + sqrt, + log, + mod, + leaky_relu, +}; + +pub const Node = struct { + op: Op, + inputs: []const usize, + rows: usize, + cols: usize, + aux: usize, + vec: bool, +}; + +pub const buf_len = 16; +pub const has_solve_qp = false; +pub const n_outputs = 1; + +// One entry per node. Const nodes own no workspace slot, so their offset is +// unused (0); every other node gets a distinct two-f64 slot. +pub const offsets = [_]usize{ + 0, // 0 inp x + 2, // 1 inp r + 0, // 2 cst A (no slot) + 4, // 3 matmul + 0, // 4 cst b (no slot) + 6, // 5 add + 8, // 6 clip + 10, // 7 out -> named output + 12, // 8 tanh + 14, // 9 out -> state output +}; + +pub const nodes = [_]Node{ + .{ .op = .inp, .inputs = &.{}, .rows = 2, .cols = 1, .aux = 0, .vec = true }, + .{ .op = .inp, .inputs = &.{}, .rows = 2, .cols = 1, .aux = 2, .vec = true }, + .{ .op = .cst, .inputs = &.{}, .rows = 2, .cols = 2, .aux = 0, .vec = false }, + .{ .op = .matmul, .inputs = &.{ 2, 0 }, .rows = 2, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .cst, .inputs = &.{}, .rows = 2, .cols = 1, .aux = 4, .vec = false }, + .{ .op = .add, .inputs = &.{ 3, 4 }, .rows = 2, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .clip, .inputs = &.{5}, .rows = 2, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .out, .inputs = &.{6}, .rows = 2, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .tanh, .inputs = &.{1}, .rows = 2, .cols = 1, .aux = 0, .vec = false }, + .{ .op = .out, .inputs = &.{8}, .rows = 2, .cols = 1, .aux = 1, .vec = false }, +}; + +// A (2x2, offset 0) then b (2x1, offset 4): A = [[2,0],[0,3]], b = [1,2]. +pub const const_blob = [_]f64{ 2, 0, 0, 3, 1, 2 }; +pub const const_blob_f32 = [_]f32{}; + +// clip's bounds are indexed per element by node.aux: clamp each element of +// z = [3,8] into [-10, 5], so only the second element moves (8 -> 5). +pub const clip_lo = [_]f64{ -10, -10 }; +pub const clip_hi = [_]f64{ 5, 5 }; + +pub const output_offsets = [_]usize{0}; +pub const state_offsets = [_]usize{0}; diff --git a/src/shinro/runtime/tests/lower_graph.zig b/src/shinro/runtime/tests/lower_graph.zig new file mode 100644 index 0000000..dce7cf3 --- /dev/null +++ b/src/shinro/runtime/tests/lower_graph.zig @@ -0,0 +1,38 @@ +// Zig-native C-ABI oracle for the comptime graph VM, driven by a frozen fixture. +// +// One copy of this file is compiled per fixture: build.zig wires each fixture's +// `entry` module (rooted at entry.zig, with that fixture's graph) and its +// expected vectors in as `vectors`. The test calls the *exported* C-ABI entry +// `entry.shinro_step` — the same symbol the host dlopen-s — on the recorded +// inputs and checks the outputs and recurrent state against `interpret()` +// within `tol`. No `.so`, no ctypes, no Python: a VM/ABI regression fails here +// in the plain `zig build test` step. +// +// The QP fixture's `entry` module carries the baked OSQP solver too, so this +// same driver covers the `.solve_qp` op natively. +// +// The graphs and vectors are generated once by scripts/gen_lower_fixtures.py +// (see its docstring) and committed; this driver is handwritten and never +// regenerated. + +const std = @import("std"); +const entry = @import("entry"); +const v = @import("vectors"); + +test "shinro_step matches interpret() on the frozen fixture" { + for (0..v.n_samples) |s| { + var inputs: [v.n_in]f64 = undefined; + @memcpy(&inputs, v.inputs[s * v.n_in ..][0..v.n_in]); + + var outputs = [_]f64{0.0} ** v.n_out; + var state = [_]f64{0.0} ** v.n_state; + entry.shinro_step(&inputs, &outputs, &state); + + for (0..v.n_out) |j| { + try std.testing.expectApproxEqAbs(v.outputs[s * v.n_out + j], outputs[j], v.tol); + } + for (0..v.n_state) |j| { + try std.testing.expectApproxEqAbs(v.states[s * v.n_state + j], state[j], v.tol); + } + } +} diff --git a/tests/test_zig_lowering.py b/tests/test_zig_lowering.py index f1cbf1e..df8f73a 100644 --- a/tests/test_zig_lowering.py +++ b/tests/test_zig_lowering.py @@ -2835,3 +2835,92 @@ def test_compiled_policy_carries_state(self, recurrent_so): np.testing.assert_allclose(got, want, atol=1e-13, err_msg=f"{op} tick {tick}") # and the state actually moved (a frozen state would pass tick 0 only) assert not np.allclose(outs[-1], np.asarray(compiled.step({"state": x}))) + + +# ─── Frozen multi-graph fixtures through the C-ABI ────────────────────────── +# +# The Zig-native oracle (runtime/tests/lower_graph.zig, run by `zig build test`) +# drives `Vm(Ctx).step` in-process. These tests go through the *exported* C +# symbol instead: build a `.so` from each committed fixture graph +# (runtime/tests/graphs/) and call `shinro_step` via ctypes, against the same +# committed vectors. That covers the export / port-packing surface and the +# compiled path for the compact `@embedFile` graph format. Self-contained: reads +# only the committed fixtures (no shinro-bench, no ONNX) — regenerate them with +# scripts/gen_lower_fixtures.py. + +FIXTURE_DIR = RUNTIME / "tests" / "graphs" +FIXTURE_NAMES = ["kf_lqr", "toy_lstm", "go2", "drone_gru", "mpc"] + + +def _zig_const_int(text: str, name: str) -> int: + m = re.search(rf"pub const {name} = (\d+);", text) + assert m is not None, f"missing integer const {name!r}" + return int(m.group(1)) + + +def _zig_f64_array(text: str, name: str) -> list[float]: + m = re.search(rf"pub const {name} = \[_\]f64\{{(.*?)\}};", text, re.S) + assert m is not None, f"missing f64 array {name!r}" + return [float.fromhex(tok.strip()) for tok in m.group(1).split(",") if tok.strip()] + + +def _build_fixture_so(graph_path: Path, build_dir: Path) -> ctypes.CDLL: + """Compile a committed fixture graph into a .so (no lowering, no bake).""" + if shutil.which("zig") is None: + pytest.skip("zig not on PATH; skipping fixture C-ABI oracle") + result = subprocess.run( + [ + "zig", + "build", + "--build-file", + str(RUNTIME / "build.zig"), + "--prefix", + str(build_dir), + f"-Dgraph={graph_path}", + ], + capture_output=True, + text=True, + ) + if result.returncode != 0: + pytest.skip(f"zig build failed: {result.stderr.strip()[:400]}") + lib = ctypes.CDLL(str(build_dir / "lib" / "libbase.so")) + lib.shinro_step.argtypes = [ctypes.POINTER(ctypes.c_double)] * 3 + lib.shinro_step.restype = None + return lib + + +class TestFrozenFixturesCAbi: + """Each committed fixture's .so matches its committed `interpret()` vectors.""" + + @pytest.mark.parametrize("name", FIXTURE_NAMES) + def test_fixture_so_matches_vectors(self, name, tmp_path_factory): + data = (FIXTURE_DIR / f"{name}_data.zig").read_text() + n_samples = _zig_const_int(data, "n_samples") + n_in = _zig_const_int(data, "n_in") + n_out = _zig_const_int(data, "n_out") + n_state = _zig_const_int(data, "n_state") + tol_match = re.search(r"pub const tol = ([^;]+);", data) + assert tol_match is not None, "missing tol" + tol = float(tol_match.group(1)) + inputs = _zig_f64_array(data, "inputs") + outputs = _zig_f64_array(data, "outputs") + states = _zig_f64_array(data, "states") + + build_dir = tmp_path_factory.mktemp(f"fixture-{name}") + lib = _build_fixture_so((FIXTURE_DIR / f"{name}_graph.zig").resolve(), build_dir) + + for s in range(n_samples): + packed = np.ascontiguousarray(inputs[s * n_in : (s + 1) * n_in], dtype=np.float64) + out = np.zeros(n_out, dtype=np.float64) + state = np.zeros(n_state, dtype=np.float64) + lib.shinro_step( + packed.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), + out.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), + state.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), + ) + np.testing.assert_allclose( + out, outputs[s * n_out : (s + 1) * n_out], atol=tol, err_msg=f"{name} sample {s} outputs" + ) + np.testing.assert_allclose( + state, states[s * n_state : (s + 1) * n_state], atol=tol, err_msg=f"{name} sample {s} state" + )