• 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        // NOTE (ikorobkov): dealing with this overload is tricky
112        // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
113        let arr = Array.from<Number>(elements)
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    }
122
123    /**
124     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
125     *
126     * @param buf data initializer
127     *
128     * @param byteOffset byte offset from begin of the buf
129     *
130     * @param length size of elements of type int in newly created Uint8ClampedArray
131     */
132    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
133        let intByteOffset: int = 0
134        if (byteOffset != undefined) {
135            intByteOffset = byteOffset.intValue()
136            if (intByteOffset < 0) {
137                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
138            }
139        }
140        let intByteLength: int
141        if (buf instanceof ArrayBuffer) {
142            intByteLength = (buf as ArrayBuffer).getByteLength()
143        } else if (buf instanceof SharedArrayBuffer) {
144            intByteLength = (buf as SharedArrayBuffer).getByteLength()
145        } else {
146            throw new Error("unexpected type of ArrayBufferLike")
147        }
148        intByteLength = intByteLength - intByteOffset
149        if (intByteLength < 0) {
150            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
151        }
152
153        let intLength: int
154        if (length != undefined) {
155            intLength = length.intValue()
156            if (intLength > intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int) {
157                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
158            }
159        } else {
160            intLength = intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int
161        }
162        if (intLength < 0) {
163            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
164        }
165        if (intLength < intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int) {
166            intByteLength = intLength * Uint8ClampedArray.BYTES_PER_ELEMENT as int
167        }
168        this.byteLengthInt = intByteLength
169        this.byteOffsetInt = intByteOffset
170        this.lengthInt = intLength
171        this.buffer = buf
172    }
173
174    /**
175     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
176     *
177     * @param buf data initializer
178     *
179     * @param byteOffset byte offset from begin of the buf
180     */
181    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
182        this(buf, byteOffset, undefined)
183    }
184
185    /**
186     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
187     *
188     * @param buf data initializer
189     *
190     * @param byteOffset byte offset from begin of the buf
191     *
192     * @param length size of elements of type int in newly created Uint8ClampedArray
193     */
194    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
195        this(buf, new Number(byteOffset), new Number(length))
196    }
197
198    /**
199     * Creates an Uint8ClampedArray with respect to buf and byteOffset.
200     *
201     * @param buf data initializer
202     *
203     * @param byteOffset byte offset from begin of the buf
204     */
205    public constructor(buf: ArrayBufferLike, byteOffset: number) {
206        this(buf, new Number(byteOffset), undefined)
207    }
208
209    /**
210     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
211     *
212     * @param buf data initializer
213     *
214     * @param byteOffset byte offset from begin of the buf
215     *
216     * @param length size of elements of type int in newly created Uint8ClampedArray
217     */
218    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
219        this(buf, new Number(byteOffset), new Number(length))
220    }
221
222    /**
223     * Creates an Uint8ClampedArray with respect to buf and byteOffset.
224     *
225     * @param buf data initializer
226     *
227     * @param byteOffset byte offset from begin of the buf
228     */
229    public constructor(buf: ArrayBufferLike, byteOffset: int) {
230        this(buf, new Number(byteOffset), undefined)
231    }
232
233    /**
234     * Creates an Uint8ClampedArray with respect to buf.
235     *
236     * @param buf data initializer
237     */
238    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
239        if (buf instanceof ArrayBuffer) {
240            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
241            if (this.byteLengthInt % Uint8ClampedArray.BYTES_PER_ELEMENT as int != 0) {
242               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8ClampedArray.BYTES_PER_ELEMENT")
243            }
244            this.lengthInt = this.byteLengthInt / Uint8ClampedArray.BYTES_PER_ELEMENT as int
245            this.buffer = buf as ArrayBuffer
246            this.byteOffsetInt = 0
247        } else if (buf instanceof SharedArrayBuffer) {
248            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
249            if (this.byteLengthInt % Uint8ClampedArray.BYTES_PER_ELEMENT as int != 0) {
250               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8ClampedArray.BYTES_PER_ELEMENT")
251            }
252            this.lengthInt = this.byteLengthInt / Uint8ClampedArray.BYTES_PER_ELEMENT as int
253            this.buffer = buf as SharedArrayBuffer
254            this.byteOffsetInt = 0
255        } else if (buf instanceof ArrayLike) {
256            // NOTE (ikorobkov): dealing with this overload is tricky
257            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
258            let arr = Array.from<Number>((buf as ArrayLike<Number>))
259            this.byteLengthInt = arr.length as int * Uint8ClampedArray.BYTES_PER_ELEMENT as int
260            this.lengthInt = arr.length as int
261            this.buffer = new ArrayBuffer(this.byteLengthInt)
262            this.byteOffsetInt = 0
263            for (let i: int = 0; i < this.lengthInt; ++i) {
264                this.setUnsafe(i, Uint8ClampedArray.clamp(arr.$_get(i).intValue()))
265            }
266        } else {
267            throw new Error("unexpected type of buf")
268        }
269    }
270
271    /**
272     * Creates an Uint8ClampedArray with respect to length.
273     *
274     * @param length data initializer
275     */
276    public constructor(length: int) {
277        if (length < 0) {
278            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
279        }
280        this.lengthInt = length
281        this.byteLengthInt = length * Uint8ClampedArray.BYTES_PER_ELEMENT as int
282        this.byteOffsetInt = 0
283        this.buffer = new ArrayBuffer(this.byteLengthInt)
284    }
285
286    /**
287     * Creates an Uint8ClampedArray with respect to length.
288     *
289     * @param length data initializer
290     */
291    public constructor(length: number) {
292        this(length as int)
293    }
294
295    /**
296     * Creates a copy of Uint8ClampedArray.
297     *
298     * @param other data initializer
299     */
300    public constructor(other: Uint8ClampedArray) {
301        if (other.buffer instanceof ArrayBuffer) {
302            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
303        } else if (other.buffer instanceof SharedArrayBuffer) {
304            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
305        } else {
306            throw new Error("unexpected type of buffer")
307        }
308        this.byteLengthInt = other.byteLength as int
309        this.lengthInt = other.length as int
310        this.byteOffsetInt = 0
311    }
312
313    /**
314     * Creates an Uint8ClampedArray from number[]
315     */
316    public constructor(numbers: number[]) {
317        this(numbers.length)
318        for (let i: int = 0; i < this.lengthInt; ++i) {
319            this.setUnsafeClamp(i, numbers[i] as int)
320        }
321    }
322
323    /**
324     * Creates an Uint8ClampedArray from int[]
325     */
326    public constructor(numbers: int[]) {
327        this(numbers.length)
328        for (let i: int = 0; i < this.lengthInt; ++i) {
329            this.setUnsafeClamp(i, numbers[i] as int)
330        }
331    }
332
333    /**
334     * Iteratorable interface implementation
335     *
336     * @returns iterator over all elements
337     */
338    public override $_iterator(): IterableIterator<Number> {
339         return this.values()
340    }
341
342    /**
343     * Returns an instance of primitive type at passed index.
344     *
345     * @param index index to look at
346     *
347     * @returns a primitive at index
348     */
349    public at(index: number): Number | undefined {
350        return this.at(index as int)
351    }
352
353    /**
354     * Returns an instance of primitive type at passed index if index is correct.
355     *
356     * @param index index to look at
357     *
358     * @returns a primitive at index
359     */
360    public at(index: int): Number | undefined {
361        let k: int
362        if (index >= 0) {
363            k = index
364        } else {
365            k = this.lengthInt + index
366        }
367        if (k < 0 || k >= this.lengthInt) {
368            return undefined
369        }
370        return new Number(this.getUnsafe(k))
371    }
372
373    /**
374     * Returns an instance of number at passed index.
375     *
376     * @param index index to look at
377     *
378     * @returns a primitive at index
379     */
380    public override $_get(index: number): Number {
381        return this.$_get(index as int) as Number
382    }
383
384    /**
385     * Returns an instance of number at passed index.
386     *
387     * @param index index to look at
388     *
389     * @returns a primitive at index
390     */
391    public $_get(i: int): number {
392        if (i < 0 || i >= this.lengthInt) {
393            throw new RangeError("invalid offset")
394        }
395        return this.getUnsafe(i) as number
396    }
397
398    /**
399     * Assigns val as element on index.
400     *
401     * @param val value to set
402     *
403     * @param index index to change
404     */
405    public $_set(index: number, val: number): void {
406        this.$_set(index as int, val)
407    }
408
409    /**
410     * Assigns val as element on index.
411     *
412     * @param val value to set
413     *
414     * @param index index to change
415     */
416    public $_set(index: int, val: number): void {
417        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
418        if (index < 0 || index >= this.lengthInt) {
419            throw new RangeError("invalid index")
420        }
421        this.setUnsafeClamp(index, val as int)
422    }
423
424    /**
425     * Assigns val as element on index.
426     *
427     * @param val value to set
428     *
429     * @param index index to change
430     */
431    public $_set(index: number, val: int): void {
432        this.$_set(index as int, val)
433    }
434
435    /**
436     * Assigns val as element on index.
437     *
438     * @param val value to set
439     *
440     * @param index index to change
441     */
442    public $_set(index: int, val: int): void {
443        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
444        if (index < 0 || index >= this.lengthInt) {
445            throw new RangeError("invalid index")
446        }
447        this.setUnsafeClamp(index, val)
448    }
449
450    /**
451     * Makes a copy of internal elements to targetPos from startPos to endPos.
452     *
453     * @param target insert index to place copied elements
454     *
455     * @param start start index to begin copy from
456     *
457     * @param end last index to end copy from, excluded
458     *
459     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
460     */
461    public copyWithin(target: number, start: number, end?: number): Uint8ClampedArray {
462        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
463    }
464
465    /**
466     * Makes a copy of internal elements to targetPos from startPos to endPos.
467     *
468     * @param target insert index to place copied elements
469     *
470     * @param start start index to begin copy from
471     *
472     * @param end last index to end copy from, excluded
473     *
474     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
475     */
476    public copyWithin(target: int, start: number, end?: number): Uint8ClampedArray {
477        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
478    }
479
480    /**
481     * Makes a copy of internal elements to targetPos from startPos to endPos.
482     *
483     * @param target insert index to place copied elements
484     *
485     * @param start start index to begin copy from
486     *
487     * @param end last index to end copy from, excluded
488     *
489     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
490     */
491    public copyWithin(target: number, start: int, end?: number): Uint8ClampedArray {
492        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
493    }
494
495    /**
496     * Makes a copy of internal elements to targetPos from startPos to endPos.
497     *
498     * @param target insert index to place copied elements
499     *
500     * @param start start index to begin copy from
501     *
502     * @param end last index to end copy from, excluded
503     *
504     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
505     */
506    public copyWithin(target: int, start: int, end?: number): Uint8ClampedArray {
507        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
508    }
509
510    /**
511     * Makes a copy of internal elements to targetPos from startPos to endPos.
512     *
513     * @param insert insert index to place copied elements
514     *
515     * @param start start index to begin copy from
516     *
517     * @param end last index to end copy from, excluded
518     *
519     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
520     */
521    public copyWithin(target: int, start: int, end: int): Uint8ClampedArray {
522        let toPos = normalizeIndex(target, this.lengthInt)
523        let fromPos = normalizeIndex(start, this.lengthInt)
524        const finalPos = normalizeIndex(end, this.lengthInt)
525        let count: int = finalPos - fromPos
526        if (count > (this.lengthInt - toPos)) {
527            count = this.lengthInt - toPos
528        }
529        let direction: int = 1
530        if ((fromPos < toPos) && (toPos < fromPos + count)) {
531            fromPos = fromPos + count - 1
532            toPos   = toPos   + count - 1
533            direction = -1
534        }
535        while (count > 0) {
536            const value = this.getUnsafe(fromPos)
537            this.setUnsafe(toPos, value)
538            fromPos = fromPos + direction
539            toPos = toPos + direction
540            --count
541        }
542        return this
543    }
544
545    /**
546     * Makes a copy of internal elements to targetPos from begin to end of Uint8ClampedArray.
547     *
548     * @param target insert index to place copied elements
549     *
550     * See rules of parameters normalization:
551     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
552     */
553    public copyWithin(target: number): Uint8ClampedArray {
554        return this.copyWithin(target as int)
555    }
556
557    /**
558     * Makes a copy of internal elements to targetPos from begin to end of Uint8ClampedArray.
559     *
560     * @param insert insert index to place copied elements
561     *
562     * See rules of parameters normalization:
563     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
564     */
565    public copyWithin(target: int): Uint8ClampedArray {
566        return this.copyWithin(target, 0, this.lengthInt)
567    }
568
569    /**
570     * Returns an array of key, value pairs for every entry in the Uint8ClampedArray
571     *
572     * @returns key, value pairs for every entry in the array
573     */
574    public entries(): IterableIterator<[Number, Number]> {
575        return new Uint8ClampedArrayIteratorEntries(this)
576    }
577
578    /**
579     * Fills the Uint8ClampedArray with specified value
580     *
581     * @param value new value
582     *
583     * @returns modified Uint8ClampedArray
584     */
585    public fill(value: number, start?: number, end?: number): Uint8ClampedArray {
586        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
587        return this
588    }
589
590    /**
591     * Fills the Uint8ClampedArray with specified value
592     *
593     * @param value new value
594     *
595     * @returns modified Uint8ClampedArray
596     */
597    public fill(value: number, start: int, end?: number): Uint8ClampedArray {
598        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
599        return this
600    }
601
602    /**
603     * Fills the Uint8ClampedArray with specified value
604     *
605     * @param value new value
606     *
607     * @returns modified Uint8ClampedArray
608     */
609    public fill(value: number, start: int, end: number): Uint8ClampedArray {
610        this.fill(value as int, start as int, end as int)
611        return this
612    }
613
614    /**
615     * Fills the Uint8ClampedArray with specified value
616     *
617     * @param value new value
618     *
619     * @returns modified Uint8ClampedArray
620     */
621    public fill(value: number, start: number, end: int): Uint8ClampedArray {
622        this.fill(value as int, start as int, end as int)
623        return this
624    }
625
626    /**
627     * Fills the Uint8ClampedArray with specified value
628     *
629     * @param value new value
630     *
631     * @returns modified Uint8ClampedArray
632     */
633    public fill(value: number, start: int, end: int): Uint8ClampedArray {
634        this.fill(value as int, start as int, end as int)
635        return this
636    }
637
638    /**
639     * Fills the Uint8ClampedArray with specified value
640     *
641     * @param value new value
642     *
643     * @returns modified Uint8ClampedArray
644     */
645    public fill(value: int, start?: number, end?: number): Uint8ClampedArray {
646        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
647        return this
648    }
649
650    /**
651     * Fills the Uint8ClampedArray with specified value
652     *
653     * @param value new value
654     *
655     * @returns modified Uint8ClampedArray
656     */
657    public fill(value: int, start: int, end?: number): Uint8ClampedArray {
658        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
659        return this
660    }
661
662    /**
663     * Fills the Uint8ClampedArray with specified value
664     *
665     * @param value new value
666     *
667     * @returns modified Uint8ClampedArray
668     */
669    public fill(value: int, start: int, end: number): Uint8ClampedArray {
670        this.fill(value, start as int, end as int)
671        return this
672    }
673
674    /**
675     * Fills the Uint8ClampedArray with specified value
676     *
677     * @param value new value
678     *
679     * @returns modified Uint8ClampedArray
680     */
681    public fill(value: int, start: number, end: int): Uint8ClampedArray {
682        this.fill(value, start as int, end as int)
683        return this
684    }
685
686    /**
687     * Fills the Uint8ClampedArray with specified value
688     *
689     * @param value new value
690     *
691     * @returns modified Uint8ClampedArray
692     */
693    public fill(value: int, start: int, end: int): Uint8ClampedArray {
694        value = Uint8ClampedArray.clamp(value)
695        const k = normalizeIndex(start, this.lengthInt)
696        const finalPos = normalizeIndex(end, this.lengthInt)
697        for (let i: int = k; i < finalPos; ++i) {
698            this.setUnsafe(i, value)
699        }
700        return this
701    }
702
703    /**
704     * Assigns val as element on index.
705     *
706     * @param val value to set
707     *
708     * @param index index to change
709     */
710    public set(insertPos: number, val: number): void {
711        this.$_set(insertPos as int, val)
712    }
713
714    /**
715     * Assigns val as element on index.
716     *
717     * @param val value to set
718     *
719     * @param index index to change
720     */
721    public set(insertPos: int, val: number): void {
722        this.$_set(insertPos as int, val)
723    }
724
725    /**
726     * Assigns val as element on index.
727     *
728     * @param val value to set
729     *
730     * @param index index to change
731     */
732    public set(insertPos: number, val: int): void {
733        this.$_set(insertPos as int, val)
734    }
735
736    /**
737     * Assigns val as element on index.
738     *
739     * @param val value to set
740     *
741     * @param index index to change
742     */
743    public set(insertPos: int, val: int): void {
744        this.$_set(insertPos as int, val)
745    }
746
747    /**
748     * Copies all elements of arr to the current Uint8ClampedArray starting from insertPos.
749     *
750     * @param arr array to copy data from
751     *
752     * @param insertPos start index where data from arr will be inserted
753     *
754     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
755     */
756    public set(arr: number[], insertPos1: number): void {
757        const insertPos = insertPos1 as int
758        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
759            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8ClampedArray.length")
760        }
761        for (let i = 0; i < arr.length; i++) {
762            this.setUnsafeClamp(insertPos as int + i as int, arr[i] as int)
763        }
764    }
765
766    /**
767     * Copies all elements of arr to the current Uint8ClampedArray starting from insertPos.
768     *
769     * @param arr array to copy data from
770     *
771     * @param insertPos start index where data from arr will be inserted
772     *
773     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
774     */
775    public set(arr: int[], insertPos: int): void {
776        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
777            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8ClampedArray.length")
778        }
779        for (let i = 0; i < arr.length; i++) {
780            this.setUnsafeClamp(insertPos + i, arr[i])
781        }
782    }
783
784    /**
785     * Copies all elements of arr to the current Uint8ClampedArray.
786     *
787     * @param arr array to copy data from
788     */
789    public set(arr: number[]): void {
790        this.set(arr, 0)
791    }
792
793    /**
794     * Copies all elements of arr to the current Uint8ClampedArray.
795     *
796     * @param arr array to copy data from
797     */
798    public set(arr: int[]): void {
799        this.set(arr, 0)
800    }
801
802    /**
803     * Copies elements from an ArrayLike object to the Uint8ClampedArray.
804     *
805     * @param array An ArrayLike object containing the elements to copy.
806     *
807     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
808     */
809    public set(array: ArrayLike<number>, offset: number = 0): void {
810        const insertPos = offset as int
811        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
812            throw new RangeError("offset is out of bounds")
813        }
814        for (let i = 0; i < array.length; i++) {
815            this.setUnsafeClamp(insertPos as int + i as int, array[i] as int)
816        }
817    }
818
819    /**
820     * Returns a new array from a set of elements.
821     *
822     * @param items a set of elements to include in the new array object.
823     *
824     * @returns new Uint8ClampedArray
825     */
826    public static of(...items: number[]): Uint8ClampedArray {
827        let res = new Uint8ClampedArray(items.length as int)
828        for (let i: int = 0; i < items.length; i++) {
829            res.setUnsafeClamp(i, items[i] as int)
830        }
831        return res
832    }
833
834    /**
835     * Returns a new array from a set of elements.
836     *
837     * @param items a set of elements to include in the new array object.
838     *
839     * @returns new Uint8ClampedArray
840     */
841    public static of(...items: int[]): Uint8ClampedArray {
842        let res = new Uint8ClampedArray(items.length as int)
843        for (let i: int = 0; i < items.length; i++) {
844            res.setUnsafeClamp(i, items[i])
845        }
846        return res
847    }
848
849    /**
850     * Returns a new array from a set of elements.
851     *
852     * @param items a set of elements to include in the new array object.
853     *
854     * @returns new Uint8ClampedArray
855     */
856    public static of(...items: short[]): Uint8ClampedArray {
857        let res = new Uint8ClampedArray(items.length as int)
858        for (let i: int = 0; i < items.length; i++) {
859            res.setUnsafeClamp(i, items[i] as int)
860        }
861        return res
862    }
863
864    /**
865     * Returns a new array from a set of elements.
866     *
867     * @param items a set of elements to include in the new array object.
868     *
869     * @returns new Uint8ClampedArray
870     */
871    public static of(): Uint8ClampedArray {
872        return new Uint8ClampedArray(0 as int)
873    }
874
875    /**
876     * Creates an array from an array-like or iterable object.
877     *
878     * @param arrayLike An array-like or iterable object to convert to an array.
879     *
880     * @returns new Uint8ClampedArray
881     */
882    public static from(arr: ArrayLike<number>): Uint8ClampedArray {
883        return Uint8ClampedArray.from<number>(arr, (x: number, k: number): number => x)
884    }
885
886    /**
887     * Creates an array from an array-like or iterable object.
888     *
889     * @param arrayLike An array-like or iterable object to convert to an array.
890     *
891     * @param mapfn A mapping function to call on every element of the array.
892     *
893     * @returns new Uint8ClampedArray
894     */
895    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint8ClampedArray {
896        if (mapfn == undefined) {
897            mapfn = (v: number, k: number): number => { return v }
898        }
899        // Calc length of items inside arrayLike, save length into i variable
900        let i: long = 0
901        let iter = arrayLike.$_iterator()
902        while (true) {
903            const v = iter.next()
904            if (v.done) {
905                break
906            }
907            i++
908        }
909
910        let res = new Uint8ClampedArray(i as int)
911        i = 0
912        iter = arrayLike.$_iterator()
913        while (true) {
914            const v = iter.next()
915            if (v.done) {
916                return res
917            }
918            res.setUnsafeClamp(i as int, (mapfn)!(v.value as number, i as number) as int)
919            i++
920        }
921    }
922
923    /**
924     * Creates an array from an array-like or iterable object.
925     *
926     * @param arrayLike An array-like or iterable object to convert to an array.
927     *
928     * @param mapfn A mapping function to call on every element of the array.
929     *
930     * @returns new Uint8ClampedArray
931     */
932    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint8ClampedArray {
933        let res = new Uint8ClampedArray(arrayLike.length)
934        // 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
935        const idx = new int[1]
936        idx[0] = 0
937        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
938            res.setUnsafeClamp(idx[0], mapfn(x as T, idx[0] as number) as int)
939            idx[0] += 1
940        })
941        return res
942    }
943
944    /**
945     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
946     *
947     * @param searchElement The element to search for
948     *
949     * @param fromIndex The position in this array at which to begin searching for searchElement
950     *
951     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
952     */
953    public includes(searchElement: number, fromIndex?: number): boolean {
954        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
955    }
956
957    /**
958     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
959     *
960     * @param searchElement The element to search for
961     *
962     * @param fromIndex The position in this array at which to begin searching for searchElement
963     *
964     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
965     */
966    public includes(searchElement: int, fromIndex: int): boolean {
967        return this.indexOf(searchElement as int, fromIndex) != -1
968    }
969
970    /**
971     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
972     *
973     * @param searchElement The element to search for
974     *
975     * @param fromIndex The position in this array at which to begin searching for searchElement
976     *
977     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
978     */
979    public includes(searchElement: int): boolean {
980        return this.indexOf(searchElement as int, 0) != -1
981    }
982
983    /**
984     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
985     *
986     * @param searchElement The value to locate in the array.
987     *
988     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
989     *  search starts at index 0.
990     *
991     * @returns index of element if it presents, -1 otherwise
992     */
993    public indexOf(searchElement: number, fromIndex?: number): number {
994        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
995    }
996
997    /**
998     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
999     *
1000     * @param searchElement The value to locate in the array.
1001     *
1002     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1003     *  search starts at index 0.
1004     *
1005     * @returns index of element if it presents, -1 otherwise
1006     */
1007    public indexOf(searchElement: number, fromIndex: int): number {
1008        if (isNaN(searchElement)) {
1009            return -1
1010        }
1011        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
1012        for (let i = fromIndex; i < this.lengthInt; i++) {
1013            if (this.getUnsafe(i) as number == searchElement) {
1014                return i
1015            }
1016        }
1017        return -1
1018    }
1019
1020    /**
1021     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
1022     *
1023     * @param searchElement The value to locate in the array.
1024     *
1025     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1026     *  search starts at index 0.
1027     *
1028     * @returns index of element if it presents, -1 otherwise
1029     */
1030    public indexOf(searchElement: int, fromIndex: int): number {
1031        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
1032        for (let i = fromIndex; i < this.lengthInt; i++) {
1033            if (this.getUnsafe(i) == searchElement) {
1034                return i
1035            }
1036        }
1037        return -1
1038
1039    }
1040
1041    /**
1042     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
1043     *
1044     * @param searchElement The value to locate in the array.
1045     *
1046     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1047     *  search starts at index 0.
1048     *
1049     * @returns index of element if it presents, -1 otherwise
1050     */
1051    public indexOf(searchElement: int): number {
1052        return this.indexOf(searchElement, 0)
1053    }
1054
1055    /**
1056     * Adds all the elements of an array separated by the specified separator string
1057     *
1058     * @param separator A string used to separate one element of an array from the next in the
1059     * resulting String. If omitted, the array elements are separated with a comma
1060     *
1061     * @returns joined representation
1062     */
1063    public join(separator?: String): string {
1064        if (separator == undefined) {
1065            return this.join(",")
1066        }
1067        let res: StringBuilder = new StringBuilder("")
1068        for (let i = 0; i < this.lengthInt - 1; i++) {
1069            res.append(this.getUnsafe(i) as number)
1070            res.append(separator)
1071        }
1072        if (this.lengthInt > 0) {
1073            res.append(this.getUnsafe(this.lengthInt - 1) as number)
1074        }
1075        return res.toString()
1076    }
1077
1078    /**
1079     * Returns an list of keys in Uint8ClampedArray
1080     *
1081     * @returns iterator over keys
1082     */
1083    public keys(): IterableIterator<number> {
1084        return new Uint8ClampedArrayIteratorKeys(this)
1085    }
1086
1087    /**
1088     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1089     *
1090     * @param searchElement The value to locate in the array.
1091     *
1092     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1093     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1094     *
1095     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1096     */
1097    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
1098        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
1099    }
1100
1101    /**
1102     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1103     *
1104     * @param searchElement The value to locate in the array.
1105     *
1106     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1107     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1108     *
1109     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1110     */
1111    public lastIndexOf(searchElement: number): number {
1112        return this.lastIndexOf(searchElement, this.lengthInt - 1)
1113    }
1114
1115    /**
1116     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1117     *
1118     * @param searchElement The value to locate in the array.
1119     *
1120     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1121     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1122     *
1123     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1124     */
1125    public lastIndexOf(searchElement: number, fromIndex: int): number {
1126        if (isNaN(searchElement)) {
1127            return -1
1128        }
1129        if (this.lengthInt == 0) {
1130            return -1
1131        }
1132        let k: int = this.lengthInt + fromIndex
1133        if (fromIndex >= 0) {
1134            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
1135        }
1136        while (k >= 0) {
1137            if (this.getUnsafe(k) as number == searchElement) {
1138                return k
1139            }
1140            k--
1141        }
1142        return -1
1143    }
1144
1145    /**
1146     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1147     *
1148     * @param searchElement The value to locate in the array.
1149     *
1150     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1151     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1152     *
1153     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1154     */
1155    public lastIndexOf(searchElement: int, fromIndex: int): number {
1156        if (this.lengthInt == 0) {
1157            return -1
1158        }
1159        let k: int = this.lengthInt + fromIndex
1160        if (fromIndex >= 0) {
1161            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
1162        }
1163        while (k >= 0) {
1164            if (this.getUnsafe(k) == searchElement) {
1165                return k
1166            }
1167            k--
1168        }
1169        return -1
1170    }
1171
1172    /**
1173     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1174     *
1175     * @param searchElement The value to locate in the array.
1176     *
1177     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1178     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1179     *
1180     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1181     */
1182    public lastIndexOf(searchElement: int): number {
1183        return this.lastIndexOf(searchElement, this.lengthInt - 1)
1184    }
1185
1186   /**
1187    * Creates a new Uint8ClampedArray using initializer
1188    *
1189    * @param data initializer
1190    *
1191    * @returns a new Uint8ClampedArray from data
1192    */
1193    public of(...data: number[]): Uint8ClampedArray {
1194        throw new Error("Uint8ClampedArray.of: not implemented")
1195    }
1196
1197    /**
1198     * Creates a new Uint8ClampedArray using reversed data from the current one
1199     *
1200     * @returns a new Uint8ClampedArray using reversed data from the current one
1201     */
1202    public reverse(): Uint8ClampedArray {
1203        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
1204            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
1205            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
1206            this.setUnsafe(i, tmp)
1207        }
1208        return this
1209    }
1210
1211    /**
1212     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1213     *
1214     * @param begin start index to be taken into slice
1215     *
1216     * @param end last index to be taken into slice
1217     *
1218     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1219     *
1220     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1221     */
1222    public slice(begin?: number, end?: number): Uint8ClampedArray {
1223        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
1224    }
1225
1226    /**
1227     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1228     *
1229     * @param begin start index to be taken into slice
1230     *
1231     * @param end last index to be taken into slice
1232     *
1233     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1234     *
1235     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1236     */
1237    public slice(begin: number, end: number): Uint8ClampedArray {
1238        return this.slice(begin as int, end as int)
1239    }
1240
1241    /**
1242     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1243     *
1244     * @param begin start index to be taken into slice
1245     *
1246     * @param end last index to be taken into slice
1247     *
1248     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1249     *
1250     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1251     */
1252    public slice(begin: number, end: int): Uint8ClampedArray {
1253        return this.slice(begin as int, end as int)
1254    }
1255
1256    /**
1257     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1258     *
1259     * @param begin start index to be taken into slice
1260     *
1261     * @param end last index to be taken into slice
1262     *
1263     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1264     *
1265     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1266     */
1267    public slice(begin: int, end: number): Uint8ClampedArray {
1268        return this.slice(begin as int, end as int)
1269    }
1270
1271    /**
1272     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1273     *
1274     * @param begin start index to be taken into slice
1275     *
1276     * @param end last index to be taken into slice
1277     *
1278     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1279     *
1280     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1281     */
1282    public slice(begin: int, end: int): Uint8ClampedArray {
1283        const len: int = this.lengthInt
1284        const relStart = normalizeIndex(begin, len)
1285        const relEnd = normalizeIndex(end, len)
1286        let count = relEnd - relStart
1287        if (count < 0) {
1288            count = 0
1289        }
1290        if (this.buffer instanceof ArrayBuffer) {
1291            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, relEnd * Uint8ClampedArray.BYTES_PER_ELEMENT as int) as ArrayBuffer
1292            return new Uint8ClampedArray(buf)
1293        } else if (this.buffer instanceof SharedArrayBuffer) {
1294            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, relEnd * Uint8ClampedArray.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
1295            return new Uint8ClampedArray(buf)
1296        } else {
1297            throw new Error("unexpected type of buffer")
1298        }
1299    }
1300
1301    /**
1302     * Creates a slice of current Uint8ClampedArray using range [begin, this.lengthInt).
1303     *
1304     * @param begin start index to be taken into slice
1305     *
1306     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin, this.lengthInt)
1307     */
1308    public slice(begin: number): Uint8ClampedArray {
1309        return this.slice(begin as int)
1310    }
1311
1312    /**
1313     * Creates a slice of current Uint8ClampedArray using range [begin, this.lengthInt).
1314     *
1315     * @param begin start index to be taken into slice
1316     *
1317     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin, this.lengthInt)
1318     */
1319    public slice(begin: int): Uint8ClampedArray {
1320        return this.slice(begin, this.lengthInt)
1321    }
1322
1323    /**
1324     * Sorts in-place
1325     *
1326     * @param compareFn comparator —  used to determine the order of the elements.
1327     * compareFn returns a negative value if first argument is less than second argument,
1328     * zero if they're equal and a positive value otherwise.
1329     * If omitted, the elements are sorted in ascending order.
1330     *
1331     * @returns sorted Uint8ClampedArray
1332     */
1333    public sort(compareFn?: (a: number, b: number) => number): this {
1334        let arr: int[] = new int[this.lengthInt]
1335        for (let i = 0; i < this.lengthInt; ++i) {
1336            arr[i] = this.getUnsafe(i)
1337        }
1338        let cmp = (l: int, r: int): number => {
1339                return (l - r) as number
1340            }
1341        if (compareFn != undefined) {
1342            cmp = (l: int, r: int): number => {
1343                return compareFn!(l as number, r as number)
1344            }
1345        }
1346        sort(arr, cmp)
1347        for (let i = 0; i < this.lengthInt; ++i) {
1348            this.setUnsafe(i, arr[i])
1349        }
1350        return this
1351    }
1352
1353    /**
1354     * Sorts in-place
1355     *
1356     * @param compareFn comparator —  used to determine the order of the elements.
1357     * compareFn returns a negative value if first argument is less than second argument,
1358     * zero if they're equal and a positive value otherwise.
1359     *
1360     * @returns sorted Uint8ClampedArray
1361     */
1362    public sort(compareFn: (a: number) => number): this {
1363        let cmp = (a: number, b: number) => { return compareFn(a)}
1364        this.sort(cmp)
1365        return this
1366    }
1367
1368    /**
1369     * Sorts in-place
1370     *
1371     * @param fn compareFn —  used to determine the order of the elements.
1372     * compareFn returns a negative value if first argument is less than second argument,
1373     * zero if they're equal and a positive value otherwise.
1374     *
1375     * @returns sorted Uint8ClampedArray
1376     */
1377    public sort(compareFn: () => number): this {
1378        let cmp = (a: number, b: number) => { return compareFn()}
1379        this.sort(cmp)
1380        return this
1381    }
1382    /**
1383     * Creates a Uint8ClampedArray with the same underlying Buffer
1384     *
1385     * @param begin start index, inclusive
1386     *
1387     * @param end last index, exclusive
1388     *
1389     * @returns new Uint8ClampedArray with the same underlying Buffer
1390     */
1391    public subarray(begin?: number, end?: number): Uint8ClampedArray {
1392        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
1393    }
1394
1395    /**
1396     * Creates a Uint8ClampedArray with the same underlying Buffer
1397     *
1398     * @param begin start index, inclusive
1399     *
1400     * @param end last index, exclusive
1401     *
1402     * @returns new Uint8ClampedArray with the same underlying Buffer
1403     */
1404    public subarray(begin: number, end: number): Uint8ClampedArray {
1405        return this.subarray(begin as int, end as int)
1406    }
1407
1408    /**
1409     * Creates a Uint8ClampedArray with the same underlying Buffer
1410     *
1411     * @param begin start index, inclusive
1412     *
1413     * @param end last index, exclusive
1414     *
1415     * @returns new Uint8ClampedArray with the same underlying Buffer
1416     */
1417    public subarray(begin: number, end: int): Uint8ClampedArray {
1418        return this.subarray(begin as int, end as int)
1419    }
1420
1421    /**
1422     * Creates a Uint8ClampedArray with the same underlying Buffer
1423     *
1424     * @param begin start index, inclusive
1425     *
1426     * @param end last index, exclusive
1427     *
1428     * @returns new Uint8ClampedArray with the same underlying Buffer
1429     */
1430    public subarray(begin: int, end: number): Uint8ClampedArray {
1431        return this.subarray(begin as int, end as int)
1432    }
1433
1434    /**
1435     * Creates a Uint8ClampedArray with the same underlying Buffer
1436     *
1437     * @param begin start index, inclusive
1438     *
1439     * @param end last index, exclusive
1440     *
1441     * @returns new Uint8ClampedArray with the same underlying Buffer
1442     */
1443    public subarray(begin: int, end: int): Uint8ClampedArray {
1444        const len: int = this.lengthInt
1445        const relStart = normalizeIndex(begin, len)
1446        const relEnd = normalizeIndex(end, len)
1447        let count = relEnd - relStart
1448        if (count < 0) {
1449            count = 0
1450        }
1451        return new Uint8ClampedArray(this.buffer, relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, count)
1452    }
1453
1454    /**
1455     * Creates a Uint8ClampedArray with the same Buffer
1456     *
1457     * @param begin start index, inclusive
1458     *
1459     * @returns new Uint8ClampedArray with the same Buffer
1460     */
1461    public subarray(begin: number): Uint8ClampedArray {
1462        return this.subarray(begin as int, this.lengthInt)
1463    }
1464
1465    /**
1466     * Creates a Uint8ClampedArray with the same Buffer
1467     *
1468     * @param begin start index, inclusive
1469     *
1470     * @returns new Uint8ClampedArray with the same Buffer
1471     */
1472    public subarray(begin: int): Uint8ClampedArray {
1473        return this.subarray(begin, this.lengthInt)
1474    }
1475
1476    /**
1477     * Converts Uint8ClampedArray to a string with respect to locale
1478     *
1479     * @param locales
1480     *
1481     * @param options
1482     *
1483     * @returns string representation
1484     */
1485    public toLocaleString(locales: Object, options: Object): string {
1486        throw new Error("Uint8ClampedArray.toLocaleString: not implemented")
1487    }
1488
1489    /**
1490     * Converts Uint8ClampedArray to a string with respect to locale
1491     *
1492     * @param locales
1493     *
1494     * @returns string representation
1495     */
1496    public toLocaleString(locales: Object): string {
1497        return this.toLocaleString(new Object(), new Object())
1498    }
1499
1500    /**
1501     * Converts Uint8ClampedArray to a string with respect to locale
1502     *
1503     * @returns string representation
1504     */
1505    public toLocaleString(): string {
1506        let res: StringBuilder = new StringBuilder("")
1507        for (let i = 0; i < this.lengthInt - 1; ++i) {
1508            res.append((this.getUnsafe(i) as Number).toLocaleString())
1509            res.append(",")
1510        }
1511        if (this.lengthInt > 0) {
1512            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
1513        }
1514        return res.toString()
1515    }
1516
1517    /**
1518     * Creates a reversed copy
1519     *
1520     * @returns a reversed copy
1521     */
1522    public toReversed(): Uint8ClampedArray {
1523        return new Uint8ClampedArray(this).reverse()
1524    }
1525
1526    /**
1527     * Creates a sorted copy
1528     *
1529     * @returns a sorted copy
1530     */
1531    public toSorted(): Uint8ClampedArray {
1532        return new Uint8ClampedArray(this).sort()
1533    }
1534
1535    /**
1536     * Returns a string representation of the Uint8ClampedArray
1537     *
1538     * @returns a string representation of the Uint8ClampedArray
1539     */
1540    public override toString(): string {
1541        return this.join(",")
1542    }
1543
1544    /**
1545     * Returns array values iterator
1546     *
1547     * @returns an iterator
1548     */
1549    public values(): IterableIterator<Number> {
1550         return new Uint8ClampedArrayIterator(this)
1551    }
1552
1553    /**
1554     * Creates a copy with replaced value on index
1555     *
1556     * @param index
1557     *
1558     * @param value
1559     *
1560     * @returns an Uint8ClampedArray with replaced value on index
1561     */
1562    public with(index: number, value: number): Uint8ClampedArray {
1563        return this.with(index as int, value as int)
1564    }
1565
1566    /**
1567     * Creates a copy with replaced value on index
1568     *
1569     * @param index
1570     *
1571     * @param value
1572     *
1573     * @returns an Uint8ClampedArray with replaced value on index
1574     */
1575    /* public */ internal with(index: int, value: int): Uint8ClampedArray {
1576        let res = new Uint8ClampedArray(this)
1577        res.setUnsafeClamp(index, value)
1578        return res
1579    }
1580
1581    /// === with element lambda functions ===
1582
1583    /**
1584     * Determines whether the specified callback function returns true for all elements of an array.
1585     *
1586     * @param predicate A function that accepts one argument.
1587     * The every method calls the predicate function for each element in the array until the predicate returns a false,
1588     * or until the end of the array.
1589     *
1590     * @returns true unless predicate function returns a false for an array element,
1591     * in which case false is immediately returned.
1592     */
1593    public every(predicate: (element: number) => boolean): boolean {
1594        return this.every((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element))
1595    }
1596
1597    /**
1598     * creates a new Uint8ClampedArray from current Uint8ClampedArray based on a condition fn
1599     *
1600     * @param fn the condition to apply for each element
1601     *
1602     * @returns a new Uint8ClampedArray with elements from current Uint8ClampedArray that satisfy condition fn
1603     */
1604    public filter(fn: (val: number) => boolean): Uint8ClampedArray {
1605        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
1606            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val) }
1607        return this.filter(newF)
1608    }
1609
1610    /**
1611     * Returns the value of the first element in the array where predicate is true, and undefined
1612     * otherwise
1613     *
1614     * @param predicate find calls predicate once for each element of the array, in ascending
1615     * order, until it finds one where predicate returns true. If such an element is found, find
1616     * immediately returns that element value. Otherwise, find returns undefined
1617     *
1618     * @returns number | undefined
1619     */
1620    public find(predicate: () => boolean): number | undefined {
1621        return this.find((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate())
1622    }
1623
1624    /**
1625     * Returns the value of the first element in the array where predicate is true, and undefined
1626     * otherwise
1627     *
1628     * @param predicate find calls predicate once for each element of the array, in ascending
1629     * order, until it finds one where predicate returns true. If such an element is found, find
1630     * immediately returns that element value. Otherwise, find returns undefined
1631     *
1632     * @returns number | undefined
1633     */
1634    public find(predicate: (value: number) => boolean): number | undefined {
1635        return this.find((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value))
1636    }
1637
1638    /**
1639     * Returns the index of the first element in the array where predicate is true, and -1
1640     * otherwise
1641     *
1642     * @param predicate find calls predicate once for each element of the array, in ascending
1643     * order, until it finds one where predicate returns true. If such an element is found,
1644     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
1645     *
1646     * @returns number
1647     */
1648    public findIndex(predicate: (value: number) => boolean): number {
1649        return this.findIndex((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value)) as number
1650    }
1651
1652    /**
1653     * Finds the last element in the Uint8ClampedArray that satisfies the condition
1654     *
1655     * @param fn condition
1656     *
1657     * @returns the last element that satisfies fn
1658     */
1659    public findLast(fn: (val: number) => boolean): number {
1660        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
1661            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val) }
1662        return this.findLast(newF)
1663    }
1664
1665    /**
1666     * Finds an index of the last element in the Uint8ClampedArray that satisfies the condition
1667     *
1668     * @param fn condition
1669     *
1670     * @returns the index of the last element that satisfies fn, -1 otherwise
1671     */
1672    public findLastIndex(fn: (val: number) => boolean): number {
1673        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
1674            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val) }
1675        return this.findLastIndex(newF) as number
1676    }
1677
1678    /**
1679     * Performs the specified action for each element in Uint8ClampedArray
1680     *
1681     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
1682     * callbackfn function one time for each element in the array.
1683     *
1684     * @returns None
1685     */
1686    public forEach(callbackfn: (val: number) => void): void {
1687        this.forEach((value: number, index: number, array: Uint8ClampedArray): void => callbackfn(value))
1688    }
1689
1690    /**
1691     * Creates a new Uint8ClampedArray using fn(arr[i]) over all elements of current Uint8ClampedArray
1692     *
1693     * @param fn a function to apply for each element of current Uint8ClampedArray
1694     *
1695     * @returns a new Uint8ClampedArray where for each element from current Uint8ClampedArray fn was applied
1696     */
1697    public map(fn: (val: number) => number): Uint8ClampedArray {
1698        let newF: (val: number, index: number) => number =
1699            (val: number, index: number): number => { return fn(val) }
1700        return this.map(newF)
1701    }
1702
1703    /**
1704     * Determines whether the specified callback function returns true for any element of an array.
1705     *
1706     * @param predicate A function that accepts one argument.
1707     * The some method calls the predicate function for each element in the array
1708     * until the predicate returns a true or until the end of the array.
1709     *
1710     * @returns false unless predicate function returns true for an array element,
1711     * in which case true is immediately returned.
1712     */
1713    public some(predicate: (element: number) => boolean): boolean {
1714        return this.some((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element))
1715    }
1716
1717    /**
1718     * Determines whether the specified callback function returns true for any element of an array.
1719     *
1720     * @param predicate A function that accepts three arguments.
1721     * The some method calls the predicate function for each element in the array
1722     * until the predicate returns a true or until the end of the array.
1723     *
1724     * @returns false unless predicate function returns true for an array element,
1725     * in which case true is immediately returned.
1726     */
1727    public some(predicate: (element: number, index: number, array: Uint8ClampedArray) => boolean): boolean {
1728        for (let i = 0; i < this.lengthInt; i++) {
1729            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
1730                return true
1731            }
1732        }
1733        return false
1734    }
1735
1736    /**
1737     * Determines whether the specified callback function returns true for any element of an array.
1738     *
1739     * @param predicate A function that accepts two arguments.
1740     * The some method calls the predicate function for each element in the array
1741     * until the predicate returns a true or until the end of the array.
1742     *
1743     * @returns false unless predicate function returns true for an array element,
1744     * in which case true is immediately returned.
1745     */
1746    public some(predicate: (element: number, index: number) => boolean): boolean {
1747        return this.some((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element, index))
1748    }
1749
1750    /**
1751     * Determines whether the specified callback function returns true for any element of an array.
1752     *
1753     * @param predicate A function that accepts no arguments.
1754     * The some method calls the predicate function for each element in the array
1755     * until the predicate returns a true or until the end of the array.
1756     *
1757     * @returns false unless predicate function returns true for an array element,
1758     * in which case true is immediately returned.
1759     */
1760    public some(predicate: () => boolean): boolean {
1761        return this.some((element: number, index: number, array: Uint8ClampedArray): boolean => predicate())
1762    }
1763
1764    /**
1765     * Calls the specified callback function for all the elements in an array.
1766     * The return value of the callback function is the accumulated result,
1767     * and is provided as an argument in the next call to the callback function.
1768     *
1769     * @param callbackfn A function that accepts four arguments.
1770     * The reduce method calls the callbackfn function one time for each element in the array.
1771     *
1772     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1773     * The first call to the callbackfn function provides this value as an argument.
1774     *
1775     * @returns The value that results from running the callback function to completion over the entire typed array.
1776     */
1777    public reduce<U = number>(
1778                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U,
1779                initialValue: U): U {
1780        let accumulatedValue = initialValue
1781        for (let i = 0; i < this.lengthInt; i++) {
1782            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1783        }
1784        return accumulatedValue
1785    }
1786
1787    /**
1788     * Calls the specified callback function for all the elements in an array.
1789     * The return value of the callback function is the accumulated result,
1790     * and is provided as an argument in the next call to the callback function.
1791     *
1792     * @param callbackfn A function that accepts three arguments.
1793     * The reduce method calls the callbackfn function one time for each element in the array.
1794     *
1795     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1796     * The first call to the callbackfn function provides this value as an argument.
1797     *
1798     * @returns The value that results from running the callback function to completion over the entire typed array.
1799     */
1800    public reduce<U = number>(
1801                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
1802                initialValue: U): U {
1803        return this.reduce(
1804                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1805                        callbackfn(prevVal, currVal, currIndex),
1806                initialValue)
1807    }
1808
1809    /**
1810     * Calls the specified callback function for all the elements in an array.
1811     * The return value of the callback function is the accumulated result,
1812     * and is provided as an argument in the next call to the callback function.
1813     *
1814     * @param callbackfn A function that accepts two arguments.
1815     * The reduce method calls the callbackfn function one time for each element in the array.
1816     *
1817     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1818     * The first call to the callbackfn function provides this value as an argument.
1819     *
1820     * @returns The value that results from running the callback function to completion over the entire typed array.
1821     */
1822    public reduce<U = number>(
1823                callbackfn: (previousValue: U, currentValue: number) => U,
1824                initialValue: U): U {
1825        return this.reduce(
1826                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1827                        callbackfn(prevVal, currVal),
1828                initialValue)
1829    }
1830
1831    /**
1832     * Calls the specified callback function for all the elements in an array.
1833     * The return value of the callback function is the accumulated result,
1834     * and is provided as an argument in the next call to the callback function.
1835     *
1836     * @param callbackfn A function that accepts one argument
1837     * The reduce method calls the callbackfn function one time for each element in the array.
1838     *
1839     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1840     * The first call to the callbackfn function provides this value as an argument.
1841     *
1842     * @returns The value that results from running the callback function to completion over the entire typed array.
1843     */
1844    public reduce<U = number>(
1845                callbackfn: (previousValue: U) => U,
1846                initialValue: U): U {
1847        return this.reduce(
1848                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1849                        callbackfn(prevVal),
1850                initialValue)
1851    }
1852
1853    /**
1854     * Calls the specified callback function for all the elements in an array.
1855     * The return value of the callback function is the accumulated result,
1856     * and is provided as an argument in the next call to the callback function.
1857     *
1858     * @param callbackfn A function that accepts no arguments
1859     * The reduce method calls the callbackfn function one time for each element in the array.
1860     *
1861     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1862     * The first call to the callbackfn function provides this value as an argument.
1863     *
1864     * @returns The value that results from running the callback function to completion over the entire typed array.
1865     */
1866    public reduce<U = number>(
1867                callbackfn: () => U,
1868                initialValue: U): U {
1869        return this.reduce(
1870                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1871                        callbackfn(),
1872                initialValue)
1873    }
1874
1875    /**
1876     * Calls the specified callback function for all the elements in an array.
1877     * The return value of the callback function is the accumulated result,
1878     * and is provided as an argument in the next call to the callback function.
1879     *
1880     * @param callbackfn A function that accepts four arguments.
1881     * The reduce method calls the callbackfn function one time for each element in the array.
1882     * The first call to the callbackfn function provides array first element value as an argument
1883     *
1884     * @returns The value that results from running the callback function to completion over the entire typed array.
1885     * calling reduce method on an empty array without an initial value creates a TypeError
1886     */
1887    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number {
1888        if (this.lengthInt == 0) {
1889            throw new TypeError("Reduce of empty array with no initial value")
1890        }
1891
1892        let accumulatedValue = this.$_get(0) as number
1893        for (let i = 1; i < this.lengthInt; i++) {
1894            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1895        }
1896        return accumulatedValue
1897    }
1898
1899    /**
1900     * Calls the specified callback function for all the elements in an array.
1901     * The return value of the callback function is the accumulated result,
1902     * and is provided as an argument in the next call to the callback function.
1903     *
1904     * @param callbackfn A function that accepts three arguments.
1905     * The reduce method calls the callbackfn function one time for each element in the array.
1906     * The first call to the callbackfn function provides array first element value as an argument
1907     *
1908     * @returns The value that results from running the callback function to completion over the entire typed array.
1909     * calling reduce method on an empty array without an initial value creates a TypeError
1910     */
1911    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
1912        return this.reduce(
1913                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1914                        callbackfn(prevVal, currVal, currIndex))
1915    }
1916
1917    /**
1918     * Calls the specified callback function for all the elements in an array.
1919     * The return value of the callback function is the accumulated result,
1920     * and is provided as an argument in the next call to the callback function.
1921     *
1922     * @param callbackfn A function that accepts two arguments.
1923     * The reduce method calls the callbackfn function one time for each element in the array.
1924     * The first call to the callbackfn function provides array first element value as an argument
1925     *
1926     * @returns The value that results from running the callback function to completion over the entire typed array.
1927     * calling reduce method on an empty array without an initial value creates a TypeError
1928     */
1929    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
1930        return this.reduce(
1931                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1932                        callbackfn(prevVal, currVal))
1933    }
1934
1935    /**
1936     * Calls the specified callback function for all the elements in an array.
1937     * The return value of the callback function is the accumulated result,
1938     * and is provided as an argument in the next call to the callback function.
1939     *
1940     * @param callbackfn A function that accepts one argument.
1941     * The reduce method calls the callbackfn function one time for each element in the array.
1942     * The first call to the callbackfn function provides array first element value as an argument
1943     *
1944     * @returns The value that results from running the callback function to completion over the entire typed array.
1945     * calling reduce method on an empty array without an initial value creates a TypeError
1946     */
1947    public reduce(callbackfn: (previousValue: number) => number): number {
1948        return this.reduce(
1949                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1950                        callbackfn(prevVal))
1951    }
1952
1953    /**
1954     * Calls the specified callback function for all the elements in an array.
1955     * The return value of the callback function is the accumulated result,
1956     * and is provided as an argument in the next call to the callback function.
1957     *
1958     * @param callbackfn A function that accepts no arguments.
1959     * The reduce method calls the callbackfn function one time for each element in the array.
1960     * The first call to the callbackfn function provides array first element value as an argument
1961     *
1962     * @returns The value that results from running the callback function to completion over the entire typed array.
1963     * calling reduce method on an empty array without an initial value creates a TypeError
1964     */
1965    public reduce(callbackfn: () => number): number {
1966        return this.reduce(
1967                (prevVal: number, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
1968                        callbackfn())
1969    }
1970
1971    /**
1972     * Calls the specified callback function for all the elements in an array, in descending order.
1973     * The return value of the callback function is the accumulated result,
1974     * and is provided as an argument in the next call to the callback function.
1975     *
1976     * @param callbackfn A function that accepts four arguments.
1977     * The reduceRight method calls the callbackfn function one time for each element in the array.
1978     *
1979     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1980     * The first call to the callbackfn function provides this value as an argument.
1981     *
1982     * @returns The value that results from running the callback function to completion over the entire typed array.
1983     */
1984    public reduceRight<U = number>(
1985                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U,
1986                initialValue: U): U {
1987        let accumulatedValue = initialValue
1988        for (let i = this.lengthInt - 1; i >= 0; i--) {
1989            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1990        }
1991        return accumulatedValue
1992    }
1993
1994    /**
1995     * Calls the specified callback function for all the elements in an array, in descending order.
1996     * The return value of the callback function is the accumulated result,
1997     * and is provided as an argument in the next call to the callback function.
1998     *
1999     * @param callbackfn A function that accepts three arguments.
2000     * The reduceRight method calls the callbackfn function one time for each element in the array.
2001     *
2002     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2003     * The first call to the callbackfn function provides this value as an argument.
2004     *
2005     * @returns The value that results from running the callback function to completion over the entire typed array.
2006     */
2007    public reduceRight<U = number>(
2008                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
2009                initialValue: U): U {
2010        return this.reduceRight(
2011                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2012                        callbackfn(prevVal, currVal, currIndex),
2013                initialValue)
2014    }
2015
2016    /**
2017     * Calls the specified callback function for all the elements in an array, in descending order.
2018     * The return value of the callback function is the accumulated result,
2019     * and is provided as an argument in the next call to the callback function.
2020     *
2021     * @param callbackfn A function that accepts two arguments.
2022     * The reduceRight method calls the callbackfn function one time for each element in the array.
2023     *
2024     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2025     * The first call to the callbackfn function provides this value as an argument.
2026     *
2027     * @returns The value that results from running the callback function to completion over the entire typed array.
2028     */
2029    public reduceRight<U = number>(
2030                callbackfn: (previuosValue: U, currentValue: number) => U,
2031                initialValue: U): U {
2032        return this.reduceRight(
2033                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2034                        callbackfn(prevVal, currVal),
2035                initialValue)
2036    }
2037
2038    /**
2039     * Calls the specified callback function for all the elements in an array, in descending order.
2040     * The return value of the callback function is the accumulated result,
2041     * and is provided as an argument in the next call to the callback function.
2042     *
2043     * @param callbackfn A function that accepts one argument.
2044     * The reduceRight method calls the callbackfn function one time for each element in the array.
2045     *
2046     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2047     * The first call to the callbackfn function provides this value as an argument.
2048     *
2049     * @returns The value that results from running the callback function to completion over the entire typed array.
2050     */
2051    public reduceRight<U = number>(
2052                callbackfn: (previuosValue: U) => U,
2053                initialValue: U): U {
2054        return this.reduceRight(
2055                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2056                        callbackfn(prevVal),
2057                initialValue)
2058    }
2059
2060    /**
2061     * Calls the specified callback function for all the elements in an array, in descending order.
2062     * The return value of the callback function is the accumulated result,
2063     * and is provided as an argument in the next call to the callback function.
2064     *
2065     * @param callbackfn A function that accepts no arguments.
2066     * The reduceRight method calls the callbackfn function one time for each element in the array.
2067     *
2068     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
2069     * The first call to the callbackfn function provides this value as an argument.
2070     *
2071     * @returns The value that results from running the callback function to completion over the entire typed array.
2072     */
2073    public reduceRight<U = number>(
2074                callbackfn: () => U,
2075                initialValue: U): U {
2076        return this.reduceRight(
2077                (prevVal: U, currVal: number, currIndex: number, array: Uint8ClampedArray) =>
2078                        callbackfn(),
2079                initialValue)
2080    }
2081
2082    /**
2083     * Calls the specified callback function for all the elements in an array, in descending order.
2084     * The return value of the callback function is the accumulated result,
2085     * and is provided as an argument in the next call to the callback function.
2086     *
2087     * @param callbackfn A function that accepts four arguments.
2088     * The reduceRight method calls the callbackfn function one time for each element in the array.
2089     * The first call to the callbackfn function provides array last element value as an argument
2090     *
2091     * @returns The value that results from running the callback function to completion over the entire typed array.
2092     * calling reduceRight method on an empty array without an initial value creates a TypeError
2093     */
2094    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number {
2095        if (this.lengthInt == 0) {
2096            throw new TypeError("Reduce of empty array with no initial value")
2097        }
2098
2099        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
2100        for (let i = this.lengthInt - 2; i >= 0; i--) {
2101            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
2102        }
2103        return accumulatedValue
2104    }
2105
2106    /**
2107     * Calls the specified callback function for all the elements in an array, in descending order.
2108     * The return value of the callback function is the accumulated result,
2109     * and is provided as an argument in the next call to the callback function.
2110     *
2111     * @param callbackfn A function that accepts three arguments.
2112     * The reduceRight method calls the callbackfn function one time for each element in the array.
2113     * The first call to the callbackfn function provides array last element value as an argument
2114     *
2115     * @returns The value that results from running the callback function to completion over the entire typed array.
2116     * calling reduceRight method on an empty array without an initial value creates a TypeError
2117     */
2118    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
2119        return this.reduceRight(
2120                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2121                        callbackfn(prevValue, currValue, currIndex))
2122    }
2123
2124    /**
2125     * Calls the specified callback function for all the elements in an array, in descending order.
2126     * The return value of the callback function is the accumulated result,
2127     * and is provided as an argument in the next call to the callback function.
2128     *
2129     * @param callbackfn A function that accepts two arguments.
2130     * The reduceRight method calls the callbackfn function one time for each element in the array.
2131     * The first call to the callbackfn function provides array last element value as an argument
2132     *
2133     * @returns The value that results from running the callback function to completion over the entire typed array.
2134     * calling reduceRight method on an empty array without an initial value creates a TypeError
2135     */
2136    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
2137        return this.reduceRight(
2138                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2139                        callbackfn(prevValue, currValue))
2140    }
2141
2142    /**
2143     * Calls the specified callback function for all the elements in an array, in descending order.
2144     * The return value of the callback function is the accumulated result,
2145     * and is provided as an argument in the next call to the callback function.
2146     *
2147     * @param callbackfn A function that accepts one argument.
2148     * The reduceRight method calls the callbackfn function one time for each element in the array.
2149     * The first call to the callbackfn function provides array last element value as an argument
2150     *
2151     * @returns The value that results from running the callback function to completion over the entire typed array.
2152     * calling reduceRight method on an empty array without an initial value creates a TypeError
2153     */
2154    public reduceRight(callbackfn: (previousValue: number) => number): number {
2155        return this.reduceRight(
2156                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2157                        callbackfn(prevValue))
2158    }
2159
2160    /**
2161     * Calls the specified callback function for all the elements in an array, in descending order.
2162     * The return value of the callback function is the accumulated result,
2163     * and is provided as an argument in the next call to the callback function.
2164     *
2165     * @param callbackfn A function that accepts no arguments.
2166     * The reduceRight method calls the callbackfn function one time for each element in the array.
2167     * The first call to the callbackfn function provides array last element value as an argument
2168     *
2169     * @returns The value that results from running the callback function to completion over the entire typed array.
2170     * calling reduceRight method on an empty array without an initial value creates a TypeError
2171     */
2172    public reduceRight(callbackfn: () => number): number {
2173        return this.reduceRight(
2174                (prevValue: number, currValue: number, currIndex: number, array: Uint8ClampedArray) =>
2175                        callbackfn())
2176    }
2177
2178    /**
2179     * Creates a new Uint8ClampedArray using fn(arr[i]) over all elements of current Uint8ClampedArray.
2180     *
2181     * @param fn a function to apply for each element of current Uint8ClampedArray
2182     *
2183     * @returns a new Uint8ClampedArray where for each element from current Uint8ClampedArray fn was applied
2184     */
2185    public map(fn: (val: number, index: number) => number): Uint8ClampedArray {
2186        let resBuf = new ArrayBuffer(this.lengthInt * Uint8ClampedArray.BYTES_PER_ELEMENT as int)
2187        let res = new Uint8ClampedArray(resBuf)
2188        for (let i = 0; i < this.lengthInt; i++) {
2189            const fnRes = fn(this.getUnsafe(i) as number, i as number)
2190            res.setUnsafeClamp(i, fnRes as int)
2191        }
2192        return res
2193    }
2194
2195    /**
2196     * Determines whether the specified callback function returns true for all elements of an array.
2197     *
2198     * @param predicate A function that accepts three arguments.
2199     * The every method calls the predicate function for each element in the array until the predicate returns a false,
2200     * or until the end of the array.
2201     *
2202     * @returns true unless predicate function returns a false for an array element,
2203     * in which case false is immediately returned.
2204     */
2205    public every(predicate: (element: number, index: number, array: Uint8ClampedArray) => boolean): boolean {
2206        for (let i = 0; i < this.lengthInt; i++) {
2207            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
2208                return false
2209            }
2210        }
2211        return true
2212    }
2213
2214    /**
2215     * Determines whether the specified callback function returns true for all elements of an array.
2216     *
2217     * @param predicate A function that accepts two arguments.
2218     * The every method calls the predicate function for each element in the array until the predicate returns a false,
2219     * or until the end of the array.
2220     *
2221     * @returns true unless predicate function returns a false for an array element,
2222     * in which case false is immediately returned.
2223     */
2224    public every(predicate: (element: number, index: number) => boolean): boolean {
2225        return this.every((element: number, index: number, array: Uint8ClampedArray): boolean => predicate(element, index))
2226    }
2227
2228    /**
2229     * Determines whether the specified callback function returns true for all elements of an array.
2230     *
2231     * @param predicate A function that accepts no arguments.
2232     * The every method calls the predicate function for each element in the array until the predicate returns a false,
2233     * or until the end of the array.
2234     *
2235     * @returns true unless predicate function returns a false for an array element,
2236     * in which case false is immediately returned.
2237     */
2238    public every(predicate: () => boolean): boolean {
2239        return this.every((element: number, index: number, array: Uint8ClampedArray): boolean => predicate())
2240    }
2241
2242    /**
2243     * Creates a new Uint8ClampedArray from current Uint8ClampedArray based on a condition fn.
2244     *
2245     * @param fn the condition to apply for each element
2246     *
2247     * @returns a new Uint8ClampedArray with elements from current Uint8ClampedArray that satisfy condition fn
2248     */
2249    public filter(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): Uint8ClampedArray {
2250        let markers = new boolean[this.lengthInt]
2251        let resLen = 0
2252        for (let i = 0; i < this.lengthInt; i++) {
2253            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
2254            if (markers[i]) {
2255                ++resLen
2256            }
2257        }
2258        let res = new Uint8ClampedArray(resLen)
2259        for (let i = 0, j = 0; i < this.lengthInt; i++) {
2260            if (markers[i]) {
2261                res.setUnsafe(j, this.getUnsafe(i))
2262                ++j
2263            }
2264        }
2265        return res
2266    }
2267
2268    /**
2269     * creates a new Uint8ClampedArray from current Uint8ClampedArray based on a condition fn
2270     *
2271     * @param fn the condition to apply for each element
2272     *
2273     * @returns a new Uint8ClampedArray with elements from current Uint8ClampedArray that satisfy condition fn
2274     */
2275    public filter(fn: (val: number, index: number) => boolean): Uint8ClampedArray {
2276        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
2277            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val, index) }
2278        return this.filter(newF)
2279    }
2280
2281    /**
2282     * Returns the value of the first element in the array where predicate is true, and undefined
2283     * otherwise
2284     *
2285     * @param predicate find calls predicate once for each element of the array, in ascending
2286     * order, until it finds one where predicate returns true. If such an element is found, find
2287     * immediately returns that element value. Otherwise, find returns undefined
2288     *
2289     * @returns number | undefined
2290     */
2291    public find(predicate: (value: number, index: number, array: Uint8ClampedArray) => boolean): number | undefined {
2292        for (let i = 0; i < this.lengthInt; i++) {
2293            let val = this.getUnsafe(i) as number
2294            if (predicate(val, i as number, this)) {
2295                return val
2296            }
2297        }
2298        return undefined
2299    }
2300
2301    /**
2302     * Returns the value of the first element in the array where predicate is true, and undefined
2303     * otherwise
2304     *
2305     * @param predicate find calls predicate once for each element of the array, in ascending
2306     * order, until it finds one where predicate returns true. If such an element is found, find
2307     * immediately returns that element value. Otherwise, find returns undefined
2308     *
2309     * @returns number | undefined
2310     */
2311    public find(predicate: (value: number, index: number) => boolean): number | undefined {
2312        return this.find((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value, index))
2313    }
2314
2315    /**
2316     * Returns the index of the first element in the array where predicate is true, and -1
2317     * otherwise
2318     *
2319     * @param predicate find calls predicate once for each element of the array, in ascending
2320     * order, until it finds one where predicate returns true. If such an element is found,
2321     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
2322     *
2323     * @returns number
2324     */
2325    public findIndex(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean): number {
2326        for (let i = 0; i < this.lengthInt; i++) {
2327            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
2328                return i as number
2329            }
2330        }
2331        return -1 as number
2332    }
2333
2334    /**
2335     * Returns the index of the first element in the array where predicate is true, and -1
2336     * otherwise
2337     *
2338     * @param predicate find calls predicate once for each element of the array, in ascending
2339     * order, until it finds one where predicate returns true. If such an element is found,
2340     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
2341     *
2342     * @returns number
2343     */
2344    public findIndex(predicate: (value: number, index: number) => boolean): number {
2345        return this.findIndex((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate(value, index))
2346    }
2347
2348    /**
2349     * Returns the index of the first element in the array where predicate is true, and -1
2350     * otherwise
2351     *
2352     * @param predicate find calls predicate once for each element of the array, in ascending
2353     * order, until it finds one where predicate returns true. If such an element is found,
2354     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
2355     *
2356     * @returns number
2357     */
2358    public findIndex(predicate: () => boolean): number {
2359        return this.findIndex((value: number, index: number, obj: Uint8ClampedArray): boolean => predicate())
2360    }
2361
2362    /**
2363     * Finds the last element in the Uint8ClampedArray that satisfies the condition
2364     *
2365     * @param fn condition
2366     *
2367     * @returns the last element that satisfies fn
2368     */
2369    public findLast(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): number {
2370        for (let i = this.lengthInt - 1; i >= 0; i--) {
2371            let val = this.getUnsafe(i) as number
2372            if (fn(val, i as number, this)) {
2373                return val
2374            }
2375        }
2376        throw new Error("Uint8ClampedArray.findLast: not implemented if an element was not found")
2377    }
2378
2379    /**
2380     * Finds the last element in the Uint8ClampedArray that satisfies the condition
2381     *
2382     * @param fn condition
2383     *
2384     * @returns the last element that satisfies fn
2385     */
2386    public findLast(fn: (val: number, index: number) => boolean): number {
2387        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
2388            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val, index) }
2389        return this.findLast(newF)
2390    }
2391
2392    /**
2393     * Finds an index of the last element in the Uint8ClampedArray that satisfies the condition
2394     *
2395     * @param fn condition
2396     *
2397     * @returns the index of the last element that satisfies fn, -1 otherwise
2398     */
2399    public findLastIndex(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): number {
2400        for (let i = this.lengthInt - 1; i >= 0; i--) {
2401            if (fn(this.getUnsafe(i) as number, i as number, this)) {
2402                return i as number
2403            }
2404        }
2405        return -1 as number
2406    }
2407
2408    /**
2409     * Finds an index of the last element in the Uint8ClampedArray that satisfies the condition
2410     *
2411     * @param fn condition
2412     *
2413     * @returns the index of the last element that satisfies fn, -1 otherwise
2414     */
2415    public findLastIndex(fn: (val: number, index: number) => boolean): number {
2416        let newF: (val: number, index: number, array: Uint8ClampedArray) => boolean =
2417            (val: number, index: number, array: Uint8ClampedArray): boolean => { return fn(val, index) }
2418        return this.findLastIndex(newF) as number
2419    }
2420
2421    /**
2422     * Performs the specified action for each element in Uint8ClampedArray
2423     *
2424     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
2425     * callbackfn function one time for each element in the array.
2426     *
2427     * @returns None
2428     */
2429    public forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void): void {
2430        for (let i = 0; i < this.lengthInt; i++) {
2431            callbackfn(this.getUnsafe(i) as number, i as number, this)
2432        }
2433    }
2434
2435    /**
2436     * Performs the specified action for each element in Uint8ClampedArray
2437     *
2438     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
2439     * callbackfn function one time for each element in the array.
2440     *
2441     * @returns None
2442     */
2443    public forEach(callbackfn: (value: number, index: number) => void): void {
2444        this.forEach((value: number, index: number, array: Uint8ClampedArray): void => callbackfn(value, index))
2445    }
2446
2447    /**
2448     * Performs the specified action for each element in Uint8ClampedArray
2449     *
2450     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
2451     * callbackfn function one time for each element in the array.
2452     *
2453     * @returns None
2454     */
2455    public forEach(callbackfn: () => void): void {
2456        this.forEach((value: number, index: number, array: Uint8ClampedArray): void => callbackfn())
2457    }
2458
2459    /**
2460     * Returns the object itself
2461     *
2462     * @returns Uint8ClampedArray
2463     */
2464    public valueOf(): Uint8ClampedArray {
2465        return this
2466    }
2467
2468    /** Byte offset within the underlying Buffer */
2469    public get byteOffset(): number {
2470        return this.byteOffsetInt
2471    }
2472
2473    /** Number of bytes used */
2474    public get byteLength(): number {
2475        return this.byteLengthInt
2476    }
2477
2478    /** Number of int stored in Uint8ClampedArray */
2479    public get length(): number {
2480        return this.lengthInt
2481    }
2482
2483    /** String \"Uint8ClampedArray\" */
2484    public readonly name = "Uint8ClampedArray"
2485
2486    private static clamp(val: int): int {
2487        if (val > 255) {
2488            val = 255
2489        } else if (val < 0) {
2490            val = 0
2491        }
2492        return val
2493    }
2494
2495    internal setUnsafeClamp(insertPos: int, val: int): void {
2496        val = Uint8ClampedArray.clamp(val)
2497        this.setUnsafe(insertPos, val)
2498    }
2499
2500    internal getUnsafe(index: int): int {
2501        index = index * Uint8ClampedArray.BYTES_PER_ELEMENT as int + this.byteOffsetInt
2502        let res: int = 0
2503        if (IS_LITTLE_ENDIAN) {
2504            if (this.buffer instanceof ArrayBuffer) {
2505                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2506                    let el = (this.buffer as ArrayBuffer).at(index + i) as int
2507                    el &= 0xff
2508                    res |= el << (8 * i)
2509                }
2510            } else if (this.buffer instanceof SharedArrayBuffer) {
2511                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2512                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as int
2513                    el &= 0xff
2514                    res |= el << (8 * i)
2515                }
2516            } else {
2517                throw new Error("unexpected type of ArrayBufferLike")
2518            }
2519        } else {
2520            if (this.buffer instanceof ArrayBuffer) {
2521                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2522                    let el = (this.buffer as ArrayBuffer).at(index + 0 - i) as int
2523                    el &= 0xff
2524                    res |= el << (8 * i)
2525                }
2526            } else if (this.buffer instanceof SharedArrayBuffer) {
2527                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2528                    let el = (this.buffer as SharedArrayBuffer).at(index + 0 - i) as int
2529                    el &= 0xff
2530                    res |= el << (8 * i)
2531                }
2532            } else {
2533                throw new Error("unexpected type of ArrayBufferLike")
2534            }
2535        }
2536        return res
2537    }
2538
2539    internal setUnsafe(index: int, val: int): void {
2540        index = index * Uint8ClampedArray.BYTES_PER_ELEMENT as int + this.byteOffsetInt
2541        let res: int = 0
2542        if (IS_LITTLE_ENDIAN) {
2543            if (this.buffer instanceof ArrayBuffer) {
2544                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2545                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
2546                    val = val >> 8
2547                }
2548            } else if (this.buffer instanceof SharedArrayBuffer) {
2549                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2550                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
2551                    val = val >> 8
2552                }
2553            } else {
2554                throw new Error("unexpected type of ArrayBufferLike")
2555            }
2556        } else {
2557            if (this.buffer instanceof ArrayBuffer) {
2558                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2559                    (this.buffer as ArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
2560                    val = val >> 8
2561                }
2562            } else if (this.buffer instanceof SharedArrayBuffer) {
2563                for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
2564                    (this.buffer as SharedArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
2565                    val = val >> 8
2566                }
2567            } else {
2568                throw new Error("unexpected type of ArrayBufferLike")
2569            }
2570        }
2571    }
2572}
2573
2574
2575class Uint8ArrayIteratorKeys implements IterableIterator<number> {
2576    private length: int = 0
2577    private idx: int = 0
2578
2579    constructor(parent: Uint8Array) {
2580        this.length = parent.length as int
2581    }
2582
2583    public override $_iterator(): IterableIterator<Number> {
2584        return this
2585    }
2586
2587    override next(): IteratorResult<number> {
2588        if (this.idx < 0 || this.idx >= this.length) {
2589            return new IteratorResult<number>()
2590        }
2591        return new IteratorResult<number>(false, this.idx++ as number)
2592    }
2593}
2594
2595class Uint8ArrayIterator implements IterableIterator<Number> {
2596    private parent: Uint8Array
2597    private idx: int = 0
2598
2599    constructor(parent: Uint8Array) {
2600        this.parent = parent
2601    }
2602
2603    public override $_iterator(): IterableIterator<Number> {
2604        return this
2605    }
2606
2607    override next(): IteratorResult<Number> {
2608        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
2609            return new IteratorResult<Number>()
2610        }
2611        return new IteratorResult<Number>(false, new Number(this.parent.getUnsafe(this.idx++)))
2612    }
2613}
2614
2615class Uint8ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
2616    private parent: Uint8Array
2617    private idx: int = 0
2618
2619    constructor(parent: Uint8Array) {
2620        this.parent = parent
2621    }
2622
2623    public override $_iterator(): IterableIterator<[Number, Number]> {
2624        return this
2625    }
2626
2627    override next(): IteratorResult<[Number, Number]> {
2628        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
2629            return new IteratorResult<[Number, Number]>()
2630        }
2631        return new IteratorResult<[Number, Number]>(
2632            false,
2633            [new Number(this.idx), new Number(this.parent.getUnsafe(this.idx++))]
2634        )
2635    }
2636}
2637
2638/**
2639 * JS Uint8Array API-compatible class
2640 */
2641export class Uint8Array implements Iterable<Number>, ArrayLike<Number> {
2642    public static readonly BYTES_PER_ELEMENT: number = 1
2643
2644    /** Underlying Buffer */
2645    public readonly buffer: ArrayBufferLike
2646
2647    internal readonly byteOffsetInt: int
2648    internal readonly byteLengthInt: int
2649    internal readonly lengthInt: int
2650
2651    /**
2652     * Creates an empty Uint8Array.
2653     */
2654    public constructor() {
2655        this(0 as int)
2656    }
2657
2658    /**
2659     * Creates an Uint8Array with respect to data accessed via Iterable<Number> interface
2660     */
2661    public constructor(elements: Iterable<Number>) {
2662        // NOTE (ikorobkov): dealing with this overload is tricky
2663        // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
2664        let arr = Array.from<Number>(elements)
2665        this.byteLengthInt = arr.length as int * Uint8Array.BYTES_PER_ELEMENT as int
2666        this.lengthInt = arr.length as int
2667        this.buffer = new ArrayBuffer(this.byteLengthInt)
2668        this.byteOffsetInt = 0
2669        for (let i: int = 0; i < this.lengthInt; ++i) {
2670            this.setUnsafe(i, arr.$_get(i).intValue())
2671        }
2672    }
2673
2674    /**
2675     * Creates an Uint8Array with respect to data, byteOffset and length.
2676     *
2677     * @param buf data initializer
2678     *
2679     * @param byteOffset byte offset from begin of the buf
2680     *
2681     * @param length size of elements of type int in newly created Uint8Array
2682     */
2683    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
2684        let intByteOffset: int = 0
2685        if (byteOffset != undefined) {
2686            intByteOffset = byteOffset.intValue()
2687            if (intByteOffset < 0) {
2688                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
2689            }
2690        }
2691        let intByteLength: int
2692        if (buf instanceof ArrayBuffer) {
2693            intByteLength = (buf as ArrayBuffer).getByteLength()
2694        } else if (buf instanceof SharedArrayBuffer) {
2695            intByteLength = (buf as SharedArrayBuffer).getByteLength()
2696        } else {
2697            throw new Error("unexpected type of ArrayBufferLike")
2698        }
2699        intByteLength = intByteLength - intByteOffset
2700        if (intByteLength < 0) {
2701            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
2702        }
2703
2704        let intLength: int
2705        if (length != undefined) {
2706            intLength = length.intValue()
2707            if (intLength > intByteLength / Uint8Array.BYTES_PER_ELEMENT as int) {
2708                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
2709            }
2710        } else {
2711            intLength = intByteLength / Uint8Array.BYTES_PER_ELEMENT as int
2712        }
2713        if (intLength < 0) {
2714            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
2715        }
2716        if (intLength < intByteLength / Uint8Array.BYTES_PER_ELEMENT as int) {
2717            intByteLength = intLength * Uint8Array.BYTES_PER_ELEMENT as int
2718        }
2719        this.byteLengthInt = intByteLength
2720        this.byteOffsetInt = intByteOffset
2721        this.lengthInt = intLength
2722        this.buffer = buf
2723    }
2724
2725    /**
2726     * Creates an Uint8Array with respect to data, byteOffset and length.
2727     *
2728     * @param buf data initializer
2729     *
2730     * @param byteOffset byte offset from begin of the buf
2731     */
2732    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
2733        this(buf, byteOffset, undefined)
2734    }
2735
2736    /**
2737     * Creates an Uint8Array with respect to data, byteOffset and length.
2738     *
2739     * @param buf data initializer
2740     *
2741     * @param byteOffset byte offset from begin of the buf
2742     *
2743     * @param length size of elements of type int in newly created Uint8Array
2744     */
2745    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
2746        this(buf, new Number(byteOffset), new Number(length))
2747    }
2748
2749    /**
2750     * Creates an Uint8Array with respect to buf and byteOffset.
2751     *
2752     * @param buf data initializer
2753     *
2754     * @param byteOffset byte offset from begin of the buf
2755     */
2756    public constructor(buf: ArrayBufferLike, byteOffset: number) {
2757        this(buf, new Number(byteOffset), undefined)
2758    }
2759
2760    /**
2761     * Creates an Uint8Array with respect to data, byteOffset and length.
2762     *
2763     * @param buf data initializer
2764     *
2765     * @param byteOffset byte offset from begin of the buf
2766     *
2767     * @param length size of elements of type int in newly created Uint8Array
2768     */
2769    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
2770        this(buf, new Number(byteOffset), new Number(length))
2771    }
2772
2773    /**
2774     * Creates an Uint8Array with respect to buf and byteOffset.
2775     *
2776     * @param buf data initializer
2777     *
2778     * @param byteOffset byte offset from begin of the buf
2779     */
2780    public constructor(buf: ArrayBufferLike, byteOffset: int) {
2781        this(buf, new Number(byteOffset), undefined)
2782    }
2783
2784    /**
2785     * Creates an Uint8Array with respect to buf.
2786     *
2787     * @param buf data initializer
2788     */
2789    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
2790        if (buf instanceof ArrayBuffer) {
2791            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
2792            if (this.byteLengthInt % Uint8Array.BYTES_PER_ELEMENT as int != 0) {
2793               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8Array.BYTES_PER_ELEMENT")
2794            }
2795            this.lengthInt = this.byteLengthInt / Uint8Array.BYTES_PER_ELEMENT as int
2796            this.buffer = buf as ArrayBuffer
2797            this.byteOffsetInt = 0
2798        } else if (buf instanceof SharedArrayBuffer) {
2799            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
2800            if (this.byteLengthInt % Uint8Array.BYTES_PER_ELEMENT as int != 0) {
2801               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint8Array.BYTES_PER_ELEMENT")
2802            }
2803            this.lengthInt = this.byteLengthInt / Uint8Array.BYTES_PER_ELEMENT as int
2804            this.buffer = buf as SharedArrayBuffer
2805            this.byteOffsetInt = 0
2806        } else if (buf instanceof ArrayLike) {
2807            // NOTE (ikorobkov): dealing with this overload is tricky
2808            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
2809            let arr = Array.from<Number>((buf as ArrayLike<Number>))
2810            this.byteLengthInt = arr.length as int * Uint8Array.BYTES_PER_ELEMENT as int
2811            this.lengthInt = arr.length as int
2812            this.buffer = new ArrayBuffer(this.byteLengthInt)
2813            this.byteOffsetInt = 0
2814            for (let i: int = 0; i < this.lengthInt; ++i) {
2815                this.setUnsafe(i, arr.$_get(i).intValue())
2816            }
2817        } else {
2818            throw new Error("unexpected type of buf")
2819        }
2820    }
2821
2822    /**
2823     * Creates an Uint8Array with respect to length.
2824     *
2825     * @param length data initializer
2826     */
2827    public constructor(length: int) {
2828        if (length < 0) {
2829            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
2830        }
2831        this.lengthInt = length
2832        this.byteLengthInt = length * Uint8Array.BYTES_PER_ELEMENT as int
2833        this.byteOffsetInt = 0
2834        this.buffer = new ArrayBuffer(this.byteLengthInt)
2835    }
2836
2837    /**
2838     * Creates an Uint8Array with respect to length.
2839     *
2840     * @param length data initializer
2841     */
2842    public constructor(length: number) {
2843        this(length as int)
2844    }
2845
2846    /**
2847     * Creates a copy of Uint8Array.
2848     *
2849     * @param other data initializer
2850     */
2851    public constructor(other: Uint8Array) {
2852        if (other.buffer instanceof ArrayBuffer) {
2853            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
2854        } else if (other.buffer instanceof SharedArrayBuffer) {
2855            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
2856        } else {
2857            throw new Error("unexpected type of buffer")
2858        }
2859        this.byteLengthInt = other.byteLength as int
2860        this.lengthInt = other.length as int
2861        this.byteOffsetInt = 0
2862    }
2863
2864    /**
2865     * Creates an Uint8Array from number[]
2866     */
2867    public constructor(numbers: number[]) {
2868        this(numbers.length)
2869        for (let i: int = 0; i < this.lengthInt; ++i) {
2870            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
2871        }
2872    }
2873
2874    /**
2875     * Creates an Uint8Array from int[]
2876     */
2877    public constructor(numbers: int[]) {
2878        this(numbers.length)
2879        for (let i: int = 0; i < this.lengthInt; ++i) {
2880            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
2881        }
2882    }
2883
2884    internal zeroIfInfinity(val: number): number {
2885        if ((val == Infinity) || (val == -Infinity)) {
2886            return 0 as number
2887        }
2888        return val as number
2889    }
2890
2891    internal zeroIfInfinity(val: int): int {
2892        if ((val == Infinity) || (val == -Infinity)) {
2893            return 0 as int
2894        }
2895        return val
2896    }
2897
2898    /**
2899     * Iteratorable interface implementation
2900     *
2901     * @returns iterator over all elements
2902     */
2903    public override $_iterator(): IterableIterator<Number> {
2904         return this.values()
2905    }
2906
2907    /**
2908     * Returns an instance of primitive type at passed index.
2909     *
2910     * @param index index to look at
2911     *
2912     * @returns a primitive at index
2913     */
2914    public at(index: number): Number | undefined {
2915        return this.at(index as int)
2916    }
2917
2918    /**
2919     * Returns an instance of primitive type at passed index if index is correct.
2920     *
2921     * @param index index to look at
2922     *
2923     * @returns a primitive at index
2924     */
2925    public at(index: int): Number | undefined {
2926        let k: int
2927        if (index >= 0) {
2928            k = index
2929        } else {
2930            k = this.lengthInt + index
2931        }
2932        if (k < 0 || k >= this.lengthInt) {
2933            return undefined
2934        }
2935        return new Number(this.getUnsafe(k))
2936    }
2937
2938    /**
2939     * Returns an instance of number at passed index.
2940     *
2941     * @param index index to look at
2942     *
2943     * @returns a primitive at index
2944     */
2945    public override $_get(index: number): Number {
2946        return this.$_get(index as int) as Number
2947    }
2948
2949    /**
2950     * Returns an instance of number at passed index.
2951     *
2952     * @param index index to look at
2953     *
2954     * @returns a primitive at index
2955     */
2956    public $_get(i: int): number {
2957        if (i < 0 || i >= this.lengthInt) {
2958            throw new RangeError("invalid offset")
2959        }
2960        return this.getUnsafe(i) as number
2961    }
2962
2963    /**
2964     * Assigns val as element on index.
2965     *
2966     * @param val value to set
2967     *
2968     * @param index index to change
2969     */
2970    public $_set(index: number, val: number): void {
2971        this.$_set(index as int, val)
2972    }
2973
2974    /**
2975     * Assigns val as element on index.
2976     *
2977     * @param val value to set
2978     *
2979     * @param index index to change
2980     */
2981    public $_set(index: int, val: number): void {
2982        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
2983        if (index < 0 || index >= this.lengthInt) {
2984            throw new RangeError("invalid index")
2985        }
2986        let v = this.zeroIfInfinity(val)
2987        this.setUnsafeClamp(index, v as int)
2988    }
2989
2990    /**
2991     * Assigns val as element on index.
2992     *
2993     * @param val value to set
2994     *
2995     * @param index index to change
2996     */
2997    public $_set(index: number, val: int): void {
2998        this.$_set(index as int, val)
2999    }
3000
3001    /**
3002     * Assigns val as element on index.
3003     *
3004     * @param val value to set
3005     *
3006     * @param index index to change
3007     */
3008    public $_set(index: int, val: int): void {
3009        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
3010        if (index < 0 || index >= this.lengthInt) {
3011            throw new RangeError("invalid index")
3012        }
3013        let v = this.zeroIfInfinity(val)
3014        this.setUnsafeClamp(index, v)
3015    }
3016
3017    /**
3018     * Makes a copy of internal elements to targetPos from startPos to endPos.
3019     *
3020     * @param target insert index to place copied elements
3021     *
3022     * @param start start index to begin copy from
3023     *
3024     * @param end last index to end copy from, excluded
3025     *
3026     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3027     */
3028    public copyWithin(target: number, start: number, end?: number): Uint8Array {
3029        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3030    }
3031
3032    /**
3033     * Makes a copy of internal elements to targetPos from startPos to endPos.
3034     *
3035     * @param target insert index to place copied elements
3036     *
3037     * @param start start index to begin copy from
3038     *
3039     * @param end last index to end copy from, excluded
3040     *
3041     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3042     */
3043    public copyWithin(target: int, start: number, end?: number): Uint8Array {
3044        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3045    }
3046
3047    /**
3048     * Makes a copy of internal elements to targetPos from startPos to endPos.
3049     *
3050     * @param target insert index to place copied elements
3051     *
3052     * @param start start index to begin copy from
3053     *
3054     * @param end last index to end copy from, excluded
3055     *
3056     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3057     */
3058    public copyWithin(target: number, start: int, end?: number): Uint8Array {
3059        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3060    }
3061
3062    /**
3063     * Makes a copy of internal elements to targetPos from startPos to endPos.
3064     *
3065     * @param target insert index to place copied elements
3066     *
3067     * @param start start index to begin copy from
3068     *
3069     * @param end last index to end copy from, excluded
3070     *
3071     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3072     */
3073    public copyWithin(target: int, start: int, end?: number): Uint8Array {
3074        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
3075    }
3076
3077    /**
3078     * Makes a copy of internal elements to targetPos from startPos to endPos.
3079     *
3080     * @param insert insert index to place copied elements
3081     *
3082     * @param start start index to begin copy from
3083     *
3084     * @param end last index to end copy from, excluded
3085     *
3086     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
3087     */
3088    public copyWithin(target: int, start: int, end: int): Uint8Array {
3089        let toPos = normalizeIndex(target, this.lengthInt)
3090        let fromPos = normalizeIndex(start, this.lengthInt)
3091        const finalPos = normalizeIndex(end, this.lengthInt)
3092        let count: int = finalPos - fromPos
3093        if (count > (this.lengthInt - toPos)) {
3094            count = this.lengthInt - toPos
3095        }
3096        let direction: int = 1
3097        if ((fromPos < toPos) && (toPos < fromPos + count)) {
3098            fromPos = fromPos + count - 1
3099            toPos   = toPos   + count - 1
3100            direction = -1
3101        }
3102        while (count > 0) {
3103            const value = this.getUnsafe(fromPos)
3104            this.setUnsafe(toPos, value)
3105            fromPos = fromPos + direction
3106            toPos = toPos + direction
3107            --count
3108        }
3109        return this
3110    }
3111
3112    /**
3113     * Makes a copy of internal elements to targetPos from begin to end of Uint8Array.
3114     *
3115     * @param target insert index to place copied elements
3116     *
3117     * See rules of parameters normalization:
3118     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
3119     */
3120    public copyWithin(target: number): Uint8Array {
3121        return this.copyWithin(target as int)
3122    }
3123
3124    /**
3125     * Makes a copy of internal elements to targetPos from begin to end of Uint8Array.
3126     *
3127     * @param insert insert index to place copied elements
3128     *
3129     * See rules of parameters normalization:
3130     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
3131     */
3132    public copyWithin(target: int): Uint8Array {
3133        return this.copyWithin(target, 0, this.lengthInt)
3134    }
3135
3136    /**
3137     * Returns an array of key, value pairs for every entry in the Uint8Array
3138     *
3139     * @returns key, value pairs for every entry in the array
3140     */
3141    public entries(): IterableIterator<[Number, Number]> {
3142        return new Uint8ArrayIteratorEntries(this)
3143    }
3144
3145    /**
3146     * Fills the Uint8Array with specified value
3147     *
3148     * @param value new value
3149     *
3150     * @returns modified Uint8Array
3151     */
3152    public fill(value: number, start?: number, end?: number): Uint8Array {
3153        value = this.zeroIfInfinity(value)
3154        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
3155        return this
3156    }
3157
3158    /**
3159     * Fills the Uint8Array with specified value
3160     *
3161     * @param value new value
3162     *
3163     * @returns modified Uint8Array
3164     */
3165    public fill(value: number, start: int, end?: number): Uint8Array {
3166        value = this.zeroIfInfinity(value)
3167        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
3168        return this
3169    }
3170
3171    /**
3172     * Fills the Uint8Array with specified value
3173     *
3174     * @param value new value
3175     *
3176     * @returns modified Uint8Array
3177     */
3178    public fill(value: number, start: int, end: number): Uint8Array {
3179        value = this.zeroIfInfinity(value)
3180        this.fill(value as int, start as int, end as int)
3181        return this
3182    }
3183
3184    /**
3185     * Fills the Uint8Array with specified value
3186     *
3187     * @param value new value
3188     *
3189     * @returns modified Uint8Array
3190     */
3191    public fill(value: number, start: number, end: int): Uint8Array {
3192        value = this.zeroIfInfinity(value)
3193        this.fill(value as int, start as int, end as int)
3194        return this
3195    }
3196
3197    /**
3198     * Fills the Uint8Array with specified value
3199     *
3200     * @param value new value
3201     *
3202     * @returns modified Uint8Array
3203     */
3204    public fill(value: number, start: int, end: int): Uint8Array {
3205        value = this.zeroIfInfinity(value)
3206        this.fill(value as int, start as int, end as int)
3207        return this
3208    }
3209
3210    /**
3211     * Fills the Uint8Array with specified value
3212     *
3213     * @param value new value
3214     *
3215     * @returns modified Uint8Array
3216     */
3217    public fill(value: int, start?: number, end?: number): Uint8Array {
3218        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
3219        return this
3220    }
3221
3222    /**
3223     * Fills the Uint8Array with specified value
3224     *
3225     * @param value new value
3226     *
3227     * @returns modified Uint8Array
3228     */
3229    public fill(value: int, start: int, end?: number): Uint8Array {
3230        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
3231        return this
3232    }
3233
3234    /**
3235     * Fills the Uint8Array with specified value
3236     *
3237     * @param value new value
3238     *
3239     * @returns modified Uint8Array
3240     */
3241    public fill(value: int, start: int, end: number): Uint8Array {
3242        this.fill(value, start as int, end as int)
3243        return this
3244    }
3245
3246    /**
3247     * Fills the Uint8Array with specified value
3248     *
3249     * @param value new value
3250     *
3251     * @returns modified Uint8Array
3252     */
3253    public fill(value: int, start: number, end: int): Uint8Array {
3254        this.fill(value, start as int, end as int)
3255        return this
3256    }
3257
3258    /**
3259     * Fills the Uint8Array with specified value
3260     *
3261     * @param value new value
3262     *
3263     * @returns modified Uint8Array
3264     */
3265    public fill(value: int, start: int, end: int): Uint8Array {
3266        const k = normalizeIndex(start, this.lengthInt)
3267        const finalPos = normalizeIndex(end, this.lengthInt)
3268        for (let i: int = k; i < finalPos; ++i) {
3269            this.setUnsafe(i, value)
3270        }
3271        return this
3272    }
3273
3274    /**
3275     * Assigns val as element on index.
3276     *
3277     * @param val value to set
3278     *
3279     * @param index index to change
3280     */
3281    public set(insertPos: number, val: number): void {
3282        this.$_set(insertPos as int, val)
3283    }
3284
3285    /**
3286     * Assigns val as element on index.
3287     *
3288     * @param val value to set
3289     *
3290     * @param index index to change
3291     */
3292    public set(insertPos: int, val: number): void {
3293        this.$_set(insertPos as int, val)
3294    }
3295
3296    /**
3297     * Assigns val as element on index.
3298     *
3299     * @param val value to set
3300     *
3301     * @param index index to change
3302     */
3303    public set(insertPos: number, val: int): void {
3304        this.$_set(insertPos as int, val)
3305    }
3306
3307    /**
3308     * Assigns val as element on index.
3309     *
3310     * @param val value to set
3311     *
3312     * @param index index to change
3313     */
3314    public set(insertPos: int, val: int): void {
3315        this.$_set(insertPos as int, val)
3316    }
3317
3318    /**
3319     * Copies all elements of arr to the current Uint8Array starting from insertPos.
3320     *
3321     * @param arr array to copy data from
3322     *
3323     * @param insertPos start index where data from arr will be inserted
3324     *
3325     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
3326     */
3327    public set(arr: number[], insertPos1: number): void {
3328        const insertPos = insertPos1 as int
3329        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
3330            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8Array.length")
3331        }
3332        for (let i = 0; i < arr.length; i++) {
3333            let v = this.zeroIfInfinity(arr[i])
3334            this.setUnsafeClamp(insertPos as int + i as int, v as int)
3335        }
3336    }
3337
3338    /**
3339     * Copies all elements of arr to the current Uint8Array starting from insertPos.
3340     *
3341     * @param arr array to copy data from
3342     *
3343     * @param insertPos start index where data from arr will be inserted
3344     *
3345     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
3346     */
3347    public set(arr: int[], insertPos: int): void {
3348        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
3349            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint8Array.length")
3350        }
3351        for (let i = 0; i < arr.length; i++) {
3352            let v = this.zeroIfInfinity(arr[i])
3353            this.setUnsafeClamp(insertPos + i, v)
3354        }
3355    }
3356
3357    /**
3358     * Copies all elements of arr to the current Uint8Array.
3359     *
3360     * @param arr array to copy data from
3361     */
3362    public set(arr: number[]): void {
3363        this.set(arr, 0)
3364    }
3365
3366    /**
3367     * Copies all elements of arr to the current Uint8Array.
3368     *
3369     * @param arr array to copy data from
3370     */
3371    public set(arr: int[]): void {
3372        this.set(arr, 0)
3373    }
3374
3375    /**
3376     * Copies elements from an ArrayLike object to the Uint8Array.
3377     *
3378     * @param array An ArrayLike object containing the elements to copy.
3379     *
3380     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
3381     */
3382    public set(array: ArrayLike<number>, offset: number = 0): void {
3383        const insertPos = offset as int
3384        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
3385            throw new RangeError("offset is out of bounds")
3386        }
3387        for (let i = 0; i < array.length; i++) {
3388            let v = this.zeroIfInfinity(array[i])
3389            this.setUnsafeClamp(insertPos as int + i as int, v as int)
3390        }
3391    }
3392
3393    /**
3394     * Returns a new array from a set of elements.
3395     *
3396     * @param items a set of elements to include in the new array object.
3397     *
3398     * @returns new Uint8Array
3399     */
3400    public static of(...items: number[]): Uint8Array {
3401        let res = new Uint8Array(items.length as int)
3402        for (let i: int = 0; i < items.length; i++) {
3403            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as int)
3404        }
3405        return res
3406    }
3407
3408    /**
3409     * Returns a new array from a set of elements.
3410     *
3411     * @param items a set of elements to include in the new array object.
3412     *
3413     * @returns new Uint8Array
3414     */
3415    public static of(...items: int[]): Uint8Array {
3416        let res = new Uint8Array(items.length as int)
3417        for (let i: int = 0; i < items.length; i++) {
3418            res.setUnsafeClamp(i, items[i])
3419        }
3420        return res
3421    }
3422
3423    /**
3424     * Returns a new array from a set of elements.
3425     *
3426     * @param items a set of elements to include in the new array object.
3427     *
3428     * @returns new Uint8Array
3429     */
3430    public static of(...items: short[]): Uint8Array {
3431        let res = new Uint8Array(items.length as int)
3432        for (let i: int = 0; i < items.length; i++) {
3433            res.setUnsafeClamp(i, items[i] as int)
3434        }
3435        return res
3436    }
3437
3438    /**
3439     * Returns a new array from a set of elements.
3440     *
3441     * @param items a set of elements to include in the new array object.
3442     *
3443     * @returns new Uint8Array
3444     */
3445    public static of(): Uint8Array {
3446        return new Uint8Array(0 as int)
3447    }
3448
3449    /**
3450     * Creates an array from an array-like or iterable object.
3451     *
3452     * @param arrayLike An array-like or iterable object to convert to an array.
3453     *
3454     * @returns new Uint8Array
3455     */
3456    public static from(arr: ArrayLike<number>): Uint8Array {
3457        return Uint8Array.from<number>(arr, (x: number, k: number): number => x)
3458    }
3459
3460    /**
3461     * Creates an array from an array-like or iterable object.
3462     *
3463     * @param arrayLike An array-like or iterable object to convert to an array.
3464     *
3465     * @param mapfn A mapping function to call on every element of the array.
3466     *
3467     * @returns new Uint8Array
3468     */
3469    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint8Array {
3470        if (mapfn == undefined) {
3471            mapfn = (v: number, k: number): number => { return v }
3472        }
3473        // Calc length of items inside arrayLike, save length into i variable
3474        let i: long = 0
3475        let iter = arrayLike.$_iterator()
3476        while (true) {
3477            const v = iter.next()
3478            if (v.done) {
3479                break
3480            }
3481            i++
3482        }
3483
3484        let res = new Uint8Array(i as int)
3485        i = 0
3486        iter = arrayLike.$_iterator()
3487        while (true) {
3488            const v = iter.next()
3489            if (v.done) {
3490                return res
3491            }
3492            res.setUnsafeClamp(i as int, res.zeroIfInfinity((mapfn)!(v.value as number, i as number)) as int)
3493            i++
3494        }
3495    }
3496
3497    /**
3498     * Creates an array from an array-like or iterable object.
3499     *
3500     * @param arrayLike An array-like or iterable object to convert to an array.
3501     *
3502     * @param mapfn A mapping function to call on every element of the array.
3503     *
3504     * @returns new Uint8Array
3505     */
3506    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint8Array {
3507        let res = new Uint8Array(arrayLike.length)
3508        // 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
3509        const idx = new int[1]
3510        idx[0] = 0
3511        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
3512            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as int)
3513            idx[0] += 1
3514        })
3515        return res
3516    }
3517
3518    /**
3519     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
3520     *
3521     * @param searchElement The element to search for
3522     *
3523     * @param fromIndex The position in this array at which to begin searching for searchElement
3524     *
3525     * @returns true if searchElement is in Uint8Array, false otherwise
3526     */
3527    public includes(searchElement: number, fromIndex?: number): boolean {
3528        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
3529    }
3530
3531    /**
3532     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
3533     *
3534     * @param searchElement The element to search for
3535     *
3536     * @param fromIndex The position in this array at which to begin searching for searchElement
3537     *
3538     * @returns true if searchElement is in Uint8Array, false otherwise
3539     */
3540    public includes(searchElement: int, fromIndex: int): boolean {
3541        return this.indexOf(searchElement as int, fromIndex) != -1
3542    }
3543
3544    /**
3545     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
3546     *
3547     * @param searchElement The element to search for
3548     *
3549     * @param fromIndex The position in this array at which to begin searching for searchElement
3550     *
3551     * @returns true if searchElement is in Uint8Array, false otherwise
3552     */
3553    public includes(searchElement: int): boolean {
3554        return this.indexOf(searchElement as int, 0) != -1
3555    }
3556
3557    /**
3558     * Returns the index of the first occurrence of a value in Uint8Array.
3559     *
3560     * @param searchElement The value to locate in the array.
3561     *
3562     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3563     *  search starts at index 0.
3564     *
3565     * @returns index of element if it presents, -1 otherwise
3566     */
3567    public indexOf(searchElement: number, fromIndex?: number): number {
3568        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
3569    }
3570
3571    /**
3572     * Returns the index of the first occurrence of a value in Uint8Array.
3573     *
3574     * @param searchElement The value to locate in the array.
3575     *
3576     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3577     *  search starts at index 0.
3578     *
3579     * @returns index of element if it presents, -1 otherwise
3580     */
3581    public indexOf(searchElement: number, fromIndex: int): number {
3582        if (isNaN(searchElement)) {
3583            return -1
3584        }
3585        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
3586        for (let i = fromIndex; i < this.lengthInt; i++) {
3587            if (this.getUnsafe(i) as number == searchElement) {
3588                return i
3589            }
3590        }
3591        return -1
3592    }
3593
3594    /**
3595     * Returns the index of the first occurrence of a value in Uint8Array.
3596     *
3597     * @param searchElement The value to locate in the array.
3598     *
3599     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3600     *  search starts at index 0.
3601     *
3602     * @returns index of element if it presents, -1 otherwise
3603     */
3604    public indexOf(searchElement: int, fromIndex: int): number {
3605        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
3606        for (let i = fromIndex; i < this.lengthInt; i++) {
3607            if (this.getUnsafe(i) == searchElement) {
3608                return i
3609            }
3610        }
3611        return -1
3612
3613    }
3614
3615    /**
3616     * Returns the index of the first occurrence of a value in Uint8Array.
3617     *
3618     * @param searchElement The value to locate in the array.
3619     *
3620     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
3621     *  search starts at index 0.
3622     *
3623     * @returns index of element if it presents, -1 otherwise
3624     */
3625    public indexOf(searchElement: int): number {
3626        return this.indexOf(searchElement, 0)
3627    }
3628
3629    /**
3630     * Adds all the elements of an array separated by the specified separator string
3631     *
3632     * @param separator A string used to separate one element of an array from the next in the
3633     * resulting String. If omitted, the array elements are separated with a comma
3634     *
3635     * @returns joined representation
3636     */
3637    public join(separator?: String): string {
3638        if (separator == undefined) {
3639            return this.join(",")
3640        }
3641        let res: StringBuilder = new StringBuilder("")
3642        for (let i = 0; i < this.lengthInt - 1; i++) {
3643            res.append(this.getUnsafe(i) as number)
3644            res.append(separator)
3645        }
3646        if (this.lengthInt > 0) {
3647            res.append(this.getUnsafe(this.lengthInt - 1) as number)
3648        }
3649        return res.toString()
3650    }
3651
3652    /**
3653     * Returns an list of keys in Uint8Array
3654     *
3655     * @returns iterator over keys
3656     */
3657    public keys(): IterableIterator<number> {
3658        return new Uint8ArrayIteratorKeys(this)
3659    }
3660
3661    /**
3662     * Returns the index of the last occurrence of a value in Uint8Array.
3663     *
3664     * @param searchElement The value to locate in the array.
3665     *
3666     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3667     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3668     *
3669     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3670     */
3671    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
3672        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
3673    }
3674
3675    /**
3676     * Returns the index of the last occurrence of a value in Uint8Array.
3677     *
3678     * @param searchElement The value to locate in the array.
3679     *
3680     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3681     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3682     *
3683     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3684     */
3685    public lastIndexOf(searchElement: number): number {
3686        return this.lastIndexOf(searchElement, this.lengthInt - 1)
3687    }
3688
3689    /**
3690     * Returns the index of the last occurrence of a value in Uint8Array.
3691     *
3692     * @param searchElement The value to locate in the array.
3693     *
3694     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3695     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3696     *
3697     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3698     */
3699    public lastIndexOf(searchElement: number, fromIndex: int): number {
3700        if (isNaN(searchElement)) {
3701            return -1
3702        }
3703        if (this.lengthInt == 0) {
3704            return -1
3705        }
3706        let k: int = this.lengthInt + fromIndex
3707        if (fromIndex >= 0) {
3708            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
3709        }
3710        while (k >= 0) {
3711            if (this.getUnsafe(k) as number == searchElement) {
3712                return k
3713            }
3714            k--
3715        }
3716        return -1
3717    }
3718
3719    /**
3720     * Returns the index of the last occurrence of a value in Uint8Array.
3721     *
3722     * @param searchElement The value to locate in the array.
3723     *
3724     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3725     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3726     *
3727     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3728     */
3729    public lastIndexOf(searchElement: int, fromIndex: int): number {
3730        if (this.lengthInt == 0) {
3731            return -1
3732        }
3733        let k: int = this.lengthInt + fromIndex
3734        if (fromIndex >= 0) {
3735            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
3736        }
3737        while (k >= 0) {
3738            if (this.getUnsafe(k) == searchElement) {
3739                return k
3740            }
3741            k--
3742        }
3743        return -1
3744    }
3745
3746    /**
3747     * Returns the index of the last occurrence of a value in Uint8Array.
3748     *
3749     * @param searchElement The value to locate in the array.
3750     *
3751     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
3752     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
3753     *
3754     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
3755     */
3756    public lastIndexOf(searchElement: int): number {
3757        return this.lastIndexOf(searchElement, this.lengthInt - 1)
3758    }
3759
3760   /**
3761    * Creates a new Uint8Array using initializer
3762    *
3763    * @param data initializer
3764    *
3765    * @returns a new Uint8Array from data
3766    */
3767    public of(...data: number[]): Uint8Array {
3768        throw new Error("Uint8Array.of: not implemented")
3769    }
3770
3771    /**
3772     * Creates a new Uint8Array using reversed data from the current one
3773     *
3774     * @returns a new Uint8Array using reversed data from the current one
3775     */
3776    public reverse(): Uint8Array {
3777        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
3778            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
3779            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
3780            this.setUnsafe(i, tmp)
3781        }
3782        return this
3783    }
3784
3785    /**
3786     * Creates a slice of current Uint8Array using range [begin, end)
3787     *
3788     * @param begin start index to be taken into slice
3789     *
3790     * @param end last index to be taken into slice
3791     *
3792     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3793     *
3794     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3795     */
3796    public slice(begin?: number, end?: number): Uint8Array {
3797        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
3798    }
3799
3800    /**
3801     * Creates a slice of current Uint8Array using range [begin, end)
3802     *
3803     * @param begin start index to be taken into slice
3804     *
3805     * @param end last index to be taken into slice
3806     *
3807     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3808     *
3809     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3810     */
3811    public slice(begin: number, end: number): Uint8Array {
3812        return this.slice(begin as int, end as int)
3813    }
3814
3815    /**
3816     * Creates a slice of current Uint8Array using range [begin, end)
3817     *
3818     * @param begin start index to be taken into slice
3819     *
3820     * @param end last index to be taken into slice
3821     *
3822     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3823     *
3824     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3825     */
3826    public slice(begin: number, end: int): Uint8Array {
3827        return this.slice(begin as int, end as int)
3828    }
3829
3830    /**
3831     * Creates a slice of current Uint8Array using range [begin, end)
3832     *
3833     * @param begin start index to be taken into slice
3834     *
3835     * @param end last index to be taken into slice
3836     *
3837     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3838     *
3839     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3840     */
3841    public slice(begin: int, end: number): Uint8Array {
3842        return this.slice(begin as int, end as int)
3843    }
3844
3845    /**
3846     * Creates a slice of current Uint8Array using range [begin, end)
3847     *
3848     * @param begin start index to be taken into slice
3849     *
3850     * @param end last index to be taken into slice
3851     *
3852     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3853     *
3854     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3855     */
3856    public slice(begin: int, end: int): Uint8Array {
3857        const len: int = this.lengthInt
3858        const relStart = normalizeIndex(begin, len)
3859        const relEnd = normalizeIndex(end, len)
3860        let count = relEnd - relStart
3861        if (count < 0) {
3862            count = 0
3863        }
3864        if (this.buffer instanceof ArrayBuffer) {
3865            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint8Array.BYTES_PER_ELEMENT as int, relEnd * Uint8Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
3866            return new Uint8Array(buf)
3867        } else if (this.buffer instanceof SharedArrayBuffer) {
3868            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint8Array.BYTES_PER_ELEMENT as int, relEnd * Uint8Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
3869            return new Uint8Array(buf)
3870        } else {
3871            throw new Error("unexpected type of buffer")
3872        }
3873    }
3874
3875    /**
3876     * Creates a slice of current Uint8Array using range [begin, this.lengthInt).
3877     *
3878     * @param begin start index to be taken into slice
3879     *
3880     * @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)
3881     */
3882    public slice(begin: number): Uint8Array {
3883        return this.slice(begin as int)
3884    }
3885
3886    /**
3887     * Creates a slice of current Uint8Array using range [begin, this.lengthInt).
3888     *
3889     * @param begin start index to be taken into slice
3890     *
3891     * @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)
3892     */
3893    public slice(begin: int): Uint8Array {
3894        return this.slice(begin, this.lengthInt)
3895    }
3896
3897    /**
3898     * Sorts in-place
3899     *
3900     * @param compareFn comparator —  used to determine the order of the elements.
3901     * compareFn returns a negative value if first argument is less than second argument,
3902     * zero if they're equal and a positive value otherwise.
3903     * If omitted, the elements are sorted in ascending order.
3904     *
3905     * @returns sorted Uint8Array
3906     */
3907    public sort(compareFn?: (a: number, b: number) => number): this {
3908        let arr: int[] = new int[this.lengthInt]
3909        for (let i = 0; i < this.lengthInt; ++i) {
3910            arr[i] = this.getUnsafe(i)
3911        }
3912        let cmp = (l: int, r: int): number => {
3913                return (l - r) as number
3914            }
3915        if (compareFn != undefined) {
3916            cmp = (l: int, r: int): number => {
3917                return compareFn!(l as number, r as number)
3918            }
3919        }
3920        sort(arr, cmp)
3921        for (let i = 0; i < this.lengthInt; ++i) {
3922            this.setUnsafe(i, arr[i])
3923        }
3924        return this
3925    }
3926
3927    /**
3928     * Sorts in-place
3929     *
3930     * @param compareFn comparator —  used to determine the order of the elements.
3931     * compareFn returns a negative value if first argument is less than second argument,
3932     * zero if they're equal and a positive value otherwise.
3933     *
3934     * @returns sorted Uint8Array
3935     */
3936    public sort(compareFn: (a: number) => number): this {
3937        let cmp = (a: number, b: number) => { return compareFn(a)}
3938        this.sort(cmp)
3939        return this
3940    }
3941
3942    /**
3943     * Sorts in-place
3944     *
3945     * @param fn compareFn —  used to determine the order of the elements.
3946     * compareFn returns a negative value if first argument is less than second argument,
3947     * zero if they're equal and a positive value otherwise.
3948     *
3949     * @returns sorted Uint8Array
3950     */
3951    public sort(compareFn: () => number): this {
3952        let cmp = (a: number, b: number) => { return compareFn()}
3953        this.sort(cmp)
3954        return this
3955    }
3956    /**
3957     * Creates a Uint8Array with the same underlying Buffer
3958     *
3959     * @param begin start index, inclusive
3960     *
3961     * @param end last index, exclusive
3962     *
3963     * @returns new Uint8Array with the same underlying Buffer
3964     */
3965    public subarray(begin?: number, end?: number): Uint8Array {
3966        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
3967    }
3968
3969    /**
3970     * Creates a Uint8Array with the same underlying Buffer
3971     *
3972     * @param begin start index, inclusive
3973     *
3974     * @param end last index, exclusive
3975     *
3976     * @returns new Uint8Array with the same underlying Buffer
3977     */
3978    public subarray(begin: number, end: number): Uint8Array {
3979        return this.subarray(begin as int, end as int)
3980    }
3981
3982    /**
3983     * Creates a Uint8Array with the same underlying Buffer
3984     *
3985     * @param begin start index, inclusive
3986     *
3987     * @param end last index, exclusive
3988     *
3989     * @returns new Uint8Array with the same underlying Buffer
3990     */
3991    public subarray(begin: number, end: int): Uint8Array {
3992        return this.subarray(begin as int, end as int)
3993    }
3994
3995    /**
3996     * Creates a Uint8Array with the same underlying Buffer
3997     *
3998     * @param begin start index, inclusive
3999     *
4000     * @param end last index, exclusive
4001     *
4002     * @returns new Uint8Array with the same underlying Buffer
4003     */
4004    public subarray(begin: int, end: number): Uint8Array {
4005        return this.subarray(begin as int, end as int)
4006    }
4007
4008    /**
4009     * Creates a Uint8Array with the same underlying Buffer
4010     *
4011     * @param begin start index, inclusive
4012     *
4013     * @param end last index, exclusive
4014     *
4015     * @returns new Uint8Array with the same underlying Buffer
4016     */
4017    public subarray(begin: int, end: int): Uint8Array {
4018        const len: int = this.lengthInt
4019        const relStart = normalizeIndex(begin, len)
4020        const relEnd = normalizeIndex(end, len)
4021        let count = relEnd - relStart
4022        if (count < 0) {
4023            count = 0
4024        }
4025        return new Uint8Array(this.buffer, relStart * Uint8Array.BYTES_PER_ELEMENT as int, count)
4026    }
4027
4028    /**
4029     * Creates a Uint8Array with the same Buffer
4030     *
4031     * @param begin start index, inclusive
4032     *
4033     * @returns new Uint8Array with the same Buffer
4034     */
4035    public subarray(begin: number): Uint8Array {
4036        return this.subarray(begin as int, this.lengthInt)
4037    }
4038
4039    /**
4040     * Creates a Uint8Array with the same Buffer
4041     *
4042     * @param begin start index, inclusive
4043     *
4044     * @returns new Uint8Array with the same Buffer
4045     */
4046    public subarray(begin: int): Uint8Array {
4047        return this.subarray(begin, this.lengthInt)
4048    }
4049
4050    /**
4051     * Converts Uint8Array to a string with respect to locale
4052     *
4053     * @param locales
4054     *
4055     * @param options
4056     *
4057     * @returns string representation
4058     */
4059    public toLocaleString(locales: Object, options: Object): string {
4060        throw new Error("Uint8Array.toLocaleString: not implemented")
4061    }
4062
4063    /**
4064     * Converts Uint8Array to a string with respect to locale
4065     *
4066     * @param locales
4067     *
4068     * @returns string representation
4069     */
4070    public toLocaleString(locales: Object): string {
4071        return this.toLocaleString(new Object(), new Object())
4072    }
4073
4074    /**
4075     * Converts Uint8Array to a string with respect to locale
4076     *
4077     * @returns string representation
4078     */
4079    public toLocaleString(): string {
4080        let res: StringBuilder = new StringBuilder("")
4081        for (let i = 0; i < this.lengthInt - 1; ++i) {
4082            res.append((this.getUnsafe(i) as Number).toLocaleString())
4083            res.append(",")
4084        }
4085        if (this.lengthInt > 0) {
4086            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
4087        }
4088        return res.toString()
4089    }
4090
4091    /**
4092     * Creates a reversed copy
4093     *
4094     * @returns a reversed copy
4095     */
4096    public toReversed(): Uint8Array {
4097        return new Uint8Array(this).reverse()
4098    }
4099
4100    /**
4101     * Creates a sorted copy
4102     *
4103     * @returns a sorted copy
4104     */
4105    public toSorted(): Uint8Array {
4106        return new Uint8Array(this).sort()
4107    }
4108
4109    /**
4110     * Returns a string representation of the Uint8Array
4111     *
4112     * @returns a string representation of the Uint8Array
4113     */
4114    public override toString(): string {
4115        return this.join(",")
4116    }
4117
4118    /**
4119     * Returns array values iterator
4120     *
4121     * @returns an iterator
4122     */
4123    public values(): IterableIterator<Number> {
4124         return new Uint8ArrayIterator(this)
4125    }
4126
4127    /**
4128     * Creates a copy with replaced value on index
4129     *
4130     * @param index
4131     *
4132     * @param value
4133     *
4134     * @returns an Uint8Array with replaced value on index
4135     */
4136    public with(index: number, value: number): Uint8Array {
4137        return this.with(index as int, value as int)
4138    }
4139
4140    /**
4141     * Creates a copy with replaced value on index
4142     *
4143     * @param index
4144     *
4145     * @param value
4146     *
4147     * @returns an Uint8Array with replaced value on index
4148     */
4149    /* public */ internal with(index: int, value: int): Uint8Array {
4150        let res = new Uint8Array(this)
4151        res.setUnsafeClamp(index, value)
4152        return res
4153    }
4154
4155    /// === with element lambda functions ===
4156
4157    /**
4158     * Determines whether the specified callback function returns true for all elements of an array.
4159     *
4160     * @param predicate A function that accepts one argument.
4161     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4162     * or until the end of the array.
4163     *
4164     * @returns true unless predicate function returns a false for an array element,
4165     * in which case false is immediately returned.
4166     */
4167    public every(predicate: (element: number) => boolean): boolean {
4168        return this.every((element: number, index: number, array: Uint8Array): boolean => predicate(element))
4169    }
4170
4171    /**
4172     * creates a new Uint8Array from current Uint8Array based on a condition fn
4173     *
4174     * @param fn the condition to apply for each element
4175     *
4176     * @returns a new Uint8Array with elements from current Uint8Array that satisfy condition fn
4177     */
4178    public filter(fn: (val: number) => boolean): Uint8Array {
4179        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4180            (val: number, index: number, array: Uint8Array): boolean => { return fn(val) }
4181        return this.filter(newF)
4182    }
4183
4184    /**
4185     * Returns the value of the first element in the array where predicate is true, and undefined
4186     * otherwise
4187     *
4188     * @param predicate find calls predicate once for each element of the array, in ascending
4189     * order, until it finds one where predicate returns true. If such an element is found, find
4190     * immediately returns that element value. Otherwise, find returns undefined
4191     *
4192     * @returns number | undefined
4193     */
4194    public find(predicate: () => boolean): number | undefined {
4195        return this.find((value: number, index: number, obj: Uint8Array): boolean => predicate())
4196    }
4197
4198    /**
4199     * Returns the value of the first element in the array where predicate is true, and undefined
4200     * otherwise
4201     *
4202     * @param predicate find calls predicate once for each element of the array, in ascending
4203     * order, until it finds one where predicate returns true. If such an element is found, find
4204     * immediately returns that element value. Otherwise, find returns undefined
4205     *
4206     * @returns number | undefined
4207     */
4208    public find(predicate: (value: number) => boolean): number | undefined {
4209        return this.find((value: number, index: number, obj: Uint8Array): boolean => predicate(value))
4210    }
4211
4212    /**
4213     * Returns the index of the first element in the array where predicate is true, and -1
4214     * otherwise
4215     *
4216     * @param predicate find calls predicate once for each element of the array, in ascending
4217     * order, until it finds one where predicate returns true. If such an element is found,
4218     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
4219     *
4220     * @returns number
4221     */
4222    public findIndex(predicate: (value: number) => boolean): number {
4223        return this.findIndex((value: number, index: number, obj: Uint8Array): boolean => predicate(value)) as number
4224    }
4225
4226    /**
4227     * Finds the last element in the Uint8Array that satisfies the condition
4228     *
4229     * @param fn condition
4230     *
4231     * @returns the last element that satisfies fn
4232     */
4233    public findLast(fn: (val: number) => boolean): number {
4234        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4235            (val: number, index: number, array: Uint8Array): boolean => { return fn(val) }
4236        return this.findLast(newF)
4237    }
4238
4239    /**
4240     * Finds an index of the last element in the Uint8Array that satisfies the condition
4241     *
4242     * @param fn condition
4243     *
4244     * @returns the index of the last element that satisfies fn, -1 otherwise
4245     */
4246    public findLastIndex(fn: (val: number) => boolean): number {
4247        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4248            (val: number, index: number, array: Uint8Array): boolean => { return fn(val) }
4249        return this.findLastIndex(newF) as number
4250    }
4251
4252    /**
4253     * Performs the specified action for each element in Uint8Array
4254     *
4255     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
4256     * callbackfn function one time for each element in the array.
4257     *
4258     * @returns None
4259     */
4260    public forEach(callbackfn: (val: number) => void): void {
4261        this.forEach((value: number, index: number, array: Uint8Array): void => callbackfn(value))
4262    }
4263
4264    /**
4265     * Creates a new Uint8Array using fn(arr[i]) over all elements of current Uint8Array
4266     *
4267     * @param fn a function to apply for each element of current Uint8Array
4268     *
4269     * @returns a new Uint8Array where for each element from current Uint8Array fn was applied
4270     */
4271    public map(fn: (val: number) => number): Uint8Array {
4272        let newF: (val: number, index: number) => number =
4273            (val: number, index: number): number => { return fn(val) }
4274        return this.map(newF)
4275    }
4276
4277    /**
4278     * Determines whether the specified callback function returns true for any element of an array.
4279     *
4280     * @param predicate A function that accepts one argument.
4281     * The some method calls the predicate function for each element in the array
4282     * until the predicate returns a true or until the end of the array.
4283     *
4284     * @returns false unless predicate function returns true for an array element,
4285     * in which case true is immediately returned.
4286     */
4287    public some(predicate: (element: number) => boolean): boolean {
4288        return this.some((element: number, index: number, array: Uint8Array): boolean => predicate(element))
4289    }
4290
4291    /**
4292     * Determines whether the specified callback function returns true for any element of an array.
4293     *
4294     * @param predicate A function that accepts three arguments.
4295     * The some method calls the predicate function for each element in the array
4296     * until the predicate returns a true or until the end of the array.
4297     *
4298     * @returns false unless predicate function returns true for an array element,
4299     * in which case true is immediately returned.
4300     */
4301    public some(predicate: (element: number, index: number, array: Uint8Array) => boolean): boolean {
4302        for (let i = 0; i < this.lengthInt; i++) {
4303            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
4304                return true
4305            }
4306        }
4307        return false
4308    }
4309
4310    /**
4311     * Determines whether the specified callback function returns true for any element of an array.
4312     *
4313     * @param predicate A function that accepts two arguments.
4314     * The some method calls the predicate function for each element in the array
4315     * until the predicate returns a true or until the end of the array.
4316     *
4317     * @returns false unless predicate function returns true for an array element,
4318     * in which case true is immediately returned.
4319     */
4320    public some(predicate: (element: number, index: number) => boolean): boolean {
4321        return this.some((element: number, index: number, array: Uint8Array): boolean => predicate(element, index))
4322    }
4323
4324    /**
4325     * Determines whether the specified callback function returns true for any element of an array.
4326     *
4327     * @param predicate A function that accepts no arguments.
4328     * The some method calls the predicate function for each element in the array
4329     * until the predicate returns a true or until the end of the array.
4330     *
4331     * @returns false unless predicate function returns true for an array element,
4332     * in which case true is immediately returned.
4333     */
4334    public some(predicate: () => boolean): boolean {
4335        return this.some((element: number, index: number, array: Uint8Array): boolean => predicate())
4336    }
4337
4338    /**
4339     * Calls the specified callback function for all the elements in an array.
4340     * The return value of the callback function is the accumulated result,
4341     * and is provided as an argument in the next call to the callback function.
4342     *
4343     * @param callbackfn A function that accepts four arguments.
4344     * The reduce method calls the callbackfn function one time for each element in the array.
4345     *
4346     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4347     * The first call to the callbackfn function provides this value as an argument.
4348     *
4349     * @returns The value that results from running the callback function to completion over the entire typed array.
4350     */
4351    public reduce<U = number>(
4352                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U,
4353                initialValue: U): U {
4354        let accumulatedValue = initialValue
4355        for (let i = 0; i < this.lengthInt; i++) {
4356            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4357        }
4358        return accumulatedValue
4359    }
4360
4361    /**
4362     * Calls the specified callback function for all the elements in an array.
4363     * The return value of the callback function is the accumulated result,
4364     * and is provided as an argument in the next call to the callback function.
4365     *
4366     * @param callbackfn A function that accepts three arguments.
4367     * The reduce method calls the callbackfn function one time for each element in the array.
4368     *
4369     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4370     * The first call to the callbackfn function provides this value as an argument.
4371     *
4372     * @returns The value that results from running the callback function to completion over the entire typed array.
4373     */
4374    public reduce<U = number>(
4375                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
4376                initialValue: U): U {
4377        return this.reduce(
4378                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4379                        callbackfn(prevVal, currVal, currIndex),
4380                initialValue)
4381    }
4382
4383    /**
4384     * Calls the specified callback function for all the elements in an array.
4385     * The return value of the callback function is the accumulated result,
4386     * and is provided as an argument in the next call to the callback function.
4387     *
4388     * @param callbackfn A function that accepts two arguments.
4389     * The reduce method calls the callbackfn function one time for each element in the array.
4390     *
4391     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4392     * The first call to the callbackfn function provides this value as an argument.
4393     *
4394     * @returns The value that results from running the callback function to completion over the entire typed array.
4395     */
4396    public reduce<U = number>(
4397                callbackfn: (previousValue: U, currentValue: number) => U,
4398                initialValue: U): U {
4399        return this.reduce(
4400                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4401                        callbackfn(prevVal, currVal),
4402                initialValue)
4403    }
4404
4405    /**
4406     * Calls the specified callback function for all the elements in an array.
4407     * The return value of the callback function is the accumulated result,
4408     * and is provided as an argument in the next call to the callback function.
4409     *
4410     * @param callbackfn A function that accepts one argument
4411     * The reduce method calls the callbackfn function one time for each element in the array.
4412     *
4413     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4414     * The first call to the callbackfn function provides this value as an argument.
4415     *
4416     * @returns The value that results from running the callback function to completion over the entire typed array.
4417     */
4418    public reduce<U = number>(
4419                callbackfn: (previousValue: U) => U,
4420                initialValue: U): U {
4421        return this.reduce(
4422                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4423                        callbackfn(prevVal),
4424                initialValue)
4425    }
4426
4427    /**
4428     * Calls the specified callback function for all the elements in an array.
4429     * The return value of the callback function is the accumulated result,
4430     * and is provided as an argument in the next call to the callback function.
4431     *
4432     * @param callbackfn A function that accepts no arguments
4433     * The reduce method calls the callbackfn function one time for each element in the array.
4434     *
4435     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4436     * The first call to the callbackfn function provides this value as an argument.
4437     *
4438     * @returns The value that results from running the callback function to completion over the entire typed array.
4439     */
4440    public reduce<U = number>(
4441                callbackfn: () => U,
4442                initialValue: U): U {
4443        return this.reduce(
4444                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4445                        callbackfn(),
4446                initialValue)
4447    }
4448
4449    /**
4450     * Calls the specified callback function for all the elements in an array.
4451     * The return value of the callback function is the accumulated result,
4452     * and is provided as an argument in the next call to the callback function.
4453     *
4454     * @param callbackfn A function that accepts four arguments.
4455     * The reduce method calls the callbackfn function one time for each element in the array.
4456     * The first call to the callbackfn function provides array first element value as an argument
4457     *
4458     * @returns The value that results from running the callback function to completion over the entire typed array.
4459     * calling reduce method on an empty array without an initial value creates a TypeError
4460     */
4461    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number {
4462        if (this.lengthInt == 0) {
4463            throw new TypeError("Reduce of empty array with no initial value")
4464        }
4465
4466        let accumulatedValue = this.$_get(0) as number
4467        for (let i = 1; i < this.lengthInt; i++) {
4468            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4469        }
4470        return accumulatedValue
4471    }
4472
4473    /**
4474     * Calls the specified callback function for all the elements in an array.
4475     * The return value of the callback function is the accumulated result,
4476     * and is provided as an argument in the next call to the callback function.
4477     *
4478     * @param callbackfn A function that accepts three arguments.
4479     * The reduce method calls the callbackfn function one time for each element in the array.
4480     * The first call to the callbackfn function provides array first element value as an argument
4481     *
4482     * @returns The value that results from running the callback function to completion over the entire typed array.
4483     * calling reduce method on an empty array without an initial value creates a TypeError
4484     */
4485    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
4486        return this.reduce(
4487                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4488                        callbackfn(prevVal, currVal, currIndex))
4489    }
4490
4491    /**
4492     * Calls the specified callback function for all the elements in an array.
4493     * The return value of the callback function is the accumulated result,
4494     * and is provided as an argument in the next call to the callback function.
4495     *
4496     * @param callbackfn A function that accepts two arguments.
4497     * The reduce method calls the callbackfn function one time for each element in the array.
4498     * The first call to the callbackfn function provides array first element value as an argument
4499     *
4500     * @returns The value that results from running the callback function to completion over the entire typed array.
4501     * calling reduce method on an empty array without an initial value creates a TypeError
4502     */
4503    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
4504        return this.reduce(
4505                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4506                        callbackfn(prevVal, currVal))
4507    }
4508
4509    /**
4510     * Calls the specified callback function for all the elements in an array.
4511     * The return value of the callback function is the accumulated result,
4512     * and is provided as an argument in the next call to the callback function.
4513     *
4514     * @param callbackfn A function that accepts one argument.
4515     * The reduce method calls the callbackfn function one time for each element in the array.
4516     * The first call to the callbackfn function provides array first element value as an argument
4517     *
4518     * @returns The value that results from running the callback function to completion over the entire typed array.
4519     * calling reduce method on an empty array without an initial value creates a TypeError
4520     */
4521    public reduce(callbackfn: (previousValue: number) => number): number {
4522        return this.reduce(
4523                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4524                        callbackfn(prevVal))
4525    }
4526
4527    /**
4528     * Calls the specified callback function for all the elements in an array.
4529     * The return value of the callback function is the accumulated result,
4530     * and is provided as an argument in the next call to the callback function.
4531     *
4532     * @param callbackfn A function that accepts no arguments.
4533     * The reduce method calls the callbackfn function one time for each element in the array.
4534     * The first call to the callbackfn function provides array first element value as an argument
4535     *
4536     * @returns The value that results from running the callback function to completion over the entire typed array.
4537     * calling reduce method on an empty array without an initial value creates a TypeError
4538     */
4539    public reduce(callbackfn: () => number): number {
4540        return this.reduce(
4541                (prevVal: number, currVal: number, currIndex: number, array: Uint8Array) =>
4542                        callbackfn())
4543    }
4544
4545    /**
4546     * Calls the specified callback function for all the elements in an array, in descending order.
4547     * The return value of the callback function is the accumulated result,
4548     * and is provided as an argument in the next call to the callback function.
4549     *
4550     * @param callbackfn A function that accepts four arguments.
4551     * The reduceRight method calls the callbackfn function one time for each element in the array.
4552     *
4553     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4554     * The first call to the callbackfn function provides this value as an argument.
4555     *
4556     * @returns The value that results from running the callback function to completion over the entire typed array.
4557     */
4558    public reduceRight<U = number>(
4559                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U,
4560                initialValue: U): U {
4561        let accumulatedValue = initialValue
4562        for (let i = this.lengthInt - 1; i >= 0; i--) {
4563            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4564        }
4565        return accumulatedValue
4566    }
4567
4568    /**
4569     * Calls the specified callback function for all the elements in an array, in descending order.
4570     * The return value of the callback function is the accumulated result,
4571     * and is provided as an argument in the next call to the callback function.
4572     *
4573     * @param callbackfn A function that accepts three arguments.
4574     * The reduceRight method calls the callbackfn function one time for each element in the array.
4575     *
4576     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4577     * The first call to the callbackfn function provides this value as an argument.
4578     *
4579     * @returns The value that results from running the callback function to completion over the entire typed array.
4580     */
4581    public reduceRight<U = number>(
4582                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
4583                initialValue: U): U {
4584        return this.reduceRight(
4585                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4586                        callbackfn(prevVal, currVal, currIndex),
4587                initialValue)
4588    }
4589
4590    /**
4591     * Calls the specified callback function for all the elements in an array, in descending order.
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 two arguments.
4596     * The reduceRight method calls the callbackfn function one time for each element in the array.
4597     *
4598     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4599     * The first call to the callbackfn function provides this value as an argument.
4600     *
4601     * @returns The value that results from running the callback function to completion over the entire typed array.
4602     */
4603    public reduceRight<U = number>(
4604                callbackfn: (previuosValue: U, currentValue: number) => U,
4605                initialValue: U): U {
4606        return this.reduceRight(
4607                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4608                        callbackfn(prevVal, currVal),
4609                initialValue)
4610    }
4611
4612    /**
4613     * Calls the specified callback function for all the elements in an array, in descending order.
4614     * The return value of the callback function is the accumulated result,
4615     * and is provided as an argument in the next call to the callback function.
4616     *
4617     * @param callbackfn A function that accepts one argument.
4618     * The reduceRight method calls the callbackfn function one time for each element in the array.
4619     *
4620     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4621     * The first call to the callbackfn function provides this value as an argument.
4622     *
4623     * @returns The value that results from running the callback function to completion over the entire typed array.
4624     */
4625    public reduceRight<U = number>(
4626                callbackfn: (previuosValue: U) => U,
4627                initialValue: U): U {
4628        return this.reduceRight(
4629                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4630                        callbackfn(prevVal),
4631                initialValue)
4632    }
4633
4634    /**
4635     * Calls the specified callback function for all the elements in an array, in descending order.
4636     * The return value of the callback function is the accumulated result,
4637     * and is provided as an argument in the next call to the callback function.
4638     *
4639     * @param callbackfn A function that accepts no arguments.
4640     * The reduceRight method calls the callbackfn function one time for each element in the array.
4641     *
4642     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
4643     * The first call to the callbackfn function provides this value as an argument.
4644     *
4645     * @returns The value that results from running the callback function to completion over the entire typed array.
4646     */
4647    public reduceRight<U = number>(
4648                callbackfn: () => U,
4649                initialValue: U): U {
4650        return this.reduceRight(
4651                (prevVal: U, currVal: number, currIndex: number, array: Uint8Array) =>
4652                        callbackfn(),
4653                initialValue)
4654    }
4655
4656    /**
4657     * Calls the specified callback function for all the elements in an array, in descending order.
4658     * The return value of the callback function is the accumulated result,
4659     * and is provided as an argument in the next call to the callback function.
4660     *
4661     * @param callbackfn A function that accepts four arguments.
4662     * The reduceRight method calls the callbackfn function one time for each element in the array.
4663     * The first call to the callbackfn function provides array last element value as an argument
4664     *
4665     * @returns The value that results from running the callback function to completion over the entire typed array.
4666     * calling reduceRight method on an empty array without an initial value creates a TypeError
4667     */
4668    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number {
4669        if (this.lengthInt == 0) {
4670            throw new TypeError("Reduce of empty array with no initial value")
4671        }
4672
4673        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
4674        for (let i = this.lengthInt - 2; i >= 0; i--) {
4675            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
4676        }
4677        return accumulatedValue
4678    }
4679
4680    /**
4681     * Calls the specified callback function for all the elements in an array, in descending order.
4682     * The return value of the callback function is the accumulated result,
4683     * and is provided as an argument in the next call to the callback function.
4684     *
4685     * @param callbackfn A function that accepts three arguments.
4686     * The reduceRight method calls the callbackfn function one time for each element in the array.
4687     * The first call to the callbackfn function provides array last element value as an argument
4688     *
4689     * @returns The value that results from running the callback function to completion over the entire typed array.
4690     * calling reduceRight method on an empty array without an initial value creates a TypeError
4691     */
4692    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
4693        return this.reduceRight(
4694                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4695                        callbackfn(prevValue, currValue, currIndex))
4696    }
4697
4698    /**
4699     * Calls the specified callback function for all the elements in an array, in descending order.
4700     * The return value of the callback function is the accumulated result,
4701     * and is provided as an argument in the next call to the callback function.
4702     *
4703     * @param callbackfn A function that accepts two arguments.
4704     * The reduceRight method calls the callbackfn function one time for each element in the array.
4705     * The first call to the callbackfn function provides array last element value as an argument
4706     *
4707     * @returns The value that results from running the callback function to completion over the entire typed array.
4708     * calling reduceRight method on an empty array without an initial value creates a TypeError
4709     */
4710    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
4711        return this.reduceRight(
4712                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4713                        callbackfn(prevValue, currValue))
4714    }
4715
4716    /**
4717     * Calls the specified callback function for all the elements in an array, in descending order.
4718     * The return value of the callback function is the accumulated result,
4719     * and is provided as an argument in the next call to the callback function.
4720     *
4721     * @param callbackfn A function that accepts one argument.
4722     * The reduceRight method calls the callbackfn function one time for each element in the array.
4723     * The first call to the callbackfn function provides array last element value as an argument
4724     *
4725     * @returns The value that results from running the callback function to completion over the entire typed array.
4726     * calling reduceRight method on an empty array without an initial value creates a TypeError
4727     */
4728    public reduceRight(callbackfn: (previousValue: number) => number): number {
4729        return this.reduceRight(
4730                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4731                        callbackfn(prevValue))
4732    }
4733
4734    /**
4735     * Calls the specified callback function for all the elements in an array, in descending order.
4736     * The return value of the callback function is the accumulated result,
4737     * and is provided as an argument in the next call to the callback function.
4738     *
4739     * @param callbackfn A function that accepts no arguments.
4740     * The reduceRight method calls the callbackfn function one time for each element in the array.
4741     * The first call to the callbackfn function provides array last element value as an argument
4742     *
4743     * @returns The value that results from running the callback function to completion over the entire typed array.
4744     * calling reduceRight method on an empty array without an initial value creates a TypeError
4745     */
4746    public reduceRight(callbackfn: () => number): number {
4747        return this.reduceRight(
4748                (prevValue: number, currValue: number, currIndex: number, array: Uint8Array) =>
4749                        callbackfn())
4750    }
4751
4752    /**
4753     * Creates a new Uint8Array using fn(arr[i]) over all elements of current Uint8Array.
4754     *
4755     * @param fn a function to apply for each element of current Uint8Array
4756     *
4757     * @returns a new Uint8Array where for each element from current Uint8Array fn was applied
4758     */
4759    public map(fn: (val: number, index: number) => number): Uint8Array {
4760        let resBuf = new ArrayBuffer(this.lengthInt * Uint8Array.BYTES_PER_ELEMENT as int)
4761        let res = new Uint8Array(resBuf)
4762        for (let i = 0; i < this.lengthInt; i++) {
4763            const fnRes = fn(this.getUnsafe(i) as number, i as number)
4764            res.setUnsafeClamp(i, fnRes as int)
4765        }
4766        return res
4767    }
4768
4769    /**
4770     * Determines whether the specified callback function returns true for all elements of an array.
4771     *
4772     * @param predicate A function that accepts three arguments.
4773     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4774     * or until the end of the array.
4775     *
4776     * @returns true unless predicate function returns a false for an array element,
4777     * in which case false is immediately returned.
4778     */
4779    public every(predicate: (element: number, index: number, array: Uint8Array) => boolean): boolean {
4780        for (let i = 0; i < this.lengthInt; i++) {
4781            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
4782                return false
4783            }
4784        }
4785        return true
4786    }
4787
4788    /**
4789     * Determines whether the specified callback function returns true for all elements of an array.
4790     *
4791     * @param predicate A function that accepts two arguments.
4792     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4793     * or until the end of the array.
4794     *
4795     * @returns true unless predicate function returns a false for an array element,
4796     * in which case false is immediately returned.
4797     */
4798    public every(predicate: (element: number, index: number) => boolean): boolean {
4799        return this.every((element: number, index: number, array: Uint8Array): boolean => predicate(element, index))
4800    }
4801
4802    /**
4803     * Determines whether the specified callback function returns true for all elements of an array.
4804     *
4805     * @param predicate A function that accepts no arguments.
4806     * The every method calls the predicate function for each element in the array until the predicate returns a false,
4807     * or until the end of the array.
4808     *
4809     * @returns true unless predicate function returns a false for an array element,
4810     * in which case false is immediately returned.
4811     */
4812    public every(predicate: () => boolean): boolean {
4813        return this.every((element: number, index: number, array: Uint8Array): boolean => predicate())
4814    }
4815
4816    /**
4817     * Creates a new Uint8Array from current Uint8Array based on a condition fn.
4818     *
4819     * @param fn the condition to apply for each element
4820     *
4821     * @returns a new Uint8Array with elements from current Uint8Array that satisfy condition fn
4822     */
4823    public filter(fn: (val: number, index: number, array: Uint8Array) => boolean): Uint8Array {
4824        let markers = new boolean[this.lengthInt]
4825        let resLen = 0
4826        for (let i = 0; i < this.lengthInt; i++) {
4827            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
4828            if (markers[i]) {
4829                ++resLen
4830            }
4831        }
4832        let res = new Uint8Array(resLen)
4833        for (let i = 0, j = 0; i < this.lengthInt; i++) {
4834            if (markers[i]) {
4835                res.setUnsafe(j, this.getUnsafe(i))
4836                ++j
4837            }
4838        }
4839        return res
4840    }
4841
4842    /**
4843     * creates a new Uint8Array from current Uint8Array based on a condition fn
4844     *
4845     * @param fn the condition to apply for each element
4846     *
4847     * @returns a new Uint8Array with elements from current Uint8Array that satisfy condition fn
4848     */
4849    public filter(fn: (val: number, index: number) => boolean): Uint8Array {
4850        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4851            (val: number, index: number, array: Uint8Array): boolean => { return fn(val, index) }
4852        return this.filter(newF)
4853    }
4854
4855    /**
4856     * Returns the value of the first element in the array where predicate is true, and undefined
4857     * otherwise
4858     *
4859     * @param predicate find calls predicate once for each element of the array, in ascending
4860     * order, until it finds one where predicate returns true. If such an element is found, find
4861     * immediately returns that element value. Otherwise, find returns undefined
4862     *
4863     * @returns number | undefined
4864     */
4865    public find(predicate: (value: number, index: number, array: Uint8Array) => boolean): number | undefined {
4866        for (let i = 0; i < this.lengthInt; i++) {
4867            let val = this.getUnsafe(i) as number
4868            if (predicate(val, i as number, this)) {
4869                return val
4870            }
4871        }
4872        return undefined
4873    }
4874
4875    /**
4876     * Returns the value of the first element in the array where predicate is true, and undefined
4877     * otherwise
4878     *
4879     * @param predicate find calls predicate once for each element of the array, in ascending
4880     * order, until it finds one where predicate returns true. If such an element is found, find
4881     * immediately returns that element value. Otherwise, find returns undefined
4882     *
4883     * @returns number | undefined
4884     */
4885    public find(predicate: (value: number, index: number) => boolean): number | undefined {
4886        return this.find((value: number, index: number, obj: Uint8Array): boolean => predicate(value, index))
4887    }
4888
4889    /**
4890     * Returns the index of the first element in the array where predicate is true, and -1
4891     * otherwise
4892     *
4893     * @param predicate find calls predicate once for each element of the array, in ascending
4894     * order, until it finds one where predicate returns true. If such an element is found,
4895     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
4896     *
4897     * @returns number
4898     */
4899    public findIndex(predicate: (value: number, index: number, obj: Uint8Array) => boolean): number {
4900        for (let i = 0; i < this.lengthInt; i++) {
4901            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
4902                return i as number
4903            }
4904        }
4905        return -1 as number
4906    }
4907
4908    /**
4909     * Returns the index of the first element in the array where predicate is true, and -1
4910     * otherwise
4911     *
4912     * @param predicate find calls predicate once for each element of the array, in ascending
4913     * order, until it finds one where predicate returns true. If such an element is found,
4914     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
4915     *
4916     * @returns number
4917     */
4918    public findIndex(predicate: (value: number, index: number) => boolean): number {
4919        return this.findIndex((value: number, index: number, obj: Uint8Array): boolean => predicate(value, index))
4920    }
4921
4922    /**
4923     * Returns the index of the first element in the array where predicate is true, and -1
4924     * otherwise
4925     *
4926     * @param predicate find calls predicate once for each element of the array, in ascending
4927     * order, until it finds one where predicate returns true. If such an element is found,
4928     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
4929     *
4930     * @returns number
4931     */
4932    public findIndex(predicate: () => boolean): number {
4933        return this.findIndex((value: number, index: number, obj: Uint8Array): boolean => predicate())
4934    }
4935
4936    /**
4937     * Finds the last element in the Uint8Array that satisfies the condition
4938     *
4939     * @param fn condition
4940     *
4941     * @returns the last element that satisfies fn
4942     */
4943    public findLast(fn: (val: number, index: number, array: Uint8Array) => boolean): number {
4944        for (let i = this.lengthInt - 1; i >= 0; i--) {
4945            let val = this.getUnsafe(i) as number
4946            if (fn(val, i as number, this)) {
4947                return val
4948            }
4949        }
4950        throw new Error("Uint8Array.findLast: not implemented if an element was not found")
4951    }
4952
4953    /**
4954     * Finds the last element in the Uint8Array that satisfies the condition
4955     *
4956     * @param fn condition
4957     *
4958     * @returns the last element that satisfies fn
4959     */
4960    public findLast(fn: (val: number, index: number) => boolean): number {
4961        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4962            (val: number, index: number, array: Uint8Array): boolean => { return fn(val, index) }
4963        return this.findLast(newF)
4964    }
4965
4966    /**
4967     * Finds an index of the last element in the Uint8Array that satisfies the condition
4968     *
4969     * @param fn condition
4970     *
4971     * @returns the index of the last element that satisfies fn, -1 otherwise
4972     */
4973    public findLastIndex(fn: (val: number, index: number, array: Uint8Array) => boolean): number {
4974        for (let i = this.lengthInt - 1; i >= 0; i--) {
4975            if (fn(this.getUnsafe(i) as number, i as number, this)) {
4976                return i as number
4977            }
4978        }
4979        return -1 as number
4980    }
4981
4982    /**
4983     * Finds an index of the last element in the Uint8Array that satisfies the condition
4984     *
4985     * @param fn condition
4986     *
4987     * @returns the index of the last element that satisfies fn, -1 otherwise
4988     */
4989    public findLastIndex(fn: (val: number, index: number) => boolean): number {
4990        let newF: (val: number, index: number, array: Uint8Array) => boolean =
4991            (val: number, index: number, array: Uint8Array): boolean => { return fn(val, index) }
4992        return this.findLastIndex(newF) as number
4993    }
4994
4995    /**
4996     * Performs the specified action for each element in Uint8Array
4997     *
4998     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
4999     * callbackfn function one time for each element in the array.
5000     *
5001     * @returns None
5002     */
5003    public forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void): void {
5004        for (let i = 0; i < this.lengthInt; i++) {
5005            callbackfn(this.getUnsafe(i) as number, i as number, this)
5006        }
5007    }
5008
5009    /**
5010     * Performs the specified action for each element in Uint8Array
5011     *
5012     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
5013     * callbackfn function one time for each element in the array.
5014     *
5015     * @returns None
5016     */
5017    public forEach(callbackfn: (value: number, index: number) => void): void {
5018        this.forEach((value: number, index: number, array: Uint8Array): void => callbackfn(value, index))
5019    }
5020
5021    /**
5022     * Performs the specified action for each element in Uint8Array
5023     *
5024     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
5025     * callbackfn function one time for each element in the array.
5026     *
5027     * @returns None
5028     */
5029    public forEach(callbackfn: () => void): void {
5030        this.forEach((value: number, index: number, array: Uint8Array): void => callbackfn())
5031    }
5032
5033    /**
5034     * Returns the object itself
5035     *
5036     * @returns Uint8Array
5037     */
5038    public valueOf(): Uint8Array {
5039        return this
5040    }
5041
5042    /** Byte offset within the underlying Buffer */
5043    public get byteOffset(): number {
5044        return this.byteOffsetInt
5045    }
5046
5047    /** Number of bytes used */
5048    public get byteLength(): number {
5049        return this.byteLengthInt
5050    }
5051
5052    /** Number of int stored in Uint8Array */
5053    public get length(): number {
5054        return this.lengthInt
5055    }
5056
5057    /** String \"Uint8Array\" */
5058    public readonly name = "Uint8Array"
5059
5060    private static clamp(val: int): int {
5061        return val
5062    }
5063
5064    internal setUnsafeClamp(insertPos: int, val: int): void {
5065        this.setUnsafe(insertPos, val)
5066    }
5067
5068    internal getUnsafe(index: int): int {
5069        index = index * Uint8Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
5070        let res: int = 0
5071        if (IS_LITTLE_ENDIAN) {
5072            if (this.buffer instanceof ArrayBuffer) {
5073                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5074                    let el = (this.buffer as ArrayBuffer).at(index + i) as int
5075                    el &= 0xff
5076                    res |= el << (8 * i)
5077                }
5078            } else if (this.buffer instanceof SharedArrayBuffer) {
5079                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5080                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as int
5081                    el &= 0xff
5082                    res |= el << (8 * i)
5083                }
5084            } else {
5085                throw new Error("unexpected type of ArrayBufferLike")
5086            }
5087        } else {
5088            if (this.buffer instanceof ArrayBuffer) {
5089                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5090                    let el = (this.buffer as ArrayBuffer).at(index + 0 - i) as int
5091                    el &= 0xff
5092                    res |= el << (8 * i)
5093                }
5094            } else if (this.buffer instanceof SharedArrayBuffer) {
5095                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5096                    let el = (this.buffer as SharedArrayBuffer).at(index + 0 - i) as int
5097                    el &= 0xff
5098                    res |= el << (8 * i)
5099                }
5100            } else {
5101                throw new Error("unexpected type of ArrayBufferLike")
5102            }
5103        }
5104        return res
5105    }
5106
5107    internal setUnsafe(index: int, val: int): void {
5108        index = index * Uint8Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
5109        let res: int = 0
5110        if (IS_LITTLE_ENDIAN) {
5111            if (this.buffer instanceof ArrayBuffer) {
5112                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5113                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
5114                    val = val >> 8
5115                }
5116            } else if (this.buffer instanceof SharedArrayBuffer) {
5117                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5118                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
5119                    val = val >> 8
5120                }
5121            } else {
5122                throw new Error("unexpected type of ArrayBufferLike")
5123            }
5124        } else {
5125            if (this.buffer instanceof ArrayBuffer) {
5126                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5127                    (this.buffer as ArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
5128                    val = val >> 8
5129                }
5130            } else if (this.buffer instanceof SharedArrayBuffer) {
5131                for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
5132                    (this.buffer as SharedArrayBuffer).set(index + 0 - i, (val & 0xff) as byte)
5133                    val = val >> 8
5134                }
5135            } else {
5136                throw new Error("unexpected type of ArrayBufferLike")
5137            }
5138        }
5139    }
5140}
5141
5142
5143class Uint16ArrayIteratorKeys implements IterableIterator<number> {
5144    private length: int = 0
5145    private idx: int = 0
5146
5147    constructor(parent: Uint16Array) {
5148        this.length = parent.length as int
5149    }
5150
5151    public override $_iterator(): IterableIterator<Number> {
5152        return this
5153    }
5154
5155    override next(): IteratorResult<number> {
5156        if (this.idx < 0 || this.idx >= this.length) {
5157            return new IteratorResult<number>()
5158        }
5159        return new IteratorResult<number>(false, this.idx++ as number)
5160    }
5161}
5162
5163class Uint16ArrayIterator implements IterableIterator<Number> {
5164    private parent: Uint16Array
5165    private idx: int = 0
5166
5167    constructor(parent: Uint16Array) {
5168        this.parent = parent
5169    }
5170
5171    public override $_iterator(): IterableIterator<Number> {
5172        return this
5173    }
5174
5175    override next(): IteratorResult<Number> {
5176        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
5177            return new IteratorResult<Number>()
5178        }
5179        return new IteratorResult<Number>(false, new Number(this.parent.getUnsafe(this.idx++)))
5180    }
5181}
5182
5183class Uint16ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
5184    private parent: Uint16Array
5185    private idx: int = 0
5186
5187    constructor(parent: Uint16Array) {
5188        this.parent = parent
5189    }
5190
5191    public override $_iterator(): IterableIterator<[Number, Number]> {
5192        return this
5193    }
5194
5195    override next(): IteratorResult<[Number, Number]> {
5196        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
5197            return new IteratorResult<[Number, Number]>()
5198        }
5199        return new IteratorResult<[Number, Number]>(
5200            false,
5201            [new Number(this.idx), new Number(this.parent.getUnsafe(this.idx++))]
5202        )
5203    }
5204}
5205
5206/**
5207 * JS Uint16Array API-compatible class
5208 */
5209export class Uint16Array implements Iterable<Number>, ArrayLike<Number> {
5210    public static readonly BYTES_PER_ELEMENT: number = 2
5211
5212    /** Underlying Buffer */
5213    public readonly buffer: ArrayBufferLike
5214
5215    internal readonly byteOffsetInt: int
5216    internal readonly byteLengthInt: int
5217    internal readonly lengthInt: int
5218
5219    /**
5220     * Creates an empty Uint16Array.
5221     */
5222    public constructor() {
5223        this(0 as int)
5224    }
5225
5226    /**
5227     * Creates an Uint16Array with respect to data accessed via Iterable<Number> interface
5228     */
5229    public constructor(elements: Iterable<Number>) {
5230        // NOTE (ikorobkov): dealing with this overload is tricky
5231        // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
5232        let arr = Array.from<Number>(elements)
5233        this.byteLengthInt = arr.length as int * Uint16Array.BYTES_PER_ELEMENT as int
5234        this.lengthInt = arr.length as int
5235        this.buffer = new ArrayBuffer(this.byteLengthInt)
5236        this.byteOffsetInt = 0
5237        for (let i: int = 0; i < this.lengthInt; ++i) {
5238            this.setUnsafe(i, arr.$_get(i).intValue())
5239        }
5240    }
5241
5242    /**
5243     * Creates an Uint16Array with respect to data, byteOffset and length.
5244     *
5245     * @param buf data initializer
5246     *
5247     * @param byteOffset byte offset from begin of the buf
5248     *
5249     * @param length size of elements of type int in newly created Uint16Array
5250     */
5251    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
5252        let intByteOffset: int = 0
5253        if (byteOffset != undefined) {
5254            intByteOffset = byteOffset.intValue()
5255            if (intByteOffset < 0) {
5256                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
5257            }
5258        }
5259        let intByteLength: int
5260        if (buf instanceof ArrayBuffer) {
5261            intByteLength = (buf as ArrayBuffer).getByteLength()
5262        } else if (buf instanceof SharedArrayBuffer) {
5263            intByteLength = (buf as SharedArrayBuffer).getByteLength()
5264        } else {
5265            throw new Error("unexpected type of ArrayBufferLike")
5266        }
5267        intByteLength = intByteLength - intByteOffset
5268        if (intByteLength < 0) {
5269            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
5270        }
5271
5272        if (intByteLength % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5273            throw new RangeError("ArrayBufferLike.byteLength should be multiple of 2 as Uint16Array.BYTES_PER_ELEMENT")
5274        }
5275        if (intByteOffset % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5276            throw new RangeError("byteOffset should be multiple of 2 as Uint16Array.BYTES_PER_ELEMENT")
5277        }
5278
5279        let intLength: int
5280        if (length != undefined) {
5281            intLength = length.intValue()
5282            if (intLength > intByteLength / Uint16Array.BYTES_PER_ELEMENT as int) {
5283                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
5284            }
5285        } else {
5286            intLength = intByteLength / Uint16Array.BYTES_PER_ELEMENT as int
5287        }
5288        if (intLength < 0) {
5289            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
5290        }
5291        if (intLength < intByteLength / Uint16Array.BYTES_PER_ELEMENT as int) {
5292            intByteLength = intLength * Uint16Array.BYTES_PER_ELEMENT as int
5293        }
5294        this.byteLengthInt = intByteLength
5295        this.byteOffsetInt = intByteOffset
5296        this.lengthInt = intLength
5297        this.buffer = buf
5298    }
5299
5300    /**
5301     * Creates an Uint16Array with respect to data, byteOffset and length.
5302     *
5303     * @param buf data initializer
5304     *
5305     * @param byteOffset byte offset from begin of the buf
5306     */
5307    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
5308        this(buf, byteOffset, undefined)
5309    }
5310
5311    /**
5312     * Creates an Uint16Array with respect to data, byteOffset and length.
5313     *
5314     * @param buf data initializer
5315     *
5316     * @param byteOffset byte offset from begin of the buf
5317     *
5318     * @param length size of elements of type int in newly created Uint16Array
5319     */
5320    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
5321        this(buf, new Number(byteOffset), new Number(length))
5322    }
5323
5324    /**
5325     * Creates an Uint16Array with respect to buf and byteOffset.
5326     *
5327     * @param buf data initializer
5328     *
5329     * @param byteOffset byte offset from begin of the buf
5330     */
5331    public constructor(buf: ArrayBufferLike, byteOffset: number) {
5332        this(buf, new Number(byteOffset), undefined)
5333    }
5334
5335    /**
5336     * Creates an Uint16Array with respect to data, byteOffset and length.
5337     *
5338     * @param buf data initializer
5339     *
5340     * @param byteOffset byte offset from begin of the buf
5341     *
5342     * @param length size of elements of type int in newly created Uint16Array
5343     */
5344    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
5345        this(buf, new Number(byteOffset), new Number(length))
5346    }
5347
5348    /**
5349     * Creates an Uint16Array with respect to buf and byteOffset.
5350     *
5351     * @param buf data initializer
5352     *
5353     * @param byteOffset byte offset from begin of the buf
5354     */
5355    public constructor(buf: ArrayBufferLike, byteOffset: int) {
5356        this(buf, new Number(byteOffset), undefined)
5357    }
5358
5359    /**
5360     * Creates an Uint16Array with respect to buf.
5361     *
5362     * @param buf data initializer
5363     */
5364    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
5365        if (buf instanceof ArrayBuffer) {
5366            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
5367            if (this.byteLengthInt % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5368               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint16Array.BYTES_PER_ELEMENT")
5369            }
5370            this.lengthInt = this.byteLengthInt / Uint16Array.BYTES_PER_ELEMENT as int
5371            this.buffer = buf as ArrayBuffer
5372            this.byteOffsetInt = 0
5373        } else if (buf instanceof SharedArrayBuffer) {
5374            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
5375            if (this.byteLengthInt % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
5376               throw new RangeError("ArrayBufferLike.byteLength should be multiple of int as Uint16Array.BYTES_PER_ELEMENT")
5377            }
5378            this.lengthInt = this.byteLengthInt / Uint16Array.BYTES_PER_ELEMENT as int
5379            this.buffer = buf as SharedArrayBuffer
5380            this.byteOffsetInt = 0
5381        } else if (buf instanceof ArrayLike) {
5382            // NOTE (ikorobkov): dealing with this overload is tricky
5383            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
5384            let arr = Array.from<Number>((buf as ArrayLike<Number>))
5385            this.byteLengthInt = arr.length as int * Uint16Array.BYTES_PER_ELEMENT as int
5386            this.lengthInt = arr.length as int
5387            this.buffer = new ArrayBuffer(this.byteLengthInt)
5388            this.byteOffsetInt = 0
5389            for (let i: int = 0; i < this.lengthInt; ++i) {
5390                this.setUnsafe(i, arr.$_get(i).intValue())
5391            }
5392        } else {
5393            throw new Error("unexpected type of buf")
5394        }
5395    }
5396
5397    /**
5398     * Creates an Uint16Array with respect to length.
5399     *
5400     * @param length data initializer
5401     */
5402    public constructor(length: int) {
5403        if (length < 0) {
5404            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
5405        }
5406        this.lengthInt = length
5407        this.byteLengthInt = length * Uint16Array.BYTES_PER_ELEMENT as int
5408        this.byteOffsetInt = 0
5409        this.buffer = new ArrayBuffer(this.byteLengthInt)
5410    }
5411
5412    /**
5413     * Creates an Uint16Array with respect to length.
5414     *
5415     * @param length data initializer
5416     */
5417    public constructor(length: number) {
5418        this(length as int)
5419    }
5420
5421    /**
5422     * Creates a copy of Uint16Array.
5423     *
5424     * @param other data initializer
5425     */
5426    public constructor(other: Uint16Array) {
5427        if (other.buffer instanceof ArrayBuffer) {
5428            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
5429        } else if (other.buffer instanceof SharedArrayBuffer) {
5430            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
5431        } else {
5432            throw new Error("unexpected type of buffer")
5433        }
5434        this.byteLengthInt = other.byteLength as int
5435        this.lengthInt = other.length as int
5436        this.byteOffsetInt = 0
5437    }
5438
5439    /**
5440     * Creates an Uint16Array from number[]
5441     */
5442    public constructor(numbers: number[]) {
5443        this(numbers.length)
5444        for (let i: int = 0; i < this.lengthInt; ++i) {
5445            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
5446        }
5447    }
5448
5449    /**
5450     * Creates an Uint16Array from int[]
5451     */
5452    public constructor(numbers: int[]) {
5453        this(numbers.length)
5454        for (let i: int = 0; i < this.lengthInt; ++i) {
5455            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
5456        }
5457    }
5458
5459    internal zeroIfInfinity(val: number): number {
5460        if ((val == Infinity) || (val == -Infinity)) {
5461            return 0 as number
5462        }
5463        return val as number
5464    }
5465
5466    internal zeroIfInfinity(val: int): int {
5467        if ((val == Infinity) || (val == -Infinity)) {
5468            return 0 as int
5469        }
5470        return val
5471    }
5472
5473    /**
5474     * Iteratorable interface implementation
5475     *
5476     * @returns iterator over all elements
5477     */
5478    public override $_iterator(): IterableIterator<Number> {
5479         return this.values()
5480    }
5481
5482    /**
5483     * Returns an instance of primitive type at passed index.
5484     *
5485     * @param index index to look at
5486     *
5487     * @returns a primitive at index
5488     */
5489    public at(index: number): Number | undefined {
5490        return this.at(index as int)
5491    }
5492
5493    /**
5494     * Returns an instance of primitive type at passed index if index is correct.
5495     *
5496     * @param index index to look at
5497     *
5498     * @returns a primitive at index
5499     */
5500    public at(index: int): Number | undefined {
5501        let k: int
5502        if (index >= 0) {
5503            k = index
5504        } else {
5505            k = this.lengthInt + index
5506        }
5507        if (k < 0 || k >= this.lengthInt) {
5508            return undefined
5509        }
5510        return new Number(this.getUnsafe(k))
5511    }
5512
5513    /**
5514     * Returns an instance of number at passed index.
5515     *
5516     * @param index index to look at
5517     *
5518     * @returns a primitive at index
5519     */
5520    public override $_get(index: number): Number {
5521        return this.$_get(index as int) as Number
5522    }
5523
5524    /**
5525     * Returns an instance of number at passed index.
5526     *
5527     * @param index index to look at
5528     *
5529     * @returns a primitive at index
5530     */
5531    public $_get(i: int): number {
5532        if (i < 0 || i >= this.lengthInt) {
5533            throw new RangeError("invalid offset")
5534        }
5535        return this.getUnsafe(i) as number
5536    }
5537
5538    /**
5539     * Assigns val as element on index.
5540     *
5541     * @param val value to set
5542     *
5543     * @param index index to change
5544     */
5545    public $_set(index: number, val: number): void {
5546        this.$_set(index as int, val)
5547    }
5548
5549    /**
5550     * Assigns val as element on index.
5551     *
5552     * @param val value to set
5553     *
5554     * @param index index to change
5555     */
5556    public $_set(index: int, val: number): void {
5557        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
5558        if (index < 0 || index >= this.lengthInt) {
5559            throw new RangeError("invalid index")
5560        }
5561        let v = this.zeroIfInfinity(val)
5562        this.setUnsafeClamp(index, v as int)
5563    }
5564
5565    /**
5566     * Assigns val as element on index.
5567     *
5568     * @param val value to set
5569     *
5570     * @param index index to change
5571     */
5572    public $_set(index: number, val: int): void {
5573        this.$_set(index as int, val)
5574    }
5575
5576    /**
5577     * Assigns val as element on index.
5578     *
5579     * @param val value to set
5580     *
5581     * @param index index to change
5582     */
5583    public $_set(index: int, val: int): void {
5584        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
5585        if (index < 0 || index >= this.lengthInt) {
5586            throw new RangeError("invalid index")
5587        }
5588        let v = this.zeroIfInfinity(val)
5589        this.setUnsafeClamp(index, v)
5590    }
5591
5592    /**
5593     * Makes a copy of internal elements to targetPos from startPos to endPos.
5594     *
5595     * @param target insert index to place copied elements
5596     *
5597     * @param start start index to begin copy from
5598     *
5599     * @param end last index to end copy from, excluded
5600     *
5601     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5602     */
5603    public copyWithin(target: number, start: number, end?: number): Uint16Array {
5604        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5605    }
5606
5607    /**
5608     * Makes a copy of internal elements to targetPos from startPos to endPos.
5609     *
5610     * @param target insert index to place copied elements
5611     *
5612     * @param start start index to begin copy from
5613     *
5614     * @param end last index to end copy from, excluded
5615     *
5616     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5617     */
5618    public copyWithin(target: int, start: number, end?: number): Uint16Array {
5619        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5620    }
5621
5622    /**
5623     * Makes a copy of internal elements to targetPos from startPos to endPos.
5624     *
5625     * @param target insert index to place copied elements
5626     *
5627     * @param start start index to begin copy from
5628     *
5629     * @param end last index to end copy from, excluded
5630     *
5631     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5632     */
5633    public copyWithin(target: number, start: int, end?: number): Uint16Array {
5634        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5635    }
5636
5637    /**
5638     * Makes a copy of internal elements to targetPos from startPos to endPos.
5639     *
5640     * @param target insert index to place copied elements
5641     *
5642     * @param start start index to begin copy from
5643     *
5644     * @param end last index to end copy from, excluded
5645     *
5646     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5647     */
5648    public copyWithin(target: int, start: int, end?: number): Uint16Array {
5649        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5650    }
5651
5652    /**
5653     * Makes a copy of internal elements to targetPos from startPos to endPos.
5654     *
5655     * @param insert insert index to place copied elements
5656     *
5657     * @param start start index to begin copy from
5658     *
5659     * @param end last index to end copy from, excluded
5660     *
5661     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5662     */
5663    public copyWithin(target: int, start: int, end: int): Uint16Array {
5664        let toPos = normalizeIndex(target, this.lengthInt)
5665        let fromPos = normalizeIndex(start, this.lengthInt)
5666        const finalPos = normalizeIndex(end, this.lengthInt)
5667        let count: int = finalPos - fromPos
5668        if (count > (this.lengthInt - toPos)) {
5669            count = this.lengthInt - toPos
5670        }
5671        let direction: int = 1
5672        if ((fromPos < toPos) && (toPos < fromPos + count)) {
5673            fromPos = fromPos + count - 1
5674            toPos   = toPos   + count - 1
5675            direction = -1
5676        }
5677        while (count > 0) {
5678            const value = this.getUnsafe(fromPos)
5679            this.setUnsafe(toPos, value)
5680            fromPos = fromPos + direction
5681            toPos = toPos + direction
5682            --count
5683        }
5684        return this
5685    }
5686
5687    /**
5688     * Makes a copy of internal elements to targetPos from begin to end of Uint16Array.
5689     *
5690     * @param target insert index to place copied elements
5691     *
5692     * See rules of parameters normalization:
5693     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
5694     */
5695    public copyWithin(target: number): Uint16Array {
5696        return this.copyWithin(target as int)
5697    }
5698
5699    /**
5700     * Makes a copy of internal elements to targetPos from begin to end of Uint16Array.
5701     *
5702     * @param insert insert index to place copied elements
5703     *
5704     * See rules of parameters normalization:
5705     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
5706     */
5707    public copyWithin(target: int): Uint16Array {
5708        return this.copyWithin(target, 0, this.lengthInt)
5709    }
5710
5711    /**
5712     * Returns an array of key, value pairs for every entry in the Uint16Array
5713     *
5714     * @returns key, value pairs for every entry in the array
5715     */
5716    public entries(): IterableIterator<[Number, Number]> {
5717        return new Uint16ArrayIteratorEntries(this)
5718    }
5719
5720    /**
5721     * Fills the Uint16Array with specified value
5722     *
5723     * @param value new value
5724     *
5725     * @returns modified Uint16Array
5726     */
5727    public fill(value: number, start?: number, end?: number): Uint16Array {
5728        value = this.zeroIfInfinity(value)
5729        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
5730        return this
5731    }
5732
5733    /**
5734     * Fills the Uint16Array with specified value
5735     *
5736     * @param value new value
5737     *
5738     * @returns modified Uint16Array
5739     */
5740    public fill(value: number, start: int, end?: number): Uint16Array {
5741        value = this.zeroIfInfinity(value)
5742        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
5743        return this
5744    }
5745
5746    /**
5747     * Fills the Uint16Array with specified value
5748     *
5749     * @param value new value
5750     *
5751     * @returns modified Uint16Array
5752     */
5753    public fill(value: number, start: int, end: number): Uint16Array {
5754        value = this.zeroIfInfinity(value)
5755        this.fill(value as int, start as int, end as int)
5756        return this
5757    }
5758
5759    /**
5760     * Fills the Uint16Array with specified value
5761     *
5762     * @param value new value
5763     *
5764     * @returns modified Uint16Array
5765     */
5766    public fill(value: number, start: number, end: int): Uint16Array {
5767        value = this.zeroIfInfinity(value)
5768        this.fill(value as int, start as int, end as int)
5769        return this
5770    }
5771
5772    /**
5773     * Fills the Uint16Array with specified value
5774     *
5775     * @param value new value
5776     *
5777     * @returns modified Uint16Array
5778     */
5779    public fill(value: number, start: int, end: int): Uint16Array {
5780        value = this.zeroIfInfinity(value)
5781        this.fill(value as int, start as int, end as int)
5782        return this
5783    }
5784
5785    /**
5786     * Fills the Uint16Array with specified value
5787     *
5788     * @param value new value
5789     *
5790     * @returns modified Uint16Array
5791     */
5792    public fill(value: int, start?: number, end?: number): Uint16Array {
5793        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
5794        return this
5795    }
5796
5797    /**
5798     * Fills the Uint16Array with specified value
5799     *
5800     * @param value new value
5801     *
5802     * @returns modified Uint16Array
5803     */
5804    public fill(value: int, start: int, end?: number): Uint16Array {
5805        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
5806        return this
5807    }
5808
5809    /**
5810     * Fills the Uint16Array with specified value
5811     *
5812     * @param value new value
5813     *
5814     * @returns modified Uint16Array
5815     */
5816    public fill(value: int, start: int, end: number): Uint16Array {
5817        this.fill(value, start as int, end as int)
5818        return this
5819    }
5820
5821    /**
5822     * Fills the Uint16Array with specified value
5823     *
5824     * @param value new value
5825     *
5826     * @returns modified Uint16Array
5827     */
5828    public fill(value: int, start: number, end: int): Uint16Array {
5829        this.fill(value, start as int, end as int)
5830        return this
5831    }
5832
5833    /**
5834     * Fills the Uint16Array with specified value
5835     *
5836     * @param value new value
5837     *
5838     * @returns modified Uint16Array
5839     */
5840    public fill(value: int, start: int, end: int): Uint16Array {
5841        const k = normalizeIndex(start, this.lengthInt)
5842        const finalPos = normalizeIndex(end, this.lengthInt)
5843        for (let i: int = k; i < finalPos; ++i) {
5844            this.setUnsafe(i, value)
5845        }
5846        return this
5847    }
5848
5849    /**
5850     * Assigns val as element on index.
5851     *
5852     * @param val value to set
5853     *
5854     * @param index index to change
5855     */
5856    public set(insertPos: number, val: number): void {
5857        this.$_set(insertPos as int, val)
5858    }
5859
5860    /**
5861     * Assigns val as element on index.
5862     *
5863     * @param val value to set
5864     *
5865     * @param index index to change
5866     */
5867    public set(insertPos: int, val: number): void {
5868        this.$_set(insertPos as int, val)
5869    }
5870
5871    /**
5872     * Assigns val as element on index.
5873     *
5874     * @param val value to set
5875     *
5876     * @param index index to change
5877     */
5878    public set(insertPos: number, val: int): void {
5879        this.$_set(insertPos as int, val)
5880    }
5881
5882    /**
5883     * Assigns val as element on index.
5884     *
5885     * @param val value to set
5886     *
5887     * @param index index to change
5888     */
5889    public set(insertPos: int, val: int): void {
5890        this.$_set(insertPos as int, val)
5891    }
5892
5893    /**
5894     * Copies all elements of arr to the current Uint16Array starting from insertPos.
5895     *
5896     * @param arr array to copy data from
5897     *
5898     * @param insertPos start index where data from arr will be inserted
5899     *
5900     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
5901     */
5902    public set(arr: number[], insertPos1: number): void {
5903        const insertPos = insertPos1 as int
5904        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
5905            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint16Array.length")
5906        }
5907        for (let i = 0; i < arr.length; i++) {
5908            let v = this.zeroIfInfinity(arr[i])
5909            this.setUnsafeClamp(insertPos as int + i as int, v as int)
5910        }
5911    }
5912
5913    /**
5914     * Copies all elements of arr to the current Uint16Array starting from insertPos.
5915     *
5916     * @param arr array to copy data from
5917     *
5918     * @param insertPos start index where data from arr will be inserted
5919     *
5920     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
5921     */
5922    public set(arr: int[], insertPos: int): void {
5923        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
5924            throw new RangeError("set(insertPos: int, arr: int[]): size of arr is greater than Uint16Array.length")
5925        }
5926        for (let i = 0; i < arr.length; i++) {
5927            let v = this.zeroIfInfinity(arr[i])
5928            this.setUnsafeClamp(insertPos + i, v)
5929        }
5930    }
5931
5932    /**
5933     * Copies all elements of arr to the current Uint16Array.
5934     *
5935     * @param arr array to copy data from
5936     */
5937    public set(arr: number[]): void {
5938        this.set(arr, 0)
5939    }
5940
5941    /**
5942     * Copies all elements of arr to the current Uint16Array.
5943     *
5944     * @param arr array to copy data from
5945     */
5946    public set(arr: int[]): void {
5947        this.set(arr, 0)
5948    }
5949
5950    /**
5951     * Copies elements from an ArrayLike object to the Uint16Array.
5952     *
5953     * @param array An ArrayLike object containing the elements to copy.
5954     *
5955     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
5956     */
5957    public set(array: ArrayLike<number>, offset: number = 0): void {
5958        const insertPos = offset as int
5959        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
5960            throw new RangeError("offset is out of bounds")
5961        }
5962        for (let i = 0; i < array.length; i++) {
5963            let v = this.zeroIfInfinity(array[i])
5964            this.setUnsafeClamp(insertPos as int + i as int, v as int)
5965        }
5966    }
5967
5968    /**
5969     * Returns a new array from a set of elements.
5970     *
5971     * @param items a set of elements to include in the new array object.
5972     *
5973     * @returns new Uint16Array
5974     */
5975    public static of(...items: number[]): Uint16Array {
5976        let res = new Uint16Array(items.length as int)
5977        for (let i: int = 0; i < items.length; i++) {
5978            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as int)
5979        }
5980        return res
5981    }
5982
5983    /**
5984     * Returns a new array from a set of elements.
5985     *
5986     * @param items a set of elements to include in the new array object.
5987     *
5988     * @returns new Uint16Array
5989     */
5990    public static of(...items: int[]): Uint16Array {
5991        let res = new Uint16Array(items.length as int)
5992        for (let i: int = 0; i < items.length; i++) {
5993            res.setUnsafeClamp(i, items[i])
5994        }
5995        return res
5996    }
5997
5998    /**
5999     * Returns a new array from a set of elements.
6000     *
6001     * @param items a set of elements to include in the new array object.
6002     *
6003     * @returns new Uint16Array
6004     */
6005    public static of(): Uint16Array {
6006        return new Uint16Array(0 as int)
6007    }
6008
6009    /**
6010     * Creates an array from an array-like or iterable object.
6011     *
6012     * @param arrayLike An array-like or iterable object to convert to an array.
6013     *
6014     * @returns new Uint16Array
6015     */
6016    public static from(arr: ArrayLike<number>): Uint16Array {
6017        return Uint16Array.from<number>(arr, (x: number, k: number): number => x)
6018    }
6019
6020    /**
6021     * Creates an array from an array-like or iterable object.
6022     *
6023     * @param arrayLike An array-like or iterable object to convert to an array.
6024     *
6025     * @param mapfn A mapping function to call on every element of the array.
6026     *
6027     * @returns new Uint16Array
6028     */
6029    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint16Array {
6030        if (mapfn == undefined) {
6031            mapfn = (v: number, k: number): number => { return v }
6032        }
6033        // Calc length of items inside arrayLike, save length into i variable
6034        let i: long = 0
6035        let iter = arrayLike.$_iterator()
6036        while (true) {
6037            const v = iter.next()
6038            if (v.done) {
6039                break
6040            }
6041            i++
6042        }
6043
6044        let res = new Uint16Array(i as int)
6045        i = 0
6046        iter = arrayLike.$_iterator()
6047        while (true) {
6048            const v = iter.next()
6049            if (v.done) {
6050                return res
6051            }
6052            res.setUnsafeClamp(i as int, res.zeroIfInfinity((mapfn)!(v.value as number, i as number)) as int)
6053            i++
6054        }
6055    }
6056
6057    /**
6058     * Creates an array from an array-like or iterable object.
6059     *
6060     * @param arrayLike An array-like or iterable object to convert to an array.
6061     *
6062     * @param mapfn A mapping function to call on every element of the array.
6063     *
6064     * @returns new Uint16Array
6065     */
6066    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint16Array {
6067        let res = new Uint16Array(arrayLike.length)
6068        // 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
6069        const idx = new int[1]
6070        idx[0] = 0
6071        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
6072            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as int)
6073            idx[0] += 1
6074        })
6075        return res
6076    }
6077
6078    /**
6079     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
6080     *
6081     * @param searchElement The element to search for
6082     *
6083     * @param fromIndex The position in this array at which to begin searching for searchElement
6084     *
6085     * @returns true if searchElement is in Uint16Array, false otherwise
6086     */
6087    public includes(searchElement: number, fromIndex?: number): boolean {
6088        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
6089    }
6090
6091    /**
6092     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
6093     *
6094     * @param searchElement The element to search for
6095     *
6096     * @param fromIndex The position in this array at which to begin searching for searchElement
6097     *
6098     * @returns true if searchElement is in Uint16Array, false otherwise
6099     */
6100    public includes(searchElement: int, fromIndex: int): boolean {
6101        return this.indexOf(searchElement as int, fromIndex) != -1
6102    }
6103
6104    /**
6105     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
6106     *
6107     * @param searchElement The element to search for
6108     *
6109     * @param fromIndex The position in this array at which to begin searching for searchElement
6110     *
6111     * @returns true if searchElement is in Uint16Array, false otherwise
6112     */
6113    public includes(searchElement: int): boolean {
6114        return this.indexOf(searchElement as int, 0) != -1
6115    }
6116
6117    /**
6118     * Returns the index of the first occurrence of a value in Uint16Array.
6119     *
6120     * @param searchElement The value to locate in the array.
6121     *
6122     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6123     *  search starts at index 0.
6124     *
6125     * @returns index of element if it presents, -1 otherwise
6126     */
6127    public indexOf(searchElement: number, fromIndex?: number): number {
6128        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
6129    }
6130
6131    /**
6132     * Returns the index of the first occurrence of a value in Uint16Array.
6133     *
6134     * @param searchElement The value to locate in the array.
6135     *
6136     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6137     *  search starts at index 0.
6138     *
6139     * @returns index of element if it presents, -1 otherwise
6140     */
6141    public indexOf(searchElement: number, fromIndex: int): number {
6142        if (isNaN(searchElement)) {
6143            return -1
6144        }
6145        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
6146        for (let i = fromIndex; i < this.lengthInt; i++) {
6147            if (this.getUnsafe(i) as number == searchElement) {
6148                return i
6149            }
6150        }
6151        return -1
6152    }
6153
6154    /**
6155     * Returns the index of the first occurrence of a value in Uint16Array.
6156     *
6157     * @param searchElement The value to locate in the array.
6158     *
6159     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6160     *  search starts at index 0.
6161     *
6162     * @returns index of element if it presents, -1 otherwise
6163     */
6164    public indexOf(searchElement: int, fromIndex: int): number {
6165        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
6166        for (let i = fromIndex; i < this.lengthInt; i++) {
6167            if (this.getUnsafe(i) == searchElement) {
6168                return i
6169            }
6170        }
6171        return -1
6172
6173    }
6174
6175    /**
6176     * Returns the index of the first occurrence of a value in Uint16Array.
6177     *
6178     * @param searchElement The value to locate in the array.
6179     *
6180     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6181     *  search starts at index 0.
6182     *
6183     * @returns index of element if it presents, -1 otherwise
6184     */
6185    public indexOf(searchElement: int): number {
6186        return this.indexOf(searchElement, 0)
6187    }
6188
6189    /**
6190     * Adds all the elements of an array separated by the specified separator string
6191     *
6192     * @param separator A string used to separate one element of an array from the next in the
6193     * resulting String. If omitted, the array elements are separated with a comma
6194     *
6195     * @returns joined representation
6196     */
6197    public join(separator?: String): string {
6198        if (separator == undefined) {
6199            return this.join(",")
6200        }
6201        let res: StringBuilder = new StringBuilder("")
6202        for (let i = 0; i < this.lengthInt - 1; i++) {
6203            res.append(this.getUnsafe(i) as number)
6204            res.append(separator)
6205        }
6206        if (this.lengthInt > 0) {
6207            res.append(this.getUnsafe(this.lengthInt - 1) as number)
6208        }
6209        return res.toString()
6210    }
6211
6212    /**
6213     * Returns an list of keys in Uint16Array
6214     *
6215     * @returns iterator over keys
6216     */
6217    public keys(): IterableIterator<number> {
6218        return new Uint16ArrayIteratorKeys(this)
6219    }
6220
6221    /**
6222     * Returns the index of the last occurrence of a value in Uint16Array.
6223     *
6224     * @param searchElement The value to locate in the array.
6225     *
6226     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6227     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6228     *
6229     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6230     */
6231    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
6232        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
6233    }
6234
6235    /**
6236     * Returns the index of the last occurrence of a value in Uint16Array.
6237     *
6238     * @param searchElement The value to locate in the array.
6239     *
6240     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6241     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6242     *
6243     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6244     */
6245    public lastIndexOf(searchElement: number): number {
6246        return this.lastIndexOf(searchElement, this.lengthInt - 1)
6247    }
6248
6249    /**
6250     * Returns the index of the last occurrence of a value in Uint16Array.
6251     *
6252     * @param searchElement The value to locate in the array.
6253     *
6254     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6255     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6256     *
6257     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6258     */
6259    public lastIndexOf(searchElement: number, fromIndex: int): number {
6260        if (isNaN(searchElement)) {
6261            return -1
6262        }
6263        if (this.lengthInt == 0) {
6264            return -1
6265        }
6266        let k: int = this.lengthInt + fromIndex
6267        if (fromIndex >= 0) {
6268            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
6269        }
6270        while (k >= 0) {
6271            if (this.getUnsafe(k) as number == searchElement) {
6272                return k
6273            }
6274            k--
6275        }
6276        return -1
6277    }
6278
6279    /**
6280     * Returns the index of the last occurrence of a value in Uint16Array.
6281     *
6282     * @param searchElement The value to locate in the array.
6283     *
6284     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6285     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6286     *
6287     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6288     */
6289    public lastIndexOf(searchElement: int, fromIndex: int): number {
6290        if (this.lengthInt == 0) {
6291            return -1
6292        }
6293        let k: int = this.lengthInt + fromIndex
6294        if (fromIndex >= 0) {
6295            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
6296        }
6297        while (k >= 0) {
6298            if (this.getUnsafe(k) == searchElement) {
6299                return k
6300            }
6301            k--
6302        }
6303        return -1
6304    }
6305
6306    /**
6307     * Returns the index of the last occurrence of a value in Uint16Array.
6308     *
6309     * @param searchElement The value to locate in the array.
6310     *
6311     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6312     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6313     *
6314     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6315     */
6316    public lastIndexOf(searchElement: int): number {
6317        return this.lastIndexOf(searchElement, this.lengthInt - 1)
6318    }
6319
6320   /**
6321    * Creates a new Uint16Array using initializer
6322    *
6323    * @param data initializer
6324    *
6325    * @returns a new Uint16Array from data
6326    */
6327    public of(...data: number[]): Uint16Array {
6328        throw new Error("Uint16Array.of: not implemented")
6329    }
6330
6331    /**
6332     * Creates a new Uint16Array using reversed data from the current one
6333     *
6334     * @returns a new Uint16Array using reversed data from the current one
6335     */
6336    public reverse(): Uint16Array {
6337        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
6338            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
6339            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
6340            this.setUnsafe(i, tmp)
6341        }
6342        return this
6343    }
6344
6345    /**
6346     * Creates a slice of current Uint16Array using range [begin, end)
6347     *
6348     * @param begin start index to be taken into slice
6349     *
6350     * @param end last index to be taken into slice
6351     *
6352     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6353     *
6354     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6355     */
6356    public slice(begin?: number, end?: number): Uint16Array {
6357        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
6358    }
6359
6360    /**
6361     * Creates a slice of current Uint16Array using range [begin, end)
6362     *
6363     * @param begin start index to be taken into slice
6364     *
6365     * @param end last index to be taken into slice
6366     *
6367     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6368     *
6369     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6370     */
6371    public slice(begin: number, end: number): Uint16Array {
6372        return this.slice(begin as int, end as int)
6373    }
6374
6375    /**
6376     * Creates a slice of current Uint16Array using range [begin, end)
6377     *
6378     * @param begin start index to be taken into slice
6379     *
6380     * @param end last index to be taken into slice
6381     *
6382     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6383     *
6384     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6385     */
6386    public slice(begin: number, end: int): Uint16Array {
6387        return this.slice(begin as int, end as int)
6388    }
6389
6390    /**
6391     * Creates a slice of current Uint16Array using range [begin, end)
6392     *
6393     * @param begin start index to be taken into slice
6394     *
6395     * @param end last index to be taken into slice
6396     *
6397     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6398     *
6399     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6400     */
6401    public slice(begin: int, end: number): Uint16Array {
6402        return this.slice(begin as int, end as int)
6403    }
6404
6405    /**
6406     * Creates a slice of current Uint16Array using range [begin, end)
6407     *
6408     * @param begin start index to be taken into slice
6409     *
6410     * @param end last index to be taken into slice
6411     *
6412     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
6413     *
6414     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6415     */
6416    public slice(begin: int, end: int): Uint16Array {
6417        const len: int = this.lengthInt
6418        const relStart = normalizeIndex(begin, len)
6419        const relEnd = normalizeIndex(end, len)
6420        let count = relEnd - relStart
6421        if (count < 0) {
6422            count = 0
6423        }
6424        if (this.buffer instanceof ArrayBuffer) {
6425            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint16Array.BYTES_PER_ELEMENT as int, relEnd * Uint16Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
6426            return new Uint16Array(buf)
6427        } else if (this.buffer instanceof SharedArrayBuffer) {
6428            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint16Array.BYTES_PER_ELEMENT as int, relEnd * Uint16Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
6429            return new Uint16Array(buf)
6430        } else {
6431            throw new Error("unexpected type of buffer")
6432        }
6433    }
6434
6435    /**
6436     * Creates a slice of current Uint16Array using range [begin, this.lengthInt).
6437     *
6438     * @param begin start index to be taken into slice
6439     *
6440     * @returns a new Uint16Array with elements of current Uint16Array[begin, this.lengthInt)
6441     */
6442    public slice(begin: number): Uint16Array {
6443        return this.slice(begin as int)
6444    }
6445
6446    /**
6447     * Creates a slice of current Uint16Array using range [begin, this.lengthInt).
6448     *
6449     * @param begin start index to be taken into slice
6450     *
6451     * @returns a new Uint16Array with elements of current Uint16Array[begin, this.lengthInt)
6452     */
6453    public slice(begin: int): Uint16Array {
6454        return this.slice(begin, this.lengthInt)
6455    }
6456
6457    /**
6458     * Sorts in-place
6459     *
6460     * @param compareFn comparator —  used to determine the order of the elements.
6461     * compareFn returns a negative value if first argument is less than second argument,
6462     * zero if they're equal and a positive value otherwise.
6463     * If omitted, the elements are sorted in ascending order.
6464     *
6465     * @returns sorted Uint16Array
6466     */
6467    public sort(compareFn?: (a: number, b: number) => number): this {
6468        let arr: int[] = new int[this.lengthInt]
6469        for (let i = 0; i < this.lengthInt; ++i) {
6470            arr[i] = this.getUnsafe(i)
6471        }
6472        let cmp = (l: int, r: int): number => {
6473                return (l - r) as number
6474            }
6475        if (compareFn != undefined) {
6476            cmp = (l: int, r: int): number => {
6477                return compareFn!(l as number, r as number)
6478            }
6479        }
6480        sort(arr, cmp)
6481        for (let i = 0; i < this.lengthInt; ++i) {
6482            this.setUnsafe(i, arr[i])
6483        }
6484        return this
6485    }
6486
6487    /**
6488     * Sorts in-place
6489     *
6490     * @param compareFn comparator —  used to determine the order of the elements.
6491     * compareFn returns a negative value if first argument is less than second argument,
6492     * zero if they're equal and a positive value otherwise.
6493     *
6494     * @returns sorted Uint16Array
6495     */
6496    public sort(compareFn: (a: number) => number): this {
6497        let cmp = (a: number, b: number) => { return compareFn(a)}
6498        this.sort(cmp)
6499        return this
6500    }
6501
6502    /**
6503     * Sorts in-place
6504     *
6505     * @param fn compareFn —  used to determine the order of the elements.
6506     * compareFn returns a negative value if first argument is less than second argument,
6507     * zero if they're equal and a positive value otherwise.
6508     *
6509     * @returns sorted Uint16Array
6510     */
6511    public sort(compareFn: () => number): this {
6512        let cmp = (a: number, b: number) => { return compareFn()}
6513        this.sort(cmp)
6514        return this
6515    }
6516    /**
6517     * Creates a Uint16Array with the same underlying Buffer
6518     *
6519     * @param begin start index, inclusive
6520     *
6521     * @param end last index, exclusive
6522     *
6523     * @returns new Uint16Array with the same underlying Buffer
6524     */
6525    public subarray(begin?: number, end?: number): Uint16Array {
6526        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
6527    }
6528
6529    /**
6530     * Creates a Uint16Array with the same underlying Buffer
6531     *
6532     * @param begin start index, inclusive
6533     *
6534     * @param end last index, exclusive
6535     *
6536     * @returns new Uint16Array with the same underlying Buffer
6537     */
6538    public subarray(begin: number, end: number): Uint16Array {
6539        return this.subarray(begin as int, end as int)
6540    }
6541
6542    /**
6543     * Creates a Uint16Array with the same underlying Buffer
6544     *
6545     * @param begin start index, inclusive
6546     *
6547     * @param end last index, exclusive
6548     *
6549     * @returns new Uint16Array with the same underlying Buffer
6550     */
6551    public subarray(begin: number, end: int): Uint16Array {
6552        return this.subarray(begin as int, end as int)
6553    }
6554
6555    /**
6556     * Creates a Uint16Array with the same underlying Buffer
6557     *
6558     * @param begin start index, inclusive
6559     *
6560     * @param end last index, exclusive
6561     *
6562     * @returns new Uint16Array with the same underlying Buffer
6563     */
6564    public subarray(begin: int, end: number): Uint16Array {
6565        return this.subarray(begin as int, end as int)
6566    }
6567
6568    /**
6569     * Creates a Uint16Array with the same underlying Buffer
6570     *
6571     * @param begin start index, inclusive
6572     *
6573     * @param end last index, exclusive
6574     *
6575     * @returns new Uint16Array with the same underlying Buffer
6576     */
6577    public subarray(begin: int, end: int): Uint16Array {
6578        const len: int = this.lengthInt
6579        const relStart = normalizeIndex(begin, len)
6580        const relEnd = normalizeIndex(end, len)
6581        let count = relEnd - relStart
6582        if (count < 0) {
6583            count = 0
6584        }
6585        return new Uint16Array(this.buffer, relStart * Uint16Array.BYTES_PER_ELEMENT as int, count)
6586    }
6587
6588    /**
6589     * Creates a Uint16Array with the same Buffer
6590     *
6591     * @param begin start index, inclusive
6592     *
6593     * @returns new Uint16Array with the same Buffer
6594     */
6595    public subarray(begin: number): Uint16Array {
6596        return this.subarray(begin as int, this.lengthInt)
6597    }
6598
6599    /**
6600     * Creates a Uint16Array with the same Buffer
6601     *
6602     * @param begin start index, inclusive
6603     *
6604     * @returns new Uint16Array with the same Buffer
6605     */
6606    public subarray(begin: int): Uint16Array {
6607        return this.subarray(begin, this.lengthInt)
6608    }
6609
6610    /**
6611     * Converts Uint16Array to a string with respect to locale
6612     *
6613     * @param locales
6614     *
6615     * @param options
6616     *
6617     * @returns string representation
6618     */
6619    public toLocaleString(locales: Object, options: Object): string {
6620        throw new Error("Uint16Array.toLocaleString: not implemented")
6621    }
6622
6623    /**
6624     * Converts Uint16Array to a string with respect to locale
6625     *
6626     * @param locales
6627     *
6628     * @returns string representation
6629     */
6630    public toLocaleString(locales: Object): string {
6631        return this.toLocaleString(new Object(), new Object())
6632    }
6633
6634    /**
6635     * Converts Uint16Array to a string with respect to locale
6636     *
6637     * @returns string representation
6638     */
6639    public toLocaleString(): string {
6640        let res: StringBuilder = new StringBuilder("")
6641        for (let i = 0; i < this.lengthInt - 1; ++i) {
6642            res.append((this.getUnsafe(i) as Number).toLocaleString())
6643            res.append(",")
6644        }
6645        if (this.lengthInt > 0) {
6646            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
6647        }
6648        return res.toString()
6649    }
6650
6651    /**
6652     * Creates a reversed copy
6653     *
6654     * @returns a reversed copy
6655     */
6656    public toReversed(): Uint16Array {
6657        return new Uint16Array(this).reverse()
6658    }
6659
6660    /**
6661     * Creates a sorted copy
6662     *
6663     * @returns a sorted copy
6664     */
6665    public toSorted(): Uint16Array {
6666        return new Uint16Array(this).sort()
6667    }
6668
6669    /**
6670     * Returns a string representation of the Uint16Array
6671     *
6672     * @returns a string representation of the Uint16Array
6673     */
6674    public override toString(): string {
6675        return this.join(",")
6676    }
6677
6678    /**
6679     * Returns array values iterator
6680     *
6681     * @returns an iterator
6682     */
6683    public values(): IterableIterator<Number> {
6684         return new Uint16ArrayIterator(this)
6685    }
6686
6687    /**
6688     * Creates a copy with replaced value on index
6689     *
6690     * @param index
6691     *
6692     * @param value
6693     *
6694     * @returns an Uint16Array with replaced value on index
6695     */
6696    public with(index: number, value: number): Uint16Array {
6697        return this.with(index as int, value as int)
6698    }
6699
6700    /**
6701     * Creates a copy with replaced value on index
6702     *
6703     * @param index
6704     *
6705     * @param value
6706     *
6707     * @returns an Uint16Array with replaced value on index
6708     */
6709    /* public */ internal with(index: int, value: int): Uint16Array {
6710        let res = new Uint16Array(this)
6711        res.setUnsafeClamp(index, value)
6712        return res
6713    }
6714
6715    /// === with element lambda functions ===
6716
6717    /**
6718     * Determines whether the specified callback function returns true for all elements of an array.
6719     *
6720     * @param predicate A function that accepts one argument.
6721     * The every method calls the predicate function for each element in the array until the predicate returns a false,
6722     * or until the end of the array.
6723     *
6724     * @returns true unless predicate function returns a false for an array element,
6725     * in which case false is immediately returned.
6726     */
6727    public every(predicate: (element: number) => boolean): boolean {
6728        return this.every((element: number, index: number, array: Uint16Array): boolean => predicate(element))
6729    }
6730
6731    /**
6732     * creates a new Uint16Array from current Uint16Array based on a condition fn
6733     *
6734     * @param fn the condition to apply for each element
6735     *
6736     * @returns a new Uint16Array with elements from current Uint16Array that satisfy condition fn
6737     */
6738    public filter(fn: (val: number) => boolean): Uint16Array {
6739        let newF: (val: number, index: number, array: Uint16Array) => boolean =
6740            (val: number, index: number, array: Uint16Array): boolean => { return fn(val) }
6741        return this.filter(newF)
6742    }
6743
6744    /**
6745     * Returns the value of the first element in the array where predicate is true, and undefined
6746     * otherwise
6747     *
6748     * @param predicate find calls predicate once for each element of the array, in ascending
6749     * order, until it finds one where predicate returns true. If such an element is found, find
6750     * immediately returns that element value. Otherwise, find returns undefined
6751     *
6752     * @returns number | undefined
6753     */
6754    public find(predicate: () => boolean): number | undefined {
6755        return this.find((value: number, index: number, obj: Uint16Array): boolean => predicate())
6756    }
6757
6758    /**
6759     * Returns the value of the first element in the array where predicate is true, and undefined
6760     * otherwise
6761     *
6762     * @param predicate find calls predicate once for each element of the array, in ascending
6763     * order, until it finds one where predicate returns true. If such an element is found, find
6764     * immediately returns that element value. Otherwise, find returns undefined
6765     *
6766     * @returns number | undefined
6767     */
6768    public find(predicate: (value: number) => boolean): number | undefined {
6769        return this.find((value: number, index: number, obj: Uint16Array): boolean => predicate(value))
6770    }
6771
6772    /**
6773     * Returns the index of the first element in the array where predicate is true, and -1
6774     * otherwise
6775     *
6776     * @param predicate find calls predicate once for each element of the array, in ascending
6777     * order, until it finds one where predicate returns true. If such an element is found,
6778     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
6779     *
6780     * @returns number
6781     */
6782    public findIndex(predicate: (value: number) => boolean): number {
6783        return this.findIndex((value: number, index: number, obj: Uint16Array): boolean => predicate(value)) as number
6784    }
6785
6786    /**
6787     * Finds the last element in the Uint16Array that satisfies the condition
6788     *
6789     * @param fn condition
6790     *
6791     * @returns the last element that satisfies fn
6792     */
6793    public findLast(fn: (val: number) => boolean): number {
6794        let newF: (val: number, index: number, array: Uint16Array) => boolean =
6795            (val: number, index: number, array: Uint16Array): boolean => { return fn(val) }
6796        return this.findLast(newF)
6797    }
6798
6799    /**
6800     * Finds an index of the last element in the Uint16Array that satisfies the condition
6801     *
6802     * @param fn condition
6803     *
6804     * @returns the index of the last element that satisfies fn, -1 otherwise
6805     */
6806    public findLastIndex(fn: (val: number) => boolean): number {
6807        let newF: (val: number, index: number, array: Uint16Array) => boolean =
6808            (val: number, index: number, array: Uint16Array): boolean => { return fn(val) }
6809        return this.findLastIndex(newF) as number
6810    }
6811
6812    /**
6813     * Performs the specified action for each element in Uint16Array
6814     *
6815     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
6816     * callbackfn function one time for each element in the array.
6817     *
6818     * @returns None
6819     */
6820    public forEach(callbackfn: (val: number) => void): void {
6821        this.forEach((value: number, index: number, array: Uint16Array): void => callbackfn(value))
6822    }
6823
6824    /**
6825     * Creates a new Uint16Array using fn(arr[i]) over all elements of current Uint16Array
6826     *
6827     * @param fn a function to apply for each element of current Uint16Array
6828     *
6829     * @returns a new Uint16Array where for each element from current Uint16Array fn was applied
6830     */
6831    public map(fn: (val: number) => number): Uint16Array {
6832        let newF: (val: number, index: number) => number =
6833            (val: number, index: number): number => { return fn(val) }
6834        return this.map(newF)
6835    }
6836
6837    /**
6838     * Determines whether the specified callback function returns true for any element of an array.
6839     *
6840     * @param predicate A function that accepts one argument.
6841     * The some method calls the predicate function for each element in the array
6842     * until the predicate returns a true or until the end of the array.
6843     *
6844     * @returns false unless predicate function returns true for an array element,
6845     * in which case true is immediately returned.
6846     */
6847    public some(predicate: (element: number) => boolean): boolean {
6848        return this.some((element: number, index: number, array: Uint16Array): boolean => predicate(element))
6849    }
6850
6851    /**
6852     * Determines whether the specified callback function returns true for any element of an array.
6853     *
6854     * @param predicate A function that accepts three arguments.
6855     * The some method calls the predicate function for each element in the array
6856     * until the predicate returns a true or until the end of the array.
6857     *
6858     * @returns false unless predicate function returns true for an array element,
6859     * in which case true is immediately returned.
6860     */
6861    public some(predicate: (element: number, index: number, array: Uint16Array) => boolean): boolean {
6862        for (let i = 0; i < this.lengthInt; i++) {
6863            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
6864                return true
6865            }
6866        }
6867        return false
6868    }
6869
6870    /**
6871     * Determines whether the specified callback function returns true for any element of an array.
6872     *
6873     * @param predicate A function that accepts two arguments.
6874     * The some method calls the predicate function for each element in the array
6875     * until the predicate returns a true or until the end of the array.
6876     *
6877     * @returns false unless predicate function returns true for an array element,
6878     * in which case true is immediately returned.
6879     */
6880    public some(predicate: (element: number, index: number) => boolean): boolean {
6881        return this.some((element: number, index: number, array: Uint16Array): boolean => predicate(element, index))
6882    }
6883
6884    /**
6885     * Determines whether the specified callback function returns true for any element of an array.
6886     *
6887     * @param predicate A function that accepts no arguments.
6888     * The some method calls the predicate function for each element in the array
6889     * until the predicate returns a true or until the end of the array.
6890     *
6891     * @returns false unless predicate function returns true for an array element,
6892     * in which case true is immediately returned.
6893     */
6894    public some(predicate: () => boolean): boolean {
6895        return this.some((element: number, index: number, array: Uint16Array): boolean => predicate())
6896    }
6897
6898    /**
6899     * Calls the specified callback function for all the elements in an array.
6900     * The return value of the callback function is the accumulated result,
6901     * and is provided as an argument in the next call to the callback function.
6902     *
6903     * @param callbackfn A function that accepts four arguments.
6904     * The reduce method calls the callbackfn function one time for each element in the array.
6905     *
6906     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
6907     * The first call to the callbackfn function provides this value as an argument.
6908     *
6909     * @returns The value that results from running the callback function to completion over the entire typed array.
6910     */
6911    public reduce<U = number>(
6912                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U,
6913                initialValue: U): U {
6914        let accumulatedValue = initialValue
6915        for (let i = 0; i < this.lengthInt; i++) {
6916            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
6917        }
6918        return accumulatedValue
6919    }
6920
6921    /**
6922     * Calls the specified callback function for all the elements in an array.
6923     * The return value of the callback function is the accumulated result,
6924     * and is provided as an argument in the next call to the callback function.
6925     *
6926     * @param callbackfn A function that accepts three arguments.
6927     * The reduce method calls the callbackfn function one time for each element in the array.
6928     *
6929     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
6930     * The first call to the callbackfn function provides this value as an argument.
6931     *
6932     * @returns The value that results from running the callback function to completion over the entire typed array.
6933     */
6934    public reduce<U = number>(
6935                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
6936                initialValue: U): U {
6937        return this.reduce(
6938                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
6939                        callbackfn(prevVal, currVal, currIndex),
6940                initialValue)
6941    }
6942
6943    /**
6944     * Calls the specified callback function for all the elements in an array.
6945     * The return value of the callback function is the accumulated result,
6946     * and is provided as an argument in the next call to the callback function.
6947     *
6948     * @param callbackfn A function that accepts two arguments.
6949     * The reduce method calls the callbackfn function one time for each element in the array.
6950     *
6951     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
6952     * The first call to the callbackfn function provides this value as an argument.
6953     *
6954     * @returns The value that results from running the callback function to completion over the entire typed array.
6955     */
6956    public reduce<U = number>(
6957                callbackfn: (previousValue: U, currentValue: number) => U,
6958                initialValue: U): U {
6959        return this.reduce(
6960                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
6961                        callbackfn(prevVal, currVal),
6962                initialValue)
6963    }
6964
6965    /**
6966     * Calls the specified callback function for all the elements in an array.
6967     * The return value of the callback function is the accumulated result,
6968     * and is provided as an argument in the next call to the callback function.
6969     *
6970     * @param callbackfn A function that accepts one argument
6971     * The reduce method calls the callbackfn function one time for each element in the array.
6972     *
6973     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
6974     * The first call to the callbackfn function provides this value as an argument.
6975     *
6976     * @returns The value that results from running the callback function to completion over the entire typed array.
6977     */
6978    public reduce<U = number>(
6979                callbackfn: (previousValue: U) => U,
6980                initialValue: U): U {
6981        return this.reduce(
6982                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
6983                        callbackfn(prevVal),
6984                initialValue)
6985    }
6986
6987    /**
6988     * Calls the specified callback function for all the elements in an array.
6989     * The return value of the callback function is the accumulated result,
6990     * and is provided as an argument in the next call to the callback function.
6991     *
6992     * @param callbackfn A function that accepts no arguments
6993     * The reduce method calls the callbackfn function one time for each element in the array.
6994     *
6995     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
6996     * The first call to the callbackfn function provides this value as an argument.
6997     *
6998     * @returns The value that results from running the callback function to completion over the entire typed array.
6999     */
7000    public reduce<U = number>(
7001                callbackfn: () => U,
7002                initialValue: U): U {
7003        return this.reduce(
7004                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7005                        callbackfn(),
7006                initialValue)
7007    }
7008
7009    /**
7010     * Calls the specified callback function for all the elements in an array.
7011     * The return value of the callback function is the accumulated result,
7012     * and is provided as an argument in the next call to the callback function.
7013     *
7014     * @param callbackfn A function that accepts four arguments.
7015     * The reduce method calls the callbackfn function one time for each element in the array.
7016     * The first call to the callbackfn function provides array first element value as an argument
7017     *
7018     * @returns The value that results from running the callback function to completion over the entire typed array.
7019     * calling reduce method on an empty array without an initial value creates a TypeError
7020     */
7021    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number {
7022        if (this.lengthInt == 0) {
7023            throw new TypeError("Reduce of empty array with no initial value")
7024        }
7025
7026        let accumulatedValue = this.$_get(0) as number
7027        for (let i = 1; i < this.lengthInt; i++) {
7028            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7029        }
7030        return accumulatedValue
7031    }
7032
7033    /**
7034     * Calls the specified callback function for all the elements in an array.
7035     * The return value of the callback function is the accumulated result,
7036     * and is provided as an argument in the next call to the callback function.
7037     *
7038     * @param callbackfn A function that accepts three arguments.
7039     * The reduce method calls the callbackfn function one time for each element in the array.
7040     * The first call to the callbackfn function provides array first element value as an argument
7041     *
7042     * @returns The value that results from running the callback function to completion over the entire typed array.
7043     * calling reduce method on an empty array without an initial value creates a TypeError
7044     */
7045    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
7046        return this.reduce(
7047                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7048                        callbackfn(prevVal, currVal, currIndex))
7049    }
7050
7051    /**
7052     * Calls the specified callback function for all the elements in an array.
7053     * The return value of the callback function is the accumulated result,
7054     * and is provided as an argument in the next call to the callback function.
7055     *
7056     * @param callbackfn A function that accepts two arguments.
7057     * The reduce method calls the callbackfn function one time for each element in the array.
7058     * The first call to the callbackfn function provides array first element value as an argument
7059     *
7060     * @returns The value that results from running the callback function to completion over the entire typed array.
7061     * calling reduce method on an empty array without an initial value creates a TypeError
7062     */
7063    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
7064        return this.reduce(
7065                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7066                        callbackfn(prevVal, currVal))
7067    }
7068
7069    /**
7070     * Calls the specified callback function for all the elements in an array.
7071     * The return value of the callback function is the accumulated result,
7072     * and is provided as an argument in the next call to the callback function.
7073     *
7074     * @param callbackfn A function that accepts one argument.
7075     * The reduce method calls the callbackfn function one time for each element in the array.
7076     * The first call to the callbackfn function provides array first element value as an argument
7077     *
7078     * @returns The value that results from running the callback function to completion over the entire typed array.
7079     * calling reduce method on an empty array without an initial value creates a TypeError
7080     */
7081    public reduce(callbackfn: (previousValue: number) => number): number {
7082        return this.reduce(
7083                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7084                        callbackfn(prevVal))
7085    }
7086
7087    /**
7088     * Calls the specified callback function for all the elements in an array.
7089     * The return value of the callback function is the accumulated result,
7090     * and is provided as an argument in the next call to the callback function.
7091     *
7092     * @param callbackfn A function that accepts no arguments.
7093     * The reduce method calls the callbackfn function one time for each element in the array.
7094     * The first call to the callbackfn function provides array first element value as an argument
7095     *
7096     * @returns The value that results from running the callback function to completion over the entire typed array.
7097     * calling reduce method on an empty array without an initial value creates a TypeError
7098     */
7099    public reduce(callbackfn: () => number): number {
7100        return this.reduce(
7101                (prevVal: number, currVal: number, currIndex: number, array: Uint16Array) =>
7102                        callbackfn())
7103    }
7104
7105    /**
7106     * Calls the specified callback function for all the elements in an array, in descending order.
7107     * The return value of the callback function is the accumulated result,
7108     * and is provided as an argument in the next call to the callback function.
7109     *
7110     * @param callbackfn A function that accepts four arguments.
7111     * The reduceRight method calls the callbackfn function one time for each element in the array.
7112     *
7113     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7114     * The first call to the callbackfn function provides this value as an argument.
7115     *
7116     * @returns The value that results from running the callback function to completion over the entire typed array.
7117     */
7118    public reduceRight<U = number>(
7119                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U,
7120                initialValue: U): U {
7121        let accumulatedValue = initialValue
7122        for (let i = this.lengthInt - 1; i >= 0; i--) {
7123            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7124        }
7125        return accumulatedValue
7126    }
7127
7128    /**
7129     * Calls the specified callback function for all the elements in an array, in descending order.
7130     * The return value of the callback function is the accumulated result,
7131     * and is provided as an argument in the next call to the callback function.
7132     *
7133     * @param callbackfn A function that accepts three arguments.
7134     * The reduceRight method calls the callbackfn function one time for each element in the array.
7135     *
7136     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7137     * The first call to the callbackfn function provides this value as an argument.
7138     *
7139     * @returns The value that results from running the callback function to completion over the entire typed array.
7140     */
7141    public reduceRight<U = number>(
7142                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
7143                initialValue: U): U {
7144        return this.reduceRight(
7145                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7146                        callbackfn(prevVal, currVal, currIndex),
7147                initialValue)
7148    }
7149
7150    /**
7151     * Calls the specified callback function for all the elements in an array, in descending order.
7152     * The return value of the callback function is the accumulated result,
7153     * and is provided as an argument in the next call to the callback function.
7154     *
7155     * @param callbackfn A function that accepts two arguments.
7156     * The reduceRight method calls the callbackfn function one time for each element in the array.
7157     *
7158     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7159     * The first call to the callbackfn function provides this value as an argument.
7160     *
7161     * @returns The value that results from running the callback function to completion over the entire typed array.
7162     */
7163    public reduceRight<U = number>(
7164                callbackfn: (previuosValue: U, currentValue: number) => U,
7165                initialValue: U): U {
7166        return this.reduceRight(
7167                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7168                        callbackfn(prevVal, currVal),
7169                initialValue)
7170    }
7171
7172    /**
7173     * Calls the specified callback function for all the elements in an array, in descending order.
7174     * The return value of the callback function is the accumulated result,
7175     * and is provided as an argument in the next call to the callback function.
7176     *
7177     * @param callbackfn A function that accepts one argument.
7178     * The reduceRight method calls the callbackfn function one time for each element in the array.
7179     *
7180     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7181     * The first call to the callbackfn function provides this value as an argument.
7182     *
7183     * @returns The value that results from running the callback function to completion over the entire typed array.
7184     */
7185    public reduceRight<U = number>(
7186                callbackfn: (previuosValue: U) => U,
7187                initialValue: U): U {
7188        return this.reduceRight(
7189                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7190                        callbackfn(prevVal),
7191                initialValue)
7192    }
7193
7194    /**
7195     * Calls the specified callback function for all the elements in an array, in descending order.
7196     * The return value of the callback function is the accumulated result,
7197     * and is provided as an argument in the next call to the callback function.
7198     *
7199     * @param callbackfn A function that accepts no arguments.
7200     * The reduceRight method calls the callbackfn function one time for each element in the array.
7201     *
7202     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
7203     * The first call to the callbackfn function provides this value as an argument.
7204     *
7205     * @returns The value that results from running the callback function to completion over the entire typed array.
7206     */
7207    public reduceRight<U = number>(
7208                callbackfn: () => U,
7209                initialValue: U): U {
7210        return this.reduceRight(
7211                (prevVal: U, currVal: number, currIndex: number, array: Uint16Array) =>
7212                        callbackfn(),
7213                initialValue)
7214    }
7215
7216    /**
7217     * Calls the specified callback function for all the elements in an array, in descending order.
7218     * The return value of the callback function is the accumulated result,
7219     * and is provided as an argument in the next call to the callback function.
7220     *
7221     * @param callbackfn A function that accepts four arguments.
7222     * The reduceRight method calls the callbackfn function one time for each element in the array.
7223     * The first call to the callbackfn function provides array last element value as an argument
7224     *
7225     * @returns The value that results from running the callback function to completion over the entire typed array.
7226     * calling reduceRight method on an empty array without an initial value creates a TypeError
7227     */
7228    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number {
7229        if (this.lengthInt == 0) {
7230            throw new TypeError("Reduce of empty array with no initial value")
7231        }
7232
7233        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
7234        for (let i = this.lengthInt - 2; i >= 0; i--) {
7235            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7236        }
7237        return accumulatedValue
7238    }
7239
7240    /**
7241     * Calls the specified callback function for all the elements in an array, in descending order.
7242     * The return value of the callback function is the accumulated result,
7243     * and is provided as an argument in the next call to the callback function.
7244     *
7245     * @param callbackfn A function that accepts three arguments.
7246     * The reduceRight method calls the callbackfn function one time for each element in the array.
7247     * The first call to the callbackfn function provides array last element value as an argument
7248     *
7249     * @returns The value that results from running the callback function to completion over the entire typed array.
7250     * calling reduceRight method on an empty array without an initial value creates a TypeError
7251     */
7252    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
7253        return this.reduceRight(
7254                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7255                        callbackfn(prevValue, currValue, currIndex))
7256    }
7257
7258    /**
7259     * Calls the specified callback function for all the elements in an array, in descending order.
7260     * The return value of the callback function is the accumulated result,
7261     * and is provided as an argument in the next call to the callback function.
7262     *
7263     * @param callbackfn A function that accepts two arguments.
7264     * The reduceRight method calls the callbackfn function one time for each element in the array.
7265     * The first call to the callbackfn function provides array last element value as an argument
7266     *
7267     * @returns The value that results from running the callback function to completion over the entire typed array.
7268     * calling reduceRight method on an empty array without an initial value creates a TypeError
7269     */
7270    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
7271        return this.reduceRight(
7272                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7273                        callbackfn(prevValue, currValue))
7274    }
7275
7276    /**
7277     * Calls the specified callback function for all the elements in an array, in descending order.
7278     * The return value of the callback function is the accumulated result,
7279     * and is provided as an argument in the next call to the callback function.
7280     *
7281     * @param callbackfn A function that accepts one argument.
7282     * The reduceRight method calls the callbackfn function one time for each element in the array.
7283     * The first call to the callbackfn function provides array last element value as an argument
7284     *
7285     * @returns The value that results from running the callback function to completion over the entire typed array.
7286     * calling reduceRight method on an empty array without an initial value creates a TypeError
7287     */
7288    public reduceRight(callbackfn: (previousValue: number) => number): number {
7289        return this.reduceRight(
7290                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7291                        callbackfn(prevValue))
7292    }
7293
7294    /**
7295     * Calls the specified callback function for all the elements in an array, in descending order.
7296     * The return value of the callback function is the accumulated result,
7297     * and is provided as an argument in the next call to the callback function.
7298     *
7299     * @param callbackfn A function that accepts no arguments.
7300     * The reduceRight method calls the callbackfn function one time for each element in the array.
7301     * The first call to the callbackfn function provides array last element value as an argument
7302     *
7303     * @returns The value that results from running the callback function to completion over the entire typed array.
7304     * calling reduceRight method on an empty array without an initial value creates a TypeError
7305     */
7306    public reduceRight(callbackfn: () => number): number {
7307        return this.reduceRight(
7308                (prevValue: number, currValue: number, currIndex: number, array: Uint16Array) =>
7309                        callbackfn())
7310    }
7311
7312    /**
7313     * Creates a new Uint16Array using fn(arr[i]) over all elements of current Uint16Array.
7314     *
7315     * @param fn a function to apply for each element of current Uint16Array
7316     *
7317     * @returns a new Uint16Array where for each element from current Uint16Array fn was applied
7318     */
7319    public map(fn: (val: number, index: number) => number): Uint16Array {
7320        let resBuf = new ArrayBuffer(this.lengthInt * Uint16Array.BYTES_PER_ELEMENT as int)
7321        let res = new Uint16Array(resBuf)
7322        for (let i = 0; i < this.lengthInt; i++) {
7323            const fnRes = fn(this.getUnsafe(i) as number, i as number)
7324            res.setUnsafeClamp(i, fnRes as int)
7325        }
7326        return res
7327    }
7328
7329    /**
7330     * Determines whether the specified callback function returns true for all elements of an array.
7331     *
7332     * @param predicate A function that accepts three arguments.
7333     * The every method calls the predicate function for each element in the array until the predicate returns a false,
7334     * or until the end of the array.
7335     *
7336     * @returns true unless predicate function returns a false for an array element,
7337     * in which case false is immediately returned.
7338     */
7339    public every(predicate: (element: number, index: number, array: Uint16Array) => boolean): boolean {
7340        for (let i = 0; i < this.lengthInt; i++) {
7341            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
7342                return false
7343            }
7344        }
7345        return true
7346    }
7347
7348    /**
7349     * Determines whether the specified callback function returns true for all elements of an array.
7350     *
7351     * @param predicate A function that accepts two arguments.
7352     * The every method calls the predicate function for each element in the array until the predicate returns a false,
7353     * or until the end of the array.
7354     *
7355     * @returns true unless predicate function returns a false for an array element,
7356     * in which case false is immediately returned.
7357     */
7358    public every(predicate: (element: number, index: number) => boolean): boolean {
7359        return this.every((element: number, index: number, array: Uint16Array): boolean => predicate(element, index))
7360    }
7361
7362    /**
7363     * Determines whether the specified callback function returns true for all elements of an array.
7364     *
7365     * @param predicate A function that accepts no arguments.
7366     * The every method calls the predicate function for each element in the array until the predicate returns a false,
7367     * or until the end of the array.
7368     *
7369     * @returns true unless predicate function returns a false for an array element,
7370     * in which case false is immediately returned.
7371     */
7372    public every(predicate: () => boolean): boolean {
7373        return this.every((element: number, index: number, array: Uint16Array): boolean => predicate())
7374    }
7375
7376    /**
7377     * Creates a new Uint16Array from current Uint16Array based on a condition fn.
7378     *
7379     * @param fn the condition to apply for each element
7380     *
7381     * @returns a new Uint16Array with elements from current Uint16Array that satisfy condition fn
7382     */
7383    public filter(fn: (val: number, index: number, array: Uint16Array) => boolean): Uint16Array {
7384        let markers = new boolean[this.lengthInt]
7385        let resLen = 0
7386        for (let i = 0; i < this.lengthInt; i++) {
7387            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
7388            if (markers[i]) {
7389                ++resLen
7390            }
7391        }
7392        let res = new Uint16Array(resLen)
7393        for (let i = 0, j = 0; i < this.lengthInt; i++) {
7394            if (markers[i]) {
7395                res.setUnsafe(j, this.getUnsafe(i))
7396                ++j
7397            }
7398        }
7399        return res
7400    }
7401
7402    /**
7403     * creates a new Uint16Array from current Uint16Array based on a condition fn
7404     *
7405     * @param fn the condition to apply for each element
7406     *
7407     * @returns a new Uint16Array with elements from current Uint16Array that satisfy condition fn
7408     */
7409    public filter(fn: (val: number, index: number) => boolean): Uint16Array {
7410        let newF: (val: number, index: number, array: Uint16Array) => boolean =
7411            (val: number, index: number, array: Uint16Array): boolean => { return fn(val, index) }
7412        return this.filter(newF)
7413    }
7414
7415    /**
7416     * Returns the value of the first element in the array where predicate is true, and undefined
7417     * otherwise
7418     *
7419     * @param predicate find calls predicate once for each element of the array, in ascending
7420     * order, until it finds one where predicate returns true. If such an element is found, find
7421     * immediately returns that element value. Otherwise, find returns undefined
7422     *
7423     * @returns number | undefined
7424     */
7425    public find(predicate: (value: number, index: number, array: Uint16Array) => boolean): number | undefined {
7426        for (let i = 0; i < this.lengthInt; i++) {
7427            let val = this.getUnsafe(i) as number
7428            if (predicate(val, i as number, this)) {
7429                return val
7430            }
7431        }
7432        return undefined
7433    }
7434
7435    /**
7436     * Returns the value of the first element in the array where predicate is true, and undefined
7437     * otherwise
7438     *
7439     * @param predicate find calls predicate once for each element of the array, in ascending
7440     * order, until it finds one where predicate returns true. If such an element is found, find
7441     * immediately returns that element value. Otherwise, find returns undefined
7442     *
7443     * @returns number | undefined
7444     */
7445    public find(predicate: (value: number, index: number) => boolean): number | undefined {
7446        return this.find((value: number, index: number, obj: Uint16Array): boolean => predicate(value, index))
7447    }
7448
7449    /**
7450     * Returns the index of the first element in the array where predicate is true, and -1
7451     * otherwise
7452     *
7453     * @param predicate find calls predicate once for each element of the array, in ascending
7454     * order, until it finds one where predicate returns true. If such an element is found,
7455     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
7456     *
7457     * @returns number
7458     */
7459    public findIndex(predicate: (value: number, index: number, obj: Uint16Array) => boolean): number {
7460        for (let i = 0; i < this.lengthInt; i++) {
7461            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
7462                return i as number
7463            }
7464        }
7465        return -1 as number
7466    }
7467
7468    /**
7469     * Returns the index of the first element in the array where predicate is true, and -1
7470     * otherwise
7471     *
7472     * @param predicate find calls predicate once for each element of the array, in ascending
7473     * order, until it finds one where predicate returns true. If such an element is found,
7474     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
7475     *
7476     * @returns number
7477     */
7478    public findIndex(predicate: (value: number, index: number) => boolean): number {
7479        return this.findIndex((value: number, index: number, obj: Uint16Array): boolean => predicate(value, index))
7480    }
7481
7482    /**
7483     * Returns the index of the first element in the array where predicate is true, and -1
7484     * otherwise
7485     *
7486     * @param predicate find calls predicate once for each element of the array, in ascending
7487     * order, until it finds one where predicate returns true. If such an element is found,
7488     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
7489     *
7490     * @returns number
7491     */
7492    public findIndex(predicate: () => boolean): number {
7493        return this.findIndex((value: number, index: number, obj: Uint16Array): boolean => predicate())
7494    }
7495
7496    /**
7497     * Finds the last element in the Uint16Array that satisfies the condition
7498     *
7499     * @param fn condition
7500     *
7501     * @returns the last element that satisfies fn
7502     */
7503    public findLast(fn: (val: number, index: number, array: Uint16Array) => boolean): number {
7504        for (let i = this.lengthInt - 1; i >= 0; i--) {
7505            let val = this.getUnsafe(i) as number
7506            if (fn(val, i as number, this)) {
7507                return val
7508            }
7509        }
7510        throw new Error("Uint16Array.findLast: not implemented if an element was not found")
7511    }
7512
7513    /**
7514     * Finds the last element in the Uint16Array that satisfies the condition
7515     *
7516     * @param fn condition
7517     *
7518     * @returns the last element that satisfies fn
7519     */
7520    public findLast(fn: (val: number, index: number) => boolean): number {
7521        let newF: (val: number, index: number, array: Uint16Array) => boolean =
7522            (val: number, index: number, array: Uint16Array): boolean => { return fn(val, index) }
7523        return this.findLast(newF)
7524    }
7525
7526    /**
7527     * Finds an index of the last element in the Uint16Array that satisfies the condition
7528     *
7529     * @param fn condition
7530     *
7531     * @returns the index of the last element that satisfies fn, -1 otherwise
7532     */
7533    public findLastIndex(fn: (val: number, index: number, array: Uint16Array) => boolean): number {
7534        for (let i = this.lengthInt - 1; i >= 0; i--) {
7535            if (fn(this.getUnsafe(i) as number, i as number, this)) {
7536                return i as number
7537            }
7538        }
7539        return -1 as number
7540    }
7541
7542    /**
7543     * Finds an index of the last element in the Uint16Array that satisfies the condition
7544     *
7545     * @param fn condition
7546     *
7547     * @returns the index of the last element that satisfies fn, -1 otherwise
7548     */
7549    public findLastIndex(fn: (val: number, index: number) => boolean): number {
7550        let newF: (val: number, index: number, array: Uint16Array) => boolean =
7551            (val: number, index: number, array: Uint16Array): boolean => { return fn(val, index) }
7552        return this.findLastIndex(newF) as number
7553    }
7554
7555    /**
7556     * Performs the specified action for each element in Uint16Array
7557     *
7558     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
7559     * callbackfn function one time for each element in the array.
7560     *
7561     * @returns None
7562     */
7563    public forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void): void {
7564        for (let i = 0; i < this.lengthInt; i++) {
7565            callbackfn(this.getUnsafe(i) as number, i as number, this)
7566        }
7567    }
7568
7569    /**
7570     * Performs the specified action for each element in Uint16Array
7571     *
7572     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
7573     * callbackfn function one time for each element in the array.
7574     *
7575     * @returns None
7576     */
7577    public forEach(callbackfn: (value: number, index: number) => void): void {
7578        this.forEach((value: number, index: number, array: Uint16Array): void => callbackfn(value, index))
7579    }
7580
7581    /**
7582     * Performs the specified action for each element in Uint16Array
7583     *
7584     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
7585     * callbackfn function one time for each element in the array.
7586     *
7587     * @returns None
7588     */
7589    public forEach(callbackfn: () => void): void {
7590        this.forEach((value: number, index: number, array: Uint16Array): void => callbackfn())
7591    }
7592
7593    /**
7594     * Returns the object itself
7595     *
7596     * @returns Uint16Array
7597     */
7598    public valueOf(): Uint16Array {
7599        return this
7600    }
7601
7602    /** Byte offset within the underlying Buffer */
7603    public get byteOffset(): number {
7604        return this.byteOffsetInt
7605    }
7606
7607    /** Number of bytes used */
7608    public get byteLength(): number {
7609        return this.byteLengthInt
7610    }
7611
7612    /** Number of int stored in Uint16Array */
7613    public get length(): number {
7614        return this.lengthInt
7615    }
7616
7617    /** String \"Uint16Array\" */
7618    public readonly name = "Uint16Array"
7619
7620    private static clamp(val: int): int {
7621        return val
7622    }
7623
7624    internal setUnsafeClamp(insertPos: int, val: int): void {
7625        this.setUnsafe(insertPos, val)
7626    }
7627
7628    internal getUnsafe(index: int): int {
7629        index = index * Uint16Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
7630        let res: int = 0
7631        if (IS_LITTLE_ENDIAN) {
7632            if (this.buffer instanceof ArrayBuffer) {
7633                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7634                    let el = (this.buffer as ArrayBuffer).at(index + i) as int
7635                    el &= 0xff
7636                    res |= el << (8 * i)
7637                }
7638            } else if (this.buffer instanceof SharedArrayBuffer) {
7639                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7640                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as int
7641                    el &= 0xff
7642                    res |= el << (8 * i)
7643                }
7644            } else {
7645                throw new Error("unexpected type of ArrayBufferLike")
7646            }
7647        } else {
7648            if (this.buffer instanceof ArrayBuffer) {
7649                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7650                    let el = (this.buffer as ArrayBuffer).at(index + 1 - i) as int
7651                    el &= 0xff
7652                    res |= el << (8 * i)
7653                }
7654            } else if (this.buffer instanceof SharedArrayBuffer) {
7655                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7656                    let el = (this.buffer as SharedArrayBuffer).at(index + 1 - i) as int
7657                    el &= 0xff
7658                    res |= el << (8 * i)
7659                }
7660            } else {
7661                throw new Error("unexpected type of ArrayBufferLike")
7662            }
7663        }
7664        return res
7665    }
7666
7667    internal setUnsafe(index: int, val: int): void {
7668        index = index * Uint16Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
7669        let res: int = 0
7670        if (IS_LITTLE_ENDIAN) {
7671            if (this.buffer instanceof ArrayBuffer) {
7672                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7673                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
7674                    val = val >> 8
7675                }
7676            } else if (this.buffer instanceof SharedArrayBuffer) {
7677                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7678                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
7679                    val = val >> 8
7680                }
7681            } else {
7682                throw new Error("unexpected type of ArrayBufferLike")
7683            }
7684        } else {
7685            if (this.buffer instanceof ArrayBuffer) {
7686                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7687                    (this.buffer as ArrayBuffer).set(index + 1 - i, (val & 0xff) as byte)
7688                    val = val >> 8
7689                }
7690            } else if (this.buffer instanceof SharedArrayBuffer) {
7691                for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
7692                    (this.buffer as SharedArrayBuffer).set(index + 1 - i, (val & 0xff) as byte)
7693                    val = val >> 8
7694                }
7695            } else {
7696                throw new Error("unexpected type of ArrayBufferLike")
7697            }
7698        }
7699    }
7700}
7701
7702
7703class Uint32ArrayIteratorKeys implements IterableIterator<number> {
7704    private length: int = 0
7705    private idx: int = 0
7706
7707    constructor(parent: Uint32Array) {
7708        this.length = parent.length as int
7709    }
7710
7711    public override $_iterator(): IterableIterator<Number> {
7712        return this
7713    }
7714
7715    override next(): IteratorResult<number> {
7716        if (this.idx < 0 || this.idx >= this.length) {
7717            return new IteratorResult<number>()
7718        }
7719        return new IteratorResult<number>(false, this.idx++ as number)
7720    }
7721}
7722
7723class Uint32ArrayIterator implements IterableIterator<Number> {
7724    private parent: Uint32Array
7725    private idx: int = 0
7726
7727    constructor(parent: Uint32Array) {
7728        this.parent = parent
7729    }
7730
7731    public override $_iterator(): IterableIterator<Number> {
7732        return this
7733    }
7734
7735    override next(): IteratorResult<Number> {
7736        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
7737            return new IteratorResult<Number>()
7738        }
7739        return new IteratorResult<Number>(false, new Number(this.parent.getUnsafe(this.idx++)))
7740    }
7741}
7742
7743class Uint32ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
7744    private parent: Uint32Array
7745    private idx: int = 0
7746
7747    constructor(parent: Uint32Array) {
7748        this.parent = parent
7749    }
7750
7751    public override $_iterator(): IterableIterator<[Number, Number]> {
7752        return this
7753    }
7754
7755    override next(): IteratorResult<[Number, Number]> {
7756        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
7757            return new IteratorResult<[Number, Number]>()
7758        }
7759        return new IteratorResult<[Number, Number]>(
7760            false,
7761            [new Number(this.idx), new Number(this.parent.getUnsafe(this.idx++))]
7762        )
7763    }
7764}
7765
7766/**
7767 * JS Uint32Array API-compatible class
7768 */
7769export class Uint32Array implements Iterable<Number>, ArrayLike<Number> {
7770    public static readonly BYTES_PER_ELEMENT: number = 4
7771
7772    /** Underlying Buffer */
7773    public readonly buffer: ArrayBufferLike
7774
7775    internal readonly byteOffsetInt: int
7776    internal readonly byteLengthInt: int
7777    internal readonly lengthInt: int
7778
7779    /**
7780     * Creates an empty Uint32Array.
7781     */
7782    public constructor() {
7783        this(0 as int)
7784    }
7785
7786    /**
7787     * Creates an Uint32Array with respect to data accessed via Iterable<Number> interface
7788     */
7789    public constructor(elements: Iterable<Number>) {
7790        // NOTE (ikorobkov): dealing with this overload is tricky
7791        // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
7792        let arr = Array.from<Number>(elements)
7793        this.byteLengthInt = arr.length as int * Uint32Array.BYTES_PER_ELEMENT as int
7794        this.lengthInt = arr.length as int
7795        this.buffer = new ArrayBuffer(this.byteLengthInt)
7796        this.byteOffsetInt = 0
7797        for (let i: int = 0; i < this.lengthInt; ++i) {
7798            this.setUnsafe(i, arr.$_get(i).longValue())
7799        }
7800    }
7801
7802    /**
7803     * Creates an Uint32Array with respect to data, byteOffset and length.
7804     *
7805     * @param buf data initializer
7806     *
7807     * @param byteOffset byte offset from begin of the buf
7808     *
7809     * @param length size of elements of type long in newly created Uint32Array
7810     */
7811    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
7812        let intByteOffset: int = 0
7813        if (byteOffset != undefined) {
7814            intByteOffset = byteOffset.intValue()
7815            if (intByteOffset < 0) {
7816                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
7817            }
7818        }
7819        let intByteLength: int
7820        if (buf instanceof ArrayBuffer) {
7821            intByteLength = (buf as ArrayBuffer).getByteLength()
7822        } else if (buf instanceof SharedArrayBuffer) {
7823            intByteLength = (buf as SharedArrayBuffer).getByteLength()
7824        } else {
7825            throw new Error("unexpected type of ArrayBufferLike")
7826        }
7827        intByteLength = intByteLength - intByteOffset
7828        if (intByteLength < 0) {
7829            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
7830        }
7831
7832        if (intByteLength % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
7833            throw new RangeError("ArrayBufferLike.byteLength should be multiple of 4 as Uint32Array.BYTES_PER_ELEMENT")
7834        }
7835        if (intByteOffset % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
7836            throw new RangeError("byteOffset should be multiple of 4 as Uint32Array.BYTES_PER_ELEMENT")
7837        }
7838
7839        let intLength: int
7840        if (length != undefined) {
7841            intLength = length.intValue()
7842            if (intLength > intByteLength / Uint32Array.BYTES_PER_ELEMENT as int) {
7843                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
7844            }
7845        } else {
7846            intLength = intByteLength / Uint32Array.BYTES_PER_ELEMENT as int
7847        }
7848        if (intLength < 0) {
7849            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
7850        }
7851        if (intLength < intByteLength / Uint32Array.BYTES_PER_ELEMENT as int) {
7852            intByteLength = intLength * Uint32Array.BYTES_PER_ELEMENT as int
7853        }
7854        this.byteLengthInt = intByteLength
7855        this.byteOffsetInt = intByteOffset
7856        this.lengthInt = intLength
7857        this.buffer = buf
7858    }
7859
7860    /**
7861     * Creates an Uint32Array with respect to data, byteOffset and length.
7862     *
7863     * @param buf data initializer
7864     *
7865     * @param byteOffset byte offset from begin of the buf
7866     */
7867    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
7868        this(buf, byteOffset, undefined)
7869    }
7870
7871    /**
7872     * Creates an Uint32Array with respect to data, byteOffset and length.
7873     *
7874     * @param buf data initializer
7875     *
7876     * @param byteOffset byte offset from begin of the buf
7877     *
7878     * @param length size of elements of type long in newly created Uint32Array
7879     */
7880    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
7881        this(buf, new Number(byteOffset), new Number(length))
7882    }
7883
7884    /**
7885     * Creates an Uint32Array with respect to buf and byteOffset.
7886     *
7887     * @param buf data initializer
7888     *
7889     * @param byteOffset byte offset from begin of the buf
7890     */
7891    public constructor(buf: ArrayBufferLike, byteOffset: number) {
7892        this(buf, new Number(byteOffset), undefined)
7893    }
7894
7895    /**
7896     * Creates an Uint32Array with respect to data, byteOffset and length.
7897     *
7898     * @param buf data initializer
7899     *
7900     * @param byteOffset byte offset from begin of the buf
7901     *
7902     * @param length size of elements of type long in newly created Uint32Array
7903     */
7904    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
7905        this(buf, new Number(byteOffset), new Number(length))
7906    }
7907
7908    /**
7909     * Creates an Uint32Array with respect to buf and byteOffset.
7910     *
7911     * @param buf data initializer
7912     *
7913     * @param byteOffset byte offset from begin of the buf
7914     */
7915    public constructor(buf: ArrayBufferLike, byteOffset: int) {
7916        this(buf, new Number(byteOffset), undefined)
7917    }
7918
7919    /**
7920     * Creates an Uint32Array with respect to buf.
7921     *
7922     * @param buf data initializer
7923     */
7924    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
7925        if (buf instanceof ArrayBuffer) {
7926            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
7927            if (this.byteLengthInt % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
7928               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as Uint32Array.BYTES_PER_ELEMENT")
7929            }
7930            this.lengthInt = this.byteLengthInt / Uint32Array.BYTES_PER_ELEMENT as int
7931            this.buffer = buf as ArrayBuffer
7932            this.byteOffsetInt = 0
7933        } else if (buf instanceof SharedArrayBuffer) {
7934            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
7935            if (this.byteLengthInt % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
7936               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as Uint32Array.BYTES_PER_ELEMENT")
7937            }
7938            this.lengthInt = this.byteLengthInt / Uint32Array.BYTES_PER_ELEMENT as int
7939            this.buffer = buf as SharedArrayBuffer
7940            this.byteOffsetInt = 0
7941        } else if (buf instanceof ArrayLike) {
7942            // NOTE (ikorobkov): dealing with this overload is tricky
7943            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
7944            let arr = Array.from<Number>((buf as ArrayLike<Number>))
7945            this.byteLengthInt = arr.length as int * Uint32Array.BYTES_PER_ELEMENT as int
7946            this.lengthInt = arr.length as int
7947            this.buffer = new ArrayBuffer(this.byteLengthInt)
7948            this.byteOffsetInt = 0
7949            for (let i: int = 0; i < this.lengthInt; ++i) {
7950                this.setUnsafe(i, arr.$_get(i).longValue())
7951            }
7952        } else {
7953            throw new Error("unexpected type of buf")
7954        }
7955    }
7956
7957    /**
7958     * Creates an Uint32Array with respect to length.
7959     *
7960     * @param length data initializer
7961     */
7962    public constructor(length: int) {
7963        if (length < 0) {
7964            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
7965        }
7966        this.lengthInt = length
7967        this.byteLengthInt = length * Uint32Array.BYTES_PER_ELEMENT as int
7968        this.byteOffsetInt = 0
7969        this.buffer = new ArrayBuffer(this.byteLengthInt)
7970    }
7971
7972    /**
7973     * Creates an Uint32Array with respect to length.
7974     *
7975     * @param length data initializer
7976     */
7977    public constructor(length: number) {
7978        this(length as int)
7979    }
7980
7981    /**
7982     * Creates a copy of Uint32Array.
7983     *
7984     * @param other data initializer
7985     */
7986    public constructor(other: Uint32Array) {
7987        if (other.buffer instanceof ArrayBuffer) {
7988            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
7989        } else if (other.buffer instanceof SharedArrayBuffer) {
7990            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
7991        } else {
7992            throw new Error("unexpected type of buffer")
7993        }
7994        this.byteLengthInt = other.byteLength as int
7995        this.lengthInt = other.length as int
7996        this.byteOffsetInt = 0
7997    }
7998
7999    /**
8000     * Creates an Uint32Array from number[]
8001     */
8002    public constructor(numbers: number[]) {
8003        this(numbers.length)
8004        for (let i: int = 0; i < this.lengthInt; ++i) {
8005            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as long)
8006        }
8007    }
8008
8009    /**
8010     * Creates an Uint32Array from int[]
8011     */
8012    public constructor(numbers: int[]) {
8013        this(numbers.length)
8014        for (let i: int = 0; i < this.lengthInt; ++i) {
8015            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as long)
8016        }
8017    }
8018
8019    internal zeroIfInfinity(val: number): number {
8020        if ((val == Infinity) || (val == -Infinity)) {
8021            return 0 as number
8022        }
8023        return val as number
8024    }
8025
8026    internal zeroIfInfinity(val: long): long {
8027        if ((val == Infinity) || (val == -Infinity)) {
8028            return 0 as long
8029        }
8030        return val
8031    }
8032
8033    /**
8034     * Iteratorable interface implementation
8035     *
8036     * @returns iterator over all elements
8037     */
8038    public override $_iterator(): IterableIterator<Number> {
8039         return this.values()
8040    }
8041
8042    /**
8043     * Returns an instance of primitive type at passed index.
8044     *
8045     * @param index index to look at
8046     *
8047     * @returns a primitive at index
8048     */
8049    public at(index: number): Number | undefined {
8050        return this.at(index as int)
8051    }
8052
8053    /**
8054     * Returns an instance of primitive type at passed index if index is correct.
8055     *
8056     * @param index index to look at
8057     *
8058     * @returns a primitive at index
8059     */
8060    public at(index: int): Number | undefined {
8061        let k: int
8062        if (index >= 0) {
8063            k = index
8064        } else {
8065            k = this.lengthInt + index
8066        }
8067        if (k < 0 || k >= this.lengthInt) {
8068            return undefined
8069        }
8070        return new Number(this.getUnsafe(k))
8071    }
8072
8073    /**
8074     * Returns an instance of number at passed index.
8075     *
8076     * @param index index to look at
8077     *
8078     * @returns a primitive at index
8079     */
8080    public override $_get(index: number): Number {
8081        return this.$_get(index as int) as Number
8082    }
8083
8084    /**
8085     * Returns an instance of number at passed index.
8086     *
8087     * @param index index to look at
8088     *
8089     * @returns a primitive at index
8090     */
8091    public $_get(i: int): number {
8092        if (i < 0 || i >= this.lengthInt) {
8093            throw new RangeError("invalid offset")
8094        }
8095        return this.getUnsafe(i) as number
8096    }
8097
8098    /**
8099     * Assigns val as element on index.
8100     *
8101     * @param val value to set
8102     *
8103     * @param index index to change
8104     */
8105    public $_set(index: number, val: number): void {
8106        this.$_set(index as int, val)
8107    }
8108
8109    /**
8110     * Assigns val as element on index.
8111     *
8112     * @param val value to set
8113     *
8114     * @param index index to change
8115     */
8116    public $_set(index: int, val: number): void {
8117        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
8118        if (index < 0 || index >= this.lengthInt) {
8119            throw new RangeError("invalid index")
8120        }
8121        let v = this.zeroIfInfinity(val)
8122        this.setUnsafeClamp(index, v as long)
8123    }
8124
8125    /**
8126     * Assigns val as element on index.
8127     *
8128     * @param val value to set
8129     *
8130     * @param index index to change
8131     */
8132    public $_set(index: number, val: long): void {
8133        this.$_set(index as int, val)
8134    }
8135
8136    /**
8137     * Assigns val as element on index.
8138     *
8139     * @param val value to set
8140     *
8141     * @param index index to change
8142     */
8143    public $_set(index: int, val: long): void {
8144        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
8145        if (index < 0 || index >= this.lengthInt) {
8146            throw new RangeError("invalid index")
8147        }
8148        let v = this.zeroIfInfinity(val)
8149        this.setUnsafeClamp(index, v)
8150    }
8151
8152    /**
8153     * Assigns val as element on index.
8154     *
8155     * @param val value to set
8156     *
8157     * @param index index to change
8158     */
8159    public $_set(index: number, val: int): void {
8160        this.$_set(index as int, val as int)
8161    }
8162
8163    /**
8164     * Assigns val as element on index.
8165     *
8166     * @param val value to set
8167     *
8168     * @param index index to change
8169     */
8170    public $_set(index: int, val: int): void {
8171        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
8172        if (index < 0 || index >= this.lengthInt) {
8173            throw new RangeError("invalid index")
8174        }
8175        let v = this.zeroIfInfinity(val as long)
8176        this.setUnsafeClamp(index, v)
8177    }
8178
8179    /**
8180     * Makes a copy of internal elements to targetPos from startPos to endPos.
8181     *
8182     * @param target insert index to place copied elements
8183     *
8184     * @param start start index to begin copy from
8185     *
8186     * @param end last index to end copy from, excluded
8187     *
8188     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8189     */
8190    public copyWithin(target: number, start: number, end?: number): Uint32Array {
8191        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8192    }
8193
8194    /**
8195     * Makes a copy of internal elements to targetPos from startPos to endPos.
8196     *
8197     * @param target insert index to place copied elements
8198     *
8199     * @param start start index to begin copy from
8200     *
8201     * @param end last index to end copy from, excluded
8202     *
8203     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8204     */
8205    public copyWithin(target: int, start: number, end?: number): Uint32Array {
8206        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8207    }
8208
8209    /**
8210     * Makes a copy of internal elements to targetPos from startPos to endPos.
8211     *
8212     * @param target insert index to place copied elements
8213     *
8214     * @param start start index to begin copy from
8215     *
8216     * @param end last index to end copy from, excluded
8217     *
8218     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8219     */
8220    public copyWithin(target: number, start: int, end?: number): Uint32Array {
8221        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8222    }
8223
8224    /**
8225     * Makes a copy of internal elements to targetPos from startPos to endPos.
8226     *
8227     * @param target insert index to place copied elements
8228     *
8229     * @param start start index to begin copy from
8230     *
8231     * @param end last index to end copy from, excluded
8232     *
8233     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8234     */
8235    public copyWithin(target: int, start: int, end?: number): Uint32Array {
8236        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
8237    }
8238
8239    /**
8240     * Makes a copy of internal elements to targetPos from startPos to endPos.
8241     *
8242     * @param insert insert index to place copied elements
8243     *
8244     * @param start start index to begin copy from
8245     *
8246     * @param end last index to end copy from, excluded
8247     *
8248     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
8249     */
8250    public copyWithin(target: int, start: int, end: int): Uint32Array {
8251        let toPos = normalizeIndex(target, this.lengthInt)
8252        let fromPos = normalizeIndex(start, this.lengthInt)
8253        const finalPos = normalizeIndex(end, this.lengthInt)
8254        let count: int = finalPos - fromPos
8255        if (count > (this.lengthInt - toPos)) {
8256            count = this.lengthInt - toPos
8257        }
8258        let direction: int = 1
8259        if ((fromPos < toPos) && (toPos < fromPos + count)) {
8260            fromPos = fromPos + count - 1
8261            toPos   = toPos   + count - 1
8262            direction = -1
8263        }
8264        while (count > 0) {
8265            const value = this.getUnsafe(fromPos)
8266            this.setUnsafe(toPos, value)
8267            fromPos = fromPos + direction
8268            toPos = toPos + direction
8269            --count
8270        }
8271        return this
8272    }
8273
8274    /**
8275     * Makes a copy of internal elements to targetPos from begin to end of Uint32Array.
8276     *
8277     * @param target insert index to place copied elements
8278     *
8279     * See rules of parameters normalization:
8280     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
8281     */
8282    public copyWithin(target: number): Uint32Array {
8283        return this.copyWithin(target as int)
8284    }
8285
8286    /**
8287     * Makes a copy of internal elements to targetPos from begin to end of Uint32Array.
8288     *
8289     * @param insert insert index to place copied elements
8290     *
8291     * See rules of parameters normalization:
8292     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
8293     */
8294    public copyWithin(target: int): Uint32Array {
8295        return this.copyWithin(target, 0, this.lengthInt)
8296    }
8297
8298    /**
8299     * Returns an array of key, value pairs for every entry in the Uint32Array
8300     *
8301     * @returns key, value pairs for every entry in the array
8302     */
8303    public entries(): IterableIterator<[Number, Number]> {
8304        return new Uint32ArrayIteratorEntries(this)
8305    }
8306
8307    /**
8308     * Fills the Uint32Array with specified value
8309     *
8310     * @param value new value
8311     *
8312     * @returns modified Uint32Array
8313     */
8314    public fill(value: number, start?: number, end?: number): Uint32Array {
8315        value = this.zeroIfInfinity(value)
8316        this.fill(value as long, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
8317        return this
8318    }
8319
8320    /**
8321     * Fills the Uint32Array with specified value
8322     *
8323     * @param value new value
8324     *
8325     * @returns modified Uint32Array
8326     */
8327    public fill(value: number, start: int, end?: number): Uint32Array {
8328        value = this.zeroIfInfinity(value)
8329        this.fill(value as long, start as int, asIntOrDefault(end, this.lengthInt))
8330        return this
8331    }
8332
8333    /**
8334     * Fills the Uint32Array with specified value
8335     *
8336     * @param value new value
8337     *
8338     * @returns modified Uint32Array
8339     */
8340    public fill(value: number, start: int, end: number): Uint32Array {
8341        value = this.zeroIfInfinity(value)
8342        this.fill(value as long, start as int, end as int)
8343        return this
8344    }
8345
8346    /**
8347     * Fills the Uint32Array with specified value
8348     *
8349     * @param value new value
8350     *
8351     * @returns modified Uint32Array
8352     */
8353    public fill(value: number, start: number, end: int): Uint32Array {
8354        value = this.zeroIfInfinity(value)
8355        this.fill(value as long, start as int, end as int)
8356        return this
8357    }
8358
8359    /**
8360     * Fills the Uint32Array with specified value
8361     *
8362     * @param value new value
8363     *
8364     * @returns modified Uint32Array
8365     */
8366    public fill(value: number, start: int, end: int): Uint32Array {
8367        value = this.zeroIfInfinity(value)
8368        this.fill(value as long, start as int, end as int)
8369        return this
8370    }
8371
8372    /**
8373     * Fills the Uint32Array with specified value
8374     *
8375     * @param value new value
8376     *
8377     * @returns modified Uint32Array
8378     */
8379    public fill(value: long, start?: number, end?: number): Uint32Array {
8380        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
8381        return this
8382    }
8383
8384    /**
8385     * Fills the Uint32Array with specified value
8386     *
8387     * @param value new value
8388     *
8389     * @returns modified Uint32Array
8390     */
8391    public fill(value: long, start: int, end?: number): Uint32Array {
8392        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
8393        return this
8394    }
8395
8396    /**
8397     * Fills the Uint32Array with specified value
8398     *
8399     * @param value new value
8400     *
8401     * @returns modified Uint32Array
8402     */
8403    public fill(value: long, start: int, end: number): Uint32Array {
8404        this.fill(value, start as int, end as int)
8405        return this
8406    }
8407
8408    /**
8409     * Fills the Uint32Array with specified value
8410     *
8411     * @param value new value
8412     *
8413     * @returns modified Uint32Array
8414     */
8415    public fill(value: long, start: number, end: int): Uint32Array {
8416        this.fill(value, start as int, end as int)
8417        return this
8418    }
8419
8420    /**
8421     * Fills the Uint32Array with specified value
8422     *
8423     * @param value new value
8424     *
8425     * @returns modified Uint32Array
8426     */
8427    public fill(value: long, start: int, end: int): Uint32Array {
8428        const k = normalizeIndex(start, this.lengthInt)
8429        const finalPos = normalizeIndex(end, this.lengthInt)
8430        for (let i: int = k; i < finalPos; ++i) {
8431            this.setUnsafe(i, value)
8432        }
8433        return this
8434    }
8435
8436    /**
8437     * Assigns val as element on index.
8438     *
8439     * @param val value to set
8440     *
8441     * @param index index to change
8442     */
8443    public set(insertPos: number, val: number): void {
8444        this.$_set(insertPos as int, val)
8445    }
8446
8447    /**
8448     * Assigns val as element on index.
8449     *
8450     * @param val value to set
8451     *
8452     * @param index index to change
8453     */
8454    public set(insertPos: int, val: number): void {
8455        this.$_set(insertPos as int, val)
8456    }
8457
8458    /**
8459     * Assigns val as element on index.
8460     *
8461     * @param val value to set
8462     *
8463     * @param index index to change
8464     */
8465    public set(insertPos: number, val: long): void {
8466        this.$_set(insertPos as int, val)
8467    }
8468
8469    /**
8470     * Assigns val as element on index.
8471     *
8472     * @param val value to set
8473     *
8474     * @param index index to change
8475     */
8476    public set(insertPos: int, val: long): void {
8477        this.$_set(insertPos as int, val)
8478    }
8479
8480    /**
8481     * Copies all elements of arr to the current Uint32Array starting from insertPos.
8482     *
8483     * @param arr array to copy data from
8484     *
8485     * @param insertPos start index where data from arr will be inserted
8486     *
8487     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
8488     */
8489    public set(arr: number[], insertPos1: number): void {
8490        const insertPos = insertPos1 as int
8491        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
8492            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than Uint32Array.length")
8493        }
8494        for (let i = 0; i < arr.length; i++) {
8495            let v = this.zeroIfInfinity(arr[i])
8496            this.setUnsafeClamp(insertPos as int + i as int, v as long)
8497        }
8498    }
8499
8500    /**
8501     * Copies all elements of arr to the current Uint32Array starting from insertPos.
8502     *
8503     * @param arr array to copy data from
8504     *
8505     * @param insertPos start index where data from arr will be inserted
8506     *
8507     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
8508     */
8509    public set(arr: long[], insertPos: int): void {
8510        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
8511            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than Uint32Array.length")
8512        }
8513        for (let i = 0; i < arr.length; i++) {
8514            let v = this.zeroIfInfinity(arr[i])
8515            this.setUnsafeClamp(insertPos + i, v)
8516        }
8517    }
8518
8519    /**
8520     * Copies all elements of arr to the current Uint32Array.
8521     *
8522     * @param arr array to copy data from
8523     */
8524    public set(arr: number[]): void {
8525        this.set(arr, 0)
8526    }
8527
8528    /**
8529     * Copies all elements of arr to the current Uint32Array.
8530     *
8531     * @param arr array to copy data from
8532     */
8533    public set(arr: long[]): void {
8534        this.set(arr, 0)
8535    }
8536
8537    /**
8538     * Copies elements from an ArrayLike object to the Uint32Array.
8539     *
8540     * @param array An ArrayLike object containing the elements to copy.
8541     *
8542     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
8543     */
8544    public set(array: ArrayLike<number>, offset: number = 0): void {
8545        const insertPos = offset as int
8546        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
8547            throw new RangeError("offset is out of bounds")
8548        }
8549        for (let i = 0; i < array.length; i++) {
8550            let v = this.zeroIfInfinity(array[i])
8551            this.setUnsafeClamp(insertPos as int + i as int, v as long)
8552        }
8553    }
8554
8555    /**
8556     * Returns a new array from a set of elements.
8557     *
8558     * @param items a set of elements to include in the new array object.
8559     *
8560     * @returns new Uint32Array
8561     */
8562    public static of(...items: number[]): Uint32Array {
8563        let res = new Uint32Array(items.length as int)
8564        for (let i: int = 0; i < items.length; i++) {
8565            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as long)
8566        }
8567        return res
8568    }
8569
8570    /**
8571     * Returns a new array from a set of elements.
8572     *
8573     * @param items a set of elements to include in the new array object.
8574     *
8575     * @returns new Uint32Array
8576     */
8577    public static of(...items: int[]): Uint32Array {
8578        let res = new Uint32Array(items.length as int)
8579        for (let i: int = 0; i < items.length; i++) {
8580            res.setUnsafeClamp(i, items[i] as long)
8581        }
8582        return res
8583    }
8584
8585    /**
8586     * Returns a new array from a set of elements.
8587     *
8588     * @param items a set of elements to include in the new array object.
8589     *
8590     * @returns new Uint32Array
8591     */
8592    public static of(...items: long[]): Uint32Array {
8593        let res = new Uint32Array(items.length as int)
8594        for (let i: int = 0; i < items.length; i++) {
8595            res.setUnsafeClamp(i, items[i])
8596        }
8597        return res
8598    }
8599
8600    /**
8601     * Returns a new array from a set of elements.
8602     *
8603     * @param items a set of elements to include in the new array object.
8604     *
8605     * @returns new Uint32Array
8606     */
8607    public static of(): Uint32Array {
8608        return new Uint32Array(0 as int)
8609    }
8610
8611    /**
8612     * Creates an array from an array-like or iterable object.
8613     *
8614     * @param arrayLike An array-like or iterable object to convert to an array.
8615     *
8616     * @returns new Uint32Array
8617     */
8618    public static from(arr: ArrayLike<number>): Uint32Array {
8619        return Uint32Array.from<number>(arr, (x: number, k: number): number => x)
8620    }
8621
8622    /**
8623     * Creates an array from an array-like or iterable object.
8624     *
8625     * @param arrayLike An array-like or iterable object to convert to an array.
8626     *
8627     * @param mapfn A mapping function to call on every element of the array.
8628     *
8629     * @returns new Uint32Array
8630     */
8631    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint32Array {
8632        if (mapfn == undefined) {
8633            mapfn = (v: number, k: number): number => { return v }
8634        }
8635        // Calc length of items inside arrayLike, save length into i variable
8636        let i: long = 0
8637        let iter = arrayLike.$_iterator()
8638        while (true) {
8639            const v = iter.next()
8640            if (v.done) {
8641                break
8642            }
8643            i++
8644        }
8645
8646        let res = new Uint32Array(i as int)
8647        i = 0
8648        iter = arrayLike.$_iterator()
8649        while (true) {
8650            const v = iter.next()
8651            if (v.done) {
8652                return res
8653            }
8654            res.setUnsafeClamp(i as int, res.zeroIfInfinity((mapfn)!(v.value as number, i as number)) as long)
8655            i++
8656        }
8657    }
8658
8659    /**
8660     * Creates an array from an array-like or iterable object.
8661     *
8662     * @param arrayLike An array-like or iterable object to convert to an array.
8663     *
8664     * @param mapfn A mapping function to call on every element of the array.
8665     *
8666     * @returns new Uint32Array
8667     */
8668    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint32Array {
8669        let res = new Uint32Array(arrayLike.length)
8670        // 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
8671        const idx = new int[1]
8672        idx[0] = 0
8673        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
8674            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as long)
8675            idx[0] += 1
8676        })
8677        return res
8678    }
8679
8680    /**
8681     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
8682     *
8683     * @param searchElement The element to search for
8684     *
8685     * @param fromIndex The position in this array at which to begin searching for searchElement
8686     *
8687     * @returns true if searchElement is in Uint32Array, false otherwise
8688     */
8689    public includes(searchElement: number, fromIndex?: number): boolean {
8690        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
8691    }
8692
8693    /**
8694     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
8695     *
8696     * @param searchElement The element to search for
8697     *
8698     * @param fromIndex The position in this array at which to begin searching for searchElement
8699     *
8700     * @returns true if searchElement is in Uint32Array, false otherwise
8701     */
8702    public includes(searchElement: long, fromIndex: int): boolean {
8703        return this.indexOf(searchElement as int, fromIndex) != -1
8704    }
8705
8706    /**
8707     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
8708     *
8709     * @param searchElement The element to search for
8710     *
8711     * @param fromIndex The position in this array at which to begin searching for searchElement
8712     *
8713     * @returns true if searchElement is in Uint32Array, false otherwise
8714     */
8715    public includes(searchElement: long): boolean {
8716        return this.indexOf(searchElement as int, 0) != -1
8717    }
8718
8719    /**
8720     * Returns the index of the first occurrence of a value in Uint32Array.
8721     *
8722     * @param searchElement The value to locate in the array.
8723     *
8724     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8725     *  search starts at index 0.
8726     *
8727     * @returns index of element if it presents, -1 otherwise
8728     */
8729    public indexOf(searchElement: number, fromIndex?: number): number {
8730        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
8731    }
8732
8733    /**
8734     * Returns the index of the first occurrence of a value in Uint32Array.
8735     *
8736     * @param searchElement The value to locate in the array.
8737     *
8738     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8739     *  search starts at index 0.
8740     *
8741     * @returns index of element if it presents, -1 otherwise
8742     */
8743    public indexOf(searchElement: number, fromIndex: int): number {
8744        if (isNaN(searchElement)) {
8745            return -1
8746        }
8747        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
8748        for (let i = fromIndex; i < this.lengthInt; i++) {
8749            if (this.getUnsafe(i) as number == searchElement) {
8750                return i
8751            }
8752        }
8753        return -1
8754    }
8755
8756    /**
8757     * Returns the index of the first occurrence of a value in Uint32Array.
8758     *
8759     * @param searchElement The value to locate in the array.
8760     *
8761     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8762     *  search starts at index 0.
8763     *
8764     * @returns index of element if it presents, -1 otherwise
8765     */
8766    public indexOf(searchElement: int, fromIndex: int): number {
8767        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
8768        for (let i = fromIndex; i < this.lengthInt; i++) {
8769            if (this.getUnsafe(i) == searchElement as long) {
8770                return i
8771            }
8772        }
8773        return -1
8774
8775    }
8776
8777    /**
8778     * Returns the index of the first occurrence of a value in Uint32Array.
8779     *
8780     * @param searchElement The value to locate in the array.
8781     *
8782     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8783     *  search starts at index 0.
8784     *
8785     * @returns index of element if it presents, -1 otherwise
8786     */
8787    public indexOf(searchElement: int): number {
8788        return this.indexOf(searchElement, 0)
8789    }
8790
8791    /**
8792     * Adds all the elements of an array separated by the specified separator string
8793     *
8794     * @param separator A string used to separate one element of an array from the next in the
8795     * resulting String. If omitted, the array elements are separated with a comma
8796     *
8797     * @returns joined representation
8798     */
8799    public join(separator?: String): string {
8800        if (separator == undefined) {
8801            return this.join(",")
8802        }
8803        let res: StringBuilder = new StringBuilder("")
8804        for (let i = 0; i < this.lengthInt - 1; i++) {
8805            res.append(this.getUnsafe(i) as number)
8806            res.append(separator)
8807        }
8808        if (this.lengthInt > 0) {
8809            res.append(this.getUnsafe(this.lengthInt - 1) as number)
8810        }
8811        return res.toString()
8812    }
8813
8814    /**
8815     * Returns an list of keys in Uint32Array
8816     *
8817     * @returns iterator over keys
8818     */
8819    public keys(): IterableIterator<number> {
8820        return new Uint32ArrayIteratorKeys(this)
8821    }
8822
8823    /**
8824     * Returns the index of the last occurrence of a value in Uint32Array.
8825     *
8826     * @param searchElement The value to locate in the array.
8827     *
8828     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8829     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8830     *
8831     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8832     */
8833    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
8834        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
8835    }
8836
8837    /**
8838     * Returns the index of the last occurrence of a value in Uint32Array.
8839     *
8840     * @param searchElement The value to locate in the array.
8841     *
8842     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8843     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8844     *
8845     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8846     */
8847    public lastIndexOf(searchElement: number): number {
8848        return this.lastIndexOf(searchElement, this.lengthInt - 1)
8849    }
8850
8851    /**
8852     * Returns the index of the last occurrence of a value in Uint32Array.
8853     *
8854     * @param searchElement The value to locate in the array.
8855     *
8856     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8857     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8858     *
8859     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8860     */
8861    public lastIndexOf(searchElement: number, fromIndex: int): number {
8862        if (isNaN(searchElement)) {
8863            return -1
8864        }
8865        if (this.lengthInt == 0) {
8866            return -1
8867        }
8868        let k: int = this.lengthInt + fromIndex
8869        if (fromIndex >= 0) {
8870            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
8871        }
8872        while (k >= 0) {
8873            if (this.getUnsafe(k) as number == searchElement) {
8874                return k
8875            }
8876            k--
8877        }
8878        return -1
8879    }
8880
8881    /**
8882     * Returns the index of the last occurrence of a value in Uint32Array.
8883     *
8884     * @param searchElement The value to locate in the array.
8885     *
8886     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8887     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8888     *
8889     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8890     */
8891    public lastIndexOf(searchElement: int, fromIndex: int): number {
8892        if (this.lengthInt == 0) {
8893            return -1
8894        }
8895        let k: int = this.lengthInt + fromIndex
8896        if (fromIndex >= 0) {
8897            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
8898        }
8899        while (k >= 0) {
8900            if (this.getUnsafe(k) == searchElement as long) {
8901                return k
8902            }
8903            k--
8904        }
8905        return -1
8906    }
8907
8908    /**
8909     * Returns the index of the last occurrence of a value in Uint32Array.
8910     *
8911     * @param searchElement The value to locate in the array.
8912     *
8913     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8914     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8915     *
8916     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8917     */
8918    public lastIndexOf(searchElement: int): number {
8919        return this.lastIndexOf(searchElement, this.lengthInt - 1)
8920    }
8921
8922   /**
8923    * Creates a new Uint32Array using initializer
8924    *
8925    * @param data initializer
8926    *
8927    * @returns a new Uint32Array from data
8928    */
8929    public of(...data: number[]): Uint32Array {
8930        throw new Error("Uint32Array.of: not implemented")
8931    }
8932
8933    /**
8934     * Creates a new Uint32Array using reversed data from the current one
8935     *
8936     * @returns a new Uint32Array using reversed data from the current one
8937     */
8938    public reverse(): Uint32Array {
8939        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
8940            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
8941            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
8942            this.setUnsafe(i, tmp)
8943        }
8944        return this
8945    }
8946
8947    /**
8948     * Creates a slice of current Uint32Array using range [begin, end)
8949     *
8950     * @param begin start index to be taken into slice
8951     *
8952     * @param end last index to be taken into slice
8953     *
8954     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
8955     *
8956     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8957     */
8958    public slice(begin?: number, end?: number): Uint32Array {
8959        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
8960    }
8961
8962    /**
8963     * Creates a slice of current Uint32Array using range [begin, end)
8964     *
8965     * @param begin start index to be taken into slice
8966     *
8967     * @param end last index to be taken into slice
8968     *
8969     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
8970     *
8971     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8972     */
8973    public slice(begin: number, end: number): Uint32Array {
8974        return this.slice(begin as int, end as int)
8975    }
8976
8977    /**
8978     * Creates a slice of current Uint32Array using range [begin, end)
8979     *
8980     * @param begin start index to be taken into slice
8981     *
8982     * @param end last index to be taken into slice
8983     *
8984     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
8985     *
8986     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8987     */
8988    public slice(begin: number, end: int): Uint32Array {
8989        return this.slice(begin as int, end as int)
8990    }
8991
8992    /**
8993     * Creates a slice of current Uint32Array using range [begin, end)
8994     *
8995     * @param begin start index to be taken into slice
8996     *
8997     * @param end last index to be taken into slice
8998     *
8999     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
9000     *
9001     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
9002     */
9003    public slice(begin: int, end: number): Uint32Array {
9004        return this.slice(begin as int, end as int)
9005    }
9006
9007    /**
9008     * Creates a slice of current Uint32Array using range [begin, end)
9009     *
9010     * @param begin start index to be taken into slice
9011     *
9012     * @param end last index to be taken into slice
9013     *
9014     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
9015     *
9016     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
9017     */
9018    public slice(begin: int, end: int): Uint32Array {
9019        const len: int = this.lengthInt
9020        const relStart = normalizeIndex(begin, len)
9021        const relEnd = normalizeIndex(end, len)
9022        let count = relEnd - relStart
9023        if (count < 0) {
9024            count = 0
9025        }
9026        if (this.buffer instanceof ArrayBuffer) {
9027            let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint32Array.BYTES_PER_ELEMENT as int, relEnd * Uint32Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
9028            return new Uint32Array(buf)
9029        } else if (this.buffer instanceof SharedArrayBuffer) {
9030            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint32Array.BYTES_PER_ELEMENT as int, relEnd * Uint32Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
9031            return new Uint32Array(buf)
9032        } else {
9033            throw new Error("unexpected type of buffer")
9034        }
9035    }
9036
9037    /**
9038     * Creates a slice of current Uint32Array using range [begin, this.lengthInt).
9039     *
9040     * @param begin start index to be taken into slice
9041     *
9042     * @returns a new Uint32Array with elements of current Uint32Array[begin, this.lengthInt)
9043     */
9044    public slice(begin: number): Uint32Array {
9045        return this.slice(begin as int)
9046    }
9047
9048    /**
9049     * Creates a slice of current Uint32Array using range [begin, this.lengthInt).
9050     *
9051     * @param begin start index to be taken into slice
9052     *
9053     * @returns a new Uint32Array with elements of current Uint32Array[begin, this.lengthInt)
9054     */
9055    public slice(begin: int): Uint32Array {
9056        return this.slice(begin, this.lengthInt)
9057    }
9058
9059    /**
9060     * Sorts in-place
9061     *
9062     * @param compareFn comparator —  used to determine the order of the elements.
9063     * compareFn returns a negative value if first argument is less than second argument,
9064     * zero if they're equal and a positive value otherwise.
9065     * If omitted, the elements are sorted in ascending order.
9066     *
9067     * @returns sorted Uint32Array
9068     */
9069    public sort(compareFn?: (a: number, b: number) => number): this {
9070        let arr: long[] = new long[this.lengthInt]
9071        for (let i = 0; i < this.lengthInt; ++i) {
9072            arr[i] = this.getUnsafe(i)
9073        }
9074        let cmp = (l: long, r: long): number => {
9075                return (l - r) as number
9076            }
9077        if (compareFn != undefined) {
9078            cmp = (l: long, r: long): number => {
9079                return compareFn!(l as number, r as number)
9080            }
9081        }
9082        sort(arr, cmp)
9083        for (let i = 0; i < this.lengthInt; ++i) {
9084            this.setUnsafe(i, arr[i])
9085        }
9086        return this
9087    }
9088
9089    /**
9090     * Sorts in-place
9091     *
9092     * @param compareFn comparator —  used to determine the order of the elements.
9093     * compareFn returns a negative value if first argument is less than second argument,
9094     * zero if they're equal and a positive value otherwise.
9095     *
9096     * @returns sorted Uint32Array
9097     */
9098    public sort(compareFn: (a: number) => number): this {
9099        let cmp = (a: number, b: number) => { return compareFn(a)}
9100        this.sort(cmp)
9101        return this
9102    }
9103
9104    /**
9105     * Sorts in-place
9106     *
9107     * @param fn compareFn —  used to determine the order of the elements.
9108     * compareFn returns a negative value if first argument is less than second argument,
9109     * zero if they're equal and a positive value otherwise.
9110     *
9111     * @returns sorted Uint32Array
9112     */
9113    public sort(compareFn: () => number): this {
9114        let cmp = (a: number, b: number) => { return compareFn()}
9115        this.sort(cmp)
9116        return this
9117    }
9118    /**
9119     * Creates a Uint32Array with the same underlying Buffer
9120     *
9121     * @param begin start index, inclusive
9122     *
9123     * @param end last index, exclusive
9124     *
9125     * @returns new Uint32Array with the same underlying Buffer
9126     */
9127    public subarray(begin?: number, end?: number): Uint32Array {
9128        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
9129    }
9130
9131    /**
9132     * Creates a Uint32Array with the same underlying Buffer
9133     *
9134     * @param begin start index, inclusive
9135     *
9136     * @param end last index, exclusive
9137     *
9138     * @returns new Uint32Array with the same underlying Buffer
9139     */
9140    public subarray(begin: number, end: number): Uint32Array {
9141        return this.subarray(begin as int, end as int)
9142    }
9143
9144    /**
9145     * Creates a Uint32Array with the same underlying Buffer
9146     *
9147     * @param begin start index, inclusive
9148     *
9149     * @param end last index, exclusive
9150     *
9151     * @returns new Uint32Array with the same underlying Buffer
9152     */
9153    public subarray(begin: number, end: int): Uint32Array {
9154        return this.subarray(begin as int, end as int)
9155    }
9156
9157    /**
9158     * Creates a Uint32Array with the same underlying Buffer
9159     *
9160     * @param begin start index, inclusive
9161     *
9162     * @param end last index, exclusive
9163     *
9164     * @returns new Uint32Array with the same underlying Buffer
9165     */
9166    public subarray(begin: int, end: number): Uint32Array {
9167        return this.subarray(begin as int, end as int)
9168    }
9169
9170    /**
9171     * Creates a Uint32Array with the same underlying Buffer
9172     *
9173     * @param begin start index, inclusive
9174     *
9175     * @param end last index, exclusive
9176     *
9177     * @returns new Uint32Array with the same underlying Buffer
9178     */
9179    public subarray(begin: int, end: int): Uint32Array {
9180        const len: int = this.lengthInt
9181        const relStart = normalizeIndex(begin, len)
9182        const relEnd = normalizeIndex(end, len)
9183        let count = relEnd - relStart
9184        if (count < 0) {
9185            count = 0
9186        }
9187        return new Uint32Array(this.buffer, relStart * Uint32Array.BYTES_PER_ELEMENT as int, count)
9188    }
9189
9190    /**
9191     * Creates a Uint32Array with the same Buffer
9192     *
9193     * @param begin start index, inclusive
9194     *
9195     * @returns new Uint32Array with the same Buffer
9196     */
9197    public subarray(begin: number): Uint32Array {
9198        return this.subarray(begin as int, this.lengthInt)
9199    }
9200
9201    /**
9202     * Creates a Uint32Array with the same Buffer
9203     *
9204     * @param begin start index, inclusive
9205     *
9206     * @returns new Uint32Array with the same Buffer
9207     */
9208    public subarray(begin: int): Uint32Array {
9209        return this.subarray(begin, this.lengthInt)
9210    }
9211
9212    /**
9213     * Converts Uint32Array to a string with respect to locale
9214     *
9215     * @param locales
9216     *
9217     * @param options
9218     *
9219     * @returns string representation
9220     */
9221    public toLocaleString(locales: Object, options: Object): string {
9222        throw new Error("Uint32Array.toLocaleString: not implemented")
9223    }
9224
9225    /**
9226     * Converts Uint32Array to a string with respect to locale
9227     *
9228     * @param locales
9229     *
9230     * @returns string representation
9231     */
9232    public toLocaleString(locales: Object): string {
9233        return this.toLocaleString(new Object(), new Object())
9234    }
9235
9236    /**
9237     * Converts Uint32Array to a string with respect to locale
9238     *
9239     * @returns string representation
9240     */
9241    public toLocaleString(): string {
9242        let res: StringBuilder = new StringBuilder("")
9243        for (let i = 0; i < this.lengthInt - 1; ++i) {
9244            res.append((this.getUnsafe(i) as Number).toLocaleString())
9245            res.append(",")
9246        }
9247        if (this.lengthInt > 0) {
9248            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
9249        }
9250        return res.toString()
9251    }
9252
9253    /**
9254     * Creates a reversed copy
9255     *
9256     * @returns a reversed copy
9257     */
9258    public toReversed(): Uint32Array {
9259        return new Uint32Array(this).reverse()
9260    }
9261
9262    /**
9263     * Creates a sorted copy
9264     *
9265     * @returns a sorted copy
9266     */
9267    public toSorted(): Uint32Array {
9268        return new Uint32Array(this).sort()
9269    }
9270
9271    /**
9272     * Returns a string representation of the Uint32Array
9273     *
9274     * @returns a string representation of the Uint32Array
9275     */
9276    public override toString(): string {
9277        return this.join(",")
9278    }
9279
9280    /**
9281     * Returns array values iterator
9282     *
9283     * @returns an iterator
9284     */
9285    public values(): IterableIterator<Number> {
9286         return new Uint32ArrayIterator(this)
9287    }
9288
9289    /**
9290     * Creates a copy with replaced value on index
9291     *
9292     * @param index
9293     *
9294     * @param value
9295     *
9296     * @returns an Uint32Array with replaced value on index
9297     */
9298    public with(index: number, value: number): Uint32Array {
9299        return this.with(index as int, value as long)
9300    }
9301
9302    /**
9303     * Creates a copy with replaced value on index
9304     *
9305     * @param index
9306     *
9307     * @param value
9308     *
9309     * @returns an Uint32Array with replaced value on index
9310     */
9311    /* public */ internal with(index: int, value: long): Uint32Array {
9312        let res = new Uint32Array(this)
9313        res.setUnsafeClamp(index, value)
9314        return res
9315    }
9316
9317    /// === with element lambda functions ===
9318
9319    /**
9320     * Determines whether the specified callback function returns true for all elements of an array.
9321     *
9322     * @param predicate A function that accepts one argument.
9323     * The every method calls the predicate function for each element in the array until the predicate returns a false,
9324     * or until the end of the array.
9325     *
9326     * @returns true unless predicate function returns a false for an array element,
9327     * in which case false is immediately returned.
9328     */
9329    public every(predicate: (element: number) => boolean): boolean {
9330        return this.every((element: number, index: number, array: Uint32Array): boolean => predicate(element))
9331    }
9332
9333    /**
9334     * creates a new Uint32Array from current Uint32Array based on a condition fn
9335     *
9336     * @param fn the condition to apply for each element
9337     *
9338     * @returns a new Uint32Array with elements from current Uint32Array that satisfy condition fn
9339     */
9340    public filter(fn: (val: number) => boolean): Uint32Array {
9341        let newF: (val: number, index: number, array: Uint32Array) => boolean =
9342            (val: number, index: number, array: Uint32Array): boolean => { return fn(val) }
9343        return this.filter(newF)
9344    }
9345
9346    /**
9347     * Returns the value of the first element in the array where predicate is true, and undefined
9348     * otherwise
9349     *
9350     * @param predicate find calls predicate once for each element of the array, in ascending
9351     * order, until it finds one where predicate returns true. If such an element is found, find
9352     * immediately returns that element value. Otherwise, find returns undefined
9353     *
9354     * @returns number | undefined
9355     */
9356    public find(predicate: () => boolean): number | undefined {
9357        return this.find((value: number, index: number, obj: Uint32Array): boolean => predicate())
9358    }
9359
9360    /**
9361     * Returns the value of the first element in the array where predicate is true, and undefined
9362     * otherwise
9363     *
9364     * @param predicate find calls predicate once for each element of the array, in ascending
9365     * order, until it finds one where predicate returns true. If such an element is found, find
9366     * immediately returns that element value. Otherwise, find returns undefined
9367     *
9368     * @returns number | undefined
9369     */
9370    public find(predicate: (value: number) => boolean): number | undefined {
9371        return this.find((value: number, index: number, obj: Uint32Array): boolean => predicate(value))
9372    }
9373
9374    /**
9375     * Returns the index of the first element in the array where predicate is true, and -1
9376     * otherwise
9377     *
9378     * @param predicate find calls predicate once for each element of the array, in ascending
9379     * order, until it finds one where predicate returns true. If such an element is found,
9380     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
9381     *
9382     * @returns number
9383     */
9384    public findIndex(predicate: (value: number) => boolean): number {
9385        return this.findIndex((value: number, index: number, obj: Uint32Array): boolean => predicate(value)) as number
9386    }
9387
9388    /**
9389     * Finds the last element in the Uint32Array that satisfies the condition
9390     *
9391     * @param fn condition
9392     *
9393     * @returns the last element that satisfies fn
9394     */
9395    public findLast(fn: (val: number) => boolean): number {
9396        let newF: (val: number, index: number, array: Uint32Array) => boolean =
9397            (val: number, index: number, array: Uint32Array): boolean => { return fn(val) }
9398        return this.findLast(newF)
9399    }
9400
9401    /**
9402     * Finds an index of the last element in the Uint32Array that satisfies the condition
9403     *
9404     * @param fn condition
9405     *
9406     * @returns the index of the last element that satisfies fn, -1 otherwise
9407     */
9408    public findLastIndex(fn: (val: number) => boolean): number {
9409        let newF: (val: number, index: number, array: Uint32Array) => boolean =
9410            (val: number, index: number, array: Uint32Array): boolean => { return fn(val) }
9411        return this.findLastIndex(newF) as number
9412    }
9413
9414    /**
9415     * Performs the specified action for each element in Uint32Array
9416     *
9417     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
9418     * callbackfn function one time for each element in the array.
9419     *
9420     * @returns None
9421     */
9422    public forEach(callbackfn: (val: number) => void): void {
9423        this.forEach((value: number, index: number, array: Uint32Array): void => callbackfn(value))
9424    }
9425
9426    /**
9427     * Creates a new Uint32Array using fn(arr[i]) over all elements of current Uint32Array
9428     *
9429     * @param fn a function to apply for each element of current Uint32Array
9430     *
9431     * @returns a new Uint32Array where for each element from current Uint32Array fn was applied
9432     */
9433    public map(fn: (val: number) => number): Uint32Array {
9434        let newF: (val: number, index: number) => number =
9435            (val: number, index: number): number => { return fn(val) }
9436        return this.map(newF)
9437    }
9438
9439    /**
9440     * Determines whether the specified callback function returns true for any element of an array.
9441     *
9442     * @param predicate A function that accepts one argument.
9443     * The some method calls the predicate function for each element in the array
9444     * until the predicate returns a true or until the end of the array.
9445     *
9446     * @returns false unless predicate function returns true for an array element,
9447     * in which case true is immediately returned.
9448     */
9449    public some(predicate: (element: number) => boolean): boolean {
9450        return this.some((element: number, index: number, array: Uint32Array): boolean => predicate(element))
9451    }
9452
9453    /**
9454     * Determines whether the specified callback function returns true for any element of an array.
9455     *
9456     * @param predicate A function that accepts three arguments.
9457     * The some method calls the predicate function for each element in the array
9458     * until the predicate returns a true or until the end of the array.
9459     *
9460     * @returns false unless predicate function returns true for an array element,
9461     * in which case true is immediately returned.
9462     */
9463    public some(predicate: (element: number, index: number, array: Uint32Array) => boolean): boolean {
9464        for (let i = 0; i < this.lengthInt; i++) {
9465            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
9466                return true
9467            }
9468        }
9469        return false
9470    }
9471
9472    /**
9473     * Determines whether the specified callback function returns true for any element of an array.
9474     *
9475     * @param predicate A function that accepts two arguments.
9476     * The some method calls the predicate function for each element in the array
9477     * until the predicate returns a true or until the end of the array.
9478     *
9479     * @returns false unless predicate function returns true for an array element,
9480     * in which case true is immediately returned.
9481     */
9482    public some(predicate: (element: number, index: number) => boolean): boolean {
9483        return this.some((element: number, index: number, array: Uint32Array): boolean => predicate(element, index))
9484    }
9485
9486    /**
9487     * Determines whether the specified callback function returns true for any element of an array.
9488     *
9489     * @param predicate A function that accepts no arguments.
9490     * The some method calls the predicate function for each element in the array
9491     * until the predicate returns a true or until the end of the array.
9492     *
9493     * @returns false unless predicate function returns true for an array element,
9494     * in which case true is immediately returned.
9495     */
9496    public some(predicate: () => boolean): boolean {
9497        return this.some((element: number, index: number, array: Uint32Array): boolean => predicate())
9498    }
9499
9500    /**
9501     * Calls the specified callback function for all the elements in an array.
9502     * The return value of the callback function is the accumulated result,
9503     * and is provided as an argument in the next call to the callback function.
9504     *
9505     * @param callbackfn A function that accepts four arguments.
9506     * The reduce method calls the callbackfn function one time for each element in the array.
9507     *
9508     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9509     * The first call to the callbackfn function provides this value as an argument.
9510     *
9511     * @returns The value that results from running the callback function to completion over the entire typed array.
9512     */
9513    public reduce<U = number>(
9514                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U,
9515                initialValue: U): U {
9516        let accumulatedValue = initialValue
9517        for (let i = 0; i < this.lengthInt; i++) {
9518            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
9519        }
9520        return accumulatedValue
9521    }
9522
9523    /**
9524     * Calls the specified callback function for all the elements in an array.
9525     * The return value of the callback function is the accumulated result,
9526     * and is provided as an argument in the next call to the callback function.
9527     *
9528     * @param callbackfn A function that accepts three arguments.
9529     * The reduce method calls the callbackfn function one time for each element in the array.
9530     *
9531     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9532     * The first call to the callbackfn function provides this value as an argument.
9533     *
9534     * @returns The value that results from running the callback function to completion over the entire typed array.
9535     */
9536    public reduce<U = number>(
9537                callbackfn: (previousValue: U, currentValue: number, currentIndex: number) => U,
9538                initialValue: U): U {
9539        return this.reduce(
9540                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9541                        callbackfn(prevVal, currVal, currIndex),
9542                initialValue)
9543    }
9544
9545    /**
9546     * Calls the specified callback function for all the elements in an array.
9547     * The return value of the callback function is the accumulated result,
9548     * and is provided as an argument in the next call to the callback function.
9549     *
9550     * @param callbackfn A function that accepts two arguments.
9551     * The reduce method calls the callbackfn function one time for each element in the array.
9552     *
9553     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9554     * The first call to the callbackfn function provides this value as an argument.
9555     *
9556     * @returns The value that results from running the callback function to completion over the entire typed array.
9557     */
9558    public reduce<U = number>(
9559                callbackfn: (previousValue: U, currentValue: number) => U,
9560                initialValue: U): U {
9561        return this.reduce(
9562                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9563                        callbackfn(prevVal, currVal),
9564                initialValue)
9565    }
9566
9567    /**
9568     * Calls the specified callback function for all the elements in an array.
9569     * The return value of the callback function is the accumulated result,
9570     * and is provided as an argument in the next call to the callback function.
9571     *
9572     * @param callbackfn A function that accepts one argument
9573     * The reduce method calls the callbackfn function one time for each element in the array.
9574     *
9575     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9576     * The first call to the callbackfn function provides this value as an argument.
9577     *
9578     * @returns The value that results from running the callback function to completion over the entire typed array.
9579     */
9580    public reduce<U = number>(
9581                callbackfn: (previousValue: U) => U,
9582                initialValue: U): U {
9583        return this.reduce(
9584                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9585                        callbackfn(prevVal),
9586                initialValue)
9587    }
9588
9589    /**
9590     * Calls the specified callback function for all the elements in an array.
9591     * The return value of the callback function is the accumulated result,
9592     * and is provided as an argument in the next call to the callback function.
9593     *
9594     * @param callbackfn A function that accepts no arguments
9595     * The reduce method calls the callbackfn function one time for each element in the array.
9596     *
9597     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9598     * The first call to the callbackfn function provides this value as an argument.
9599     *
9600     * @returns The value that results from running the callback function to completion over the entire typed array.
9601     */
9602    public reduce<U = number>(
9603                callbackfn: () => U,
9604                initialValue: U): U {
9605        return this.reduce(
9606                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9607                        callbackfn(),
9608                initialValue)
9609    }
9610
9611    /**
9612     * Calls the specified callback function for all the elements in an array.
9613     * The return value of the callback function is the accumulated result,
9614     * and is provided as an argument in the next call to the callback function.
9615     *
9616     * @param callbackfn A function that accepts four arguments.
9617     * The reduce method calls the callbackfn function one time for each element in the array.
9618     * The first call to the callbackfn function provides array first element value as an argument
9619     *
9620     * @returns The value that results from running the callback function to completion over the entire typed array.
9621     * calling reduce method on an empty array without an initial value creates a TypeError
9622     */
9623    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number {
9624        if (this.lengthInt == 0) {
9625            throw new TypeError("Reduce of empty array with no initial value")
9626        }
9627
9628        let accumulatedValue = this.$_get(0) as number
9629        for (let i = 1; i < this.lengthInt; i++) {
9630            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
9631        }
9632        return accumulatedValue
9633    }
9634
9635    /**
9636     * Calls the specified callback function for all the elements in an array.
9637     * The return value of the callback function is the accumulated result,
9638     * and is provided as an argument in the next call to the callback function.
9639     *
9640     * @param callbackfn A function that accepts three arguments.
9641     * The reduce method calls the callbackfn function one time for each element in the array.
9642     * The first call to the callbackfn function provides array first element value as an argument
9643     *
9644     * @returns The value that results from running the callback function to completion over the entire typed array.
9645     * calling reduce method on an empty array without an initial value creates a TypeError
9646     */
9647    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
9648        return this.reduce(
9649                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9650                        callbackfn(prevVal, currVal, currIndex))
9651    }
9652
9653    /**
9654     * Calls the specified callback function for all the elements in an array.
9655     * The return value of the callback function is the accumulated result,
9656     * and is provided as an argument in the next call to the callback function.
9657     *
9658     * @param callbackfn A function that accepts two arguments.
9659     * The reduce method calls the callbackfn function one time for each element in the array.
9660     * The first call to the callbackfn function provides array first element value as an argument
9661     *
9662     * @returns The value that results from running the callback function to completion over the entire typed array.
9663     * calling reduce method on an empty array without an initial value creates a TypeError
9664     */
9665    public reduce(callbackfn: (previousValue: number, currentValue: number) => number): number {
9666        return this.reduce(
9667                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9668                        callbackfn(prevVal, currVal))
9669    }
9670
9671    /**
9672     * Calls the specified callback function for all the elements in an array.
9673     * The return value of the callback function is the accumulated result,
9674     * and is provided as an argument in the next call to the callback function.
9675     *
9676     * @param callbackfn A function that accepts one argument.
9677     * The reduce method calls the callbackfn function one time for each element in the array.
9678     * The first call to the callbackfn function provides array first element value as an argument
9679     *
9680     * @returns The value that results from running the callback function to completion over the entire typed array.
9681     * calling reduce method on an empty array without an initial value creates a TypeError
9682     */
9683    public reduce(callbackfn: (previousValue: number) => number): number {
9684        return this.reduce(
9685                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9686                        callbackfn(prevVal))
9687    }
9688
9689    /**
9690     * Calls the specified callback function for all the elements in an array.
9691     * The return value of the callback function is the accumulated result,
9692     * and is provided as an argument in the next call to the callback function.
9693     *
9694     * @param callbackfn A function that accepts no arguments.
9695     * The reduce method calls the callbackfn function one time for each element in the array.
9696     * The first call to the callbackfn function provides array first element value as an argument
9697     *
9698     * @returns The value that results from running the callback function to completion over the entire typed array.
9699     * calling reduce method on an empty array without an initial value creates a TypeError
9700     */
9701    public reduce(callbackfn: () => number): number {
9702        return this.reduce(
9703                (prevVal: number, currVal: number, currIndex: number, array: Uint32Array) =>
9704                        callbackfn())
9705    }
9706
9707    /**
9708     * Calls the specified callback function for all the elements in an array, in descending order.
9709     * The return value of the callback function is the accumulated result,
9710     * and is provided as an argument in the next call to the callback function.
9711     *
9712     * @param callbackfn A function that accepts four arguments.
9713     * The reduceRight method calls the callbackfn function one time for each element in the array.
9714     *
9715     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9716     * The first call to the callbackfn function provides this value as an argument.
9717     *
9718     * @returns The value that results from running the callback function to completion over the entire typed array.
9719     */
9720    public reduceRight<U = number>(
9721                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U,
9722                initialValue: U): U {
9723        let accumulatedValue = initialValue
9724        for (let i = this.lengthInt - 1; i >= 0; i--) {
9725            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
9726        }
9727        return accumulatedValue
9728    }
9729
9730    /**
9731     * Calls the specified callback function for all the elements in an array, in descending order.
9732     * The return value of the callback function is the accumulated result,
9733     * and is provided as an argument in the next call to the callback function.
9734     *
9735     * @param callbackfn A function that accepts three arguments.
9736     * The reduceRight method calls the callbackfn function one time for each element in the array.
9737     *
9738     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9739     * The first call to the callbackfn function provides this value as an argument.
9740     *
9741     * @returns The value that results from running the callback function to completion over the entire typed array.
9742     */
9743    public reduceRight<U = number>(
9744                callbackfn: (previuosValue: U, currentValue: number, currentIndex: number) => U,
9745                initialValue: U): U {
9746        return this.reduceRight(
9747                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9748                        callbackfn(prevVal, currVal, currIndex),
9749                initialValue)
9750    }
9751
9752    /**
9753     * Calls the specified callback function for all the elements in an array, in descending order.
9754     * The return value of the callback function is the accumulated result,
9755     * and is provided as an argument in the next call to the callback function.
9756     *
9757     * @param callbackfn A function that accepts two arguments.
9758     * The reduceRight method calls the callbackfn function one time for each element in the array.
9759     *
9760     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9761     * The first call to the callbackfn function provides this value as an argument.
9762     *
9763     * @returns The value that results from running the callback function to completion over the entire typed array.
9764     */
9765    public reduceRight<U = number>(
9766                callbackfn: (previuosValue: U, currentValue: number) => U,
9767                initialValue: U): U {
9768        return this.reduceRight(
9769                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9770                        callbackfn(prevVal, currVal),
9771                initialValue)
9772    }
9773
9774    /**
9775     * Calls the specified callback function for all the elements in an array, in descending order.
9776     * The return value of the callback function is the accumulated result,
9777     * and is provided as an argument in the next call to the callback function.
9778     *
9779     * @param callbackfn A function that accepts one argument.
9780     * The reduceRight method calls the callbackfn function one time for each element in the array.
9781     *
9782     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9783     * The first call to the callbackfn function provides this value as an argument.
9784     *
9785     * @returns The value that results from running the callback function to completion over the entire typed array.
9786     */
9787    public reduceRight<U = number>(
9788                callbackfn: (previuosValue: U) => U,
9789                initialValue: U): U {
9790        return this.reduceRight(
9791                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9792                        callbackfn(prevVal),
9793                initialValue)
9794    }
9795
9796    /**
9797     * Calls the specified callback function for all the elements in an array, in descending order.
9798     * The return value of the callback function is the accumulated result,
9799     * and is provided as an argument in the next call to the callback function.
9800     *
9801     * @param callbackfn A function that accepts no arguments.
9802     * The reduceRight method calls the callbackfn function one time for each element in the array.
9803     *
9804     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
9805     * The first call to the callbackfn function provides this value as an argument.
9806     *
9807     * @returns The value that results from running the callback function to completion over the entire typed array.
9808     */
9809    public reduceRight<U = number>(
9810                callbackfn: () => U,
9811                initialValue: U): U {
9812        return this.reduceRight(
9813                (prevVal: U, currVal: number, currIndex: number, array: Uint32Array) =>
9814                        callbackfn(),
9815                initialValue)
9816    }
9817
9818    /**
9819     * Calls the specified callback function for all the elements in an array, in descending order.
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 four arguments.
9824     * The reduceRight method calls the callbackfn function one time for each element in the array.
9825     * The first call to the callbackfn function provides array last 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 reduceRight method on an empty array without an initial value creates a TypeError
9829     */
9830    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number {
9831        if (this.lengthInt == 0) {
9832            throw new TypeError("Reduce of empty array with no initial value")
9833        }
9834
9835        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
9836        for (let i = this.lengthInt - 2; i >= 0; i--) {
9837            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
9838        }
9839        return accumulatedValue
9840    }
9841
9842    /**
9843     * Calls the specified callback function for all the elements in an array, in descending order.
9844     * The return value of the callback function is the accumulated result,
9845     * and is provided as an argument in the next call to the callback function.
9846     *
9847     * @param callbackfn A function that accepts three arguments.
9848     * The reduceRight method calls the callbackfn function one time for each element in the array.
9849     * The first call to the callbackfn function provides array last element value as an argument
9850     *
9851     * @returns The value that results from running the callback function to completion over the entire typed array.
9852     * calling reduceRight method on an empty array without an initial value creates a TypeError
9853     */
9854    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number) => number): number {
9855        return this.reduceRight(
9856                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
9857                        callbackfn(prevValue, currValue, currIndex))
9858    }
9859
9860    /**
9861     * Calls the specified callback function for all the elements in an array, in descending order.
9862     * The return value of the callback function is the accumulated result,
9863     * and is provided as an argument in the next call to the callback function.
9864     *
9865     * @param callbackfn A function that accepts two arguments.
9866     * The reduceRight method calls the callbackfn function one time for each element in the array.
9867     * The first call to the callbackfn function provides array last element value as an argument
9868     *
9869     * @returns The value that results from running the callback function to completion over the entire typed array.
9870     * calling reduceRight method on an empty array without an initial value creates a TypeError
9871     */
9872    public reduceRight(callbackfn: (previousValue: number, currentValue: number) => number): number {
9873        return this.reduceRight(
9874                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
9875                        callbackfn(prevValue, currValue))
9876    }
9877
9878    /**
9879     * Calls the specified callback function for all the elements in an array, in descending order.
9880     * The return value of the callback function is the accumulated result,
9881     * and is provided as an argument in the next call to the callback function.
9882     *
9883     * @param callbackfn A function that accepts one argument.
9884     * The reduceRight method calls the callbackfn function one time for each element in the array.
9885     * The first call to the callbackfn function provides array last element value as an argument
9886     *
9887     * @returns The value that results from running the callback function to completion over the entire typed array.
9888     * calling reduceRight method on an empty array without an initial value creates a TypeError
9889     */
9890    public reduceRight(callbackfn: (previousValue: number) => number): number {
9891        return this.reduceRight(
9892                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
9893                        callbackfn(prevValue))
9894    }
9895
9896    /**
9897     * Calls the specified callback function for all the elements in an array, in descending order.
9898     * The return value of the callback function is the accumulated result,
9899     * and is provided as an argument in the next call to the callback function.
9900     *
9901     * @param callbackfn A function that accepts no arguments.
9902     * The reduceRight method calls the callbackfn function one time for each element in the array.
9903     * The first call to the callbackfn function provides array last element value as an argument
9904     *
9905     * @returns The value that results from running the callback function to completion over the entire typed array.
9906     * calling reduceRight method on an empty array without an initial value creates a TypeError
9907     */
9908    public reduceRight(callbackfn: () => number): number {
9909        return this.reduceRight(
9910                (prevValue: number, currValue: number, currIndex: number, array: Uint32Array) =>
9911                        callbackfn())
9912    }
9913
9914    /**
9915     * Creates a new Uint32Array using fn(arr[i]) over all elements of current Uint32Array.
9916     *
9917     * @param fn a function to apply for each element of current Uint32Array
9918     *
9919     * @returns a new Uint32Array where for each element from current Uint32Array fn was applied
9920     */
9921    public map(fn: (val: number, index: number) => number): Uint32Array {
9922        let resBuf = new ArrayBuffer(this.lengthInt * Uint32Array.BYTES_PER_ELEMENT as int)
9923        let res = new Uint32Array(resBuf)
9924        for (let i = 0; i < this.lengthInt; i++) {
9925            const fnRes = fn(this.getUnsafe(i) as number, i as number)
9926            res.setUnsafeClamp(i, fnRes as long)
9927        }
9928        return res
9929    }
9930
9931    /**
9932     * Determines whether the specified callback function returns true for all elements of an array.
9933     *
9934     * @param predicate A function that accepts three arguments.
9935     * The every method calls the predicate function for each element in the array until the predicate returns a false,
9936     * or until the end of the array.
9937     *
9938     * @returns true unless predicate function returns a false for an array element,
9939     * in which case false is immediately returned.
9940     */
9941    public every(predicate: (element: number, index: number, array: Uint32Array) => boolean): boolean {
9942        for (let i = 0; i < this.lengthInt; i++) {
9943            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
9944                return false
9945            }
9946        }
9947        return true
9948    }
9949
9950    /**
9951     * Determines whether the specified callback function returns true for all elements of an array.
9952     *
9953     * @param predicate A function that accepts two arguments.
9954     * The every method calls the predicate function for each element in the array until the predicate returns a false,
9955     * or until the end of the array.
9956     *
9957     * @returns true unless predicate function returns a false for an array element,
9958     * in which case false is immediately returned.
9959     */
9960    public every(predicate: (element: number, index: number) => boolean): boolean {
9961        return this.every((element: number, index: number, array: Uint32Array): boolean => predicate(element, index))
9962    }
9963
9964    /**
9965     * Determines whether the specified callback function returns true for all elements of an array.
9966     *
9967     * @param predicate A function that accepts no arguments.
9968     * The every method calls the predicate function for each element in the array until the predicate returns a false,
9969     * or until the end of the array.
9970     *
9971     * @returns true unless predicate function returns a false for an array element,
9972     * in which case false is immediately returned.
9973     */
9974    public every(predicate: () => boolean): boolean {
9975        return this.every((element: number, index: number, array: Uint32Array): boolean => predicate())
9976    }
9977
9978    /**
9979     * Creates a new Uint32Array from current Uint32Array based on a condition fn.
9980     *
9981     * @param fn the condition to apply for each element
9982     *
9983     * @returns a new Uint32Array with elements from current Uint32Array that satisfy condition fn
9984     */
9985    public filter(fn: (val: number, index: number, array: Uint32Array) => boolean): Uint32Array {
9986        let markers = new boolean[this.lengthInt]
9987        let resLen = 0
9988        for (let i = 0; i < this.lengthInt; i++) {
9989            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
9990            if (markers[i]) {
9991                ++resLen
9992            }
9993        }
9994        let res = new Uint32Array(resLen)
9995        for (let i = 0, j = 0; i < this.lengthInt; i++) {
9996            if (markers[i]) {
9997                res.setUnsafe(j, this.getUnsafe(i))
9998                ++j
9999            }
10000        }
10001        return res
10002    }
10003
10004    /**
10005     * creates a new Uint32Array from current Uint32Array based on a condition fn
10006     *
10007     * @param fn the condition to apply for each element
10008     *
10009     * @returns a new Uint32Array with elements from current Uint32Array that satisfy condition fn
10010     */
10011    public filter(fn: (val: number, index: number) => boolean): Uint32Array {
10012        let newF: (val: number, index: number, array: Uint32Array) => boolean =
10013            (val: number, index: number, array: Uint32Array): boolean => { return fn(val, index) }
10014        return this.filter(newF)
10015    }
10016
10017    /**
10018     * Returns the value of the first element in the array where predicate is true, and undefined
10019     * otherwise
10020     *
10021     * @param predicate find calls predicate once for each element of the array, in ascending
10022     * order, until it finds one where predicate returns true. If such an element is found, find
10023     * immediately returns that element value. Otherwise, find returns undefined
10024     *
10025     * @returns number | undefined
10026     */
10027    public find(predicate: (value: number, index: number, array: Uint32Array) => boolean): number | undefined {
10028        for (let i = 0; i < this.lengthInt; i++) {
10029            let val = this.getUnsafe(i) as number
10030            if (predicate(val, i as number, this)) {
10031                return val
10032            }
10033        }
10034        return undefined
10035    }
10036
10037    /**
10038     * Returns the value of the first element in the array where predicate is true, and undefined
10039     * otherwise
10040     *
10041     * @param predicate find calls predicate once for each element of the array, in ascending
10042     * order, until it finds one where predicate returns true. If such an element is found, find
10043     * immediately returns that element value. Otherwise, find returns undefined
10044     *
10045     * @returns number | undefined
10046     */
10047    public find(predicate: (value: number, index: number) => boolean): number | undefined {
10048        return this.find((value: number, index: number, obj: Uint32Array): boolean => predicate(value, index))
10049    }
10050
10051    /**
10052     * Returns the index of the first element in the array where predicate is true, and -1
10053     * otherwise
10054     *
10055     * @param predicate find calls predicate once for each element of the array, in ascending
10056     * order, until it finds one where predicate returns true. If such an element is found,
10057     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
10058     *
10059     * @returns number
10060     */
10061    public findIndex(predicate: (value: number, index: number, obj: Uint32Array) => boolean): number {
10062        for (let i = 0; i < this.lengthInt; i++) {
10063            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
10064                return i as number
10065            }
10066        }
10067        return -1 as number
10068    }
10069
10070    /**
10071     * Returns the index of the first element in the array where predicate is true, and -1
10072     * otherwise
10073     *
10074     * @param predicate find calls predicate once for each element of the array, in ascending
10075     * order, until it finds one where predicate returns true. If such an element is found,
10076     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
10077     *
10078     * @returns number
10079     */
10080    public findIndex(predicate: (value: number, index: number) => boolean): number {
10081        return this.findIndex((value: number, index: number, obj: Uint32Array): boolean => predicate(value, index))
10082    }
10083
10084    /**
10085     * Returns the index of the first element in the array where predicate is true, and -1
10086     * otherwise
10087     *
10088     * @param predicate find calls predicate once for each element of the array, in ascending
10089     * order, until it finds one where predicate returns true. If such an element is found,
10090     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
10091     *
10092     * @returns number
10093     */
10094    public findIndex(predicate: () => boolean): number {
10095        return this.findIndex((value: number, index: number, obj: Uint32Array): boolean => predicate())
10096    }
10097
10098    /**
10099     * Finds the last element in the Uint32Array that satisfies the condition
10100     *
10101     * @param fn condition
10102     *
10103     * @returns the last element that satisfies fn
10104     */
10105    public findLast(fn: (val: number, index: number, array: Uint32Array) => boolean): number {
10106        for (let i = this.lengthInt - 1; i >= 0; i--) {
10107            let val = this.getUnsafe(i) as number
10108            if (fn(val, i as number, this)) {
10109                return val
10110            }
10111        }
10112        throw new Error("Uint32Array.findLast: not implemented if an element was not found")
10113    }
10114
10115    /**
10116     * Finds the last element in the Uint32Array that satisfies the condition
10117     *
10118     * @param fn condition
10119     *
10120     * @returns the last element that satisfies fn
10121     */
10122    public findLast(fn: (val: number, index: number) => boolean): number {
10123        let newF: (val: number, index: number, array: Uint32Array) => boolean =
10124            (val: number, index: number, array: Uint32Array): boolean => { return fn(val, index) }
10125        return this.findLast(newF)
10126    }
10127
10128    /**
10129     * Finds an index of the last element in the Uint32Array that satisfies the condition
10130     *
10131     * @param fn condition
10132     *
10133     * @returns the index of the last element that satisfies fn, -1 otherwise
10134     */
10135    public findLastIndex(fn: (val: number, index: number, array: Uint32Array) => boolean): number {
10136        for (let i = this.lengthInt - 1; i >= 0; i--) {
10137            if (fn(this.getUnsafe(i) as number, i as number, this)) {
10138                return i as number
10139            }
10140        }
10141        return -1 as number
10142    }
10143
10144    /**
10145     * Finds an index of the last element in the Uint32Array that satisfies the condition
10146     *
10147     * @param fn condition
10148     *
10149     * @returns the index of the last element that satisfies fn, -1 otherwise
10150     */
10151    public findLastIndex(fn: (val: number, index: number) => boolean): number {
10152        let newF: (val: number, index: number, array: Uint32Array) => boolean =
10153            (val: number, index: number, array: Uint32Array): boolean => { return fn(val, index) }
10154        return this.findLastIndex(newF) as number
10155    }
10156
10157    /**
10158     * Performs the specified action for each element in Uint32Array
10159     *
10160     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
10161     * callbackfn function one time for each element in the array.
10162     *
10163     * @returns None
10164     */
10165    public forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void): void {
10166        for (let i = 0; i < this.lengthInt; i++) {
10167            callbackfn(this.getUnsafe(i) as number, i as number, this)
10168        }
10169    }
10170
10171    /**
10172     * Performs the specified action for each element in Uint32Array
10173     *
10174     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
10175     * callbackfn function one time for each element in the array.
10176     *
10177     * @returns None
10178     */
10179    public forEach(callbackfn: (value: number, index: number) => void): void {
10180        this.forEach((value: number, index: number, array: Uint32Array): void => callbackfn(value, index))
10181    }
10182
10183    /**
10184     * Performs the specified action for each element in Uint32Array
10185     *
10186     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
10187     * callbackfn function one time for each element in the array.
10188     *
10189     * @returns None
10190     */
10191    public forEach(callbackfn: () => void): void {
10192        this.forEach((value: number, index: number, array: Uint32Array): void => callbackfn())
10193    }
10194
10195    /**
10196     * Returns the object itself
10197     *
10198     * @returns Uint32Array
10199     */
10200    public valueOf(): Uint32Array {
10201        return this
10202    }
10203
10204    /** Byte offset within the underlying Buffer */
10205    public get byteOffset(): number {
10206        return this.byteOffsetInt
10207    }
10208
10209    /** Number of bytes used */
10210    public get byteLength(): number {
10211        return this.byteLengthInt
10212    }
10213
10214    /** Number of long stored in Uint32Array */
10215    public get length(): number {
10216        return this.lengthInt
10217    }
10218
10219    /** String \"Uint32Array\" */
10220    public readonly name = "Uint32Array"
10221
10222    private static clamp(val: long): long {
10223        return val
10224    }
10225
10226    internal setUnsafeClamp(insertPos: int, val: long): void {
10227        this.setUnsafe(insertPos, val)
10228    }
10229
10230    internal getUnsafe(index: int): long {
10231        index = index * Uint32Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
10232        let res: long = 0
10233        if (IS_LITTLE_ENDIAN) {
10234            if (this.buffer instanceof ArrayBuffer) {
10235                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10236                    let el = (this.buffer as ArrayBuffer).at(index + i) as long
10237                    el &= 0xff
10238                    res |= el << (8 * i)
10239                }
10240            } else if (this.buffer instanceof SharedArrayBuffer) {
10241                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10242                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as long
10243                    el &= 0xff
10244                    res |= el << (8 * i)
10245                }
10246            } else {
10247                throw new Error("unexpected type of ArrayBufferLike")
10248            }
10249        } else {
10250            if (this.buffer instanceof ArrayBuffer) {
10251                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10252                    let el = (this.buffer as ArrayBuffer).at(index + 3 - i) as long
10253                    el &= 0xff
10254                    res |= el << (8 * i)
10255                }
10256            } else if (this.buffer instanceof SharedArrayBuffer) {
10257                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10258                    let el = (this.buffer as SharedArrayBuffer).at(index + 3 - i) as long
10259                    el &= 0xff
10260                    res |= el << (8 * i)
10261                }
10262            } else {
10263                throw new Error("unexpected type of ArrayBufferLike")
10264            }
10265        }
10266        return res
10267    }
10268
10269    internal setUnsafe(index: int, val: long): void {
10270        index = index * Uint32Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
10271        let res: long = 0
10272        if (IS_LITTLE_ENDIAN) {
10273            if (this.buffer instanceof ArrayBuffer) {
10274                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10275                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
10276                    val = val >> 8
10277                }
10278            } else if (this.buffer instanceof SharedArrayBuffer) {
10279                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10280                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
10281                    val = val >> 8
10282                }
10283            } else {
10284                throw new Error("unexpected type of ArrayBufferLike")
10285            }
10286        } else {
10287            if (this.buffer instanceof ArrayBuffer) {
10288                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10289                    (this.buffer as ArrayBuffer).set(index + 3 - i, (val & 0xff) as byte)
10290                    val = val >> 8
10291                }
10292            } else if (this.buffer instanceof SharedArrayBuffer) {
10293                for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
10294                    (this.buffer as SharedArrayBuffer).set(index + 3 - i, (val & 0xff) as byte)
10295                    val = val >> 8
10296                }
10297            } else {
10298                throw new Error("unexpected type of ArrayBufferLike")
10299            }
10300        }
10301    }
10302}
10303
10304
10305class BigUint64ArrayIteratorKeys implements IterableIterator<number> {
10306    private length: int = 0
10307    private idx: int = 0
10308
10309    constructor(parent: BigUint64Array) {
10310        this.length = parent.length as int
10311    }
10312
10313    public override $_iterator(): IterableIterator<Number> {
10314        return this
10315    }
10316
10317    override next(): IteratorResult<number> {
10318        if (this.idx < 0 || this.idx >= this.length) {
10319            return new IteratorResult<number>()
10320        }
10321        return new IteratorResult<number>(false, this.idx++ as number)
10322    }
10323}
10324
10325class BigUint64ArrayIterator implements IterableIterator<BigInt> {
10326    private parent: BigUint64Array
10327    private idx: int = 0
10328
10329    constructor(parent: BigUint64Array) {
10330        this.parent = parent
10331    }
10332
10333    public override $_iterator(): IterableIterator<BigInt> {
10334        return this
10335    }
10336
10337    override next(): IteratorResult<BigInt> {
10338        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
10339            return new IteratorResult<BigInt>()
10340        }
10341        return new IteratorResult<BigInt>(false, new BigInt(this.parent.getUnsafe(this.idx++)))
10342    }
10343}
10344
10345class BigUint64ArrayIteratorEntries implements IterableIterator<[Number, BigInt]> {
10346    private parent: BigUint64Array
10347    private idx: int = 0
10348
10349    constructor(parent: BigUint64Array) {
10350        this.parent = parent
10351    }
10352
10353    public override $_iterator(): IterableIterator<[Number, BigInt]> {
10354        return this
10355    }
10356
10357    override next(): IteratorResult<[Number, BigInt]> {
10358        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
10359            return new IteratorResult<[Number, BigInt]>()
10360        }
10361        return new IteratorResult<[Number, BigInt]>(
10362            false,
10363            [new Number(this.idx), new BigInt(this.parent.getUnsafe(this.idx++))] as [Number, BigInt]
10364        )
10365    }
10366}
10367
10368/**
10369 * JS BigUint64Array API-compatible class
10370 */
10371export class BigUint64Array implements Iterable<BigInt>, ArrayLike<BigInt> {
10372    public static readonly BYTES_PER_ELEMENT: number = 8
10373
10374    /** Underlying Buffer */
10375    public readonly buffer: ArrayBufferLike
10376
10377    internal readonly byteOffsetInt: int
10378    internal readonly byteLengthInt: int
10379    internal readonly lengthInt: int
10380
10381    /**
10382     * Creates an empty BigUint64Array.
10383     */
10384    public constructor() {
10385        this(0 as int)
10386    }
10387
10388    /**
10389     * Creates an BigUint64Array with respect to data accessed via Iterable<Number> interface
10390     */
10391    public constructor(elements: Iterable<BigInt>) {
10392        // NOTE (ikorobkov): dealing with this overload is tricky
10393        // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
10394        let arr = Array.from<BigInt>(elements)
10395        this.byteLengthInt = arr.length as int * BigUint64Array.BYTES_PER_ELEMENT as int
10396        this.lengthInt = arr.length as int
10397        this.buffer = new ArrayBuffer(this.byteLengthInt)
10398        this.byteOffsetInt = 0
10399        for (let i: int = 0; i < this.lengthInt; ++i) {
10400            this.setUnsafe(i, arr.$_get(i).getULong())
10401        }
10402    }
10403
10404    /**
10405     * Creates an BigUint64Array with respect to data, byteOffset and length.
10406     *
10407     * @param buf data initializer
10408     *
10409     * @param byteOffset byte offset from begin of the buf
10410     *
10411     * @param length size of elements of type long in newly created BigUint64Array
10412     */
10413    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined, length: Number | undefined) {
10414        let intByteOffset: int = 0
10415        if (byteOffset != undefined) {
10416            intByteOffset = byteOffset.intValue()
10417            if (intByteOffset < 0) {
10418                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
10419            }
10420        }
10421        let intByteLength: int
10422        if (buf instanceof ArrayBuffer) {
10423            intByteLength = (buf as ArrayBuffer).getByteLength()
10424        } else if (buf instanceof SharedArrayBuffer) {
10425            intByteLength = (buf as SharedArrayBuffer).getByteLength()
10426        } else {
10427            throw new Error("unexpected type of ArrayBufferLike")
10428        }
10429        intByteLength = intByteLength - intByteOffset
10430        if (intByteLength < 0) {
10431            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
10432        }
10433
10434        if (intByteLength % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10435            throw new RangeError("ArrayBufferLike.byteLength should be multiple of 8 as BigUint64Array.BYTES_PER_ELEMENT")
10436        }
10437        if (intByteOffset % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10438            throw new RangeError("byteOffset should be multiple of 8 as BigUint64Array.BYTES_PER_ELEMENT")
10439        }
10440
10441        let intLength: int
10442        if (length != undefined) {
10443            intLength = length.intValue()
10444            if (intLength > intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int) {
10445                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
10446            }
10447        } else {
10448            intLength = intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int
10449        }
10450        if (intLength < 0) {
10451            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
10452        }
10453        if (intLength < intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int) {
10454            intByteLength = intLength * BigUint64Array.BYTES_PER_ELEMENT as int
10455        }
10456        this.byteLengthInt = intByteLength
10457        this.byteOffsetInt = intByteOffset
10458        this.lengthInt = intLength
10459        this.buffer = buf
10460    }
10461
10462    /**
10463     * Creates an BigUint64Array with respect to data, byteOffset and length.
10464     *
10465     * @param buf data initializer
10466     *
10467     * @param byteOffset byte offset from begin of the buf
10468     */
10469    public constructor(buf: ArrayBufferLike, byteOffset: Number | undefined) {
10470        this(buf, byteOffset, undefined)
10471    }
10472
10473    /**
10474     * Creates an BigUint64Array with respect to data, byteOffset and length.
10475     *
10476     * @param buf data initializer
10477     *
10478     * @param byteOffset byte offset from begin of the buf
10479     *
10480     * @param length size of elements of type long in newly created BigUint64Array
10481     */
10482    public constructor(buf: ArrayBufferLike, byteOffset: number, length: number) {
10483        this(buf, new Number(byteOffset), new Number(length))
10484    }
10485
10486    /**
10487     * Creates an BigUint64Array with respect to buf and byteOffset.
10488     *
10489     * @param buf data initializer
10490     *
10491     * @param byteOffset byte offset from begin of the buf
10492     */
10493    public constructor(buf: ArrayBufferLike, byteOffset: number) {
10494        this(buf, new Number(byteOffset), undefined)
10495    }
10496
10497    /**
10498     * Creates an BigUint64Array with respect to data, byteOffset and length.
10499     *
10500     * @param buf data initializer
10501     *
10502     * @param byteOffset byte offset from begin of the buf
10503     *
10504     * @param length size of elements of type long in newly created BigUint64Array
10505     */
10506    public constructor(buf: ArrayBufferLike, byteOffset: int, length: int) {
10507        this(buf, new Number(byteOffset), new Number(length))
10508    }
10509
10510    /**
10511     * Creates an BigUint64Array with respect to buf and byteOffset.
10512     *
10513     * @param buf data initializer
10514     *
10515     * @param byteOffset byte offset from begin of the buf
10516     */
10517    public constructor(buf: ArrayBufferLike, byteOffset: int) {
10518        this(buf, new Number(byteOffset), undefined)
10519    }
10520
10521    /**
10522     * Creates an BigUint64Array with respect to buf.
10523     *
10524     * @param buf data initializer
10525     */
10526    public constructor(buf: ArrayLike<Number> | ArrayBufferLike) {
10527        if (buf instanceof ArrayBuffer) {
10528            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
10529            if (this.byteLengthInt % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10530               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as BigUint64Array.BYTES_PER_ELEMENT")
10531            }
10532            this.lengthInt = this.byteLengthInt / BigUint64Array.BYTES_PER_ELEMENT as int
10533            this.buffer = buf as ArrayBuffer
10534            this.byteOffsetInt = 0
10535        } else if (buf instanceof SharedArrayBuffer) {
10536            this.byteLengthInt = (buf as SharedArrayBuffer).getByteLength()
10537            if (this.byteLengthInt % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
10538               throw new RangeError("ArrayBufferLike.byteLength should be multiple of long as BigUint64Array.BYTES_PER_ELEMENT")
10539            }
10540            this.lengthInt = this.byteLengthInt / BigUint64Array.BYTES_PER_ELEMENT as int
10541            this.buffer = buf as SharedArrayBuffer
10542            this.byteOffsetInt = 0
10543        } else if (buf instanceof ArrayLike) {
10544            // NOTE (ikorobkov): dealing with this overload is tricky
10545            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.sts
10546            let arr = Array.from<Number>((buf as ArrayLike<Number>))
10547            this.byteLengthInt = arr.length as int * BigUint64Array.BYTES_PER_ELEMENT as int
10548            this.lengthInt = arr.length as int
10549            this.buffer = new ArrayBuffer(this.byteLengthInt)
10550            this.byteOffsetInt = 0
10551            for (let i: int = 0; i < this.lengthInt; ++i) {
10552                this.setUnsafe(i, arr.$_get(i).longValue())
10553            }
10554        } else {
10555            throw new Error("unexpected type of buf")
10556        }
10557    }
10558
10559    /**
10560     * Creates an BigUint64Array with respect to length.
10561     *
10562     * @param length data initializer
10563     */
10564    public constructor(length: int) {
10565        if (length < 0) {
10566            throw new RangeError("Range Error: length " + length + " is outside the bounds of the buffer")
10567        }
10568        this.lengthInt = length
10569        this.byteLengthInt = length * BigUint64Array.BYTES_PER_ELEMENT as int
10570        this.byteOffsetInt = 0
10571        this.buffer = new ArrayBuffer(this.byteLengthInt)
10572    }
10573
10574    /**
10575     * Creates an BigUint64Array with respect to length.
10576     *
10577     * @param length data initializer
10578     */
10579    public constructor(length: number) {
10580        this(length as int)
10581    }
10582
10583    /**
10584     * Creates a copy of BigUint64Array.
10585     *
10586     * @param other data initializer
10587     */
10588    public constructor(other: BigUint64Array) {
10589        if (other.buffer instanceof ArrayBuffer) {
10590            this.buffer = (other.buffer as ArrayBuffer).slice(0 as int, other.byteLength as int) as ArrayBuffer
10591        } else if (other.buffer instanceof SharedArrayBuffer) {
10592            this.buffer = (other.buffer as SharedArrayBuffer).slice(0 as int, other.byteLength as int) as SharedArrayBuffer
10593        } else {
10594            throw new Error("unexpected type of buffer")
10595        }
10596        this.byteLengthInt = other.byteLength as int
10597        this.lengthInt = other.length as int
10598        this.byteOffsetInt = 0
10599    }
10600
10601    /**
10602     * Creates an BigUint64Array from number[]
10603     */
10604    public constructor(numbers: number[]) {
10605        this(numbers.length)
10606        for (let i: int = 0; i < this.lengthInt; ++i) {
10607            this.setUnsafeClamp(i, this.zeroIfInfinity(new BigInt(numbers[i]).getULong()))
10608        }
10609    }
10610
10611    /**
10612     * Creates an BigUint64Array from int[]
10613     */
10614    public constructor(numbers: int[]) {
10615        this(numbers.length)
10616        for (let i: int = 0; i < this.lengthInt; ++i) {
10617            this.setUnsafeClamp(i, this.zeroIfInfinity(new BigInt(numbers[i]).getULong()))
10618        }
10619    }
10620
10621    internal zeroIfInfinity(val: BigInt): BigInt {
10622        if ((val.getULong() == Infinity) || (val.getULong() == -Infinity)) {
10623            return new BigInt(0)
10624        }
10625        return new BigInt(val)
10626    }
10627
10628    internal zeroIfInfinity(val: long): long {
10629        if ((val == Infinity) || (val == -Infinity)) {
10630            return 0 as long
10631        }
10632        return val
10633    }
10634
10635    /**
10636     * Iteratorable interface implementation
10637     *
10638     * @returns iterator over all elements
10639     */
10640    public override $_iterator(): IterableIterator<BigInt> {
10641         return this.values()
10642    }
10643
10644    /**
10645     * Returns an instance of primitive type at passed index.
10646     *
10647     * @param index index to look at
10648     *
10649     * @returns a primitive at index
10650     */
10651    public at(index: number): BigInt | undefined {
10652        return this.at(index as int)
10653    }
10654
10655    /**
10656     * Returns an instance of primitive type at passed index if index is correct.
10657     *
10658     * @param index index to look at
10659     *
10660     * @returns a primitive at index
10661     */
10662    public at(index: int): BigInt | undefined {
10663        let k: int
10664        if (index >= 0) {
10665            k = index
10666        } else {
10667            k = this.lengthInt + index
10668        }
10669        if (k < 0 || k >= this.lengthInt) {
10670            return undefined
10671        }
10672        return new BigInt(this.getUnsafe(k))
10673    }
10674
10675    /**
10676     * Returns an instance of BigInt at passed index.
10677     *
10678     * @param index index to look at
10679     *
10680     * @returns a primitive at index
10681     */
10682    public override $_get(index: number): BigInt {
10683        return this.$_get(index as int) as BigInt
10684    }
10685
10686    /**
10687     * Returns an instance of BigInt at passed index.
10688     *
10689     * @param index index to look at
10690     *
10691     * @returns a primitive at index
10692     */
10693    public $_get(i: int): BigInt {
10694        if (i < 0 || i >= this.lengthInt) {
10695            throw new RangeError("invalid offset")
10696        }
10697        return new BigInt(this.getUnsafe(i))
10698    }
10699
10700    /**
10701     * Assigns val as element on index.
10702     *
10703     * @param val value to set
10704     *
10705     * @param index index to change
10706     */
10707    public $_set(index: number, val: BigInt): void {
10708        this.$_set(index as int, val)
10709    }
10710
10711    /**
10712     * Assigns val as element on index.
10713     *
10714     * @param val value to set
10715     *
10716     * @param index index to change
10717     */
10718    public $_set(index: int, val: BigInt): void {
10719        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
10720        if (index < 0 || index >= this.lengthInt) {
10721            throw new RangeError("invalid index")
10722        }
10723        let v = this.zeroIfInfinity(val)
10724        this.setUnsafeClamp(index, v.getULong())
10725    }
10726
10727    /**
10728     * Assigns val as element on index.
10729     *
10730     * @param val value to set
10731     *
10732     * @param index index to change
10733     */
10734    public $_set(index: number, val: long): void {
10735        this.$_set(index as int, val)
10736    }
10737
10738    /**
10739     * Assigns val as element on index.
10740     *
10741     * @param val value to set
10742     *
10743     * @param index index to change
10744     */
10745    public $_set(index: int, val: long): void {
10746        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
10747        if (index < 0 || index >= this.lengthInt) {
10748            throw new RangeError("invalid index")
10749        }
10750        let v = this.zeroIfInfinity(val)
10751        this.setUnsafeClamp(index, v)
10752    }
10753
10754    /**
10755     * Assigns val as element on index.
10756     *
10757     * @param val value to set
10758     *
10759     * @param index index to change
10760     */
10761    public $_set(index: number, val: int): void {
10762        this.$_set(index as int, val as int)
10763    }
10764
10765    /**
10766     * Assigns val as element on index.
10767     *
10768     * @param val value to set
10769     *
10770     * @param index index to change
10771     */
10772    public $_set(index: int, val: int): void {
10773        // NOTE (ikorobkov): TS doesn't throw exception. Exception was added to avoid memory's out-of-range access
10774        if (index < 0 || index >= this.lengthInt) {
10775            throw new RangeError("invalid index")
10776        }
10777        let v = this.zeroIfInfinity(val as long)
10778        this.setUnsafeClamp(index, v)
10779    }
10780
10781    /**
10782     * Makes a copy of internal elements to targetPos from startPos to endPos.
10783     *
10784     * @param target insert index to place copied elements
10785     *
10786     * @param start start index to begin copy from
10787     *
10788     * @param end last index to end copy from, excluded
10789     *
10790     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
10791     */
10792    public copyWithin(target: number, start: number, end?: number): BigUint64Array {
10793        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
10794    }
10795
10796    /**
10797     * Makes a copy of internal elements to targetPos from startPos to endPos.
10798     *
10799     * @param target insert index to place copied elements
10800     *
10801     * @param start start index to begin copy from
10802     *
10803     * @param end last index to end copy from, excluded
10804     *
10805     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
10806     */
10807    public copyWithin(target: int, start: number, end?: number): BigUint64Array {
10808        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
10809    }
10810
10811    /**
10812     * Makes a copy of internal elements to targetPos from startPos to endPos.
10813     *
10814     * @param target insert index to place copied elements
10815     *
10816     * @param start start index to begin copy from
10817     *
10818     * @param end last index to end copy from, excluded
10819     *
10820     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
10821     */
10822    public copyWithin(target: number, start: int, end?: number): BigUint64Array {
10823        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
10824    }
10825
10826    /**
10827     * Makes a copy of internal elements to targetPos from startPos to endPos.
10828     *
10829     * @param target insert index to place copied elements
10830     *
10831     * @param start start index to begin copy from
10832     *
10833     * @param end last index to end copy from, excluded
10834     *
10835     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
10836     */
10837    public copyWithin(target: int, start: int, end?: number): BigUint64Array {
10838        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
10839    }
10840
10841    /**
10842     * Makes a copy of internal elements to targetPos from startPos to endPos.
10843     *
10844     * @param insert insert index to place copied elements
10845     *
10846     * @param start start index to begin copy from
10847     *
10848     * @param end last index to end copy from, excluded
10849     *
10850     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
10851     */
10852    public copyWithin(target: int, start: int, end: int): BigUint64Array {
10853        let toPos = normalizeIndex(target, this.lengthInt)
10854        let fromPos = normalizeIndex(start, this.lengthInt)
10855        const finalPos = normalizeIndex(end, this.lengthInt)
10856        let count: int = finalPos - fromPos
10857        if (count > (this.lengthInt - toPos)) {
10858            count = this.lengthInt - toPos
10859        }
10860        let direction: int = 1
10861        if ((fromPos < toPos) && (toPos < fromPos + count)) {
10862            fromPos = fromPos + count - 1
10863            toPos   = toPos   + count - 1
10864            direction = -1
10865        }
10866        while (count > 0) {
10867            const value = this.getUnsafe(fromPos)
10868            this.setUnsafe(toPos, value)
10869            fromPos = fromPos + direction
10870            toPos = toPos + direction
10871            --count
10872        }
10873        return this
10874    }
10875
10876    /**
10877     * Makes a copy of internal elements to targetPos from begin to end of BigUint64Array.
10878     *
10879     * @param target insert index to place copied elements
10880     *
10881     * See rules of parameters normalization:
10882     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
10883     */
10884    public copyWithin(target: number): BigUint64Array {
10885        return this.copyWithin(target as int)
10886    }
10887
10888    /**
10889     * Makes a copy of internal elements to targetPos from begin to end of BigUint64Array.
10890     *
10891     * @param insert insert index to place copied elements
10892     *
10893     * See rules of parameters normalization:
10894     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
10895     */
10896    public copyWithin(target: int): BigUint64Array {
10897        return this.copyWithin(target, 0, this.lengthInt)
10898    }
10899
10900    /**
10901     * Returns an array of key, value pairs for every entry in the BigUint64Array
10902     *
10903     * @returns key, value pairs for every entry in the array
10904     */
10905    public entries(): IterableIterator<[Number, BigInt]> {
10906        return new BigUint64ArrayIteratorEntries(this)
10907    }
10908
10909    /**
10910     * Fills the BigUint64Array with specified value
10911     *
10912     * @param value new value
10913     *
10914     * @returns modified BigUint64Array
10915     */
10916    public fill(value: BigInt, start?: number, end?: number): BigUint64Array {
10917        value = this.zeroIfInfinity(value)
10918        this.fill(value.getULong(), asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
10919        return this
10920    }
10921
10922    /**
10923     * Fills the BigUint64Array with specified value
10924     *
10925     * @param value new value
10926     *
10927     * @returns modified BigUint64Array
10928     */
10929    public fill(value: BigInt, start: int, end?: number): BigUint64Array {
10930        value = this.zeroIfInfinity(value)
10931        this.fill(value.getULong(), start as int, asIntOrDefault(end, this.lengthInt))
10932        return this
10933    }
10934
10935    /**
10936     * Fills the BigUint64Array with specified value
10937     *
10938     * @param value new value
10939     *
10940     * @returns modified BigUint64Array
10941     */
10942    public fill(value: BigInt, start: int, end: number): BigUint64Array {
10943        value = this.zeroIfInfinity(value)
10944        this.fill(value.getULong(), start as int, end as int)
10945        return this
10946    }
10947
10948    /**
10949     * Fills the BigUint64Array with specified value
10950     *
10951     * @param value new value
10952     *
10953     * @returns modified BigUint64Array
10954     */
10955    public fill(value: BigInt, start: number, end: int): BigUint64Array {
10956        value = this.zeroIfInfinity(value)
10957        this.fill(value.getULong(), start as int, end as int)
10958        return this
10959    }
10960
10961    /**
10962     * Fills the BigUint64Array with specified value
10963     *
10964     * @param value new value
10965     *
10966     * @returns modified BigUint64Array
10967     */
10968    public fill(value: BigInt, start: int, end: int): BigUint64Array {
10969        value = this.zeroIfInfinity(value)
10970        this.fill(value.getULong(), start as int, end as int)
10971        return this
10972    }
10973
10974    /**
10975     * Fills the BigUint64Array with specified value
10976     *
10977     * @param value new value
10978     *
10979     * @returns modified BigUint64Array
10980     */
10981    public fill(value: long, start?: number, end?: number): BigUint64Array {
10982        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
10983        return this
10984    }
10985
10986    /**
10987     * Fills the BigUint64Array with specified value
10988     *
10989     * @param value new value
10990     *
10991     * @returns modified BigUint64Array
10992     */
10993    public fill(value: long, start: int, end?: number): BigUint64Array {
10994        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
10995        return this
10996    }
10997
10998    /**
10999     * Fills the BigUint64Array with specified value
11000     *
11001     * @param value new value
11002     *
11003     * @returns modified BigUint64Array
11004     */
11005    public fill(value: long, start: int, end: number): BigUint64Array {
11006        this.fill(value, start as int, end as int)
11007        return this
11008    }
11009
11010    /**
11011     * Fills the BigUint64Array with specified value
11012     *
11013     * @param value new value
11014     *
11015     * @returns modified BigUint64Array
11016     */
11017    public fill(value: long, start: number, end: int): BigUint64Array {
11018        this.fill(value, start as int, end as int)
11019        return this
11020    }
11021
11022    /**
11023     * Fills the BigUint64Array with specified value
11024     *
11025     * @param value new value
11026     *
11027     * @returns modified BigUint64Array
11028     */
11029    public fill(value: long, start: int, end: int): BigUint64Array {
11030        const k = normalizeIndex(start, this.lengthInt)
11031        const finalPos = normalizeIndex(end, this.lengthInt)
11032        for (let i: int = k; i < finalPos; ++i) {
11033            this.setUnsafe(i, value)
11034        }
11035        return this
11036    }
11037
11038    /**
11039     * Assigns val as element on index.
11040     *
11041     * @param val value to set
11042     *
11043     * @param index index to change
11044     */
11045    public set(insertPos: number, val: BigInt): void {
11046        this.$_set(insertPos as int, val)
11047    }
11048
11049    /**
11050     * Assigns val as element on index.
11051     *
11052     * @param val value to set
11053     *
11054     * @param index index to change
11055     */
11056    public set(insertPos: int, val: BigInt): void {
11057        this.$_set(insertPos as int, val)
11058    }
11059
11060    /**
11061     * Assigns val as element on index.
11062     *
11063     * @param val value to set
11064     *
11065     * @param index index to change
11066     */
11067    public set(insertPos: number, val: long): void {
11068        this.$_set(insertPos as int, val)
11069    }
11070
11071    /**
11072     * Assigns val as element on index.
11073     *
11074     * @param val value to set
11075     *
11076     * @param index index to change
11077     */
11078    public set(insertPos: int, val: long): void {
11079        this.$_set(insertPos as int, val)
11080    }
11081
11082    /**
11083     * Copies all elements of arr to the current BigUint64Array starting from insertPos.
11084     *
11085     * @param arr array to copy data from
11086     *
11087     * @param insertPos start index where data from arr will be inserted
11088     *
11089     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
11090     */
11091    public set(arr: BigInt[], insertPos1: number): void {
11092        const insertPos = insertPos1 as int
11093        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
11094            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than BigUint64Array.length")
11095        }
11096        for (let i = 0; i < arr.length; i++) {
11097            let v = this.zeroIfInfinity(arr[i])
11098            this.setUnsafeClamp(insertPos as int + i as int, v.getULong())
11099        }
11100    }
11101
11102    /**
11103     * Copies all elements of arr to the current BigUint64Array starting from insertPos.
11104     *
11105     * @param arr array to copy data from
11106     *
11107     * @param insertPos start index where data from arr will be inserted
11108     *
11109     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
11110     */
11111    public set(arr: long[], insertPos: int): void {
11112        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
11113            throw new RangeError("set(insertPos: int, arr: long[]): size of arr is greater than BigUint64Array.length")
11114        }
11115        for (let i = 0; i < arr.length; i++) {
11116            let v = this.zeroIfInfinity(arr[i])
11117            this.setUnsafeClamp(insertPos + i, v)
11118        }
11119    }
11120
11121    /**
11122     * Copies all elements of arr to the current BigUint64Array.
11123     *
11124     * @param arr array to copy data from
11125     */
11126    public set(arr: BigInt[]): void {
11127        this.set(arr, 0)
11128    }
11129
11130    /**
11131     * Copies all elements of arr to the current BigUint64Array.
11132     *
11133     * @param arr array to copy data from
11134     */
11135    public set(arr: long[]): void {
11136        this.set(arr, 0)
11137    }
11138
11139    /**
11140     * Copies elements from an ArrayLike object to the BigUint64Array.
11141     *
11142     * @param array An ArrayLike object containing the elements to copy.
11143     *
11144     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
11145     */
11146    public set(array: ArrayLike<BigInt>, offset: number = 0): void {
11147        const insertPos = offset as int
11148        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
11149            throw new RangeError("offset is out of bounds")
11150        }
11151        for (let i = 0; i < array.length; i++) {
11152            let v = this.zeroIfInfinity(array[i])
11153            this.setUnsafeClamp(insertPos as int + i as int, v.getULong())
11154        }
11155    }
11156
11157    /**
11158     * Returns a new array from a set of elements.
11159     *
11160     * @param items a set of elements to include in the new array object.
11161     *
11162     * @returns new BigUint64Array
11163     */
11164    public static of(...items: number[]): BigUint64Array {
11165        throw new Error("Array.of: not implemented")
11166    }
11167
11168    /**
11169     * Returns a new array from a set of elements.
11170     *
11171     * @param items a set of elements to include in the new array object.
11172     *
11173     * @returns new BigUint64Array
11174     */
11175    public static of(...items: int[]): BigUint64Array {
11176        throw new Error("Array.of: not implemented")
11177    }
11178
11179    /**
11180     * Returns a new array from a set of elements.
11181     *
11182     * @param items a set of elements to include in the new array object.
11183     *
11184     * @returns new BigUint64Array
11185     */
11186    public static of(...items: long[]): BigUint64Array {
11187        throw new Error("Array.of: not implemented")
11188    }
11189
11190    /**
11191     * Returns a new array from a set of elements.
11192     *
11193     * @param items a set of elements to include in the new array object.
11194     *
11195     * @returns new BigUint64Array
11196     */
11197    public static of(): BigUint64Array {
11198        return new BigUint64Array(0 as int)
11199    }
11200
11201    /**
11202     * Creates an array from an array-like or iterable object.
11203     *
11204     * @param arrayLike An array-like or iterable object to convert to an array.
11205     *
11206     * @returns new BigUint64Array
11207     */
11208    public static from(arr: ArrayLike<BigInt>): BigUint64Array {
11209        throw new Error("BigUint64Array.from: not implemented")
11210    }
11211
11212    /**
11213     * Creates an array from an array-like or iterable object.
11214     *
11215     * @param arrayLike An array-like or iterable object to convert to an array.
11216     *
11217     * @param mapfn A mapping function to call on every element of the array.
11218     *
11219     * @returns new BigUint64Array
11220     */
11221    public static from(arrayLike: Iterable<BigInt>, mapfn?: (v: BigInt, k: number) => BigInt): BigUint64Array {
11222        throw new Error("BigUint64Array.from: not implemented")
11223    }
11224
11225    /**
11226     * Creates an array from an array-like or iterable object.
11227     *
11228     * @param arrayLike An array-like or iterable object to convert to an array.
11229     *
11230     * @param mapfn A mapping function to call on every element of the array.
11231     *
11232     * @returns new BigUint64Array
11233     */
11234    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => BigInt): BigUint64Array {
11235        throw new Error("BigUint64Array.from: not implemented")
11236    }
11237
11238    /**
11239     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
11240     *
11241     * @param searchElement The element to search for
11242     *
11243     * @param fromIndex The position in this array at which to begin searching for searchElement
11244     *
11245     * @returns true if searchElement is in BigUint64Array, false otherwise
11246     */
11247    public includes(searchElement: BigInt, fromIndex?: number): boolean {
11248        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
11249    }
11250
11251    /**
11252     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
11253     *
11254     * @param searchElement The element to search for
11255     *
11256     * @param fromIndex The position in this array at which to begin searching for searchElement
11257     *
11258     * @returns true if searchElement is in BigUint64Array, false otherwise
11259     */
11260    public includes(searchElement: long, fromIndex: int): boolean {
11261        return this.indexOf(searchElement as int, fromIndex) != -1
11262    }
11263
11264    /**
11265     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
11266     *
11267     * @param searchElement The element to search for
11268     *
11269     * @param fromIndex The position in this array at which to begin searching for searchElement
11270     *
11271     * @returns true if searchElement is in BigUint64Array, false otherwise
11272     */
11273    public includes(searchElement: long): boolean {
11274        return this.indexOf(searchElement as int, 0) != -1
11275    }
11276
11277    /**
11278     * Returns the index of the first occurrence of a value in BigUint64Array.
11279     *
11280     * @param searchElement The value to locate in the array.
11281     *
11282     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11283     *  search starts at index 0.
11284     *
11285     * @returns index of element if it presents, -1 otherwise
11286     */
11287    public indexOf(searchElement: BigInt, fromIndex?: number): number {
11288        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
11289    }
11290
11291    /**
11292     * Returns the index of the first occurrence of a value in BigUint64Array.
11293     *
11294     * @param searchElement The value to locate in the array.
11295     *
11296     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11297     *  search starts at index 0.
11298     *
11299     * @returns index of element if it presents, -1 otherwise
11300     */
11301    public indexOf(searchElement: BigInt, fromIndex: int): number {
11302        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
11303        for (let i = fromIndex; i < this.lengthInt; i++) {
11304            if (new BigInt(this.getUnsafe(i)) == searchElement) {
11305                return i
11306            }
11307        }
11308        return -1
11309    }
11310
11311    /**
11312     * Returns the index of the first occurrence of a value in BigUint64Array.
11313     *
11314     * @param searchElement The value to locate in the array.
11315     *
11316     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11317     *  search starts at index 0.
11318     *
11319     * @returns index of element if it presents, -1 otherwise
11320     */
11321    public indexOf(searchElement: int, fromIndex: int): number {
11322        fromIndex = normalizeIndex(fromIndex, this.lengthInt)
11323        for (let i = fromIndex; i < this.lengthInt; i++) {
11324            if (this.getUnsafe(i) == searchElement as long) {
11325                return i
11326            }
11327        }
11328        return -1
11329
11330    }
11331
11332    /**
11333     * Returns the index of the first occurrence of a value in BigUint64Array.
11334     *
11335     * @param searchElement The value to locate in the array.
11336     *
11337     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
11338     *  search starts at index 0.
11339     *
11340     * @returns index of element if it presents, -1 otherwise
11341     */
11342    public indexOf(searchElement: int): number {
11343        return this.indexOf(searchElement, 0)
11344    }
11345
11346    /**
11347     * Adds all the elements of an array separated by the specified separator string
11348     *
11349     * @param separator A string used to separate one element of an array from the next in the
11350     * resulting String. If omitted, the array elements are separated with a comma
11351     *
11352     * @returns joined representation
11353     */
11354    public join(separator?: String): string {
11355        if (separator == undefined) {
11356            return this.join(",")
11357        }
11358        let res: StringBuilder = new StringBuilder("")
11359        for (let i = 0; i < this.lengthInt - 1; i++) {
11360            res.append(new BigInt(this.getUnsafe(i)))
11361            res.append(separator)
11362        }
11363        if (this.lengthInt > 0) {
11364            res.append(new BigInt(this.getUnsafe(this.lengthInt - 1)))
11365        }
11366        return res.toString()
11367    }
11368
11369    /**
11370     * Returns an list of keys in BigUint64Array
11371     *
11372     * @returns iterator over keys
11373     */
11374    public keys(): IterableIterator<number> {
11375        return new BigUint64ArrayIteratorKeys(this)
11376    }
11377
11378    /**
11379     * Returns the index of the last occurrence of a value in BigUint64Array.
11380     *
11381     * @param searchElement The value to locate in the array.
11382     *
11383     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11384     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11385     *
11386     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11387     */
11388    public lastIndexOf(searchElement: BigInt, fromIndex: number|undefined): number {
11389        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
11390    }
11391
11392    /**
11393     * Returns the index of the last occurrence of a value in BigUint64Array.
11394     *
11395     * @param searchElement The value to locate in the array.
11396     *
11397     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11398     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11399     *
11400     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11401     */
11402    public lastIndexOf(searchElement: BigInt): number {
11403        return this.lastIndexOf(searchElement, this.lengthInt - 1)
11404    }
11405
11406    /**
11407     * Returns the index of the last occurrence of a value in BigUint64Array.
11408     *
11409     * @param searchElement The value to locate in the array.
11410     *
11411     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11412     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11413     *
11414     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11415     */
11416    public lastIndexOf(searchElement: BigInt, fromIndex: int): number {
11417        if (this.lengthInt == 0) {
11418            return -1
11419        }
11420        let k: int = this.lengthInt + fromIndex
11421        if (fromIndex >= 0) {
11422            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
11423        }
11424        while (k >= 0) {
11425            if (new BigInt(this.getUnsafe(k)) == searchElement) {
11426                return k
11427            }
11428            k--
11429        }
11430        return -1
11431    }
11432
11433    /**
11434     * Returns the index of the last occurrence of a value in BigUint64Array.
11435     *
11436     * @param searchElement The value to locate in the array.
11437     *
11438     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11439     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11440     *
11441     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11442     */
11443    public lastIndexOf(searchElement: int, fromIndex: int): number {
11444        if (this.lengthInt == 0) {
11445            return -1
11446        }
11447        let k: int = this.lengthInt + fromIndex
11448        if (fromIndex >= 0) {
11449            k = (this.lengthInt - 1 < fromIndex) ? this.lengthInt - 1 : fromIndex
11450        }
11451        while (k >= 0) {
11452            if (this.getUnsafe(k) == searchElement as long) {
11453                return k
11454            }
11455            k--
11456        }
11457        return -1
11458    }
11459
11460    /**
11461     * Returns the index of the last occurrence of a value in BigUint64Array.
11462     *
11463     * @param searchElement The value to locate in the array.
11464     *
11465     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
11466     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
11467     *
11468     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
11469     */
11470    public lastIndexOf(searchElement: int): number {
11471        return this.lastIndexOf(searchElement, this.lengthInt - 1)
11472    }
11473
11474   /**
11475    * Creates a new BigUint64Array using initializer
11476    *
11477    * @param data initializer
11478    *
11479    * @returns a new BigUint64Array from data
11480    */
11481    public of(...data: BigInt[]): BigUint64Array {
11482        throw new Error("BigUint64Array.of: not implemented")
11483    }
11484
11485    /**
11486     * Creates a new BigUint64Array using reversed data from the current one
11487     *
11488     * @returns a new BigUint64Array using reversed data from the current one
11489     */
11490    public reverse(): BigUint64Array {
11491        for (let i: int = 0; i < this.lengthInt / 2 as int; i++) {
11492            const tmp = this.getUnsafe(this.lengthInt - 1 - i)
11493            this.setUnsafe(this.lengthInt - 1 - i, this.getUnsafe(i))
11494            this.setUnsafe(i, tmp)
11495        }
11496        return this
11497    }
11498
11499    /**
11500     * Creates a slice of current BigUint64Array using range [begin, end)
11501     *
11502     * @param begin start index to be taken into slice
11503     *
11504     * @param end last index to be taken into slice
11505     *
11506     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11507     *
11508     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11509     */
11510    public slice(begin?: number, end?: number): BigUint64Array {
11511        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
11512    }
11513
11514    /**
11515     * Creates a slice of current BigUint64Array using range [begin, end)
11516     *
11517     * @param begin start index to be taken into slice
11518     *
11519     * @param end last index to be taken into slice
11520     *
11521     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11522     *
11523     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11524     */
11525    public slice(begin: number, end: number): BigUint64Array {
11526        return this.slice(begin as int, end as int)
11527    }
11528
11529    /**
11530     * Creates a slice of current BigUint64Array using range [begin, end)
11531     *
11532     * @param begin start index to be taken into slice
11533     *
11534     * @param end last index to be taken into slice
11535     *
11536     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11537     *
11538     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11539     */
11540    public slice(begin: number, end: int): BigUint64Array {
11541        return this.slice(begin as int, end as int)
11542    }
11543
11544    /**
11545     * Creates a slice of current BigUint64Array using range [begin, end)
11546     *
11547     * @param begin start index to be taken into slice
11548     *
11549     * @param end last index to be taken into slice
11550     *
11551     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11552     *
11553     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11554     */
11555    public slice(begin: int, end: number): BigUint64Array {
11556        return this.slice(begin as int, end as int)
11557    }
11558
11559    /**
11560     * Creates a slice of current BigUint64Array using range [begin, end)
11561     *
11562     * @param begin start index to be taken into slice
11563     *
11564     * @param end last index to be taken into slice
11565     *
11566     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
11567     *
11568     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
11569     */
11570    public slice(begin: int, end: int): BigUint64Array {
11571        const len: int = this.lengthInt
11572        const relStart = normalizeIndex(begin, len)
11573        const relEnd = normalizeIndex(end, len)
11574        let count = relEnd - relStart
11575        if (count < 0) {
11576            count = 0
11577        }
11578        if (this.buffer instanceof ArrayBuffer) {
11579            let buf = (this.buffer as ArrayBuffer).slice(relStart * BigUint64Array.BYTES_PER_ELEMENT as int, relEnd * BigUint64Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
11580            return new BigUint64Array(buf)
11581        } else if (this.buffer instanceof SharedArrayBuffer) {
11582            let buf = (this.buffer as SharedArrayBuffer).slice(relStart * BigUint64Array.BYTES_PER_ELEMENT as int, relEnd * BigUint64Array.BYTES_PER_ELEMENT as int) as SharedArrayBuffer
11583            return new BigUint64Array(buf)
11584        } else {
11585            throw new Error("unexpected type of buffer")
11586        }
11587    }
11588
11589    /**
11590     * Creates a slice of current BigUint64Array using range [begin, this.lengthInt).
11591     *
11592     * @param begin start index to be taken into slice
11593     *
11594     * @returns a new BigUint64Array with elements of current BigUint64Array[begin, this.lengthInt)
11595     */
11596    public slice(begin: number): BigUint64Array {
11597        return this.slice(begin as int)
11598    }
11599
11600    /**
11601     * Creates a slice of current BigUint64Array using range [begin, this.lengthInt).
11602     *
11603     * @param begin start index to be taken into slice
11604     *
11605     * @returns a new BigUint64Array with elements of current BigUint64Array[begin, this.lengthInt)
11606     */
11607    public slice(begin: int): BigUint64Array {
11608        return this.slice(begin, this.lengthInt)
11609    }
11610
11611    /**
11612     * Sorts in-place
11613     *
11614     * @param compareFn comparator —  used to determine the order of the elements.
11615     * compareFn returns a negative value if first argument is less than second argument,
11616     * zero if they're equal and a positive value otherwise.
11617     * If omitted, the elements are sorted in ascending order.
11618     *
11619     * @returns sorted BigUint64Array
11620     */
11621    public sort(compareFn?: (a: BigInt, b: BigInt) => number): this {
11622        let arr: long[] = new long[this.lengthInt]
11623        for (let i = 0; i < this.lengthInt; ++i) {
11624            arr[i] = this.getUnsafe(i)
11625        }
11626        let cmp = (l: long, r: long): number => {
11627                return (l - r) as number
11628            }
11629        if (compareFn != undefined) {
11630            cmp = (l: long, r: long): number => {
11631                return compareFn!(new BigInt(l), new BigInt(r))
11632            }
11633        }
11634        sort(arr, cmp)
11635        for (let i = 0; i < this.lengthInt; ++i) {
11636            this.setUnsafe(i, arr[i])
11637        }
11638        return this
11639    }
11640
11641    /**
11642     * Sorts in-place
11643     *
11644     * @param compareFn comparator —  used to determine the order of the elements.
11645     * compareFn returns a negative value if first argument is less than second argument,
11646     * zero if they're equal and a positive value otherwise.
11647     *
11648     * @returns sorted BigUint64Array
11649     */
11650    public sort(compareFn: (a: BigInt) => number): this {
11651        let cmp = (a: BigInt, b: BigInt) => { return compareFn(a)}
11652        this.sort(cmp)
11653        return this
11654    }
11655
11656    /**
11657     * Sorts in-place
11658     *
11659     * @param fn compareFn —  used to determine the order of the elements.
11660     * compareFn returns a negative value if first argument is less than second argument,
11661     * zero if they're equal and a positive value otherwise.
11662     *
11663     * @returns sorted BigUint64Array
11664     */
11665    public sort(compareFn: () => number): this {
11666        let cmp = (a: BigInt, b: BigInt) => { return compareFn()}
11667        this.sort(cmp)
11668        return this
11669    }
11670    /**
11671     * Creates a BigUint64Array with the same underlying Buffer
11672     *
11673     * @param begin start index, inclusive
11674     *
11675     * @param end last index, exclusive
11676     *
11677     * @returns new BigUint64Array with the same underlying Buffer
11678     */
11679    public subarray(begin?: number, end?: number): BigUint64Array {
11680        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
11681    }
11682
11683    /**
11684     * Creates a BigUint64Array with the same underlying Buffer
11685     *
11686     * @param begin start index, inclusive
11687     *
11688     * @param end last index, exclusive
11689     *
11690     * @returns new BigUint64Array with the same underlying Buffer
11691     */
11692    public subarray(begin: number, end: number): BigUint64Array {
11693        return this.subarray(begin as int, end as int)
11694    }
11695
11696    /**
11697     * Creates a BigUint64Array with the same underlying Buffer
11698     *
11699     * @param begin start index, inclusive
11700     *
11701     * @param end last index, exclusive
11702     *
11703     * @returns new BigUint64Array with the same underlying Buffer
11704     */
11705    public subarray(begin: number, end: int): BigUint64Array {
11706        return this.subarray(begin as int, end as int)
11707    }
11708
11709    /**
11710     * Creates a BigUint64Array with the same underlying Buffer
11711     *
11712     * @param begin start index, inclusive
11713     *
11714     * @param end last index, exclusive
11715     *
11716     * @returns new BigUint64Array with the same underlying Buffer
11717     */
11718    public subarray(begin: int, end: number): BigUint64Array {
11719        return this.subarray(begin as int, end as int)
11720    }
11721
11722    /**
11723     * Creates a BigUint64Array with the same underlying Buffer
11724     *
11725     * @param begin start index, inclusive
11726     *
11727     * @param end last index, exclusive
11728     *
11729     * @returns new BigUint64Array with the same underlying Buffer
11730     */
11731    public subarray(begin: int, end: int): BigUint64Array {
11732        const len: int = this.lengthInt
11733        const relStart = normalizeIndex(begin, len)
11734        const relEnd = normalizeIndex(end, len)
11735        let count = relEnd - relStart
11736        if (count < 0) {
11737            count = 0
11738        }
11739        return new BigUint64Array(this.buffer, relStart * BigUint64Array.BYTES_PER_ELEMENT as int, count)
11740    }
11741
11742    /**
11743     * Creates a BigUint64Array with the same Buffer
11744     *
11745     * @param begin start index, inclusive
11746     *
11747     * @returns new BigUint64Array with the same Buffer
11748     */
11749    public subarray(begin: number): BigUint64Array {
11750        return this.subarray(begin as int, this.lengthInt)
11751    }
11752
11753    /**
11754     * Creates a BigUint64Array with the same Buffer
11755     *
11756     * @param begin start index, inclusive
11757     *
11758     * @returns new BigUint64Array with the same Buffer
11759     */
11760    public subarray(begin: int): BigUint64Array {
11761        return this.subarray(begin, this.lengthInt)
11762    }
11763
11764    /**
11765     * Converts BigUint64Array to a string with respect to locale
11766     *
11767     * @param locales
11768     *
11769     * @param options
11770     *
11771     * @returns string representation
11772     */
11773    public toLocaleString(locales: Object, options: Object): string {
11774        throw new Error("BigUint64Array.toLocaleString: not implemented")
11775    }
11776
11777    /**
11778     * Converts BigUint64Array to a string with respect to locale
11779     *
11780     * @param locales
11781     *
11782     * @returns string representation
11783     */
11784    public toLocaleString(locales: Object): string {
11785        return this.toLocaleString(new Object(), new Object())
11786    }
11787
11788    /**
11789     * Converts BigUint64Array to a string with respect to locale
11790     *
11791     * @returns string representation
11792     */
11793    public toLocaleString(): string {
11794        let res: StringBuilder = new StringBuilder("")
11795        for (let i = 0; i < this.lengthInt - 1; ++i) {
11796            res.append(new BigInt(this.getUnsafe(i)).toLocaleString())
11797            res.append(",")
11798        }
11799        if (this.lengthInt > 0) {
11800            res.append(new BigInt(this.getUnsafe(this.lengthInt - 1)).toLocaleString())
11801        }
11802        return res.toString()
11803    }
11804
11805    /**
11806     * Creates a reversed copy
11807     *
11808     * @returns a reversed copy
11809     */
11810    public toReversed(): BigUint64Array {
11811        return new BigUint64Array(this).reverse()
11812    }
11813
11814    /**
11815     * Creates a sorted copy
11816     *
11817     * @returns a sorted copy
11818     */
11819    public toSorted(): BigUint64Array {
11820        return new BigUint64Array(this).sort()
11821    }
11822
11823    /**
11824     * Returns a string representation of the BigUint64Array
11825     *
11826     * @returns a string representation of the BigUint64Array
11827     */
11828    public override toString(): string {
11829        return this.join(",")
11830    }
11831
11832    /**
11833     * Returns array values iterator
11834     *
11835     * @returns an iterator
11836     */
11837    public values(): IterableIterator<BigInt> {
11838         return new BigUint64ArrayIterator(this)
11839    }
11840
11841    /**
11842     * Creates a copy with replaced value on index
11843     *
11844     * @param index
11845     *
11846     * @param value
11847     *
11848     * @returns an BigUint64Array with replaced value on index
11849     */
11850    public with(index: number, value: BigInt): BigUint64Array {
11851        return this.with(index as int, value.getULong())
11852    }
11853
11854    /**
11855     * Creates a copy with replaced value on index
11856     *
11857     * @param index
11858     *
11859     * @param value
11860     *
11861     * @returns an BigUint64Array with replaced value on index
11862     */
11863    private with(index: int, value: long): BigUint64Array {
11864        let res = new BigUint64Array(this)
11865        res.setUnsafeClamp(index, value)
11866        return res
11867    }
11868
11869    /// === with element lambda functions ===
11870
11871    /**
11872     * Determines whether the specified callback function returns true for all elements of an array.
11873     *
11874     * @param predicate A function that accepts one argument.
11875     * The every method calls the predicate function for each element in the array until the predicate returns a false,
11876     * or until the end of the array.
11877     *
11878     * @returns true unless predicate function returns a false for an array element,
11879     * in which case false is immediately returned.
11880     */
11881    public every(predicate: (element: BigInt) => boolean): boolean {
11882        return this.every((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element))
11883    }
11884
11885    /**
11886     * creates a new BigUint64Array from current BigUint64Array based on a condition fn
11887     *
11888     * @param fn the condition to apply for each element
11889     *
11890     * @returns a new BigUint64Array with elements from current BigUint64Array that satisfy condition fn
11891     */
11892    public filter(fn: (val: BigInt) => boolean): BigUint64Array {
11893        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
11894            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val) }
11895        return this.filter(newF)
11896    }
11897
11898    /**
11899     * Returns the value of the first element in the array where predicate is true, and undefined
11900     * otherwise
11901     *
11902     * @param predicate find calls predicate once for each element of the array, in ascending
11903     * order, until it finds one where predicate returns true. If such an element is found, find
11904     * immediately returns that element value. Otherwise, find returns undefined
11905     *
11906     * @returns BigInt | undefined
11907     */
11908    public find(predicate: () => boolean): BigInt | undefined {
11909        return this.find((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate())
11910    }
11911
11912    /**
11913     * Returns the value of the first element in the array where predicate is true, and undefined
11914     * otherwise
11915     *
11916     * @param predicate find calls predicate once for each element of the array, in ascending
11917     * order, until it finds one where predicate returns true. If such an element is found, find
11918     * immediately returns that element value. Otherwise, find returns undefined
11919     *
11920     * @returns BigInt | undefined
11921     */
11922    public find(predicate: (value: BigInt) => boolean): BigInt | undefined {
11923        return this.find((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value))
11924    }
11925
11926    /**
11927     * Returns the index of the first element in the array where predicate is true, and -1
11928     * otherwise
11929     *
11930     * @param predicate find calls predicate once for each element of the array, in ascending
11931     * order, until it finds one where predicate returns true. If such an element is found,
11932     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
11933     *
11934     * @returns number
11935     */
11936    public findIndex(predicate: (value: BigInt) => boolean): number {
11937        return this.findIndex((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value)) as number
11938    }
11939
11940    /**
11941     * Finds the last element in the BigUint64Array that satisfies the condition
11942     *
11943     * @param fn condition
11944     *
11945     * @returns the last element that satisfies fn
11946     */
11947    public findLast(fn: (val: BigInt) => boolean): BigInt {
11948        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
11949            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val) }
11950        return this.findLast(newF)
11951    }
11952
11953    /**
11954     * Finds an index of the last element in the BigUint64Array that satisfies the condition
11955     *
11956     * @param fn condition
11957     *
11958     * @returns the index of the last element that satisfies fn, -1 otherwise
11959     */
11960    public findLastIndex(fn: (val: BigInt) => boolean): number {
11961        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
11962            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val) }
11963        return this.findLastIndex(newF) as number
11964    }
11965
11966    /**
11967     * Performs the specified action for each element in BigUint64Array
11968     *
11969     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
11970     * callbackfn function one time for each element in the array.
11971     *
11972     * @returns None
11973     */
11974    public forEach(callbackfn: (val: BigInt) => void): void {
11975        this.forEach((value: BigInt, index: number, array: BigUint64Array): void => callbackfn(value))
11976    }
11977
11978    /**
11979     * Creates a new BigUint64Array using fn(arr[i]) over all elements of current BigUint64Array
11980     *
11981     * @param fn a function to apply for each element of current BigUint64Array
11982     *
11983     * @returns a new BigUint64Array where for each element from current BigUint64Array fn was applied
11984     */
11985    public map(fn: (val: BigInt) => BigInt): BigUint64Array {
11986        let newF: (val: BigInt, index: number) => BigInt =
11987            (val: BigInt, index: number): BigInt => { return fn(val) }
11988        return this.map(newF)
11989    }
11990
11991    /**
11992     * Determines whether the specified callback function returns true for any element of an array.
11993     *
11994     * @param predicate A function that accepts one argument.
11995     * The some method calls the predicate function for each element in the array
11996     * until the predicate returns a true or until the end of the array.
11997     *
11998     * @returns false unless predicate function returns true for an array element,
11999     * in which case true is immediately returned.
12000     */
12001    public some(predicate: (element: BigInt) => boolean): boolean {
12002        return this.some((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element))
12003    }
12004
12005    /**
12006     * Determines whether the specified callback function returns true for any element of an array.
12007     *
12008     * @param predicate A function that accepts three arguments.
12009     * The some method calls the predicate function for each element in the array
12010     * until the predicate returns a true or until the end of the array.
12011     *
12012     * @returns false unless predicate function returns true for an array element,
12013     * in which case true is immediately returned.
12014     */
12015    public some(predicate: (element: BigInt, index: number, array: BigUint64Array) => boolean): boolean {
12016        for (let i = 0; i < this.lengthInt; i++) {
12017            if (predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
12018                return true
12019            }
12020        }
12021        return false
12022    }
12023
12024    /**
12025     * Determines whether the specified callback function returns true for any element of an array.
12026     *
12027     * @param predicate A function that accepts two arguments.
12028     * The some method calls the predicate function for each element in the array
12029     * until the predicate returns a true or until the end of the array.
12030     *
12031     * @returns false unless predicate function returns true for an array element,
12032     * in which case true is immediately returned.
12033     */
12034    public some(predicate: (element: BigInt, index: number) => boolean): boolean {
12035        return this.some((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element, index))
12036    }
12037
12038    /**
12039     * Determines whether the specified callback function returns true for any element of an array.
12040     *
12041     * @param predicate A function that accepts no arguments.
12042     * The some method calls the predicate function for each element in the array
12043     * until the predicate returns a true or until the end of the array.
12044     *
12045     * @returns false unless predicate function returns true for an array element,
12046     * in which case true is immediately returned.
12047     */
12048    public some(predicate: () => boolean): boolean {
12049        return this.some((element: BigInt, index: number, array: BigUint64Array): boolean => predicate())
12050    }
12051
12052    /**
12053     * Calls the specified callback function for all the elements in an array.
12054     * The return value of the callback function is the accumulated result,
12055     * and is provided as an argument in the next call to the callback function.
12056     *
12057     * @param callbackfn A function that accepts four arguments.
12058     * The reduce method calls the callbackfn function one time for each element in the array.
12059     *
12060     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12061     * The first call to the callbackfn function provides this value as an argument.
12062     *
12063     * @returns The value that results from running the callback function to completion over the entire typed array.
12064     */
12065    public reduce<U = BigInt>(
12066                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => U,
12067                initialValue: U): U {
12068        let accumulatedValue = initialValue
12069        for (let i = 0; i < this.lengthInt; i++) {
12070            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12071        }
12072        return accumulatedValue
12073    }
12074
12075    /**
12076     * Calls the specified callback function for all the elements in an array.
12077     * The return value of the callback function is the accumulated result,
12078     * and is provided as an argument in the next call to the callback function.
12079     *
12080     * @param callbackfn A function that accepts three arguments.
12081     * The reduce method calls the callbackfn function one time for each element in the array.
12082     *
12083     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12084     * The first call to the callbackfn function provides this value as an argument.
12085     *
12086     * @returns The value that results from running the callback function to completion over the entire typed array.
12087     */
12088    public reduce<U = BigInt>(
12089                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number) => U,
12090                initialValue: U): U {
12091        return this.reduce(
12092                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12093                        callbackfn(prevVal, currVal, currIndex),
12094                initialValue)
12095    }
12096
12097    /**
12098     * Calls the specified callback function for all the elements in an array.
12099     * The return value of the callback function is the accumulated result,
12100     * and is provided as an argument in the next call to the callback function.
12101     *
12102     * @param callbackfn A function that accepts two arguments.
12103     * The reduce method calls the callbackfn function one time for each element in the array.
12104     *
12105     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12106     * The first call to the callbackfn function provides this value as an argument.
12107     *
12108     * @returns The value that results from running the callback function to completion over the entire typed array.
12109     */
12110    public reduce<U = BigInt>(
12111                callbackfn: (previousValue: U, currentValue: BigInt) => U,
12112                initialValue: U): U {
12113        return this.reduce(
12114                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12115                        callbackfn(prevVal, currVal),
12116                initialValue)
12117    }
12118
12119    /**
12120     * Calls the specified callback function for all the elements in an array.
12121     * The return value of the callback function is the accumulated result,
12122     * and is provided as an argument in the next call to the callback function.
12123     *
12124     * @param callbackfn A function that accepts one argument
12125     * The reduce method calls the callbackfn function one time for each element in the array.
12126     *
12127     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12128     * The first call to the callbackfn function provides this value as an argument.
12129     *
12130     * @returns The value that results from running the callback function to completion over the entire typed array.
12131     */
12132    public reduce<U = BigInt>(
12133                callbackfn: (previousValue: U) => U,
12134                initialValue: U): U {
12135        return this.reduce(
12136                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12137                        callbackfn(prevVal),
12138                initialValue)
12139    }
12140
12141    /**
12142     * Calls the specified callback function for all the elements in an array.
12143     * The return value of the callback function is the accumulated result,
12144     * and is provided as an argument in the next call to the callback function.
12145     *
12146     * @param callbackfn A function that accepts no arguments
12147     * The reduce method calls the callbackfn function one time for each element in the array.
12148     *
12149     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12150     * The first call to the callbackfn function provides this value as an argument.
12151     *
12152     * @returns The value that results from running the callback function to completion over the entire typed array.
12153     */
12154    public reduce<U = BigInt>(
12155                callbackfn: () => U,
12156                initialValue: U): U {
12157        return this.reduce(
12158                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12159                        callbackfn(),
12160                initialValue)
12161    }
12162
12163    /**
12164     * Calls the specified callback function for all the elements in an array.
12165     * The return value of the callback function is the accumulated result,
12166     * and is provided as an argument in the next call to the callback function.
12167     *
12168     * @param callbackfn A function that accepts four arguments.
12169     * The reduce method calls the callbackfn function one time for each element in the array.
12170     * The first call to the callbackfn function provides array first element value as an argument
12171     *
12172     * @returns The value that results from running the callback function to completion over the entire typed array.
12173     * calling reduce method on an empty array without an initial value creates a TypeError
12174     */
12175    public reduce(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => BigInt): BigInt {
12176        if (this.lengthInt == 0) {
12177            throw new TypeError("Reduce of empty array with no initial value")
12178        }
12179
12180        let accumulatedValue = new BigInt(this.$_get(0))
12181        for (let i = 1; i < this.lengthInt; i++) {
12182            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12183        }
12184        return accumulatedValue
12185    }
12186
12187    /**
12188     * Calls the specified callback function for all the elements in an array.
12189     * The return value of the callback function is the accumulated result,
12190     * and is provided as an argument in the next call to the callback function.
12191     *
12192     * @param callbackfn A function that accepts three arguments.
12193     * The reduce method calls the callbackfn function one time for each element in the array.
12194     * The first call to the callbackfn function provides array first element value as an argument
12195     *
12196     * @returns The value that results from running the callback function to completion over the entire typed array.
12197     * calling reduce method on an empty array without an initial value creates a TypeError
12198     */
12199    public reduce(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number) => BigInt): BigInt {
12200        return this.reduce(
12201                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12202                        callbackfn(prevVal, currVal, currIndex))
12203    }
12204
12205    /**
12206     * Calls the specified callback function for all the elements in an array.
12207     * The return value of the callback function is the accumulated result,
12208     * and is provided as an argument in the next call to the callback function.
12209     *
12210     * @param callbackfn A function that accepts two arguments.
12211     * The reduce method calls the callbackfn function one time for each element in the array.
12212     * The first call to the callbackfn function provides array first element value as an argument
12213     *
12214     * @returns The value that results from running the callback function to completion over the entire typed array.
12215     * calling reduce method on an empty array without an initial value creates a TypeError
12216     */
12217    public reduce(callbackfn: (previousValue: BigInt, currentValue: BigInt) => BigInt): BigInt {
12218        return this.reduce(
12219                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12220                        callbackfn(prevVal, currVal))
12221    }
12222
12223    /**
12224     * Calls the specified callback function for all the elements in an array.
12225     * The return value of the callback function is the accumulated result,
12226     * and is provided as an argument in the next call to the callback function.
12227     *
12228     * @param callbackfn A function that accepts one argument.
12229     * The reduce method calls the callbackfn function one time for each element in the array.
12230     * The first call to the callbackfn function provides array first element value as an argument
12231     *
12232     * @returns The value that results from running the callback function to completion over the entire typed array.
12233     * calling reduce method on an empty array without an initial value creates a TypeError
12234     */
12235    public reduce(callbackfn: (previousValue: BigInt) => BigInt): BigInt {
12236        return this.reduce(
12237                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12238                        callbackfn(prevVal))
12239    }
12240
12241    /**
12242     * Calls the specified callback function for all the elements in an array.
12243     * The return value of the callback function is the accumulated result,
12244     * and is provided as an argument in the next call to the callback function.
12245     *
12246     * @param callbackfn A function that accepts no arguments.
12247     * The reduce method calls the callbackfn function one time for each element in the array.
12248     * The first call to the callbackfn function provides array first element value as an argument
12249     *
12250     * @returns The value that results from running the callback function to completion over the entire typed array.
12251     * calling reduce method on an empty array without an initial value creates a TypeError
12252     */
12253    public reduce(callbackfn: () => BigInt): BigInt {
12254        return this.reduce(
12255                (prevVal: BigInt, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12256                        callbackfn())
12257    }
12258
12259    /**
12260     * Calls the specified callback function for all the elements in an array, in descending order.
12261     * The return value of the callback function is the accumulated result,
12262     * and is provided as an argument in the next call to the callback function.
12263     *
12264     * @param callbackfn A function that accepts four arguments.
12265     * The reduceRight method calls the callbackfn function one time for each element in the array.
12266     *
12267     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12268     * The first call to the callbackfn function provides this value as an argument.
12269     *
12270     * @returns The value that results from running the callback function to completion over the entire typed array.
12271     */
12272    public reduceRight<U = BigInt>(
12273                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => U,
12274                initialValue: U): U {
12275        let accumulatedValue = initialValue
12276        for (let i = this.lengthInt - 1; i >= 0; i--) {
12277            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12278        }
12279        return accumulatedValue
12280    }
12281
12282    /**
12283     * Calls the specified callback function for all the elements in an array, in descending order.
12284     * The return value of the callback function is the accumulated result,
12285     * and is provided as an argument in the next call to the callback function.
12286     *
12287     * @param callbackfn A function that accepts three arguments.
12288     * The reduceRight method calls the callbackfn function one time for each element in the array.
12289     *
12290     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12291     * The first call to the callbackfn function provides this value as an argument.
12292     *
12293     * @returns The value that results from running the callback function to completion over the entire typed array.
12294     */
12295    public reduceRight<U = BigInt>(
12296                callbackfn: (previuosValue: U, currentValue: BigInt, currentIndex: number) => U,
12297                initialValue: U): U {
12298        return this.reduceRight(
12299                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12300                        callbackfn(prevVal, currVal, currIndex),
12301                initialValue)
12302    }
12303
12304    /**
12305     * Calls the specified callback function for all the elements in an array, in descending order.
12306     * The return value of the callback function is the accumulated result,
12307     * and is provided as an argument in the next call to the callback function.
12308     *
12309     * @param callbackfn A function that accepts two arguments.
12310     * The reduceRight method calls the callbackfn function one time for each element in the array.
12311     *
12312     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12313     * The first call to the callbackfn function provides this value as an argument.
12314     *
12315     * @returns The value that results from running the callback function to completion over the entire typed array.
12316     */
12317    public reduceRight<U = BigInt>(
12318                callbackfn: (previuosValue: U, currentValue: BigInt) => U,
12319                initialValue: U): U {
12320        return this.reduceRight(
12321                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12322                        callbackfn(prevVal, currVal),
12323                initialValue)
12324    }
12325
12326    /**
12327     * Calls the specified callback function for all the elements in an array, in descending order.
12328     * The return value of the callback function is the accumulated result,
12329     * and is provided as an argument in the next call to the callback function.
12330     *
12331     * @param callbackfn A function that accepts one argument.
12332     * The reduceRight method calls the callbackfn function one time for each element in the array.
12333     *
12334     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12335     * The first call to the callbackfn function provides this value as an argument.
12336     *
12337     * @returns The value that results from running the callback function to completion over the entire typed array.
12338     */
12339    public reduceRight<U = BigInt>(
12340                callbackfn: (previuosValue: U) => U,
12341                initialValue: U): U {
12342        return this.reduceRight(
12343                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12344                        callbackfn(prevVal),
12345                initialValue)
12346    }
12347
12348    /**
12349     * Calls the specified callback function for all the elements in an array, in descending order.
12350     * The return value of the callback function is the accumulated result,
12351     * and is provided as an argument in the next call to the callback function.
12352     *
12353     * @param callbackfn A function that accepts no arguments.
12354     * The reduceRight method calls the callbackfn function one time for each element in the array.
12355     *
12356     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
12357     * The first call to the callbackfn function provides this value as an argument.
12358     *
12359     * @returns The value that results from running the callback function to completion over the entire typed array.
12360     */
12361    public reduceRight<U = BigInt>(
12362                callbackfn: () => U,
12363                initialValue: U): U {
12364        return this.reduceRight(
12365                (prevVal: U, currVal: BigInt, currIndex: number, array: BigUint64Array) =>
12366                        callbackfn(),
12367                initialValue)
12368    }
12369
12370    /**
12371     * Calls the specified callback function for all the elements in an array, in descending order.
12372     * The return value of the callback function is the accumulated result,
12373     * and is provided as an argument in the next call to the callback function.
12374     *
12375     * @param callbackfn A function that accepts four arguments.
12376     * The reduceRight method calls the callbackfn function one time for each element in the array.
12377     * The first call to the callbackfn function provides array last element value as an argument
12378     *
12379     * @returns The value that results from running the callback function to completion over the entire typed array.
12380     * calling reduceRight method on an empty array without an initial value creates a TypeError
12381     */
12382    public reduceRight(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => BigInt): BigInt {
12383        if (this.lengthInt == 0) {
12384            throw new TypeError("Reduce of empty array with no initial value")
12385        }
12386
12387        let accumulatedValue: BigInt = new BigInt(this.$_get(this.lengthInt - 1))
12388        for (let i = this.lengthInt - 2; i >= 0; i--) {
12389            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
12390        }
12391        return accumulatedValue
12392    }
12393
12394    /**
12395     * Calls the specified callback function for all the elements in an array, in descending order.
12396     * The return value of the callback function is the accumulated result,
12397     * and is provided as an argument in the next call to the callback function.
12398     *
12399     * @param callbackfn A function that accepts three arguments.
12400     * The reduceRight method calls the callbackfn function one time for each element in the array.
12401     * The first call to the callbackfn function provides array last element value as an argument
12402     *
12403     * @returns The value that results from running the callback function to completion over the entire typed array.
12404     * calling reduceRight method on an empty array without an initial value creates a TypeError
12405     */
12406    public reduceRight(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number) => BigInt): BigInt {
12407        return this.reduceRight(
12408                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12409                        callbackfn(prevValue, currValue, currIndex))
12410    }
12411
12412    /**
12413     * Calls the specified callback function for all the elements in an array, in descending order.
12414     * The return value of the callback function is the accumulated result,
12415     * and is provided as an argument in the next call to the callback function.
12416     *
12417     * @param callbackfn A function that accepts two arguments.
12418     * The reduceRight method calls the callbackfn function one time for each element in the array.
12419     * The first call to the callbackfn function provides array last element value as an argument
12420     *
12421     * @returns The value that results from running the callback function to completion over the entire typed array.
12422     * calling reduceRight method on an empty array without an initial value creates a TypeError
12423     */
12424    public reduceRight(callbackfn: (previousValue: BigInt, currentValue: BigInt) => BigInt): BigInt {
12425        return this.reduceRight(
12426                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12427                        callbackfn(prevValue, currValue))
12428    }
12429
12430    /**
12431     * Calls the specified callback function for all the elements in an array, in descending order.
12432     * The return value of the callback function is the accumulated result,
12433     * and is provided as an argument in the next call to the callback function.
12434     *
12435     * @param callbackfn A function that accepts one argument.
12436     * The reduceRight method calls the callbackfn function one time for each element in the array.
12437     * The first call to the callbackfn function provides array last element value as an argument
12438     *
12439     * @returns The value that results from running the callback function to completion over the entire typed array.
12440     * calling reduceRight method on an empty array without an initial value creates a TypeError
12441     */
12442    public reduceRight(callbackfn: (previousValue: BigInt) => BigInt): BigInt {
12443        return this.reduceRight(
12444                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12445                        callbackfn(prevValue))
12446    }
12447
12448    /**
12449     * Calls the specified callback function for all the elements in an array, in descending order.
12450     * The return value of the callback function is the accumulated result,
12451     * and is provided as an argument in the next call to the callback function.
12452     *
12453     * @param callbackfn A function that accepts no arguments.
12454     * The reduceRight method calls the callbackfn function one time for each element in the array.
12455     * The first call to the callbackfn function provides array last element value as an argument
12456     *
12457     * @returns The value that results from running the callback function to completion over the entire typed array.
12458     * calling reduceRight method on an empty array without an initial value creates a TypeError
12459     */
12460    public reduceRight(callbackfn: () => BigInt): BigInt {
12461        return this.reduceRight(
12462                (prevValue: BigInt, currValue: BigInt, currIndex: number, array: BigUint64Array) =>
12463                        callbackfn())
12464    }
12465
12466    /**
12467     * Creates a new BigUint64Array using fn(arr[i]) over all elements of current BigUint64Array.
12468     *
12469     * @param fn a function to apply for each element of current BigUint64Array
12470     *
12471     * @returns a new BigUint64Array where for each element from current BigUint64Array fn was applied
12472     */
12473    public map(fn: (val: BigInt, index: number) => BigInt): BigUint64Array {
12474        let resBuf = new ArrayBuffer(this.lengthInt * BigUint64Array.BYTES_PER_ELEMENT as int)
12475        let res = new BigUint64Array(resBuf)
12476        for (let i = 0; i < this.lengthInt; i++) {
12477            const fnRes = fn(new BigInt(this.getUnsafe(i)), i as number)
12478            res.setUnsafeClamp(i, fnRes.getULong())
12479        }
12480        return res
12481    }
12482
12483    /**
12484     * Determines whether the specified callback function returns true for all elements of an array.
12485     *
12486     * @param predicate A function that accepts three arguments.
12487     * The every method calls the predicate function for each element in the array until the predicate returns a false,
12488     * or until the end of the array.
12489     *
12490     * @returns true unless predicate function returns a false for an array element,
12491     * in which case false is immediately returned.
12492     */
12493    public every(predicate: (element: BigInt, index: number, array: BigUint64Array) => boolean): boolean {
12494        for (let i = 0; i < this.lengthInt; i++) {
12495            if (!predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
12496                return false
12497            }
12498        }
12499        return true
12500    }
12501
12502    /**
12503     * Determines whether the specified callback function returns true for all elements of an array.
12504     *
12505     * @param predicate A function that accepts two arguments.
12506     * The every method calls the predicate function for each element in the array until the predicate returns a false,
12507     * or until the end of the array.
12508     *
12509     * @returns true unless predicate function returns a false for an array element,
12510     * in which case false is immediately returned.
12511     */
12512    public every(predicate: (element: BigInt, index: number) => boolean): boolean {
12513        return this.every((element: BigInt, index: number, array: BigUint64Array): boolean => predicate(element, index))
12514    }
12515
12516    /**
12517     * Determines whether the specified callback function returns true for all elements of an array.
12518     *
12519     * @param predicate A function that accepts no arguments.
12520     * The every method calls the predicate function for each element in the array until the predicate returns a false,
12521     * or until the end of the array.
12522     *
12523     * @returns true unless predicate function returns a false for an array element,
12524     * in which case false is immediately returned.
12525     */
12526    public every(predicate: () => boolean): boolean {
12527        return this.every((element: BigInt, index: number, array: BigUint64Array): boolean => predicate())
12528    }
12529
12530    /**
12531     * Creates a new BigUint64Array from current BigUint64Array based on a condition fn.
12532     *
12533     * @param fn the condition to apply for each element
12534     *
12535     * @returns a new BigUint64Array with elements from current BigUint64Array that satisfy condition fn
12536     */
12537    public filter(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): BigUint64Array {
12538        let markers = new boolean[this.lengthInt]
12539        let resLen = 0
12540        for (let i = 0; i < this.lengthInt; i++) {
12541            markers[i] = fn(new BigInt(this.getUnsafe(i)), i as number, this)
12542            if (markers[i]) {
12543                ++resLen
12544            }
12545        }
12546        let res = new BigUint64Array(resLen)
12547        for (let i = 0, j = 0; i < this.lengthInt; i++) {
12548            if (markers[i]) {
12549                res.setUnsafe(j, this.getUnsafe(i))
12550                ++j
12551            }
12552        }
12553        return res
12554    }
12555
12556    /**
12557     * creates a new BigUint64Array from current BigUint64Array based on a condition fn
12558     *
12559     * @param fn the condition to apply for each element
12560     *
12561     * @returns a new BigUint64Array with elements from current BigUint64Array that satisfy condition fn
12562     */
12563    public filter(fn: (val: BigInt, index: number) => boolean): BigUint64Array {
12564        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
12565            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val, index) }
12566        return this.filter(newF)
12567    }
12568
12569    /**
12570     * Returns the value of the first element in the array where predicate is true, and undefined
12571     * otherwise
12572     *
12573     * @param predicate find calls predicate once for each element of the array, in ascending
12574     * order, until it finds one where predicate returns true. If such an element is found, find
12575     * immediately returns that element value. Otherwise, find returns undefined
12576     *
12577     * @returns BigInt | undefined
12578     */
12579    public find(predicate: (value: BigInt, index: number, array: BigUint64Array) => boolean): BigInt | undefined {
12580        for (let i = 0; i < this.lengthInt; i++) {
12581            let val = new BigInt(this.getUnsafe(i))
12582            if (predicate(val, i as number, this)) {
12583                return val
12584            }
12585        }
12586        return undefined
12587    }
12588
12589    /**
12590     * Returns the value of the first element in the array where predicate is true, and undefined
12591     * otherwise
12592     *
12593     * @param predicate find calls predicate once for each element of the array, in ascending
12594     * order, until it finds one where predicate returns true. If such an element is found, find
12595     * immediately returns that element value. Otherwise, find returns undefined
12596     *
12597     * @returns BigInt | undefined
12598     */
12599    public find(predicate: (value: BigInt, index: number) => boolean): BigInt | undefined {
12600        return this.find((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value, index))
12601    }
12602
12603    /**
12604     * Returns the index of the first element in the array where predicate is true, and -1
12605     * otherwise
12606     *
12607     * @param predicate find calls predicate once for each element of the array, in ascending
12608     * order, until it finds one where predicate returns true. If such an element is found,
12609     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
12610     *
12611     * @returns number
12612     */
12613    public findIndex(predicate: (value: BigInt, index: number, obj: BigUint64Array) => boolean): number {
12614        for (let i = 0; i < this.lengthInt; i++) {
12615            if (predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
12616                return i as number
12617            }
12618        }
12619        return -1 as number
12620    }
12621
12622    /**
12623     * Returns the index of the first element in the array where predicate is true, and -1
12624     * otherwise
12625     *
12626     * @param predicate find calls predicate once for each element of the array, in ascending
12627     * order, until it finds one where predicate returns true. If such an element is found,
12628     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
12629     *
12630     * @returns number
12631     */
12632    public findIndex(predicate: (value: BigInt, index: number) => boolean): number {
12633        return this.findIndex((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate(value, index))
12634    }
12635
12636    /**
12637     * Returns the index of the first element in the array where predicate is true, and -1
12638     * otherwise
12639     *
12640     * @param predicate find calls predicate once for each element of the array, in ascending
12641     * order, until it finds one where predicate returns true. If such an element is found,
12642     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
12643     *
12644     * @returns number
12645     */
12646    public findIndex(predicate: () => boolean): number {
12647        return this.findIndex((value: BigInt, index: number, obj: BigUint64Array): boolean => predicate())
12648    }
12649
12650    /**
12651     * Finds the last element in the BigUint64Array that satisfies the condition
12652     *
12653     * @param fn condition
12654     *
12655     * @returns the last element that satisfies fn
12656     */
12657    public findLast(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): BigInt {
12658        for (let i = this.lengthInt - 1; i >= 0; i--) {
12659            let val = new BigInt(this.getUnsafe(i))
12660            if (fn(val, i as number, this)) {
12661                return val
12662            }
12663        }
12664        throw new Error("BigUint64Array.findLast: not implemented if an element was not found")
12665    }
12666
12667    /**
12668     * Finds the last element in the BigUint64Array that satisfies the condition
12669     *
12670     * @param fn condition
12671     *
12672     * @returns the last element that satisfies fn
12673     */
12674    public findLast(fn: (val: BigInt, index: number) => boolean): BigInt {
12675        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
12676            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val, index) }
12677        return this.findLast(newF)
12678    }
12679
12680    /**
12681     * Finds an index of the last element in the BigUint64Array that satisfies the condition
12682     *
12683     * @param fn condition
12684     *
12685     * @returns the index of the last element that satisfies fn, -1 otherwise
12686     */
12687    public findLastIndex(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): number {
12688        for (let i = this.lengthInt - 1; i >= 0; i--) {
12689            if (fn(new BigInt(this.getUnsafe(i)), i as number, this)) {
12690                return i as number
12691            }
12692        }
12693        return -1 as number
12694    }
12695
12696    /**
12697     * Finds an index of the last element in the BigUint64Array that satisfies the condition
12698     *
12699     * @param fn condition
12700     *
12701     * @returns the index of the last element that satisfies fn, -1 otherwise
12702     */
12703    public findLastIndex(fn: (val: BigInt, index: number) => boolean): number {
12704        let newF: (val: BigInt, index: number, array: BigUint64Array) => boolean =
12705            (val: BigInt, index: number, array: BigUint64Array): boolean => { return fn(val, index) }
12706        return this.findLastIndex(newF) as number
12707    }
12708
12709    /**
12710     * Performs the specified action for each element in BigUint64Array
12711     *
12712     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
12713     * callbackfn function one time for each element in the array.
12714     *
12715     * @returns None
12716     */
12717    public forEach(callbackfn: (value: BigInt, index: number, array: BigUint64Array) => void): void {
12718        for (let i = 0; i < this.lengthInt; i++) {
12719            callbackfn(new BigInt(this.getUnsafe(i)), i as number, this)
12720        }
12721    }
12722
12723    /**
12724     * Performs the specified action for each element in BigUint64Array
12725     *
12726     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
12727     * callbackfn function one time for each element in the array.
12728     *
12729     * @returns None
12730     */
12731    public forEach(callbackfn: (value: BigInt, index: number) => void): void {
12732        this.forEach((value: BigInt, index: number, array: BigUint64Array): void => callbackfn(value, index))
12733    }
12734
12735    /**
12736     * Performs the specified action for each element in BigUint64Array
12737     *
12738     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
12739     * callbackfn function one time for each element in the array.
12740     *
12741     * @returns None
12742     */
12743    public forEach(callbackfn: () => void): void {
12744        this.forEach((value: BigInt, index: number, array: BigUint64Array): void => callbackfn())
12745    }
12746
12747    /**
12748     * Returns the object itself
12749     *
12750     * @returns BigUint64Array
12751     */
12752    public valueOf(): BigUint64Array {
12753        return this
12754    }
12755
12756    /** Byte offset within the underlying Buffer */
12757    public get byteOffset(): number {
12758        return this.byteOffsetInt
12759    }
12760
12761    /** Number of bytes used */
12762    public get byteLength(): number {
12763        return this.byteLengthInt
12764    }
12765
12766    /** Number of long stored in BigUint64Array */
12767    public get length(): number {
12768        return this.lengthInt
12769    }
12770
12771    /** String \"BigUint64Array\" */
12772    public readonly name = "BigUint64Array"
12773
12774    private static clamp(val: long): long {
12775        return val
12776    }
12777
12778    internal setUnsafeClamp(insertPos: int, val: long): void {
12779        this.setUnsafe(insertPos, val)
12780    }
12781
12782    internal getUnsafe(index: int): long {
12783        index = index * BigUint64Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
12784        let res: long = 0
12785        if (IS_LITTLE_ENDIAN) {
12786            if (this.buffer instanceof ArrayBuffer) {
12787                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12788                    let el = (this.buffer as ArrayBuffer).at(index + i) as long
12789                    el &= 0xff
12790                    res |= el << (8 * i)
12791                }
12792            } else if (this.buffer instanceof SharedArrayBuffer) {
12793                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12794                    let el = (this.buffer as SharedArrayBuffer).at(index + i) as long
12795                    el &= 0xff
12796                    res |= el << (8 * i)
12797                }
12798            } else {
12799                throw new Error("unexpected type of ArrayBufferLike")
12800            }
12801        } else {
12802            if (this.buffer instanceof ArrayBuffer) {
12803                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12804                    let el = (this.buffer as ArrayBuffer).at(index + 7 - i) as long
12805                    el &= 0xff
12806                    res |= el << (8 * i)
12807                }
12808            } else if (this.buffer instanceof SharedArrayBuffer) {
12809                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12810                    let el = (this.buffer as SharedArrayBuffer).at(index + 7 - i) as long
12811                    el &= 0xff
12812                    res |= el << (8 * i)
12813                }
12814            } else {
12815                throw new Error("unexpected type of ArrayBufferLike")
12816            }
12817        }
12818        return res
12819    }
12820
12821    internal setUnsafe(index: int, val: long): void {
12822        index = index * BigUint64Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
12823        let res: long = 0
12824        if (IS_LITTLE_ENDIAN) {
12825            if (this.buffer instanceof ArrayBuffer) {
12826                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12827                    (this.buffer as ArrayBuffer).set(index + i, (val & 0xff) as byte)
12828                    val = val >> 8
12829                }
12830            } else if (this.buffer instanceof SharedArrayBuffer) {
12831                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12832                    (this.buffer as SharedArrayBuffer).set(index + i, (val & 0xff) as byte)
12833                    val = val >> 8
12834                }
12835            } else {
12836                throw new Error("unexpected type of ArrayBufferLike")
12837            }
12838        } else {
12839            if (this.buffer instanceof ArrayBuffer) {
12840                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12841                    (this.buffer as ArrayBuffer).set(index + 7 - i, (val & 0xff) as byte)
12842                    val = val >> 8
12843                }
12844            } else if (this.buffer instanceof SharedArrayBuffer) {
12845                for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
12846                    (this.buffer as SharedArrayBuffer).set(index + 7 - i, (val & 0xff) as byte)
12847                    val = val >> 8
12848                }
12849            } else {
12850                throw new Error("unexpected type of ArrayBufferLike")
12851            }
12852        }
12853    }
12854}
12855