@danielsimonjr/mathts-matrix 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backends/JSBackend.d.ts.map +1 -1
- package/dist/backends/ParallelBackend.d.ts.map +1 -1
- package/dist/index.js +857 -812
- package/dist/types/DenseMatrix.d.ts +10 -3
- package/dist/types/DenseMatrix.d.ts.map +1 -1
- package/dist/types/SparseMatrix.d.ts +8 -0
- package/dist/types/SparseMatrix.d.ts.map +1 -1
- package/dist/types/dense/arithmetic.d.ts.map +1 -1
- package/dist/types/dense/reduction.d.ts.map +1 -1
- package/dist/types/dense/storage.d.ts +23 -0
- package/dist/types/dense/storage.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,102 +2,78 @@ import { BufferPool, BufferPool as BufferPool$1, GPUContext, GPUContext as GPUCo
|
|
|
2
2
|
import { ComputePool, computePool } from "@danielsimonjr/mathts-parallel";
|
|
3
3
|
import { allocAsHeader } from "@danielsimonjr/mathts-core/internal";
|
|
4
4
|
import { mathTyped } from "@danielsimonjr/mathts-core";
|
|
5
|
-
//#region
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
return fn && (res = fn(fn = 0)), res;
|
|
14
|
-
} catch (e) {
|
|
15
|
-
throw err = [e], e;
|
|
5
|
+
//#region src/types/Matrix.ts
|
|
6
|
+
var Matrix = class {
|
|
7
|
+
get size() {
|
|
8
|
+
return {
|
|
9
|
+
rows: this.rows,
|
|
10
|
+
cols: this.cols
|
|
11
|
+
};
|
|
16
12
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
13
|
+
get isSquare() {
|
|
14
|
+
return this.rows === this.cols;
|
|
15
|
+
}
|
|
16
|
+
get isVector() {
|
|
17
|
+
return this.rows === 1 || this.cols === 1;
|
|
18
|
+
}
|
|
19
|
+
get isRowVector() {
|
|
20
|
+
return this.rows === 1;
|
|
21
|
+
}
|
|
22
|
+
get isColumnVector() {
|
|
23
|
+
return this.cols === 1;
|
|
24
|
+
}
|
|
25
|
+
get length() {
|
|
26
|
+
return this.rows * this.cols;
|
|
27
|
+
}
|
|
28
|
+
checkBounds(row, col) {
|
|
29
|
+
if (row < 0 || row >= this.rows || col < 0 || col >= this.cols) throw new RangeError(`Index (${row}, ${col}) out of bounds for matrix of size ${this.rows}×${this.cols}`);
|
|
30
|
+
}
|
|
31
|
+
checkDimensionsMatch(other) {
|
|
32
|
+
if (this.rows !== other.rows || this.cols !== other.cols) throw new Error(`Matrix dimensions must match: ${this.rows}×${this.cols} vs ${other.rows}×${other.cols}`);
|
|
33
|
+
}
|
|
34
|
+
checkMultiplyDimensions(other) {
|
|
35
|
+
if (this.cols !== other.rows) throw new Error(`Cannot multiply ${this.rows}×${this.cols} matrix with ${other.rows}×${other.cols} matrix`);
|
|
36
|
+
}
|
|
37
|
+
toString() {
|
|
38
|
+
const lines = [];
|
|
39
|
+
for (let i = 0; i < this.rows; i++) {
|
|
40
|
+
const rowValues = [];
|
|
41
|
+
for (let j = 0; j < this.cols; j++) rowValues.push(String(this.get(i, j)));
|
|
42
|
+
lines.push(`[ ${rowValues.join(", ")} ]`);
|
|
43
|
+
}
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
}
|
|
46
|
+
equals(other, tolerance = 0) {
|
|
47
|
+
if (this.rows !== other.rows || this.cols !== other.cols) return false;
|
|
48
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) {
|
|
49
|
+
const a = this.get(i, j);
|
|
50
|
+
const b = other.get(i, j);
|
|
51
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
52
|
+
if (Math.abs(a - b) > tolerance) return false;
|
|
53
|
+
} else if (a !== b) return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
34
56
|
}
|
|
35
|
-
return to;
|
|
36
57
|
};
|
|
37
|
-
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/types/Matrix.ts
|
|
40
58
|
function isMatrix(value) {
|
|
41
59
|
return value instanceof Matrix || typeof value === "object" && value !== null && "rows" in value && "cols" in value && "get" in value && typeof value.type === "string";
|
|
42
60
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
get isVector() {
|
|
56
|
-
return this.rows === 1 || this.cols === 1;
|
|
57
|
-
}
|
|
58
|
-
get isRowVector() {
|
|
59
|
-
return this.rows === 1;
|
|
60
|
-
}
|
|
61
|
-
get isColumnVector() {
|
|
62
|
-
return this.cols === 1;
|
|
63
|
-
}
|
|
64
|
-
get length() {
|
|
65
|
-
return this.rows * this.cols;
|
|
66
|
-
}
|
|
67
|
-
checkBounds(row, col) {
|
|
68
|
-
if (row < 0 || row >= this.rows || col < 0 || col >= this.cols) throw new RangeError(`Index (${row}, ${col}) out of bounds for matrix of size ${this.rows}×${this.cols}`);
|
|
69
|
-
}
|
|
70
|
-
checkDimensionsMatch(other) {
|
|
71
|
-
if (this.rows !== other.rows || this.cols !== other.cols) throw new Error(`Matrix dimensions must match: ${this.rows}×${this.cols} vs ${other.rows}×${other.cols}`);
|
|
72
|
-
}
|
|
73
|
-
checkMultiplyDimensions(other) {
|
|
74
|
-
if (this.cols !== other.rows) throw new Error(`Cannot multiply ${this.rows}×${this.cols} matrix with ${other.rows}×${other.cols} matrix`);
|
|
75
|
-
}
|
|
76
|
-
toString() {
|
|
77
|
-
const lines = [];
|
|
78
|
-
for (let i = 0; i < this.rows; i++) {
|
|
79
|
-
const rowValues = [];
|
|
80
|
-
for (let j = 0; j < this.cols; j++) rowValues.push(String(this.get(i, j)));
|
|
81
|
-
lines.push(`[ ${rowValues.join(", ")} ]`);
|
|
82
|
-
}
|
|
83
|
-
return lines.join("\n");
|
|
84
|
-
}
|
|
85
|
-
equals(other, tolerance = 0) {
|
|
86
|
-
if (this.rows !== other.rows || this.cols !== other.cols) return false;
|
|
87
|
-
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) {
|
|
88
|
-
const a = this.get(i, j);
|
|
89
|
-
const b = other.get(i, j);
|
|
90
|
-
if (typeof a === "number" && typeof b === "number") {
|
|
91
|
-
if (Math.abs(a - b) > tolerance) return false;
|
|
92
|
-
} else if (a !== b) return false;
|
|
93
|
-
}
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
}));
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/types/dense/storage.ts
|
|
63
|
+
function isDenseStorage(m) {
|
|
64
|
+
const s = m;
|
|
65
|
+
return typeof s === "object" && s !== null && s.data instanceof Float64Array && typeof s.isView === "boolean" && typeof s.offset === "number" && typeof s.rowStride === "number" && typeof s.toFlatFloat64Array === "function";
|
|
66
|
+
}
|
|
67
|
+
function contiguousDenseData(matrix) {
|
|
68
|
+
if (!isDenseStorage(matrix)) return null;
|
|
69
|
+
if (!matrix.isView && matrix.offset === 0 && matrix.rowStride === matrix.cols) return matrix.data;
|
|
70
|
+
return matrix.toFlatFloat64Array();
|
|
71
|
+
}
|
|
98
72
|
//#endregion
|
|
99
73
|
//#region src/types/dense/arithmetic.ts
|
|
100
74
|
function flat(m) {
|
|
75
|
+
const dense = contiguousDenseData(m);
|
|
76
|
+
if (dense !== null) return dense;
|
|
101
77
|
const maybe = m;
|
|
102
78
|
if (typeof maybe.toFloat64Array === "function") return maybe.toFloat64Array();
|
|
103
79
|
const out = new Float64Array(m.rows * m.cols);
|
|
@@ -167,11 +143,15 @@ function transpose$2(a) {
|
|
|
167
143
|
}
|
|
168
144
|
return result;
|
|
169
145
|
}
|
|
170
|
-
var init_arithmetic = __esmMin((() => {}));
|
|
171
146
|
//#endregion
|
|
172
147
|
//#region src/types/dense/reduction.ts
|
|
173
148
|
function sum$1(a) {
|
|
174
149
|
let total = 0;
|
|
150
|
+
const d = contiguousDenseData(a);
|
|
151
|
+
if (d !== null) {
|
|
152
|
+
for (let i = 0; i < d.length; i++) total += d[i];
|
|
153
|
+
return total;
|
|
154
|
+
}
|
|
175
155
|
for (let i = 0; i < a.rows; i++) for (let j = 0; j < a.cols; j++) total += a.get(i, j);
|
|
176
156
|
return total;
|
|
177
157
|
}
|
|
@@ -180,6 +160,14 @@ function mean$1(a) {
|
|
|
180
160
|
}
|
|
181
161
|
function min$1(a) {
|
|
182
162
|
let minVal = Infinity;
|
|
163
|
+
const d = contiguousDenseData(a);
|
|
164
|
+
if (d !== null) {
|
|
165
|
+
for (let i = 0; i < d.length; i++) {
|
|
166
|
+
const val = d[i];
|
|
167
|
+
if (val < minVal) minVal = val;
|
|
168
|
+
}
|
|
169
|
+
return minVal;
|
|
170
|
+
}
|
|
183
171
|
for (let i = 0; i < a.rows; i++) for (let j = 0; j < a.cols; j++) {
|
|
184
172
|
const val = a.get(i, j);
|
|
185
173
|
if (val < minVal) minVal = val;
|
|
@@ -188,6 +176,14 @@ function min$1(a) {
|
|
|
188
176
|
}
|
|
189
177
|
function max$1(a) {
|
|
190
178
|
let maxVal = -Infinity;
|
|
179
|
+
const d = contiguousDenseData(a);
|
|
180
|
+
if (d !== null) {
|
|
181
|
+
for (let i = 0; i < d.length; i++) {
|
|
182
|
+
const val = d[i];
|
|
183
|
+
if (val > maxVal) maxVal = val;
|
|
184
|
+
}
|
|
185
|
+
return maxVal;
|
|
186
|
+
}
|
|
191
187
|
for (let i = 0; i < a.rows; i++) for (let j = 0; j < a.cols; j++) {
|
|
192
188
|
const val = a.get(i, j);
|
|
193
189
|
if (val > maxVal) maxVal = val;
|
|
@@ -196,6 +192,11 @@ function max$1(a) {
|
|
|
196
192
|
}
|
|
197
193
|
function norm$1(a) {
|
|
198
194
|
let sumSquared = 0;
|
|
195
|
+
const d = contiguousDenseData(a);
|
|
196
|
+
if (d !== null) {
|
|
197
|
+
for (let i = 0; i < d.length; i++) sumSquared += d[i] * d[i];
|
|
198
|
+
return Math.sqrt(sumSquared);
|
|
199
|
+
}
|
|
199
200
|
for (let i = 0; i < a.rows; i++) for (let j = 0; j < a.cols; j++) {
|
|
200
201
|
const val = a.get(i, j);
|
|
201
202
|
sumSquared += val * val;
|
|
@@ -208,729 +209,764 @@ function trace$1(a) {
|
|
|
208
209
|
for (let i = 0; i < a.rows; i++) traceSum += a.get(i, i);
|
|
209
210
|
return traceSum;
|
|
210
211
|
}
|
|
211
|
-
var init_reduction = __esmMin((() => {}));
|
|
212
212
|
//#endregion
|
|
213
|
-
//#region src/types/
|
|
214
|
-
var
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
this.
|
|
236
|
-
this.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
if (
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
for (let j = 0; j < dense.cols; j++) {
|
|
250
|
-
const val = dense.get(i, j);
|
|
251
|
-
if (Math.abs(val) > dropTolerance) {
|
|
252
|
-
values.push(val);
|
|
253
|
-
colIndices.push(j);
|
|
213
|
+
//#region src/types/DenseMatrix.ts
|
|
214
|
+
var DenseMatrix = class DenseMatrix extends Matrix {
|
|
215
|
+
type = "DenseMatrix";
|
|
216
|
+
rows;
|
|
217
|
+
cols;
|
|
218
|
+
data;
|
|
219
|
+
isView;
|
|
220
|
+
offset;
|
|
221
|
+
rowStride;
|
|
222
|
+
constructor(rows, cols, data, viewConfig) {
|
|
223
|
+
super();
|
|
224
|
+
if (!Number.isInteger(rows) || !Number.isInteger(cols)) throw new TypeError(`Matrix dimensions must be integers, got ${String(rows)}×${String(cols)}`);
|
|
225
|
+
if (rows < 0 || cols < 0) throw new Error("Matrix dimensions must be non-negative");
|
|
226
|
+
this.rows = rows;
|
|
227
|
+
this.cols = cols;
|
|
228
|
+
if (viewConfig) {
|
|
229
|
+
this.isView = viewConfig.isView;
|
|
230
|
+
this.offset = viewConfig.offset;
|
|
231
|
+
this.rowStride = viewConfig.rowStride;
|
|
232
|
+
this.data = data;
|
|
233
|
+
} else {
|
|
234
|
+
this.isView = false;
|
|
235
|
+
this.offset = 0;
|
|
236
|
+
this.rowStride = cols;
|
|
237
|
+
if (data === void 0) this.data = new Float64Array(rows * cols);
|
|
238
|
+
else if (data instanceof Float64Array) {
|
|
239
|
+
if (data.length !== rows * cols) throw new Error(`Data length ${data.length} does not match dimensions ${rows}×${cols}`);
|
|
240
|
+
this.data = data;
|
|
241
|
+
} else if (Array.isArray(data)) {
|
|
242
|
+
if (Array.isArray(data[0])) {
|
|
243
|
+
const nested = data;
|
|
244
|
+
if (nested.length !== rows) throw new Error(`Expected ${rows} rows, got ${nested.length}`);
|
|
245
|
+
this.data = new Float64Array(rows * cols);
|
|
246
|
+
for (let i = 0; i < rows; i++) {
|
|
247
|
+
if (nested[i].length !== cols) throw new Error(`Row ${i} has ${nested[i].length} elements, expected ${cols}`);
|
|
248
|
+
for (let j = 0; j < cols; j++) this.data[i * cols + j] = nested[i][j];
|
|
254
249
|
}
|
|
250
|
+
} else {
|
|
251
|
+
const flat = data;
|
|
252
|
+
if (flat.length !== rows * cols) throw new Error(`Data length ${flat.length} does not match dimensions ${rows}×${cols}`);
|
|
253
|
+
this.data = new Float64Array(flat);
|
|
255
254
|
}
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
return new SparseMatrix(dense.rows, dense.cols, new Float64Array(values), new Int32Array(colIndices), new Int32Array(rowPointers));
|
|
255
|
+
} else throw new TypeError(`DenseMatrix data must be a Float64Array, number[] or number[][], got ${typeof data}`);
|
|
259
256
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
257
|
+
}
|
|
258
|
+
static fromArray(arr) {
|
|
259
|
+
const rows = arr.length;
|
|
260
|
+
const cols = arr[0]?.length ?? 0;
|
|
261
|
+
return new DenseMatrix(rows, cols, arr);
|
|
262
|
+
}
|
|
263
|
+
static fromFlat(rows, cols, data) {
|
|
264
|
+
return new DenseMatrix(rows, cols, data);
|
|
265
|
+
}
|
|
266
|
+
static zeros(rows, cols) {
|
|
267
|
+
return new DenseMatrix(rows, cols);
|
|
268
|
+
}
|
|
269
|
+
static ones(rows, cols) {
|
|
270
|
+
const data = new Float64Array(rows * cols).fill(1);
|
|
271
|
+
return new DenseMatrix(rows, cols, data);
|
|
272
|
+
}
|
|
273
|
+
static identity(n) {
|
|
274
|
+
const data = new Float64Array(n * n);
|
|
275
|
+
for (let i = 0; i < n; i++) data[i * n + i] = 1;
|
|
276
|
+
return new DenseMatrix(n, n, data);
|
|
277
|
+
}
|
|
278
|
+
static diag(values) {
|
|
279
|
+
const n = values.length;
|
|
280
|
+
const data = new Float64Array(n * n);
|
|
281
|
+
for (let i = 0; i < n; i++) data[i * n + i] = values[i];
|
|
282
|
+
return new DenseMatrix(n, n, data);
|
|
283
|
+
}
|
|
284
|
+
static fill(rows, cols, value) {
|
|
285
|
+
const data = new Float64Array(rows * cols).fill(value);
|
|
286
|
+
return new DenseMatrix(rows, cols, data);
|
|
287
|
+
}
|
|
288
|
+
static random(rows, cols) {
|
|
289
|
+
const data = new Float64Array(rows * cols);
|
|
290
|
+
for (let i = 0; i < data.length; i++) data[i] = Math.random();
|
|
291
|
+
return new DenseMatrix(rows, cols, data);
|
|
292
|
+
}
|
|
293
|
+
get(row, col) {
|
|
294
|
+
this.checkBounds(row, col);
|
|
295
|
+
return this.data[this.offset + row * this.rowStride + col];
|
|
296
|
+
}
|
|
297
|
+
set(row, col, value) {
|
|
298
|
+
this.checkBounds(row, col);
|
|
299
|
+
const newData = this.toFlatFloat64Array();
|
|
300
|
+
newData[row * this.cols + col] = value;
|
|
301
|
+
return new DenseMatrix(this.rows, this.cols, newData);
|
|
302
|
+
}
|
|
303
|
+
toFlatFloat64Array() {
|
|
304
|
+
if (!this.isView && this.offset === 0 && this.rowStride === this.cols) return new Float64Array(this.data);
|
|
305
|
+
const result = new Float64Array(this.rows * this.cols);
|
|
306
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) result[i * this.cols + j] = this.data[this.offset + i * this.rowStride + j];
|
|
307
|
+
return result;
|
|
308
|
+
}
|
|
309
|
+
row(index) {
|
|
310
|
+
if (index < 0 || index >= this.rows) throw new RangeError(`Row index ${index} out of bounds for matrix with ${this.rows} rows`);
|
|
311
|
+
return new DenseMatrix(1, this.cols, this.data, {
|
|
312
|
+
isView: true,
|
|
313
|
+
offset: this.offset + index * this.rowStride,
|
|
314
|
+
rowStride: this.rowStride
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
column(index) {
|
|
318
|
+
if (index < 0 || index >= this.cols) throw new RangeError(`Column index ${index} out of bounds for matrix with ${this.cols} columns`);
|
|
319
|
+
const data = new Float64Array(this.rows);
|
|
320
|
+
for (let i = 0; i < this.rows; i++) data[i] = this.get(i, index);
|
|
321
|
+
return new DenseMatrix(this.rows, 1, data);
|
|
322
|
+
}
|
|
323
|
+
slice(spec) {
|
|
324
|
+
const rowStart = spec.rowStart ?? 0;
|
|
325
|
+
const rowEnd = spec.rowEnd ?? this.rows;
|
|
326
|
+
const colStart = spec.colStart ?? 0;
|
|
327
|
+
const colEnd = spec.colEnd ?? this.cols;
|
|
328
|
+
if (rowStart < 0 || rowEnd > this.rows || colStart < 0 || colEnd > this.cols) throw new RangeError("Slice indices out of bounds");
|
|
329
|
+
if (rowStart >= rowEnd || colStart >= colEnd) throw new Error("Invalid slice: start must be less than end");
|
|
330
|
+
const newRows = rowEnd - rowStart;
|
|
331
|
+
const newCols = colEnd - colStart;
|
|
332
|
+
if (colStart === 0 && colEnd === this.cols) return new DenseMatrix(newRows, newCols, this.data, {
|
|
333
|
+
isView: true,
|
|
334
|
+
offset: this.offset + rowStart * this.rowStride,
|
|
335
|
+
rowStride: this.rowStride
|
|
336
|
+
});
|
|
337
|
+
const data = new Float64Array(newRows * newCols);
|
|
338
|
+
for (let i = 0; i < newRows; i++) for (let j = 0; j < newCols; j++) data[i * newCols + j] = this.get(rowStart + i, colStart + j);
|
|
339
|
+
return new DenseMatrix(newRows, newCols, data);
|
|
340
|
+
}
|
|
341
|
+
diagonal(k = 0) {
|
|
342
|
+
const diagLength = Math.min(this.rows - Math.max(0, -k), this.cols - Math.max(0, k));
|
|
343
|
+
if (diagLength <= 0) return new DenseMatrix(0, 1);
|
|
344
|
+
const data = new Float64Array(diagLength);
|
|
345
|
+
const rowOffset = Math.max(0, -k);
|
|
346
|
+
const colOffset = Math.max(0, k);
|
|
347
|
+
for (let i = 0; i < diagLength; i++) data[i] = this.get(rowOffset + i, colOffset + i);
|
|
348
|
+
return new DenseMatrix(diagLength, 1, data);
|
|
349
|
+
}
|
|
350
|
+
add(other) {
|
|
351
|
+
this.checkDimensionsMatch(other);
|
|
352
|
+
return new DenseMatrix(this.rows, this.cols, add$1(this, other));
|
|
353
|
+
}
|
|
354
|
+
subtract(other) {
|
|
355
|
+
this.checkDimensionsMatch(other);
|
|
356
|
+
return new DenseMatrix(this.rows, this.cols, subtract$1(this, other));
|
|
357
|
+
}
|
|
358
|
+
multiplyElementwise(other) {
|
|
359
|
+
this.checkDimensionsMatch(other);
|
|
360
|
+
return new DenseMatrix(this.rows, this.cols, multiplyElementwise(this, other));
|
|
361
|
+
}
|
|
362
|
+
multiply(other) {
|
|
363
|
+
this.checkMultiplyDimensions(other);
|
|
364
|
+
return new DenseMatrix(this.rows, other.cols, multiply$1(this, other));
|
|
365
|
+
}
|
|
366
|
+
scale(scalar) {
|
|
367
|
+
return new DenseMatrix(this.rows, this.cols, scale(this, scalar));
|
|
368
|
+
}
|
|
369
|
+
transpose() {
|
|
370
|
+
return new DenseMatrix(this.cols, this.rows, transpose$2(this));
|
|
371
|
+
}
|
|
372
|
+
negate() {
|
|
373
|
+
return this.scale(-1);
|
|
374
|
+
}
|
|
375
|
+
sum() {
|
|
376
|
+
return sum$1(this);
|
|
377
|
+
}
|
|
378
|
+
mean() {
|
|
379
|
+
return mean$1(this);
|
|
380
|
+
}
|
|
381
|
+
min() {
|
|
382
|
+
return min$1(this);
|
|
383
|
+
}
|
|
384
|
+
max() {
|
|
385
|
+
return max$1(this);
|
|
386
|
+
}
|
|
387
|
+
norm() {
|
|
388
|
+
return norm$1(this);
|
|
389
|
+
}
|
|
390
|
+
trace() {
|
|
391
|
+
return trace$1(this);
|
|
392
|
+
}
|
|
393
|
+
toArray() {
|
|
394
|
+
const result = [];
|
|
395
|
+
for (let i = 0; i < this.rows; i++) {
|
|
396
|
+
result[i] = [];
|
|
397
|
+
for (let j = 0; j < this.cols; j++) result[i][j] = this.get(i, j);
|
|
275
398
|
}
|
|
276
|
-
|
|
277
|
-
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
401
|
+
toFlatArray() {
|
|
402
|
+
return Array.from(this.toFlatFloat64Array());
|
|
403
|
+
}
|
|
404
|
+
toFloat64Array() {
|
|
405
|
+
return this.toFlatFloat64Array();
|
|
406
|
+
}
|
|
407
|
+
clone() {
|
|
408
|
+
return new DenseMatrix(this.rows, this.cols, this.toFlatFloat64Array());
|
|
409
|
+
}
|
|
410
|
+
toSparse(dropTolerance = 0) {
|
|
411
|
+
const values = [];
|
|
412
|
+
const colIndices = [];
|
|
413
|
+
const rowPointers = [0];
|
|
414
|
+
for (let i = 0; i < this.rows; i++) {
|
|
415
|
+
for (let j = 0; j < this.cols; j++) {
|
|
416
|
+
const val = this.get(i, j);
|
|
417
|
+
if (Math.abs(val) > dropTolerance) {
|
|
418
|
+
values.push(val);
|
|
419
|
+
colIndices.push(j);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
rowPointers.push(values.length);
|
|
278
423
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
424
|
+
if (sparseMatrixFactory === void 0) throw new Error("DenseMatrix.toSparse: SparseMatrix is not loaded; import it from @danielsimonjr/mathts-matrix");
|
|
425
|
+
return sparseMatrixFactory(this.rows, this.cols, new Float64Array(values), new Int32Array(colIndices), new Int32Array(rowPointers));
|
|
426
|
+
}
|
|
427
|
+
*entries() {
|
|
428
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) yield {
|
|
429
|
+
row: i,
|
|
430
|
+
col: j,
|
|
431
|
+
value: this.get(i, j)
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
*values() {
|
|
435
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) yield this.get(i, j);
|
|
436
|
+
}
|
|
437
|
+
[Symbol.iterator]() {
|
|
438
|
+
return this.values();
|
|
439
|
+
}
|
|
440
|
+
map(fn) {
|
|
441
|
+
const result = new Float64Array(this.rows * this.cols);
|
|
442
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) result[i * this.cols + j] = fn(this.get(i, j), i, j);
|
|
443
|
+
return new DenseMatrix(this.rows, this.cols, result);
|
|
444
|
+
}
|
|
445
|
+
forEach(fn) {
|
|
446
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) fn(this.get(i, j), i, j);
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
function isDenseMatrix(value) {
|
|
450
|
+
return value instanceof DenseMatrix;
|
|
451
|
+
}
|
|
452
|
+
let sparseMatrixFactory;
|
|
453
|
+
function registerSparseMatrixFactory(factory) {
|
|
454
|
+
sparseMatrixFactory = factory;
|
|
455
|
+
}
|
|
456
|
+
function denseContiguousData(matrix) {
|
|
457
|
+
return contiguousDenseData(matrix) ?? matrix.toFloat64Array();
|
|
458
|
+
}
|
|
459
|
+
//#endregion
|
|
460
|
+
//#region src/types/SparseMatrix.ts
|
|
461
|
+
var SparseMatrix = class SparseMatrix extends Matrix {
|
|
462
|
+
type = "SparseMatrix";
|
|
463
|
+
rows;
|
|
464
|
+
cols;
|
|
465
|
+
_data;
|
|
466
|
+
_colIndices;
|
|
467
|
+
_rowPointers;
|
|
468
|
+
constructor(rows, cols, values, colIndices, rowPointers) {
|
|
469
|
+
super();
|
|
470
|
+
if (!Number.isInteger(rows) || !Number.isInteger(cols)) throw new TypeError(`Matrix dimensions must be integers, got ${String(rows)}×${String(cols)}`);
|
|
471
|
+
if (rows < 0 || cols < 0) throw new Error("Matrix dimensions must be non-negative");
|
|
472
|
+
this.rows = rows;
|
|
473
|
+
this.cols = cols;
|
|
474
|
+
this._data = values instanceof Float64Array ? values : new Float64Array(values);
|
|
475
|
+
this._colIndices = colIndices instanceof Int32Array ? colIndices : new Int32Array(colIndices);
|
|
476
|
+
this._rowPointers = rowPointers instanceof Int32Array ? rowPointers : new Int32Array(rowPointers);
|
|
477
|
+
if (this._rowPointers.length !== rows + 1) throw new Error(`rowPointers length must be ${rows + 1}, got ${this._rowPointers.length}`);
|
|
478
|
+
if (this._data.length !== this._colIndices.length) throw new Error("values and colIndices must have same length");
|
|
479
|
+
if (this._rowPointers[rows] !== this._data.length) throw new Error("rowPointers[rows] must equal number of non-zeros");
|
|
480
|
+
const rp = this._rowPointers;
|
|
481
|
+
if (rp[0] !== 0) throw new Error("rowPointers[0] must be 0");
|
|
482
|
+
for (let i = 0; i < rows; i++) if (rp[i + 1] < rp[i]) throw new Error(`rowPointers must be non-decreasing (violated at row ${i})`);
|
|
483
|
+
const ci = this._colIndices;
|
|
484
|
+
for (let k = 0; k < ci.length; k++) {
|
|
485
|
+
const c = ci[k];
|
|
486
|
+
if (c < 0 || c >= cols) throw new RangeError(`Column index ${c} at position ${k} out of range for ${cols} columns`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
static validate(m) {
|
|
490
|
+
const rp = m._rowPointers;
|
|
491
|
+
const ci = m._colIndices;
|
|
492
|
+
if (rp.length !== m.rows + 1) throw new Error(`rowPointers length must be ${m.rows + 1}`);
|
|
493
|
+
if (rp[0] !== 0) throw new Error("rowPointers[0] must be 0");
|
|
494
|
+
if (rp[m.rows] !== m._data.length) throw new Error("rowPointers[rows] must equal number of non-zeros");
|
|
495
|
+
for (let i = 0; i < m.rows; i++) {
|
|
496
|
+
const start = rp[i];
|
|
497
|
+
const end = rp[i + 1];
|
|
498
|
+
if (end < start) throw new Error(`rowPointers must be non-decreasing (violated at row ${i})`);
|
|
499
|
+
for (let k = start; k < end; k++) {
|
|
500
|
+
const c = ci[k];
|
|
501
|
+
if (c < 0 || c >= m.cols) throw new RangeError(`Column index ${c} in row ${i} out of range for ${m.cols} columns`);
|
|
502
|
+
if (k > start && c <= ci[k - 1]) throw new Error(`Column indices in row ${i} must be strictly increasing`);
|
|
286
503
|
}
|
|
287
|
-
rowPointers[n] = n;
|
|
288
|
-
return new SparseMatrix(n, n, values, colIndices, rowPointers);
|
|
289
504
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
for (let
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
505
|
+
}
|
|
506
|
+
static fromDense(dense, dropTolerance = 0) {
|
|
507
|
+
const values = [];
|
|
508
|
+
const colIndices = [];
|
|
509
|
+
const rowPointers = [0];
|
|
510
|
+
for (let i = 0; i < dense.rows; i++) {
|
|
511
|
+
for (let j = 0; j < dense.cols; j++) {
|
|
512
|
+
const val = dense.get(i, j);
|
|
513
|
+
if (Math.abs(val) > dropTolerance) {
|
|
514
|
+
values.push(val);
|
|
515
|
+
colIndices.push(j);
|
|
300
516
|
}
|
|
301
|
-
rowPointers.push(idx);
|
|
302
517
|
}
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
get nnz() {
|
|
306
|
-
return this._data.length;
|
|
307
|
-
}
|
|
308
|
-
get sparsity() {
|
|
309
|
-
const total = this.rows * this.cols;
|
|
310
|
-
return total === 0 ? 1 : 1 - this.nnz / total;
|
|
518
|
+
rowPointers.push(values.length);
|
|
311
519
|
}
|
|
312
|
-
|
|
313
|
-
|
|
520
|
+
return new SparseMatrix(dense.rows, dense.cols, new Float64Array(values), new Int32Array(colIndices), new Int32Array(rowPointers));
|
|
521
|
+
}
|
|
522
|
+
static fromCOO(rows, cols, entries) {
|
|
523
|
+
if (!Number.isInteger(rows) || !Number.isInteger(cols) || rows < 0 || cols < 0) throw new Error(`Invalid matrix dimensions ${String(rows)}×${String(cols)}`);
|
|
524
|
+
for (const e of entries) {
|
|
525
|
+
if (!Number.isInteger(e.row) || e.row < 0 || e.row >= rows) throw new RangeError(`COO row index ${e.row} out of range for ${rows} rows`);
|
|
526
|
+
if (!Number.isInteger(e.col) || e.col < 0 || e.col >= cols) throw new RangeError(`COO column index ${e.col} out of range for ${cols} columns`);
|
|
314
527
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
528
|
+
const sorted = [...entries].sort((a, b) => {
|
|
529
|
+
if (a.row !== b.row) return a.row - b.row;
|
|
530
|
+
return a.col - b.col;
|
|
531
|
+
});
|
|
532
|
+
const values = [];
|
|
533
|
+
const colIndices = [];
|
|
534
|
+
const rowPointers = new Array(rows + 1).fill(0);
|
|
535
|
+
let idx = 0;
|
|
536
|
+
while (idx < sorted.length) {
|
|
537
|
+
const { row, col } = sorted[idx];
|
|
538
|
+
let value = sorted[idx].value;
|
|
539
|
+
idx++;
|
|
540
|
+
while (idx < sorted.length && sorted[idx].row === row && sorted[idx].col === col) {
|
|
541
|
+
value += sorted[idx].value;
|
|
542
|
+
idx++;
|
|
543
|
+
}
|
|
544
|
+
if (value !== 0) {
|
|
545
|
+
values.push(value);
|
|
546
|
+
colIndices.push(col);
|
|
547
|
+
rowPointers[row + 1]++;
|
|
327
548
|
}
|
|
328
|
-
return 0;
|
|
329
549
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
550
|
+
for (let i = 1; i <= rows; i++) rowPointers[i] += rowPointers[i - 1];
|
|
551
|
+
return new SparseMatrix(rows, cols, new Float64Array(values), new Int32Array(colIndices), new Int32Array(rowPointers));
|
|
552
|
+
}
|
|
553
|
+
static zeros(rows, cols) {
|
|
554
|
+
return new SparseMatrix(rows, cols, /* @__PURE__ */ new Float64Array(0), /* @__PURE__ */ new Int32Array(0), new Int32Array(rows + 1).fill(0));
|
|
555
|
+
}
|
|
556
|
+
static identity(n) {
|
|
557
|
+
const values = new Float64Array(n).fill(1);
|
|
558
|
+
const colIndices = new Int32Array(n);
|
|
559
|
+
const rowPointers = new Int32Array(n + 1);
|
|
560
|
+
for (let i = 0; i < n; i++) {
|
|
561
|
+
colIndices[i] = i;
|
|
562
|
+
rowPointers[i] = i;
|
|
563
|
+
}
|
|
564
|
+
rowPointers[n] = n;
|
|
565
|
+
return new SparseMatrix(n, n, values, colIndices, rowPointers);
|
|
566
|
+
}
|
|
567
|
+
static diag(values) {
|
|
568
|
+
const n = values.length;
|
|
569
|
+
const vals = new Float64Array(values.filter((v) => v !== 0));
|
|
570
|
+
const colIndices = [];
|
|
571
|
+
const rowPointers = [0];
|
|
572
|
+
let idx = 0;
|
|
573
|
+
for (let i = 0; i < n; i++) {
|
|
574
|
+
if (values[i] !== 0) {
|
|
575
|
+
colIndices.push(i);
|
|
576
|
+
idx++;
|
|
577
|
+
}
|
|
578
|
+
rowPointers.push(idx);
|
|
579
|
+
}
|
|
580
|
+
return new SparseMatrix(n, n, vals, new Int32Array(colIndices), new Int32Array(rowPointers));
|
|
581
|
+
}
|
|
582
|
+
get nnz() {
|
|
583
|
+
return this._data.length;
|
|
584
|
+
}
|
|
585
|
+
get sparsity() {
|
|
586
|
+
const total = this.rows * this.cols;
|
|
587
|
+
return total === 0 ? 1 : 1 - this.nnz / total;
|
|
588
|
+
}
|
|
589
|
+
get density() {
|
|
590
|
+
return 1 - this.sparsity;
|
|
591
|
+
}
|
|
592
|
+
get(row, col) {
|
|
593
|
+
this.checkBounds(row, col);
|
|
594
|
+
const start = this._rowPointers[row];
|
|
595
|
+
const end = this._rowPointers[row + 1];
|
|
596
|
+
let left = start;
|
|
597
|
+
let right = end - 1;
|
|
598
|
+
while (left <= right) {
|
|
599
|
+
const mid = Math.floor((left + right) / 2);
|
|
600
|
+
const midCol = this._colIndices[mid];
|
|
601
|
+
if (midCol === col) return this._data[mid];
|
|
602
|
+
else if (midCol < col) left = mid + 1;
|
|
603
|
+
else right = mid - 1;
|
|
604
|
+
}
|
|
605
|
+
return 0;
|
|
606
|
+
}
|
|
607
|
+
set(row, col, value) {
|
|
608
|
+
this.checkBounds(row, col);
|
|
609
|
+
const start = this._rowPointers[row];
|
|
610
|
+
const end = this._rowPointers[row + 1];
|
|
611
|
+
let insertPos = start;
|
|
612
|
+
let found = false;
|
|
613
|
+
for (let i = start; i < end; i++) if (this._colIndices[i] === col) {
|
|
614
|
+
insertPos = i;
|
|
615
|
+
found = true;
|
|
616
|
+
break;
|
|
617
|
+
} else if (this._colIndices[i] > col) {
|
|
618
|
+
insertPos = i;
|
|
619
|
+
break;
|
|
620
|
+
} else insertPos = i + 1;
|
|
621
|
+
if (found) {
|
|
622
|
+
if (value === 0) {
|
|
623
|
+
const newData = new Float64Array(this._data.length - 1);
|
|
624
|
+
const newColIndices = new Int32Array(this._colIndices.length - 1);
|
|
369
625
|
const newRowPointers = new Int32Array(this._rowPointers.length);
|
|
370
626
|
for (let i = 0; i < insertPos; i++) {
|
|
371
627
|
newData[i] = this._data[i];
|
|
372
628
|
newColIndices[i] = this._colIndices[i];
|
|
373
629
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
newData[i + 1] = this._data[i];
|
|
378
|
-
newColIndices[i + 1] = this._colIndices[i];
|
|
630
|
+
for (let i = insertPos + 1; i < this._data.length; i++) {
|
|
631
|
+
newData[i - 1] = this._data[i];
|
|
632
|
+
newColIndices[i - 1] = this._colIndices[i];
|
|
379
633
|
}
|
|
380
634
|
for (let i = 0; i <= row; i++) newRowPointers[i] = this._rowPointers[i];
|
|
381
|
-
for (let i = row + 1; i <= this.rows; i++) newRowPointers[i] = this._rowPointers[i]
|
|
635
|
+
for (let i = row + 1; i <= this.rows; i++) newRowPointers[i] = this._rowPointers[i] - 1;
|
|
382
636
|
return new SparseMatrix(this.rows, this.cols, newData, newColIndices, newRowPointers);
|
|
637
|
+
} else {
|
|
638
|
+
const newData = new Float64Array(this._data);
|
|
639
|
+
newData[insertPos] = value;
|
|
640
|
+
return new SparseMatrix(this.rows, this.cols, newData, this._colIndices, this._rowPointers);
|
|
383
641
|
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
const
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
for (let i = 0; i < nnzCount; i++) {
|
|
393
|
-
data[i] = this._data[start + i];
|
|
394
|
-
colIndices[i] = this._colIndices[start + i];
|
|
395
|
-
}
|
|
396
|
-
return new SparseMatrix(1, this.cols, data, colIndices, rowPointers);
|
|
397
|
-
}
|
|
398
|
-
column(index) {
|
|
399
|
-
if (index < 0 || index >= this.cols) throw new RangeError(`Column index ${index} out of bounds for matrix with ${this.cols} columns`);
|
|
400
|
-
const entries = [];
|
|
401
|
-
for (let i = 0; i < this.rows; i++) {
|
|
402
|
-
const start = this._rowPointers[i];
|
|
403
|
-
const end = this._rowPointers[i + 1];
|
|
404
|
-
for (let j = start; j < end; j++) if (this._colIndices[j] === index) {
|
|
405
|
-
entries.push({
|
|
406
|
-
row: i,
|
|
407
|
-
col: 0,
|
|
408
|
-
value: this._data[j]
|
|
409
|
-
});
|
|
410
|
-
break;
|
|
411
|
-
}
|
|
642
|
+
} else {
|
|
643
|
+
if (value === 0) return this;
|
|
644
|
+
const newData = new Float64Array(this._data.length + 1);
|
|
645
|
+
const newColIndices = new Int32Array(this._colIndices.length + 1);
|
|
646
|
+
const newRowPointers = new Int32Array(this._rowPointers.length);
|
|
647
|
+
for (let i = 0; i < insertPos; i++) {
|
|
648
|
+
newData[i] = this._data[i];
|
|
649
|
+
newColIndices[i] = this._colIndices[i];
|
|
412
650
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const colStart = spec.colStart ?? 0;
|
|
419
|
-
const colEnd = spec.colEnd ?? this.cols;
|
|
420
|
-
if (rowStart < 0 || rowEnd > this.rows || colStart < 0 || colEnd > this.cols) throw new RangeError("Slice indices out of bounds");
|
|
421
|
-
if (rowStart >= rowEnd || colStart >= colEnd) throw new Error("Invalid slice: start must be less than end");
|
|
422
|
-
const entries = [];
|
|
423
|
-
for (let i = rowStart; i < rowEnd; i++) {
|
|
424
|
-
const start = this._rowPointers[i];
|
|
425
|
-
const end = this._rowPointers[i + 1];
|
|
426
|
-
for (let j = start; j < end; j++) {
|
|
427
|
-
const col = this._colIndices[j];
|
|
428
|
-
if (col >= colStart && col < colEnd) entries.push({
|
|
429
|
-
row: i - rowStart,
|
|
430
|
-
col: col - colStart,
|
|
431
|
-
value: this._data[j]
|
|
432
|
-
});
|
|
433
|
-
}
|
|
651
|
+
newData[insertPos] = value;
|
|
652
|
+
newColIndices[insertPos] = col;
|
|
653
|
+
for (let i = insertPos; i < this._data.length; i++) {
|
|
654
|
+
newData[i + 1] = this._data[i];
|
|
655
|
+
newColIndices[i + 1] = this._colIndices[i];
|
|
434
656
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
657
|
+
for (let i = 0; i <= row; i++) newRowPointers[i] = this._rowPointers[i];
|
|
658
|
+
for (let i = row + 1; i <= this.rows; i++) newRowPointers[i] = this._rowPointers[i] + 1;
|
|
659
|
+
return new SparseMatrix(this.rows, this.cols, newData, newColIndices, newRowPointers);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
row(index) {
|
|
663
|
+
if (index < 0 || index >= this.rows) throw new RangeError(`Row index ${index} out of bounds for matrix with ${this.rows} rows`);
|
|
664
|
+
const start = this._rowPointers[index];
|
|
665
|
+
const nnzCount = this._rowPointers[index + 1] - start;
|
|
666
|
+
const data = new Float64Array(nnzCount);
|
|
667
|
+
const colIndices = new Int32Array(nnzCount);
|
|
668
|
+
const rowPointers = new Int32Array([0, nnzCount]);
|
|
669
|
+
for (let i = 0; i < nnzCount; i++) {
|
|
670
|
+
data[i] = this._data[start + i];
|
|
671
|
+
colIndices[i] = this._colIndices[start + i];
|
|
672
|
+
}
|
|
673
|
+
return new SparseMatrix(1, this.cols, data, colIndices, rowPointers);
|
|
674
|
+
}
|
|
675
|
+
column(index) {
|
|
676
|
+
if (index < 0 || index >= this.cols) throw new RangeError(`Column index ${index} out of bounds for matrix with ${this.cols} columns`);
|
|
677
|
+
const entries = [];
|
|
678
|
+
for (let i = 0; i < this.rows; i++) {
|
|
679
|
+
const start = this._rowPointers[i];
|
|
680
|
+
const end = this._rowPointers[i + 1];
|
|
681
|
+
for (let j = start; j < end; j++) if (this._colIndices[j] === index) {
|
|
682
|
+
entries.push({
|
|
446
683
|
row: i,
|
|
447
684
|
col: 0,
|
|
448
|
-
value:
|
|
685
|
+
value: this._data[j]
|
|
449
686
|
});
|
|
687
|
+
break;
|
|
450
688
|
}
|
|
451
|
-
return SparseMatrix.fromCOO(diagLength, 1, entries);
|
|
452
689
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
row: i,
|
|
474
|
-
col: thisCol,
|
|
475
|
-
value: this._data[thisIdx]
|
|
476
|
-
});
|
|
477
|
-
thisIdx++;
|
|
478
|
-
} else if (otherCol < thisCol) {
|
|
479
|
-
entries.push({
|
|
480
|
-
row: i,
|
|
481
|
-
col: otherCol,
|
|
482
|
-
value: other._data[otherIdx]
|
|
483
|
-
});
|
|
484
|
-
otherIdx++;
|
|
485
|
-
} else {
|
|
486
|
-
const sum = this._data[thisIdx] + other._data[otherIdx];
|
|
487
|
-
if (sum !== 0) entries.push({
|
|
488
|
-
row: i,
|
|
489
|
-
col: thisCol,
|
|
490
|
-
value: sum
|
|
491
|
-
});
|
|
492
|
-
thisIdx++;
|
|
493
|
-
otherIdx++;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
690
|
+
return SparseMatrix.fromCOO(this.rows, 1, entries);
|
|
691
|
+
}
|
|
692
|
+
slice(spec) {
|
|
693
|
+
const rowStart = spec.rowStart ?? 0;
|
|
694
|
+
const rowEnd = spec.rowEnd ?? this.rows;
|
|
695
|
+
const colStart = spec.colStart ?? 0;
|
|
696
|
+
const colEnd = spec.colEnd ?? this.cols;
|
|
697
|
+
if (rowStart < 0 || rowEnd > this.rows || colStart < 0 || colEnd > this.cols) throw new RangeError("Slice indices out of bounds");
|
|
698
|
+
if (rowStart >= rowEnd || colStart >= colEnd) throw new Error("Invalid slice: start must be less than end");
|
|
699
|
+
const entries = [];
|
|
700
|
+
for (let i = rowStart; i < rowEnd; i++) {
|
|
701
|
+
const start = this._rowPointers[i];
|
|
702
|
+
const end = this._rowPointers[i + 1];
|
|
703
|
+
for (let j = start; j < end; j++) {
|
|
704
|
+
const col = this._colIndices[j];
|
|
705
|
+
if (col >= colStart && col < colEnd) entries.push({
|
|
706
|
+
row: i - rowStart,
|
|
707
|
+
col: col - colStart,
|
|
708
|
+
value: this._data[j]
|
|
709
|
+
});
|
|
496
710
|
}
|
|
497
|
-
return SparseMatrix.fromCOO(this.rows, this.cols, entries);
|
|
498
711
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
712
|
+
return SparseMatrix.fromCOO(rowEnd - rowStart, colEnd - colStart, entries);
|
|
713
|
+
}
|
|
714
|
+
diagonal(k = 0) {
|
|
715
|
+
const diagLength = Math.min(this.rows - Math.max(0, -k), this.cols - Math.max(0, k));
|
|
716
|
+
if (diagLength <= 0) return SparseMatrix.zeros(0, 1);
|
|
717
|
+
const entries = [];
|
|
718
|
+
const rowOffset = Math.max(0, -k);
|
|
719
|
+
const colOffset = Math.max(0, k);
|
|
720
|
+
for (let i = 0; i < diagLength; i++) {
|
|
721
|
+
const val = this.get(rowOffset + i, colOffset + i);
|
|
722
|
+
if (val !== 0) entries.push({
|
|
723
|
+
row: i,
|
|
724
|
+
col: 0,
|
|
725
|
+
value: val
|
|
726
|
+
});
|
|
504
727
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
728
|
+
return SparseMatrix.fromCOO(diagLength, 1, entries);
|
|
729
|
+
}
|
|
730
|
+
add(other) {
|
|
731
|
+
this.checkDimensionsMatch(other);
|
|
732
|
+
if (other instanceof SparseMatrix) return this.addSparse(other);
|
|
733
|
+
const result = this.toDense().add(other);
|
|
734
|
+
return SparseMatrix.fromDense(result);
|
|
735
|
+
}
|
|
736
|
+
addSparse(other) {
|
|
737
|
+
const entries = [];
|
|
738
|
+
for (let i = 0; i < this.rows; i++) {
|
|
739
|
+
const thisStart = this._rowPointers[i];
|
|
740
|
+
const thisEnd = this._rowPointers[i + 1];
|
|
741
|
+
const otherStart = other._rowPointers[i];
|
|
742
|
+
const otherEnd = other._rowPointers[i + 1];
|
|
743
|
+
let thisIdx = thisStart;
|
|
744
|
+
let otherIdx = otherStart;
|
|
745
|
+
while (thisIdx < thisEnd || otherIdx < otherEnd) {
|
|
746
|
+
const thisCol = thisIdx < thisEnd ? this._colIndices[thisIdx] : this.cols;
|
|
747
|
+
const otherCol = otherIdx < otherEnd ? other._colIndices[otherIdx] : this.cols;
|
|
748
|
+
if (thisCol < otherCol) {
|
|
749
|
+
entries.push({
|
|
515
750
|
row: i,
|
|
516
|
-
col,
|
|
517
|
-
value:
|
|
751
|
+
col: thisCol,
|
|
752
|
+
value: this._data[thisIdx]
|
|
518
753
|
});
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
const rowEnd = this._rowPointers[i + 1];
|
|
530
|
-
for (let j = 0; j < other.cols; j++) {
|
|
531
|
-
let sum = 0;
|
|
532
|
-
for (let k = rowStart; k < rowEnd; k++) {
|
|
533
|
-
const col = this._colIndices[k];
|
|
534
|
-
sum += this._data[k] * other.get(col, j);
|
|
535
|
-
}
|
|
754
|
+
thisIdx++;
|
|
755
|
+
} else if (otherCol < thisCol) {
|
|
756
|
+
entries.push({
|
|
757
|
+
row: i,
|
|
758
|
+
col: otherCol,
|
|
759
|
+
value: other._data[otherIdx]
|
|
760
|
+
});
|
|
761
|
+
otherIdx++;
|
|
762
|
+
} else {
|
|
763
|
+
const sum = this._data[thisIdx] + other._data[otherIdx];
|
|
536
764
|
if (sum !== 0) entries.push({
|
|
537
765
|
row: i,
|
|
538
|
-
col:
|
|
766
|
+
col: thisCol,
|
|
539
767
|
value: sum
|
|
540
768
|
});
|
|
769
|
+
thisIdx++;
|
|
770
|
+
otherIdx++;
|
|
541
771
|
}
|
|
542
772
|
}
|
|
543
|
-
return SparseMatrix.fromCOO(this.rows, other.cols, entries);
|
|
544
773
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
for (const [col, value] of rowResult.entries()) if (value !== 0) entries.push({
|
|
774
|
+
return SparseMatrix.fromCOO(this.rows, this.cols, entries);
|
|
775
|
+
}
|
|
776
|
+
subtract(other) {
|
|
777
|
+
this.checkDimensionsMatch(other);
|
|
778
|
+
if (other instanceof SparseMatrix) return this.addSparse(other.scale(-1));
|
|
779
|
+
const result = this.toDense().subtract(other);
|
|
780
|
+
return SparseMatrix.fromDense(result);
|
|
781
|
+
}
|
|
782
|
+
multiplyElementwise(other) {
|
|
783
|
+
this.checkDimensionsMatch(other);
|
|
784
|
+
const entries = [];
|
|
785
|
+
for (let i = 0; i < this.rows; i++) {
|
|
786
|
+
const start = this._rowPointers[i];
|
|
787
|
+
const end = this._rowPointers[i + 1];
|
|
788
|
+
for (let j = start; j < end; j++) {
|
|
789
|
+
const col = this._colIndices[j];
|
|
790
|
+
const product = this._data[j] * other.get(i, col);
|
|
791
|
+
if (product !== 0) entries.push({
|
|
564
792
|
row: i,
|
|
565
793
|
col,
|
|
566
|
-
value
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
return SparseMatrix.fromCOO(this.rows, other.cols, entries);
|
|
570
|
-
}
|
|
571
|
-
scale(scalar) {
|
|
572
|
-
if (scalar === 0) return SparseMatrix.zeros(this.rows, this.cols);
|
|
573
|
-
const newData = new Float64Array(this._data.length);
|
|
574
|
-
for (let i = 0; i < this._data.length; i++) newData[i] = this._data[i] * scalar;
|
|
575
|
-
return new SparseMatrix(this.rows, this.cols, newData, this._colIndices, this._rowPointers);
|
|
576
|
-
}
|
|
577
|
-
transpose() {
|
|
578
|
-
const entries = [];
|
|
579
|
-
for (let i = 0; i < this.rows; i++) {
|
|
580
|
-
const start = this._rowPointers[i];
|
|
581
|
-
const end = this._rowPointers[i + 1];
|
|
582
|
-
for (let j = start; j < end; j++) entries.push({
|
|
583
|
-
row: this._colIndices[j],
|
|
584
|
-
col: i,
|
|
585
|
-
value: this._data[j]
|
|
794
|
+
value: product
|
|
586
795
|
});
|
|
587
796
|
}
|
|
588
|
-
return SparseMatrix.fromCOO(this.cols, this.rows, entries);
|
|
589
|
-
}
|
|
590
|
-
negate() {
|
|
591
|
-
return this.scale(-1);
|
|
592
|
-
}
|
|
593
|
-
sum() {
|
|
594
|
-
let total = 0;
|
|
595
|
-
for (let i = 0; i < this._data.length; i++) total += this._data[i];
|
|
596
|
-
return total;
|
|
597
|
-
}
|
|
598
|
-
norm() {
|
|
599
|
-
let sumSq = 0;
|
|
600
|
-
for (let i = 0; i < this._data.length; i++) sumSq += this._data[i] * this._data[i];
|
|
601
|
-
return Math.sqrt(sumSq);
|
|
602
|
-
}
|
|
603
|
-
trace() {
|
|
604
|
-
if (!this.isSquare) throw new Error("Trace is only defined for square matrices");
|
|
605
|
-
let sum = 0;
|
|
606
|
-
for (let i = 0; i < this.rows; i++) sum += this.get(i, i);
|
|
607
|
-
return sum;
|
|
608
|
-
}
|
|
609
|
-
toDense() {
|
|
610
|
-
const data = new Float64Array(this.rows * this.cols);
|
|
611
|
-
for (let i = 0; i < this.rows; i++) {
|
|
612
|
-
const start = this._rowPointers[i];
|
|
613
|
-
const end = this._rowPointers[i + 1];
|
|
614
|
-
for (let j = start; j < end; j++) data[i * this.cols + this._colIndices[j]] = this._data[j];
|
|
615
|
-
}
|
|
616
|
-
return new DenseMatrix(this.rows, this.cols, data);
|
|
617
|
-
}
|
|
618
|
-
toArray() {
|
|
619
|
-
return this.toDense().toArray();
|
|
620
|
-
}
|
|
621
|
-
toFlatArray() {
|
|
622
|
-
return this.toDense().toFlatArray();
|
|
623
|
-
}
|
|
624
|
-
clone() {
|
|
625
|
-
return new SparseMatrix(this.rows, this.cols, new Float64Array(this._data), new Int32Array(this._colIndices), new Int32Array(this._rowPointers));
|
|
626
|
-
}
|
|
627
|
-
getCSR() {
|
|
628
|
-
return {
|
|
629
|
-
values: new Float64Array(this._data),
|
|
630
|
-
colIndices: new Int32Array(this._colIndices),
|
|
631
|
-
rowPointers: new Int32Array(this._rowPointers)
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
*entries() {
|
|
635
|
-
for (let i = 0; i < this.rows; i++) {
|
|
636
|
-
const start = this._rowPointers[i];
|
|
637
|
-
const end = this._rowPointers[i + 1];
|
|
638
|
-
for (let j = start; j < end; j++) yield {
|
|
639
|
-
row: i,
|
|
640
|
-
col: this._colIndices[j],
|
|
641
|
-
value: this._data[j]
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
797
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
for (let j = start; j < end; j++) {
|
|
660
|
-
const col = this._colIndices[j];
|
|
661
|
-
const newVal = fn(this._data[j], i, col);
|
|
662
|
-
if (newVal !== 0) entries.push({
|
|
663
|
-
row: i,
|
|
664
|
-
col,
|
|
665
|
-
value: newVal
|
|
666
|
-
});
|
|
798
|
+
return SparseMatrix.fromCOO(this.rows, this.cols, entries);
|
|
799
|
+
}
|
|
800
|
+
multiply(other) {
|
|
801
|
+
this.checkMultiplyDimensions(other);
|
|
802
|
+
if (other instanceof SparseMatrix) return this.multiplySparse(other);
|
|
803
|
+
const entries = [];
|
|
804
|
+
for (let i = 0; i < this.rows; i++) {
|
|
805
|
+
const rowStart = this._rowPointers[i];
|
|
806
|
+
const rowEnd = this._rowPointers[i + 1];
|
|
807
|
+
for (let j = 0; j < other.cols; j++) {
|
|
808
|
+
let sum = 0;
|
|
809
|
+
for (let k = rowStart; k < rowEnd; k++) {
|
|
810
|
+
const col = this._colIndices[k];
|
|
811
|
+
sum += this._data[k] * other.get(col, j);
|
|
667
812
|
}
|
|
668
|
-
|
|
669
|
-
return SparseMatrix.fromCOO(this.rows, this.cols, entries);
|
|
670
|
-
}
|
|
671
|
-
map(fn) {
|
|
672
|
-
const entries = [];
|
|
673
|
-
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) {
|
|
674
|
-
const newVal = fn(this.get(i, j), i, j);
|
|
675
|
-
if (newVal !== 0) entries.push({
|
|
813
|
+
if (sum !== 0) entries.push({
|
|
676
814
|
row: i,
|
|
677
815
|
col: j,
|
|
678
|
-
value:
|
|
816
|
+
value: sum
|
|
679
817
|
});
|
|
680
818
|
}
|
|
681
|
-
return SparseMatrix.fromCOO(this.rows, this.cols, entries);
|
|
682
819
|
}
|
|
683
|
-
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
type = "DenseMatrix";
|
|
702
|
-
rows;
|
|
703
|
-
cols;
|
|
704
|
-
data;
|
|
705
|
-
isView;
|
|
706
|
-
offset;
|
|
707
|
-
rowStride;
|
|
708
|
-
constructor(rows, cols, data, viewConfig) {
|
|
709
|
-
super();
|
|
710
|
-
if (rows < 0 || cols < 0) throw new Error("Matrix dimensions must be non-negative");
|
|
711
|
-
this.rows = rows;
|
|
712
|
-
this.cols = cols;
|
|
713
|
-
if (viewConfig) {
|
|
714
|
-
this.isView = viewConfig.isView;
|
|
715
|
-
this.offset = viewConfig.offset;
|
|
716
|
-
this.rowStride = viewConfig.rowStride;
|
|
717
|
-
this.data = data;
|
|
718
|
-
} else {
|
|
719
|
-
this.isView = false;
|
|
720
|
-
this.offset = 0;
|
|
721
|
-
this.rowStride = cols;
|
|
722
|
-
if (data === void 0) this.data = new Float64Array(rows * cols);
|
|
723
|
-
else if (data instanceof Float64Array) {
|
|
724
|
-
if (data.length !== rows * cols) throw new Error(`Data length ${data.length} does not match dimensions ${rows}×${cols}`);
|
|
725
|
-
this.data = data;
|
|
726
|
-
} else if (Array.isArray(data)) {
|
|
727
|
-
if (Array.isArray(data[0])) {
|
|
728
|
-
const nested = data;
|
|
729
|
-
if (nested.length !== rows) throw new Error(`Expected ${rows} rows, got ${nested.length}`);
|
|
730
|
-
this.data = new Float64Array(rows * cols);
|
|
731
|
-
for (let i = 0; i < rows; i++) {
|
|
732
|
-
if (nested[i].length !== cols) throw new Error(`Row ${i} has ${nested[i].length} elements, expected ${cols}`);
|
|
733
|
-
for (let j = 0; j < cols; j++) this.data[i * cols + j] = nested[i][j];
|
|
734
|
-
}
|
|
735
|
-
} else {
|
|
736
|
-
const flat = data;
|
|
737
|
-
if (flat.length !== rows * cols) throw new Error(`Data length ${flat.length} does not match dimensions ${rows}×${cols}`);
|
|
738
|
-
this.data = new Float64Array(flat);
|
|
739
|
-
}
|
|
820
|
+
return SparseMatrix.fromCOO(this.rows, other.cols, entries);
|
|
821
|
+
}
|
|
822
|
+
multiplySparse(other) {
|
|
823
|
+
const entries = [];
|
|
824
|
+
for (let i = 0; i < this.rows; i++) {
|
|
825
|
+
const rowStart = this._rowPointers[i];
|
|
826
|
+
const rowEnd = this._rowPointers[i + 1];
|
|
827
|
+
const rowResult = /* @__PURE__ */ new Map();
|
|
828
|
+
for (let k = rowStart; k < rowEnd; k++) {
|
|
829
|
+
const colA = this._colIndices[k];
|
|
830
|
+
const valA = this._data[k];
|
|
831
|
+
const otherRowStart = other._rowPointers[colA];
|
|
832
|
+
const otherRowEnd = other._rowPointers[colA + 1];
|
|
833
|
+
for (let l = otherRowStart; l < otherRowEnd; l++) {
|
|
834
|
+
const colB = other._colIndices[l];
|
|
835
|
+
const valB = other._data[l];
|
|
836
|
+
const existing = rowResult.get(colB) || 0;
|
|
837
|
+
rowResult.set(colB, existing + valA * valB);
|
|
740
838
|
}
|
|
741
839
|
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
return new DenseMatrix(rows, cols, arr);
|
|
747
|
-
}
|
|
748
|
-
static fromFlat(rows, cols, data) {
|
|
749
|
-
return new DenseMatrix(rows, cols, data);
|
|
750
|
-
}
|
|
751
|
-
static zeros(rows, cols) {
|
|
752
|
-
return new DenseMatrix(rows, cols);
|
|
753
|
-
}
|
|
754
|
-
static ones(rows, cols) {
|
|
755
|
-
const data = new Float64Array(rows * cols).fill(1);
|
|
756
|
-
return new DenseMatrix(rows, cols, data);
|
|
757
|
-
}
|
|
758
|
-
static identity(n) {
|
|
759
|
-
const data = new Float64Array(n * n);
|
|
760
|
-
for (let i = 0; i < n; i++) data[i * n + i] = 1;
|
|
761
|
-
return new DenseMatrix(n, n, data);
|
|
762
|
-
}
|
|
763
|
-
static diag(values) {
|
|
764
|
-
const n = values.length;
|
|
765
|
-
const data = new Float64Array(n * n);
|
|
766
|
-
for (let i = 0; i < n; i++) data[i * n + i] = values[i];
|
|
767
|
-
return new DenseMatrix(n, n, data);
|
|
768
|
-
}
|
|
769
|
-
static fill(rows, cols, value) {
|
|
770
|
-
const data = new Float64Array(rows * cols).fill(value);
|
|
771
|
-
return new DenseMatrix(rows, cols, data);
|
|
772
|
-
}
|
|
773
|
-
static random(rows, cols) {
|
|
774
|
-
const data = new Float64Array(rows * cols);
|
|
775
|
-
for (let i = 0; i < data.length; i++) data[i] = Math.random();
|
|
776
|
-
return new DenseMatrix(rows, cols, data);
|
|
777
|
-
}
|
|
778
|
-
get(row, col) {
|
|
779
|
-
this.checkBounds(row, col);
|
|
780
|
-
return this.data[this.offset + row * this.rowStride + col];
|
|
781
|
-
}
|
|
782
|
-
set(row, col, value) {
|
|
783
|
-
this.checkBounds(row, col);
|
|
784
|
-
const newData = this.toFlatFloat64Array();
|
|
785
|
-
newData[row * this.cols + col] = value;
|
|
786
|
-
return new DenseMatrix(this.rows, this.cols, newData);
|
|
787
|
-
}
|
|
788
|
-
toFlatFloat64Array() {
|
|
789
|
-
if (!this.isView && this.offset === 0 && this.rowStride === this.cols) return new Float64Array(this.data);
|
|
790
|
-
const result = new Float64Array(this.rows * this.cols);
|
|
791
|
-
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) result[i * this.cols + j] = this.data[this.offset + i * this.rowStride + j];
|
|
792
|
-
return result;
|
|
793
|
-
}
|
|
794
|
-
row(index) {
|
|
795
|
-
if (index < 0 || index >= this.rows) throw new RangeError(`Row index ${index} out of bounds for matrix with ${this.rows} rows`);
|
|
796
|
-
return new DenseMatrix(1, this.cols, this.data, {
|
|
797
|
-
isView: true,
|
|
798
|
-
offset: this.offset + index * this.rowStride,
|
|
799
|
-
rowStride: this.rowStride
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
column(index) {
|
|
803
|
-
if (index < 0 || index >= this.cols) throw new RangeError(`Column index ${index} out of bounds for matrix with ${this.cols} columns`);
|
|
804
|
-
const data = new Float64Array(this.rows);
|
|
805
|
-
for (let i = 0; i < this.rows; i++) data[i] = this.get(i, index);
|
|
806
|
-
return new DenseMatrix(this.rows, 1, data);
|
|
807
|
-
}
|
|
808
|
-
slice(spec) {
|
|
809
|
-
const rowStart = spec.rowStart ?? 0;
|
|
810
|
-
const rowEnd = spec.rowEnd ?? this.rows;
|
|
811
|
-
const colStart = spec.colStart ?? 0;
|
|
812
|
-
const colEnd = spec.colEnd ?? this.cols;
|
|
813
|
-
if (rowStart < 0 || rowEnd > this.rows || colStart < 0 || colEnd > this.cols) throw new RangeError("Slice indices out of bounds");
|
|
814
|
-
if (rowStart >= rowEnd || colStart >= colEnd) throw new Error("Invalid slice: start must be less than end");
|
|
815
|
-
const newRows = rowEnd - rowStart;
|
|
816
|
-
const newCols = colEnd - colStart;
|
|
817
|
-
if (colStart === 0 && colEnd === this.cols) return new DenseMatrix(newRows, newCols, this.data, {
|
|
818
|
-
isView: true,
|
|
819
|
-
offset: this.offset + rowStart * this.rowStride,
|
|
820
|
-
rowStride: this.rowStride
|
|
840
|
+
for (const [col, value] of rowResult.entries()) if (value !== 0) entries.push({
|
|
841
|
+
row: i,
|
|
842
|
+
col,
|
|
843
|
+
value
|
|
821
844
|
});
|
|
822
|
-
const data = new Float64Array(newRows * newCols);
|
|
823
|
-
for (let i = 0; i < newRows; i++) for (let j = 0; j < newCols; j++) data[i * newCols + j] = this.get(rowStart + i, colStart + j);
|
|
824
|
-
return new DenseMatrix(newRows, newCols, data);
|
|
825
|
-
}
|
|
826
|
-
diagonal(k = 0) {
|
|
827
|
-
const diagLength = Math.min(this.rows - Math.max(0, k), this.cols - Math.max(0, -k));
|
|
828
|
-
if (diagLength <= 0) return new DenseMatrix(0, 1);
|
|
829
|
-
const data = new Float64Array(diagLength);
|
|
830
|
-
const rowOffset = Math.max(0, -k);
|
|
831
|
-
const colOffset = Math.max(0, k);
|
|
832
|
-
for (let i = 0; i < diagLength; i++) data[i] = this.get(rowOffset + i, colOffset + i);
|
|
833
|
-
return new DenseMatrix(diagLength, 1, data);
|
|
834
|
-
}
|
|
835
|
-
add(other) {
|
|
836
|
-
this.checkDimensionsMatch(other);
|
|
837
|
-
return new DenseMatrix(this.rows, this.cols, add$1(this, other));
|
|
838
|
-
}
|
|
839
|
-
subtract(other) {
|
|
840
|
-
this.checkDimensionsMatch(other);
|
|
841
|
-
return new DenseMatrix(this.rows, this.cols, subtract$1(this, other));
|
|
842
|
-
}
|
|
843
|
-
multiplyElementwise(other) {
|
|
844
|
-
this.checkDimensionsMatch(other);
|
|
845
|
-
return new DenseMatrix(this.rows, this.cols, multiplyElementwise(this, other));
|
|
846
|
-
}
|
|
847
|
-
multiply(other) {
|
|
848
|
-
this.checkMultiplyDimensions(other);
|
|
849
|
-
return new DenseMatrix(this.rows, other.cols, multiply$1(this, other));
|
|
850
|
-
}
|
|
851
|
-
scale(scalar) {
|
|
852
|
-
return new DenseMatrix(this.rows, this.cols, scale(this, scalar));
|
|
853
|
-
}
|
|
854
|
-
transpose() {
|
|
855
|
-
return new DenseMatrix(this.cols, this.rows, transpose$2(this));
|
|
856
|
-
}
|
|
857
|
-
negate() {
|
|
858
|
-
return this.scale(-1);
|
|
859
|
-
}
|
|
860
|
-
sum() {
|
|
861
|
-
return sum$1(this);
|
|
862
845
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
846
|
+
return SparseMatrix.fromCOO(this.rows, other.cols, entries);
|
|
847
|
+
}
|
|
848
|
+
scale(scalar) {
|
|
849
|
+
if (scalar === 0) return SparseMatrix.zeros(this.rows, this.cols);
|
|
850
|
+
const newData = new Float64Array(this._data.length);
|
|
851
|
+
for (let i = 0; i < this._data.length; i++) newData[i] = this._data[i] * scalar;
|
|
852
|
+
return new SparseMatrix(this.rows, this.cols, newData, this._colIndices, this._rowPointers);
|
|
853
|
+
}
|
|
854
|
+
transpose() {
|
|
855
|
+
const nnz = this._data.length;
|
|
856
|
+
const outPtr = new Int32Array(this.cols + 1);
|
|
857
|
+
for (let k = 0; k < nnz; k++) outPtr[this._colIndices[k] + 1]++;
|
|
858
|
+
for (let c = 0; c < this.cols; c++) outPtr[c + 1] += outPtr[c];
|
|
859
|
+
const next = outPtr.slice(0, this.cols);
|
|
860
|
+
const outIdx = new Int32Array(nnz);
|
|
861
|
+
const outVal = new Float64Array(nnz);
|
|
862
|
+
for (let i = 0; i < this.rows; i++) {
|
|
863
|
+
const end = this._rowPointers[i + 1];
|
|
864
|
+
for (let k = this._rowPointers[i]; k < end; k++) {
|
|
865
|
+
const pos = next[this._colIndices[k]]++;
|
|
866
|
+
outIdx[pos] = i;
|
|
867
|
+
outVal[pos] = this._data[k];
|
|
883
868
|
}
|
|
884
|
-
return result;
|
|
885
869
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
870
|
+
return new SparseMatrix(this.cols, this.rows, outVal, outIdx, outPtr);
|
|
871
|
+
}
|
|
872
|
+
negate() {
|
|
873
|
+
return this.scale(-1);
|
|
874
|
+
}
|
|
875
|
+
sum() {
|
|
876
|
+
let total = 0;
|
|
877
|
+
for (let i = 0; i < this._data.length; i++) total += this._data[i];
|
|
878
|
+
return total;
|
|
879
|
+
}
|
|
880
|
+
norm() {
|
|
881
|
+
let sumSq = 0;
|
|
882
|
+
for (let i = 0; i < this._data.length; i++) sumSq += this._data[i] * this._data[i];
|
|
883
|
+
return Math.sqrt(sumSq);
|
|
884
|
+
}
|
|
885
|
+
trace() {
|
|
886
|
+
if (!this.isSquare) throw new Error("Trace is only defined for square matrices");
|
|
887
|
+
let sum = 0;
|
|
888
|
+
for (let i = 0; i < this.rows; i++) sum += this.get(i, i);
|
|
889
|
+
return sum;
|
|
890
|
+
}
|
|
891
|
+
toDense() {
|
|
892
|
+
const data = new Float64Array(this.rows * this.cols);
|
|
893
|
+
for (let i = 0; i < this.rows; i++) {
|
|
894
|
+
const start = this._rowPointers[i];
|
|
895
|
+
const end = this._rowPointers[i + 1];
|
|
896
|
+
for (let j = start; j < end; j++) data[i * this.cols + this._colIndices[j]] = this._data[j];
|
|
891
897
|
}
|
|
892
|
-
|
|
893
|
-
|
|
898
|
+
return new DenseMatrix(this.rows, this.cols, data);
|
|
899
|
+
}
|
|
900
|
+
toArray() {
|
|
901
|
+
return this.toDense().toArray();
|
|
902
|
+
}
|
|
903
|
+
toFlatArray() {
|
|
904
|
+
return this.toDense().toFlatArray();
|
|
905
|
+
}
|
|
906
|
+
clone() {
|
|
907
|
+
return new SparseMatrix(this.rows, this.cols, new Float64Array(this._data), new Int32Array(this._colIndices), new Int32Array(this._rowPointers));
|
|
908
|
+
}
|
|
909
|
+
getCSR() {
|
|
910
|
+
return {
|
|
911
|
+
values: new Float64Array(this._data),
|
|
912
|
+
colIndices: new Int32Array(this._colIndices),
|
|
913
|
+
rowPointers: new Int32Array(this._rowPointers)
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
*entries() {
|
|
917
|
+
for (let i = 0; i < this.rows; i++) {
|
|
918
|
+
const start = this._rowPointers[i];
|
|
919
|
+
const end = this._rowPointers[i + 1];
|
|
920
|
+
for (let j = start; j < end; j++) yield {
|
|
921
|
+
row: i,
|
|
922
|
+
col: this._colIndices[j],
|
|
923
|
+
value: this._data[j]
|
|
924
|
+
};
|
|
894
925
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
926
|
+
}
|
|
927
|
+
*values() {
|
|
928
|
+
for (let i = 0; i < this._data.length; i++) yield this._data[i];
|
|
929
|
+
}
|
|
930
|
+
*allValues() {
|
|
931
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) yield this.get(i, j);
|
|
932
|
+
}
|
|
933
|
+
[Symbol.iterator]() {
|
|
934
|
+
return this.values();
|
|
935
|
+
}
|
|
936
|
+
mapNonZeros(fn) {
|
|
937
|
+
const entries = [];
|
|
938
|
+
for (let i = 0; i < this.rows; i++) {
|
|
939
|
+
const start = this._rowPointers[i];
|
|
940
|
+
const end = this._rowPointers[i + 1];
|
|
941
|
+
for (let j = start; j < end; j++) {
|
|
942
|
+
const col = this._colIndices[j];
|
|
943
|
+
const newVal = fn(this._data[j], i, col);
|
|
944
|
+
if (newVal !== 0) entries.push({
|
|
945
|
+
row: i,
|
|
946
|
+
col,
|
|
947
|
+
value: newVal
|
|
948
|
+
});
|
|
908
949
|
}
|
|
909
|
-
return new (init_SparseMatrix(), __toCommonJS(SparseMatrix_exports)).SparseMatrix(this.rows, this.cols, new Float64Array(values), new Int32Array(colIndices), new Int32Array(rowPointers));
|
|
910
950
|
}
|
|
911
|
-
|
|
912
|
-
|
|
951
|
+
return SparseMatrix.fromCOO(this.rows, this.cols, entries);
|
|
952
|
+
}
|
|
953
|
+
map(fn) {
|
|
954
|
+
const entries = [];
|
|
955
|
+
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) {
|
|
956
|
+
const newVal = fn(this.get(i, j), i, j);
|
|
957
|
+
if (newVal !== 0) entries.push({
|
|
913
958
|
row: i,
|
|
914
959
|
col: j,
|
|
915
|
-
value:
|
|
916
|
-
};
|
|
917
|
-
}
|
|
918
|
-
*values() {
|
|
919
|
-
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) yield this.get(i, j);
|
|
920
|
-
}
|
|
921
|
-
[Symbol.iterator]() {
|
|
922
|
-
return this.values();
|
|
923
|
-
}
|
|
924
|
-
map(fn) {
|
|
925
|
-
const result = new Float64Array(this.rows * this.cols);
|
|
926
|
-
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) result[i * this.cols + j] = fn(this.get(i, j), i, j);
|
|
927
|
-
return new DenseMatrix(this.rows, this.cols, result);
|
|
928
|
-
}
|
|
929
|
-
forEach(fn) {
|
|
930
|
-
for (let i = 0; i < this.rows; i++) for (let j = 0; j < this.cols; j++) fn(this.get(i, j), i, j);
|
|
960
|
+
value: newVal
|
|
961
|
+
});
|
|
931
962
|
}
|
|
932
|
-
|
|
933
|
-
}
|
|
963
|
+
return SparseMatrix.fromCOO(this.rows, this.cols, entries);
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
registerSparseMatrixFactory((rows, cols, values, colIndices, rowPointers) => new SparseMatrix(rows, cols, values, colIndices, rowPointers));
|
|
967
|
+
function isSparseMatrix(value) {
|
|
968
|
+
return value instanceof SparseMatrix;
|
|
969
|
+
}
|
|
934
970
|
//#endregion
|
|
935
971
|
//#region src/backends/Backend.ts
|
|
936
972
|
const DEFAULT_BACKEND_HINTS = {
|
|
@@ -987,8 +1023,6 @@ var BackendRegistry = class {
|
|
|
987
1023
|
const backendRegistry = new BackendRegistry();
|
|
988
1024
|
//#endregion
|
|
989
1025
|
//#region src/backends/JSBackend.ts
|
|
990
|
-
init_DenseMatrix();
|
|
991
|
-
init_reduction();
|
|
992
1026
|
var JSBackend = class {
|
|
993
1027
|
type = "js";
|
|
994
1028
|
isAvailable() {
|
|
@@ -997,36 +1031,52 @@ var JSBackend = class {
|
|
|
997
1031
|
async initialize() {}
|
|
998
1032
|
add(a, b) {
|
|
999
1033
|
this.checkDimensionsMatch(a, b);
|
|
1000
|
-
const
|
|
1001
|
-
|
|
1034
|
+
const ad = denseContiguousData(a);
|
|
1035
|
+
const bd = denseContiguousData(b);
|
|
1036
|
+
const n = ad.length;
|
|
1037
|
+
const result = new Float64Array(n);
|
|
1038
|
+
for (let i = 0; i < n; i++) result[i] = ad[i] + bd[i];
|
|
1002
1039
|
return new DenseMatrix(a.rows, a.cols, result);
|
|
1003
1040
|
}
|
|
1004
1041
|
subtract(a, b) {
|
|
1005
1042
|
this.checkDimensionsMatch(a, b);
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1043
|
+
const ad = denseContiguousData(a);
|
|
1044
|
+
const bd = denseContiguousData(b);
|
|
1045
|
+
const n = ad.length;
|
|
1046
|
+
const result = new Float64Array(n);
|
|
1047
|
+
for (let i = 0; i < n; i++) result[i] = ad[i] - bd[i];
|
|
1008
1048
|
return new DenseMatrix(a.rows, a.cols, result);
|
|
1009
1049
|
}
|
|
1010
1050
|
multiplyElementwise(a, b) {
|
|
1011
1051
|
this.checkDimensionsMatch(a, b);
|
|
1012
|
-
const
|
|
1013
|
-
|
|
1052
|
+
const ad = denseContiguousData(a);
|
|
1053
|
+
const bd = denseContiguousData(b);
|
|
1054
|
+
const n = ad.length;
|
|
1055
|
+
const result = new Float64Array(n);
|
|
1056
|
+
for (let i = 0; i < n; i++) result[i] = ad[i] * bd[i];
|
|
1014
1057
|
return new DenseMatrix(a.rows, a.cols, result);
|
|
1015
1058
|
}
|
|
1016
1059
|
divideElementwise(a, b) {
|
|
1017
1060
|
this.checkDimensionsMatch(a, b);
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1061
|
+
const ad = denseContiguousData(a);
|
|
1062
|
+
const bd = denseContiguousData(b);
|
|
1063
|
+
const n = ad.length;
|
|
1064
|
+
const result = new Float64Array(n);
|
|
1065
|
+
for (let i = 0; i < n; i++) result[i] = ad[i] / bd[i];
|
|
1020
1066
|
return new DenseMatrix(a.rows, a.cols, result);
|
|
1021
1067
|
}
|
|
1022
1068
|
scale(a, scalar) {
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1069
|
+
const ad = denseContiguousData(a);
|
|
1070
|
+
const n = ad.length;
|
|
1071
|
+
const result = new Float64Array(n);
|
|
1072
|
+
for (let i = 0; i < n; i++) result[i] = ad[i] * scalar;
|
|
1025
1073
|
return new DenseMatrix(a.rows, a.cols, result);
|
|
1026
1074
|
}
|
|
1027
1075
|
abs(a) {
|
|
1028
|
-
const
|
|
1029
|
-
|
|
1076
|
+
const ad = denseContiguousData(a);
|
|
1077
|
+
const n = ad.length;
|
|
1078
|
+
const result = new Float64Array(n);
|
|
1079
|
+
for (let i = 0; i < n; i++) result[i] = Math.abs(ad[i]);
|
|
1030
1080
|
return new DenseMatrix(a.rows, a.cols, result);
|
|
1031
1081
|
}
|
|
1032
1082
|
negate(a) {
|
|
@@ -1052,24 +1102,42 @@ var JSBackend = class {
|
|
|
1052
1102
|
return new DenseMatrix(m, n, result);
|
|
1053
1103
|
}
|
|
1054
1104
|
transpose(a) {
|
|
1055
|
-
const
|
|
1056
|
-
|
|
1057
|
-
|
|
1105
|
+
const rows = a.rows;
|
|
1106
|
+
const cols = a.cols;
|
|
1107
|
+
const ad = denseContiguousData(a);
|
|
1108
|
+
const result = new Float64Array(cols * rows);
|
|
1109
|
+
for (let i = 0; i < rows; i++) {
|
|
1110
|
+
const ai = i * cols;
|
|
1111
|
+
for (let j = 0; j < cols; j++) result[j * rows + i] = ad[ai + j];
|
|
1112
|
+
}
|
|
1113
|
+
return new DenseMatrix(cols, rows, result);
|
|
1058
1114
|
}
|
|
1059
1115
|
sum(a) {
|
|
1116
|
+
const ad = denseContiguousData(a);
|
|
1060
1117
|
let total = 0;
|
|
1061
|
-
for (let i = 0; i <
|
|
1118
|
+
for (let i = 0; i < ad.length; i++) total += ad[i];
|
|
1062
1119
|
return total;
|
|
1063
1120
|
}
|
|
1064
1121
|
sumAxis(a, axis) {
|
|
1122
|
+
const rows = a.rows;
|
|
1123
|
+
const cols = a.cols;
|
|
1124
|
+
const ad = denseContiguousData(a);
|
|
1065
1125
|
if (axis === 0) {
|
|
1066
|
-
const result = new Float64Array(
|
|
1067
|
-
for (let
|
|
1068
|
-
|
|
1126
|
+
const result = new Float64Array(cols);
|
|
1127
|
+
for (let i = 0; i < rows; i++) {
|
|
1128
|
+
const ai = i * cols;
|
|
1129
|
+
for (let j = 0; j < cols; j++) result[j] += ad[ai + j];
|
|
1130
|
+
}
|
|
1131
|
+
return new DenseMatrix(1, cols, result);
|
|
1069
1132
|
} else {
|
|
1070
|
-
const result = new Float64Array(
|
|
1071
|
-
for (let i = 0; i <
|
|
1072
|
-
|
|
1133
|
+
const result = new Float64Array(rows);
|
|
1134
|
+
for (let i = 0; i < rows; i++) {
|
|
1135
|
+
const ai = i * cols;
|
|
1136
|
+
let acc = 0;
|
|
1137
|
+
for (let j = 0; j < cols; j++) acc += ad[ai + j];
|
|
1138
|
+
result[i] = acc;
|
|
1139
|
+
}
|
|
1140
|
+
return new DenseMatrix(rows, 1, result);
|
|
1073
1141
|
}
|
|
1074
1142
|
}
|
|
1075
1143
|
norm(a) {
|
|
@@ -1079,9 +1147,9 @@ var JSBackend = class {
|
|
|
1079
1147
|
if (!a.isVector || !b.isVector) throw new Error("Dot product requires two vectors");
|
|
1080
1148
|
if (a.length !== b.length) throw new Error(`Vector lengths must match: ${a.length} vs ${b.length}`);
|
|
1081
1149
|
let sum = 0;
|
|
1082
|
-
const
|
|
1083
|
-
const
|
|
1084
|
-
for (let i = 0; i <
|
|
1150
|
+
const ad = denseContiguousData(a);
|
|
1151
|
+
const bd = denseContiguousData(b);
|
|
1152
|
+
for (let i = 0; i < ad.length; i++) sum += ad[i] * bd[i];
|
|
1085
1153
|
return sum;
|
|
1086
1154
|
}
|
|
1087
1155
|
checkDimensionsMatch(a, b) {
|
|
@@ -1094,7 +1162,6 @@ var JSBackend = class {
|
|
|
1094
1162
|
const jsBackend = new JSBackend();
|
|
1095
1163
|
//#endregion
|
|
1096
1164
|
//#region src/backends/ParallelBackend.ts
|
|
1097
|
-
init_DenseMatrix();
|
|
1098
1165
|
var ParallelBackend = class {
|
|
1099
1166
|
type = "parallel";
|
|
1100
1167
|
pool;
|
|
@@ -1493,7 +1560,6 @@ function allocAsTypedView(module, byteLength, length, typeId, Ctor) {
|
|
|
1493
1560
|
}
|
|
1494
1561
|
//#endregion
|
|
1495
1562
|
//#region src/backends/WASMBackend.ts
|
|
1496
|
-
init_DenseMatrix();
|
|
1497
1563
|
var AsAllocCache = class {
|
|
1498
1564
|
free = /* @__PURE__ */ new Map();
|
|
1499
1565
|
acquire(module, length) {
|
|
@@ -1701,7 +1767,7 @@ var WASMBackend = class {
|
|
|
1701
1767
|
try {
|
|
1702
1768
|
mod.matrix_multiply_simd_ptr(aAlloc.bufferPtr, a.rows, a.cols, bAlloc.bufferPtr, b.cols, rAlloc.bufferPtr);
|
|
1703
1769
|
const result = readAsFloat64Array(mod, rAlloc);
|
|
1704
|
-
return DenseMatrix
|
|
1770
|
+
return new DenseMatrix(a.rows, b.cols, result);
|
|
1705
1771
|
} finally {
|
|
1706
1772
|
this.allocCache.release(aAlloc);
|
|
1707
1773
|
this.allocCache.release(bAlloc);
|
|
@@ -1744,7 +1810,7 @@ var WASMBackend = class {
|
|
|
1744
1810
|
for (let i = 0; i < n; i++) for (let j = 0; j < n; j++) combined[i * n + j] = i > j ? lFlat[i * n + j] : uFlat[i * n + j];
|
|
1745
1811
|
const perm = readAsInt32Array(mod, permAlloc);
|
|
1746
1812
|
return {
|
|
1747
|
-
lu: DenseMatrix
|
|
1813
|
+
lu: new DenseMatrix(n, n, combined),
|
|
1748
1814
|
perm,
|
|
1749
1815
|
singular: false
|
|
1750
1816
|
};
|
|
@@ -1772,7 +1838,7 @@ var WASMBackend = class {
|
|
|
1772
1838
|
}
|
|
1773
1839
|
}
|
|
1774
1840
|
if (maxVal < 1e-14) return {
|
|
1775
|
-
lu: DenseMatrix
|
|
1841
|
+
lu: new DenseMatrix(n, n, data),
|
|
1776
1842
|
perm,
|
|
1777
1843
|
singular: true
|
|
1778
1844
|
};
|
|
@@ -1794,7 +1860,7 @@ var WASMBackend = class {
|
|
|
1794
1860
|
}
|
|
1795
1861
|
}
|
|
1796
1862
|
return {
|
|
1797
|
-
lu: DenseMatrix
|
|
1863
|
+
lu: new DenseMatrix(n, n, data),
|
|
1798
1864
|
perm,
|
|
1799
1865
|
singular: false
|
|
1800
1866
|
};
|
|
@@ -1813,8 +1879,8 @@ var WASMBackend = class {
|
|
|
1813
1879
|
const qFlat = readAsFloat64Array(mod, qAlloc);
|
|
1814
1880
|
const rFlat = readAsFloat64Array(mod, rAlloc);
|
|
1815
1881
|
return {
|
|
1816
|
-
q: DenseMatrix
|
|
1817
|
-
r: DenseMatrix
|
|
1882
|
+
q: new DenseMatrix(m, m, qFlat),
|
|
1883
|
+
r: new DenseMatrix(m, n, rFlat)
|
|
1818
1884
|
};
|
|
1819
1885
|
} finally {
|
|
1820
1886
|
this.allocCache.release(aAlloc);
|
|
@@ -1862,8 +1928,8 @@ var WASMBackend = class {
|
|
|
1862
1928
|
}
|
|
1863
1929
|
}
|
|
1864
1930
|
return {
|
|
1865
|
-
q: DenseMatrix
|
|
1866
|
-
r: DenseMatrix
|
|
1931
|
+
q: new DenseMatrix(m, m, q),
|
|
1932
|
+
r: new DenseMatrix(m, n, r)
|
|
1867
1933
|
};
|
|
1868
1934
|
}
|
|
1869
1935
|
async inverse(a) {
|
|
@@ -1879,9 +1945,8 @@ var WASMBackend = class {
|
|
|
1879
1945
|
inverse: DenseMatrix.zeros(n, n),
|
|
1880
1946
|
singular: true
|
|
1881
1947
|
};
|
|
1882
|
-
const result = readAsFloat64Array(mod, resultAlloc);
|
|
1883
1948
|
return {
|
|
1884
|
-
inverse: DenseMatrix
|
|
1949
|
+
inverse: new DenseMatrix(n, n, readAsFloat64Array(mod, resultAlloc)),
|
|
1885
1950
|
singular: false
|
|
1886
1951
|
};
|
|
1887
1952
|
} finally {
|
|
@@ -1916,7 +1981,7 @@ var WASMBackend = class {
|
|
|
1916
1981
|
for (let i = 0; i < n; i++) result[i * n + col] = x[i];
|
|
1917
1982
|
}
|
|
1918
1983
|
return {
|
|
1919
|
-
inverse: DenseMatrix
|
|
1984
|
+
inverse: new DenseMatrix(n, n, result),
|
|
1920
1985
|
singular: false
|
|
1921
1986
|
};
|
|
1922
1987
|
}
|
|
@@ -1966,9 +2031,8 @@ var WASMBackend = class {
|
|
|
1966
2031
|
l: DenseMatrix.zeros(n, n),
|
|
1967
2032
|
positiveDefinite: false
|
|
1968
2033
|
};
|
|
1969
|
-
const result = readAsFloat64Array(mod, lAlloc);
|
|
1970
2034
|
return {
|
|
1971
|
-
l: DenseMatrix
|
|
2035
|
+
l: new DenseMatrix(n, n, readAsFloat64Array(mod, lAlloc)),
|
|
1972
2036
|
positiveDefinite: true
|
|
1973
2037
|
};
|
|
1974
2038
|
} finally {
|
|
@@ -1993,7 +2057,7 @@ var WASMBackend = class {
|
|
|
1993
2057
|
} else l[i * n + j] = sum / l[j * n + j];
|
|
1994
2058
|
}
|
|
1995
2059
|
return {
|
|
1996
|
-
l: DenseMatrix
|
|
2060
|
+
l: new DenseMatrix(n, n, l),
|
|
1997
2061
|
positiveDefinite: true
|
|
1998
2062
|
};
|
|
1999
2063
|
}
|
|
@@ -2524,7 +2588,6 @@ async function gpuOrJs(useGpu, js, gpu, executeWithFallback) {
|
|
|
2524
2588
|
}
|
|
2525
2589
|
//#endregion
|
|
2526
2590
|
//#region src/backends/GPUMatrixBackend.ts
|
|
2527
|
-
init_DenseMatrix();
|
|
2528
2591
|
const DEFAULT_CONFIG$1 = {
|
|
2529
2592
|
minElements: 65536,
|
|
2530
2593
|
useGlobalBackend: true,
|
|
@@ -2596,7 +2659,7 @@ var GPUMatrixBackend = class {
|
|
|
2596
2659
|
const aData = new Float32Array(a.toFloat64Array());
|
|
2597
2660
|
const bData = new Float32Array(b.toFloat64Array());
|
|
2598
2661
|
const result = await this.backend.add(aData, bData, a.rows, a.cols);
|
|
2599
|
-
return DenseMatrix
|
|
2662
|
+
return new DenseMatrix(a.rows, a.cols, new Float64Array(result));
|
|
2600
2663
|
}, (gpuOp, fallback) => this.executeWithFallback(gpuOp, fallback));
|
|
2601
2664
|
}
|
|
2602
2665
|
subtract(a, b) {
|
|
@@ -2624,7 +2687,7 @@ var GPUMatrixBackend = class {
|
|
|
2624
2687
|
return gpuOrJs(this.shouldUseGPU(elementCount), () => jsBackend.scale(a, scalar), async () => {
|
|
2625
2688
|
const aData = new Float32Array(a.toFloat64Array());
|
|
2626
2689
|
const result = await this.backend.scale(aData, scalar);
|
|
2627
|
-
return DenseMatrix
|
|
2690
|
+
return new DenseMatrix(a.rows, a.cols, new Float64Array(result));
|
|
2628
2691
|
}, (gpuOp, fallback) => this.executeWithFallback(gpuOp, fallback));
|
|
2629
2692
|
}
|
|
2630
2693
|
abs(a) {
|
|
@@ -2644,7 +2707,7 @@ var GPUMatrixBackend = class {
|
|
|
2644
2707
|
const aData = new Float32Array(a.toFloat64Array());
|
|
2645
2708
|
const bData = new Float32Array(b.toFloat64Array());
|
|
2646
2709
|
const result = await this.backend.matmul(aData, bData, a.rows, a.cols, b.cols);
|
|
2647
|
-
return DenseMatrix
|
|
2710
|
+
return new DenseMatrix(a.rows, b.cols, new Float64Array(result));
|
|
2648
2711
|
}, (gpuOp, fallback) => this.executeWithFallback(gpuOp, fallback));
|
|
2649
2712
|
}
|
|
2650
2713
|
transpose(a) {
|
|
@@ -2658,7 +2721,7 @@ var GPUMatrixBackend = class {
|
|
|
2658
2721
|
return this.executeWithFallback(async () => {
|
|
2659
2722
|
const aData = new Float32Array(a.toFloat64Array());
|
|
2660
2723
|
const result = await this.backend.transpose(aData, a.rows, a.cols);
|
|
2661
|
-
return DenseMatrix
|
|
2724
|
+
return new DenseMatrix(a.cols, a.rows, new Float64Array(result));
|
|
2662
2725
|
}, () => jsBackend.transpose(a));
|
|
2663
2726
|
}
|
|
2664
2727
|
sum(a) {
|
|
@@ -4513,7 +4576,6 @@ async function svdWasm(matrix, options) {
|
|
|
4513
4576
|
}
|
|
4514
4577
|
//#endregion
|
|
4515
4578
|
//#region src/operations/pinv.ts
|
|
4516
|
-
init_DenseMatrix();
|
|
4517
4579
|
function pinv(A, opts) {
|
|
4518
4580
|
const rcond = opts?.rcond ?? 1e-10;
|
|
4519
4581
|
const m = A.rows;
|
|
@@ -4533,7 +4595,6 @@ function pinv(A, opts) {
|
|
|
4533
4595
|
}
|
|
4534
4596
|
//#endregion
|
|
4535
4597
|
//#region src/operations/qr.ts
|
|
4536
|
-
init_DenseMatrix();
|
|
4537
4598
|
function qr(A, opts) {
|
|
4538
4599
|
const mode = opts?.mode ?? "reduced";
|
|
4539
4600
|
const m = A.rows;
|
|
@@ -4622,12 +4683,10 @@ function qr(A, opts) {
|
|
|
4622
4683
|
}
|
|
4623
4684
|
//#endregion
|
|
4624
4685
|
//#region src/operations/lu.ts
|
|
4625
|
-
init_DenseMatrix();
|
|
4626
4686
|
function lu(A) {
|
|
4627
4687
|
const n = A.rows;
|
|
4628
4688
|
if (A.cols !== n) throw new Error(`lu: matrix must be square (got ${A.rows}×${A.cols})`);
|
|
4629
|
-
const
|
|
4630
|
-
const W = new Float64Array(flat);
|
|
4689
|
+
const W = A.toFloat64Array();
|
|
4631
4690
|
const perm = new Array(n);
|
|
4632
4691
|
for (let i = 0; i < n; i++) perm[i] = i;
|
|
4633
4692
|
for (let k = 0; k < n; k++) {
|
|
@@ -4693,7 +4752,6 @@ function luSolve(fac, b) {
|
|
|
4693
4752
|
}
|
|
4694
4753
|
//#endregion
|
|
4695
4754
|
//#region src/operations/cholesky.ts
|
|
4696
|
-
init_DenseMatrix();
|
|
4697
4755
|
function cholesky(A) {
|
|
4698
4756
|
const n = A.rows;
|
|
4699
4757
|
if (A.cols !== n) throw new Error(`cholesky: matrix must be square (got ${A.rows}×${A.cols})`);
|
|
@@ -4715,7 +4773,6 @@ function cholesky(A) {
|
|
|
4715
4773
|
}
|
|
4716
4774
|
//#endregion
|
|
4717
4775
|
//#region src/operations/expm.ts
|
|
4718
|
-
init_DenseMatrix();
|
|
4719
4776
|
const THETA_13 = 5.371920351148152;
|
|
4720
4777
|
const B = [
|
|
4721
4778
|
0xe6173304aa2000,
|
|
@@ -4777,7 +4834,6 @@ function matrixExpm(A) {
|
|
|
4777
4834
|
}
|
|
4778
4835
|
//#endregion
|
|
4779
4836
|
//#region src/operations/schur.ts
|
|
4780
|
-
init_DenseMatrix();
|
|
4781
4837
|
function hessenbergReduce(A) {
|
|
4782
4838
|
const n = A.length;
|
|
4783
4839
|
const H = cloneMatrix(A);
|
|
@@ -4987,7 +5043,6 @@ function schurInternal(A, maxIterations = 1e3, tolerance = 1e-12) {
|
|
|
4987
5043
|
}
|
|
4988
5044
|
//#endregion
|
|
4989
5045
|
//#region src/operations/sqrtm.ts
|
|
4990
|
-
init_DenseMatrix();
|
|
4991
5046
|
function symmetrize(A) {
|
|
4992
5047
|
const n = A.length;
|
|
4993
5048
|
return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (A[i][j] + A[j][i]) / 2));
|
|
@@ -5189,7 +5244,6 @@ function matrixSqrtNewtonInternal(A) {
|
|
|
5189
5244
|
}
|
|
5190
5245
|
//#endregion
|
|
5191
5246
|
//#region src/operations/logm.ts
|
|
5192
|
-
init_DenseMatrix();
|
|
5193
5247
|
const GL16_NODES = [
|
|
5194
5248
|
.00529953674226076,
|
|
5195
5249
|
.02771248846338012,
|
|
@@ -5350,7 +5404,6 @@ function matrixLogm(A, opts) {
|
|
|
5350
5404
|
}
|
|
5351
5405
|
//#endregion
|
|
5352
5406
|
//#region src/operations/qr-pivoted.ts
|
|
5353
|
-
init_DenseMatrix();
|
|
5354
5407
|
function qrPivoted(A, opts) {
|
|
5355
5408
|
const m = A.rows;
|
|
5356
5409
|
const n = A.cols;
|
|
@@ -5423,7 +5476,6 @@ function qrPivoted(A, opts) {
|
|
|
5423
5476
|
}
|
|
5424
5477
|
//#endregion
|
|
5425
5478
|
//#region src/operations/qr-family.ts
|
|
5426
|
-
init_DenseMatrix();
|
|
5427
5479
|
function flipDense(M, axis) {
|
|
5428
5480
|
const m = M.rows;
|
|
5429
5481
|
const n = M.cols;
|
|
@@ -5550,7 +5602,6 @@ function condest(A, p = 1) {
|
|
|
5550
5602
|
}
|
|
5551
5603
|
//#endregion
|
|
5552
5604
|
//#region src/typed-operations.ts
|
|
5553
|
-
init_DenseMatrix();
|
|
5554
5605
|
const matrix = mathTyped("matrix", {
|
|
5555
5606
|
Array: (arr) => DenseMatrix.fromArray(arr),
|
|
5556
5607
|
"number, number": (rows, cols) => DenseMatrix.zeros(rows, cols),
|
|
@@ -5689,7 +5740,6 @@ const typedMatrixOperations = {
|
|
|
5689
5740
|
};
|
|
5690
5741
|
//#endregion
|
|
5691
5742
|
//#region src/parallel-matrix.ts
|
|
5692
|
-
init_DenseMatrix();
|
|
5693
5743
|
const computePool$1 = computePool;
|
|
5694
5744
|
async function pSum(data) {
|
|
5695
5745
|
return computePool$1.sum(data);
|
|
@@ -6153,9 +6203,4 @@ async function terminateParallelMatrix() {
|
|
|
6153
6203
|
await computePool$1.terminate();
|
|
6154
6204
|
}
|
|
6155
6205
|
//#endregion
|
|
6156
|
-
//#region src/index.ts
|
|
6157
|
-
init_Matrix();
|
|
6158
|
-
init_SparseMatrix();
|
|
6159
|
-
init_DenseMatrix();
|
|
6160
|
-
//#endregion
|
|
6161
6206
|
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 };
|