@danielsimonjr/mathts-matrix 0.7.9 → 0.8.1

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 (46) hide show
  1. package/README.md +51 -14
  2. package/dist/backends/BackendManager.d.ts +1 -1
  3. package/dist/backends/BackendManager.d.ts.map +1 -1
  4. package/dist/backends/GPUBackend.d.ts.map +1 -1
  5. package/dist/backends/GPUMatrixBackend.d.ts.map +1 -1
  6. package/dist/backends/JSBackend.d.ts.map +1 -1
  7. package/dist/backends/ParallelBackend.d.ts +10 -0
  8. package/dist/backends/ParallelBackend.d.ts.map +1 -1
  9. package/dist/backends/WASMBackend.d.ts.map +1 -1
  10. package/dist/backends/gpu/gpu-or-js.d.ts +5 -0
  11. package/dist/backends/gpu/gpu-or-js.d.ts.map +1 -0
  12. package/dist/backends/gpu/run-shader.d.ts +37 -0
  13. package/dist/backends/gpu/run-shader.d.ts.map +1 -0
  14. package/dist/backends/wasm/as-typed-array.d.ts +37 -0
  15. package/dist/backends/wasm/as-typed-array.d.ts.map +1 -0
  16. package/dist/backends/wasm/index.d.ts +0 -2
  17. package/dist/backends/wasm/index.d.ts.map +1 -1
  18. package/dist/config.d.ts +1 -1
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/index.js +621 -1047
  21. package/dist/operations/common.d.ts +79 -2
  22. package/dist/operations/common.d.ts.map +1 -1
  23. package/dist/operations/expm.d.ts.map +1 -1
  24. package/dist/operations/givens.d.ts +22 -0
  25. package/dist/operations/givens.d.ts.map +1 -0
  26. package/dist/operations/index.d.ts +1 -0
  27. package/dist/operations/index.d.ts.map +1 -1
  28. package/dist/operations/logm.d.ts.map +1 -1
  29. package/dist/operations/qr-family.d.ts +2 -0
  30. package/dist/operations/qr-family.d.ts.map +1 -1
  31. package/dist/operations/schur.d.ts.map +1 -1
  32. package/dist/operations/sqrtm.d.ts.map +1 -1
  33. package/dist/operations/svd.d.ts.map +1 -1
  34. package/dist/parallel-matrix.d.ts.map +1 -1
  35. package/dist/types/DenseMatrix.d.ts +7 -0
  36. package/dist/types/DenseMatrix.d.ts.map +1 -1
  37. package/dist/types/SparseMatrix.d.ts +3 -0
  38. package/dist/types/SparseMatrix.d.ts.map +1 -1
  39. package/dist/types/dense/arithmetic.d.ts.map +1 -1
  40. package/dist/wasm/mathts-as.wasm +0 -0
  41. package/dist/wasm/wasm-manifest.json +1 -1
  42. package/package.json +3 -3
  43. package/dist/backends/WasmLoader.d.ts +0 -356
  44. package/dist/backends/WasmLoader.d.ts.map +0 -1
  45. package/dist/backends/wasm/fft-wasm.d.ts +0 -120
  46. package/dist/backends/wasm/fft-wasm.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { BufferPool, BufferPool as BufferPool$1, GPUContext, GPUContext as GPUContext$1, GPU_MIN_ELEMENTS, ShaderManager, ShaderManager as ShaderManager$1, destroyGlobalGPU, detectGPUCapabilities, detectGPUCapabilities as detectGPUCapabilities$1, getGlobalGPUContext, getGlobalGPUContext as getGlobalGPUContext$1, getRecommendedWorkgroupSize, getRecommendedWorkgroupSize as getRecommendedWorkgroupSize$1, hasWebGPU, hasWebGPU as hasWebGPU$1 } from "@danielsimonjr/mathts-gpu";
2
2
  import { ComputePool, computePool } from "@danielsimonjr/mathts-parallel";
3
+ import { allocAsHeader } from "@danielsimonjr/mathts-core/internal";
3
4
  import { mathTyped } from "@danielsimonjr/mathts-core";
4
5
  //#region \0rolldown/runtime.js
5
6
  var __defProp = Object.defineProperty;
@@ -136,8 +137,14 @@ function multiply$1(a, b) {
136
137
  const ri = i * m;
137
138
  for (let k = 0; k < p; k++) {
138
139
  const aik = ad[ai + k];
139
- if (aik === 0) continue;
140
140
  const bk = k * m;
141
+ if (aik === 0) {
142
+ for (let j = 0; j < m; j++) {
143
+ const bij = bd[bk + j];
144
+ if (bij !== 0 && !Number.isFinite(bij)) result[ri + j] += aik * bij;
145
+ }
146
+ continue;
147
+ }
141
148
  for (let j = 0; j < m; j++) result[ri + j] += aik * bd[bk + j];
142
149
  }
143
150
  }
@@ -680,6 +687,11 @@ var init_SparseMatrix = __esmMin((() => {
680
687
  function isDenseMatrix(value) {
681
688
  return value instanceof DenseMatrix;
682
689
  }
690
+ function denseContiguousData(matrix) {
691
+ const m = matrix;
692
+ if (!m.isView && m.offset === 0 && m.rowStride === m.cols) return m.data;
693
+ return m.toFlatFloat64Array();
694
+ }
683
695
  var DenseMatrix;
684
696
  var init_DenseMatrix = __esmMin((() => {
685
697
  init_Matrix();
@@ -976,6 +988,7 @@ const backendRegistry = new BackendRegistry();
976
988
  //#endregion
977
989
  //#region src/backends/JSBackend.ts
978
990
  init_DenseMatrix();
991
+ init_reduction();
979
992
  var JSBackend = class {
980
993
  type = "js";
981
994
  isAvailable() {
@@ -1024,10 +1037,17 @@ var JSBackend = class {
1024
1037
  const m = a.rows;
1025
1038
  const n = b.cols;
1026
1039
  const k = a.cols;
1040
+ const ad = denseContiguousData(a);
1041
+ const bd = denseContiguousData(b);
1027
1042
  const result = new Float64Array(m * n);
1028
- for (let i = 0; i < m; i++) for (let p = 0; p < k; p++) {
1029
- const aip = a.get(i, p);
1030
- for (let j = 0; j < n; j++) result[i * n + j] += aip * b.get(p, j);
1043
+ for (let i = 0; i < m; i++) {
1044
+ const ai = i * k;
1045
+ const ri = i * n;
1046
+ for (let p = 0; p < k; p++) {
1047
+ const aip = ad[ai + p];
1048
+ const bp = p * n;
1049
+ for (let j = 0; j < n; j++) result[ri + j] += aip * bd[bp + j];
1050
+ }
1031
1051
  }
1032
1052
  return new DenseMatrix(m, n, result);
1033
1053
  }
@@ -1053,12 +1073,7 @@ var JSBackend = class {
1053
1073
  }
1054
1074
  }
1055
1075
  norm(a) {
1056
- let sumSq = 0;
1057
- for (let i = 0; i < a.rows; i++) for (let j = 0; j < a.cols; j++) {
1058
- const val = a.get(i, j);
1059
- sumSq += val * val;
1060
- }
1061
- return Math.sqrt(sumSq);
1076
+ return norm$1(a);
1062
1077
  }
1063
1078
  dot(a, b) {
1064
1079
  if (!a.isVector || !b.isVector) throw new Error("Dot product requires two vectors");
@@ -1105,51 +1120,24 @@ var ParallelBackend = class {
1105
1120
  return elementCount >= this.parallelThreshold;
1106
1121
  }
1107
1122
  async add(a, b) {
1108
- this.checkDimensionsMatch(a, b);
1109
- const elementCount = a.rows * a.cols;
1110
- if (!this.shouldParallelize(elementCount) || !this.isReady()) return a.add(b);
1111
- const aData = a.toFloat64Array();
1112
- const bData = b.toFloat64Array();
1113
- const result = await this.pool.elementwise(aData, bData, "add");
1114
- return new DenseMatrix(a.rows, a.cols, result.result);
1123
+ return this.parallelBinary(a, b, "add", (x, y) => x.add(y));
1115
1124
  }
1116
1125
  async subtract(a, b) {
1117
- this.checkDimensionsMatch(a, b);
1118
- const elementCount = a.rows * a.cols;
1119
- if (!this.shouldParallelize(elementCount) || !this.isReady()) return a.subtract(b);
1120
- const aData = a.toFloat64Array();
1121
- const bData = b.toFloat64Array();
1122
- const result = await this.pool.elementwise(aData, bData, "subtract");
1123
- return new DenseMatrix(a.rows, a.cols, result.result);
1126
+ return this.parallelBinary(a, b, "subtract", (x, y) => x.subtract(y));
1124
1127
  }
1125
1128
  async multiplyElementwise(a, b) {
1126
- this.checkDimensionsMatch(a, b);
1127
- const elementCount = a.rows * a.cols;
1128
- if (!this.shouldParallelize(elementCount) || !this.isReady()) return a.multiplyElementwise(b);
1129
- const aData = a.toFloat64Array();
1130
- const bData = b.toFloat64Array();
1131
- const result = await this.pool.elementwise(aData, bData, "multiply");
1132
- return new DenseMatrix(a.rows, a.cols, result.result);
1129
+ return this.parallelBinary(a, b, "multiply", (x, y) => x.multiplyElementwise(y));
1133
1130
  }
1134
1131
  async divideElementwise(a, b) {
1135
- this.checkDimensionsMatch(a, b);
1136
- const elementCount = a.rows * a.cols;
1137
- if (!this.shouldParallelize(elementCount) || !this.isReady()) {
1138
- const result = new Float64Array(a.rows * a.cols);
1139
- for (let i = 0; i < a.rows; i++) for (let j = 0; j < a.cols; j++) result[i * a.cols + j] = a.get(i, j) / b.get(i, j);
1140
- return new DenseMatrix(a.rows, a.cols, result);
1141
- }
1142
- const aData = a.toFloat64Array();
1143
- const bData = b.toFloat64Array();
1144
- const result = await this.pool.elementwise(aData, bData, "divide");
1145
- return new DenseMatrix(a.rows, a.cols, result.result);
1132
+ return this.parallelBinary(a, b, "divide", (x, y) => jsBackend.divideElementwise(x, y));
1146
1133
  }
1147
1134
  async scale(a, scalar) {
1148
1135
  const elementCount = a.rows * a.cols;
1149
- if (!this.shouldParallelize(elementCount) || !this.isReady()) return a.scale(scalar);
1150
- const aData = a.toFloat64Array();
1151
- const result = await this.pool.scale(aData, scalar);
1152
- return new DenseMatrix(a.rows, a.cols, result.result);
1136
+ return this.whenParallel(elementCount, () => a.scale(scalar), async () => {
1137
+ const aData = a.toFloat64Array();
1138
+ const result = await this.pool.scale(aData, scalar);
1139
+ return new DenseMatrix(a.rows, a.cols, result.result);
1140
+ });
1153
1141
  }
1154
1142
  abs(a) {
1155
1143
  return a.map((v) => Math.abs(v));
@@ -1160,35 +1148,30 @@ var ParallelBackend = class {
1160
1148
  async multiply(a, b) {
1161
1149
  this.checkMultiplyDimensions(a, b);
1162
1150
  const resultSize = a.rows * b.cols;
1163
- if (!this.shouldParallelize(resultSize) || !this.isReady()) return a.multiply(b);
1164
- const aData = a.toFloat64Array();
1165
- const bData = b.toFloat64Array();
1166
- const result = await this.pool.matmul(aData, a.rows, a.cols, bData, b.cols);
1167
- return new DenseMatrix(a.rows, b.cols, result.result);
1151
+ return this.whenParallel(resultSize, () => a.multiply(b), async () => {
1152
+ const aData = a.toFloat64Array();
1153
+ const bData = b.toFloat64Array();
1154
+ const result = await this.pool.matmul(aData, a.rows, a.cols, bData, b.cols);
1155
+ return new DenseMatrix(a.rows, b.cols, result.result);
1156
+ });
1168
1157
  }
1169
1158
  async transpose(a) {
1170
1159
  const elementCount = a.rows * a.cols;
1171
- if (!this.shouldParallelize(elementCount) || !this.isReady()) return a.transpose();
1172
- const aData = a.toFloat64Array();
1173
- const result = await this.pool.transpose(aData, a.rows, a.cols);
1174
- return new DenseMatrix(a.cols, a.rows, result.result);
1160
+ return this.whenParallel(elementCount, () => a.transpose(), async () => {
1161
+ const aData = a.toFloat64Array();
1162
+ const result = await this.pool.transpose(aData, a.rows, a.cols);
1163
+ return new DenseMatrix(a.cols, a.rows, result.result);
1164
+ });
1175
1165
  }
1176
1166
  async sum(a) {
1177
1167
  const elementCount = a.rows * a.cols;
1178
- if (!this.shouldParallelize(elementCount) || !this.isReady()) return a.sum();
1179
- const aData = a.toFloat64Array();
1180
- return (await this.pool.sum(aData)).result;
1168
+ return this.whenParallel(elementCount, () => a.sum(), async () => {
1169
+ const aData = a.toFloat64Array();
1170
+ return (await this.pool.sum(aData)).result;
1171
+ });
1181
1172
  }
1182
1173
  sumAxis(a, axis) {
1183
- if (axis === 0) {
1184
- const result = new Float64Array(a.cols);
1185
- for (let j = 0; j < a.cols; j++) for (let i = 0; i < a.rows; i++) result[j] += a.get(i, j);
1186
- return new DenseMatrix(1, a.cols, result);
1187
- } else {
1188
- const result = new Float64Array(a.rows);
1189
- for (let i = 0; i < a.rows; i++) for (let j = 0; j < a.cols; j++) result[i] += a.get(i, j);
1190
- return new DenseMatrix(a.rows, 1, result);
1191
- }
1174
+ return jsBackend.sumAxis(a, axis);
1192
1175
  }
1193
1176
  norm(a) {
1194
1177
  return a.norm();
@@ -1197,16 +1180,11 @@ var ParallelBackend = class {
1197
1180
  if (!a.isVector || !b.isVector) throw new Error("Dot product requires two vectors");
1198
1181
  if (a.length !== b.length) throw new Error(`Vector lengths must match: ${a.length} vs ${b.length}`);
1199
1182
  const elementCount = a.length;
1200
- if (!this.shouldParallelize(elementCount) || !this.isReady()) {
1201
- let sum = 0;
1202
- const aValues = Array.from(a.values());
1203
- const bValues = Array.from(b.values());
1204
- for (let i = 0; i < aValues.length; i++) sum += aValues[i] * bValues[i];
1205
- return sum;
1206
- }
1207
- const aData = a.toFloat64Array();
1208
- const bData = b.toFloat64Array();
1209
- return (await this.pool.dot(aData, bData)).result;
1183
+ return this.whenParallel(elementCount, () => jsBackend.dot(a, b), async () => {
1184
+ const aData = a.toFloat64Array();
1185
+ const bData = b.toFloat64Array();
1186
+ return (await this.pool.dot(aData, bData)).result;
1187
+ });
1210
1188
  }
1211
1189
  async terminate() {
1212
1190
  if (this.initialized) {
@@ -1217,6 +1195,19 @@ var ParallelBackend = class {
1217
1195
  getStats() {
1218
1196
  return this.pool.stats();
1219
1197
  }
1198
+ whenParallel(elementCount, sequential, parallel) {
1199
+ if (!this.shouldParallelize(elementCount) || !this.isReady()) return sequential();
1200
+ return parallel();
1201
+ }
1202
+ async parallelBinary(a, b, op, sequential) {
1203
+ this.checkDimensionsMatch(a, b);
1204
+ const elementCount = a.rows * a.cols;
1205
+ if (!this.shouldParallelize(elementCount) || !this.isReady()) return sequential(a, b);
1206
+ const aData = a.toFloat64Array();
1207
+ const bData = b.toFloat64Array();
1208
+ const result = await this.pool.elementwise(aData, bData, op);
1209
+ return new DenseMatrix(a.rows, a.cols, result.result);
1210
+ }
1220
1211
  checkDimensionsMatch(a, b) {
1221
1212
  if (a.rows !== b.rows || a.cols !== b.cols) throw new Error(`Matrix dimensions must match: ${a.rows}×${a.cols} vs ${b.rows}×${b.cols}`);
1222
1213
  }
@@ -1489,14 +1480,20 @@ function getCachedFeatures() {
1489
1480
  return cachedFeatures;
1490
1481
  }
1491
1482
  //#endregion
1483
+ //#region src/backends/wasm/as-typed-array.ts
1484
+ function allocAsTypedView(module, byteLength, length, typeId, Ctor) {
1485
+ const { headerPtr, bufferPtr } = allocAsHeader(module, byteLength, typeId);
1486
+ return {
1487
+ headerPtr,
1488
+ bufferPtr,
1489
+ view: new Ctor(module.memory.buffer, bufferPtr, length),
1490
+ byteLength,
1491
+ length
1492
+ };
1493
+ }
1494
+ //#endregion
1492
1495
  //#region src/backends/WASMBackend.ts
1493
1496
  init_DenseMatrix();
1494
- const AS_ID_ARRAY_BUFFER$1 = 1;
1495
- const AS_ID_FLOAT64_ARRAY$1 = 5;
1496
- const AS_ID_INT32_ARRAY$1 = 6;
1497
- const AS_F64_ALIGN_SHIFT = 3;
1498
- const AS_I32_ALIGN_SHIFT = 2;
1499
- const AS_HEADER_BYTES$1 = 12;
1500
1497
  var AsAllocCache = class {
1501
1498
  free = /* @__PURE__ */ new Map();
1502
1499
  acquire(module, length) {
@@ -1517,22 +1514,22 @@ var AsAllocCache = class {
1517
1514
  pool.push(alloc);
1518
1515
  }
1519
1516
  allocate(module, length) {
1520
- const byteLength = length << AS_F64_ALIGN_SHIFT;
1521
- const bufferPtr = module.__pin(module.__new(byteLength, AS_ID_ARRAY_BUFFER$1)) >>> 0;
1522
- const headerPtr = module.__new(AS_HEADER_BYTES$1, AS_ID_FLOAT64_ARRAY$1) >>> 0;
1523
- module.__pin(headerPtr);
1524
- const dv = new DataView(module.memory.buffer);
1525
- dv.setUint32(headerPtr + 0, bufferPtr, true);
1526
- dv.setUint32(headerPtr + 4, bufferPtr, true);
1527
- dv.setUint32(headerPtr + 8, byteLength, true);
1528
- return {
1529
- headerPtr,
1530
- bufferPtr,
1531
- view: new Float64Array(module.memory.buffer, bufferPtr, length),
1532
- length
1533
- };
1517
+ return allocHeader(module, length, {
1518
+ shift: 3,
1519
+ typeId: 5,
1520
+ Ctor: Float64Array
1521
+ });
1534
1522
  }
1535
1523
  };
1524
+ function allocHeader(module, length, opts) {
1525
+ const { headerPtr, bufferPtr, view } = allocAsTypedView(module, length << opts.shift, length, opts.typeId, opts.Ctor);
1526
+ return {
1527
+ headerPtr,
1528
+ bufferPtr,
1529
+ view,
1530
+ length
1531
+ };
1532
+ }
1536
1533
  function writeAsFloat64Array(cache, module, data) {
1537
1534
  const alloc = cache.acquire(module, data.length);
1538
1535
  alloc.view.set(data);
@@ -1546,20 +1543,11 @@ function readAsFloat64Array(module, alloc) {
1546
1543
  return new Float64Array(view);
1547
1544
  }
1548
1545
  function allocAsInt32Array(module, length) {
1549
- const byteLength = length << AS_I32_ALIGN_SHIFT;
1550
- const bufferPtr = module.__pin(module.__new(byteLength, AS_ID_ARRAY_BUFFER$1)) >>> 0;
1551
- const headerPtr = module.__new(AS_HEADER_BYTES$1, AS_ID_INT32_ARRAY$1) >>> 0;
1552
- module.__pin(headerPtr);
1553
- const dv = new DataView(module.memory.buffer);
1554
- dv.setUint32(headerPtr + 0, bufferPtr, true);
1555
- dv.setUint32(headerPtr + 4, bufferPtr, true);
1556
- dv.setUint32(headerPtr + 8, byteLength, true);
1557
- return {
1558
- headerPtr,
1559
- bufferPtr,
1560
- view: new Int32Array(module.memory.buffer, bufferPtr, length),
1561
- length
1562
- };
1546
+ return allocHeader(module, length, {
1547
+ shift: 2,
1548
+ typeId: 6,
1549
+ Ctor: Int32Array
1550
+ });
1563
1551
  }
1564
1552
  function readAsInt32Array(module, alloc) {
1565
1553
  const view = new Int32Array(module.memory.buffer, alloc.bufferPtr, alloc.length);
@@ -2190,6 +2178,165 @@ function registerBuiltinShaders(sm) {
2190
2178
  for (const [name, code] of Object.entries(BUILTIN_SHADERS)) sm.registerShader(name, code);
2191
2179
  }
2192
2180
  //#endregion
2181
+ //#region src/backends/gpu/run-shader.ts
2182
+ const UNIFORM_BYTES = 16;
2183
+ function planRunShaderFromAdd(a, b, rows, cols, workgroups) {
2184
+ const size = rows * cols * 4;
2185
+ return {
2186
+ pipeline: "matrixAdd",
2187
+ bytes: [
2188
+ size,
2189
+ size,
2190
+ size
2191
+ ],
2192
+ storageLabels: [
2193
+ "matrix-a",
2194
+ "matrix-b",
2195
+ "matrix-result"
2196
+ ],
2197
+ writes: [a, b],
2198
+ bindEntries: [
2199
+ {
2200
+ binding: 0,
2201
+ bufferIndex: 0
2202
+ },
2203
+ {
2204
+ binding: 1,
2205
+ bufferIndex: 1
2206
+ },
2207
+ {
2208
+ binding: 2,
2209
+ bufferIndex: 2
2210
+ },
2211
+ {
2212
+ binding: 3,
2213
+ bufferIndex: -1
2214
+ }
2215
+ ],
2216
+ params: new Uint32Array([
2217
+ rows,
2218
+ cols,
2219
+ 0,
2220
+ 0
2221
+ ]),
2222
+ workgroups,
2223
+ resultBufferIndex: 2
2224
+ };
2225
+ }
2226
+ function planRunShaderFromMatmul(a, b, M, K, N, workgroups) {
2227
+ return {
2228
+ pipeline: "matmul",
2229
+ bytes: [
2230
+ M * K * 4,
2231
+ K * N * 4,
2232
+ M * N * 4
2233
+ ],
2234
+ storageLabels: [
2235
+ "matmul-a",
2236
+ "matmul-b",
2237
+ "matmul-result"
2238
+ ],
2239
+ writes: [a, b],
2240
+ bindEntries: [
2241
+ {
2242
+ binding: 0,
2243
+ bufferIndex: 0
2244
+ },
2245
+ {
2246
+ binding: 1,
2247
+ bufferIndex: 1
2248
+ },
2249
+ {
2250
+ binding: 2,
2251
+ bufferIndex: 2
2252
+ },
2253
+ {
2254
+ binding: 3,
2255
+ bufferIndex: -1
2256
+ }
2257
+ ],
2258
+ params: new Uint32Array([
2259
+ M,
2260
+ N,
2261
+ K,
2262
+ 0
2263
+ ]),
2264
+ workgroups,
2265
+ resultBufferIndex: 2
2266
+ };
2267
+ }
2268
+ function planRunShaderFromTranspose(a, rows, cols, workgroups) {
2269
+ const size = rows * cols * 4;
2270
+ return {
2271
+ pipeline: "transpose",
2272
+ bytes: [size, size],
2273
+ storageLabels: ["transpose-a", "transpose-result"],
2274
+ writes: [a],
2275
+ bindEntries: [
2276
+ {
2277
+ binding: 0,
2278
+ bufferIndex: 0
2279
+ },
2280
+ {
2281
+ binding: 1,
2282
+ bufferIndex: 1
2283
+ },
2284
+ {
2285
+ binding: 2,
2286
+ bufferIndex: -1
2287
+ }
2288
+ ],
2289
+ params: new Uint32Array([
2290
+ rows,
2291
+ cols,
2292
+ 0,
2293
+ 0
2294
+ ]),
2295
+ workgroups,
2296
+ resultBufferIndex: 1
2297
+ };
2298
+ }
2299
+ async function runShader(backend, plan) {
2300
+ const ctx = backend.getContext();
2301
+ const pool = backend.getBufferPool();
2302
+ const shaders = backend.getShaderManager();
2303
+ const storageBuffers = [];
2304
+ let bufferParams;
2305
+ try {
2306
+ for (let idx = 0; idx < plan.bytes.length; idx++) {
2307
+ const byteSize = plan.bytes[idx];
2308
+ if (byteSize === void 0) throw new Error(`runShader: missing byte size at index ${idx}`);
2309
+ storageBuffers.push(pool.acquireStorageBuffer(byteSize, plan.storageLabels[idx] ?? `storage-${idx}`, true, idx !== plan.resultBufferIndex));
2310
+ }
2311
+ bufferParams = pool.acquireUniformBuffer(UNIFORM_BYTES, "params");
2312
+ for (let i = 0; i < plan.writes.length; i++) {
2313
+ const target = storageBuffers[i];
2314
+ const payload = plan.writes[i];
2315
+ if (target === void 0 || payload === void 0) throw new Error(`runShader: missing write target at index ${i}`);
2316
+ ctx.writeBuffer(target, payload);
2317
+ }
2318
+ ctx.writeBuffer(bufferParams, plan.params);
2319
+ const pipeline = shaders.getRegisteredPipeline(plan.pipeline);
2320
+ const bindResources = plan.bindEntries.map((entry) => {
2321
+ const buffer = entry.bufferIndex === -1 ? bufferParams : storageBuffers[entry.bufferIndex];
2322
+ if (buffer === void 0) throw new Error(`runShader: missing buffer for binding ${entry.binding}`);
2323
+ return {
2324
+ binding: entry.binding,
2325
+ resource: { buffer }
2326
+ };
2327
+ });
2328
+ const bindGroup = ctx.createBindGroup(pipeline.getBindGroupLayout(0), bindResources);
2329
+ ctx.dispatchCompute(pipeline, [bindGroup], plan.workgroups);
2330
+ const resultBuf = storageBuffers[plan.resultBufferIndex];
2331
+ if (resultBuf === void 0) throw new Error(`runShader: missing result buffer at index ${plan.resultBufferIndex}`);
2332
+ const resultData = await ctx.readBuffer(resultBuf);
2333
+ return new Float32Array(resultData);
2334
+ } finally {
2335
+ for (const buf of storageBuffers) pool.release(buf);
2336
+ if (bufferParams !== void 0) pool.release(bufferParams);
2337
+ }
2338
+ }
2339
+ //#endregion
2193
2340
  //#region src/backends/GPUBackend.ts
2194
2341
  const DEFAULT_THRESHOLD = 256;
2195
2342
  var GPUBackend = class {
@@ -2283,131 +2430,13 @@ var GPUBackend = class {
2283
2430
  return this.shaderManager;
2284
2431
  }
2285
2432
  async add(a, b, rows, cols) {
2286
- const ctx = this.getContext();
2287
- const pool = this.getBufferPool();
2288
- const shaders = this.getShaderManager();
2289
- const size = rows * cols * 4;
2290
- const bufferA = pool.acquireStorageBuffer(size, "matrix-a", true, true);
2291
- const bufferB = pool.acquireStorageBuffer(size, "matrix-b", true, true);
2292
- const bufferResult = pool.acquireStorageBuffer(size, "matrix-result", true, false);
2293
- const bufferParams = pool.acquireUniformBuffer(16, "params");
2294
- ctx.writeBuffer(bufferA, a);
2295
- ctx.writeBuffer(bufferB, b);
2296
- ctx.writeBuffer(bufferParams, new Uint32Array([
2297
- rows,
2298
- cols,
2299
- 0,
2300
- 0
2301
- ]));
2302
- const pipeline = shaders.getRegisteredPipeline("matrixAdd");
2303
- const bindGroup = ctx.createBindGroup(pipeline.getBindGroupLayout(0), [
2304
- {
2305
- binding: 0,
2306
- resource: { buffer: bufferA }
2307
- },
2308
- {
2309
- binding: 1,
2310
- resource: { buffer: bufferB }
2311
- },
2312
- {
2313
- binding: 2,
2314
- resource: { buffer: bufferResult }
2315
- },
2316
- {
2317
- binding: 3,
2318
- resource: { buffer: bufferParams }
2319
- }
2320
- ]);
2321
- ctx.dispatchCompute(pipeline, [bindGroup], this.calculateWorkgroups(rows, cols));
2322
- const resultData = await ctx.readBuffer(bufferResult);
2323
- pool.release(bufferA);
2324
- pool.release(bufferB);
2325
- pool.release(bufferResult);
2326
- pool.release(bufferParams);
2327
- return new Float32Array(resultData);
2433
+ return runShader(this, planRunShaderFromAdd(a, b, rows, cols, this.calculateWorkgroups(rows, cols)));
2328
2434
  }
2329
2435
  async matmul(a, b, M, K, N) {
2330
- const ctx = this.getContext();
2331
- const pool = this.getBufferPool();
2332
- const shaders = this.getShaderManager();
2333
- const sizeA = M * K * 4;
2334
- const sizeB = K * N * 4;
2335
- const sizeResult = M * N * 4;
2336
- const bufferA = pool.acquireStorageBuffer(sizeA, "matmul-a", true, true);
2337
- const bufferB = pool.acquireStorageBuffer(sizeB, "matmul-b", true, true);
2338
- const bufferResult = pool.acquireStorageBuffer(sizeResult, "matmul-result", true, false);
2339
- const bufferParams = pool.acquireUniformBuffer(16, "params");
2340
- ctx.writeBuffer(bufferA, a);
2341
- ctx.writeBuffer(bufferB, b);
2342
- ctx.writeBuffer(bufferParams, new Uint32Array([
2343
- M,
2344
- N,
2345
- K,
2346
- 0
2347
- ]));
2348
- const pipeline = shaders.getRegisteredPipeline("matmul");
2349
- const bindGroup = ctx.createBindGroup(pipeline.getBindGroupLayout(0), [
2350
- {
2351
- binding: 0,
2352
- resource: { buffer: bufferA }
2353
- },
2354
- {
2355
- binding: 1,
2356
- resource: { buffer: bufferB }
2357
- },
2358
- {
2359
- binding: 2,
2360
- resource: { buffer: bufferResult }
2361
- },
2362
- {
2363
- binding: 3,
2364
- resource: { buffer: bufferParams }
2365
- }
2366
- ]);
2367
- ctx.dispatchCompute(pipeline, [bindGroup], this.calculateWorkgroups(M, N));
2368
- const resultData = await ctx.readBuffer(bufferResult);
2369
- pool.release(bufferA);
2370
- pool.release(bufferB);
2371
- pool.release(bufferResult);
2372
- pool.release(bufferParams);
2373
- return new Float32Array(resultData);
2436
+ return runShader(this, planRunShaderFromMatmul(a, b, M, K, N, this.calculateWorkgroups(M, N)));
2374
2437
  }
2375
2438
  async transpose(a, rows, cols) {
2376
- const ctx = this.getContext();
2377
- const pool = this.getBufferPool();
2378
- const shaders = this.getShaderManager();
2379
- const size = rows * cols * 4;
2380
- const bufferA = pool.acquireStorageBuffer(size, "transpose-a", true, true);
2381
- const bufferResult = pool.acquireStorageBuffer(size, "transpose-result", true, false);
2382
- const bufferParams = pool.acquireUniformBuffer(16, "params");
2383
- ctx.writeBuffer(bufferA, a);
2384
- ctx.writeBuffer(bufferParams, new Uint32Array([
2385
- rows,
2386
- cols,
2387
- 0,
2388
- 0
2389
- ]));
2390
- const pipeline = shaders.getRegisteredPipeline("transpose");
2391
- const bindGroup = ctx.createBindGroup(pipeline.getBindGroupLayout(0), [
2392
- {
2393
- binding: 0,
2394
- resource: { buffer: bufferA }
2395
- },
2396
- {
2397
- binding: 1,
2398
- resource: { buffer: bufferResult }
2399
- },
2400
- {
2401
- binding: 2,
2402
- resource: { buffer: bufferParams }
2403
- }
2404
- ]);
2405
- ctx.dispatchCompute(pipeline, [bindGroup], this.calculateWorkgroups(rows, cols));
2406
- const resultData = await ctx.readBuffer(bufferResult);
2407
- pool.release(bufferA);
2408
- pool.release(bufferResult);
2409
- pool.release(bufferParams);
2410
- return new Float32Array(resultData);
2439
+ return runShader(this, planRunShaderFromTranspose(a, rows, cols, this.calculateWorkgroups(rows, cols)));
2411
2440
  }
2412
2441
  async scale(a, scalar) {
2413
2442
  const ctx = this.getContext();
@@ -2488,6 +2517,12 @@ function destroyGlobalGPUBackend() {
2488
2517
  }
2489
2518
  }
2490
2519
  //#endregion
2520
+ //#region src/backends/gpu/gpu-or-js.ts
2521
+ async function gpuOrJs(useGpu, js, gpu, executeWithFallback) {
2522
+ if (!useGpu) return js();
2523
+ return executeWithFallback(gpu, js);
2524
+ }
2525
+ //#endregion
2491
2526
  //#region src/backends/GPUMatrixBackend.ts
2492
2527
  init_DenseMatrix();
2493
2528
  const DEFAULT_CONFIG$1 = {
@@ -2557,13 +2592,12 @@ var GPUMatrixBackend = class {
2557
2592
  }
2558
2593
  async addAsync(a, b) {
2559
2594
  const elementCount = a.rows * a.cols;
2560
- if (!this.shouldUseGPU(elementCount)) return jsBackend.add(a, b);
2561
- return this.executeWithFallback(async () => {
2595
+ return gpuOrJs(this.shouldUseGPU(elementCount), () => jsBackend.add(a, b), async () => {
2562
2596
  const aData = new Float32Array(a.toFloat64Array());
2563
2597
  const bData = new Float32Array(b.toFloat64Array());
2564
2598
  const result = await this.backend.add(aData, bData, a.rows, a.cols);
2565
2599
  return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2566
- }, () => jsBackend.add(a, b));
2600
+ }, (gpuOp, fallback) => this.executeWithFallback(gpuOp, fallback));
2567
2601
  }
2568
2602
  subtract(a, b) {
2569
2603
  const elementCount = a.rows * a.cols;
@@ -2587,12 +2621,11 @@ var GPUMatrixBackend = class {
2587
2621
  }
2588
2622
  async scaleAsync(a, scalar) {
2589
2623
  const elementCount = a.rows * a.cols;
2590
- if (!this.shouldUseGPU(elementCount)) return jsBackend.scale(a, scalar);
2591
- return this.executeWithFallback(async () => {
2624
+ return gpuOrJs(this.shouldUseGPU(elementCount), () => jsBackend.scale(a, scalar), async () => {
2592
2625
  const aData = new Float32Array(a.toFloat64Array());
2593
2626
  const result = await this.backend.scale(aData, scalar);
2594
2627
  return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2595
- }, () => jsBackend.scale(a, scalar));
2628
+ }, (gpuOp, fallback) => this.executeWithFallback(gpuOp, fallback));
2596
2629
  }
2597
2630
  abs(a) {
2598
2631
  return jsBackend.abs(a);
@@ -2607,13 +2640,12 @@ var GPUMatrixBackend = class {
2607
2640
  }
2608
2641
  async multiplyAsync(a, b) {
2609
2642
  const elementCount = a.rows * b.cols * a.cols;
2610
- if (!this.shouldUseGPU(elementCount)) return jsBackend.multiply(a, b);
2611
- return this.executeWithFallback(async () => {
2643
+ return gpuOrJs(this.shouldUseGPU(elementCount), () => jsBackend.multiply(a, b), async () => {
2612
2644
  const aData = new Float32Array(a.toFloat64Array());
2613
2645
  const bData = new Float32Array(b.toFloat64Array());
2614
2646
  const result = await this.backend.matmul(aData, bData, a.rows, a.cols, b.cols);
2615
2647
  return DenseMatrix.fromFlat(a.rows, b.cols, Array.from(result));
2616
- }, () => jsBackend.multiply(a, b));
2648
+ }, (gpuOp, fallback) => this.executeWithFallback(gpuOp, fallback));
2617
2649
  }
2618
2650
  transpose(a) {
2619
2651
  const elementCount = a.rows * a.cols;
@@ -2659,7 +2691,9 @@ const gpuMatrixBackend = new GPUMatrixBackend();
2659
2691
  function createGPUMatrixBackend(config) {
2660
2692
  return new GPUMatrixBackend(config);
2661
2693
  }
2662
- let currentConfig = {
2694
+ //#endregion
2695
+ //#region src/config.ts
2696
+ const DEFAULT_CONFIG = {
2663
2697
  backends: {
2664
2698
  js: {
2665
2699
  enabled: true,
@@ -2670,21 +2704,21 @@ let currentConfig = {
2670
2704
  wasm: {
2671
2705
  enabled: true,
2672
2706
  preference: "auto",
2673
- threshold: 1e3,
2707
+ threshold: DEFAULT_BACKEND_HINTS.wasmThreshold,
2674
2708
  operationThresholds: {
2675
- multiply: 500,
2709
+ multiply: 256,
2676
2710
  decomposition: 100,
2677
2711
  transpose: 2e3
2678
2712
  }
2679
2713
  },
2680
2714
  gpu: {
2681
- enabled: true,
2715
+ enabled: false,
2682
2716
  preference: "auto",
2683
- threshold: 1e5,
2717
+ threshold: DEFAULT_BACKEND_HINTS.gpuThreshold,
2684
2718
  operationThresholds: {
2685
- multiply: 5e4,
2686
- decomposition: 1e4,
2687
- transpose: 2e5
2719
+ multiply: DEFAULT_BACKEND_HINTS.gpuThreshold,
2720
+ decomposition: DEFAULT_BACKEND_HINTS.gpuThreshold,
2721
+ transpose: DEFAULT_BACKEND_HINTS.gpuThreshold
2688
2722
  }
2689
2723
  }
2690
2724
  },
@@ -2703,6 +2737,7 @@ let currentConfig = {
2703
2737
  precision: "double",
2704
2738
  debug: false
2705
2739
  };
2740
+ let currentConfig = { ...DEFAULT_CONFIG };
2706
2741
  const listeners = /* @__PURE__ */ new Set();
2707
2742
  function getConfig() {
2708
2743
  return currentConfig;
@@ -2717,25 +2752,33 @@ backendRegistry.register(jsBackend);
2717
2752
  backendRegistry.register(wasmBackend);
2718
2753
  //#endregion
2719
2754
  //#region src/backends/BackendManager.ts
2720
- const DEFAULT_EXTENDED_HINTS = {
2721
- ...DEFAULT_BACKEND_HINTS,
2722
- operationThresholds: {
2723
- multiply: {
2724
- wasm: 256,
2725
- gpu: GPU_MIN_ELEMENTS
2726
- },
2727
- decomposition: {
2728
- wasm: 100,
2729
- gpu: GPU_MIN_ELEMENTS
2755
+ function extendedHintsFromConfig(config) {
2756
+ const { wasm, gpu } = config.backends;
2757
+ const wasmOps = wasm.operationThresholds ?? {};
2758
+ const gpuOps = gpu.operationThresholds ?? {};
2759
+ return {
2760
+ wasmThreshold: wasm.threshold,
2761
+ gpuThreshold: gpu.threshold,
2762
+ preferredBackend: DEFAULT_BACKEND_HINTS.preferredBackend,
2763
+ operationThresholds: {
2764
+ multiply: {
2765
+ wasm: wasmOps.multiply ?? wasm.threshold,
2766
+ gpu: gpuOps.multiply ?? gpu.threshold
2767
+ },
2768
+ decomposition: {
2769
+ wasm: wasmOps.decomposition ?? wasm.threshold,
2770
+ gpu: gpuOps.decomposition ?? gpu.threshold
2771
+ },
2772
+ transpose: {
2773
+ wasm: wasmOps.transpose ?? wasm.threshold,
2774
+ gpu: gpuOps.transpose ?? gpu.threshold
2775
+ }
2730
2776
  },
2731
- transpose: {
2732
- wasm: 2e3,
2733
- gpu: GPU_MIN_ELEMENTS
2734
- }
2735
- },
2736
- autoSIMD: true,
2737
- fallbackOnError: true
2738
- };
2777
+ autoSIMD: true,
2778
+ fallbackOnError: true
2779
+ };
2780
+ }
2781
+ const DEFAULT_EXTENDED_HINTS = extendedHintsFromConfig(DEFAULT_CONFIG);
2739
2782
  var BackendManager = class {
2740
2783
  hints;
2741
2784
  initialized = false;
@@ -3018,387 +3061,6 @@ function createBackendManager(hints) {
3018
3061
  return new BackendManager(hints);
3019
3062
  }
3020
3063
  //#endregion
3021
- //#region src/backends/WasmLoader.ts
3022
- const AS_ID_ARRAY_BUFFER = 1;
3023
- const AS_ID_INT32_ARRAY = 4;
3024
- const AS_ID_FLOAT64_ARRAY = 5;
3025
- const AS_HEADER_BYTES = 12;
3026
- (class WasmLoader {
3027
- static instance = null;
3028
- wasmModule = null;
3029
- compiledModule = null;
3030
- loading = null;
3031
- isNode;
3032
- lastMetrics = null;
3033
- float64Pool = [];
3034
- int32Pool = [];
3035
- poolSizeThreshold = 1048576;
3036
- constructor() {
3037
- this.isNode = typeof process !== "undefined" && process.versions?.node !== void 0;
3038
- }
3039
- static getInstance() {
3040
- if (!WasmLoader.instance) WasmLoader.instance = new WasmLoader();
3041
- return WasmLoader.instance;
3042
- }
3043
- async load(wasmPath) {
3044
- if (this.wasmModule) return this.wasmModule;
3045
- if (this.loading) return this.loading;
3046
- this.loading = this.loadModule(wasmPath);
3047
- try {
3048
- this.wasmModule = await this.loading;
3049
- } catch (error) {
3050
- this.compiledModule = null;
3051
- throw error;
3052
- } finally {
3053
- this.loading = null;
3054
- }
3055
- return this.wasmModule;
3056
- }
3057
- async precompile(wasmPath) {
3058
- if (this.compiledModule) return;
3059
- const path = wasmPath || await this.getDefaultWasmPath();
3060
- const startTime = performance.now();
3061
- const { loadWasmManifest, verifyWasmIntegrity } = await import("./integrity-Hbf0W3mK.js");
3062
- if (this.isNode) {
3063
- const fs = await import("fs");
3064
- const { promisify } = await import("util");
3065
- const buffer = await promisify(fs.readFile)(path);
3066
- await verifyWasmIntegrity(buffer, path);
3067
- this.compiledModule = await WebAssembly.compile(buffer);
3068
- } else {
3069
- const manifest = await loadWasmManifest(path);
3070
- if (!manifest && typeof WebAssembly.compileStreaming === "function") this.compiledModule = await WebAssembly.compileStreaming(fetch(path));
3071
- else {
3072
- const buffer = await (await fetch(path)).arrayBuffer();
3073
- await verifyWasmIntegrity(buffer, path, { manifest });
3074
- this.compiledModule = await WebAssembly.compile(buffer);
3075
- }
3076
- }
3077
- this.lastMetrics = {
3078
- fileReadMs: 0,
3079
- compileMs: performance.now() - startTime,
3080
- instantiateMs: 0,
3081
- totalMs: performance.now() - startTime,
3082
- fromCache: false
3083
- };
3084
- }
3085
- async loadModule(wasmPath) {
3086
- const path = wasmPath || await this.getDefaultWasmPath();
3087
- const totalStart = performance.now();
3088
- if (this.compiledModule) {
3089
- const instStart = performance.now();
3090
- const instance = await WebAssembly.instantiate(this.compiledModule, this.getImports());
3091
- this.lastMetrics = {
3092
- fileReadMs: 0,
3093
- compileMs: 0,
3094
- instantiateMs: performance.now() - instStart,
3095
- totalMs: performance.now() - totalStart,
3096
- fromCache: true
3097
- };
3098
- return instance.exports;
3099
- }
3100
- if (this.isNode) return this.loadNodeWasm(path, totalStart);
3101
- else return this.loadBrowserWasm(path, totalStart);
3102
- }
3103
- async getDefaultWasmPath() {
3104
- const wasmFile = "mathts-as.wasm";
3105
- if (this.isNode) {
3106
- const { resolvePackagedWasm } = await import("./resolve-BzZxSO28.js");
3107
- const found = await resolvePackagedWasm(import.meta.url, wasmFile);
3108
- if (found) return found;
3109
- const { defaultWasmLocation } = await import("./resolve-BzZxSO28.js");
3110
- return defaultWasmLocation(import.meta.url, wasmFile);
3111
- }
3112
- const { defaultWasmLocation } = await import("./resolve-BzZxSO28.js");
3113
- return defaultWasmLocation(import.meta.url, wasmFile, { browser: true });
3114
- }
3115
- async loadNodeWasm(path, totalStart) {
3116
- const fs = await import("fs");
3117
- const { promisify } = await import("util");
3118
- const readFile = promisify(fs.readFile);
3119
- const { verifyWasmIntegrity } = await import("./integrity-Hbf0W3mK.js");
3120
- const readStart = performance.now();
3121
- const buffer = await readFile(path);
3122
- const readEnd = performance.now();
3123
- await verifyWasmIntegrity(buffer, path);
3124
- const compileStart = performance.now();
3125
- this.compiledModule = await WebAssembly.compile(buffer);
3126
- const compileEnd = performance.now();
3127
- const instStart = performance.now();
3128
- const instance = await WebAssembly.instantiate(this.compiledModule, this.getImports());
3129
- const instEnd = performance.now();
3130
- this.lastMetrics = {
3131
- fileReadMs: readEnd - readStart,
3132
- compileMs: compileEnd - compileStart,
3133
- instantiateMs: instEnd - instStart,
3134
- totalMs: performance.now() - totalStart,
3135
- fromCache: false
3136
- };
3137
- return instance.exports;
3138
- }
3139
- async loadBrowserWasm(path, totalStart) {
3140
- const { loadWasmManifest, verifyWasmIntegrity } = await import("./integrity-Hbf0W3mK.js");
3141
- const manifest = await loadWasmManifest(path);
3142
- if (!manifest && typeof WebAssembly.instantiateStreaming === "function") {
3143
- const instStart = performance.now();
3144
- const result = await WebAssembly.instantiateStreaming(fetch(path), this.getImports());
3145
- this.compiledModule = result.module;
3146
- this.lastMetrics = {
3147
- fileReadMs: 0,
3148
- compileMs: 0,
3149
- instantiateMs: performance.now() - instStart,
3150
- totalMs: performance.now() - totalStart,
3151
- fromCache: false
3152
- };
3153
- return result.instance.exports;
3154
- }
3155
- const readStart = performance.now();
3156
- const buffer = await (await fetch(path)).arrayBuffer();
3157
- const readEnd = performance.now();
3158
- await verifyWasmIntegrity(buffer, path, { manifest });
3159
- const compileStart = performance.now();
3160
- this.compiledModule = await WebAssembly.compile(buffer);
3161
- const compileEnd = performance.now();
3162
- const instStart = performance.now();
3163
- const instance = await WebAssembly.instantiate(this.compiledModule, this.getImports());
3164
- const instEnd = performance.now();
3165
- this.lastMetrics = {
3166
- fileReadMs: readEnd - readStart,
3167
- compileMs: compileEnd - compileStart,
3168
- instantiateMs: instEnd - instStart,
3169
- totalMs: performance.now() - totalStart,
3170
- fromCache: false
3171
- };
3172
- return instance.exports;
3173
- }
3174
- getImports() {
3175
- return {
3176
- env: {
3177
- abort: (msg, file, line, column) => {
3178
- console.error("WASM abort", {
3179
- msg,
3180
- file,
3181
- line,
3182
- column
3183
- });
3184
- throw new Error("WASM abort");
3185
- },
3186
- seed: () => Date.now()
3187
- },
3188
- Math,
3189
- Date
3190
- };
3191
- }
3192
- getModule() {
3193
- return this.wasmModule;
3194
- }
3195
- getCompiledModule() {
3196
- return this.compiledModule;
3197
- }
3198
- isLoaded() {
3199
- return this.wasmModule !== null;
3200
- }
3201
- isPrecompiled() {
3202
- return this.compiledModule !== null;
3203
- }
3204
- getLoadingMetrics() {
3205
- return this.lastMetrics;
3206
- }
3207
- allocateFloat64Array(data) {
3208
- const module = this.wasmModule;
3209
- if (!module) throw new Error("WASM module not loaded");
3210
- const length = data.length;
3211
- const alloc = this.allocateAsFloat64(module, length);
3212
- alloc.array.set(data);
3213
- return alloc;
3214
- }
3215
- readReturnedFloat64Array(headerPtr) {
3216
- const module = this.wasmModule;
3217
- if (!module) throw new Error("WASM module not loaded");
3218
- const hdr = headerPtr >>> 0;
3219
- const dv = new DataView(module.memory.buffer);
3220
- const dataStart = dv.getUint32(hdr + 4, true);
3221
- const byteLength = dv.getUint32(hdr + 8, true);
3222
- const view = new Float64Array(module.memory.buffer, dataStart, byteLength >>> 3);
3223
- return new Float64Array(view);
3224
- }
3225
- allocateFloat64ArrayEmpty(length) {
3226
- const module = this.wasmModule;
3227
- if (!module) throw new Error("WASM module not loaded");
3228
- const alloc = this.allocateAsFloat64(module, length);
3229
- alloc.array.fill(0);
3230
- return alloc;
3231
- }
3232
- allocateInt32Array(data) {
3233
- const module = this.wasmModule;
3234
- if (!module) throw new Error("WASM module not loaded");
3235
- const length = data.length;
3236
- const alloc = this.allocateAsInt32(module, length);
3237
- alloc.array.set(data);
3238
- return alloc;
3239
- }
3240
- allocateInt32ArrayEmpty(length) {
3241
- const module = this.wasmModule;
3242
- if (!module) throw new Error("WASM module not loaded");
3243
- const alloc = this.allocateAsInt32(module, length);
3244
- alloc.array.fill(0);
3245
- return alloc;
3246
- }
3247
- allocateAsFloat64(module, length) {
3248
- const byteLength = length * 8;
3249
- if (byteLength <= this.poolSizeThreshold) {
3250
- const recycled = this.acquireFromAsPool(module, this.float64Pool, byteLength);
3251
- if (recycled) {
3252
- const array = new Float64Array(module.memory.buffer, recycled.dataPtr, length);
3253
- return {
3254
- ptr: recycled.ptr,
3255
- dataPtr: recycled.dataPtr,
3256
- array,
3257
- length
3258
- };
3259
- }
3260
- }
3261
- return this.makeAsFloat64(module, length);
3262
- }
3263
- allocateAsInt32(module, length) {
3264
- const byteLength = length * 4;
3265
- if (byteLength <= this.poolSizeThreshold) {
3266
- const recycled = this.acquireFromAsPool(module, this.int32Pool, byteLength);
3267
- if (recycled) {
3268
- const array = new Int32Array(module.memory.buffer, recycled.dataPtr, length);
3269
- return {
3270
- ptr: recycled.ptr,
3271
- dataPtr: recycled.dataPtr,
3272
- array,
3273
- length
3274
- };
3275
- }
3276
- }
3277
- return this.makeAsInt32(module, length);
3278
- }
3279
- makeAsFloat64(module, length) {
3280
- const byteLength = length * 8;
3281
- const bufferPtr = module.__pin(module.__new(byteLength, AS_ID_ARRAY_BUFFER)) >>> 0;
3282
- const headerPtr = module.__new(AS_HEADER_BYTES, AS_ID_FLOAT64_ARRAY) >>> 0;
3283
- module.__pin(headerPtr);
3284
- const dv = new DataView(module.memory.buffer);
3285
- dv.setUint32(headerPtr + 0, bufferPtr, true);
3286
- dv.setUint32(headerPtr + 4, bufferPtr, true);
3287
- dv.setUint32(headerPtr + 8, byteLength, true);
3288
- const array = new Float64Array(module.memory.buffer, bufferPtr, length);
3289
- this.track(this.float64Pool, headerPtr, bufferPtr, byteLength);
3290
- return {
3291
- ptr: headerPtr,
3292
- dataPtr: bufferPtr,
3293
- array,
3294
- length
3295
- };
3296
- }
3297
- makeAsInt32(module, length) {
3298
- const byteLength = length * 4;
3299
- const bufferPtr = module.__pin(module.__new(byteLength, AS_ID_ARRAY_BUFFER)) >>> 0;
3300
- const headerPtr = module.__new(AS_HEADER_BYTES, AS_ID_INT32_ARRAY) >>> 0;
3301
- module.__pin(headerPtr);
3302
- const dv = new DataView(module.memory.buffer);
3303
- dv.setUint32(headerPtr + 0, bufferPtr, true);
3304
- dv.setUint32(headerPtr + 4, bufferPtr, true);
3305
- dv.setUint32(headerPtr + 8, byteLength, true);
3306
- const array = new Int32Array(module.memory.buffer, bufferPtr, length);
3307
- this.track(this.int32Pool, headerPtr, bufferPtr, byteLength);
3308
- return {
3309
- ptr: headerPtr,
3310
- dataPtr: bufferPtr,
3311
- array,
3312
- length
3313
- };
3314
- }
3315
- track(pool, ptr, dataPtr, size) {
3316
- if (size <= this.poolSizeThreshold) pool.push({
3317
- ptr,
3318
- dataPtr,
3319
- size,
3320
- inUse: true
3321
- });
3322
- }
3323
- acquireFromAsPool(module, pool, requestedSize) {
3324
- let bestFit = null;
3325
- let bestFitWaste = Infinity;
3326
- for (const entry of pool) if (!entry.inUse && entry.size >= requestedSize) {
3327
- const waste = entry.size - requestedSize;
3328
- if (waste < bestFitWaste && entry.size <= requestedSize * 2) {
3329
- bestFit = entry;
3330
- bestFitWaste = waste;
3331
- }
3332
- }
3333
- if (bestFit) {
3334
- bestFit.inUse = true;
3335
- new DataView(module.memory.buffer).setUint32(bestFit.ptr + 8, requestedSize, true);
3336
- }
3337
- return bestFit;
3338
- }
3339
- findEntry(ptr) {
3340
- return this.float64Pool.find((e) => e.ptr === ptr) ?? this.int32Pool.find((e) => e.ptr === ptr);
3341
- }
3342
- unpinAllocation(module, ptr, dataPtr) {
3343
- if (typeof module.__unpin !== "function") return;
3344
- module.__unpin(ptr);
3345
- if (dataPtr !== void 0) module.__unpin(dataPtr);
3346
- }
3347
- headerDataPtr(module, ptr) {
3348
- return new DataView(module.memory.buffer).getUint32(ptr + 4, true);
3349
- }
3350
- release(ptr, isFloat64 = true) {
3351
- const entry = this.findEntry(ptr);
3352
- if (entry) {
3353
- entry.inUse = false;
3354
- return;
3355
- }
3356
- const module = this.wasmModule;
3357
- if (!module) return;
3358
- this.unpinAllocation(module, ptr, this.headerDataPtr(module, ptr));
3359
- }
3360
- free(ptr) {
3361
- this.release(ptr);
3362
- }
3363
- clearPool() {
3364
- const module = this.wasmModule;
3365
- if (!module) return;
3366
- for (const entry of [...this.float64Pool, ...this.int32Pool]) if (!entry.inUse) this.unpinAllocation(module, entry.ptr, entry.dataPtr);
3367
- this.float64Pool = [];
3368
- this.int32Pool = [];
3369
- }
3370
- getPoolStats() {
3371
- const f64InUse = this.float64Pool.filter((e) => e.inUse).length;
3372
- const f64Bytes = this.float64Pool.reduce((sum, e) => sum + e.size, 0);
3373
- const i32InUse = this.int32Pool.filter((e) => e.inUse).length;
3374
- const i32Bytes = this.int32Pool.reduce((sum, e) => sum + e.size, 0);
3375
- return {
3376
- float64: {
3377
- total: this.float64Pool.length,
3378
- inUse: f64InUse,
3379
- totalBytes: f64Bytes
3380
- },
3381
- int32: {
3382
- total: this.int32Pool.length,
3383
- inUse: i32InUse,
3384
- totalBytes: i32Bytes
3385
- }
3386
- };
3387
- }
3388
- collect() {
3389
- const module = this.wasmModule;
3390
- if (!module) return;
3391
- if (typeof module.__collect === "function") module.__collect();
3392
- }
3393
- reset() {
3394
- this.clearPool();
3395
- this.wasmModule = null;
3396
- this.compiledModule = null;
3397
- this.loading = null;
3398
- this.lastMetrics = null;
3399
- }
3400
- }).getInstance();
3401
- //#endregion
3402
3064
  //#region src/backends/gpu/BatchExecutor.ts
3403
3065
  var BatchExecutor = class {
3404
3066
  context;
@@ -3833,6 +3495,66 @@ function transpose$1(A) {
3833
3495
  const n = A[0].length;
3834
3496
  return Array.from({ length: n }, (_, j) => Array.from({ length: m }, (_, i) => A[i][j]));
3835
3497
  }
3498
+ function matInv(A) {
3499
+ const n = A.length;
3500
+ return gaussJordanSolve(A, Array.from({ length: n }, (_, i) => {
3501
+ const row = new Array(n).fill(0);
3502
+ row[i] = 1;
3503
+ return row;
3504
+ }));
3505
+ }
3506
+ function gaussJordanSolve(a, rhs) {
3507
+ const n = a.length;
3508
+ if (n === 0) return [];
3509
+ const width = rhs[0]?.length ?? 0;
3510
+ const M = a.map((row, i) => {
3511
+ const r = new Array(n + width);
3512
+ for (let j = 0; j < n; j++) r[j] = row[j];
3513
+ const b = rhs[i] ?? [];
3514
+ for (let j = 0; j < width; j++) r[n + j] = b[j] ?? 0;
3515
+ return r;
3516
+ });
3517
+ for (let col = 0; col < n; col++) {
3518
+ let maxRow = col;
3519
+ let maxVal = Math.abs(M[col][col]);
3520
+ for (let row = col + 1; row < n; row++) if (Math.abs(M[row][col]) > maxVal) {
3521
+ maxVal = Math.abs(M[row][col]);
3522
+ maxRow = row;
3523
+ }
3524
+ if (maxRow !== col) [M[col], M[maxRow]] = [M[maxRow], M[col]];
3525
+ const pivot = M[col][col];
3526
+ if (Math.abs(pivot) < 1e-15) return null;
3527
+ for (let j = col; j < n + width; j++) M[col][j] /= pivot;
3528
+ for (let row = 0; row < n; row++) {
3529
+ if (row === col) continue;
3530
+ const f = M[row][col];
3531
+ if (f === 0) continue;
3532
+ for (let j = col; j < n + width; j++) M[row][j] -= f * M[col][j];
3533
+ }
3534
+ }
3535
+ return M.map((row) => row.slice(n));
3536
+ }
3537
+ function gaussJordanContinue(aug, n, pivotTol) {
3538
+ const width = aug[0].length;
3539
+ for (let col = 0; col < n; col++) {
3540
+ let maxRow = col;
3541
+ let maxVal = Math.abs(aug[col][col]);
3542
+ for (let row = col + 1; row < n; row++) if (Math.abs(aug[row][col]) > maxVal) {
3543
+ maxVal = Math.abs(aug[row][col]);
3544
+ maxRow = row;
3545
+ }
3546
+ if (maxRow !== col) [aug[col], aug[maxRow]] = [aug[maxRow], aug[col]];
3547
+ const pivot = aug[col][col];
3548
+ if (Math.abs(pivot) < pivotTol) continue;
3549
+ for (let j = col; j < width; j++) aug[col][j] /= pivot;
3550
+ for (let row = 0; row < n; row++) {
3551
+ if (row === col) continue;
3552
+ const factor = aug[row][col];
3553
+ if (factor === 0) continue;
3554
+ for (let j = col; j < width; j++) aug[row][j] -= factor * aug[col][j];
3555
+ }
3556
+ }
3557
+ }
3836
3558
  function isSymmetric(matrix, tolerance = 1e-10) {
3837
3559
  const n = matrix.length;
3838
3560
  if (n === 0) return true;
@@ -4385,6 +4107,38 @@ function powerIteration(matrix, options = {}) {
4385
4107
  };
4386
4108
  }
4387
4109
  //#endregion
4110
+ //#region src/operations/givens.ts
4111
+ function givensRotation(a, b) {
4112
+ if (b === 0) return {
4113
+ c: 1,
4114
+ s: 0
4115
+ };
4116
+ if (Math.abs(b) > Math.abs(a)) {
4117
+ const t = -a / b;
4118
+ const s = 1 / Math.sqrt(1 + t * t);
4119
+ return {
4120
+ c: s * t,
4121
+ s
4122
+ };
4123
+ }
4124
+ const t = -b / a;
4125
+ const c = 1 / Math.sqrt(1 + t * t);
4126
+ return {
4127
+ c,
4128
+ s: c * t
4129
+ };
4130
+ }
4131
+ function applyGivensCols(A, c, s, i, k, rowStart, rowEnd) {
4132
+ for (let j = rowStart; j < rowEnd; j++) {
4133
+ const temp = c * A[j][i] - s * A[j][k];
4134
+ A[j][k] = s * A[j][i] + c * A[j][k];
4135
+ A[j][i] = temp;
4136
+ }
4137
+ }
4138
+ function applyGivensRight(A, c, s, i, k, startRow) {
4139
+ applyGivensCols(A, c, s, i, k, startRow, A.length);
4140
+ }
4141
+ //#endregion
4388
4142
  //#region src/operations/svd.ts
4389
4143
  const DEFAULT_MAX_ITERATIONS = 1e3;
4390
4144
  const DEFAULT_TOLERANCE = 1e-12;
@@ -4422,34 +4176,6 @@ function bidiagonalize(A) {
4422
4176
  V
4423
4177
  };
4424
4178
  }
4425
- function givens(a, b) {
4426
- if (b === 0) return {
4427
- c: 1,
4428
- s: 0
4429
- };
4430
- else if (Math.abs(b) > Math.abs(a)) {
4431
- const t = -a / b;
4432
- const s = 1 / Math.sqrt(1 + t * t);
4433
- return {
4434
- c: s * t,
4435
- s
4436
- };
4437
- } else {
4438
- const t = -b / a;
4439
- const c = 1 / Math.sqrt(1 + t * t);
4440
- return {
4441
- c,
4442
- s: c * t
4443
- };
4444
- }
4445
- }
4446
- function applyGivensCols(A, c, s, i, k, rowStart, rowEnd) {
4447
- for (let j = rowStart; j < rowEnd; j++) {
4448
- const temp = c * A[j][i] - s * A[j][k];
4449
- A[j][k] = s * A[j][i] + c * A[j][k];
4450
- A[j][i] = temp;
4451
- }
4452
- }
4453
4179
  function svdStep(d, e, U, V, start, end) {
4454
4180
  if (end - start + 1 < 2) return;
4455
4181
  const dm1 = d[end - 1];
@@ -4467,14 +4193,14 @@ function svdStep(d, e, U, V, start, end) {
4467
4193
  let f = d[start] * d[start] - shift;
4468
4194
  let g = d[start] * e[start];
4469
4195
  for (let k = start; k < end; k++) {
4470
- const { c: cs, s: sn } = givens(f, g);
4196
+ const { c: cs, s: sn } = givensRotation(f, g);
4471
4197
  if (k > start) e[k - 1] = cs * f - sn * g;
4472
4198
  f = cs * d[k] - sn * e[k];
4473
4199
  e[k] = sn * d[k] + cs * e[k];
4474
4200
  g = -sn * d[k + 1];
4475
4201
  d[k + 1] = cs * d[k + 1];
4476
4202
  applyGivensCols(V, cs, sn, k, k + 1, 0, V.length);
4477
- const { c: cs2, s: sn2 } = givens(f, g);
4203
+ const { c: cs2, s: sn2 } = givensRotation(f, g);
4478
4204
  d[k] = cs2 * f - sn2 * g;
4479
4205
  f = cs2 * e[k] - sn2 * d[k + 1];
4480
4206
  d[k + 1] = sn2 * e[k] + cs2 * d[k + 1];
@@ -4489,7 +4215,7 @@ function svdStep(d, e, U, V, start, end) {
4489
4215
  function handleZero(d, e, _U, V, zeroIdx, isDiagonal, _tolerance) {
4490
4216
  const n = d.length;
4491
4217
  if (isDiagonal) for (let k = zeroIdx; k < n - 1; k++) {
4492
- const { c, s } = givens(d[k + 1], e[k]);
4218
+ const { c, s } = givensRotation(d[k + 1], e[k]);
4493
4219
  d[k + 1] = c * d[k + 1] - s * e[k];
4494
4220
  e[k] = 0;
4495
4221
  if (k < n - 2) {
@@ -5009,26 +4735,8 @@ const B = [
5009
4735
  ];
5010
4736
  function matSolve(M, N) {
5011
4737
  const n = M.length;
5012
- const cols = N[0].length;
5013
4738
  const Aug = M.map((row, i) => [...row, ...N[i]]);
5014
- for (let col = 0; col < n; col++) {
5015
- let maxRow = col;
5016
- let maxVal = Math.abs(Aug[col][col]);
5017
- for (let row = col + 1; row < n; row++) if (Math.abs(Aug[row][col]) > maxVal) {
5018
- maxVal = Math.abs(Aug[row][col]);
5019
- maxRow = row;
5020
- }
5021
- if (maxRow !== col) [Aug[col], Aug[maxRow]] = [Aug[maxRow], Aug[col]];
5022
- const pivot = Aug[col][col];
5023
- if (Math.abs(pivot) < 1e-15) continue;
5024
- for (let j = col; j < n + cols; j++) Aug[col][j] /= pivot;
5025
- for (let row = 0; row < n; row++) {
5026
- if (row === col) continue;
5027
- const factor = Aug[row][col];
5028
- if (factor === 0) continue;
5029
- for (let j = col; j < n + cols; j++) Aug[row][j] -= factor * Aug[col][j];
5030
- }
5031
- }
4739
+ gaussJordanContinue(Aug, n, 1e-15);
5032
4740
  return Aug.map((row) => row.slice(n));
5033
4741
  }
5034
4742
  function pade13(A) {
@@ -5090,26 +4798,6 @@ function hessenbergReduce(A) {
5090
4798
  Q
5091
4799
  };
5092
4800
  }
5093
- function givensParams(a, b) {
5094
- if (b === 0) return {
5095
- c: 1,
5096
- s: 0
5097
- };
5098
- if (Math.abs(b) > Math.abs(a)) {
5099
- const t = -a / b;
5100
- const s = 1 / Math.sqrt(1 + t * t);
5101
- return {
5102
- c: s * t,
5103
- s
5104
- };
5105
- }
5106
- const t = -b / a;
5107
- const c = 1 / Math.sqrt(1 + t * t);
5108
- return {
5109
- c,
5110
- s: c * t
5111
- };
5112
- }
5113
4801
  function applyGivensLeft(A, c, s, i, k, startCol) {
5114
4802
  const n = A[0].length;
5115
4803
  for (let j = startCol; j < n; j++) {
@@ -5118,14 +4806,6 @@ function applyGivensLeft(A, c, s, i, k, startCol) {
5118
4806
  A[i][j] = temp;
5119
4807
  }
5120
4808
  }
5121
- function applyGivensRight(A, c, s, i, k, startRow) {
5122
- const m = A.length;
5123
- for (let j = startRow; j < m; j++) {
5124
- const temp = c * A[j][i] - s * A[j][k];
5125
- A[j][k] = s * A[j][i] + c * A[j][k];
5126
- A[j][i] = temp;
5127
- }
5128
- }
5129
4809
  function qrStepSingle(H, Q, start, end) {
5130
4810
  const a = H[end - 1][end - 1];
5131
4811
  const b = H[end - 1][end];
@@ -5141,18 +4821,7 @@ function qrStepSingle(H, Q, start, end) {
5141
4821
  const e2 = (trace - sqrtDisc) / 2;
5142
4822
  shift = Math.abs(e1 - d) < Math.abs(e2 - d) ? e1 : e2;
5143
4823
  } else shift = d;
5144
- let x = H[start][start] - shift;
5145
- let y = H[start + 1][start];
5146
- for (let k = start; k < end; k++) {
5147
- const { c: gc, s: gs } = givensParams(x, y);
5148
- applyGivensLeft(H, gc, gs, k, k + 1, Math.max(0, k - 1));
5149
- applyGivensRight(H, gc, gs, k, k + 1, 0);
5150
- applyGivensRight(Q, gc, gs, k, k + 1, 0);
5151
- if (k < end - 1) {
5152
- x = H[k + 1][k];
5153
- y = H[k + 2][k];
5154
- }
5155
- }
4824
+ qrStepSingleShift(H, Q, start, end, shift);
5156
4825
  }
5157
4826
  function qrStepDouble(H, Q, start, end) {
5158
4827
  const n = H.length;
@@ -5198,7 +4867,7 @@ function qrStepDouble(H, Q, start, end) {
5198
4867
  y = H[k + 2][k];
5199
4868
  if (k < end - 2) z = H[k + 3][k];
5200
4869
  }
5201
- const { c: gc, s: gs } = givensParams(x, y);
4870
+ const { c: gc, s: gs } = givensRotation(x, y);
5202
4871
  applyGivensLeft(H, gc, gs, end - 1, end, end - 2);
5203
4872
  applyGivensRight(H, gc, gs, end - 1, end, 0);
5204
4873
  applyGivensRight(Q, gc, gs, end - 1, end, 0);
@@ -5207,7 +4876,7 @@ function qrStepSingleShift(H, Q, start, end, shift) {
5207
4876
  let x = H[start][start] - shift;
5208
4877
  let y = H[start + 1][start];
5209
4878
  for (let k = start; k < end; k++) {
5210
- const { c: gc, s: gs } = givensParams(x, y);
4879
+ const { c: gc, s: gs } = givensRotation(x, y);
5211
4880
  applyGivensLeft(H, gc, gs, k, k + 1, Math.max(0, k - 1));
5212
4881
  applyGivensRight(H, gc, gs, k, k + 1, 0);
5213
4882
  applyGivensRight(Q, gc, gs, k, k + 1, 0);
@@ -5317,51 +4986,210 @@ function schurInternal(A, maxIterations = 1e3, tolerance = 1e-12) {
5317
4986
  return schurRaw(A, maxIterations, tolerance);
5318
4987
  }
5319
4988
  //#endregion
5320
- //#region src/operations/logm.ts
4989
+ //#region src/operations/sqrtm.ts
5321
4990
  init_DenseMatrix();
5322
- function matInv$1(A) {
4991
+ function symmetrize(A) {
5323
4992
  const n = A.length;
5324
- const M = A.map((row, i) => {
5325
- const r = new Array(2 * n).fill(0);
5326
- for (let j = 0; j < n; j++) r[j] = row[j];
5327
- r[n + i] = 1;
5328
- return r;
5329
- });
5330
- for (let col = 0; col < n; col++) {
5331
- let maxRow = col;
5332
- let maxVal = Math.abs(M[col][col]);
5333
- for (let row = col + 1; row < n; row++) if (Math.abs(M[row][col]) > maxVal) {
5334
- maxVal = Math.abs(M[row][col]);
5335
- maxRow = row;
5336
- }
5337
- if (maxRow !== col) [M[col], M[maxRow]] = [M[maxRow], M[col]];
5338
- const pivot = M[col][col];
5339
- if (Math.abs(pivot) < 1e-15) return null;
5340
- for (let j = 0; j < 2 * n; j++) M[col][j] /= pivot;
5341
- for (let row = 0; row < n; row++) {
5342
- if (row === col) continue;
5343
- const f = M[row][col];
5344
- if (f === 0) continue;
5345
- for (let j = 0; j < 2 * n; j++) M[row][j] -= f * M[col][j];
4993
+ return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (A[i][j] + A[j][i]) / 2));
4994
+ }
4995
+ function gramSchmidt(A) {
4996
+ const m = A.length;
4997
+ const n = A[0].length;
4998
+ const Q = Array.from({ length: m }, () => new Array(n).fill(0));
4999
+ for (let j = 0; j < n; j++) {
5000
+ const v = A.map((row) => row[j]);
5001
+ for (let k = 0; k < j; k++) {
5002
+ let dot = 0;
5003
+ for (let i = 0; i < m; i++) dot += Q[i][k] * v[i];
5004
+ for (let i = 0; i < m; i++) v[i] -= dot * Q[i][k];
5346
5005
  }
5006
+ let norm = 0;
5007
+ for (let i = 0; i < m; i++) norm += v[i] * v[i];
5008
+ norm = Math.sqrt(norm);
5009
+ if (norm < 1e-14) for (let i = 0; i < m; i++) Q[i][j] = i === j ? 1 : 0;
5010
+ else for (let i = 0; i < m; i++) Q[i][j] = v[i] / norm;
5347
5011
  }
5348
- return M.map((row) => row.slice(n));
5012
+ return Q;
5349
5013
  }
5350
- function matSqrt(A) {
5014
+ function sqrtmSymmetric(A) {
5015
+ const n = A.length;
5016
+ const Asym = symmetrize(A);
5017
+ const { values, vectors } = eig(Asym, { computeVectors: true });
5018
+ for (const v of values) if (v.re < -1e-8) throw new Error(`matrixSqrtm: negative eigenvalue (${v.re}) — matrix is not positive semi-definite`);
5019
+ const Ynewton = sqrtmNewton(Asym);
5020
+ if (Ynewton !== null) return Ynewton;
5021
+ const Q = gramSchmidt(transpose$1(vectors));
5022
+ const Qt = transpose$1(Q);
5023
+ const Dsqrt = eye(n);
5024
+ for (let i = 0; i < n; i++) Dsqrt[i][i] = Math.sqrt(Math.max(values[i].re, 0));
5025
+ return matMul(matMul(Q, Dsqrt), Qt);
5026
+ }
5027
+ function newtonSqrtUpdate(A, Y) {
5028
+ const n = A.length;
5029
+ const Yinv = matInv(Y);
5030
+ if (Yinv === null) return null;
5031
+ const AYinv = matMul(A, Yinv);
5032
+ const next = Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (Y[i][j] + AYinv[i][j]) / 2));
5033
+ let diff = 0;
5034
+ for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) diff = Math.max(diff, Math.abs(next[i][j] - Y[i][j]));
5035
+ return {
5036
+ next,
5037
+ diff
5038
+ };
5039
+ }
5040
+ function sqrtmNewton(A) {
5351
5041
  const n = A.length;
5352
5042
  let Y = eye(n);
5353
5043
  for (let iter = 0; iter < 150; iter++) {
5354
- const Yinv = matInv$1(Y);
5355
- if (Yinv === null) break;
5356
- const AYinv = matMul(A, Yinv);
5357
- const Ynew = Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (Y[i][j] + AYinv[i][j]) / 2));
5358
- let diff = 0;
5359
- for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) diff = Math.max(diff, Math.abs(Ynew[i][j] - Y[i][j]));
5360
- Y = Ynew;
5361
- if (diff < 1e-14) break;
5044
+ const step = newtonSqrtUpdate(A, Y);
5045
+ if (step === null) return null;
5046
+ Y = step.next;
5047
+ if (step.diff < 1e-13) return Y;
5048
+ }
5049
+ const Y2 = matMul(Y, Y);
5050
+ let err = 0;
5051
+ for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) err = Math.max(err, Math.abs(Y2[i][j] - A[i][j]));
5052
+ return err < 1e-6 ? Y : null;
5053
+ }
5054
+ function sqrtmGeneral(A) {
5055
+ const n = A.length;
5056
+ const { values, vectors } = eig(A, { computeVectors: true });
5057
+ for (const v of values) {
5058
+ if (Math.abs(v.im) > 1e-7) throw new Error("matrixSqrtm: complex eigenvalues detected — real square root not supported");
5059
+ if (v.re < -1e-7) throw new Error(`matrixSqrtm: negative eigenvalue (${v.re}) — principal square root not real`);
5060
+ }
5061
+ const Ynewton = sqrtmNewton(A);
5062
+ if (Ynewton !== null) return Ynewton;
5063
+ const Q = transpose$1(vectors);
5064
+ const Qinv = matInv(Q);
5065
+ if (Qinv === null) throw new Error("matrixSqrtm: eigenvector matrix is singular — matrix appears to be non-diagonalisable");
5066
+ const Dsqrt = eye(n);
5067
+ for (let i = 0; i < n; i++) Dsqrt[i][i] = Math.sqrt(Math.max(values[i].re, 0));
5068
+ return matMul(matMul(Q, Dsqrt), Qinv);
5069
+ }
5070
+ function sqrtmQuasiTriangular(T) {
5071
+ const n = T.length;
5072
+ const U = Array.from({ length: n }, () => new Array(n).fill(0));
5073
+ const blockStart = [];
5074
+ const blockSize = [];
5075
+ let i = 0;
5076
+ while (i < n) if (i === n - 1 || Math.abs(T[i + 1][i]) < 1e-12) {
5077
+ blockStart.push(i);
5078
+ blockSize.push(1);
5079
+ i++;
5080
+ } else {
5081
+ blockStart.push(i);
5082
+ blockSize.push(2);
5083
+ i += 2;
5084
+ }
5085
+ const numBlocks = blockStart.length;
5086
+ for (let b = 0; b < numBlocks; b++) {
5087
+ const r = blockStart[b];
5088
+ if (blockSize[b] === 1) {
5089
+ if (T[r][r] < 0) return null;
5090
+ U[r][r] = Math.sqrt(T[r][r]);
5091
+ } else {
5092
+ const a = T[r][r];
5093
+ const b2 = T[r][r + 1];
5094
+ const c = T[r + 1][r];
5095
+ const d = T[r + 1][r + 1];
5096
+ const detM = a * d - b2 * c;
5097
+ const trM = a + d;
5098
+ if (detM < 0) return null;
5099
+ const sqrtDet = Math.sqrt(detM);
5100
+ const tauSq = trM + 2 * sqrtDet;
5101
+ if (tauSq < 0) return null;
5102
+ const tau = Math.sqrt(tauSq);
5103
+ if (Math.abs(tau) < 1e-14) return null;
5104
+ U[r][r] = (a + sqrtDet) / tau;
5105
+ U[r][r + 1] = b2 / tau;
5106
+ U[r + 1][r] = c / tau;
5107
+ U[r + 1][r + 1] = (d + sqrtDet) / tau;
5108
+ }
5109
+ }
5110
+ for (let bj = 1; bj < numBlocks; bj++) for (let bi = bj - 1; bi >= 0; bi--) {
5111
+ const ri = blockStart[bi];
5112
+ const rj = blockStart[bj];
5113
+ const si = blockSize[bi];
5114
+ const sj = blockSize[bj];
5115
+ const RHS = Array.from({ length: si }, (_, ii) => Array.from({ length: sj }, (_, jj) => T[ri + ii][rj + jj]));
5116
+ for (let bk = bi + 1; bk < bj; bk++) {
5117
+ const rk = blockStart[bk];
5118
+ const sk = blockSize[bk];
5119
+ for (let ii = 0; ii < si; ii++) for (let jj = 0; jj < sj; jj++) {
5120
+ let sum = 0;
5121
+ for (let kk = 0; kk < sk; kk++) sum += U[ri + ii][rk + kk] * U[rk + kk][rj + jj];
5122
+ RHS[ii][jj] -= sum;
5123
+ }
5124
+ }
5125
+ const total = si * sj;
5126
+ const MAT = Array.from({ length: total }, () => new Array(total).fill(0));
5127
+ const rhs = new Array(total).fill(0);
5128
+ for (let ii = 0; ii < si; ii++) for (let jj = 0; jj < sj; jj++) {
5129
+ const eq = ii * sj + jj;
5130
+ for (let kk = 0; kk < si; kk++) MAT[eq][kk * sj + jj] += U[ri + ii][ri + kk];
5131
+ for (let kk = 0; kk < sj; kk++) MAT[eq][ii * sj + kk] += U[rj + kk][rj + jj];
5132
+ rhs[eq] = RHS[ii][jj];
5133
+ }
5134
+ const sol = solveLinearSystem(MAT, rhs);
5135
+ if (sol === null) return null;
5136
+ for (let ii = 0; ii < si; ii++) for (let jj = 0; jj < sj; jj++) U[ri + ii][rj + jj] = sol[ii * sj + jj];
5137
+ }
5138
+ return U;
5139
+ }
5140
+ function solveLinearSystem(A, b) {
5141
+ const solved = gaussJordanSolve(A, b.map((value) => [value]));
5142
+ if (solved === null) return null;
5143
+ return solved.map((row) => row[0]);
5144
+ }
5145
+ function sqrtmSchur(A) {
5146
+ const { H: T, Q } = schurInternal(A);
5147
+ const U = sqrtmQuasiTriangular(T);
5148
+ if (U === null) return null;
5149
+ const Qt = transpose$1(Q);
5150
+ return matMul(matMul(Q, U), Qt);
5151
+ }
5152
+ function matrixSqrtm(A, opts) {
5153
+ const n = A.rows;
5154
+ if (n !== A.cols) throw new Error(`matrixSqrtm: matrix must be square (got ${A.rows}×${A.cols})`);
5155
+ if (n === 0) return DenseMatrix.zeros(0, 0);
5156
+ if (n === 1) {
5157
+ const val = A.get(0, 0);
5158
+ if (val < 0) throw new Error(`matrixSqrtm: negative scalar (${val}) has no real square root`);
5159
+ return DenseMatrix.fromArray([[Math.sqrt(val)]]);
5160
+ }
5161
+ const Aarr = A.toArray();
5162
+ const isSymm = (opts?.assumeSymmetric ?? false) || isSymmetricMatrix(Aarr);
5163
+ let result;
5164
+ if (isSymm) result = sqrtmSymmetric(Aarr);
5165
+ else {
5166
+ const schurResult = sqrtmSchur(Aarr);
5167
+ if (schurResult !== null) result = schurResult;
5168
+ else result = sqrtmGeneral(Aarr);
5169
+ }
5170
+ const data = new Float64Array(n * n);
5171
+ for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) data[i * n + j] = result[i][j];
5172
+ return new DenseMatrix(n, n, data);
5173
+ }
5174
+ function isSymmetricMatrix(A, tol = 1e-8) {
5175
+ const n = A.length;
5176
+ for (let i = 0; i < n; i++) for (let j = i + 1; j < n; j++) if (Math.abs(A[i][j] - A[j][i]) > tol) return false;
5177
+ return true;
5178
+ }
5179
+ function matrixSqrtNewtonInternal(A) {
5180
+ const n = A.length;
5181
+ let Y = eye(n);
5182
+ for (let iter = 0; iter < 150; iter++) {
5183
+ const step = newtonSqrtUpdate(A, Y);
5184
+ if (step === null) break;
5185
+ Y = step.next;
5186
+ if (step.diff < 1e-14) break;
5362
5187
  }
5363
5188
  return Y;
5364
5189
  }
5190
+ //#endregion
5191
+ //#region src/operations/logm.ts
5192
+ init_DenseMatrix();
5365
5193
  const GL16_NODES = [
5366
5194
  .00529953674226076,
5367
5195
  .02771248846338012,
@@ -5401,24 +5229,7 @@ const GL16_WEIGHTS = [
5401
5229
  function solveCol(M, b) {
5402
5230
  const n = M.length;
5403
5231
  const Aug = M.map((row, i) => [...row, b[i]]);
5404
- for (let col = 0; col < n; col++) {
5405
- let maxRow = col;
5406
- let maxVal = Math.abs(Aug[col][col]);
5407
- for (let row = col + 1; row < n; row++) if (Math.abs(Aug[row][col]) > maxVal) {
5408
- maxVal = Math.abs(Aug[row][col]);
5409
- maxRow = row;
5410
- }
5411
- if (maxRow !== col) [Aug[col], Aug[maxRow]] = [Aug[maxRow], Aug[col]];
5412
- const pivot = Aug[col][col];
5413
- if (Math.abs(pivot) < 1e-30) continue;
5414
- for (let j = col; j <= n; j++) Aug[col][j] /= pivot;
5415
- for (let row = 0; row < n; row++) {
5416
- if (row === col) continue;
5417
- const f = Aug[row][col];
5418
- if (f === 0) continue;
5419
- for (let j = col; j <= n; j++) Aug[row][j] -= f * Aug[col][j];
5420
- }
5421
- }
5232
+ gaussJordanContinue(Aug, n, 1e-30);
5422
5233
  return Aug.map((row) => row[n]);
5423
5234
  }
5424
5235
  function logPade(X) {
@@ -5496,7 +5307,7 @@ function logmEig(A) {
5496
5307
  if (v.re <= 0) throw new Error("matrixLogm: non-positive eigenvalue detected — principal logarithm is undefined (eigenvalue = " + v.re + ")");
5497
5308
  }
5498
5309
  const Q = transpose$1(vectors);
5499
- const Qinv = matInv$1(Q);
5310
+ const Qinv = matInv(Q);
5500
5311
  if (Qinv === null) throw new Error("matrixLogm: eigenvector matrix is singular — matrix appears to be non-diagonalisable (Slice 5.9a limitation; full Schur-based implementation deferred to Slice 5.9b)");
5501
5312
  const D = eye(n);
5502
5313
  for (let i = 0; i < n; i++) D[i][i] = Math.log(values[i].re);
@@ -5520,7 +5331,7 @@ function matrixLogm(A, opts) {
5520
5331
  const maxSqrt = 64;
5521
5332
  while (numSqrt < maxSqrt) {
5522
5333
  if (norm1(M.map((row, i) => row.map((v, j) => v - (i === j ? 1 : 0)))) < tol) break;
5523
- const sqrtM = matSqrt(M);
5334
+ const sqrtM = matrixSqrtNewtonInternal(M);
5524
5335
  if (!isFinite(normInf(sqrtM))) break;
5525
5336
  M = sqrtM;
5526
5337
  numSqrt++;
@@ -5538,234 +5349,6 @@ function matrixLogm(A, opts) {
5538
5349
  return new DenseMatrix(n, n, data);
5539
5350
  }
5540
5351
  //#endregion
5541
- //#region src/operations/sqrtm.ts
5542
- init_DenseMatrix();
5543
- function symmetrize(A) {
5544
- const n = A.length;
5545
- return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (A[i][j] + A[j][i]) / 2));
5546
- }
5547
- function matInv(A) {
5548
- const n = A.length;
5549
- const M = A.map((row, i) => {
5550
- const r = new Array(2 * n).fill(0);
5551
- for (let j = 0; j < n; j++) r[j] = row[j];
5552
- r[n + i] = 1;
5553
- return r;
5554
- });
5555
- for (let col = 0; col < n; col++) {
5556
- let maxRow = col;
5557
- let maxVal = Math.abs(M[col][col]);
5558
- for (let row = col + 1; row < n; row++) if (Math.abs(M[row][col]) > maxVal) {
5559
- maxVal = Math.abs(M[row][col]);
5560
- maxRow = row;
5561
- }
5562
- if (maxRow !== col) [M[col], M[maxRow]] = [M[maxRow], M[col]];
5563
- const pivot = M[col][col];
5564
- if (Math.abs(pivot) < 1e-15) return null;
5565
- for (let j = 0; j < 2 * n; j++) M[col][j] /= pivot;
5566
- for (let row = 0; row < n; row++) {
5567
- if (row === col) continue;
5568
- const f = M[row][col];
5569
- if (f === 0) continue;
5570
- for (let j = 0; j < 2 * n; j++) M[row][j] -= f * M[col][j];
5571
- }
5572
- }
5573
- return M.map((row) => row.slice(n));
5574
- }
5575
- function gramSchmidt(A) {
5576
- const m = A.length;
5577
- const n = A[0].length;
5578
- const Q = Array.from({ length: m }, () => new Array(n).fill(0));
5579
- for (let j = 0; j < n; j++) {
5580
- const v = A.map((row) => row[j]);
5581
- for (let k = 0; k < j; k++) {
5582
- let dot = 0;
5583
- for (let i = 0; i < m; i++) dot += Q[i][k] * v[i];
5584
- for (let i = 0; i < m; i++) v[i] -= dot * Q[i][k];
5585
- }
5586
- let norm = 0;
5587
- for (let i = 0; i < m; i++) norm += v[i] * v[i];
5588
- norm = Math.sqrt(norm);
5589
- if (norm < 1e-14) for (let i = 0; i < m; i++) Q[i][j] = i === j ? 1 : 0;
5590
- else for (let i = 0; i < m; i++) Q[i][j] = v[i] / norm;
5591
- }
5592
- return Q;
5593
- }
5594
- function sqrtmSymmetric(A) {
5595
- const n = A.length;
5596
- const Asym = symmetrize(A);
5597
- const { values, vectors } = eig(Asym, { computeVectors: true });
5598
- for (const v of values) if (v.re < -1e-8) throw new Error(`matrixSqrtm: negative eigenvalue (${v.re}) — matrix is not positive semi-definite`);
5599
- const Ynewton = sqrtmNewton(Asym);
5600
- if (Ynewton !== null) return Ynewton;
5601
- const Q = gramSchmidt(transpose$1(vectors));
5602
- const Qt = transpose$1(Q);
5603
- const Dsqrt = eye(n);
5604
- for (let i = 0; i < n; i++) Dsqrt[i][i] = Math.sqrt(Math.max(values[i].re, 0));
5605
- return matMul(matMul(Q, Dsqrt), Qt);
5606
- }
5607
- function sqrtmNewton(A) {
5608
- const n = A.length;
5609
- let Y = eye(n);
5610
- for (let iter = 0; iter < 150; iter++) {
5611
- const Yinv = matInv(Y);
5612
- if (Yinv === null) return null;
5613
- const AYinv = matMul(A, Yinv);
5614
- const Ynew = Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (Y[i][j] + AYinv[i][j]) / 2));
5615
- let diff = 0;
5616
- for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) diff = Math.max(diff, Math.abs(Ynew[i][j] - Y[i][j]));
5617
- Y = Ynew;
5618
- if (diff < 1e-13) return Y;
5619
- }
5620
- const Y2 = matMul(Y, Y);
5621
- let err = 0;
5622
- for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) err = Math.max(err, Math.abs(Y2[i][j] - A[i][j]));
5623
- return err < 1e-6 ? Y : null;
5624
- }
5625
- function sqrtmGeneral(A) {
5626
- const n = A.length;
5627
- const { values, vectors } = eig(A, { computeVectors: true });
5628
- for (const v of values) {
5629
- if (Math.abs(v.im) > 1e-7) throw new Error("matrixSqrtm: complex eigenvalues detected — real square root not supported");
5630
- if (v.re < -1e-7) throw new Error(`matrixSqrtm: negative eigenvalue (${v.re}) — principal square root not real`);
5631
- }
5632
- const Ynewton = sqrtmNewton(A);
5633
- if (Ynewton !== null) return Ynewton;
5634
- const Q = transpose$1(vectors);
5635
- const Qinv = matInv(Q);
5636
- if (Qinv === null) throw new Error("matrixSqrtm: eigenvector matrix is singular — matrix appears to be non-diagonalisable");
5637
- const Dsqrt = eye(n);
5638
- for (let i = 0; i < n; i++) Dsqrt[i][i] = Math.sqrt(Math.max(values[i].re, 0));
5639
- return matMul(matMul(Q, Dsqrt), Qinv);
5640
- }
5641
- function sqrtmQuasiTriangular(T) {
5642
- const n = T.length;
5643
- const U = Array.from({ length: n }, () => new Array(n).fill(0));
5644
- const blockStart = [];
5645
- const blockSize = [];
5646
- let i = 0;
5647
- while (i < n) if (i === n - 1 || Math.abs(T[i + 1][i]) < 1e-12) {
5648
- blockStart.push(i);
5649
- blockSize.push(1);
5650
- i++;
5651
- } else {
5652
- blockStart.push(i);
5653
- blockSize.push(2);
5654
- i += 2;
5655
- }
5656
- const numBlocks = blockStart.length;
5657
- for (let b = 0; b < numBlocks; b++) {
5658
- const r = blockStart[b];
5659
- if (blockSize[b] === 1) {
5660
- if (T[r][r] < 0) return null;
5661
- U[r][r] = Math.sqrt(T[r][r]);
5662
- } else {
5663
- const a = T[r][r];
5664
- const b2 = T[r][r + 1];
5665
- const c = T[r + 1][r];
5666
- const d = T[r + 1][r + 1];
5667
- const detM = a * d - b2 * c;
5668
- const trM = a + d;
5669
- if (detM < 0) return null;
5670
- const sqrtDet = Math.sqrt(detM);
5671
- const tauSq = trM + 2 * sqrtDet;
5672
- if (tauSq < 0) return null;
5673
- const tau = Math.sqrt(tauSq);
5674
- if (Math.abs(tau) < 1e-14) return null;
5675
- U[r][r] = (a + sqrtDet) / tau;
5676
- U[r][r + 1] = b2 / tau;
5677
- U[r + 1][r] = c / tau;
5678
- U[r + 1][r + 1] = (d + sqrtDet) / tau;
5679
- }
5680
- }
5681
- for (let bj = 1; bj < numBlocks; bj++) for (let bi = bj - 1; bi >= 0; bi--) {
5682
- const ri = blockStart[bi];
5683
- const rj = blockStart[bj];
5684
- const si = blockSize[bi];
5685
- const sj = blockSize[bj];
5686
- const RHS = Array.from({ length: si }, (_, ii) => Array.from({ length: sj }, (_, jj) => T[ri + ii][rj + jj]));
5687
- for (let bk = bi + 1; bk < bj; bk++) {
5688
- const rk = blockStart[bk];
5689
- const sk = blockSize[bk];
5690
- for (let ii = 0; ii < si; ii++) for (let jj = 0; jj < sj; jj++) {
5691
- let sum = 0;
5692
- for (let kk = 0; kk < sk; kk++) sum += U[ri + ii][rk + kk] * U[rk + kk][rj + jj];
5693
- RHS[ii][jj] -= sum;
5694
- }
5695
- }
5696
- const total = si * sj;
5697
- const MAT = Array.from({ length: total }, () => new Array(total).fill(0));
5698
- const rhs = new Array(total).fill(0);
5699
- for (let ii = 0; ii < si; ii++) for (let jj = 0; jj < sj; jj++) {
5700
- const eq = ii * sj + jj;
5701
- for (let kk = 0; kk < si; kk++) MAT[eq][kk * sj + jj] += U[ri + ii][ri + kk];
5702
- for (let kk = 0; kk < sj; kk++) MAT[eq][ii * sj + kk] += U[rj + kk][rj + jj];
5703
- rhs[eq] = RHS[ii][jj];
5704
- }
5705
- const sol = solveLinearSystem(MAT, rhs);
5706
- if (sol === null) return null;
5707
- for (let ii = 0; ii < si; ii++) for (let jj = 0; jj < sj; jj++) U[ri + ii][rj + jj] = sol[ii * sj + jj];
5708
- }
5709
- return U;
5710
- }
5711
- function solveLinearSystem(A, b) {
5712
- const n = A.length;
5713
- const Aug = A.map((row, i) => [...row, b[i]]);
5714
- for (let col = 0; col < n; col++) {
5715
- let maxRow = col;
5716
- let maxVal = Math.abs(Aug[col][col]);
5717
- for (let row = col + 1; row < n; row++) if (Math.abs(Aug[row][col]) > maxVal) {
5718
- maxVal = Math.abs(Aug[row][col]);
5719
- maxRow = row;
5720
- }
5721
- if (maxRow !== col) [Aug[col], Aug[maxRow]] = [Aug[maxRow], Aug[col]];
5722
- const pivot = Aug[col][col];
5723
- if (Math.abs(pivot) < 1e-15) return null;
5724
- for (let j = col; j <= n; j++) Aug[col][j] /= pivot;
5725
- for (let row = 0; row < n; row++) {
5726
- if (row === col) continue;
5727
- const f = Aug[row][col];
5728
- if (f === 0) continue;
5729
- for (let j = col; j <= n; j++) Aug[row][j] -= f * Aug[col][j];
5730
- }
5731
- }
5732
- return Aug.map((row) => row[n]);
5733
- }
5734
- function sqrtmSchur(A) {
5735
- const { H: T, Q } = schurInternal(A);
5736
- const U = sqrtmQuasiTriangular(T);
5737
- if (U === null) return null;
5738
- const Qt = transpose$1(Q);
5739
- return matMul(matMul(Q, U), Qt);
5740
- }
5741
- function matrixSqrtm(A, opts) {
5742
- const n = A.rows;
5743
- if (n !== A.cols) throw new Error(`matrixSqrtm: matrix must be square (got ${A.rows}×${A.cols})`);
5744
- if (n === 0) return DenseMatrix.zeros(0, 0);
5745
- if (n === 1) {
5746
- const val = A.get(0, 0);
5747
- if (val < 0) throw new Error(`matrixSqrtm: negative scalar (${val}) has no real square root`);
5748
- return DenseMatrix.fromArray([[Math.sqrt(val)]]);
5749
- }
5750
- const Aarr = A.toArray();
5751
- const isSymm = (opts?.assumeSymmetric ?? false) || isSymmetricMatrix(Aarr);
5752
- let result;
5753
- if (isSymm) result = sqrtmSymmetric(Aarr);
5754
- else {
5755
- const schurResult = sqrtmSchur(Aarr);
5756
- if (schurResult !== null) result = schurResult;
5757
- else result = sqrtmGeneral(Aarr);
5758
- }
5759
- const data = new Float64Array(n * n);
5760
- for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) data[i * n + j] = result[i][j];
5761
- return new DenseMatrix(n, n, data);
5762
- }
5763
- function isSymmetricMatrix(A, tol = 1e-8) {
5764
- const n = A.length;
5765
- for (let i = 0; i < n; i++) for (let j = i + 1; j < n; j++) if (Math.abs(A[i][j] - A[j][i]) > tol) return false;
5766
- return true;
5767
- }
5768
- //#endregion
5769
5352
  //#region src/operations/qr-pivoted.ts
5770
5353
  init_DenseMatrix();
5771
5354
  function qrPivoted(A, opts) {
@@ -5841,21 +5424,20 @@ function qrPivoted(A, opts) {
5841
5424
  //#endregion
5842
5425
  //#region src/operations/qr-family.ts
5843
5426
  init_DenseMatrix();
5844
- function flipRows(M) {
5427
+ function flipDense(M, axis) {
5845
5428
  const m = M.rows;
5846
5429
  const n = M.cols;
5847
5430
  const src = M.toFloat64Array();
5848
5431
  const data = new Float64Array(m * n);
5849
- for (let i = 0; i < m; i++) for (let j = 0; j < n; j++) data[i * n + j] = src[(m - 1 - i) * n + j];
5432
+ if (axis === 0) for (let i = 0; i < m; i++) for (let j = 0; j < n; j++) data[i * n + j] = src[(m - 1 - i) * n + j];
5433
+ else for (let i = 0; i < m; i++) for (let j = 0; j < n; j++) data[i * n + j] = src[i * n + (n - 1 - j)];
5850
5434
  return new DenseMatrix(m, n, data);
5851
5435
  }
5436
+ function flipRows(M) {
5437
+ return flipDense(M, 0);
5438
+ }
5852
5439
  function flipCols(M) {
5853
- const m = M.rows;
5854
- const n = M.cols;
5855
- const src = M.toFloat64Array();
5856
- const data = new Float64Array(m * n);
5857
- for (let i = 0; i < m; i++) for (let j = 0; j < n; j++) data[i * n + j] = src[i * n + (n - 1 - j)];
5858
- return new DenseMatrix(m, n, data);
5440
+ return flipDense(M, 1);
5859
5441
  }
5860
5442
  function lq(A) {
5861
5443
  const { Q: Q1, R: R1 } = qr(A.transpose(), { mode: "reduced" });
@@ -6199,6 +5781,10 @@ function matrixToFloat64(m) {
6199
5781
  function float64ToMatrix(data, rows, cols) {
6200
5782
  return new DenseMatrix(rows, cols, data);
6201
5783
  }
5784
+ async function densePair(a, b, op, mismatch) {
5785
+ if (a.rows !== b.rows || a.cols !== b.cols) throw new Error(mismatch(a, b));
5786
+ return float64ToMatrix((await op(matrixToFloat64(a), matrixToFloat64(b))).result, a.rows, a.cols);
5787
+ }
6202
5788
  const parallelMatrix = mathTyped("parallelMatrix", {
6203
5789
  Array: (arr) => DenseMatrix.fromArray(arr),
6204
5790
  "number, number": (rows, cols) => DenseMatrix.zeros(rows, cols),
@@ -6215,10 +5801,7 @@ const parallelDiag = mathTyped("parallelDiag", {
6215
5801
  });
6216
5802
  const parallelRandom = mathTyped("parallelRandom", { "number, number": (rows, cols) => DenseMatrix.random(rows, cols) });
6217
5803
  const parallelMatrixAdd = mathTyped("parallelMatrixAdd", {
6218
- "DenseMatrix, DenseMatrix": async (a, b) => {
6219
- if (a.rows !== b.rows || a.cols !== b.cols) throw new Error(`Matrix dimensions must match: ${a.rows}×${a.cols} vs ${b.rows}×${b.cols}`);
6220
- return float64ToMatrix((await pAdd(matrixToFloat64(a), matrixToFloat64(b))).result, a.rows, a.cols);
6221
- },
5804
+ "DenseMatrix, DenseMatrix": (a, b) => densePair(a, b, pAdd, (left, right) => `Matrix dimensions must match: ${left.rows}×${left.cols} vs ${right.rows}×${right.cols}`),
6222
5805
  "DenseMatrix, number": async (a, scalar) => {
6223
5806
  const dataA = matrixToFloat64(a);
6224
5807
  return float64ToMatrix((await pAdd(dataA, new Float64Array(dataA.length).fill(scalar))).result, a.rows, a.cols);
@@ -6232,10 +5815,7 @@ const parallelMatrixAdd = mathTyped("parallelMatrixAdd", {
6232
5815
  "number, number": (a, b) => a + b
6233
5816
  });
6234
5817
  const parallelMatrixSubtract = mathTyped("parallelMatrixSubtract", {
6235
- "DenseMatrix, DenseMatrix": async (a, b) => {
6236
- if (a.rows !== b.rows || a.cols !== b.cols) throw new Error(`Matrix dimensions must match: ${a.rows}×${a.cols} vs ${b.rows}×${b.cols}`);
6237
- return float64ToMatrix((await pSubtract(matrixToFloat64(a), matrixToFloat64(b))).result, a.rows, a.cols);
6238
- },
5818
+ "DenseMatrix, DenseMatrix": (a, b) => densePair(a, b, pSubtract, (left, right) => `Matrix dimensions must match: ${left.rows}×${left.cols} vs ${right.rows}×${right.cols}`),
6239
5819
  "DenseMatrix, number": async (a, scalar) => {
6240
5820
  const dataA = matrixToFloat64(a);
6241
5821
  return float64ToMatrix((await pSubtract(dataA, new Float64Array(dataA.length).fill(scalar))).result, a.rows, a.cols);
@@ -6265,10 +5845,7 @@ const parallelMatrixMultiply = mathTyped("parallelMatrixMultiply", {
6265
5845
  "number, number": (a, b) => a * b
6266
5846
  });
6267
5847
  const parallelDotMultiply = mathTyped("parallelDotMultiply", {
6268
- "DenseMatrix, DenseMatrix": async (a, b) => {
6269
- if (a.rows !== b.rows || a.cols !== b.cols) throw new Error(`Matrix dimensions must match for element-wise multiply`);
6270
- return float64ToMatrix((await pMultiply(matrixToFloat64(a), matrixToFloat64(b))).result, a.rows, a.cols);
6271
- },
5848
+ "DenseMatrix, DenseMatrix": (a, b) => densePair(a, b, pMultiply, () => `Matrix dimensions must match for element-wise multiply`),
6272
5849
  "Float64Array, Float64Array": async (a, b) => {
6273
5850
  return (await pMultiply(a, b)).result;
6274
5851
  },
@@ -6282,10 +5859,7 @@ const parallelMatrixDivide = mathTyped("parallelMatrixDivide", {
6282
5859
  const dataA = matrixToFloat64(a);
6283
5860
  return float64ToMatrix((await pDivide(new Float64Array(dataA.length).fill(scalar), dataA)).result, a.rows, a.cols);
6284
5861
  },
6285
- "DenseMatrix, DenseMatrix": async (a, b) => {
6286
- if (a.rows !== b.rows || a.cols !== b.cols) throw new Error(`Matrix dimensions must match for element-wise divide`);
6287
- return float64ToMatrix((await pDivide(matrixToFloat64(a), matrixToFloat64(b))).result, a.rows, a.cols);
6288
- },
5862
+ "DenseMatrix, DenseMatrix": (a, b) => densePair(a, b, pDivide, () => `Matrix dimensions must match for element-wise divide`),
6289
5863
  "Float64Array, Float64Array": async (a, b) => {
6290
5864
  return (await pDivide(a, b)).result;
6291
5865
  },
@@ -6584,4 +6158,4 @@ init_Matrix();
6584
6158
  init_SparseMatrix();
6585
6159
  init_DenseMatrix();
6586
6160
  //#endregion
6587
- export { BUILTIN_SHADERS, BackendManager, BackendRegistry, BatchExecutor, BufferPool, DEFAULT_BACKEND_HINTS, DEFAULT_EXTENDED_HINTS, DenseMatrix, GPUBackend, GPUContext, GPUMatrixBackend, JSBackend, Matrix, ParallelBackend, ShaderManager, SparseMatrix, SyncManager, WASMBackend, abs, add, backendManager, backendRegistry, cholesky, clearFeatureCache, column, cond, condest, createBackendManager, createGPUMatrixBackend, createParallelBackend, createSyncManager, createWASMBackend, destroyGlobalGPU, destroyGlobalGPUBackend, detectGPUCapabilities, detectWasmFeatures, diag, diagonal, divide, dotMultiply, eig, eigWasm, eigvals, eigvalsWasm, exp, getCachedFeatures, getGlobalGPUBackend, getGlobalGPUContext, getRecommendedWorkgroupSize, gpuMatrixBackend, hasWebGPU, identity, initializeGlobalGPUBackend, initializeParallelMatrix, isAtomicsAvailable, isDenseMatrix, isMatrix, isSharedMemoryAvailable, isSparseMatrix, isWasmAvailable, jsBackend, log, lowRankApprox, lq, lu, luSolve, matrix, matrixExpm, matrixLogm, pinv as matrixPinv, matrixSchur, matrixSqrtm, max, mean, min, multiply, norm, norm2, normFro, ones, parallelBackend, parallelDiag, parallelDotMultiply, parallelIdentity, parallelMatrix, parallelMatrixAbs, parallelMatrixAdd, parallelMatrixColumn, parallelMatrixCos, parallelMatrixDiagonal, parallelMatrixDistance, parallelMatrixDivide, parallelMatrixDot, parallelMatrixExp, parallelMatrixHistogram, parallelMatrixLog, parallelMatrixMatvec, parallelMatrixMax, parallelMatrixMean, parallelMatrixMin, parallelMatrixMultiply, parallelMatrixNorm, parallelMatrixOperations, parallelMatrixOuter, parallelMatrixRow, parallelMatrixSin, parallelMatrixSize, parallelMatrixSqrt, parallelMatrixSquare, parallelMatrixStd, parallelMatrixSubset, parallelMatrixSubtract, parallelMatrixSum, parallelMatrixTan, parallelMatrixTrace, parallelMatrixTranspose, parallelMatrixVariance, parallelOnes, parallelRandom, parallelUnaryMinus, parallelZeros, pinv$1 as pinv, pow, powerIteration, ql, qr, qrPivoted, random, row, rq, singularValues, size, spectralRadiusWasm, sqrt, square, subset, subtract, sum, svd, svdWasm, terminateParallelMatrix, trace, transpose, typedMatrixOperations, unaryMinus, wasmBackend, zeros };
6161
+ export { BUILTIN_SHADERS, BackendManager, BackendRegistry, BatchExecutor, BufferPool, DEFAULT_BACKEND_HINTS, DEFAULT_EXTENDED_HINTS, DenseMatrix, GPUBackend, GPUContext, GPUMatrixBackend, JSBackend, Matrix, ParallelBackend, ShaderManager, SparseMatrix, SyncManager, WASMBackend, abs, add, backendManager, backendRegistry, cholesky, clearFeatureCache, column, cond, condest, createBackendManager, createGPUMatrixBackend, createParallelBackend, createSyncManager, createWASMBackend, destroyGlobalGPU, destroyGlobalGPUBackend, detectGPUCapabilities, detectWasmFeatures, diag, diagonal, divide, dotMultiply, eig, eigWasm, eigvals, eigvalsWasm, exp, getCachedFeatures, getGlobalGPUBackend, getGlobalGPUContext, getRecommendedWorkgroupSize, gpuMatrixBackend, hasWebGPU, identity, initializeGlobalGPUBackend, initializeParallelMatrix, isAtomicsAvailable, isDenseMatrix, isMatrix, isSharedMemoryAvailable, isSparseMatrix, isWasmAvailable, jsBackend, log, lowRankApprox, lq, lu, luSolve, matMul, matrix, matrixExpm, matrixLogm, pinv as matrixPinv, matrixSchur, matrixSqrtm, max, mean, min, multiply, norm, norm2, normFro, ones, parallelBackend, parallelDiag, parallelDotMultiply, parallelIdentity, parallelMatrix, parallelMatrixAbs, parallelMatrixAdd, parallelMatrixColumn, parallelMatrixCos, parallelMatrixDiagonal, parallelMatrixDistance, parallelMatrixDivide, parallelMatrixDot, parallelMatrixExp, parallelMatrixHistogram, parallelMatrixLog, parallelMatrixMatvec, parallelMatrixMax, parallelMatrixMean, parallelMatrixMin, parallelMatrixMultiply, parallelMatrixNorm, parallelMatrixOperations, parallelMatrixOuter, parallelMatrixRow, parallelMatrixSin, parallelMatrixSize, parallelMatrixSqrt, parallelMatrixSquare, parallelMatrixStd, parallelMatrixSubset, parallelMatrixSubtract, parallelMatrixSum, parallelMatrixTan, parallelMatrixTrace, parallelMatrixTranspose, parallelMatrixVariance, parallelOnes, parallelRandom, parallelUnaryMinus, parallelZeros, pinv$1 as pinv, pow, powerIteration, ql, qr, qrPivoted, random, row, rq, singularValues, size, spectralRadiusWasm, sqrt, square, subset, subtract, sum, svd, svdWasm, terminateParallelMatrix, trace, transpose, transpose$1 as transposeNestedArray, typedMatrixOperations, unaryMinus, wasmBackend, zeros };