@danielsimonjr/mathts-tensor 0.2.18 → 0.2.20

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.
Files changed (44) hide show
  1. package/dist/Tensor.d.ts +176 -0
  2. package/dist/Tensor.d.ts.map +1 -0
  3. package/dist/contraction-sequence.d.ts +93 -0
  4. package/dist/contraction-sequence.d.ts.map +1 -0
  5. package/dist/index.d.ts +37 -1129
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +1 -1
  8. package/dist/named-index.d.ts +76 -0
  9. package/dist/named-index.d.ts.map +1 -0
  10. package/dist/operations/cholesky.d.ts +47 -0
  11. package/dist/operations/cholesky.d.ts.map +1 -0
  12. package/dist/operations/concatenate.d.ts +35 -0
  13. package/dist/operations/concatenate.d.ts.map +1 -0
  14. package/dist/operations/eig.d.ts +50 -0
  15. package/dist/operations/eig.d.ts.map +1 -0
  16. package/dist/operations/flip.d.ts +35 -0
  17. package/dist/operations/flip.d.ts.map +1 -0
  18. package/dist/operations/gather.d.ts +33 -0
  19. package/dist/operations/gather.d.ts.map +1 -0
  20. package/dist/operations/kron.d.ts +38 -0
  21. package/dist/operations/kron.d.ts.map +1 -0
  22. package/dist/operations/lu.d.ts +48 -0
  23. package/dist/operations/lu.d.ts.map +1 -0
  24. package/dist/operations/pad.d.ts +50 -0
  25. package/dist/operations/pad.d.ts.map +1 -0
  26. package/dist/operations/pinv.d.ts +39 -0
  27. package/dist/operations/pinv.d.ts.map +1 -0
  28. package/dist/operations/qr.d.ts +49 -0
  29. package/dist/operations/qr.d.ts.map +1 -0
  30. package/dist/operations/random.d.ts +61 -0
  31. package/dist/operations/random.d.ts.map +1 -0
  32. package/dist/operations/roll.d.ts +44 -0
  33. package/dist/operations/roll.d.ts.map +1 -0
  34. package/dist/operations/scatter.d.ts +54 -0
  35. package/dist/operations/scatter.d.ts.map +1 -0
  36. package/dist/operations/slice.d.ts +43 -0
  37. package/dist/operations/slice.d.ts.map +1 -0
  38. package/dist/operations/solve.d.ts +54 -0
  39. package/dist/operations/solve.d.ts.map +1 -0
  40. package/dist/operations/stack.d.ts +50 -0
  41. package/dist/operations/stack.d.ts.map +1 -0
  42. package/dist/operations/svd.d.ts +56 -0
  43. package/dist/operations/svd.d.ts.map +1 -0
  44. package/package.json +57 -57
package/dist/index.d.ts CHANGED
@@ -1,1129 +1,37 @@
1
- import { DenseMatrix } from '@danielsimonjr/mathts-matrix';
2
- import { NestedArray as NestedArray$1 } from '@danielsimonjr/mathts-core/internal';
3
-
4
- /**
5
- * Index — an immutable value type carrying a unique identity, a dimension,
6
- * optional tags, and a prime level. Two indices *match* (and will be
7
- * contracted by `Tensor.contract`) iff their `id` and `primeLevel` agree.
8
- * Dimension agreement is validated at contraction time, not at matching time.
9
- *
10
- * Inspired by ITensors.jl's `Index` primitive.
11
- */
12
- interface IndexOpts {
13
- /** Human-readable name; not used for matching but useful in errors / debug. */
14
- name?: string;
15
- /**
16
- * Free-form tag list. Two indices with the SAME id but DIFFERENT tags still
17
- * match by id.
18
- */
19
- tags?: ReadonlyArray<string>;
20
- /**
21
- * Prime level (ITensor's "prime"). Two indices with the same id but different
22
- * prime levels do NOT match.
23
- */
24
- primeLevel?: number;
25
- }
26
- /**
27
- * A first-class index value. Each `new Index(...)` call mints a fresh `id`
28
- * (Symbol) that can never collide with another. Methods that would mutate
29
- * state instead return a new `Index` sharing the same `id`.
30
- */
31
- declare class Index {
32
- readonly id: symbol;
33
- readonly dim: number;
34
- readonly name?: string;
35
- readonly tags: ReadonlyArray<string>;
36
- readonly primeLevel: number;
37
- constructor(dim: number, opts?: IndexOpts);
38
- /**
39
- * Internal constructor used by mutating-style methods that need to share the
40
- * same `id` with a different primeLevel / tags. Not exposed publicly.
41
- */
42
- private static _from;
43
- /**
44
- * Return a new Index with `primeLevel` incremented by `by` (default 1).
45
- */
46
- prime(by?: number): Index;
47
- /**
48
- * Return a new Index with `primeLevel` reset to 0.
49
- */
50
- noprime(): Index;
51
- /**
52
- * Return a new Index with `tag` added to its tag list (no-op if already present).
53
- */
54
- addTag(tag: string): Index;
55
- /**
56
- * Return a new Index with `tag` removed from its tag list (no-op if absent).
57
- */
58
- removeTag(tag: string): Index;
59
- /**
60
- * True if `tag` is in this index's tag list.
61
- */
62
- hasTag(tag: string): boolean;
63
- /**
64
- * Two indices match iff they share the same `id` AND the same `primeLevel`.
65
- * Dimension is NOT used for matching — it is validated at contraction time.
66
- */
67
- matches(other: Index): boolean;
68
- toString(): string;
69
- }
70
- /**
71
- * Convenience factory: `const i = idx(3, 'i')`.
72
- *
73
- * ```ts
74
- * const i = idx(3, 'i'); // dim=3, name='i', primeLevel=0
75
- * const j = idx(4, 'j', { tags: ['site'] });
76
- * ```
77
- */
78
- declare function idx(dim: number, name?: string, opts?: Omit<IndexOpts, 'name'>): Index;
79
-
80
- /**
81
- * Tensor — rank-N, Float64Array-backed, row-major dense tensor. The
82
- * compute primitive behind @danielsimonjr/mathts-tensor. Construction,
83
- * elementwise, einsum, matMul, transpose, reshape live here.
84
- *
85
- * Element-wise and data-movement ops are straightforward O(n) loops (a
86
- * correctness baseline). Heavy ops delegate to the standard packages rather
87
- * than reinventing them: `matMul` uses matrix's backend-selected multiply
88
- * (SIMD-WASM for large inputs), and the decompositions (in `operations/`)
89
- * route through matrix's `svd`/`eig`/`lu`/`qr`/`cholesky`. Storage mirrors
90
- * DenseMatrix (Float64Array, row-major), generalised to arbitrary rank.
91
- */
92
-
93
- /**
94
- * Consolidated onto `@danielsimonjr/mathts-core`'s generic `NestedArray<T>`,
95
- * specialised to `number` (Tensor is Float64Array-backed) — see
96
- * docs/Architecture/duplicate-symbols.json.
97
- */
98
- type NestedArray = NestedArray$1<number>;
99
- interface EinsumSpec {
100
- readonly contractions: ReadonlyArray<{
101
- readonly pair: readonly [readonly [number, number], readonly [number, number]];
102
- }>;
103
- readonly free: ReadonlyArray<{
104
- readonly operand: number;
105
- readonly axis: number;
106
- }>;
107
- }
108
- declare class Tensor {
109
- readonly shape: ReadonlyArray<number>;
110
- readonly data: Float64Array;
111
- /** Optional per-axis Index labels. When set, enables `contract`, `replaceIndex`, `axisOf`. */
112
- readonly axisLabels?: ReadonlyArray<Index>;
113
- constructor(shape: ReadonlyArray<number>, data: Float64Array, axisLabels?: ReadonlyArray<Index>);
114
- static sizeOf(shape: ReadonlyArray<number>): number;
115
- static rowMajorStrides(shape: ReadonlyArray<number>): number[];
116
- static fromNested(data: NestedArray, shape: ReadonlyArray<number>): Tensor;
117
- static identity(n: number): Tensor;
118
- toNested(): NestedArray;
119
- /**
120
- * Build a rank-2 Tensor from a native DenseMatrix. Bridges the tensor and
121
- * matrix packages so matrix data can flow into rank-N / autodiff code.
122
- */
123
- static fromDenseMatrix(m: DenseMatrix): Tensor;
124
- /**
125
- * Convert a rank-2 Tensor to a native DenseMatrix. Throws for any other rank.
126
- */
127
- toDenseMatrix(): DenseMatrix;
128
- private sameShape;
129
- private elementwise;
130
- add(other: Tensor | number): Tensor;
131
- sub(other: Tensor | number): Tensor;
132
- mul(other: Tensor | number): Tensor;
133
- scale(k: number): Tensor;
134
- normInf(): number;
135
- /**
136
- * Compute the broadcast output shape of two shapes following NumPy rules:
137
- * right-align the two shapes; a dimension of 1 broadcasts against any size;
138
- * missing leading axes are treated as length-1.
139
- * Throws with message including both shape arrays on incompatibility.
140
- */
141
- static broadcastShape(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number[];
142
- /**
143
- * Apply a binary elementwise op with NumPy-style broadcasting.
144
- * Both tensors are read via virtual broadcast indices — no data is copied
145
- * until the output is written.
146
- */
147
- private static broadcastOp;
148
- /**
149
- * Generic strided reduction over a set of axes.
150
- *
151
- * `init` is the neutral element; `combine` folds one new value into the
152
- * accumulator; `finalise` (optional) post-processes the accumulator once
153
- * all elements have been visited.
154
- */
155
- private reduceAxes;
156
- /**
157
- * Sum elements along the given axis/axes (or all axes if omitted).
158
- * `keepDims: true` preserves reduced axes as length-1.
159
- */
160
- sum(axis?: number | ReadonlyArray<number>, opts?: {
161
- keepDims?: boolean;
162
- }): Tensor;
163
- /**
164
- * Arithmetic mean along the given axis/axes (or all axes if omitted).
165
- */
166
- mean(axis?: number | ReadonlyArray<number>, opts?: {
167
- keepDims?: boolean;
168
- }): Tensor;
169
- /**
170
- * Element-wise maximum along the given axis/axes (or all axes if omitted).
171
- * NaN propagates (matches NumPy default behaviour).
172
- */
173
- max(axis?: number | ReadonlyArray<number>, opts?: {
174
- keepDims?: boolean;
175
- }): Tensor;
176
- /**
177
- * Element-wise minimum along the given axis/axes (or all axes if omitted).
178
- * NaN propagates (matches NumPy default behaviour).
179
- */
180
- min(axis?: number | ReadonlyArray<number>, opts?: {
181
- keepDims?: boolean;
182
- }): Tensor;
183
- /**
184
- * Product of elements along the given axis/axes (or all axes if omitted).
185
- */
186
- prod(axis?: number | ReadonlyArray<number>, opts?: {
187
- keepDims?: boolean;
188
- }): Tensor;
189
- /**
190
- * p-norm of the tensor.
191
- *
192
- * - `p = 2` (default): Euclidean / Frobenius norm — `sqrt(sum x_i^2)`.
193
- * - `p = 'fro'`: alias for p=2 (Frobenius).
194
- * - `p = 'inf'`: max of absolute values.
195
- * - `p = '-inf'`: min of absolute values.
196
- * - numeric p: `(sum |x_i|^p)^(1/p)`.
197
- *
198
- * When `axis` is given, the norm is computed along that single axis and the
199
- * result has rank reduced by 1 (or stays the same with `keepDims`).
200
- * When `axis` is omitted, the norm is computed over all elements.
201
- */
202
- norm(opts?: {
203
- p?: number | 'inf' | '-inf' | 'fro';
204
- axis?: number;
205
- keepDims?: boolean;
206
- }): Tensor;
207
- /**
208
- * Generalised dot product (NumPy `tensordot`) over explicitly specified axis pairs.
209
- *
210
- * `axes[i] = [a, b]` contracts axis `a` of `this` with axis `b` of `other`.
211
- * The result shape is `this`'s non-contracted axes followed by `other`'s
212
- * non-contracted axes (NumPy convention).
213
- *
214
- * Delegates to `Tensor.einsum` under the hood.
215
- */
216
- tensordot(other: Tensor, axes: ReadonlyArray<readonly [number, number]>): Tensor;
217
- /**
218
- * Normalise an `axis` argument into a sorted list of axis indices.
219
- * `undefined` ⇒ all axes (reduce everything to a rank-0 scalar).
220
- */
221
- private resolveAxes;
222
- private static forEachIndex;
223
- private static flatIndex;
224
- reshape(shape: ReadonlyArray<number>): Tensor;
225
- transpose(perm?: ReadonlyArray<number>): Tensor;
226
- matMul(other: Tensor): Tensor;
227
- static einsum(spec: EinsumSpec, ...operands: Tensor[]): Tensor;
228
- /**
229
- * Return the axis position (0-based) of a labelled index.
230
- * Throws if the index is not found in `axisLabels`.
231
- */
232
- axisOf(index: Index): number;
233
- /**
234
- * Return a new Tensor with the same data and shape but with `oldIndex`
235
- * swapped for `newIndex` in `axisLabels`.
236
- * Throws if `oldIndex` is not found.
237
- */
238
- replaceIndex(oldIndex: Index, newIndex: Index): Tensor;
239
- /**
240
- * Contract this tensor with `other` over every shared index (matched by
241
- * `Index.matches`). Both operands must carry `axisLabels`.
242
- *
243
- * The result tensor carries the non-shared axes from `this` followed by
244
- * the non-shared axes from `other` as its `axisLabels`.
245
- *
246
- * Throws:
247
- * - If either operand lacks `axisLabels`.
248
- * - If there are no shared indices (use `einsum` or an explicit outer product).
249
- * - If a shared index has mismatched dimensions on the two operands.
250
- */
251
- contract(other: Tensor): Tensor;
252
- }
253
-
254
- /**
255
- * tensorSvd — truncated SVD for rank-N tensors.
256
- *
257
- * Partitions the axes of `t` into "row" axes (joining with U) and "col" axes
258
- * (the remaining axes, joining with V), permutes + reshapes `t` into a 2-D
259
- * matrix, calls the existing DenseMatrix SVD primitive, optionally truncates
260
- * the singular-value spectrum, and reshapes U / S / V back into Tensors.
261
- *
262
- * Phase-2 note: `rowAxes` is positional-integer-only. The named-Index overload
263
- * (accepting `ReadonlyArray<Index>`) is reserved for the Phase-1-enabled
264
- * follow-up once `Index` is part of the Tensor surface.
265
- *
266
- * The `joiningIndexName` option is accepted for forward-compatibility with the
267
- * labelled-tensor extension but is unused in Phase 2 — the output Tensors carry
268
- * no `axisLabels`.
269
- */
270
-
271
- interface TensorSvdOpts {
272
- /** If set, keep at most `maxdim` singular values. */
273
- maxdim?: number;
274
- /**
275
- * If set, drop singular values whose absolute value is strictly less than
276
- * `cutoff`. Default is 0 (no cutoff). The test is `s >= cutoff`.
277
- */
278
- cutoff?: number;
279
- /**
280
- * Accepted for forward-compatibility with the labelled-tensor extension
281
- * (Phase-2-extension follow-up). Currently unused — output Tensors carry
282
- * no `axisLabels` in Phase 2.
283
- */
284
- joiningIndexName?: string;
285
- }
286
- interface TensorSvdResult {
287
- /** U factor reshaped to [...rowDims, k]. */
288
- U: Tensor;
289
- /** Singular values as a rank-1 Tensor of shape [k]. */
290
- S: Tensor;
291
- /** V factor reshaped to [k, ...colDims]. */
292
- V: Tensor;
293
- /** Number of singular values retained after truncation. */
294
- truncatedDim: number;
295
- /** Sum of squares of the dropped singular values (Frobenius-norm squared of the discarded part). */
296
- truncationError: number;
297
- }
298
- /**
299
- * Truncated tensor SVD using the pure-JS DenseMatrix SVD primitive (synchronous).
300
- */
301
- declare function tensorSvd(t: Tensor, rowAxes: ReadonlyArray<number>, opts?: TensorSvdOpts): TensorSvdResult;
302
- /**
303
- * Truncated tensor SVD routed through the AssemblyScript WASM SVD kernel
304
- * (`svdWasm`) — the same result as {@link tensorSvd} but accelerated for large
305
- * matricisations. Async because WASM instantiation is async; falls back to JS
306
- * inside `svdWasm` when no binary is available.
307
- */
308
- declare function tensorSvdWasm(t: Tensor, rowAxes: ReadonlyArray<number>, opts?: TensorSvdOpts): Promise<TensorSvdResult>;
309
-
310
- /**
311
- * randomTensor — construct a Tensor filled with pseudo-random values.
312
- *
313
- * Supported distributions:
314
- * 'uniform' — U(0, 1) via the seeded PRNG or Math.random().
315
- * 'normal' — N(0, 1) via Box–Muller transform on the underlying PRNG.
316
- * 'orthogonal' — Uniform on the orthogonal group O(n) via QR decomposition
317
- * of a normal random matrix. Rank-2 shapes only.
318
- *
319
- * Seeded RNG: Mulberry32 — a small, fast, high-quality 32-bit PRNG.
320
- * Reference: Tommy Ettinger, https://gist.github.com/tommyettinger/46a874533244883189143505d203312c
321
- *
322
- * WARNING: The seeded path is NOT cryptographically secure. Do not use for
323
- * security-sensitive purposes (key generation, nonces, etc.).
324
- */
325
-
326
- interface RandomTensorOpts {
327
- /**
328
- * Distribution to sample from.
329
- *
330
- * - `'uniform'` — U(0, 1).
331
- * - `'normal'` — N(0, 1) via Box–Muller transform.
332
- * - `'orthogonal'` — uniform on the orthogonal group; rank-2 shape only.
333
- *
334
- * @default 'uniform'
335
- */
336
- distribution?: 'uniform' | 'normal' | 'orthogonal';
337
- /**
338
- * Integer seed for the Mulberry32 PRNG. When omitted, Math.random() is
339
- * used (non-reproducible). NOT cryptographically secure.
340
- */
341
- seed?: number;
342
- /**
343
- * Optional axis labels forwarded into the new Tensor's constructor.
344
- * Requires Phase-1 `axisLabels` support in the Tensor constructor
345
- * (constructor signature: `Tensor(shape, data, axisLabels?)`).
346
- */
347
- axisLabels?: ReadonlyArray<Index>;
348
- }
349
- /**
350
- * Construct a Tensor of the given `shape` filled with pseudo-random values.
351
- *
352
- * @param shape - Array of positive integers defining the tensor dimensions.
353
- * @param opts - Optional configuration (distribution, seed, axisLabels).
354
- * @returns A new Tensor.
355
- *
356
- * @example
357
- * ```ts
358
- * // 3x4 uniform random tensor
359
- * const t = randomTensor([3, 4]);
360
- *
361
- * // Seeded normal random vector (reproducible)
362
- * const v = randomTensor([100], { distribution: 'normal', seed: 42 });
363
- *
364
- * // 8x8 random orthogonal matrix
365
- * const O = randomTensor([8, 8], { distribution: 'orthogonal', seed: 7 });
366
- * ```
367
- */
368
- declare function randomTensor(shape: ReadonlyArray<number>, opts?: RandomTensorOpts): Tensor;
369
-
370
- /**
371
- * contractNetwork — given an ordered list of Tensors (each carrying
372
- * `axisLabels`), find the pairwise-contraction order minimising the total
373
- * FLOP count and execute it. ITensor's `optimal_contraction_sequence`
374
- * equivalent.
375
- *
376
- * Two algorithms are provided:
377
- *
378
- * - 'exact' — bitmask dynamic programming. For every non-empty subset
379
- * S ⊂ {0..N-1} of input tensors, we compute `bestCost[S]` and the
380
- * partition (S₁, S₂) achieving it (S = S₁ ⊔ S₂, both non-empty).
381
- * Transition:
382
- *
383
- * bestCost[S] = min over all proper subset pairs (S₁, S₂) of
384
- * bestCost[S₁] + bestCost[S₂] + pairwiseCost(net(S₁), net(S₂))
385
- *
386
- * Base: bestCost[{i}] = 0. Subset enumeration via the standard
387
- * submask trick `for (sub = (mask-1) & mask; sub > 0; sub = (sub-1) & mask)`
388
- * visits every non-empty proper subset in O(3^N) total.
389
- *
390
- * Determinism: ties broken by preferring the lexicographically smaller
391
- * (subsetMask₁, subsetMask₂) where subsetMask₁ ≤ subsetMask₂.
392
- *
393
- * Bitmask encoding: bit `i` of a 32-bit integer is set iff input tensor
394
- * index `i` is part of the subset. So `0b1011 = {0, 1, 3}`. We use
395
- * ordinary JavaScript numbers (safe up to 2^32 for bitwise ops; capped
396
- * at N ≤ 30 for headroom).
397
- *
398
- * - 'greedy' — Hendrickson–Sundaram. Maintain a working list of
399
- * intermediate tensor shapes. At each step, choose the pair (i, j) with
400
- * the cheapest pairwise contraction cost and replace them with their
401
- * contraction. Repeat until one remains. O(N³) per step × O(N) steps.
402
- *
403
- * Cost model: for a pairwise contraction of two intermediate tensors with
404
- * shared-axis dimension product `D_shared` and free-axis dimension products
405
- * `D_free_left`, `D_free_right`, the contraction FLOP cost is
406
- *
407
- * cost = D_shared * D_free_left * D_free_right
408
- *
409
- * which is the volume of the OUTPUT tensor times the contraction depth. If
410
- * `D_shared = 1` (no shared axes — outer product) we use `D_free_left *
411
- * D_free_right`; mathematically that is the same formula. We follow this
412
- * convention but it never fires in practice because we drive the cost
413
- * through pairs with at least one shared index when possible.
414
- *
415
- * Output-tensor size for `intermediateSizes`: `D_free_left * D_free_right`
416
- * (the contracted-axis dimensions are summed away, not multiplied into the
417
- * result).
418
- *
419
- * `contractionOrder` indexing convention: each pair `[i, j]` is in
420
- * "virtual-index" space. Input tensors occupy slots 0..N-1; the first
421
- * pairwise contraction produces virtual slot N, the second slot N+1, and
422
- * so on. So a length-N input network has a length-(N-1) order array.
423
- */
424
-
425
- interface ContractNetworkOpts {
426
- /** Cap intermediate-tensor element count to avoid blowups. Default: 2^31. */
427
- maxIntermediateSize?: number;
428
- /**
429
- * 'exact' = DP optimal (≤ ~16 tensors, slow beyond that).
430
- * 'greedy' = Hendrickson–Sundaram heuristic (any N).
431
- * 'auto' = 'exact' when N ≤ 16, otherwise 'greedy'.
432
- * Default: 'auto'.
433
- */
434
- algorithm?: 'exact' | 'greedy' | 'auto';
435
- }
436
- interface ContractNetworkResult {
437
- result: Tensor;
438
- /** Pairwise contractions in (virtual) input-index space; see file header. */
439
- contractionOrder: ReadonlyArray<readonly [number, number]>;
440
- /** Sum of pairwise FLOP costs along the chosen order. */
441
- totalFlops: number;
442
- /** Element count of each intermediate, in creation order. */
443
- intermediateSizes: ReadonlyArray<number>;
444
- }
445
- /**
446
- * Contract a network of named-index tensors in the optimal pairwise order.
447
- *
448
- * Returns:
449
- * - `result` — the fully contracted final Tensor.
450
- * - `contractionOrder` — the chosen sequence of pairwise contractions in
451
- * virtual-slot space (slots 0..N-1 = inputs; each produced intermediate
452
- * takes the next free slot).
453
- * - `totalFlops` — sum of per-step FLOP costs along the chosen order.
454
- * - `intermediateSizes` — element count of each produced intermediate.
455
- *
456
- * Throws:
457
- * - on empty input.
458
- * - if any input lacks `axisLabels`.
459
- * - if `maxIntermediateSize` is so tight no valid order exists.
460
- */
461
- declare function contractNetwork(tensors: ReadonlyArray<Tensor>, opts?: ContractNetworkOpts): ContractNetworkResult;
462
-
463
- /**
464
- * tensorQr — QR decomposition for rank-N tensors.
465
- *
466
- * Mirrors the `tensorSvd` pattern: partitions the axes of `t` into "row" axes
467
- * (joining with Q) and "col" axes (joining with R), permutes + reshapes `t`
468
- * into a 2-D matrix, calls the DenseMatrix `qr` primitive, then reshapes Q
469
- * and R back into Tensors.
470
- *
471
- * In 'reduced' mode (default, thin QR):
472
- * Q has shape [...rowDims, k] where k = min(numRows, numCols)
473
- * R has shape [k, ...colDims]
474
- *
475
- * In 'full' mode:
476
- * Q has shape [...rowDims, numRows] (square in the row direction)
477
- * R has shape [numRows, ...colDims]
478
- *
479
- * `axisLabels` propagation: when the input carries labels, the row-axis
480
- * labels are forwarded to Q's leading dims and the col-axis labels to R's
481
- * trailing dims. A fresh "joining" Index of dimension `k` (or `numRows` in
482
- * full mode) is inserted between them.
483
- */
484
-
485
- interface TensorQrOpts {
486
- /** 'reduced' (default, thin QR) or 'full'. */
487
- mode?: 'reduced' | 'full';
488
- /**
489
- * Optional name for the joining index between Q and R. Used only when
490
- * input axisLabels are present to label the new joining axis. Defaults
491
- * to "qr".
492
- */
493
- joiningIndexName?: string;
494
- }
495
- interface TensorQrResult {
496
- /** Q factor with orthonormal columns reshaped to [...rowDims, k]. */
497
- Q: Tensor;
498
- /** R factor (upper-triangular) reshaped to [k, ...colDims]. */
499
- R: Tensor;
500
- }
501
- /**
502
- * Compute the QR decomposition of tensor `t` by partitioning its axes into
503
- * "row" and "col" groups.
504
- *
505
- * @param t - Input tensor of any rank ≥ 1.
506
- * @param rowAxes - Axis indices forming the row dimension of the effective
507
- * 2-D matrix. The remaining axes form the column dimension.
508
- * @param opts - Optional mode + naming settings.
509
- */
510
- declare function tensorQr(t: Tensor, rowAxes: ReadonlyArray<number>, opts?: TensorQrOpts): TensorQrResult;
511
-
512
- /**
513
- * tensorLU — LU decomposition with partial pivoting for rank-N tensors.
514
- *
515
- * Mirrors the `tensorSvd` pattern: partitions the axes of `t` into "row"
516
- * axes and "col" axes, reshapes `t` into a 2-D matrix, performs LU with
517
- * partial pivoting (Doolittle's algorithm via the matrix primitive), and
518
- * returns the factors as Tensors.
519
- *
520
- * The 2-D-reshaped input must be square; otherwise an error is thrown.
521
- *
522
- * Decomposition: P · A = L · U, where L is unit lower-triangular and U is
523
- * upper-triangular. P is returned as the row-permutation array (P[i] is
524
- * the row index of the original A that was moved to position i).
525
- *
526
- * `axisLabels` propagation: L receives the rowAxes labels on its leading
527
- * dims and a fresh joining Index on its trailing axis; U receives the
528
- * joining Index on its leading axis and the colAxes labels on its trailing
529
- * dims.
530
- */
531
-
532
- interface TensorLUResult {
533
- /** Unit lower-triangular L. Shape [...rowDims, n]. */
534
- L: Tensor;
535
- /** Upper-triangular U. Shape [n, ...colDims]. */
536
- U: Tensor;
537
- /** Row permutation array of length n. P[i] is the original-row index now at position i. */
538
- P: Int32Array;
539
- /** Sign of the permutation (+1 for even, -1 for odd) — useful for det(). */
540
- parity: 1 | -1;
541
- }
542
- interface TensorLUOpts {
543
- /** Optional name for the joining index between L and U. Defaults to "lu". */
544
- joiningIndexName?: string;
545
- }
546
- /**
547
- * Compute the LU decomposition of tensor `t` by partitioning its axes into
548
- * "row" and "col" groups. The reshaped 2-D matrix must be square.
549
- *
550
- * Delegates the core Doolittle algorithm to `@danielsimonjr/mathts-matrix`'s
551
- * `lu` primitive.
552
- *
553
- * @param t - Input tensor of any rank ≥ 1.
554
- * @param rowAxes - Axis indices forming the row dimension of the effective
555
- * 2-D matrix. The remaining axes form the column dimension.
556
- * @param opts - Optional joining-index name.
557
- */
558
- declare function tensorLU(t: Tensor, rowAxes: ReadonlyArray<number>, opts?: TensorLUOpts): TensorLUResult;
559
-
560
- /**
561
- * tensorCholesky — Cholesky decomposition for symmetric positive-definite
562
- * rank-N tensors.
563
- *
564
- * Mirrors the `tensorSvd` pattern: partitions the axes of `t` into "row"
565
- * axes and "col" axes, reshapes `t` into a 2-D matrix, performs the
566
- * Cholesky decomposition via the matrix primitive (right-looking algorithm),
567
- * and returns the factor as a Tensor.
568
- *
569
- * The 2-D reshaped input must be square and symmetric positive-definite;
570
- * otherwise an error is thrown.
571
- *
572
- * Decomposition modes:
573
- * - default (`lower: true`): returns L such that A = L · Lᵀ.
574
- * - `lower: false`: returns U such that A = Uᵀ · U.
575
- *
576
- * `axisLabels` propagation: the returned factor receives the rowAxes labels
577
- * on its leading dims and a fresh joining Index on its trailing axis
578
- * (for L), or the joining Index on the leading axis and colAxes labels on
579
- * the trailing dims (for U).
580
- */
581
-
582
- interface TensorCholeskyOpts {
583
- /** When true (default), return L such that A = L·Lᵀ. When false, return U such that A = Uᵀ·U. */
584
- lower?: boolean;
585
- /** Optional name for the joining index on the returned factor. Defaults to "cholesky". */
586
- joiningIndexName?: string;
587
- }
588
- interface TensorCholeskyResult {
589
- /** Cholesky factor (lower or upper depending on `opts.lower`). */
590
- L: Tensor;
591
- }
592
- /**
593
- * Compute the Cholesky decomposition of tensor `t` by partitioning its
594
- * axes into "row" and "col" groups. The reshaped 2-D matrix must be
595
- * square and symmetric positive-definite.
596
- *
597
- * Delegates the core right-looking Cholesky algorithm to
598
- * `@danielsimonjr/mathts-matrix`'s `cholesky` primitive.
599
- *
600
- * @param t - Input tensor of any rank ≥ 1.
601
- * @param rowAxes - Axis indices forming the row dimension of the effective
602
- * 2-D matrix. The remaining axes form the column dimension.
603
- * @param opts - Optional triangle selector + naming.
604
- */
605
- declare function tensorCholesky(t: Tensor, rowAxes: ReadonlyArray<number>, opts?: TensorCholeskyOpts): TensorCholeskyResult;
606
-
607
- /**
608
- * tensorEig — eigenvalue / eigenvector decomposition for rank-N tensors.
609
- *
610
- * Mirrors the `tensorSvd` pattern: partitions the axes of `t` into "row"
611
- * axes and "col" axes, reshapes `t` into a 2-D matrix, and delegates to
612
- * the DenseMatrix `eig` primitive.
613
- *
614
- * The 2-D reshaped input must be square.
615
- *
616
- * Routing:
617
- * - `symmetric: true` — eigenvalues are real and eigenvectors are
618
- * orthogonal (matrix routes the symmetric path
619
- * internally).
620
- * - `symmetric: false` (default) — general eigensolver. If any eigenvalue
621
- * has a non-zero imaginary part, the result
622
- * includes an `eigenvaluesImaginary` Tensor;
623
- * otherwise the field is undefined.
624
- * - `computeVectors: false` — only eigenvalues are returned (faster).
625
- */
626
-
627
- interface TensorEigOpts {
628
- /** Hint that the input is symmetric; routes through a stable real-eigenvalue path. */
629
- symmetric?: boolean;
630
- /** When false, only eigenvalues are computed. Default true. */
631
- computeVectors?: boolean;
632
- }
633
- interface TensorEigResult {
634
- /** Real parts of the eigenvalues. 1-D Tensor of length n. */
635
- eigenvalues: Tensor;
636
- /** Eigenvectors as columns; shape [n, n]. Present only when computeVectors !== false. */
637
- eigenvectors?: Tensor;
638
- /**
639
- * Imaginary parts of the eigenvalues. 1-D Tensor of length n.
640
- * Only present when any eigenvalue has nonzero imaginary part (general
641
- * non-symmetric case). Undefined when all eigenvalues are real.
642
- */
643
- eigenvaluesImaginary?: Tensor;
644
- }
645
- /**
646
- * Tensor eigendecomposition using the pure-JS matrix eig primitive (synchronous).
647
- */
648
- declare function tensorEig(t: Tensor, rowAxes: ReadonlyArray<number>, opts?: TensorEigOpts): TensorEigResult;
649
- /**
650
- * Tensor eigendecomposition routed through the AssemblyScript WASM eig kernel
651
- * (`eigWasm`) — same result as {@link tensorEig}, accelerated for large
652
- * matricisations. Async (WASM instantiation); `eigWasm` falls back to JS when no
653
- * binary is available.
654
- */
655
- declare function tensorEigWasm(t: Tensor, rowAxes: ReadonlyArray<number>, opts?: TensorEigOpts): Promise<TensorEigResult>;
656
-
657
- /**
658
- * tensorPinv — Moore-Penrose pseudoinverse for rank-N tensors.
659
- *
660
- * Partitions the axes of `t` into "row" axes (the axes that form the
661
- * numerically "tall" side of the matrix) and the remaining "col" axes.
662
- * Then:
663
- * 1. Permutes + reshapes `t` to a 2-D matrix M (numRows × numCols).
664
- * 2. Computes the full SVD: M = U · diag(S) · V^T.
665
- * 3. Thresholds small singular values using `rcond`: keep s_i if
666
- * s_i > rcond · max(S), else treat as zero.
667
- * 4. Computes pinv(M) = V · diag(S^+) · U^T (shape: numCols × numRows).
668
- * 5. Reshapes the result back into a Tensor with swapped row/col dims.
669
- *
670
- * Axis labels: if the input carries `axisLabels`, the output tensor's
671
- * leading axes get the original col-axis labels and the trailing axes get
672
- * the original row-axis labels (because the pseudoinverse swaps rows ↔ cols).
673
- */
674
-
675
- interface TensorPinvOpts {
676
- /**
677
- * Relative condition threshold for singular-value truncation.
678
- * A singular value s_i is treated as zero when s_i ≤ rcond · max(S).
679
- * Default: 1e-10.
680
- */
681
- rcond?: number;
682
- }
683
- /**
684
- * Compute the Moore-Penrose pseudoinverse of tensor `t` by partitioning its
685
- * axes into "row" and "col" groups.
686
- *
687
- * @param t - Input tensor of any rank ≥ 1.
688
- * @param rowAxes - Axis indices (integers) or Index objects whose dimensions
689
- * form the row dimension of the effective 2-D matrix. The
690
- * remaining axes form the column dimension.
691
- * @param opts - Optional rcond threshold.
692
- */
693
- declare function tensorPinv(t: Tensor, rowAxes: ReadonlyArray<number | Index>, opts?: TensorPinvOpts): Tensor;
694
-
695
- /**
696
- * tensorSolve — named-index linear solver for rank-N tensors.
697
- *
698
- * Reshapes tensor A into a square matrix and tensor b into a column vector (or
699
- * multi-column RHS matrix), solves A·x = b via LU decomposition with partial
700
- * pivoting, and reshapes the solution back.
701
- *
702
- * Axis matching:
703
- * - When A has `axisLabels` and `b` has `axisLabels`, the "row" axes of A
704
- * are matched to axes of `b` by Index identity (ignoring prime level).
705
- * - Otherwise `rowAxesA` / `rowAxesB` (integer indices) must be provided,
706
- * or the first axes of each tensor are used by default.
707
- *
708
- * Constraints:
709
- * - The reshaped A must be square (numRows_A × numRows_A).
710
- * - A must be non-singular (LU decomposition throws if pivot is zero).
711
- * - For multi-RHS, the RHS col dimension must match A's row dimension.
712
- *
713
- * Result shape:
714
- * - `x` has shape [...colDimsA, ...colDimsB] where colDimsA are the axes
715
- * of A not used as row axes and colDimsB are the axes of b not used as
716
- * row (contracting) axes.
717
- * - When A is square as a whole tensor (rank 2), the result has the same
718
- * shape as b.
719
- *
720
- * Axis labels: propagated from A's col axes and b's col axes.
721
- */
722
-
723
- interface TensorSolveOpts {
724
- /**
725
- * Axis indices (integers) or Index objects of A that form the "contracting"
726
- * (row) side of the square matrix. Default: first `ceil(rank/2)` axes.
727
- */
728
- rowAxesA?: ReadonlyArray<number | Index>;
729
- /**
730
- * Axis indices (integers) or Index objects of b that form the "contracting"
731
- * (row) side matched to A's row dimension. Default: first axis of b.
732
- */
733
- rowAxesB?: ReadonlyArray<number | Index>;
734
- }
735
- interface TensorSolveResult {
736
- /** Solution tensor x satisfying A·x ≈ b. */
737
- x: Tensor;
738
- }
739
- /**
740
- * Solve A·x = b for x using LU decomposition.
741
- *
742
- * @param A - Coefficient tensor (rank ≥ 2 when reshaped to square).
743
- * @param b - Right-hand side tensor.
744
- * @param opts - Optional axis-selection overrides.
745
- */
746
- declare function tensorSolve(A: Tensor, b: Tensor, opts?: TensorSolveOpts): TensorSolveResult;
747
-
748
- /**
749
- * tensorKron — Kronecker product for rank-N tensors.
750
- *
751
- * Computes the Kronecker product of tensors `a` and `b`. For rank-2 matrices
752
- * this is the classical Kronecker product:
753
- *
754
- * kron(A, B)[i0, j0] = A[i0 / B.rows, j0 / B.cols] * B[i0 % B.rows, j0 % B.cols]
755
- *
756
- * For higher-rank tensors, the same rule is applied axis-by-axis:
757
- *
758
- * result.shape[k] = a.shape[k] * b.shape[k]
759
- * result[...i] = a[i[0]/b.shape[0], ..., i[r-1]/b.shape[r-1]]
760
- * * b[i[0]%b.shape[0], ..., i[r-1]%b.shape[r-1]]
761
- *
762
- * Rank alignment: if the tensors have different ranks, the smaller one is
763
- * broadcast-aligned to the right by prepending size-1 dimensions (numpy-style).
764
- *
765
- * Axis labels: when both tensors carry `axisLabels`, the output axis labels
766
- * are formed by concatenating each pair as `"<aName>_X_<bName>"` to avoid
767
- * collisions. When only one tensor has labels, the output carries no labels.
768
- */
769
-
770
- interface TensorKronOpts {
771
- /**
772
- * Separator string inserted between a's and b's axis-label names when
773
- * building the output axisLabels. Default: "_X_".
774
- */
775
- separator?: string;
776
- }
777
- /**
778
- * Compute the Kronecker product of tensors `a` and `b`.
779
- *
780
- * @param a - Left operand tensor.
781
- * @param b - Right operand tensor.
782
- * @param opts - Optional separator for axis-label naming.
783
- */
784
- declare function tensorKron(a: Tensor, b: Tensor, opts?: TensorKronOpts): Tensor;
785
-
786
- /**
787
- * slice — extract a sub-tensor by per-axis [start, stop, step] ranges.
788
- *
789
- * Mirrors NumPy / JAX basic slicing semantics:
790
- * - Negative indices wrap around: -1 refers to the last element.
791
- * - `null` range for an axis means "take the entire axis".
792
- * - `step` must be >= 1 (reverse-step slicing is deferred).
793
- * - Output shape for axis i: Math.ceil((stop - start) / step).
794
- *
795
- * Axis-label semantics: labels from the input axes are preserved in the
796
- * output. A slice is still the same logical axis — just smaller — so the
797
- * label name and tags are carried forward (dimension is updated to match the
798
- * new axis size; the id is re-minted since the Index type is immutable and
799
- * dimension is part of the index identity).
800
- */
801
-
802
- interface SliceRange {
803
- /** Default 0. Supports negative indexing: -1 means shape[axis]-1. */
804
- start?: number;
805
- /** Default = shape[axis]. Supports negative indexing. */
806
- stop?: number;
807
- /** Default 1. Must be >= 1 (no reverse step). */
808
- step?: number;
809
- }
810
- /**
811
- * Extract a sub-tensor by per-axis `SliceRange` triples.
812
- *
813
- * @param t - Input tensor of any rank.
814
- * @param ranges - Array of length `t.shape.length`. Each element is either a
815
- * `SliceRange` or `null` (which means "take the entire axis").
816
- * Must have the same length as `t.shape`.
817
- * @returns A new `Tensor` whose shape[i] = ceil((stop_i - start_i) / step_i),
818
- * carrying preserved axis labels (same name/tags, updated dim).
819
- *
820
- * @throws {RangeError} If `step` is not a positive integer.
821
- * @throws {Error} If `ranges.length !== t.shape.length`.
822
- *
823
- * @example
824
- * // Extract rows 1–3 (exclusive), all columns from a 5×4 tensor:
825
- * const sub = slice(t, [{ start: 1, stop: 3 }, null]);
826
- */
827
- declare function slice(t: Tensor, ranges: (SliceRange | null)[]): Tensor;
828
-
829
- /**
830
- * gather — pull elements along one axis (NumPy `take` / JAX `gather`).
831
- *
832
- * For each index in `indices`, the output contains the corresponding "slice"
833
- * of the input tensor along `axis`. The output has the same rank as the input;
834
- * only `shape[axis]` changes to `indices.length`.
835
- *
836
- * Axis-label semantics: the gathered axis's label is **primed** (primeLevel
837
- * incremented by 1 via `Index.prime()`) so it does not auto-match the original
838
- * axis in `contract`. All other axis labels are preserved unchanged.
839
- *
840
- * The priming approach mirrors ITensors.jl's convention: after gathering, the
841
- * index is the "selected" variant of the original, not the original itself.
842
- */
843
-
844
- /**
845
- * Gather elements along `axis` using `indices`.
846
- *
847
- * @param t - Input tensor of any rank.
848
- * @param axis - The axis along which to gather. Supports negative indexing.
849
- * @param indices - The indices to gather. Duplicates are allowed.
850
- * @returns A new `Tensor` with `shape[axis] === indices.length` and all other
851
- * dimensions unchanged. The gathered-axis label is primed.
852
- *
853
- * @throws {RangeError} If any index in `indices` is outside [0, shape[axis]).
854
- * @throws {Error} If `axis` is out of range.
855
- *
856
- * @example
857
- * // Select rows 0 and 2 from a 3×4 matrix:
858
- * const rows = gather(matrix, 0, [0, 2]); // shape [2, 4]
859
- */
860
- declare function gather(t: Tensor, axis: number, indices: readonly number[]): Tensor;
861
-
862
- /**
863
- * stack — stack same-shape tensors along a new axis (NumPy `stack`).
864
- *
865
- * All input tensors must have identical shapes. A new axis is inserted at
866
- * position `axis` in the output, making the output rank = input rank + 1.
867
- * `stack([a, b], 0)` is equivalent to NumPy's `np.stack([a, b], axis=0)`.
868
- *
869
- * Axis-label semantics:
870
- * - The new axis gets `undefined` label by default (it has no correspondence
871
- * to any input axis).
872
- * - Pass `opts.newAxisLabel` (an `Index`) to label the new axis explicitly.
873
- * - The remaining axes inherit labels from `tensors[0]`. If labels disagree
874
- * across inputs for a given axis, `tensors[0]`'s label is used silently
875
- * (no error, no warning — document this choice here).
876
- * - If `tensors[0]` has no `axisLabels`, the output also carries none.
877
- */
878
-
879
- interface StackOpts {
880
- /**
881
- * Optional label for the newly created axis. If omitted, the new axis
882
- * carries no label (`axisLabels[axis] === undefined` in the output, or more
883
- * precisely: the output `axisLabels` array contains `undefined` at that
884
- * position — encoded as `null` in the array but TypeScript sees it as the
885
- * slot being absent when axisLabels is stripped to only defined entries).
886
- *
887
- * In practice: if `tensors[0].axisLabels` is defined, an `Index` for the
888
- * new axis is created either from this option or as a placeholder.
889
- */
890
- newAxisLabel?: Index;
891
- }
892
- /**
893
- * Stack same-shape tensors along a new axis.
894
- *
895
- * @param tensors - Array of tensors, all with the same shape. Must be non-empty.
896
- * @param axis - Position of the new axis in the output. Supports negative
897
- * indexing relative to the output rank. E.g. `axis=0` inserts
898
- * a new leading axis; `axis=-1` appends a new trailing axis.
899
- * @param opts - Optional `newAxisLabel` for the inserted axis.
900
- * @returns A tensor of rank `inputRank + 1` with `shape[axis] === tensors.length`.
901
- *
902
- * @throws {Error} If `tensors` is empty, or if any tensor's shape differs from
903
- * `tensors[0]`.
904
- *
905
- * @example
906
- * // Stack two row-vectors [a, b, c] and [d, e, f] → 2×3 matrix:
907
- * const matrix = stack([v1, v2], 0);
908
- */
909
- declare function stack(tensors: Tensor[], axis: number, opts?: StackOpts): Tensor;
910
-
911
- /**
912
- * concatenate — join tensors along an existing axis (NumPy `concatenate`).
913
- *
914
- * All tensors must agree on every axis except the join axis. The output rank
915
- * equals the input rank; only `shape[axis]` grows (sum of all input shapes
916
- * along that axis).
917
- *
918
- * Axis-label semantics:
919
- * - All axis labels are taken from `tensors[0]`.
920
- * - If any `tensors[i].axisLabels[axis]` disagrees with `tensors[0]`'s label
921
- * on the join axis, `tensors[0]`'s label is used silently (matching the
922
- * principle that the first tensor is authoritative for label semantics).
923
- * - If `tensors[0]` carries no `axisLabels`, the output also carries none.
924
- */
925
-
926
- /**
927
- * Concatenate tensors along an existing `axis`.
928
- *
929
- * @param tensors - Array of tensors. Must be non-empty. All must agree on every
930
- * axis except `axis`.
931
- * @param axis - The axis along which to concatenate. Supports negative indexing.
932
- * @returns A tensor with the same rank and with `shape[axis]` equal to the sum
933
- * of `tensors[i].shape[axis]`.
934
- *
935
- * @throws {Error} If `tensors` is empty, if any tensor has a different rank, or
936
- * if shapes disagree on any non-join axis.
937
- *
938
- * @example
939
- * // Vertically stack two 2×3 matrices → 4×3 matrix:
940
- * const tall = concatenate([a, b], 0);
941
- * // Horizontally stack two 2×3 matrices → 2×6 matrix:
942
- * const wide = concatenate([a, b], 1);
943
- */
944
- declare function concatenate(tensors: Tensor[], axis: number): Tensor;
945
-
946
- /**
947
- * scatter — inverse of gather. Writes `updates` into a copy of `t` at the
948
- * given `indices` along `axis` (NumPy `np.put_along_axis` / JAX `scatter`).
949
- *
950
- * For each position `i` in `indices`, the corresponding "slice" of `updates`
951
- * along `axis` is written into the matching "slice" of the output at position
952
- * `indices[i]`. All positions of `t` not referenced by `indices` are copied
953
- * unchanged.
954
- *
955
- * Duplicate-index semantics: **last-wins** — when the same index appears more
956
- * than once in `indices`, the last occurrence overwrites earlier ones. This
957
- * mirrors NumPy's default scatter behaviour. Document-level note: if
958
- * deterministic accumulation (e.g. `add`) is needed, use `ScatterOpts.reduce`.
959
- *
960
- * Axis-label semantics: the output has exactly the same shape as `t`
961
- * (scatter never changes the size of any axis), so all axis labels from `t`
962
- * are preserved unchanged.
963
- */
964
-
965
- interface ScatterOpts {
966
- /**
967
- * How to combine `updates` with existing values at the target positions.
968
- * - `'overwrite'` (default) — last-wins; target is replaced.
969
- * - `'add'` — target is incremented by the update value.
970
- */
971
- reduce?: 'overwrite' | 'add';
972
- }
973
- /**
974
- * Scatter `updates` into a copy of `t` at `indices` along `axis`.
975
- *
976
- * @param t - Destination tensor (not mutated). Any rank.
977
- * @param axis - The axis along which to scatter. Supports negative indexing.
978
- * @param indices - Target positions along `axis`. Must all be in
979
- * `[0, t.shape[axis])`. Duplicates are allowed (last-wins
980
- * by default, or add-accumulate when `opts.reduce === 'add'`).
981
- * @param updates - Source tensor. Must have the same rank as `t` with
982
- * `updates.shape[axis] === indices.length` and all other
983
- * dimensions equal to `t.shape`.
984
- * @param opts - Optional scatter options.
985
- * @returns A new `Tensor` with the same shape as `t`, with axis labels
986
- * preserved from `t`.
987
- *
988
- * @throws {Error} If `axis` is out of range, `updates` rank mismatches,
989
- * or `updates` shape is incompatible.
990
- * @throws {RangeError} If any index in `indices` is outside `[0, shape[axis])`.
991
- *
992
- * @example
993
- * // Round-trip with gather: scatter zeros back to a masked copy
994
- * const zeros = new Tensor([3, 4], new Float64Array(12));
995
- * const result = scatter(zeros, 0, [0, 2], gather(t, 0, [0, 2]));
996
- * // result[0, :] === t[0, :], result[1, :] === 0, result[2, :] === t[2, :]
997
- */
998
- declare function scatter(t: Tensor, axis: number, indices: readonly number[], updates: Tensor, opts?: ScatterOpts): Tensor;
999
-
1000
- /**
1001
- * pad — pad each axis by [before, after] amounts.
1002
- *
1003
- * Three modes are supported, mirroring NumPy's `np.pad`:
1004
- *
1005
- * - `'constant'` (default): Fill padded cells with `constantValue` (default 0).
1006
- * - `'edge'`: Repeat the boundary element along each padded slice.
1007
- * - `'reflect'`: Mirror the data across the boundary, excluding the boundary
1008
- * element itself. Requires that each padding amount is strictly
1009
- * less than the corresponding axis size.
1010
- *
1011
- * Axis-label semantics: output rank equals input rank and axis identities do
1012
- * not change (padding is just extension, not transformation). All axis labels
1013
- * from the input are preserved unchanged in the output.
1014
- */
1015
-
1016
- interface PadOptions {
1017
- /**
1018
- * Padding mode.
1019
- * - `'constant'` (default): fill with `constantValue`.
1020
- * - `'edge'`: repeat boundary element.
1021
- * - `'reflect'`: mirror across boundary, excluding boundary itself.
1022
- */
1023
- mode?: 'constant' | 'edge' | 'reflect';
1024
- /** Value used when `mode === 'constant'`. Default `0`. */
1025
- constantValue?: number;
1026
- }
1027
- /**
1028
- * Pad a tensor along each axis by specified widths.
1029
- *
1030
- * @param t - Input tensor of any rank.
1031
- * @param padWidths - Array of `[before, after]` pairs, one per axis. Length
1032
- * must equal `t.shape.length`. Each value must be >= 0.
1033
- * @param opts - Optional padding options (mode and constantValue).
1034
- * @returns A new `Tensor` with `shape[k] = t.shape[k] + before_k + after_k`
1035
- * and axis labels preserved from `t`.
1036
- *
1037
- * @throws {Error} If `padWidths.length !== t.shape.length`, any pad
1038
- * value is negative, or `mode === 'reflect'` is used
1039
- * with a pad amount >= the corresponding axis size.
1040
- *
1041
- * @example
1042
- * // Constant-pad a 3×4 tensor with 1 cell of zeros on each side:
1043
- * const padded = pad(t, [[1, 1], [1, 1]]); // shape [5, 6]
1044
- *
1045
- * // Edge-pad with asymmetric widths:
1046
- * const ep = pad(t, [[2, 0], [0, 1]], { mode: 'edge' });
1047
- */
1048
- declare function pad(t: Tensor, padWidths: readonly (readonly [number, number])[], opts?: PadOptions): Tensor;
1049
-
1050
- /**
1051
- * roll — cyclic shift along given axes.
1052
- *
1053
- * Each element is moved `shifts[k]` positions forward along `axes[k]`
1054
- * (wrapping around at the axis boundaries). Negative shifts move backward.
1055
- *
1056
- * When `axes` is omitted, `shifts` must be a single number and the tensor is
1057
- * treated as a flattened 1-D array that is shifted by that amount, then
1058
- * reshaped back to the original shape — exactly matching NumPy `np.roll(t, n)`.
1059
- *
1060
- * Implementation: for each output flat index, the corresponding input flat
1061
- * index is computed by decoding the multi-index, un-shifting each specified
1062
- * axis (with modulo wrap), then re-encoding to a flat input index.
1063
- *
1064
- * Axis-label semantics: cyclic shifting does not change the semantic identity
1065
- * of any axis (it is the same axis with reordered elements), so all axis
1066
- * labels from the input are preserved unchanged in the output.
1067
- */
1068
-
1069
- /**
1070
- * Cyclically shift a tensor along given axes.
1071
- *
1072
- * @param t - Input tensor of any rank.
1073
- * @param shifts - Number of positions to shift. A single number when `axes` is
1074
- * omitted (flat shift); an array of the same length as `axes`
1075
- * when `axes` is provided.
1076
- * @param axes - Axes to shift along. Supports negative indexing. When
1077
- * omitted, the tensor is treated as flattened and `shifts` must
1078
- * be a single number.
1079
- * @returns A new `Tensor` with the same shape as `t`, with axis labels
1080
- * preserved from `t`.
1081
- *
1082
- * @throws {Error} If `axes` is provided and `shifts` array length !== `axes`
1083
- * length, or if any axis value is out of range.
1084
- *
1085
- * @example
1086
- * // Shift a rank-1 tensor [1,2,3,4,5] by 2: → [4,5,1,2,3]
1087
- * const r = roll(t, 2, [0]);
1088
- *
1089
- * // Flat shift (no axes):
1090
- * const flat = roll(matrix, 3);
1091
- */
1092
- declare function roll(t: Tensor, shifts: number | readonly number[], axes?: readonly number[]): Tensor;
1093
-
1094
- /**
1095
- * flip — reverse element order along given axes.
1096
- *
1097
- * For each axis in `axes`, the index along that axis is reversed:
1098
- *
1099
- * out[..., i, ...] = in[..., dim - 1 - i, ...]
1100
- *
1101
- * Multiple axes can be flipped in a single pass. An empty `axes` array is
1102
- * a no-op (returns a copy of the input).
1103
- *
1104
- * Axis-label semantics: reversing the iteration order of an axis does not
1105
- * change its semantic identity — it is still the same logical axis. All axis
1106
- * labels from the input are therefore preserved unchanged in the output.
1107
- */
1108
-
1109
- /**
1110
- * Reverse element order along the specified axes.
1111
- *
1112
- * @param t - Input tensor of any rank.
1113
- * @param axes - The axes to flip. Supports negative indexing. Duplicates are
1114
- * ignored. An empty array returns a copy of `t`.
1115
- * @returns A new `Tensor` with the same shape as `t`, with axis labels
1116
- * preserved from `t`.
1117
- *
1118
- * @throws {Error} If any axis value is out of range.
1119
- *
1120
- * @example
1121
- * // Flip rows (axis 0) of a 3×4 matrix:
1122
- * const flipped = flip(matrix, [0]);
1123
- *
1124
- * // Flip both axes simultaneously:
1125
- * const rotated180 = flip(matrix, [0, 1]);
1126
- */
1127
- declare function flip(t: Tensor, axes: readonly number[]): Tensor;
1128
-
1129
- export { type ContractNetworkOpts, type ContractNetworkResult, type EinsumSpec, Index, type IndexOpts, type NestedArray, type PadOptions, type RandomTensorOpts, type ScatterOpts, type SliceRange, type StackOpts, Tensor, type TensorCholeskyOpts, type TensorCholeskyResult, type TensorEigOpts, type TensorEigResult, type TensorKronOpts, type TensorLUOpts, type TensorLUResult, type TensorPinvOpts, type TensorQrOpts, type TensorQrResult, type TensorSolveOpts, type TensorSolveResult, type TensorSvdOpts, type TensorSvdResult, concatenate, contractNetwork, flip, gather, idx, pad, randomTensor, roll, scatter, slice, stack, tensorCholesky, tensorEig, tensorEigWasm, tensorKron, tensorLU, tensorPinv, tensorQr, tensorSolve, tensorSvd, tensorSvdWasm };
1
+ export { Tensor } from './Tensor';
2
+ export type { NestedArray, EinsumSpec } from './Tensor';
3
+ export { Index, idx } from './named-index';
4
+ export type { IndexOpts } from './named-index';
5
+ export { tensorSvd, tensorSvdWasm } from './operations/svd';
6
+ export type { TensorSvdOpts, TensorSvdResult } from './operations/svd';
7
+ export { randomTensor } from './operations/random';
8
+ export type { RandomTensorOpts } from './operations/random';
9
+ export { contractNetwork } from './contraction-sequence';
10
+ export type { ContractNetworkOpts, ContractNetworkResult } from './contraction-sequence';
11
+ export { tensorQr } from './operations/qr';
12
+ export type { TensorQrOpts, TensorQrResult } from './operations/qr';
13
+ export { tensorLU } from './operations/lu';
14
+ export type { TensorLUOpts, TensorLUResult } from './operations/lu';
15
+ export { tensorCholesky } from './operations/cholesky';
16
+ export type { TensorCholeskyOpts, TensorCholeskyResult } from './operations/cholesky';
17
+ export { tensorEig, tensorEigWasm } from './operations/eig';
18
+ export type { TensorEigOpts, TensorEigResult } from './operations/eig';
19
+ export { tensorPinv } from './operations/pinv';
20
+ export type { TensorPinvOpts } from './operations/pinv';
21
+ export { tensorSolve } from './operations/solve';
22
+ export type { TensorSolveOpts, TensorSolveResult } from './operations/solve';
23
+ export { tensorKron } from './operations/kron';
24
+ export type { TensorKronOpts } from './operations/kron';
25
+ export { slice } from './operations/slice';
26
+ export type { SliceRange } from './operations/slice';
27
+ export { gather } from './operations/gather';
28
+ export { stack } from './operations/stack';
29
+ export type { StackOpts } from './operations/stack';
30
+ export { concatenate } from './operations/concatenate';
31
+ export { scatter } from './operations/scatter';
32
+ export type { ScatterOpts } from './operations/scatter';
33
+ export { pad } from './operations/pad';
34
+ export type { PadOptions } from './operations/pad';
35
+ export { roll } from './operations/roll';
36
+ export { flip } from './operations/flip';
37
+ //# sourceMappingURL=index.d.ts.map