diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a0bab06 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 5 + + - package-ecosystem: cargo + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 5 diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..5bd6811 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.19.0 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..55cc7c0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,103 @@ +# prime — Changelog + +## 2026-03-29 (all commits) + +### Features + +- 64-bit PRNG tests + dynamics TS port updates (2257edc) +- **prime-random:** add SplitMix64 (2^64 period) + memoize_1d (969b5de) +- **prime-dynamics:** add numerical calculus + Van der Pol + benchmarks (fe0e102) +- add Criterion benchmarks for prime-dynamics and prime-voronoi (9cfa941) +- **prime-voronoi:** add Bowyer-Watson Delaunay triangulation (3dc27e4) +- **prime-dynamics:** add L-system string rewriting (b6b5060) +- Bridson im::Vector optimization, ADR-006/007, README update (af4c8b2) +- CausalStep type + receiver model docs + ADR-005 (4c6b753) +- WASM bindings for Phase 2-6 + architecture decision records (17e96d9) +- **ts:** Phase 10 — complete batch 3 tests + diffusion PRNG unification (b5be424) +- **ts:** Phase 10 — update TS ports for prime-dynamics, prime-spatial, prime-splines (0f4a784) +- **ts:** Phase 10 — update TS ports for prime-signal, prime-osc, prime-interp (097fa43) +- **ts:** Phase 10 — update TS ports for prime-noise, prime-color, prime-voronoi (28ea695) +- additional Phase 3/5 completions from parallel agents (616d1e7) +- complete Phases 2-6 — add missing ROADMAP functions across 6 crates (c309abf) +- **prime-interp:** add missing Phase 1 functions, complete doc-tests (d1f2c37) +- **prime-random:** add distributions, quasi-random, Monte Carlo, fix Bridson (71dc0e9) +- **prime-wasm:** add WASM bindings for all prime crates + CI job (00a1a34) +- **prime-voronoi:** Voronoi nearest-neighbor, F1/F2 distances, Lloyd relaxation (5313880) +- **prime-diffusion:** Ornstein-Uhlenbeck and geometric Brownian motion (40c54b4) +- **prime-splines:** implement Bezier, Hermite, Catmull-Rom, B-spline, slerp (095db0c) +- **prime-noise:** add 3D noise, simplex, and domain warping (e0b3ec2) +- **prime-dynamics:** implement dynamical systems and numerical integration (fc14b94) +- **prime-render:** pure sample-level scan loop — ADVANCE evaluator (d2abac8) +- **ts-ports:** prime-noise, prime-color, prime-spatial TypeScript ports (fa4605e) +- **prime-spatial:** ray tests, AABB, frustum cull — unblocks Form (91df676) +- **prime-color:** Oklab, sRGB, HSL — pure color math, zero deps (623ff00) +- **prime-noise:** value noise, Perlin, FBM, Worley — pure, zero deps (af47955) +- **prime-osc:** LFO shapes + ADSR envelope — unblocks Score (9671d5f) +- **prime-signal:** smoothdamp, spring, lowpass, highpass, deadzone (563440e) +- **prime-interp:** easing + interpolation — Rust + TS, full test coverage (6f3fffd) +- **prime-random:** pure Mulberry32 — no class, APPEND/ADVANCE only (db0b1be) + +### Bug Fixes + +- use std::hint::black_box for criterion 0.8, fix clippy in prime-noise (b6f4570) +- **thesis:** self-contained eslint config — no file: dependency (b2420be) +- **prime-random:** noUncheckedIndexedAccess compatibility — non-null assertions + loose null check (cfa3922) +- **thesis:** remove mut params from private helpers hash_u32 and hsl_component (2e16950) +- **prime-voronoi:** fix typecheck error in voronoiF1F2_2d parity test (b35374b) +- **prime-splines:** remove --passWithNoTests from test script (9b024ac) +- vitest --passWithNoTests for stub packages (sdf, splines, voronoi) (537dcc1) +- rng.test.ts prngBool reduce return type annotation (f1ec24a) +- remaining clippy + TS type annotation issues (dddc4a8) +- noise fbm2d callback return type annotation for TS strict overload resolution (14c40fe) +- CI — clippy excessive_precision + map_or + TS Array.from type inference (a7a93a5) + +### Performance + +- revert im::Vector — Vec clone faster at Bridson grid sizes (68b2bc7) +- **prime-random:** thesis-pure Bridson, add stratified MC integration (b2d8eae) + +### Refactoring + +- **prime-diffusion:** unify PRNG with prime-random Mulberry32 (1422f59) +- **prime-random:** replace let/while with successors utility in TS Bridson (2af35dd) + +### Tests + +- add 7 rigorous statistical tests for academic/production standards (75bcbe2) +- add 8 statistical validation tests for thesis proof (517ac99) +- add receiver model golden fixture tests (0f15287) + +### Documentation + +- **audit:** TS bindings audit + CLAUDE.md ADVANCE-EXCEPTION clarification (d03d8ab) +- update ROADMAP — all PRIME phases complete (9d1d00e) +- add README for release (da11035) +- math reference for prime-splines (cac902d) +- complete math reference for all remaining crates (471d94a) +- math reference for prime-interp, prime-signal, prime-osc (0204555) +- update prime-random benchmarks with post-merge numbers (006630a) +- write prime-random mathematical reference for thesis (16607b8) +- **prime:** document batch publish policy + GitHub dep strategy for consumers (adccecb) + +### Chores + +- upgrade glam 0.27 → 0.32, criterion 0.5 → 0.8 (998e6b3) +- trim remaining rustdoc bloat on MC and Bridson functions (f08d516) +- trim rustdoc bloat, remove dead deps, update CLAUDE.md (79c9711) +- scrub research language from comments + add NOTICE file (a995f1c) +- migrate thesis enforcement to shared ESLint config (8ce575d) +- add thesis-check CI gate (TS packages) (2e5c8da) +- **polish:** implement prime-sdf TS, add cross-language parity tests, fill coverage gaps (fc6b105) +- full coverage pass — edge cases, WASM gaps, overflow fix (98bbc1d) +- update pnpm lockfile for new packages (fbea8c4) +- gitignore THESIS.md — local only, not ready to publish (701da3e) +- remove stage-* TypeScript packages from prime workspace (fc168b4) +- remove stage-* crate dirs from prime workspace (444f84f) +- temporal assembly vocabulary, workspace tsconfig + pnpm setup (95760c8) +- roadmap, prime-diffusion + prime-dynamics stubs, remove form packages (47600b4) +- initial scaffold — workspace, all crate stubs, TS packages (3003184) + +### CI + +- trigger CI after retarget to dev (7f08ab5) +- add GitHub Actions workflow — Rust + TypeScript (75e010f) diff --git a/CLAUDE.md b/CLAUDE.md index 21e1667..521f7a8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -98,7 +98,7 @@ ADVANCE ← move forward reduce/fold over time steps 6. **TypeScript: no `let` — use `const` only.** Production code AND tests. - Fold pattern: `Array.from({ length: N }).reduce((state) => step(state, dt), init)` - Tuple destructuring `const [a, b] = fn()` threads state explicitly between steps. - - Exceptions: `while` loops in Bridson-class algorithms (stack overflow risk) — mark with `// ADVANCE-EXCEPTION`. + - Exceptions: `while`/`for` loops where termination is data-dependent (Bridson-class algorithms, adaptive ODE solvers, bounded convergence loops like Newton-Raphson and bisection) — mark with `// ADVANCE-EXCEPTION`. Mutation must be local to the function; same inputs always produce the same output. ### Flag these patterns diff --git a/Cargo.toml b/Cargo.toml index 263694c..aa930bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,10 +23,12 @@ glam = "0.32" criterion = { version = "0.8", features = ["html_reports"] } [workspace.package] -version = "0.1.0" +version = "1.1.1" edition = "2021" license = "MIT" repository = "https://github.com/bwyard/prime" +authors = ["Bree Yard"] +readme = "README.md" # No unsafe code, no &mut in public API — pure functions throughout. # CI runs: cargo clippy --workspace -- -D warnings (all lints are errors) diff --git a/crates/prime-color/Cargo.toml b/crates/prime-color/Cargo.toml index 4804fa5..4cd0020 100644 --- a/crates/prime-color/Cargo.toml +++ b/crates/prime-color/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["color", "graphics", "oklab", "srgb", "palette"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-color/README.md b/crates/prime-color/README.md new file mode 100644 index 0000000..6f2b17d --- /dev/null +++ b/crates/prime-color/README.md @@ -0,0 +1,37 @@ +# prime-color + +Color math — perceptual color spaces (Oklab), sRGB, HSL, HSV, palette generation, luminance, and contrast ratio. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `srgb_to_oklab` / `oklab_to_srgb` — perceptual color space conversion +- `srgb_to_linear` / `linear_to_srgb` — gamma correction +- `srgb_to_hsl` / `hsl_to_srgb` — HSL conversion +- `srgb_to_hsv` / `hsv_to_srgb` — HSV conversion +- `oklab_mix` — perceptually uniform color interpolation +- `luminance` / `contrast_ratio` — WCAG accessibility math +- `palette_complementary` / `palette_triadic` / `palette_analogous` — palette generation + +## Usage + +```rust +use prime_color::{srgb_to_oklab, oklab_mix, contrast_ratio}; + +// Convert to Oklab for perceptual operations +let (l, a, b) = srgb_to_oklab(0.8, 0.2, 0.4); + +// Perceptually uniform mix — avoids muddy grays in the middle +let (r, g, b) = oklab_mix(0.9, 0.1, 0.1, // red + 0.1, 0.1, 0.9, // blue + 0.5); // t + +// WCAG contrast ratio +let ratio = contrast_ratio(0.0, 0.0, 0.0, // black + 1.0, 1.0, 1.0); // white — 21.0 +``` + +## License + +MIT diff --git a/crates/prime-diffusion/Cargo.toml b/crates/prime-diffusion/Cargo.toml index 9e1ad63..b4d2eb1 100644 --- a/crates/prime-diffusion/Cargo.toml +++ b/crates/prime-diffusion/Cargo.toml @@ -1,9 +1,14 @@ [package] -name = "prime-diffusion" -version.workspace = true -edition.workspace = true -license.workspace = true +name = "prime-diffusion" +description = "Diffusion systems — Gray-Scott reaction-diffusion, cellular automata" +version.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true +keywords = ["diffusion", "reaction-diffusion", "cellular-automata", "simulation", "procedural"] +categories = ["mathematics", "game-engines"] [dependencies] -prime-random = { path = "../prime-random" } +prime-random = { path = "../prime-random", version = "1.1.0" } diff --git a/crates/prime-diffusion/README.md b/crates/prime-diffusion/README.md new file mode 100644 index 0000000..ded452f --- /dev/null +++ b/crates/prime-diffusion/README.md @@ -0,0 +1,31 @@ +# prime-diffusion + +Stochastic diffusion processes — Ornstein-Uhlenbeck and Geometric Brownian Motion, with seeded and unseeded variants. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `ou_step` / `ou_step_seeded` — Ornstein-Uhlenbeck mean-reverting process +- `gbm_step` / `gbm_step_seeded` — Geometric Brownian Motion + +## Usage + +```rust +use prime_diffusion::{ou_step_seeded, gbm_step_seeded}; + +// Ornstein-Uhlenbeck — mean-reverting random walk (useful for AI behavior, price simulation) +// Returns (next_value, next_seed) +let (x_next, seed_next) = ou_step_seeded(x, mu, theta, sigma, dt, seed); + +// Geometric Brownian Motion — multiplicative random walk (asset prices, population growth) +let (x_next, seed_next) = gbm_step_seeded(x, mu, sigma, dt, seed); +``` + +## Design + +Seeded variants use `prime-random` to thread noise deterministically. Unseeded variants accept a pre-sampled Wiener increment `w` for integration with external noise sources. + +## License + +MIT diff --git a/crates/prime-dynamics/Cargo.toml b/crates/prime-dynamics/Cargo.toml index 578b008..60198fc 100644 --- a/crates/prime-dynamics/Cargo.toml +++ b/crates/prime-dynamics/Cargo.toml @@ -1,9 +1,14 @@ [package] -name = "prime-dynamics" -version.workspace = true -edition.workspace = true -license.workspace = true +name = "prime-dynamics" +description = "Dynamical systems — RK4/RK45, Lorenz, Duffing, L-systems, Newton-Raphson" +version.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true +keywords = ["ode", "dynamical-systems", "runge-kutta", "lorenz", "l-systems"] +categories = ["mathematics", "science"] [dependencies] diff --git a/crates/prime-dynamics/README.md b/crates/prime-dynamics/README.md new file mode 100644 index 0000000..54ed0a8 --- /dev/null +++ b/crates/prime-dynamics/README.md @@ -0,0 +1,41 @@ +# prime-dynamics + +Dynamical systems — ODE solvers (RK4, Euler), chaotic attractors (Lorenz, Rössler, Duffing), population models, L-systems, and numerical differentiation. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +**ODE solvers:** `rk4_step` / `rk4_step3` / `euler_step` + +**Chaotic systems:** `lorenz_step` / `rossler_step` / `duffing_step` + +**Population models:** `lotka_volterra_step` / `sir_step` (predator-prey, epidemic) + +**Reaction-diffusion:** `gray_scott_step` + +**L-systems:** `lsystem_step` / `lsystem_generate` with `LRule` + +**Numerical math:** `derivative` / `derivative2` / `gradient_2d` + +**Logistic map:** `logistic` + +## Usage + +```rust +use prime_dynamics::{rk4_step, lorenz_step, lsystem_generate, LRule}; + +// Integrate dy/dt = -y using RK4 +let y_next = rk4_step(y, t, dt, |y, _t| -y); + +// Lorenz attractor — returns (dx, dy, dz) +let (dx, dy, dz) = lorenz_step(x, y, z, sigma, rho, beta, dt); + +// L-system plant growth +let rules = vec![LRule { from: 'F', to: "FF+[+F-F-F]-[-F+F+F]".to_string() }]; +let result = lsystem_generate("F", &rules, 3); +``` + +## License + +MIT diff --git a/crates/prime-interp/Cargo.toml b/crates/prime-interp/Cargo.toml index 1a09f3a..032bcba 100644 --- a/crates/prime-interp/Cargo.toml +++ b/crates/prime-interp/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["easing", "interpolation", "animation", "smoothstep", "lerp"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-interp/README.md b/crates/prime-interp/README.md new file mode 100644 index 0000000..589ad53 --- /dev/null +++ b/crates/prime-interp/README.md @@ -0,0 +1,35 @@ +# prime-interp + +Interpolation, easing, and remapping. Lerp, smoothstep, and a full easing function library — quad through elastic. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `lerp` / `lerp_clamped` / `inv_lerp` — linear interpolation +- `remap` — map a value from one range to another +- `smoothstep` / `smootherstep` — Hermite interpolation +- `repeat` / `pingpong` — wrapping and bouncing ranges +- Easing functions: `ease_in/out/in_out` × quad, cubic, quart, quint, sine, expo, circ, back, elastic, bounce + +## Usage + +```rust +use prime_interp::{lerp, remap, ease_out_cubic, smoothstep}; + +// Linear interpolation +let mid = lerp(0.0, 10.0, 0.5); // 5.0 + +// Remap from one range to another +let remapped = remap(0.5, 0.0, 1.0, 100.0, 200.0); // 150.0 + +// Eased animation progress +let t = ease_out_cubic(0.3); // decelerated + +// Smooth threshold +let alpha = smoothstep(0.2, 0.8, 0.5); +``` + +## License + +MIT diff --git a/crates/prime-interp/src/lib.rs b/crates/prime-interp/src/lib.rs index 0fcdaba..71aa6f7 100644 --- a/crates/prime-interp/src/lib.rs +++ b/crates/prime-interp/src/lib.rs @@ -25,7 +25,7 @@ use std::f32::consts::PI; /// # Arguments /// * `a` - Start value (returned when t = 0.0) /// * `b` - End value (returned when t = 1.0) -/// * `t` - Interpolation factor. Not clamped — extrapolates outside [0,1]. +/// * `t` - Interpolation factor. Not clamped — extrapolates outside \[0,1\]. /// /// # Example /// ```rust diff --git a/crates/prime-noise/Cargo.toml b/crates/prime-noise/Cargo.toml index 15f7a63..b44af9b 100644 --- a/crates/prime-noise/Cargo.toml +++ b/crates/prime-noise/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["noise", "procedural", "graphics", "perlin", "simplex"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-noise/README.md b/crates/prime-noise/README.md new file mode 100644 index 0000000..e750307 --- /dev/null +++ b/crates/prime-noise/README.md @@ -0,0 +1,34 @@ +# prime-noise + +Noise functions — Value, Perlin, Simplex, FBM, Worley, domain warping, and curl noise. 2D and 3D variants throughout. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `value_noise_2d` / `value_noise_3d` — lattice value noise +- `perlin_2d` / `perlin_3d` — gradient noise +- `simplex_2d` / `simplex_3d` — simplex noise +- `fbm_2d` / `fbm_3d` — fractal Brownian motion (octaves, lacunarity, gain) +- `worley_2d` — cellular / Worley noise +- `domain_warp_2d` / `domain_warp_3d` — FBM-based domain warping +- `curl_2d` / `curl_3d` — divergence-free curl noise (fluid simulation) + +## Usage + +```rust +use prime_noise::{perlin_2d, fbm_2d, curl_2d}; + +// Basic Perlin noise +let n = perlin_2d(x, y); // [-1, 1] + +// Layered FBM terrain +let height = fbm_2d(x, y, 6, 2.0, 0.5); + +// Curl noise for fluid-like motion +let (vx, vy) = curl_2d(x, y, 0.01); +``` + +## License + +MIT diff --git a/crates/prime-osc/Cargo.toml b/crates/prime-osc/Cargo.toml index 4d816ec..77ff586 100644 --- a/crates/prime-osc/Cargo.toml +++ b/crates/prime-osc/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["lfo", "adsr", "audio", "oscillator", "envelope"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-osc/README.md b/crates/prime-osc/README.md new file mode 100644 index 0000000..99343f7 --- /dev/null +++ b/crates/prime-osc/README.md @@ -0,0 +1,33 @@ +# prime-osc + +Oscillators and envelopes — LFO waveforms, stateless phase stepping, and ADSR envelope simulation. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `lfo_sine` / `lfo_cosine` / `lfo_triangle` / `lfo_sawtooth` / `lfo_square` — LFO shapes from a phase value +- `osc_step` — advance phase by one sample, returns `(sample, next_phase)` +- `adsr_step` — ADSR envelope simulation, returns `(level, next_state)` +- `AdsrParams` / `AdsrState` / `AdsrStage` — envelope state types + +## Usage + +```rust +use prime_osc::{osc_step, lfo_sine, adsr_step, AdsrParams, AdsrState}; + +// LFO — advance phase and sample +let (sample, next_phase) = osc_step(phase, freq, sample_rate, lfo_sine); + +// ADSR envelope — thread state forward per sample +let params = AdsrParams { attack: 0.01, decay: 0.1, sustain: 0.7, release: 0.3 }; +let (level, next_state) = adsr_step(state, ¶ms, gate, dt); +``` + +## Design + +Phase and envelope state are explicit return values — no mutation, no hidden counters. + +## License + +MIT diff --git a/crates/prime-random/Cargo.toml b/crates/prime-random/Cargo.toml index 96e85d4..71b3e24 100644 --- a/crates/prime-random/Cargo.toml +++ b/crates/prime-random/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["random", "prng", "procedural", "deterministic", "game-dev"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-random/README.md b/crates/prime-random/README.md new file mode 100644 index 0000000..1ec86cb --- /dev/null +++ b/crates/prime-random/README.md @@ -0,0 +1,39 @@ +# prime-random + +Seeded, deterministic randomness. Mulberry32 PRNG, probability distributions, geometric sampling, and quasi-random sequences. No hidden state — the seed is the RNG. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `prng_next` / `prng_range_f32` / `prng_bool` — core Mulberry32 PRNG +- `prng_gaussian` / `prng_exponential` — probability distributions +- `prng_disk_uniform` / `prng_annulus_uniform` — geometric sampling +- `prng_shuffled` / `prng_choose` / `weighted_choice` — collection sampling +- `van_der_corput` / Halton sequences — quasi-random low-discrepancy +- `CausalStep` — builder-style API for threaded state + +## Usage + +```rust +use prime_random::{prng_next, prng_gaussian, prng_shuffled}; + +// Thread state forward explicitly — same seed always produces the same sequence +let (value, next_seed) = prng_next(42); +let (value2, next_seed2) = prng_next(next_seed); + +// Gaussian sample +let (sample, next_seed) = prng_gaussian(42); + +// Shuffle a slice without mutating it +let items = vec![1, 2, 3, 4, 5]; +let (shuffled, _) = prng_shuffled(42, &items); +``` + +## Design + +State is threaded explicitly: every function takes a seed and returns `(value, next_seed)`. No struct, no mutable write head, no global state. Deterministic across platforms. + +## License + +MIT diff --git a/crates/prime-render/Cargo.toml b/crates/prime-render/Cargo.toml index 8a9397e..2186dc9 100644 --- a/crates/prime-render/Cargo.toml +++ b/crates/prime-render/Cargo.toml @@ -5,3 +5,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true +keywords = ["audio", "render", "dsp", "sample-loop", "functional"] +categories = ["mathematics", "multimedia::audio"] diff --git a/crates/prime-render/README.md b/crates/prime-render/README.md new file mode 100644 index 0000000..395bee3 --- /dev/null +++ b/crates/prime-render/README.md @@ -0,0 +1,34 @@ +# prime-render + +Pure sample-level audio scan loop — fold a stateless step function over N audio samples. The proof that a song is a pure function of time. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `render` — fold a mono step function over a sample buffer +- `render_stereo` — fold a stereo step function over an interleaved buffer +- `render_fold` — fold with an accumulator (collect events, gather analysis data) + +## Usage + +```rust +use prime_render::render; + +// Step function: (state, sample_index) -> (sample, next_state) +let step = |state: MyState, i: usize| -> (f32, MyState) { + let phase = state.phase + state.freq / sample_rate; + let sample = (phase * std::f32::consts::TAU).sin(); + (sample, MyState { phase, ..state }) +}; + +let buffer = render(initial_state, num_samples, step); +``` + +## Design + +No audio thread, no callbacks, no mutation. The render loop is a pure fold — same initial state always produces the same buffer. Useful for offline rendering, testing, and proving that audio synthesis is deterministic. + +## License + +MIT diff --git a/crates/prime-sdf/Cargo.toml b/crates/prime-sdf/Cargo.toml index 28fa1fa..13c4775 100644 --- a/crates/prime-sdf/Cargo.toml +++ b/crates/prime-sdf/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["sdf", "graphics", "geometry", "game-dev", "procedural"] categories = ["graphics", "game-engines", "mathematics"] diff --git a/crates/prime-sdf/README.md b/crates/prime-sdf/README.md new file mode 100644 index 0000000..d532a7c --- /dev/null +++ b/crates/prime-sdf/README.md @@ -0,0 +1,39 @@ +# prime-sdf + +Signed distance functions — 2D and 3D primitives, boolean CSG operations, smooth blending, and domain transforms. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +**2D primitives:** `circle`, `box_2d`, `rounded_box`, `capsule_2d`, `line_segment`, `triangle`, `ring` + +**3D primitives:** `sphere`, `box_3d`, `capsule_3d`, `cylinder`, `torus` + +**Boolean ops:** `union`, `intersection`, `subtract`, `xor` + +**Smooth ops:** `smooth_union`, `smooth_intersection`, `smooth_subtract` + +**Domain transforms:** `translate`, `rotate_2d`, `scale`, `repeat`, `mirror_x`, `mirror_y`, `elongate` + +## Usage + +```rust +use prime_sdf::{sphere, box_3d, smooth_union, translate}; +use glam::{Vec2, Vec3}; + +// Distance from point to sphere +let d = sphere(Vec3::new(1.0, 0.0, 0.0), Vec3::ZERO, 0.5); + +// CSG: smoothly blend two shapes +let d_sphere = sphere(p, center_a, 0.5); +let d_box = box_3d(p, center_b, Vec3::splat(0.3)); +let blended = smooth_union(d_sphere, d_box, 0.1); + +// Repeated tiling +let p_tiled = repeat(p.truncate(), Vec2::splat(2.0)); +``` + +## License + +MIT diff --git a/crates/prime-sdf/src/primitives/d2.rs b/crates/prime-sdf/src/primitives/d2.rs index b252038..bbc8358 100644 --- a/crates/prime-sdf/src/primitives/d2.rs +++ b/crates/prime-sdf/src/primitives/d2.rs @@ -68,7 +68,7 @@ pub fn rounded_box(p: Vec2, center: Vec2, half_extents: Vec2, radius: f32) -> f3 /// Signed distance from point `p` to a 2D capsule (stadium shape). /// /// # Math -/// Project p onto line segment AB, clamp t in [0,1], measure distance to +/// Project p onto line segment AB, clamp t in \[0,1\], measure distance to /// nearest point minus radius. /// /// # Arguments diff --git a/crates/prime-sdf/src/primitives/d3.rs b/crates/prime-sdf/src/primitives/d3.rs index 6a2f7fa..0dddbc0 100644 --- a/crates/prime-sdf/src/primitives/d3.rs +++ b/crates/prime-sdf/src/primitives/d3.rs @@ -29,7 +29,7 @@ pub fn box_3d(p: Vec3, center: Vec3, half_extents: Vec3) -> f32 { /// Signed distance from point `p` to a 3D capsule. /// /// # Math -/// Project p onto segment AB, clamp t in [0,1], measure to nearest point minus radius. +/// Project p onto segment AB, clamp t in \[0,1\], measure to nearest point minus radius. pub fn capsule_3d(p: Vec3, a: Vec3, b: Vec3, radius: f32) -> f32 { let pa = p - a; let ba = b - a; diff --git a/crates/prime-signal/Cargo.toml b/crates/prime-signal/Cargo.toml index 729dc91..c7cd1be 100644 --- a/crates/prime-signal/Cargo.toml +++ b/crates/prime-signal/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["signal", "smoothdamp", "spring", "game-dev", "interpolation"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-signal/README.md b/crates/prime-signal/README.md new file mode 100644 index 0000000..3c0f234 --- /dev/null +++ b/crates/prime-signal/README.md @@ -0,0 +1,32 @@ +# prime-signal + +Signal processing for game feel and animation. Smoothdamp, springs, low/high-pass filters, and deadzone shaping — all pure functions that return new state. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `smoothdamp` / `smoothdamp_vec2` / `smoothdamp_vec3` — Unity-style smooth follow +- `spring` / `spring_vec2` / `spring_vec3` — spring-damper simulation +- `low_pass` / `high_pass` — first-order filters +- `deadzone` — input deadzone with curve shaping + +## Usage + +```rust +use prime_signal::{smoothdamp, spring}; + +// Smooth-follow a target value — returns (new_pos, new_velocity) +let (pos, vel) = smoothdamp(current_pos, target, velocity, smooth_time, dt); + +// Spring physics — returns (new_pos, new_velocity) +let (pos, vel) = spring(pos, vel, target, stiffness, damping, dt); +``` + +## Design + +No `&mut` in public signatures. Every function takes current state and returns the next state as a tuple. Thread state forward explicitly between frames. + +## License + +MIT diff --git a/crates/prime-spatial/Cargo.toml b/crates/prime-spatial/Cargo.toml index bec3009..b90ee90 100644 --- a/crates/prime-spatial/Cargo.toml +++ b/crates/prime-spatial/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["spatial", "collision", "raycast", "aabb", "frustum"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-spatial/README.md b/crates/prime-spatial/README.md new file mode 100644 index 0000000..05bb411 --- /dev/null +++ b/crates/prime-spatial/README.md @@ -0,0 +1,31 @@ +# prime-spatial + +Spatial queries — ray casting, AABB operations, and frustum culling. Pure functions for collision detection and visibility testing. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `ray_aabb` / `ray_sphere` / `ray_plane` — ray intersection tests +- `aabb_overlaps` / `aabb_contains` / `aabb_union` / `aabb_closest_point` — AABB operations +- `frustum_cull_sphere` / `frustum_cull_aabb` — frustum visibility tests + +## Usage + +```rust +use prime_spatial::{ray_sphere, aabb_overlaps, frustum_cull_sphere}; +use glam::Vec3; + +// Ray-sphere intersection — returns hit distance if any +let hit = ray_sphere(ray_origin, ray_dir, sphere_center, sphere_radius); + +// AABB overlap test +let overlapping = aabb_overlaps(min_a, max_a, min_b, max_b); + +// Frustum culling +let visible = frustum_cull_sphere(&frustum_planes, sphere_center, sphere_radius); +``` + +## License + +MIT diff --git a/crates/prime-splines/Cargo.toml b/crates/prime-splines/Cargo.toml index 0f60d2a..7aab5b8 100644 --- a/crates/prime-splines/Cargo.toml +++ b/crates/prime-splines/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["splines", "bezier", "interpolation", "curves", "catmull-rom"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-splines/README.md b/crates/prime-splines/README.md new file mode 100644 index 0000000..4b803e3 --- /dev/null +++ b/crates/prime-splines/README.md @@ -0,0 +1,35 @@ +# prime-splines + +Spline math — Bezier (quadratic, cubic), Hermite, Catmull-Rom, B-spline, slerp, arc length, and uniform-speed parameterization. Scalar and 3D variants. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `bezier_quadratic` / `bezier_cubic` — Bezier curves (scalar + 3D) +- `hermite` / `hermite_3d` — Hermite interpolation with tangents +- `catmull_rom` / `catmull_rom_3d` — smooth pass-through splines +- `b_spline_cubic` / `b_spline_cubic_3d` — B-spline curves +- `slerp` — spherical linear interpolation for rotations +- `bezier_cubic_arc_length` — arc length approximation +- `bezier_cubic_t_at_length` — uniform-speed parameterization + +## Usage + +```rust +use prime_splines::{catmull_rom_3d, slerp, bezier_cubic_t_at_length_3d}; +use glam::Vec3; + +// Smooth path through control points +let pos = catmull_rom_3d(t, p0, p1, p2, p3); + +// Spherical interpolation between directions +let dir = slerp(from, to, t); + +// Move at constant speed along a bezier +let uniform_t = bezier_cubic_t_at_length_3d(p0, p1, p2, p3, target_length, 64); +``` + +## License + +MIT diff --git a/crates/prime-voronoi/Cargo.toml b/crates/prime-voronoi/Cargo.toml index d61b366..c2a62ff 100644 --- a/crates/prime-voronoi/Cargo.toml +++ b/crates/prime-voronoi/Cargo.toml @@ -5,6 +5,8 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +readme = "README.md" +authors.workspace = true keywords = ["voronoi", "delaunay", "procedural", "spatial", "noise"] categories = ["mathematics", "game-engines"] diff --git a/crates/prime-voronoi/README.md b/crates/prime-voronoi/README.md new file mode 100644 index 0000000..f8daa0e --- /dev/null +++ b/crates/prime-voronoi/README.md @@ -0,0 +1,34 @@ +# prime-voronoi + +Voronoi and Delaunay geometry — nearest-cell queries, F1/F2 distances, Lloyd relaxation, and Bowyer-Watson triangulation. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +- `voronoi_nearest_2d` — find nearest seed and distance for a query point +- `voronoi_f1_f2_2d` — F1 (nearest) and F2 (second-nearest) distances for cellular noise +- `lloyd_relax_step_2d` — one step of Lloyd relaxation (centroidal Voronoi) +- `delaunay_2d` — Delaunay triangulation, returns triangle indices + +## Usage + +```rust +use prime_voronoi::{voronoi_nearest_2d, delaunay_2d, lloyd_relax_step_2d}; + +let seeds = vec![(0.0, 0.0), (1.0, 0.5), (0.5, 1.0)]; + +// Nearest cell +let (cell_index, distance) = voronoi_nearest_2d((0.4, 0.4), &seeds).unwrap(); + +// Delaunay triangulation +let triangles = delaunay_2d(&seeds); // Vec<(usize, usize, usize)> + +// Centroidal relaxation +let samples: Vec<(f32, f32)> = /* dense point set */; +let relaxed = lloyd_relax_step_2d(&seeds, &samples); +``` + +## License + +MIT diff --git a/crates/prime-wasm/Cargo.toml b/crates/prime-wasm/Cargo.toml index 53c8fd3..d2c6960 100644 --- a/crates/prime-wasm/Cargo.toml +++ b/crates/prime-wasm/Cargo.toml @@ -1,10 +1,14 @@ [package] -name = "prime-wasm" -version.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true +name = "prime-wasm" description = "WASM bindings for the prime math library" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +readme = "README.md" +authors.workspace = true +keywords = ["wasm", "webassembly", "math", "game-dev", "graphics"] +categories = ["wasm", "mathematics"] [lib] crate-type = ["cdylib", "rlib"] @@ -12,19 +16,19 @@ crate-type = ["cdylib", "rlib"] [dependencies] wasm-bindgen = "0.2" glam = { workspace = true } -prime-noise = { path = "../prime-noise" } -prime-color = { path = "../prime-color" } -prime-sdf = { path = "../prime-sdf" } -prime-interp = { path = "../prime-interp" } -prime-signal = { path = "../prime-signal" } -prime-random = { path = "../prime-random" } -prime-osc = { path = "../prime-osc" } -prime-spatial = { path = "../prime-spatial" } -prime-splines = { path = "../prime-splines" } -prime-dynamics = { path = "../prime-dynamics" } -prime-diffusion = { path = "../prime-diffusion" } -prime-voronoi = { path = "../prime-voronoi" } -prime-render = { path = "../prime-render" } +prime-noise = { path = "../prime-noise", version = "1.1.0" } +prime-color = { path = "../prime-color", version = "1.1.0" } +prime-sdf = { path = "../prime-sdf", version = "1.1.0" } +prime-interp = { path = "../prime-interp", version = "1.1.0" } +prime-signal = { path = "../prime-signal", version = "1.1.0" } +prime-random = { path = "../prime-random", version = "1.1.0" } +prime-osc = { path = "../prime-osc", version = "1.1.0" } +prime-spatial = { path = "../prime-spatial", version = "1.1.0" } +prime-splines = { path = "../prime-splines", version = "1.1.0" } +prime-dynamics = { path = "../prime-dynamics", version = "1.1.0" } +prime-diffusion = { path = "../prime-diffusion", version = "1.1.0" } +prime-voronoi = { path = "../prime-voronoi", version = "1.1.0" } +prime-render = { path = "../prime-render", version = "1.1.0" } [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/prime-wasm/README.md b/crates/prime-wasm/README.md new file mode 100644 index 0000000..41adf16 --- /dev/null +++ b/crates/prime-wasm/README.md @@ -0,0 +1,38 @@ +# prime-wasm + +WebAssembly bindings for the prime math ecosystem. Exposes color, SDF, noise, and signal functions to JavaScript/TypeScript via wasm-bindgen. + +Part of the [prime](https://github.com/bwyard/prime) math ecosystem. + +## What's inside + +Flat WASM-friendly API (arrays returned as `Box<[f32]>`) covering: + +- **Color:** `srgb_to_oklab`, `oklab_to_srgb`, `srgb_to_linear`, `linear_to_srgb`, `hsl_to_srgb`, `srgb_to_hsl`, `srgb_to_hsv`, `hsv_to_srgb`, `oklab_mix`, `luminance`, `contrast_ratio`, `palette_complementary`, `palette_triadic`, `palette_analogous` +- **SDF:** `sdf_sphere`, `sdf_box`, `sdf_torus`, `sdf_capsule` +- **Noise:** `curl_2d`, `curl_3d` + +## Usage + +Build with `wasm-pack`: + +```bash +wasm-pack build --target web +``` + +Then in JavaScript/TypeScript: + +```js +import init, { srgb_to_oklab, sdf_sphere } from './pkg/prime_wasm.js'; + +await init(); + +const [l, a, b] = srgb_to_oklab(0.8, 0.2, 0.4); +const dist = sdf_sphere(1, 0, 0, // point + 0, 0, 0, // center + 0.5); // radius +``` + +## License + +MIT diff --git a/docs/design/ts-bindings-audit.md b/docs/design/ts-bindings-audit.md new file mode 100644 index 0000000..8efa1dc --- /dev/null +++ b/docs/design/ts-bindings-audit.md @@ -0,0 +1,220 @@ +# PRIME TypeScript Bindings Audit +Session: prime s004 | Date: 2026-03-29 | Todo: t227 + +Audit of all TypeScript packages against thesis compliance: +zero `let`, zero classes, pure functions, factory pattern, immutable by default. + +--- + +## Verdict by Package + +| Package | Status | Notes | +|---|---|---| +| prime-random | ✅ COMPLIANT | | +| prime-sdf | ✅ COMPLIANT | | +| prime-interp | ✅ COMPLIANT | | +| prime-voronoi | ✅ COMPLIANT | | +| prime-dynamics | ✅ COMPLIANT | `let` in ADVANCE-EXCEPTION blocks only — all marked and justified | + +--- + +## Detail: prime-random + +**Pattern:** `(seed, ...params) => [value, nextSeed]` +All state threads forward through return values. No hidden RNG state. + +**ADVANCE-EXCEPTION:** `successors()` helper encapsulates the one `let` + `while` needed +for Bridson-class algorithms. The exception rationale is documented inline: +data-dependent termination, stack overflow risk, encapsulated mutation. + +All other functions are pure `const` → tuple. `vanDerCorput` has a `while` loop +for digit extraction, also marked ADVANCE-EXCEPTION. + +**No issues.** + +--- + +## Detail: prime-sdf + +Pure coordinate → scalar functions. No state. No tuples needed (geometry is stateless). + +**No issues.** + +--- + +## Detail: prime-interp + +Pure `(t) => number` easing functions. All `const`. No state. + +Minor gap: most easing functions have one-liner comments only. Full TSDoc with +`@param` and `@example` present only on the core functions (`lerp`, `smoothstep`, +`remap`). Not a thesis violation — a doc quality note. + +**No issues.** + +--- + +## Detail: prime-voronoi + +Pure functions over `readonly [number, number][]` point arrays. +Uses `reduce` throughout — no loops, no mutation. + +Functions audited: `voronoiNearest2d`, `voronoiF1F2_2d`, Lloyd relaxation, +Bowyer-Watson Delaunay triangulation. + +**No issues.** + +--- + +## Detail: prime-dynamics + +Pure step functions: `(state, ...params) => newState`. +State is a scalar or `[number, number, number]` tuple. + +**ADVANCE-EXCEPTION blocks (all justified and marked):** + +| Function | Let vars | Reason | +|---|---|---| +| `rk45Adaptive` | `y, t, dt, steps` | Adaptive step ODE — termination is data-dependent, step count unknown a priori | +| `newtonRaphson` | `x` | Convergence loop — bounded by `maxIter` | +| `bisection` | `lo, hi, fLo` | Convergence loop — bounded by `maxIter` | +| `integrateAdaptive` | none | Uses recursion (bounded by `maxDepth`) — no `let` | + +The CLAUDE.md ADVANCE-EXCEPTION rule was originally scoped to Bridson-class algorithms. +The dynamics convergence loops extend the scope. This extension is valid — the rationale +(data-dependent termination, mutation encapsulated within the function, same inputs → +same output) applies equally to convergence loops. + +**Recommendation:** Update CLAUDE.md to extend ADVANCE-EXCEPTION to bounded convergence +loops, not just Bridson-class. Proposed wording: +> "ADVANCE-EXCEPTION: `while`/`for` loops where termination is data-dependent +> (Bridson-class algorithms, adaptive ODE solvers, convergence loops) — mark with +> `// ADVANCE-EXCEPTION`. Mutation must be local to the function." + +**TSDoc gap:** `duffingStep` is exported without a block docstring. Minor — fix in same PR. + +--- + +## Chainable Vectors — Closed + +The coordination audit specifically asked about chainable vectors. + +**Decision: the current tuple approach is correct. Chainable vectors are a thesis violation.** + +A chainable vector (`new Vec2(1,2).add(Vec2(3,4)).scale(2)`) requires a class with +methods — zero classes is a hard rule. The tuple approach (`[x, y]` + pure functions) +is the correct thesis-aligned pattern. It is more composable, not less: any `reduce`, +`map`, or destructuring works directly. + +FORM and STAGE may introduce `ChainableShape` or `ChainableEntity` builder objects in +their DSL layers. Those live above PRIME in the stack. PRIME stays pure math: tuples + +pure functions only. + +**No chainable vector API should be added to any prime package.** + +--- + +## Factory Function Pattern + +The coordination audit asked about factory functions. + +PRIME doesn't need `createX` factories because there are no stateful objects to +construct. Every package exports pure functions. A "factory" in PRIME would return +a closure (e.g., `memoize1d` returns a lookup function — this is the correct pattern). + +The `createX` factory pattern applies to Score/Form/Stage where stateful or configurable +objects are needed. PRIME has no such objects. + +**Verdict: factory functions are not needed. `memoize1d`-style closures are the correct +pattern when a pre-computation step is needed.** + +--- + +## Issues Added as Todos + +Three open GitHub issues were added to the todo list (t331–t333): + +| Todo | Issue | Description | +|---|---|---| +| t331 | #31 | Adaptive Simpson's quadrature — Rust crate implementation | +| t332 | #32 | Dormand-Prince RK45 adaptive ODE solver — Rust crate implementation | +| t333 | #33 | Newton-Raphson + bisection root finding — Rust crate implementation | + +Note: all three are **already implemented in prime-dynamics TS**. The issues track the +corresponding Rust crate implementations in `prime-dynamics/src/`. + +--- + +## Gaps: Packages with No TS Bindings Yet + +These packages have Rust crates but no TS `index.ts`: + +| Package | Rust status | TS status | Priority | +|---|---|---|---| +| prime-noise | stub | none | Medium (FORM needs this) | +| prime-color | stub | none | Medium (FORM needs this) | +| prime-splines | stub | none | Low | +| prime-signal | stub | none | High (SCORE + STAGE need smoothdamp/spring) | +| prime-osc | stub | none | Medium (SCORE needs LFO/ADSR) | +| prime-spatial | stub | none | Low | + +`prime-signal` is highest priority because `smoothdamp` and `spring` are needed by +both SCORE (parameter smoothing) and STAGE (game feel). These should be pure TS +(no WASM needed — they're simple numerical functions). + +--- + +## CLI Scope + +The coordination notes listed CLI scoping as part of t227. Proposed scope: + +**Purpose:** Development tooling for PRIME consumers. Not a user-facing product. + +**Commands:** +``` +prime sample [args] # evaluate a function, print result +prime bench # run Criterion benchmarks +prime xtest # cross-language determinism test (TS vs Rust) +prime lint # run ESLint + cargo clippy together +``` + +**Implementation:** Pure Node.js script (`packages/prime-cli/src/index.ts`). +No external CLI framework — just `process.argv` + direct function calls. + +**Priority:** Low. Not needed until SCORE/FORM start consuming PRIME packages. +Add as a separate todo when actually needed. + +--- + +## Recommended Actions + +### Immediate (this session) + +1. Update CLAUDE.md to extend ADVANCE-EXCEPTION to bounded convergence loops (not just Bridson) +2. Add TSDoc to `duffingStep` + +### Next session + +3. Implement `prime-signal` TS bindings: `smoothdamp`, `spring`, `deadzone` — pure TS, no WASM +4. Implement `prime-osc` TS bindings: `lfoSine`, `lfoSquare`, `adsr` — pure TS +5. After Rust crates are implemented (t331–t333): add TS counterparts to `prime-dynamics` + +### Planning sessions now unblocked + +- **STAGE DSL planning** (t228) — PRIME audit complete +- **FORM DSL planning** (t230) — PRIME audit complete +- **Idle Hero PRIME wiring** — PRIME audit complete; `prime-signal` TS needed first + +--- + +## Phase Plan Sketch + +| Phase | Scope | Blocks | +|---|---|---| +| P1 (current) | Audit complete, CLAUDE.md update, duffingStep doc | Nothing | +| P2 | prime-signal TS bindings | Idle Hero PRIME wiring | +| P3 | prime-osc TS bindings | SCORE LFO/ADSR wiring | +| P4 | Rust implementations: #31 #32 #33 | Cross-language determinism tests | +| P5 | prime-noise + prime-color TS bindings | FORM shader pipeline | +| P6 | CLI tooling | Developer ergonomics | +| P7 | Batch publish to npm + crates.io | All consumers switch to registry deps | diff --git a/packages/prime-color/package.json b/packages/prime-color/package.json index a6ff08a..d968bbc 100644 --- a/packages/prime-color/package.json +++ b/packages/prime-color/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-color", - "version": "0.1.0", - "description": "Color math utilities (pure TypeScript)", + "version": "1.1.0", + "description": "Color math — Oklab, sRGB, HSL/HSV, palette utilities", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-color" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "color" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-color/tsconfig.json b/packages/prime-color/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-color/tsconfig.json +++ b/packages/prime-color/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-diffusion/package.json b/packages/prime-diffusion/package.json index 3fc4593..f6d1421 100644 --- a/packages/prime-diffusion/package.json +++ b/packages/prime-diffusion/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-diffusion", - "version": "0.1.0", - "description": "Stochastic processes: Ornstein-Uhlenbeck and geometric Brownian motion", + "version": "1.1.0", + "description": "Diffusion systems — Gray-Scott, cellular automata", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-diffusion" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "diffusion" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-diffusion/tsconfig.json b/packages/prime-diffusion/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-diffusion/tsconfig.json +++ b/packages/prime-diffusion/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-dynamics/package.json b/packages/prime-dynamics/package.json index cb60903..996fa36 100644 --- a/packages/prime-dynamics/package.json +++ b/packages/prime-dynamics/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-dynamics", - "version": "0.1.0", - "description": "Dynamical systems and numerical integration — RK4, Euler, Lorenz, Rössler, Duffing", + "version": "1.1.0", + "description": "Dynamical systems — RK4, Lorenz, Duffing, L-systems, numerical calculus", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-dynamics" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "dynamics" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-dynamics/src/index.ts b/packages/prime-dynamics/src/index.ts index 6eeb03b..9dab6b0 100644 --- a/packages/prime-dynamics/src/index.ts +++ b/packages/prime-dynamics/src/index.ts @@ -546,6 +546,25 @@ export const vanDerPolStep = ( // ── Duffing oscillator ──────────────────────────────────────────────────────── +/** + * Advance the Duffing oscillator state by one RK4 step. + * + * Models a damped, driven nonlinear spring. State is `[position, velocity]`. + * + * Math: + * dx/dt = v + * dv/dt = -δv - αx - βx³ + γcos(ωt) + * + * @param state - `[x, v]` position and velocity + * @param t - current time (seconds; used for driving term) + * @param p - Duffing parameters (see `DuffingParams`) + * @param dt - time step + * @returns new `[x, v]` state + * + * @example + * const p = { delta: 0.3, alpha: -1, beta: 1, gamma: 0.37, omega: 1.2 } + * const [x1, v1] = duffingStep([0, 0], 0, p, 0.01) + */ export const duffingStep = ( state: [number, number], t: number, diff --git a/packages/prime-dynamics/tsconfig.json b/packages/prime-dynamics/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-dynamics/tsconfig.json +++ b/packages/prime-dynamics/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-interp/package.json b/packages/prime-interp/package.json index 1ac41e1..4d20796 100644 --- a/packages/prime-interp/package.json +++ b/packages/prime-interp/package.json @@ -1,11 +1,36 @@ { "name": "@prime/prime-interp", - "version": "0.1.0", - "description": "Interpolation, easing, and smoothstep functions", + "version": "1.1.0", + "description": "Interpolation and easing — lerp, smoothstep, 30+ easing functions", "license": "MIT", "type": "module", - "main": "./src/index.ts", - "types": "./src/index.ts", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-interp" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "interp" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-interp/tsconfig.json b/packages/prime-interp/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-interp/tsconfig.json +++ b/packages/prime-interp/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-noise/package.json b/packages/prime-noise/package.json index 81f473a..4a2432b 100644 --- a/packages/prime-noise/package.json +++ b/packages/prime-noise/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-noise", - "version": "0.1.0", - "description": "TypeScript bindings for prime-noise (WASM wrapper)", + "version": "1.1.0", + "description": "Noise functions — Perlin, Simplex, FBM, Worley, curl noise", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-noise" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "noise" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-noise/tsconfig.json b/packages/prime-noise/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-noise/tsconfig.json +++ b/packages/prime-noise/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-osc/package.json b/packages/prime-osc/package.json index 6c915f5..cebca0c 100644 --- a/packages/prime-osc/package.json +++ b/packages/prime-osc/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-osc", - "version": "0.1.0", - "description": "LFO shapes and ADSR envelope (pure TypeScript)", + "version": "1.1.0", + "description": "Oscillator shapes — LFO waveforms, ADSR envelope", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-osc" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "osc" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-osc/tsconfig.json b/packages/prime-osc/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-osc/tsconfig.json +++ b/packages/prime-osc/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-random/package.json b/packages/prime-random/package.json index f9dc27b..ffad95c 100644 --- a/packages/prime-random/package.json +++ b/packages/prime-random/package.json @@ -1,11 +1,36 @@ { "name": "@prime/prime-random", - "version": "0.1.0", + "version": "1.1.0", "description": "Seeded RNG — deterministic cross-platform randomness", "license": "MIT", "type": "module", - "main": "./src/index.ts", - "types": "./src/index.ts", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-random" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "random" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-random/tsconfig.json b/packages/prime-random/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-random/tsconfig.json +++ b/packages/prime-random/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-render/package.json b/packages/prime-render/package.json index 7a8da1a..61fc055 100644 --- a/packages/prime-render/package.json +++ b/packages/prime-render/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-render", - "version": "0.1.0", - "description": "Pure sample-level scan loop — fold a pure step function over N samples", + "version": "1.1.0", + "description": "Render math utilities — projection, viewport transforms", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-render" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "render" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-render/tsconfig.json b/packages/prime-render/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-render/tsconfig.json +++ b/packages/prime-render/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-sdf/package.json b/packages/prime-sdf/package.json index 50d942d..92ae6f4 100644 --- a/packages/prime-sdf/package.json +++ b/packages/prime-sdf/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-sdf", - "version": "0.1.0", - "description": "TypeScript bindings for prime-sdf (WASM wrapper)", + "version": "1.1.0", + "description": "Signed distance functions — 2D/3D primitives, boolean ops, domain transforms", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-sdf" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "sdf" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-sdf/tsconfig.json b/packages/prime-sdf/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-sdf/tsconfig.json +++ b/packages/prime-sdf/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-signal/package.json b/packages/prime-signal/package.json index b611740..39e05ad 100644 --- a/packages/prime-signal/package.json +++ b/packages/prime-signal/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-signal", - "version": "0.1.0", - "description": "Signal processing utilities (pure TypeScript)", + "version": "1.1.0", + "description": "Signal processing — smoothdamp, spring, low-pass, deadzone", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-signal" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "signal" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-signal/tsconfig.json b/packages/prime-signal/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-signal/tsconfig.json +++ b/packages/prime-signal/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-spatial/package.json b/packages/prime-spatial/package.json index 23be643..f568f4f 100644 --- a/packages/prime-spatial/package.json +++ b/packages/prime-spatial/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-spatial", - "version": "0.1.0", - "description": "Spatial queries (pure TypeScript)", + "version": "1.1.0", + "description": "Spatial math — ray tests, AABB, frustum culling", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-spatial" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "spatial" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-spatial/tsconfig.json b/packages/prime-spatial/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-spatial/tsconfig.json +++ b/packages/prime-spatial/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-splines/package.json b/packages/prime-splines/package.json index 916d208..e9ddee9 100644 --- a/packages/prime-splines/package.json +++ b/packages/prime-splines/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-splines", - "version": "0.1.0", - "description": "Spline math (pure TypeScript)", + "version": "1.1.0", + "description": "Spline math — Bezier, Catmull-Rom, B-spline, slerp", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-splines" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "splines" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-splines/tsconfig.json b/packages/prime-splines/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-splines/tsconfig.json +++ b/packages/prime-splines/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] } diff --git a/packages/prime-voronoi/package.json b/packages/prime-voronoi/package.json index c42d8b0..24f1ec8 100644 --- a/packages/prime-voronoi/package.json +++ b/packages/prime-voronoi/package.json @@ -1,10 +1,36 @@ { "name": "@prime/prime-voronoi", - "version": "0.1.0", - "description": "Voronoi and Delaunay (pure TypeScript)", + "version": "1.1.0", + "description": "Voronoi diagrams — Delaunay triangulation, Lloyd relaxation, Bowyer-Watson", "license": "MIT", - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/bwyard/prime", + "directory": "packages/prime-voronoi" + }, + "keywords": [ + "prime", + "math", + "pure-functions", + "functional", + "typescript", + "voronoi" + ], + "author": "Bree Yard", "scripts": { "build": "tsc", "test": "vitest run", diff --git a/packages/prime-voronoi/tsconfig.json b/packages/prime-voronoi/tsconfig.json index 792172f..8e5a11d 100644 --- a/packages/prime-voronoi/tsconfig.json +++ b/packages/prime-voronoi/tsconfig.json @@ -4,5 +4,11 @@ "outDir": "./dist", "rootDir": "./src" }, - "include": ["src"] + "include": [ + "src" + ], + "exclude": [ + "src/__tests__", + "node_modules" + ] }