Deterministic trigonometric helpers, 3D vectors, and quaternions implemented in Rust, compiled to WebAssembly, and exposed through a clean TypeScript API. The crate relies on the pure-Rust libm backend to deliver bit-for-bit identical results across browsers and devices.
-
- Deterministic wrappers for
sin,cos,atan2, andsqrt
- Deterministic wrappers for
-
- 3D math primitives (
Vec3,Quat, plus helpers for normalization and rotations)
- 3D math primitives (
-
- Ships as both ESM (
.mjs) and CommonJS (.cjs) with generated typings
- Ships as both ESM (
-
- Includes the pre-built WASM artifacts (
dist/pkg/*) so consumers only need to import and callinitMath()
- Includes the pre-built WASM artifacts (
-
- Benchmark and determinism demo pages to compare WASM vs native math across environments
npm install @lagless/deterministic-math
# or
yarn add @lagless/deterministic-mathimport {
initMath,
Vec3,
Quat,
dm_sin,
dm_cos,
dm_atan2,
dm_sqrt,
makeNormalizedVec3,
} from "@lagless/deterministic-math";
async function demo() {
await initMath(); // must be awaited once before calling into the WASM exports
const axis = makeNormalizedVec3(0.0, 1.0, 0.0);
const quat = Quat.from_axis_angle(axis, Math.PI * 0.5);
const vector = new Vec3(1, 0, 0);
const rotated = quat.rotate_vec3(vector);
console.log("Rotated:", rotated.x(), rotated.y(), rotated.z());
console.log("Deterministic sin:", dm_sin(1.2345));
}
demo();initMath() automatically detects Node runtimes (Vitest, SSR frameworks, plain scripts) and loads the bundled dist/pkg/det_math_wasm_bg.wasm directly from the filesystem, so you can import the package in Node without adding a custom fetch polyfill or manual fs plumbing.
If you need direct access to the generated wasm-bindgen module, it is re-exported via the wasm subpath:
import initWasmModule from "@lagless/deterministic-math/wasm";
await initWasmModule();The subpath points at the same files the TypeScript wrapper consumes (dist/pkg/*).
Hosting under a different GitHub account? Replace
lagless/deterministic-mathin the URLs above.
git clone https://gbgr.github.io/deterministic_math/
cd deterministic-math
npm install
# Build the publishable artifacts (Rust WASM + tsup bundle)
npm run build:package
# Build the demo/benchmark pages (outputs to dist/web)
npm run build:web
# Copy the demo pages + assets into docs/ for GitHub Pages
npm run docs
# Full build (type-check + package + demo + docs)
npm run buildnpm run build:wasmrunswasm-pack build --target web --release --out-dir pkg.npm run build:libbundlessrc/index.tsintodist/lib/index.{mjs,cjs}and emitsdist/lib/index.d.ts.npm run copy:pkgmirrors the freshly builtpkg/folder intodist/pkg/so the npm package stays self-contained.npm run build:packagechains the three steps above.npm run build:webuses Vite to emitdist/web/*.npm run docs(ornpm run docs:sync) copiespublic/*.htmlplus the freshly builtdist/webbundle intodocs/, which GitHub Pages can serve directly.npm run release(optional helper) runsnpm run build:package, bumps the patch version, and publishes withnpm publish --access public.
- Run
npm run docs(or the fullnpm run build) to refresh thedocs/folder. - Serve the
docs/directory locally (npx serve docs) or enable GitHub Pages withdocs/as the publishing source. - Open:
docs/benchmark.html(or the hosted version) to compare nativeMath.*vs WASM.docs/determinism-test.html(or the hosted version) to run the long-form determinism test with configurable seeds/iterations. The UI reports hashes for both WASM and native math plus the largest observed difference so you can spot divergence instantly.
pkg/ # wasm-pack output (det_math_wasm.js + .wasm + .d.ts)
src/ # TypeScript glue, benchmarks, and determinism harness
dist/lib/ # npm entry points (index.cjs, index.mjs, index.d.ts)
dist/pkg/ # copied wasm artifacts shipped with the npm package
dist/web/ # Vite bundle for the benchmark/test demo pages
docs/ # GitHub Pages-ready HTML + assets (generated via npm run docs)
public/ # Static HTML shells for the demos
MIT (c) Lagless