@thi.ng/tensors 0.2.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2025-05-02T08:39:24Z
3
+ - **Last updated**: 2025-05-08T15:13:02Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -11,6 +11,25 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
11
11
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
12
12
  and/or version bumps of transitive dependencies.
13
13
 
14
+ ## [0.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/tensors@0.3.0) (2025-05-08)
15
+
16
+ #### 🚀 Features
17
+
18
+ - add swap(), update defOpRT/TT() fns ([5d2dd2a](https://github.com/thi-ng/umbrella/commit/5d2dd2a))
19
+ - add range() tensor factory ([a8a6365](https://github.com/thi-ng/umbrella/commit/a8a6365))
20
+ - add ITensor.position() & impls ([595764d](https://github.com/thi-ng/umbrella/commit/595764d))
21
+ - add filteredIndices() & presets ([edd8983](https://github.com/thi-ng/umbrella/commit/edd8983))
22
+ - add nonZeroIndices()
23
+ - add negativeIndices(), positiveIndices()
24
+
25
+ #### 🩹 Bug fixes
26
+
27
+ - update ITensor.broadcast() return type ([f7b2e7a](https://github.com/thi-ng/umbrella/commit/f7b2e7a))
28
+
29
+ #### ♻️ Refactoring
30
+
31
+ - update range() impl (w/o dependencies) ([ce89d71](https://github.com/thi-ng/umbrella/commit/ce89d71))
32
+
14
33
  ## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/tensors@0.2.0) (2025-05-02)
15
34
 
16
35
  #### 🚀 Features
package/README.md CHANGED
@@ -180,7 +180,7 @@ For Node.js REPL:
180
180
  const ten = await import("@thi.ng/tensors");
181
181
  ```
182
182
 
183
- Package sizes (brotli'd, pre-treeshake): ESM: 7.72 KB
183
+ Package sizes (brotli'd, pre-treeshake): ESM: 8.06 KB
184
184
 
185
185
  ## Dependencies
186
186
 
package/api.d.ts CHANGED
@@ -80,9 +80,28 @@ export interface ITensor<T = number> extends ICopy<ITensor<T>>, IEquiv, IEqualsD
80
80
  *
81
81
  * @internal
82
82
  */
83
- broadcast(shape: number[], stride: number[]): this;
83
+ broadcast<S extends Shape>(shape: S, stride: S): ShapeTensor<S, T>;
84
84
  empty(storage?: ITensorStorage<T>): this;
85
+ /**
86
+ * Computes linear array index from given grid position. Reverse-op of
87
+ * {@link ITensor.position}.
88
+ *
89
+ * @param pos
90
+ */
85
91
  index(pos: NumericArray): number;
92
+ /**
93
+ * Computes nD grid position for given linear array index. Reverse-op of
94
+ * {@link ITensor.index}.
95
+ *
96
+ * @remarks
97
+ * **CAUTION:** Currently only supports tensors with positive strides,
98
+ * otherwise will yield incorrect results! Tensors with negative strides
99
+ * (aka flipped axes in reverse order) need to be first packed via
100
+ * {@link ITensor.pack}.
101
+ *
102
+ * @param index
103
+ */
104
+ position(index: number): number[];
86
105
  get(pos: NumericArray): T;
87
106
  set(pos: NumericArray, value: T): this;
88
107
  lo(pos: NumericArray): this;
package/broadcast.d.ts CHANGED
@@ -18,7 +18,7 @@ import type { ITensor, Shape } from "./api.js";
18
18
  */
19
19
  export declare const broadcast: <T = number>(a: ITensor<T>, b: ITensor<T>) => {
20
20
  shape: Shape;
21
- a: ITensor<T>;
22
- b: ITensor<T>;
21
+ a: ITensor<T> | import("./tensor.js").Tensor4<T> | import("./tensor.js").Tensor3<T> | import("./tensor.js").Tensor2<T> | import("./tensor.js").Tensor1<T>;
22
+ b: ITensor<T> | import("./tensor.js").Tensor4<T> | import("./tensor.js").Tensor3<T> | import("./tensor.js").Tensor2<T> | import("./tensor.js").Tensor1<T>;
23
23
  };
24
24
  //# sourceMappingURL=broadcast.d.ts.map
package/defoprt.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Fn0, Fn2 } from "@thi.ng/api";
2
- import type { TensorOpRT } from "./api.js";
1
+ import type { Fn0 } from "@thi.ng/api";
2
+ import type { TensorData, TensorOpRT } from "./api.js";
3
3
  /**
4
4
  * Higher order tensor reduction op factory. Takes given reduction `rfn` and
5
5
  * `init` function to produce an initial result. Returns a {@link TensorOpRT}
@@ -8,5 +8,5 @@ import type { TensorOpRT } from "./api.js";
8
8
  * @param rfn
9
9
  * @param init
10
10
  */
11
- export declare const defOpRT: <A = number, B = A>(rfn: Fn2<B, A, B>, init: Fn0<B>) => import("./api.js").MultiTensorOpImpl<TensorOpRT<A, B>>;
11
+ export declare const defOpRT: <A = number, B = A>(rfn: (acc: B, data: TensorData<A>, i: number) => B, init: Fn0<B>) => import("./api.js").MultiTensorOpImpl<TensorOpRT<A, B>>;
12
12
  //# sourceMappingURL=defoprt.d.ts.map
package/defoprt.js CHANGED
@@ -9,7 +9,7 @@ const defOpRT = (rfn, init) => {
9
9
  } = a;
10
10
  let res = init();
11
11
  for (let x = 0; x < sx; x++) {
12
- res = rfn(res, data[offset + x * tx]);
12
+ res = rfn(res, data, offset + x * tx);
13
13
  }
14
14
  return res;
15
15
  };
@@ -25,7 +25,7 @@ const defOpRT = (rfn, init) => {
25
25
  for (let x = 0; x < sx; x++) {
26
26
  ox = offset + x * tx;
27
27
  for (let y = 0; y < sy; y++) {
28
- res = rfn(res, data[ox + y * ty]);
28
+ res = rfn(res, data, ox + y * ty);
29
29
  }
30
30
  }
31
31
  return res;
@@ -44,7 +44,7 @@ const defOpRT = (rfn, init) => {
44
44
  for (let y = 0; y < sy; y++) {
45
45
  oy = ox + y * ty;
46
46
  for (let z = 0; z < sz; z++) {
47
- res = rfn(res, data[oy + z * tz]);
47
+ res = rfn(res, data, oy + z * tz);
48
48
  }
49
49
  }
50
50
  }
@@ -66,7 +66,7 @@ const defOpRT = (rfn, init) => {
66
66
  for (let z = 0; z < sz; z++) {
67
67
  oz = oy + z * tz;
68
68
  for (let w = 0; w < sw; w++) {
69
- res = rfn(res, data[oz + w * tw]);
69
+ res = rfn(res, data, oz + w * tw);
70
70
  }
71
71
  }
72
72
  }
package/defoprtt.d.ts CHANGED
@@ -1,13 +1,14 @@
1
- import type { Fn0, Fn3 } from "@thi.ng/api";
2
- import type { TensorOpRTT } from "./api.js";
1
+ import type { Fn0 } from "@thi.ng/api";
2
+ import type { TensorData, TensorOpRTT } from "./api.js";
3
3
  /**
4
4
  * Higher order tensor reduction op factory. Takes given reduction `rfn` and
5
5
  * `init` function to produce an initial result. Returns a {@link TensorOpRTT}
6
- * applying the given function componentwise with broadcasting rules (see
7
- * {@link broadcast} for details).
6
+ * applying the given function componentwise, by default with broadcasting rules
7
+ * (see {@link broadcast} for details).
8
8
  *
9
9
  * @param rfn
10
10
  * @param init
11
+ * @param useBroadcast
11
12
  */
12
- export declare const defOpRTT: <A = number, B = A>(rfn: Fn3<B, A, A, B>, init: Fn0<B>) => TensorOpRTT<A, B>;
13
+ export declare const defOpRTT: <A = number, B = A>(rfn: (acc: B, adata: TensorData<A>, bdata: TensorData<A>, ia: number, ib: number) => B, init: Fn0<B>, useBroadcast?: boolean) => TensorOpRTT<A, B>;
13
14
  //# sourceMappingURL=defoprtt.d.ts.map
package/defoprtt.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { broadcast } from "./broadcast.js";
2
- const defOpRTT = (rfn, init) => {
2
+ const defOpRTT = (rfn, init, useBroadcast = true) => {
3
3
  const f1 = (a, b) => {
4
4
  const {
5
5
  data: adata,
@@ -14,7 +14,7 @@ const defOpRTT = (rfn, init) => {
14
14
  } = b;
15
15
  let res = init();
16
16
  for (let x = 0; x < sx; x++) {
17
- res = rfn(res, adata[oa + x * txa], bdata[ob + x * txb]);
17
+ res = rfn(res, adata, bdata, oa + x * txa, ob + x * txb);
18
18
  }
19
19
  return res;
20
20
  };
@@ -36,7 +36,7 @@ const defOpRTT = (rfn, init) => {
36
36
  oax = oa + x * txa;
37
37
  obx = ob + x * txb;
38
38
  for (let y = 0; y < sy; y++) {
39
- res = rfn(res, adata[oax + y * tya], bdata[obx + y * tyb]);
39
+ res = rfn(res, adata, bdata, oax + y * tya, obx + y * tyb);
40
40
  }
41
41
  }
42
42
  return res;
@@ -62,7 +62,7 @@ const defOpRTT = (rfn, init) => {
62
62
  oay = oax + y * tya;
63
63
  oby = obx + y * tyb;
64
64
  for (let z = 0; z < sz; z++) {
65
- res = rfn(res, adata[oay + z * tza], bdata[oby + z * tzb]);
65
+ res = rfn(res, adata, bdata, oay + z * tza, oby + z * tzb);
66
66
  }
67
67
  }
68
68
  }
@@ -94,8 +94,10 @@ const defOpRTT = (rfn, init) => {
94
94
  for (let w = 0; w < sw; w++) {
95
95
  res = rfn(
96
96
  res,
97
- adata[oaz + w * twa],
98
- bdata[obz + w * twb]
97
+ adata,
98
+ bdata,
99
+ oaz + w * twa,
100
+ obz + w * twb
99
101
  );
100
102
  }
101
103
  }
@@ -104,10 +106,10 @@ const defOpRTT = (rfn, init) => {
104
106
  return res;
105
107
  };
106
108
  const impls = [, f1, f2, f3, f4];
107
- const wrapper = (a, b) => {
109
+ const wrapper = useBroadcast ? (a, b) => {
108
110
  const { shape, a: $a, b: $b } = broadcast(a, b);
109
111
  return impls[shape.length]($a, $b);
110
- };
112
+ } : (a, b) => impls[a.dim](a, b);
111
113
  return wrapper;
112
114
  };
113
115
  export {
package/dot.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defOpRTT } from "./defoprtt.js";
2
2
  const dot = defOpRTT(
3
- (acc, x, y) => acc + x * y,
3
+ (acc, adata, bdata, ia, ib) => acc + adata[ia] * bdata[ib],
4
4
  () => 0
5
5
  );
6
6
  export {
@@ -0,0 +1,34 @@
1
+ import type { Predicate } from "@thi.ng/api";
2
+ /**
3
+ * Higher order function. Takes a predicate function and returns a new function
4
+ * which accepts a tensor and then returns an array of tensor component indices
5
+ * for which the predicate passed.
6
+ *
7
+ * @remarks
8
+ * Also see {@link nonZeroIndices}.
9
+ *
10
+ * @param pred
11
+ */
12
+ export declare const filteredIndices: <T = number>(pred: Predicate<T>) => import("./api.js").MultiTensorOpImpl<import("./api.js").TensorOpRT<T, number[]>>;
13
+ /**
14
+ * Returns an array of indices where the given tensor has non-zero component
15
+ * values.
16
+ *
17
+ * @param a
18
+ */
19
+ export declare const nonZeroIndices: import("./api.js").MultiTensorOpImpl<import("./api.js").TensorOpRT<number, number[]>>;
20
+ /**
21
+ * Returns an array of indices where the given tensor has negative component
22
+ * values.
23
+ *
24
+ * @param a
25
+ */
26
+ export declare const negativeIndices: import("./api.js").MultiTensorOpImpl<import("./api.js").TensorOpRT<number, number[]>>;
27
+ /**
28
+ * Returns an array of indices where the given tensor has positive component
29
+ * values.
30
+ *
31
+ * @param a
32
+ */
33
+ export declare const positiveIndices: import("./api.js").MultiTensorOpImpl<import("./api.js").TensorOpRT<number, number[]>>;
34
+ //# sourceMappingURL=filtered-indices.d.ts.map
@@ -0,0 +1,17 @@
1
+ import { defOpRT } from "./defoprt.js";
2
+ const filteredIndices = (pred) => defOpRT(
3
+ (acc, data, i) => {
4
+ if (pred(data[i])) acc.push(i);
5
+ return acc;
6
+ },
7
+ () => []
8
+ );
9
+ const nonZeroIndices = filteredIndices((x) => x !== 0);
10
+ const negativeIndices = filteredIndices((x) => x < 0);
11
+ const positiveIndices = filteredIndices((x) => x > 0);
12
+ export {
13
+ filteredIndices,
14
+ negativeIndices,
15
+ nonZeroIndices,
16
+ positiveIndices
17
+ };
package/index.d.ts CHANGED
@@ -21,6 +21,7 @@ export * from "./dot.js";
21
21
  export * from "./errors.js";
22
22
  export * from "./exp.js";
23
23
  export * from "./exp2.js";
24
+ export * from "./filtered-indices.js";
24
25
  export * from "./format.js";
25
26
  export * from "./identity.js";
26
27
  export * from "./log.js";
@@ -40,6 +41,7 @@ export * from "./pow.js";
40
41
  export * from "./pown.js";
41
42
  export * from "./product.js";
42
43
  export * from "./rand-distrib.js";
44
+ export * from "./range.js";
43
45
  export * from "./relu.js";
44
46
  export * from "./relun.js";
45
47
  export * from "./select.js";
@@ -56,6 +58,7 @@ export * from "./sub.js";
56
58
  export * from "./subn.js";
57
59
  export * from "./sum.js";
58
60
  export * from "./svd.js";
61
+ export * from "./swap.js";
59
62
  export * from "./tan.js";
60
63
  export * from "./tanh.js";
61
64
  export * from "./tensor.js";
package/index.js CHANGED
@@ -21,6 +21,7 @@ export * from "./dot.js";
21
21
  export * from "./errors.js";
22
22
  export * from "./exp.js";
23
23
  export * from "./exp2.js";
24
+ export * from "./filtered-indices.js";
24
25
  export * from "./format.js";
25
26
  export * from "./identity.js";
26
27
  export * from "./log.js";
@@ -40,6 +41,7 @@ export * from "./pow.js";
40
41
  export * from "./pown.js";
41
42
  export * from "./product.js";
42
43
  export * from "./rand-distrib.js";
44
+ export * from "./range.js";
43
45
  export * from "./relu.js";
44
46
  export * from "./relun.js";
45
47
  export * from "./select.js";
@@ -56,6 +58,7 @@ export * from "./sub.js";
56
58
  export * from "./subn.js";
57
59
  export * from "./sum.js";
58
60
  export * from "./svd.js";
61
+ export * from "./swap.js";
59
62
  export * from "./tan.js";
60
63
  export * from "./tanh.js";
61
64
  export * from "./tensor.js";
package/magsq.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defOpRT } from "./defoprt.js";
2
2
  const magSq = defOpRT(
3
- (acc, x) => acc + x * x,
3
+ (acc, data, i) => acc + data[i] ** 2,
4
4
  () => 0
5
5
  );
6
6
  export {
package/normalize.d.ts CHANGED
@@ -7,5 +7,5 @@ import type { ITensor } from "./api.js";
7
7
  * @param a
8
8
  * @param n
9
9
  */
10
- export declare const normalize: (out: ITensor | null, a: ITensor, n?: number) => ITensor<number> | import("./tensor.js").Tensor1<any>;
10
+ export declare const normalize: (out: ITensor | null, a: ITensor, n?: number) => import("./tensor.js").Tensor1<any> | ITensor<number>;
11
11
  //# sourceMappingURL=normalize.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/tensors",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "1D/2D/3D/4D tensors with extensible polymorphic operations and customizable storage",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -170,6 +170,9 @@
170
170
  "./exp2": {
171
171
  "default": "./exp2.js"
172
172
  },
173
+ "./filtered-indices": {
174
+ "default": "./filtered-indices.js"
175
+ },
173
176
  "./format": {
174
177
  "default": "./format.js"
175
178
  },
@@ -227,6 +230,9 @@
227
230
  "./rand-distrib": {
228
231
  "default": "./rand-distrib.js"
229
232
  },
233
+ "./range": {
234
+ "default": "./range.js"
235
+ },
230
236
  "./relu": {
231
237
  "default": "./relu.js"
232
238
  },
@@ -275,6 +281,9 @@
275
281
  "./svd": {
276
282
  "default": "./svd.js"
277
283
  },
284
+ "./swap": {
285
+ "default": "./swap.js"
286
+ },
278
287
  "./tan": {
279
288
  "default": "./tan.js"
280
289
  },
@@ -292,5 +301,5 @@
292
301
  "status": "alpha",
293
302
  "year": 2018
294
303
  },
295
- "gitHead": "21e1e46f087a0b8e53b7eafa38ac38a83596ef8f\n"
304
+ "gitHead": "8e61726779260744ea70bfe38438e755d6b53844\n"
296
305
  }
package/product.js CHANGED
@@ -1,6 +1,8 @@
1
- import { $mul } from "@thi.ng/vectors/ops";
2
1
  import { defOpRT } from "./defoprt.js";
3
- const product = defOpRT($mul, () => 1);
2
+ const product = defOpRT(
3
+ (acc, data, i) => acc * data[i],
4
+ () => 1
5
+ );
4
6
  export {
5
7
  product
6
8
  };
package/range.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import type { TensorOpts } from "./api.js";
2
+ import { Tensor1 } from "./tensor.js";
3
+ /**
4
+ * Creates a 1D tensor of monotonically increasing values in the interval `[0,max)`.
5
+ *
6
+ * @param max
7
+ * @param opts
8
+ */
9
+ export declare function range(max: number, opts?: Pick<TensorOpts<number, any>, "storage">): Tensor1;
10
+ /**
11
+ * Creates a 1D tensor of monotonically increasing values in the interval
12
+ * `[min,max)`, using optional `step` and `opts`. If `from <= to`, the default
13
+ * step is 1, otherise -1.
14
+ *
15
+ * @param from
16
+ * @param to
17
+ * @param opts
18
+ */
19
+ export declare function range(from: number, to: number, step?: number, opts?: Pick<TensorOpts<number, any>, "storage">): Tensor1;
20
+ //# sourceMappingURL=range.d.ts.map
package/range.js ADDED
@@ -0,0 +1,28 @@
1
+ import { peek } from "@thi.ng/arrays/peek";
2
+ import { isPlainObject } from "@thi.ng/checks";
3
+ import { tensor, Tensor1 } from "./tensor.js";
4
+ function range(...args) {
5
+ const opts = isPlainObject(peek(args)) ? args.pop() : void 0;
6
+ let [from, to, step] = args;
7
+ if (to === void 0) {
8
+ to = from;
9
+ from = 0;
10
+ }
11
+ step = step === void 0 ? from < to ? 1 : -1 : step;
12
+ const data = [];
13
+ if (step > 0) {
14
+ while (from < to) {
15
+ data.push(from);
16
+ from += step;
17
+ }
18
+ } else if (step < 0) {
19
+ while (from > to) {
20
+ data.push(from);
21
+ from += step;
22
+ }
23
+ }
24
+ return tensor("num", [data.length], { ...opts, data });
25
+ }
26
+ export {
27
+ range
28
+ };
package/sum.js CHANGED
@@ -1,6 +1,8 @@
1
- import { $add } from "@thi.ng/vectors/ops";
2
1
  import { defOpRT } from "./defoprt.js";
3
- const sum = defOpRT($add, () => 0);
2
+ const sum = defOpRT(
3
+ (acc, data, i) => acc + data[i],
4
+ () => 0
5
+ );
4
6
  export {
5
7
  sum
6
8
  };
package/swap.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { ITensor } from "./api.js";
2
+ /**
3
+ * Swaps all data value of the two given tensors (which must have same shape).
4
+ * Returns `a`.
5
+ *
6
+ * @remarks
7
+ * Combined with {@link ITensor.pick}, this can be used to swap
8
+ * columns/rows/slices of a shared parent tensor.
9
+ *
10
+ * ```ts tangle:../export/swap.ts
11
+ * import { swap, range, print } from "@thi.ng/tensors";
12
+ *
13
+ * const a = range(12).reshape([3,4]);
14
+ * print(a);
15
+ *
16
+ * // swap data from 1st & 3rd column
17
+ * swap(a.pick([-1,0]), a.pick([-1,2]));
18
+ *
19
+ * print(a);
20
+ * ```
21
+ *
22
+ * @param a
23
+ * @param b
24
+ */
25
+ export declare const swap: <A, TA extends ITensor<A>>(a: TA, b: TA) => TA;
26
+ //# sourceMappingURL=swap.d.ts.map
package/swap.js ADDED
@@ -0,0 +1,15 @@
1
+ import { defOpRTT } from "./defoprtt.js";
2
+ const $swap = defOpRTT(
3
+ (_, adata, bdata, ia, ib) => {
4
+ const t = adata[ia];
5
+ adata[ia] = bdata[ib];
6
+ bdata[ib] = t;
7
+ },
8
+ () => {
9
+ },
10
+ false
11
+ );
12
+ const swap = (a, b) => $swap(a, b);
13
+ export {
14
+ swap
15
+ };
package/tensor.d.ts CHANGED
@@ -14,12 +14,13 @@ export declare abstract class ATensor<T = number> implements ITensor<T> {
14
14
  get orderedShape(): number[];
15
15
  get orderedStride(): number[];
16
16
  abstract [Symbol.iterator](): IterableIterator<T>;
17
- broadcast(shape: number[], stride: number[]): typeof this;
17
+ broadcast<S extends Shape>(shape: S, stride: S): ShapeTensor<S, T>;
18
18
  copy(): typeof this;
19
19
  empty(storage?: ITensorStorage<T>): typeof this;
20
20
  equiv(o: any): boolean;
21
21
  eqDelta(o: ITensor<T>, eps?: number): boolean;
22
22
  abstract index(pos: NumericArray): number;
23
+ position(index: number): any[];
23
24
  abstract get(pos: NumericArray): T;
24
25
  abstract set(pos: NumericArray, v: T): this;
25
26
  hi(pos: NumericArray): this;
@@ -43,6 +44,7 @@ export declare class Tensor1<T = number> extends ATensor<T> {
43
44
  get order(): number[];
44
45
  get length(): number;
45
46
  index([x]: NumericArray): number;
47
+ position(index: number): number[];
46
48
  get([x]: NumericArray): T;
47
49
  set([x]: NumericArray, v: T): this;
48
50
  pick([x]: NumericArray): Tensor1<T>;
@@ -125,6 +127,6 @@ export declare function tensorFromArray<T extends NumType, N extends Nested<numb
125
127
  export declare function tensorFromArray<N extends Nested<string>>(data: N, opts?: TensorFromArrayOpts<"str", string>): NestedTensor<N, string>;
126
128
  export declare const zeroes: <S extends Shape>(shape: S, type?: NumType, storage?: ITensorStorage<number>) => ShapeTensor<S, number>;
127
129
  export declare const ones: <S extends Shape>(shape: S, type?: NumType, storage?: ITensorStorage<number>) => ShapeTensor<S, number>;
128
- export declare const shapeToStride: (shape: NumericArray) => any[];
130
+ export declare const shapeToStride: (shape: number[]) => any[];
129
131
  export declare const strideOrder: (strides: number[]) => number[];
130
132
  //# sourceMappingURL=tensor.d.ts.map
package/tensor.js CHANGED
@@ -30,7 +30,7 @@ class ATensor {
30
30
  return swizzle(this.order)(this.stride);
31
31
  }
32
32
  broadcast(shape, stride) {
33
- return new this.constructor(
33
+ return new TENSOR_IMPLS[shape.length](
34
34
  this.type,
35
35
  this.storage,
36
36
  this.data,
@@ -64,6 +64,16 @@ class ATensor {
64
64
  eqDelta(o, eps = 1e-6) {
65
65
  return this === o || equiv(this.shape, o.shape) && _eqDelta([...this], [...o], this.length, eps);
66
66
  }
67
+ position(index) {
68
+ const { order, stride } = this;
69
+ index -= this.offset;
70
+ const idx = order.map((o) => {
71
+ const i = ~~(index / stride[o]);
72
+ index -= i * stride[o];
73
+ return i;
74
+ });
75
+ return swizzle(order)(idx);
76
+ }
67
77
  hi(pos) {
68
78
  return new this.constructor(
69
79
  this.type,
@@ -167,6 +177,9 @@ class Tensor1 extends ATensor {
167
177
  index([x]) {
168
178
  return this.offset + x * this.stride[0];
169
179
  }
180
+ position(index) {
181
+ return [~~((index - this.offset) / this.stride[0])];
182
+ }
170
183
  get([x]) {
171
184
  return this.data[this.offset + x * this.stride[0]];
172
185
  }
package/defopbtt.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import type { FnU2 } from "@thi.ng/api";
2
- import type { ITensor } from "./api.js";
3
- /**
4
- * Higher order tensor op factory. Takes given `fn` and returns a
5
- * {@link TensorOpTT}s applying the given function component-wise.
6
- *
7
- * @param fn
8
- * @param dispatch
9
- */
10
- export declare const defOpBTT: <T = number>(fn: FnU2<T>) => (out: ITensor<T> | null, a: ITensor<T>, b: ITensor<T>) => ITensor<T>;
11
- //# sourceMappingURL=defopbtt.d.ts.map
package/defopbtt.js DELETED
@@ -1,153 +0,0 @@
1
- import { equals } from "@thi.ng/vectors/equals";
2
- import { broadcast } from "./broadcast.js";
3
- import { illegalShape } from "./errors.js";
4
- import { tensor } from "./tensor.js";
5
- const defOpBTT = (fn) => {
6
- const f1 = (out, a, b) => {
7
- !out && (out = a);
8
- const {
9
- data: odata,
10
- offset: oo,
11
- stride: [txo]
12
- } = out;
13
- const {
14
- data: adata,
15
- offset: oa,
16
- shape: [sx],
17
- stride: [txa]
18
- } = a;
19
- const {
20
- data: bdata,
21
- offset: ob,
22
- stride: [txb]
23
- } = b;
24
- for (let x = 0; x < sx; x++) {
25
- odata[oo + x * txo] = fn(adata[oa + x * txa], bdata[ob + x * txb]);
26
- }
27
- return out;
28
- };
29
- const f2 = (out, a, b) => {
30
- !out && (out = a);
31
- const {
32
- data: odata,
33
- offset: oo,
34
- stride: [txo, tyo]
35
- } = out;
36
- const {
37
- data: adata,
38
- offset: oa,
39
- shape: [sx, sy],
40
- stride: [txa, tya]
41
- } = a;
42
- const {
43
- data: bdata,
44
- offset: ob,
45
- stride: [txb, tyb]
46
- } = b;
47
- let oox, oax, obx;
48
- for (let x = 0; x < sx; x++) {
49
- oox = oo + x * txo;
50
- oax = oa + x * txa;
51
- obx = ob + x * txb;
52
- for (let y = 0; y < sy; y++) {
53
- odata[oox + y * tyo] = fn(
54
- adata[oax + y * tya],
55
- bdata[obx + y * tyb]
56
- );
57
- }
58
- }
59
- return out;
60
- };
61
- const f3 = (out, a, b) => {
62
- !out && (out = a);
63
- const {
64
- data: odata,
65
- offset: oo,
66
- stride: [txo, tyo, tzo]
67
- } = out;
68
- const {
69
- data: adata,
70
- offset: oa,
71
- shape: [sx, sy, sz],
72
- stride: [txa, tya, tza]
73
- } = a;
74
- const {
75
- data: bdata,
76
- offset: ob,
77
- stride: [txb, tyb, tzb]
78
- } = b;
79
- let oox, oax, obx, ooy, oay, oby;
80
- for (let x = 0; x < sx; x++) {
81
- oox = oo + x * txo;
82
- oax = oa + x * txa;
83
- obx = ob + x * txb;
84
- for (let y = 0; y < sy; y++) {
85
- ooy = oox + y * tyo;
86
- oay = oax + y * tya;
87
- oby = obx + y * tyb;
88
- for (let z = 0; z < sz; z++) {
89
- odata[ooy + z * tzo] = fn(
90
- adata[oay + z * tza],
91
- bdata[oby + z * tzb]
92
- );
93
- }
94
- }
95
- }
96
- return out;
97
- };
98
- const f4 = (out, a, b) => {
99
- !out && (out = a);
100
- const {
101
- data: odata,
102
- offset: oo,
103
- stride: [txo, tyo, tzo, two]
104
- } = out;
105
- const {
106
- data: adata,
107
- offset: oa,
108
- shape: [sx, sy, sz, sw],
109
- stride: [txa, tya, tza, twa]
110
- } = a;
111
- const {
112
- data: bdata,
113
- offset: ob,
114
- stride: [txb, tyb, tzb, twb]
115
- } = b;
116
- let oox, oax, obx, ooy, oay, oby, ooz, oaz, obz;
117
- for (let x = 0; x < sx; x++) {
118
- oox = oo + x * txo;
119
- oax = oa + x * txa;
120
- obx = ob + x * txb;
121
- for (let y = 0; y < sy; y++) {
122
- ooy = oox + y * tyo;
123
- oay = oax + y * tya;
124
- oby = obx + y * tyb;
125
- for (let z = 0; z < sz; z++) {
126
- ooz = ooy + z * tzo;
127
- oaz = oay + z * tza;
128
- obz = oby + z * tzb;
129
- for (let w = 0; w < sw; w++) {
130
- odata[ooz + w * two] = fn(
131
- adata[oaz + w * twa],
132
- bdata[obz + w * twb]
133
- );
134
- }
135
- }
136
- }
137
- }
138
- return out;
139
- };
140
- const impls = [, f1, f2, f3, f4];
141
- return (out, a, b) => {
142
- const { shape, a: $a, b: $b } = broadcast(a, b);
143
- if (out) {
144
- if (!equals(out.shape, shape)) illegalShape(out.shape);
145
- } else {
146
- out = tensor(a.type, shape, { storage: a.storage });
147
- }
148
- return impls[shape.length](out, $a, $b);
149
- };
150
- };
151
- export {
152
- defOpBTT
153
- };