edgeflowjs 0.1.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.
Files changed (98) hide show
  1. package/README.md +473 -0
  2. package/dist/backends/index.d.ts +13 -0
  3. package/dist/backends/index.d.ts.map +1 -0
  4. package/dist/backends/index.js +32 -0
  5. package/dist/backends/index.js.map +1 -0
  6. package/dist/backends/onnx.d.ts +46 -0
  7. package/dist/backends/onnx.d.ts.map +1 -0
  8. package/dist/backends/onnx.js +249 -0
  9. package/dist/backends/onnx.js.map +1 -0
  10. package/dist/backends/wasm.d.ts +78 -0
  11. package/dist/backends/wasm.d.ts.map +1 -0
  12. package/dist/backends/wasm.js +358 -0
  13. package/dist/backends/wasm.js.map +1 -0
  14. package/dist/backends/webgpu.d.ts +143 -0
  15. package/dist/backends/webgpu.d.ts.map +1 -0
  16. package/dist/backends/webgpu.js +326 -0
  17. package/dist/backends/webgpu.js.map +1 -0
  18. package/dist/backends/webnn.d.ts +115 -0
  19. package/dist/backends/webnn.d.ts.map +1 -0
  20. package/dist/backends/webnn.js +202 -0
  21. package/dist/backends/webnn.js.map +1 -0
  22. package/dist/core/index.d.ts +9 -0
  23. package/dist/core/index.d.ts.map +1 -0
  24. package/dist/core/index.js +14 -0
  25. package/dist/core/index.js.map +1 -0
  26. package/dist/core/memory.d.ts +234 -0
  27. package/dist/core/memory.d.ts.map +1 -0
  28. package/dist/core/memory.js +554 -0
  29. package/dist/core/memory.js.map +1 -0
  30. package/dist/core/runtime.d.ts +129 -0
  31. package/dist/core/runtime.d.ts.map +1 -0
  32. package/dist/core/runtime.js +352 -0
  33. package/dist/core/runtime.js.map +1 -0
  34. package/dist/core/scheduler.d.ts +118 -0
  35. package/dist/core/scheduler.d.ts.map +1 -0
  36. package/dist/core/scheduler.js +600 -0
  37. package/dist/core/scheduler.js.map +1 -0
  38. package/dist/core/tensor.d.ts +149 -0
  39. package/dist/core/tensor.d.ts.map +1 -0
  40. package/dist/core/tensor.js +719 -0
  41. package/dist/core/tensor.js.map +1 -0
  42. package/dist/core/types.d.ts +367 -0
  43. package/dist/core/types.d.ts.map +1 -0
  44. package/dist/core/types.js +54 -0
  45. package/dist/core/types.js.map +1 -0
  46. package/dist/edgeflow.browser.js +5601 -0
  47. package/dist/edgeflow.browser.js.map +7 -0
  48. package/dist/edgeflow.browser.min.js +19 -0
  49. package/dist/edgeflow.browser.min.js.map +7 -0
  50. package/dist/index.d.ts +71 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +158 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/pipelines/base.d.ts +122 -0
  55. package/dist/pipelines/base.d.ts.map +1 -0
  56. package/dist/pipelines/base.js +155 -0
  57. package/dist/pipelines/base.js.map +1 -0
  58. package/dist/pipelines/feature-extraction.d.ts +68 -0
  59. package/dist/pipelines/feature-extraction.d.ts.map +1 -0
  60. package/dist/pipelines/feature-extraction.js +197 -0
  61. package/dist/pipelines/feature-extraction.js.map +1 -0
  62. package/dist/pipelines/image-classification.d.ts +61 -0
  63. package/dist/pipelines/image-classification.d.ts.map +1 -0
  64. package/dist/pipelines/image-classification.js +140 -0
  65. package/dist/pipelines/image-classification.js.map +1 -0
  66. package/dist/pipelines/index.d.ts +58 -0
  67. package/dist/pipelines/index.d.ts.map +1 -0
  68. package/dist/pipelines/index.js +72 -0
  69. package/dist/pipelines/index.js.map +1 -0
  70. package/dist/pipelines/text-classification.d.ts +71 -0
  71. package/dist/pipelines/text-classification.d.ts.map +1 -0
  72. package/dist/pipelines/text-classification.js +175 -0
  73. package/dist/pipelines/text-classification.js.map +1 -0
  74. package/dist/tools/index.d.ts +143 -0
  75. package/dist/tools/index.d.ts.map +1 -0
  76. package/dist/tools/index.js +294 -0
  77. package/dist/tools/index.js.map +1 -0
  78. package/dist/utils/cache.d.ts +162 -0
  79. package/dist/utils/cache.d.ts.map +1 -0
  80. package/dist/utils/cache.js +443 -0
  81. package/dist/utils/cache.js.map +1 -0
  82. package/dist/utils/index.d.ts +8 -0
  83. package/dist/utils/index.d.ts.map +1 -0
  84. package/dist/utils/index.js +12 -0
  85. package/dist/utils/index.js.map +1 -0
  86. package/dist/utils/model-loader.d.ts +107 -0
  87. package/dist/utils/model-loader.d.ts.map +1 -0
  88. package/dist/utils/model-loader.js +694 -0
  89. package/dist/utils/model-loader.js.map +1 -0
  90. package/dist/utils/preprocessor.d.ts +147 -0
  91. package/dist/utils/preprocessor.d.ts.map +1 -0
  92. package/dist/utils/preprocessor.js +423 -0
  93. package/dist/utils/preprocessor.js.map +1 -0
  94. package/dist/utils/tokenizer.d.ts +140 -0
  95. package/dist/utils/tokenizer.d.ts.map +1 -0
  96. package/dist/utils/tokenizer.js +397 -0
  97. package/dist/utils/tokenizer.js.map +1 -0
  98. package/package.json +87 -0
@@ -0,0 +1,719 @@
1
+ /**
2
+ * edgeFlow.js - Tensor Implementation
3
+ *
4
+ * Lightweight tensor implementation with efficient memory management.
5
+ */
6
+ import { EdgeFlowError, ErrorCodes } from './types.js';
7
+ // Counter for generating unique tensor IDs
8
+ let tensorIdCounter = 0;
9
+ /**
10
+ * Generate a unique tensor ID
11
+ */
12
+ function generateTensorId() {
13
+ return `tensor_${++tensorIdCounter}_${Date.now().toString(36)}`;
14
+ }
15
+ /**
16
+ * Get the typed array constructor for a data type
17
+ */
18
+ function getTypedArrayConstructor(dtype) {
19
+ switch (dtype) {
20
+ case 'float32':
21
+ return Float32Array;
22
+ case 'float16':
23
+ // Float16 not natively supported, use Float32Array
24
+ return Float32Array;
25
+ case 'int32':
26
+ return Int32Array;
27
+ case 'int64':
28
+ return BigInt64Array;
29
+ case 'uint8':
30
+ case 'bool':
31
+ return Uint8Array;
32
+ case 'int8':
33
+ return Int8Array;
34
+ default:
35
+ throw new EdgeFlowError(`Unsupported data type: ${dtype}`, ErrorCodes.INVALID_ARGUMENT, { dtype });
36
+ }
37
+ }
38
+ /**
39
+ * Calculate the total number of elements from shape
40
+ */
41
+ function calculateSize(shape) {
42
+ if (shape.length === 0)
43
+ return 1; // Scalar
44
+ return shape.reduce((acc, dim) => acc * dim, 1);
45
+ }
46
+ /**
47
+ * Validate tensor shape
48
+ */
49
+ function validateShape(shape) {
50
+ for (let i = 0; i < shape.length; i++) {
51
+ const dim = shape[i];
52
+ if (dim === undefined || !Number.isInteger(dim) || dim < 0) {
53
+ throw new EdgeFlowError(`Invalid shape dimension at index ${i}: ${dim}`, ErrorCodes.INVALID_ARGUMENT, { shape, index: i, dimension: dim });
54
+ }
55
+ }
56
+ }
57
+ /**
58
+ * EdgeFlowTensor - Core tensor implementation
59
+ */
60
+ export class EdgeFlowTensor {
61
+ id;
62
+ dtype;
63
+ shape;
64
+ size;
65
+ _data;
66
+ _isDisposed = false;
67
+ constructor(data, shape, dtype = 'float32') {
68
+ validateShape(shape);
69
+ this.id = generateTensorId();
70
+ this.dtype = dtype;
71
+ this.shape = Object.freeze([...shape]);
72
+ this.size = calculateSize(this.shape);
73
+ // Validate data size matches shape
74
+ const expectedSize = this.size;
75
+ if (data.length !== expectedSize) {
76
+ throw new EdgeFlowError(`Data length (${data.length}) does not match shape ${JSON.stringify(shape)} (expected ${expectedSize})`, ErrorCodes.TENSOR_SHAPE_MISMATCH, { dataLength: data.length, expectedSize, shape });
77
+ }
78
+ // Convert to appropriate typed array
79
+ if (data instanceof Array) {
80
+ const TypedArrayCtor = getTypedArrayConstructor(dtype);
81
+ this._data = new TypedArrayCtor(data.length);
82
+ if (dtype === 'int64') {
83
+ // BigInt64Array requires BigInt values
84
+ const bigIntData = this._data;
85
+ for (let i = 0; i < data.length; i++) {
86
+ bigIntData[i] = BigInt(Math.round(data[i] ?? 0));
87
+ }
88
+ }
89
+ else {
90
+ for (let i = 0; i < data.length; i++) {
91
+ this._data[i] = data[i] ?? 0;
92
+ }
93
+ }
94
+ }
95
+ else {
96
+ this._data = data;
97
+ }
98
+ }
99
+ get data() {
100
+ this.checkDisposed();
101
+ return this._data;
102
+ }
103
+ get isDisposed() {
104
+ return this._isDisposed;
105
+ }
106
+ /**
107
+ * Check if tensor has been disposed
108
+ */
109
+ checkDisposed() {
110
+ if (this._isDisposed) {
111
+ throw new EdgeFlowError('Cannot access disposed tensor', ErrorCodes.TENSOR_DISPOSED, { tensorId: this.id });
112
+ }
113
+ }
114
+ /**
115
+ * Convert to Float32Array
116
+ */
117
+ toFloat32Array() {
118
+ this.checkDisposed();
119
+ if (this._data instanceof Float32Array) {
120
+ return this._data;
121
+ }
122
+ const result = new Float32Array(this.size);
123
+ for (let i = 0; i < this.size; i++) {
124
+ result[i] = Number(this._data[i] ?? 0);
125
+ }
126
+ return result;
127
+ }
128
+ /**
129
+ * Convert to regular array
130
+ */
131
+ toArray() {
132
+ this.checkDisposed();
133
+ if (this.dtype === 'int64') {
134
+ // BigInt64Array needs special handling
135
+ const bigIntData = this._data;
136
+ const result = [];
137
+ for (let i = 0; i < bigIntData.length; i++) {
138
+ result.push(Number(bigIntData[i]));
139
+ }
140
+ return result;
141
+ }
142
+ return Array.from(this._data);
143
+ }
144
+ /**
145
+ * Clone the tensor
146
+ */
147
+ clone() {
148
+ this.checkDisposed();
149
+ const TypedArrayCtor = this._data.constructor;
150
+ const clonedData = new TypedArrayCtor(this._data);
151
+ return new EdgeFlowTensor(clonedData, this.shape, this.dtype);
152
+ }
153
+ /**
154
+ * Dispose the tensor and free memory
155
+ */
156
+ dispose() {
157
+ if (!this._isDisposed) {
158
+ this._isDisposed = true;
159
+ // Help garbage collection - use Object.assign to avoid type issues
160
+ Object.assign(this, { _data: null });
161
+ }
162
+ }
163
+ /**
164
+ * Get value at specific indices
165
+ */
166
+ get(...indices) {
167
+ this.checkDisposed();
168
+ if (indices.length !== this.shape.length) {
169
+ throw new EdgeFlowError(`Expected ${this.shape.length} indices, got ${indices.length}`, ErrorCodes.INVALID_ARGUMENT, { expectedIndices: this.shape.length, gotIndices: indices.length });
170
+ }
171
+ let flatIndex = 0;
172
+ let stride = 1;
173
+ for (let i = this.shape.length - 1; i >= 0; i--) {
174
+ const idx = indices[i] ?? 0;
175
+ const dim = this.shape[i] ?? 1;
176
+ if (idx < 0 || idx >= dim) {
177
+ throw new EdgeFlowError(`Index ${idx} out of bounds for dimension ${i} with size ${dim}`, ErrorCodes.INVALID_ARGUMENT, { index: idx, dimension: i, size: dim });
178
+ }
179
+ flatIndex += idx * stride;
180
+ stride *= dim;
181
+ }
182
+ return Number(this._data[flatIndex] ?? 0);
183
+ }
184
+ /**
185
+ * Set value at specific indices
186
+ */
187
+ set(value, ...indices) {
188
+ this.checkDisposed();
189
+ if (indices.length !== this.shape.length) {
190
+ throw new EdgeFlowError(`Expected ${this.shape.length} indices, got ${indices.length}`, ErrorCodes.INVALID_ARGUMENT, { expectedIndices: this.shape.length, gotIndices: indices.length });
191
+ }
192
+ let flatIndex = 0;
193
+ let stride = 1;
194
+ for (let i = this.shape.length - 1; i >= 0; i--) {
195
+ const idx = indices[i] ?? 0;
196
+ const dim = this.shape[i] ?? 1;
197
+ if (idx < 0 || idx >= dim) {
198
+ throw new EdgeFlowError(`Index ${idx} out of bounds for dimension ${i} with size ${dim}`, ErrorCodes.INVALID_ARGUMENT, { index: idx, dimension: i, size: dim });
199
+ }
200
+ flatIndex += idx * stride;
201
+ stride *= dim;
202
+ }
203
+ this._data[flatIndex] = value;
204
+ }
205
+ /**
206
+ * Reshape the tensor (returns new tensor)
207
+ */
208
+ reshape(newShape) {
209
+ this.checkDisposed();
210
+ const newSize = calculateSize(newShape);
211
+ if (newSize !== this.size) {
212
+ throw new EdgeFlowError(`Cannot reshape tensor of size ${this.size} to shape ${JSON.stringify(newShape)} (size ${newSize})`, ErrorCodes.TENSOR_SHAPE_MISMATCH, { currentSize: this.size, newSize, newShape });
213
+ }
214
+ const TypedArrayCtor = this._data.constructor;
215
+ const clonedData = new TypedArrayCtor(this._data);
216
+ return new EdgeFlowTensor(clonedData, newShape, this.dtype);
217
+ }
218
+ /**
219
+ * Transpose the tensor (2D only for now)
220
+ */
221
+ transpose() {
222
+ this.checkDisposed();
223
+ if (this.shape.length !== 2) {
224
+ throw new EdgeFlowError('Transpose is currently only supported for 2D tensors', ErrorCodes.NOT_IMPLEMENTED, { shape: this.shape });
225
+ }
226
+ const [rows, cols] = this.shape;
227
+ const result = new Float32Array(this.size);
228
+ for (let i = 0; i < rows; i++) {
229
+ for (let j = 0; j < cols; j++) {
230
+ result[j * rows + i] = Number(this._data[i * cols + j] ?? 0);
231
+ }
232
+ }
233
+ return new EdgeFlowTensor(result, [cols, rows], this.dtype);
234
+ }
235
+ /**
236
+ * Create string representation
237
+ */
238
+ toString() {
239
+ return `Tensor(shape=[${this.shape.join(', ')}], dtype=${this.dtype})`;
240
+ }
241
+ }
242
+ // ============================================================================
243
+ // Tensor Factory Functions
244
+ // ============================================================================
245
+ /**
246
+ * Create a tensor from data
247
+ */
248
+ export function tensor(data, shape, dtype = 'float32') {
249
+ // Handle nested arrays
250
+ if (Array.isArray(data) && data.length > 0 && Array.isArray(data[0])) {
251
+ const rows = data.length;
252
+ const cols = data[0].length;
253
+ const flatData = [];
254
+ for (const row of data) {
255
+ if (row.length !== cols) {
256
+ throw new EdgeFlowError('Nested arrays must have consistent dimensions', ErrorCodes.INVALID_ARGUMENT);
257
+ }
258
+ flatData.push(...row);
259
+ }
260
+ return new EdgeFlowTensor(flatData, shape ?? [rows, cols], dtype);
261
+ }
262
+ // Infer shape if not provided
263
+ const inferredShape = shape ?? [data.length];
264
+ return new EdgeFlowTensor(data, inferredShape, dtype);
265
+ }
266
+ /**
267
+ * Create a tensor filled with zeros
268
+ */
269
+ export function zeros(shape, dtype = 'float32') {
270
+ const size = calculateSize(shape);
271
+ const TypedArrayCtor = getTypedArrayConstructor(dtype);
272
+ const data = new TypedArrayCtor(size);
273
+ return new EdgeFlowTensor(data, shape, dtype);
274
+ }
275
+ /**
276
+ * Create a tensor filled with ones
277
+ */
278
+ export function ones(shape, dtype = 'float32') {
279
+ const size = calculateSize(shape);
280
+ const TypedArrayCtor = getTypedArrayConstructor(dtype);
281
+ const data = new TypedArrayCtor(size);
282
+ data.fill(1);
283
+ return new EdgeFlowTensor(data, shape, dtype);
284
+ }
285
+ /**
286
+ * Create a tensor filled with a specific value
287
+ */
288
+ export function full(shape, value, dtype = 'float32') {
289
+ const size = calculateSize(shape);
290
+ const TypedArrayCtor = getTypedArrayConstructor(dtype);
291
+ const data = new TypedArrayCtor(size);
292
+ data.fill(value);
293
+ return new EdgeFlowTensor(data, shape, dtype);
294
+ }
295
+ /**
296
+ * Create a tensor with random values between 0 and 1
297
+ */
298
+ export function random(shape, dtype = 'float32') {
299
+ const size = calculateSize(shape);
300
+ const data = new Float32Array(size);
301
+ for (let i = 0; i < size; i++) {
302
+ data[i] = Math.random();
303
+ }
304
+ return new EdgeFlowTensor(data, shape, dtype);
305
+ }
306
+ /**
307
+ * Create a tensor with random values from normal distribution
308
+ */
309
+ export function randn(shape, dtype = 'float32') {
310
+ const size = calculateSize(shape);
311
+ const data = new Float32Array(size);
312
+ // Box-Muller transform for normal distribution
313
+ for (let i = 0; i < size; i += 2) {
314
+ const u1 = Math.random();
315
+ const u2 = Math.random();
316
+ const r = Math.sqrt(-2 * Math.log(u1));
317
+ const theta = 2 * Math.PI * u2;
318
+ data[i] = r * Math.cos(theta);
319
+ if (i + 1 < size) {
320
+ data[i + 1] = r * Math.sin(theta);
321
+ }
322
+ }
323
+ return new EdgeFlowTensor(data, shape, dtype);
324
+ }
325
+ /**
326
+ * Create a 1D tensor with evenly spaced values
327
+ */
328
+ export function arange(start, stop, step = 1, dtype = 'float32') {
329
+ if (stop === undefined) {
330
+ stop = start;
331
+ start = 0;
332
+ }
333
+ const size = Math.ceil((stop - start) / step);
334
+ const data = new Float32Array(size);
335
+ for (let i = 0; i < size; i++) {
336
+ data[i] = start + i * step;
337
+ }
338
+ return new EdgeFlowTensor(data, [size], dtype);
339
+ }
340
+ /**
341
+ * Create a 1D tensor with evenly spaced values (specify number of points)
342
+ */
343
+ export function linspace(start, stop, num = 50, dtype = 'float32') {
344
+ const data = new Float32Array(num);
345
+ const step = (stop - start) / (num - 1);
346
+ for (let i = 0; i < num; i++) {
347
+ data[i] = start + i * step;
348
+ }
349
+ return new EdgeFlowTensor(data, [num], dtype);
350
+ }
351
+ /**
352
+ * Create an identity matrix
353
+ */
354
+ export function eye(n, dtype = 'float32') {
355
+ const data = new Float32Array(n * n);
356
+ for (let i = 0; i < n; i++) {
357
+ data[i * n + i] = 1;
358
+ }
359
+ return new EdgeFlowTensor(data, [n, n], dtype);
360
+ }
361
+ // ============================================================================
362
+ // Tensor Operations
363
+ // ============================================================================
364
+ /**
365
+ * Element-wise addition
366
+ */
367
+ export function add(a, b) {
368
+ if (typeof b === 'number') {
369
+ const result = new Float32Array(a.size);
370
+ const aData = a.toFloat32Array();
371
+ for (let i = 0; i < a.size; i++) {
372
+ result[i] = (aData[i] ?? 0) + b;
373
+ }
374
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
375
+ }
376
+ if (a.size !== b.size) {
377
+ throw new EdgeFlowError('Tensor sizes must match for element-wise operations', ErrorCodes.TENSOR_SHAPE_MISMATCH, { aShape: a.shape, bShape: b.shape });
378
+ }
379
+ const result = new Float32Array(a.size);
380
+ const aData = a.toFloat32Array();
381
+ const bData = b.toFloat32Array();
382
+ for (let i = 0; i < a.size; i++) {
383
+ result[i] = (aData[i] ?? 0) + (bData[i] ?? 0);
384
+ }
385
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
386
+ }
387
+ /**
388
+ * Element-wise subtraction
389
+ */
390
+ export function sub(a, b) {
391
+ if (typeof b === 'number') {
392
+ const result = new Float32Array(a.size);
393
+ const aData = a.toFloat32Array();
394
+ for (let i = 0; i < a.size; i++) {
395
+ result[i] = (aData[i] ?? 0) - b;
396
+ }
397
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
398
+ }
399
+ if (a.size !== b.size) {
400
+ throw new EdgeFlowError('Tensor sizes must match for element-wise operations', ErrorCodes.TENSOR_SHAPE_MISMATCH, { aShape: a.shape, bShape: b.shape });
401
+ }
402
+ const result = new Float32Array(a.size);
403
+ const aData = a.toFloat32Array();
404
+ const bData = b.toFloat32Array();
405
+ for (let i = 0; i < a.size; i++) {
406
+ result[i] = (aData[i] ?? 0) - (bData[i] ?? 0);
407
+ }
408
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
409
+ }
410
+ /**
411
+ * Element-wise multiplication
412
+ */
413
+ export function mul(a, b) {
414
+ if (typeof b === 'number') {
415
+ const result = new Float32Array(a.size);
416
+ const aData = a.toFloat32Array();
417
+ for (let i = 0; i < a.size; i++) {
418
+ result[i] = (aData[i] ?? 0) * b;
419
+ }
420
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
421
+ }
422
+ if (a.size !== b.size) {
423
+ throw new EdgeFlowError('Tensor sizes must match for element-wise operations', ErrorCodes.TENSOR_SHAPE_MISMATCH, { aShape: a.shape, bShape: b.shape });
424
+ }
425
+ const result = new Float32Array(a.size);
426
+ const aData = a.toFloat32Array();
427
+ const bData = b.toFloat32Array();
428
+ for (let i = 0; i < a.size; i++) {
429
+ result[i] = (aData[i] ?? 0) * (bData[i] ?? 0);
430
+ }
431
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
432
+ }
433
+ /**
434
+ * Element-wise division
435
+ */
436
+ export function div(a, b) {
437
+ if (typeof b === 'number') {
438
+ const result = new Float32Array(a.size);
439
+ const aData = a.toFloat32Array();
440
+ for (let i = 0; i < a.size; i++) {
441
+ result[i] = (aData[i] ?? 0) / b;
442
+ }
443
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
444
+ }
445
+ if (a.size !== b.size) {
446
+ throw new EdgeFlowError('Tensor sizes must match for element-wise operations', ErrorCodes.TENSOR_SHAPE_MISMATCH, { aShape: a.shape, bShape: b.shape });
447
+ }
448
+ const result = new Float32Array(a.size);
449
+ const aData = a.toFloat32Array();
450
+ const bData = b.toFloat32Array();
451
+ for (let i = 0; i < a.size; i++) {
452
+ result[i] = (aData[i] ?? 0) / (bData[i] ?? 0);
453
+ }
454
+ return new EdgeFlowTensor(result, a.shape, a.dtype);
455
+ }
456
+ /**
457
+ * Matrix multiplication (2D tensors)
458
+ */
459
+ export function matmul(a, b) {
460
+ if (a.shape.length !== 2 || b.shape.length !== 2) {
461
+ throw new EdgeFlowError('matmul requires 2D tensors', ErrorCodes.INVALID_ARGUMENT, { aShape: a.shape, bShape: b.shape });
462
+ }
463
+ const [m, k1] = a.shape;
464
+ const [k2, n] = b.shape;
465
+ if (k1 !== k2) {
466
+ throw new EdgeFlowError(`Matrix dimensions incompatible for multiplication: (${m}x${k1}) @ (${k2}x${n})`, ErrorCodes.TENSOR_SHAPE_MISMATCH, { aShape: a.shape, bShape: b.shape });
467
+ }
468
+ const result = new Float32Array(m * n);
469
+ const aData = a.toFloat32Array();
470
+ const bData = b.toFloat32Array();
471
+ for (let i = 0; i < m; i++) {
472
+ for (let j = 0; j < n; j++) {
473
+ let sum = 0;
474
+ for (let k = 0; k < k1; k++) {
475
+ sum += (aData[i * k1 + k] ?? 0) * (bData[k * n + j] ?? 0);
476
+ }
477
+ result[i * n + j] = sum;
478
+ }
479
+ }
480
+ return new EdgeFlowTensor(result, [m, n], a.dtype);
481
+ }
482
+ /**
483
+ * Softmax activation
484
+ */
485
+ export function softmax(t, axis = -1) {
486
+ const data = t.toFloat32Array();
487
+ const result = new Float32Array(t.size);
488
+ // Handle negative axis
489
+ const actualAxis = axis < 0 ? t.shape.length + axis : axis;
490
+ if (actualAxis < 0 || actualAxis >= t.shape.length) {
491
+ throw new EdgeFlowError(`Invalid axis ${axis} for tensor with ${t.shape.length} dimensions`, ErrorCodes.INVALID_ARGUMENT, { axis, shape: t.shape });
492
+ }
493
+ // For 1D tensors
494
+ if (t.shape.length === 1) {
495
+ let max = -Infinity;
496
+ for (let i = 0; i < t.size; i++) {
497
+ if ((data[i] ?? 0) > max)
498
+ max = data[i] ?? 0;
499
+ }
500
+ let sum = 0;
501
+ for (let i = 0; i < t.size; i++) {
502
+ result[i] = Math.exp((data[i] ?? 0) - max);
503
+ sum += result[i] ?? 0;
504
+ }
505
+ for (let i = 0; i < t.size; i++) {
506
+ result[i] = (result[i] ?? 0) / sum;
507
+ }
508
+ return new EdgeFlowTensor(result, t.shape, t.dtype);
509
+ }
510
+ // For 2D tensors along last axis
511
+ if (t.shape.length === 2 && actualAxis === 1) {
512
+ const [rows, cols] = t.shape;
513
+ for (let i = 0; i < rows; i++) {
514
+ let max = -Infinity;
515
+ for (let j = 0; j < cols; j++) {
516
+ if ((data[i * cols + j] ?? 0) > max)
517
+ max = data[i * cols + j] ?? 0;
518
+ }
519
+ let sum = 0;
520
+ for (let j = 0; j < cols; j++) {
521
+ result[i * cols + j] = Math.exp((data[i * cols + j] ?? 0) - max);
522
+ sum += result[i * cols + j] ?? 0;
523
+ }
524
+ for (let j = 0; j < cols; j++) {
525
+ result[i * cols + j] = (result[i * cols + j] ?? 0) / sum;
526
+ }
527
+ }
528
+ return new EdgeFlowTensor(result, t.shape, t.dtype);
529
+ }
530
+ throw new EdgeFlowError('Softmax currently only supports 1D tensors or 2D tensors along the last axis', ErrorCodes.NOT_IMPLEMENTED, { shape: t.shape, axis });
531
+ }
532
+ /**
533
+ * ReLU activation
534
+ */
535
+ export function relu(t) {
536
+ const data = t.toFloat32Array();
537
+ const result = new Float32Array(t.size);
538
+ for (let i = 0; i < t.size; i++) {
539
+ result[i] = Math.max(0, data[i] ?? 0);
540
+ }
541
+ return new EdgeFlowTensor(result, t.shape, t.dtype);
542
+ }
543
+ /**
544
+ * Sigmoid activation
545
+ */
546
+ export function sigmoid(t) {
547
+ const data = t.toFloat32Array();
548
+ const result = new Float32Array(t.size);
549
+ for (let i = 0; i < t.size; i++) {
550
+ result[i] = 1 / (1 + Math.exp(-(data[i] ?? 0)));
551
+ }
552
+ return new EdgeFlowTensor(result, t.shape, t.dtype);
553
+ }
554
+ /**
555
+ * Tanh activation
556
+ */
557
+ export function tanh(t) {
558
+ const data = t.toFloat32Array();
559
+ const result = new Float32Array(t.size);
560
+ for (let i = 0; i < t.size; i++) {
561
+ result[i] = Math.tanh(data[i] ?? 0);
562
+ }
563
+ return new EdgeFlowTensor(result, t.shape, t.dtype);
564
+ }
565
+ /**
566
+ * Sum all elements or along an axis
567
+ */
568
+ export function sum(t, axis) {
569
+ const data = t.toFloat32Array();
570
+ if (axis === undefined) {
571
+ let total = 0;
572
+ for (let i = 0; i < t.size; i++) {
573
+ total += data[i] ?? 0;
574
+ }
575
+ return total;
576
+ }
577
+ // Handle negative axis
578
+ const actualAxis = axis < 0 ? t.shape.length + axis : axis;
579
+ if (actualAxis < 0 || actualAxis >= t.shape.length) {
580
+ throw new EdgeFlowError(`Invalid axis ${axis} for tensor with ${t.shape.length} dimensions`, ErrorCodes.INVALID_ARGUMENT, { axis, shape: t.shape });
581
+ }
582
+ // Calculate new shape
583
+ const newShape = [...t.shape];
584
+ newShape.splice(actualAxis, 1);
585
+ if (newShape.length === 0) {
586
+ let total = 0;
587
+ for (let i = 0; i < t.size; i++) {
588
+ total += data[i] ?? 0;
589
+ }
590
+ return total;
591
+ }
592
+ // For 2D sum along axis
593
+ if (t.shape.length === 2) {
594
+ const [rows, cols] = t.shape;
595
+ if (actualAxis === 0) {
596
+ const result = new Float32Array(cols);
597
+ for (let j = 0; j < cols; j++) {
598
+ for (let i = 0; i < rows; i++) {
599
+ result[j] = (result[j] ?? 0) + (data[i * cols + j] ?? 0);
600
+ }
601
+ }
602
+ return new EdgeFlowTensor(result, [cols], t.dtype);
603
+ }
604
+ else {
605
+ const result = new Float32Array(rows);
606
+ for (let i = 0; i < rows; i++) {
607
+ for (let j = 0; j < cols; j++) {
608
+ result[i] = (result[i] ?? 0) + (data[i * cols + j] ?? 0);
609
+ }
610
+ }
611
+ return new EdgeFlowTensor(result, [rows], t.dtype);
612
+ }
613
+ }
614
+ throw new EdgeFlowError('Sum along axis currently only supports up to 2D tensors', ErrorCodes.NOT_IMPLEMENTED, { shape: t.shape, axis });
615
+ }
616
+ /**
617
+ * Mean of all elements or along an axis
618
+ */
619
+ export function mean(t, axis) {
620
+ if (axis === undefined) {
621
+ return sum(t) / t.size;
622
+ }
623
+ const result = sum(t, axis);
624
+ if (typeof result === 'number') {
625
+ return result / (t.shape[axis] ?? 1);
626
+ }
627
+ const axisSize = t.shape[axis] ?? 1;
628
+ return div(result, axisSize);
629
+ }
630
+ /**
631
+ * Argmax - return index of maximum value
632
+ */
633
+ export function argmax(t, axis) {
634
+ const data = t.toFloat32Array();
635
+ if (axis === undefined) {
636
+ let maxIdx = 0;
637
+ let maxVal = data[0] ?? -Infinity;
638
+ for (let i = 1; i < t.size; i++) {
639
+ if ((data[i] ?? -Infinity) > maxVal) {
640
+ maxVal = data[i] ?? -Infinity;
641
+ maxIdx = i;
642
+ }
643
+ }
644
+ return maxIdx;
645
+ }
646
+ // Handle negative axis
647
+ const actualAxis = axis < 0 ? t.shape.length + axis : axis;
648
+ // For 2D along last axis
649
+ if (t.shape.length === 2 && actualAxis === 1) {
650
+ const [rows, cols] = t.shape;
651
+ const result = new Float32Array(rows);
652
+ for (let i = 0; i < rows; i++) {
653
+ let maxIdx = 0;
654
+ let maxVal = data[i * cols] ?? -Infinity;
655
+ for (let j = 1; j < cols; j++) {
656
+ if ((data[i * cols + j] ?? -Infinity) > maxVal) {
657
+ maxVal = data[i * cols + j] ?? -Infinity;
658
+ maxIdx = j;
659
+ }
660
+ }
661
+ result[i] = maxIdx;
662
+ }
663
+ return new EdgeFlowTensor(result, [rows], 'int32');
664
+ }
665
+ throw new EdgeFlowError('Argmax along axis currently only supports 2D tensors along the last axis', ErrorCodes.NOT_IMPLEMENTED, { shape: t.shape, axis });
666
+ }
667
+ /**
668
+ * Concatenate tensors along an axis
669
+ */
670
+ export function concat(tensors, axis = 0) {
671
+ if (tensors.length === 0) {
672
+ throw new EdgeFlowError('Cannot concatenate empty array of tensors', ErrorCodes.INVALID_ARGUMENT);
673
+ }
674
+ if (tensors.length === 1) {
675
+ return tensors[0]?.clone() ?? zeros([0]);
676
+ }
677
+ const first = tensors[0];
678
+ if (!first) {
679
+ throw new EdgeFlowError('First tensor is undefined', ErrorCodes.INVALID_ARGUMENT);
680
+ }
681
+ // Handle negative axis
682
+ const actualAxis = axis < 0 ? first.shape.length + axis : axis;
683
+ // Validate shapes
684
+ for (let i = 1; i < tensors.length; i++) {
685
+ const t = tensors[i];
686
+ if (!t)
687
+ continue;
688
+ if (t.shape.length !== first.shape.length) {
689
+ throw new EdgeFlowError('All tensors must have the same number of dimensions', ErrorCodes.TENSOR_SHAPE_MISMATCH);
690
+ }
691
+ for (let j = 0; j < first.shape.length; j++) {
692
+ if (j !== actualAxis && first.shape[j] !== t.shape[j]) {
693
+ throw new EdgeFlowError(`Shape mismatch at dimension ${j}`, ErrorCodes.TENSOR_SHAPE_MISMATCH);
694
+ }
695
+ }
696
+ }
697
+ // Calculate new shape
698
+ const newShape = [...first.shape];
699
+ let totalAxisSize = 0;
700
+ for (const t of tensors) {
701
+ if (t)
702
+ totalAxisSize += t.shape[actualAxis] ?? 0;
703
+ }
704
+ newShape[actualAxis] = totalAxisSize;
705
+ // For 1D concatenation
706
+ if (first.shape.length === 1) {
707
+ const result = new Float32Array(totalAxisSize);
708
+ let offset = 0;
709
+ for (const t of tensors) {
710
+ if (!t)
711
+ continue;
712
+ result.set(t.toFloat32Array(), offset);
713
+ offset += t.size;
714
+ }
715
+ return new EdgeFlowTensor(result, newShape, first.dtype);
716
+ }
717
+ throw new EdgeFlowError('Concatenation currently only supports 1D tensors', ErrorCodes.NOT_IMPLEMENTED);
718
+ }
719
+ //# sourceMappingURL=tensor.js.map