bireactive 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/{core/anim.d.ts → animation/animators.d.ts} +5 -3
- package/dist/{core/anim.js → animation/animators.js} +8 -5
- package/dist/animation/index.d.ts +1 -0
- package/dist/animation/index.js +1 -0
- package/dist/constraints/cluster.js +1 -1
- package/dist/constraints/expose.d.ts +17 -0
- package/dist/constraints/expose.js +61 -0
- package/dist/constraints/index.d.ts +1 -0
- package/dist/constraints/index.js +1 -0
- package/dist/constraints/linalg.d.ts +1 -8
- package/dist/constraints/linalg.js +5 -108
- package/dist/core/{signal.d.ts → cell.d.ts} +29 -6
- package/dist/core/{signal.js → cell.js} +134 -53
- package/dist/core/derived-geometry.d.ts +11 -0
- package/dist/core/derived-geometry.js +32 -0
- package/dist/core/index.d.ts +5 -10
- package/dist/core/index.js +5 -10
- package/dist/core/{aggregates.d.ts → lenses/aggregates.d.ts} +3 -14
- package/dist/core/{aggregates.js → lenses/aggregates.js} +5 -78
- package/dist/core/lenses/closed-form-policies.d.ts +6 -13
- package/dist/core/lenses/closed-form-policies.js +14 -24
- package/dist/core/lenses/decompositions.d.ts +14 -0
- package/dist/core/lenses/decompositions.js +224 -0
- package/dist/core/lenses/domain-aggregates.d.ts +10 -22
- package/dist/core/lenses/domain-aggregates.js +25 -39
- package/dist/core/{new-primitives.d.ts → lenses/geometry.d.ts} +11 -14
- package/dist/core/{new-primitives.js → lenses/geometry.js} +23 -37
- package/dist/core/lenses/index.d.ts +6 -4
- package/dist/core/lenses/index.js +6 -15
- package/dist/core/lenses/typed-factor.d.ts +1 -6
- package/dist/core/lenses/typed-factor.js +12 -114
- package/dist/core/{network-utils.d.ts → lifecycle.d.ts} +1 -1
- package/dist/core/{network-utils.js → lifecycle.js} +2 -2
- package/dist/core/linalg.d.ts +10 -0
- package/dist/core/linalg.js +109 -0
- package/dist/core/values/anchor.d.ts +1 -1
- package/dist/core/values/audio.d.ts +1 -1
- package/dist/core/values/audio.js +1 -1
- package/dist/core/values/bool.d.ts +1 -1
- package/dist/core/values/bool.js +1 -1
- package/dist/core/values/box.d.ts +2 -3
- package/dist/core/values/box.js +5 -6
- package/dist/core/values/canvas.d.ts +1 -1
- package/dist/core/values/canvas.js +2 -3
- package/dist/core/values/color.d.ts +2 -3
- package/dist/core/values/color.js +3 -4
- package/dist/core/values/flags.d.ts +1 -1
- package/dist/core/values/flags.js +1 -1
- package/dist/core/values/matrix.d.ts +1 -1
- package/dist/core/values/matrix.js +2 -3
- package/dist/core/values/num.d.ts +8 -3
- package/dist/core/values/num.js +22 -2
- package/dist/core/values/pose.d.ts +5 -1
- package/dist/core/values/pose.js +11 -1
- package/dist/core/values/range.d.ts +6 -4
- package/dist/core/values/range.js +16 -11
- package/dist/core/values/str.d.ts +1 -1
- package/dist/core/values/str.js +1 -1
- package/dist/core/values/template.d.ts +1 -1
- package/dist/core/values/transform.d.ts +2 -3
- package/dist/core/values/transform.js +2 -3
- package/dist/core/values/tri.d.ts +10 -8
- package/dist/core/values/tri.js +12 -12
- package/dist/core/values/vec.d.ts +10 -4
- package/dist/core/values/vec.js +30 -21
- package/dist/ext/timeline.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/propagators/layout.js +1 -1
- package/dist/shapes/handle.js +4 -4
- package/dist/shapes/shape.js +7 -7
- package/dist/shapes/transitions.js +2 -2
- package/package.json +7 -2
- package/dist/core/introspect.d.ts +0 -5
- package/dist/core/introspect.js +0 -31
- package/dist/core/lenses/factor-lens.d.ts +0 -42
- package/dist/core/lenses/factor-lens.js +0 -419
- package/dist/core/writable.d.ts +0 -15
- package/dist/core/writable.js +0 -29
- /package/dist/{core/tree.d.ts → tree.d.ts} +0 -0
- /package/dist/{core/tree.js → tree.js} +0 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# bi-reactive
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
[npm](https://www.npmjs.com/package/bireactive) · [GitHub](https://github.com/OrionReed/bireactive) · [site](https://orionreed.github.io/bireactive/)
|
|
4
|
+
|
|
5
|
+
A signals-like bidirectional reactive programming system where edges can go both ways. Forward and backward propagation are handled by the engine, with the same set of caveats as regular reactive programming.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -36,12 +36,12 @@ Values also come as small classes (`Num`, `Vec`, `Box`, `Color`, ...) with field
|
|
|
36
36
|
lenses and bidirectional operators.
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
|
-
import { vec, box,
|
|
39
|
+
import { vec, box, mean } from "bireactive";
|
|
40
40
|
|
|
41
|
-
// Free-function lens: the midpoint of two points, writable.
|
|
41
|
+
// Free-function lens: the mean (midpoint) of two points, writable.
|
|
42
42
|
const a = vec(0, 0);
|
|
43
43
|
const b = vec(10, 0);
|
|
44
|
-
const mid =
|
|
44
|
+
const mid = mean([a, b]);
|
|
45
45
|
mid.value = { x: 5, y: 10 }; // drag it up…
|
|
46
46
|
a.value; // { x: 0, y: 10 } — both ends translate to keep it the midpoint
|
|
47
47
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { Cell, type Read, type Val, type Writable } from "../core/cell.js";
|
|
2
|
+
import { type TraitKey, type Traits } from "../core/traits.js";
|
|
3
|
+
import type { Yieldable } from "./anim.js";
|
|
4
|
+
import { type Animator, type Tick } from "./anim.js";
|
|
5
|
+
import { type Easing } from "./easings.js";
|
|
4
6
|
/** Animator-style constraint: a writable reactive carrying `T` whose
|
|
5
7
|
* class declares the listed traits. Reads as a sentence:
|
|
6
8
|
*
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
//
|
|
2
|
-
// nominal trait constraint)
|
|
1
|
+
// animators.ts — animator primitives over `Animatable<T, K>` (writable +
|
|
2
|
+
// nominal trait constraint): the signals↔generators bridge. Lives with the
|
|
3
|
+
// generator runtime; depends on core for the reactive substrate.
|
|
3
4
|
//
|
|
4
5
|
// Signatures read as a sentence ("spring takes a writable carrying T
|
|
5
6
|
// with linear+metric"), so misuse is a compile error: `spring(box, …)`
|
|
6
7
|
// (no metric), `spring(roVec, …)` (not writable).
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { Cell, derive, effect, reader } from "../core/cell.js";
|
|
9
|
+
import { requireLerp, requireLinear, requireMetric, } from "../core/traits.js";
|
|
10
|
+
import { isGenerator } from "./anim.js";
|
|
11
|
+
import { drive, race, suspend } from "./combinators.js";
|
|
12
|
+
import { easeOut } from "./easings.js";
|
|
10
13
|
const defaultEase = easeOut;
|
|
11
14
|
/** Chainable Animator over a writable cell: `.to(...).to(...).from(start)`
|
|
12
15
|
* reads naturally. `.to`/`.from` are pure data — segments accumulate at
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { Anim, type Animator, type Cut, cut, isGenerator, type Resume, type Suspend, type Tick, type Yieldable, } from "./anim.js";
|
|
2
|
+
export { type Animatable, attract, driven, every, loop, not, type Play, play, type SpringOpts, spring, Tween, toward, tween, untilChange, wave, when, } from "./animators.js";
|
|
2
3
|
export { all, allSettled, anySuccess, commit, detach, drive, firstMatching, firstN, race, rand, type Settled, suspend, untilEvent, untilPromise, } from "./combinators.js";
|
|
3
4
|
export { type Easing, easeIn, easeInOut, easeOut, linear } from "./easings.js";
|
package/dist/animation/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { Anim, cut, isGenerator, } from "./anim.js";
|
|
2
|
+
export { attract, driven, every, loop, not, play, spring, Tween, toward, tween, untilChange, wave, when, } from "./animators.js";
|
|
2
3
|
export { all, allSettled, anySuccess, commit, detach, drive, firstMatching, firstN, race, rand, suspend, untilEvent, untilPromise, } from "./combinators.js";
|
|
3
4
|
export { easeIn, easeInOut, easeOut, linear } from "./easings.js";
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// returns a disposer. `c.add(rel)` calls `bind`; `c.remove(rel)`
|
|
15
15
|
// calls the disposer.
|
|
16
16
|
import { cell, network, requirePack, } from "../core/index.js";
|
|
17
|
-
import { when } from "../core/
|
|
17
|
+
import { when } from "../core/lifecycle.js";
|
|
18
18
|
import { reactivePipeline } from "./phases.js";
|
|
19
19
|
import { Solver } from "./solver.js";
|
|
20
20
|
export class Constraints {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Vec, type Writable } from "../core/index.js";
|
|
2
|
+
import type { Constraints } from "./cluster.js";
|
|
3
|
+
export interface ExposeOpts {
|
|
4
|
+
/** Solver sweeps per write (each `step` runs `cluster.iterations`
|
|
5
|
+
* inner iterations, warm-started from the previous sweep). Default 4
|
|
6
|
+
* — enough to land on a reachable target in one write; the cluster
|
|
7
|
+
* also warm-starts across writes, so a spring/drag refines per frame. */
|
|
8
|
+
iters?: number;
|
|
9
|
+
/** Stiffness of the soft pull toward the written target. High → the
|
|
10
|
+
* handle lands on the target; lower → it lags onto the manifold like
|
|
11
|
+
* a dragged-through-load anchor. Default 1e5. */
|
|
12
|
+
stiffness?: number;
|
|
13
|
+
}
|
|
14
|
+
/** Expose one cell of a `Vec` constraint cluster as a writable lens over
|
|
15
|
+
* the cluster's solution manifold. `free` is the set whose solved
|
|
16
|
+
* positions are read back (`handle` must be among them). See module note. */
|
|
17
|
+
export declare function exposeVec(c: Constraints, free: readonly Writable<Vec>[], handle: Writable<Vec>, opts?: ExposeOpts): Writable<Vec>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// expose.ts — a constraint cluster, oriented as a writable lens.
|
|
2
|
+
//
|
|
3
|
+
// A constraint network is an *unoriented* relation: it has no inputs or
|
|
4
|
+
// outputs, just cells that must agree. A lens is an *oriented* relation —
|
|
5
|
+
// one end you write, the rest follow. `exposeVec` picks the orientation:
|
|
6
|
+
// it names one bound cell the handle and hands back a single
|
|
7
|
+
// `Writable<Vec>` whose backward direction relaxes the cluster.
|
|
8
|
+
//
|
|
9
|
+
// Writing the handle re-aims a strong soft pull at the target, steps the
|
|
10
|
+
// (manually-driven) solver, and reads the settled positions of `free`
|
|
11
|
+
// straight out of the solver buffers — so the whole mechanism collapses
|
|
12
|
+
// to one composable value. `spring`, `handle`, `crossfade`, `mean` — any
|
|
13
|
+
// lens or animator that takes a `Writable<Vec>` now drives the network.
|
|
14
|
+
//
|
|
15
|
+
// Ownership: `exposeVec` disposes the cluster's reactive driver and takes
|
|
16
|
+
// over stepping (the lens body is the only thing that calls `step`), so
|
|
17
|
+
// there's no auto-resolve racing the backward pass. Drive the network
|
|
18
|
+
// through the returned handle(s), not by writing the bound cells directly.
|
|
19
|
+
//
|
|
20
|
+
// One cluster, many handles: call `exposeVec` again with a different cell
|
|
21
|
+
// to expose another section of the same relation (each write relaxes the
|
|
22
|
+
// shared solver). The writeback phase is dropped, so the handles never
|
|
23
|
+
// fight over committing the bound signals — each backward pass reads the
|
|
24
|
+
// freshly solved positions and returns them as its own updates.
|
|
25
|
+
import { Vec } from "../core/index.js";
|
|
26
|
+
import { prepare, solve } from "./phases.js";
|
|
27
|
+
import { SoftTargetTerm } from "./terms.js";
|
|
28
|
+
/** Expose one cell of a `Vec` constraint cluster as a writable lens over
|
|
29
|
+
* the cluster's solution manifold. `free` is the set whose solved
|
|
30
|
+
* positions are read back (`handle` must be among them). See module note. */
|
|
31
|
+
export function exposeVec(c, free, handle, opts = {}) {
|
|
32
|
+
const iters = opts.iters ?? 4;
|
|
33
|
+
const stiffness = opts.stiffness ?? 1e5;
|
|
34
|
+
const hidx = free.indexOf(handle);
|
|
35
|
+
if (hidx < 0)
|
|
36
|
+
throw new Error("exposeVec: handle must be one of `free`");
|
|
37
|
+
// Take over the time loop: the backward pass is the only `step` caller.
|
|
38
|
+
c.dispose();
|
|
39
|
+
// Drop BOTH snapshot and writeback: the solver's own `positions` are the
|
|
40
|
+
// state. `_bind` seeded them from the cells; each write iterates `solve`
|
|
41
|
+
// in place (warm-started), then we read the settled positions back as
|
|
42
|
+
// the lens's updates — committed once by the engine. No re-snapshot means
|
|
43
|
+
// repeated sweeps actually converge, and state persists across writes.
|
|
44
|
+
c.pipeline = [prepare, solve];
|
|
45
|
+
// A re-aimable soft pull standing in for "the value you wrote".
|
|
46
|
+
const seed = handle.peek();
|
|
47
|
+
const drive = new SoftTargetTerm(c.solver, c._bind(handle), [seed.x, seed.y], stiffness);
|
|
48
|
+
c.solver.addTerm(drive);
|
|
49
|
+
const offsets = free.map(f => c.solver.offsets[c._bind(f)]);
|
|
50
|
+
const readSolved = (i) => {
|
|
51
|
+
const off = offsets[i];
|
|
52
|
+
return { x: c.solver.positions[off], y: c.solver.positions[off + 1] };
|
|
53
|
+
};
|
|
54
|
+
return Vec.lens(free, (vals) => vals[hidx], (target) => {
|
|
55
|
+
drive.target[0] = target.x;
|
|
56
|
+
drive.target[1] = target.y;
|
|
57
|
+
for (let i = 0; i < iters; i++)
|
|
58
|
+
c.step();
|
|
59
|
+
return free.map((_, i) => readSolved(i));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { Constraints, constraints, type Relation } from "./cluster.js";
|
|
2
2
|
export { animate, dilated, fixedStep, } from "./drivers.js";
|
|
3
|
+
export { type ExposeOpts, exposeVec } from "./expose.js";
|
|
3
4
|
export { angle, bend, clamp, collinear, distance, eq, equalDist, gap, generic, geq, inside, lensNum, leq, midpoint, onCircle, parallel, perpendicular, pin, repel, rightAngle, softTarget, spring, } from "./factories.js";
|
|
4
5
|
export { dragBody, dragBodyAnchored } from "./interaction.js";
|
|
5
6
|
export { type Phase, prepare, snapshot, solve, writeback } from "./phases.js";
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
// https://github.com/savant117/avbd-demo2d.
|
|
29
29
|
export { Constraints, constraints } from "./cluster.js";
|
|
30
30
|
export { animate, dilated, fixedStep, } from "./drivers.js";
|
|
31
|
+
export { exposeVec } from "./expose.js";
|
|
31
32
|
export { angle, bend, clamp, collinear, distance, eq, equalDist, gap, generic, geq, inside, lensNum, leq, midpoint, onCircle, parallel, perpendicular, pin, repel, rightAngle, softTarget, spring, } from "./factories.js";
|
|
32
33
|
export { dragBody, dragBodyAnchored } from "./interaction.js";
|
|
33
34
|
export { prepare, snapshot, solve, writeback } from "./phases.js";
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* LDLᵀ. Returns `false` if too singular to solve safely (leaving
|
|
3
|
-
* `b` undefined — callers typically leave the cell unchanged). */
|
|
4
|
-
export declare function solveSPD(A: Float64Array, b: Float64Array, n: number): boolean;
|
|
5
|
-
/** 2×2 SPD direct solve. A is row-major; we use the symmetry. */
|
|
6
|
-
export declare function solve2(A: Float64Array, b: Float64Array): boolean;
|
|
7
|
-
/** 3×3 SPD direct solve via cofactor expansion. */
|
|
8
|
-
export declare function solve3(A: Float64Array, b: Float64Array): boolean;
|
|
1
|
+
export { solve2, solve3, solveSPD } from "../core/linalg.js";
|
|
9
2
|
/** Add `α · v · vᵀ` to a square matrix `A` in row-major form.
|
|
10
3
|
* Used to accumulate Jᵀ J terms in the local Newton system. */
|
|
11
4
|
export declare function addOuterProduct(A: Float64Array, v: Float64Array, alpha: number, n: number): void;
|
|
@@ -1,113 +1,10 @@
|
|
|
1
|
-
// linalg.ts —
|
|
2
|
-
// Newton
|
|
3
|
-
//
|
|
1
|
+
// linalg.ts — constraint-specific dense matrix helpers for AVBD's
|
|
2
|
+
// per-cell local Newton system. The SPD solve itself is shared with the
|
|
3
|
+
// numerical lenses (`solveSPD` lives in core); this module re-exports it
|
|
4
|
+
// and adds the accumulation helpers the solver assembles its LHS with.
|
|
4
5
|
//
|
|
5
6
|
// Convention: matrices are row-major Float64Array of length n*n.
|
|
6
|
-
|
|
7
|
-
const TINY = 1e-14;
|
|
8
|
-
/** Solve an SPD (or semi-definite) system `A·x = b` in place via
|
|
9
|
-
* LDLᵀ. Returns `false` if too singular to solve safely (leaving
|
|
10
|
-
* `b` undefined — callers typically leave the cell unchanged). */
|
|
11
|
-
export function solveSPD(A, b, n) {
|
|
12
|
-
if (n === 1) {
|
|
13
|
-
const a = A[0];
|
|
14
|
-
if (Math.abs(a) < TINY)
|
|
15
|
-
return false;
|
|
16
|
-
b[0] = b[0] / a;
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
if (n === 2)
|
|
20
|
-
return solve2(A, b);
|
|
21
|
-
if (n === 3)
|
|
22
|
-
return solve3(A, b);
|
|
23
|
-
// General LDLᵀ.
|
|
24
|
-
return ldltGeneric(A, b, n);
|
|
25
|
-
}
|
|
26
|
-
/** 2×2 SPD direct solve. A is row-major; we use the symmetry. */
|
|
27
|
-
export function solve2(A, b) {
|
|
28
|
-
const a = A[0];
|
|
29
|
-
const c = A[1]; // = A[2] by symmetry
|
|
30
|
-
const d = A[3];
|
|
31
|
-
const det = a * d - c * c;
|
|
32
|
-
if (Math.abs(det) < TINY)
|
|
33
|
-
return false;
|
|
34
|
-
const inv = 1 / det;
|
|
35
|
-
const x0 = (d * b[0] - c * b[1]) * inv;
|
|
36
|
-
const x1 = (-c * b[0] + a * b[1]) * inv;
|
|
37
|
-
b[0] = x0;
|
|
38
|
-
b[1] = x1;
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
/** 3×3 SPD direct solve via cofactor expansion. */
|
|
42
|
-
export function solve3(A, b) {
|
|
43
|
-
const a00 = A[0], a01 = A[1], a02 = A[2];
|
|
44
|
-
const a10 = A[3], a11 = A[4], a12 = A[5];
|
|
45
|
-
const a20 = A[6], a21 = A[7], a22 = A[8];
|
|
46
|
-
const c00 = a11 * a22 - a12 * a21;
|
|
47
|
-
const c01 = -(a10 * a22 - a12 * a20);
|
|
48
|
-
const c02 = a10 * a21 - a11 * a20;
|
|
49
|
-
const det = a00 * c00 + a01 * c01 + a02 * c02;
|
|
50
|
-
if (Math.abs(det) < TINY)
|
|
51
|
-
return false;
|
|
52
|
-
const c10 = -(a01 * a22 - a02 * a21);
|
|
53
|
-
const c11 = a00 * a22 - a02 * a20;
|
|
54
|
-
const c12 = -(a00 * a21 - a01 * a20);
|
|
55
|
-
const c20 = a01 * a12 - a02 * a11;
|
|
56
|
-
const c21 = -(a00 * a12 - a02 * a10);
|
|
57
|
-
const c22 = a00 * a11 - a01 * a10;
|
|
58
|
-
const inv = 1 / det;
|
|
59
|
-
const b0 = b[0], b1 = b[1], b2 = b[2];
|
|
60
|
-
// Inverse is transpose of cofactor / det. For SPD it equals the
|
|
61
|
-
// adjugate / det. We multiply by b directly.
|
|
62
|
-
b[0] = (c00 * b0 + c10 * b1 + c20 * b2) * inv;
|
|
63
|
-
b[1] = (c01 * b0 + c11 * b1 + c21 * b2) * inv;
|
|
64
|
-
b[2] = (c02 * b0 + c12 * b1 + c22 * b2) * inv;
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
/** General LDLᵀ for `n ≥ 4`. In-place: `A` is overwritten with the
|
|
68
|
-
* factor, `b` is overwritten with the solution. */
|
|
69
|
-
function ldltGeneric(A, b, n) {
|
|
70
|
-
// Factor: A = L D Lᵀ where L is unit lower-triangular and D is
|
|
71
|
-
// diagonal. We store L in the strictly-lower part of A and D on
|
|
72
|
-
// the diagonal.
|
|
73
|
-
for (let j = 0; j < n; j++) {
|
|
74
|
-
// D[j] = A[j,j] - Σ_{k<j} L[j,k]² · D[k]
|
|
75
|
-
let djj = A[j * n + j];
|
|
76
|
-
for (let k = 0; k < j; k++) {
|
|
77
|
-
const ljk = A[j * n + k];
|
|
78
|
-
djj -= ljk * ljk * A[k * n + k];
|
|
79
|
-
}
|
|
80
|
-
if (Math.abs(djj) < TINY)
|
|
81
|
-
return false;
|
|
82
|
-
A[j * n + j] = djj;
|
|
83
|
-
// L[i,j] = (A[i,j] - Σ_{k<j} L[i,k] L[j,k] D[k]) / D[j]
|
|
84
|
-
for (let i = j + 1; i < n; i++) {
|
|
85
|
-
let lij = A[i * n + j];
|
|
86
|
-
for (let k = 0; k < j; k++) {
|
|
87
|
-
lij -= A[i * n + k] * A[j * n + k] * A[k * n + k];
|
|
88
|
-
}
|
|
89
|
-
A[i * n + j] = lij / djj;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// Forward solve L y = b → y in b.
|
|
93
|
-
for (let i = 0; i < n; i++) {
|
|
94
|
-
let yi = b[i];
|
|
95
|
-
for (let k = 0; k < i; k++)
|
|
96
|
-
yi -= A[i * n + k] * b[k];
|
|
97
|
-
b[i] = yi;
|
|
98
|
-
}
|
|
99
|
-
// D solve: y_i ← y_i / D[i].
|
|
100
|
-
for (let i = 0; i < n; i++)
|
|
101
|
-
b[i] /= A[i * n + i];
|
|
102
|
-
// Backward solve Lᵀ x = y → x in b.
|
|
103
|
-
for (let i = n - 1; i >= 0; i--) {
|
|
104
|
-
let xi = b[i];
|
|
105
|
-
for (let k = i + 1; k < n; k++)
|
|
106
|
-
xi -= A[k * n + i] * b[k];
|
|
107
|
-
b[i] = xi;
|
|
108
|
-
}
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
7
|
+
export { solve2, solve3, solveSPD } from "../core/linalg.js";
|
|
111
8
|
/** Add `α · v · vᵀ` to a square matrix `A` in row-major form.
|
|
112
9
|
* Used to accumulate Jᵀ J terms in the local Newton system. */
|
|
113
10
|
export function addOuterProduct(A, v, alpha, n) {
|
|
@@ -18,7 +18,7 @@ interface Link {
|
|
|
18
18
|
nextDep: Link | undefined;
|
|
19
19
|
}
|
|
20
20
|
/** Install a hook fired on every source value-change; returns a restore fn. */
|
|
21
|
-
export declare function setCellWriteHook(fn: ((
|
|
21
|
+
export declare function setCellWriteHook(fn: ((cell: Cell<unknown>) => void) | undefined): () => void;
|
|
22
22
|
export interface MergePolicy<T> {
|
|
23
23
|
readonly identity: T;
|
|
24
24
|
combine(acc: T, x: T): T;
|
|
@@ -99,8 +99,8 @@ export declare function lazy<R>(self: object, key: string | symbol, make: () =>
|
|
|
99
99
|
export declare const isCell: (v: unknown) => v is Cell<unknown>;
|
|
100
100
|
/** Lens mode: a derived cell that can be written back (has a backward sidecar). */
|
|
101
101
|
export declare const isLens: (v: unknown) => v is Cell<unknown>;
|
|
102
|
-
/**
|
|
103
|
-
export declare const
|
|
102
|
+
/** Read-only mode: derived with no backward path. */
|
|
103
|
+
export declare const isReadonly: (v: unknown) => v is Cell<unknown>;
|
|
104
104
|
export interface CellOptions<T = unknown> {
|
|
105
105
|
/** First subscriber attached; fired from `link`. */
|
|
106
106
|
watched?: () => void;
|
|
@@ -149,6 +149,9 @@ export declare class Cell<T = unknown> implements ReactiveNode {
|
|
|
149
149
|
/** Endomorphic lens. A 2-arg `bwd(view, current)` consults the current
|
|
150
150
|
* source; a 1-arg `bwd(view)` reconstructs it from the view alone. */
|
|
151
151
|
lens(this: Cell<T>, fwd: (v: T) => T, bwd: (target: T, current: T) => T): this;
|
|
152
|
+
/** Read-only same-type view: the RO dual of the endo `.lens`. For a cross-type view use the typed static
|
|
153
|
+
* `Target.derive(src, fn)`. */
|
|
154
|
+
derive(this: Cell<T>, fn: (v: T) => T): this;
|
|
152
155
|
/** Backward-aggregating node — bwd dual of computed. Forward, the
|
|
153
156
|
* identity view of its parent; backward, folds contributions from
|
|
154
157
|
* upstream lenses (slot-keyed) and direct writes (DIRECT_SLOT). */
|
|
@@ -205,7 +208,6 @@ export interface StatefulLensSpec<S extends readonly unknown[], V, C> {
|
|
|
205
208
|
}
|
|
206
209
|
/** Writable source; passes an existing `Writable` through (idempotent). */
|
|
207
210
|
export declare function cell<T>(initial: T | Writable<Cell<T>>, opts?: CellOptions<T>): Writable<Cell<T>>;
|
|
208
|
-
export declare function computed<T>(fn: () => T): Cell<T>;
|
|
209
211
|
/** Untyped read-only view: `derive(parent, fn)`, `derive(parents, fn)`,
|
|
210
212
|
* or `derive(fn)` (closure). */
|
|
211
213
|
export declare function derive<P, R>(parent: Read<P>, fn: (v: P) => R): Cell<R>;
|
|
@@ -238,9 +240,9 @@ export interface Network {
|
|
|
238
240
|
/** Run the body now (manual mode's only advance; no-op if unchanged). */
|
|
239
241
|
flush(): void;
|
|
240
242
|
/** Add cells to the topology (idempotent; does NOT fire the body). */
|
|
241
|
-
subscribe(...
|
|
243
|
+
subscribe(...cells: Cell<any>[]): void;
|
|
242
244
|
/** Remove cells from the topology (idempotent; does NOT fire). */
|
|
243
|
-
unsubscribe(...
|
|
245
|
+
unsubscribe(...cells: Cell<any>[]): void;
|
|
244
246
|
}
|
|
245
247
|
/** Build a reactive sub-DAG node with explicit topology. The body fires
|
|
246
248
|
* when any subscribed dep changes (`dirty` = the changed subset), runs
|
|
@@ -251,4 +253,25 @@ export interface Network {
|
|
|
251
253
|
export declare function network(deps: readonly Cell<any>[], body: (dirty: ReadonlySet<Cell<unknown>>, handle: Network) => void, opts?: {
|
|
252
254
|
manual?: boolean;
|
|
253
255
|
}): Network;
|
|
256
|
+
/** Bidirectional field lens onto `parent.value[key]`; write spread-
|
|
257
|
+
* replaces the composite. Cached per (instance, key). Return type is
|
|
258
|
+
* conditional: `Writable<Cls>` on a writable parent, bare `Cls` on RO.
|
|
259
|
+
*
|
|
260
|
+
* get x() { return field(this, "x", Num); } */
|
|
261
|
+
export declare function field<S extends Cell<any>, K extends keyof Inner<S>, C extends new (...args: never[]) => Cell<Inner<S>[K]>>(parent: S, key: K, Cls: C): S extends WritableBrand ? Writable<InstanceType<C>> : InstanceType<C>;
|
|
262
|
+
/** Read-only derived view via `Cls.derive(parent, fn)`, memoized per
|
|
263
|
+
* (instance, key); always bare `Cls` (RO). The cache is the point — the
|
|
264
|
+
* getter form, not a new kind of cell.
|
|
265
|
+
*
|
|
266
|
+
* get magnitude() {
|
|
267
|
+
* return cachedDerive(this, "magnitude", Num, v => Math.hypot(v.x, v.y));
|
|
268
|
+
* } */
|
|
269
|
+
export declare function cachedDerive<S extends Cell<any>, C extends new (...args: never[]) => Cell<any>>(parent: S, key: string | symbol, Cls: C, fn: (v: Inner<S>) => Inner<InstanceType<C>>): InstanceType<C>;
|
|
270
|
+
/** Every cell `s` transitively depends on, including itself. Raw cells
|
|
271
|
+
* return `{s}`; lens chains return the chain plus all parents. BFS,
|
|
272
|
+
* peeking each Computed to populate deps; the `seen` set breaks cycles.
|
|
273
|
+
* Used by `Propagators` to expand declared reads into their transitive
|
|
274
|
+
* parent set. Inspection is safe: it only reads engine state and peeks
|
|
275
|
+
* `.value` (idempotent for lazy Computeds). */
|
|
276
|
+
export declare function transitiveDeps(s: Cell<unknown>): Set<Cell<unknown>>;
|
|
254
277
|
export {};
|