• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16// Autogenerated file. DO NOT EDIT
17package escompat
18
19// NOTE(kprokopenko): placing into std.core.Runtime breaks frontend
20native function RuntimeGetPlatformIsLittleEndian(): boolean
21
22const IS_LITTLE_ENDIAN = RuntimeGetPlatformIsLittleEndian()
23
24class Uint8ClampedArrayIteratorKeys implements IterableIterator<number> {
25    private length: int = 0
26    private idx: int = 0
27
28    constructor(parent: Uint8ClampedArray) {
29        this.length = parent.length as int
30    }
31
32    public override $_iterator(): IterableIterator<Number> {
33        return this
34    }
35
36    override next(): IteratorResult<number> {
37        if (this.idx < 0 || this.idx >= this.length) {
38            return new IteratorResult<number>()
39        }
40        return new IteratorResult<number>(false, this.idx++ as number)
41    }
42}
43
44class Uint8ClampedArrayIterator implements IterableIterator<Number> {
45    private parent: Uint8ClampedArray
46    private idx: int = 0
47
48    constructor(parent: Uint8ClampedArray) {
49        this.parent = parent
50    }
51
52    public override $_iterator(): IterableIterator<Number> {
53        return this
54    }
55
56    override next(): IteratorResult<Number> {
57        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
58            return new IteratorResult<Number>()
59        }
60        return new IteratorResult<Number>(false, new Number(this.parent.getUnsafe(this.idx++)))
61    }
62}
63
64class Uint8ClampedArrayIteratorEntries implements IterableIterator<[Number, Number]> {
65    private parent: Uint8ClampedArray
66    private idx: int = 0
67
68    constructor(parent: Uint8ClampedArray) {
69        this.parent = parent
70    }
71
72    public override $_iterator(): IterableIterator<[Number, Number]> {
73        return this
74    }
75
76    override next(): IteratorResult<[Number, Number]> {
77        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
78            return new IteratorResult<[Number, Number]>()
79        }
80        return new IteratorResult<[Number, Number]>(
81            false,
82            [new Number(this.idx), new Number(this.parent.getUnsafe(this.idx++))]
83        )
84    }
85}
86
87/**
88 * JS Uint8ClampedArray API-compatible class
89 */
90export class Uint8ClampedArray implements Iterable<Number>, ArrayLike<Number> {
91    public static readonly BYTES_PER_ELEMENT: number = 1
92
93    /** Underlying Buffer */
94    public readonly buffer: ArrayBufferLike
95
96    internal readonly byteOffsetInt: int
97    internal readonly byteLengthInt: int
98    internal readonly lengthInt: int
99
100    /**
101     * Creates an empty Uint8ClampedArray.
102     */
103    public constructor() {
104        this(0 as int)
105    }
106
107    /**
108     * Creates an Uint8ClampedArray with respect to data accessed via Iterable<Number> interface
109     */
110    public constructor(elements: Iterable<Number>) {
111        const items: Object = elements as Object
112        if (items instanceof ArrayLike) {
113            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
114            this.byteLengthInt = arr.length as int * Uint8ClampedArray.BYTES_PER_ELEMENT as int
115            this.lengthInt = arr.length as int
116            this.buffer = new ArrayBuffer(this.byteLengthInt)
117            this.byteOffsetInt = 0
118            for (let i: int = 0; i < this.lengthInt; ++i) {
119                this.setUnsafe(i, Uint8ClampedArray.clamp(arr.$_get(i).intValue()))
120            }
121        } else {
122            let x = Uint8ClampedArray.from(elements)
123            this.byteLengthInt = x.byteLengthInt
124            this.lengthInt = x.lengthInt
125            this.buffer = x.buffer
126            this.byteOffsetInt = x.byteOffsetInt
127        }
128    }
129
130    /**
131     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
132     *
133     * @param buf data initializer
134     *
135     * @param byteOffset byte offset from begin of the buf
136     *
137     * @param length size of elements of type int in newly created Uint8ClampedArray
138     */
139    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
140        let intByteOffset: int = 0
141        if (byteOffset != undefined) {
142            intByteOffset = byteOffset.intValue()
143            if (intByteOffset < 0) {
144                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
145            }
146        }
147        let intByteLength: int
148        if (buf instanceof ArrayBuffer) {
149            intByteLength = (buf as ArrayBuffer).getByteLength()
150        } else if (buf instanceof SharedArrayBuffer) {
151            intByteLength = (buf as SharedArrayBuffer).getByteLength()
152        } else {
153            throw new Error("unexpected type of ArrayBufferLike")
154        }
155        intByteLength = intByteLength - intByteOffset
156        if (intByteLength < 0) {
157            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
158        }
159
160        let intLength: int
161        if (length != undefined) {
162            intLength = length.intValue()
163            if (intLength > intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int) {
164                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
165            }
166        } else {
167            intLength = intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int
168        }
169        if (intLength < 0) {
170            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
171        }
172        if (intLength < intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int) {
173            intByteLength = intLength * Uint8ClampedArray.BYTES_PER_ELEMENT as int
174        }
175        this.byteLengthInt = intByteLength
176        this.byteOffsetInt = intByteOffset
177        this.lengthInt = intLength
178        this.buffer = buf
179    }
180
181    /**
182     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
183     *
184     * @param buf data initializer
185     *
186     * @param byteOffset byte offset from begin of the buf
187     */
188    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
189        this(buf, byteOffset, undefined)
190    }
191
192    /**
193     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
194     *
195     * @param buf data initializer
196     *
197     * @param byteOffset byte offset from begin of the buf
198     *
199     * @param length size of elements of type int in newly created Uint8ClampedArray
200     */
201    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
202        this(buf, new Number(byteOffset), new Number(length))
203    }
204
205    /**
206     * Creates an Uint8ClampedArray with respect to buf and byteOffset.
207     *
208     * @param buf data initializer
209     *
210     * @param byteOffset byte offset from begin of the buf
211     */
212    public constructor(buf: ArrayBufferLike, byteOffset: number) {
213        this(buf, new Number(byteOffset), undefined)
214    }
215
216    /**
217     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
218     *
219     * @param buf data initializer
220     *
221     * @param byteOffset byte offset from begin of the buf
222     *
223     * @param length size of elements of type int in newly created Uint8ClampedArray
224     */
225    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
226        this(buf, new Number(byteOffset), new Number(length))
227    }
228
229    /**
230     * Creates an Uint8ClampedArray with respect to buf and byteOffset.
231     *
232     * @param buf data initializer
233     *
234     * @param byteOffset byte offset from begin of the buf
235     */
236    public constructor(buf: ArrayBufferLike, byteOffset: int) {
237        this(buf, new Number(byteOffset), undefined)
238    }
239
240    /**
241     * Creates an Uint8ClampedArray with respect to buf.
242     *
243     * @param buf data initializer
244     */
245    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
246        if (buf instanceof ArrayBuffer) {
247            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
248            if (this.byteLengthInt % Uint8ClampedArray.BYTES_PER_ELEMENT as int != 0) {
249               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8ClampedArray.BYTES_PER_ELEMENT")
250            }
251            this.lengthInt = this.byteLengthInt / Uint8ClampedArray.BYTES_PER_ELEMENT as int
252            this.buffer = buf as ArrayBuffer
253            this.byteOffsetInt = 0
254        } else if (buf instanceof SharedArrayBuffer) {
255            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
256            if (this.byteLengthInt % Uint8ClampedArray.BYTES_PER_ELEMENT as int != 0) {
257               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8ClampedArray.BYTES_PER_ELEMENT")
258            }
259            this.lengthInt = this.byteLengthInt / Uint8ClampedArray.BYTES_PER_ELEMENT as int
260            this.buffer = buf as SharedArrayBuffer
261            this.byteOffsetInt = 0
262        } else if (buf instanceof ArrayLike) {
263            // NOTE (ikorobkov): dealing with this overload is tricky
264            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
265            let arr = Array.from<Number>((buf as ArrayLike<Number>))
266            this.byteLengthInt = arr.length as int * Uint8ClampedArray.BYTES_PER_ELEMENT as int
267            this.lengthInt = arr.length as int
268            this.buffer = new ArrayBuffer(this.byteLengthInt)
269            this.byteOffsetInt = 0
270            for (let i: int = 0; i < this.lengthInt; ++i) {
271                this.setUnsafe(i, Uint8ClampedArray.clamp(arr.$_get(i).intValue()))
272            }
273        } else {
274            throw new Error("unexpected type of buf")
275        }
276    }
277
278    /**
279     * Creates an Uint8ClampedArray with respect to length.
280     *
281     * @param length data initializer
282     */
283    public constructor(length: int) {
284        if (length < 0) {
285            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
286        }
287        this.lengthInt = length
288        this.byteLengthInt = length * Uint8ClampedArray.BYTES_PER_ELEMENT as int
289        this.byteOffsetInt = 0
290        this.buffer = new ArrayBuffer(this.byteLengthInt)
291    }
292
293    /**
294     * Creates an Uint8ClampedArray with respect to length.
295     *
296     * @param length data initializer
297     */
298    public constructor(length: number) {
299        this(length as int)
300    }
301
302    /**
303     * Creates a copy of Uint8ClampedArray.
304     *
305     * @param other data initializer
306     */
307    public constructor(other: Uint8ClampedArray) {
308        if (other.buffer instanceof ArrayBuffer) {
309            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
310        } else if (other.buffer instanceof SharedArrayBuffer) {
311            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
312        } else {
313            throw new Error("unexpected type of buffer")
314        }
315        this.byteLengthInt = other.byteLength as int
316        this.lengthInt = other.length as int
317        this.byteOffsetInt = 0
318    }
319
320    /**
321     * Creates an Uint8ClampedArray from number[]
322     */
323    public constructor(numbers: number[]) {
324        this(numbers.length)
325        for (let i: int = 0; i < this.lengthInt; ++i) {
326            this.setUnsafeClamp(i, numbers[i] as int)
327        }
328    }
329
330    /**
331     * Creates an Uint8ClampedArray from int[]
332     */
333    public constructor(numbers: int[]) {
334        this(numbers.length)
335        for (let i: int = 0; i < this.lengthInt; ++i) {
336            this.setUnsafeClamp(i, numbers[i] as int)
337        }
338    }
339
340    /**
341     * Iteratorable interface implementation
342     *
343     * @returns iterator over all elements
344     */
345    public override $_iterator(): IterableIterator<Number> {
346         return this.values()
347    }
348
349    /**
350     * Returns an instance of primitive type at passed index.
351     *
352     * @param index index to look at
353     *
354     * @returns a primitive at index
355     */
356    public at(index: number): Number | undefined {
357        return this.at(index as int)
358    }
359
360    /**
361     * Returns an instance of primitive type at passed index if index is correct.
362     *
363     * @param index index to look at
364     *
365     * @returns a primitive at index
366     */
367    public at(index: int): Number | undefined {
368        let k: int
369        if (index >= 0) {
370            k = index
371        } else {
372            k = this.lengthInt + index
373        }
374        if (k < 0 || k >= this.lengthInt) {
375            return undefined
376        }
377        return new Number(this.getUnsafe(k))
378    }
379
380    /**
381     * Returns an instance of number at passed index.
382     *
383     * @param index index to look at
384     *
385     * @returns a primitive at index
386     */
387    public override $_get(index: number): Number {
388        return this.$_get(index as int) as Number
389    }
390
391    /**
392     * Returns an instance of number at passed index.
393     *
394     * @param index index to look at
395     *
396     * @returns a primitive at index
397     */
398    public $_get(i: int): number {
399        if (i < 0 || i >= this.lengthInt) {
400            throw new RangeError("invalid offset")
401        }
402        return this.getUnsafe(i) as number
403    }
404
405    /**
406     * Assigns val as element on index.
407     *
408     * @param val value to set
409     *
410     * @param index index to change
411     */
412    public $_set(index: number, val: number): void {
413        this.$_set(index as int, val)
414    }
415
416    /**
417     * Assigns val as element on index.
418     *
419     * @param val value to set
420     *
421     * @param index index to change
422     */
423    public $_set(index: int, val: number): void {
424        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
425        if (index < 0 || index >= this.lengthInt) {
426            throw new RangeError("invalid index")
427        }
428        this.setUnsafeClamp(index, val as int)
429    }
430
431    /**
432     * Assigns val as element on index.
433     *
434     * @param val value to set
435     *
436     * @param index index to change
437     */
438    public $_set(index: number, val: int): void {
439        this.$_set(index as int, val)
440    }
441
442    /**
443     * Assigns val as element on index.
444     *
445     * @param val value to set
446     *
447     * @param index index to change
448     */
449    public $_set(index: int, val: int): void {
450        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
451        if (index < 0 || index >= this.lengthInt) {
452            throw new RangeError("invalid index")
453        }
454        this.setUnsafeClamp(index, val)
455    }
456
457    /**
458     * Makes a copy of internal elements to targetPos from startPos to endPos.
459     *
460     * @param target insert index to place copied elements
461     *
462     * @param start start index to begin copy from
463     *
464     * @param end last index to end copy from, excluded
465     *
466     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
467     */
468    public copyWithin(target: number, start: number, end?: number): Uint8ClampedArray {
469        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
470    }
471
472    /**
473     * Makes a copy of internal elements to targetPos from startPos to endPos.
474     *
475     * @param target insert index to place copied elements
476     *
477     * @param start start index to begin copy from
478     *
479     * @param end last index to end copy from, excluded
480     *
481     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
482     */
483    public copyWithin(target: int, start: number, end?: number): Uint8ClampedArray {
484        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
485    }
486
487    /**
488     * Makes a copy of internal elements to targetPos from startPos to endPos.
489     *
490     * @param target insert index to place copied elements
491     *
492     * @param start start index to begin copy from
493     *
494     * @param end last index to end copy from, excluded
495     *
496     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
497     */
498    public copyWithin(target: number, start: int, end?: number): Uint8ClampedArray {
499        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
500    }
501
502    /**
503     * Makes a copy of internal elements to targetPos from startPos to endPos.
504     *
505     * @param target insert index to place copied elements
506     *
507     * @param start start index to begin copy from
508     *
509     * @param end last index to end copy from, excluded
510     *
511     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
512     */
513    public copyWithin(target: int, start: int, end?: number): Uint8ClampedArray {
514        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
515    }
516
517    /**
518     * Makes a copy of internal elements to targetPos from startPos to endPos.
519     *
520     * @param insert insert index to place copied elements
521     *
522     * @param start start index to begin copy from
523     *
524     * @param end last index to end copy from, excluded
525     *
526     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
527     */
528    public copyWithin(target: int, start: int, end: int): Uint8ClampedArray {
529        let toPos = normalizeIndex(target, this.lengthInt)
530        let fromPos = normalizeIndex(start, this.lengthInt)
531        const finalPos = normalizeIndex(end, this.lengthInt)
532        let count: int = finalPos - fromPos
533        if (count > (this.lengthInt - toPos)) {
534            count = this.lengthInt - toPos
535        }
536        let direction: int = 1
537        if ((fromPos < toPos) && (toPos < fromPos + count)) {
538            fromPos = fromPos + count - 1
539            toPos   = toPos   + count - 1
540            direction = -1
541        }
542        while (count > 0) {
543            const value = this.getUnsafe(fromPos)
544            this.setUnsafe(toPos, value)
545            fromPos = fromPos + direction
546            toPos = toPos + direction
547            --count
548        }
549        return this
550    }
551
552    /**
553     * Makes a copy of internal elements to targetPos from begin to end of Uint8ClampedArray.
554     *
555     * @param target insert index to place copied elements
556     *
557     * See rules of parameters normalization:
558     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
559     */
560    public copyWithin(target: number): Uint8ClampedArray {
561        return this.copyWithin(target as int)
562    }
563
564    /**
565     * Makes a copy of internal elements to targetPos from begin to end of Uint8ClampedArray.
566     *
567     * @param insert insert index to place copied elements
568     *
569     * See rules of parameters normalization:
570     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
571     */
572    public copyWithin(target: int): Uint8ClampedArray {
573        return this.copyWithin(target, 0, this.lengthInt)
574    }
575
576    /**
577     * Returns an array of key, value pairs for every entry in the Uint8ClampedArray
578     *
579     * @returns key, value pairs for every entry in the array
580     */
581    public entries(): IterableIterator<[Number, Number]> {
582        return new Uint8ClampedArrayIteratorEntries(this)
583    }
584
585    /**
586     * Fills the Uint8ClampedArray with specified value
587     *
588     * @param value new value
589     *
590     * @returns modified Uint8ClampedArray
591     */
592    public fill(value: number, start?: number, end?: number): Uint8ClampedArray {
593        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
594        return this
595    }
596
597    /**
598     * Fills the Uint8ClampedArray with specified value
599     *
600     * @param value new value
601     *
602     * @returns modified Uint8ClampedArray
603     */
604    public fill(value: number, start: int, end?: number): Uint8ClampedArray {
605        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
606        return this
607    }
608
609    /**
610     * Fills the Uint8ClampedArray with specified value
611     *
612     * @param value new value
613     *
614     * @returns modified Uint8ClampedArray
615     */
616    public fill(value: number, start: int, end: number): Uint8ClampedArray {
617        this.fill(value as int, start as int, end as int)
618        return this
619    }
620
621    /**
622     * Fills the Uint8ClampedArray with specified value
623     *
624     * @param value new value
625     *
626     * @returns modified Uint8ClampedArray
627     */
628    public fill(value: number, start: number, end: int): Uint8ClampedArray {
629        this.fill(value as int, start as int, end as int)
630        return this
631    }
632
633    /**
634     * Fills the Uint8ClampedArray with specified value
635     *
636     * @param value new value
637     *
638     * @returns modified Uint8ClampedArray
639     */
640    public fill(value: number, start: int, end: int): Uint8ClampedArray {
641        this.fill(value as int, start as int, end as int)
642        return this
643    }
644
645    /**
646     * Fills the Uint8ClampedArray with specified value
647     *
648     * @param value new value
649     *
650     * @returns modified Uint8ClampedArray
651     */
652    public fill(value: int, start?: number, end?: number): Uint8ClampedArray {
653        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
654        return this
655    }
656
657    /**
658     * Fills the Uint8ClampedArray with specified value
659     *
660     * @param value new value
661     *
662     * @returns modified Uint8ClampedArray
663     */
664    public fill(value: int, start: int, end?: number): Uint8ClampedArray {
665        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
666        return this
667    }
668
669    /**
670     * Fills the Uint8ClampedArray with specified value
671     *
672     * @param value new value
673     *
674     * @returns modified Uint8ClampedArray
675     */
676    public fill(value: int, start: int, end: number): Uint8ClampedArray {
677        this.fill(value, start as int, end as int)
678        return this
679    }
680
681    /**
682     * Fills the Uint8ClampedArray with specified value
683     *
684     * @param value new value
685     *
686     * @returns modified Uint8ClampedArray
687     */
688    public fill(value: int, start: number, end: int): Uint8ClampedArray {
689        this.fill(value, start as int, end as int)
690        return this
691    }
692
693    /**
694     * Fills the Uint8ClampedArray with specified value
695     *
696     * @param value new value
697     *
698     * @returns modified Uint8ClampedArray
699     */
700    public fill(value: int, start: int, end: int): Uint8ClampedArray {
701        value = Uint8ClampedArray.clamp(value)
702        const k = normalizeIndex(start, this.lengthInt)
703        const finalPos = normalizeIndex(end, this.lengthInt)
704        for (let i: int = k; i < finalPos; ++i) {
705            this.setUnsafe(i, value)
706        }
707        return this
708    }
709
710    /**
711     * Assigns val as element on index.
712     *
713     * @param val value to set
714     *
715     * @param index index to change
716     */
717    public set(insertPos: number, val: number): void {
718        this.$_set(insertPos as int, val)
719    }
720
721    /**
722     * Assigns val as element on index.
723     *
724     * @param val value to set
725     *
726     * @param index index to change
727     */
728    public set(insertPos: int, val: number): void {
729        this.$_set(insertPos as int, val)
730    }
731
732    /**
733     * Assigns val as element on index.
734     *
735     * @param val value to set
736     *
737     * @param index index to change
738     */
739    public set(insertPos: number, val: int): void {
740        this.$_set(insertPos as int, val)
741    }
742
743    /**
744     * Assigns val as element on index.
745     *
746     * @param val value to set
747     *
748     * @param index index to change
749     */
750    public set(insertPos: int, val: int): void {
751        this.$_set(insertPos as int, val)
752    }
753
754    /**
755     * Copies all elements of arr to the current Uint8ClampedArray starting from insertPos.
756     *
757     * @param arr array to copy data from
758     *
759     * @param insertPos start index where data from arr will be inserted
760     *
761     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
762     */
763    public set(arr: number[], insertPos1: number): void {
764        const insertPos = insertPos1 as int
765        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
766            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8ClampedArray.length")
767        }
768        for (let i = 0; i < arr.length; i++) {
769            this.setUnsafeClamp(insertPos as int + i as int, arr[i] as int)
770        }
771    }
772
773    /**
774     * Copies all elements of arr to the current Uint8ClampedArray starting from insertPos.
775     *
776     * @param arr array to copy data from
777     *
778     * @param insertPos start index where data from arr will be inserted
779     *
780     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
781     */
782    public set(arr: int[], insertPos: int): void {
783        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
784            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8ClampedArray.length")
785        }
786        for (let i = 0; i < arr.length; i++) {
787            this.setUnsafeClamp(insertPos + i, arr[i])
788        }
789    }
790
791    /**
792     * Copies all elements of arr to the current Uint8ClampedArray.
793     *
794     * @param arr array to copy data from
795     */
796    public set(arr: number[]): void {
797        this.set(arr, 0)
798    }
799
800    /**
801     * Copies all elements of arr to the current Uint8ClampedArray.
802     *
803     * @param arr array to copy data from
804     */
805    public set(arr: int[]): void {
806        this.set(arr, 0)
807    }
808
809    /**
810     * Copies elements from an ArrayLike object to the Uint8ClampedArray.
811     *
812     * @param array An ArrayLike object containing the elements to copy.
813     *
814     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
815     */
816    public set(array: ArrayLike<number>, offset: number = 0): void {
817        const insertPos = offset as int
818        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
819            throw new RangeError("offset is out of bounds")
820        }
821        for (let i = 0; i < array.length; i++) {
822            this.setUnsafeClamp(insertPos as int + i as int, array[i] as int)
823        }
824    }
825
826    /**
827     * Returns a new array from a set of elements.
828     *
829     * @param items a set of elements to include in the new array object.
830     *
831     * @returns new Uint8ClampedArray
832     */
833    public static of(...items: number[]): Uint8ClampedArray {
834        let res = new Uint8ClampedArray(items.length as int)
835        for (let i: int = 0; i < items.length; i++) {
836            res.setUnsafeClamp(i, items[i] as int)
837        }
838        return res
839    }
840
841    /**
842     * Returns a new array from a set of elements.
843     *
844     * @param items a set of elements to include in the new array object.
845     *
846     * @returns new Uint8ClampedArray
847     */
848    public static of(...items: int[]): Uint8ClampedArray {
849        let res = new Uint8ClampedArray(items.length as int)
850        for (let i: int = 0; i < items.length; i++) {
851            res.setUnsafeClamp(i, items[i])
852        }
853        return res
854    }
855
856    /**
857     * Returns a new array from a set of elements.
858     *
859     * @param items a set of elements to include in the new array object.
860     *
861     * @returns new Uint8ClampedArray
862     */
863    public static of(...items: short[]): Uint8ClampedArray {
864        let res = new Uint8ClampedArray(items.length as int)
865        for (let i: int = 0; i < items.length; i++) {
866            res.setUnsafeClamp(i, items[i] as int)
867        }
868        return res
869    }
870
871    /**
872     * Returns a new array from a set of elements.
873     *
874     * @param items a set of elements to include in the new array object.
875     *
876     * @returns new Uint8ClampedArray
877     */
878    public static of(): Uint8ClampedArray {
879        return new Uint8ClampedArray(0 as int)
880    }
881
882    /**
883     * Creates an array from an array-like or iterable object.
884     *
885     * @param arrayLike An array-like or iterable object to convert to an array.
886     *
887     * @returns new Uint8ClampedArray
888     */
889    public static from(arr: ArrayLike<number>): Uint8ClampedArray {
890        return Uint8ClampedArray.from<number>(arr, (x: number, k: number): number => x)
891    }
892
893    /**
894     * Creates an array from an array-like or iterable object.
895     *
896     * @param arrayLike An array-like or iterable object to convert to an array.
897     *
898     * @param mapfn A mapping function to call on every element of the array.
899     *
900     * @returns new Uint8ClampedArray
901     */
902    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint8ClampedArray {
903        if (mapfn == undefined) {
904            mapfn = (v: number, k: number): number => { return v }
905        }
906
907        let iter = arrayLike.$_iterator()
908        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
909        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
910        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
911        //  we can make one pass through the iterator without the need for memory reallocation.
912        const maybeLength = tryGetIteratorLength(arrayLike)
913        if (maybeLength) {
914            const result = new Uint8ClampedArray(maybeLength)
915            for (let i = 0; i < maybeLength; ++i) {
916                const x = iter.next()
917                if (x.done) {
918                    return new Uint8ClampedArray(result.buffer, 0, i)
919                }
920                result.setUnsafeClamp(i, (mapfn)!(x.value!, i) as int)
921            }
922            return result
923        }
924
925        // NOTE (templin.konstantin): Create builtin array as buffer
926        let temp = new Uint8ClampedArray(6)
927        let index = new int[1]
928        index[0] = 0
929
930        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
931            if (index[0] + 1 > temp.lengthInt) {
932                // NOTE (templin.konstantin): Progressive reallocation
933                const curLength = (temp.buffer as Buffer).getByteLength()
934                const tb = new ArrayBuffer(curLength * 2)
935                for (let i = 0; i < curLength; ++i) {
936                    tb.set(i, (temp.buffer as Buffer).at(i))
937                }
938                temp = new Uint8ClampedArray(tb)
939            }
940            temp.setUnsafeClamp(index[0], (mapfn)!(x, index[0]) as int)
941            index[0]++
942        })
943
944        return new Uint8ClampedArray(temp.buffer, 0, index[0])
945    }
946
947    /**
948     * Creates an array from an array-like or iterable object.
949     *
950     * @param arrayLike An array-like or iterable object to convert to an array.
951     *
952     * @param mapfn A mapping function to call on every element of the array.
953     *
954     * @returns new Uint8ClampedArray
955     */
956    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint8ClampedArray {
957        let res = new Uint8ClampedArray(arrayLike.length)
958        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
959        const idx = new int[1]
960        idx[0] = 0
961        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
962            res.setUnsafeClamp(idx[0], mapfn(x as T, idx[0] as number) as int)
963            idx[0] += 1
964        })
965        return res
966    }
967
968    /**
969     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
970     *
971     * @param searchElement The element to search for
972     *
973     * @param fromIndex The position in this array at which to begin searching for searchElement
974     *
975     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
976     */
977    public includes(searchElement: number, fromIndex?: number): boolean {
978        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
979    }
980
981    /**
982     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
983     *
984     * @param searchElement The element to search for
985     *
986     * @param fromIndex The position in this array at which to begin searching for searchElement
987     *
988     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
989     */
990    public includes(searchElement: int, fromIndex: int): boolean {
991        return this.indexOf(searchElement as int, fromIndex) != -1
992    }
993
994    /**
995     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
996     *
997     * @param searchElement The element to search for
998     *
999     * @param fromIndex The position in this array at which to begin searching for searchElement
1000     *
1001     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
1002     */
1003    public includes(searchElement: int): boolean {
1004        return this.indexOf(searchElement as int, 0) != -1
1005    }
1006
1007    /**
1008     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
1009     *
1010     * @param searchElement The value to locate in the array.
1011     *
1012     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1013     *  search starts at index 0.
1014     *
1015     * @returns index of element if it presents, -1 otherwise
1016     */
1017    public indexOf(searchElement: number, fromIndex?: number): number {
1018        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
1019    }
1020
1021    /**
1022     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
1023     *
1024     * @param searchElement The value to locate in the array.
1025     *
1026     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1027     *  search starts at index 0.
1028     *
1029     * @returns index of element if it presents, -1 otherwise
1030     */
1031    public indexOf(searchElement: number, fromIndex: int): number {
1032        if (isNaN(searchElement)) {
1033            return -1
1034        }
1035        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
1036        for (let i = fromIndex; i < this.lengthInt; i++) {
1037            if (this.getUnsafe(i) as number == searchElement) {
1038                return i
1039            }
1040        }
1041        return -1
1042    }
1043
1044    /**
1045     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
1046     *
1047     * @param searchElement The value to locate in the array.
1048     *
1049     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1050     *  search starts at index 0.
1051     *
1052     * @returns index of element if it presents, -1 otherwise
1053     */
1054    public indexOf(searchElement: int, fromIndex: int): number {
1055        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
1056        for (let i = fromIndex; i < this.lengthInt; i++) {
1057            if (this.getUnsafe(i) == searchElement) {
1058                return i
1059            }
1060        }
1061        return -1
1062
1063    }
1064
1065    /**
1066     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
1067     *
1068     * @param searchElement The value to locate in the array.
1069     *
1070     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1071     *  search starts at index 0.
1072     *
1073     * @returns index of element if it presents, -1 otherwise
1074     */
1075    public indexOf(searchElement: int): number {
1076        return this.indexOf(searchElement, 0)
1077    }
1078
1079    /**
1080     * Adds all the elements of an array separated by the specified separator string
1081     *
1082     * @param separator A string used to separate one element of an array from the next in the
1083     * resulting String. If omitted, the array elements are separated with a comma
1084     *
1085     * @returns joined representation
1086     */
1087    public join(separator?: String): string {
1088        if (separator == undefined) {
1089            return this.join(",")
1090        }
1091        let res: StringBuilder = new StringBuilder("")
1092        for (let i = 0; i < this.lengthInt - 1; i++) {
1093            res.append(this.getUnsafe(i) as number)
1094            res.append(separator)
1095        }
1096        if (this.lengthInt > 0) {
1097            res.append(this.getUnsafe(this.lengthInt - 1) as number)
1098        }
1099        return res.toString()
1100    }
1101
1102    /**
1103     * Returns an list of keys in Uint8ClampedArray
1104     *
1105     * @returns iterator over keys
1106     */
1107    public keys(): IterableIterator<number> {
1108        return new Uint8ClampedArrayIteratorKeys(this)
1109    }
1110
1111    /**
1112     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1113     *
1114     * @param searchElement The value to locate in the array.
1115     *
1116     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1117     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1118     *
1119     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1120     */
1121    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
1122        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
1123    }
1124
1125    /**
1126     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1127     *
1128     * @param searchElement The value to locate in the array.
1129     *
1130     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1131     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1132     *
1133     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1134     */
1135    public lastIndexOf(searchElement: number): number {
1136        return this.lastIndexOf(searchElement, this.lengthInt - 1)
1137    }
1138
1139    /**
1140     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1141     *
1142     * @param searchElement The value to locate in the array.
1143     *
1144     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1145     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1146     *
1147     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1148     */
1149    public lastIndexOf(searchElement: number, fromIndex: int): number {
1150        if (isNaN(searchElement)) {
1151            return -1
1152        }
1153        if (this.lengthInt == 0) {
1154            return -1
1155        }
1156        let k: int = this.lengthInt + fromIndex
1157        if (fromIndex >= 0) {
1158            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
1159        }
1160        while (k >= 0) {
1161            if (this.getUnsafe(k) as number == searchElement) {
1162                return k
1163            }
1164            k--
1165        }
1166        return -1
1167    }
1168
1169    /**
1170     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1171     *
1172     * @param searchElement The value to locate in the array.
1173     *
1174     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1175     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1176     *
1177     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1178     */
1179    public lastIndexOf(searchElement: int, fromIndex: int): number {
1180        if (this.lengthInt == 0) {
1181            return -1
1182        }
1183        let k: int = this.lengthInt + fromIndex
1184        if (fromIndex >= 0) {
1185            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
1186        }
1187        while (k >= 0) {
1188            if (this.getUnsafe(k) == searchElement) {
1189                return k
1190            }
1191            k--
1192        }
1193        return -1
1194    }
1195
1196    /**
1197     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1198     *
1199     * @param searchElement The value to locate in the array.
1200     *
1201     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1202     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1203     *
1204     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1205     */
1206    public lastIndexOf(searchElement: int): number {
1207        return this.lastIndexOf(searchElement, this.lengthInt - 1)
1208    }
1209
1210   /**
1211    * Creates a new Uint8ClampedArray using initializer
1212    *
1213    * @param data initializer
1214    *
1215    * @returns a new Uint8ClampedArray from data
1216    */
1217    public of(...data: number[]): Uint8ClampedArray {
1218        throw new Error("Uint8ClampedArray.of: not implemented")
1219    }
1220
1221    /**
1222     * Creates a new Uint8ClampedArray using reversed data from the current one
1223     *
1224     * @returns a new Uint8ClampedArray using reversed data from the current one
1225     */
1226    public reverse(): Uint8ClampedArray {
1227        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
1228            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
1229            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
1230            this.setUnsafe(i, tmp)
1231        }
1232        return this
1233    }
1234
1235    /**
1236     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1237     *
1238     * @param begin start index to be taken into slice
1239     *
1240     * @param end last index to be taken into slice
1241     *
1242     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1243     *
1244     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1245     */
1246    public slice(begin?: number, end?: number): Uint8ClampedArray {
1247        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
1248    }
1249
1250    /**
1251     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1252     *
1253     * @param begin start index to be taken into slice
1254     *
1255     * @param end last index to be taken into slice
1256     *
1257     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1258     *
1259     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1260     */
1261    public slice(begin: number, end: number): Uint8ClampedArray {
1262        return this.slice(begin as int, end as int)
1263    }
1264
1265    /**
1266     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1267     *
1268     * @param begin start index to be taken into slice
1269     *
1270     * @param end last index to be taken into slice
1271     *
1272     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1273     *
1274     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1275     */
1276    public slice(begin: number, end: int): Uint8ClampedArray {
1277        return this.slice(begin as int, end as int)
1278    }
1279
1280    /**
1281     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1282     *
1283     * @param begin start index to be taken into slice
1284     *
1285     * @param end last index to be taken into slice
1286     *
1287     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1288     *
1289     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1290     */
1291    public slice(begin: int, end: number): Uint8ClampedArray {
1292        return this.slice(begin as int, end as int)
1293    }
1294
1295    /**
1296     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1297     *
1298     * @param begin start index to be taken into slice
1299     *
1300     * @param end last index to be taken into slice
1301     *
1302     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1303     *
1304     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1305     */
1306    public slice(begin: int, end: int): Uint8ClampedArray {
1307        const len: int = this.lengthInt
1308        const relStart = normalizeIndex(begin, len)
1309        const relEnd = normalizeIndex(end, len)
1310        let count = relEnd - relStart
1311        if (count < 0) {
1312            count = 0
1313        }
1314        if (this.buffer instanceof ArrayBuffer) {
1315            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, relEnd * Uint8ClampedArray.BYTES_PER_ELEMENT as int) as ArrayBuffer
1316            return new Uint8ClampedArray(buf)
1317        } else if (this.buffer instanceof SharedArrayBuffer) {
1318            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, relEnd * Uint8ClampedArray.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
1319            return new Uint8ClampedArray(buf)
1320        } else {
1321            throw new Error("unexpected type of buffer")
1322        }
1323    }
1324
1325    /**
1326     * Creates a slice of current Uint8ClampedArray using range [begin, this.lengthInt).
1327     *
1328     * @param begin start index to be taken into slice
1329     *
1330     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin, this.lengthInt)
1331     */
1332    public slice(begin: number): Uint8ClampedArray {
1333        return this.slice(begin as int)
1334    }
1335
1336    /**
1337     * Creates a slice of current Uint8ClampedArray using range [begin, this.lengthInt).
1338     *
1339     * @param begin start index to be taken into slice
1340     *
1341     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin, this.lengthInt)
1342     */
1343    public slice(begin: int): Uint8ClampedArray {
1344        return this.slice(begin, this.lengthInt)
1345    }
1346
1347    /**
1348     * Sorts in-place
1349     *
1350     * @param compareFn comparator —  used to determine the order of the elements.
1351     * compareFn returns a negative value if first argument is less than second argument,
1352     * zero if they're equal and a positive value otherwise.
1353     * If omitted, the elements are sorted in ascending order.
1354     *
1355     * @returns sorted Uint8ClampedArray
1356     */
1357    public sort(compareFn?: (a: number, b: number) => number): this {
1358        let arr: int[] = new int[this.lengthInt]
1359        for (let i = 0; i < this.lengthInt; ++i) {
1360            arr[i] = this.getUnsafe(i)
1361        }
1362        let cmp = (l: int, r: int): number => {
1363                return (l - r) as number
1364            }
1365        if (compareFn != undefined) {
1366            cmp = (l: int, r: int): number => {
1367                return compareFn!(l as number, r as number)
1368            }
1369        }
1370        sort(arr, cmp)
1371        for (let i = 0; i < this.lengthInt; ++i) {
1372            this.setUnsafe(i, arr[i])
1373        }
1374        return this
1375    }
1376
1377    /**
1378     * Sorts in-place
1379     *
1380     * @param compareFn comparator —  used to determine the order of the elements.
1381     * compareFn returns a negative value if first argument is less than second argument,
1382     * zero if they're equal and a positive value otherwise.
1383     *
1384     * @returns sorted Uint8ClampedArray
1385     */
1386    public sort(compareFn: (a: number) => number): this {
1387        let cmp = (a: number, b: number) => { return compareFn(a)}
1388        this.sort(cmp)
1389        return this
1390    }
1391
1392    /**
1393     * Sorts in-place
1394     *
1395     * @param fn compareFn —  used to determine the order of the elements.
1396     * compareFn returns a negative value if first argument is less than second argument,
1397     * zero if they're equal and a positive value otherwise.
1398     *
1399     * @returns sorted Uint8ClampedArray
1400     */
1401    public sort(compareFn: () => number): this {
1402        let cmp = (a: number, b: number) => { return compareFn()}
1403        this.sort(cmp)
1404        return this
1405    }
1406    /**
1407     * Creates a Uint8ClampedArray with the same underlying Buffer
1408     *
1409     * @param begin start index, inclusive
1410     *
1411     * @param end last index, exclusive
1412     *
1413     * @returns new Uint8ClampedArray with the same underlying Buffer
1414     */
1415    public subarray(begin?: number, end?: number): Uint8ClampedArray {
1416        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
1417    }
1418
1419    /**
1420     * Creates a Uint8ClampedArray with the same underlying Buffer
1421     *
1422     * @param begin start index, inclusive
1423     *
1424     * @param end last index, exclusive
1425     *
1426     * @returns new Uint8ClampedArray with the same underlying Buffer
1427     */
1428    public subarray(begin: number, end: number): Uint8ClampedArray {
1429        return this.subarray(begin as int, end as int)
1430    }
1431
1432    /**
1433     * Creates a Uint8ClampedArray with the same underlying Buffer
1434     *
1435     * @param begin start index, inclusive
1436     *
1437     * @param end last index, exclusive
1438     *
1439     * @returns new Uint8ClampedArray with the same underlying Buffer
1440     */
1441    public subarray(begin: number, end: int): Uint8ClampedArray {
1442        return this.subarray(begin as int, end as int)
1443    }
1444
1445    /**
1446     * Creates a Uint8ClampedArray with the same underlying Buffer
1447     *
1448     * @param begin start index, inclusive
1449     *
1450     * @param end last index, exclusive
1451     *
1452     * @returns new Uint8ClampedArray with the same underlying Buffer
1453     */
1454    public subarray(begin: int, end: number): Uint8ClampedArray {
1455        return this.subarray(begin as int, end as int)
1456    }
1457
1458    /**
1459     * Creates a Uint8ClampedArray with the same underlying Buffer
1460     *
1461     * @param begin start index, inclusive
1462     *
1463     * @param end last index, exclusive
1464     *
1465     * @returns new Uint8ClampedArray with the same underlying Buffer
1466     */
1467    public subarray(begin: int, end: int): Uint8ClampedArray {
1468        const len: int = this.lengthInt
1469        const relStart = normalizeIndex(begin, len)
1470        const relEnd = normalizeIndex(end, len)
1471        let count = relEnd - relStart
1472        if (count < 0) {
1473            count = 0
1474        }
1475        return new Uint8ClampedArray(this.buffer, relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, count)
1476    }
1477
1478    /**
1479     * Creates a Uint8ClampedArray with the same Buffer
1480     *
1481     * @param begin start index, inclusive
1482     *
1483     * @returns new Uint8ClampedArray with the same Buffer
1484     */
1485    public subarray(begin: number): Uint8ClampedArray {
1486        return this.subarray(begin as int, this.lengthInt)
1487    }
1488
1489    /**
1490     * Creates a Uint8ClampedArray with the same Buffer
1491     *
1492     * @param begin start index, inclusive
1493     *
1494     * @returns new Uint8ClampedArray with the same Buffer
1495     */
1496    public subarray(begin: int): Uint8ClampedArray {
1497        return this.subarray(begin, this.lengthInt)
1498    }
1499
1500    /**
1501     * Converts Uint8ClampedArray to a string with respect to locale
1502     *
1503     * @param locales
1504     *
1505     * @param options
1506     *
1507     * @returns string representation
1508     */
1509    public toLocaleString(locales: Object, options: Object): string {
1510        throw new Error("Uint8ClampedArray.toLocaleString: not implemented")
1511    }
1512
1513    /**
1514     * Converts Uint8ClampedArray to a string with respect to locale
1515     *
1516     * @param locales
1517     *
1518     * @returns string representation
1519     */
1520    public toLocaleString(locales: Object): string {
1521        return this.toLocaleString(new Object(), new Object())
1522    }
1523
1524    /**
1525     * Converts Uint8ClampedArray to a string with respect to locale
1526     *
1527     * @returns string representation
1528     */
1529    public toLocaleString(): string {
1530        let res: StringBuilder = new StringBuilder("")
1531        for (let i = 0; i < this.lengthInt - 1; ++i) {
1532            res.append((this.getUnsafe(i) as Number).toLocaleString())
1533            res.append(",")
1534        }
1535        if (this.lengthInt > 0) {
1536            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
1537        }
1538        return res.toString()
1539    }
1540
1541    /**
1542     * Creates a reversed copy
1543     *
1544     * @returns a reversed copy
1545     */
1546    public toReversed(): Uint8ClampedArray {
1547        return new Uint8ClampedArray(this).reverse()
1548    }
1549
1550    /**
1551     * Creates a sorted copy
1552     *
1553     * @returns a sorted copy
1554     */
1555    public toSorted(): Uint8ClampedArray {
1556        return new Uint8ClampedArray(this).sort()
1557    }
1558
1559    /**
1560     * Returns a string representation of the Uint8ClampedArray
1561     *
1562     * @returns a string representation of the Uint8ClampedArray
1563     */
1564    public override toString(): string {
1565        return this.join(",")
1566    }
1567
1568    /**
1569     * Returns array values iterator
1570     *
1571     * @returns an iterator
1572     */
1573    public values(): IterableIterator<Number> {
1574         return new Uint8ClampedArrayIterator(this)
1575    }
1576
1577    /**
1578     * Creates a copy with replaced value on index
1579     *
1580     * @param index
1581     *
1582     * @param value
1583     *
1584     * @returns an Uint8ClampedArray with replaced value on index
1585     */
1586    public with(index: number, value: number): Uint8ClampedArray {
1587        return this.with(index as int, value as int)
1588    }
1589
1590    /**
1591     * Creates a copy with replaced value on index
1592     *
1593     * @param index
1594     *
1595     * @param value
1596     *
1597     * @returns an Uint8ClampedArray with replaced value on index
1598     */
1599    public with(index: int, value: int): Uint8ClampedArray {
1600        let res = new Uint8ClampedArray(this)
1601        res.setUnsafeClamp(index, value)
1602        return res
1603    }
1604
1605    /// === with element lambda functions ===
1606
1607    /**
1608     * Determines whether the specified callback function returns true for all elements of an array.
1609     *
1610     * @param predicate A function that accepts one argument.
1611     * The every method calls the predicate function for each element in the array until the predicate returns a false,
1612     * or until the end of the array.
1613     *
1614     * @returns true unless predicate function returns a false for an array element,
1615     * in which case false is immediately returned.
1616     */
1617    public every(predicate: (element: number) => boolean): boolean {
1618        return this.every((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element))
1619    }
1620
1621    /**
1622     * creates a new Uint8ClampedArray from current Uint8ClampedArray based on a condition fn
1623     *
1624     * @param fn the condition to apply for each element
1625     *
1626     * @returns a new Uint8ClampedArray with elements from current Uint8ClampedArray that satisfy condition fn
1627     */
1628    public filter(fn: (val: number) => boolean): Uint8ClampedArray {
1629        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
1630            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val) }
1631        return this.filter(newF)
1632    }
1633
1634    /**
1635     * Returns the value of the first element in the array where predicate is true, and undefined
1636     * otherwise
1637     *
1638     * @param predicate find calls predicate once for each element of the array, in ascending
1639     * order, until it finds one where predicate returns true. If such an element is found, find
1640     * immediately returns that element value. Otherwise, find returns undefined
1641     *
1642     * @returns number | undefined
1643     */
1644    public find(predicate: () => boolean): number | undefined {
1645        return this.find((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate())
1646    }
1647
1648    /**
1649     * Returns the value of the first element in the array where predicate is true, and undefined
1650     * otherwise
1651     *
1652     * @param predicate find calls predicate once for each element of the array, in ascending
1653     * order, until it finds one where predicate returns true. If such an element is found, find
1654     * immediately returns that element value. Otherwise, find returns undefined
1655     *
1656     * @returns number | undefined
1657     */
1658    public find(predicate: (value: number) => boolean): number | undefined {
1659        return this.find((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value))
1660    }
1661
1662    /**
1663     * Returns the index of the first element in the array where predicate is true, and -1
1664     * otherwise
1665     *
1666     * @param predicate find calls predicate once for each element of the array, in ascending
1667     * order, until it finds one where predicate returns true. If such an element is found,
1668     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
1669     *
1670     * @returns number
1671     */
1672    public findIndex(predicate: (value: number) => boolean): number {
1673        return this.findIndex((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value)) as number
1674    }
1675
1676    /**
1677     * Finds the last element in the Uint8ClampedArray that satisfies the condition
1678     *
1679     * @param fn condition
1680     *
1681     * @returns the last element that satisfies fn
1682     */
1683    public findLast(fn: (val: number) => boolean): number {
1684        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
1685            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val) }
1686        return this.findLast(newF)
1687    }
1688
1689    /**
1690     * Finds an index of the last element in the Uint8ClampedArray that satisfies the condition
1691     *
1692     * @param fn condition
1693     *
1694     * @returns the index of the last element that satisfies fn, -1 otherwise
1695     */
1696    public findLastIndex(fn: (val: number) => boolean): number {
1697        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
1698            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val) }
1699        return this.findLastIndex(newF) as number
1700    }
1701
1702    /**
1703     * Performs the specified action for each element in Uint8ClampedArray
1704     *
1705     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
1706     * callbackfn function one time for each element in the array.
1707     *
1708     * @returns None
1709     */
1710    public forEach(callbackfn: (val: number) => void): void {
1711        this.forEach((value: number, index: number, array: Uint8ClampedArray): void => callbackfn(value))
1712    }
1713
1714
1715    /**
1716     * Determines whether the specified callback function returns true for any element of an array.
1717     *
1718     * @param predicate A function that accepts one argument.
1719     * The some method calls the predicate function for each element in the array
1720     * until the predicate returns a true or until the end of the array.
1721     *
1722     * @returns false unless predicate function returns true for an array element,
1723     * in which case true is immediately returned.
1724     */
1725    public some(predicate: (element: number) => boolean): boolean {
1726        return this.some((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element))
1727    }
1728
1729    /**
1730     * Determines whether the specified callback function returns true for any element of an array.
1731     *
1732     * @param predicate A function that accepts three arguments.
1733     * The some method calls the predicate function for each element in the array
1734     * until the predicate returns a true or until the end of the array.
1735     *
1736     * @returns false unless predicate function returns true for an array element,
1737     * in which case true is immediately returned.
1738     */
1739    public some(predicate: (element: number, index: number, array: Uint8ClampedArray) => boolean): boolean {
1740        for (let i = 0; i < this.lengthInt; i++) {
1741            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
1742                return true
1743            }
1744        }
1745        return false
1746    }
1747
1748    /**
1749     * Determines whether the specified callback function returns true for any element of an array.
1750     *
1751     * @param predicate A function that accepts two arguments.
1752     * The some method calls the predicate function for each element in the array
1753     * until the predicate returns a true or until the end of the array.
1754     *
1755     * @returns false unless predicate function returns true for an array element,
1756     * in which case true is immediately returned.
1757     */
1758    public some(predicate: (element: number, index: number) => boolean): boolean {
1759        return this.some((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element, index))
1760    }
1761
1762    /**
1763     * Determines whether the specified callback function returns true for any element of an array.
1764     *
1765     * @param predicate A function that accepts no arguments.
1766     * The some method calls the predicate function for each element in the array
1767     * until the predicate returns a true or until the end of the array.
1768     *
1769     * @returns false unless predicate function returns true for an array element,
1770     * in which case true is immediately returned.
1771     */
1772    public some(predicate: () => boolean): boolean {
1773        return this.some((element: number, index: number, array: Uint8ClampedArray): boolean => predicate())
1774    }
1775
1776    /**
1777     * Calls the specified callback function for all the elements in an array.
1778     * The return value of the callback function is the accumulated result,
1779     * and is provided as an argument in the next call to the callback function.
1780     *
1781     * @param callbackfn A function that accepts four arguments.
1782     * The reduce method calls the callbackfn function one time for each element in the array.
1783     *
1784     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1785     * The first call to the callbackfn function provides this value as an argument.
1786     *
1787     * @returns The value that results from running the callback function to completion over the entire typed array.
1788     */
1789    public reduce<U = number>(
1790                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U,
1791                initialValue: U): U {
1792        let accumulatedValue = initialValue
1793        for (let i = 0; i < this.lengthInt; i++) {
1794            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1795        }
1796        return accumulatedValue
1797    }
1798
1799    /**
1800     * Calls the specified callback function for all the elements in an array.
1801     * The return value of the callback function is the accumulated result,
1802     * and is provided as an argument in the next call to the callback function.
1803     *
1804     * @param callbackfn A function that accepts three arguments.
1805     * The reduce method calls the callbackfn function one time for each element in the array.
1806     *
1807     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1808     * The first call to the callbackfn function provides this value as an argument.
1809     *
1810     * @returns The value that results from running the callback function to completion over the entire typed array.
1811     */
1812    public reduce<U = number>(
1813                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
1814                initialValue: U): U {
1815        return this.reduce(
1816                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1817                        callbackfn(prevVal, currVal, currIndex),
1818                initialValue)
1819    }
1820
1821    /**
1822     * Calls the specified callback function for all the elements in an array.
1823     * The return value of the callback function is the accumulated result,
1824     * and is provided as an argument in the next call to the callback function.
1825     *
1826     * @param callbackfn A function that accepts two arguments.
1827     * The reduce method calls the callbackfn function one time for each element in the array.
1828     *
1829     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1830     * The first call to the callbackfn function provides this value as an argument.
1831     *
1832     * @returns The value that results from running the callback function to completion over the entire typed array.
1833     */
1834    public reduce<U = number>(
1835                callbackfn: (previousValue: U, currentValue: number) => U,
1836                initialValue: U): U {
1837        return this.reduce(
1838                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1839                        callbackfn(prevVal, currVal),
1840                initialValue)
1841    }
1842
1843    /**
1844     * Calls the specified callback function for all the elements in an array.
1845     * The return value of the callback function is the accumulated result,
1846     * and is provided as an argument in the next call to the callback function.
1847     *
1848     * @param callbackfn A function that accepts one argument
1849     * The reduce method calls the callbackfn function one time for each element in the array.
1850     *
1851     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1852     * The first call to the callbackfn function provides this value as an argument.
1853     *
1854     * @returns The value that results from running the callback function to completion over the entire typed array.
1855     */
1856    public reduce<U = number>(
1857                callbackfn: (previousValue: U) => U,
1858                initialValue: U): U {
1859        return this.reduce(
1860                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1861                        callbackfn(prevVal),
1862                initialValue)
1863    }
1864
1865    /**
1866     * Calls the specified callback function for all the elements in an array.
1867     * The return value of the callback function is the accumulated result,
1868     * and is provided as an argument in the next call to the callback function.
1869     *
1870     * @param callbackfn A function that accepts no arguments
1871     * The reduce method calls the callbackfn function one time for each element in the array.
1872     *
1873     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1874     * The first call to the callbackfn function provides this value as an argument.
1875     *
1876     * @returns The value that results from running the callback function to completion over the entire typed array.
1877     */
1878    public reduce<U = number>(
1879                callbackfn: () => U,
1880                initialValue: U): U {
1881        return this.reduce(
1882                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1883                        callbackfn(),
1884                initialValue)
1885    }
1886
1887    /**
1888     * Calls the specified callback function for all the elements in an array.
1889     * The return value of the callback function is the accumulated result,
1890     * and is provided as an argument in the next call to the callback function.
1891     *
1892     * @param callbackfn A function that accepts four arguments.
1893     * The reduce method calls the callbackfn function one time for each element in the array.
1894     * The first call to the callbackfn function provides array first element value as an argument
1895     *
1896     * @returns The value that results from running the callback function to completion over the entire typed array.
1897     * calling reduce method on an empty array without an initial value creates a TypeError
1898     */
1899    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number {
1900        if (this.lengthInt == 0) {
1901            throw new TypeError("Reduce of empty array with no initial value")
1902        }
1903
1904        let accumulatedValue = this.$_get(0) as number
1905        for (let i = 1; i < this.lengthInt; i++) {
1906            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1907        }
1908        return accumulatedValue
1909    }
1910
1911    /**
1912     * Calls the specified callback function for all the elements in an array.
1913     * The return value of the callback function is the accumulated result,
1914     * and is provided as an argument in the next call to the callback function.
1915     *
1916     * @param callbackfn A function that accepts three arguments.
1917     * The reduce method calls the callbackfn function one time for each element in the array.
1918     * The first call to the callbackfn function provides array first element value as an argument
1919     *
1920     * @returns The value that results from running the callback function to completion over the entire typed array.
1921     * calling reduce method on an empty array without an initial value creates a TypeError
1922     */
1923    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
1924        return this.reduce(
1925                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1926                        callbackfn(prevVal, currVal, currIndex))
1927    }
1928
1929    /**
1930     * Calls the specified callback function for all the elements in an array.
1931     * The return value of the callback function is the accumulated result,
1932     * and is provided as an argument in the next call to the callback function.
1933     *
1934     * @param callbackfn A function that accepts two arguments.
1935     * The reduce method calls the callbackfn function one time for each element in the array.
1936     * The first call to the callbackfn function provides array first element value as an argument
1937     *
1938     * @returns The value that results from running the callback function to completion over the entire typed array.
1939     * calling reduce method on an empty array without an initial value creates a TypeError
1940     */
1941    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
1942        return this.reduce(
1943                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1944                        callbackfn(prevVal, currVal))
1945    }
1946
1947    /**
1948     * Calls the specified callback function for all the elements in an array.
1949     * The return value of the callback function is the accumulated result,
1950     * and is provided as an argument in the next call to the callback function.
1951     *
1952     * @param callbackfn A function that accepts one argument.
1953     * The reduce method calls the callbackfn function one time for each element in the array.
1954     * The first call to the callbackfn function provides array first element value as an argument
1955     *
1956     * @returns The value that results from running the callback function to completion over the entire typed array.
1957     * calling reduce method on an empty array without an initial value creates a TypeError
1958     */
1959    public reduce(callbackfn: (previousValue: number) => number): number {
1960        return this.reduce(
1961                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1962                        callbackfn(prevVal))
1963    }
1964
1965    /**
1966     * Calls the specified callback function for all the elements in an array.
1967     * The return value of the callback function is the accumulated result,
1968     * and is provided as an argument in the next call to the callback function.
1969     *
1970     * @param callbackfn A function that accepts no arguments.
1971     * The reduce method calls the callbackfn function one time for each element in the array.
1972     * The first call to the callbackfn function provides array first element value as an argument
1973     *
1974     * @returns The value that results from running the callback function to completion over the entire typed array.
1975     * calling reduce method on an empty array without an initial value creates a TypeError
1976     */
1977    public reduce(callbackfn: () => number): number {
1978        return this.reduce(
1979                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1980                        callbackfn())
1981    }
1982
1983    /**
1984     * Calls the specified callback function for all the elements in an array, in descending order.
1985     * The return value of the callback function is the accumulated result,
1986     * and is provided as an argument in the next call to the callback function.
1987     *
1988     * @param callbackfn A function that accepts four arguments.
1989     * The reduceRight method calls the callbackfn function one time for each element in the array.
1990     *
1991     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1992     * The first call to the callbackfn function provides this value as an argument.
1993     *
1994     * @returns The value that results from running the callback function to completion over the entire typed array.
1995     */
1996    public reduceRight<U = number>(
1997                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U,
1998                initialValue: U): U {
1999        let accumulatedValue = initialValue
2000        for (let i = this.lengthInt - 1; i >= 0; i--) {
2001            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
2002        }
2003        return accumulatedValue
2004    }
2005
2006    /**
2007     * Calls the specified callback function for all the elements in an array, in descending order.
2008     * The return value of the callback function is the accumulated result,
2009     * and is provided as an argument in the next call to the callback function.
2010     *
2011     * @param callbackfn A function that accepts three arguments.
2012     * The reduceRight method calls the callbackfn function one time for each element in the array.
2013     *
2014     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2015     * The first call to the callbackfn function provides this value as an argument.
2016     *
2017     * @returns The value that results from running the callback function to completion over the entire typed array.
2018     */
2019    public reduceRight<U = number>(
2020                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
2021                initialValue: U): U {
2022        return this.reduceRight(
2023                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2024                        callbackfn(prevVal, currVal, currIndex),
2025                initialValue)
2026    }
2027
2028    /**
2029     * Calls the specified callback function for all the elements in an array, in descending order.
2030     * The return value of the callback function is the accumulated result,
2031     * and is provided as an argument in the next call to the callback function.
2032     *
2033     * @param callbackfn A function that accepts two arguments.
2034     * The reduceRight method calls the callbackfn function one time for each element in the array.
2035     *
2036     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2037     * The first call to the callbackfn function provides this value as an argument.
2038     *
2039     * @returns The value that results from running the callback function to completion over the entire typed array.
2040     */
2041    public reduceRight<U = number>(
2042                callbackfn: (previuosValue: U, currentValue: number) => U,
2043                initialValue: U): U {
2044        return this.reduceRight(
2045                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2046                        callbackfn(prevVal, currVal),
2047                initialValue)
2048    }
2049
2050    /**
2051     * Calls the specified callback function for all the elements in an array, in descending order.
2052     * The return value of the callback function is the accumulated result,
2053     * and is provided as an argument in the next call to the callback function.
2054     *
2055     * @param callbackfn A function that accepts one argument.
2056     * The reduceRight method calls the callbackfn function one time for each element in the array.
2057     *
2058     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2059     * The first call to the callbackfn function provides this value as an argument.
2060     *
2061     * @returns The value that results from running the callback function to completion over the entire typed array.
2062     */
2063    public reduceRight<U = number>(
2064                callbackfn: (previuosValue: U) => U,
2065                initialValue: U): U {
2066        return this.reduceRight(
2067                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2068                        callbackfn(prevVal),
2069                initialValue)
2070    }
2071
2072    /**
2073     * Calls the specified callback function for all the elements in an array, in descending order.
2074     * The return value of the callback function is the accumulated result,
2075     * and is provided as an argument in the next call to the callback function.
2076     *
2077     * @param callbackfn A function that accepts no arguments.
2078     * The reduceRight method calls the callbackfn function one time for each element in the array.
2079     *
2080     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2081     * The first call to the callbackfn function provides this value as an argument.
2082     *
2083     * @returns The value that results from running the callback function to completion over the entire typed array.
2084     */
2085    public reduceRight<U = number>(
2086                callbackfn: () => U,
2087                initialValue: U): U {
2088        return this.reduceRight(
2089                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2090                        callbackfn(),
2091                initialValue)
2092    }
2093
2094    /**
2095     * Calls the specified callback function for all the elements in an array, in descending order.
2096     * The return value of the callback function is the accumulated result,
2097     * and is provided as an argument in the next call to the callback function.
2098     *
2099     * @param callbackfn A function that accepts four arguments.
2100     * The reduceRight method calls the callbackfn function one time for each element in the array.
2101     * The first call to the callbackfn function provides array last element value as an argument
2102     *
2103     * @returns The value that results from running the callback function to completion over the entire typed array.
2104     * calling reduceRight method on an empty array without an initial value creates a TypeError
2105     */
2106    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number {
2107        if (this.lengthInt == 0) {
2108            throw new TypeError("Reduce of empty array with no initial value")
2109        }
2110
2111        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
2112        for (let i = this.lengthInt - 2; i >= 0; i--) {
2113            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
2114        }
2115        return accumulatedValue
2116    }
2117
2118    /**
2119     * Calls the specified callback function for all the elements in an array, in descending order.
2120     * The return value of the callback function is the accumulated result,
2121     * and is provided as an argument in the next call to the callback function.
2122     *
2123     * @param callbackfn A function that accepts three arguments.
2124     * The reduceRight method calls the callbackfn function one time for each element in the array.
2125     * The first call to the callbackfn function provides array last element value as an argument
2126     *
2127     * @returns The value that results from running the callback function to completion over the entire typed array.
2128     * calling reduceRight method on an empty array without an initial value creates a TypeError
2129     */
2130    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
2131        return this.reduceRight(
2132                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2133                        callbackfn(prevValue, currValue, currIndex))
2134    }
2135
2136    /**
2137     * Calls the specified callback function for all the elements in an array, in descending order.
2138     * The return value of the callback function is the accumulated result,
2139     * and is provided as an argument in the next call to the callback function.
2140     *
2141     * @param callbackfn A function that accepts two arguments.
2142     * The reduceRight method calls the callbackfn function one time for each element in the array.
2143     * The first call to the callbackfn function provides array last element value as an argument
2144     *
2145     * @returns The value that results from running the callback function to completion over the entire typed array.
2146     * calling reduceRight method on an empty array without an initial value creates a TypeError
2147     */
2148    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
2149        return this.reduceRight(
2150                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2151                        callbackfn(prevValue, currValue))
2152    }
2153
2154    /**
2155     * Calls the specified callback function for all the elements in an array, in descending order.
2156     * The return value of the callback function is the accumulated result,
2157     * and is provided as an argument in the next call to the callback function.
2158     *
2159     * @param callbackfn A function that accepts one argument.
2160     * The reduceRight method calls the callbackfn function one time for each element in the array.
2161     * The first call to the callbackfn function provides array last element value as an argument
2162     *
2163     * @returns The value that results from running the callback function to completion over the entire typed array.
2164     * calling reduceRight method on an empty array without an initial value creates a TypeError
2165     */
2166    public reduceRight(callbackfn: (previousValue: number) => number): number {
2167        return this.reduceRight(
2168                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2169                        callbackfn(prevValue))
2170    }
2171
2172    /**
2173     * Calls the specified callback function for all the elements in an array, in descending order.
2174     * The return value of the callback function is the accumulated result,
2175     * and is provided as an argument in the next call to the callback function.
2176     *
2177     * @param callbackfn A function that accepts no arguments.
2178     * The reduceRight method calls the callbackfn function one time for each element in the array.
2179     * The first call to the callbackfn function provides array last element value as an argument
2180     *
2181     * @returns The value that results from running the callback function to completion over the entire typed array.
2182     * calling reduceRight method on an empty array without an initial value creates a TypeError
2183     */
2184    public reduceRight(callbackfn: () => number): number {
2185        return this.reduceRight(
2186                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2187                        callbackfn())
2188    }
2189
2190    /**
2191     * Creates a new Uint8ClampedArray using fn(arr[i]) over all elements of current Uint8ClampedArray.
2192     *
2193     * @param fn a function to apply for each element of current Uint8ClampedArray
2194     *
2195     * @returns a new Uint8ClampedArray where for each element from current Uint8ClampedArray fn was applied
2196     */
2197    public map(fn: (val: number, index: number, array: Uint8ClampedArray) => number): Uint8ClampedArray {
2198        let resBuf = new ArrayBuffer(this.lengthInt * Uint8ClampedArray.BYTES_PER_ELEMENT as int)
2199        let res = new Uint8ClampedArray(resBuf)
2200        for (let i = 0; i < this.lengthInt; i++) {
2201            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
2202            res.setUnsafeClamp(i, fnRes as int)
2203        }
2204        return res
2205    }
2206
2207    /**
2208     * Creates a new Uint8ClampedArray using fn(arr[i], i) over all elements of current Uint8ClampedArray
2209     *
2210     * @param fn a function to apply for each element of current Uint8ClampedArray
2211     *
2212     * @returns a new Uint8ClampedArray where for each element from current Uint8ClampedArray fn was applied
2213     */
2214    public map(fn: (val: number, index: number) => number): Uint8ClampedArray {
2215        let newF: (val: number, index: number, array: Uint8ClampedArray) => number =
2216            (val: number, index: number, array: Uint8ClampedArray): number => { return fn(val, index) }
2217        return this.map(newF)
2218    }
2219
2220    /**
2221     * Creates a new Uint8ClampedArray using fn(arr[i]) over all elements of current Uint8ClampedArray
2222     *
2223     * @param fn a function to apply for each element of current Uint8ClampedArray
2224     *
2225     * @returns a new Uint8ClampedArray where for each element from current Uint8ClampedArray fn was applied
2226     */
2227    public map(fn: (val: number) => number): Uint8ClampedArray {
2228        let newF: (val: number, index: number, array: Uint8ClampedArray) => number =
2229            (val: number, index: number, array: Uint8ClampedArray): number => { return fn(val) }
2230        return this.map(newF)
2231    }
2232
2233    /**
2234     * Creates a new Uint8ClampedArray using fn() over all elements of current Uint8ClampedArray
2235     *
2236     * @param fn a function to apply for each element of current Uint8ClampedArray
2237     *
2238     * @returns a new Uint8ClampedArray where for each element from current Uint8ClampedArray fn was applied
2239     */
2240    public map(fn: () => number): Uint8ClampedArray {
2241        let newF: (val: number, index: number, array: Uint8ClampedArray) => number =
2242            (val: number, index: number, array: Uint8ClampedArray): number => { return fn() }
2243        return this.map(newF)
2244    }
2245
2246    /**
2247     * Determines whether the specified callback function returns true for all elements of an array.
2248     *
2249     * @param predicate A function that accepts three arguments.
2250     * The every method calls the predicate function for each element in the array until the predicate returns a false,
2251     * or until the end of the array.
2252     *
2253     * @returns true unless predicate function returns a false for an array element,
2254     * in which case false is immediately returned.
2255     */
2256    public every(predicate: (element: number, index: number, array: Uint8ClampedArray) => boolean): boolean {
2257        for (let i = 0; i < this.lengthInt; i++) {
2258            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
2259                return false
2260            }
2261        }
2262        return true
2263    }
2264
2265    /**
2266     * Determines whether the specified callback function returns true for all elements of an array.
2267     *
2268     * @param predicate A function that accepts two arguments.
2269     * The every method calls the predicate function for each element in the array until the predicate returns a false,
2270     * or until the end of the array.
2271     *
2272     * @returns true unless predicate function returns a false for an array element,
2273     * in which case false is immediately returned.
2274     */
2275    public every(predicate: (element: number, index: number) => boolean): boolean {
2276        return this.every((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element, index))
2277    }
2278
2279    /**
2280     * Determines whether the specified callback function returns true for all elements of an array.
2281     *
2282     * @param predicate A function that accepts no arguments.
2283     * The every method calls the predicate function for each element in the array until the predicate returns a false,
2284     * or until the end of the array.
2285     *
2286     * @returns true unless predicate function returns a false for an array element,
2287     * in which case false is immediately returned.
2288     */
2289    public every(predicate: () => boolean): boolean {
2290        return this.every((element: number, index: number, array: Uint8ClampedArray): boolean => predicate())
2291    }
2292
2293    /**
2294     * Creates a new Uint8ClampedArray from current Uint8ClampedArray based on a condition fn.
2295     *
2296     * @param fn the condition to apply for each element
2297     *
2298     * @returns a new Uint8ClampedArray with elements from current Uint8ClampedArray that satisfy condition fn
2299     */
2300    public filter(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): Uint8ClampedArray {
2301        let markers = new boolean[this.lengthInt]
2302        let resLen = 0
2303        for (let i = 0; i < this.lengthInt; i++) {
2304            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
2305            if (markers[i]) {
2306                ++resLen
2307            }
2308        }
2309        let res = new Uint8ClampedArray(resLen)
2310        for (let i = 0, j = 0; i < this.lengthInt; i++) {
2311            if (markers[i]) {
2312                res.setUnsafe(j, this.getUnsafe(i))
2313                ++j
2314            }
2315        }
2316        return res
2317    }
2318
2319    /**
2320     * creates a new Uint8ClampedArray from current Uint8ClampedArray based on a condition fn
2321     *
2322     * @param fn the condition to apply for each element
2323     *
2324     * @returns a new Uint8ClampedArray with elements from current Uint8ClampedArray that satisfy condition fn
2325     */
2326    public filter(fn: (val: number, index: number) => boolean): Uint8ClampedArray {
2327        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
2328            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val, index) }
2329        return this.filter(newF)
2330    }
2331
2332    /**
2333     * Returns the value of the first element in the array where predicate is true, and undefined
2334     * otherwise
2335     *
2336     * @param predicate find calls predicate once for each element of the array, in ascending
2337     * order, until it finds one where predicate returns true. If such an element is found, find
2338     * immediately returns that element value. Otherwise, find returns undefined
2339     *
2340     * @returns number | undefined
2341     */
2342    public find(predicate: (value: number, index: number, array: Uint8ClampedArray) => boolean): number | undefined {
2343        for (let i = 0; i < this.lengthInt; i++) {
2344            let val = this.getUnsafe(i) as number
2345            if (predicate(val, i as number, this)) {
2346                return val
2347            }
2348        }
2349        return undefined
2350    }
2351
2352    /**
2353     * Returns the value of the first element in the array where predicate is true, and undefined
2354     * otherwise
2355     *
2356     * @param predicate find calls predicate once for each element of the array, in ascending
2357     * order, until it finds one where predicate returns true. If such an element is found, find
2358     * immediately returns that element value. Otherwise, find returns undefined
2359     *
2360     * @returns number | undefined
2361     */
2362    public find(predicate: (value: number, index: number) => boolean): number | undefined {
2363        return this.find((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value, index))
2364    }
2365
2366    /**
2367     * Returns the index of the first element in the array where predicate is true, and -1
2368     * otherwise
2369     *
2370     * @param predicate find calls predicate once for each element of the array, in ascending
2371     * order, until it finds one where predicate returns true. If such an element is found,
2372     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
2373     *
2374     * @returns number
2375     */
2376    public findIndex(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean): number {
2377        for (let i = 0; i < this.lengthInt; i++) {
2378            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
2379                return i as number
2380            }
2381        }
2382        return -1 as number
2383    }
2384
2385    /**
2386     * Returns the index of the first element in the array where predicate is true, and -1
2387     * otherwise
2388     *
2389     * @param predicate find calls predicate once for each element of the array, in ascending
2390     * order, until it finds one where predicate returns true. If such an element is found,
2391     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
2392     *
2393     * @returns number
2394     */
2395    public findIndex(predicate: (value: number, index: number) => boolean): number {
2396        return this.findIndex((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value, index))
2397    }
2398
2399    /**
2400     * Returns the index of the first element in the array where predicate is true, and -1
2401     * otherwise
2402     *
2403     * @param predicate find calls predicate once for each element of the array, in ascending
2404     * order, until it finds one where predicate returns true. If such an element is found,
2405     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
2406     *
2407     * @returns number
2408     */
2409    public findIndex(predicate: () => boolean): number {
2410        return this.findIndex((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate())
2411    }
2412
2413    /**
2414     * Finds the last element in the Uint8ClampedArray that satisfies the condition
2415     *
2416     * @param fn condition
2417     *
2418     * @returns the last element that satisfies fn
2419     */
2420    public findLast(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): number {
2421        for (let i = this.lengthInt - 1; i >= 0; i--) {
2422            let val = this.getUnsafe(i) as number
2423            if (fn(val, i as number, this)) {
2424                return val
2425            }
2426        }
2427        throw new Error("Uint8ClampedArray.findLast: not implemented if an element was not found")
2428    }
2429
2430    /**
2431     * Finds the last element in the Uint8ClampedArray that satisfies the condition
2432     *
2433     * @param fn condition
2434     *
2435     * @returns the last element that satisfies fn
2436     */
2437    public findLast(fn: (val: number, index: number) => boolean): number {
2438        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
2439            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val, index) }
2440        return this.findLast(newF)
2441    }
2442
2443    /**
2444     * Finds an index of the last element in the Uint8ClampedArray that satisfies the condition
2445     *
2446     * @param fn condition
2447     *
2448     * @returns the index of the last element that satisfies fn, -1 otherwise
2449     */
2450    public findLastIndex(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): number {
2451        for (let i = this.lengthInt - 1; i >= 0; i--) {
2452            if (fn(this.getUnsafe(i) as number, i as number, this)) {
2453                return i as number
2454            }
2455        }
2456        return -1 as number
2457    }
2458
2459    /**
2460     * Finds an index of the last element in the Uint8ClampedArray that satisfies the condition
2461     *
2462     * @param fn condition
2463     *
2464     * @returns the index of the last element that satisfies fn, -1 otherwise
2465     */
2466    public findLastIndex(fn: (val: number, index: number) => boolean): number {
2467        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
2468            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val, index) }
2469        return this.findLastIndex(newF) as number
2470    }
2471
2472    /**
2473     * Performs the specified action for each element in Uint8ClampedArray
2474     *
2475     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
2476     * callbackfn function one time for each element in the array.
2477     *
2478     * @returns None
2479     */
2480    public forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void): void {
2481        for (let i = 0; i < this.lengthInt; i++) {
2482            callbackfn(this.getUnsafe(i) as number, i as number, this)
2483        }
2484    }
2485
2486    /**
2487     * Performs the specified action for each element in Uint8ClampedArray
2488     *
2489     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
2490     * callbackfn function one time for each element in the array.
2491     *
2492     * @returns None
2493     */
2494    public forEach(callbackfn: (value: number, index: number) => void): void {
2495        this.forEach((value: number, index: number, array: Uint8ClampedArray): void => callbackfn(value, index))
2496    }
2497
2498    /**
2499     * Performs the specified action for each element in Uint8ClampedArray
2500     *
2501     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
2502     * callbackfn function one time for each element in the array.
2503     *
2504     * @returns None
2505     */
2506    public forEach(callbackfn: () => void): void {
2507        this.forEach((value: number, index: number, array: Uint8ClampedArray): void => callbackfn())
2508    }
2509
2510    /**
2511     * Returns the object itself
2512     *
2513     * @returns Uint8ClampedArray
2514     */
2515    public valueOf(): Uint8ClampedArray {
2516        return this
2517    }
2518
2519    /** Byte offset within the underlying Buffer */
2520    public get byteOffset(): number {
2521        return this.byteOffsetInt
2522    }
2523
2524    /** Number of bytes used */
2525    public get byteLength(): number {
2526        return this.byteLengthInt
2527    }
2528
2529    /** Number of int stored in Uint8ClampedArray */
2530    public get length(): number {
2531        return this.lengthInt
2532    }
2533
2534    /** String \"Uint8ClampedArray\" */
2535    public readonly name = "Uint8ClampedArray"
2536
2537    private static clamp(val: int): int {
2538        if (val > 255) {
2539            val = 255
2540        } else if (val < 0) {
2541            val = 0
2542        }
2543        return val
2544    }
2545
2546    internal setUnsafeClamp(insertPos: int, val: int): void {
2547        val = Uint8ClampedArray.clamp(val)
2548        this.setUnsafe(insertPos, val)
2549    }
2550
2551    internal getUnsafe(index: int): int {
2552        index = index * Uint8ClampedArray.BYTES_PER_ELEMENT as int + this.byteOffsetInt
2553        let res: int = 0
2554        if (IS_LITTLE_ENDIAN) {
2555            if (this.buffer instanceof ArrayBuffer) {
2556                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2557                    let el = (this.buffer as ArrayBuffer).at(index + i) as int
2558                    el &= 0xff
2559                    res |= el << (8 * i)
2560                }
2561            } else if (this.buffer instanceof SharedArrayBuffer) {
2562                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2563                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as int
2564                    el &= 0xff
2565                    res |= el << (8 * i)
2566                }
2567            } else {
2568                throw new Error("unexpected type of ArrayBufferLike")
2569            }
2570        } else {
2571            if (this.buffer instanceof ArrayBuffer) {
2572                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2573                    let el = (this.buffer as ArrayBuffer).at(index + 0 - i) as int
2574                    el &= 0xff
2575                    res |= el << (8 * i)
2576                }
2577            } else if (this.buffer instanceof SharedArrayBuffer) {
2578                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2579                    let el = (this.buffer as SharedArrayBuffer).at(index + 0 - i) as int
2580                    el &= 0xff
2581                    res |= el << (8 * i)
2582                }
2583            } else {
2584                throw new Error("unexpected type of ArrayBufferLike")
2585            }
2586        }
2587        return res
2588    }
2589
2590    internal setUnsafe(index: int, val: int): void {
2591        index = index * Uint8ClampedArray.BYTES_PER_ELEMENT as int + this.byteOffsetInt
2592        let res: int = 0
2593        if (IS_LITTLE_ENDIAN) {
2594            if (this.buffer instanceof ArrayBuffer) {
2595                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2596                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
2597                    val = val >> 8
2598                }
2599            } else if (this.buffer instanceof SharedArrayBuffer) {
2600                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2601                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
2602                    val = val >> 8
2603                }
2604            } else {
2605                throw new Error("unexpected type of ArrayBufferLike")
2606            }
2607        } else {
2608            if (this.buffer instanceof ArrayBuffer) {
2609                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2610                    (this.buffer as ArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
2611                    val = val >> 8
2612                }
2613            } else if (this.buffer instanceof SharedArrayBuffer) {
2614                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2615                    (this.buffer as SharedArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
2616                    val = val >> 8
2617                }
2618            } else {
2619                throw new Error("unexpected type of ArrayBufferLike")
2620            }
2621        }
2622    }
2623}
2624
2625
2626class Uint8ArrayIteratorKeys implements IterableIterator<number> {
2627    private length: int = 0
2628    private idx: int = 0
2629
2630    constructor(parent: Uint8Array) {
2631        this.length = parent.length as int
2632    }
2633
2634    public override $_iterator(): IterableIterator<Number> {
2635        return this
2636    }
2637
2638    override next(): IteratorResult<number> {
2639        if (this.idx < 0 || this.idx >= this.length) {
2640            return new IteratorResult<number>()
2641        }
2642        return new IteratorResult<number>(false, this.idx++ as number)
2643    }
2644}
2645
2646class Uint8ArrayIterator implements IterableIterator<Number> {
2647    private parent: Uint8Array
2648    private idx: int = 0
2649
2650    constructor(parent: Uint8Array) {
2651        this.parent = parent
2652    }
2653
2654    public override $_iterator(): IterableIterator<Number> {
2655        return this
2656    }
2657
2658    override next(): IteratorResult<Number> {
2659        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
2660            return new IteratorResult<Number>()
2661        }
2662        return new IteratorResult<Number>(false, new Number(this.parent.getUnsafe(this.idx++)))
2663    }
2664}
2665
2666class Uint8ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
2667    private parent: Uint8Array
2668    private idx: int = 0
2669
2670    constructor(parent: Uint8Array) {
2671        this.parent = parent
2672    }
2673
2674    public override $_iterator(): IterableIterator<[Number, Number]> {
2675        return this
2676    }
2677
2678    override next(): IteratorResult<[Number, Number]> {
2679        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
2680            return new IteratorResult<[Number, Number]>()
2681        }
2682        return new IteratorResult<[Number, Number]>(
2683            false,
2684            [new Number(this.idx), new Number(this.parent.getUnsafe(this.idx++))]
2685        )
2686    }
2687}
2688
2689/**
2690 * JS Uint8Array API-compatible class
2691 */
2692export class Uint8Array implements Iterable<Number>, ArrayLike<Number> {
2693    public static readonly BYTES_PER_ELEMENT: number = 1
2694
2695    /** Underlying Buffer */
2696    public readonly buffer: ArrayBufferLike
2697
2698    internal readonly byteOffsetInt: int
2699    internal readonly byteLengthInt: int
2700    internal readonly lengthInt: int
2701
2702    /**
2703     * Creates an empty Uint8Array.
2704     */
2705    public constructor() {
2706        this(0 as int)
2707    }
2708
2709    /**
2710     * Creates an Uint8Array with respect to data accessed via Iterable<Number> interface
2711     */
2712    public constructor(elements: Iterable<Number>) {
2713        const items: Object = elements as Object
2714        if (items instanceof ArrayLike) {
2715            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
2716            this.byteLengthInt = arr.length as int * Uint8Array.BYTES_PER_ELEMENT as int
2717            this.lengthInt = arr.length as int
2718            this.buffer = new ArrayBuffer(this.byteLengthInt)
2719            this.byteOffsetInt = 0
2720            for (let i: int = 0; i < this.lengthInt; ++i) {
2721                this.setUnsafe(i, arr.$_get(i).intValue())
2722            }
2723        } else {
2724            let x = Uint8Array.from(elements)
2725            this.byteLengthInt = x.byteLengthInt
2726            this.lengthInt = x.lengthInt
2727            this.buffer = x.buffer
2728            this.byteOffsetInt = x.byteOffsetInt
2729        }
2730    }
2731
2732    /**
2733     * Creates an Uint8Array with respect to data, byteOffset and length.
2734     *
2735     * @param buf data initializer
2736     *
2737     * @param byteOffset byte offset from begin of the buf
2738     *
2739     * @param length size of elements of type int in newly created Uint8Array
2740     */
2741    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
2742        let intByteOffset: int = 0
2743        if (byteOffset != undefined) {
2744            intByteOffset = byteOffset.intValue()
2745            if (intByteOffset < 0) {
2746                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
2747            }
2748        }
2749        let intByteLength: int
2750        if (buf instanceof ArrayBuffer) {
2751            intByteLength = (buf as ArrayBuffer).getByteLength()
2752        } else if (buf instanceof SharedArrayBuffer) {
2753            intByteLength = (buf as SharedArrayBuffer).getByteLength()
2754        } else {
2755            throw new Error("unexpected type of ArrayBufferLike")
2756        }
2757        intByteLength = intByteLength - intByteOffset
2758        if (intByteLength < 0) {
2759            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
2760        }
2761
2762        let intLength: int
2763        if (length != undefined) {
2764            intLength = length.intValue()
2765            if (intLength > intByteLength / Uint8Array.BYTES_PER_ELEMENT as int) {
2766                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
2767            }
2768        } else {
2769            intLength = intByteLength / Uint8Array.BYTES_PER_ELEMENT as int
2770        }
2771        if (intLength < 0) {
2772            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
2773        }
2774        if (intLength < intByteLength / Uint8Array.BYTES_PER_ELEMENT as int) {
2775            intByteLength = intLength * Uint8Array.BYTES_PER_ELEMENT as int
2776        }
2777        this.byteLengthInt = intByteLength
2778        this.byteOffsetInt = intByteOffset
2779        this.lengthInt = intLength
2780        this.buffer = buf
2781    }
2782
2783    /**
2784     * Creates an Uint8Array with respect to data, byteOffset and length.
2785     *
2786     * @param buf data initializer
2787     *
2788     * @param byteOffset byte offset from begin of the buf
2789     */
2790    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
2791        this(buf, byteOffset, undefined)
2792    }
2793
2794    /**
2795     * Creates an Uint8Array with respect to data, byteOffset and length.
2796     *
2797     * @param buf data initializer
2798     *
2799     * @param byteOffset byte offset from begin of the buf
2800     *
2801     * @param length size of elements of type int in newly created Uint8Array
2802     */
2803    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
2804        this(buf, new Number(byteOffset), new Number(length))
2805    }
2806
2807    /**
2808     * Creates an Uint8Array with respect to buf and byteOffset.
2809     *
2810     * @param buf data initializer
2811     *
2812     * @param byteOffset byte offset from begin of the buf
2813     */
2814    public constructor(buf: ArrayBufferLike, byteOffset: number) {
2815        this(buf, new Number(byteOffset), undefined)
2816    }
2817
2818    /**
2819     * Creates an Uint8Array with respect to data, byteOffset and length.
2820     *
2821     * @param buf data initializer
2822     *
2823     * @param byteOffset byte offset from begin of the buf
2824     *
2825     * @param length size of elements of type int in newly created Uint8Array
2826     */
2827    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
2828        this(buf, new Number(byteOffset), new Number(length))
2829    }
2830
2831    /**
2832     * Creates an Uint8Array with respect to buf and byteOffset.
2833     *
2834     * @param buf data initializer
2835     *
2836     * @param byteOffset byte offset from begin of the buf
2837     */
2838    public constructor(buf: ArrayBufferLike, byteOffset: int) {
2839        this(buf, new Number(byteOffset), undefined)
2840    }
2841
2842    /**
2843     * Creates an Uint8Array with respect to buf.
2844     *
2845     * @param buf data initializer
2846     */
2847    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
2848        if (buf instanceof ArrayBuffer) {
2849            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
2850            if (this.byteLengthInt % Uint8Array.BYTES_PER_ELEMENT as int != 0) {
2851               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8Array.BYTES_PER_ELEMENT")
2852            }
2853            this.lengthInt = this.byteLengthInt / Uint8Array.BYTES_PER_ELEMENT as int
2854            this.buffer = buf as ArrayBuffer
2855            this.byteOffsetInt = 0
2856        } else if (buf instanceof SharedArrayBuffer) {
2857            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
2858            if (this.byteLengthInt % Uint8Array.BYTES_PER_ELEMENT as int != 0) {
2859               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8Array.BYTES_PER_ELEMENT")
2860            }
2861            this.lengthInt = this.byteLengthInt / Uint8Array.BYTES_PER_ELEMENT as int
2862            this.buffer = buf as SharedArrayBuffer
2863            this.byteOffsetInt = 0
2864        } else if (buf instanceof ArrayLike) {
2865            // NOTE (ikorobkov): dealing with this overload is tricky
2866            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
2867            let arr = Array.from<Number>((buf as ArrayLike<Number>))
2868            this.byteLengthInt = arr.length as int * Uint8Array.BYTES_PER_ELEMENT as int
2869            this.lengthInt = arr.length as int
2870            this.buffer = new ArrayBuffer(this.byteLengthInt)
2871            this.byteOffsetInt = 0
2872            for (let i: int = 0; i < this.lengthInt; ++i) {
2873                this.setUnsafe(i, arr.$_get(i).intValue())
2874            }
2875        } else {
2876            throw new Error("unexpected type of buf")
2877        }
2878    }
2879
2880    /**
2881     * Creates an Uint8Array with respect to length.
2882     *
2883     * @param length data initializer
2884     */
2885    public constructor(length: int) {
2886        if (length < 0) {
2887            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
2888        }
2889        this.lengthInt = length
2890        this.byteLengthInt = length * Uint8Array.BYTES_PER_ELEMENT as int
2891        this.byteOffsetInt = 0
2892        this.buffer = new ArrayBuffer(this.byteLengthInt)
2893    }
2894
2895    /**
2896     * Creates an Uint8Array with respect to length.
2897     *
2898     * @param length data initializer
2899     */
2900    public constructor(length: number) {
2901        this(length as int)
2902    }
2903
2904    /**
2905     * Creates a copy of Uint8Array.
2906     *
2907     * @param other data initializer
2908     */
2909    public constructor(other: Uint8Array) {
2910        if (other.buffer instanceof ArrayBuffer) {
2911            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
2912        } else if (other.buffer instanceof SharedArrayBuffer) {
2913            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
2914        } else {
2915            throw new Error("unexpected type of buffer")
2916        }
2917        this.byteLengthInt = other.byteLength as int
2918        this.lengthInt = other.length as int
2919        this.byteOffsetInt = 0
2920    }
2921
2922    /**
2923     * Creates an Uint8Array from number[]
2924     */
2925    public constructor(numbers: number[]) {
2926        this(numbers.length)
2927        for (let i: int = 0; i < this.lengthInt; ++i) {
2928            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
2929        }
2930    }
2931
2932    /**
2933     * Creates an Uint8Array from int[]
2934     */
2935    public constructor(numbers: int[]) {
2936        this(numbers.length)
2937        for (let i: int = 0; i < this.lengthInt; ++i) {
2938            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
2939        }
2940    }
2941
2942    internal zeroIfInfinity(val: number): number {
2943        if ((val == Infinity) || (val == -Infinity)) {
2944            return 0 as number
2945        }
2946        return val as number
2947    }
2948
2949    internal zeroIfInfinity(val: int): int {
2950        if ((val == Infinity) || (val == -Infinity)) {
2951            return 0 as int
2952        }
2953        return val
2954    }
2955
2956    /**
2957     * Iteratorable interface implementation
2958     *
2959     * @returns iterator over all elements
2960     */
2961    public override $_iterator(): IterableIterator<Number> {
2962         return this.values()
2963    }
2964
2965    /**
2966     * Returns an instance of primitive type at passed index.
2967     *
2968     * @param index index to look at
2969     *
2970     * @returns a primitive at index
2971     */
2972    public at(index: number): Number | undefined {
2973        return this.at(index as int)
2974    }
2975
2976    /**
2977     * Returns an instance of primitive type at passed index if index is correct.
2978     *
2979     * @param index index to look at
2980     *
2981     * @returns a primitive at index
2982     */
2983    public at(index: int): Number | undefined {
2984        let k: int
2985        if (index >= 0) {
2986            k = index
2987        } else {
2988            k = this.lengthInt + index
2989        }
2990        if (k < 0 || k >= this.lengthInt) {
2991            return undefined
2992        }
2993        return new Number(this.getUnsafe(k))
2994    }
2995
2996    /**
2997     * Returns an instance of number at passed index.
2998     *
2999     * @param index index to look at
3000     *
3001     * @returns a primitive at index
3002     */
3003    public override $_get(index: number): Number {
3004        return this.$_get(index as int) as Number
3005    }
3006
3007    /**
3008     * Returns an instance of number at passed index.
3009     *
3010     * @param index index to look at
3011     *
3012     * @returns a primitive at index
3013     */
3014    public $_get(i: int): number {
3015        if (i < 0 || i >= this.lengthInt) {
3016            throw new RangeError("invalid offset")
3017        }
3018        return this.getUnsafe(i) as number
3019    }
3020
3021    /**
3022     * Assigns val as element on index.
3023     *
3024     * @param val value to set
3025     *
3026     * @param index index to change
3027     */
3028    public $_set(index: number, val: number): void {
3029        this.$_set(index as int, val)
3030    }
3031
3032    /**
3033     * Assigns val as element on index.
3034     *
3035     * @param val value to set
3036     *
3037     * @param index index to change
3038     */
3039    public $_set(index: int, val: number): void {
3040        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
3041        if (index < 0 || index >= this.lengthInt) {
3042            throw new RangeError("invalid index")
3043        }
3044        let v = this.zeroIfInfinity(val)
3045        this.setUnsafeClamp(index, v as int)
3046    }
3047
3048    /**
3049     * Assigns val as element on index.
3050     *
3051     * @param val value to set
3052     *
3053     * @param index index to change
3054     */
3055    public $_set(index: number, val: int): void {
3056        this.$_set(index as int, val)
3057    }
3058
3059    /**
3060     * Assigns val as element on index.
3061     *
3062     * @param val value to set
3063     *
3064     * @param index index to change
3065     */
3066    public $_set(index: int, val: int): void {
3067        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
3068        if (index < 0 || index >= this.lengthInt) {
3069            throw new RangeError("invalid index")
3070        }
3071        let v = this.zeroIfInfinity(val)
3072        this.setUnsafeClamp(index, v)
3073    }
3074
3075    /**
3076     * Makes a copy of internal elements to targetPos from startPos to endPos.
3077     *
3078     * @param target insert index to place copied elements
3079     *
3080     * @param start start index to begin copy from
3081     *
3082     * @param end last index to end copy from, excluded
3083     *
3084     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3085     */
3086    public copyWithin(target: number, start: number, end?: number): Uint8Array {
3087        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3088    }
3089
3090    /**
3091     * Makes a copy of internal elements to targetPos from startPos to endPos.
3092     *
3093     * @param target insert index to place copied elements
3094     *
3095     * @param start start index to begin copy from
3096     *
3097     * @param end last index to end copy from, excluded
3098     *
3099     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3100     */
3101    public copyWithin(target: int, start: number, end?: number): Uint8Array {
3102        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3103    }
3104
3105    /**
3106     * Makes a copy of internal elements to targetPos from startPos to endPos.
3107     *
3108     * @param target insert index to place copied elements
3109     *
3110     * @param start start index to begin copy from
3111     *
3112     * @param end last index to end copy from, excluded
3113     *
3114     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3115     */
3116    public copyWithin(target: number, start: int, end?: number): Uint8Array {
3117        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3118    }
3119
3120    /**
3121     * Makes a copy of internal elements to targetPos from startPos to endPos.
3122     *
3123     * @param target insert index to place copied elements
3124     *
3125     * @param start start index to begin copy from
3126     *
3127     * @param end last index to end copy from, excluded
3128     *
3129     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3130     */
3131    public copyWithin(target: int, start: int, end?: number): Uint8Array {
3132        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3133    }
3134
3135    /**
3136     * Makes a copy of internal elements to targetPos from startPos to endPos.
3137     *
3138     * @param insert insert index to place copied elements
3139     *
3140     * @param start start index to begin copy from
3141     *
3142     * @param end last index to end copy from, excluded
3143     *
3144     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3145     */
3146    public copyWithin(target: int, start: int, end: int): Uint8Array {
3147        let toPos = normalizeIndex(target, this.lengthInt)
3148        let fromPos = normalizeIndex(start, this.lengthInt)
3149        const finalPos = normalizeIndex(end, this.lengthInt)
3150        let count: int = finalPos - fromPos
3151        if (count > (this.lengthInt - toPos)) {
3152            count = this.lengthInt - toPos
3153        }
3154        let direction: int = 1
3155        if ((fromPos < toPos) && (toPos < fromPos + count)) {
3156            fromPos = fromPos + count - 1
3157            toPos   = toPos   + count - 1
3158            direction = -1
3159        }
3160        while (count > 0) {
3161            const value = this.getUnsafe(fromPos)
3162            this.setUnsafe(toPos, value)
3163            fromPos = fromPos + direction
3164            toPos = toPos + direction
3165            --count
3166        }
3167        return this
3168    }
3169
3170    /**
3171     * Makes a copy of internal elements to targetPos from begin to end of Uint8Array.
3172     *
3173     * @param target insert index to place copied elements
3174     *
3175     * See rules of parameters normalization:
3176     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
3177     */
3178    public copyWithin(target: number): Uint8Array {
3179        return this.copyWithin(target as int)
3180    }
3181
3182    /**
3183     * Makes a copy of internal elements to targetPos from begin to end of Uint8Array.
3184     *
3185     * @param insert insert index to place copied elements
3186     *
3187     * See rules of parameters normalization:
3188     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
3189     */
3190    public copyWithin(target: int): Uint8Array {
3191        return this.copyWithin(target, 0, this.lengthInt)
3192    }
3193
3194    /**
3195     * Returns an array of key, value pairs for every entry in the Uint8Array
3196     *
3197     * @returns key, value pairs for every entry in the array
3198     */
3199    public entries(): IterableIterator<[Number, Number]> {
3200        return new Uint8ArrayIteratorEntries(this)
3201    }
3202
3203    /**
3204     * Fills the Uint8Array with specified value
3205     *
3206     * @param value new value
3207     *
3208     * @returns modified Uint8Array
3209     */
3210    public fill(value: number, start?: number, end?: number): Uint8Array {
3211        value = this.zeroIfInfinity(value)
3212        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
3213        return this
3214    }
3215
3216    /**
3217     * Fills the Uint8Array with specified value
3218     *
3219     * @param value new value
3220     *
3221     * @returns modified Uint8Array
3222     */
3223    public fill(value: number, start: int, end?: number): Uint8Array {
3224        value = this.zeroIfInfinity(value)
3225        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
3226        return this
3227    }
3228
3229    /**
3230     * Fills the Uint8Array with specified value
3231     *
3232     * @param value new value
3233     *
3234     * @returns modified Uint8Array
3235     */
3236    public fill(value: number, start: int, end: number): Uint8Array {
3237        value = this.zeroIfInfinity(value)
3238        this.fill(value as int, start as int, end as int)
3239        return this
3240    }
3241
3242    /**
3243     * Fills the Uint8Array with specified value
3244     *
3245     * @param value new value
3246     *
3247     * @returns modified Uint8Array
3248     */
3249    public fill(value: number, start: number, end: int): Uint8Array {
3250        value = this.zeroIfInfinity(value)
3251        this.fill(value as int, start as int, end as int)
3252        return this
3253    }
3254
3255    /**
3256     * Fills the Uint8Array with specified value
3257     *
3258     * @param value new value
3259     *
3260     * @returns modified Uint8Array
3261     */
3262    public fill(value: number, start: int, end: int): Uint8Array {
3263        value = this.zeroIfInfinity(value)
3264        this.fill(value as int, start as int, end as int)
3265        return this
3266    }
3267
3268    /**
3269     * Fills the Uint8Array with specified value
3270     *
3271     * @param value new value
3272     *
3273     * @returns modified Uint8Array
3274     */
3275    public fill(value: int, start?: number, end?: number): Uint8Array {
3276        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
3277        return this
3278    }
3279
3280    /**
3281     * Fills the Uint8Array with specified value
3282     *
3283     * @param value new value
3284     *
3285     * @returns modified Uint8Array
3286     */
3287    public fill(value: int, start: int, end?: number): Uint8Array {
3288        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
3289        return this
3290    }
3291
3292    /**
3293     * Fills the Uint8Array with specified value
3294     *
3295     * @param value new value
3296     *
3297     * @returns modified Uint8Array
3298     */
3299    public fill(value: int, start: int, end: number): Uint8Array {
3300        this.fill(value, start as int, end as int)
3301        return this
3302    }
3303
3304    /**
3305     * Fills the Uint8Array with specified value
3306     *
3307     * @param value new value
3308     *
3309     * @returns modified Uint8Array
3310     */
3311    public fill(value: int, start: number, end: int): Uint8Array {
3312        this.fill(value, start as int, end as int)
3313        return this
3314    }
3315
3316    /**
3317     * Fills the Uint8Array with specified value
3318     *
3319     * @param value new value
3320     *
3321     * @returns modified Uint8Array
3322     */
3323    public fill(value: int, start: int, end: int): Uint8Array {
3324        const k = normalizeIndex(start, this.lengthInt)
3325        const finalPos = normalizeIndex(end, this.lengthInt)
3326        for (let i: int = k; i < finalPos; ++i) {
3327            this.setUnsafe(i, value)
3328        }
3329        return this
3330    }
3331
3332    /**
3333     * Assigns val as element on index.
3334     *
3335     * @param val value to set
3336     *
3337     * @param index index to change
3338     */
3339    public set(insertPos: number, val: number): void {
3340        this.$_set(insertPos as int, val)
3341    }
3342
3343    /**
3344     * Assigns val as element on index.
3345     *
3346     * @param val value to set
3347     *
3348     * @param index index to change
3349     */
3350    public set(insertPos: int, val: number): void {
3351        this.$_set(insertPos as int, val)
3352    }
3353
3354    /**
3355     * Assigns val as element on index.
3356     *
3357     * @param val value to set
3358     *
3359     * @param index index to change
3360     */
3361    public set(insertPos: number, val: int): void {
3362        this.$_set(insertPos as int, val)
3363    }
3364
3365    /**
3366     * Assigns val as element on index.
3367     *
3368     * @param val value to set
3369     *
3370     * @param index index to change
3371     */
3372    public set(insertPos: int, val: int): void {
3373        this.$_set(insertPos as int, val)
3374    }
3375
3376    /**
3377     * Copies all elements of arr to the current Uint8Array starting from insertPos.
3378     *
3379     * @param arr array to copy data from
3380     *
3381     * @param insertPos start index where data from arr will be inserted
3382     *
3383     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
3384     */
3385    public set(arr: number[], insertPos1: number): void {
3386        const insertPos = insertPos1 as int
3387        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
3388            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8Array.length")
3389        }
3390        for (let i = 0; i < arr.length; i++) {
3391            let v = this.zeroIfInfinity(arr[i])
3392            this.setUnsafeClamp(insertPos as int + i as int, v as int)
3393        }
3394    }
3395
3396    /**
3397     * Copies all elements of arr to the current Uint8Array starting from insertPos.
3398     *
3399     * @param arr array to copy data from
3400     *
3401     * @param insertPos start index where data from arr will be inserted
3402     *
3403     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
3404     */
3405    public set(arr: int[], insertPos: int): void {
3406        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
3407            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8Array.length")
3408        }
3409        for (let i = 0; i < arr.length; i++) {
3410            let v = this.zeroIfInfinity(arr[i])
3411            this.setUnsafeClamp(insertPos + i, v)
3412        }
3413    }
3414
3415    /**
3416     * Copies all elements of arr to the current Uint8Array.
3417     *
3418     * @param arr array to copy data from
3419     */
3420    public set(arr: number[]): void {
3421        this.set(arr, 0)
3422    }
3423
3424    /**
3425     * Copies all elements of arr to the current Uint8Array.
3426     *
3427     * @param arr array to copy data from
3428     */
3429    public set(arr: int[]): void {
3430        this.set(arr, 0)
3431    }
3432
3433    /**
3434     * Copies elements from an ArrayLike object to the Uint8Array.
3435     *
3436     * @param array An ArrayLike object containing the elements to copy.
3437     *
3438     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
3439     */
3440    public set(array: ArrayLike<number>, offset: number = 0): void {
3441        const insertPos = offset as int
3442        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
3443            throw new RangeError("offset is out of bounds")
3444        }
3445        for (let i = 0; i < array.length; i++) {
3446            let v = this.zeroIfInfinity(array[i])
3447            this.setUnsafeClamp(insertPos as int + i as int, v as int)
3448        }
3449    }
3450
3451    /**
3452     * Returns a new array from a set of elements.
3453     *
3454     * @param items a set of elements to include in the new array object.
3455     *
3456     * @returns new Uint8Array
3457     */
3458    public static of(...items: number[]): Uint8Array {
3459        let res = new Uint8Array(items.length as int)
3460        for (let i: int = 0; i < items.length; i++) {
3461            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as int)
3462        }
3463        return res
3464    }
3465
3466    /**
3467     * Returns a new array from a set of elements.
3468     *
3469     * @param items a set of elements to include in the new array object.
3470     *
3471     * @returns new Uint8Array
3472     */
3473    public static of(...items: int[]): Uint8Array {
3474        let res = new Uint8Array(items.length as int)
3475        for (let i: int = 0; i < items.length; i++) {
3476            res.setUnsafeClamp(i, items[i])
3477        }
3478        return res
3479    }
3480
3481    /**
3482     * Returns a new array from a set of elements.
3483     *
3484     * @param items a set of elements to include in the new array object.
3485     *
3486     * @returns new Uint8Array
3487     */
3488    public static of(...items: short[]): Uint8Array {
3489        let res = new Uint8Array(items.length as int)
3490        for (let i: int = 0; i < items.length; i++) {
3491            res.setUnsafeClamp(i, items[i] as int)
3492        }
3493        return res
3494    }
3495
3496    /**
3497     * Returns a new array from a set of elements.
3498     *
3499     * @param items a set of elements to include in the new array object.
3500     *
3501     * @returns new Uint8Array
3502     */
3503    public static of(): Uint8Array {
3504        return new Uint8Array(0 as int)
3505    }
3506
3507    /**
3508     * Creates an array from an array-like or iterable object.
3509     *
3510     * @param arrayLike An array-like or iterable object to convert to an array.
3511     *
3512     * @returns new Uint8Array
3513     */
3514    public static from(arr: ArrayLike<number>): Uint8Array {
3515        return Uint8Array.from<number>(arr, (x: number, k: number): number => x)
3516    }
3517
3518    /**
3519     * Creates an array from an array-like or iterable object.
3520     *
3521     * @param arrayLike An array-like or iterable object to convert to an array.
3522     *
3523     * @param mapfn A mapping function to call on every element of the array.
3524     *
3525     * @returns new Uint8Array
3526     */
3527    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint8Array {
3528        if (mapfn == undefined) {
3529            mapfn = (v: number, k: number): number => { return v }
3530        }
3531
3532        let iter = arrayLike.$_iterator()
3533        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
3534        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
3535        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
3536        //  we can make one pass through the iterator without the need for memory reallocation.
3537        const maybeLength = tryGetIteratorLength(arrayLike)
3538        if (maybeLength) {
3539            const result = new Uint8Array(maybeLength)
3540            for (let i = 0; i < maybeLength; ++i) {
3541                const x = iter.next()
3542                if (x.done) {
3543                    return new Uint8Array(result.buffer, 0, i)
3544                }
3545                result.setUnsafeClamp(i, result.zeroIfInfinity((mapfn)!(x.value!, i)) as int)
3546            }
3547            return result
3548        }
3549
3550        // NOTE (templin.konstantin): Create builtin array as buffer
3551        let temp = new Uint8Array(6)
3552        let index = new int[1]
3553        index[0] = 0
3554
3555        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
3556            if (index[0] + 1 > temp.lengthInt) {
3557                // NOTE (templin.konstantin): Progressive reallocation
3558                const curLength = (temp.buffer as Buffer).getByteLength()
3559                const tb = new ArrayBuffer(curLength * 2)
3560                for (let i = 0; i < curLength; ++i) {
3561                    tb.set(i, (temp.buffer as Buffer).at(i))
3562                }
3563                temp = new Uint8Array(tb)
3564            }
3565            temp.setUnsafeClamp(index[0], temp.zeroIfInfinity((mapfn)!(x, index[0])) as int)
3566            index[0]++
3567        })
3568
3569        return new Uint8Array(temp.buffer, 0, index[0])
3570    }
3571
3572    /**
3573     * Creates an array from an array-like or iterable object.
3574     *
3575     * @param arrayLike An array-like or iterable object to convert to an array.
3576     *
3577     * @param mapfn A mapping function to call on every element of the array.
3578     *
3579     * @returns new Uint8Array
3580     */
3581    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint8Array {
3582        let res = new Uint8Array(arrayLike.length)
3583        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
3584        const idx = new int[1]
3585        idx[0] = 0
3586        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
3587            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as int)
3588            idx[0] += 1
3589        })
3590        return res
3591    }
3592
3593    /**
3594     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
3595     *
3596     * @param searchElement The element to search for
3597     *
3598     * @param fromIndex The position in this array at which to begin searching for searchElement
3599     *
3600     * @returns true if searchElement is in Uint8Array, false otherwise
3601     */
3602    public includes(searchElement: number, fromIndex?: number): boolean {
3603        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
3604    }
3605
3606    /**
3607     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
3608     *
3609     * @param searchElement The element to search for
3610     *
3611     * @param fromIndex The position in this array at which to begin searching for searchElement
3612     *
3613     * @returns true if searchElement is in Uint8Array, false otherwise
3614     */
3615    public includes(searchElement: int, fromIndex: int): boolean {
3616        return this.indexOf(searchElement as int, fromIndex) != -1
3617    }
3618
3619    /**
3620     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
3621     *
3622     * @param searchElement The element to search for
3623     *
3624     * @param fromIndex The position in this array at which to begin searching for searchElement
3625     *
3626     * @returns true if searchElement is in Uint8Array, false otherwise
3627     */
3628    public includes(searchElement: int): boolean {
3629        return this.indexOf(searchElement as int, 0) != -1
3630    }
3631
3632    /**
3633     * Returns the index of the first occurrence of a value in Uint8Array.
3634     *
3635     * @param searchElement The value to locate in the array.
3636     *
3637     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3638     *  search starts at index 0.
3639     *
3640     * @returns index of element if it presents, -1 otherwise
3641     */
3642    public indexOf(searchElement: number, fromIndex?: number): number {
3643        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
3644    }
3645
3646    /**
3647     * Returns the index of the first occurrence of a value in Uint8Array.
3648     *
3649     * @param searchElement The value to locate in the array.
3650     *
3651     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3652     *  search starts at index 0.
3653     *
3654     * @returns index of element if it presents, -1 otherwise
3655     */
3656    public indexOf(searchElement: number, fromIndex: int): number {
3657        if (isNaN(searchElement)) {
3658            return -1
3659        }
3660        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
3661        for (let i = fromIndex; i < this.lengthInt; i++) {
3662            if (this.getUnsafe(i) as number == searchElement) {
3663                return i
3664            }
3665        }
3666        return -1
3667    }
3668
3669    /**
3670     * Returns the index of the first occurrence of a value in Uint8Array.
3671     *
3672     * @param searchElement The value to locate in the array.
3673     *
3674     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3675     *  search starts at index 0.
3676     *
3677     * @returns index of element if it presents, -1 otherwise
3678     */
3679    public indexOf(searchElement: int, fromIndex: int): number {
3680        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
3681        for (let i = fromIndex; i < this.lengthInt; i++) {
3682            if (this.getUnsafe(i) == searchElement) {
3683                return i
3684            }
3685        }
3686        return -1
3687
3688    }
3689
3690    /**
3691     * Returns the index of the first occurrence of a value in Uint8Array.
3692     *
3693     * @param searchElement The value to locate in the array.
3694     *
3695     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3696     *  search starts at index 0.
3697     *
3698     * @returns index of element if it presents, -1 otherwise
3699     */
3700    public indexOf(searchElement: int): number {
3701        return this.indexOf(searchElement, 0)
3702    }
3703
3704    /**
3705     * Adds all the elements of an array separated by the specified separator string
3706     *
3707     * @param separator A string used to separate one element of an array from the next in the
3708     * resulting String. If omitted, the array elements are separated with a comma
3709     *
3710     * @returns joined representation
3711     */
3712    public join(separator?: String): string {
3713        if (separator == undefined) {
3714            return this.join(",")
3715        }
3716        let res: StringBuilder = new StringBuilder("")
3717        for (let i = 0; i < this.lengthInt - 1; i++) {
3718            res.append(this.getUnsafe(i) as number)
3719            res.append(separator)
3720        }
3721        if (this.lengthInt > 0) {
3722            res.append(this.getUnsafe(this.lengthInt - 1) as number)
3723        }
3724        return res.toString()
3725    }
3726
3727    /**
3728     * Returns an list of keys in Uint8Array
3729     *
3730     * @returns iterator over keys
3731     */
3732    public keys(): IterableIterator<number> {
3733        return new Uint8ArrayIteratorKeys(this)
3734    }
3735
3736    /**
3737     * Returns the index of the last occurrence of a value in Uint8Array.
3738     *
3739     * @param searchElement The value to locate in the array.
3740     *
3741     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3742     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3743     *
3744     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3745     */
3746    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
3747        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
3748    }
3749
3750    /**
3751     * Returns the index of the last occurrence of a value in Uint8Array.
3752     *
3753     * @param searchElement The value to locate in the array.
3754     *
3755     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3756     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3757     *
3758     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3759     */
3760    public lastIndexOf(searchElement: number): number {
3761        return this.lastIndexOf(searchElement, this.lengthInt - 1)
3762    }
3763
3764    /**
3765     * Returns the index of the last occurrence of a value in Uint8Array.
3766     *
3767     * @param searchElement The value to locate in the array.
3768     *
3769     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3770     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3771     *
3772     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3773     */
3774    public lastIndexOf(searchElement: number, fromIndex: int): number {
3775        if (isNaN(searchElement)) {
3776            return -1
3777        }
3778        if (this.lengthInt == 0) {
3779            return -1
3780        }
3781        let k: int = this.lengthInt + fromIndex
3782        if (fromIndex >= 0) {
3783            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
3784        }
3785        while (k >= 0) {
3786            if (this.getUnsafe(k) as number == searchElement) {
3787                return k
3788            }
3789            k--
3790        }
3791        return -1
3792    }
3793
3794    /**
3795     * Returns the index of the last occurrence of a value in Uint8Array.
3796     *
3797     * @param searchElement The value to locate in the array.
3798     *
3799     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3800     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3801     *
3802     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3803     */
3804    public lastIndexOf(searchElement: int, fromIndex: int): number {
3805        if (this.lengthInt == 0) {
3806            return -1
3807        }
3808        let k: int = this.lengthInt + fromIndex
3809        if (fromIndex >= 0) {
3810            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
3811        }
3812        while (k >= 0) {
3813            if (this.getUnsafe(k) == searchElement) {
3814                return k
3815            }
3816            k--
3817        }
3818        return -1
3819    }
3820
3821    /**
3822     * Returns the index of the last occurrence of a value in Uint8Array.
3823     *
3824     * @param searchElement The value to locate in the array.
3825     *
3826     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3827     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3828     *
3829     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3830     */
3831    public lastIndexOf(searchElement: int): number {
3832        return this.lastIndexOf(searchElement, this.lengthInt - 1)
3833    }
3834
3835   /**
3836    * Creates a new Uint8Array using initializer
3837    *
3838    * @param data initializer
3839    *
3840    * @returns a new Uint8Array from data
3841    */
3842    public of(...data: number[]): Uint8Array {
3843        throw new Error("Uint8Array.of: not implemented")
3844    }
3845
3846    /**
3847     * Creates a new Uint8Array using reversed data from the current one
3848     *
3849     * @returns a new Uint8Array using reversed data from the current one
3850     */
3851    public reverse(): Uint8Array {
3852        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
3853            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
3854            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
3855            this.setUnsafe(i, tmp)
3856        }
3857        return this
3858    }
3859
3860    /**
3861     * Creates a slice of current Uint8Array using range [begin, end)
3862     *
3863     * @param begin start index to be taken into slice
3864     *
3865     * @param end last index to be taken into slice
3866     *
3867     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3868     *
3869     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3870     */
3871    public slice(begin?: number, end?: number): Uint8Array {
3872        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
3873    }
3874
3875    /**
3876     * Creates a slice of current Uint8Array using range [begin, end)
3877     *
3878     * @param begin start index to be taken into slice
3879     *
3880     * @param end last index to be taken into slice
3881     *
3882     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3883     *
3884     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3885     */
3886    public slice(begin: number, end: number): Uint8Array {
3887        return this.slice(begin as int, end as int)
3888    }
3889
3890    /**
3891     * Creates a slice of current Uint8Array using range [begin, end)
3892     *
3893     * @param begin start index to be taken into slice
3894     *
3895     * @param end last index to be taken into slice
3896     *
3897     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3898     *
3899     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3900     */
3901    public slice(begin: number, end: int): Uint8Array {
3902        return this.slice(begin as int, end as int)
3903    }
3904
3905    /**
3906     * Creates a slice of current Uint8Array using range [begin, end)
3907     *
3908     * @param begin start index to be taken into slice
3909     *
3910     * @param end last index to be taken into slice
3911     *
3912     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3913     *
3914     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3915     */
3916    public slice(begin: int, end: number): Uint8Array {
3917        return this.slice(begin as int, end as int)
3918    }
3919
3920    /**
3921     * Creates a slice of current Uint8Array using range [begin, end)
3922     *
3923     * @param begin start index to be taken into slice
3924     *
3925     * @param end last index to be taken into slice
3926     *
3927     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3928     *
3929     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3930     */
3931    public slice(begin: int, end: int): Uint8Array {
3932        const len: int = this.lengthInt
3933        const relStart = normalizeIndex(begin, len)
3934        const relEnd = normalizeIndex(end, len)
3935        let count = relEnd - relStart
3936        if (count < 0) {
3937            count = 0
3938        }
3939        if (this.buffer instanceof ArrayBuffer) {
3940            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint8Array.BYTES_PER_ELEMENT as int, relEnd * Uint8Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
3941            return new Uint8Array(buf)
3942        } else if (this.buffer instanceof SharedArrayBuffer) {
3943            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint8Array.BYTES_PER_ELEMENT as int, relEnd * Uint8Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
3944            return new Uint8Array(buf)
3945        } else {
3946            throw new Error("unexpected type of buffer")
3947        }
3948    }
3949
3950    /**
3951     * Creates a slice of current Uint8Array using range [begin, this.lengthInt).
3952     *
3953     * @param begin start index to be taken into slice
3954     *
3955     * @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)
3956     */
3957    public slice(begin: number): Uint8Array {
3958        return this.slice(begin as int)
3959    }
3960
3961    /**
3962     * Creates a slice of current Uint8Array using range [begin, this.lengthInt).
3963     *
3964     * @param begin start index to be taken into slice
3965     *
3966     * @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)
3967     */
3968    public slice(begin: int): Uint8Array {
3969        return this.slice(begin, this.lengthInt)
3970    }
3971
3972    /**
3973     * Sorts in-place
3974     *
3975     * @param compareFn comparator —  used to determine the order of the elements.
3976     * compareFn returns a negative value if first argument is less than second argument,
3977     * zero if they're equal and a positive value otherwise.
3978     * If omitted, the elements are sorted in ascending order.
3979     *
3980     * @returns sorted Uint8Array
3981     */
3982    public sort(compareFn?: (a: number, b: number) => number): this {
3983        let arr: int[] = new int[this.lengthInt]
3984        for (let i = 0; i < this.lengthInt; ++i) {
3985            arr[i] = this.getUnsafe(i)
3986        }
3987        let cmp = (l: int, r: int): number => {
3988                return (l - r) as number
3989            }
3990        if (compareFn != undefined) {
3991            cmp = (l: int, r: int): number => {
3992                return compareFn!(l as number, r as number)
3993            }
3994        }
3995        sort(arr, cmp)
3996        for (let i = 0; i < this.lengthInt; ++i) {
3997            this.setUnsafe(i, arr[i])
3998        }
3999        return this
4000    }
4001
4002    /**
4003     * Sorts in-place
4004     *
4005     * @param compareFn comparator —  used to determine the order of the elements.
4006     * compareFn returns a negative value if first argument is less than second argument,
4007     * zero if they're equal and a positive value otherwise.
4008     *
4009     * @returns sorted Uint8Array
4010     */
4011    public sort(compareFn: (a: number) => number): this {
4012        let cmp = (a: number, b: number) => { return compareFn(a)}
4013        this.sort(cmp)
4014        return this
4015    }
4016
4017    /**
4018     * Sorts in-place
4019     *
4020     * @param fn compareFn —  used to determine the order of the elements.
4021     * compareFn returns a negative value if first argument is less than second argument,
4022     * zero if they're equal and a positive value otherwise.
4023     *
4024     * @returns sorted Uint8Array
4025     */
4026    public sort(compareFn: () => number): this {
4027        let cmp = (a: number, b: number) => { return compareFn()}
4028        this.sort(cmp)
4029        return this
4030    }
4031    /**
4032     * Creates a Uint8Array with the same underlying Buffer
4033     *
4034     * @param begin start index, inclusive
4035     *
4036     * @param end last index, exclusive
4037     *
4038     * @returns new Uint8Array with the same underlying Buffer
4039     */
4040    public subarray(begin?: number, end?: number): Uint8Array {
4041        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
4042    }
4043
4044    /**
4045     * Creates a Uint8Array with the same underlying Buffer
4046     *
4047     * @param begin start index, inclusive
4048     *
4049     * @param end last index, exclusive
4050     *
4051     * @returns new Uint8Array with the same underlying Buffer
4052     */
4053    public subarray(begin: number, end: number): Uint8Array {
4054        return this.subarray(begin as int, end as int)
4055    }
4056
4057    /**
4058     * Creates a Uint8Array with the same underlying Buffer
4059     *
4060     * @param begin start index, inclusive
4061     *
4062     * @param end last index, exclusive
4063     *
4064     * @returns new Uint8Array with the same underlying Buffer
4065     */
4066    public subarray(begin: number, end: int): Uint8Array {
4067        return this.subarray(begin as int, end as int)
4068    }
4069
4070    /**
4071     * Creates a Uint8Array with the same underlying Buffer
4072     *
4073     * @param begin start index, inclusive
4074     *
4075     * @param end last index, exclusive
4076     *
4077     * @returns new Uint8Array with the same underlying Buffer
4078     */
4079    public subarray(begin: int, end: number): Uint8Array {
4080        return this.subarray(begin as int, end as int)
4081    }
4082
4083    /**
4084     * Creates a Uint8Array with the same underlying Buffer
4085     *
4086     * @param begin start index, inclusive
4087     *
4088     * @param end last index, exclusive
4089     *
4090     * @returns new Uint8Array with the same underlying Buffer
4091     */
4092    public subarray(begin: int, end: int): Uint8Array {
4093        const len: int = this.lengthInt
4094        const relStart = normalizeIndex(begin, len)
4095        const relEnd = normalizeIndex(end, len)
4096        let count = relEnd - relStart
4097        if (count < 0) {
4098            count = 0
4099        }
4100        return new Uint8Array(this.buffer, relStart * Uint8Array.BYTES_PER_ELEMENT as int, count)
4101    }
4102
4103    /**
4104     * Creates a Uint8Array with the same Buffer
4105     *
4106     * @param begin start index, inclusive
4107     *
4108     * @returns new Uint8Array with the same Buffer
4109     */
4110    public subarray(begin: number): Uint8Array {
4111        return this.subarray(begin as int, this.lengthInt)
4112    }
4113
4114    /**
4115     * Creates a Uint8Array with the same Buffer
4116     *
4117     * @param begin start index, inclusive
4118     *
4119     * @returns new Uint8Array with the same Buffer
4120     */
4121    public subarray(begin: int): Uint8Array {
4122        return this.subarray(begin, this.lengthInt)
4123    }
4124
4125    /**
4126     * Converts Uint8Array to a string with respect to locale
4127     *
4128     * @param locales
4129     *
4130     * @param options
4131     *
4132     * @returns string representation
4133     */
4134    public toLocaleString(locales: Object, options: Object): string {
4135        throw new Error("Uint8Array.toLocaleString: not implemented")
4136    }
4137
4138    /**
4139     * Converts Uint8Array to a string with respect to locale
4140     *
4141     * @param locales
4142     *
4143     * @returns string representation
4144     */
4145    public toLocaleString(locales: Object): string {
4146        return this.toLocaleString(new Object(), new Object())
4147    }
4148
4149    /**
4150     * Converts Uint8Array to a string with respect to locale
4151     *
4152     * @returns string representation
4153     */
4154    public toLocaleString(): string {
4155        let res: StringBuilder = new StringBuilder("")
4156        for (let i = 0; i < this.lengthInt - 1; ++i) {
4157            res.append((this.getUnsafe(i) as Number).toLocaleString())
4158            res.append(",")
4159        }
4160        if (this.lengthInt > 0) {
4161            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
4162        }
4163        return res.toString()
4164    }
4165
4166    /**
4167     * Creates a reversed copy
4168     *
4169     * @returns a reversed copy
4170     */
4171    public toReversed(): Uint8Array {
4172        return new Uint8Array(this).reverse()
4173    }
4174
4175    /**
4176     * Creates a sorted copy
4177     *
4178     * @returns a sorted copy
4179     */
4180    public toSorted(): Uint8Array {
4181        return new Uint8Array(this).sort()
4182    }
4183
4184    /**
4185     * Returns a string representation of the Uint8Array
4186     *
4187     * @returns a string representation of the Uint8Array
4188     */
4189    public override toString(): string {
4190        return this.join(",")
4191    }
4192
4193    /**
4194     * Returns array values iterator
4195     *
4196     * @returns an iterator
4197     */
4198    public values(): IterableIterator<Number> {
4199         return new Uint8ArrayIterator(this)
4200    }
4201
4202    /**
4203     * Creates a copy with replaced value on index
4204     *
4205     * @param index
4206     *
4207     * @param value
4208     *
4209     * @returns an Uint8Array with replaced value on index
4210     */
4211    public with(index: number, value: number): Uint8Array {
4212        return this.with(index as int, value as int)
4213    }
4214
4215    /**
4216     * Creates a copy with replaced value on index
4217     *
4218     * @param index
4219     *
4220     * @param value
4221     *
4222     * @returns an Uint8Array with replaced value on index
4223     */
4224    public with(index: int, value: int): Uint8Array {
4225        let res = new Uint8Array(this)
4226        res.setUnsafeClamp(index, value)
4227        return res
4228    }
4229
4230    /// === with element lambda functions ===
4231
4232    /**
4233     * Determines whether the specified callback function returns true for all elements of an array.
4234     *
4235     * @param predicate A function that accepts one argument.
4236     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4237     * or until the end of the array.
4238     *
4239     * @returns true unless predicate function returns a false for an array element,
4240     * in which case false is immediately returned.
4241     */
4242    public every(predicate: (element: number) => boolean): boolean {
4243        return this.every((element: number, index: number, array: Uint8Array): boolean => predicate(element))
4244    }
4245
4246    /**
4247     * creates a new Uint8Array from current Uint8Array based on a condition fn
4248     *
4249     * @param fn the condition to apply for each element
4250     *
4251     * @returns a new Uint8Array with elements from current Uint8Array that satisfy condition fn
4252     */
4253    public filter(fn: (val: number) => boolean): Uint8Array {
4254        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4255            (val: number, index: number, array: Uint8Array): boolean => { return fn(val) }
4256        return this.filter(newF)
4257    }
4258
4259    /**
4260     * Returns the value of the first element in the array where predicate is true, and undefined
4261     * otherwise
4262     *
4263     * @param predicate find calls predicate once for each element of the array, in ascending
4264     * order, until it finds one where predicate returns true. If such an element is found, find
4265     * immediately returns that element value. Otherwise, find returns undefined
4266     *
4267     * @returns number | undefined
4268     */
4269    public find(predicate: () => boolean): number | undefined {
4270        return this.find((value: number, index: number, obj: Uint8Array): boolean => predicate())
4271    }
4272
4273    /**
4274     * Returns the value of the first element in the array where predicate is true, and undefined
4275     * otherwise
4276     *
4277     * @param predicate find calls predicate once for each element of the array, in ascending
4278     * order, until it finds one where predicate returns true. If such an element is found, find
4279     * immediately returns that element value. Otherwise, find returns undefined
4280     *
4281     * @returns number | undefined
4282     */
4283    public find(predicate: (value: number) => boolean): number | undefined {
4284        return this.find((value: number, index: number, obj: Uint8Array): boolean => predicate(value))
4285    }
4286
4287    /**
4288     * Returns the index of the first element in the array where predicate is true, and -1
4289     * otherwise
4290     *
4291     * @param predicate find calls predicate once for each element of the array, in ascending
4292     * order, until it finds one where predicate returns true. If such an element is found,
4293     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
4294     *
4295     * @returns number
4296     */
4297    public findIndex(predicate: (value: number) => boolean): number {
4298        return this.findIndex((value: number, index: number, obj: Uint8Array): boolean => predicate(value)) as number
4299    }
4300
4301    /**
4302     * Finds the last element in the Uint8Array that satisfies the condition
4303     *
4304     * @param fn condition
4305     *
4306     * @returns the last element that satisfies fn
4307     */
4308    public findLast(fn: (val: number) => boolean): number {
4309        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4310            (val: number, index: number, array: Uint8Array): boolean => { return fn(val) }
4311        return this.findLast(newF)
4312    }
4313
4314    /**
4315     * Finds an index of the last element in the Uint8Array that satisfies the condition
4316     *
4317     * @param fn condition
4318     *
4319     * @returns the index of the last element that satisfies fn, -1 otherwise
4320     */
4321    public findLastIndex(fn: (val: number) => boolean): number {
4322        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4323            (val: number, index: number, array: Uint8Array): boolean => { return fn(val) }
4324        return this.findLastIndex(newF) as number
4325    }
4326
4327    /**
4328     * Performs the specified action for each element in Uint8Array
4329     *
4330     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
4331     * callbackfn function one time for each element in the array.
4332     *
4333     * @returns None
4334     */
4335    public forEach(callbackfn: (val: number) => void): void {
4336        this.forEach((value: number, index: number, array: Uint8Array): void => callbackfn(value))
4337    }
4338
4339
4340    /**
4341     * Determines whether the specified callback function returns true for any element of an array.
4342     *
4343     * @param predicate A function that accepts one argument.
4344     * The some method calls the predicate function for each element in the array
4345     * until the predicate returns a true or until the end of the array.
4346     *
4347     * @returns false unless predicate function returns true for an array element,
4348     * in which case true is immediately returned.
4349     */
4350    public some(predicate: (element: number) => boolean): boolean {
4351        return this.some((element: number, index: number, array: Uint8Array): boolean => predicate(element))
4352    }
4353
4354    /**
4355     * Determines whether the specified callback function returns true for any element of an array.
4356     *
4357     * @param predicate A function that accepts three arguments.
4358     * The some method calls the predicate function for each element in the array
4359     * until the predicate returns a true or until the end of the array.
4360     *
4361     * @returns false unless predicate function returns true for an array element,
4362     * in which case true is immediately returned.
4363     */
4364    public some(predicate: (element: number, index: number, array: Uint8Array) => boolean): boolean {
4365        for (let i = 0; i < this.lengthInt; i++) {
4366            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
4367                return true
4368            }
4369        }
4370        return false
4371    }
4372
4373    /**
4374     * Determines whether the specified callback function returns true for any element of an array.
4375     *
4376     * @param predicate A function that accepts two arguments.
4377     * The some method calls the predicate function for each element in the array
4378     * until the predicate returns a true or until the end of the array.
4379     *
4380     * @returns false unless predicate function returns true for an array element,
4381     * in which case true is immediately returned.
4382     */
4383    public some(predicate: (element: number, index: number) => boolean): boolean {
4384        return this.some((element: number, index: number, array: Uint8Array): boolean => predicate(element, index))
4385    }
4386
4387    /**
4388     * Determines whether the specified callback function returns true for any element of an array.
4389     *
4390     * @param predicate A function that accepts no arguments.
4391     * The some method calls the predicate function for each element in the array
4392     * until the predicate returns a true or until the end of the array.
4393     *
4394     * @returns false unless predicate function returns true for an array element,
4395     * in which case true is immediately returned.
4396     */
4397    public some(predicate: () => boolean): boolean {
4398        return this.some((element: number, index: number, array: Uint8Array): boolean => predicate())
4399    }
4400
4401    /**
4402     * Calls the specified callback function for all the elements in an array.
4403     * The return value of the callback function is the accumulated result,
4404     * and is provided as an argument in the next call to the callback function.
4405     *
4406     * @param callbackfn A function that accepts four arguments.
4407     * The reduce method calls the callbackfn function one time for each element in the array.
4408     *
4409     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4410     * The first call to the callbackfn function provides this value as an argument.
4411     *
4412     * @returns The value that results from running the callback function to completion over the entire typed array.
4413     */
4414    public reduce<U = number>(
4415                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U,
4416                initialValue: U): U {
4417        let accumulatedValue = initialValue
4418        for (let i = 0; i < this.lengthInt; i++) {
4419            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4420        }
4421        return accumulatedValue
4422    }
4423
4424    /**
4425     * Calls the specified callback function for all the elements in an array.
4426     * The return value of the callback function is the accumulated result,
4427     * and is provided as an argument in the next call to the callback function.
4428     *
4429     * @param callbackfn A function that accepts three arguments.
4430     * The reduce method calls the callbackfn function one time for each element in the array.
4431     *
4432     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4433     * The first call to the callbackfn function provides this value as an argument.
4434     *
4435     * @returns The value that results from running the callback function to completion over the entire typed array.
4436     */
4437    public reduce<U = number>(
4438                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
4439                initialValue: U): U {
4440        return this.reduce(
4441                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4442                        callbackfn(prevVal, currVal, currIndex),
4443                initialValue)
4444    }
4445
4446    /**
4447     * Calls the specified callback function for all the elements in an array.
4448     * The return value of the callback function is the accumulated result,
4449     * and is provided as an argument in the next call to the callback function.
4450     *
4451     * @param callbackfn A function that accepts two arguments.
4452     * The reduce method calls the callbackfn function one time for each element in the array.
4453     *
4454     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4455     * The first call to the callbackfn function provides this value as an argument.
4456     *
4457     * @returns The value that results from running the callback function to completion over the entire typed array.
4458     */
4459    public reduce<U = number>(
4460                callbackfn: (previousValue: U, currentValue: number) => U,
4461                initialValue: U): U {
4462        return this.reduce(
4463                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4464                        callbackfn(prevVal, currVal),
4465                initialValue)
4466    }
4467
4468    /**
4469     * Calls the specified callback function for all the elements in an array.
4470     * The return value of the callback function is the accumulated result,
4471     * and is provided as an argument in the next call to the callback function.
4472     *
4473     * @param callbackfn A function that accepts one argument
4474     * The reduce method calls the callbackfn function one time for each element in the array.
4475     *
4476     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4477     * The first call to the callbackfn function provides this value as an argument.
4478     *
4479     * @returns The value that results from running the callback function to completion over the entire typed array.
4480     */
4481    public reduce<U = number>(
4482                callbackfn: (previousValue: U) => U,
4483                initialValue: U): U {
4484        return this.reduce(
4485                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4486                        callbackfn(prevVal),
4487                initialValue)
4488    }
4489
4490    /**
4491     * Calls the specified callback function for all the elements in an array.
4492     * The return value of the callback function is the accumulated result,
4493     * and is provided as an argument in the next call to the callback function.
4494     *
4495     * @param callbackfn A function that accepts no arguments
4496     * The reduce method calls the callbackfn function one time for each element in the array.
4497     *
4498     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4499     * The first call to the callbackfn function provides this value as an argument.
4500     *
4501     * @returns The value that results from running the callback function to completion over the entire typed array.
4502     */
4503    public reduce<U = number>(
4504                callbackfn: () => U,
4505                initialValue: U): U {
4506        return this.reduce(
4507                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4508                        callbackfn(),
4509                initialValue)
4510    }
4511
4512    /**
4513     * Calls the specified callback function for all the elements in an array.
4514     * The return value of the callback function is the accumulated result,
4515     * and is provided as an argument in the next call to the callback function.
4516     *
4517     * @param callbackfn A function that accepts four arguments.
4518     * The reduce method calls the callbackfn function one time for each element in the array.
4519     * The first call to the callbackfn function provides array first element value as an argument
4520     *
4521     * @returns The value that results from running the callback function to completion over the entire typed array.
4522     * calling reduce method on an empty array without an initial value creates a TypeError
4523     */
4524    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number {
4525        if (this.lengthInt == 0) {
4526            throw new TypeError("Reduce of empty array with no initial value")
4527        }
4528
4529        let accumulatedValue = this.$_get(0) as number
4530        for (let i = 1; i < this.lengthInt; i++) {
4531            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4532        }
4533        return accumulatedValue
4534    }
4535
4536    /**
4537     * Calls the specified callback function for all the elements in an array.
4538     * The return value of the callback function is the accumulated result,
4539     * and is provided as an argument in the next call to the callback function.
4540     *
4541     * @param callbackfn A function that accepts three arguments.
4542     * The reduce method calls the callbackfn function one time for each element in the array.
4543     * The first call to the callbackfn function provides array first element value as an argument
4544     *
4545     * @returns The value that results from running the callback function to completion over the entire typed array.
4546     * calling reduce method on an empty array without an initial value creates a TypeError
4547     */
4548    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
4549        return this.reduce(
4550                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4551                        callbackfn(prevVal, currVal, currIndex))
4552    }
4553
4554    /**
4555     * Calls the specified callback function for all the elements in an array.
4556     * The return value of the callback function is the accumulated result,
4557     * and is provided as an argument in the next call to the callback function.
4558     *
4559     * @param callbackfn A function that accepts two arguments.
4560     * The reduce method calls the callbackfn function one time for each element in the array.
4561     * The first call to the callbackfn function provides array first element value as an argument
4562     *
4563     * @returns The value that results from running the callback function to completion over the entire typed array.
4564     * calling reduce method on an empty array without an initial value creates a TypeError
4565     */
4566    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
4567        return this.reduce(
4568                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4569                        callbackfn(prevVal, currVal))
4570    }
4571
4572    /**
4573     * Calls the specified callback function for all the elements in an array.
4574     * The return value of the callback function is the accumulated result,
4575     * and is provided as an argument in the next call to the callback function.
4576     *
4577     * @param callbackfn A function that accepts one argument.
4578     * The reduce method calls the callbackfn function one time for each element in the array.
4579     * The first call to the callbackfn function provides array first element value as an argument
4580     *
4581     * @returns The value that results from running the callback function to completion over the entire typed array.
4582     * calling reduce method on an empty array without an initial value creates a TypeError
4583     */
4584    public reduce(callbackfn: (previousValue: number) => number): number {
4585        return this.reduce(
4586                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4587                        callbackfn(prevVal))
4588    }
4589
4590    /**
4591     * Calls the specified callback function for all the elements in an array.
4592     * The return value of the callback function is the accumulated result,
4593     * and is provided as an argument in the next call to the callback function.
4594     *
4595     * @param callbackfn A function that accepts no arguments.
4596     * The reduce method calls the callbackfn function one time for each element in the array.
4597     * The first call to the callbackfn function provides array first element value as an argument
4598     *
4599     * @returns The value that results from running the callback function to completion over the entire typed array.
4600     * calling reduce method on an empty array without an initial value creates a TypeError
4601     */
4602    public reduce(callbackfn: () => number): number {
4603        return this.reduce(
4604                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4605                        callbackfn())
4606    }
4607
4608    /**
4609     * Calls the specified callback function for all the elements in an array, in descending order.
4610     * The return value of the callback function is the accumulated result,
4611     * and is provided as an argument in the next call to the callback function.
4612     *
4613     * @param callbackfn A function that accepts four arguments.
4614     * The reduceRight method calls the callbackfn function one time for each element in the array.
4615     *
4616     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4617     * The first call to the callbackfn function provides this value as an argument.
4618     *
4619     * @returns The value that results from running the callback function to completion over the entire typed array.
4620     */
4621    public reduceRight<U = number>(
4622                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U,
4623                initialValue: U): U {
4624        let accumulatedValue = initialValue
4625        for (let i = this.lengthInt - 1; i >= 0; i--) {
4626            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4627        }
4628        return accumulatedValue
4629    }
4630
4631    /**
4632     * Calls the specified callback function for all the elements in an array, in descending order.
4633     * The return value of the callback function is the accumulated result,
4634     * and is provided as an argument in the next call to the callback function.
4635     *
4636     * @param callbackfn A function that accepts three arguments.
4637     * The reduceRight method calls the callbackfn function one time for each element in the array.
4638     *
4639     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4640     * The first call to the callbackfn function provides this value as an argument.
4641     *
4642     * @returns The value that results from running the callback function to completion over the entire typed array.
4643     */
4644    public reduceRight<U = number>(
4645                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
4646                initialValue: U): U {
4647        return this.reduceRight(
4648                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4649                        callbackfn(prevVal, currVal, currIndex),
4650                initialValue)
4651    }
4652
4653    /**
4654     * Calls the specified callback function for all the elements in an array, in descending order.
4655     * The return value of the callback function is the accumulated result,
4656     * and is provided as an argument in the next call to the callback function.
4657     *
4658     * @param callbackfn A function that accepts two arguments.
4659     * The reduceRight method calls the callbackfn function one time for each element in the array.
4660     *
4661     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4662     * The first call to the callbackfn function provides this value as an argument.
4663     *
4664     * @returns The value that results from running the callback function to completion over the entire typed array.
4665     */
4666    public reduceRight<U = number>(
4667                callbackfn: (previuosValue: U, currentValue: number) => U,
4668                initialValue: U): U {
4669        return this.reduceRight(
4670                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4671                        callbackfn(prevVal, currVal),
4672                initialValue)
4673    }
4674
4675    /**
4676     * Calls the specified callback function for all the elements in an array, in descending order.
4677     * The return value of the callback function is the accumulated result,
4678     * and is provided as an argument in the next call to the callback function.
4679     *
4680     * @param callbackfn A function that accepts one argument.
4681     * The reduceRight method calls the callbackfn function one time for each element in the array.
4682     *
4683     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4684     * The first call to the callbackfn function provides this value as an argument.
4685     *
4686     * @returns The value that results from running the callback function to completion over the entire typed array.
4687     */
4688    public reduceRight<U = number>(
4689                callbackfn: (previuosValue: U) => U,
4690                initialValue: U): U {
4691        return this.reduceRight(
4692                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4693                        callbackfn(prevVal),
4694                initialValue)
4695    }
4696
4697    /**
4698     * Calls the specified callback function for all the elements in an array, in descending order.
4699     * The return value of the callback function is the accumulated result,
4700     * and is provided as an argument in the next call to the callback function.
4701     *
4702     * @param callbackfn A function that accepts no arguments.
4703     * The reduceRight method calls the callbackfn function one time for each element in the array.
4704     *
4705     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4706     * The first call to the callbackfn function provides this value as an argument.
4707     *
4708     * @returns The value that results from running the callback function to completion over the entire typed array.
4709     */
4710    public reduceRight<U = number>(
4711                callbackfn: () => U,
4712                initialValue: U): U {
4713        return this.reduceRight(
4714                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4715                        callbackfn(),
4716                initialValue)
4717    }
4718
4719    /**
4720     * Calls the specified callback function for all the elements in an array, in descending order.
4721     * The return value of the callback function is the accumulated result,
4722     * and is provided as an argument in the next call to the callback function.
4723     *
4724     * @param callbackfn A function that accepts four arguments.
4725     * The reduceRight method calls the callbackfn function one time for each element in the array.
4726     * The first call to the callbackfn function provides array last element value as an argument
4727     *
4728     * @returns The value that results from running the callback function to completion over the entire typed array.
4729     * calling reduceRight method on an empty array without an initial value creates a TypeError
4730     */
4731    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number {
4732        if (this.lengthInt == 0) {
4733            throw new TypeError("Reduce of empty array with no initial value")
4734        }
4735
4736        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
4737        for (let i = this.lengthInt - 2; i >= 0; i--) {
4738            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4739        }
4740        return accumulatedValue
4741    }
4742
4743    /**
4744     * Calls the specified callback function for all the elements in an array, in descending order.
4745     * The return value of the callback function is the accumulated result,
4746     * and is provided as an argument in the next call to the callback function.
4747     *
4748     * @param callbackfn A function that accepts three arguments.
4749     * The reduceRight method calls the callbackfn function one time for each element in the array.
4750     * The first call to the callbackfn function provides array last element value as an argument
4751     *
4752     * @returns The value that results from running the callback function to completion over the entire typed array.
4753     * calling reduceRight method on an empty array without an initial value creates a TypeError
4754     */
4755    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
4756        return this.reduceRight(
4757                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4758                        callbackfn(prevValue, currValue, currIndex))
4759    }
4760
4761    /**
4762     * Calls the specified callback function for all the elements in an array, in descending order.
4763     * The return value of the callback function is the accumulated result,
4764     * and is provided as an argument in the next call to the callback function.
4765     *
4766     * @param callbackfn A function that accepts two arguments.
4767     * The reduceRight method calls the callbackfn function one time for each element in the array.
4768     * The first call to the callbackfn function provides array last element value as an argument
4769     *
4770     * @returns The value that results from running the callback function to completion over the entire typed array.
4771     * calling reduceRight method on an empty array without an initial value creates a TypeError
4772     */
4773    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
4774        return this.reduceRight(
4775                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4776                        callbackfn(prevValue, currValue))
4777    }
4778
4779    /**
4780     * Calls the specified callback function for all the elements in an array, in descending order.
4781     * The return value of the callback function is the accumulated result,
4782     * and is provided as an argument in the next call to the callback function.
4783     *
4784     * @param callbackfn A function that accepts one argument.
4785     * The reduceRight method calls the callbackfn function one time for each element in the array.
4786     * The first call to the callbackfn function provides array last element value as an argument
4787     *
4788     * @returns The value that results from running the callback function to completion over the entire typed array.
4789     * calling reduceRight method on an empty array without an initial value creates a TypeError
4790     */
4791    public reduceRight(callbackfn: (previousValue: number) => number): number {
4792        return this.reduceRight(
4793                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4794                        callbackfn(prevValue))
4795    }
4796
4797    /**
4798     * Calls the specified callback function for all the elements in an array, in descending order.
4799     * The return value of the callback function is the accumulated result,
4800     * and is provided as an argument in the next call to the callback function.
4801     *
4802     * @param callbackfn A function that accepts no arguments.
4803     * The reduceRight method calls the callbackfn function one time for each element in the array.
4804     * The first call to the callbackfn function provides array last element value as an argument
4805     *
4806     * @returns The value that results from running the callback function to completion over the entire typed array.
4807     * calling reduceRight method on an empty array without an initial value creates a TypeError
4808     */
4809    public reduceRight(callbackfn: () => number): number {
4810        return this.reduceRight(
4811                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4812                        callbackfn())
4813    }
4814
4815    /**
4816     * Creates a new Uint8Array using fn(arr[i]) over all elements of current Uint8Array.
4817     *
4818     * @param fn a function to apply for each element of current Uint8Array
4819     *
4820     * @returns a new Uint8Array where for each element from current Uint8Array fn was applied
4821     */
4822    public map(fn: (val: number, index: number, array: Uint8Array) => number): Uint8Array {
4823        let resBuf = new ArrayBuffer(this.lengthInt * Uint8Array.BYTES_PER_ELEMENT as int)
4824        let res = new Uint8Array(resBuf)
4825        for (let i = 0; i < this.lengthInt; i++) {
4826            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
4827            res.setUnsafeClamp(i, fnRes as int)
4828        }
4829        return res
4830    }
4831
4832    /**
4833     * Creates a new Uint8Array using fn(arr[i], i) over all elements of current Uint8Array
4834     *
4835     * @param fn a function to apply for each element of current Uint8Array
4836     *
4837     * @returns a new Uint8Array where for each element from current Uint8Array fn was applied
4838     */
4839    public map(fn: (val: number, index: number) => number): Uint8Array {
4840        let newF: (val: number, index: number, array: Uint8Array) => number =
4841            (val: number, index: number, array: Uint8Array): number => { return fn(val, index) }
4842        return this.map(newF)
4843    }
4844
4845    /**
4846     * Creates a new Uint8Array using fn(arr[i]) over all elements of current Uint8Array
4847     *
4848     * @param fn a function to apply for each element of current Uint8Array
4849     *
4850     * @returns a new Uint8Array where for each element from current Uint8Array fn was applied
4851     */
4852    public map(fn: (val: number) => number): Uint8Array {
4853        let newF: (val: number, index: number, array: Uint8Array) => number =
4854            (val: number, index: number, array: Uint8Array): number => { return fn(val) }
4855        return this.map(newF)
4856    }
4857
4858    /**
4859     * Creates a new Uint8Array using fn() over all elements of current Uint8Array
4860     *
4861     * @param fn a function to apply for each element of current Uint8Array
4862     *
4863     * @returns a new Uint8Array where for each element from current Uint8Array fn was applied
4864     */
4865    public map(fn: () => number): Uint8Array {
4866        let newF: (val: number, index: number, array: Uint8Array) => number =
4867            (val: number, index: number, array: Uint8Array): number => { return fn() }
4868        return this.map(newF)
4869    }
4870
4871    /**
4872     * Determines whether the specified callback function returns true for all elements of an array.
4873     *
4874     * @param predicate A function that accepts three arguments.
4875     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4876     * or until the end of the array.
4877     *
4878     * @returns true unless predicate function returns a false for an array element,
4879     * in which case false is immediately returned.
4880     */
4881    public every(predicate: (element: number, index: number, array: Uint8Array) => boolean): boolean {
4882        for (let i = 0; i < this.lengthInt; i++) {
4883            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
4884                return false
4885            }
4886        }
4887        return true
4888    }
4889
4890    /**
4891     * Determines whether the specified callback function returns true for all elements of an array.
4892     *
4893     * @param predicate A function that accepts two arguments.
4894     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4895     * or until the end of the array.
4896     *
4897     * @returns true unless predicate function returns a false for an array element,
4898     * in which case false is immediately returned.
4899     */
4900    public every(predicate: (element: number, index: number) => boolean): boolean {
4901        return this.every((element: number, index: number, array: Uint8Array): boolean => predicate(element, index))
4902    }
4903
4904    /**
4905     * Determines whether the specified callback function returns true for all elements of an array.
4906     *
4907     * @param predicate A function that accepts no arguments.
4908     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4909     * or until the end of the array.
4910     *
4911     * @returns true unless predicate function returns a false for an array element,
4912     * in which case false is immediately returned.
4913     */
4914    public every(predicate: () => boolean): boolean {
4915        return this.every((element: number, index: number, array: Uint8Array): boolean => predicate())
4916    }
4917
4918    /**
4919     * Creates a new Uint8Array from current Uint8Array based on a condition fn.
4920     *
4921     * @param fn the condition to apply for each element
4922     *
4923     * @returns a new Uint8Array with elements from current Uint8Array that satisfy condition fn
4924     */
4925    public filter(fn: (val: number, index: number, array: Uint8Array) => boolean): Uint8Array {
4926        let markers = new boolean[this.lengthInt]
4927        let resLen = 0
4928        for (let i = 0; i < this.lengthInt; i++) {
4929            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
4930            if (markers[i]) {
4931                ++resLen
4932            }
4933        }
4934        let res = new Uint8Array(resLen)
4935        for (let i = 0, j = 0; i < this.lengthInt; i++) {
4936            if (markers[i]) {
4937                res.setUnsafe(j, this.getUnsafe(i))
4938                ++j
4939            }
4940        }
4941        return res
4942    }
4943
4944    /**
4945     * creates a new Uint8Array from current Uint8Array based on a condition fn
4946     *
4947     * @param fn the condition to apply for each element
4948     *
4949     * @returns a new Uint8Array with elements from current Uint8Array that satisfy condition fn
4950     */
4951    public filter(fn: (val: number, index: number) => boolean): Uint8Array {
4952        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4953            (val: number, index: number, array: Uint8Array): boolean => { return fn(val, index) }
4954        return this.filter(newF)
4955    }
4956
4957    /**
4958     * Returns the value of the first element in the array where predicate is true, and undefined
4959     * otherwise
4960     *
4961     * @param predicate find calls predicate once for each element of the array, in ascending
4962     * order, until it finds one where predicate returns true. If such an element is found, find
4963     * immediately returns that element value. Otherwise, find returns undefined
4964     *
4965     * @returns number | undefined
4966     */
4967    public find(predicate: (value: number, index: number, array: Uint8Array) => boolean): number | undefined {
4968        for (let i = 0; i < this.lengthInt; i++) {
4969            let val = this.getUnsafe(i) as number
4970            if (predicate(val, i as number, this)) {
4971                return val
4972            }
4973        }
4974        return undefined
4975    }
4976
4977    /**
4978     * Returns the value of the first element in the array where predicate is true, and undefined
4979     * otherwise
4980     *
4981     * @param predicate find calls predicate once for each element of the array, in ascending
4982     * order, until it finds one where predicate returns true. If such an element is found, find
4983     * immediately returns that element value. Otherwise, find returns undefined
4984     *
4985     * @returns number | undefined
4986     */
4987    public find(predicate: (value: number, index: number) => boolean): number | undefined {
4988        return this.find((value: number, index: number, obj: Uint8Array): boolean => predicate(value, index))
4989    }
4990
4991    /**
4992     * Returns the index of the first element in the array where predicate is true, and -1
4993     * otherwise
4994     *
4995     * @param predicate find calls predicate once for each element of the array, in ascending
4996     * order, until it finds one where predicate returns true. If such an element is found,
4997     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
4998     *
4999     * @returns number
5000     */
5001    public findIndex(predicate: (value: number, index: number, obj: Uint8Array) => boolean): number {
5002        for (let i = 0; i < this.lengthInt; i++) {
5003            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
5004                return i as number
5005            }
5006        }
5007        return -1 as number
5008    }
5009
5010    /**
5011     * Returns the index of the first element in the array where predicate is true, and -1
5012     * otherwise
5013     *
5014     * @param predicate find calls predicate once for each element of the array, in ascending
5015     * order, until it finds one where predicate returns true. If such an element is found,
5016     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
5017     *
5018     * @returns number
5019     */
5020    public findIndex(predicate: (value: number, index: number) => boolean): number {
5021        return this.findIndex((value: number, index: number, obj: Uint8Array): boolean => predicate(value, index))
5022    }
5023
5024    /**
5025     * Returns the index of the first element in the array where predicate is true, and -1
5026     * otherwise
5027     *
5028     * @param predicate find calls predicate once for each element of the array, in ascending
5029     * order, until it finds one where predicate returns true. If such an element is found,
5030     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
5031     *
5032     * @returns number
5033     */
5034    public findIndex(predicate: () => boolean): number {
5035        return this.findIndex((value: number, index: number, obj: Uint8Array): boolean => predicate())
5036    }
5037
5038    /**
5039     * Finds the last element in the Uint8Array that satisfies the condition
5040     *
5041     * @param fn condition
5042     *
5043     * @returns the last element that satisfies fn
5044     */
5045    public findLast(fn: (val: number, index: number, array: Uint8Array) => boolean): number {
5046        for (let i = this.lengthInt - 1; i >= 0; i--) {
5047            let val = this.getUnsafe(i) as number
5048            if (fn(val, i as number, this)) {
5049                return val
5050            }
5051        }
5052        throw new Error("Uint8Array.findLast: not implemented if an element was not found")
5053    }
5054
5055    /**
5056     * Finds the last element in the Uint8Array that satisfies the condition
5057     *
5058     * @param fn condition
5059     *
5060     * @returns the last element that satisfies fn
5061     */
5062    public findLast(fn: (val: number, index: number) => boolean): number {
5063        let newF: (val: number, index: number, array: Uint8Array) => boolean =
5064            (val: number, index: number, array: Uint8Array): boolean => { return fn(val, index) }
5065        return this.findLast(newF)
5066    }
5067
5068    /**
5069     * Finds an index of the last element in the Uint8Array that satisfies the condition
5070     *
5071     * @param fn condition
5072     *
5073     * @returns the index of the last element that satisfies fn, -1 otherwise
5074     */
5075    public findLastIndex(fn: (val: number, index: number, array: Uint8Array) => boolean): number {
5076        for (let i = this.lengthInt - 1; i >= 0; i--) {
5077            if (fn(this.getUnsafe(i) as number, i as number, this)) {
5078                return i as number
5079            }
5080        }
5081        return -1 as number
5082    }
5083
5084    /**
5085     * Finds an index of the last element in the Uint8Array that satisfies the condition
5086     *
5087     * @param fn condition
5088     *
5089     * @returns the index of the last element that satisfies fn, -1 otherwise
5090     */
5091    public findLastIndex(fn: (val: number, index: number) => boolean): number {
5092        let newF: (val: number, index: number, array: Uint8Array) => boolean =
5093            (val: number, index: number, array: Uint8Array): boolean => { return fn(val, index) }
5094        return this.findLastIndex(newF) as number
5095    }
5096
5097    /**
5098     * Performs the specified action for each element in Uint8Array
5099     *
5100     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
5101     * callbackfn function one time for each element in the array.
5102     *
5103     * @returns None
5104     */
5105    public forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void): void {
5106        for (let i = 0; i < this.lengthInt; i++) {
5107            callbackfn(this.getUnsafe(i) as number, i as number, this)
5108        }
5109    }
5110
5111    /**
5112     * Performs the specified action for each element in Uint8Array
5113     *
5114     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
5115     * callbackfn function one time for each element in the array.
5116     *
5117     * @returns None
5118     */
5119    public forEach(callbackfn: (value: number, index: number) => void): void {
5120        this.forEach((value: number, index: number, array: Uint8Array): void => callbackfn(value, index))
5121    }
5122
5123    /**
5124     * Performs the specified action for each element in Uint8Array
5125     *
5126     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
5127     * callbackfn function one time for each element in the array.
5128     *
5129     * @returns None
5130     */
5131    public forEach(callbackfn: () => void): void {
5132        this.forEach((value: number, index: number, array: Uint8Array): void => callbackfn())
5133    }
5134
5135    /**
5136     * Returns the object itself
5137     *
5138     * @returns Uint8Array
5139     */
5140    public valueOf(): Uint8Array {
5141        return this
5142    }
5143
5144    /** Byte offset within the underlying Buffer */
5145    public get byteOffset(): number {
5146        return this.byteOffsetInt
5147    }
5148
5149    /** Number of bytes used */
5150    public get byteLength(): number {
5151        return this.byteLengthInt
5152    }
5153
5154    /** Number of int stored in Uint8Array */
5155    public get length(): number {
5156        return this.lengthInt
5157    }
5158
5159    /** String \"Uint8Array\" */
5160    public readonly name = "Uint8Array"
5161
5162    private static clamp(val: int): int {
5163        return val
5164    }
5165
5166    internal setUnsafeClamp(insertPos: int, val: int): void {
5167        this.setUnsafe(insertPos, val)
5168    }
5169
5170    internal getUnsafe(index: int): int {
5171        index = index * Uint8Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
5172        let res: int = 0
5173        if (IS_LITTLE_ENDIAN) {
5174            if (this.buffer instanceof ArrayBuffer) {
5175                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5176                    let el = (this.buffer as ArrayBuffer).at(index + i) as int
5177                    el &= 0xff
5178                    res |= el << (8 * i)
5179                }
5180            } else if (this.buffer instanceof SharedArrayBuffer) {
5181                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5182                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as int
5183                    el &= 0xff
5184                    res |= el << (8 * i)
5185                }
5186            } else {
5187                throw new Error("unexpected type of ArrayBufferLike")
5188            }
5189        } else {
5190            if (this.buffer instanceof ArrayBuffer) {
5191                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5192                    let el = (this.buffer as ArrayBuffer).at(index + 0 - i) as int
5193                    el &= 0xff
5194                    res |= el << (8 * i)
5195                }
5196            } else if (this.buffer instanceof SharedArrayBuffer) {
5197                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5198                    let el = (this.buffer as SharedArrayBuffer).at(index + 0 - i) as int
5199                    el &= 0xff
5200                    res |= el << (8 * i)
5201                }
5202            } else {
5203                throw new Error("unexpected type of ArrayBufferLike")
5204            }
5205        }
5206        return res
5207    }
5208
5209    internal setUnsafe(index: int, val: int): void {
5210        index = index * Uint8Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
5211        let res: int = 0
5212        if (IS_LITTLE_ENDIAN) {
5213            if (this.buffer instanceof ArrayBuffer) {
5214                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5215                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
5216                    val = val >> 8
5217                }
5218            } else if (this.buffer instanceof SharedArrayBuffer) {
5219                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5220                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
5221                    val = val >> 8
5222                }
5223            } else {
5224                throw new Error("unexpected type of ArrayBufferLike")
5225            }
5226        } else {
5227            if (this.buffer instanceof ArrayBuffer) {
5228                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5229                    (this.buffer as ArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
5230                    val = val >> 8
5231                }
5232            } else if (this.buffer instanceof SharedArrayBuffer) {
5233                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5234                    (this.buffer as SharedArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
5235                    val = val >> 8
5236                }
5237            } else {
5238                throw new Error("unexpected type of ArrayBufferLike")
5239            }
5240        }
5241    }
5242}
5243
5244
5245class Uint16ArrayIteratorKeys implements IterableIterator<number> {
5246    private length: int = 0
5247    private idx: int = 0
5248
5249    constructor(parent: Uint16Array) {
5250        this.length = parent.length as int
5251    }
5252
5253    public override $_iterator(): IterableIterator<Number> {
5254        return this
5255    }
5256
5257    override next(): IteratorResult<number> {
5258        if (this.idx < 0 || this.idx >= this.length) {
5259            return new IteratorResult<number>()
5260        }
5261        return new IteratorResult<number>(false, this.idx++ as number)
5262    }
5263}
5264
5265class Uint16ArrayIterator implements IterableIterator<Number> {
5266    private parent: Uint16Array
5267    private idx: int = 0
5268
5269    constructor(parent: Uint16Array) {
5270        this.parent = parent
5271    }
5272
5273    public override $_iterator(): IterableIterator<Number> {
5274        return this
5275    }
5276
5277    override next(): IteratorResult<Number> {
5278        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
5279            return new IteratorResult<Number>()
5280        }
5281        return new IteratorResult<Number>(false, new Number(this.parent.getUnsafe(this.idx++)))
5282    }
5283}
5284
5285class Uint16ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
5286    private parent: Uint16Array
5287    private idx: int = 0
5288
5289    constructor(parent: Uint16Array) {
5290        this.parent = parent
5291    }
5292
5293    public override $_iterator(): IterableIterator<[Number, Number]> {
5294        return this
5295    }
5296
5297    override next(): IteratorResult<[Number, Number]> {
5298        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
5299            return new IteratorResult<[Number, Number]>()
5300        }
5301        return new IteratorResult<[Number, Number]>(
5302            false,
5303            [new Number(this.idx), new Number(this.parent.getUnsafe(this.idx++))]
5304        )
5305    }
5306}
5307
5308/**
5309 * JS Uint16Array API-compatible class
5310 */
5311export class Uint16Array implements Iterable<Number>, ArrayLike<Number> {
5312    public static readonly BYTES_PER_ELEMENT: number = 2
5313
5314    /** Underlying Buffer */
5315    public readonly buffer: ArrayBufferLike
5316
5317    internal readonly byteOffsetInt: int
5318    internal readonly byteLengthInt: int
5319    internal readonly lengthInt: int
5320
5321    /**
5322     * Creates an empty Uint16Array.
5323     */
5324    public constructor() {
5325        this(0 as int)
5326    }
5327
5328    /**
5329     * Creates an Uint16Array with respect to data accessed via Iterable<Number> interface
5330     */
5331    public constructor(elements: Iterable<Number>) {
5332        const items: Object = elements as Object
5333        if (items instanceof ArrayLike) {
5334            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
5335            this.byteLengthInt = arr.length as int * Uint16Array.BYTES_PER_ELEMENT as int
5336            this.lengthInt = arr.length as int
5337            this.buffer = new ArrayBuffer(this.byteLengthInt)
5338            this.byteOffsetInt = 0
5339            for (let i: int = 0; i < this.lengthInt; ++i) {
5340                this.setUnsafe(i, arr.$_get(i).intValue())
5341            }
5342        } else {
5343            let x = Uint16Array.from(elements)
5344            this.byteLengthInt = x.byteLengthInt
5345            this.lengthInt = x.lengthInt
5346            this.buffer = x.buffer
5347            this.byteOffsetInt = x.byteOffsetInt
5348        }
5349    }
5350
5351    /**
5352     * Creates an Uint16Array with respect to data, byteOffset and length.
5353     *
5354     * @param buf data initializer
5355     *
5356     * @param byteOffset byte offset from begin of the buf
5357     *
5358     * @param length size of elements of type int in newly created Uint16Array
5359     */
5360    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
5361        let intByteOffset: int = 0
5362        if (byteOffset != undefined) {
5363            intByteOffset = byteOffset.intValue()
5364            if (intByteOffset < 0) {
5365                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
5366            }
5367        }
5368        let intByteLength: int
5369        if (buf instanceof ArrayBuffer) {
5370            intByteLength = (buf as ArrayBuffer).getByteLength()
5371        } else if (buf instanceof SharedArrayBuffer) {
5372            intByteLength = (buf as SharedArrayBuffer).getByteLength()
5373        } else {
5374            throw new Error("unexpected type of ArrayBufferLike")
5375        }
5376        intByteLength = intByteLength - intByteOffset
5377        if (intByteLength < 0) {
5378            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
5379        }
5380
5381        if (intByteLength % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5382            throw new RangeError("ArrayBufferLike.byteLength should be multiple of 2 as Uint16Array.BYTES_PER_ELEMENT")
5383        }
5384        if (intByteOffset % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5385            throw new RangeError("byteOffset should be multiple of 2 as Uint16Array.BYTES_PER_ELEMENT")
5386        }
5387
5388        let intLength: int
5389        if (length != undefined) {
5390            intLength = length.intValue()
5391            if (intLength > intByteLength / Uint16Array.BYTES_PER_ELEMENT as int) {
5392                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
5393            }
5394        } else {
5395            intLength = intByteLength / Uint16Array.BYTES_PER_ELEMENT as int
5396        }
5397        if (intLength < 0) {
5398            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
5399        }
5400        if (intLength < intByteLength / Uint16Array.BYTES_PER_ELEMENT as int) {
5401            intByteLength = intLength * Uint16Array.BYTES_PER_ELEMENT as int
5402        }
5403        this.byteLengthInt = intByteLength
5404        this.byteOffsetInt = intByteOffset
5405        this.lengthInt = intLength
5406        this.buffer = buf
5407    }
5408
5409    /**
5410     * Creates an Uint16Array with respect to data, byteOffset and length.
5411     *
5412     * @param buf data initializer
5413     *
5414     * @param byteOffset byte offset from begin of the buf
5415     */
5416    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
5417        this(buf, byteOffset, undefined)
5418    }
5419
5420    /**
5421     * Creates an Uint16Array with respect to data, byteOffset and length.
5422     *
5423     * @param buf data initializer
5424     *
5425     * @param byteOffset byte offset from begin of the buf
5426     *
5427     * @param length size of elements of type int in newly created Uint16Array
5428     */
5429    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
5430        this(buf, new Number(byteOffset), new Number(length))
5431    }
5432
5433    /**
5434     * Creates an Uint16Array with respect to buf and byteOffset.
5435     *
5436     * @param buf data initializer
5437     *
5438     * @param byteOffset byte offset from begin of the buf
5439     */
5440    public constructor(buf: ArrayBufferLike, byteOffset: number) {
5441        this(buf, new Number(byteOffset), undefined)
5442    }
5443
5444    /**
5445     * Creates an Uint16Array with respect to data, byteOffset and length.
5446     *
5447     * @param buf data initializer
5448     *
5449     * @param byteOffset byte offset from begin of the buf
5450     *
5451     * @param length size of elements of type int in newly created Uint16Array
5452     */
5453    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
5454        this(buf, new Number(byteOffset), new Number(length))
5455    }
5456
5457    /**
5458     * Creates an Uint16Array with respect to buf and byteOffset.
5459     *
5460     * @param buf data initializer
5461     *
5462     * @param byteOffset byte offset from begin of the buf
5463     */
5464    public constructor(buf: ArrayBufferLike, byteOffset: int) {
5465        this(buf, new Number(byteOffset), undefined)
5466    }
5467
5468    /**
5469     * Creates an Uint16Array with respect to buf.
5470     *
5471     * @param buf data initializer
5472     */
5473    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
5474        if (buf instanceof ArrayBuffer) {
5475            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
5476            if (this.byteLengthInt % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5477               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint16Array.BYTES_PER_ELEMENT")
5478            }
5479            this.lengthInt = this.byteLengthInt / Uint16Array.BYTES_PER_ELEMENT as int
5480            this.buffer = buf as ArrayBuffer
5481            this.byteOffsetInt = 0
5482        } else if (buf instanceof SharedArrayBuffer) {
5483            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
5484            if (this.byteLengthInt % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5485               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint16Array.BYTES_PER_ELEMENT")
5486            }
5487            this.lengthInt = this.byteLengthInt / Uint16Array.BYTES_PER_ELEMENT as int
5488            this.buffer = buf as SharedArrayBuffer
5489            this.byteOffsetInt = 0
5490        } else if (buf instanceof ArrayLike) {
5491            // NOTE (ikorobkov): dealing with this overload is tricky
5492            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
5493            let arr = Array.from<Number>((buf as ArrayLike<Number>))
5494            this.byteLengthInt = arr.length as int * Uint16Array.BYTES_PER_ELEMENT as int
5495            this.lengthInt = arr.length as int
5496            this.buffer = new ArrayBuffer(this.byteLengthInt)
5497            this.byteOffsetInt = 0
5498            for (let i: int = 0; i < this.lengthInt; ++i) {
5499                this.setUnsafe(i, arr.$_get(i).intValue())
5500            }
5501        } else {
5502            throw new Error("unexpected type of buf")
5503        }
5504    }
5505
5506    /**
5507     * Creates an Uint16Array with respect to length.
5508     *
5509     * @param length data initializer
5510     */
5511    public constructor(length: int) {
5512        if (length < 0) {
5513            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
5514        }
5515        this.lengthInt = length
5516        this.byteLengthInt = length * Uint16Array.BYTES_PER_ELEMENT as int
5517        this.byteOffsetInt = 0
5518        this.buffer = new ArrayBuffer(this.byteLengthInt)
5519    }
5520
5521    /**
5522     * Creates an Uint16Array with respect to length.
5523     *
5524     * @param length data initializer
5525     */
5526    public constructor(length: number) {
5527        this(length as int)
5528    }
5529
5530    /**
5531     * Creates a copy of Uint16Array.
5532     *
5533     * @param other data initializer
5534     */
5535    public constructor(other: Uint16Array) {
5536        if (other.buffer instanceof ArrayBuffer) {
5537            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
5538        } else if (other.buffer instanceof SharedArrayBuffer) {
5539            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
5540        } else {
5541            throw new Error("unexpected type of buffer")
5542        }
5543        this.byteLengthInt = other.byteLength as int
5544        this.lengthInt = other.length as int
5545        this.byteOffsetInt = 0
5546    }
5547
5548    /**
5549     * Creates an Uint16Array from number[]
5550     */
5551    public constructor(numbers: number[]) {
5552        this(numbers.length)
5553        for (let i: int = 0; i < this.lengthInt; ++i) {
5554            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
5555        }
5556    }
5557
5558    /**
5559     * Creates an Uint16Array from int[]
5560     */
5561    public constructor(numbers: int[]) {
5562        this(numbers.length)
5563        for (let i: int = 0; i < this.lengthInt; ++i) {
5564            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
5565        }
5566    }
5567
5568    internal zeroIfInfinity(val: number): number {
5569        if ((val == Infinity) || (val == -Infinity)) {
5570            return 0 as number
5571        }
5572        return val as number
5573    }
5574
5575    internal zeroIfInfinity(val: int): int {
5576        if ((val == Infinity) || (val == -Infinity)) {
5577            return 0 as int
5578        }
5579        return val
5580    }
5581
5582    /**
5583     * Iteratorable interface implementation
5584     *
5585     * @returns iterator over all elements
5586     */
5587    public override $_iterator(): IterableIterator<Number> {
5588         return this.values()
5589    }
5590
5591    /**
5592     * Returns an instance of primitive type at passed index.
5593     *
5594     * @param index index to look at
5595     *
5596     * @returns a primitive at index
5597     */
5598    public at(index: number): Number | undefined {
5599        return this.at(index as int)
5600    }
5601
5602    /**
5603     * Returns an instance of primitive type at passed index if index is correct.
5604     *
5605     * @param index index to look at
5606     *
5607     * @returns a primitive at index
5608     */
5609    public at(index: int): Number | undefined {
5610        let k: int
5611        if (index >= 0) {
5612            k = index
5613        } else {
5614            k = this.lengthInt + index
5615        }
5616        if (k < 0 || k >= this.lengthInt) {
5617            return undefined
5618        }
5619        return new Number(this.getUnsafe(k))
5620    }
5621
5622    /**
5623     * Returns an instance of number at passed index.
5624     *
5625     * @param index index to look at
5626     *
5627     * @returns a primitive at index
5628     */
5629    public override $_get(index: number): Number {
5630        return this.$_get(index as int) as Number
5631    }
5632
5633    /**
5634     * Returns an instance of number at passed index.
5635     *
5636     * @param index index to look at
5637     *
5638     * @returns a primitive at index
5639     */
5640    public $_get(i: int): number {
5641        if (i < 0 || i >= this.lengthInt) {
5642            throw new RangeError("invalid offset")
5643        }
5644        return this.getUnsafe(i) as number
5645    }
5646
5647    /**
5648     * Assigns val as element on index.
5649     *
5650     * @param val value to set
5651     *
5652     * @param index index to change
5653     */
5654    public $_set(index: number, val: number): void {
5655        this.$_set(index as int, val)
5656    }
5657
5658    /**
5659     * Assigns val as element on index.
5660     *
5661     * @param val value to set
5662     *
5663     * @param index index to change
5664     */
5665    public $_set(index: int, val: number): void {
5666        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
5667        if (index < 0 || index >= this.lengthInt) {
5668            throw new RangeError("invalid index")
5669        }
5670        let v = this.zeroIfInfinity(val)
5671        this.setUnsafeClamp(index, v as int)
5672    }
5673
5674    /**
5675     * Assigns val as element on index.
5676     *
5677     * @param val value to set
5678     *
5679     * @param index index to change
5680     */
5681    public $_set(index: number, val: int): void {
5682        this.$_set(index as int, val)
5683    }
5684
5685    /**
5686     * Assigns val as element on index.
5687     *
5688     * @param val value to set
5689     *
5690     * @param index index to change
5691     */
5692    public $_set(index: int, val: int): void {
5693        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
5694        if (index < 0 || index >= this.lengthInt) {
5695            throw new RangeError("invalid index")
5696        }
5697        let v = this.zeroIfInfinity(val)
5698        this.setUnsafeClamp(index, v)
5699    }
5700
5701    /**
5702     * Makes a copy of internal elements to targetPos from startPos to endPos.
5703     *
5704     * @param target insert index to place copied elements
5705     *
5706     * @param start start index to begin copy from
5707     *
5708     * @param end last index to end copy from, excluded
5709     *
5710     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5711     */
5712    public copyWithin(target: number, start: number, end?: number): Uint16Array {
5713        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5714    }
5715
5716    /**
5717     * Makes a copy of internal elements to targetPos from startPos to endPos.
5718     *
5719     * @param target insert index to place copied elements
5720     *
5721     * @param start start index to begin copy from
5722     *
5723     * @param end last index to end copy from, excluded
5724     *
5725     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5726     */
5727    public copyWithin(target: int, start: number, end?: number): Uint16Array {
5728        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5729    }
5730
5731    /**
5732     * Makes a copy of internal elements to targetPos from startPos to endPos.
5733     *
5734     * @param target insert index to place copied elements
5735     *
5736     * @param start start index to begin copy from
5737     *
5738     * @param end last index to end copy from, excluded
5739     *
5740     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5741     */
5742    public copyWithin(target: number, start: int, end?: number): Uint16Array {
5743        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5744    }
5745
5746    /**
5747     * Makes a copy of internal elements to targetPos from startPos to endPos.
5748     *
5749     * @param target insert index to place copied elements
5750     *
5751     * @param start start index to begin copy from
5752     *
5753     * @param end last index to end copy from, excluded
5754     *
5755     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5756     */
5757    public copyWithin(target: int, start: int, end?: number): Uint16Array {
5758        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5759    }
5760
5761    /**
5762     * Makes a copy of internal elements to targetPos from startPos to endPos.
5763     *
5764     * @param insert insert index to place copied elements
5765     *
5766     * @param start start index to begin copy from
5767     *
5768     * @param end last index to end copy from, excluded
5769     *
5770     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5771     */
5772    public copyWithin(target: int, start: int, end: int): Uint16Array {
5773        let toPos = normalizeIndex(target, this.lengthInt)
5774        let fromPos = normalizeIndex(start, this.lengthInt)
5775        const finalPos = normalizeIndex(end, this.lengthInt)
5776        let count: int = finalPos - fromPos
5777        if (count > (this.lengthInt - toPos)) {
5778            count = this.lengthInt - toPos
5779        }
5780        let direction: int = 1
5781        if ((fromPos < toPos) && (toPos < fromPos + count)) {
5782            fromPos = fromPos + count - 1
5783            toPos   = toPos   + count - 1
5784            direction = -1
5785        }
5786        while (count > 0) {
5787            const value = this.getUnsafe(fromPos)
5788            this.setUnsafe(toPos, value)
5789            fromPos = fromPos + direction
5790            toPos = toPos + direction
5791            --count
5792        }
5793        return this
5794    }
5795
5796    /**
5797     * Makes a copy of internal elements to targetPos from begin to end of Uint16Array.
5798     *
5799     * @param target insert index to place copied elements
5800     *
5801     * See rules of parameters normalization:
5802     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
5803     */
5804    public copyWithin(target: number): Uint16Array {
5805        return this.copyWithin(target as int)
5806    }
5807
5808    /**
5809     * Makes a copy of internal elements to targetPos from begin to end of Uint16Array.
5810     *
5811     * @param insert insert index to place copied elements
5812     *
5813     * See rules of parameters normalization:
5814     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
5815     */
5816    public copyWithin(target: int): Uint16Array {
5817        return this.copyWithin(target, 0, this.lengthInt)
5818    }
5819
5820    /**
5821     * Returns an array of key, value pairs for every entry in the Uint16Array
5822     *
5823     * @returns key, value pairs for every entry in the array
5824     */
5825    public entries(): IterableIterator<[Number, Number]> {
5826        return new Uint16ArrayIteratorEntries(this)
5827    }
5828
5829    /**
5830     * Fills the Uint16Array with specified value
5831     *
5832     * @param value new value
5833     *
5834     * @returns modified Uint16Array
5835     */
5836    public fill(value: number, start?: number, end?: number): Uint16Array {
5837        value = this.zeroIfInfinity(value)
5838        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
5839        return this
5840    }
5841
5842    /**
5843     * Fills the Uint16Array with specified value
5844     *
5845     * @param value new value
5846     *
5847     * @returns modified Uint16Array
5848     */
5849    public fill(value: number, start: int, end?: number): Uint16Array {
5850        value = this.zeroIfInfinity(value)
5851        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
5852        return this
5853    }
5854
5855    /**
5856     * Fills the Uint16Array with specified value
5857     *
5858     * @param value new value
5859     *
5860     * @returns modified Uint16Array
5861     */
5862    public fill(value: number, start: int, end: number): Uint16Array {
5863        value = this.zeroIfInfinity(value)
5864        this.fill(value as int, start as int, end as int)
5865        return this
5866    }
5867
5868    /**
5869     * Fills the Uint16Array with specified value
5870     *
5871     * @param value new value
5872     *
5873     * @returns modified Uint16Array
5874     */
5875    public fill(value: number, start: number, end: int): Uint16Array {
5876        value = this.zeroIfInfinity(value)
5877        this.fill(value as int, start as int, end as int)
5878        return this
5879    }
5880
5881    /**
5882     * Fills the Uint16Array with specified value
5883     *
5884     * @param value new value
5885     *
5886     * @returns modified Uint16Array
5887     */
5888    public fill(value: number, start: int, end: int): Uint16Array {
5889        value = this.zeroIfInfinity(value)
5890        this.fill(value as int, start as int, end as int)
5891        return this
5892    }
5893
5894    /**
5895     * Fills the Uint16Array with specified value
5896     *
5897     * @param value new value
5898     *
5899     * @returns modified Uint16Array
5900     */
5901    public fill(value: int, start?: number, end?: number): Uint16Array {
5902        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
5903        return this
5904    }
5905
5906    /**
5907     * Fills the Uint16Array with specified value
5908     *
5909     * @param value new value
5910     *
5911     * @returns modified Uint16Array
5912     */
5913    public fill(value: int, start: int, end?: number): Uint16Array {
5914        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
5915        return this
5916    }
5917
5918    /**
5919     * Fills the Uint16Array with specified value
5920     *
5921     * @param value new value
5922     *
5923     * @returns modified Uint16Array
5924     */
5925    public fill(value: int, start: int, end: number): Uint16Array {
5926        this.fill(value, start as int, end as int)
5927        return this
5928    }
5929
5930    /**
5931     * Fills the Uint16Array with specified value
5932     *
5933     * @param value new value
5934     *
5935     * @returns modified Uint16Array
5936     */
5937    public fill(value: int, start: number, end: int): Uint16Array {
5938        this.fill(value, start as int, end as int)
5939        return this
5940    }
5941
5942    /**
5943     * Fills the Uint16Array with specified value
5944     *
5945     * @param value new value
5946     *
5947     * @returns modified Uint16Array
5948     */
5949    public fill(value: int, start: int, end: int): Uint16Array {
5950        const k = normalizeIndex(start, this.lengthInt)
5951        const finalPos = normalizeIndex(end, this.lengthInt)
5952        for (let i: int = k; i < finalPos; ++i) {
5953            this.setUnsafe(i, value)
5954        }
5955        return this
5956    }
5957
5958    /**
5959     * Assigns val as element on index.
5960     *
5961     * @param val value to set
5962     *
5963     * @param index index to change
5964     */
5965    public set(insertPos: number, val: number): void {
5966        this.$_set(insertPos as int, val)
5967    }
5968
5969    /**
5970     * Assigns val as element on index.
5971     *
5972     * @param val value to set
5973     *
5974     * @param index index to change
5975     */
5976    public set(insertPos: int, val: number): void {
5977        this.$_set(insertPos as int, val)
5978    }
5979
5980    /**
5981     * Assigns val as element on index.
5982     *
5983     * @param val value to set
5984     *
5985     * @param index index to change
5986     */
5987    public set(insertPos: number, val: int): void {
5988        this.$_set(insertPos as int, val)
5989    }
5990
5991    /**
5992     * Assigns val as element on index.
5993     *
5994     * @param val value to set
5995     *
5996     * @param index index to change
5997     */
5998    public set(insertPos: int, val: int): void {
5999        this.$_set(insertPos as int, val)
6000    }
6001
6002    /**
6003     * Copies all elements of arr to the current Uint16Array starting from insertPos.
6004     *
6005     * @param arr array to copy data from
6006     *
6007     * @param insertPos start index where data from arr will be inserted
6008     *
6009     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
6010     */
6011    public set(arr: number[], insertPos1: number): void {
6012        const insertPos = insertPos1 as int
6013        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
6014            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint16Array.length")
6015        }
6016        for (let i = 0; i < arr.length; i++) {
6017            let v = this.zeroIfInfinity(arr[i])
6018            this.setUnsafeClamp(insertPos as int + i as int, v as int)
6019        }
6020    }
6021
6022    /**
6023     * Copies all elements of arr to the current Uint16Array starting from insertPos.
6024     *
6025     * @param arr array to copy data from
6026     *
6027     * @param insertPos start index where data from arr will be inserted
6028     *
6029     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
6030     */
6031    public set(arr: int[], insertPos: int): void {
6032        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
6033            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint16Array.length")
6034        }
6035        for (let i = 0; i < arr.length; i++) {
6036            let v = this.zeroIfInfinity(arr[i])
6037            this.setUnsafeClamp(insertPos + i, v)
6038        }
6039    }
6040
6041    /**
6042     * Copies all elements of arr to the current Uint16Array.
6043     *
6044     * @param arr array to copy data from
6045     */
6046    public set(arr: number[]): void {
6047        this.set(arr, 0)
6048    }
6049
6050    /**
6051     * Copies all elements of arr to the current Uint16Array.
6052     *
6053     * @param arr array to copy data from
6054     */
6055    public set(arr: int[]): void {
6056        this.set(arr, 0)
6057    }
6058
6059    /**
6060     * Copies elements from an ArrayLike object to the Uint16Array.
6061     *
6062     * @param array An ArrayLike object containing the elements to copy.
6063     *
6064     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
6065     */
6066    public set(array: ArrayLike<number>, offset: number = 0): void {
6067        const insertPos = offset as int
6068        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
6069            throw new RangeError("offset is out of bounds")
6070        }
6071        for (let i = 0; i < array.length; i++) {
6072            let v = this.zeroIfInfinity(array[i])
6073            this.setUnsafeClamp(insertPos as int + i as int, v as int)
6074        }
6075    }
6076
6077    /**
6078     * Returns a new array from a set of elements.
6079     *
6080     * @param items a set of elements to include in the new array object.
6081     *
6082     * @returns new Uint16Array
6083     */
6084    public static of(...items: number[]): Uint16Array {
6085        let res = new Uint16Array(items.length as int)
6086        for (let i: int = 0; i < items.length; i++) {
6087            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as int)
6088        }
6089        return res
6090    }
6091
6092    /**
6093     * Returns a new array from a set of elements.
6094     *
6095     * @param items a set of elements to include in the new array object.
6096     *
6097     * @returns new Uint16Array
6098     */
6099    public static of(...items: int[]): Uint16Array {
6100        let res = new Uint16Array(items.length as int)
6101        for (let i: int = 0; i < items.length; i++) {
6102            res.setUnsafeClamp(i, items[i])
6103        }
6104        return res
6105    }
6106
6107    /**
6108     * Returns a new array from a set of elements.
6109     *
6110     * @param items a set of elements to include in the new array object.
6111     *
6112     * @returns new Uint16Array
6113     */
6114    public static of(): Uint16Array {
6115        return new Uint16Array(0 as int)
6116    }
6117
6118    /**
6119     * Creates an array from an array-like or iterable object.
6120     *
6121     * @param arrayLike An array-like or iterable object to convert to an array.
6122     *
6123     * @returns new Uint16Array
6124     */
6125    public static from(arr: ArrayLike<number>): Uint16Array {
6126        return Uint16Array.from<number>(arr, (x: number, k: number): number => x)
6127    }
6128
6129    /**
6130     * Creates an array from an array-like or iterable object.
6131     *
6132     * @param arrayLike An array-like or iterable object to convert to an array.
6133     *
6134     * @param mapfn A mapping function to call on every element of the array.
6135     *
6136     * @returns new Uint16Array
6137     */
6138    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint16Array {
6139        if (mapfn == undefined) {
6140            mapfn = (v: number, k: number): number => { return v }
6141        }
6142
6143        let iter = arrayLike.$_iterator()
6144        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
6145        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
6146        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
6147        //  we can make one pass through the iterator without the need for memory reallocation.
6148        const maybeLength = tryGetIteratorLength(arrayLike)
6149        if (maybeLength) {
6150            const result = new Uint16Array(maybeLength)
6151            for (let i = 0; i < maybeLength; ++i) {
6152                const x = iter.next()
6153                if (x.done) {
6154                    return new Uint16Array(result.buffer, 0, i)
6155                }
6156                result.setUnsafeClamp(i, result.zeroIfInfinity((mapfn)!(x.value!, i)) as int)
6157            }
6158            return result
6159        }
6160
6161        // NOTE (templin.konstantin): Create builtin array as buffer
6162        let temp = new Uint16Array(6)
6163        let index = new int[1]
6164        index[0] = 0
6165
6166        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
6167            if (index[0] + 1 > temp.lengthInt) {
6168                // NOTE (templin.konstantin): Progressive reallocation
6169                const curLength = (temp.buffer as Buffer).getByteLength()
6170                const tb = new ArrayBuffer(curLength * 2)
6171                for (let i = 0; i < curLength; ++i) {
6172                    tb.set(i, (temp.buffer as Buffer).at(i))
6173                }
6174                temp = new Uint16Array(tb)
6175            }
6176            temp.setUnsafeClamp(index[0], temp.zeroIfInfinity((mapfn)!(x, index[0])) as int)
6177            index[0]++
6178        })
6179
6180        return new Uint16Array(temp.buffer, 0, index[0])
6181    }
6182
6183    /**
6184     * Creates an array from an array-like or iterable object.
6185     *
6186     * @param arrayLike An array-like or iterable object to convert to an array.
6187     *
6188     * @param mapfn A mapping function to call on every element of the array.
6189     *
6190     * @returns new Uint16Array
6191     */
6192    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint16Array {
6193        let res = new Uint16Array(arrayLike.length)
6194        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
6195        const idx = new int[1]
6196        idx[0] = 0
6197        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
6198            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as int)
6199            idx[0] += 1
6200        })
6201        return res
6202    }
6203
6204    /**
6205     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
6206     *
6207     * @param searchElement The element to search for
6208     *
6209     * @param fromIndex The position in this array at which to begin searching for searchElement
6210     *
6211     * @returns true if searchElement is in Uint16Array, false otherwise
6212     */
6213    public includes(searchElement: number, fromIndex?: number): boolean {
6214        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
6215    }
6216
6217    /**
6218     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
6219     *
6220     * @param searchElement The element to search for
6221     *
6222     * @param fromIndex The position in this array at which to begin searching for searchElement
6223     *
6224     * @returns true if searchElement is in Uint16Array, false otherwise
6225     */
6226    public includes(searchElement: int, fromIndex: int): boolean {
6227        return this.indexOf(searchElement as int, fromIndex) != -1
6228    }
6229
6230    /**
6231     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
6232     *
6233     * @param searchElement The element to search for
6234     *
6235     * @param fromIndex The position in this array at which to begin searching for searchElement
6236     *
6237     * @returns true if searchElement is in Uint16Array, false otherwise
6238     */
6239    public includes(searchElement: int): boolean {
6240        return this.indexOf(searchElement as int, 0) != -1
6241    }
6242
6243    /**
6244     * Returns the index of the first occurrence of a value in Uint16Array.
6245     *
6246     * @param searchElement The value to locate in the array.
6247     *
6248     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6249     *  search starts at index 0.
6250     *
6251     * @returns index of element if it presents, -1 otherwise
6252     */
6253    public indexOf(searchElement: number, fromIndex?: number): number {
6254        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
6255    }
6256
6257    /**
6258     * Returns the index of the first occurrence of a value in Uint16Array.
6259     *
6260     * @param searchElement The value to locate in the array.
6261     *
6262     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6263     *  search starts at index 0.
6264     *
6265     * @returns index of element if it presents, -1 otherwise
6266     */
6267    public indexOf(searchElement: number, fromIndex: int): number {
6268        if (isNaN(searchElement)) {
6269            return -1
6270        }
6271        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
6272        for (let i = fromIndex; i < this.lengthInt; i++) {
6273            if (this.getUnsafe(i) as number == searchElement) {
6274                return i
6275            }
6276        }
6277        return -1
6278    }
6279
6280    /**
6281     * Returns the index of the first occurrence of a value in Uint16Array.
6282     *
6283     * @param searchElement The value to locate in the array.
6284     *
6285     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6286     *  search starts at index 0.
6287     *
6288     * @returns index of element if it presents, -1 otherwise
6289     */
6290    public indexOf(searchElement: int, fromIndex: int): number {
6291        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
6292        for (let i = fromIndex; i < this.lengthInt; i++) {
6293            if (this.getUnsafe(i) == searchElement) {
6294                return i
6295            }
6296        }
6297        return -1
6298
6299    }
6300
6301    /**
6302     * Returns the index of the first occurrence of a value in Uint16Array.
6303     *
6304     * @param searchElement The value to locate in the array.
6305     *
6306     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6307     *  search starts at index 0.
6308     *
6309     * @returns index of element if it presents, -1 otherwise
6310     */
6311    public indexOf(searchElement: int): number {
6312        return this.indexOf(searchElement, 0)
6313    }
6314
6315    /**
6316     * Adds all the elements of an array separated by the specified separator string
6317     *
6318     * @param separator A string used to separate one element of an array from the next in the
6319     * resulting String. If omitted, the array elements are separated with a comma
6320     *
6321     * @returns joined representation
6322     */
6323    public join(separator?: String): string {
6324        if (separator == undefined) {
6325            return this.join(",")
6326        }
6327        let res: StringBuilder = new StringBuilder("")
6328        for (let i = 0; i < this.lengthInt - 1; i++) {
6329            res.append(this.getUnsafe(i) as number)
6330            res.append(separator)
6331        }
6332        if (this.lengthInt > 0) {
6333            res.append(this.getUnsafe(this.lengthInt - 1) as number)
6334        }
6335        return res.toString()
6336    }
6337
6338    /**
6339     * Returns an list of keys in Uint16Array
6340     *
6341     * @returns iterator over keys
6342     */
6343    public keys(): IterableIterator<number> {
6344        return new Uint16ArrayIteratorKeys(this)
6345    }
6346
6347    /**
6348     * Returns the index of the last occurrence of a value in Uint16Array.
6349     *
6350     * @param searchElement The value to locate in the array.
6351     *
6352     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6353     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6354     *
6355     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6356     */
6357    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
6358        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
6359    }
6360
6361    /**
6362     * Returns the index of the last occurrence of a value in Uint16Array.
6363     *
6364     * @param searchElement The value to locate in the array.
6365     *
6366     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6367     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6368     *
6369     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6370     */
6371    public lastIndexOf(searchElement: number): number {
6372        return this.lastIndexOf(searchElement, this.lengthInt - 1)
6373    }
6374
6375    /**
6376     * Returns the index of the last occurrence of a value in Uint16Array.
6377     *
6378     * @param searchElement The value to locate in the array.
6379     *
6380     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6381     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6382     *
6383     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6384     */
6385    public lastIndexOf(searchElement: number, fromIndex: int): number {
6386        if (isNaN(searchElement)) {
6387            return -1
6388        }
6389        if (this.lengthInt == 0) {
6390            return -1
6391        }
6392        let k: int = this.lengthInt + fromIndex
6393        if (fromIndex >= 0) {
6394            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
6395        }
6396        while (k >= 0) {
6397            if (this.getUnsafe(k) as number == searchElement) {
6398                return k
6399            }
6400            k--
6401        }
6402        return -1
6403    }
6404
6405    /**
6406     * Returns the index of the last occurrence of a value in Uint16Array.
6407     *
6408     * @param searchElement The value to locate in the array.
6409     *
6410     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6411     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6412     *
6413     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6414     */
6415    public lastIndexOf(searchElement: int, fromIndex: int): number {
6416        if (this.lengthInt == 0) {
6417            return -1
6418        }
6419        let k: int = this.lengthInt + fromIndex
6420        if (fromIndex >= 0) {
6421            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
6422        }
6423        while (k >= 0) {
6424            if (this.getUnsafe(k) == searchElement) {
6425                return k
6426            }
6427            k--
6428        }
6429        return -1
6430    }
6431
6432    /**
6433     * Returns the index of the last occurrence of a value in Uint16Array.
6434     *
6435     * @param searchElement The value to locate in the array.
6436     *
6437     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6438     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6439     *
6440     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6441     */
6442    public lastIndexOf(searchElement: int): number {
6443        return this.lastIndexOf(searchElement, this.lengthInt - 1)
6444    }
6445
6446   /**
6447    * Creates a new Uint16Array using initializer
6448    *
6449    * @param data initializer
6450    *
6451    * @returns a new Uint16Array from data
6452    */
6453    public of(...data: number[]): Uint16Array {
6454        throw new Error("Uint16Array.of: not implemented")
6455    }
6456
6457    /**
6458     * Creates a new Uint16Array using reversed data from the current one
6459     *
6460     * @returns a new Uint16Array using reversed data from the current one
6461     */
6462    public reverse(): Uint16Array {
6463        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
6464            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
6465            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
6466            this.setUnsafe(i, tmp)
6467        }
6468        return this
6469    }
6470
6471    /**
6472     * Creates a slice of current Uint16Array using range [begin, end)
6473     *
6474     * @param begin start index to be taken into slice
6475     *
6476     * @param end last index to be taken into slice
6477     *
6478     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6479     *
6480     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6481     */
6482    public slice(begin?: number, end?: number): Uint16Array {
6483        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
6484    }
6485
6486    /**
6487     * Creates a slice of current Uint16Array using range [begin, end)
6488     *
6489     * @param begin start index to be taken into slice
6490     *
6491     * @param end last index to be taken into slice
6492     *
6493     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6494     *
6495     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6496     */
6497    public slice(begin: number, end: number): Uint16Array {
6498        return this.slice(begin as int, end as int)
6499    }
6500
6501    /**
6502     * Creates a slice of current Uint16Array using range [begin, end)
6503     *
6504     * @param begin start index to be taken into slice
6505     *
6506     * @param end last index to be taken into slice
6507     *
6508     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6509     *
6510     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6511     */
6512    public slice(begin: number, end: int): Uint16Array {
6513        return this.slice(begin as int, end as int)
6514    }
6515
6516    /**
6517     * Creates a slice of current Uint16Array using range [begin, end)
6518     *
6519     * @param begin start index to be taken into slice
6520     *
6521     * @param end last index to be taken into slice
6522     *
6523     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6524     *
6525     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6526     */
6527    public slice(begin: int, end: number): Uint16Array {
6528        return this.slice(begin as int, end as int)
6529    }
6530
6531    /**
6532     * Creates a slice of current Uint16Array using range [begin, end)
6533     *
6534     * @param begin start index to be taken into slice
6535     *
6536     * @param end last index to be taken into slice
6537     *
6538     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6539     *
6540     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6541     */
6542    public slice(begin: int, end: int): Uint16Array {
6543        const len: int = this.lengthInt
6544        const relStart = normalizeIndex(begin, len)
6545        const relEnd = normalizeIndex(end, len)
6546        let count = relEnd - relStart
6547        if (count < 0) {
6548            count = 0
6549        }
6550        if (this.buffer instanceof ArrayBuffer) {
6551            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint16Array.BYTES_PER_ELEMENT as int, relEnd * Uint16Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
6552            return new Uint16Array(buf)
6553        } else if (this.buffer instanceof SharedArrayBuffer) {
6554            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint16Array.BYTES_PER_ELEMENT as int, relEnd * Uint16Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
6555            return new Uint16Array(buf)
6556        } else {
6557            throw new Error("unexpected type of buffer")
6558        }
6559    }
6560
6561    /**
6562     * Creates a slice of current Uint16Array using range [begin, this.lengthInt).
6563     *
6564     * @param begin start index to be taken into slice
6565     *
6566     * @returns a new Uint16Array with elements of current Uint16Array[begin, this.lengthInt)
6567     */
6568    public slice(begin: number): Uint16Array {
6569        return this.slice(begin as int)
6570    }
6571
6572    /**
6573     * Creates a slice of current Uint16Array using range [begin, this.lengthInt).
6574     *
6575     * @param begin start index to be taken into slice
6576     *
6577     * @returns a new Uint16Array with elements of current Uint16Array[begin, this.lengthInt)
6578     */
6579    public slice(begin: int): Uint16Array {
6580        return this.slice(begin, this.lengthInt)
6581    }
6582
6583    /**
6584     * Sorts in-place
6585     *
6586     * @param compareFn comparator —  used to determine the order of the elements.
6587     * compareFn returns a negative value if first argument is less than second argument,
6588     * zero if they're equal and a positive value otherwise.
6589     * If omitted, the elements are sorted in ascending order.
6590     *
6591     * @returns sorted Uint16Array
6592     */
6593    public sort(compareFn?: (a: number, b: number) => number): this {
6594        let arr: int[] = new int[this.lengthInt]
6595        for (let i = 0; i < this.lengthInt; ++i) {
6596            arr[i] = this.getUnsafe(i)
6597        }
6598        let cmp = (l: int, r: int): number => {
6599                return (l - r) as number
6600            }
6601        if (compareFn != undefined) {
6602            cmp = (l: int, r: int): number => {
6603                return compareFn!(l as number, r as number)
6604            }
6605        }
6606        sort(arr, cmp)
6607        for (let i = 0; i < this.lengthInt; ++i) {
6608            this.setUnsafe(i, arr[i])
6609        }
6610        return this
6611    }
6612
6613    /**
6614     * Sorts in-place
6615     *
6616     * @param compareFn comparator —  used to determine the order of the elements.
6617     * compareFn returns a negative value if first argument is less than second argument,
6618     * zero if they're equal and a positive value otherwise.
6619     *
6620     * @returns sorted Uint16Array
6621     */
6622    public sort(compareFn: (a: number) => number): this {
6623        let cmp = (a: number, b: number) => { return compareFn(a)}
6624        this.sort(cmp)
6625        return this
6626    }
6627
6628    /**
6629     * Sorts in-place
6630     *
6631     * @param fn compareFn —  used to determine the order of the elements.
6632     * compareFn returns a negative value if first argument is less than second argument,
6633     * zero if they're equal and a positive value otherwise.
6634     *
6635     * @returns sorted Uint16Array
6636     */
6637    public sort(compareFn: () => number): this {
6638        let cmp = (a: number, b: number) => { return compareFn()}
6639        this.sort(cmp)
6640        return this
6641    }
6642    /**
6643     * Creates a Uint16Array with the same underlying Buffer
6644     *
6645     * @param begin start index, inclusive
6646     *
6647     * @param end last index, exclusive
6648     *
6649     * @returns new Uint16Array with the same underlying Buffer
6650     */
6651    public subarray(begin?: number, end?: number): Uint16Array {
6652        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
6653    }
6654
6655    /**
6656     * Creates a Uint16Array with the same underlying Buffer
6657     *
6658     * @param begin start index, inclusive
6659     *
6660     * @param end last index, exclusive
6661     *
6662     * @returns new Uint16Array with the same underlying Buffer
6663     */
6664    public subarray(begin: number, end: number): Uint16Array {
6665        return this.subarray(begin as int, end as int)
6666    }
6667
6668    /**
6669     * Creates a Uint16Array with the same underlying Buffer
6670     *
6671     * @param begin start index, inclusive
6672     *
6673     * @param end last index, exclusive
6674     *
6675     * @returns new Uint16Array with the same underlying Buffer
6676     */
6677    public subarray(begin: number, end: int): Uint16Array {
6678        return this.subarray(begin as int, end as int)
6679    }
6680
6681    /**
6682     * Creates a Uint16Array with the same underlying Buffer
6683     *
6684     * @param begin start index, inclusive
6685     *
6686     * @param end last index, exclusive
6687     *
6688     * @returns new Uint16Array with the same underlying Buffer
6689     */
6690    public subarray(begin: int, end: number): Uint16Array {
6691        return this.subarray(begin as int, end as int)
6692    }
6693
6694    /**
6695     * Creates a Uint16Array with the same underlying Buffer
6696     *
6697     * @param begin start index, inclusive
6698     *
6699     * @param end last index, exclusive
6700     *
6701     * @returns new Uint16Array with the same underlying Buffer
6702     */
6703    public subarray(begin: int, end: int): Uint16Array {
6704        const len: int = this.lengthInt
6705        const relStart = normalizeIndex(begin, len)
6706        const relEnd = normalizeIndex(end, len)
6707        let count = relEnd - relStart
6708        if (count < 0) {
6709            count = 0
6710        }
6711        return new Uint16Array(this.buffer, relStart * Uint16Array.BYTES_PER_ELEMENT as int, count)
6712    }
6713
6714    /**
6715     * Creates a Uint16Array with the same Buffer
6716     *
6717     * @param begin start index, inclusive
6718     *
6719     * @returns new Uint16Array with the same Buffer
6720     */
6721    public subarray(begin: number): Uint16Array {
6722        return this.subarray(begin as int, this.lengthInt)
6723    }
6724
6725    /**
6726     * Creates a Uint16Array with the same Buffer
6727     *
6728     * @param begin start index, inclusive
6729     *
6730     * @returns new Uint16Array with the same Buffer
6731     */
6732    public subarray(begin: int): Uint16Array {
6733        return this.subarray(begin, this.lengthInt)
6734    }
6735
6736    /**
6737     * Converts Uint16Array to a string with respect to locale
6738     *
6739     * @param locales
6740     *
6741     * @param options
6742     *
6743     * @returns string representation
6744     */
6745    public toLocaleString(locales: Object, options: Object): string {
6746        throw new Error("Uint16Array.toLocaleString: not implemented")
6747    }
6748
6749    /**
6750     * Converts Uint16Array to a string with respect to locale
6751     *
6752     * @param locales
6753     *
6754     * @returns string representation
6755     */
6756    public toLocaleString(locales: Object): string {
6757        return this.toLocaleString(new Object(), new Object())
6758    }
6759
6760    /**
6761     * Converts Uint16Array to a string with respect to locale
6762     *
6763     * @returns string representation
6764     */
6765    public toLocaleString(): string {
6766        let res: StringBuilder = new StringBuilder("")
6767        for (let i = 0; i < this.lengthInt - 1; ++i) {
6768            res.append((this.getUnsafe(i) as Number).toLocaleString())
6769            res.append(",")
6770        }
6771        if (this.lengthInt > 0) {
6772            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
6773        }
6774        return res.toString()
6775    }
6776
6777    /**
6778     * Creates a reversed copy
6779     *
6780     * @returns a reversed copy
6781     */
6782    public toReversed(): Uint16Array {
6783        return new Uint16Array(this).reverse()
6784    }
6785
6786    /**
6787     * Creates a sorted copy
6788     *
6789     * @returns a sorted copy
6790     */
6791    public toSorted(): Uint16Array {
6792        return new Uint16Array(this).sort()
6793    }
6794
6795    /**
6796     * Returns a string representation of the Uint16Array
6797     *
6798     * @returns a string representation of the Uint16Array
6799     */
6800    public override toString(): string {
6801        return this.join(",")
6802    }
6803
6804    /**
6805     * Returns array values iterator
6806     *
6807     * @returns an iterator
6808     */
6809    public values(): IterableIterator<Number> {
6810         return new Uint16ArrayIterator(this)
6811    }
6812
6813    /**
6814     * Creates a copy with replaced value on index
6815     *
6816     * @param index
6817     *
6818     * @param value
6819     *
6820     * @returns an Uint16Array with replaced value on index
6821     */
6822    public with(index: number, value: number): Uint16Array {
6823        return this.with(index as int, value as int)
6824    }
6825
6826    /**
6827     * Creates a copy with replaced value on index
6828     *
6829     * @param index
6830     *
6831     * @param value
6832     *
6833     * @returns an Uint16Array with replaced value on index
6834     */
6835    public with(index: int, value: int): Uint16Array {
6836        let res = new Uint16Array(this)
6837        res.setUnsafeClamp(index, value)
6838        return res
6839    }
6840
6841    /// === with element lambda functions ===
6842
6843    /**
6844     * Determines whether the specified callback function returns true for all elements of an array.
6845     *
6846     * @param predicate A function that accepts one argument.
6847     * The every method calls the predicate function for each element in the array until the predicate returns a false,
6848     * or until the end of the array.
6849     *
6850     * @returns true unless predicate function returns a false for an array element,
6851     * in which case false is immediately returned.
6852     */
6853    public every(predicate: (element: number) => boolean): boolean {
6854        return this.every((element: number, index: number, array: Uint16Array): boolean => predicate(element))
6855    }
6856
6857    /**
6858     * creates a new Uint16Array from current Uint16Array based on a condition fn
6859     *
6860     * @param fn the condition to apply for each element
6861     *
6862     * @returns a new Uint16Array with elements from current Uint16Array that satisfy condition fn
6863     */
6864    public filter(fn: (val: number) => boolean): Uint16Array {
6865        let newF: (val: number, index: number, array: Uint16Array) => boolean =
6866            (val: number, index: number, array: Uint16Array): boolean => { return fn(val) }
6867        return this.filter(newF)
6868    }
6869
6870    /**
6871     * Returns the value of the first element in the array where predicate is true, and undefined
6872     * otherwise
6873     *
6874     * @param predicate find calls predicate once for each element of the array, in ascending
6875     * order, until it finds one where predicate returns true. If such an element is found, find
6876     * immediately returns that element value. Otherwise, find returns undefined
6877     *
6878     * @returns number | undefined
6879     */
6880    public find(predicate: () => boolean): number | undefined {
6881        return this.find((value: number, index: number, obj: Uint16Array): boolean => predicate())
6882    }
6883
6884    /**
6885     * Returns the value of the first element in the array where predicate is true, and undefined
6886     * otherwise
6887     *
6888     * @param predicate find calls predicate once for each element of the array, in ascending
6889     * order, until it finds one where predicate returns true. If such an element is found, find
6890     * immediately returns that element value. Otherwise, find returns undefined
6891     *
6892     * @returns number | undefined
6893     */
6894    public find(predicate: (value: number) => boolean): number | undefined {
6895        return this.find((value: number, index: number, obj: Uint16Array): boolean => predicate(value))
6896    }
6897
6898    /**
6899     * Returns the index of the first element in the array where predicate is true, and -1
6900     * otherwise
6901     *
6902     * @param predicate find calls predicate once for each element of the array, in ascending
6903     * order, until it finds one where predicate returns true. If such an element is found,
6904     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
6905     *
6906     * @returns number
6907     */
6908    public findIndex(predicate: (value: number) => boolean): number {
6909        return this.findIndex((value: number, index: number, obj: Uint16Array): boolean => predicate(value)) as number
6910    }
6911
6912    /**
6913     * Finds the last element in the Uint16Array that satisfies the condition
6914     *
6915     * @param fn condition
6916     *
6917     * @returns the last element that satisfies fn
6918     */
6919    public findLast(fn: (val: number) => boolean): number {
6920        let newF: (val: number, index: number, array: Uint16Array) => boolean =
6921            (val: number, index: number, array: Uint16Array): boolean => { return fn(val) }
6922        return this.findLast(newF)
6923    }
6924
6925    /**
6926     * Finds an index of the last element in the Uint16Array that satisfies the condition
6927     *
6928     * @param fn condition
6929     *
6930     * @returns the index of the last element that satisfies fn, -1 otherwise
6931     */
6932    public findLastIndex(fn: (val: number) => boolean): number {
6933        let newF: (val: number, index: number, array: Uint16Array) => boolean =
6934            (val: number, index: number, array: Uint16Array): boolean => { return fn(val) }
6935        return this.findLastIndex(newF) as number
6936    }
6937
6938    /**
6939     * Performs the specified action for each element in Uint16Array
6940     *
6941     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
6942     * callbackfn function one time for each element in the array.
6943     *
6944     * @returns None
6945     */
6946    public forEach(callbackfn: (val: number) => void): void {
6947        this.forEach((value: number, index: number, array: Uint16Array): void => callbackfn(value))
6948    }
6949
6950
6951    /**
6952     * Determines whether the specified callback function returns true for any element of an array.
6953     *
6954     * @param predicate A function that accepts one argument.
6955     * The some method calls the predicate function for each element in the array
6956     * until the predicate returns a true or until the end of the array.
6957     *
6958     * @returns false unless predicate function returns true for an array element,
6959     * in which case true is immediately returned.
6960     */
6961    public some(predicate: (element: number) => boolean): boolean {
6962        return this.some((element: number, index: number, array: Uint16Array): boolean => predicate(element))
6963    }
6964
6965    /**
6966     * Determines whether the specified callback function returns true for any element of an array.
6967     *
6968     * @param predicate A function that accepts three arguments.
6969     * The some method calls the predicate function for each element in the array
6970     * until the predicate returns a true or until the end of the array.
6971     *
6972     * @returns false unless predicate function returns true for an array element,
6973     * in which case true is immediately returned.
6974     */
6975    public some(predicate: (element: number, index: number, array: Uint16Array) => boolean): boolean {
6976        for (let i = 0; i < this.lengthInt; i++) {
6977            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
6978                return true
6979            }
6980        }
6981        return false
6982    }
6983
6984    /**
6985     * Determines whether the specified callback function returns true for any element of an array.
6986     *
6987     * @param predicate A function that accepts two arguments.
6988     * The some method calls the predicate function for each element in the array
6989     * until the predicate returns a true or until the end of the array.
6990     *
6991     * @returns false unless predicate function returns true for an array element,
6992     * in which case true is immediately returned.
6993     */
6994    public some(predicate: (element: number, index: number) => boolean): boolean {
6995        return this.some((element: number, index: number, array: Uint16Array): boolean => predicate(element, index))
6996    }
6997
6998    /**
6999     * Determines whether the specified callback function returns true for any element of an array.
7000     *
7001     * @param predicate A function that accepts no arguments.
7002     * The some method calls the predicate function for each element in the array
7003     * until the predicate returns a true or until the end of the array.
7004     *
7005     * @returns false unless predicate function returns true for an array element,
7006     * in which case true is immediately returned.
7007     */
7008    public some(predicate: () => boolean): boolean {
7009        return this.some((element: number, index: number, array: Uint16Array): boolean => predicate())
7010    }
7011
7012    /**
7013     * Calls the specified callback function for all the elements in an array.
7014     * The return value of the callback function is the accumulated result,
7015     * and is provided as an argument in the next call to the callback function.
7016     *
7017     * @param callbackfn A function that accepts four arguments.
7018     * The reduce method calls the callbackfn function one time for each element in the array.
7019     *
7020     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7021     * The first call to the callbackfn function provides this value as an argument.
7022     *
7023     * @returns The value that results from running the callback function to completion over the entire typed array.
7024     */
7025    public reduce<U = number>(
7026                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U,
7027                initialValue: U): U {
7028        let accumulatedValue = initialValue
7029        for (let i = 0; i < this.lengthInt; i++) {
7030            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7031        }
7032        return accumulatedValue
7033    }
7034
7035    /**
7036     * Calls the specified callback function for all the elements in an array.
7037     * The return value of the callback function is the accumulated result,
7038     * and is provided as an argument in the next call to the callback function.
7039     *
7040     * @param callbackfn A function that accepts three arguments.
7041     * The reduce method calls the callbackfn function one time for each element in the array.
7042     *
7043     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7044     * The first call to the callbackfn function provides this value as an argument.
7045     *
7046     * @returns The value that results from running the callback function to completion over the entire typed array.
7047     */
7048    public reduce<U = number>(
7049                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
7050                initialValue: U): U {
7051        return this.reduce(
7052                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7053                        callbackfn(prevVal, currVal, currIndex),
7054                initialValue)
7055    }
7056
7057    /**
7058     * Calls the specified callback function for all the elements in an array.
7059     * The return value of the callback function is the accumulated result,
7060     * and is provided as an argument in the next call to the callback function.
7061     *
7062     * @param callbackfn A function that accepts two arguments.
7063     * The reduce method calls the callbackfn function one time for each element in the array.
7064     *
7065     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7066     * The first call to the callbackfn function provides this value as an argument.
7067     *
7068     * @returns The value that results from running the callback function to completion over the entire typed array.
7069     */
7070    public reduce<U = number>(
7071                callbackfn: (previousValue: U, currentValue: number) => U,
7072                initialValue: U): U {
7073        return this.reduce(
7074                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7075                        callbackfn(prevVal, currVal),
7076                initialValue)
7077    }
7078
7079    /**
7080     * Calls the specified callback function for all the elements in an array.
7081     * The return value of the callback function is the accumulated result,
7082     * and is provided as an argument in the next call to the callback function.
7083     *
7084     * @param callbackfn A function that accepts one argument
7085     * The reduce method calls the callbackfn function one time for each element in the array.
7086     *
7087     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7088     * The first call to the callbackfn function provides this value as an argument.
7089     *
7090     * @returns The value that results from running the callback function to completion over the entire typed array.
7091     */
7092    public reduce<U = number>(
7093                callbackfn: (previousValue: U) => U,
7094                initialValue: U): U {
7095        return this.reduce(
7096                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7097                        callbackfn(prevVal),
7098                initialValue)
7099    }
7100
7101    /**
7102     * Calls the specified callback function for all the elements in an array.
7103     * The return value of the callback function is the accumulated result,
7104     * and is provided as an argument in the next call to the callback function.
7105     *
7106     * @param callbackfn A function that accepts no arguments
7107     * The reduce method calls the callbackfn function one time for each element in the array.
7108     *
7109     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7110     * The first call to the callbackfn function provides this value as an argument.
7111     *
7112     * @returns The value that results from running the callback function to completion over the entire typed array.
7113     */
7114    public reduce<U = number>(
7115                callbackfn: () => U,
7116                initialValue: U): U {
7117        return this.reduce(
7118                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7119                        callbackfn(),
7120                initialValue)
7121    }
7122
7123    /**
7124     * Calls the specified callback function for all the elements in an array.
7125     * The return value of the callback function is the accumulated result,
7126     * and is provided as an argument in the next call to the callback function.
7127     *
7128     * @param callbackfn A function that accepts four arguments.
7129     * The reduce method calls the callbackfn function one time for each element in the array.
7130     * The first call to the callbackfn function provides array first element value as an argument
7131     *
7132     * @returns The value that results from running the callback function to completion over the entire typed array.
7133     * calling reduce method on an empty array without an initial value creates a TypeError
7134     */
7135    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number {
7136        if (this.lengthInt == 0) {
7137            throw new TypeError("Reduce of empty array with no initial value")
7138        }
7139
7140        let accumulatedValue = this.$_get(0) as number
7141        for (let i = 1; i < this.lengthInt; i++) {
7142            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7143        }
7144        return accumulatedValue
7145    }
7146
7147    /**
7148     * Calls the specified callback function for all the elements in an array.
7149     * The return value of the callback function is the accumulated result,
7150     * and is provided as an argument in the next call to the callback function.
7151     *
7152     * @param callbackfn A function that accepts three arguments.
7153     * The reduce method calls the callbackfn function one time for each element in the array.
7154     * The first call to the callbackfn function provides array first element value as an argument
7155     *
7156     * @returns The value that results from running the callback function to completion over the entire typed array.
7157     * calling reduce method on an empty array without an initial value creates a TypeError
7158     */
7159    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
7160        return this.reduce(
7161                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7162                        callbackfn(prevVal, currVal, currIndex))
7163    }
7164
7165    /**
7166     * Calls the specified callback function for all the elements in an array.
7167     * The return value of the callback function is the accumulated result,
7168     * and is provided as an argument in the next call to the callback function.
7169     *
7170     * @param callbackfn A function that accepts two arguments.
7171     * The reduce method calls the callbackfn function one time for each element in the array.
7172     * The first call to the callbackfn function provides array first element value as an argument
7173     *
7174     * @returns The value that results from running the callback function to completion over the entire typed array.
7175     * calling reduce method on an empty array without an initial value creates a TypeError
7176     */
7177    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
7178        return this.reduce(
7179                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7180                        callbackfn(prevVal, currVal))
7181    }
7182
7183    /**
7184     * Calls the specified callback function for all the elements in an array.
7185     * The return value of the callback function is the accumulated result,
7186     * and is provided as an argument in the next call to the callback function.
7187     *
7188     * @param callbackfn A function that accepts one argument.
7189     * The reduce method calls the callbackfn function one time for each element in the array.
7190     * The first call to the callbackfn function provides array first element value as an argument
7191     *
7192     * @returns The value that results from running the callback function to completion over the entire typed array.
7193     * calling reduce method on an empty array without an initial value creates a TypeError
7194     */
7195    public reduce(callbackfn: (previousValue: number) => number): number {
7196        return this.reduce(
7197                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7198                        callbackfn(prevVal))
7199    }
7200
7201    /**
7202     * Calls the specified callback function for all the elements in an array.
7203     * The return value of the callback function is the accumulated result,
7204     * and is provided as an argument in the next call to the callback function.
7205     *
7206     * @param callbackfn A function that accepts no arguments.
7207     * The reduce method calls the callbackfn function one time for each element in the array.
7208     * The first call to the callbackfn function provides array first element value as an argument
7209     *
7210     * @returns The value that results from running the callback function to completion over the entire typed array.
7211     * calling reduce method on an empty array without an initial value creates a TypeError
7212     */
7213    public reduce(callbackfn: () => number): number {
7214        return this.reduce(
7215                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7216                        callbackfn())
7217    }
7218
7219    /**
7220     * Calls the specified callback function for all the elements in an array, in descending order.
7221     * The return value of the callback function is the accumulated result,
7222     * and is provided as an argument in the next call to the callback function.
7223     *
7224     * @param callbackfn A function that accepts four arguments.
7225     * The reduceRight method calls the callbackfn function one time for each element in the array.
7226     *
7227     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7228     * The first call to the callbackfn function provides this value as an argument.
7229     *
7230     * @returns The value that results from running the callback function to completion over the entire typed array.
7231     */
7232    public reduceRight<U = number>(
7233                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U,
7234                initialValue: U): U {
7235        let accumulatedValue = initialValue
7236        for (let i = this.lengthInt - 1; i >= 0; i--) {
7237            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7238        }
7239        return accumulatedValue
7240    }
7241
7242    /**
7243     * Calls the specified callback function for all the elements in an array, in descending order.
7244     * The return value of the callback function is the accumulated result,
7245     * and is provided as an argument in the next call to the callback function.
7246     *
7247     * @param callbackfn A function that accepts three arguments.
7248     * The reduceRight method calls the callbackfn function one time for each element in the array.
7249     *
7250     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7251     * The first call to the callbackfn function provides this value as an argument.
7252     *
7253     * @returns The value that results from running the callback function to completion over the entire typed array.
7254     */
7255    public reduceRight<U = number>(
7256                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
7257                initialValue: U): U {
7258        return this.reduceRight(
7259                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7260                        callbackfn(prevVal, currVal, currIndex),
7261                initialValue)
7262    }
7263
7264    /**
7265     * Calls the specified callback function for all the elements in an array, in descending order.
7266     * The return value of the callback function is the accumulated result,
7267     * and is provided as an argument in the next call to the callback function.
7268     *
7269     * @param callbackfn A function that accepts two arguments.
7270     * The reduceRight method calls the callbackfn function one time for each element in the array.
7271     *
7272     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7273     * The first call to the callbackfn function provides this value as an argument.
7274     *
7275     * @returns The value that results from running the callback function to completion over the entire typed array.
7276     */
7277    public reduceRight<U = number>(
7278                callbackfn: (previuosValue: U, currentValue: number) => U,
7279                initialValue: U): U {
7280        return this.reduceRight(
7281                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7282                        callbackfn(prevVal, currVal),
7283                initialValue)
7284    }
7285
7286    /**
7287     * Calls the specified callback function for all the elements in an array, in descending order.
7288     * The return value of the callback function is the accumulated result,
7289     * and is provided as an argument in the next call to the callback function.
7290     *
7291     * @param callbackfn A function that accepts one argument.
7292     * The reduceRight method calls the callbackfn function one time for each element in the array.
7293     *
7294     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7295     * The first call to the callbackfn function provides this value as an argument.
7296     *
7297     * @returns The value that results from running the callback function to completion over the entire typed array.
7298     */
7299    public reduceRight<U = number>(
7300                callbackfn: (previuosValue: U) => U,
7301                initialValue: U): U {
7302        return this.reduceRight(
7303                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7304                        callbackfn(prevVal),
7305                initialValue)
7306    }
7307
7308    /**
7309     * Calls the specified callback function for all the elements in an array, in descending order.
7310     * The return value of the callback function is the accumulated result,
7311     * and is provided as an argument in the next call to the callback function.
7312     *
7313     * @param callbackfn A function that accepts no arguments.
7314     * The reduceRight method calls the callbackfn function one time for each element in the array.
7315     *
7316     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7317     * The first call to the callbackfn function provides this value as an argument.
7318     *
7319     * @returns The value that results from running the callback function to completion over the entire typed array.
7320     */
7321    public reduceRight<U = number>(
7322                callbackfn: () => U,
7323                initialValue: U): U {
7324        return this.reduceRight(
7325                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7326                        callbackfn(),
7327                initialValue)
7328    }
7329
7330    /**
7331     * Calls the specified callback function for all the elements in an array, in descending order.
7332     * The return value of the callback function is the accumulated result,
7333     * and is provided as an argument in the next call to the callback function.
7334     *
7335     * @param callbackfn A function that accepts four arguments.
7336     * The reduceRight method calls the callbackfn function one time for each element in the array.
7337     * The first call to the callbackfn function provides array last element value as an argument
7338     *
7339     * @returns The value that results from running the callback function to completion over the entire typed array.
7340     * calling reduceRight method on an empty array without an initial value creates a TypeError
7341     */
7342    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number {
7343        if (this.lengthInt == 0) {
7344            throw new TypeError("Reduce of empty array with no initial value")
7345        }
7346
7347        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
7348        for (let i = this.lengthInt - 2; i >= 0; i--) {
7349            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7350        }
7351        return accumulatedValue
7352    }
7353
7354    /**
7355     * Calls the specified callback function for all the elements in an array, in descending order.
7356     * The return value of the callback function is the accumulated result,
7357     * and is provided as an argument in the next call to the callback function.
7358     *
7359     * @param callbackfn A function that accepts three arguments.
7360     * The reduceRight method calls the callbackfn function one time for each element in the array.
7361     * The first call to the callbackfn function provides array last element value as an argument
7362     *
7363     * @returns The value that results from running the callback function to completion over the entire typed array.
7364     * calling reduceRight method on an empty array without an initial value creates a TypeError
7365     */
7366    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
7367        return this.reduceRight(
7368                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7369                        callbackfn(prevValue, currValue, currIndex))
7370    }
7371
7372    /**
7373     * Calls the specified callback function for all the elements in an array, in descending order.
7374     * The return value of the callback function is the accumulated result,
7375     * and is provided as an argument in the next call to the callback function.
7376     *
7377     * @param callbackfn A function that accepts two arguments.
7378     * The reduceRight method calls the callbackfn function one time for each element in the array.
7379     * The first call to the callbackfn function provides array last element value as an argument
7380     *
7381     * @returns The value that results from running the callback function to completion over the entire typed array.
7382     * calling reduceRight method on an empty array without an initial value creates a TypeError
7383     */
7384    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
7385        return this.reduceRight(
7386                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7387                        callbackfn(prevValue, currValue))
7388    }
7389
7390    /**
7391     * Calls the specified callback function for all the elements in an array, in descending order.
7392     * The return value of the callback function is the accumulated result,
7393     * and is provided as an argument in the next call to the callback function.
7394     *
7395     * @param callbackfn A function that accepts one argument.
7396     * The reduceRight method calls the callbackfn function one time for each element in the array.
7397     * The first call to the callbackfn function provides array last element value as an argument
7398     *
7399     * @returns The value that results from running the callback function to completion over the entire typed array.
7400     * calling reduceRight method on an empty array without an initial value creates a TypeError
7401     */
7402    public reduceRight(callbackfn: (previousValue: number) => number): number {
7403        return this.reduceRight(
7404                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7405                        callbackfn(prevValue))
7406    }
7407
7408    /**
7409     * Calls the specified callback function for all the elements in an array, in descending order.
7410     * The return value of the callback function is the accumulated result,
7411     * and is provided as an argument in the next call to the callback function.
7412     *
7413     * @param callbackfn A function that accepts no arguments.
7414     * The reduceRight method calls the callbackfn function one time for each element in the array.
7415     * The first call to the callbackfn function provides array last element value as an argument
7416     *
7417     * @returns The value that results from running the callback function to completion over the entire typed array.
7418     * calling reduceRight method on an empty array without an initial value creates a TypeError
7419     */
7420    public reduceRight(callbackfn: () => number): number {
7421        return this.reduceRight(
7422                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7423                        callbackfn())
7424    }
7425
7426    /**
7427     * Creates a new Uint16Array using fn(arr[i]) over all elements of current Uint16Array.
7428     *
7429     * @param fn a function to apply for each element of current Uint16Array
7430     *
7431     * @returns a new Uint16Array where for each element from current Uint16Array fn was applied
7432     */
7433    public map(fn: (val: number, index: number, array: Uint16Array) => number): Uint16Array {
7434        let resBuf = new ArrayBuffer(this.lengthInt * Uint16Array.BYTES_PER_ELEMENT as int)
7435        let res = new Uint16Array(resBuf)
7436        for (let i = 0; i < this.lengthInt; i++) {
7437            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
7438            res.setUnsafeClamp(i, fnRes as int)
7439        }
7440        return res
7441    }
7442
7443    /**
7444     * Creates a new Uint16Array using fn(arr[i], i) over all elements of current Uint16Array
7445     *
7446     * @param fn a function to apply for each element of current Uint16Array
7447     *
7448     * @returns a new Uint16Array where for each element from current Uint16Array fn was applied
7449     */
7450    public map(fn: (val: number, index: number) => number): Uint16Array {
7451        let newF: (val: number, index: number, array: Uint16Array) => number =
7452            (val: number, index: number, array: Uint16Array): number => { return fn(val, index) }
7453        return this.map(newF)
7454    }
7455
7456    /**
7457     * Creates a new Uint16Array using fn(arr[i]) over all elements of current Uint16Array
7458     *
7459     * @param fn a function to apply for each element of current Uint16Array
7460     *
7461     * @returns a new Uint16Array where for each element from current Uint16Array fn was applied
7462     */
7463    public map(fn: (val: number) => number): Uint16Array {
7464        let newF: (val: number, index: number, array: Uint16Array) => number =
7465            (val: number, index: number, array: Uint16Array): number => { return fn(val) }
7466        return this.map(newF)
7467    }
7468
7469    /**
7470     * Creates a new Uint16Array using fn() over all elements of current Uint16Array
7471     *
7472     * @param fn a function to apply for each element of current Uint16Array
7473     *
7474     * @returns a new Uint16Array where for each element from current Uint16Array fn was applied
7475     */
7476    public map(fn: () => number): Uint16Array {
7477        let newF: (val: number, index: number, array: Uint16Array) => number =
7478            (val: number, index: number, array: Uint16Array): number => { return fn() }
7479        return this.map(newF)
7480    }
7481
7482    /**
7483     * Determines whether the specified callback function returns true for all elements of an array.
7484     *
7485     * @param predicate A function that accepts three arguments.
7486     * The every method calls the predicate function for each element in the array until the predicate returns a false,
7487     * or until the end of the array.
7488     *
7489     * @returns true unless predicate function returns a false for an array element,
7490     * in which case false is immediately returned.
7491     */
7492    public every(predicate: (element: number, index: number, array: Uint16Array) => boolean): boolean {
7493        for (let i = 0; i < this.lengthInt; i++) {
7494            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
7495                return false
7496            }
7497        }
7498        return true
7499    }
7500
7501    /**
7502     * Determines whether the specified callback function returns true for all elements of an array.
7503     *
7504     * @param predicate A function that accepts two arguments.
7505     * The every method calls the predicate function for each element in the array until the predicate returns a false,
7506     * or until the end of the array.
7507     *
7508     * @returns true unless predicate function returns a false for an array element,
7509     * in which case false is immediately returned.
7510     */
7511    public every(predicate: (element: number, index: number) => boolean): boolean {
7512        return this.every((element: number, index: number, array: Uint16Array): boolean => predicate(element, index))
7513    }
7514
7515    /**
7516     * Determines whether the specified callback function returns true for all elements of an array.
7517     *
7518     * @param predicate A function that accepts no arguments.
7519     * The every method calls the predicate function for each element in the array until the predicate returns a false,
7520     * or until the end of the array.
7521     *
7522     * @returns true unless predicate function returns a false for an array element,
7523     * in which case false is immediately returned.
7524     */
7525    public every(predicate: () => boolean): boolean {
7526        return this.every((element: number, index: number, array: Uint16Array): boolean => predicate())
7527    }
7528
7529    /**
7530     * Creates a new Uint16Array from current Uint16Array based on a condition fn.
7531     *
7532     * @param fn the condition to apply for each element
7533     *
7534     * @returns a new Uint16Array with elements from current Uint16Array that satisfy condition fn
7535     */
7536    public filter(fn: (val: number, index: number, array: Uint16Array) => boolean): Uint16Array {
7537        let markers = new boolean[this.lengthInt]
7538        let resLen = 0
7539        for (let i = 0; i < this.lengthInt; i++) {
7540            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
7541            if (markers[i]) {
7542                ++resLen
7543            }
7544        }
7545        let res = new Uint16Array(resLen)
7546        for (let i = 0, j = 0; i < this.lengthInt; i++) {
7547            if (markers[i]) {
7548                res.setUnsafe(j, this.getUnsafe(i))
7549                ++j
7550            }
7551        }
7552        return res
7553    }
7554
7555    /**
7556     * creates a new Uint16Array from current Uint16Array based on a condition fn
7557     *
7558     * @param fn the condition to apply for each element
7559     *
7560     * @returns a new Uint16Array with elements from current Uint16Array that satisfy condition fn
7561     */
7562    public filter(fn: (val: number, index: number) => boolean): Uint16Array {
7563        let newF: (val: number, index: number, array: Uint16Array) => boolean =
7564            (val: number, index: number, array: Uint16Array): boolean => { return fn(val, index) }
7565        return this.filter(newF)
7566    }
7567
7568    /**
7569     * Returns the value of the first element in the array where predicate is true, and undefined
7570     * otherwise
7571     *
7572     * @param predicate find calls predicate once for each element of the array, in ascending
7573     * order, until it finds one where predicate returns true. If such an element is found, find
7574     * immediately returns that element value. Otherwise, find returns undefined
7575     *
7576     * @returns number | undefined
7577     */
7578    public find(predicate: (value: number, index: number, array: Uint16Array) => boolean): number | undefined {
7579        for (let i = 0; i < this.lengthInt; i++) {
7580            let val = this.getUnsafe(i) as number
7581            if (predicate(val, i as number, this)) {
7582                return val
7583            }
7584        }
7585        return undefined
7586    }
7587
7588    /**
7589     * Returns the value of the first element in the array where predicate is true, and undefined
7590     * otherwise
7591     *
7592     * @param predicate find calls predicate once for each element of the array, in ascending
7593     * order, until it finds one where predicate returns true. If such an element is found, find
7594     * immediately returns that element value. Otherwise, find returns undefined
7595     *
7596     * @returns number | undefined
7597     */
7598    public find(predicate: (value: number, index: number) => boolean): number | undefined {
7599        return this.find((value: number, index: number, obj: Uint16Array): boolean => predicate(value, index))
7600    }
7601
7602    /**
7603     * Returns the index of the first element in the array where predicate is true, and -1
7604     * otherwise
7605     *
7606     * @param predicate find calls predicate once for each element of the array, in ascending
7607     * order, until it finds one where predicate returns true. If such an element is found,
7608     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
7609     *
7610     * @returns number
7611     */
7612    public findIndex(predicate: (value: number, index: number, obj: Uint16Array) => boolean): number {
7613        for (let i = 0; i < this.lengthInt; i++) {
7614            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
7615                return i as number
7616            }
7617        }
7618        return -1 as number
7619    }
7620
7621    /**
7622     * Returns the index of the first element in the array where predicate is true, and -1
7623     * otherwise
7624     *
7625     * @param predicate find calls predicate once for each element of the array, in ascending
7626     * order, until it finds one where predicate returns true. If such an element is found,
7627     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
7628     *
7629     * @returns number
7630     */
7631    public findIndex(predicate: (value: number, index: number) => boolean): number {
7632        return this.findIndex((value: number, index: number, obj: Uint16Array): boolean => predicate(value, index))
7633    }
7634
7635    /**
7636     * Returns the index of the first element in the array where predicate is true, and -1
7637     * otherwise
7638     *
7639     * @param predicate find calls predicate once for each element of the array, in ascending
7640     * order, until it finds one where predicate returns true. If such an element is found,
7641     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
7642     *
7643     * @returns number
7644     */
7645    public findIndex(predicate: () => boolean): number {
7646        return this.findIndex((value: number, index: number, obj: Uint16Array): boolean => predicate())
7647    }
7648
7649    /**
7650     * Finds the last element in the Uint16Array that satisfies the condition
7651     *
7652     * @param fn condition
7653     *
7654     * @returns the last element that satisfies fn
7655     */
7656    public findLast(fn: (val: number, index: number, array: Uint16Array) => boolean): number {
7657        for (let i = this.lengthInt - 1; i >= 0; i--) {
7658            let val = this.getUnsafe(i) as number
7659            if (fn(val, i as number, this)) {
7660                return val
7661            }
7662        }
7663        throw new Error("Uint16Array.findLast: not implemented if an element was not found")
7664    }
7665
7666    /**
7667     * Finds the last element in the Uint16Array that satisfies the condition
7668     *
7669     * @param fn condition
7670     *
7671     * @returns the last element that satisfies fn
7672     */
7673    public findLast(fn: (val: number, index: number) => boolean): number {
7674        let newF: (val: number, index: number, array: Uint16Array) => boolean =
7675            (val: number, index: number, array: Uint16Array): boolean => { return fn(val, index) }
7676        return this.findLast(newF)
7677    }
7678
7679    /**
7680     * Finds an index of the last element in the Uint16Array that satisfies the condition
7681     *
7682     * @param fn condition
7683     *
7684     * @returns the index of the last element that satisfies fn, -1 otherwise
7685     */
7686    public findLastIndex(fn: (val: number, index: number, array: Uint16Array) => boolean): number {
7687        for (let i = this.lengthInt - 1; i >= 0; i--) {
7688            if (fn(this.getUnsafe(i) as number, i as number, this)) {
7689                return i as number
7690            }
7691        }
7692        return -1 as number
7693    }
7694
7695    /**
7696     * Finds an index of the last element in the Uint16Array that satisfies the condition
7697     *
7698     * @param fn condition
7699     *
7700     * @returns the index of the last element that satisfies fn, -1 otherwise
7701     */
7702    public findLastIndex(fn: (val: number, index: number) => boolean): number {
7703        let newF: (val: number, index: number, array: Uint16Array) => boolean =
7704            (val: number, index: number, array: Uint16Array): boolean => { return fn(val, index) }
7705        return this.findLastIndex(newF) as number
7706    }
7707
7708    /**
7709     * Performs the specified action for each element in Uint16Array
7710     *
7711     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
7712     * callbackfn function one time for each element in the array.
7713     *
7714     * @returns None
7715     */
7716    public forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void): void {
7717        for (let i = 0; i < this.lengthInt; i++) {
7718            callbackfn(this.getUnsafe(i) as number, i as number, this)
7719        }
7720    }
7721
7722    /**
7723     * Performs the specified action for each element in Uint16Array
7724     *
7725     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
7726     * callbackfn function one time for each element in the array.
7727     *
7728     * @returns None
7729     */
7730    public forEach(callbackfn: (value: number, index: number) => void): void {
7731        this.forEach((value: number, index: number, array: Uint16Array): void => callbackfn(value, index))
7732    }
7733
7734    /**
7735     * Performs the specified action for each element in Uint16Array
7736     *
7737     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
7738     * callbackfn function one time for each element in the array.
7739     *
7740     * @returns None
7741     */
7742    public forEach(callbackfn: () => void): void {
7743        this.forEach((value: number, index: number, array: Uint16Array): void => callbackfn())
7744    }
7745
7746    /**
7747     * Returns the object itself
7748     *
7749     * @returns Uint16Array
7750     */
7751    public valueOf(): Uint16Array {
7752        return this
7753    }
7754
7755    /** Byte offset within the underlying Buffer */
7756    public get byteOffset(): number {
7757        return this.byteOffsetInt
7758    }
7759
7760    /** Number of bytes used */
7761    public get byteLength(): number {
7762        return this.byteLengthInt
7763    }
7764
7765    /** Number of int stored in Uint16Array */
7766    public get length(): number {
7767        return this.lengthInt
7768    }
7769
7770    /** String \"Uint16Array\" */
7771    public readonly name = "Uint16Array"
7772
7773    private static clamp(val: int): int {
7774        return val
7775    }
7776
7777    internal setUnsafeClamp(insertPos: int, val: int): void {
7778        this.setUnsafe(insertPos, val)
7779    }
7780
7781    internal getUnsafe(index: int): int {
7782        index = index * Uint16Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
7783        let res: int = 0
7784        if (IS_LITTLE_ENDIAN) {
7785            if (this.buffer instanceof ArrayBuffer) {
7786                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7787                    let el = (this.buffer as ArrayBuffer).at(index + i) as int
7788                    el &= 0xff
7789                    res |= el << (8 * i)
7790                }
7791            } else if (this.buffer instanceof SharedArrayBuffer) {
7792                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7793                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as int
7794                    el &= 0xff
7795                    res |= el << (8 * i)
7796                }
7797            } else {
7798                throw new Error("unexpected type of ArrayBufferLike")
7799            }
7800        } else {
7801            if (this.buffer instanceof ArrayBuffer) {
7802                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7803                    let el = (this.buffer as ArrayBuffer).at(index + 1 - i) as int
7804                    el &= 0xff
7805                    res |= el << (8 * i)
7806                }
7807            } else if (this.buffer instanceof SharedArrayBuffer) {
7808                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7809                    let el = (this.buffer as SharedArrayBuffer).at(index + 1 - i) as int
7810                    el &= 0xff
7811                    res |= el << (8 * i)
7812                }
7813            } else {
7814                throw new Error("unexpected type of ArrayBufferLike")
7815            }
7816        }
7817        return res
7818    }
7819
7820    internal setUnsafe(index: int, val: int): void {
7821        index = index * Uint16Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
7822        let res: int = 0
7823        if (IS_LITTLE_ENDIAN) {
7824            if (this.buffer instanceof ArrayBuffer) {
7825                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7826                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
7827                    val = val >> 8
7828                }
7829            } else if (this.buffer instanceof SharedArrayBuffer) {
7830                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7831                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
7832                    val = val >> 8
7833                }
7834            } else {
7835                throw new Error("unexpected type of ArrayBufferLike")
7836            }
7837        } else {
7838            if (this.buffer instanceof ArrayBuffer) {
7839                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7840                    (this.buffer as ArrayBuffer).set(index + 1 - i, (val & 0xff) as byte)
7841                    val = val >> 8
7842                }
7843            } else if (this.buffer instanceof SharedArrayBuffer) {
7844                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7845                    (this.buffer as SharedArrayBuffer).set(index + 1 - i, (val & 0xff) as byte)
7846                    val = val >> 8
7847                }
7848            } else {
7849                throw new Error("unexpected type of ArrayBufferLike")
7850            }
7851        }
7852    }
7853}
7854
7855
7856class Uint32ArrayIteratorKeys implements IterableIterator<number> {
7857    private length: int = 0
7858    private idx: int = 0
7859
7860    constructor(parent: Uint32Array) {
7861        this.length = parent.length as int
7862    }
7863
7864    public override $_iterator(): IterableIterator<Number> {
7865        return this
7866    }
7867
7868    override next(): IteratorResult<number> {
7869        if (this.idx < 0 || this.idx >= this.length) {
7870            return new IteratorResult<number>()
7871        }
7872        return new IteratorResult<number>(false, this.idx++ as number)
7873    }
7874}
7875
7876class Uint32ArrayIterator implements IterableIterator<Number> {
7877    private parent: Uint32Array
7878    private idx: int = 0
7879
7880    constructor(parent: Uint32Array) {
7881        this.parent = parent
7882    }
7883
7884    public override $_iterator(): IterableIterator<Number> {
7885        return this
7886    }
7887
7888    override next(): IteratorResult<Number> {
7889        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
7890            return new IteratorResult<Number>()
7891        }
7892        return new IteratorResult<Number>(false, new Number(this.parent.getUnsafe(this.idx++)))
7893    }
7894}
7895
7896class Uint32ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
7897    private parent: Uint32Array
7898    private idx: int = 0
7899
7900    constructor(parent: Uint32Array) {
7901        this.parent = parent
7902    }
7903
7904    public override $_iterator(): IterableIterator<[Number, Number]> {
7905        return this
7906    }
7907
7908    override next(): IteratorResult<[Number, Number]> {
7909        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
7910            return new IteratorResult<[Number, Number]>()
7911        }
7912        return new IteratorResult<[Number, Number]>(
7913            false,
7914            [new Number(this.idx), new Number(this.parent.getUnsafe(this.idx++))]
7915        )
7916    }
7917}
7918
7919/**
7920 * JS Uint32Array API-compatible class
7921 */
7922export class Uint32Array implements Iterable<Number>, ArrayLike<Number> {
7923    public static readonly BYTES_PER_ELEMENT: number = 4
7924
7925    /** Underlying Buffer */
7926    public readonly buffer: ArrayBufferLike
7927
7928    internal readonly byteOffsetInt: int
7929    internal readonly byteLengthInt: int
7930    internal readonly lengthInt: int
7931
7932    /**
7933     * Creates an empty Uint32Array.
7934     */
7935    public constructor() {
7936        this(0 as int)
7937    }
7938
7939    /**
7940     * Creates an Uint32Array with respect to data accessed via Iterable<Number> interface
7941     */
7942    public constructor(elements: Iterable<Number>) {
7943        const items: Object = elements as Object
7944        if (items instanceof ArrayLike) {
7945            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
7946            this.byteLengthInt = arr.length as int * Uint32Array.BYTES_PER_ELEMENT as int
7947            this.lengthInt = arr.length as int
7948            this.buffer = new ArrayBuffer(this.byteLengthInt)
7949            this.byteOffsetInt = 0
7950            for (let i: int = 0; i < this.lengthInt; ++i) {
7951                this.setUnsafe(i, arr.$_get(i).longValue())
7952            }
7953        } else {
7954            let x = Uint32Array.from(elements)
7955            this.byteLengthInt = x.byteLengthInt
7956            this.lengthInt = x.lengthInt
7957            this.buffer = x.buffer
7958            this.byteOffsetInt = x.byteOffsetInt
7959        }
7960    }
7961
7962    /**
7963     * Creates an Uint32Array with respect to data, byteOffset and length.
7964     *
7965     * @param buf data initializer
7966     *
7967     * @param byteOffset byte offset from begin of the buf
7968     *
7969     * @param length size of elements of type long in newly created Uint32Array
7970     */
7971    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
7972        let intByteOffset: int = 0
7973        if (byteOffset != undefined) {
7974            intByteOffset = byteOffset.intValue()
7975            if (intByteOffset < 0) {
7976                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
7977            }
7978        }
7979        let intByteLength: int
7980        if (buf instanceof ArrayBuffer) {
7981            intByteLength = (buf as ArrayBuffer).getByteLength()
7982        } else if (buf instanceof SharedArrayBuffer) {
7983            intByteLength = (buf as SharedArrayBuffer).getByteLength()
7984        } else {
7985            throw new Error("unexpected type of ArrayBufferLike")
7986        }
7987        intByteLength = intByteLength - intByteOffset
7988        if (intByteLength < 0) {
7989            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
7990        }
7991
7992        if (intByteLength % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
7993            throw new RangeError("ArrayBufferLike.byteLength should be multiple of 4 as Uint32Array.BYTES_PER_ELEMENT")
7994        }
7995        if (intByteOffset % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
7996            throw new RangeError("byteOffset should be multiple of 4 as Uint32Array.BYTES_PER_ELEMENT")
7997        }
7998
7999        let intLength: int
8000        if (length != undefined) {
8001            intLength = length.intValue()
8002            if (intLength > intByteLength / Uint32Array.BYTES_PER_ELEMENT as int) {
8003                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
8004            }
8005        } else {
8006            intLength = intByteLength / Uint32Array.BYTES_PER_ELEMENT as int
8007        }
8008        if (intLength < 0) {
8009            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
8010        }
8011        if (intLength < intByteLength / Uint32Array.BYTES_PER_ELEMENT as int) {
8012            intByteLength = intLength * Uint32Array.BYTES_PER_ELEMENT as int
8013        }
8014        this.byteLengthInt = intByteLength
8015        this.byteOffsetInt = intByteOffset
8016        this.lengthInt = intLength
8017        this.buffer = buf
8018    }
8019
8020    /**
8021     * Creates an Uint32Array with respect to data, byteOffset and length.
8022     *
8023     * @param buf data initializer
8024     *
8025     * @param byteOffset byte offset from begin of the buf
8026     */
8027    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
8028        this(buf, byteOffset, undefined)
8029    }
8030
8031    /**
8032     * Creates an Uint32Array with respect to data, byteOffset and length.
8033     *
8034     * @param buf data initializer
8035     *
8036     * @param byteOffset byte offset from begin of the buf
8037     *
8038     * @param length size of elements of type long in newly created Uint32Array
8039     */
8040    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
8041        this(buf, new Number(byteOffset), new Number(length))
8042    }
8043
8044    /**
8045     * Creates an Uint32Array with respect to buf and byteOffset.
8046     *
8047     * @param buf data initializer
8048     *
8049     * @param byteOffset byte offset from begin of the buf
8050     */
8051    public constructor(buf: ArrayBufferLike, byteOffset: number) {
8052        this(buf, new Number(byteOffset), undefined)
8053    }
8054
8055    /**
8056     * Creates an Uint32Array with respect to data, byteOffset and length.
8057     *
8058     * @param buf data initializer
8059     *
8060     * @param byteOffset byte offset from begin of the buf
8061     *
8062     * @param length size of elements of type long in newly created Uint32Array
8063     */
8064    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
8065        this(buf, new Number(byteOffset), new Number(length))
8066    }
8067
8068    /**
8069     * Creates an Uint32Array with respect to buf and byteOffset.
8070     *
8071     * @param buf data initializer
8072     *
8073     * @param byteOffset byte offset from begin of the buf
8074     */
8075    public constructor(buf: ArrayBufferLike, byteOffset: int) {
8076        this(buf, new Number(byteOffset), undefined)
8077    }
8078
8079    /**
8080     * Creates an Uint32Array with respect to buf.
8081     *
8082     * @param buf data initializer
8083     */
8084    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
8085        if (buf instanceof ArrayBuffer) {
8086            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
8087            if (this.byteLengthInt % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
8088               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as Uint32Array.BYTES_PER_ELEMENT")
8089            }
8090            this.lengthInt = this.byteLengthInt / Uint32Array.BYTES_PER_ELEMENT as int
8091            this.buffer = buf as ArrayBuffer
8092            this.byteOffsetInt = 0
8093        } else if (buf instanceof SharedArrayBuffer) {
8094            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
8095            if (this.byteLengthInt % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
8096               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as Uint32Array.BYTES_PER_ELEMENT")
8097            }
8098            this.lengthInt = this.byteLengthInt / Uint32Array.BYTES_PER_ELEMENT as int
8099            this.buffer = buf as SharedArrayBuffer
8100            this.byteOffsetInt = 0
8101        } else if (buf instanceof ArrayLike) {
8102            // NOTE (ikorobkov): dealing with this overload is tricky
8103            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
8104            let arr = Array.from<Number>((buf as ArrayLike<Number>))
8105            this.byteLengthInt = arr.length as int * Uint32Array.BYTES_PER_ELEMENT as int
8106            this.lengthInt = arr.length as int
8107            this.buffer = new ArrayBuffer(this.byteLengthInt)
8108            this.byteOffsetInt = 0
8109            for (let i: int = 0; i < this.lengthInt; ++i) {
8110                this.setUnsafe(i, arr.$_get(i).longValue())
8111            }
8112        } else {
8113            throw new Error("unexpected type of buf")
8114        }
8115    }
8116
8117    /**
8118     * Creates an Uint32Array with respect to length.
8119     *
8120     * @param length data initializer
8121     */
8122    public constructor(length: int) {
8123        if (length < 0) {
8124            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
8125        }
8126        this.lengthInt = length
8127        this.byteLengthInt = length * Uint32Array.BYTES_PER_ELEMENT as int
8128        this.byteOffsetInt = 0
8129        this.buffer = new ArrayBuffer(this.byteLengthInt)
8130    }
8131
8132    /**
8133     * Creates an Uint32Array with respect to length.
8134     *
8135     * @param length data initializer
8136     */
8137    public constructor(length: number) {
8138        this(length as int)
8139    }
8140
8141    /**
8142     * Creates a copy of Uint32Array.
8143     *
8144     * @param other data initializer
8145     */
8146    public constructor(other: Uint32Array) {
8147        if (other.buffer instanceof ArrayBuffer) {
8148            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
8149        } else if (other.buffer instanceof SharedArrayBuffer) {
8150            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
8151        } else {
8152            throw new Error("unexpected type of buffer")
8153        }
8154        this.byteLengthInt = other.byteLength as int
8155        this.lengthInt = other.length as int
8156        this.byteOffsetInt = 0
8157    }
8158
8159    /**
8160     * Creates an Uint32Array from number[]
8161     */
8162    public constructor(numbers: number[]) {
8163        this(numbers.length)
8164        for (let i: int = 0; i < this.lengthInt; ++i) {
8165            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as long)
8166        }
8167    }
8168
8169    /**
8170     * Creates an Uint32Array from int[]
8171     */
8172    public constructor(numbers: int[]) {
8173        this(numbers.length)
8174        for (let i: int = 0; i < this.lengthInt; ++i) {
8175            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as long)
8176        }
8177    }
8178
8179    internal zeroIfInfinity(val: number): number {
8180        if ((val == Infinity) || (val == -Infinity)) {
8181            return 0 as number
8182        }
8183        return val as number
8184    }
8185
8186    internal zeroIfInfinity(val: long): long {
8187        if ((val == Infinity) || (val == -Infinity)) {
8188            return 0 as long
8189        }
8190        return val
8191    }
8192
8193    /**
8194     * Iteratorable interface implementation
8195     *
8196     * @returns iterator over all elements
8197     */
8198    public override $_iterator(): IterableIterator<Number> {
8199         return this.values()
8200    }
8201
8202    /**
8203     * Returns an instance of primitive type at passed index.
8204     *
8205     * @param index index to look at
8206     *
8207     * @returns a primitive at index
8208     */
8209    public at(index: number): Number | undefined {
8210        return this.at(index as int)
8211    }
8212
8213    /**
8214     * Returns an instance of primitive type at passed index if index is correct.
8215     *
8216     * @param index index to look at
8217     *
8218     * @returns a primitive at index
8219     */
8220    public at(index: int): Number | undefined {
8221        let k: int
8222        if (index >= 0) {
8223            k = index
8224        } else {
8225            k = this.lengthInt + index
8226        }
8227        if (k < 0 || k >= this.lengthInt) {
8228            return undefined
8229        }
8230        return new Number(this.getUnsafe(k))
8231    }
8232
8233    /**
8234     * Returns an instance of number at passed index.
8235     *
8236     * @param index index to look at
8237     *
8238     * @returns a primitive at index
8239     */
8240    public override $_get(index: number): Number {
8241        return this.$_get(index as int) as Number
8242    }
8243
8244    /**
8245     * Returns an instance of number at passed index.
8246     *
8247     * @param index index to look at
8248     *
8249     * @returns a primitive at index
8250     */
8251    public $_get(i: int): number {
8252        if (i < 0 || i >= this.lengthInt) {
8253            throw new RangeError("invalid offset")
8254        }
8255        return this.getUnsafe(i) as number
8256    }
8257
8258    /**
8259     * Assigns val as element on index.
8260     *
8261     * @param val value to set
8262     *
8263     * @param index index to change
8264     */
8265    public $_set(index: number, val: number): void {
8266        this.$_set(index as int, val)
8267    }
8268
8269    /**
8270     * Assigns val as element on index.
8271     *
8272     * @param val value to set
8273     *
8274     * @param index index to change
8275     */
8276    public $_set(index: int, val: number): void {
8277        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
8278        if (index < 0 || index >= this.lengthInt) {
8279            throw new RangeError("invalid index")
8280        }
8281        let v = this.zeroIfInfinity(val)
8282        this.setUnsafeClamp(index, v as long)
8283    }
8284
8285    /**
8286     * Assigns val as element on index.
8287     *
8288     * @param val value to set
8289     *
8290     * @param index index to change
8291     */
8292    public $_set(index: number, val: long): void {
8293        this.$_set(index as int, val)
8294    }
8295
8296    /**
8297     * Assigns val as element on index.
8298     *
8299     * @param val value to set
8300     *
8301     * @param index index to change
8302     */
8303    public $_set(index: int, val: long): void {
8304        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
8305        if (index < 0 || index >= this.lengthInt) {
8306            throw new RangeError("invalid index")
8307        }
8308        let v = this.zeroIfInfinity(val)
8309        this.setUnsafeClamp(index, v)
8310    }
8311
8312    /**
8313     * Assigns val as element on index.
8314     *
8315     * @param val value to set
8316     *
8317     * @param index index to change
8318     */
8319    public $_set(index: number, val: int): void {
8320        this.$_set(index as int, val as int)
8321    }
8322
8323    /**
8324     * Assigns val as element on index.
8325     *
8326     * @param val value to set
8327     *
8328     * @param index index to change
8329     */
8330    public $_set(index: int, val: int): void {
8331        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
8332        if (index < 0 || index >= this.lengthInt) {
8333            throw new RangeError("invalid index")
8334        }
8335        let v = this.zeroIfInfinity(val as long)
8336        this.setUnsafeClamp(index, v)
8337    }
8338
8339    /**
8340     * Makes a copy of internal elements to targetPos from startPos to endPos.
8341     *
8342     * @param target insert index to place copied elements
8343     *
8344     * @param start start index to begin copy from
8345     *
8346     * @param end last index to end copy from, excluded
8347     *
8348     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8349     */
8350    public copyWithin(target: number, start: number, end?: number): Uint32Array {
8351        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8352    }
8353
8354    /**
8355     * Makes a copy of internal elements to targetPos from startPos to endPos.
8356     *
8357     * @param target insert index to place copied elements
8358     *
8359     * @param start start index to begin copy from
8360     *
8361     * @param end last index to end copy from, excluded
8362     *
8363     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8364     */
8365    public copyWithin(target: int, start: number, end?: number): Uint32Array {
8366        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8367    }
8368
8369    /**
8370     * Makes a copy of internal elements to targetPos from startPos to endPos.
8371     *
8372     * @param target insert index to place copied elements
8373     *
8374     * @param start start index to begin copy from
8375     *
8376     * @param end last index to end copy from, excluded
8377     *
8378     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8379     */
8380    public copyWithin(target: number, start: int, end?: number): Uint32Array {
8381        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8382    }
8383
8384    /**
8385     * Makes a copy of internal elements to targetPos from startPos to endPos.
8386     *
8387     * @param target insert index to place copied elements
8388     *
8389     * @param start start index to begin copy from
8390     *
8391     * @param end last index to end copy from, excluded
8392     *
8393     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8394     */
8395    public copyWithin(target: int, start: int, end?: number): Uint32Array {
8396        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8397    }
8398
8399    /**
8400     * Makes a copy of internal elements to targetPos from startPos to endPos.
8401     *
8402     * @param insert insert index to place copied elements
8403     *
8404     * @param start start index to begin copy from
8405     *
8406     * @param end last index to end copy from, excluded
8407     *
8408     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8409     */
8410    public copyWithin(target: int, start: int, end: int): Uint32Array {
8411        let toPos = normalizeIndex(target, this.lengthInt)
8412        let fromPos = normalizeIndex(start, this.lengthInt)
8413        const finalPos = normalizeIndex(end, this.lengthInt)
8414        let count: int = finalPos - fromPos
8415        if (count > (this.lengthInt - toPos)) {
8416            count = this.lengthInt - toPos
8417        }
8418        let direction: int = 1
8419        if ((fromPos < toPos) && (toPos < fromPos + count)) {
8420            fromPos = fromPos + count - 1
8421            toPos   = toPos   + count - 1
8422            direction = -1
8423        }
8424        while (count > 0) {
8425            const value = this.getUnsafe(fromPos)
8426            this.setUnsafe(toPos, value)
8427            fromPos = fromPos + direction
8428            toPos = toPos + direction
8429            --count
8430        }
8431        return this
8432    }
8433
8434    /**
8435     * Makes a copy of internal elements to targetPos from begin to end of Uint32Array.
8436     *
8437     * @param target insert index to place copied elements
8438     *
8439     * See rules of parameters normalization:
8440     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
8441     */
8442    public copyWithin(target: number): Uint32Array {
8443        return this.copyWithin(target as int)
8444    }
8445
8446    /**
8447     * Makes a copy of internal elements to targetPos from begin to end of Uint32Array.
8448     *
8449     * @param insert insert index to place copied elements
8450     *
8451     * See rules of parameters normalization:
8452     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
8453     */
8454    public copyWithin(target: int): Uint32Array {
8455        return this.copyWithin(target, 0, this.lengthInt)
8456    }
8457
8458    /**
8459     * Returns an array of key, value pairs for every entry in the Uint32Array
8460     *
8461     * @returns key, value pairs for every entry in the array
8462     */
8463    public entries(): IterableIterator<[Number, Number]> {
8464        return new Uint32ArrayIteratorEntries(this)
8465    }
8466
8467    /**
8468     * Fills the Uint32Array with specified value
8469     *
8470     * @param value new value
8471     *
8472     * @returns modified Uint32Array
8473     */
8474    public fill(value: number, start?: number, end?: number): Uint32Array {
8475        value = this.zeroIfInfinity(value)
8476        this.fill(value as long, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
8477        return this
8478    }
8479
8480    /**
8481     * Fills the Uint32Array with specified value
8482     *
8483     * @param value new value
8484     *
8485     * @returns modified Uint32Array
8486     */
8487    public fill(value: number, start: int, end?: number): Uint32Array {
8488        value = this.zeroIfInfinity(value)
8489        this.fill(value as long, start as int, asIntOrDefault(end, this.lengthInt))
8490        return this
8491    }
8492
8493    /**
8494     * Fills the Uint32Array with specified value
8495     *
8496     * @param value new value
8497     *
8498     * @returns modified Uint32Array
8499     */
8500    public fill(value: number, start: int, end: number): Uint32Array {
8501        value = this.zeroIfInfinity(value)
8502        this.fill(value as long, start as int, end as int)
8503        return this
8504    }
8505
8506    /**
8507     * Fills the Uint32Array with specified value
8508     *
8509     * @param value new value
8510     *
8511     * @returns modified Uint32Array
8512     */
8513    public fill(value: number, start: number, end: int): Uint32Array {
8514        value = this.zeroIfInfinity(value)
8515        this.fill(value as long, start as int, end as int)
8516        return this
8517    }
8518
8519    /**
8520     * Fills the Uint32Array with specified value
8521     *
8522     * @param value new value
8523     *
8524     * @returns modified Uint32Array
8525     */
8526    public fill(value: number, start: int, end: int): Uint32Array {
8527        value = this.zeroIfInfinity(value)
8528        this.fill(value as long, start as int, end as int)
8529        return this
8530    }
8531
8532    /**
8533     * Fills the Uint32Array with specified value
8534     *
8535     * @param value new value
8536     *
8537     * @returns modified Uint32Array
8538     */
8539    public fill(value: long, start?: number, end?: number): Uint32Array {
8540        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
8541        return this
8542    }
8543
8544    /**
8545     * Fills the Uint32Array with specified value
8546     *
8547     * @param value new value
8548     *
8549     * @returns modified Uint32Array
8550     */
8551    public fill(value: long, start: int, end?: number): Uint32Array {
8552        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
8553        return this
8554    }
8555
8556    /**
8557     * Fills the Uint32Array with specified value
8558     *
8559     * @param value new value
8560     *
8561     * @returns modified Uint32Array
8562     */
8563    public fill(value: long, start: int, end: number): Uint32Array {
8564        this.fill(value, start as int, end as int)
8565        return this
8566    }
8567
8568    /**
8569     * Fills the Uint32Array with specified value
8570     *
8571     * @param value new value
8572     *
8573     * @returns modified Uint32Array
8574     */
8575    public fill(value: long, start: number, end: int): Uint32Array {
8576        this.fill(value, start as int, end as int)
8577        return this
8578    }
8579
8580    /**
8581     * Fills the Uint32Array with specified value
8582     *
8583     * @param value new value
8584     *
8585     * @returns modified Uint32Array
8586     */
8587    public fill(value: long, start: int, end: int): Uint32Array {
8588        const k = normalizeIndex(start, this.lengthInt)
8589        const finalPos = normalizeIndex(end, this.lengthInt)
8590        for (let i: int = k; i < finalPos; ++i) {
8591            this.setUnsafe(i, value)
8592        }
8593        return this
8594    }
8595
8596    /**
8597     * Assigns val as element on index.
8598     *
8599     * @param val value to set
8600     *
8601     * @param index index to change
8602     */
8603    public set(insertPos: number, val: number): void {
8604        this.$_set(insertPos as int, val)
8605    }
8606
8607    /**
8608     * Assigns val as element on index.
8609     *
8610     * @param val value to set
8611     *
8612     * @param index index to change
8613     */
8614    public set(insertPos: int, val: number): void {
8615        this.$_set(insertPos as int, val)
8616    }
8617
8618    /**
8619     * Assigns val as element on index.
8620     *
8621     * @param val value to set
8622     *
8623     * @param index index to change
8624     */
8625    public set(insertPos: number, val: long): void {
8626        this.$_set(insertPos as int, val)
8627    }
8628
8629    /**
8630     * Assigns val as element on index.
8631     *
8632     * @param val value to set
8633     *
8634     * @param index index to change
8635     */
8636    public set(insertPos: int, val: long): void {
8637        this.$_set(insertPos as int, val)
8638    }
8639
8640    /**
8641     * Copies all elements of arr to the current Uint32Array starting from insertPos.
8642     *
8643     * @param arr array to copy data from
8644     *
8645     * @param insertPos start index where data from arr will be inserted
8646     *
8647     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
8648     */
8649    public set(arr: number[], insertPos1: number): void {
8650        const insertPos = insertPos1 as int
8651        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
8652            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than Uint32Array.length")
8653        }
8654        for (let i = 0; i < arr.length; i++) {
8655            let v = this.zeroIfInfinity(arr[i])
8656            this.setUnsafeClamp(insertPos as int + i as int, v as long)
8657        }
8658    }
8659
8660    /**
8661     * Copies all elements of arr to the current Uint32Array starting from insertPos.
8662     *
8663     * @param arr array to copy data from
8664     *
8665     * @param insertPos start index where data from arr will be inserted
8666     *
8667     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
8668     */
8669    public set(arr: long[], insertPos: int): void {
8670        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
8671            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than Uint32Array.length")
8672        }
8673        for (let i = 0; i < arr.length; i++) {
8674            let v = this.zeroIfInfinity(arr[i])
8675            this.setUnsafeClamp(insertPos + i, v)
8676        }
8677    }
8678
8679    /**
8680     * Copies all elements of arr to the current Uint32Array.
8681     *
8682     * @param arr array to copy data from
8683     */
8684    public set(arr: number[]): void {
8685        this.set(arr, 0)
8686    }
8687
8688    /**
8689     * Copies all elements of arr to the current Uint32Array.
8690     *
8691     * @param arr array to copy data from
8692     */
8693    public set(arr: long[]): void {
8694        this.set(arr, 0)
8695    }
8696
8697    /**
8698     * Copies elements from an ArrayLike object to the Uint32Array.
8699     *
8700     * @param array An ArrayLike object containing the elements to copy.
8701     *
8702     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
8703     */
8704    public set(array: ArrayLike<number>, offset: number = 0): void {
8705        const insertPos = offset as int
8706        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
8707            throw new RangeError("offset is out of bounds")
8708        }
8709        for (let i = 0; i < array.length; i++) {
8710            let v = this.zeroIfInfinity(array[i])
8711            this.setUnsafeClamp(insertPos as int + i as int, v as long)
8712        }
8713    }
8714
8715    /**
8716     * Returns a new array from a set of elements.
8717     *
8718     * @param items a set of elements to include in the new array object.
8719     *
8720     * @returns new Uint32Array
8721     */
8722    public static of(...items: number[]): Uint32Array {
8723        let res = new Uint32Array(items.length as int)
8724        for (let i: int = 0; i < items.length; i++) {
8725            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as long)
8726        }
8727        return res
8728    }
8729
8730    /**
8731     * Returns a new array from a set of elements.
8732     *
8733     * @param items a set of elements to include in the new array object.
8734     *
8735     * @returns new Uint32Array
8736     */
8737    public static of(...items: int[]): Uint32Array {
8738        let res = new Uint32Array(items.length as int)
8739        for (let i: int = 0; i < items.length; i++) {
8740            res.setUnsafeClamp(i, items[i] as long)
8741        }
8742        return res
8743    }
8744
8745    /**
8746     * Returns a new array from a set of elements.
8747     *
8748     * @param items a set of elements to include in the new array object.
8749     *
8750     * @returns new Uint32Array
8751     */
8752    public static of(...items: long[]): Uint32Array {
8753        let res = new Uint32Array(items.length as int)
8754        for (let i: int = 0; i < items.length; i++) {
8755            res.setUnsafeClamp(i, items[i])
8756        }
8757        return res
8758    }
8759
8760    /**
8761     * Returns a new array from a set of elements.
8762     *
8763     * @param items a set of elements to include in the new array object.
8764     *
8765     * @returns new Uint32Array
8766     */
8767    public static of(): Uint32Array {
8768        return new Uint32Array(0 as int)
8769    }
8770
8771    /**
8772     * Creates an array from an array-like or iterable object.
8773     *
8774     * @param arrayLike An array-like or iterable object to convert to an array.
8775     *
8776     * @returns new Uint32Array
8777     */
8778    public static from(arr: ArrayLike<number>): Uint32Array {
8779        return Uint32Array.from<number>(arr, (x: number, k: number): number => x)
8780    }
8781
8782    /**
8783     * Creates an array from an array-like or iterable object.
8784     *
8785     * @param arrayLike An array-like or iterable object to convert to an array.
8786     *
8787     * @param mapfn A mapping function to call on every element of the array.
8788     *
8789     * @returns new Uint32Array
8790     */
8791    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint32Array {
8792        if (mapfn == undefined) {
8793            mapfn = (v: number, k: number): number => { return v }
8794        }
8795
8796        let iter = arrayLike.$_iterator()
8797        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
8798        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
8799        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
8800        //  we can make one pass through the iterator without the need for memory reallocation.
8801        const maybeLength = tryGetIteratorLength(arrayLike)
8802        if (maybeLength) {
8803            const result = new Uint32Array(maybeLength)
8804            for (let i = 0; i < maybeLength; ++i) {
8805                const x = iter.next()
8806                if (x.done) {
8807                    return new Uint32Array(result.buffer, 0, i)
8808                }
8809                result.setUnsafeClamp(i, result.zeroIfInfinity((mapfn)!(x.value!, i)) as long)
8810            }
8811            return result
8812        }
8813
8814        // NOTE (templin.konstantin): Create builtin array as buffer
8815        let temp = new Uint32Array(6)
8816        let index = new int[1]
8817        index[0] = 0
8818
8819        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
8820            if (index[0] + 1 > temp.lengthInt) {
8821                // NOTE (templin.konstantin): Progressive reallocation
8822                const curLength = (temp.buffer as Buffer).getByteLength()
8823                const tb = new ArrayBuffer(curLength * 2)
8824                for (let i = 0; i < curLength; ++i) {
8825                    tb.set(i, (temp.buffer as Buffer).at(i))
8826                }
8827                temp = new Uint32Array(tb)
8828            }
8829            temp.setUnsafeClamp(index[0], temp.zeroIfInfinity((mapfn)!(x, index[0])) as long)
8830            index[0]++
8831        })
8832
8833        return new Uint32Array(temp.buffer, 0, index[0])
8834    }
8835
8836    /**
8837     * Creates an array from an array-like or iterable object.
8838     *
8839     * @param arrayLike An array-like or iterable object to convert to an array.
8840     *
8841     * @param mapfn A mapping function to call on every element of the array.
8842     *
8843     * @returns new Uint32Array
8844     */
8845    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint32Array {
8846        let res = new Uint32Array(arrayLike.length)
8847        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
8848        const idx = new int[1]
8849        idx[0] = 0
8850        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
8851            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as long)
8852            idx[0] += 1
8853        })
8854        return res
8855    }
8856
8857    /**
8858     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
8859     *
8860     * @param searchElement The element to search for
8861     *
8862     * @param fromIndex The position in this array at which to begin searching for searchElement
8863     *
8864     * @returns true if searchElement is in Uint32Array, false otherwise
8865     */
8866    public includes(searchElement: number, fromIndex?: number): boolean {
8867        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
8868    }
8869
8870    /**
8871     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
8872     *
8873     * @param searchElement The element to search for
8874     *
8875     * @param fromIndex The position in this array at which to begin searching for searchElement
8876     *
8877     * @returns true if searchElement is in Uint32Array, false otherwise
8878     */
8879    public includes(searchElement: long, fromIndex: int): boolean {
8880        return this.indexOf(searchElement as int, fromIndex) != -1
8881    }
8882
8883    /**
8884     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
8885     *
8886     * @param searchElement The element to search for
8887     *
8888     * @param fromIndex The position in this array at which to begin searching for searchElement
8889     *
8890     * @returns true if searchElement is in Uint32Array, false otherwise
8891     */
8892    public includes(searchElement: long): boolean {
8893        return this.indexOf(searchElement as int, 0) != -1
8894    }
8895
8896    /**
8897     * Returns the index of the first occurrence of a value in Uint32Array.
8898     *
8899     * @param searchElement The value to locate in the array.
8900     *
8901     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8902     *  search starts at index 0.
8903     *
8904     * @returns index of element if it presents, -1 otherwise
8905     */
8906    public indexOf(searchElement: number, fromIndex?: number): number {
8907        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
8908    }
8909
8910    /**
8911     * Returns the index of the first occurrence of a value in Uint32Array.
8912     *
8913     * @param searchElement The value to locate in the array.
8914     *
8915     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8916     *  search starts at index 0.
8917     *
8918     * @returns index of element if it presents, -1 otherwise
8919     */
8920    public indexOf(searchElement: number, fromIndex: int): number {
8921        if (isNaN(searchElement)) {
8922            return -1
8923        }
8924        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
8925        for (let i = fromIndex; i < this.lengthInt; i++) {
8926            if (this.getUnsafe(i) as number == searchElement) {
8927                return i
8928            }
8929        }
8930        return -1
8931    }
8932
8933    /**
8934     * Returns the index of the first occurrence of a value in Uint32Array.
8935     *
8936     * @param searchElement The value to locate in the array.
8937     *
8938     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8939     *  search starts at index 0.
8940     *
8941     * @returns index of element if it presents, -1 otherwise
8942     */
8943    public indexOf(searchElement: int, fromIndex: int): number {
8944        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
8945        for (let i = fromIndex; i < this.lengthInt; i++) {
8946            if (this.getUnsafe(i) == searchElement as long) {
8947                return i
8948            }
8949        }
8950        return -1
8951
8952    }
8953
8954    /**
8955     * Returns the index of the first occurrence of a value in Uint32Array.
8956     *
8957     * @param searchElement The value to locate in the array.
8958     *
8959     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8960     *  search starts at index 0.
8961     *
8962     * @returns index of element if it presents, -1 otherwise
8963     */
8964    public indexOf(searchElement: int): number {
8965        return this.indexOf(searchElement, 0)
8966    }
8967
8968    /**
8969     * Adds all the elements of an array separated by the specified separator string
8970     *
8971     * @param separator A string used to separate one element of an array from the next in the
8972     * resulting String. If omitted, the array elements are separated with a comma
8973     *
8974     * @returns joined representation
8975     */
8976    public join(separator?: String): string {
8977        if (separator == undefined) {
8978            return this.join(",")
8979        }
8980        let res: StringBuilder = new StringBuilder("")
8981        for (let i = 0; i < this.lengthInt - 1; i++) {
8982            res.append(this.getUnsafe(i) as number)
8983            res.append(separator)
8984        }
8985        if (this.lengthInt > 0) {
8986            res.append(this.getUnsafe(this.lengthInt - 1) as number)
8987        }
8988        return res.toString()
8989    }
8990
8991    /**
8992     * Returns an list of keys in Uint32Array
8993     *
8994     * @returns iterator over keys
8995     */
8996    public keys(): IterableIterator<number> {
8997        return new Uint32ArrayIteratorKeys(this)
8998    }
8999
9000    /**
9001     * Returns the index of the last occurrence of a value in Uint32Array.
9002     *
9003     * @param searchElement The value to locate in the array.
9004     *
9005     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
9006     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
9007     *
9008     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
9009     */
9010    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
9011        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
9012    }
9013
9014    /**
9015     * Returns the index of the last occurrence of a value in Uint32Array.
9016     *
9017     * @param searchElement The value to locate in the array.
9018     *
9019     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
9020     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
9021     *
9022     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
9023     */
9024    public lastIndexOf(searchElement: number): number {
9025        return this.lastIndexOf(searchElement, this.lengthInt - 1)
9026    }
9027
9028    /**
9029     * Returns the index of the last occurrence of a value in Uint32Array.
9030     *
9031     * @param searchElement The value to locate in the array.
9032     *
9033     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
9034     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
9035     *
9036     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
9037     */
9038    public lastIndexOf(searchElement: number, fromIndex: int): number {
9039        if (isNaN(searchElement)) {
9040            return -1
9041        }
9042        if (this.lengthInt == 0) {
9043            return -1
9044        }
9045        let k: int = this.lengthInt + fromIndex
9046        if (fromIndex >= 0) {
9047            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
9048        }
9049        while (k >= 0) {
9050            if (this.getUnsafe(k) as number == searchElement) {
9051                return k
9052            }
9053            k--
9054        }
9055        return -1
9056    }
9057
9058    /**
9059     * Returns the index of the last occurrence of a value in Uint32Array.
9060     *
9061     * @param searchElement The value to locate in the array.
9062     *
9063     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
9064     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
9065     *
9066     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
9067     */
9068    public lastIndexOf(searchElement: int, fromIndex: int): number {
9069        if (this.lengthInt == 0) {
9070            return -1
9071        }
9072        let k: int = this.lengthInt + fromIndex
9073        if (fromIndex >= 0) {
9074            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
9075        }
9076        while (k >= 0) {
9077            if (this.getUnsafe(k) == searchElement as long) {
9078                return k
9079            }
9080            k--
9081        }
9082        return -1
9083    }
9084
9085    /**
9086     * Returns the index of the last occurrence of a value in Uint32Array.
9087     *
9088     * @param searchElement The value to locate in the array.
9089     *
9090     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
9091     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
9092     *
9093     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
9094     */
9095    public lastIndexOf(searchElement: int): number {
9096        return this.lastIndexOf(searchElement, this.lengthInt - 1)
9097    }
9098
9099   /**
9100    * Creates a new Uint32Array using initializer
9101    *
9102    * @param data initializer
9103    *
9104    * @returns a new Uint32Array from data
9105    */
9106    public of(...data: number[]): Uint32Array {
9107        throw new Error("Uint32Array.of: not implemented")
9108    }
9109
9110    /**
9111     * Creates a new Uint32Array using reversed data from the current one
9112     *
9113     * @returns a new Uint32Array using reversed data from the current one
9114     */
9115    public reverse(): Uint32Array {
9116        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
9117            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
9118            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
9119            this.setUnsafe(i, tmp)
9120        }
9121        return this
9122    }
9123
9124    /**
9125     * Creates a slice of current Uint32Array using range [begin, end)
9126     *
9127     * @param begin start index to be taken into slice
9128     *
9129     * @param end last index to be taken into slice
9130     *
9131     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
9132     *
9133     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
9134     */
9135    public slice(begin?: number, end?: number): Uint32Array {
9136        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
9137    }
9138
9139    /**
9140     * Creates a slice of current Uint32Array using range [begin, end)
9141     *
9142     * @param begin start index to be taken into slice
9143     *
9144     * @param end last index to be taken into slice
9145     *
9146     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
9147     *
9148     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
9149     */
9150    public slice(begin: number, end: number): Uint32Array {
9151        return this.slice(begin as int, end as int)
9152    }
9153
9154    /**
9155     * Creates a slice of current Uint32Array using range [begin, end)
9156     *
9157     * @param begin start index to be taken into slice
9158     *
9159     * @param end last index to be taken into slice
9160     *
9161     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
9162     *
9163     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
9164     */
9165    public slice(begin: number, end: int): Uint32Array {
9166        return this.slice(begin as int, end as int)
9167    }
9168
9169    /**
9170     * Creates a slice of current Uint32Array using range [begin, end)
9171     *
9172     * @param begin start index to be taken into slice
9173     *
9174     * @param end last index to be taken into slice
9175     *
9176     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
9177     *
9178     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
9179     */
9180    public slice(begin: int, end: number): Uint32Array {
9181        return this.slice(begin as int, end as int)
9182    }
9183
9184    /**
9185     * Creates a slice of current Uint32Array using range [begin, end)
9186     *
9187     * @param begin start index to be taken into slice
9188     *
9189     * @param end last index to be taken into slice
9190     *
9191     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
9192     *
9193     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
9194     */
9195    public slice(begin: int, end: int): Uint32Array {
9196        const len: int = this.lengthInt
9197        const relStart = normalizeIndex(begin, len)
9198        const relEnd = normalizeIndex(end, len)
9199        let count = relEnd - relStart
9200        if (count < 0) {
9201            count = 0
9202        }
9203        if (this.buffer instanceof ArrayBuffer) {
9204            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint32Array.BYTES_PER_ELEMENT as int, relEnd * Uint32Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
9205            return new Uint32Array(buf)
9206        } else if (this.buffer instanceof SharedArrayBuffer) {
9207            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint32Array.BYTES_PER_ELEMENT as int, relEnd * Uint32Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
9208            return new Uint32Array(buf)
9209        } else {
9210            throw new Error("unexpected type of buffer")
9211        }
9212    }
9213
9214    /**
9215     * Creates a slice of current Uint32Array using range [begin, this.lengthInt).
9216     *
9217     * @param begin start index to be taken into slice
9218     *
9219     * @returns a new Uint32Array with elements of current Uint32Array[begin, this.lengthInt)
9220     */
9221    public slice(begin: number): Uint32Array {
9222        return this.slice(begin as int)
9223    }
9224
9225    /**
9226     * Creates a slice of current Uint32Array using range [begin, this.lengthInt).
9227     *
9228     * @param begin start index to be taken into slice
9229     *
9230     * @returns a new Uint32Array with elements of current Uint32Array[begin, this.lengthInt)
9231     */
9232    public slice(begin: int): Uint32Array {
9233        return this.slice(begin, this.lengthInt)
9234    }
9235
9236    /**
9237     * Sorts in-place
9238     *
9239     * @param compareFn comparator —  used to determine the order of the elements.
9240     * compareFn returns a negative value if first argument is less than second argument,
9241     * zero if they're equal and a positive value otherwise.
9242     * If omitted, the elements are sorted in ascending order.
9243     *
9244     * @returns sorted Uint32Array
9245     */
9246    public sort(compareFn?: (a: number, b: number) => number): this {
9247        let arr: long[] = new long[this.lengthInt]
9248        for (let i = 0; i < this.lengthInt; ++i) {
9249            arr[i] = this.getUnsafe(i)
9250        }
9251        let cmp = (l: long, r: long): number => {
9252                return (l - r) as number
9253            }
9254        if (compareFn != undefined) {
9255            cmp = (l: long, r: long): number => {
9256                return compareFn!(l as number, r as number)
9257            }
9258        }
9259        sort(arr, cmp)
9260        for (let i = 0; i < this.lengthInt; ++i) {
9261            this.setUnsafe(i, arr[i])
9262        }
9263        return this
9264    }
9265
9266    /**
9267     * Sorts in-place
9268     *
9269     * @param compareFn comparator —  used to determine the order of the elements.
9270     * compareFn returns a negative value if first argument is less than second argument,
9271     * zero if they're equal and a positive value otherwise.
9272     *
9273     * @returns sorted Uint32Array
9274     */
9275    public sort(compareFn: (a: number) => number): this {
9276        let cmp = (a: number, b: number) => { return compareFn(a)}
9277        this.sort(cmp)
9278        return this
9279    }
9280
9281    /**
9282     * Sorts in-place
9283     *
9284     * @param fn compareFn —  used to determine the order of the elements.
9285     * compareFn returns a negative value if first argument is less than second argument,
9286     * zero if they're equal and a positive value otherwise.
9287     *
9288     * @returns sorted Uint32Array
9289     */
9290    public sort(compareFn: () => number): this {
9291        let cmp = (a: number, b: number) => { return compareFn()}
9292        this.sort(cmp)
9293        return this
9294    }
9295    /**
9296     * Creates a Uint32Array with the same underlying Buffer
9297     *
9298     * @param begin start index, inclusive
9299     *
9300     * @param end last index, exclusive
9301     *
9302     * @returns new Uint32Array with the same underlying Buffer
9303     */
9304    public subarray(begin?: number, end?: number): Uint32Array {
9305        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
9306    }
9307
9308    /**
9309     * Creates a Uint32Array with the same underlying Buffer
9310     *
9311     * @param begin start index, inclusive
9312     *
9313     * @param end last index, exclusive
9314     *
9315     * @returns new Uint32Array with the same underlying Buffer
9316     */
9317    public subarray(begin: number, end: number): Uint32Array {
9318        return this.subarray(begin as int, end as int)
9319    }
9320
9321    /**
9322     * Creates a Uint32Array with the same underlying Buffer
9323     *
9324     * @param begin start index, inclusive
9325     *
9326     * @param end last index, exclusive
9327     *
9328     * @returns new Uint32Array with the same underlying Buffer
9329     */
9330    public subarray(begin: number, end: int): Uint32Array {
9331        return this.subarray(begin as int, end as int)
9332    }
9333
9334    /**
9335     * Creates a Uint32Array with the same underlying Buffer
9336     *
9337     * @param begin start index, inclusive
9338     *
9339     * @param end last index, exclusive
9340     *
9341     * @returns new Uint32Array with the same underlying Buffer
9342     */
9343    public subarray(begin: int, end: number): Uint32Array {
9344        return this.subarray(begin as int, end as int)
9345    }
9346
9347    /**
9348     * Creates a Uint32Array with the same underlying Buffer
9349     *
9350     * @param begin start index, inclusive
9351     *
9352     * @param end last index, exclusive
9353     *
9354     * @returns new Uint32Array with the same underlying Buffer
9355     */
9356    public subarray(begin: int, end: int): Uint32Array {
9357        const len: int = this.lengthInt
9358        const relStart = normalizeIndex(begin, len)
9359        const relEnd = normalizeIndex(end, len)
9360        let count = relEnd - relStart
9361        if (count < 0) {
9362            count = 0
9363        }
9364        return new Uint32Array(this.buffer, relStart * Uint32Array.BYTES_PER_ELEMENT as int, count)
9365    }
9366
9367    /**
9368     * Creates a Uint32Array with the same Buffer
9369     *
9370     * @param begin start index, inclusive
9371     *
9372     * @returns new Uint32Array with the same Buffer
9373     */
9374    public subarray(begin: number): Uint32Array {
9375        return this.subarray(begin as int, this.lengthInt)
9376    }
9377
9378    /**
9379     * Creates a Uint32Array with the same Buffer
9380     *
9381     * @param begin start index, inclusive
9382     *
9383     * @returns new Uint32Array with the same Buffer
9384     */
9385    public subarray(begin: int): Uint32Array {
9386        return this.subarray(begin, this.lengthInt)
9387    }
9388
9389    /**
9390     * Converts Uint32Array to a string with respect to locale
9391     *
9392     * @param locales
9393     *
9394     * @param options
9395     *
9396     * @returns string representation
9397     */
9398    public toLocaleString(locales: Object, options: Object): string {
9399        throw new Error("Uint32Array.toLocaleString: not implemented")
9400    }
9401
9402    /**
9403     * Converts Uint32Array to a string with respect to locale
9404     *
9405     * @param locales
9406     *
9407     * @returns string representation
9408     */
9409    public toLocaleString(locales: Object): string {
9410        return this.toLocaleString(new Object(), new Object())
9411    }
9412
9413    /**
9414     * Converts Uint32Array to a string with respect to locale
9415     *
9416     * @returns string representation
9417     */
9418    public toLocaleString(): string {
9419        let res: StringBuilder = new StringBuilder("")
9420        for (let i = 0; i < this.lengthInt - 1; ++i) {
9421            res.append((this.getUnsafe(i) as Number).toLocaleString())
9422            res.append(",")
9423        }
9424        if (this.lengthInt > 0) {
9425            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
9426        }
9427        return res.toString()
9428    }
9429
9430    /**
9431     * Creates a reversed copy
9432     *
9433     * @returns a reversed copy
9434     */
9435    public toReversed(): Uint32Array {
9436        return new Uint32Array(this).reverse()
9437    }
9438
9439    /**
9440     * Creates a sorted copy
9441     *
9442     * @returns a sorted copy
9443     */
9444    public toSorted(): Uint32Array {
9445        return new Uint32Array(this).sort()
9446    }
9447
9448    /**
9449     * Returns a string representation of the Uint32Array
9450     *
9451     * @returns a string representation of the Uint32Array
9452     */
9453    public override toString(): string {
9454        return this.join(",")
9455    }
9456
9457    /**
9458     * Returns array values iterator
9459     *
9460     * @returns an iterator
9461     */
9462    public values(): IterableIterator<Number> {
9463         return new Uint32ArrayIterator(this)
9464    }
9465
9466    /**
9467     * Creates a copy with replaced value on index
9468     *
9469     * @param index
9470     *
9471     * @param value
9472     *
9473     * @returns an Uint32Array with replaced value on index
9474     */
9475    public with(index: number, value: number): Uint32Array {
9476        return this.with(index as int, value as long)
9477    }
9478
9479    /**
9480     * Creates a copy with replaced value on index
9481     *
9482     * @param index
9483     *
9484     * @param value
9485     *
9486     * @returns an Uint32Array with replaced value on index
9487     */
9488    public with(index: int, value: long): Uint32Array {
9489        let res = new Uint32Array(this)
9490        res.setUnsafeClamp(index, value)
9491        return res
9492    }
9493
9494    /// === with element lambda functions ===
9495
9496    /**
9497     * Determines whether the specified callback function returns true for all elements of an array.
9498     *
9499     * @param predicate A function that accepts one argument.
9500     * The every method calls the predicate function for each element in the array until the predicate returns a false,
9501     * or until the end of the array.
9502     *
9503     * @returns true unless predicate function returns a false for an array element,
9504     * in which case false is immediately returned.
9505     */
9506    public every(predicate: (element: number) => boolean): boolean {
9507        return this.every((element: number, index: number, array: Uint32Array): boolean => predicate(element))
9508    }
9509
9510    /**
9511     * creates a new Uint32Array from current Uint32Array based on a condition fn
9512     *
9513     * @param fn the condition to apply for each element
9514     *
9515     * @returns a new Uint32Array with elements from current Uint32Array that satisfy condition fn
9516     */
9517    public filter(fn: (val: number) => boolean): Uint32Array {
9518        let newF: (val: number, index: number, array: Uint32Array) => boolean =
9519            (val: number, index: number, array: Uint32Array): boolean => { return fn(val) }
9520        return this.filter(newF)
9521    }
9522
9523    /**
9524     * Returns the value of the first element in the array where predicate is true, and undefined
9525     * otherwise
9526     *
9527     * @param predicate find calls predicate once for each element of the array, in ascending
9528     * order, until it finds one where predicate returns true. If such an element is found, find
9529     * immediately returns that element value. Otherwise, find returns undefined
9530     *
9531     * @returns number | undefined
9532     */
9533    public find(predicate: () => boolean): number | undefined {
9534        return this.find((value: number, index: number, obj: Uint32Array): boolean => predicate())
9535    }
9536
9537    /**
9538     * Returns the value of the first element in the array where predicate is true, and undefined
9539     * otherwise
9540     *
9541     * @param predicate find calls predicate once for each element of the array, in ascending
9542     * order, until it finds one where predicate returns true. If such an element is found, find
9543     * immediately returns that element value. Otherwise, find returns undefined
9544     *
9545     * @returns number | undefined
9546     */
9547    public find(predicate: (value: number) => boolean): number | undefined {
9548        return this.find((value: number, index: number, obj: Uint32Array): boolean => predicate(value))
9549    }
9550
9551    /**
9552     * Returns the index of the first element in the array where predicate is true, and -1
9553     * otherwise
9554     *
9555     * @param predicate find calls predicate once for each element of the array, in ascending
9556     * order, until it finds one where predicate returns true. If such an element is found,
9557     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
9558     *
9559     * @returns number
9560     */
9561    public findIndex(predicate: (value: number) => boolean): number {
9562        return this.findIndex((value: number, index: number, obj: Uint32Array): boolean => predicate(value)) as number
9563    }
9564
9565    /**
9566     * Finds the last element in the Uint32Array that satisfies the condition
9567     *
9568     * @param fn condition
9569     *
9570     * @returns the last element that satisfies fn
9571     */
9572    public findLast(fn: (val: number) => boolean): number {
9573        let newF: (val: number, index: number, array: Uint32Array) => boolean =
9574            (val: number, index: number, array: Uint32Array): boolean => { return fn(val) }
9575        return this.findLast(newF)
9576    }
9577
9578    /**
9579     * Finds an index of the last element in the Uint32Array that satisfies the condition
9580     *
9581     * @param fn condition
9582     *
9583     * @returns the index of the last element that satisfies fn, -1 otherwise
9584     */
9585    public findLastIndex(fn: (val: number) => boolean): number {
9586        let newF: (val: number, index: number, array: Uint32Array) => boolean =
9587            (val: number, index: number, array: Uint32Array): boolean => { return fn(val) }
9588        return this.findLastIndex(newF) as number
9589    }
9590
9591    /**
9592     * Performs the specified action for each element in Uint32Array
9593     *
9594     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
9595     * callbackfn function one time for each element in the array.
9596     *
9597     * @returns None
9598     */
9599    public forEach(callbackfn: (val: number) => void): void {
9600        this.forEach((value: number, index: number, array: Uint32Array): void => callbackfn(value))
9601    }
9602
9603
9604    /**
9605     * Determines whether the specified callback function returns true for any element of an array.
9606     *
9607     * @param predicate A function that accepts one argument.
9608     * The some method calls the predicate function for each element in the array
9609     * until the predicate returns a true or until the end of the array.
9610     *
9611     * @returns false unless predicate function returns true for an array element,
9612     * in which case true is immediately returned.
9613     */
9614    public some(predicate: (element: number) => boolean): boolean {
9615        return this.some((element: number, index: number, array: Uint32Array): boolean => predicate(element))
9616    }
9617
9618    /**
9619     * Determines whether the specified callback function returns true for any element of an array.
9620     *
9621     * @param predicate A function that accepts three arguments.
9622     * The some method calls the predicate function for each element in the array
9623     * until the predicate returns a true or until the end of the array.
9624     *
9625     * @returns false unless predicate function returns true for an array element,
9626     * in which case true is immediately returned.
9627     */
9628    public some(predicate: (element: number, index: number, array: Uint32Array) => boolean): boolean {
9629        for (let i = 0; i < this.lengthInt; i++) {
9630            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
9631                return true
9632            }
9633        }
9634        return false
9635    }
9636
9637    /**
9638     * Determines whether the specified callback function returns true for any element of an array.
9639     *
9640     * @param predicate A function that accepts two arguments.
9641     * The some method calls the predicate function for each element in the array
9642     * until the predicate returns a true or until the end of the array.
9643     *
9644     * @returns false unless predicate function returns true for an array element,
9645     * in which case true is immediately returned.
9646     */
9647    public some(predicate: (element: number, index: number) => boolean): boolean {
9648        return this.some((element: number, index: number, array: Uint32Array): boolean => predicate(element, index))
9649    }
9650
9651    /**
9652     * Determines whether the specified callback function returns true for any element of an array.
9653     *
9654     * @param predicate A function that accepts no arguments.
9655     * The some method calls the predicate function for each element in the array
9656     * until the predicate returns a true or until the end of the array.
9657     *
9658     * @returns false unless predicate function returns true for an array element,
9659     * in which case true is immediately returned.
9660     */
9661    public some(predicate: () => boolean): boolean {
9662        return this.some((element: number, index: number, array: Uint32Array): boolean => predicate())
9663    }
9664
9665    /**
9666     * Calls the specified callback function for all the elements in an array.
9667     * The return value of the callback function is the accumulated result,
9668     * and is provided as an argument in the next call to the callback function.
9669     *
9670     * @param callbackfn A function that accepts four arguments.
9671     * The reduce method calls the callbackfn function one time for each element in the array.
9672     *
9673     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9674     * The first call to the callbackfn function provides this value as an argument.
9675     *
9676     * @returns The value that results from running the callback function to completion over the entire typed array.
9677     */
9678    public reduce<U = number>(
9679                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U,
9680                initialValue: U): U {
9681        let accumulatedValue = initialValue
9682        for (let i = 0; i < this.lengthInt; i++) {
9683            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
9684        }
9685        return accumulatedValue
9686    }
9687
9688    /**
9689     * Calls the specified callback function for all the elements in an array.
9690     * The return value of the callback function is the accumulated result,
9691     * and is provided as an argument in the next call to the callback function.
9692     *
9693     * @param callbackfn A function that accepts three arguments.
9694     * The reduce method calls the callbackfn function one time for each element in the array.
9695     *
9696     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9697     * The first call to the callbackfn function provides this value as an argument.
9698     *
9699     * @returns The value that results from running the callback function to completion over the entire typed array.
9700     */
9701    public reduce<U = number>(
9702                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
9703                initialValue: U): U {
9704        return this.reduce(
9705                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9706                        callbackfn(prevVal, currVal, currIndex),
9707                initialValue)
9708    }
9709
9710    /**
9711     * Calls the specified callback function for all the elements in an array.
9712     * The return value of the callback function is the accumulated result,
9713     * and is provided as an argument in the next call to the callback function.
9714     *
9715     * @param callbackfn A function that accepts two arguments.
9716     * The reduce method calls the callbackfn function one time for each element in the array.
9717     *
9718     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9719     * The first call to the callbackfn function provides this value as an argument.
9720     *
9721     * @returns The value that results from running the callback function to completion over the entire typed array.
9722     */
9723    public reduce<U = number>(
9724                callbackfn: (previousValue: U, currentValue: number) => U,
9725                initialValue: U): U {
9726        return this.reduce(
9727                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9728                        callbackfn(prevVal, currVal),
9729                initialValue)
9730    }
9731
9732    /**
9733     * Calls the specified callback function for all the elements in an array.
9734     * The return value of the callback function is the accumulated result,
9735     * and is provided as an argument in the next call to the callback function.
9736     *
9737     * @param callbackfn A function that accepts one argument
9738     * The reduce method calls the callbackfn function one time for each element in the array.
9739     *
9740     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9741     * The first call to the callbackfn function provides this value as an argument.
9742     *
9743     * @returns The value that results from running the callback function to completion over the entire typed array.
9744     */
9745    public reduce<U = number>(
9746                callbackfn: (previousValue: U) => U,
9747                initialValue: U): U {
9748        return this.reduce(
9749                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9750                        callbackfn(prevVal),
9751                initialValue)
9752    }
9753
9754    /**
9755     * Calls the specified callback function for all the elements in an array.
9756     * The return value of the callback function is the accumulated result,
9757     * and is provided as an argument in the next call to the callback function.
9758     *
9759     * @param callbackfn A function that accepts no arguments
9760     * The reduce method calls the callbackfn function one time for each element in the array.
9761     *
9762     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9763     * The first call to the callbackfn function provides this value as an argument.
9764     *
9765     * @returns The value that results from running the callback function to completion over the entire typed array.
9766     */
9767    public reduce<U = number>(
9768                callbackfn: () => U,
9769                initialValue: U): U {
9770        return this.reduce(
9771                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9772                        callbackfn(),
9773                initialValue)
9774    }
9775
9776    /**
9777     * Calls the specified callback function for all the elements in an array.
9778     * The return value of the callback function is the accumulated result,
9779     * and is provided as an argument in the next call to the callback function.
9780     *
9781     * @param callbackfn A function that accepts four arguments.
9782     * The reduce method calls the callbackfn function one time for each element in the array.
9783     * The first call to the callbackfn function provides array first element value as an argument
9784     *
9785     * @returns The value that results from running the callback function to completion over the entire typed array.
9786     * calling reduce method on an empty array without an initial value creates a TypeError
9787     */
9788    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number {
9789        if (this.lengthInt == 0) {
9790            throw new TypeError("Reduce of empty array with no initial value")
9791        }
9792
9793        let accumulatedValue = this.$_get(0) as number
9794        for (let i = 1; i < this.lengthInt; i++) {
9795            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
9796        }
9797        return accumulatedValue
9798    }
9799
9800    /**
9801     * Calls the specified callback function for all the elements in an array.
9802     * The return value of the callback function is the accumulated result,
9803     * and is provided as an argument in the next call to the callback function.
9804     *
9805     * @param callbackfn A function that accepts three arguments.
9806     * The reduce method calls the callbackfn function one time for each element in the array.
9807     * The first call to the callbackfn function provides array first element value as an argument
9808     *
9809     * @returns The value that results from running the callback function to completion over the entire typed array.
9810     * calling reduce method on an empty array without an initial value creates a TypeError
9811     */
9812    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
9813        return this.reduce(
9814                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9815                        callbackfn(prevVal, currVal, currIndex))
9816    }
9817
9818    /**
9819     * Calls the specified callback function for all the elements in an array.
9820     * The return value of the callback function is the accumulated result,
9821     * and is provided as an argument in the next call to the callback function.
9822     *
9823     * @param callbackfn A function that accepts two arguments.
9824     * The reduce method calls the callbackfn function one time for each element in the array.
9825     * The first call to the callbackfn function provides array first element value as an argument
9826     *
9827     * @returns The value that results from running the callback function to completion over the entire typed array.
9828     * calling reduce method on an empty array without an initial value creates a TypeError
9829     */
9830    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
9831        return this.reduce(
9832                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9833                        callbackfn(prevVal, currVal))
9834    }
9835
9836    /**
9837     * Calls the specified callback function for all the elements in an array.
9838     * The return value of the callback function is the accumulated result,
9839     * and is provided as an argument in the next call to the callback function.
9840     *
9841     * @param callbackfn A function that accepts one argument.
9842     * The reduce method calls the callbackfn function one time for each element in the array.
9843     * The first call to the callbackfn function provides array first element value as an argument
9844     *
9845     * @returns The value that results from running the callback function to completion over the entire typed array.
9846     * calling reduce method on an empty array without an initial value creates a TypeError
9847     */
9848    public reduce(callbackfn: (previousValue: number) => number): number {
9849        return this.reduce(
9850                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9851                        callbackfn(prevVal))
9852    }
9853
9854    /**
9855     * Calls the specified callback function for all the elements in an array.
9856     * The return value of the callback function is the accumulated result,
9857     * and is provided as an argument in the next call to the callback function.
9858     *
9859     * @param callbackfn A function that accepts no arguments.
9860     * The reduce method calls the callbackfn function one time for each element in the array.
9861     * The first call to the callbackfn function provides array first element value as an argument
9862     *
9863     * @returns The value that results from running the callback function to completion over the entire typed array.
9864     * calling reduce method on an empty array without an initial value creates a TypeError
9865     */
9866    public reduce(callbackfn: () => number): number {
9867        return this.reduce(
9868                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9869                        callbackfn())
9870    }
9871
9872    /**
9873     * Calls the specified callback function for all the elements in an array, in descending order.
9874     * The return value of the callback function is the accumulated result,
9875     * and is provided as an argument in the next call to the callback function.
9876     *
9877     * @param callbackfn A function that accepts four arguments.
9878     * The reduceRight method calls the callbackfn function one time for each element in the array.
9879     *
9880     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9881     * The first call to the callbackfn function provides this value as an argument.
9882     *
9883     * @returns The value that results from running the callback function to completion over the entire typed array.
9884     */
9885    public reduceRight<U = number>(
9886                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U,
9887                initialValue: U): U {
9888        let accumulatedValue = initialValue
9889        for (let i = this.lengthInt - 1; i >= 0; i--) {
9890            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
9891        }
9892        return accumulatedValue
9893    }
9894
9895    /**
9896     * Calls the specified callback function for all the elements in an array, in descending order.
9897     * The return value of the callback function is the accumulated result,
9898     * and is provided as an argument in the next call to the callback function.
9899     *
9900     * @param callbackfn A function that accepts three arguments.
9901     * The reduceRight method calls the callbackfn function one time for each element in the array.
9902     *
9903     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9904     * The first call to the callbackfn function provides this value as an argument.
9905     *
9906     * @returns The value that results from running the callback function to completion over the entire typed array.
9907     */
9908    public reduceRight<U = number>(
9909                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
9910                initialValue: U): U {
9911        return this.reduceRight(
9912                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9913                        callbackfn(prevVal, currVal, currIndex),
9914                initialValue)
9915    }
9916
9917    /**
9918     * Calls the specified callback function for all the elements in an array, in descending order.
9919     * The return value of the callback function is the accumulated result,
9920     * and is provided as an argument in the next call to the callback function.
9921     *
9922     * @param callbackfn A function that accepts two arguments.
9923     * The reduceRight method calls the callbackfn function one time for each element in the array.
9924     *
9925     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9926     * The first call to the callbackfn function provides this value as an argument.
9927     *
9928     * @returns The value that results from running the callback function to completion over the entire typed array.
9929     */
9930    public reduceRight<U = number>(
9931                callbackfn: (previuosValue: U, currentValue: number) => U,
9932                initialValue: U): U {
9933        return this.reduceRight(
9934                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9935                        callbackfn(prevVal, currVal),
9936                initialValue)
9937    }
9938
9939    /**
9940     * Calls the specified callback function for all the elements in an array, in descending order.
9941     * The return value of the callback function is the accumulated result,
9942     * and is provided as an argument in the next call to the callback function.
9943     *
9944     * @param callbackfn A function that accepts one argument.
9945     * The reduceRight method calls the callbackfn function one time for each element in the array.
9946     *
9947     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9948     * The first call to the callbackfn function provides this value as an argument.
9949     *
9950     * @returns The value that results from running the callback function to completion over the entire typed array.
9951     */
9952    public reduceRight<U = number>(
9953                callbackfn: (previuosValue: U) => U,
9954                initialValue: U): U {
9955        return this.reduceRight(
9956                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9957                        callbackfn(prevVal),
9958                initialValue)
9959    }
9960
9961    /**
9962     * Calls the specified callback function for all the elements in an array, in descending order.
9963     * The return value of the callback function is the accumulated result,
9964     * and is provided as an argument in the next call to the callback function.
9965     *
9966     * @param callbackfn A function that accepts no arguments.
9967     * The reduceRight method calls the callbackfn function one time for each element in the array.
9968     *
9969     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9970     * The first call to the callbackfn function provides this value as an argument.
9971     *
9972     * @returns The value that results from running the callback function to completion over the entire typed array.
9973     */
9974    public reduceRight<U = number>(
9975                callbackfn: () => U,
9976                initialValue: U): U {
9977        return this.reduceRight(
9978                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9979                        callbackfn(),
9980                initialValue)
9981    }
9982
9983    /**
9984     * Calls the specified callback function for all the elements in an array, in descending order.
9985     * The return value of the callback function is the accumulated result,
9986     * and is provided as an argument in the next call to the callback function.
9987     *
9988     * @param callbackfn A function that accepts four arguments.
9989     * The reduceRight method calls the callbackfn function one time for each element in the array.
9990     * The first call to the callbackfn function provides array last element value as an argument
9991     *
9992     * @returns The value that results from running the callback function to completion over the entire typed array.
9993     * calling reduceRight method on an empty array without an initial value creates a TypeError
9994     */
9995    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number {
9996        if (this.lengthInt == 0) {
9997            throw new TypeError("Reduce of empty array with no initial value")
9998        }
9999
10000        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
10001        for (let i = this.lengthInt - 2; i >= 0; i--) {
10002            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
10003        }
10004        return accumulatedValue
10005    }
10006
10007    /**
10008     * Calls the specified callback function for all the elements in an array, in descending order.
10009     * The return value of the callback function is the accumulated result,
10010     * and is provided as an argument in the next call to the callback function.
10011     *
10012     * @param callbackfn A function that accepts three arguments.
10013     * The reduceRight method calls the callbackfn function one time for each element in the array.
10014     * The first call to the callbackfn function provides array last element value as an argument
10015     *
10016     * @returns The value that results from running the callback function to completion over the entire typed array.
10017     * calling reduceRight method on an empty array without an initial value creates a TypeError
10018     */
10019    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
10020        return this.reduceRight(
10021                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
10022                        callbackfn(prevValue, currValue, currIndex))
10023    }
10024
10025    /**
10026     * Calls the specified callback function for all the elements in an array, in descending order.
10027     * The return value of the callback function is the accumulated result,
10028     * and is provided as an argument in the next call to the callback function.
10029     *
10030     * @param callbackfn A function that accepts two arguments.
10031     * The reduceRight method calls the callbackfn function one time for each element in the array.
10032     * The first call to the callbackfn function provides array last element value as an argument
10033     *
10034     * @returns The value that results from running the callback function to completion over the entire typed array.
10035     * calling reduceRight method on an empty array without an initial value creates a TypeError
10036     */
10037    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
10038        return this.reduceRight(
10039                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
10040                        callbackfn(prevValue, currValue))
10041    }
10042
10043    /**
10044     * Calls the specified callback function for all the elements in an array, in descending order.
10045     * The return value of the callback function is the accumulated result,
10046     * and is provided as an argument in the next call to the callback function.
10047     *
10048     * @param callbackfn A function that accepts one argument.
10049     * The reduceRight method calls the callbackfn function one time for each element in the array.
10050     * The first call to the callbackfn function provides array last element value as an argument
10051     *
10052     * @returns The value that results from running the callback function to completion over the entire typed array.
10053     * calling reduceRight method on an empty array without an initial value creates a TypeError
10054     */
10055    public reduceRight(callbackfn: (previousValue: number) => number): number {
10056        return this.reduceRight(
10057                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
10058                        callbackfn(prevValue))
10059    }
10060
10061    /**
10062     * Calls the specified callback function for all the elements in an array, in descending order.
10063     * The return value of the callback function is the accumulated result,
10064     * and is provided as an argument in the next call to the callback function.
10065     *
10066     * @param callbackfn A function that accepts no arguments.
10067     * The reduceRight method calls the callbackfn function one time for each element in the array.
10068     * The first call to the callbackfn function provides array last element value as an argument
10069     *
10070     * @returns The value that results from running the callback function to completion over the entire typed array.
10071     * calling reduceRight method on an empty array without an initial value creates a TypeError
10072     */
10073    public reduceRight(callbackfn: () => number): number {
10074        return this.reduceRight(
10075                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
10076                        callbackfn())
10077    }
10078
10079    /**
10080     * Creates a new Uint32Array using fn(arr[i]) over all elements of current Uint32Array.
10081     *
10082     * @param fn a function to apply for each element of current Uint32Array
10083     *
10084     * @returns a new Uint32Array where for each element from current Uint32Array fn was applied
10085     */
10086    public map(fn: (val: number, index: number, array: Uint32Array) => number): Uint32Array {
10087        let resBuf = new ArrayBuffer(this.lengthInt * Uint32Array.BYTES_PER_ELEMENT as int)
10088        let res = new Uint32Array(resBuf)
10089        for (let i = 0; i < this.lengthInt; i++) {
10090            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
10091            res.setUnsafeClamp(i, fnRes as long)
10092        }
10093        return res
10094    }
10095
10096    /**
10097     * Creates a new Uint32Array using fn(arr[i], i) over all elements of current Uint32Array
10098     *
10099     * @param fn a function to apply for each element of current Uint32Array
10100     *
10101     * @returns a new Uint32Array where for each element from current Uint32Array fn was applied
10102     */
10103    public map(fn: (val: number, index: number) => number): Uint32Array {
10104        let newF: (val: number, index: number, array: Uint32Array) => number =
10105            (val: number, index: number, array: Uint32Array): number => { return fn(val, index) }
10106        return this.map(newF)
10107    }
10108
10109    /**
10110     * Creates a new Uint32Array using fn(arr[i]) over all elements of current Uint32Array
10111     *
10112     * @param fn a function to apply for each element of current Uint32Array
10113     *
10114     * @returns a new Uint32Array where for each element from current Uint32Array fn was applied
10115     */
10116    public map(fn: (val: number) => number): Uint32Array {
10117        let newF: (val: number, index: number, array: Uint32Array) => number =
10118            (val: number, index: number, array: Uint32Array): number => { return fn(val) }
10119        return this.map(newF)
10120    }
10121
10122    /**
10123     * Creates a new Uint32Array using fn() over all elements of current Uint32Array
10124     *
10125     * @param fn a function to apply for each element of current Uint32Array
10126     *
10127     * @returns a new Uint32Array where for each element from current Uint32Array fn was applied
10128     */
10129    public map(fn: () => number): Uint32Array {
10130        let newF: (val: number, index: number, array: Uint32Array) => number =
10131            (val: number, index: number, array: Uint32Array): number => { return fn() }
10132        return this.map(newF)
10133    }
10134
10135    /**
10136     * Determines whether the specified callback function returns true for all elements of an array.
10137     *
10138     * @param predicate A function that accepts three arguments.
10139     * The every method calls the predicate function for each element in the array until the predicate returns a false,
10140     * or until the end of the array.
10141     *
10142     * @returns true unless predicate function returns a false for an array element,
10143     * in which case false is immediately returned.
10144     */
10145    public every(predicate: (element: number, index: number, array: Uint32Array) => boolean): boolean {
10146        for (let i = 0; i < this.lengthInt; i++) {
10147            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
10148                return false
10149            }
10150        }
10151        return true
10152    }
10153
10154    /**
10155     * Determines whether the specified callback function returns true for all elements of an array.
10156     *
10157     * @param predicate A function that accepts two arguments.
10158     * The every method calls the predicate function for each element in the array until the predicate returns a false,
10159     * or until the end of the array.
10160     *
10161     * @returns true unless predicate function returns a false for an array element,
10162     * in which case false is immediately returned.
10163     */
10164    public every(predicate: (element: number, index: number) => boolean): boolean {
10165        return this.every((element: number, index: number, array: Uint32Array): boolean => predicate(element, index))
10166    }
10167
10168    /**
10169     * Determines whether the specified callback function returns true for all elements of an array.
10170     *
10171     * @param predicate A function that accepts no arguments.
10172     * The every method calls the predicate function for each element in the array until the predicate returns a false,
10173     * or until the end of the array.
10174     *
10175     * @returns true unless predicate function returns a false for an array element,
10176     * in which case false is immediately returned.
10177     */
10178    public every(predicate: () => boolean): boolean {
10179        return this.every((element: number, index: number, array: Uint32Array): boolean => predicate())
10180    }
10181
10182    /**
10183     * Creates a new Uint32Array from current Uint32Array based on a condition fn.
10184     *
10185     * @param fn the condition to apply for each element
10186     *
10187     * @returns a new Uint32Array with elements from current Uint32Array that satisfy condition fn
10188     */
10189    public filter(fn: (val: number, index: number, array: Uint32Array) => boolean): Uint32Array {
10190        let markers = new boolean[this.lengthInt]
10191        let resLen = 0
10192        for (let i = 0; i < this.lengthInt; i++) {
10193            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
10194            if (markers[i]) {
10195                ++resLen
10196            }
10197        }
10198        let res = new Uint32Array(resLen)
10199        for (let i = 0, j = 0; i < this.lengthInt; i++) {
10200            if (markers[i]) {
10201                res.setUnsafe(j, this.getUnsafe(i))
10202                ++j
10203            }
10204        }
10205        return res
10206    }
10207
10208    /**
10209     * creates a new Uint32Array from current Uint32Array based on a condition fn
10210     *
10211     * @param fn the condition to apply for each element
10212     *
10213     * @returns a new Uint32Array with elements from current Uint32Array that satisfy condition fn
10214     */
10215    public filter(fn: (val: number, index: number) => boolean): Uint32Array {
10216        let newF: (val: number, index: number, array: Uint32Array) => boolean =
10217            (val: number, index: number, array: Uint32Array): boolean => { return fn(val, index) }
10218        return this.filter(newF)
10219    }
10220
10221    /**
10222     * Returns the value of the first element in the array where predicate is true, and undefined
10223     * otherwise
10224     *
10225     * @param predicate find calls predicate once for each element of the array, in ascending
10226     * order, until it finds one where predicate returns true. If such an element is found, find
10227     * immediately returns that element value. Otherwise, find returns undefined
10228     *
10229     * @returns number | undefined
10230     */
10231    public find(predicate: (value: number, index: number, array: Uint32Array) => boolean): number | undefined {
10232        for (let i = 0; i < this.lengthInt; i++) {
10233            let val = this.getUnsafe(i) as number
10234            if (predicate(val, i as number, this)) {
10235                return val
10236            }
10237        }
10238        return undefined
10239    }
10240
10241    /**
10242     * Returns the value of the first element in the array where predicate is true, and undefined
10243     * otherwise
10244     *
10245     * @param predicate find calls predicate once for each element of the array, in ascending
10246     * order, until it finds one where predicate returns true. If such an element is found, find
10247     * immediately returns that element value. Otherwise, find returns undefined
10248     *
10249     * @returns number | undefined
10250     */
10251    public find(predicate: (value: number, index: number) => boolean): number | undefined {
10252        return this.find((value: number, index: number, obj: Uint32Array): boolean => predicate(value, index))
10253    }
10254
10255    /**
10256     * Returns the index of the first element in the array where predicate is true, and -1
10257     * otherwise
10258     *
10259     * @param predicate find calls predicate once for each element of the array, in ascending
10260     * order, until it finds one where predicate returns true. If such an element is found,
10261     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
10262     *
10263     * @returns number
10264     */
10265    public findIndex(predicate: (value: number, index: number, obj: Uint32Array) => boolean): number {
10266        for (let i = 0; i < this.lengthInt; i++) {
10267            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
10268                return i as number
10269            }
10270        }
10271        return -1 as number
10272    }
10273
10274    /**
10275     * Returns the index of the first element in the array where predicate is true, and -1
10276     * otherwise
10277     *
10278     * @param predicate find calls predicate once for each element of the array, in ascending
10279     * order, until it finds one where predicate returns true. If such an element is found,
10280     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
10281     *
10282     * @returns number
10283     */
10284    public findIndex(predicate: (value: number, index: number) => boolean): number {
10285        return this.findIndex((value: number, index: number, obj: Uint32Array): boolean => predicate(value, index))
10286    }
10287
10288    /**
10289     * Returns the index of the first element in the array where predicate is true, and -1
10290     * otherwise
10291     *
10292     * @param predicate find calls predicate once for each element of the array, in ascending
10293     * order, until it finds one where predicate returns true. If such an element is found,
10294     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
10295     *
10296     * @returns number
10297     */
10298    public findIndex(predicate: () => boolean): number {
10299        return this.findIndex((value: number, index: number, obj: Uint32Array): boolean => predicate())
10300    }
10301
10302    /**
10303     * Finds the last element in the Uint32Array that satisfies the condition
10304     *
10305     * @param fn condition
10306     *
10307     * @returns the last element that satisfies fn
10308     */
10309    public findLast(fn: (val: number, index: number, array: Uint32Array) => boolean): number {
10310        for (let i = this.lengthInt - 1; i >= 0; i--) {
10311            let val = this.getUnsafe(i) as number
10312            if (fn(val, i as number, this)) {
10313                return val
10314            }
10315        }
10316        throw new Error("Uint32Array.findLast: not implemented if an element was not found")
10317    }
10318
10319    /**
10320     * Finds the last element in the Uint32Array that satisfies the condition
10321     *
10322     * @param fn condition
10323     *
10324     * @returns the last element that satisfies fn
10325     */
10326    public findLast(fn: (val: number, index: number) => boolean): number {
10327        let newF: (val: number, index: number, array: Uint32Array) => boolean =
10328            (val: number, index: number, array: Uint32Array): boolean => { return fn(val, index) }
10329        return this.findLast(newF)
10330    }
10331
10332    /**
10333     * Finds an index of the last element in the Uint32Array that satisfies the condition
10334     *
10335     * @param fn condition
10336     *
10337     * @returns the index of the last element that satisfies fn, -1 otherwise
10338     */
10339    public findLastIndex(fn: (val: number, index: number, array: Uint32Array) => boolean): number {
10340        for (let i = this.lengthInt - 1; i >= 0; i--) {
10341            if (fn(this.getUnsafe(i) as number, i as number, this)) {
10342                return i as number
10343            }
10344        }
10345        return -1 as number
10346    }
10347
10348    /**
10349     * Finds an index of the last element in the Uint32Array that satisfies the condition
10350     *
10351     * @param fn condition
10352     *
10353     * @returns the index of the last element that satisfies fn, -1 otherwise
10354     */
10355    public findLastIndex(fn: (val: number, index: number) => boolean): number {
10356        let newF: (val: number, index: number, array: Uint32Array) => boolean =
10357            (val: number, index: number, array: Uint32Array): boolean => { return fn(val, index) }
10358        return this.findLastIndex(newF) as number
10359    }
10360
10361    /**
10362     * Performs the specified action for each element in Uint32Array
10363     *
10364     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
10365     * callbackfn function one time for each element in the array.
10366     *
10367     * @returns None
10368     */
10369    public forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void): void {
10370        for (let i = 0; i < this.lengthInt; i++) {
10371            callbackfn(this.getUnsafe(i) as number, i as number, this)
10372        }
10373    }
10374
10375    /**
10376     * Performs the specified action for each element in Uint32Array
10377     *
10378     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
10379     * callbackfn function one time for each element in the array.
10380     *
10381     * @returns None
10382     */
10383    public forEach(callbackfn: (value: number, index: number) => void): void {
10384        this.forEach((value: number, index: number, array: Uint32Array): void => callbackfn(value, index))
10385    }
10386
10387    /**
10388     * Performs the specified action for each element in Uint32Array
10389     *
10390     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
10391     * callbackfn function one time for each element in the array.
10392     *
10393     * @returns None
10394     */
10395    public forEach(callbackfn: () => void): void {
10396        this.forEach((value: number, index: number, array: Uint32Array): void => callbackfn())
10397    }
10398
10399    /**
10400     * Returns the object itself
10401     *
10402     * @returns Uint32Array
10403     */
10404    public valueOf(): Uint32Array {
10405        return this
10406    }
10407
10408    /** Byte offset within the underlying Buffer */
10409    public get byteOffset(): number {
10410        return this.byteOffsetInt
10411    }
10412
10413    /** Number of bytes used */
10414    public get byteLength(): number {
10415        return this.byteLengthInt
10416    }
10417
10418    /** Number of long stored in Uint32Array */
10419    public get length(): number {
10420        return this.lengthInt
10421    }
10422
10423    /** String \"Uint32Array\" */
10424    public readonly name = "Uint32Array"
10425
10426    private static clamp(val: long): long {
10427        return val
10428    }
10429
10430    internal setUnsafeClamp(insertPos: int, val: long): void {
10431        this.setUnsafe(insertPos, val)
10432    }
10433
10434    internal getUnsafe(index: int): long {
10435        index = index * Uint32Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
10436        let res: long = 0
10437        if (IS_LITTLE_ENDIAN) {
10438            if (this.buffer instanceof ArrayBuffer) {
10439                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10440                    let el = (this.buffer as ArrayBuffer).at(index + i) as long
10441                    el &= 0xff
10442                    res |= el << (8 * i)
10443                }
10444            } else if (this.buffer instanceof SharedArrayBuffer) {
10445                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10446                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as long
10447                    el &= 0xff
10448                    res |= el << (8 * i)
10449                }
10450            } else {
10451                throw new Error("unexpected type of ArrayBufferLike")
10452            }
10453        } else {
10454            if (this.buffer instanceof ArrayBuffer) {
10455                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10456                    let el = (this.buffer as ArrayBuffer).at(index + 3 - i) as long
10457                    el &= 0xff
10458                    res |= el << (8 * i)
10459                }
10460            } else if (this.buffer instanceof SharedArrayBuffer) {
10461                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10462                    let el = (this.buffer as SharedArrayBuffer).at(index + 3 - i) as long
10463                    el &= 0xff
10464                    res |= el << (8 * i)
10465                }
10466            } else {
10467                throw new Error("unexpected type of ArrayBufferLike")
10468            }
10469        }
10470        return res
10471    }
10472
10473    internal setUnsafe(index: int, val: long): void {
10474        index = index * Uint32Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
10475        let res: long = 0
10476        if (IS_LITTLE_ENDIAN) {
10477            if (this.buffer instanceof ArrayBuffer) {
10478                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10479                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
10480                    val = val >> 8
10481                }
10482            } else if (this.buffer instanceof SharedArrayBuffer) {
10483                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10484                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
10485                    val = val >> 8
10486                }
10487            } else {
10488                throw new Error("unexpected type of ArrayBufferLike")
10489            }
10490        } else {
10491            if (this.buffer instanceof ArrayBuffer) {
10492                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10493                    (this.buffer as ArrayBuffer).set(index + 3 - i, (val & 0xff) as byte)
10494                    val = val >> 8
10495                }
10496            } else if (this.buffer instanceof SharedArrayBuffer) {
10497                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10498                    (this.buffer as SharedArrayBuffer).set(index + 3 - i, (val & 0xff) as byte)
10499                    val = val >> 8
10500                }
10501            } else {
10502                throw new Error("unexpected type of ArrayBufferLike")
10503            }
10504        }
10505    }
10506}
10507
10508
10509class BigUint64ArrayIteratorKeys implements IterableIterator<number> {
10510    private length: int = 0
10511    private idx: int = 0
10512
10513    constructor(parent: BigUint64Array) {
10514        this.length = parent.length as int
10515    }
10516
10517    public override $_iterator(): IterableIterator<Number> {
10518        return this
10519    }
10520
10521    override next(): IteratorResult<number> {
10522        if (this.idx < 0 || this.idx >= this.length) {
10523            return new IteratorResult<number>()
10524        }
10525        return new IteratorResult<number>(false, this.idx++ as number)
10526    }
10527}
10528
10529class BigUint64ArrayIterator implements IterableIterator<BigInt> {
10530    private parent: BigUint64Array
10531    private idx: int = 0
10532
10533    constructor(parent: BigUint64Array) {
10534        this.parent = parent
10535    }
10536
10537    public override $_iterator(): IterableIterator<BigInt> {
10538        return this
10539    }
10540
10541    override next(): IteratorResult<BigInt> {
10542        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
10543            return new IteratorResult<BigInt>()
10544        }
10545        return new IteratorResult<BigInt>(false, new BigInt(this.parent.getUnsafe(this.idx++)))
10546    }
10547}
10548
10549class BigUint64ArrayIteratorEntries implements IterableIterator<[Number, BigInt]> {
10550    private parent: BigUint64Array
10551    private idx: int = 0
10552
10553    constructor(parent: BigUint64Array) {
10554        this.parent = parent
10555    }
10556
10557    public override $_iterator(): IterableIterator<[Number, BigInt]> {
10558        return this
10559    }
10560
10561    override next(): IteratorResult<[Number, BigInt]> {
10562        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
10563            return new IteratorResult<[Number, BigInt]>()
10564        }
10565        return new IteratorResult<[Number, BigInt]>(
10566            false,
10567            [new Number(this.idx), new BigInt(this.parent.getUnsafe(this.idx++))] as [Number, BigInt]
10568        )
10569    }
10570}
10571
10572/**
10573 * JS BigUint64Array API-compatible class
10574 */
10575export class BigUint64Array implements Iterable<BigInt>, ArrayLike<BigInt> {
10576    public static readonly BYTES_PER_ELEMENT: number = 8
10577
10578    /** Underlying Buffer */
10579    public readonly buffer: ArrayBufferLike
10580
10581    internal readonly byteOffsetInt: int
10582    internal readonly byteLengthInt: int
10583    internal readonly lengthInt: int
10584
10585    /**
10586     * Creates an empty BigUint64Array.
10587     */
10588    public constructor() {
10589        this(0 as int)
10590    }
10591
10592    /**
10593     * Creates an BigUint64Array with respect to data accessed via Iterable<Number> interface
10594     */
10595    public constructor(elements: Iterable<BigInt>) {
10596        const items: Object = elements as Object
10597        if (items instanceof ArrayLike) {
10598            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
10599            this.byteLengthInt = arr.length as int * BigUint64Array.BYTES_PER_ELEMENT as int
10600            this.lengthInt = arr.length as int
10601            this.buffer = new ArrayBuffer(this.byteLengthInt)
10602            this.byteOffsetInt = 0
10603            for (let i: int = 0; i < this.lengthInt; ++i) {
10604                this.setUnsafe(i, arr.$_get(i).longValue())
10605            }
10606        } else {
10607            let x = BigUint64Array.from(elements)
10608            this.byteLengthInt = x.byteLengthInt
10609            this.lengthInt = x.lengthInt
10610            this.buffer = x.buffer
10611            this.byteOffsetInt = x.byteOffsetInt
10612        }
10613    }
10614
10615    /**
10616     * Creates an BigUint64Array with respect to data, byteOffset and length.
10617     *
10618     * @param buf data initializer
10619     *
10620     * @param byteOffset byte offset from begin of the buf
10621     *
10622     * @param length size of elements of type long in newly created BigUint64Array
10623     */
10624    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
10625        let intByteOffset: int = 0
10626        if (byteOffset != undefined) {
10627            intByteOffset = byteOffset.intValue()
10628            if (intByteOffset < 0) {
10629                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
10630            }
10631        }
10632        let intByteLength: int
10633        if (buf instanceof ArrayBuffer) {
10634            intByteLength = (buf as ArrayBuffer).getByteLength()
10635        } else if (buf instanceof SharedArrayBuffer) {
10636            intByteLength = (buf as SharedArrayBuffer).getByteLength()
10637        } else {
10638            throw new Error("unexpected type of ArrayBufferLike")
10639        }
10640        intByteLength = intByteLength - intByteOffset
10641        if (intByteLength < 0) {
10642            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
10643        }
10644
10645        if (intByteLength % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10646            throw new RangeError("ArrayBufferLike.byteLength should be multiple of 8 as BigUint64Array.BYTES_PER_ELEMENT")
10647        }
10648        if (intByteOffset % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10649            throw new RangeError("byteOffset should be multiple of 8 as BigUint64Array.BYTES_PER_ELEMENT")
10650        }
10651
10652        let intLength: int
10653        if (length != undefined) {
10654            intLength = length.intValue()
10655            if (intLength > intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int) {
10656                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
10657            }
10658        } else {
10659            intLength = intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int
10660        }
10661        if (intLength < 0) {
10662            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
10663        }
10664        if (intLength < intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int) {
10665            intByteLength = intLength * BigUint64Array.BYTES_PER_ELEMENT as int
10666        }
10667        this.byteLengthInt = intByteLength
10668        this.byteOffsetInt = intByteOffset
10669        this.lengthInt = intLength
10670        this.buffer = buf
10671    }
10672
10673    /**
10674     * Creates an BigUint64Array with respect to data, byteOffset and length.
10675     *
10676     * @param buf data initializer
10677     *
10678     * @param byteOffset byte offset from begin of the buf
10679     */
10680    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
10681        this(buf, byteOffset, undefined)
10682    }
10683
10684    /**
10685     * Creates an BigUint64Array with respect to data, byteOffset and length.
10686     *
10687     * @param buf data initializer
10688     *
10689     * @param byteOffset byte offset from begin of the buf
10690     *
10691     * @param length size of elements of type long in newly created BigUint64Array
10692     */
10693    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
10694        this(buf, new Number(byteOffset), new Number(length))
10695    }
10696
10697    /**
10698     * Creates an BigUint64Array with respect to buf and byteOffset.
10699     *
10700     * @param buf data initializer
10701     *
10702     * @param byteOffset byte offset from begin of the buf
10703     */
10704    public constructor(buf: ArrayBufferLike, byteOffset: number) {
10705        this(buf, new Number(byteOffset), undefined)
10706    }
10707
10708    /**
10709     * Creates an BigUint64Array with respect to data, byteOffset and length.
10710     *
10711     * @param buf data initializer
10712     *
10713     * @param byteOffset byte offset from begin of the buf
10714     *
10715     * @param length size of elements of type long in newly created BigUint64Array
10716     */
10717    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
10718        this(buf, new Number(byteOffset), new Number(length))
10719    }
10720
10721    /**
10722     * Creates an BigUint64Array with respect to buf and byteOffset.
10723     *
10724     * @param buf data initializer
10725     *
10726     * @param byteOffset byte offset from begin of the buf
10727     */
10728    public constructor(buf: ArrayBufferLike, byteOffset: int) {
10729        this(buf, new Number(byteOffset), undefined)
10730    }
10731
10732    /**
10733     * Creates an BigUint64Array with respect to buf.
10734     *
10735     * @param buf data initializer
10736     */
10737    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
10738        if (buf instanceof ArrayBuffer) {
10739            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
10740            if (this.byteLengthInt % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10741               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as BigUint64Array.BYTES_PER_ELEMENT")
10742            }
10743            this.lengthInt = this.byteLengthInt / BigUint64Array.BYTES_PER_ELEMENT as int
10744            this.buffer = buf as ArrayBuffer
10745            this.byteOffsetInt = 0
10746        } else if (buf instanceof SharedArrayBuffer) {
10747            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
10748            if (this.byteLengthInt % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10749               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as BigUint64Array.BYTES_PER_ELEMENT")
10750            }
10751            this.lengthInt = this.byteLengthInt / BigUint64Array.BYTES_PER_ELEMENT as int
10752            this.buffer = buf as SharedArrayBuffer
10753            this.byteOffsetInt = 0
10754        } else if (buf instanceof ArrayLike) {
10755            // NOTE (ikorobkov): dealing with this overload is tricky
10756            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
10757            let arr = Array.from<Number>((buf as ArrayLike<Number>))
10758            this.byteLengthInt = arr.length as int * BigUint64Array.BYTES_PER_ELEMENT as int
10759            this.lengthInt = arr.length as int
10760            this.buffer = new ArrayBuffer(this.byteLengthInt)
10761            this.byteOffsetInt = 0
10762            for (let i: int = 0; i < this.lengthInt; ++i) {
10763                this.setUnsafe(i, arr.$_get(i).longValue())
10764            }
10765        } else {
10766            throw new Error("unexpected type of buf")
10767        }
10768    }
10769
10770    /**
10771     * Creates an BigUint64Array with respect to length.
10772     *
10773     * @param length data initializer
10774     */
10775    public constructor(length: int) {
10776        if (length < 0) {
10777            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
10778        }
10779        this.lengthInt = length
10780        this.byteLengthInt = length * BigUint64Array.BYTES_PER_ELEMENT as int
10781        this.byteOffsetInt = 0
10782        this.buffer = new ArrayBuffer(this.byteLengthInt)
10783    }
10784
10785    /**
10786     * Creates an BigUint64Array with respect to length.
10787     *
10788     * @param length data initializer
10789     */
10790    public constructor(length: number) {
10791        this(length as int)
10792    }
10793
10794    /**
10795     * Creates a copy of BigUint64Array.
10796     *
10797     * @param other data initializer
10798     */
10799    public constructor(other: BigUint64Array) {
10800        if (other.buffer instanceof ArrayBuffer) {
10801            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
10802        } else if (other.buffer instanceof SharedArrayBuffer) {
10803            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
10804        } else {
10805            throw new Error("unexpected type of buffer")
10806        }
10807        this.byteLengthInt = other.byteLength as int
10808        this.lengthInt = other.length as int
10809        this.byteOffsetInt = 0
10810    }
10811
10812    /**
10813     * Creates an BigUint64Array from number[]
10814     */
10815    public constructor(numbers: number[]) {
10816        this(numbers.length)
10817        for (let i: int = 0; i < this.lengthInt; ++i) {
10818            this.setUnsafeClamp(i, this.zeroIfInfinity(new BigInt(numbers[i]).getULong()))
10819        }
10820    }
10821
10822    /**
10823     * Creates an BigUint64Array from int[]
10824     */
10825    public constructor(numbers: int[]) {
10826        this(numbers.length)
10827        for (let i: int = 0; i < this.lengthInt; ++i) {
10828            this.setUnsafeClamp(i, this.zeroIfInfinity(new BigInt(numbers[i]).getULong()))
10829        }
10830    }
10831
10832    /**
10833     * Creates an BigUint64Array from bigint[]
10834     */
10835    public constructor(numbers: bigint[]) {
10836        this(numbers.length)
10837        for (let i: int = 0; i < this.lengthInt; ++i) {
10838            this.setUnsafe(i, numbers[i].getULong())
10839        }
10840    }
10841
10842    internal zeroIfInfinity(val: BigInt): BigInt {
10843        if ((val.getULong() == Infinity) || (val.getULong() == -Infinity)) {
10844            return new BigInt(0)
10845        }
10846        return new BigInt(val)
10847    }
10848
10849    internal zeroIfInfinity(val: long): long {
10850        if ((val == Infinity) || (val == -Infinity)) {
10851            return 0 as long
10852        }
10853        return val
10854    }
10855
10856    /**
10857     * Iteratorable interface implementation
10858     *
10859     * @returns iterator over all elements
10860     */
10861    public override $_iterator(): IterableIterator<BigInt> {
10862         return this.values()
10863    }
10864
10865    /**
10866     * Returns an instance of primitive type at passed index.
10867     *
10868     * @param index index to look at
10869     *
10870     * @returns a primitive at index
10871     */
10872    public at(index: number): BigInt | undefined {
10873        return this.at(index as int)
10874    }
10875
10876    /**
10877     * Returns an instance of primitive type at passed index if index is correct.
10878     *
10879     * @param index index to look at
10880     *
10881     * @returns a primitive at index
10882     */
10883    public at(index: int): BigInt | undefined {
10884        let k: int
10885        if (index >= 0) {
10886            k = index
10887        } else {
10888            k = this.lengthInt + index
10889        }
10890        if (k < 0 || k >= this.lengthInt) {
10891            return undefined
10892        }
10893        return new BigInt(this.getUnsafe(k))
10894    }
10895
10896    /**
10897     * Returns an instance of BigInt at passed index.
10898     *
10899     * @param index index to look at
10900     *
10901     * @returns a primitive at index
10902     */
10903    public override $_get(index: number): BigInt {
10904        return this.$_get(index as int) as BigInt
10905    }
10906
10907    /**
10908     * Returns an instance of BigInt at passed index.
10909     *
10910     * @param index index to look at
10911     *
10912     * @returns a primitive at index
10913     */
10914    public $_get(i: int): BigInt {
10915        if (i < 0 || i >= this.lengthInt) {
10916            throw new RangeError("invalid offset")
10917        }
10918        return new BigInt(this.getUnsafe(i))
10919    }
10920
10921    /**
10922     * Assigns val as element on index.
10923     *
10924     * @param val value to set
10925     *
10926     * @param index index to change
10927     */
10928    public $_set(index: number, val: BigInt): void {
10929        this.$_set(index as int, val)
10930    }
10931
10932    /**
10933     * Assigns val as element on index.
10934     *
10935     * @param val value to set
10936     *
10937     * @param index index to change
10938     */
10939    public $_set(index: int, val: BigInt): void {
10940        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
10941        if (index < 0 || index >= this.lengthInt) {
10942            throw new RangeError("invalid index")
10943        }
10944        let v = this.zeroIfInfinity(val)
10945        this.setUnsafeClamp(index, v.getULong())
10946    }
10947
10948    /**
10949     * Assigns val as element on index.
10950     *
10951     * @param val value to set
10952     *
10953     * @param index index to change
10954     */
10955    public $_set(index: number, val: long): void {
10956        this.$_set(index as int, val)
10957    }
10958
10959    /**
10960     * Assigns val as element on index.
10961     *
10962     * @param val value to set
10963     *
10964     * @param index index to change
10965     */
10966    public $_set(index: int, val: long): void {
10967        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
10968        if (index < 0 || index >= this.lengthInt) {
10969            throw new RangeError("invalid index")
10970        }
10971        let v = this.zeroIfInfinity(val)
10972        this.setUnsafeClamp(index, v)
10973    }
10974
10975    /**
10976     * Assigns val as element on index.
10977     *
10978     * @param val value to set
10979     *
10980     * @param index index to change
10981     */
10982    public $_set(index: number, val: int): void {
10983        this.$_set(index as int, val as int)
10984    }
10985
10986    /**
10987     * Assigns val as element on index.
10988     *
10989     * @param val value to set
10990     *
10991     * @param index index to change
10992     */
10993    public $_set(index: int, val: int): void {
10994        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
10995        if (index < 0 || index >= this.lengthInt) {
10996            throw new RangeError("invalid index")
10997        }
10998        let v = this.zeroIfInfinity(val as long)
10999        this.setUnsafeClamp(index, v)
11000    }
11001
11002    /**
11003     * Makes a copy of internal elements to targetPos from startPos to endPos.
11004     *
11005     * @param target insert index to place copied elements
11006     *
11007     * @param start start index to begin copy from
11008     *
11009     * @param end last index to end copy from, excluded
11010     *
11011     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
11012     */
11013    public copyWithin(target: number, start: number, end?: number): BigUint64Array {
11014        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
11015    }
11016
11017    /**
11018     * Makes a copy of internal elements to targetPos from startPos to endPos.
11019     *
11020     * @param target insert index to place copied elements
11021     *
11022     * @param start start index to begin copy from
11023     *
11024     * @param end last index to end copy from, excluded
11025     *
11026     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
11027     */
11028    public copyWithin(target: int, start: number, end?: number): BigUint64Array {
11029        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
11030    }
11031
11032    /**
11033     * Makes a copy of internal elements to targetPos from startPos to endPos.
11034     *
11035     * @param target insert index to place copied elements
11036     *
11037     * @param start start index to begin copy from
11038     *
11039     * @param end last index to end copy from, excluded
11040     *
11041     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
11042     */
11043    public copyWithin(target: number, start: int, end?: number): BigUint64Array {
11044        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
11045    }
11046
11047    /**
11048     * Makes a copy of internal elements to targetPos from startPos to endPos.
11049     *
11050     * @param target insert index to place copied elements
11051     *
11052     * @param start start index to begin copy from
11053     *
11054     * @param end last index to end copy from, excluded
11055     *
11056     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
11057     */
11058    public copyWithin(target: int, start: int, end?: number): BigUint64Array {
11059        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
11060    }
11061
11062    /**
11063     * Makes a copy of internal elements to targetPos from startPos to endPos.
11064     *
11065     * @param insert insert index to place copied elements
11066     *
11067     * @param start start index to begin copy from
11068     *
11069     * @param end last index to end copy from, excluded
11070     *
11071     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
11072     */
11073    public copyWithin(target: int, start: int, end: int): BigUint64Array {
11074        let toPos = normalizeIndex(target, this.lengthInt)
11075        let fromPos = normalizeIndex(start, this.lengthInt)
11076        const finalPos = normalizeIndex(end, this.lengthInt)
11077        let count: int = finalPos - fromPos
11078        if (count > (this.lengthInt - toPos)) {
11079            count = this.lengthInt - toPos
11080        }
11081        let direction: int = 1
11082        if ((fromPos < toPos) && (toPos < fromPos + count)) {
11083            fromPos = fromPos + count - 1
11084            toPos   = toPos   + count - 1
11085            direction = -1
11086        }
11087        while (count > 0) {
11088            const value = this.getUnsafe(fromPos)
11089            this.setUnsafe(toPos, value)
11090            fromPos = fromPos + direction
11091            toPos = toPos + direction
11092            --count
11093        }
11094        return this
11095    }
11096
11097    /**
11098     * Makes a copy of internal elements to targetPos from begin to end of BigUint64Array.
11099     *
11100     * @param target insert index to place copied elements
11101     *
11102     * See rules of parameters normalization:
11103     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
11104     */
11105    public copyWithin(target: number): BigUint64Array {
11106        return this.copyWithin(target as int)
11107    }
11108
11109    /**
11110     * Makes a copy of internal elements to targetPos from begin to end of BigUint64Array.
11111     *
11112     * @param insert insert index to place copied elements
11113     *
11114     * See rules of parameters normalization:
11115     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
11116     */
11117    public copyWithin(target: int): BigUint64Array {
11118        return this.copyWithin(target, 0, this.lengthInt)
11119    }
11120
11121    /**
11122     * Returns an array of key, value pairs for every entry in the BigUint64Array
11123     *
11124     * @returns key, value pairs for every entry in the array
11125     */
11126    public entries(): IterableIterator<[Number, BigInt]> {
11127        return new BigUint64ArrayIteratorEntries(this)
11128    }
11129
11130    /**
11131     * Fills the BigUint64Array with specified value
11132     *
11133     * @param value new value
11134     *
11135     * @returns modified BigUint64Array
11136     */
11137    public fill(value: BigInt, start?: number, end?: number): BigUint64Array {
11138        value = this.zeroIfInfinity(value)
11139        this.fill(value.getULong(), asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
11140        return this
11141    }
11142
11143    /**
11144     * Fills the BigUint64Array with specified value
11145     *
11146     * @param value new value
11147     *
11148     * @returns modified BigUint64Array
11149     */
11150    public fill(value: BigInt, start: int, end?: number): BigUint64Array {
11151        value = this.zeroIfInfinity(value)
11152        this.fill(value.getULong(), start as int, asIntOrDefault(end, this.lengthInt))
11153        return this
11154    }
11155
11156    /**
11157     * Fills the BigUint64Array with specified value
11158     *
11159     * @param value new value
11160     *
11161     * @returns modified BigUint64Array
11162     */
11163    public fill(value: BigInt, start: int, end: number): BigUint64Array {
11164        value = this.zeroIfInfinity(value)
11165        this.fill(value.getULong(), start as int, end as int)
11166        return this
11167    }
11168
11169    /**
11170     * Fills the BigUint64Array with specified value
11171     *
11172     * @param value new value
11173     *
11174     * @returns modified BigUint64Array
11175     */
11176    public fill(value: BigInt, start: number, end: int): BigUint64Array {
11177        value = this.zeroIfInfinity(value)
11178        this.fill(value.getULong(), start as int, end as int)
11179        return this
11180    }
11181
11182    /**
11183     * Fills the BigUint64Array with specified value
11184     *
11185     * @param value new value
11186     *
11187     * @returns modified BigUint64Array
11188     */
11189    public fill(value: BigInt, start: int, end: int): BigUint64Array {
11190        value = this.zeroIfInfinity(value)
11191        this.fill(value.getULong(), start as int, end as int)
11192        return this
11193    }
11194
11195    /**
11196     * Fills the BigUint64Array with specified value
11197     *
11198     * @param value new value
11199     *
11200     * @returns modified BigUint64Array
11201     */
11202    public fill(value: long, start?: number, end?: number): BigUint64Array {
11203        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
11204        return this
11205    }
11206
11207    /**
11208     * Fills the BigUint64Array with specified value
11209     *
11210     * @param value new value
11211     *
11212     * @returns modified BigUint64Array
11213     */
11214    public fill(value: long, start: int, end?: number): BigUint64Array {
11215        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
11216        return this
11217    }
11218
11219    /**
11220     * Fills the BigUint64Array with specified value
11221     *
11222     * @param value new value
11223     *
11224     * @returns modified BigUint64Array
11225     */
11226    public fill(value: long, start: int, end: number): BigUint64Array {
11227        this.fill(value, start as int, end as int)
11228        return this
11229    }
11230
11231    /**
11232     * Fills the BigUint64Array with specified value
11233     *
11234     * @param value new value
11235     *
11236     * @returns modified BigUint64Array
11237     */
11238    public fill(value: long, start: number, end: int): BigUint64Array {
11239        this.fill(value, start as int, end as int)
11240        return this
11241    }
11242
11243    /**
11244     * Fills the BigUint64Array with specified value
11245     *
11246     * @param value new value
11247     *
11248     * @returns modified BigUint64Array
11249     */
11250    public fill(value: long, start: int, end: int): BigUint64Array {
11251        const k = normalizeIndex(start, this.lengthInt)
11252        const finalPos = normalizeIndex(end, this.lengthInt)
11253        for (let i: int = k; i < finalPos; ++i) {
11254            this.setUnsafe(i, value)
11255        }
11256        return this
11257    }
11258
11259    /**
11260     * Assigns val as element on index.
11261     *
11262     * @param val value to set
11263     *
11264     * @param index index to change
11265     */
11266    public set(insertPos: number, val: BigInt): void {
11267        this.$_set(insertPos as int, val)
11268    }
11269
11270    /**
11271     * Assigns val as element on index.
11272     *
11273     * @param val value to set
11274     *
11275     * @param index index to change
11276     */
11277    public set(insertPos: int, val: BigInt): void {
11278        this.$_set(insertPos as int, val)
11279    }
11280
11281    /**
11282     * Assigns val as element on index.
11283     *
11284     * @param val value to set
11285     *
11286     * @param index index to change
11287     */
11288    public set(insertPos: number, val: long): void {
11289        this.$_set(insertPos as int, val)
11290    }
11291
11292    /**
11293     * Assigns val as element on index.
11294     *
11295     * @param val value to set
11296     *
11297     * @param index index to change
11298     */
11299    public set(insertPos: int, val: long): void {
11300        this.$_set(insertPos as int, val)
11301    }
11302
11303    /**
11304     * Copies all elements of arr to the current BigUint64Array starting from insertPos.
11305     *
11306     * @param arr array to copy data from
11307     *
11308     * @param insertPos start index where data from arr will be inserted
11309     *
11310     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
11311     */
11312    public set(arr: BigInt[], insertPos1: number): void {
11313        const insertPos = insertPos1 as int
11314        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
11315            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than BigUint64Array.length")
11316        }
11317        for (let i = 0; i < arr.length; i++) {
11318            let v = this.zeroIfInfinity(arr[i])
11319            this.setUnsafeClamp(insertPos as int + i as int, v.getULong())
11320        }
11321    }
11322
11323    /**
11324     * Copies all elements of arr to the current BigUint64Array starting from insertPos.
11325     *
11326     * @param arr array to copy data from
11327     *
11328     * @param insertPos start index where data from arr will be inserted
11329     *
11330     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
11331     */
11332    public set(arr: long[], insertPos: int): void {
11333        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
11334            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than BigUint64Array.length")
11335        }
11336        for (let i = 0; i < arr.length; i++) {
11337            let v = this.zeroIfInfinity(arr[i])
11338            this.setUnsafeClamp(insertPos + i, v)
11339        }
11340    }
11341
11342    /**
11343     * Copies all elements of arr to the current BigUint64Array.
11344     *
11345     * @param arr array to copy data from
11346     */
11347    public set(arr: BigInt[]): void {
11348        this.set(arr, 0)
11349    }
11350
11351    /**
11352     * Copies all elements of arr to the current BigUint64Array.
11353     *
11354     * @param arr array to copy data from
11355     */
11356    public set(arr: long[]): void {
11357        this.set(arr, 0)
11358    }
11359
11360    /**
11361     * Copies elements from an ArrayLike object to the BigUint64Array.
11362     *
11363     * @param array An ArrayLike object containing the elements to copy.
11364     *
11365     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
11366     */
11367    public set(array: ArrayLike<BigInt>, offset: number = 0): void {
11368        const insertPos = offset as int
11369        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
11370            throw new RangeError("offset is out of bounds")
11371        }
11372        for (let i = 0; i < array.length; i++) {
11373            let v = this.zeroIfInfinity(array[i])
11374            this.setUnsafeClamp(insertPos as int + i as int, v.getULong())
11375        }
11376    }
11377
11378    /**
11379     * Returns a new array from a set of elements.
11380     *
11381     * @param items a set of elements to include in the new array object.
11382     *
11383     * @returns new BigUint64Array
11384     */
11385    public static of(...items: number[]): BigUint64Array {
11386        let res = new BigUint64Array(items.length as int)
11387        for (let i: int = 0; i < items.length; i++) {
11388            const isInfinity = (items[i] == Infinity) || (items[i] == -Infinity)
11389            res.setUnsafeClamp(i, (new BigInt((isInfinity ? 0 : items[i]))).getULong())
11390        }
11391        return res
11392    }
11393
11394    /**
11395     * Returns a new array from a set of elements.
11396     *
11397     * @param items a set of elements to include in the new array object.
11398     *
11399     * @returns new BigUint64Array
11400     */
11401    public static of(...items: int[]): BigUint64Array {
11402        let res = new BigUint64Array(items.length as int)
11403        for (let i: int = 0; i < items.length; i++) {
11404            res.setUnsafeClamp(i, items[i] as long)
11405        }
11406        return res
11407    }
11408
11409    /**
11410     * Returns a new array from a set of elements.
11411     *
11412     * @param items a set of elements to include in the new array object.
11413     *
11414     * @returns new BigUint64Array
11415     */
11416    public static of(...items: long[]): BigUint64Array {
11417        let res = new BigUint64Array(items.length as int)
11418        for (let i: int = 0; i < items.length; i++) {
11419            res.setUnsafeClamp(i, items[i])
11420        }
11421        return res
11422    }
11423
11424    /**
11425     * Returns a new array from a set of elements.
11426     *
11427     * @param items a set of elements to include in the new array object.
11428     *
11429     * @returns new BigUint64Array
11430     */
11431    public static of(...items: bigint[]): BigUint64Array {
11432        let res = new BigUint64Array(items.length as int)
11433        for (let i: int = 0; i < items.length; i++) {
11434            res.setUnsafeClamp(i, items[i].getULong())
11435        }
11436        return res
11437    }
11438
11439    /**
11440     * Returns a new array from a set of elements.
11441     *
11442     * @param items a set of elements to include in the new array object.
11443     *
11444     * @returns new BigUint64Array
11445     */
11446    public static of(): BigUint64Array {
11447        return new BigUint64Array(0 as int)
11448    }
11449
11450    /**
11451     * Creates an array from an array-like or iterable object.
11452     *
11453     * @param arrayLike An array-like or iterable object to convert to an array.
11454     *
11455     * @returns new BigUint64Array
11456     */
11457    public static from(arr: ArrayLike<BigInt>): BigUint64Array {
11458        throw new Error("BigUint64Array.from: not implemented")
11459    }
11460
11461    /**
11462     * Creates an array from an array-like or iterable object.
11463     *
11464     * @param arrayLike An array-like or iterable object to convert to an array.
11465     *
11466     * @param mapfn A mapping function to call on every element of the array.
11467     *
11468     * @returns new BigUint64Array
11469     */
11470    public static from(arrayLike: Iterable<BigInt>, mapfn?: (v: BigInt, k: number) => BigInt): BigUint64Array {
11471        if (mapfn == undefined) {
11472            mapfn = (v: BigInt, k: number): BigInt => { return v }
11473        }
11474
11475        let iter = arrayLike.$_iterator()
11476        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
11477        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
11478        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
11479        //  we can make one pass through the iterator without the need for memory reallocation.
11480        const maybeLength = tryGetIteratorLength(arrayLike)
11481        if (maybeLength) {
11482            const result = new BigUint64Array(maybeLength)
11483            for (let i = 0; i < maybeLength; ++i) {
11484                const x = iter.next()
11485                if (x.done) {
11486                    return new BigUint64Array(result.buffer, 0, i)
11487                }
11488                result.setUnsafeClamp(i, ((mapfn)!(x.value!, i)).getULong())
11489            }
11490            return result
11491        }
11492
11493        // NOTE (templin.konstantin): Create builtin array as buffer
11494        let temp = new BigUint64Array(6)
11495        let index = new int[1]
11496        index[0] = 0
11497
11498        iteratorForEach<BigInt>(arrayLike.$_iterator(), (x: BigInt): void => {
11499            if (index[0] + 1 > temp.lengthInt) {
11500                // NOTE (templin.konstantin): Progressive reallocation
11501                const curLength = (temp.buffer as Buffer).getByteLength()
11502                const tb = new ArrayBuffer(curLength * 2)
11503                for (let i = 0; i < curLength; ++i) {
11504                    tb.set(i, (temp.buffer as Buffer).at(i))
11505                }
11506                temp = new BigUint64Array(tb)
11507            }
11508            temp.setUnsafeClamp(index[0], ((mapfn)!(x, index[0])).getULong())
11509            index[0]++
11510        })
11511
11512        return new BigUint64Array(temp.buffer, 0, index[0])
11513    }
11514
11515    /**
11516     * Creates an array from an array-like or iterable object.
11517     *
11518     * @param arrayLike An array-like or iterable object to convert to an array.
11519     *
11520     * @param mapfn A mapping function to call on every element of the array.
11521     *
11522     * @returns new BigUint64Array
11523     */
11524    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => BigInt): BigUint64Array {
11525        let res = new BigUint64Array(arrayLike.length)
11526        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
11527        const idx = new int[1]
11528        idx[0] = 0
11529        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
11530            res.setUnsafeClamp(idx[0], (mapfn(x as T, idx[0] as number)).getULong())
11531            idx[0] += 1
11532        })
11533        return res
11534    }
11535
11536    /**
11537     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
11538     *
11539     * @param searchElement The element to search for
11540     *
11541     * @param fromIndex The position in this array at which to begin searching for searchElement
11542     *
11543     * @returns true if searchElement is in BigUint64Array, false otherwise
11544     */
11545    public includes(searchElement: BigInt, fromIndex?: number): boolean {
11546        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
11547    }
11548
11549    /**
11550     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
11551     *
11552     * @param searchElement The element to search for
11553     *
11554     * @param fromIndex The position in this array at which to begin searching for searchElement
11555     *
11556     * @returns true if searchElement is in BigUint64Array, false otherwise
11557     */
11558    public includes(searchElement: long, fromIndex: int): boolean {
11559        return this.indexOf(searchElement as int, fromIndex) != -1
11560    }
11561
11562    /**
11563     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
11564     *
11565     * @param searchElement The element to search for
11566     *
11567     * @param fromIndex The position in this array at which to begin searching for searchElement
11568     *
11569     * @returns true if searchElement is in BigUint64Array, false otherwise
11570     */
11571    public includes(searchElement: long): boolean {
11572        return this.indexOf(searchElement as int, 0) != -1
11573    }
11574
11575    /**
11576     * Returns the index of the first occurrence of a value in BigUint64Array.
11577     *
11578     * @param searchElement The value to locate in the array.
11579     *
11580     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11581     *  search starts at index 0.
11582     *
11583     * @returns index of element if it presents, -1 otherwise
11584     */
11585    public indexOf(searchElement: BigInt, fromIndex?: number): number {
11586        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
11587    }
11588
11589    /**
11590     * Returns the index of the first occurrence of a value in BigUint64Array.
11591     *
11592     * @param searchElement The value to locate in the array.
11593     *
11594     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11595     *  search starts at index 0.
11596     *
11597     * @returns index of element if it presents, -1 otherwise
11598     */
11599    public indexOf(searchElement: BigInt, fromIndex: int): number {
11600        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
11601        for (let i = fromIndex; i < this.lengthInt; i++) {
11602            if (new BigInt(this.getUnsafe(i)) == searchElement) {
11603                return i
11604            }
11605        }
11606        return -1
11607    }
11608
11609    /**
11610     * Returns the index of the first occurrence of a value in BigUint64Array.
11611     *
11612     * @param searchElement The value to locate in the array.
11613     *
11614     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11615     *  search starts at index 0.
11616     *
11617     * @returns index of element if it presents, -1 otherwise
11618     */
11619    public indexOf(searchElement: int, fromIndex: int): number {
11620        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
11621        for (let i = fromIndex; i < this.lengthInt; i++) {
11622            if (this.getUnsafe(i) == searchElement as long) {
11623                return i
11624            }
11625        }
11626        return -1
11627
11628    }
11629
11630    /**
11631     * Returns the index of the first occurrence of a value in BigUint64Array.
11632     *
11633     * @param searchElement The value to locate in the array.
11634     *
11635     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11636     *  search starts at index 0.
11637     *
11638     * @returns index of element if it presents, -1 otherwise
11639     */
11640    public indexOf(searchElement: int): number {
11641        return this.indexOf(searchElement, 0)
11642    }
11643
11644    /**
11645     * Adds all the elements of an array separated by the specified separator string
11646     *
11647     * @param separator A string used to separate one element of an array from the next in the
11648     * resulting String. If omitted, the array elements are separated with a comma
11649     *
11650     * @returns joined representation
11651     */
11652    public join(separator?: String): string {
11653        if (separator == undefined) {
11654            return this.join(",")
11655        }
11656        let res: StringBuilder = new StringBuilder("")
11657        for (let i = 0; i < this.lengthInt - 1; i++) {
11658            res.append(new BigInt(this.getUnsafe(i)))
11659            res.append(separator)
11660        }
11661        if (this.lengthInt > 0) {
11662            res.append(new BigInt(this.getUnsafe(this.lengthInt - 1)))
11663        }
11664        return res.toString()
11665    }
11666
11667    /**
11668     * Returns an list of keys in BigUint64Array
11669     *
11670     * @returns iterator over keys
11671     */
11672    public keys(): IterableIterator<number> {
11673        return new BigUint64ArrayIteratorKeys(this)
11674    }
11675
11676    /**
11677     * Returns the index of the last occurrence of a value in BigUint64Array.
11678     *
11679     * @param searchElement The value to locate in the array.
11680     *
11681     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11682     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11683     *
11684     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11685     */
11686    public lastIndexOf(searchElement: BigInt, fromIndex: number|undefined): number {
11687        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
11688    }
11689
11690    /**
11691     * Returns the index of the last occurrence of a value in BigUint64Array.
11692     *
11693     * @param searchElement The value to locate in the array.
11694     *
11695     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11696     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11697     *
11698     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11699     */
11700    public lastIndexOf(searchElement: BigInt): number {
11701        return this.lastIndexOf(searchElement, this.lengthInt - 1)
11702    }
11703
11704    /**
11705     * Returns the index of the last occurrence of a value in BigUint64Array.
11706     *
11707     * @param searchElement The value to locate in the array.
11708     *
11709     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11710     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11711     *
11712     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11713     */
11714    public lastIndexOf(searchElement: BigInt, fromIndex: int): number {
11715        if (this.lengthInt == 0) {
11716            return -1
11717        }
11718        let k: int = this.lengthInt + fromIndex
11719        if (fromIndex >= 0) {
11720            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
11721        }
11722        while (k >= 0) {
11723            if (new BigInt(this.getUnsafe(k)) == searchElement) {
11724                return k
11725            }
11726            k--
11727        }
11728        return -1
11729    }
11730
11731    /**
11732     * Returns the index of the last occurrence of a value in BigUint64Array.
11733     *
11734     * @param searchElement The value to locate in the array.
11735     *
11736     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11737     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11738     *
11739     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11740     */
11741    public lastIndexOf(searchElement: int, fromIndex: int): number {
11742        if (this.lengthInt == 0) {
11743            return -1
11744        }
11745        let k: int = this.lengthInt + fromIndex
11746        if (fromIndex >= 0) {
11747            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
11748        }
11749        while (k >= 0) {
11750            if (this.getUnsafe(k) == searchElement as long) {
11751                return k
11752            }
11753            k--
11754        }
11755        return -1
11756    }
11757
11758    /**
11759     * Returns the index of the last occurrence of a value in BigUint64Array.
11760     *
11761     * @param searchElement The value to locate in the array.
11762     *
11763     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11764     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11765     *
11766     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11767     */
11768    public lastIndexOf(searchElement: int): number {
11769        return this.lastIndexOf(searchElement, this.lengthInt - 1)
11770    }
11771
11772   /**
11773    * Creates a new BigUint64Array using initializer
11774    *
11775    * @param data initializer
11776    *
11777    * @returns a new BigUint64Array from data
11778    */
11779    public of(...data: BigInt[]): BigUint64Array {
11780        throw new Error("BigUint64Array.of: not implemented")
11781    }
11782
11783    /**
11784     * Creates a new BigUint64Array using reversed data from the current one
11785     *
11786     * @returns a new BigUint64Array using reversed data from the current one
11787     */
11788    public reverse(): BigUint64Array {
11789        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
11790            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
11791            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
11792            this.setUnsafe(i, tmp)
11793        }
11794        return this
11795    }
11796
11797    /**
11798     * Creates a slice of current BigUint64Array using range [begin, end)
11799     *
11800     * @param begin start index to be taken into slice
11801     *
11802     * @param end last index to be taken into slice
11803     *
11804     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11805     *
11806     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11807     */
11808    public slice(begin?: number, end?: number): BigUint64Array {
11809        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
11810    }
11811
11812    /**
11813     * Creates a slice of current BigUint64Array using range [begin, end)
11814     *
11815     * @param begin start index to be taken into slice
11816     *
11817     * @param end last index to be taken into slice
11818     *
11819     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11820     *
11821     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11822     */
11823    public slice(begin: number, end: number): BigUint64Array {
11824        return this.slice(begin as int, end as int)
11825    }
11826
11827    /**
11828     * Creates a slice of current BigUint64Array using range [begin, end)
11829     *
11830     * @param begin start index to be taken into slice
11831     *
11832     * @param end last index to be taken into slice
11833     *
11834     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11835     *
11836     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11837     */
11838    public slice(begin: number, end: int): BigUint64Array {
11839        return this.slice(begin as int, end as int)
11840    }
11841
11842    /**
11843     * Creates a slice of current BigUint64Array using range [begin, end)
11844     *
11845     * @param begin start index to be taken into slice
11846     *
11847     * @param end last index to be taken into slice
11848     *
11849     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11850     *
11851     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11852     */
11853    public slice(begin: int, end: number): BigUint64Array {
11854        return this.slice(begin as int, end as int)
11855    }
11856
11857    /**
11858     * Creates a slice of current BigUint64Array using range [begin, end)
11859     *
11860     * @param begin start index to be taken into slice
11861     *
11862     * @param end last index to be taken into slice
11863     *
11864     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11865     *
11866     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11867     */
11868    public slice(begin: int, end: int): BigUint64Array {
11869        const len: int = this.lengthInt
11870        const relStart = normalizeIndex(begin, len)
11871        const relEnd = normalizeIndex(end, len)
11872        let count = relEnd - relStart
11873        if (count < 0) {
11874            count = 0
11875        }
11876        if (this.buffer instanceof ArrayBuffer) {
11877            let buf = (this.buffer as ArrayBuffer).slice(relStart * BigUint64Array.BYTES_PER_ELEMENT as int, relEnd * BigUint64Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
11878            return new BigUint64Array(buf)
11879        } else if (this.buffer instanceof SharedArrayBuffer) {
11880            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * BigUint64Array.BYTES_PER_ELEMENT as int, relEnd * BigUint64Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
11881            return new BigUint64Array(buf)
11882        } else {
11883            throw new Error("unexpected type of buffer")
11884        }
11885    }
11886
11887    /**
11888     * Creates a slice of current BigUint64Array using range [begin, this.lengthInt).
11889     *
11890     * @param begin start index to be taken into slice
11891     *
11892     * @returns a new BigUint64Array with elements of current BigUint64Array[begin, this.lengthInt)
11893     */
11894    public slice(begin: number): BigUint64Array {
11895        return this.slice(begin as int)
11896    }
11897
11898    /**
11899     * Creates a slice of current BigUint64Array using range [begin, this.lengthInt).
11900     *
11901     * @param begin start index to be taken into slice
11902     *
11903     * @returns a new BigUint64Array with elements of current BigUint64Array[begin, this.lengthInt)
11904     */
11905    public slice(begin: int): BigUint64Array {
11906        return this.slice(begin, this.lengthInt)
11907    }
11908
11909    /**
11910     * Sorts in-place
11911     *
11912     * @param compareFn comparator —  used to determine the order of the elements.
11913     * compareFn returns a negative value if first argument is less than second argument,
11914     * zero if they're equal and a positive value otherwise.
11915     * If omitted, the elements are sorted in ascending order.
11916     *
11917     * @returns sorted BigUint64Array
11918     */
11919    public sort(compareFn?: (a: BigInt, b: BigInt) => number): this {
11920        let arr: long[] = new long[this.lengthInt]
11921        for (let i = 0; i < this.lengthInt; ++i) {
11922            arr[i] = this.getUnsafe(i)
11923        }
11924        let cmp = (l: long, r: long): number => {
11925                return (l - r) as number
11926            }
11927        if (compareFn != undefined) {
11928            cmp = (l: long, r: long): number => {
11929                return compareFn!(new BigInt(l), new BigInt(r))
11930            }
11931        }
11932        sort(arr, cmp)
11933        for (let i = 0; i < this.lengthInt; ++i) {
11934            this.setUnsafe(i, arr[i])
11935        }
11936        return this
11937    }
11938
11939    /**
11940     * Sorts in-place
11941     *
11942     * @param compareFn comparator —  used to determine the order of the elements.
11943     * compareFn returns a negative value if first argument is less than second argument,
11944     * zero if they're equal and a positive value otherwise.
11945     *
11946     * @returns sorted BigUint64Array
11947     */
11948    public sort(compareFn: (a: BigInt) => number): this {
11949        let cmp = (a: BigInt, b: BigInt) => { return compareFn(a)}
11950        this.sort(cmp)
11951        return this
11952    }
11953
11954    /**
11955     * Sorts in-place
11956     *
11957     * @param fn compareFn —  used to determine the order of the elements.
11958     * compareFn returns a negative value if first argument is less than second argument,
11959     * zero if they're equal and a positive value otherwise.
11960     *
11961     * @returns sorted BigUint64Array
11962     */
11963    public sort(compareFn: () => number): this {
11964        let cmp = (a: BigInt, b: BigInt) => { return compareFn()}
11965        this.sort(cmp)
11966        return this
11967    }
11968    /**
11969     * Creates a BigUint64Array with the same underlying Buffer
11970     *
11971     * @param begin start index, inclusive
11972     *
11973     * @param end last index, exclusive
11974     *
11975     * @returns new BigUint64Array with the same underlying Buffer
11976     */
11977    public subarray(begin?: number, end?: number): BigUint64Array {
11978        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
11979    }
11980
11981    /**
11982     * Creates a BigUint64Array with the same underlying Buffer
11983     *
11984     * @param begin start index, inclusive
11985     *
11986     * @param end last index, exclusive
11987     *
11988     * @returns new BigUint64Array with the same underlying Buffer
11989     */
11990    public subarray(begin: number, end: number): BigUint64Array {
11991        return this.subarray(begin as int, end as int)
11992    }
11993
11994    /**
11995     * Creates a BigUint64Array with the same underlying Buffer
11996     *
11997     * @param begin start index, inclusive
11998     *
11999     * @param end last index, exclusive
12000     *
12001     * @returns new BigUint64Array with the same underlying Buffer
12002     */
12003    public subarray(begin: number, end: int): BigUint64Array {
12004        return this.subarray(begin as int, end as int)
12005    }
12006
12007    /**
12008     * Creates a BigUint64Array with the same underlying Buffer
12009     *
12010     * @param begin start index, inclusive
12011     *
12012     * @param end last index, exclusive
12013     *
12014     * @returns new BigUint64Array with the same underlying Buffer
12015     */
12016    public subarray(begin: int, end: number): BigUint64Array {
12017        return this.subarray(begin as int, end as int)
12018    }
12019
12020    /**
12021     * Creates a BigUint64Array with the same underlying Buffer
12022     *
12023     * @param begin start index, inclusive
12024     *
12025     * @param end last index, exclusive
12026     *
12027     * @returns new BigUint64Array with the same underlying Buffer
12028     */
12029    public subarray(begin: int, end: int): BigUint64Array {
12030        const len: int = this.lengthInt
12031        const relStart = normalizeIndex(begin, len)
12032        const relEnd = normalizeIndex(end, len)
12033        let count = relEnd - relStart
12034        if (count < 0) {
12035            count = 0
12036        }
12037        return new BigUint64Array(this.buffer, relStart * BigUint64Array.BYTES_PER_ELEMENT as int, count)
12038    }
12039
12040    /**
12041     * Creates a BigUint64Array with the same Buffer
12042     *
12043     * @param begin start index, inclusive
12044     *
12045     * @returns new BigUint64Array with the same Buffer
12046     */
12047    public subarray(begin: number): BigUint64Array {
12048        return this.subarray(begin as int, this.lengthInt)
12049    }
12050
12051    /**
12052     * Creates a BigUint64Array with the same Buffer
12053     *
12054     * @param begin start index, inclusive
12055     *
12056     * @returns new BigUint64Array with the same Buffer
12057     */
12058    public subarray(begin: int): BigUint64Array {
12059        return this.subarray(begin, this.lengthInt)
12060    }
12061
12062    /**
12063     * Converts BigUint64Array to a string with respect to locale
12064     *
12065     * @param locales
12066     *
12067     * @param options
12068     *
12069     * @returns string representation
12070     */
12071    public toLocaleString(locales: Object, options: Object): string {
12072        throw new Error("BigUint64Array.toLocaleString: not implemented")
12073    }
12074
12075    /**
12076     * Converts BigUint64Array to a string with respect to locale
12077     *
12078     * @param locales
12079     *
12080     * @returns string representation
12081     */
12082    public toLocaleString(locales: Object): string {
12083        return this.toLocaleString(new Object(), new Object())
12084    }
12085
12086    /**
12087     * Converts BigUint64Array to a string with respect to locale
12088     *
12089     * @returns string representation
12090     */
12091    public toLocaleString(): string {
12092        let res: StringBuilder = new StringBuilder("")
12093        for (let i = 0; i < this.lengthInt - 1; ++i) {
12094            res.append(new BigInt(this.getUnsafe(i)).toLocaleString())
12095            res.append(",")
12096        }
12097        if (this.lengthInt > 0) {
12098            res.append(new BigInt(this.getUnsafe(this.lengthInt - 1)).toLocaleString())
12099        }
12100        return res.toString()
12101    }
12102
12103    /**
12104     * Creates a reversed copy
12105     *
12106     * @returns a reversed copy
12107     */
12108    public toReversed(): BigUint64Array {
12109        return new BigUint64Array(this).reverse()
12110    }
12111
12112    /**
12113     * Creates a sorted copy
12114     *
12115     * @returns a sorted copy
12116     */
12117    public toSorted(): BigUint64Array {
12118        return new BigUint64Array(this).sort()
12119    }
12120
12121    /**
12122     * Returns a string representation of the BigUint64Array
12123     *
12124     * @returns a string representation of the BigUint64Array
12125     */
12126    public override toString(): string {
12127        return this.join(",")
12128    }
12129
12130    /**
12131     * Returns array values iterator
12132     *
12133     * @returns an iterator
12134     */
12135    public values(): IterableIterator<BigInt> {
12136         return new BigUint64ArrayIterator(this)
12137    }
12138
12139    /**
12140     * Creates a copy with replaced value on index
12141     *
12142     * @param index
12143     *
12144     * @param value
12145     *
12146     * @returns an BigUint64Array with replaced value on index
12147     */
12148    public with(index: number, value: BigInt): BigUint64Array {
12149        return this.with(index as int, value.getULong())
12150    }
12151
12152    /**
12153     * Creates a copy with replaced value on index
12154     *
12155     * @param index
12156     *
12157     * @param value
12158     *
12159     * @returns an BigUint64Array with replaced value on index
12160     */
12161    public with(index: int, value: long): BigUint64Array {
12162        let res = new BigUint64Array(this)
12163        res.setUnsafeClamp(index, value)
12164        return res
12165    }
12166
12167    /// === with element lambda functions ===
12168
12169    /**
12170     * Determines whether the specified callback function returns true for all elements of an array.
12171     *
12172     * @param predicate A function that accepts one argument.
12173     * The every method calls the predicate function for each element in the array until the predicate returns a false,
12174     * or until the end of the array.
12175     *
12176     * @returns true unless predicate function returns a false for an array element,
12177     * in which case false is immediately returned.
12178     */
12179    public every(predicate: (element: BigInt) => boolean): boolean {
12180        return this.every((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element))
12181    }
12182
12183    /**
12184     * creates a new BigUint64Array from current BigUint64Array based on a condition fn
12185     *
12186     * @param fn the condition to apply for each element
12187     *
12188     * @returns a new BigUint64Array with elements from current BigUint64Array that satisfy condition fn
12189     */
12190    public filter(fn: (val: BigInt) => boolean): BigUint64Array {
12191        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
12192            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val) }
12193        return this.filter(newF)
12194    }
12195
12196    /**
12197     * Returns the value of the first element in the array where predicate is true, and undefined
12198     * otherwise
12199     *
12200     * @param predicate find calls predicate once for each element of the array, in ascending
12201     * order, until it finds one where predicate returns true. If such an element is found, find
12202     * immediately returns that element value. Otherwise, find returns undefined
12203     *
12204     * @returns BigInt | undefined
12205     */
12206    public find(predicate: () => boolean): BigInt | undefined {
12207        return this.find((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate())
12208    }
12209
12210    /**
12211     * Returns the value of the first element in the array where predicate is true, and undefined
12212     * otherwise
12213     *
12214     * @param predicate find calls predicate once for each element of the array, in ascending
12215     * order, until it finds one where predicate returns true. If such an element is found, find
12216     * immediately returns that element value. Otherwise, find returns undefined
12217     *
12218     * @returns BigInt | undefined
12219     */
12220    public find(predicate: (value: BigInt) => boolean): BigInt | undefined {
12221        return this.find((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value))
12222    }
12223
12224    /**
12225     * Returns the index of the first element in the array where predicate is true, and -1
12226     * otherwise
12227     *
12228     * @param predicate find calls predicate once for each element of the array, in ascending
12229     * order, until it finds one where predicate returns true. If such an element is found,
12230     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
12231     *
12232     * @returns number
12233     */
12234    public findIndex(predicate: (value: BigInt) => boolean): number {
12235        return this.findIndex((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value)) as number
12236    }
12237
12238    /**
12239     * Finds the last element in the BigUint64Array that satisfies the condition
12240     *
12241     * @param fn condition
12242     *
12243     * @returns the last element that satisfies fn
12244     */
12245    public findLast(fn: (val: BigInt) => boolean): BigInt {
12246        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
12247            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val) }
12248        return this.findLast(newF)
12249    }
12250
12251    /**
12252     * Finds an index of the last element in the BigUint64Array that satisfies the condition
12253     *
12254     * @param fn condition
12255     *
12256     * @returns the index of the last element that satisfies fn, -1 otherwise
12257     */
12258    public findLastIndex(fn: (val: BigInt) => boolean): number {
12259        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
12260            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val) }
12261        return this.findLastIndex(newF) as number
12262    }
12263
12264    /**
12265     * Performs the specified action for each element in BigUint64Array
12266     *
12267     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
12268     * callbackfn function one time for each element in the array.
12269     *
12270     * @returns None
12271     */
12272    public forEach(callbackfn: (val: BigInt) => void): void {
12273        this.forEach((value: BigInt, index: number, array: BigUint64Array): void => callbackfn(value))
12274    }
12275
12276
12277    /**
12278     * Determines whether the specified callback function returns true for any element of an array.
12279     *
12280     * @param predicate A function that accepts one argument.
12281     * The some method calls the predicate function for each element in the array
12282     * until the predicate returns a true or until the end of the array.
12283     *
12284     * @returns false unless predicate function returns true for an array element,
12285     * in which case true is immediately returned.
12286     */
12287    public some(predicate: (element: BigInt) => boolean): boolean {
12288        return this.some((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element))
12289    }
12290
12291    /**
12292     * Determines whether the specified callback function returns true for any element of an array.
12293     *
12294     * @param predicate A function that accepts three arguments.
12295     * The some method calls the predicate function for each element in the array
12296     * until the predicate returns a true or until the end of the array.
12297     *
12298     * @returns false unless predicate function returns true for an array element,
12299     * in which case true is immediately returned.
12300     */
12301    public some(predicate: (element: BigInt, index: number, array: BigUint64Array) => boolean): boolean {
12302        for (let i = 0; i < this.lengthInt; i++) {
12303            if (predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
12304                return true
12305            }
12306        }
12307        return false
12308    }
12309
12310    /**
12311     * Determines whether the specified callback function returns true for any element of an array.
12312     *
12313     * @param predicate A function that accepts two arguments.
12314     * The some method calls the predicate function for each element in the array
12315     * until the predicate returns a true or until the end of the array.
12316     *
12317     * @returns false unless predicate function returns true for an array element,
12318     * in which case true is immediately returned.
12319     */
12320    public some(predicate: (element: BigInt, index: number) => boolean): boolean {
12321        return this.some((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element, index))
12322    }
12323
12324    /**
12325     * Determines whether the specified callback function returns true for any element of an array.
12326     *
12327     * @param predicate A function that accepts no arguments.
12328     * The some method calls the predicate function for each element in the array
12329     * until the predicate returns a true or until the end of the array.
12330     *
12331     * @returns false unless predicate function returns true for an array element,
12332     * in which case true is immediately returned.
12333     */
12334    public some(predicate: () => boolean): boolean {
12335        return this.some((element: BigInt, index: number, array: BigUint64Array): boolean => predicate())
12336    }
12337
12338    /**
12339     * Calls the specified callback function for all the elements in an array.
12340     * The return value of the callback function is the accumulated result,
12341     * and is provided as an argument in the next call to the callback function.
12342     *
12343     * @param callbackfn A function that accepts four arguments.
12344     * The reduce method calls the callbackfn function one time for each element in the array.
12345     *
12346     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12347     * The first call to the callbackfn function provides this value as an argument.
12348     *
12349     * @returns The value that results from running the callback function to completion over the entire typed array.
12350     */
12351    public reduce<U = BigInt>(
12352                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => U,
12353                initialValue: U): U {
12354        let accumulatedValue = initialValue
12355        for (let i = 0; i < this.lengthInt; i++) {
12356            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12357        }
12358        return accumulatedValue
12359    }
12360
12361    /**
12362     * Calls the specified callback function for all the elements in an array.
12363     * The return value of the callback function is the accumulated result,
12364     * and is provided as an argument in the next call to the callback function.
12365     *
12366     * @param callbackfn A function that accepts three arguments.
12367     * The reduce method calls the callbackfn function one time for each element in the array.
12368     *
12369     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12370     * The first call to the callbackfn function provides this value as an argument.
12371     *
12372     * @returns The value that results from running the callback function to completion over the entire typed array.
12373     */
12374    public reduce<U = BigInt>(
12375                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number) => U,
12376                initialValue: U): U {
12377        return this.reduce(
12378                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12379                        callbackfn(prevVal, currVal, currIndex),
12380                initialValue)
12381    }
12382
12383    /**
12384     * Calls the specified callback function for all the elements in an array.
12385     * The return value of the callback function is the accumulated result,
12386     * and is provided as an argument in the next call to the callback function.
12387     *
12388     * @param callbackfn A function that accepts two arguments.
12389     * The reduce method calls the callbackfn function one time for each element in the array.
12390     *
12391     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12392     * The first call to the callbackfn function provides this value as an argument.
12393     *
12394     * @returns The value that results from running the callback function to completion over the entire typed array.
12395     */
12396    public reduce<U = BigInt>(
12397                callbackfn: (previousValue: U, currentValue: BigInt) => U,
12398                initialValue: U): U {
12399        return this.reduce(
12400                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12401                        callbackfn(prevVal, currVal),
12402                initialValue)
12403    }
12404
12405    /**
12406     * Calls the specified callback function for all the elements in an array.
12407     * The return value of the callback function is the accumulated result,
12408     * and is provided as an argument in the next call to the callback function.
12409     *
12410     * @param callbackfn A function that accepts one argument
12411     * The reduce method calls the callbackfn function one time for each element in the array.
12412     *
12413     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12414     * The first call to the callbackfn function provides this value as an argument.
12415     *
12416     * @returns The value that results from running the callback function to completion over the entire typed array.
12417     */
12418    public reduce<U = BigInt>(
12419                callbackfn: (previousValue: U) => U,
12420                initialValue: U): U {
12421        return this.reduce(
12422                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12423                        callbackfn(prevVal),
12424                initialValue)
12425    }
12426
12427    /**
12428     * Calls the specified callback function for all the elements in an array.
12429     * The return value of the callback function is the accumulated result,
12430     * and is provided as an argument in the next call to the callback function.
12431     *
12432     * @param callbackfn A function that accepts no arguments
12433     * The reduce method calls the callbackfn function one time for each element in the array.
12434     *
12435     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12436     * The first call to the callbackfn function provides this value as an argument.
12437     *
12438     * @returns The value that results from running the callback function to completion over the entire typed array.
12439     */
12440    public reduce<U = BigInt>(
12441                callbackfn: () => U,
12442                initialValue: U): U {
12443        return this.reduce(
12444                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12445                        callbackfn(),
12446                initialValue)
12447    }
12448
12449    /**
12450     * Calls the specified callback function for all the elements in an array.
12451     * The return value of the callback function is the accumulated result,
12452     * and is provided as an argument in the next call to the callback function.
12453     *
12454     * @param callbackfn A function that accepts four arguments.
12455     * The reduce method calls the callbackfn function one time for each element in the array.
12456     * The first call to the callbackfn function provides array first element value as an argument
12457     *
12458     * @returns The value that results from running the callback function to completion over the entire typed array.
12459     * calling reduce method on an empty array without an initial value creates a TypeError
12460     */
12461    public reduce(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => BigInt): BigInt {
12462        if (this.lengthInt == 0) {
12463            throw new TypeError("Reduce of empty array with no initial value")
12464        }
12465
12466        let accumulatedValue = new BigInt(this.$_get(0))
12467        for (let i = 1; i < this.lengthInt; i++) {
12468            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12469        }
12470        return accumulatedValue
12471    }
12472
12473    /**
12474     * Calls the specified callback function for all the elements in an array.
12475     * The return value of the callback function is the accumulated result,
12476     * and is provided as an argument in the next call to the callback function.
12477     *
12478     * @param callbackfn A function that accepts three arguments.
12479     * The reduce method calls the callbackfn function one time for each element in the array.
12480     * The first call to the callbackfn function provides array first element value as an argument
12481     *
12482     * @returns The value that results from running the callback function to completion over the entire typed array.
12483     * calling reduce method on an empty array without an initial value creates a TypeError
12484     */
12485    public reduce(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number) => BigInt): BigInt {
12486        return this.reduce(
12487                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12488                        callbackfn(prevVal, currVal, currIndex))
12489    }
12490
12491    /**
12492     * Calls the specified callback function for all the elements in an array.
12493     * The return value of the callback function is the accumulated result,
12494     * and is provided as an argument in the next call to the callback function.
12495     *
12496     * @param callbackfn A function that accepts two arguments.
12497     * The reduce method calls the callbackfn function one time for each element in the array.
12498     * The first call to the callbackfn function provides array first element value as an argument
12499     *
12500     * @returns The value that results from running the callback function to completion over the entire typed array.
12501     * calling reduce method on an empty array without an initial value creates a TypeError
12502     */
12503    public reduce(callbackfn: (previousValue: BigInt, currentValue: BigInt) => BigInt): BigInt {
12504        return this.reduce(
12505                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12506                        callbackfn(prevVal, currVal))
12507    }
12508
12509    /**
12510     * Calls the specified callback function for all the elements in an array.
12511     * The return value of the callback function is the accumulated result,
12512     * and is provided as an argument in the next call to the callback function.
12513     *
12514     * @param callbackfn A function that accepts one argument.
12515     * The reduce method calls the callbackfn function one time for each element in the array.
12516     * The first call to the callbackfn function provides array first element value as an argument
12517     *
12518     * @returns The value that results from running the callback function to completion over the entire typed array.
12519     * calling reduce method on an empty array without an initial value creates a TypeError
12520     */
12521    public reduce(callbackfn: (previousValue: BigInt) => BigInt): BigInt {
12522        return this.reduce(
12523                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12524                        callbackfn(prevVal))
12525    }
12526
12527    /**
12528     * Calls the specified callback function for all the elements in an array.
12529     * The return value of the callback function is the accumulated result,
12530     * and is provided as an argument in the next call to the callback function.
12531     *
12532     * @param callbackfn A function that accepts no arguments.
12533     * The reduce method calls the callbackfn function one time for each element in the array.
12534     * The first call to the callbackfn function provides array first element value as an argument
12535     *
12536     * @returns The value that results from running the callback function to completion over the entire typed array.
12537     * calling reduce method on an empty array without an initial value creates a TypeError
12538     */
12539    public reduce(callbackfn: () => BigInt): BigInt {
12540        return this.reduce(
12541                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12542                        callbackfn())
12543    }
12544
12545    /**
12546     * Calls the specified callback function for all the elements in an array, in descending order.
12547     * The return value of the callback function is the accumulated result,
12548     * and is provided as an argument in the next call to the callback function.
12549     *
12550     * @param callbackfn A function that accepts four arguments.
12551     * The reduceRight method calls the callbackfn function one time for each element in the array.
12552     *
12553     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12554     * The first call to the callbackfn function provides this value as an argument.
12555     *
12556     * @returns The value that results from running the callback function to completion over the entire typed array.
12557     */
12558    public reduceRight<U = BigInt>(
12559                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => U,
12560                initialValue: U): U {
12561        let accumulatedValue = initialValue
12562        for (let i = this.lengthInt - 1; i >= 0; i--) {
12563            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12564        }
12565        return accumulatedValue
12566    }
12567
12568    /**
12569     * Calls the specified callback function for all the elements in an array, in descending order.
12570     * The return value of the callback function is the accumulated result,
12571     * and is provided as an argument in the next call to the callback function.
12572     *
12573     * @param callbackfn A function that accepts three arguments.
12574     * The reduceRight method calls the callbackfn function one time for each element in the array.
12575     *
12576     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12577     * The first call to the callbackfn function provides this value as an argument.
12578     *
12579     * @returns The value that results from running the callback function to completion over the entire typed array.
12580     */
12581    public reduceRight<U = BigInt>(
12582                callbackfn: (previuosValue: U, currentValue: BigInt, currentIndex: number) => U,
12583                initialValue: U): U {
12584        return this.reduceRight(
12585                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12586                        callbackfn(prevVal, currVal, currIndex),
12587                initialValue)
12588    }
12589
12590    /**
12591     * Calls the specified callback function for all the elements in an array, in descending order.
12592     * The return value of the callback function is the accumulated result,
12593     * and is provided as an argument in the next call to the callback function.
12594     *
12595     * @param callbackfn A function that accepts two arguments.
12596     * The reduceRight method calls the callbackfn function one time for each element in the array.
12597     *
12598     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12599     * The first call to the callbackfn function provides this value as an argument.
12600     *
12601     * @returns The value that results from running the callback function to completion over the entire typed array.
12602     */
12603    public reduceRight<U = BigInt>(
12604                callbackfn: (previuosValue: U, currentValue: BigInt) => U,
12605                initialValue: U): U {
12606        return this.reduceRight(
12607                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12608                        callbackfn(prevVal, currVal),
12609                initialValue)
12610    }
12611
12612    /**
12613     * Calls the specified callback function for all the elements in an array, in descending order.
12614     * The return value of the callback function is the accumulated result,
12615     * and is provided as an argument in the next call to the callback function.
12616     *
12617     * @param callbackfn A function that accepts one argument.
12618     * The reduceRight method calls the callbackfn function one time for each element in the array.
12619     *
12620     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12621     * The first call to the callbackfn function provides this value as an argument.
12622     *
12623     * @returns The value that results from running the callback function to completion over the entire typed array.
12624     */
12625    public reduceRight<U = BigInt>(
12626                callbackfn: (previuosValue: U) => U,
12627                initialValue: U): U {
12628        return this.reduceRight(
12629                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12630                        callbackfn(prevVal),
12631                initialValue)
12632    }
12633
12634    /**
12635     * Calls the specified callback function for all the elements in an array, in descending order.
12636     * The return value of the callback function is the accumulated result,
12637     * and is provided as an argument in the next call to the callback function.
12638     *
12639     * @param callbackfn A function that accepts no arguments.
12640     * The reduceRight method calls the callbackfn function one time for each element in the array.
12641     *
12642     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12643     * The first call to the callbackfn function provides this value as an argument.
12644     *
12645     * @returns The value that results from running the callback function to completion over the entire typed array.
12646     */
12647    public reduceRight<U = BigInt>(
12648                callbackfn: () => U,
12649                initialValue: U): U {
12650        return this.reduceRight(
12651                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12652                        callbackfn(),
12653                initialValue)
12654    }
12655
12656    /**
12657     * Calls the specified callback function for all the elements in an array, in descending order.
12658     * The return value of the callback function is the accumulated result,
12659     * and is provided as an argument in the next call to the callback function.
12660     *
12661     * @param callbackfn A function that accepts four arguments.
12662     * The reduceRight method calls the callbackfn function one time for each element in the array.
12663     * The first call to the callbackfn function provides array last element value as an argument
12664     *
12665     * @returns The value that results from running the callback function to completion over the entire typed array.
12666     * calling reduceRight method on an empty array without an initial value creates a TypeError
12667     */
12668    public reduceRight(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => BigInt): BigInt {
12669        if (this.lengthInt == 0) {
12670            throw new TypeError("Reduce of empty array with no initial value")
12671        }
12672
12673        let accumulatedValue: BigInt = new BigInt(this.$_get(this.lengthInt - 1))
12674        for (let i = this.lengthInt - 2; i >= 0; i--) {
12675            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12676        }
12677        return accumulatedValue
12678    }
12679
12680    /**
12681     * Calls the specified callback function for all the elements in an array, in descending order.
12682     * The return value of the callback function is the accumulated result,
12683     * and is provided as an argument in the next call to the callback function.
12684     *
12685     * @param callbackfn A function that accepts three arguments.
12686     * The reduceRight method calls the callbackfn function one time for each element in the array.
12687     * The first call to the callbackfn function provides array last element value as an argument
12688     *
12689     * @returns The value that results from running the callback function to completion over the entire typed array.
12690     * calling reduceRight method on an empty array without an initial value creates a TypeError
12691     */
12692    public reduceRight(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number) => BigInt): BigInt {
12693        return this.reduceRight(
12694                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12695                        callbackfn(prevValue, currValue, currIndex))
12696    }
12697
12698    /**
12699     * Calls the specified callback function for all the elements in an array, in descending order.
12700     * The return value of the callback function is the accumulated result,
12701     * and is provided as an argument in the next call to the callback function.
12702     *
12703     * @param callbackfn A function that accepts two arguments.
12704     * The reduceRight method calls the callbackfn function one time for each element in the array.
12705     * The first call to the callbackfn function provides array last element value as an argument
12706     *
12707     * @returns The value that results from running the callback function to completion over the entire typed array.
12708     * calling reduceRight method on an empty array without an initial value creates a TypeError
12709     */
12710    public reduceRight(callbackfn: (previousValue: BigInt, currentValue: BigInt) => BigInt): BigInt {
12711        return this.reduceRight(
12712                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12713                        callbackfn(prevValue, currValue))
12714    }
12715
12716    /**
12717     * Calls the specified callback function for all the elements in an array, in descending order.
12718     * The return value of the callback function is the accumulated result,
12719     * and is provided as an argument in the next call to the callback function.
12720     *
12721     * @param callbackfn A function that accepts one argument.
12722     * The reduceRight method calls the callbackfn function one time for each element in the array.
12723     * The first call to the callbackfn function provides array last element value as an argument
12724     *
12725     * @returns The value that results from running the callback function to completion over the entire typed array.
12726     * calling reduceRight method on an empty array without an initial value creates a TypeError
12727     */
12728    public reduceRight(callbackfn: (previousValue: BigInt) => BigInt): BigInt {
12729        return this.reduceRight(
12730                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12731                        callbackfn(prevValue))
12732    }
12733
12734    /**
12735     * Calls the specified callback function for all the elements in an array, in descending order.
12736     * The return value of the callback function is the accumulated result,
12737     * and is provided as an argument in the next call to the callback function.
12738     *
12739     * @param callbackfn A function that accepts no arguments.
12740     * The reduceRight method calls the callbackfn function one time for each element in the array.
12741     * The first call to the callbackfn function provides array last element value as an argument
12742     *
12743     * @returns The value that results from running the callback function to completion over the entire typed array.
12744     * calling reduceRight method on an empty array without an initial value creates a TypeError
12745     */
12746    public reduceRight(callbackfn: () => BigInt): BigInt {
12747        return this.reduceRight(
12748                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12749                        callbackfn())
12750    }
12751
12752    /**
12753     * Creates a new BigUint64Array using fn(arr[i]) over all elements of current BigUint64Array.
12754     *
12755     * @param fn a function to apply for each element of current BigUint64Array
12756     *
12757     * @returns a new BigUint64Array where for each element from current BigUint64Array fn was applied
12758     */
12759    public map(fn: (val: BigInt, index: number, array: BigUint64Array) => BigInt): BigUint64Array {
12760        let resBuf = new ArrayBuffer(this.lengthInt * BigUint64Array.BYTES_PER_ELEMENT as int)
12761        let res = new BigUint64Array(resBuf)
12762        for (let i = 0; i < this.lengthInt; i++) {
12763            const fnRes = fn(new BigInt(this.getUnsafe(i)), i as number, this)
12764            res.setUnsafeClamp(i, fnRes.getULong())
12765        }
12766        return res
12767    }
12768
12769    /**
12770     * Creates a new BigUint64Array using fn(arr[i], i) over all elements of current BigUint64Array
12771     *
12772     * @param fn a function to apply for each element of current BigUint64Array
12773     *
12774     * @returns a new BigUint64Array where for each element from current BigUint64Array fn was applied
12775     */
12776    public map(fn: (val: BigInt, index: number) => BigInt): BigUint64Array {
12777        let newF: (val: BigInt, index: number, array: BigUint64Array) => BigInt =
12778            (val: BigInt, index: number, array: BigUint64Array): BigInt => { return fn(val, index) }
12779        return this.map(newF)
12780    }
12781
12782    /**
12783     * Creates a new BigUint64Array using fn(arr[i]) over all elements of current BigUint64Array
12784     *
12785     * @param fn a function to apply for each element of current BigUint64Array
12786     *
12787     * @returns a new BigUint64Array where for each element from current BigUint64Array fn was applied
12788     */
12789    public map(fn: (val: BigInt) => BigInt): BigUint64Array {
12790        let newF: (val: BigInt, index: number, array: BigUint64Array) => BigInt =
12791            (val: BigInt, index: number, array: BigUint64Array): BigInt => { return fn(val) }
12792        return this.map(newF)
12793    }
12794
12795    /**
12796     * Creates a new BigUint64Array using fn() over all elements of current BigUint64Array
12797     *
12798     * @param fn a function to apply for each element of current BigUint64Array
12799     *
12800     * @returns a new BigUint64Array where for each element from current BigUint64Array fn was applied
12801     */
12802    public map(fn: () => BigInt): BigUint64Array {
12803        let newF: (val: BigInt, index: number, array: BigUint64Array) => BigInt =
12804            (val: BigInt, index: number, array: BigUint64Array): BigInt => { return fn() }
12805        return this.map(newF)
12806    }
12807
12808    /**
12809     * Determines whether the specified callback function returns true for all elements of an array.
12810     *
12811     * @param predicate A function that accepts three arguments.
12812     * The every method calls the predicate function for each element in the array until the predicate returns a false,
12813     * or until the end of the array.
12814     *
12815     * @returns true unless predicate function returns a false for an array element,
12816     * in which case false is immediately returned.
12817     */
12818    public every(predicate: (element: BigInt, index: number, array: BigUint64Array) => boolean): boolean {
12819        for (let i = 0; i < this.lengthInt; i++) {
12820            if (!predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
12821                return false
12822            }
12823        }
12824        return true
12825    }
12826
12827    /**
12828     * Determines whether the specified callback function returns true for all elements of an array.
12829     *
12830     * @param predicate A function that accepts two arguments.
12831     * The every method calls the predicate function for each element in the array until the predicate returns a false,
12832     * or until the end of the array.
12833     *
12834     * @returns true unless predicate function returns a false for an array element,
12835     * in which case false is immediately returned.
12836     */
12837    public every(predicate: (element: BigInt, index: number) => boolean): boolean {
12838        return this.every((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element, index))
12839    }
12840
12841    /**
12842     * Determines whether the specified callback function returns true for all elements of an array.
12843     *
12844     * @param predicate A function that accepts no arguments.
12845     * The every method calls the predicate function for each element in the array until the predicate returns a false,
12846     * or until the end of the array.
12847     *
12848     * @returns true unless predicate function returns a false for an array element,
12849     * in which case false is immediately returned.
12850     */
12851    public every(predicate: () => boolean): boolean {
12852        return this.every((element: BigInt, index: number, array: BigUint64Array): boolean => predicate())
12853    }
12854
12855    /**
12856     * Creates a new BigUint64Array from current BigUint64Array based on a condition fn.
12857     *
12858     * @param fn the condition to apply for each element
12859     *
12860     * @returns a new BigUint64Array with elements from current BigUint64Array that satisfy condition fn
12861     */
12862    public filter(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): BigUint64Array {
12863        let markers = new boolean[this.lengthInt]
12864        let resLen = 0
12865        for (let i = 0; i < this.lengthInt; i++) {
12866            markers[i] = fn(new BigInt(this.getUnsafe(i)), i as number, this)
12867            if (markers[i]) {
12868                ++resLen
12869            }
12870        }
12871        let res = new BigUint64Array(resLen)
12872        for (let i = 0, j = 0; i < this.lengthInt; i++) {
12873            if (markers[i]) {
12874                res.setUnsafe(j, this.getUnsafe(i))
12875                ++j
12876            }
12877        }
12878        return res
12879    }
12880
12881    /**
12882     * creates a new BigUint64Array from current BigUint64Array based on a condition fn
12883     *
12884     * @param fn the condition to apply for each element
12885     *
12886     * @returns a new BigUint64Array with elements from current BigUint64Array that satisfy condition fn
12887     */
12888    public filter(fn: (val: BigInt, index: number) => boolean): BigUint64Array {
12889        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
12890            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val, index) }
12891        return this.filter(newF)
12892    }
12893
12894    /**
12895     * Returns the value of the first element in the array where predicate is true, and undefined
12896     * otherwise
12897     *
12898     * @param predicate find calls predicate once for each element of the array, in ascending
12899     * order, until it finds one where predicate returns true. If such an element is found, find
12900     * immediately returns that element value. Otherwise, find returns undefined
12901     *
12902     * @returns BigInt | undefined
12903     */
12904    public find(predicate: (value: BigInt, index: number, array: BigUint64Array) => boolean): BigInt | undefined {
12905        for (let i = 0; i < this.lengthInt; i++) {
12906            let val = new BigInt(this.getUnsafe(i))
12907            if (predicate(val, i as number, this)) {
12908                return val
12909            }
12910        }
12911        return undefined
12912    }
12913
12914    /**
12915     * Returns the value of the first element in the array where predicate is true, and undefined
12916     * otherwise
12917     *
12918     * @param predicate find calls predicate once for each element of the array, in ascending
12919     * order, until it finds one where predicate returns true. If such an element is found, find
12920     * immediately returns that element value. Otherwise, find returns undefined
12921     *
12922     * @returns BigInt | undefined
12923     */
12924    public find(predicate: (value: BigInt, index: number) => boolean): BigInt | undefined {
12925        return this.find((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value, index))
12926    }
12927
12928    /**
12929     * Returns the index of the first element in the array where predicate is true, and -1
12930     * otherwise
12931     *
12932     * @param predicate find calls predicate once for each element of the array, in ascending
12933     * order, until it finds one where predicate returns true. If such an element is found,
12934     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
12935     *
12936     * @returns number
12937     */
12938    public findIndex(predicate: (value: BigInt, index: number, obj: BigUint64Array) => boolean): number {
12939        for (let i = 0; i < this.lengthInt; i++) {
12940            if (predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
12941                return i as number
12942            }
12943        }
12944        return -1 as number
12945    }
12946
12947    /**
12948     * Returns the index of the first element in the array where predicate is true, and -1
12949     * otherwise
12950     *
12951     * @param predicate find calls predicate once for each element of the array, in ascending
12952     * order, until it finds one where predicate returns true. If such an element is found,
12953     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
12954     *
12955     * @returns number
12956     */
12957    public findIndex(predicate: (value: BigInt, index: number) => boolean): number {
12958        return this.findIndex((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value, index))
12959    }
12960
12961    /**
12962     * Returns the index of the first element in the array where predicate is true, and -1
12963     * otherwise
12964     *
12965     * @param predicate find calls predicate once for each element of the array, in ascending
12966     * order, until it finds one where predicate returns true. If such an element is found,
12967     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
12968     *
12969     * @returns number
12970     */
12971    public findIndex(predicate: () => boolean): number {
12972        return this.findIndex((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate())
12973    }
12974
12975    /**
12976     * Finds the last element in the BigUint64Array that satisfies the condition
12977     *
12978     * @param fn condition
12979     *
12980     * @returns the last element that satisfies fn
12981     */
12982    public findLast(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): BigInt {
12983        for (let i = this.lengthInt - 1; i >= 0; i--) {
12984            let val = new BigInt(this.getUnsafe(i))
12985            if (fn(val, i as number, this)) {
12986                return val
12987            }
12988        }
12989        throw new Error("BigUint64Array.findLast: not implemented if an element was not found")
12990    }
12991
12992    /**
12993     * Finds the last element in the BigUint64Array that satisfies the condition
12994     *
12995     * @param fn condition
12996     *
12997     * @returns the last element that satisfies fn
12998     */
12999    public findLast(fn: (val: BigInt, index: number) => boolean): BigInt {
13000        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
13001            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val, index) }
13002        return this.findLast(newF)
13003    }
13004
13005    /**
13006     * Finds an index of the last element in the BigUint64Array that satisfies the condition
13007     *
13008     * @param fn condition
13009     *
13010     * @returns the index of the last element that satisfies fn, -1 otherwise
13011     */
13012    public findLastIndex(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): number {
13013        for (let i = this.lengthInt - 1; i >= 0; i--) {
13014            if (fn(new BigInt(this.getUnsafe(i)), i as number, this)) {
13015                return i as number
13016            }
13017        }
13018        return -1 as number
13019    }
13020
13021    /**
13022     * Finds an index of the last element in the BigUint64Array that satisfies the condition
13023     *
13024     * @param fn condition
13025     *
13026     * @returns the index of the last element that satisfies fn, -1 otherwise
13027     */
13028    public findLastIndex(fn: (val: BigInt, index: number) => boolean): number {
13029        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
13030            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val, index) }
13031        return this.findLastIndex(newF) as number
13032    }
13033
13034    /**
13035     * Performs the specified action for each element in BigUint64Array
13036     *
13037     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
13038     * callbackfn function one time for each element in the array.
13039     *
13040     * @returns None
13041     */
13042    public forEach(callbackfn: (value: BigInt, index: number, array: BigUint64Array) => void): void {
13043        for (let i = 0; i < this.lengthInt; i++) {
13044            callbackfn(new BigInt(this.getUnsafe(i)), i as number, this)
13045        }
13046    }
13047
13048    /**
13049     * Performs the specified action for each element in BigUint64Array
13050     *
13051     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
13052     * callbackfn function one time for each element in the array.
13053     *
13054     * @returns None
13055     */
13056    public forEach(callbackfn: (value: BigInt, index: number) => void): void {
13057        this.forEach((value: BigInt, index: number, array: BigUint64Array): void => callbackfn(value, index))
13058    }
13059
13060    /**
13061     * Performs the specified action for each element in BigUint64Array
13062     *
13063     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
13064     * callbackfn function one time for each element in the array.
13065     *
13066     * @returns None
13067     */
13068    public forEach(callbackfn: () => void): void {
13069        this.forEach((value: BigInt, index: number, array: BigUint64Array): void => callbackfn())
13070    }
13071
13072    /**
13073     * Returns the object itself
13074     *
13075     * @returns BigUint64Array
13076     */
13077    public valueOf(): BigUint64Array {
13078        return this
13079    }
13080
13081    /** Byte offset within the underlying Buffer */
13082    public get byteOffset(): number {
13083        return this.byteOffsetInt
13084    }
13085
13086    /** Number of bytes used */
13087    public get byteLength(): number {
13088        return this.byteLengthInt
13089    }
13090
13091    /** Number of long stored in BigUint64Array */
13092    public get length(): number {
13093        return this.lengthInt
13094    }
13095
13096    /** String \"BigUint64Array\" */
13097    public readonly name = "BigUint64Array"
13098
13099    private static clamp(val: long): long {
13100        return val
13101    }
13102
13103    internal setUnsafeClamp(insertPos: int, val: long): void {
13104        this.setUnsafe(insertPos, val)
13105    }
13106
13107    internal getUnsafe(index: int): long {
13108        index = index * BigUint64Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
13109        let res: long = 0
13110        if (IS_LITTLE_ENDIAN) {
13111            if (this.buffer instanceof ArrayBuffer) {
13112                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13113                    let el = (this.buffer as ArrayBuffer).at(index + i) as long
13114                    el &= 0xff
13115                    res |= el << (8 * i)
13116                }
13117            } else if (this.buffer instanceof SharedArrayBuffer) {
13118                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13119                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as long
13120                    el &= 0xff
13121                    res |= el << (8 * i)
13122                }
13123            } else {
13124                throw new Error("unexpected type of ArrayBufferLike")
13125            }
13126        } else {
13127            if (this.buffer instanceof ArrayBuffer) {
13128                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13129                    let el = (this.buffer as ArrayBuffer).at(index + 7 - i) as long
13130                    el &= 0xff
13131                    res |= el << (8 * i)
13132                }
13133            } else if (this.buffer instanceof SharedArrayBuffer) {
13134                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13135                    let el = (this.buffer as SharedArrayBuffer).at(index + 7 - i) as long
13136                    el &= 0xff
13137                    res |= el << (8 * i)
13138                }
13139            } else {
13140                throw new Error("unexpected type of ArrayBufferLike")
13141            }
13142        }
13143        return res
13144    }
13145
13146    internal setUnsafe(index: int, val: long): void {
13147        index = index * BigUint64Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
13148        let res: long = 0
13149        if (IS_LITTLE_ENDIAN) {
13150            if (this.buffer instanceof ArrayBuffer) {
13151                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13152                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
13153                    val = val >> 8
13154                }
13155            } else if (this.buffer instanceof SharedArrayBuffer) {
13156                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13157                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
13158                    val = val >> 8
13159                }
13160            } else {
13161                throw new Error("unexpected type of ArrayBufferLike")
13162            }
13163        } else {
13164            if (this.buffer instanceof ArrayBuffer) {
13165                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13166                    (this.buffer as ArrayBuffer).set(index + 7 - i, (val & 0xff) as byte)
13167                    val = val >> 8
13168                }
13169            } else if (this.buffer instanceof SharedArrayBuffer) {
13170                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
13171                    (this.buffer as SharedArrayBuffer).set(index + 7 - i, (val & 0xff) as byte)
13172                    val = val >> 8
13173                }
13174            } else {
13175                throw new Error("unexpected type of ArrayBufferLike")
13176            }
13177        }
13178    }
13179}
13180