@fideus-labs/fizarrita 1.0.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/LICENSE.txt +9 -0
- package/dist/codec-worker.d.ts +23 -0
- package/dist/codec-worker.d.ts.map +1 -0
- package/dist/codec-worker.js +149 -0
- package/dist/codec-worker.js.map +1 -0
- package/dist/get-worker.d.ts +40 -0
- package/dist/get-worker.d.ts.map +1 -0
- package/dist/get-worker.js +203 -0
- package/dist/get-worker.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/internals/codec-pipeline.d.ts +29 -0
- package/dist/internals/codec-pipeline.d.ts.map +1 -0
- package/dist/internals/codec-pipeline.js +135 -0
- package/dist/internals/codec-pipeline.js.map +1 -0
- package/dist/internals/indexer.d.ts +81 -0
- package/dist/internals/indexer.d.ts.map +1 -0
- package/dist/internals/indexer.js +249 -0
- package/dist/internals/indexer.js.map +1 -0
- package/dist/internals/setter.d.ts +27 -0
- package/dist/internals/setter.d.ts.map +1 -0
- package/dist/internals/setter.js +132 -0
- package/dist/internals/setter.js.map +1 -0
- package/dist/internals/util.d.ts +59 -0
- package/dist/internals/util.d.ts.map +1 -0
- package/dist/internals/util.js +137 -0
- package/dist/internals/util.js.map +1 -0
- package/dist/set-worker.d.ts +44 -0
- package/dist/set-worker.d.ts.map +1 -0
- package/dist/set-worker.js +234 -0
- package/dist/set-worker.js.map +1 -0
- package/dist/types.d.ts +129 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/worker-rpc.d.ts +43 -0
- package/dist/worker-rpc.d.ts.map +1 -0
- package/dist/worker-rpc.js +219 -0
- package/dist/worker-rpc.js.map +1 -0
- package/package.json +53 -0
- package/src/codec-worker.ts +207 -0
- package/src/get-worker.ts +275 -0
- package/src/index.ts +15 -0
- package/src/internals/codec-pipeline.ts +200 -0
- package/src/internals/indexer.ts +346 -0
- package/src/internals/setter.ts +227 -0
- package/src/internals/util.ts +183 -0
- package/src/set-worker.ts +305 -0
- package/src/types.ts +158 -0
- package/src/worker-rpc.ts +347 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BasicIndexer — ported from zarrita.js/src/indexing/indexer.ts
|
|
3
|
+
*
|
|
4
|
+
* Handles multi-dimensional selection (slices, integer indices) and iterates
|
|
5
|
+
* over all chunk projections, yielding { chunk_coords, mapping } for each
|
|
6
|
+
* chunk that overlaps the selection.
|
|
7
|
+
*
|
|
8
|
+
* Self-contained — no deep imports from zarrita.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Indices, Slice } from 'zarrita'
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Helpers
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
export class IndexError extends Error {
|
|
18
|
+
constructor(msg: string) {
|
|
19
|
+
super(msg)
|
|
20
|
+
this.name = 'IndexError'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function err_too_many_indices(
|
|
25
|
+
selection: (number | Slice)[],
|
|
26
|
+
shape: readonly number[],
|
|
27
|
+
): never {
|
|
28
|
+
throw new IndexError(
|
|
29
|
+
`too many indicies for array; expected ${shape.length}, got ${selection.length}`,
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function err_boundscheck(dim_len: number): never {
|
|
34
|
+
throw new IndexError(
|
|
35
|
+
`index out of bounds for dimension with length ${dim_len}`,
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function err_negative_step(): never {
|
|
40
|
+
throw new IndexError('only slices with step >= 1 are supported')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function check_selection_length(
|
|
44
|
+
selection: (number | Slice)[],
|
|
45
|
+
shape: readonly number[],
|
|
46
|
+
): void {
|
|
47
|
+
if (selection.length > shape.length) {
|
|
48
|
+
err_too_many_indices(selection, shape)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Slice utilities
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
export function slice(stop: number | null): Slice
|
|
57
|
+
export function slice(
|
|
58
|
+
start: number | null,
|
|
59
|
+
stop?: number | null,
|
|
60
|
+
step?: number | null,
|
|
61
|
+
): Slice
|
|
62
|
+
export function slice(
|
|
63
|
+
start: number | null,
|
|
64
|
+
stop?: number | null,
|
|
65
|
+
step: number | null = null,
|
|
66
|
+
): Slice {
|
|
67
|
+
if (stop === undefined) {
|
|
68
|
+
stop = start
|
|
69
|
+
start = null
|
|
70
|
+
}
|
|
71
|
+
return { start, stop, step }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Resolve a Slice to concrete [start, stop, step] given dimension length.
|
|
76
|
+
* Matches Python's slice.indices().
|
|
77
|
+
*/
|
|
78
|
+
export function slice_indices(
|
|
79
|
+
{ start, stop, step }: Slice,
|
|
80
|
+
length: number,
|
|
81
|
+
): Indices {
|
|
82
|
+
if (step === 0) throw new Error('slice step cannot be zero')
|
|
83
|
+
step = step ?? 1
|
|
84
|
+
const step_is_negative = step < 0
|
|
85
|
+
const [lower, upper] = step_is_negative ? [-1, length - 1] : [0, length]
|
|
86
|
+
|
|
87
|
+
if (start === null) {
|
|
88
|
+
start = step_is_negative ? upper : lower
|
|
89
|
+
} else {
|
|
90
|
+
if (start < 0) {
|
|
91
|
+
start += length
|
|
92
|
+
if (start < lower) start = lower
|
|
93
|
+
} else if (start > upper) {
|
|
94
|
+
start = upper
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (stop === null) {
|
|
99
|
+
stop = step_is_negative ? lower : upper
|
|
100
|
+
} else {
|
|
101
|
+
if (stop < 0) {
|
|
102
|
+
stop += length
|
|
103
|
+
if (stop < lower) stop = lower
|
|
104
|
+
} else if (stop > upper) {
|
|
105
|
+
stop = upper
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return [start, stop, step]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Range / Product generators
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
function* range(start: number, stop?: number, step = 1): Iterable<number> {
|
|
117
|
+
if (stop === undefined) {
|
|
118
|
+
stop = start
|
|
119
|
+
start = 0
|
|
120
|
+
}
|
|
121
|
+
for (let i = start; i < stop; i += step) {
|
|
122
|
+
yield i
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function* product<T extends Iterable<unknown>[]>(
|
|
127
|
+
...iterables: T
|
|
128
|
+
): IterableIterator<unknown[]> {
|
|
129
|
+
if (iterables.length === 0) return
|
|
130
|
+
const iterators = iterables.map((it) => it[Symbol.iterator]())
|
|
131
|
+
const results = iterators.map((it) => it.next())
|
|
132
|
+
if (results.some((r) => r.done)) {
|
|
133
|
+
throw new Error('Input contains an empty iterator.')
|
|
134
|
+
}
|
|
135
|
+
for (let i = 0; ; ) {
|
|
136
|
+
if (results[i].done) {
|
|
137
|
+
iterators[i] = iterables[i][Symbol.iterator]()
|
|
138
|
+
results[i] = iterators[i].next()
|
|
139
|
+
if (++i >= iterators.length) return
|
|
140
|
+
} else {
|
|
141
|
+
yield results.map(({ value }) => value)
|
|
142
|
+
i = 0
|
|
143
|
+
}
|
|
144
|
+
results[i] = iterators[i].next()
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// normalize_integer_selection
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
export function normalize_integer_selection(
|
|
153
|
+
dim_sel: number,
|
|
154
|
+
dim_len: number,
|
|
155
|
+
): number {
|
|
156
|
+
dim_sel = Math.trunc(dim_sel)
|
|
157
|
+
if (dim_sel < 0) dim_sel = dim_len + dim_sel
|
|
158
|
+
if (dim_sel >= dim_len || dim_sel < 0) err_boundscheck(dim_len)
|
|
159
|
+
return dim_sel
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
// IntDimIndexer
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
|
|
166
|
+
interface IntChunkDimProjection {
|
|
167
|
+
dim_chunk_ix: number
|
|
168
|
+
dim_chunk_sel: number
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
class IntDimIndexer {
|
|
172
|
+
dim_sel: number
|
|
173
|
+
dim_len: number
|
|
174
|
+
dim_chunk_len: number
|
|
175
|
+
nitems: 1 = 1
|
|
176
|
+
|
|
177
|
+
constructor(opts: { dim_sel: number; dim_len: number; dim_chunk_len: number }) {
|
|
178
|
+
this.dim_sel = normalize_integer_selection(opts.dim_sel, opts.dim_len)
|
|
179
|
+
this.dim_len = opts.dim_len
|
|
180
|
+
this.dim_chunk_len = opts.dim_chunk_len
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
*[Symbol.iterator](): IterableIterator<IntChunkDimProjection> {
|
|
184
|
+
const dim_chunk_ix = Math.floor(this.dim_sel / this.dim_chunk_len)
|
|
185
|
+
const dim_offset = dim_chunk_ix * this.dim_chunk_len
|
|
186
|
+
const dim_chunk_sel = this.dim_sel - dim_offset
|
|
187
|
+
yield { dim_chunk_ix, dim_chunk_sel }
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
// SliceDimIndexer
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
interface SliceChunkDimProjection {
|
|
196
|
+
dim_chunk_ix: number
|
|
197
|
+
dim_chunk_sel: Indices
|
|
198
|
+
dim_out_sel: Indices
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
class SliceDimIndexer {
|
|
202
|
+
start: number
|
|
203
|
+
stop: number
|
|
204
|
+
step: number
|
|
205
|
+
dim_len: number
|
|
206
|
+
dim_chunk_len: number
|
|
207
|
+
nitems: number
|
|
208
|
+
nchunks: number
|
|
209
|
+
|
|
210
|
+
constructor(opts: { dim_sel: Slice; dim_len: number; dim_chunk_len: number }) {
|
|
211
|
+
const [start, stop, step] = slice_indices(opts.dim_sel, opts.dim_len)
|
|
212
|
+
this.start = start
|
|
213
|
+
this.stop = stop
|
|
214
|
+
this.step = step
|
|
215
|
+
if (this.step < 1) err_negative_step()
|
|
216
|
+
this.dim_len = opts.dim_len
|
|
217
|
+
this.dim_chunk_len = opts.dim_chunk_len
|
|
218
|
+
this.nitems = Math.max(0, Math.ceil((this.stop - this.start) / this.step))
|
|
219
|
+
this.nchunks = Math.ceil(this.dim_len / this.dim_chunk_len)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
*[Symbol.iterator](): IterableIterator<SliceChunkDimProjection> {
|
|
223
|
+
const dim_chunk_ix_from = Math.floor(this.start / this.dim_chunk_len)
|
|
224
|
+
const dim_chunk_ix_to = Math.ceil(this.stop / this.dim_chunk_len)
|
|
225
|
+
for (const dim_chunk_ix of range(dim_chunk_ix_from, dim_chunk_ix_to)) {
|
|
226
|
+
const dim_offset = dim_chunk_ix * this.dim_chunk_len
|
|
227
|
+
const dim_limit = Math.min(
|
|
228
|
+
this.dim_len,
|
|
229
|
+
(dim_chunk_ix + 1) * this.dim_chunk_len,
|
|
230
|
+
)
|
|
231
|
+
const dim_chunk_len = dim_limit - dim_offset
|
|
232
|
+
|
|
233
|
+
let dim_out_offset = 0
|
|
234
|
+
let dim_chunk_sel_start = 0
|
|
235
|
+
if (this.start < dim_offset) {
|
|
236
|
+
const remainder = (dim_offset - this.start) % this.step
|
|
237
|
+
if (remainder) dim_chunk_sel_start += this.step - remainder
|
|
238
|
+
dim_out_offset = Math.ceil((dim_offset - this.start) / this.step)
|
|
239
|
+
} else {
|
|
240
|
+
dim_chunk_sel_start = this.start - dim_offset
|
|
241
|
+
}
|
|
242
|
+
const dim_chunk_sel_stop =
|
|
243
|
+
this.stop > dim_limit ? dim_chunk_len : this.stop - dim_offset
|
|
244
|
+
|
|
245
|
+
const dim_chunk_sel: Indices = [
|
|
246
|
+
dim_chunk_sel_start,
|
|
247
|
+
dim_chunk_sel_stop,
|
|
248
|
+
this.step,
|
|
249
|
+
]
|
|
250
|
+
const dim_chunk_nitems = Math.ceil(
|
|
251
|
+
(dim_chunk_sel_stop - dim_chunk_sel_start) / this.step,
|
|
252
|
+
)
|
|
253
|
+
const dim_out_sel: Indices = [
|
|
254
|
+
dim_out_offset,
|
|
255
|
+
dim_out_offset + dim_chunk_nitems,
|
|
256
|
+
1,
|
|
257
|
+
]
|
|
258
|
+
yield { dim_chunk_ix, dim_chunk_sel, dim_out_sel }
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ---------------------------------------------------------------------------
|
|
264
|
+
// normalize_selection
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
|
|
267
|
+
export function normalize_selection(
|
|
268
|
+
selection: null | (Slice | null | number)[],
|
|
269
|
+
shape: readonly number[],
|
|
270
|
+
): (number | Slice)[] {
|
|
271
|
+
let normalized: (number | Slice)[]
|
|
272
|
+
if (selection === null || selection === undefined) {
|
|
273
|
+
normalized = shape.map(() => slice(null))
|
|
274
|
+
} else if (Array.isArray(selection)) {
|
|
275
|
+
normalized = selection.map((s) => s ?? slice(null))
|
|
276
|
+
} else {
|
|
277
|
+
normalized = shape.map(() => slice(null))
|
|
278
|
+
}
|
|
279
|
+
check_selection_length(normalized, shape)
|
|
280
|
+
return normalized
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
// Projection types
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
|
|
287
|
+
export type IndexerProjection =
|
|
288
|
+
| { from: number; to: null }
|
|
289
|
+
| { from: Indices; to: Indices }
|
|
290
|
+
|
|
291
|
+
export interface ChunkProjection {
|
|
292
|
+
chunk_coords: number[]
|
|
293
|
+
mapping: IndexerProjection[]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
// BasicIndexer
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
|
|
300
|
+
export class BasicIndexer {
|
|
301
|
+
dim_indexers: (SliceDimIndexer | IntDimIndexer)[]
|
|
302
|
+
shape: number[]
|
|
303
|
+
|
|
304
|
+
constructor(opts: {
|
|
305
|
+
selection: null | (null | number | Slice)[]
|
|
306
|
+
shape: readonly number[]
|
|
307
|
+
chunk_shape: readonly number[]
|
|
308
|
+
}) {
|
|
309
|
+
this.dim_indexers = normalize_selection(opts.selection, opts.shape).map(
|
|
310
|
+
(dim_sel, i) => {
|
|
311
|
+
if (typeof dim_sel === 'number') {
|
|
312
|
+
return new IntDimIndexer({
|
|
313
|
+
dim_sel,
|
|
314
|
+
dim_len: opts.shape[i],
|
|
315
|
+
dim_chunk_len: opts.chunk_shape[i],
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
return new SliceDimIndexer({
|
|
319
|
+
dim_sel,
|
|
320
|
+
dim_len: opts.shape[i],
|
|
321
|
+
dim_chunk_len: opts.chunk_shape[i],
|
|
322
|
+
})
|
|
323
|
+
},
|
|
324
|
+
)
|
|
325
|
+
this.shape = this.dim_indexers
|
|
326
|
+
.filter((ixr): ixr is SliceDimIndexer => ixr instanceof SliceDimIndexer)
|
|
327
|
+
.map((sixr) => sixr.nitems)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
*[Symbol.iterator](): IterableIterator<ChunkProjection> {
|
|
331
|
+
for (const dim_projections of product(...this.dim_indexers)) {
|
|
332
|
+
const chunk_coords = (
|
|
333
|
+
dim_projections as (IntChunkDimProjection | SliceChunkDimProjection)[]
|
|
334
|
+
).map((p) => p.dim_chunk_ix)
|
|
335
|
+
const mapping: IndexerProjection[] = (
|
|
336
|
+
dim_projections as (IntChunkDimProjection | SliceChunkDimProjection)[]
|
|
337
|
+
).map((p) => {
|
|
338
|
+
if ('dim_out_sel' in p) {
|
|
339
|
+
return { from: p.dim_chunk_sel, to: p.dim_out_sel }
|
|
340
|
+
}
|
|
341
|
+
return { from: p.dim_chunk_sel, to: null }
|
|
342
|
+
})
|
|
343
|
+
yield { chunk_coords, mapping }
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary setter — ported from zarrita.js/src/indexing/ops.ts
|
|
3
|
+
*
|
|
4
|
+
* Provides prepare, set_scalar, and set_from_chunk operations on Chunk objects.
|
|
5
|
+
* Works directly on raw TypedArray/Uint8Array memory for performance.
|
|
6
|
+
*
|
|
7
|
+
* Self-contained — no deep imports from zarrita.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Chunk, DataType, Indices, Projection, Scalar, TypedArray } from 'zarrita'
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Internal helpers
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
function indices_len(start: number, stop: number, step: number): number {
|
|
17
|
+
if (step < 0 && stop < start) {
|
|
18
|
+
return Math.floor((start - stop - 1) / -step) + 1
|
|
19
|
+
}
|
|
20
|
+
if (start < stop) return Math.floor((stop - start - 1) / step) + 1
|
|
21
|
+
return 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function compat_chunk<D extends DataType>(
|
|
25
|
+
arr: Chunk<D>,
|
|
26
|
+
): {
|
|
27
|
+
data: Uint8Array
|
|
28
|
+
stride: number[]
|
|
29
|
+
bytes_per_element: number
|
|
30
|
+
} {
|
|
31
|
+
return {
|
|
32
|
+
data: new Uint8Array(
|
|
33
|
+
(arr.data as unknown as { buffer: ArrayBufferLike }).buffer,
|
|
34
|
+
(arr.data as unknown as { byteOffset: number }).byteOffset,
|
|
35
|
+
(arr.data as unknown as { byteLength: number }).byteLength,
|
|
36
|
+
),
|
|
37
|
+
stride: arr.stride,
|
|
38
|
+
bytes_per_element: (arr.data as unknown as { BYTES_PER_ELEMENT: number }).BYTES_PER_ELEMENT,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function compat_scalar<D extends DataType>(
|
|
43
|
+
arr: Chunk<D>,
|
|
44
|
+
value: Scalar<D>,
|
|
45
|
+
): Uint8Array {
|
|
46
|
+
const TypedArrayCtor = (arr.data as unknown as { constructor: new (arr: unknown[]) => { buffer: ArrayBuffer; byteOffset: number; byteLength: number } }).constructor
|
|
47
|
+
const data = new TypedArrayCtor([value])
|
|
48
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// set_scalar_binary
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
function set_scalar_binary(
|
|
56
|
+
out: { data: Uint8Array; stride: number[] },
|
|
57
|
+
out_selection: (Indices | number)[],
|
|
58
|
+
value: Uint8Array,
|
|
59
|
+
bytes_per_element: number,
|
|
60
|
+
): void {
|
|
61
|
+
if (out_selection.length === 0) {
|
|
62
|
+
out.data.set(value, 0)
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
const [sel, ...rest] = out_selection
|
|
66
|
+
const [curr_stride, ...stride] = out.stride
|
|
67
|
+
if (typeof sel === 'number') {
|
|
68
|
+
const data = out.data.subarray(curr_stride * sel * bytes_per_element)
|
|
69
|
+
set_scalar_binary({ data, stride }, rest, value, bytes_per_element)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
const [from, to, step] = sel
|
|
73
|
+
const len = indices_len(from, to, step)
|
|
74
|
+
if (rest.length === 0) {
|
|
75
|
+
for (let i = 0; i < len; i++) {
|
|
76
|
+
out.data.set(value, curr_stride * (from + step * i) * bytes_per_element)
|
|
77
|
+
}
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
for (let i = 0; i < len; i++) {
|
|
81
|
+
const data = out.data.subarray(
|
|
82
|
+
curr_stride * (from + step * i) * bytes_per_element,
|
|
83
|
+
)
|
|
84
|
+
set_scalar_binary({ data, stride }, rest, value, bytes_per_element)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// set_from_chunk_binary
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
|
|
92
|
+
export function set_from_chunk_binary(
|
|
93
|
+
dest: { data: Uint8Array; stride: number[] },
|
|
94
|
+
src: { data: Uint8Array; stride: number[] },
|
|
95
|
+
bytes_per_element: number,
|
|
96
|
+
projections: Projection[],
|
|
97
|
+
): void {
|
|
98
|
+
const [proj, ...projs] = projections
|
|
99
|
+
const [dstride, ...dstrides] = dest.stride
|
|
100
|
+
const [sstride, ...sstrides] = src.stride
|
|
101
|
+
|
|
102
|
+
if (proj.from === null) {
|
|
103
|
+
if (projs.length === 0) {
|
|
104
|
+
dest.data.set(
|
|
105
|
+
src.data.subarray(0, bytes_per_element),
|
|
106
|
+
(proj.to as number) * bytes_per_element,
|
|
107
|
+
)
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
set_from_chunk_binary(
|
|
111
|
+
{
|
|
112
|
+
data: dest.data.subarray(
|
|
113
|
+
dstride * (proj.to as number) * bytes_per_element,
|
|
114
|
+
),
|
|
115
|
+
stride: dstrides,
|
|
116
|
+
},
|
|
117
|
+
src,
|
|
118
|
+
bytes_per_element,
|
|
119
|
+
projs,
|
|
120
|
+
)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
if (proj.to === null) {
|
|
124
|
+
if (projs.length === 0) {
|
|
125
|
+
const offset = (proj.from as number) * bytes_per_element
|
|
126
|
+
dest.data.set(src.data.subarray(offset, offset + bytes_per_element), 0)
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
set_from_chunk_binary(
|
|
130
|
+
dest,
|
|
131
|
+
{
|
|
132
|
+
data: src.data.subarray(
|
|
133
|
+
sstride * (proj.from as number) * bytes_per_element,
|
|
134
|
+
),
|
|
135
|
+
stride: sstrides,
|
|
136
|
+
},
|
|
137
|
+
bytes_per_element,
|
|
138
|
+
projs,
|
|
139
|
+
)
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const [from, to, step] = proj.to as Indices
|
|
144
|
+
const [sfrom, , sstep] = proj.from as Indices
|
|
145
|
+
const len = indices_len(from, to, step)
|
|
146
|
+
|
|
147
|
+
if (projs.length === 0) {
|
|
148
|
+
if (step === 1 && sstep === 1 && dstride === 1 && sstride === 1) {
|
|
149
|
+
const offset = sfrom * bytes_per_element
|
|
150
|
+
const size = len * bytes_per_element
|
|
151
|
+
dest.data.set(
|
|
152
|
+
src.data.subarray(offset, offset + size),
|
|
153
|
+
from * bytes_per_element,
|
|
154
|
+
)
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
for (let i = 0; i < len; i++) {
|
|
158
|
+
const offset = sstride * (sfrom + sstep * i) * bytes_per_element
|
|
159
|
+
dest.data.set(
|
|
160
|
+
src.data.subarray(offset, offset + bytes_per_element),
|
|
161
|
+
dstride * (from + step * i) * bytes_per_element,
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (let i = 0; i < len; i++) {
|
|
168
|
+
set_from_chunk_binary(
|
|
169
|
+
{
|
|
170
|
+
data: dest.data.subarray(
|
|
171
|
+
dstride * (from + i * step) * bytes_per_element,
|
|
172
|
+
),
|
|
173
|
+
stride: dstrides,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
data: src.data.subarray(
|
|
177
|
+
sstride * (sfrom + i * sstep) * bytes_per_element,
|
|
178
|
+
),
|
|
179
|
+
stride: sstrides,
|
|
180
|
+
},
|
|
181
|
+
bytes_per_element,
|
|
182
|
+
projs,
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
// Exported setter object
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
|
|
191
|
+
export const setter = {
|
|
192
|
+
prepare<D extends DataType>(
|
|
193
|
+
data: TypedArray<D>,
|
|
194
|
+
shape: number[],
|
|
195
|
+
stride: number[],
|
|
196
|
+
): Chunk<D> {
|
|
197
|
+
return { data, shape, stride }
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
set_scalar<D extends DataType>(
|
|
201
|
+
dest: Chunk<D>,
|
|
202
|
+
sel: (number | Indices)[],
|
|
203
|
+
value: Scalar<D>,
|
|
204
|
+
): void {
|
|
205
|
+
const view = compat_chunk(dest)
|
|
206
|
+
set_scalar_binary(
|
|
207
|
+
view,
|
|
208
|
+
sel,
|
|
209
|
+
compat_scalar(dest, value),
|
|
210
|
+
view.bytes_per_element,
|
|
211
|
+
)
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
set_from_chunk<D extends DataType>(
|
|
215
|
+
dest: Chunk<D>,
|
|
216
|
+
src: Chunk<D>,
|
|
217
|
+
projections: Projection[],
|
|
218
|
+
): void {
|
|
219
|
+
const view = compat_chunk(dest)
|
|
220
|
+
set_from_chunk_binary(
|
|
221
|
+
view,
|
|
222
|
+
compat_chunk(src),
|
|
223
|
+
view.bytes_per_element,
|
|
224
|
+
projections,
|
|
225
|
+
)
|
|
226
|
+
},
|
|
227
|
+
}
|