Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/math-validation-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

---
Expand All @@ -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.
Expand Down
18 changes: 17 additions & 1 deletion docs/spec-deterministic-math.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.

Expand All @@ -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:
Expand All @@ -84,19 +96,23 @@ 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.

---

## 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.
Expand Down