@danielsimonjr/mathts-parallel 0.1.1 → 0.2.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/dist/index.d.ts CHANGED
@@ -10,6 +10,34 @@ export { Transfer } from '@danielsimonjr/mathts-workerpool';
10
10
  * @packageDocumentation
11
11
  */
12
12
 
13
+ /**
14
+ * Recognised kernel / operation names.
15
+ *
16
+ * These are the string identifiers passed to `shouldParallelize(length, op)` so
17
+ * the per-op threshold map can be consulted before falling back to the global
18
+ * `thresholdElements`. The list covers:
19
+ * - Element-wise float ops dispatched through `ComputePool.unary/elementwise/scale`
20
+ * - Reduction ops (`sum`, `mean`, `variance`, etc.)
21
+ * - Linear-algebra ops (`matmul`, `matrixPower`, `characteristicPolynomial`)
22
+ * - Signal-processing ops (`parallelFFT`, `parallelConv`, `spectrogram`, `fft2d`)
23
+ * - Geometry ops (`distanceMatrix`)
24
+ * - Special / distribution functions (`erfc`, `besselJ`, `normalCDF`)
25
+ * - Additional ops exposed via the typed functions layer
26
+ */
27
+ type OpName = 'add' | 'subtract' | 'multiply' | 'divide' | 'pow' | 'scale' | 'abs' | 'negate' | 'sqrt' | 'square' | 'exp' | 'log' | 'sin' | 'cos' | 'tan' | 'sign' | 'tensordot' | 'sum' | 'mean' | 'variance' | 'norm' | 'histogram' | 'dot' | 'distance' | 'parallelStatProd' | 'matmul' | 'outer' | 'matvec' | 'transpose' | 'matrixPower' | 'characteristicPolynomial' | 'parallelFFT' | 'parallelConv' | 'spectrogram' | 'fft2d' | 'distanceMatrix' | 'erfc' | 'besselJ' | 'normalCDF' | 'chiSquareTest' | 'kolmogorovSmirnovTest' | 'mannWhitneyTest' | 'shapiroWilkTest' | 'integrateChunk' | 'sampleChunk';
28
+ /**
29
+ * Per-op threshold override. The value is the minimum element count required
30
+ * before parallelizing the named operation. Special string aliases:
31
+ *
32
+ * - `'never'` → `Number.MAX_SAFE_INTEGER` (never parallelize)
33
+ * - `'always'` → `0` (always parallelize when pool is ready)
34
+ */
35
+ type OpThreshold = number | 'never' | 'always';
36
+ /**
37
+ * Resolve an `OpThreshold` alias to its numeric equivalent.
38
+ * @internal
39
+ */
40
+ declare function resolveOpThreshold(t: OpThreshold): number;
13
41
  /**
14
42
  * Configuration for ComputePool
15
43
  * Extends the base WorkerPoolConfig with MathTS-specific options
@@ -21,8 +49,20 @@ interface ComputePoolConfig {
21
49
  minWorkers: number;
22
50
  /** Maximum number of workers */
23
51
  maxWorkers: number;
24
- /** Minimum elements before parallelizing */
52
+ /**
53
+ * Global minimum element count before parallelizing.
54
+ * Acts as the fallback for ops not listed in `thresholdByOp`.
55
+ */
25
56
  thresholdElements: number;
57
+ /**
58
+ * Per-operation parallelization thresholds.
59
+ *
60
+ * Values measured on a noisy CI container (2026-05-23) — re-run on target
61
+ * hardware to retune. Source: tools/benchmark/parallel/run.ts
62
+ *
63
+ * Ops absent from this map fall back to `thresholdElements`.
64
+ */
65
+ thresholdByOp?: Partial<Record<OpName, OpThreshold>>;
26
66
  /** Elements per chunk for parallel operations */
27
67
  chunkSize: number;
28
68
  /** Worker type: 'auto' | 'web' | 'thread' */
@@ -84,9 +124,14 @@ declare class ComputePool {
84
124
  */
85
125
  isReady(): boolean;
86
126
  /**
87
- * Determine if operation should be parallelized
127
+ * Determine if operation should be parallelized.
128
+ *
129
+ * When `op` is supplied the per-op threshold map is consulted first;
130
+ * if the op is absent from the map the global `thresholdElements` fallback
131
+ * is used. When `op` is omitted the global threshold is always used (for
132
+ * backward-compatibility with existing callers that don't know the op name).
88
133
  */
89
- shouldParallelize(elementCount: number): boolean;
134
+ shouldParallelize(elementCount: number, op?: OpName): boolean;
90
135
  /**
91
136
  * Execute a method in the worker pool
92
137
  */
@@ -99,6 +144,10 @@ declare class ComputePool {
99
144
  * Parallel sum of array elements
100
145
  */
101
146
  sum(data: Float64Array): Promise<ParallelResult<number>>;
147
+ /**
148
+ * Parallel product of array elements
149
+ */
150
+ prod(data: Float64Array): Promise<ParallelResult<number>>;
102
151
  /**
103
152
  * Parallel dot product
104
153
  */
@@ -170,6 +219,100 @@ declare class ComputePool {
170
219
  * Apply unary function in parallel
171
220
  */
172
221
  unary(data: Float64Array, fn: 'abs' | 'sqrt' | 'exp' | 'log' | 'sin' | 'cos' | 'tan' | 'negate' | 'square'): Promise<ParallelResult<Float64Array>>;
222
+ /**
223
+ * Apply a caller-supplied unary numeric function in parallel.
224
+ *
225
+ * @param data - Input values
226
+ * @param fnSource - Source of a self-contained `(x: number) => number`
227
+ * expression. It must not reference free variables / closures, since it
228
+ * is eval'd in an isolated worker context. Used to parallelize element-wise
229
+ * math (special functions, distribution PDFs/CDFs).
230
+ */
231
+ applyKernel(data: Float64Array, fnSource: string): Promise<ParallelResult<Float64Array>>;
232
+ /**
233
+ * Apply a caller-supplied binary numeric function in parallel.
234
+ *
235
+ * @param a - First operand array
236
+ * @param b - Second operand array (must match the length of `a`)
237
+ * @param fnSource - Source of a self-contained `(a: number, b: number) =>
238
+ * number` expression (no free variables / closures).
239
+ */
240
+ applyKernel2(a: Float64Array, b: Float64Array, fnSource: string): Promise<ParallelResult<Float64Array>>;
241
+ /**
242
+ * Fan-out Gauss-Legendre quadrature over `workerCount` sub-intervals.
243
+ *
244
+ * Partitions `[a, b]` into `workerCount` equal sub-domains and dispatches one
245
+ * `integrateChunk` worker task per sub-domain. Each task evaluates the
246
+ * integrand (supplied as a stringified closure) with the given GL nodes and
247
+ * weights and returns its partial integral. The partial sums are aggregated
248
+ * on the main thread.
249
+ *
250
+ * **Closure contract:** `fnSource` must be a self-contained `(x: number) =>
251
+ * number` expression — no free variables referencing outer scope, because it
252
+ * is eval'd inside an isolated worker context. Call-site validation (via
253
+ * `validateClosureSource`) should have already rejected unsafe closures before
254
+ * reaching this method.
255
+ *
256
+ * @param fnSource - Stringified integrand, e.g. `"(x) => Math.sin(x)"`
257
+ * @param a - Lower integration bound
258
+ * @param b - Upper integration bound
259
+ * @param workerCount - Number of sub-intervals / worker tasks
260
+ * @param nodes - GL nodes on [-1, 1]
261
+ * @param weights - Corresponding GL weights
262
+ * @returns Sum of partial integrals = approximate value of ∫ₐᵇ f(x) dx
263
+ */
264
+ integrateFanOut(fnSource: string, a: number, b: number, workerCount: number, nodes: number[], weights: number[]): Promise<number>;
265
+ /**
266
+ * Fan-out distribution batch sampling across `workerCount` workers.
267
+ *
268
+ * Partitions `n` samples into `workerCount` equal chunks (last chunk absorbs
269
+ * the remainder) and dispatches one `sampleChunk` task per chunk. Each chunk
270
+ * uses an independent seed derived from `baseSeed` via SplitMix64-style
271
+ * hashing:
272
+ *
273
+ * `chunkSeed = (baseSeed ^ (chunkIdx * 0x9E3779B97F4A7C15)) >>> 0`
274
+ *
275
+ * This Fibonacci-hashing multiplier gives good avalanche: even baseSeed=0
276
+ * produces K distinct seeds, and adjacent chunk indices produce uncorrelated
277
+ * sequences. See the `sampleChunk` worker kernel for the full rationale.
278
+ *
279
+ * @param distName - One of 'normal', 'gamma', 'beta', 'studentT', 'exponential'
280
+ * @param params - Distribution parameters (order matches factory functions)
281
+ * @param n - Total number of samples to generate
282
+ * @param baseSeed - Base seed for reproducible output
283
+ * @param workerCount - Number of parallel worker tasks
284
+ * @returns Concatenated Float64Array of `n` samples
285
+ */
286
+ distributionSampleFanOut(distName: string, params: number[], n: number, baseSeed: number, workerCount: number): Promise<Float64Array>;
287
+ /**
288
+ * Compute a batch of independent radix-2 FFTs in parallel.
289
+ *
290
+ * `real` and `imag` each hold `frameCount` concatenated frames of
291
+ * `frameLength` samples (`frameLength` must be a power of two). Each frame
292
+ * is FFT'd independently and the frames are distributed across workers.
293
+ *
294
+ * Used to parallelize the embarrassingly-parallel FFT batches in
295
+ * `spectrogram` (one FFT per windowed frame) and `fft2d` (rows then columns).
296
+ *
297
+ * @param real - Concatenated real parts (`frameCount * frameLength` values)
298
+ * @param imag - Concatenated imaginary parts (same layout as `real`)
299
+ * @param frameCount - Number of independent frames
300
+ * @param frameLength - Samples per frame (power of two)
301
+ * @param inverse - Compute the inverse FFT when true
302
+ */
303
+ fftBatch(real: Float64Array, imag: Float64Array, frameCount: number, frameLength: number, inverse?: boolean): Promise<ParallelResult<{
304
+ real: Float64Array;
305
+ imag: Float64Array;
306
+ }>>;
307
+ /**
308
+ * Compute an all-pairs Euclidean distance matrix in parallel.
309
+ *
310
+ * @param points - Flattened `n * dim` coordinate array (row-major)
311
+ * @param n - Number of points
312
+ * @param dim - Coordinate dimension
313
+ * @returns Flat row-major `n * n` distance matrix
314
+ */
315
+ distanceMatrix(points: Float64Array, n: number, dim: number): Promise<ParallelResult<Float64Array>>;
173
316
  /**
174
317
  * Parallel absolute value
175
318
  */
@@ -242,6 +385,49 @@ declare class ComputePool {
242
385
  * Parallel element-wise division
243
386
  */
244
387
  divide(a: Float64Array, b: Float64Array): Promise<ParallelResult<Float64Array>>;
388
+ /**
389
+ * Parallel element-wise exponentiation.
390
+ *
391
+ * `out[i] = a[i] ** b[i]`
392
+ *
393
+ * Delegates to `applyKernel2` with the `Math.pow` kernel. The default
394
+ * per-op threshold for `pow` is `'never'` (overhead dominates); the
395
+ * sequential path is taken unless the caller overrides `thresholdByOp.pow`.
396
+ */
397
+ pow(a: Float64Array, b: Float64Array): Promise<ParallelResult<Float64Array>>;
398
+ /**
399
+ * Parallel element-wise sign function.
400
+ *
401
+ * `out[i] = Math.sign(data[i])` → -1 | 0 | 1, with NaN → NaN (IEEE 754).
402
+ *
403
+ * Delegates to `applyKernel` with the `Math.sign` kernel. The default
404
+ * per-op threshold for `sign` is `'never'` (overhead dominates); the
405
+ * sequential path is taken unless the caller overrides `thresholdByOp.sign`.
406
+ */
407
+ sign(data: Float64Array): Promise<ParallelResult<Float64Array>>;
408
+ /**
409
+ * General tensor contraction (tensordot) over specified axis pairs.
410
+ *
411
+ * Contracts axis `axesA[i]` of `a` with axis `axesB[i]` of `b` for each
412
+ * pair index `i`. The result shape is the non-contracted axes of `a` followed
413
+ * by the non-contracted axes of `b` (NumPy convention).
414
+ *
415
+ * Parallelization threshold: contracted-axis volume (product of contracted
416
+ * dimensions) >= 8 192. When parallelized, output elements are distributed
417
+ * in contiguous slices across workers via the `tensordotChunk` kernel.
418
+ *
419
+ * @param a - Flat row-major Float64Array for tensor A
420
+ * @param aShape - Shape of tensor A
421
+ * @param b - Flat row-major Float64Array for tensor B
422
+ * @param bShape - Shape of tensor B
423
+ * @param axesA - Axes of A to contract (same length as axesB)
424
+ * @param axesB - Axes of B to contract (same length as axesA)
425
+ * @returns `{ data: Float64Array; shape: number[] }` — flat result + result shape
426
+ */
427
+ tensordot(a: Float64Array, aShape: readonly number[], b: Float64Array, bShape: readonly number[], axesA: readonly number[], axesB: readonly number[]): Promise<ParallelResult<{
428
+ data: Float64Array;
429
+ shape: number[];
430
+ }>>;
245
431
  /**
246
432
  * Compute mean in parallel (uses variance internally)
247
433
  */
@@ -258,6 +444,37 @@ declare class ComputePool {
258
444
  * Find maximum value in parallel
259
445
  */
260
446
  max(data: Float64Array): Promise<ParallelResult<number>>;
447
+ /**
448
+ * Element-wise bitwise AND on two `Int32Array`s.
449
+ */
450
+ bitAnd(a: Int32Array, b: Int32Array): Promise<ParallelResult<Int32Array>>;
451
+ /**
452
+ * Element-wise bitwise OR on two `Int32Array`s.
453
+ */
454
+ bitOr(a: Int32Array, b: Int32Array): Promise<ParallelResult<Int32Array>>;
455
+ /**
456
+ * Element-wise bitwise XOR on two `Int32Array`s.
457
+ */
458
+ bitXor(a: Int32Array, b: Int32Array): Promise<ParallelResult<Int32Array>>;
459
+ /**
460
+ * Unary bitwise NOT on an `Int32Array`.
461
+ */
462
+ bitNot(a: Int32Array): Promise<ParallelResult<Int32Array>>;
463
+ /**
464
+ * Element-wise left shift. `b` may be a per-element `Int32Array` of
465
+ * shift counts or a single scalar `number` applied uniformly.
466
+ */
467
+ leftShift(a: Int32Array, b: Int32Array | number): Promise<ParallelResult<Int32Array>>;
468
+ /**
469
+ * Element-wise arithmetic (sign-preserving) right shift.
470
+ */
471
+ rightArithShift(a: Int32Array, b: Int32Array | number): Promise<ParallelResult<Int32Array>>;
472
+ /**
473
+ * Element-wise logical (zero-filling) right shift. Results are stored
474
+ * as `Int32Array`, so values ≥ 2^31 wrap into the negative range —
475
+ * matching `(x >>> n) | 0` JavaScript semantics.
476
+ */
477
+ rightLogShift(a: Int32Array, b: Int32Array | number): Promise<ParallelResult<Int32Array>>;
261
478
  /**
262
479
  * Terminate the worker pool
263
480
  */
@@ -270,6 +487,11 @@ declare class ComputePool {
270
487
  * Get current configuration
271
488
  */
272
489
  getConfig(): ComputePoolConfig;
490
+ /**
491
+ * Maximum number of workers configured for this pool.
492
+ * Used by distribution sampling fan-out to determine chunk count.
493
+ */
494
+ get workerCount(): number;
273
495
  /**
274
496
  * Get the underlying MathWorkerPool for advanced operations
275
497
  */
@@ -853,6 +1075,77 @@ declare function partitionRange(start: number, end: number, options?: ChunkOptio
853
1075
  */
854
1076
  declare function partition2D(rows: number, cols: number, options?: ChunkOptions): Array<[number, number, number, number]>;
855
1077
 
1078
+ /**
1079
+ * Parallel Bitwise Operations
1080
+ *
1081
+ * Element-wise bitwise operations on Int32Array buffers. Operations are
1082
+ * applied in a chunked fashion so the work pattern mirrors the other
1083
+ * parallel ops (`elementwise`, `scale`, etc.). The actual chunk kernel
1084
+ * runs in-process: the MathWorkerPool kernel registry in
1085
+ * `@danielsimonjr/mathts-workerpool` is keyed on `Float64Array` buffers,
1086
+ * so cross-thread bitwise dispatch is intentionally out of scope here.
1087
+ *
1088
+ * The chunking still matters: it bounds peak-allocation pressure for
1089
+ * very large arrays and keeps the call shape uniform with the rest of
1090
+ * the parallel API, so the typed-function `Int32Array, Int32Array`
1091
+ * signatures look identical to the `Float64Array, Float64Array` ones.
1092
+ *
1093
+ * Semantics follow JavaScript bitwise semantics on 32-bit signed
1094
+ * integers (two's complement). For shift counts JavaScript itself
1095
+ * masks to the low 5 bits — we preserve that behavior.
1096
+ *
1097
+ * @packageDocumentation
1098
+ */
1099
+
1100
+ /**
1101
+ * The set of supported binary bitwise op codes.
1102
+ *
1103
+ * - `bitAnd` : `a & b`
1104
+ * - `bitOr` : `a | b`
1105
+ * - `bitXor` : `a ^ b`
1106
+ * - `leftShift` : `a << b`
1107
+ * - `rightArithShift` : `a >> b` (sign-extending)
1108
+ * - `rightLogShift` : `a >>> b` (zero-filling, returned as Int32 — values
1109
+ * above 2^31 wrap into negative range, as in `(x >>> n) | 0`)
1110
+ */
1111
+ type BitwiseBinaryOp = 'bitAnd' | 'bitOr' | 'bitXor' | 'leftShift' | 'rightArithShift' | 'rightLogShift';
1112
+ /**
1113
+ * Bitwise AND on two equal-length `Int32Array`s.
1114
+ */
1115
+ declare function bitAnd(a: Int32Array, b: Int32Array, options?: ChunkOptions): Int32Array;
1116
+ /**
1117
+ * Bitwise OR on two equal-length `Int32Array`s.
1118
+ */
1119
+ declare function bitOr(a: Int32Array, b: Int32Array, options?: ChunkOptions): Int32Array;
1120
+ /**
1121
+ * Bitwise XOR on two equal-length `Int32Array`s.
1122
+ */
1123
+ declare function bitXor(a: Int32Array, b: Int32Array, options?: ChunkOptions): Int32Array;
1124
+ /**
1125
+ * Element-wise left shift: `a[i] << b[i]`.
1126
+ *
1127
+ * `b` may be either an `Int32Array` of per-element shift counts or a
1128
+ * single scalar `number` (applied uniformly). Shift counts are masked
1129
+ * to the low 5 bits by JavaScript itself — values ≥ 32 fold back into
1130
+ * `[0, 31]`.
1131
+ */
1132
+ declare function leftShift(a: Int32Array, b: Int32Array | number, options?: ChunkOptions): Int32Array;
1133
+ /**
1134
+ * Element-wise arithmetic (sign-preserving) right shift: `a[i] >> b[i]`.
1135
+ */
1136
+ declare function rightArithShift(a: Int32Array, b: Int32Array | number, options?: ChunkOptions): Int32Array;
1137
+ /**
1138
+ * Element-wise logical (zero-filling) right shift: `a[i] >>> b[i]`.
1139
+ *
1140
+ * Result is stored as `Int32Array`, so values ≥ 2^31 wrap into the
1141
+ * negative range — equivalent to `(x >>> n) | 0`.
1142
+ */
1143
+ declare function rightLogShift(a: Int32Array, b: Int32Array | number, options?: ChunkOptions): Int32Array;
1144
+ /**
1145
+ * Unary bitwise NOT: `~a[i]`. Returns a fresh `Int32Array`.
1146
+ */
1147
+ declare function bitNot(a: Int32Array, options?: ChunkOptions): Int32Array;
1148
+
856
1149
  /**
857
1150
  * Threshold-based Dispatch Strategy
858
1151
  *
@@ -990,4 +1283,4 @@ interface PoolStats {
990
1283
  activeTasks: number;
991
1284
  }
992
1285
 
993
- export { type ChunkInfo, type ChunkOptions, type ChunkResult, ComputePool, type ComputePoolConfig, DEFAULT_POOL_CONFIG, DEFAULT_THRESHOLDS, type DispatchResult, type ElementwiseOptions, type ExecOptions, type ExecutionMode, type MapOptions, type MatmulOptions, type OperationCategory, type ParallelResult, type PoolOptions, type PoolStats, type ReduceOptions, type ThresholdConfig, ThresholdDispatcher, calculateChunks, calculateOptimalChunks, chunkArray, chunkFloat64Array, computePool, dispatch, mergeArrayChunks, mergeFloat64Chunks, parallelAbs, parallelAdd, parallelCos, parallelCount, parallelDistance, parallelDivide, parallelDot, parallelElementwise, parallelEvery, parallelExp, parallelFilter, parallelFind, parallelForEach, parallelHistogram, parallelLog, parallelMap, parallelMatmul, parallelMatvec, parallelMax, parallelMean, parallelMin, parallelMinMax, parallelMultiply, parallelNegate, parallelNorm, parallelOuter, parallelReduce, parallelScale, parallelSin, parallelSome, parallelSort, parallelSqrt, parallelSquare, parallelStd, parallelSubtract, parallelSum, parallelTan, parallelTranspose, parallelUnary, parallelVariance, partition2D, partitionRange, shouldParallelize$1 as shouldChunkParallelize, shouldParallelize, thresholdDispatcher };
1286
+ export { type BitwiseBinaryOp, type ChunkInfo, type ChunkOptions, type ChunkResult, ComputePool, type ComputePoolConfig, DEFAULT_POOL_CONFIG, DEFAULT_THRESHOLDS, type DispatchResult, type ElementwiseOptions, type ExecOptions, type ExecutionMode, type MapOptions, type MatmulOptions, type OpName, type OpThreshold, type OperationCategory, type ParallelResult, type PoolOptions, type PoolStats, type ReduceOptions, type ThresholdConfig, ThresholdDispatcher, bitAnd, bitNot, bitOr, bitXor, calculateChunks, calculateOptimalChunks, chunkArray, chunkFloat64Array, computePool, dispatch, leftShift, mergeArrayChunks, mergeFloat64Chunks, parallelAbs, parallelAdd, parallelCos, parallelCount, parallelDistance, parallelDivide, parallelDot, parallelElementwise, parallelEvery, parallelExp, parallelFilter, parallelFind, parallelForEach, parallelHistogram, parallelLog, parallelMap, parallelMatmul, parallelMatvec, parallelMax, parallelMean, parallelMin, parallelMinMax, parallelMultiply, parallelNegate, parallelNorm, parallelOuter, parallelReduce, parallelScale, parallelSin, parallelSome, parallelSort, parallelSqrt, parallelSquare, parallelStd, parallelSubtract, parallelSum, parallelTan, parallelTranspose, parallelUnary, parallelVariance, partition2D, partitionRange, resolveOpThreshold, rightArithShift, rightLogShift, shouldParallelize$1 as shouldChunkParallelize, shouldParallelize, thresholdDispatcher };