@danielsimonjr/mathts-tensor 0.2.25 → 0.2.27

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 CHANGED
@@ -13,8 +13,10 @@ npm install @danielsimonjr/mathts-tensor
13
13
  ## What it provides
14
14
 
15
15
  - `Tensor` construction from nested arrays / flat data + shape.
16
- - Elementwise ops, reshaping, broadcasting, reductions, and contraction.
17
- - The substrate for `@danielsimonjr/mathts-autograd`.
16
+ - Elementwise ops, reshaping, broadcasting, reductions, contraction, and `matMul`
17
+ (routes through `backendManager.multiply` for WASM GEMM when gated).
18
+ - Tensor decompositions and `tensorSvdWasm` / `tensorEigWasm` (async JS delegates).
19
+ - Substrate for `@danielsimonjr/mathts-autograd` (`randomTensor` uses Mulberry32).
18
20
 
19
21
  ## License
20
22
 
package/dist/Tensor.d.ts CHANGED
@@ -46,6 +46,7 @@ export declare class Tensor {
46
46
  readonly axisLabels?: ReadonlyArray<Index>;
47
47
  constructor(shape: ReadonlyArray<number>, data: Float64Array, axisLabels?: ReadonlyArray<Index>);
48
48
  static sizeOf(shape: ReadonlyArray<number>): number;
49
+ /** Row-major stride vector; forwards to `rowMajorStrides` in `@danielsimonjr/mathts-core`. */
49
50
  static rowMajorStrides(shape: ReadonlyArray<number>): number[];
50
51
  static fromNested(data: NestedArray, shape: ReadonlyArray<number>): Tensor;
51
52
  static identity(n: number): Tensor;
@@ -114,6 +115,11 @@ export declare class Tensor {
114
115
  min(axis?: number | ReadonlyArray<number>, opts?: {
115
116
  keepDims?: boolean;
116
117
  }): Tensor;
118
+ /**
119
+ * Shared max/min reduction: NaN in the window wins; NaN accumulator is kept.
120
+ * `pick` is monomorphic within one call (`Math.max` or `Math.min`).
121
+ */
122
+ private extremum;
117
123
  /**
118
124
  * Product of elements along the given axis/axes (or all axes if omitted).
119
125
  */
@@ -170,6 +176,10 @@ export declare class Tensor {
170
176
  * Throws if `oldIndex` is not found.
171
177
  */
172
178
  replaceIndex(oldIndex: Index, newIndex: Index): Tensor;
179
+ /**
180
+ * Resolve a labelled index to its axis position; error prefix matches the caller.
181
+ */
182
+ private axisPosition;
173
183
  /**
174
184
  * Contract this tensor with `other` over every shared index (matched by
175
185
  * `Index.matches`). Both operands must carry `axisLabels`.
@@ -1 +1 @@
1
- {"version":3,"file":"Tensor.d.ts","sourceRoot":"","sources":["../src/Tensor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Tensor.d.ts","sourceRoot":"","sources":["../src/Tensor.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { boxMuller, mulberry32, rowMajorStrides } from "@danielsimonjr/mathts-core";
1
2
  import { DenseMatrix, backendManager, cholesky, eig, eigWasm, lu, qr, svd, svdWasm } from "@danielsimonjr/mathts-matrix";
2
3
  //#region src/Tensor.ts
3
4
  var Tensor = class Tensor {
@@ -15,13 +16,7 @@ var Tensor = class Tensor {
15
16
  return shape.reduce((a, b) => a * b, 1);
16
17
  }
17
18
  static rowMajorStrides(shape) {
18
- const strides = new Array(shape.length);
19
- let acc = 1;
20
- for (let k = shape.length - 1; k >= 0; k--) {
21
- strides[k] = acc;
22
- acc *= shape[k];
23
- }
24
- return strides;
19
+ return rowMajorStrides(shape);
25
20
  }
26
21
  static fromNested(data, shape) {
27
22
  const size = Tensor.sizeOf(shape);
@@ -212,14 +207,15 @@ var Tensor = class Tensor {
212
207
  return this.reduceAxes(axes, keepDims, 0, (acc, v) => acc + v, (acc, count) => acc / count);
213
208
  }
214
209
  max(axis, opts) {
215
- const axes = this.resolveAxes(axis);
216
- const keepDims = opts?.keepDims ?? false;
217
- return this.reduceAxes(axes, keepDims, -Infinity, (acc, v) => isNaN(v) ? v : isNaN(acc) ? acc : Math.max(acc, v));
210
+ return this.extremum(axis, opts, -Infinity, Math.max);
218
211
  }
219
212
  min(axis, opts) {
213
+ return this.extremum(axis, opts, Infinity, Math.min);
214
+ }
215
+ extremum(axis, opts, init, pick) {
220
216
  const axes = this.resolveAxes(axis);
221
217
  const keepDims = opts?.keepDims ?? false;
222
- return this.reduceAxes(axes, keepDims, Infinity, (acc, v) => isNaN(v) ? v : isNaN(acc) ? acc : Math.min(acc, v));
218
+ return this.reduceAxes(axes, keepDims, init, (acc, v) => isNaN(v) ? v : isNaN(acc) ? acc : pick(acc, v));
223
219
  }
224
220
  prod(axis, opts) {
225
221
  const axes = this.resolveAxes(axis);
@@ -385,19 +381,20 @@ var Tensor = class Tensor {
385
381
  return new Tensor(freeSizes, out);
386
382
  }
387
383
  axisOf(index) {
388
- if (this.axisLabels === void 0) throw new Error("Tensor.axisOf: this tensor has no axisLabels");
389
- const pos = this.axisLabels.findIndex((lbl) => lbl.matches(index));
390
- if (pos === -1) throw new Error(`Tensor.axisOf: index ${index.toString()} not found in axisLabels`);
391
- return pos;
384
+ return this.axisPosition(index, "axisOf");
392
385
  }
393
386
  replaceIndex(oldIndex, newIndex) {
394
- if (this.axisLabels === void 0) throw new Error("Tensor.replaceIndex: this tensor has no axisLabels");
395
- const pos = this.axisLabels.findIndex((lbl) => lbl.matches(oldIndex));
396
- if (pos === -1) throw new Error(`Tensor.replaceIndex: index ${oldIndex.toString()} not found in axisLabels`);
387
+ const pos = this.axisPosition(oldIndex, "replaceIndex");
397
388
  const newLabels = [...this.axisLabels];
398
389
  newLabels[pos] = newIndex;
399
390
  return new Tensor([...this.shape], this.data.slice(), newLabels);
400
391
  }
392
+ axisPosition(index, op) {
393
+ if (this.axisLabels === void 0) throw new Error(`Tensor.${op}: this tensor has no axisLabels`);
394
+ const pos = this.axisLabels.findIndex((lbl) => lbl.matches(index));
395
+ if (pos === -1) throw new Error(`Tensor.${op}: index ${index.toString()} not found in axisLabels`);
396
+ return pos;
397
+ }
401
398
  contract(other) {
402
399
  if (this.axisLabels === void 0 || other.axisLabels === void 0) throw new Error("Tensor.contract requires axisLabels on both operands");
403
400
  const sharedPairs = [];
@@ -508,23 +505,40 @@ function idx(dim, name, opts) {
508
505
  });
509
506
  }
510
507
  //#endregion
511
- //#region src/operations/svd.ts
512
- function prepareSvdMatrix(t, rowAxes) {
508
+ //#region src/operations/reshape-axes.ts
509
+ function reshapeByRowAxes(t, rowAxes, messages) {
513
510
  const rank = t.shape.length;
514
- for (const ax of rowAxes) if (!Number.isInteger(ax) || ax < 0 || ax >= rank) throw new RangeError(`tensorSvd: rowAxes contains invalid axis ${ax} for tensor of rank ${rank}`);
511
+ for (const ax of rowAxes) if (!Number.isInteger(ax) || ax < 0 || ax >= rank) throw new RangeError(messages.badAxis(ax, rank));
515
512
  const rowSet = new Set(rowAxes);
516
513
  const colAxes = [];
517
514
  for (let i = 0; i < rank; i++) if (!rowSet.has(i)) colAxes.push(i);
518
- if (colAxes.length === 0) throw new Error("tensorSvd: rowAxes covers all axes — at least one axis must remain for V");
519
- if (rowAxes.length === 0) throw new Error("tensorSvd: rowAxes is empty — at least one axis must be assigned to U");
520
- const perm = [...rowAxes, ...colAxes];
521
- const permuted = t.transpose(perm);
515
+ if (colAxes.length === 0) throw new Error(messages.noColAxis);
516
+ if (rowAxes.length === 0) throw new Error(messages.noRowAxis);
522
517
  const rowDims = rowAxes.map((ax) => t.shape[ax]);
523
518
  const colDims = colAxes.map((ax) => t.shape[ax]);
524
519
  const numRows = rowDims.reduce((a, b) => a * b, 1);
525
520
  const numCols = colDims.reduce((a, b) => a * b, 1);
521
+ const perm = [...rowAxes, ...colAxes];
522
+ const permuted = t.transpose(perm);
523
+ return {
524
+ permuted,
525
+ rowDims,
526
+ colDims,
527
+ numRows,
528
+ numCols,
529
+ matrix: Array.from({ length: numRows }, (_, i) => Array.from({ length: numCols }, (_, j) => permuted.data[i * numCols + j]))
530
+ };
531
+ }
532
+ //#endregion
533
+ //#region src/operations/svd.ts
534
+ function prepareSvdMatrix(t, rowAxes) {
535
+ const { matrix, rowDims, colDims, numRows, numCols } = reshapeByRowAxes(t, rowAxes, {
536
+ badAxis: (ax, rank) => `tensorSvd: rowAxes contains invalid axis ${ax} for tensor of rank ${rank}`,
537
+ noColAxis: "tensorSvd: rowAxes covers all axes — at least one axis must remain for V",
538
+ noRowAxis: "tensorSvd: rowAxes is empty — at least one axis must be assigned to U"
539
+ });
526
540
  return {
527
- matrix: Array.from({ length: numRows }, (_, i) => Array.from({ length: numCols }, (_, j) => permuted.data[i * numCols + j])),
541
+ matrix,
528
542
  rowDims,
529
543
  colDims,
530
544
  numRows,
@@ -568,22 +582,6 @@ async function tensorSvdWasm(t, rowAxes, opts) {
568
582
  }
569
583
  //#endregion
570
584
  //#region src/operations/random.ts
571
- function makeMulberry32(seed) {
572
- let s = seed | 0;
573
- return () => {
574
- s = s + 1831565813 | 0;
575
- let z = s;
576
- z = Math.imul(z ^ z >>> 15, z | 1);
577
- z ^= z + Math.imul(z ^ z >>> 7, z | 61);
578
- z = (z ^ z >>> 14) >>> 0;
579
- return z / 4294967296;
580
- };
581
- }
582
- function boxMuller(u1, u2) {
583
- const r = Math.sqrt(-2 * Math.log(u1 === 0 ? Number.EPSILON : u1));
584
- const theta = 2 * Math.PI * u2;
585
- return [r * Math.cos(theta), r * Math.sin(theta)];
586
- }
587
585
  function thinQViaMatrixQr(data, rows, cols) {
588
586
  const matA = new DenseMatrix(rows, cols, data);
589
587
  const { Q: matQ } = qr(matA, { mode: "reduced" });
@@ -593,7 +591,7 @@ function randomTensor(shape, opts) {
593
591
  const distribution = opts?.distribution ?? "uniform";
594
592
  const axisLabels = opts?.axisLabels;
595
593
  const size = shape.reduce((acc, d) => acc * d, 1);
596
- const rng = opts?.seed !== void 0 ? makeMulberry32(opts.seed) : () => Math.random();
594
+ const rng = opts?.seed !== void 0 ? mulberry32(opts.seed) : () => Math.random();
597
595
  if (distribution === "orthogonal") {
598
596
  if (shape.length !== 2) throw new Error("randomTensor: 'orthogonal' distribution requires a rank-2 shape");
599
597
  const [rows, cols] = shape;
@@ -1256,21 +1254,15 @@ function tensorCholesky(t, rowAxes, opts) {
1256
1254
  function prepareEigMatrix(t, rowAxes, symmetricHint) {
1257
1255
  const rank = t.shape.length;
1258
1256
  for (const ax of rowAxes) if (!Number.isInteger(ax) || ax < 0 || ax >= rank) throw new RangeError(`tensorEig: rowAxes contains invalid axis ${ax} for tensor of rank ${rank}`);
1259
- const rowSet = new Set(rowAxes);
1260
- if (rowSet.size !== rowAxes.length) throw new Error("tensorEig: rowAxes contains duplicate axes");
1261
- const colAxes = [];
1262
- for (let i = 0; i < rank; i++) if (!rowSet.has(i)) colAxes.push(i);
1263
- if (colAxes.length === 0) throw new Error("tensorEig: rowAxes covers all axes — at least one axis must remain");
1264
- if (rowAxes.length === 0) throw new Error("tensorEig: rowAxes is empty — at least one axis must be assigned");
1265
- const rowDims = rowAxes.map((ax) => t.shape[ax]);
1266
- const colDims = colAxes.map((ax) => t.shape[ax]);
1267
- const numRows = rowDims.reduce((a, b) => a * b, 1);
1268
- const numCols = colDims.reduce((a, b) => a * b, 1);
1257
+ if (new Set(rowAxes).size !== rowAxes.length) throw new Error("tensorEig: rowAxes contains duplicate axes");
1258
+ const { numRows, numCols, matrix } = reshapeByRowAxes(t, rowAxes, {
1259
+ badAxis: (ax, rank) => `tensorEig: rowAxes contains invalid axis ${ax} for tensor of rank ${rank}`,
1260
+ noColAxis: "tensorEig: rowAxes covers all axes — at least one axis must remain",
1261
+ noRowAxis: "tensorEig: rowAxes is empty — at least one axis must be assigned"
1262
+ });
1269
1263
  if (numRows !== numCols) throw new Error(`tensorEig: reshaped matrix must be square (got ${numRows}×${numCols})`);
1270
- const perm = [...rowAxes, ...colAxes];
1271
- const permuted = t.transpose(perm);
1272
1264
  const n = numRows;
1273
- const matrix2D = Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => permuted.data[i * n + j]));
1265
+ const matrix2D = matrix;
1274
1266
  if (symmetricHint) for (let i = 0; i < n; i++) for (let j = i + 1; j < n; j++) {
1275
1267
  const avg = (matrix2D[i][j] + matrix2D[j][i]) / 2;
1276
1268
  matrix2D[i][j] = avg;
@@ -1 +1 @@
1
- {"version":3,"file":"eig.d.ts","sourceRoot":"","sources":["../../src/operations/eig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAItC,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,uFAAuF;AACvF,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAuHD;;GAEG;AACH,wBAAgB,SAAS,CACvB,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,eAAe,CAKjB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,OAAO,CAAC,eAAe,CAAC,CAK1B"}
1
+ {"version":3,"file":"eig.d.ts","sourceRoot":"","sources":["../../src/operations/eig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAKtC,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,uFAAuF;AACvF,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AA0GD;;GAEG;AACH,wBAAgB,SAAS,CACvB,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,eAAe,CAKjB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,OAAO,CAAC,eAAe,CAAC,CAK1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../../src/operations/random.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAO1C,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;IAEnD;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;CACnC;AAqED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAuE1F"}
1
+ {"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../../src/operations/random.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAO1C,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;IAEnD;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;CACnC;AA6BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAsE1F"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shared axis validation and 2-D matricisation for tensor eig / SVD prep.
3
+ * Callers supply error strings so observable messages stay function-specific.
4
+ */
5
+ import { Tensor } from '../Tensor.js';
6
+ /** Message templates for row-axis validation and reshape (per public entry point). */
7
+ export interface ReshapeByRowAxesMessages {
8
+ badAxis: (ax: number, rank: number) => string;
9
+ noColAxis: string;
10
+ noRowAxis: string;
11
+ }
12
+ /** Result of permuting row/col axes into a dense 2-D matrix view. */
13
+ export interface ReshapeByRowAxesResult {
14
+ permuted: Tensor;
15
+ rowDims: number[];
16
+ colDims: number[];
17
+ numRows: number;
18
+ numCols: number;
19
+ matrix: number[][];
20
+ }
21
+ /**
22
+ * Validate `rowAxes`, build the complementary column axes, permute `t`, and
23
+ * reshape to a row-major `number[][]` matrix. Does not enforce square shape
24
+ * or duplicate row axes (callers add those checks when needed).
25
+ */
26
+ export declare function reshapeByRowAxes(t: Tensor, rowAxes: ReadonlyArray<number>, messages: ReshapeByRowAxesMessages): ReshapeByRowAxesResult;
27
+ //# sourceMappingURL=reshape-axes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reshape-axes.d.ts","sourceRoot":"","sources":["../../src/operations/reshape-axes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,sFAAsF;AACtF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,QAAQ,EAAE,wBAAwB,GACjC,sBAAsB,CAmCxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"svd.d.ts","sourceRoot":"","sources":["../../src/operations/svd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAItC,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,iFAAiF;AACjF,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC;IACV,uDAAuD;IACvD,CAAC,EAAE,MAAM,CAAC;IACV,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC;IACV,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,oGAAoG;IACpG,eAAe,EAAE,MAAM,CAAC;CACzB;AAwHD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CACvB,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,eAAe,CAGjB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,OAAO,CAAC,eAAe,CAAC,CAG1B"}
1
+ {"version":3,"file":"svd.d.ts","sourceRoot":"","sources":["../../src/operations/svd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAKtC,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,iFAAiF;AACjF,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC;IACV,uDAAuD;IACvD,CAAC,EAAE,MAAM,CAAC;IACV,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC;IACV,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,oGAAoG;IACpG,eAAe,EAAE,MAAM,CAAC;CACzB;AA4FD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CACvB,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,eAAe,CAGjB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,IAAI,CAAC,EAAE,aAAa,GACnB,OAAO,CAAC,eAAe,CAAC,CAG1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danielsimonjr/mathts-tensor",
3
- "version": "0.2.25",
3
+ "version": "0.2.27",
4
4
  "description": "Rank-N dense Tensor type for MathTS with Float64Array-backed storage",
5
5
  "author": "Daniel Simon Jr.",
6
6
  "license": "MIT",
@@ -42,8 +42,8 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@danielsimonjr/mathts-core": "^0.19.0",
46
- "@danielsimonjr/mathts-matrix": "^0.7.9"
45
+ "@danielsimonjr/mathts-core": "^0.21.0",
46
+ "@danielsimonjr/mathts-matrix": "^0.8.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^26.4.0",