@johnhenry/math-sample 0.0.1 → 0.1.0
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 +111 -3
- package/dist/budget.d.ts +47 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +44 -0
- package/dist/budget.js.map +1 -0
- package/dist/complex.d.ts +79 -0
- package/dist/complex.d.ts.map +1 -0
- package/dist/complex.js +236 -0
- package/dist/complex.js.map +1 -0
- package/dist/expr.d.ts +12 -0
- package/dist/expr.d.ts.map +1 -1
- package/dist/expr.js +240 -0
- package/dist/expr.js.map +1 -1
- package/dist/field2d.d.ts +58 -0
- package/dist/field2d.d.ts.map +1 -0
- package/dist/field2d.js +199 -0
- package/dist/field2d.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/mesh.d.ts +90 -0
- package/dist/mesh.d.ts.map +1 -0
- package/dist/mesh.js +294 -0
- package/dist/mesh.js.map +1 -0
- package/dist/ode.d.ts +147 -0
- package/dist/ode.d.ts.map +1 -0
- package/dist/ode.js +466 -0
- package/dist/ode.js.map +1 -0
- package/dist/series.d.ts +53 -0
- package/dist/series.d.ts.map +1 -0
- package/dist/series.js +158 -0
- package/dist/series.js.map +1 -0
- package/package.json +3 -3
- package/src/budget.ts +72 -0
- package/src/complex.ts +327 -0
- package/src/expr.ts +244 -0
- package/src/field2d.ts +259 -0
- package/src/index.ts +76 -0
- package/src/mesh.ts +376 -0
- package/src/ode.ts +633 -0
- package/src/series.ts +209 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @johnhenry/math-sample
|
|
2
2
|
|
|
3
|
-
Sampling for plots, as a library with no DOM in it. Give it a `(x) => number`
|
|
3
|
+
Sampling for plots (1D curves, 2D implicit/contour/gradient fields, 3D meshes, complex rasters, ODEs, series), as a library with no DOM in it. Give it a `(x) => number`
|
|
4
4
|
(or an `@johnhenry/math` expression) and a viewport; get back `Float64Array`s
|
|
5
5
|
with the poles and jumps already turned into gaps, plus the viewport maths,
|
|
6
6
|
"nice" ticks and SVG path output a plot needs. Pure ESM, zero runtime
|
|
@@ -111,14 +111,122 @@ dependency**; the main entry never imports it. In a Worker: post the source
|
|
|
111
111
|
string and params, compile there, sample, and `postMessage` the arrays with
|
|
112
112
|
`[s.x.buffer, s.y.buffer]` as transferables.
|
|
113
113
|
|
|
114
|
+
## 2D and 3D samplers, ODEs, series (part 2/3)
|
|
115
|
+
|
|
116
|
+
All of these take plain functions, return typed arrays, and never draw spikes: a
|
|
117
|
+
non-finite value is a **hole** (a gap row in curves, a skipped vertex in meshes,
|
|
118
|
+
`NaN` in rasters). The grid and field samplers (`sampleSurface`, `sampleParametricSurface`,
|
|
119
|
+
`sampleSpaceCurve`, `sampleVectorField3`, `sampleComplexRaster`, `findZerosAndPoles`, `sampleSlopeField`,
|
|
120
|
+
`samplePhasePortrait` (field pass), `sampleImplicit`, `sampleContours`, `sampleGradient`) accept a
|
|
121
|
+
**budget** and the cancellation options of part 1 (`signal`, `isCancelled`, which throw
|
|
122
|
+
`SampleCancelledError`). `conformalGrid`, the ODE integrators, and the series/Fourier samplers do not take a budget
|
|
123
|
+
(they are bounded by their own `samplesPerLine`, `maxSteps`, `samples` arguments):
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
{ maxCells?: number; maxMillis?: number; now?: () => number }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
When the budget runs out the sampler stops at a row (or slab) boundary and
|
|
130
|
+
**returns what it has** with `progress: { rows, of, complete, reason? }`
|
|
131
|
+
(`reason` is `"cells"` or `"time"`), so a UI can say "stopped at row 120 of 161:
|
|
132
|
+
the time limit". The time limit is checked per row, so one row can overrun it.
|
|
133
|
+
|
|
134
|
+
### 3D (typed-array meshes)
|
|
135
|
+
|
|
136
|
+
| Function | Returns |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `sampleSurface(f(x, y), xDomain, yDomain, { columns, rows, zRange, ...budget })` | `Mesh` for `z = f(x, y)` |
|
|
139
|
+
| `sampleParametricSurface(f(u, v) => [x, y, z], uDomain, vDomain, opts)` | `Mesh` |
|
|
140
|
+
| `sampleSpaceCurve(f(t) => [x, y, z], tDomain, { samples, maxStep, ...budget })` | `Curve3` |
|
|
141
|
+
| `curve3Runs(curve)` | `[start, end)` row ranges of consecutive data |
|
|
142
|
+
| `sampleVectorField3(f(x, y, z) => [a, b, c], xD, yD, zD, { grid, ...budget })` | `VectorField3` |
|
|
143
|
+
|
|
144
|
+
`Mesh` is `{ positions: Float32Array, normals: Float32Array, indices: Uint32Array, valid: Uint8Array,
|
|
145
|
+
vertexCount, columns, rows, bounds, progress }` (3 floats per vertex; triangles are counter-clockwise
|
|
146
|
+
seen from the side the normals point to, which is `+z` for `sampleSurface`, and `dP/du x dP/dv` for a
|
|
147
|
+
parametric surface). A hole vertex has `NaN` position, zero normal and `valid = 0`, and **no triangle
|
|
148
|
+
references it**, so GPU upload needs no special casing. `zRange` also turns a pole's huge but finite
|
|
149
|
+
shoulders into holes. A quad with one hole corner keeps its other triangle. `bounds` covers valid vertices
|
|
150
|
+
(`NaN`s when there are none). A valid vertex whose own normal degenerates (the poles of a sphere parameterisation) borrows
|
|
151
|
+
a neighbouring vertex's normal. Mind the sign: `dP/du x dP/dv` on the usual sphere parameterisation
|
|
152
|
+
`(sin v cos u, sin v sin u, cos v)` points **inward**; swap the arguments or negate a component for outward normals.
|
|
153
|
+
`Curve3` is `{ positions: Float64Array (3 per row), t, count, progress }` with `NaN` rows as gaps (never first,
|
|
154
|
+
last or adjacent). `VectorField3` is `{ origins, vectors, magnitudes: Float32Array, maxMagnitude, count,
|
|
155
|
+
skipped, progress }`; points where the field is non-finite are dropped and counted in `skipped`.
|
|
156
|
+
|
|
157
|
+
### Complex functions
|
|
158
|
+
|
|
159
|
+
`ComplexFn` is `(re, im) => [re, im]`.
|
|
160
|
+
|
|
161
|
+
- `sampleComplexRaster(f, reDomain, imDomain, { width, height })`: `{ re, im, abs, arg: Float32Array,
|
|
162
|
+
width, height, progress }` sampled at cell centres, row 0 at the smallest imaginary part; `arg` in
|
|
163
|
+
`(-PI, PI]`. Colour it yourself (hue from `arg`, brightness from `abs`).
|
|
164
|
+
- `conformalGrid(f, reDomain, imDomain, { reLines, imLines, samplesPerLine, bound, maxStep })`: the image of a
|
|
165
|
+
rectangular grid of lines as `{ kind: "re" | "im", value, x, y }[]`; `NaN` gaps where `|f| > bound` (a pole)
|
|
166
|
+
or a step exceeds `maxStep` (a branch cut).
|
|
167
|
+
- `findZerosAndPoles(f, reDomain, imDomain, { grid, tolerance })`: argument principle on every grid cell
|
|
168
|
+
(winding number = zeros - poles), then Newton on `f` or `1/f` scaled by the multiplicity. Returns
|
|
169
|
+
`{ items: { re, im, kind, order, refined }[] }`. A zero and a pole in one cell cancel, and two distinct
|
|
170
|
+
roots in one cell are reported as one root of the combined order (Newton's step scaled by that order may fail to converge,
|
|
171
|
+
giving `refined: false` at the cell centre): raise `grid` if you suspect it. A genuine multiple root (`z^3`) reports
|
|
172
|
+
its multiplicity once with `refined: true`. The search grid is offset by an irrational fraction of a cell and
|
|
173
|
+
extended past the rectangle, so roots and poles on round-number domains and on grid vertices are found; results
|
|
174
|
+
outside the rectangle are dropped.
|
|
175
|
+
|
|
176
|
+
### ODEs
|
|
177
|
+
|
|
178
|
+
- `sampleSlopeField(f(x, y), xDomain, yDomain, { columns, rows })`: slopes and unit directions
|
|
179
|
+
(`dirX`, `dirY`; vertical slopes are `(0, +-1)`; `NaN` where undefined).
|
|
180
|
+
- `integrateRk4(f(t, y[]) => number[], t0, y0[], tEnd, { steps })` and `integrateAdaptive(...,
|
|
181
|
+
{ atol, rtol, hMin, hMax })` (Dormand-Prince 5(4)): a `Trajectory { t, y (steps x dim), dim, steps,
|
|
182
|
+
reason }` where `reason` is `"end" | "blowup" | "maxSteps" | "stopped" | "stepTooSmall"`. Either direction in
|
|
183
|
+
`t`. `stop(t, y)` ends the run; `blowup` (default 1e12) catches finite-time singularities cleanly.
|
|
184
|
+
- `sampleSolutionCurve(f(x, y), x0, y0, xDomain, { method: "adaptive" | "rk4" })`: the solution through a
|
|
185
|
+
point both ways as `Samples`, ending (not spiking) at an asymptote.
|
|
186
|
+
- `samplePhasePortrait(F(x, y) => [dx, dy], xDomain, yDomain, { grid, seeds, tMax, fixedPointStarts })`:
|
|
187
|
+
`{ field, trajectories, fixedPoints, progress }`. Fixed points are found by Newton from a grid of starts
|
|
188
|
+
and classified from the Jacobian by `classifyFixedPoint(J)`: `stable/unstable node`, `saddle`,
|
|
189
|
+
`stable/unstable spiral`, `center`, the star/degenerate case, or `non-hyperbolic` (det ~ 0; linearisation
|
|
190
|
+
says nothing). A `center` is a linear classification: the nonlinear system may spiral.
|
|
191
|
+
|
|
192
|
+
### Series
|
|
193
|
+
|
|
194
|
+
- `taylorCoefficients(expr, x0, order)` (in `/expr`, needs `@johnhenry/math`; computed by power-series arithmetic, so order
|
|
195
|
+
12 or more is instant for `+ - * /`, powers, `exp ln sqrt sin cos tan sinh cosh tanh atan asin acos`; any other function
|
|
196
|
+
falls back to repeated symbolic differentiation, keep `order` <= 8 there) then
|
|
197
|
+
`sampleTaylorPartialSums(coefficients, x0, domain, orders, samples)`: one curve per order.
|
|
198
|
+
- `sampleSeriesPartialSums(term(k, x), from, domain, orders, samples)`: function-series partial sums in
|
|
199
|
+
one pass over `k` (each term evaluated once per sample).
|
|
200
|
+
- `partialSums(term(k), from, to)`: numeric partial sums plus an Aitken delta-squared `limitEstimate`
|
|
201
|
+
(a hint, not a convergence proof).
|
|
202
|
+
- `fourierCoefficients(f, { min, max }, terms)` (midpoint rule on 4096 samples by default; the interval is one
|
|
203
|
+
period), `evaluateFourier`, `sampleFourierPartialSums(coefficients, domain, orders)`. Trig form
|
|
204
|
+
`a0/2 + sum a_k cos(k pi (x - c) / L) + b_k sin(...)`. A function with jumps shows the Gibbs overshoot, as it should.
|
|
205
|
+
|
|
206
|
+
### 2D (implicit, contours, gradient)
|
|
207
|
+
|
|
208
|
+
- `sampleImplicit(f(x, y), xDomain, yDomain, { grid, level })`: marching squares, saddle cells settled by the
|
|
209
|
+
centre value. Segments come back as `Samples` rows: two endpoints then a `NaN` row per segment, so
|
|
210
|
+
`runsOf` gives one run per segment. Cells with a non-finite corner are skipped.
|
|
211
|
+
- `sampleContours(f, xDomain, yDomain, { grid, levels | count })`: one pass for all levels; default levels are
|
|
212
|
+
spread strictly between the grid's least and greatest value.
|
|
213
|
+
- `sampleGradient(fx, fy, xDomain, yDomain, { grid })`: arrow tails and components with magnitudes.
|
|
214
|
+
|
|
114
215
|
## What it does not do (yet)
|
|
115
216
|
|
|
116
217
|
- **Implicit multiplication is opt-in.** `2x` fails to parse by default; write
|
|
117
218
|
`2*x`, or pass `compileExpression(src, { implicitMultiplication: true })`
|
|
118
219
|
(needs `@johnhenry/math` 0.1.0+; multi-letter variable names such as `theta`
|
|
119
220
|
then become products, use `x_1`).
|
|
120
|
-
- **
|
|
121
|
-
|
|
221
|
+
- **No interval-robust implicit mode.** `sampleImplicit` is a plain grid; thin features narrower
|
|
222
|
+
than a cell and isolated points can be missed (the quadtree/interval variant needs
|
|
223
|
+
`Symbolic.evaluateInterval`, johnhenry/math#108). Segments are not joined into long polylines.
|
|
224
|
+
- **Meshes are uniform grids.** No adaptive refinement for surfaces or space curves; normals come from
|
|
225
|
+
finite differences of the vertex grid (one-sided at holes and edges), not from analytic gradients.
|
|
226
|
+
- **Budgets stop at row boundaries**, and the time limit is only checked there. The ODE integrators take
|
|
227
|
+
`maxSteps`, not a budget.
|
|
228
|
+
- **Polar/parametric 2D curves and 3D adaptive sampling** are not here; wrap `sampleSpaceCurve`
|
|
229
|
+
(with `z = 0`) or sample a parametric function through `sampleUniform` on each coordinate.
|
|
122
230
|
- **Gaps from steep or fast-oscillating functions.** Jump detection is a
|
|
123
231
|
heuristic; a function that oscillates faster than the grid resolves can read
|
|
124
232
|
as a jump. Raise the resolution or `maxDepth`, or set `jumpFraction: Infinity`.
|
package/dist/budget.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type CancelSignal } from "./sample.ts";
|
|
2
|
+
/**
|
|
3
|
+
* A work limit for the 2D/3D samplers. When it runs out the sampler stops at a
|
|
4
|
+
* row boundary and returns what it has, with a {@link Progress} saying where
|
|
5
|
+
* it stopped (it does not throw).
|
|
6
|
+
*/
|
|
7
|
+
export interface Budget {
|
|
8
|
+
/** Most function evaluations ("cells") the call may spend. Checked per row/slab. */
|
|
9
|
+
maxCells?: number;
|
|
10
|
+
/** Wall-clock limit in milliseconds. Checked per row/slab, so a single row can overrun it. */
|
|
11
|
+
maxMillis?: number;
|
|
12
|
+
/** Clock override for tests; default `performance.now` when present, else `Date.now`. */
|
|
13
|
+
now?: () => number;
|
|
14
|
+
}
|
|
15
|
+
export interface Cancellable {
|
|
16
|
+
signal?: CancelSignal;
|
|
17
|
+
isCancelled?: () => boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface Progress {
|
|
20
|
+
/** Rows (or slabs, or steps) completed. */
|
|
21
|
+
rows: number;
|
|
22
|
+
/** Rows the full job needed. */
|
|
23
|
+
of: number;
|
|
24
|
+
complete: boolean;
|
|
25
|
+
/** Why it stopped early. Absent when `complete`. */
|
|
26
|
+
reason?: "cells" | "time";
|
|
27
|
+
}
|
|
28
|
+
/** Tracks a {@link Budget} and cancellation for one call. */
|
|
29
|
+
export declare class Meter {
|
|
30
|
+
private readonly start;
|
|
31
|
+
private spent;
|
|
32
|
+
private readonly now;
|
|
33
|
+
private readonly budget;
|
|
34
|
+
private readonly cancel;
|
|
35
|
+
constructor(budget: Budget | undefined, cancel: Cancellable | undefined);
|
|
36
|
+
/** Throws on cancellation; returns a reason when the budget cannot afford `cost` more evaluations. */
|
|
37
|
+
check(cost: number): "cells" | "time" | undefined;
|
|
38
|
+
spend(n: number): void;
|
|
39
|
+
get cells(): number;
|
|
40
|
+
}
|
|
41
|
+
export declare function progress(rows: number, of: number, reason?: "cells" | "time"): Progress;
|
|
42
|
+
export declare function assertCount(name: string, n: number, min?: number): void;
|
|
43
|
+
export declare function assertRange(name: string, d: {
|
|
44
|
+
min: number;
|
|
45
|
+
max: number;
|
|
46
|
+
}): void;
|
|
47
|
+
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAwB,MAAM,aAAa,CAAC;AAEtE;;;;GAIG;AACH,MAAM,WAAW,MAAM;IACrB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAED,6DAA6D;AAC7D,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;gBACrC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS;IAMvE,sGAAsG;IACtG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS;IAOjD,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAGtB,IAAI,KAAK,IAAI,MAAM,CAElB;CACF;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAEtF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,IAAI,CAElE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAG/E"}
|
package/dist/budget.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SampleCancelledError } from "./sample.js";
|
|
2
|
+
/** Tracks a {@link Budget} and cancellation for one call. */
|
|
3
|
+
export class Meter {
|
|
4
|
+
start;
|
|
5
|
+
spent = 0;
|
|
6
|
+
now;
|
|
7
|
+
budget;
|
|
8
|
+
cancel;
|
|
9
|
+
constructor(budget, cancel) {
|
|
10
|
+
this.budget = budget;
|
|
11
|
+
this.cancel = cancel;
|
|
12
|
+
this.now = budget?.now ?? (typeof performance !== "undefined" ? () => performance.now() : () => Date.now());
|
|
13
|
+
this.start = this.now();
|
|
14
|
+
}
|
|
15
|
+
/** Throws on cancellation; returns a reason when the budget cannot afford `cost` more evaluations. */
|
|
16
|
+
check(cost) {
|
|
17
|
+
if (this.cancel?.signal?.aborted || this.cancel?.isCancelled?.())
|
|
18
|
+
throw new SampleCancelledError();
|
|
19
|
+
const b = this.budget;
|
|
20
|
+
if (b?.maxCells !== undefined && this.spent + cost > b.maxCells)
|
|
21
|
+
return "cells";
|
|
22
|
+
if (b?.maxMillis !== undefined && this.now() - this.start > b.maxMillis)
|
|
23
|
+
return "time";
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
spend(n) {
|
|
27
|
+
this.spent += n;
|
|
28
|
+
}
|
|
29
|
+
get cells() {
|
|
30
|
+
return this.spent;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function progress(rows, of, reason) {
|
|
34
|
+
return reason === undefined ? { rows, of, complete: rows >= of } : { rows, of, complete: false, reason };
|
|
35
|
+
}
|
|
36
|
+
export function assertCount(name, n, min = 2) {
|
|
37
|
+
if (!Number.isInteger(n) || n < min)
|
|
38
|
+
throw new RangeError(`${name} must be an integer >= ${min}, got ${n}`);
|
|
39
|
+
}
|
|
40
|
+
export function assertRange(name, d) {
|
|
41
|
+
if (!Number.isFinite(d.min) || !Number.isFinite(d.max) || !(d.min < d.max))
|
|
42
|
+
throw new RangeError(`${name} must be finite with min < max`);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,oBAAoB,EAAE,MAAM,aAAa,CAAC;AA+BtE,6DAA6D;AAC7D,MAAM,OAAO,KAAK;IACC,KAAK,CAAS;IACvB,KAAK,GAAG,CAAC,CAAC;IACD,GAAG,CAAe;IAClB,MAAM,CAAqB;IAC3B,MAAM,CAA0B;IACjD,YAAY,MAA0B,EAAE,MAA+B;QACrE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5G,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC1B,CAAC;IACD,sGAAsG;IACtG,KAAK,CAAC,IAAY;QAChB,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;YAAE,MAAM,IAAI,oBAAoB,EAAE,CAAC;QACnG,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ;YAAE,OAAO,OAAO,CAAC;QAChF,IAAI,CAAC,EAAE,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS;YAAE,OAAO,MAAM,CAAC;QACvF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,KAAK,CAAC,CAAS;QACb,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,EAAU,EAAE,MAAyB;IAC1E,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3G,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,CAAS,EAAE,GAAG,GAAG,CAAC;IAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG;QAAE,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,0BAA0B,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;AAC9G,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,CAA+B;IACvE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;QACxE,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,gCAAgC,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type Budget, type Cancellable, type Progress } from "./budget.ts";
|
|
2
|
+
import type { Domain } from "./sample.ts";
|
|
3
|
+
/** A complex function over plain numbers: `(re, im) -> [re, im]`. */
|
|
4
|
+
export type ComplexFn = (re: number, im: number) => readonly [number, number];
|
|
5
|
+
export interface ComplexRasterOptions extends Budget, Cancellable {
|
|
6
|
+
/** Pixels across (real axis). Default 128. */
|
|
7
|
+
width?: number;
|
|
8
|
+
/** Pixels down (imaginary axis). Default 128. */
|
|
9
|
+
height?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Grid of `f(z)` values for domain colouring. Row 0 is the *smallest* imaginary part (mathematical
|
|
13
|
+
* orientation); flip when drawing to a canvas. Cells where `f` is not finite hold `NaN` in all four arrays
|
|
14
|
+
* (a pole shows as `abs = Infinity` only if `f` returned an infinite modulus with finite parts; otherwise NaN).
|
|
15
|
+
* `arg` is in `(-PI, PI]`.
|
|
16
|
+
*/
|
|
17
|
+
export interface ComplexRaster {
|
|
18
|
+
width: number;
|
|
19
|
+
/** Rows completed (may be fewer than requested when the budget ran out). */
|
|
20
|
+
height: number;
|
|
21
|
+
re: Float32Array;
|
|
22
|
+
im: Float32Array;
|
|
23
|
+
abs: Float32Array;
|
|
24
|
+
arg: Float32Array;
|
|
25
|
+
progress: Progress;
|
|
26
|
+
}
|
|
27
|
+
/** Sample `f` at the centre of each cell of a `width` x `height` grid over the rectangle. */
|
|
28
|
+
export declare function sampleComplexRaster(f: ComplexFn, reDomain: Domain, imDomain: Domain, options?: ComplexRasterOptions): ComplexRaster;
|
|
29
|
+
export interface ConformalLine {
|
|
30
|
+
/** `"re"`: the image of the vertical line `Re z = value`; `"im"`: of the horizontal line `Im z = value`. */
|
|
31
|
+
kind: "re" | "im";
|
|
32
|
+
value: number;
|
|
33
|
+
/** Image points; `NaN` rows are gaps (never first, last or adjacent). */
|
|
34
|
+
x: Float64Array;
|
|
35
|
+
y: Float64Array;
|
|
36
|
+
}
|
|
37
|
+
export interface ConformalGridOptions {
|
|
38
|
+
/** Vertical grid lines (constant real part), evenly spaced including both edges. Default 11. */
|
|
39
|
+
reLines?: number;
|
|
40
|
+
/** Horizontal grid lines (constant imaginary part). Default 11. */
|
|
41
|
+
imLines?: number;
|
|
42
|
+
/** Samples along each line. Default 200. */
|
|
43
|
+
samplesPerLine?: number;
|
|
44
|
+
/** Image points with modulus above this become gaps (poles). Default 1e6. */
|
|
45
|
+
bound?: number;
|
|
46
|
+
/** Segments whose image is longer than this become gaps (branch cuts). Default: no limit. */
|
|
47
|
+
maxStep?: number;
|
|
48
|
+
}
|
|
49
|
+
/** The image under `f` of a rectangular grid of lines: where the grid lines go, drawn as the conformal-map picture. */
|
|
50
|
+
export declare function conformalGrid(f: ComplexFn, reDomain: Domain, imDomain: Domain, options?: ConformalGridOptions): ConformalLine[];
|
|
51
|
+
export interface ZeroOrPole {
|
|
52
|
+
re: number;
|
|
53
|
+
im: number;
|
|
54
|
+
kind: "zero" | "pole";
|
|
55
|
+
/** Multiplicity (zero) or order (pole), from the winding number of the cell it was found in. */
|
|
56
|
+
order: number;
|
|
57
|
+
/** `false` when the local refinement did not converge and `re`/`im` is only the cell centre. */
|
|
58
|
+
refined: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface ZerosPolesOptions extends Budget, Cancellable {
|
|
61
|
+
/** Cells per side of the search grid. Default 24. */
|
|
62
|
+
grid?: number;
|
|
63
|
+
/** Convergence tolerance on the root position. Default 1e-10 (relative to the rectangle size). */
|
|
64
|
+
tolerance?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface ZerosPoles {
|
|
67
|
+
items: ZeroOrPole[];
|
|
68
|
+
progress: Progress;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Zeros and poles of `f` inside a rectangle, by the argument principle: the winding number of `f` around each
|
|
72
|
+
* grid cell is (zeros - poles) inside it; non-zero cells are refined with Newton's method (on `f` for a
|
|
73
|
+
* zero, on `1/f` for a pole, scaled by the multiplicity). A zero and a pole inside one cell cancel and are missed:
|
|
74
|
+
* raise `grid`. The search grid is offset by an irrational fraction of a cell and extended past the
|
|
75
|
+
* rectangle, so round-number domains do not put roots on cell edges; results inside the rectangle (or on its edge) are
|
|
76
|
+
* kept and results within the tolerance are merged. `progress.rows` counts grid rows searched.
|
|
77
|
+
*/
|
|
78
|
+
export declare function findZerosAndPoles(f: ComplexFn, reDomain: Domain, imDomain: Domain, options?: ZerosPolesOptions): ZerosPoles;
|
|
79
|
+
//# sourceMappingURL=complex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complex.d.ts","sourceRoot":"","sources":["../src/complex.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,MAAM,EAAE,KAAK,WAAW,EAAS,KAAK,QAAQ,EAAY,MAAM,aAAa,CAAC;AACtH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9E,MAAM,WAAW,oBAAqB,SAAQ,MAAM,EAAE,WAAW;IAC/D,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,YAAY,CAAC;IACjB,EAAE,EAAE,YAAY,CAAC;IACjB,GAAG,EAAE,YAAY,CAAC;IAClB,GAAG,EAAE,YAAY,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,SAAS,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAyCf;AAED,MAAM,WAAW,aAAa;IAC5B,4GAA4G;IAC5G,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,CAAC,EAAE,YAAY,CAAC;IAChB,CAAC,EAAE,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,gGAAgG;IAChG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,uHAAuH;AACvH,wBAAgB,aAAa,CAC3B,CAAC,EAAE,SAAS,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,aAAa,EAAE,CAiDjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,gGAAgG;IAChG,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,MAAM,EAAE,WAAW;IAC5D,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAQD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,SAAS,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,iBAAsB,GAC9B,UAAU,CA+HZ"}
|
package/dist/complex.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { assertCount, assertRange, Meter, progress } from "./budget.js";
|
|
2
|
+
/** Sample `f` at the centre of each cell of a `width` x `height` grid over the rectangle. */
|
|
3
|
+
export function sampleComplexRaster(f, reDomain, imDomain, options = {}) {
|
|
4
|
+
const width = options.width ?? 128;
|
|
5
|
+
const height = options.height ?? 128;
|
|
6
|
+
assertCount("width", width, 1);
|
|
7
|
+
assertCount("height", height, 1);
|
|
8
|
+
assertRange("re domain", reDomain);
|
|
9
|
+
assertRange("im domain", imDomain);
|
|
10
|
+
const meter = new Meter(options, options);
|
|
11
|
+
const re = new Float32Array(width * height).fill(Number.NaN);
|
|
12
|
+
const im = new Float32Array(width * height).fill(Number.NaN);
|
|
13
|
+
const abs = new Float32Array(width * height).fill(Number.NaN);
|
|
14
|
+
const arg = new Float32Array(width * height).fill(Number.NaN);
|
|
15
|
+
let rows = 0;
|
|
16
|
+
let reason;
|
|
17
|
+
for (let j = 0; j < height; j++) {
|
|
18
|
+
reason = meter.check(width);
|
|
19
|
+
if (reason)
|
|
20
|
+
break;
|
|
21
|
+
const y = imDomain.min + ((imDomain.max - imDomain.min) * (j + 0.5)) / height;
|
|
22
|
+
for (let i = 0; i < width; i++) {
|
|
23
|
+
const x = reDomain.min + ((reDomain.max - reDomain.min) * (i + 0.5)) / width;
|
|
24
|
+
const w = f(x, y);
|
|
25
|
+
const k = j * width + i;
|
|
26
|
+
if (Number.isFinite(w[0]) && Number.isFinite(w[1])) {
|
|
27
|
+
re[k] = w[0];
|
|
28
|
+
im[k] = w[1];
|
|
29
|
+
abs[k] = Math.hypot(w[0], w[1]);
|
|
30
|
+
arg[k] = Math.atan2(w[1], w[0]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
meter.spend(width);
|
|
34
|
+
rows++;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
width,
|
|
38
|
+
height: rows,
|
|
39
|
+
re: re.slice(0, width * rows),
|
|
40
|
+
im: im.slice(0, width * rows),
|
|
41
|
+
abs: abs.slice(0, width * rows),
|
|
42
|
+
arg: arg.slice(0, width * rows),
|
|
43
|
+
progress: progress(rows, height, reason),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** The image under `f` of a rectangular grid of lines: where the grid lines go, drawn as the conformal-map picture. */
|
|
47
|
+
export function conformalGrid(f, reDomain, imDomain, options = {}) {
|
|
48
|
+
const nRe = options.reLines ?? 11;
|
|
49
|
+
const nIm = options.imLines ?? 11;
|
|
50
|
+
const n = options.samplesPerLine ?? 200;
|
|
51
|
+
const bound = options.bound ?? 1e6;
|
|
52
|
+
assertCount("reLines", nRe, 1);
|
|
53
|
+
assertCount("imLines", nIm, 1);
|
|
54
|
+
assertCount("samplesPerLine", n);
|
|
55
|
+
assertRange("re domain", reDomain);
|
|
56
|
+
assertRange("im domain", imDomain);
|
|
57
|
+
const lines = [];
|
|
58
|
+
const trace = (kind, value, d) => {
|
|
59
|
+
const xs = [];
|
|
60
|
+
const ys = [];
|
|
61
|
+
let pending = false;
|
|
62
|
+
let px = Number.NaN;
|
|
63
|
+
let py = Number.NaN;
|
|
64
|
+
for (let k = 0; k < n; k++) {
|
|
65
|
+
const s = k === n - 1 ? d.max : d.min + ((d.max - d.min) * k) / (n - 1);
|
|
66
|
+
const w = kind === "re" ? f(value, s) : f(s, value);
|
|
67
|
+
const good = Number.isFinite(w[0]) && Number.isFinite(w[1]) && Math.hypot(w[0], w[1]) <= bound;
|
|
68
|
+
if (!good) {
|
|
69
|
+
pending = xs.length > 0;
|
|
70
|
+
px = Number.NaN;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const cut = options.maxStep !== undefined && !Number.isNaN(px) && Math.hypot(w[0] - px, w[1] - py) > options.maxStep;
|
|
74
|
+
if ((pending || cut) && xs.length > 0) {
|
|
75
|
+
xs.push(Number.NaN);
|
|
76
|
+
ys.push(Number.NaN);
|
|
77
|
+
}
|
|
78
|
+
xs.push(w[0]);
|
|
79
|
+
ys.push(w[1]);
|
|
80
|
+
px = w[0];
|
|
81
|
+
py = w[1];
|
|
82
|
+
pending = false;
|
|
83
|
+
}
|
|
84
|
+
return { kind, value, x: Float64Array.from(xs), y: Float64Array.from(ys) };
|
|
85
|
+
};
|
|
86
|
+
for (let i = 0; i < nRe; i++)
|
|
87
|
+
lines.push(trace("re", nRe === 1 ? reDomain.min : reDomain.min + ((reDomain.max - reDomain.min) * i) / (nRe - 1), imDomain));
|
|
88
|
+
for (let j = 0; j < nIm; j++)
|
|
89
|
+
lines.push(trace("im", nIm === 1 ? imDomain.min : imDomain.min + ((imDomain.max - imDomain.min) * j) / (nIm - 1), reDomain));
|
|
90
|
+
return lines;
|
|
91
|
+
}
|
|
92
|
+
const wrap = (d) => {
|
|
93
|
+
while (d > Math.PI)
|
|
94
|
+
d -= 2 * Math.PI;
|
|
95
|
+
while (d < -Math.PI)
|
|
96
|
+
d += 2 * Math.PI;
|
|
97
|
+
return d;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Zeros and poles of `f` inside a rectangle, by the argument principle: the winding number of `f` around each
|
|
101
|
+
* grid cell is (zeros - poles) inside it; non-zero cells are refined with Newton's method (on `f` for a
|
|
102
|
+
* zero, on `1/f` for a pole, scaled by the multiplicity). A zero and a pole inside one cell cancel and are missed:
|
|
103
|
+
* raise `grid`. The search grid is offset by an irrational fraction of a cell and extended past the
|
|
104
|
+
* rectangle, so round-number domains do not put roots on cell edges; results inside the rectangle (or on its edge) are
|
|
105
|
+
* kept and results within the tolerance are merged. `progress.rows` counts grid rows searched.
|
|
106
|
+
*/
|
|
107
|
+
export function findZerosAndPoles(f, reDomain, imDomain, options = {}) {
|
|
108
|
+
const grid = options.grid ?? 24;
|
|
109
|
+
assertCount("grid", grid, 1);
|
|
110
|
+
assertRange("re domain", reDomain);
|
|
111
|
+
assertRange("im domain", imDomain);
|
|
112
|
+
const size = Math.max(reDomain.max - reDomain.min, imDomain.max - imDomain.min);
|
|
113
|
+
const tol = (options.tolerance ?? 1e-10) * size;
|
|
114
|
+
const meter = new Meter(options, options);
|
|
115
|
+
const dx = (reDomain.max - reDomain.min) / grid;
|
|
116
|
+
const dy = (imDomain.max - imDomain.min) / grid;
|
|
117
|
+
const found = [];
|
|
118
|
+
const argAt = (x, y) => {
|
|
119
|
+
const w = f(x, y);
|
|
120
|
+
if (w[0] === 0 && w[1] === 0)
|
|
121
|
+
return Number.NaN; // an exact zero has no argument
|
|
122
|
+
return Math.atan2(w[1], w[0]);
|
|
123
|
+
};
|
|
124
|
+
// winding of f along segment p->q, subdividing until the phase moves < 1 rad per piece
|
|
125
|
+
const segment = (x0, y0, a0, x1, y1, a1, depth) => {
|
|
126
|
+
const d = wrap(a1 - a0);
|
|
127
|
+
// a minimum depth keeps a high-order root from aliasing a whole turn (3 theta moving 2 pi in one piece)
|
|
128
|
+
if ((depth >= 4 && Math.abs(d) < 1) || depth >= 14)
|
|
129
|
+
return d;
|
|
130
|
+
const xm = (x0 + x1) / 2;
|
|
131
|
+
const ym = (y0 + y1) / 2;
|
|
132
|
+
const am = argAt(xm, ym);
|
|
133
|
+
return segment(x0, y0, a0, xm, ym, am, depth + 1) + segment(xm, ym, am, x1, y1, a1, depth + 1);
|
|
134
|
+
};
|
|
135
|
+
const winding = (x0, y0, x1, y1) => {
|
|
136
|
+
const pts = [
|
|
137
|
+
[x0, y0],
|
|
138
|
+
[x1, y0],
|
|
139
|
+
[x1, y1],
|
|
140
|
+
[x0, y1],
|
|
141
|
+
[x0, y0],
|
|
142
|
+
];
|
|
143
|
+
const args = pts.map(([x, y]) => argAt(x, y));
|
|
144
|
+
if (args.some((a) => !Number.isFinite(a)))
|
|
145
|
+
return Number.NaN;
|
|
146
|
+
let total = 0;
|
|
147
|
+
for (let k = 0; k < 4; k++) {
|
|
148
|
+
const p = pts[k];
|
|
149
|
+
const q = pts[k + 1];
|
|
150
|
+
total += segment(p[0], p[1], args[k], q[0], q[1], args[k + 1], 0);
|
|
151
|
+
}
|
|
152
|
+
return Math.round(total / (2 * Math.PI));
|
|
153
|
+
};
|
|
154
|
+
const newton = (x, y, kind, order, box) => {
|
|
155
|
+
const g = (a, b) => {
|
|
156
|
+
const w = f(a, b);
|
|
157
|
+
if (kind === "zero")
|
|
158
|
+
return [w[0], w[1]];
|
|
159
|
+
const m = w[0] * w[0] + w[1] * w[1];
|
|
160
|
+
return [w[0] / m, -w[1] / m]; // 1/f
|
|
161
|
+
};
|
|
162
|
+
let zx = x;
|
|
163
|
+
let zy = y;
|
|
164
|
+
for (let it = 0; it < 60; it++) {
|
|
165
|
+
const [gr, gi] = g(zx, zy);
|
|
166
|
+
if (!Number.isFinite(gr) || !Number.isFinite(gi))
|
|
167
|
+
return undefined;
|
|
168
|
+
const h = 1e-7 * Math.max(1, Math.abs(zx), Math.abs(zy));
|
|
169
|
+
const [ar, ai] = g(zx + h, zy);
|
|
170
|
+
const dr = (ar - gr) / h; // derivative of an analytic function = d/dx
|
|
171
|
+
const di = (ai - gi) / h;
|
|
172
|
+
const den = dr * dr + di * di;
|
|
173
|
+
if (!(den > 0) || !Number.isFinite(den))
|
|
174
|
+
return undefined;
|
|
175
|
+
// step = order * g / g'
|
|
176
|
+
const sr = (order * (gr * dr + gi * di)) / den;
|
|
177
|
+
const si = (order * (gi * dr - gr * di)) / den;
|
|
178
|
+
zx -= sr;
|
|
179
|
+
zy -= si;
|
|
180
|
+
if (Math.hypot(sr, si) < tol) {
|
|
181
|
+
const pad = 0.5 * Math.max(dx, dy);
|
|
182
|
+
if (zx < box[0] - pad || zx > box[1] + pad || zy < box[2] - pad || zy > box[3] + pad)
|
|
183
|
+
return undefined;
|
|
184
|
+
return [zx, zy];
|
|
185
|
+
}
|
|
186
|
+
if (!Number.isFinite(zx) || !Number.isFinite(zy))
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
return undefined;
|
|
190
|
+
};
|
|
191
|
+
// The search grid is shifted by an irrational fraction of a cell and extended by one cell on each side, so
|
|
192
|
+
// roots and poles on a round-number domain (z^3 - z on [-2, 2]) sit inside cells, not on their edges or
|
|
193
|
+
// corners. Candidates outside the requested rectangle are discarded at the end.
|
|
194
|
+
const OFFSET = 0.3819660112501051;
|
|
195
|
+
const gx0 = reDomain.min - (1 - OFFSET) * dx;
|
|
196
|
+
const gy0 = imDomain.min - (1 - OFFSET) * dy;
|
|
197
|
+
const cells = grid + 1;
|
|
198
|
+
const slack = 1e-9 * size;
|
|
199
|
+
const insideRect = (x, y) => x >= reDomain.min - slack && x <= reDomain.max + slack && y >= imDomain.min - slack && y <= imDomain.max + slack;
|
|
200
|
+
let rows = 0;
|
|
201
|
+
let reason;
|
|
202
|
+
for (let j = 0; j < cells; j++) {
|
|
203
|
+
reason = meter.check(cells * 4);
|
|
204
|
+
if (reason)
|
|
205
|
+
break;
|
|
206
|
+
for (let i = 0; i < cells; i++) {
|
|
207
|
+
const x0 = gx0 + i * dx;
|
|
208
|
+
const y0 = gy0 + j * dy;
|
|
209
|
+
let w = winding(x0, y0, x0 + dx, y0 + dy);
|
|
210
|
+
let ex = 0;
|
|
211
|
+
if (Number.isNaN(w)) {
|
|
212
|
+
// f is zero or non-finite on this cell's boundary (an exact root/pole on an edge): retry slightly inflated
|
|
213
|
+
ex = 0.0123 * dx;
|
|
214
|
+
w = winding(x0 - ex, y0 - 0.0123 * dy, x0 + dx + ex, y0 + dy + 0.0123 * dy);
|
|
215
|
+
}
|
|
216
|
+
if (!Number.isFinite(w) || w === 0)
|
|
217
|
+
continue;
|
|
218
|
+
const kind = w > 0 ? "zero" : "pole";
|
|
219
|
+
const order = Math.abs(w);
|
|
220
|
+
const cx = x0 + dx / 2;
|
|
221
|
+
const cy = y0 + dy / 2;
|
|
222
|
+
const refined = newton(cx, cy, kind, order, [x0, x0 + dx, y0, y0 + dy]);
|
|
223
|
+
const [rx, ry] = refined ?? [cx, cy];
|
|
224
|
+
if (!insideRect(rx, ry))
|
|
225
|
+
continue;
|
|
226
|
+
if (found.some((p) => p.kind === kind && Math.hypot(p.re - rx, p.im - ry) < Math.max(tol * 1e3, 1e-7 * size)))
|
|
227
|
+
continue;
|
|
228
|
+
found.push({ re: rx, im: ry, kind, order, refined: refined !== undefined });
|
|
229
|
+
}
|
|
230
|
+
meter.spend(cells * 4);
|
|
231
|
+
rows++;
|
|
232
|
+
}
|
|
233
|
+
found.sort((a, b) => a.re - b.re || a.im - b.im);
|
|
234
|
+
return { items: found, progress: progress(rows, cells, reason) };
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=complex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complex.js","sourceRoot":"","sources":["../src/complex.ts"],"names":[],"mappings":"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"}
|
package/dist/expr.d.ts
CHANGED
|
@@ -23,4 +23,16 @@ export interface CompileOptions {
|
|
|
23
23
|
* `implicitMultiplication: true` to accept `2x`.
|
|
24
24
|
*/
|
|
25
25
|
export declare function compileExpression(expr: Expr | string, options?: CompileOptions): Fn1;
|
|
26
|
+
/**
|
|
27
|
+
* Taylor coefficients `a_k = f^(k)(x0) / k!` for `k = 0..order` of an expression. They are computed by truncated
|
|
28
|
+
* power-series ("jet") arithmetic, O(order^2) per node, so order 12 of `sin(x)*exp(x)/(1+x^2)` takes well under a
|
|
29
|
+
* millisecond. Supported: `+ - * /`, powers (integer or real exponent, or a variable exponent), and `exp ln sqrt cbrt sin
|
|
30
|
+
* cos tan sinh cosh tanh atan asin acos`. Any other node falls back to repeated symbolic differentiation with
|
|
31
|
+
* simplification after every derivative, which grows quickly: keep `order` at or below 8 there. A coefficient that is
|
|
32
|
+
* not finite at `x0` (a pole, `ln(0)`) is `NaN` or `Infinity`, and the partial sums built on it are gaps.
|
|
33
|
+
*/
|
|
34
|
+
export declare function taylorCoefficients(expr: Expr | string, x0: number, order: number, options?: {
|
|
35
|
+
variable?: string;
|
|
36
|
+
params?: Record<string, number>;
|
|
37
|
+
}): Float64Array;
|
|
26
38
|
//# sourceMappingURL=expr.d.ts.map
|
package/dist/expr.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expr.d.ts","sourceRoot":"","sources":["../src/expr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAY,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,GAAG,CAYxF"}
|
|
1
|
+
{"version":3,"file":"expr.d.ts","sourceRoot":"","sources":["../src/expr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAY,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,GAAG,CAYxF;AAqND;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GACnE,YAAY,CAkBd"}
|