npm.io
0.0.4 • Published 5h ago

@johnhenry/math-plus-adapter-onnx

Licence
MIT
Version
0.0.4
Deps
2
Size
17 kB
Vulns
0
Weekly
0

Math Plus

CI license

Full documentation: opensource.johnhenry.me/math

A JS/TypeScript-native numeric computation runtime — a NumPy + PyTorch + pandas + SciPy equivalent for Node/Deno/browser, built on Rust→WASM kernels, optional WebGPU acceleration, and Apache Arrow for tabular data.

Status: actively published. Everything ships independently under @johnhenry/math-plus-* on npm (and JSR, mostly) — install only what you need; a project that wants an FFT doesn't pull in a WebGPU backend. See each package's own CHANGELOG.md for release history, docs/PLAN.md for the original implementation plan, and docs/perplexity-conversation.md for the source design conversation.

Contents

Which package do I want?

I want to... Start with
Work with n-dimensional arrays tensor-core — everything tensor-shaped builds on it
Train something / take gradients tensor-autograd
Fuse elementwise expressions tensor-compile
Go faster on CPU tensor-wasm — read its README first; it's a separate storage type, not a drop-in backend
Go faster on GPU tensor-webgpu — browser-only in v1, and read its "honest threshold" section
Run @johnhenry/tensor-backend model code on plain CPU (the reference backend) tensor-cpu — pure TypeScript, every contract op native, built on tensor-core's kernels
Native Apple Silicon GPU from Node/Bun (experimental) tensor-mlx — MLX via @johnhenry/backend-mlx; darwin/arm64 only; prototype for RFC 0001
FFTs / filters / peaks fft, signal
Resize/normalize images image
Load/save model weights (.safetensors) safetensors — lazy reads from files, Blobs and HTTP ranges
Dataframes frame-arrow (+ frame-parquet for Parquet I/O)
Dataset pipelines for training data
Talk to it from an agent mcp (npx math-plus-mcp)
Exchange data with Python interop-python (PyPI: johnhenry-math-plus-interop)

Packages

Tensors
Package Role
@johnhenry/math-plus-tensor-core Typed n-D arrays: dtypes, strides/views, broadcasting, .npy I/O. Pure JS; its one dependency is special.
@johnhenry/math-plus-tensor-autograd Reverse-mode tape, nn.*, optim.*, trainer, checkpoints
@johnhenry/math-plus-tensor-compile Expression IR + elementwise fusion (opt-in); the shared lowering target for WGSL
@johnhenry/math-plus-tensor-wasm Rust→WASM kernels (SIMD, arena allocator, zero-alloc ...Into ops) + opt-in Deno-native FFI
@johnhenry/math-plus-tensor-webgpu WebGPU GEMM, attention primitives, IR→WGSL fusion. Chromium-family browsers only.
@johnhenry/math-plus-tensor-cpu The CPU reference Backend for the @johnhenry/tensor-backend contract (RFC 0001 §12 Q3): f32 compute on tensor-core's kernels (/kernels subpath), every optional op native, passes the conformance suite. Pure TypeScript; Node, Bun, Deno, browsers.
@johnhenry/math-plus-tensor-mlx Experimental. MLX (Metal) arrays on Node/Bun with explicit fromTensor/toTensor transfers, over the @johnhenry/tensor-backend contract. darwin/arm64 only; not on JSR.
@johnhenry/math-plus-safetensors safetensors reader/writer: validated headers, typed views (F16 as Float16Array), lazy reads from files/Blobs/HTTP ranges, optional tensor-core interop. Zero deps.
@johnhenry/math-plus-special The one canonical double-precision erf/erfc/GELU (SciPy-verified). Zero deps; used by tensor-core (which re-exports it) and frame-arrow's fn.erf.
Signal & media
Package Role
@johnhenry/math-plus-fft ComplexTensor + fft/ifft/rfft/irfft/fft2/fftn
@johnhenry/math-plus-signal convolve/stft/welch/findPeaks/sosFilter/butter/resamplePoly (SciPy-equivalent slice)
@johnhenry/math-plus-image resize/normalize tensor ops for ML/media pipelines
Data
Package Role
@johnhenry/math-plus-frame-arrow Immutable Arrow-backed Frame/Series with a lazy expression API
@johnhenry/math-plus-frame-parquet Parquet scan/write with real projection/predicate pushdown
@johnhenry/math-plus-data Async dataset pipelines: batch/shuffle/epochs/mapConcurrent/prefetch
@johnhenry/math-plus-scalar-types Re-export of @johnhenry/math scalars + tensor-boundary converters
Interop & infrastructure
Package Role
@johnhenry/math-plus-mcp MCP server: symbolic CAS + guarded numeric tools for agents (stdio, npx math-plus-mcp)
johnhenry-math-plus-interop PyPI, module math_plus_interop: Arrow IPC/Parquet/npy helpers for the Python side
@johnhenry/math-plus-telemetry Shared event schema + sink registry, zero-cost no-op default
@johnhenry/math-plus-adapter-math Bridge to @johnhenry/math (Matrix/Vector Tensor, Symbolic → IR, Graph → CSR)
@johnhenry/math-plus-adapter-onnx ONNX Runtime Web wrapper (Tensor marshalling)
@johnhenry/math-plus-unit Unit/dimension scalar type with dimensional-analysis-checked arithmetic

Adding a new package

@johnhenry/math-plus-signal is the real worked example (signal: new package -- convolve/stft/istft/findPeaks/sosFilter/butter/resamplePoly, issue #44): a SciPy-shaped slice of functionality that didn't fit inside @johnhenry/math-plus-fft (which stays a pure Fourier-transform package) or any other existing cluster, so it got its own npm identity.

Smallest: a new function on an existing package's exports. Most new numeric functionality is one more export from an existing package — another nn.* layer on tensor-autograd, another filter on signal once it exists — reusing that package's dtype/broadcasting/oracle machinery. No new package, no new npm identity, no new semver line, no new row in ## Which package do I want? — the whole cost is the export itself.

A genuinely new package is warranted when the functionality needs its own install footprint — a project that wants FFTs shouldn't have to pull in dataframes — or crosses into a distinct dependency/runtime shape (tensor-webgpu's browser-only WebGPU requirement, interop-python's separate PyPI distribution). signal is the harder case: it isn't a new runtime shape, just a decision that SciPy's signal module maps to its own npm package rather than growing fft past what "Fourier transforms" means.

Every existing package follows the same small, repeatable pattern, so a new one does too:

  1. packages/<name>/package.jsonname: "@johnhenry/math-plus-<name>", version: "0.0.0", matching publishConfig/exports shape — copy an existing package's, e.g. signal's or fft's for a numeric package.
  2. packages/<name>/tsconfig.json (+ tsconfig.typecheck.json) — copy-paste of an existing package's pair.
  3. Root package.json's build and test script strings — unlike @johnhenry/math's monorepo (a plain packages/* glob with nothing else to edit), this repo's build/test scripts enumerate every package by -w @johnhenry/math-plus-<name> explicitly; a package left out of these strings never builds or tests in CI even though workspaces picks it up for npm install. This is the step #47's planned manifest-drift check exists to catch automatically.
  4. The one part that isn't boilerplate: scripts/sync-jsr-configs.mjs's PACKAGE_DIRS. Every package also publishes to JSR (mostly), and JSR config generation is driven by this one hand-maintained list — a package present in npm's workspace list but absent here silently never gets a jsr.json, and nothing fails loudly about it today (this is the other half of what #47 is meant to close).

Tests. New numeric packages get a differential oracle wherever a reference implementation exists (NumPy for tensor ops, scipy.signal for signal, pyarrow/pandas for frame packages) — see AGENTS.md's "Oracle discipline" section. Run npm run example:NN for the package's example once one is added to examples/.

Add the row to this README's ## Which package do I want? and ## Packages tables. See @johnhenry/math's own "Adding a new package" section for the simpler contrasting case — a sibling monorepo where the plain packages/* glob needs no manual root-script registration at all.

Examples

Runnable, one-per-cluster walkthroughs live in examples/:

npm install
npm run build        # WASM kernels + TypeScript (needs Rust + lld for the kernels)
npm run examples     # the env-independent set (01-09; CI runs this)
npm run examples:all # includes the WASM example (needs the built artifact)

Working in this repo

npm install
npm run build        # build:wasm first (rustup target add wasm32-unknown-unknown; lld), then tsc
npm test             # manifest-drift guard + every workspace's tests

Differential tests skip (never fail) without their oracles — NumPy/SciPy via MATH_PLUS_ORACLE_PYTHON, headless Chrome via MATH_PLUS_CHROME_PATH; CI verifies the oracles are importable so a green run can't be a silently-skipped one. The WASM SIMD benchmark is deliberately not in npm test (mixed CI runner fleets make wall-clock thresholds meaningless — npm run test:bench -w @johnhenry/math-plus-tensor-wasm on known hardware instead).

Family

Part of the math family, alongside @johnhenry/math.

  • @johnhenry/math — the education/CAS-oriented scalar-math sibling. math-plus reuses its scalar types (ComplexNumber, Rational, Decimal) at tensor API edges via @johnhenry/math-plus-scalar-types and @johnhenry/math-plus-adapter-math, and bridges its Symbolic CAS into this repo's tensor compiler. The two repos make opposite trade-offs on purpose: @johnhenry/math's boxed, generic elements are precisely what this repo's SIMD-friendly tensor runtime forbids, and vice versa — neither is a subset of the other.
  • @johnhenry/iteration — a pull-based async iterator/transducer toolkit living in the same math monorepo. @johnhenry/math-plus-data's dataset pipelines build on the same transducer/backpressure ideas, though not as a direct dependency.