diff --git a/docs/math-validation-plan.md b/docs/math-validation-plan.md index ceb143c..77fb546 100644 --- a/docs/math-validation-plan.md +++ b/docs/math-validation-plan.md @@ -42,9 +42,10 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tooling -- Use Vitest with snapshot-style comparisons for key operations. +- Rust harness (in `rmg-core/tests/math_validation.rs`) validates scalar/vector/matrix/quaternion + PRNG behaviour against JSON fixtures. +- Provide deterministic reference values generated offline (e.g., via high-precision Python or Rust) stored in fixtures. +- Next step: mirror the fixtures in Vitest with snapshot-style comparisons for the TypeScript layer. - For cross-environment checks, add Playwright-driven tests that run the same suite in headless Chromium/WebKit (call into math module via bundled script). -- Provide deterministic reference values generated offline (e.g., via high-precision Python script) stored in fixtures. - Fixed-point tests compare against integer expectations. --- @@ -57,8 +58,9 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tasks -- [ ] Generate reference fixtures (JSON) for vector/matrix/quaternion cases. -- [ ] Implement Vitest suites covering scalar, vector, matrix, quaternion, transform, PRNG. +- [x] Generate reference fixtures (JSON) for scalar/vector/matrix/quaternion/PRNG cases. +- [x] Implement Rust-based validation suite (`cargo test -p rmg-core --test math_validation`). +- [ ] Mirror fixtures in Vitest to cover the TypeScript bindings (float32 mode). - [ ] Integrate Playwright smoke tests for browser verification. - [ ] Add CI job running math tests across environments. - [ ] Document any environment-specific deviations in decision log. diff --git a/docs/spec-deterministic-math.md b/docs/spec-deterministic-math.md index 5dcde68..0a2a361 100644 --- a/docs/spec-deterministic-math.md +++ b/docs/spec-deterministic-math.md @@ -16,23 +16,26 @@ Echo’s math module underpins every deterministic system: physics proxies, anim ## Numeric Modes ### Float32 Mode (default) + - All operations clamp to IEEE 754 float32 using `Math.fround`. - Inputs converted to float32 before computation; outputs stored in float32 buffers (`Float32Array`). - Stable across JS engines as long as `Math.fround` available (polyfill for older runtimes). ### Fixed-Point Mode (opt-in) + - 32.32 fixed-point representation using BigInt internally, surfaced as wrapper `Fixed` type. - Configured via engine options (`mathMode: "float32" | "fixed32"`). - Useful for deterministic networking or hardware without stable float operations. - Bridges through helper functions: `fixed.fromFloat`, `fixed.toFloat`, `fixed.mul`, `fixed.div`. -Mode chosen at engine init; math module provides factory returning mode-specific implementations. +Mode chosen at engine init; math module provides factory returning mode-specific implementations. The Rust runtime already exposes the float32 primitives in `rmg_core::math`, so FFI/WASM adapters can reuse a single source of truth while TypeScript bindings converge on the same fixtures. --- ## Core Types ### Vec2 / Vec3 / Vec4 + ```ts interface Vec2 { readonly x: number; @@ -45,22 +48,30 @@ type VecLike = Float32Array | number[]; - Methods: `create`, `clone`, `set`, `add`, `sub`, `scale`, `dot`, `length`, `normalize`, `lerp`, `equals`. - All mutating functions accept `out` parameter for in-place updates to reduce allocations. - Deterministic clamps: every operation ends with `fround` (float mode) or `fixed` operations. +- Rust parity: `rmg_core::math::Vec3` currently implements add/sub/scale/dot/cross/length/normalize; `Vec2`/`Vec4` remain TODO. ### Mat3 / Mat4 + - Column-major storage (`Float32Array(9)` / `Float32Array(16)`). - Methods: `identity`, `fromRotation`, `fromTranslation`, `multiply`, `invert`, `transformVec`. - Deterministic inversion: use well-defined algorithm with guard against singular matrices (records failure and returns identity or throws based on config). +- Rust parity: `rmg_core::math::Mat4` exposes `multiply` and `transform_point`; identity/fromRotation/invert are pending. ### Quat + - Represented as `[x, y, z, w]`. - Functions: `identity`, `fromAxisAngle`, `multiply`, `slerp`, `normalize`, `toMat4`. - `slerp` uses deterministic interpolation with clamped range. +- Rust parity: `rmg_core::math::Quat` implements identity/fromAxisAngle/multiply/normalize/to_mat4; `slerp` remains TBD. ### Transform + - Struct bundling position (Vec3), rotation (Quat), scale (Vec3). - Helper for constructing Mat4; ensures consistent order of operations. +- Rust parity: transform helpers are still tracked for Phase 1 (not implemented yet). ### Bounds / AABB + - Useful for physics collision; stores min/max Vec3. - Provides deterministic union/intersection operations. @@ -69,6 +80,7 @@ type VecLike = Float32Array | number[]; ## PRNG Services ### Engine PRNG + - Based on counter-based generator (e.g., Philox or Xoroshiro128+). - Implementation in TypeScript with optional WebAssembly acceleration later. - Interface: @@ -84,12 +96,15 @@ interface PRNG { - `state` serializable for replay. - `jump` used for branch forking: clone generator with deterministic offset. - `seed` derived from combination of world seed + branch ID + optional subsystem tag. +- Rust parity: `rmg_core::math::Prng` implements seeding, `next_f32`, and `next_int`; state/jump APIs are follow-up work. ### Deterministic Hashing + - Provide `hash64` function (e.g., SplitMix64) for converting strings/IDs into seeds. - Ensure stable across platforms; implement in TypeScript to avoid native differences. ### Integration Points + - Scheduler passes `math.prng` on `TickContext`. - Codex’s Baby `CommandContext` exposes `prng.spawn(scope)` for per-handler streams. - Timeline branch creation clones PRNG state to maintain deterministic divergence. @@ -97,6 +112,7 @@ interface PRNG { --- ## Utility Functions + - `clamp(value, min, max)` – deterministic clamp using `Math.min/Math.max` once (avoid multiple rounding). - `approximatelyEqual(a, b, epsilon)` – uses configured epsilon (float32 ~1e-6). - `degToRad`, `radToDeg` – using float32 rounding.