@thi.ng/tensors 0.9.0 → 0.10.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 +14 -1
- package/README.md +1 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +16 -13
- package/sample.d.ts +27 -0
- package/sample.js +290 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2025-
|
|
3
|
+
- **Last updated**: 2025-09-01T16:38:35Z
|
|
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,19 @@ 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.10.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/tensors@0.10.0) (2025-09-01)
|
|
15
|
+
|
|
16
|
+
#### 🚀 Features
|
|
17
|
+
|
|
18
|
+
- add 1D/2D/3D samplers and resampling fns ([2130067](https://github.com/thi-ng/umbrella/commit/2130067))
|
|
19
|
+
- add `defSampler1/2/3/4()` and supporting helpers
|
|
20
|
+
- add sampling kernel presets:
|
|
21
|
+
- `SAMPLE_NEAREST`
|
|
22
|
+
- `SAMPLE_LINEAR`
|
|
23
|
+
- `SAMPLE_CUBIC`
|
|
24
|
+
- `SAMPLE_LANCZOS` (higher order)
|
|
25
|
+
- add `resample1/2/3()` fns
|
|
26
|
+
|
|
14
27
|
## [0.9.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/tensors@0.9.0) (2025-08-16)
|
|
15
28
|
|
|
16
29
|
#### 🚀 Features
|
package/README.md
CHANGED
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/tensors",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "0D/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.12.
|
|
43
|
-
"@thi.ng/arrays": "^2.13.
|
|
44
|
-
"@thi.ng/checks": "^3.7.
|
|
45
|
-
"@thi.ng/equiv": "^2.1.
|
|
46
|
-
"@thi.ng/errors": "^2.5.
|
|
47
|
-
"@thi.ng/math": "^5.
|
|
48
|
-
"@thi.ng/random": "^4.1.
|
|
49
|
-
"@thi.ng/strings": "^3.9.
|
|
50
|
-
"@thi.ng/vectors": "^8.6.
|
|
42
|
+
"@thi.ng/api": "^8.12.2",
|
|
43
|
+
"@thi.ng/arrays": "^2.13.11",
|
|
44
|
+
"@thi.ng/checks": "^3.7.18",
|
|
45
|
+
"@thi.ng/equiv": "^2.1.92",
|
|
46
|
+
"@thi.ng/errors": "^2.5.42",
|
|
47
|
+
"@thi.ng/math": "^5.12.0",
|
|
48
|
+
"@thi.ng/random": "^4.1.27",
|
|
49
|
+
"@thi.ng/strings": "^3.9.22",
|
|
50
|
+
"@thi.ng/vectors": "^8.6.6"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"esbuild": "^0.25.
|
|
54
|
-
"typedoc": "^0.28.
|
|
53
|
+
"esbuild": "^0.25.9",
|
|
54
|
+
"typedoc": "^0.28.12",
|
|
55
55
|
"typescript": "^5.9.2"
|
|
56
56
|
},
|
|
57
57
|
"keywords": [
|
|
@@ -268,6 +268,9 @@
|
|
|
268
268
|
"./relun": {
|
|
269
269
|
"default": "./relun.js"
|
|
270
270
|
},
|
|
271
|
+
"./sample": {
|
|
272
|
+
"default": "./sample.js"
|
|
273
|
+
},
|
|
271
274
|
"./select": {
|
|
272
275
|
"default": "./select.js"
|
|
273
276
|
},
|
|
@@ -339,5 +342,5 @@
|
|
|
339
342
|
"status": "alpha",
|
|
340
343
|
"year": 2018
|
|
341
344
|
},
|
|
342
|
-
"gitHead": "
|
|
345
|
+
"gitHead": "e215a3e8de3809736ba0042c93bd8703a5a1a337\n"
|
|
343
346
|
}
|
package/sample.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Fn2, Fn3, Fn4, Fn5, FnN, FnN2 } from "@thi.ng/api";
|
|
2
|
+
import type { ITensor } from "./api.js";
|
|
3
|
+
import { type Tensor1 } from "./tensor.js";
|
|
4
|
+
type BoundaryFn = FnN2;
|
|
5
|
+
type Sampler1 = Fn2<ITensor, number, number>;
|
|
6
|
+
type Sampler2 = Fn3<ITensor, number, number, number>;
|
|
7
|
+
type Sampler3 = Fn4<ITensor, number, number, number, number>;
|
|
8
|
+
type Sampler4 = Fn5<ITensor, number, number, number, number, number>;
|
|
9
|
+
type BoundaryType = "clamp" | "mirror" | "wrap" | "zero";
|
|
10
|
+
type SamplerType = "nearest" | "linear" | "cubic" | "lanczos";
|
|
11
|
+
interface SamplerKernel {
|
|
12
|
+
radius: number;
|
|
13
|
+
weight: FnN;
|
|
14
|
+
}
|
|
15
|
+
export declare const SAMPLE_NEAREST: SamplerKernel;
|
|
16
|
+
export declare const SAMPLE_LINEAR: SamplerKernel;
|
|
17
|
+
export declare const SAMPLE_CUBIC: SamplerKernel;
|
|
18
|
+
export declare const SAMPLE_LANCZOS: (r?: number) => SamplerKernel;
|
|
19
|
+
export declare const defSampler1: (kernel: SamplerKernel | SamplerType, boundary?: BoundaryFn | BoundaryType) => Sampler1;
|
|
20
|
+
export declare const defSampler2: (kernel: SamplerType | SamplerKernel | [SamplerType | SamplerKernel, SamplerType | SamplerKernel], boundary?: BoundaryType | BoundaryFn | [BoundaryType | BoundaryFn, BoundaryType | BoundaryFn]) => Sampler2;
|
|
21
|
+
export declare const defSampler3: (kernel: SamplerType | SamplerKernel | [SamplerType | SamplerKernel, SamplerType | SamplerKernel, SamplerType | SamplerKernel], boundary?: BoundaryType | BoundaryFn | [BoundaryType | BoundaryFn, BoundaryType | BoundaryFn, BoundaryType | BoundaryFn]) => Sampler3;
|
|
22
|
+
export declare const defSampler4: (kernel: SamplerType | SamplerKernel | [SamplerType | SamplerKernel, SamplerType | SamplerKernel, SamplerType | SamplerKernel, SamplerType | SamplerKernel], boundary?: BoundaryType | BoundaryFn | [BoundaryType | BoundaryFn, BoundaryType | BoundaryFn, BoundaryType | BoundaryFn, BoundaryType | BoundaryFn]) => Sampler4;
|
|
23
|
+
export declare const resample1: (out: Tensor1, a: Tensor1, sampler: Sampler1) => Tensor1<number>;
|
|
24
|
+
export declare const resample2: (out: ITensor, a: ITensor, [samplerX, samplerY]: Sampler1[]) => ITensor<number>;
|
|
25
|
+
export declare const resample3: (out: ITensor, a: ITensor, [samplerX, samplerY, samplerZ]: Sampler1[]) => ITensor<number>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=sample.d.ts.map
|
package/sample.js
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { isArray } from "@thi.ng/checks/is-array";
|
|
2
|
+
import { isString } from "@thi.ng/checks/is-string";
|
|
3
|
+
import { PI } from "@thi.ng/math/api";
|
|
4
|
+
import { clamp } from "@thi.ng/math/interval";
|
|
5
|
+
import { tensor } from "./tensor.js";
|
|
6
|
+
const { abs, floor, sin } = Math;
|
|
7
|
+
const __boundaryClamp = (i, max) => clamp(i, 0, max - 1);
|
|
8
|
+
const __boundaryWrap = (i, max) => (i % max + max) % max;
|
|
9
|
+
const __boundaryMirror = (i, max) => {
|
|
10
|
+
if (max === 1) return 0;
|
|
11
|
+
const period = 2 * (max - 1);
|
|
12
|
+
i = (i % period + period) % period;
|
|
13
|
+
return i < max ? i : period - i;
|
|
14
|
+
};
|
|
15
|
+
const __boundaryZero = (i, max) => i >= 0 || i < max ? i : -1;
|
|
16
|
+
const BOUNDARY_MODES = {
|
|
17
|
+
clamp: __boundaryClamp,
|
|
18
|
+
wrap: __boundaryWrap,
|
|
19
|
+
mirror: __boundaryMirror,
|
|
20
|
+
zero: __boundaryZero
|
|
21
|
+
};
|
|
22
|
+
const SAMPLE_NEAREST = {
|
|
23
|
+
radius: 1,
|
|
24
|
+
weight: (t) => t >= -0.5 && t < 0.5 ? 1 : 0
|
|
25
|
+
};
|
|
26
|
+
const SAMPLE_LINEAR = {
|
|
27
|
+
radius: 1,
|
|
28
|
+
weight: (t) => {
|
|
29
|
+
t = abs(t);
|
|
30
|
+
return t < 1 ? 1 - t : 0;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const SAMPLE_CUBIC = {
|
|
34
|
+
radius: 2,
|
|
35
|
+
weight: (t) => {
|
|
36
|
+
t = abs(t);
|
|
37
|
+
const a = -0.5;
|
|
38
|
+
return t < 2 ? t <= 1 ? ((a + 2) * t - (a + 3)) * t * t + 1 : ((a * t - 5 * a) * t + 8 * a) * t - 4 * a : 0;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const SAMPLE_LANCZOS = (r = 2) => ({
|
|
42
|
+
radius: r,
|
|
43
|
+
weight: (t) => {
|
|
44
|
+
if (t === 0) return 1;
|
|
45
|
+
if (t > -r && t < r) {
|
|
46
|
+
t *= PI;
|
|
47
|
+
return r * sin(t) * sin(t / r) / (t * t);
|
|
48
|
+
}
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const SAMPLER_TYPES = {
|
|
53
|
+
nearest: SAMPLE_NEAREST,
|
|
54
|
+
linear: SAMPLE_LINEAR,
|
|
55
|
+
cubic: SAMPLE_CUBIC,
|
|
56
|
+
lanczos: SAMPLE_LANCZOS(2)
|
|
57
|
+
};
|
|
58
|
+
const defSampler1 = (kernel, boundary = "clamp") => {
|
|
59
|
+
const index = __resolveBoundary(boundary);
|
|
60
|
+
const { radius, weight } = __resolveKernel(kernel);
|
|
61
|
+
return ({ data, shape: [sx], stride: [tx], offset }, x) => {
|
|
62
|
+
const c = floor(x);
|
|
63
|
+
let sum = 0;
|
|
64
|
+
let wsum = 0;
|
|
65
|
+
for (let k = -radius; k <= radius; k++) {
|
|
66
|
+
const $x = c + k;
|
|
67
|
+
const w = weight(x - $x);
|
|
68
|
+
if (w === 0) continue;
|
|
69
|
+
const i = index($x, sx);
|
|
70
|
+
if (i < 0) {
|
|
71
|
+
wsum += w;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
sum += data[offset + i * tx] * w;
|
|
75
|
+
wsum += w;
|
|
76
|
+
}
|
|
77
|
+
return wsum !== 0 ? sum / wsum : 0;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const defSampler2 = (kernel, boundary = "clamp") => {
|
|
81
|
+
const [indexX, indexY] = (isArray(boundary) ? boundary : [boundary, boundary]).map(__resolveBoundary);
|
|
82
|
+
const [kernelX, kernelY] = isArray(kernel) ? kernel : [kernel, kernel];
|
|
83
|
+
const { radius: rx, weight: weightX } = __resolveKernel(kernelX);
|
|
84
|
+
const { radius: ry, weight: weightY } = __resolveKernel(kernelY);
|
|
85
|
+
const sizeY = 2 * ry + 1;
|
|
86
|
+
const cacheY = new Array(sizeY);
|
|
87
|
+
return ({ data, shape: [sx, sy], stride: [tx, ty], offset }, x, y) => {
|
|
88
|
+
const cx = floor(x);
|
|
89
|
+
const cy = floor(y);
|
|
90
|
+
let sum = 0;
|
|
91
|
+
let wsum = 0;
|
|
92
|
+
for (let i = 0; i < sizeY; i++) {
|
|
93
|
+
cacheY[i] = weightY(y - (cy + i - ry));
|
|
94
|
+
}
|
|
95
|
+
for (let kx = -rx; kx <= rx; kx++) {
|
|
96
|
+
const $x = cx + kx;
|
|
97
|
+
const ix = indexX($x, sx);
|
|
98
|
+
const wx = weightX(x - $x);
|
|
99
|
+
const idx = offset + ix * tx;
|
|
100
|
+
for (let ky = -ry; ky <= ry; ky++) {
|
|
101
|
+
const wy = cacheY[ky + ry];
|
|
102
|
+
const weight = wx * wy;
|
|
103
|
+
if (weight === 0) continue;
|
|
104
|
+
const iy = indexY(cy + ky, sy);
|
|
105
|
+
if (ix < 0 || iy < 0) {
|
|
106
|
+
wsum += weight;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
sum += data[idx + iy * ty] * weight;
|
|
110
|
+
wsum += weight;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return wsum !== 0 ? sum / wsum : 0;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
const defSampler3 = (kernel, boundary = "clamp") => {
|
|
117
|
+
const [indexX, indexY, indexZ] = (isArray(boundary) ? boundary : [boundary, boundary, boundary]).map(__resolveBoundary);
|
|
118
|
+
const [kernelX, kernelY, kernelZ] = (isArray(kernel) ? kernel : [kernel, kernel, kernel]).map(__resolveKernel);
|
|
119
|
+
const { radius: rx, weight: weightX } = kernelX;
|
|
120
|
+
const { radius: ry, weight: weightY } = kernelY;
|
|
121
|
+
const { radius: rz, weight: weightZ } = kernelZ;
|
|
122
|
+
const sizeY = 2 * ry + 1;
|
|
123
|
+
const sizeZ = 2 * rz + 1;
|
|
124
|
+
const cacheY = new Array(sizeY);
|
|
125
|
+
const cacheZ = new Array(sizeZ);
|
|
126
|
+
return ({ data, shape: [sx, sy, sz], stride: [tx, ty, tz], offset }, x, y, z) => {
|
|
127
|
+
const cx = floor(x);
|
|
128
|
+
const cy = floor(y);
|
|
129
|
+
const cz = floor(z);
|
|
130
|
+
let sum = 0;
|
|
131
|
+
let wsum = 0;
|
|
132
|
+
for (let i = 0; i < sizeY; i++) cacheY[i] = weightY(y - (cy + i - ry));
|
|
133
|
+
for (let i = 0; i < sizeZ; i++) cacheZ[i] = weightZ(z - (cz + i - rz));
|
|
134
|
+
for (let kx = -rx; kx <= rx; kx++) {
|
|
135
|
+
const $x = cx + kx;
|
|
136
|
+
const ix = indexX($x, sx);
|
|
137
|
+
const wx = weightX(x - $x);
|
|
138
|
+
const idxX = offset + ix * tx;
|
|
139
|
+
for (let ky = -ry; ky <= ry; ky++) {
|
|
140
|
+
const iy = indexY(cy + ky, sy);
|
|
141
|
+
const wy = cacheY[ky + ry];
|
|
142
|
+
const idxXY = idxX + iy * ty;
|
|
143
|
+
for (let kz = -rz; kz <= rz; kz++) {
|
|
144
|
+
const wz = cacheZ[kz + rz];
|
|
145
|
+
const weight = wx * wy * wz;
|
|
146
|
+
if (weight === 0) continue;
|
|
147
|
+
const iz = indexZ(cz + kz, sz);
|
|
148
|
+
if (ix < 0 || iy < 0 || iz < 0) {
|
|
149
|
+
wsum += weight;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
sum += data[idxXY + iz * tz] * weight;
|
|
153
|
+
wsum += weight;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return wsum !== 0 ? sum / wsum : 0;
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
const defSampler4 = (kernel, boundary = "clamp") => {
|
|
161
|
+
const [indexX, indexY, indexZ, indexW] = (isArray(boundary) ? boundary : [boundary, boundary, boundary, boundary]).map(__resolveBoundary);
|
|
162
|
+
const [kernelX, kernelY, kernelZ, kernelW] = (isArray(kernel) ? kernel : [kernel, kernel, kernel, kernel]).map(__resolveKernel);
|
|
163
|
+
const { radius: rx, weight: weightX } = kernelX;
|
|
164
|
+
const { radius: ry, weight: weightY } = kernelY;
|
|
165
|
+
const { radius: rz, weight: weightZ } = kernelZ;
|
|
166
|
+
const { radius: rw, weight: weightW } = kernelW;
|
|
167
|
+
const sizeY = 2 * ry + 1;
|
|
168
|
+
const sizeZ = 2 * rz + 1;
|
|
169
|
+
const sizeW = 2 * rw + 1;
|
|
170
|
+
const cacheY = new Array(sizeY);
|
|
171
|
+
const cacheZ = new Array(sizeZ);
|
|
172
|
+
const cacheW = new Array(sizeW);
|
|
173
|
+
return ({ data, shape: [sx, sy, sz, sw], stride: [tx, ty, tz, tw], offset }, x, y, z, w) => {
|
|
174
|
+
const cx = floor(x);
|
|
175
|
+
const cy = floor(y);
|
|
176
|
+
const cz = floor(z);
|
|
177
|
+
const cw = floor(w);
|
|
178
|
+
let sum = 0;
|
|
179
|
+
let wsum = 0;
|
|
180
|
+
for (let i = 0; i < sizeY; i++) cacheY[i] = weightY(y - (cy + i - ry));
|
|
181
|
+
for (let i = 0; i < sizeZ; i++) cacheZ[i] = weightZ(z - (cz + i - rz));
|
|
182
|
+
for (let i = 0; i < sizeW; i++) cacheW[i] = weightW(w - (cw + i - rw));
|
|
183
|
+
for (let kx = -rx; kx <= rx; kx++) {
|
|
184
|
+
const $x = cx + kx;
|
|
185
|
+
const ix = indexX($x, sx);
|
|
186
|
+
const wx = weightX(x - $x);
|
|
187
|
+
const idxX = offset + ix * tx;
|
|
188
|
+
for (let ky = -ry; ky <= ry; ky++) {
|
|
189
|
+
const iy = indexY(cy + ky, sy);
|
|
190
|
+
const wy = cacheY[ky + ry];
|
|
191
|
+
const idxXY = idxX + iy * ty;
|
|
192
|
+
for (let kz = -rz; kz <= rz; kz++) {
|
|
193
|
+
const wz = cacheZ[kz + rz];
|
|
194
|
+
const iz = indexZ(cz + kz, sz);
|
|
195
|
+
const idxXYZ = idxXY + iz * tz;
|
|
196
|
+
for (let kw = -rw; kw <= rw; kw++) {
|
|
197
|
+
const ww = cacheW[kw + rw];
|
|
198
|
+
const weight = wx * wy * wz * ww;
|
|
199
|
+
if (weight === 0) continue;
|
|
200
|
+
const iw = indexW(cw + kw, sw);
|
|
201
|
+
if (ix < 0 || iy < 0 || iz < 0 || iw < 0) {
|
|
202
|
+
wsum += weight;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
sum += data[idxXYZ + iw * tw] * weight;
|
|
206
|
+
wsum += w;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return wsum !== 0 ? sum / wsum : 0;
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
const __resolveBoundary = (mode) => isString(mode) ? BOUNDARY_MODES[mode] : mode ?? __boundaryClamp;
|
|
215
|
+
const __resolveKernel = (kernel) => isString(kernel) ? SAMPLER_TYPES[kernel] : kernel;
|
|
216
|
+
const resample1 = (out, a, sampler) => {
|
|
217
|
+
const {
|
|
218
|
+
data: odata,
|
|
219
|
+
shape: [sxo],
|
|
220
|
+
stride: [txo],
|
|
221
|
+
offset: oo
|
|
222
|
+
} = out;
|
|
223
|
+
const {
|
|
224
|
+
shape: [sxa]
|
|
225
|
+
} = a;
|
|
226
|
+
const scale = sxa / sxo;
|
|
227
|
+
for (let i = 0; i < sxo; i++) {
|
|
228
|
+
odata[oo + i * txo] = sampler(a, (i + 0.5) * scale - 0.5);
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
231
|
+
};
|
|
232
|
+
const resample2 = (out, a, [samplerX, samplerY]) => {
|
|
233
|
+
const {
|
|
234
|
+
shape: [_, syo]
|
|
235
|
+
} = out;
|
|
236
|
+
const {
|
|
237
|
+
shape: [sxa]
|
|
238
|
+
} = a;
|
|
239
|
+
const tmp = tensor("num", [sxa, syo]);
|
|
240
|
+
for (let x = 0; x < sxa; x++) {
|
|
241
|
+
resample1(tmp.pick([x, -1]), a.pick([x, -1]), samplerX);
|
|
242
|
+
}
|
|
243
|
+
for (let y = 0; y < syo; y++) {
|
|
244
|
+
resample1(out.pick([-1, y]), tmp.pick([-1, y]), samplerY);
|
|
245
|
+
}
|
|
246
|
+
return out;
|
|
247
|
+
};
|
|
248
|
+
const resample3 = (out, a, [samplerX, samplerY, samplerZ]) => {
|
|
249
|
+
const {
|
|
250
|
+
shape: [_, syo, szo]
|
|
251
|
+
} = out;
|
|
252
|
+
const {
|
|
253
|
+
shape: [sxa, sya]
|
|
254
|
+
} = a;
|
|
255
|
+
const tmpX = tensor("num", [sxa, sya, szo]);
|
|
256
|
+
for (let i = 0; i < sxa; i++) {
|
|
257
|
+
const src = a.pick([i]);
|
|
258
|
+
const dest = tmpX.pick([i]);
|
|
259
|
+
for (let j = 0; j < sya; j++) {
|
|
260
|
+
resample1(dest.pick([j]), src.pick([j]), samplerX);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const tmpY = tensor("num", [sxa, syo, szo]);
|
|
264
|
+
for (let i = 0; i < sxa; i++) {
|
|
265
|
+
const src = tmpX.pick([i]);
|
|
266
|
+
const dest = tmpY.pick([i]);
|
|
267
|
+
for (let j = 0; j < szo; j++) {
|
|
268
|
+
resample1(dest.pick([-1, j]), src.pick([-1, j]), samplerY);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
for (let i = 0; i < syo; i++) {
|
|
272
|
+
for (let j = 0; j < szo; j++) {
|
|
273
|
+
resample1(out.pick([-1, i, j]), tmpY.pick([-1, i, j]), samplerZ);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return out;
|
|
277
|
+
};
|
|
278
|
+
export {
|
|
279
|
+
SAMPLE_CUBIC,
|
|
280
|
+
SAMPLE_LANCZOS,
|
|
281
|
+
SAMPLE_LINEAR,
|
|
282
|
+
SAMPLE_NEAREST,
|
|
283
|
+
defSampler1,
|
|
284
|
+
defSampler2,
|
|
285
|
+
defSampler3,
|
|
286
|
+
defSampler4,
|
|
287
|
+
resample1,
|
|
288
|
+
resample2,
|
|
289
|
+
resample3
|
|
290
|
+
};
|