/
symbolic_typed_array.ts
262 lines (228 loc) · 7.56 KB
/
symbolic_typed_array.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/**
* @module webdnn
*/
/** Don't Remove This comment block */
import PlaceholderContext, { Placeholder } from "../placeholder";
/**
* @protected
*/
function flatten(arr: any) {
let result = [] as any[];
for (let i = 0; i < arr.length; i++) {
let v = arr[i];
if (v instanceof Array) {
result.splice(result.length, 0, flatten(v))
} else {
result[result.length] = v;
}
}
return result
}
/**
* @protected
*/
export abstract class SymbolicTypedArray<T extends Float32Array | Int32Array> {
/**
* @protected
*/
readonly _length: number | Placeholder;
/**
* @protected
*/
readonly _byteOffset: number | Placeholder;
/**
* The size in bytes of each element in the array.
*/
readonly BYTES_PER_ELEMENT: number; // removed "abstract" due to TS2715
/**
* @protected
*/
protected _buffer: ArrayBufferLike | null;
/**
* @protected
*/
name: string;
/**
* @protected
*/
constructor(buffer: ArrayBufferLike | null = null,
byteOffset: number | Placeholder = 0,
length?: number | Placeholder,
protected placeholderContext: PlaceholderContext | null = null) {
this._byteOffset = byteOffset;
this._buffer = buffer;
if (buffer) {
this._length = length === undefined ? (buffer.byteLength / this.BYTES_PER_ELEMENT) : length;
} else {
if (length === undefined) throw Error('"butter" or "length" must be specified.');
this._length = length;
}
if (this.isDynamic) {
if (!placeholderContext) {
throw Error('PlaceholderContext must be required when SymbolicTypedArray is initialized as dynamic buffer view.')
}
}
}
/**
* Convert SymbolicTypedArray instance into actual TypedArray instance.
*
* @returns actual typed array
*/
abstract toActual(): T;
/**
* The ArrayBuffer instance referenced by the array.
*/
get buffer(): ArrayBufferLike {
if (!this._buffer) this._buffer = new ArrayBuffer(this.byteOffset + this.byteLength);
return this._buffer;
}
/**
* The ArrayBuffer instance referenced by the array.
*/
set buffer(buffer: ArrayBufferLike) {
this._buffer = buffer;
}
/**
* The length in bytes of the array.
*/
get byteLength(): number {
return this.length * this.BYTES_PER_ELEMENT;
}
/**
* The number in this buffer. Actual offset size is `(offset * SIZE_OF_FLOAT)`.
*/
get offset(): number {
return this.byteOffset / this.BYTES_PER_ELEMENT;
}
/**
* @protected
*/
get isDynamic() {
return (typeof this._byteOffset !== 'number' || typeof this._length !== 'number')
}
/**
* The number of elements in this buffer. Actual byte size is `(length * SIZE_OF_FLOAT)`.
*/
get length() {
if (this.isDynamic) {
return this.placeholderContext!.resolve(this._length) as number;
} else {
return this._length as number;
}
}
/**
* The offset in bytes of the array.
*/
get byteOffset() {
if (this.isDynamic) {
return this.placeholderContext!.resolve(this._byteOffset);
} else {
return this._byteOffset as number;
}
}
/**
* Returns the this object after copying a section of the array identified by start and end
* to the same array starting at position target
* @param target If target is negative, it is treated as length+target where length is the
* length of the array.
* @param start If start is negative, it is treated as length+start. If end is negative, it
* is treated as length+end.
* @param end If not specified, length of the this object is used as its default value.
*/
copyWithin(target: number, start: number, end?: number): this {
this.toActual().copyWithin(target, start, end);
return this;
}
/**
* Returns the this object after filling the section identified by start and end with value
* @param value value to fill array section with
* @param start index to start filling the array at. If start is negative, it is treated as
* length+start where length is the length of the array.
* @param end index to stop filling the array at. If end is negative, it is treated as
* length+end.
*/
fill(value: number, start?: number, end?: number): this {
this.toActual().fill(value, start, end);
return this;
}
/**
* Returns the index of the first occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
indexOf(searchElement: number, fromIndex?: number): number {
return this.toActual().indexOf(searchElement, fromIndex);
}
/**
* Adds all the elements of an array separated by the specified separator string.
* @param separator A string used to separate one element of an array from the next in the
* resulting String. If omitted, the array elements are separated with a comma.
*/
join(separator?: string): string {
return this.toActual().join(separator);
}
/**
* Returns the index of the last occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
lastIndexOf(searchElement: number, fromIndex?: number): number {
return this.toActual().lastIndexOf(searchElement, fromIndex);
}
/**
* Sorts an array.
* @param compareFn The name of the function used to determine the order of the elements. If
* omitted, the elements are sorted in ascending, ASCII character order.
*/
sort(compareFn?: (a: number, b: number) => number): this {
this.toActual().sort(compareFn);
return this;
}
includes(searchElement: number, fromIndex?: number | undefined): boolean {
return this.toActual().includes(searchElement, fromIndex);
}
/**
* Sets a value or an array of values.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: ArrayLike<number>, offset?: number | undefined): void {
return this.toActual().set(flatten(array), offset);
}
/**
* Converts a number to a string by using the current locale.
*/
toLocaleString(): string {
return this.toActual().toLocaleString();
}
/**
* Returns a string representation of an array.
*/
toString(): string {
return this.toActual().toString();
}
/** @protected */
[Symbol.iterator](): IterableIterator<number> {
return this.toActual()[Symbol.iterator]();
}
/**
* Returns an iterable of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]> {
return this.toActual().entries();
}
/**
* Returns an iterable of keys in the array
*/
keys(): IterableIterator<number> {
return this.toActual().keys();
}
/**
* Returns an iterable of values in the array
*/
values(): IterableIterator<number> {
return this.toActual().values();
}
}