@thi.ng/tensors 0.7.0 → 0.8.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-07-09T09:42:08Z
3
+ - **Last updated**: 2025-07-10T14:20:23Z
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,13 @@ 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.8.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/tensors@0.8.0) (2025-07-10)
15
+
16
+ #### 🚀 Features
17
+
18
+ - add `step()`/`smoothStep()` variations ([b433462](https://github.com/thi-ng/umbrella/commit/b433462))
19
+ - add ITensor.crop() ([77e294d](https://github.com/thi-ng/umbrella/commit/77e294d))
20
+
14
21
  ## [0.7.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/tensors@0.7.0) (2025-07-09)
15
22
 
16
23
  #### 🚀 Features
package/README.md CHANGED
@@ -45,6 +45,7 @@ interface](https://docs.thi.ng/umbrella/tensors/interfaces/ITensor.html) shared
45
45
  by all tensor implementations provides the following methods (non-exhaustive
46
46
  list here):
47
47
 
48
+ - [.crop(pos, size)](https://docs.thi.ng/umbrella/tensors/interfaces/ITensor.html#get-1): Crop tensor region (zero copy)
48
49
  - [.get(pos)](https://docs.thi.ng/umbrella/tensors/interfaces/ITensor.html#get-1): Get value at position
49
50
  - [.hi(pos)](https://docs.thi.ng/umbrella/tensors/interfaces/ITensor.html#hi-1): Crop tensor (high end, zero copy)
50
51
  - [.index(pos)](https://docs.thi.ng/umbrella/tensors/interfaces/ITensor.html#index-1): Get index for position
@@ -66,55 +67,66 @@ conventions are closely aligned to the ones used by the
66
67
  - [abs](https://docs.thi.ng/umbrella/tensors/variables/abs.html): Componentwise `Math.abs`
67
68
  - [add](https://docs.thi.ng/umbrella/tensors/variables/add.html): Tensor-tensor addition
68
69
  - [addN](https://docs.thi.ng/umbrella/tensors/variables/addN.html): Tensor-scalar addition
69
- - [argMax](https://docs.thi.ng/umbrella/tensors/variables/argMax.html): Maximum component index/value
70
- - [argMin](https://docs.thi.ng/umbrella/tensors/variables/argMin.html): Minimum component index/value
71
- - [asTensor](https://docs.thi.ng/umbrella/tensors/variables/asTensor.html): Convert/wrap data as tensor
70
+ - [argMax](https://docs.thi.ng/umbrella/tensors/functions/argMax.html): Maximum component index/value
71
+ - [argMin](https://docs.thi.ng/umbrella/tensors/functions/argMin.html): Minimum component index/value
72
72
  - [clamp](https://docs.thi.ng/umbrella/tensors/variables/clamp.html): Tensor-tensor interval clamping
73
73
  - [clampN](https://docs.thi.ng/umbrella/tensors/variables/clampN.html): Tensor-scalar interval clamping
74
74
  - [convolve](https://docs.thi.ng/umbrella/tensors/variables/convolve.html): Tensor convolution (1D/2D/3D only)
75
75
  - [cos](https://docs.thi.ng/umbrella/tensors/variables/cos.html): Componentwise `Math.cos`
76
- - [diagonal](https://docs.thi.ng/umbrella/tensors/variables/diagonal.html): Diagonal extraction
76
+ - [diagonal](https://docs.thi.ng/umbrella/tensors/functions/diagonal.html): Diagonal extraction
77
77
  - [div](https://docs.thi.ng/umbrella/tensors/variables/div.html): Tensor-tensor division
78
78
  - [divN](https://docs.thi.ng/umbrella/tensors/variables/divN.html): Tensor-scalar division
79
79
  - [dot](https://docs.thi.ng/umbrella/tensors/variables/dot.html): Dot product
80
80
  - [exp](https://docs.thi.ng/umbrella/tensors/variables/exp.html): Componentwise `Math.exp`
81
81
  - [exp2](https://docs.thi.ng/umbrella/tensors/variables/exp2.html): Componentwise `2^x`
82
- - [integrate](https://docs.thi.ng/umbrella/tensors/variables/dot.html): Integrate tensor along innermost dimension
82
+ - [identity](https://docs.thi.ng/umbrella/tensors/functions/identity.html): Square identity matrix tensor
83
+ - [integrate](https://docs.thi.ng/umbrella/tensors/functions/integrate.html): Integrate tensor along innermost dimension
83
84
  - [log](https://docs.thi.ng/umbrella/tensors/variables/log.html): Componentwise `Math.log`
84
85
  - [log2](https://docs.thi.ng/umbrella/tensors/variables/log2.html): Componentwise `Math.log2`
85
- - [mag](https://docs.thi.ng/umbrella/tensors/variables/mag.html): Tensor magnitude
86
+ - [mag](https://docs.thi.ng/umbrella/tensors/functions/mag.html): Tensor magnitude
86
87
  - [magSq](https://docs.thi.ng/umbrella/tensors/variables/magSq.html): Tensor squared magnitude
87
88
  - [max](https://docs.thi.ng/umbrella/tensors/variables/max.html): Tensor-tensor maximum
88
89
  - [maxN](https://docs.thi.ng/umbrella/tensors/variables/maxN.html): Tensor-scalar maximum
89
- - [min](https://docs.thi.ng/umbrella/tensors/variables/min.html): Tensor-tensor minimum
90
+ - [mean](https://docs.thi.ng/umbrella/tensors/functions/mean.html): Tensor mean value
91
+ - [min](https://docs.thi.ng/umbrella/tensors/functions/min.html): Tensor-tensor minimum
90
92
  - [minN](https://docs.thi.ng/umbrella/tensors/variables/minN.html): Tensor-scalar maximum
91
93
  - [mul](https://docs.thi.ng/umbrella/tensors/variables/mul.html): Tensor-tensor multiplication
92
94
  - [mulN](https://docs.thi.ng/umbrella/tensors/variables/mulN.html): Tensor-scalar multiplication
93
- - [mulM](https://docs.thi.ng/umbrella/tensors/variables/mulM.html): Matrix-matrix product
94
- - [mulV](https://docs.thi.ng/umbrella/tensors/variables/mulV.html): Matrix-vector product
95
- - [normalize](https://docs.thi.ng/umbrella/tensors/variables/normalize.html): Tensor normalization (w/ optional length)
95
+ - [mulM](https://docs.thi.ng/umbrella/tensors/functions/mulM.html): Matrix-matrix product
96
+ - [mulV](https://docs.thi.ng/umbrella/tensors/functions/mulV.html): Matrix-vector product
97
+ - [negativeIndices](https://docs.thi.ng/umbrella/tensors/variables/negativeIndices.html): Indices of negative component values
98
+ - [nonZeroIndices](https://docs.thi.ng/umbrella/tensors/variables/nonZeroIndices.html): Indices of non-zero component values
99
+ - [normalize](https://docs.thi.ng/umbrella/tensors/functions/normalize.html): Tensor normalization (w/ optional length)
100
+ - [ones](https://docs.thi.ng/umbrella/tensors/functions/ones.html): One-filled tensor creation
101
+ - [positiveIndices](https://docs.thi.ng/umbrella/tensors/variables/positiveIndices.html): Indices of positive component values
96
102
  - [pow](https://docs.thi.ng/umbrella/tensors/variables/pow.html): Tensor-tensor `Math.pow`
97
103
  - [powN](https://docs.thi.ng/umbrella/tensors/variables/powN.html): Tensor-scalar `Math.pow`
104
+ - [print](https://docs.thi.ng/umbrella/tensors/functions/print.html): Formatted tensor output
98
105
  - [product](https://docs.thi.ng/umbrella/tensors/variables/product.html): Component product
99
106
  - [randDistrib](https://docs.thi.ng/umbrella/tensors/variables/randDistrib.html): Fill with random data from distribution fn
100
- - [range](https://docs.thi.ng/umbrella/tensors/variables/range.html): Create 1D tensor of monotonically increasing/decreasing values
107
+ - [range](https://docs.thi.ng/umbrella/tensors/functions/range.html): Create 1D tensor of monotonically increasing/decreasing values
101
108
  - [relu](https://docs.thi.ng/umbrella/tensors/variables/relu.html): ReLU activation
102
109
  - [reluN](https://docs.thi.ng/umbrella/tensors/variables/reluN.html): Leaky ReLU activation
103
- - [select](https://docs.thi.ng/umbrella/tensors/variables/select.html): Generalization of argMin/Max
104
- - [set](https://docs.thi.ng/umbrella/tensors/variables/set.html): Tensor setter
105
- - [setN](https://docs.thi.ng/umbrella/tensors/variables/setN.html): Tensor setter w/ uniform scalar
110
+ - [select](https://docs.thi.ng/umbrella/tensors/functions/select.html): Generalization of argMin/Max
111
+ - [set](https://docs.thi.ng/umbrella/tensors/functions/set.html): Tensor setter
112
+ - [setN](https://docs.thi.ng/umbrella/tensors/functions/setN.html): Tensor setter w/ uniform scalar
106
113
  - [sigmoid](https://docs.thi.ng/umbrella/tensors/variables/sigmoid.html): Sigmoid activation
107
114
  - [sin](https://docs.thi.ng/umbrella/tensors/variables/sin.html): Componentwise `Math.sin`
108
- - [softMax](https://docs.thi.ng/umbrella/tensors/variables/softMax.html): Soft Max activation
115
+ - [smoothStep](https://docs.thi.ng/umbrella/tensors/variables/smoothStep.html): Smooth threshold function (as as GLSL `smoothstep()`)
116
+ - [smoothStepN](https://docs.thi.ng/umbrella/tensors/variables/smoothStepN.html): Smooth threshold function (as as GLSL `smoothstep()`)
117
+ - [softMax](https://docs.thi.ng/umbrella/tensors/functions/softMax.html): Soft Max activation
109
118
  - [sqrt](https://docs.thi.ng/umbrella/tensors/variables/sqrt.html): Componentwise `Math.sqrt`
110
119
  - [step](https://docs.thi.ng/umbrella/tensors/variables/step.html): Threshold function (as as GLSL `step()`)
120
+ - [stepN](https://docs.thi.ng/umbrella/tensors/variables/stepN.html): Threshold function (as as GLSL `step()`)
111
121
  - [sub](https://docs.thi.ng/umbrella/tensors/variables/sub.html): Tensor-tensor subtraction
112
122
  - [subN](https://docs.thi.ng/umbrella/tensors/variables/subN.html): Tensor-scalar subtraction
113
123
  - [sum](https://docs.thi.ng/umbrella/tensors/variables/sum.html): Component sum
114
- - [svd](https://docs.thi.ng/umbrella/tensors/variables/sum.html): Singular value decomposition
124
+ - [svd](https://docs.thi.ng/umbrella/tensors/functions/svd.html): Singular value decomposition
125
+ - [swap](https://docs.thi.ng/umbrella/tensors/functions/swap.html): Swap tensor values
115
126
  - [tan](https://docs.thi.ng/umbrella/tensors/variables/tan.html): Componentwise `Math.tan`
116
127
  - [tanh](https://docs.thi.ng/umbrella/tensors/variables/tanh.html): Componentwise `Math.tanh`
117
- - [trace](https://docs.thi.ng/umbrella/tensors/variables/trace.html): Matrix trace (diagonal component sum)
128
+ - [trace](https://docs.thi.ng/umbrella/tensors/functions/trace.html): Matrix trace (diagonal component sum)
129
+ - [zeroes](https://docs.thi.ng/umbrella/tensors/functions/zeroes.html): Zero-filled tensor creation
118
130
 
119
131
  ### Broadcasting support
120
132
 
@@ -201,6 +213,8 @@ factories can be used with
201
213
  The following functions can be used to convert/coerce other data structures into
202
214
  tensors:
203
215
 
216
+ - [`asTensor()`](https://docs.thi.ng/umbrella/tensors/functions/asTensor.html):
217
+ Convert/wrap data as tensor
204
218
  - [`fromFloatBuffer()`](https://docs.thi.ng/umbrella/tensors/functions/fromFloatBuffer.html):
205
219
  Coerce [thi.ng/pixel] float buffer/image (or compatible data structures) into
206
220
  a 2D/3D tensor
@@ -237,7 +251,7 @@ For Node.js REPL:
237
251
  const ten = await import("@thi.ng/tensors");
238
252
  ```
239
253
 
240
- Package sizes (brotli'd, pre-treeshake): ESM: 9.63 KB
254
+ Package sizes (brotli'd, pre-treeshake): ESM: 9.75 KB
241
255
 
242
256
  ## Dependencies
243
257
 
package/api.d.ts CHANGED
@@ -96,6 +96,13 @@ export interface ITensor<T = number> extends ICopy<ITensor<T>>, IEquiv, IEqualsD
96
96
  * @internal
97
97
  */
98
98
  broadcast<S extends Shape>(shape: S, stride: S): ShapeTensor<S, T>;
99
+ /**
100
+ * Returns a new tensor of same shape, but all values zeroed. Unless
101
+ * `storage` is given, the new data will be allocated using this tensor's
102
+ * storage provider.
103
+ *
104
+ * @param storage
105
+ */
99
106
  empty(storage?: ITensorStorage<T>): this;
100
107
  /**
101
108
  * Computes linear array index from given grid position. Reverse-op of
@@ -117,15 +124,286 @@ export interface ITensor<T = number> extends ICopy<ITensor<T>>, IEquiv, IEqualsD
117
124
  * @param index
118
125
  */
119
126
  position(index: number): number[];
127
+ /**
128
+ * Returns value at given grid position. No bounds checking.
129
+ *
130
+ * @param pos
131
+ */
120
132
  get(pos: NumericArray): T;
133
+ /**
134
+ * Sets value at given grid position. No bounds checking.
135
+ *
136
+ * @param pos
137
+ * @param value
138
+ */
121
139
  set(pos: NumericArray, value: T): this;
140
+ /**
141
+ * Returns a new tensor of the bottom-right region starting from given
142
+ * `pos`. View transform only, no data will be copied.
143
+ *
144
+ * @remarks
145
+ * Also see {@link Itensor.hi}, {@link ITensor.crop}.
146
+ *
147
+ * @example
148
+ * ```ts tangle:../export/itensor-lo.ts
149
+ * import { print, range } from "@thi.ng/tensors";
150
+ *
151
+ * const a = range(16).reshape([4, 4]);
152
+ * print(a);
153
+ * // 0 1.0000 2.0000 3.0000
154
+ * // 4.0000 5.0000 6.0000 7.0000
155
+ * // 8.0000 9.0000 10.0000 11.0000
156
+ * // 12.0000 13.0000 14.0000 15.0000
157
+ *
158
+ * const b = a.lo([2, 1]);
159
+ * print(b);
160
+ * // 9.0000 10.0000 11.0000
161
+ * // 13.0000 14.0000 15.0000
162
+ * ```
163
+ *
164
+ * @param pos
165
+ */
122
166
  lo(pos: NumericArray): this;
167
+ /**
168
+ * Returns a new tensor of the top-left region until given `pos` (excluded).
169
+ * View transform only, no data will be copied.
170
+ *
171
+ * @remarks
172
+ * Also see {@link Itensor.lo}, {@link ITensor.crop}.
173
+ *
174
+ * @example
175
+ * ```ts tangle:../export/itensor-hi.ts
176
+ * import { print, range } from "@thi.ng/tensors";
177
+ *
178
+ * const a = range(16).reshape([4, 4]);
179
+ * print(a);
180
+ * // 0 1.0000 2.0000 3.0000
181
+ * // 4.0000 5.0000 6.0000 7.0000
182
+ * // 8.0000 9.0000 10.0000 11.0000
183
+ * // 12.0000 13.0000 14.0000 15.0000
184
+ *
185
+ * const b = a.hi([2, 3]);
186
+ * print(b);
187
+ * // 0 1.0000 2.0000
188
+ * // 4.0000 5.0000 6.0000
189
+ * ```
190
+ *
191
+ * @param pos
192
+ */
123
193
  hi(pos: NumericArray): this;
194
+ /**
195
+ * Returns a new tensor of the extracted region defined by `pos` and `size`.
196
+ * This op is a combination of {@link ITensor.lo} and {@link ITensor.hi}.
197
+ * View transform only, no data will be copied.
198
+ *
199
+ * @example
200
+ * ```ts tangle:../export/itensor-crop.ts
201
+ * import { print, range } from "@thi.ng/tensors";
202
+ *
203
+ * const a = range(16).reshape([4, 4]);
204
+ * print(a);
205
+ * // 0 1.0000 2.0000 3.0000
206
+ * // 4.0000 5.0000 6.0000 7.0000
207
+ * // 8.0000 9.0000 10.0000 11.0000
208
+ * // 12.0000 13.0000 14.0000 15.0000
209
+ *
210
+ * const b = a.crop([1, 1], [2, 2]);
211
+ * print(b);
212
+ * // 5.0000 6.0000
213
+ * // 9.0000 10.0000
214
+ * ```
215
+ *
216
+ * @param pos
217
+ * @param size
218
+ */
219
+ crop(pos: NumericArray, size: NumericArray): this;
220
+ /**
221
+ * Returns a new tensor with step sizes adjusted for selected axes (Using
222
+ * zero for an axis will keep its current step size). View transform only,
223
+ * no data will be copied.
224
+ *
225
+ * @example
226
+ * ```ts tangle:../export/itensor-step.ts
227
+ * import { print, range } from "@thi.ng/tensors";
228
+ *
229
+ * const a = range(16).reshape([4, 4]);
230
+ * print(a);
231
+ * // 0 1.0000 2.0000 3.0000
232
+ * // 4.0000 5.0000 6.0000 7.0000
233
+ * // 8.0000 9.0000 10.0000 11.0000
234
+ * // 12.0000 13.0000 14.0000 15.0000
235
+ *
236
+ * // only select every 2nd row
237
+ * const b = a.step([2, 1]);
238
+ * print(b);
239
+ * // 0 1.0000 2.0000 3.0000
240
+ * // 8.0000 9.0000 10.0000 11.0000
241
+ *
242
+ * // keep rows as is (zero), only select every 2nd column
243
+ * print(b.step([0, 2]));
244
+ * // 0 2.0000
245
+ * // 8.0000 10.0000
246
+ * ```
247
+ *
248
+ * @param select
249
+ */
124
250
  step(select: NumericArray): this;
251
+ /**
252
+ * Returns a new tensor with only the `select`ed axes. A -1 will select all
253
+ * value in that axis. View transform only, no data will be copied.
254
+ *
255
+ * @example
256
+ * ```ts tangle:../export/itensor-pick.ts
257
+ * import { print, range } from "@thi.ng/tensors";
258
+ *
259
+ * // 3D 4x4x4 tensor with values in [0,64) range
260
+ * const a = range(64).reshape([4, 4, 4]);
261
+ *
262
+ * // pick entire slice #2
263
+ * print(a.pick([2]));
264
+ * // 32.0000 33.0000 34.0000 35.0000
265
+ * // 36.0000 37.0000 38.0000 39.0000
266
+ * // 40.0000 41.0000 42.0000 43.0000
267
+ * // 44.0000 45.0000 46.0000 47.0000
268
+ *
269
+ * // pick slice #2, row #2 (1D tensor)
270
+ * print(a.pick([2, 2]));
271
+ * // 40.0000 41.0000 42.0000 43.0000
272
+ *
273
+ * // pick slice #2, column #2 (1D tensor)
274
+ * print(a.pick([2, -1, 2]));
275
+ * // 34.0000 38.0000 42.0000 46.0000
276
+ * ```
277
+ *
278
+ * @param select
279
+ */
125
280
  pick(select: NumericArray): ITensor<T>;
281
+ /**
282
+ * Creates a "packed" copy of this tensor with dense striding and the new
283
+ * data array only holding the values actually referenced by this tensor.
284
+ * Unless `storage` is given, the new data will be allocated using this
285
+ * tensor's storage provider.
286
+ *
287
+ * @remarks
288
+ * Since most other `ITensor` ops are zero-copy, view-only transforms, often
289
+ * resulting in "sparse" views which are only addressing a subset of the
290
+ * values stored, using `.pack()` is useful to extract data into a dense
291
+ * tensor/buffer.
292
+ *
293
+ * @example
294
+ * ```ts tangle:../export/itensor-pack.ts
295
+ * import { range } from "@thi.ng/tensors";
296
+ *
297
+ * const a = range(16).reshape([4, 4]);
298
+ * console.log("a data", a.data);
299
+ * // a data [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]
300
+ *
301
+ * // only select every 2nd row & column
302
+ * const b = a.step([2, 2]);
303
+ * console.log("b values", [...b]);
304
+ * // b values [ 0, 2, 8, 10 ]
305
+ * console.log("b data", b.data);
306
+ * // b data [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]
307
+ *
308
+ * // create packed version of `b`
309
+ * const c = b.pack();
310
+ * console.log("c data", c.data);
311
+ * // c data [ 0, 2, 8, 10 ]
312
+ * ```
313
+ *
314
+ * @param storage
315
+ */
126
316
  pack(storage?: ITensorStorage<T>): this;
317
+ /**
318
+ * Returns a new tensor with same data but given new shape (and optionally
319
+ * new strides). The total number of elements of the new shape MUST match
320
+ * that of the current shape (otherwise an error will be thrown).
321
+ *
322
+ * @remarks
323
+ * Also see {@link ITensor.crop} and {@link ITensor.resize}
324
+ *
325
+ * @example
326
+ * ```ts tangle:../export/itensor-reshape.ts
327
+ * import { print, range } from "@thi.ng/tensors";
328
+ *
329
+ * // 1D tensor
330
+ * const a = range(16);
331
+ *
332
+ * // reshape as 2D tensor
333
+ * print(a.reshape([4, 4]));
334
+ * // 0 1.0000 2.0000 3.0000
335
+ * // 4.0000 5.0000 6.0000 7.0000
336
+ * // 8.0000 9.0000 10.0000 11.0000
337
+ * // 12.0000 13.0000 14.0000 15.0000
338
+ *
339
+ * // reshape as 3D tensor
340
+ * print(a.reshape([2, 2, 4]));
341
+ * // --- 0: ---
342
+ * // 0 1.0000 2.0000 3.0000
343
+ * // 4.0000 5.0000 6.0000 7.0000
344
+ * // --- 1: ---
345
+ * // 8.0000 9.0000 10.0000 11.0000
346
+ * // 12.0000 13.0000 14.0000 15.0000
347
+ * ```
348
+ *
349
+ * @param newShape
350
+ * @param newStride
351
+ */
127
352
  reshape<S extends Shape>(newShape: S, newStride?: S): ShapeTensor<S, T>;
353
+ /**
354
+ * Returns a copy of the tensor resized to `newShape`. If the new shape is
355
+ * larger than the current shape, the extra data values will be initialized
356
+ * to `fill` (default: zero). Values will be copied in current iteration
357
+ * order (same logic as numpy). Unless `storage` is given, the new data will
358
+ * be allocated using this tensor's storage provider.
359
+ *
360
+ * @remarks
361
+ * Also see {@link ITensor.crop}, {@link ITensor.reshape}.
362
+ *
363
+ * @example
364
+ * ```ts tangle:../export/itensor-resize.ts
365
+ * import { print, range } from "@thi.ng/tensors";
366
+ *
367
+ * // 2D 4x4 tensor with values in [0,16) range
368
+ * const a = range(16).reshape([4, 4]);
369
+ *
370
+ * print(a.resize([4, 8]));
371
+ * // 0 1.0000 2.0000 3.0000 4.0000 5.0000 6.0000 7.0000
372
+ * // 8.0000 9.0000 10.0000 11.0000 12.0000 13.0000 14.0000 15.0000
373
+ * // 0 0 0 0 0 0 0 0
374
+ * // 0 0 0 0 0 0 0 0
375
+ * ```
376
+ *
377
+ * @param newShape
378
+ * @param fill
379
+ * @param storage
380
+ */
128
381
  resize<S extends Shape>(newShape: S, fill?: T, storage?: ITensorStorage<T>): ShapeTensor<S, T>;
382
+ /**
383
+ * Returns a new tensor with the given new axis `order`. View transform
384
+ * only, no data will be copied.
385
+ *
386
+ * @example
387
+ * ```ts tangle:../export/itensor-transpose.ts
388
+ * import { print, range } from "@thi.ng/tensors";
389
+ *
390
+ * const a = range(12).reshape([3, 4]);
391
+ * print(a);
392
+ * // 0 1.0000 2.0000 3.0000
393
+ * // 4.0000 5.0000 6.0000 7.0000
394
+ * // 8.0000 9.0000 10.0000 11.0000
395
+ *
396
+ * // swap row & column order
397
+ * const b = a.transpose([1, 0]);
398
+ * print(b);
399
+ * // 0 4.0000 8.0000
400
+ * // 1.0000 5.0000 9.0000
401
+ * // 2.0000 6.0000 10.0000
402
+ * // 3.0000 7.0000 11.0000
403
+ * ```
404
+ *
405
+ * @param order
406
+ */
129
407
  transpose(order: NumericArray): this;
130
408
  toJSON(): any;
131
409
  }
package/index.d.ts CHANGED
@@ -55,10 +55,13 @@ export * from "./set.js";
55
55
  export * from "./setn.js";
56
56
  export * from "./sigmoid.js";
57
57
  export * from "./sin.js";
58
+ export * from "./smoothstep.js";
59
+ export * from "./smoothstepn.js";
58
60
  export * from "./softmax.js";
59
61
  export * from "./softplus.js";
60
62
  export * from "./sqrt.js";
61
63
  export * from "./step.js";
64
+ export * from "./stepn.js";
62
65
  export * from "./storage.js";
63
66
  export * from "./sub.js";
64
67
  export * from "./subn.js";
package/index.js CHANGED
@@ -55,10 +55,13 @@ export * from "./set.js";
55
55
  export * from "./setn.js";
56
56
  export * from "./sigmoid.js";
57
57
  export * from "./sin.js";
58
+ export * from "./smoothstep.js";
59
+ export * from "./smoothstepn.js";
58
60
  export * from "./softmax.js";
59
61
  export * from "./softplus.js";
60
62
  export * from "./sqrt.js";
61
63
  export * from "./step.js";
64
+ export * from "./stepn.js";
62
65
  export * from "./storage.js";
63
66
  export * from "./sub.js";
64
67
  export * from "./subn.js";
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) => import("./tensor.js").Tensor1<any> | ITensor<number>;
10
+ export declare const normalize: (out: ITensor | null, a: ITensor, n?: number) => ITensor<number> | import("./tensor.js").Tensor1<any>;
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.7.0",
3
+ "version": "0.8.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",
@@ -39,19 +39,19 @@
39
39
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@thi.ng/api": "^8.11.29",
43
- "@thi.ng/arrays": "^2.13.1",
44
- "@thi.ng/checks": "^3.7.9",
45
- "@thi.ng/equiv": "^2.1.85",
46
- "@thi.ng/errors": "^2.5.35",
47
- "@thi.ng/math": "^5.11.29",
48
- "@thi.ng/random": "^4.1.20",
49
- "@thi.ng/strings": "^3.9.15",
50
- "@thi.ng/vectors": "^8.3.1"
42
+ "@thi.ng/api": "^8.11.30",
43
+ "@thi.ng/arrays": "^2.13.2",
44
+ "@thi.ng/checks": "^3.7.10",
45
+ "@thi.ng/equiv": "^2.1.86",
46
+ "@thi.ng/errors": "^2.5.36",
47
+ "@thi.ng/math": "^5.11.30",
48
+ "@thi.ng/random": "^4.1.21",
49
+ "@thi.ng/strings": "^3.9.16",
50
+ "@thi.ng/vectors": "^8.3.2"
51
51
  },
52
52
  "devDependencies": {
53
- "esbuild": "^0.25.5",
54
- "typedoc": "^0.28.5",
53
+ "esbuild": "^0.25.6",
54
+ "typedoc": "^0.28.7",
55
55
  "typescript": "^5.8.3"
56
56
  },
57
57
  "keywords": [
@@ -64,6 +64,7 @@
64
64
  "array",
65
65
  "blur",
66
66
  "broadcast",
67
+ "conversion",
67
68
  "convolution",
68
69
  "data-oriented",
69
70
  "datastructure",
@@ -85,6 +86,7 @@
85
86
  "pool",
86
87
  "presets",
87
88
  "random",
89
+ "smoothstep",
88
90
  "step",
89
91
  "svd",
90
92
  "tensor",
@@ -281,6 +283,12 @@
281
283
  "./sin": {
282
284
  "default": "./sin.js"
283
285
  },
286
+ "./smoothstep": {
287
+ "default": "./smoothstep.js"
288
+ },
289
+ "./smoothstepn": {
290
+ "default": "./smoothstepn.js"
291
+ },
284
292
  "./softmax": {
285
293
  "default": "./softmax.js"
286
294
  },
@@ -293,6 +301,9 @@
293
301
  "./step": {
294
302
  "default": "./step.js"
295
303
  },
304
+ "./stepn": {
305
+ "default": "./stepn.js"
306
+ },
296
307
  "./storage": {
297
308
  "default": "./storage.js"
298
309
  },
@@ -328,5 +339,5 @@
328
339
  "status": "alpha",
329
340
  "year": 2018
330
341
  },
331
- "gitHead": "e657c2d66574c18343a6797aef4585945729093e\n"
342
+ "gitHead": "56d8f088389b22192a06e9a395b5eecebf47697a\n"
332
343
  }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Componentwise computes smoothstep function for given nD tensor and thresholds
3
+ * `b` (low edge) and `c` (high edge). Writes result to `out`. If `out` is null,
4
+ * mutates `a`. Multi-method. Also see {@link step}.
5
+ *
6
+ * @remarks
7
+ * Same as GLSL `smoothstep()` (but with changed order of arguments).
8
+ *
9
+ * Reference:
10
+ *
11
+ * - https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml
12
+ *
13
+ * @param out - output tensor
14
+ * @param a - input tensor
15
+ * @param b - input tensor (low edge)
16
+ * @param b - input tensor (high edge)
17
+ */
18
+ export declare const smoothStep: import("./api.js").TensorOpTTT<number>;
19
+ //# sourceMappingURL=smoothstep.d.ts.map
package/smoothstep.js ADDED
@@ -0,0 +1,6 @@
1
+ import { smoothStep as $ } from "@thi.ng/math/step";
2
+ import { defOpTTT } from "./defopttt.js";
3
+ const smoothStep = defOpTTT((a, b, c) => $(b, c, a));
4
+ export {
5
+ smoothStep
6
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Componentwise computes smoothstep function for given nD tensor and uniform
3
+ * scalar thresholds `b` (low edge) and `c` (high edge). Writes result to `out`.
4
+ * If `out` is null, mutates `a`. Multi-method. Also see {@link stepN}.
5
+ *
6
+ * @remarks
7
+ * Same as GLSL `smoothstep()` (but with changed order of arguments).
8
+ *
9
+ * Reference:
10
+ *
11
+ * - https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml
12
+ *
13
+ * @param out - output tensor
14
+ * @param a - input tensor
15
+ * @param b - scalar (low edge)
16
+ * @param c - scalar (high edge)
17
+ */
18
+ export declare const smoothStepN: import("./api.js").MultiTensorOpImpl<import("./api.js").TensorOpTNN<number>>;
19
+ //# sourceMappingURL=smoothstepn.d.ts.map
package/smoothstepn.js ADDED
@@ -0,0 +1,6 @@
1
+ import { smoothStep as $ } from "@thi.ng/math/step";
2
+ import { defOpTNN } from "./defoptnn.js";
3
+ const smoothStepN = defOpTNN((a, b, c) => $(b, c, a));
4
+ export {
5
+ smoothStepN
6
+ };
package/step.d.ts CHANGED
@@ -1,16 +1,18 @@
1
1
  /**
2
- * Componentwise computes step function for given nD tensor and uniform scalar
3
- * threshold `n`. Writes result to `out`. If `out` is null, mutates `a`.
4
- * Multi-method.
2
+ * Componentwise computes step function for given nD tensor and threshold `b`.
3
+ * Writes result to `out`. If `out` is null, mutates `a`. Multi-method. Also see
4
+ * {@link stepN} and {@link smoothStep}.
5
5
  *
6
6
  * @remarks
7
- * Same logic as GLSL `step()` (but with different order of arguments). If
8
- * `n=0`, the op becomes the Heaviside function:
9
- * https://en.wikipedia.org/wiki/Heaviside_step_function
7
+ * Same logic as GLSL `step()` (but with swapped order of arguments).
8
+ *
9
+ * Reference:
10
+ *
11
+ * - https://registry.khronos.org/OpenGL-Refpages/gl4/html/step.xhtml
10
12
  *
11
13
  * @param out - output tensor
12
14
  * @param a - input tensor
13
- * @param n - scalar
15
+ * @param b - input tensor (threshold)
14
16
  */
15
- export declare const stepN: import("./api.js").MultiTensorOpImpl<import("./api.js").TensorOpTN<number>>;
17
+ export declare const step: import("./api.js").TensorOpTT<number>;
16
18
  //# sourceMappingURL=step.d.ts.map
package/step.js CHANGED
@@ -1,5 +1,5 @@
1
- import { defOpTN } from "./defoptn.js";
2
- const stepN = defOpTN((a, b) => a >= b ? 1 : 0);
1
+ import { defOpTT } from "./defoptt.js";
2
+ const step = defOpTT((a, b) => a >= b ? 1 : 0);
3
3
  export {
4
- stepN
4
+ step
5
5
  };
package/stepn.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Componentwise computes step function for given nD tensor and uniform scalar
3
+ * threshold `n`. Writes result to `out`. If `out` is null, mutates `a`.
4
+ * Multi-method. Also see {@link step} and {@link smoothStep}.
5
+ *
6
+ * @remarks
7
+ * Same logic as GLSL `step()` (but with different order of arguments). If
8
+ * `n=0`, the op becomes the Heaviside function:
9
+ * https://en.wikipedia.org/wiki/Heaviside_step_function
10
+ *
11
+ * @param out - output tensor
12
+ * @param a - input tensor
13
+ * @param n - scalar
14
+ */
15
+ export declare const stepN: import("./api.js").MultiTensorOpImpl<import("./api.js").TensorOpTN<number>>;
16
+ //# sourceMappingURL=stepn.d.ts.map
package/stepn.js ADDED
@@ -0,0 +1,5 @@
1
+ import { defOpTN } from "./defoptn.js";
2
+ const stepN = defOpTN((a, b) => a >= b ? 1 : 0);
3
+ export {
4
+ stepN
5
+ };
package/tensor.d.ts CHANGED
@@ -29,6 +29,7 @@ export declare abstract class ATensor<T = number> implements ITensor<T> {
29
29
  abstract set(pos: NumericArray, v: T): this;
30
30
  hi(pos: NumericArray): this;
31
31
  lo(pos: NumericArray): this;
32
+ crop(pos: NumericArray, size: NumericArray): this;
32
33
  step(select: NumericArray): typeof this;
33
34
  pick(select: NumericArray): ITensor<T>;
34
35
  pack(storage?: ITensorStorage<T>): typeof this;
package/tensor.js CHANGED
@@ -101,6 +101,17 @@ class ATensor {
101
101
  offset
102
102
  );
103
103
  }
104
+ crop(pos, size) {
105
+ const { shape, offset } = __crop(pos, size, this);
106
+ return new this.constructor(
107
+ this.type,
108
+ this.storage,
109
+ this.data,
110
+ shape,
111
+ this.stride,
112
+ offset
113
+ );
114
+ }
104
115
  step(select) {
105
116
  const { shape, stride, offset } = __step(select, this);
106
117
  return new this.constructor(
@@ -500,6 +511,7 @@ const __lo = (select, { shape, stride, offset }) => {
500
511
  const newShape = [];
501
512
  for (let i = 0, n = shape.length; i < n; i++) {
502
513
  const x = select[i];
514
+ if (x > shape[i]) illegalShape(select);
503
515
  newShape.push(
504
516
  x >= 0 ? (offset += stride[i] * x, shape[i] - x) : shape[i]
505
517
  );
@@ -510,10 +522,16 @@ const __hi = (select, { shape }) => {
510
522
  const newShape = [];
511
523
  for (let i = 0, n = shape.length; i < n; i++) {
512
524
  const x = select[i];
525
+ if (x > shape[i]) illegalShape(select);
513
526
  newShape.push(x > 0 ? x : shape[i]);
514
527
  }
515
528
  return newShape;
516
529
  };
530
+ const __crop = (lo, hi, src) => {
531
+ const res = __lo(lo, src);
532
+ const shape = __hi(hi, res);
533
+ return { ...res, shape };
534
+ };
517
535
  const __step = (select, { shape, stride, offset }) => {
518
536
  const newShape = shape.slice();
519
537
  const newStride = stride.slice();