/** * Numerical Integration Functions * * Provides numerical integration (quadrature) methods: * - trapz: Trapezoidal rule * - simpson: Simpson's 1/3 rule * - gaussQuad: Gauss-Legendre quadrature (composite form for n ≥ 64 sub-intervals) * - romberg: Romberg integration (adaptive Richardson extrapolation) * * Worker-dispatch strategy (Slice 3.8): * - gaussQuad / romberg: function evaluation stays on the main thread; the * weighted dot-product reduction (values × weights) is offloaded via * `computePool.dot` when sub-interval count ≥ GAUSS_WORKER_THRESHOLD. * - trapz / simpson accepting a Float64Array of pre-computed values: the * summation is offloaded via `computePool.sum` when length ≥ * ARRAY_WORKER_THRESHOLD. * * Worker-dispatch strategy (Slice 5.10) — sub-interval fan-out: * - gaussQuad / romberg accept an optional `workerCount` option (default 1). * When `workerCount > 1` and `totalPoints ≥ GAUSS_WORKER_THRESHOLD`, the * integration domain is partitioned into `workerCount` equal sub-domains and * one `integrateChunk` worker task is dispatched per sub-domain. Each task * stringifies the integrand closure and evaluates it inside the worker. * * **Closure-stringification contract:** * Only closures that are self-contained (no free variables referencing * outer scope) survive worker dispatch. The heuristic in * `validateClosureSource` tokenizes the function source and rejects any * identifier that is not: * - the declared parameter name(s), * - a `Math` property access (`Math.*`), * - a standard numeric literal keyword (`Infinity`, `NaN`), or * - a keyword / punctuation. * Arrow functions (`x => x*x`, `(x) => x*x`) and classic function expressions * (`function(x){ return x*x; }`) both stringify cleanly. * Async closures are rejected unconditionally. * * These use plain exports (not mathTyped) because they accept function * arguments, which typed-function does not handle well. * * @packageDocumentation */ /** Minimum sub-interval count before gaussQuad / romberg offload the reduction. */ export declare const GAUSS_WORKER_THRESHOLD = 64; /** Minimum array length before trapzF64 / simpsonF64 offload the summation. */ export declare const ARRAY_WORKER_THRESHOLD = 65536; /** * Validate that a stringified function closure is safe to dispatch to a worker. * * The heuristic: * 1. Rejects async closures outright (they cannot be reconstructed portably). * 2. Extracts the parameter name(s) from the function source. * 3. Tokenizes the body by extracting all bare identifiers (word characters * not preceded or followed by a dot — i.e. not `Math.sin` method parts). * 4. Rejects any identifier that is not the parameter name, not in the * ALLOWED_GLOBALS set, and not a numeric literal. * * @param fnSource - Result of `f.toString()` * @throws Error when the closure references outer-scope identifiers or is async */ export declare function validateClosureSource(fnSource: string): void; /** * Numerical integration using the trapezoidal rule over a number array. * * @param y - Array of function values * @param x - Optional array of x-coordinates (defaults to uniform spacing h=1) * @returns Approximate integral * * @example * trapz([1, 2, 3], [0, 1, 2]) // => 4 * trapz([0, 1, 0]) // => 1 (uniform spacing) */ export declare function trapz(y: number[], x?: number[]): number; /** * Numerical integration using the trapezoidal rule over a Float64Array. * * For arrays with length ≥ ARRAY_WORKER_THRESHOLD the trapezoidal terms are * computed element-wise on the main thread and the final summation is * offloaded to the compute pool via `computePool.sum`. * * @param y - Float64Array of function values (uniform spacing h=1 unless dx provided) * @param dx - Optional uniform step size (default 1) * @returns Promise resolving to the approximate integral * * @example * await trapzF64(new Float64Array([0, 1, 0])) // => 1 */ export declare function trapzF64(y: Float64Array, dx?: number): Promise; /** * Numerical integration using Simpson's 1/3 rule (function form). * * @param f - Function to integrate * @param a - Lower bound * @param b - Upper bound * @param n - Number of subintervals (must be even, default 100) * @returns Approximate integral * * @example * simpson(x => x ** 2, 0, 1) // => ~0.3333 */ export declare function simpson(f: (x: number) => number, a: number, b: number, n?: number): number; /** * Numerical integration using Simpson's 1/3 rule over a pre-computed * Float64Array of uniformly-spaced function values. * * For arrays with length ≥ ARRAY_WORKER_THRESHOLD the weighted terms are * computed on the main thread and the summation is offloaded to the pool. * * @param y - Float64Array of function values at uniform spacing * @param dx - Uniform step size (default 1) * @returns Promise resolving to the approximate integral */ export declare function simpsonF64(y: Float64Array, dx?: number): Promise; /** * Options for `gaussQuad` fan-out mode (Slice 5.10). */ export interface GaussQuadOptions { /** * Number of sub-domain worker tasks to spawn when `n ≥ GAUSS_WORKER_THRESHOLD`. * * - `1` (default): behaves exactly as Slice 3.8 — no sub-interval fan-out. * - `> 1`: the domain `[a, b]` is partitioned into `workerCount` equal * sub-domains. One `integrateChunk` worker task is dispatched per * sub-domain. The closure `f` is stringified via `f.toString()` and * reconstructed inside each worker with `new Function`. * * **Closure constraint:** The integrand must be a self-contained expression * (no references to outer-scope variables). Use `Math.*` methods and * arithmetic only. Async closures are rejected. See `validateClosureSource`. * * **Fall-back:** when `workerCount > 1` but `totalPoints < GAUSS_WORKER_THRESHOLD` * or the pool is not ready, the function falls back to single-thread evaluation * (worker overhead would dominate at small sizes). */ workerCount?: number; } /** * Numerical integration using Gauss-Legendre quadrature. * * When `n` is in [2, 5] the legacy single-interval mode is used (backward * compatible): `n` is the number of GL quadrature points applied to [a, b]. * * When `n` ≥ 64 the domain is split into `n` equal sub-intervals, each * integrated with a fixed-order GL rule (default order 5). Function * evaluation stays on the main thread; the weighted dot-product reduction is * offloaded to the compute pool when the pool is ready. * * **Sub-interval fan-out (Slice 5.10):** Pass `{ workerCount: k }` to * partition the integration domain into `k` equal sub-domains and dispatch * one worker task per sub-domain. Requires `totalPoints ≥ GAUSS_WORKER_THRESHOLD` * and the compute pool to be ready; otherwise falls back to single-thread. * The integrand `f` must satisfy the closure-stringification contract — see * `validateClosureSource` and the module-level JSDoc. * * @param f - Function to integrate * @param a - Lower bound * @param b - Upper bound * @param n - Number of quadrature points (2–5) OR number of sub-intervals (≥ 6) * @param order - GL order to use per sub-interval when n ≥ 6 (default 5) * @param options - Optional fan-out options `{ workerCount }` * @returns Approximate integral (or Promise when n ≥ GAUSS_WORKER_THRESHOLD and pool is ready) * * @example * gaussQuad(x => x ** 2, 0, 1, 3) // => ~0.3333 (3-point GL, single interval) * await gaussQuad(Math.sin, 0, Math.PI, 64) // => ~2.0 (composite, 64 sub-intervals) * await gaussQuad(Math.sin, 0, Math.PI, 64, 5, { workerCount: 4 }) // => ~2.0 (fan-out, 4 workers) */ export declare function gaussQuad(f: (x: number) => number, a: number, b: number, n?: number, order?: number, options?: GaussQuadOptions): number | Promise; /** * Options for `romberg` fan-out mode (Slice 5.10). */ export interface RombergOptions { /** * Number of sub-domain worker tasks to spawn for the initial trapezoidal * estimate when the evaluation count crosses `GAUSS_WORKER_THRESHOLD`. * * - `1` (default): behaves exactly as Slice 3.8 — no sub-interval fan-out. * - `> 1`: the domain `[a, b]` is partitioned into `workerCount` equal * sub-domains for the initial estimate. Each sub-domain is integrated * with a 5-point GL rule inside a worker. * * **Closure constraint:** Same as `GaussQuadOptions.workerCount` — see * `validateClosureSource` for details. * * **Fall-back:** when `workerCount > 1` but the point count is below * `GAUSS_WORKER_THRESHOLD` or the pool is not ready, the standard sequential * path is used. */ workerCount?: number; } /** * Romberg integration using Richardson extrapolation on the trapezoidal rule. * * Adaptively refines the estimate until the desired tolerance is reached * or the maximum number of iterations (20) is exceeded. * * When the intermediate trapezoidal sum at level `n` involves ≥ * GAUSS_WORKER_THRESHOLD new function evaluations the partial sum is * offloaded to the compute pool. Because each level n evaluates 2^(n-1) * *new* points, the pool is engaged once n ≥ log2(GAUSS_WORKER_THRESHOLD), * i.e. from level 7 onward (128 new points per level). * * **Sub-interval fan-out (Slice 5.10):** Pass `{ workerCount: k }` to fan out * the initial trapezoidal sub-domain evaluations to `k` workers. The closure * `f` must satisfy the stringification contract — see `validateClosureSource`. * * @param f - Function to integrate * @param a - Lower bound * @param b - Upper bound * @param tol - Desired absolute tolerance (default 1e-12) * @param options - Optional fan-out options `{ workerCount }` * @returns Promise resolving to the approximate integral * * @example * await romberg(Math.sin, 0, Math.PI) // => ~2.0 * await romberg(Math.sin, 0, Math.PI, 1e-12, { workerCount: 4 }) // fan-out, 4 workers */ export declare function romberg(f: (x: number) => number, a: number, b: number, tol?: number, options?: RombergOptions): Promise; //# sourceMappingURL=integration.d.ts.map