• 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
16package std.core;
17
18// NOTE: autogenerated file
19
20function asIntOrDefault(n: Number | undefined, def: int): int {
21    if (__runtimeIsSameReference(n, undefined)) {
22        return def
23    }
24    return (n! as Object as Number) as number as int;
25}
26
27function normalizeIndex(idx: int, len: int): int {
28    if (idx < -len) {
29        return 0
30    }
31    if (idx < 0) {
32        return len + idx
33    }
34    if (idx > len) {
35        return len
36    }
37    return idx
38}
39
40// Range is [startIndex, endIndex), i.e. startIndex included and endIndex is excluded
41function checkRange(arrLen: int, startIndex: int, endIndex: int): boolean {
42    // Since mostly everywhere for loop is used from startIndex till endIndex exclusive,
43    // startIndex <= endIndex is used to cover empty array case
44    return ((0 <= startIndex) && (startIndex <= endIndex) && (endIndex <= arrLen));
45}
46
47native function __alloc_array<T>(len: int, ofType: Object | null): T[]
48
49class BuiltinArrayKeysIterator implements IterableIterator<number> {
50    private len: int
51    private idx: int = 0
52
53    constructor(len: int) {
54        this.len = len
55    }
56
57    override next(): IteratorResult<number> {
58        if (this.idx >= this.len) {
59            return new IteratorResult<number>()
60        }
61        return new IteratorResult<number>(this.idx++ as number)
62    }
63
64    override $_iterator(): IterableIterator<number> {
65        return this
66    }
67}
68
69function cloneArray(self: boolean[]): boolean[] {
70    const ret = new boolean[self.length];;
71    for (let i = 0; i < self.length; i++) {
72        ret[i] = self[i];
73    }
74    return ret;
75}
76
77/**
78 * Takes an integer value and returns the item at that index,
79 * allowing for positive and negative integers. Negative integers count back
80 * from the last item in the array.
81 *
82 * @param index Zero-based index of the array element to be returned.
83 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
84 *
85 * @returns The element in the array matching the given index.
86 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
87 */
88export function at(self: boolean[], index: number): Boolean | undefined {
89    return at(self, index as int)
90}
91
92/**
93 * Creates a new `Array` from this `Array` instance and given `Array` instance.
94 *
95 * @param other to concatenate into a new array.
96 *
97 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
98 */
99// export function concat(self: boolean[], ...items: (boolean | Concatboolean[])[]): boolean[] {
100//     throw new Error("not implemented")
101// }
102
103export function concat(self: boolean[], ...items: ConcatArray<boolean>[]): boolean[] {
104    let totalAdd = self.length;
105    for (let i = 0; i < items.length; i++) {
106        totalAdd += items[i].length as int
107    }
108
109    const buf = new boolean[totalAdd];
110
111    for (let i = 0; i < self.length; i++) {
112        buf[i] = self[i];
113    }
114
115    let insertTo = self.length;
116    for (let i = 0; i < items.length; i++) {
117        const arr = items[i]
118        const len = arr.length as int
119        for (let j = 0; j < len; j++) {
120            buf[insertTo++] = arr.$_get(j)
121        }
122    }
123
124    return buf;
125}
126
127/**
128 * Takes an integer value and returns the item at that index,
129 * allowing for positive and negative integers. Negative integers count back
130 * from the last item in the array.
131 *
132 * @param index Zero-based index of the array element to be returned.
133 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
134 *
135 * @returns The element in the array matching the given index.
136 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
137 */
138export function at(self: boolean[], index: int): Boolean | undefined {
139    let len = self.length;
140    let k: int;
141    if (index >= 0) {
142        k = index;
143    } else {
144        k = len + index;
145    }
146
147    if (k < 0 || k >= len) {
148        return undefined;
149    }
150
151    return self[k];
152}
153
154/**
155 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
156 *
157 * @param target index at which to copy the sequence
158 *
159 * @param start index at which to start copying elements from
160 *
161 * @param end index at which to end copying elements from
162 *
163 * @returns this array after transformation
164 */
165export function copyWithin(self: boolean[], target: number, start: number, end?: Number): boolean[] {
166    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
167    return self;
168}
169
170/**
171 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
172 *
173 * @param target index at which to copy the sequence
174 *
175 * @param start index at which to start copying elements from
176 *
177 * @param end index at which to end copying elements from
178 *
179 * @returns this array after transformation
180 */
181export function copyWithin(self: boolean[], target: int, start: int, end: int): boolean[] {
182    target = normalizeIndex(target, self.length)
183    start = normalizeIndex(start, self.length)
184    end = normalizeIndex(end, self.length)
185
186    if (end <= start) {
187        return self;
188    }
189
190    if (target <= start) {
191        while (start < end) {
192            const read = self[start++];
193            self[target++] = read;
194        }
195    } else {
196        let len = end - start;
197        if (target + len > self.length) {
198            len = self.length - target
199        }
200        for (let i = 0; i < len; i++) {
201            const read = self[start + len - 1 - i];
202            self[target + len - 1 - i] = read;
203        }
204    }
205
206    return self;
207}
208
209/**
210 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
211 *
212 * @param target index at which to copy the sequence
213 *
214 * @param start index at which to start copying elements from
215 *
216 * @returns this array after transformation
217 */
218export function copyWithin(self: boolean[], target: int, start: int): boolean[] {
219    copyWithin(self, target, start, self.length);
220    return self;
221}
222
223/**
224 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
225 *
226 * @param target index at which to copy the sequence
227 *
228 * @returns this array after transformation
229 */
230export function copyWithin(self: boolean[], target: int): boolean[] {
231    copyWithin(self, target, 0, self.length);
232    return self;
233}
234
235/**
236 * Changes all elements in the Array to a static value, from a start index to an end index
237 *
238 * @param value to fill the array with
239 *
240 * @param start index at which to start filling
241 *
242 * @param end index at which to end filling, but not including
243 *
244 * @returns this array after transformation
245 */
246export function fill(self: boolean[], value: boolean, start?: Number, end?: Number): boolean[] {
247    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
248    return self;
249}
250
251/**
252 * Changes all elements in the Array to a static value, from a start index to an end index
253 *
254 * @param value to fill the array with
255 *
256 * @param start index at which to start filling
257 *
258 * @param end index at which to end filling, but not including
259 *
260 * @returns this array after transformation
261 */
262export function fill(self: boolean[], value: boolean, start: int, end: int): boolean[] {
263    start = normalizeIndex(start, self.length);
264    end = normalizeIndex(end, self.length)
265
266    for (let i = start; i < end; i++) {
267        self[i] = value;
268    }
269
270    return self;
271}
272
273/**
274 * Returns the value of the first element in the array where predicate is true, and undefined
275 * otherwise.
276 *
277 * @param predicate find calls predicate once for each element of the array, in ascending
278 * order, until it finds one where predicate returns true. If such an element is found, find
279 * immediately returns that element value. Otherwise, find returns undefined.
280 *
281 * @returns the value of the first element in the array or undefined
282 */
283export function find(self: boolean[], predicate: (value: boolean, index: number, array: boolean[]) => boolean): Boolean | undefined {
284    const res = findIndex(self, predicate)
285    if (res == -1) {
286        return undefined
287    }
288    return self[res as int];
289}
290
291/**
292 * Returns the index of the first element in the array where predicate is true, and -1
293 * otherwise.
294 *
295 * @param predicate find calls predicate once for each element of the array, in ascending
296 * order, until it finds one where predicate returns true. If such an element is found,
297 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
298 *
299 * @returns found element index or -1 otherwise
300 */
301export function findIndex(self: boolean[], predicate: (value: boolean, index: number, array: boolean[]) => boolean): number {
302    for (let i = 0; i < self.length; i++) {
303        if (predicate(self[i], i as number, self)) {
304            return i;
305        }
306    }
307    return -1;
308}
309
310/**
311 * Iterates the array in reverse order and returns the value of the first element
312 * that satisfies the provided testing function
313 *
314 * @param predicate testing function
315 *
316 * @returns found element or undefined otherwise
317 */
318export function findLast(self: boolean[], predicate: (elem: boolean, index: number, array: boolean[]) => boolean): Boolean | undefined {
319    for (let i = self.length - 1; i >= 0; i--) {
320        const val = self[i];
321        if (predicate(val, i as number, self)) {
322            return val;
323        }
324    }
325    return undefined;
326}
327
328/**
329 * Determines whether all the members of an array satisfy the specified test.
330 *
331 * @param predicate A function that accepts up to three arguments. The every method calls
332 * the predicate function for each element in the array until the predicate returns a value
333 * which is coercible to the Boolean value false, or until the end of the array.
334 *
335 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
336 */
337export function every(self: boolean[], predicate: (value: boolean, index: number, array: boolean[]) => boolean): boolean {
338    for (let i = 0; i < self.length; i++) {
339        if (!predicate(self[i], i as number, self)) {
340            return false
341        }
342    }
343    return true;
344}
345
346/**
347 * Determines whether the specified callback function returns true for any element of an array.
348 *
349 * @param predicate A function that accepts up to three arguments. The some method calls
350 * the predicate function for each element in the array until the predicate returns a value
351 * which is coercible to the Boolean value true, or until the end of the array.
352 *
353 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
354 */
355export function some(self: boolean[], predicate: (value: boolean, index: number, array: boolean[]) => boolean): boolean {
356    for (let i = 0; i < self.length; i++) {
357        if (predicate(self[i], i as number, self)) {
358            return true
359        }
360    }
361    return false
362}
363
364/**
365 * Returns the elements of an array that meet the condition specified in a callback function.
366 *
367 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
368 *
369 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
370 */
371export function filter(self: boolean[], predicate: (value: boolean, index: number, array: boolean[]) => boolean): boolean[] {
372    return filter(self, (value: boolean, index: number): boolean => predicate(value, index, self));
373}
374
375/**
376 * Iterates the array in reverse order and returns the index of
377 * the first element that satisfies the provided testing function.
378 * If no elements satisfy the testing function, -1 is returned.
379 *
380 * @param predicate testing function
381 *
382 * @returns index of first element satisfying to predicate, -1 if no such element
383 */
384export function findLastIndex(self: boolean[], predicate: (element: boolean, index: number, array: boolean[]) => boolean): number {
385    for (let i = self.length - 1; i >= 0; i--) {
386        if (predicate(self[i], i as number, self)) {
387            return i
388        }
389    }
390    return -1
391}
392
393/**
394 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
395 *
396 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
397 *
398 * @returns a result after applying callbackfn over all elements of the Array
399 */
400export function reduce(self: boolean[], callbackfn: (previousValue: boolean, currentValue: boolean, index: number, array: boolean[]) => boolean): boolean {
401    if (self.length == 0) {
402        throw new TypeError("Reduce of empty array with no initial value")
403    }
404    let acc: boolean = self[0];
405    for (let i = 1; i < self.length; i++) {
406        acc = callbackfn(acc, self[i], i as number, self)
407    }
408    return acc
409}
410
411/**
412 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
413 *
414 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
415 *
416 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
417 *
418 * @returns a result after applying callbackfn over all elements of the Array
419 */
420export function reduce<U = boolean>(self: boolean[], callbackfn: (previousValue: U, currentValue: boolean, index: number, array: boolean[]) => U, initialValue: U): U {
421    let acc = initialValue
422    for (let i = 0; i < self.length; i++) {
423        acc = callbackfn(acc, self[i], i as number, self)
424    }
425    return acc
426}
427
428/**
429 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
430 *
431 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
432 *
433 * @returns a result after applying callbackfn over all elements of the Array
434 */
435export function reduceRight(self: boolean[], callbackfn: (previousValue: boolean, currentValue: boolean, index: number, array: boolean[]) => boolean): boolean {
436    if (self.length == 0) {
437        throw new TypeError("Reduce of empty array with no initial value")
438    }
439    let acc: boolean = self[self.length - 1];
440    for (let i = self.length - 2; i >= 0; i--) {
441        acc = callbackfn(acc, self[i], i as number, self)
442    }
443    return acc
444}
445
446/**
447 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
448 *
449 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
450 *
451 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
452 *
453 * @returns a result after applying callbackfn over all elements of the Array
454 */
455export function reduceRight<U>(self: boolean[], callbackfn: (previousValue: U, currentValue: boolean, index: number, array: boolean[]) => U, initialValue: U): U {
456    let acc = initialValue
457    for (let i = self.length - 1; i >= 0; i--) {
458        acc = callbackfn(acc, self[i], i as number, self)
459    }
460    return acc
461}
462
463/**
464 * Performs the specified action for each element in an array.
465 *
466 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
467 */
468export function forEach(self: boolean[], callbackfn: (value: boolean, index: number, array: boolean[]) => void): void {
469    const len0 = self.length;
470    for (let i = 0; i < len0; i++) {
471        callbackfn(self[i], i as number, self)
472    }
473}
474
475/**
476 * Returns the value of the first element in the array where predicate is true, and undefined
477 * otherwise.
478 *
479 * @param predicate find calls predicate once for each element of the array, in ascending
480 * order, until it finds one where predicate returns true. If such an element is found, find
481 * immediately returns that element value. Otherwise, find returns undefined.
482 *
483 * @returns the value of the first element in the array or undefined
484 */
485export function find(self: boolean[], predicate: (value: boolean, index: number) => boolean): Boolean | undefined {
486    const res = findIndex(self, predicate)
487    if (res == -1) {
488        return undefined
489    }
490    return self[res as int];
491}
492
493/**
494 * Returns the index of the first element in the array where predicate is true, and -1
495 * otherwise.
496 *
497 * @param predicate find calls predicate once for each element of the array, in ascending
498 * order, until it finds one where predicate returns true. If such an element is found,
499 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
500 *
501 * @returns found element index or -1 otherwise
502 */
503export function findIndex(self: boolean[], predicate: (value: boolean, index: number) => boolean): number {
504    for (let i = 0; i < self.length; i++) {
505        if (predicate(self[i], i as number)) {
506            return i;
507        }
508    }
509    return -1;
510}
511
512/**
513 * Iterates the array in reverse order and returns the value of the first element
514 * that satisfies the provided testing function
515 *
516 * @param predicate testing function
517 *
518 * @returns found element or undefined otherwise
519 */
520export function findLast(self: boolean[], predicate: (elem: boolean, index: number) => boolean): Boolean | undefined {
521    for (let i = self.length - 1; i >= 0; i--) {
522        const val = self[i];
523        if (predicate(val, i as number)) {
524            return val;
525        }
526    }
527    return undefined;
528}
529
530/**
531 * Determines whether all the members of an array satisfy the specified test.
532 *
533 * @param predicate A function that accepts up to three arguments. The every method calls
534 * the predicate function for each element in the array until the predicate returns a value
535 * which is coercible to the Boolean value false, or until the end of the array.
536 *
537 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
538 */
539export function every(self: boolean[], predicate: (value: boolean, index: number) => boolean): boolean {
540    for (let i = 0; i < self.length; i++) {
541        if (!predicate(self[i], i as number)) {
542            return false
543        }
544    }
545    return true;
546}
547
548/**
549 * Determines whether the specified callback function returns true for any element of an array.
550 *
551 * @param predicate A function that accepts up to three arguments. The some method calls
552 * the predicate function for each element in the array until the predicate returns a value
553 * which is coercible to the Boolean value true, or until the end of the array.
554 *
555 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
556 */
557export function some(self: boolean[], predicate: (value: boolean, index: number) => boolean): boolean {
558    for (let i = 0; i < self.length; i++) {
559        if (predicate(self[i], i as number)) {
560            return true
561        }
562    }
563    return false
564}
565
566/**
567 * Iterates the array in reverse order and returns the index of
568 * the first element that satisfies the provided testing function.
569 * If no elements satisfy the testing function, -1 is returned.
570 *
571 * @param predicate testing function
572 *
573 * @returns index of first element satisfying to predicate, -1 if no such element
574 */
575export function findLastIndex(self: boolean[], predicate: (element: boolean, index: number) => boolean): number {
576    for (let i = self.length - 1; i >= 0; i--) {
577        if (predicate(self[i], i as number)) {
578            return i
579        }
580    }
581    return -1
582}
583
584/**
585 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
586 *
587 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
588 *
589 * @returns a result after applying callbackfn over all elements of the Array
590 */
591export function reduce(self: boolean[], callbackfn: (previousValue: boolean, currentValue: boolean, index: number) => boolean): boolean {
592    if (self.length == 0) {
593        throw new TypeError("Reduce of empty array with no initial value")
594    }
595    let acc: boolean = self[0];
596    for (let i = 1; i < self.length; i++) {
597        acc = callbackfn(acc, self[i], i as number)
598    }
599    return acc
600}
601
602/**
603 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
604 *
605 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
606 *
607 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
608 *
609 * @returns a result after applying callbackfn over all elements of the Array
610 */
611export function reduce<U = boolean>(self: boolean[], callbackfn: (previousValue: U, currentValue: boolean, index: number) => U, initialValue: U): U {
612    let acc = initialValue
613    for (let i = 0; i < self.length; i++) {
614        acc = callbackfn(acc, self[i], i as number)
615    }
616    return acc
617}
618
619/**
620 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
621 *
622 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
623 *
624 * @returns a result after applying callbackfn over all elements of the Array
625 */
626export function reduceRight(self: boolean[], callbackfn: (previousValue: boolean, currentValue: boolean, index: number) => boolean): boolean {
627    if (self.length == 0) {
628        throw new TypeError("Reduce of empty array with no initial value")
629    }
630    let acc: boolean = self[self.length - 1];
631    for (let i = self.length - 2; i >= 0; i--) {
632        acc = callbackfn(acc, self[i], i as number)
633    }
634    return acc
635}
636
637/**
638 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
639 *
640 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
641 *
642 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
643 *
644 * @returns a result after applying callbackfn over all elements of the Array
645 */
646export function reduceRight<U>(self: boolean[], callbackfn: (previousValue: U, currentValue: boolean, index: number) => U, initialValue: U): U {
647    let acc = initialValue
648    for (let i = self.length - 1; i >= 0; i--) {
649        acc = callbackfn(acc, self[i], i as number)
650    }
651    return acc
652}
653
654/**
655 * Performs the specified action for each element in an array.
656 *
657 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
658 */
659export function forEach(self: boolean[], callbackfn: (value: boolean, index: number) => void): void {
660    const len0 = self.length;
661    for (let i = 0; i < len0; i++) {
662        callbackfn(self[i], i as number)
663    }
664}
665
666/**
667 * Returns the value of the first element in the array where predicate is true, and undefined
668 * otherwise.
669 *
670 * @param predicate find calls predicate once for each element of the array, in ascending
671 * order, until it finds one where predicate returns true. If such an element is found, find
672 * immediately returns that element value. Otherwise, find returns undefined.
673 *
674 * @returns the value of the first element in the array or undefined
675 */
676export function find(self: boolean[], predicate: (value: boolean) => boolean): Boolean | undefined {
677    const res = findIndex(self, predicate)
678    if (res == -1) {
679        return undefined
680    }
681    return self[res as int];
682}
683
684/**
685 * Returns the index of the first element in the array where predicate is true, and -1
686 * otherwise.
687 *
688 * @param predicate find calls predicate once for each element of the array, in ascending
689 * order, until it finds one where predicate returns true. If such an element is found,
690 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
691 *
692 * @returns found element index or -1 otherwise
693 */
694export function findIndex(self: boolean[], predicate: (value: boolean) => boolean): number {
695    for (let i = 0; i < self.length; i++) {
696        if (predicate(self[i])) {
697            return i;
698        }
699    }
700    return -1;
701}
702
703/**
704 * Iterates the array in reverse order and returns the value of the first element
705 * that satisfies the provided testing function
706 *
707 * @param predicate testing function
708 *
709 * @returns found element or undefined otherwise
710 */
711export function findLast(self: boolean[], predicate: (elem: boolean) => boolean): Boolean | undefined {
712    for (let i = self.length - 1; i >= 0; i--) {
713        const val = self[i];
714        if (predicate(val)) {
715            return val;
716        }
717    }
718    return undefined;
719}
720
721/**
722 * Determines whether all the members of an array satisfy the specified test.
723 *
724 * @param predicate A function that accepts up to three arguments. The every method calls
725 * the predicate function for each element in the array until the predicate returns a value
726 * which is coercible to the Boolean value false, or until the end of the array.
727 *
728 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
729 */
730export function every(self: boolean[], predicate: (value: boolean) => boolean): boolean {
731    for (let i = 0; i < self.length; i++) {
732        if (!predicate(self[i])) {
733            return false
734        }
735    }
736    return true;
737}
738
739/**
740 * Determines whether the specified callback function returns true for any element of an array.
741 *
742 * @param predicate A function that accepts up to three arguments. The some method calls
743 * the predicate function for each element in the array until the predicate returns a value
744 * which is coercible to the Boolean value true, or until the end of the array.
745 *
746 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
747 */
748export function some(self: boolean[], predicate: (value: boolean) => boolean): boolean {
749    for (let i = 0; i < self.length; i++) {
750        if (predicate(self[i])) {
751            return true
752        }
753    }
754    return false
755}
756
757/**
758 * Returns the elements of an array that meet the condition specified in a callback function.
759 *
760 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
761 *
762 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
763 */
764export function filter(self: boolean[], predicate: (value: boolean) => boolean): boolean[] {
765    return filter(self, (value: boolean, index: number): boolean => predicate(value));
766}
767
768/**
769 * Iterates the array in reverse order and returns the index of
770 * the first element that satisfies the provided testing function.
771 * If no elements satisfy the testing function, -1 is returned.
772 *
773 * @param predicate testing function
774 *
775 * @returns index of first element satisfying to predicate, -1 if no such element
776 */
777export function findLastIndex(self: boolean[], predicate: (element: boolean) => boolean): number {
778    for (let i = self.length - 1; i >= 0; i--) {
779        if (predicate(self[i])) {
780            return i
781        }
782    }
783    return -1
784}
785
786/**
787 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
788 *
789 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
790 *
791 * @returns a result after applying callbackfn over all elements of the Array
792 */
793export function reduce(self: boolean[], callbackfn: (previousValue: boolean, currentValue: boolean) => boolean): boolean {
794    if (self.length == 0) {
795        throw new TypeError("Reduce of empty array with no initial value")
796    }
797    let acc: boolean = self[0];
798    for (let i = 1; i < self.length; i++) {
799        acc = callbackfn(acc, self[i])
800    }
801    return acc
802}
803
804/**
805 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
806 *
807 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
808 *
809 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
810 *
811 * @returns a result after applying callbackfn over all elements of the Array
812 */
813export function reduce<U = boolean>(self: boolean[], callbackfn: (previousValue: U, currentValue: boolean) => U, initialValue: U): U {
814    let acc = initialValue
815    for (let i = 0; i < self.length; i++) {
816        acc = callbackfn(acc, self[i])
817    }
818    return acc
819}
820
821/**
822 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
823 *
824 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
825 *
826 * @returns a result after applying callbackfn over all elements of the Array
827 */
828export function reduceRight(self: boolean[], callbackfn: (previousValue: boolean, currentValue: boolean) => boolean): boolean {
829    if (self.length == 0) {
830        throw new TypeError("Reduce of empty array with no initial value")
831    }
832    let acc: boolean = self[self.length - 1];
833    for (let i = self.length - 2; i >= 0; i--) {
834        acc = callbackfn(acc, self[i])
835    }
836    return acc
837}
838
839/**
840 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
841 *
842 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
843 *
844 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
845 *
846 * @returns a result after applying callbackfn over all elements of the Array
847 */
848export function reduceRight<U>(self: boolean[], callbackfn: (previousValue: U, currentValue: boolean) => U, initialValue: U): U {
849    let acc = initialValue
850    for (let i = self.length - 1; i >= 0; i--) {
851        acc = callbackfn(acc, self[i])
852    }
853    return acc
854}
855
856/**
857 * Performs the specified action for each element in an array.
858 *
859 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
860 */
861export function forEach(self: boolean[], callbackfn: (value: boolean) => void): void {
862    const len0 = self.length;
863    for (let i = 0; i < len0; i++) {
864        callbackfn(self[i])
865    }
866}
867
868/**
869 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
870 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
871 *
872 * @param start zero-based index at which to start extraction
873 *
874 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
875 *
876 * @returns `Array` instance, constructed from extracted elements of `this` instance.
877 */
878export function slice(self: boolean[], start?: Number, end?: Number): boolean[] {
879    const len: int = self.length;
880    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
881}
882
883/**
884 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
885 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
886 *
887 * @param start zero-based index at which to start extraction
888 *
889 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
890 *
891 * @returns `Array` instance, constructed from extracted elements of `this` instance.
892 */
893export function slice(self: boolean[], start: int, end: int): boolean[] {
894    const len: int = self.length;
895    const relStart = normalizeIndex(start, len)
896    const relEnd = normalizeIndex(end, len)
897
898    let count = relEnd - relStart;
899    if (count < 0) {
900        count = 0;
901    }
902    let res = new boolean[count]
903    for (let i = 0; i < count; i++) {
904        res[i] = self[relStart + i];
905    }
906
907    return res
908}
909
910/**
911 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
912 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
913 *
914 * @param start zero-based index at which to start extraction
915 *
916 * @returns `Array` instance, constructed from extracted elements of `this` instance.
917 */
918export function slice(self: boolean[], start: int): boolean[] {
919    return slice(self, start, Int.MAX_VALUE as int);
920}
921
922/**
923 * Returns the last index at which a given element can be found in the array,
924 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
925 *
926 * @param element element to locate in the array.
927 * @param fromIndex zero-based index at which to start searching backwards.
928 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
929 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
930 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
931 *
932 * @returns The last index of the element in the array; -1 if not found.
933 */
934export function lastIndexOf(self: boolean[], element: boolean, fromIndex: int): int {
935    if (self.length == 0) {
936        return -1;
937    }
938    let n = fromIndex;
939    let k: int;
940    if (n >= 0) {
941        k = min(self.length - 1, n);
942    } else {
943        k = self.length + n;
944    }
945
946    while (k >= 0) {
947        if (__runtimeEquals(self[k], element)) {
948            return k;
949        }
950        k--;
951    }
952    return -1;
953}
954
955/**
956 * Returns the last index at which a given element can be found in the array,
957 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
958 *
959 * @param element element to locate in the array.
960 * @param fromIndex zero-based index at which to start searching backwards.
961 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
962 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
963 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
964 *
965 * @returns The last index of the element in the array; -1 if not found.
966 */
967export function lastIndexOf(self: boolean[], element: boolean, fromIndex?: Number): number {
968    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
969}
970
971/**
972 * Creates and returns a new string by concatenating all of the elements in an `Array`,
973 * separated by a specified separator string.
974 * If the array has only one item, then that item will be returned without using the separator.
975 *
976 * @param sep specifies a separator
977 *
978 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
979 */
980export function join(self: boolean[], sep?: String): string {
981    if (self.length == 0) {
982        return ""
983    }
984    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
985    let sb = new StringBuilder(new String(self[0]))
986    for (let i: int = 1; i < self.length; i++) {
987        const tmp = self[i]
988        sb.append(sepReal);
989        sb.append(tmp)
990    }
991
992    return sb.toString();
993}
994
995/**
996 * Returns a string representing the specified array and its elements.
997 *
998 * @returns string representation
999 */
1000export function toString(self: boolean[], ): string {
1001    return join(self, ",");
1002}
1003
1004/**
1005 * Returns a locale string representing the specified array and its elements.
1006 *
1007 * @param locales
1008 *
1009 * @param options
1010 *
1011 * @returns string representation
1012 */
1013export function toLocaleString(self: boolean[], locales: Object, options: Object): string {
1014    throw new Error("Array.toLocaleString: not implemented")
1015}
1016
1017/**
1018 * Returns a locale string representing the specified array and its elements.
1019 *
1020 * @param options
1021 *
1022 * @returns string representation
1023 */
1024export function toLocaleString(self: boolean[], locales: Object): string {
1025    return toLocaleString(self, new Object(), new Object())
1026}
1027
1028/**
1029 * Returns a locale string representing the specified array and its elements.
1030 *
1031 * @returns string representation
1032 */
1033export function toLocaleString(self: boolean[], ): string {
1034    const sb = new StringBuilder()
1035    const len = self.length;
1036    for (let i = 0; i < len; i++) {
1037        if (i != 0) {
1038            sb.append(",")
1039        }
1040        let x = self[i] as NullishType;
1041        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
1042            sb.append(x!.toLocaleString())
1043        }
1044    }
1045    return sb.toString()
1046}
1047
1048/**
1049 * Copying version of the splice() method.
1050 *
1051 * @param start index
1052 *
1053 * @param delete number of items after start index
1054 *
1055 * @returns a new Array with some elements removed and/or replaced at a given index.
1056 */
1057export function toSpliced(self: boolean[], start?: Number, delete?: Number): boolean[] {
1058    const len = self.length;
1059    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
1060}
1061
1062/**
1063 * Copying version of the splice() method.
1064 *
1065 * @param start index
1066 *
1067 * @param delete number of items after start index
1068 *
1069 * @returns a new Array with some elements removed and/or replaced at a given index.
1070 */
1071export function toSpliced(self: boolean[], start: number, delete: number, ...items: boolean[]): boolean[] {
1072    const len = self.length;
1073    return toSpliced(self, start as int, delete as int, ...items)
1074}
1075
1076/**
1077 * Copying version of the splice() method.
1078 *
1079 * @param start index
1080 *
1081 * @param delete number of items after start index
1082 *
1083 * @returns a new Array with some elements removed and/or replaced at a given index.
1084 */
1085export function toSpliced(self: boolean[], start: int, delete: int, ...items: boolean[]): boolean[] {
1086    const len = self.length;
1087    start = normalizeIndex(start, len);
1088    if (delete < 0) {
1089        delete = 0;
1090    } else if (delete > len) {
1091        delete = len;
1092    }
1093    if (start > len - delete) {
1094        delete = len - start
1095    }
1096    const res = new boolean[len - delete + items.length];
1097    for (let i = 0; i < start; i++) {
1098        res[i] = self[i]
1099    }
1100    for (let i = 0; i < items.length; i++) {
1101        res[start + i] = items[i]
1102    }
1103    for (let i = start + delete; i < len; i++) {
1104        res[i - delete + items.length] = self[i]
1105    }
1106    return res;
1107}
1108
1109/**
1110 * Copying version of the splice() method.
1111 *
1112 * @param start index
1113 *
1114 * @returns a new Array with some elements removed and/or replaced at a given index.
1115 */
1116export function toSpliced(self: boolean[], start: int): boolean[] {
1117    return toSpliced(self, start, self.length)
1118}
1119
1120/**
1121 * Checks whether an Array includes a certain value among its entries,
1122 * returning true or false as appropriate.
1123 *
1124 * @param val value to search
1125 *
1126 * @param fromIndex start index
1127 *
1128 * @returns true if val is in Array
1129 */
1130export function includes(self: boolean[], val: boolean, fromIndex?: Number): boolean {
1131    const len = self.length;
1132    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
1133    for (let i = fi; i < len; i++) {
1134        if (val == self[i]) {
1135            return true;
1136        }
1137    }
1138    return false;
1139}
1140
1141/**
1142 * Returns the first index at which a given element
1143 * can be found in the array, or -1 if it is not present.
1144 *
1145 * @param val value to search
1146 *
1147 * @param fromIndex index to search from
1148 *
1149 * @returns index of val, -1 otherwise
1150 */
1151export function indexOf(self: boolean[], val: boolean, fromIndex: int): int {
1152    fromIndex = normalizeIndex(fromIndex, self.length)
1153    for (let i = fromIndex; i < self.length; i++) {
1154        if (__runtimeEquals(val, self[i])) {
1155            return i
1156        }
1157    }
1158    return -1
1159}
1160
1161/**
1162 * Returns the first index at which a given element
1163 * can be found in the array, or -1 if it is not present.
1164 *
1165 * @param val value to search
1166 *
1167 * @param fromIndex index to search from
1168 *
1169 * @returns index of val, -1 otherwise
1170 */
1171export function indexOf(self: boolean[], val: boolean, fromIndex?: Number): number {
1172    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
1173}
1174
1175/**
1176 * Copying version of the sort() method.
1177 * It returns a new array with the elements sorted in ascending order.
1178 *
1179 * @returns sorted copy of hte current instance using default comparator
1180 */
1181export function toSorted(self: boolean[], ): boolean[] {
1182    let arr = cloneArray(self);
1183    sort(arr, )
1184    return arr
1185}
1186
1187/**
1188 * Copying version of the sort() method.
1189 * It returns a new array with the elements sorted in ascending order.
1190 *
1191 * @param comparator function to compare to elements of the Array
1192 *
1193 * @returns sorted copy of the current instance comparator
1194 */
1195export function toSorted(self: boolean[], comparator: (a: boolean, b: boolean) => number): boolean[] {
1196    let arr = cloneArray(self);
1197    sort(arr, comparator)
1198    return arr
1199}
1200
1201/**
1202 * Modifies `this` instance of `Array` class and populates
1203 * it with same elements ordered towards the direction opposite to that previously stated.
1204 *
1205 * @note Mutating method
1206 */
1207export function reverse(self: boolean[], ): boolean[] {
1208    for (let i = 0; i < self.length / 2; i++) {
1209        const tmp = self[i];
1210        const idx_r = self.length - 1 - i;
1211        const val_r = self[idx_r];
1212        self[i] = val_r;
1213        self[idx_r] = tmp;
1214    }
1215    return self;
1216}
1217
1218/**
1219 * Copying version of the reverse() method.
1220 * It returns a new array with the elements in reversed order.
1221 *
1222 * @returns reversed copy of the current Array
1223 */
1224export function toReversed(self: boolean[], ): boolean[] {
1225    let arr = new boolean[self.length]
1226    for (let i = 0; i < self.length; i++) {
1227        arr[self.length - 1 - i] = self[i]
1228    }
1229    return arr
1230}
1231
1232/**
1233 * Copying version of using the bracket notation to change the value of a given index.
1234 * It returns a new Array with the element at the given index replaced with the given value.
1235 *
1236 * @param index to replace
1237 *
1238 * @param value new value
1239 *
1240 * @returns a new Array with the element at the given index replaced with the given value
1241 */
1242export function with(self: boolean[], index: number, value: boolean): boolean[] {
1243    return with(self, index as int, value)
1244}
1245
1246/**
1247 * Copying version of using the bracket notation to change the value of a given index.
1248 * It returns a new Array with the element at the given index replaced with the given value.
1249 *
1250 * @param index to replace
1251 *
1252 * @param value new value
1253 *
1254 * @returns a new Array with the element at the given index replaced with the given value
1255 */
1256export function with(self: boolean[], index: int, value: boolean): boolean[] {
1257    if (index < 0) {
1258        index += self.length;
1259    }
1260    if (index >= self.length) {
1261        throw new RangeError("Invalid index")
1262    }
1263    let arr = cloneArray(self);
1264    arr[index] = value;
1265    return arr
1266}
1267
1268/**
1269 * Returns an iterator over all values
1270 */
1271export function values(self: boolean[], ): IterableIterator<boolean> {
1272    return new ArrayValuesIterator_boolean(self);
1273}
1274
1275/**
1276 * Returns an iterable of key, value pairs for every entry in the array
1277 */
1278export function entries(self: boolean[], ): IterableIterator<[number, boolean]> {
1279    return new ArrayEntriesIterator_boolean(self);
1280}
1281
1282/**
1283 * Determines whether all the members of an array satisfy the specified test.
1284 *
1285 * @param predicate A function that accepts up to three arguments. The every method calls
1286 * the predicate function for each element in the array until the predicate returns a value
1287 * which is coercible to the Boolean value false, or until the end of the array.
1288 *
1289 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
1290 */
1291export function every(self: boolean[], predicate: () => boolean): boolean {
1292    for (let i = 0; i < self.length; i++) {
1293        if (!predicate()) {
1294            return false
1295        }
1296    }
1297    return true
1298}
1299
1300/**
1301 * Returns the elements of an array that meet the condition specified in a callback function.
1302 *
1303 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
1304 *
1305 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
1306 */
1307export function filter(self: boolean[], predicate: () => boolean): boolean[] {
1308    return filter(self, (value: boolean, index: number): boolean => predicate());
1309}
1310
1311/**
1312 * Returns the value of the first element in the array where predicate is true, and undefined
1313 * otherwise.
1314 *
1315 * @param predicate find calls predicate once for each element of the array, in ascending
1316 * order, until it finds one where predicate returns true. If such an element is found, find
1317 * immediately returns that element value. Otherwise, find returns undefined.
1318 *
1319 * @returns the value of the first element in the array or undefined
1320 */
1321export function find(self: boolean[], predicate: () => boolean): Boolean | undefined {
1322    const res = findIndex(self, predicate)
1323    if (res == -1) {
1324        return undefined
1325    }
1326    return self[res as int];
1327}
1328
1329/**
1330 * Returns the index of the first element in the array where predicate is true, and -1
1331 * otherwise.
1332 *
1333 * @param predicate find calls predicate once for each element of the array, in ascending
1334 * order, until it finds one where predicate returns true. If such an element is found,
1335 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
1336 *
1337 * @returns found element index or -1 otherwise
1338 */
1339export function findIndex(self: boolean[], predicate: () => boolean): number {
1340    for (let i = 0; i < self.length; i++) {
1341        if (predicate()) {
1342            return i;
1343        }
1344    }
1345    return -1;
1346}
1347
1348/**
1349 * Performs the specified action for each element in an array.
1350 *
1351 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
1352 */
1353export function forEach(self: boolean[], callbackfn: () => void): void {
1354    const len0 = self.length;
1355    for (let i = 0; i < len0; i++) {
1356        callbackfn()
1357    }
1358}
1359
1360/**
1361 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1362 *
1363 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1364 *
1365 * @returns a result after applying callbackfn over all elements of the Array
1366 */
1367export function reduce(self: boolean[], callbackfn: (previousValue: boolean) => boolean): boolean {
1368    if (self.length == 0) {
1369        throw new TypeError("Reduce of empty array with no initial value")
1370    }
1371    let acc: boolean = self[0];
1372    for (let i = 1; i < self.length; i++) {
1373        acc = callbackfn(acc)
1374    }
1375    return acc
1376}
1377
1378/**
1379 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1380 *
1381 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1382 *
1383 * @returns a result after applying callbackfn over all elements of the Array
1384 */
1385export function reduce(self: boolean[], callbackfn: () => boolean): boolean {
1386    if (self.length == 0) {
1387        throw new TypeError("Reduce of empty array with no initial value")
1388    }
1389    let acc: boolean = self[0];
1390    for (let i = 1; i < self.length; i++) {
1391        acc = callbackfn()
1392    }
1393    return acc
1394}
1395
1396/**
1397 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1398 *
1399 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1400 *
1401 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1402 *
1403 * @returns a result after applying callbackfn over all elements of the Array
1404 */
1405export function reduce<U = boolean>(self: boolean[], callbackfn: (previousValue: U) => U, initialValue: U): U {
1406    let acc = initialValue
1407    for (let i = 0; i < self.length; i++) {
1408        acc = callbackfn(acc)
1409    }
1410    return acc
1411}
1412
1413/**
1414 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1415 *
1416 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1417 *
1418 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1419 *
1420 * @returns a result after applying callbackfn over all elements of the Array
1421 */
1422export function reduce<U = boolean>(self: boolean[], callbackfn: () => U, initialValue: U): U {
1423    let acc = initialValue
1424    for (let i = 0; i < self.length; i++) {
1425        acc = callbackfn()
1426    }
1427    return acc
1428}
1429
1430/**
1431 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1432 *
1433 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1434 *
1435 * @returns a result after applying callbackfn over all elements of the Array
1436 */
1437export function reduceRight(self: boolean[], callbackfn: (previousValue: boolean) => boolean): boolean {
1438    if (self.length == 0) {
1439        throw new TypeError("Reduce of empty array with no initial value")
1440    }
1441    let acc: boolean = self[self.length - 1];
1442    for (let i = self.length - 2; i >= 0; i--) {
1443        acc = callbackfn(acc)
1444    }
1445    return acc
1446}
1447
1448/**
1449 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1450 *
1451 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1452 *
1453 * @returns a result after applying callbackfn over all elements of the Array
1454 */
1455export function reduceRight(self: boolean[], callbackfn: () => boolean): boolean {
1456    if (self.length == 0) {
1457        throw new TypeError("Reduce of empty array with no initial value")
1458    }
1459    let acc: boolean = self[self.length - 1];
1460    for (let i = self.length - 2; i >= 0; i--) {
1461        acc = callbackfn()
1462    }
1463    return acc
1464}
1465
1466/**
1467 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1468 *
1469 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1470 *
1471 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1472 *
1473 * @returns a result after applying callbackfn over all elements of the Array
1474 */
1475export function reduceRight<U>(self: boolean[], callbackfn: (previousValue: U) => U, initialValue: U): U {
1476    let acc = initialValue
1477    for (let i = self.length - 1; i >= 0; i--) {
1478        acc = callbackfn(acc)
1479    }
1480    return acc
1481}
1482
1483/**
1484 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1485 *
1486 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1487 *
1488 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1489 *
1490 * @returns a result after applying callbackfn over all elements of the Array
1491 */
1492export function reduceRight<U>(self: boolean[], callbackfn: () => U, initialValue: U): U {
1493    let acc = initialValue
1494    for (let i = self.length - 1; i >= 0; i--) {
1495        acc = callbackfn()
1496    }
1497    return acc
1498}
1499
1500/**
1501 * Determines whether the specified callback function returns true for any element of an array.
1502 *
1503 * @param predicate A function that accepts up to three arguments. The some method calls
1504 * the predicate function for each element in the array until the predicate returns a value
1505 * which is coercible to the Boolean value true, or until the end of the array.
1506 *
1507 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
1508 */
1509export function some(self: boolean[], predicate: () => boolean): boolean {
1510    for (let i = 0; i < self.length; i++) {
1511        if (predicate()) {
1512            return true
1513        }
1514    }
1515    return false
1516}
1517
1518/**
1519 * Iterates the array in reverse order and returns the value of the first element
1520 * that satisfies the provided testing function
1521 *
1522 * @param predicate testing function
1523 *
1524 * @returns found element or undefined otherwise
1525 */
1526export function findLast(self: boolean[], predicate: () => boolean): Boolean | undefined {
1527    for (let i = self.length - 1; i >= 0; i--) {
1528        const val = self[i];
1529        if (predicate()) {
1530            return val;
1531        }
1532    }
1533    return undefined;
1534}
1535
1536/**
1537 * Iterates the array in reverse order and returns the index of
1538 * the first element that satisfies the provided testing function.
1539 * If no elements satisfy the testing function, -1 is returned.
1540 *
1541 * @param predicate testing function
1542 *
1543 * @returns index of first element satisfying to predicate, -1 if no such element
1544 */
1545export function findLastIndex(self: boolean[], predicate: () => boolean): number {
1546    for (let i = self.length - 1; i >= 0; i--) {
1547        if (predicate()) {
1548            return i
1549        }
1550    }
1551    return -1
1552}
1553
1554/**
1555 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
1556 *
1557 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
1558 *
1559 * @returns `Array` instance, constructed from `this` and given function.
1560 */
1561export function map(self: boolean[], callbackfn: (value: boolean, index: number, array: boolean[]) => boolean): boolean[] {
1562    const len = self.length;
1563    let res = new boolean[len];
1564    for (let i = 0; i < len; i++) {
1565        res[i] = callbackfn(self[i], i as number, self);
1566    }
1567    return res;
1568}
1569
1570/**
1571 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
1572 *
1573 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
1574 *
1575 * @returns `Array` instance, constructed from `this` and given function.
1576 */
1577export function map(self: boolean[], callbackfn: (value: boolean, index: number) => boolean): boolean[] {
1578    const len = self.length;
1579    let res = new boolean[len];
1580    for (let i = 0; i < len; i++) {
1581        res[i] = callbackfn(self[i], i as number);
1582    }
1583    return res;
1584}
1585
1586/**
1587 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
1588 *
1589 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
1590 *
1591 * @returns `Array` instance, constructed from `this` and given function.
1592 */
1593export function map(self: boolean[], callbackfn: (value: boolean) => boolean): boolean[] {
1594    const len = self.length;
1595    let res = new boolean[len];
1596    for (let i = 0; i < len; i++) {
1597        res[i] = callbackfn(self[i]);
1598    }
1599    return res;
1600}
1601
1602/**
1603 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
1604 *
1605 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
1606 *
1607 * @returns `Array` instance, constructed from `this` and given function.
1608 */
1609export function map(self: boolean[], callbackfn: () => boolean): boolean[] {
1610    const len = self.length;
1611    let res = new boolean[len];
1612    for (let i = 0; i < len; i++) {
1613        res[i] = callbackfn();
1614    }
1615    return res;
1616}
1617
1618/**
1619 * Constructs a new `Array` instance and populates it with
1620 * portion of a given array, filtered down to just the elements from the
1621 * given array that pass the test implemented by the provided function.
1622 *
1623 * @param fn test function, applied to each element of an array.
1624 *
1625 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
1626 */
1627export function filter(self: boolean[], fn: (v: boolean, k: number) => boolean): boolean[] {
1628    const mask = new boolean[self.length]
1629    let cnt = 0
1630
1631    for (let i: int = 0; i < self.length; i++) {
1632        const val = self[i];
1633        if (fn(val, i)) {
1634            mask[i] = true
1635            cnt++;
1636        }
1637    }
1638    const res = new boolean[cnt];
1639    let idx_store = 0;
1640    for (let i: int = 0; i < self.length; i++) {
1641        if (mask[i]) {
1642            res[idx_store++] = self[i]
1643        }
1644    }
1645    return res;
1646}
1647
1648export function concat(self: boolean[], fst: boolean[], ...more: boolean[][]): boolean[] {
1649    const lnMin = self.length + fst.length;
1650    let ln = lnMin;
1651    for (let i = 0; i < more.length; i++) {
1652        ln += more[i].length
1653    }
1654    const r = new boolean[ln];
1655    try {
1656        copyTo(self, r, 0, 0, self.length);
1657        copyTo(fst, r, self.length, 0, fst.length);
1658        let idx = lnMin;
1659        for (let i = 0; i < more.length; i++) {
1660            copyTo(more[i], r, idx, 0, more[i].length);
1661            idx += more[i].length;
1662        }
1663    } catch (e) {
1664        // impossible
1665    }
1666    return r
1667}
1668
1669/**
1670 * Reorders elements of `this` using comparator function.
1671 *
1672 * @param comparator function that defines the sort order.
1673 *
1674 * @note Mutating method
1675 */
1676export function sort(self: boolean[], comparator: (a: boolean, b: boolean) => number): boolean[] {
1677    sort_subarray(self, 0, self.length, (l: boolean, r: boolean): boolean => {
1678        return comparator(l, r ) < 0;
1679    });
1680    return self;
1681}
1682
1683/**
1684 * Reorders elements of `this` using comparator function.
1685 *
1686 * @param comparator function that defines the sort order.
1687 *
1688 * @note Mutating method
1689 */
1690export function sort(self: boolean[], ): boolean[] {
1691    sort(self, 0, self.length);
1692    return self;
1693}
1694
1695export function keys(self: boolean[]): IterableIterator<number> {
1696    return new BuiltinArrayKeysIterator(self.length);
1697}
1698
1699class ArrayValuesIterator_boolean implements IterableIterator<boolean> {
1700    private parent: boolean[]
1701    private idx: int = 0
1702
1703    constructor(parent: boolean[]) {
1704        this.parent = parent
1705    }
1706
1707    override next(): IteratorResult<boolean> {
1708        if (this.idx >= this.parent.length) {
1709            return new IteratorResult<boolean>()
1710        }
1711        return new IteratorResult<boolean>(this.parent[this.idx++])
1712    }
1713
1714    override $_iterator(): IterableIterator<boolean> {
1715        return this;
1716    }
1717
1718    public __Iterator_getLength(): int {
1719        return this.parent.length as int
1720    }
1721}
1722
1723class ArrayEntriesIterator_boolean implements IterableIterator<[number, boolean]> {
1724    private parent: boolean[]
1725    private idx: int = 0
1726
1727    constructor(parent: boolean[]) {
1728        this.parent = parent
1729    }
1730
1731    override next(): IteratorResult<[number, boolean]> {
1732        if (this.idx >= this.parent.length) {
1733            return new IteratorResult<[number, boolean]>()
1734        }
1735        const i = this.idx++;
1736        const vl: [number, boolean] = [i as number, this.parent[i]]
1737        return new IteratorResult<[number, boolean]>(vl);
1738    }
1739
1740    override $_iterator(): IterableIterator<[number, boolean]> {
1741        return this;
1742    }
1743
1744    public __Iterator_getLength(): int {
1745        return this.parent.length as int
1746    }
1747}
1748
1749function cloneArray(self: byte[]): byte[] {
1750    const ret = new byte[self.length];;
1751    for (let i = 0; i < self.length; i++) {
1752        ret[i] = self[i];
1753    }
1754    return ret;
1755}
1756
1757/**
1758 * Takes an integer value and returns the item at that index,
1759 * allowing for positive and negative integers. Negative integers count back
1760 * from the last item in the array.
1761 *
1762 * @param index Zero-based index of the array element to be returned.
1763 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
1764 *
1765 * @returns The element in the array matching the given index.
1766 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
1767 */
1768export function at(self: byte[], index: number): Byte | undefined {
1769    return at(self, index as int)
1770}
1771
1772/**
1773 * Creates a new `Array` from this `Array` instance and given `Array` instance.
1774 *
1775 * @param other to concatenate into a new array.
1776 *
1777 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
1778 */
1779// export function concat(self: byte[], ...items: (byte | Concatbyte[])[]): byte[] {
1780//     throw new Error("not implemented")
1781// }
1782
1783export function concat(self: byte[], ...items: ConcatArray<byte>[]): byte[] {
1784    let totalAdd = self.length;
1785    for (let i = 0; i < items.length; i++) {
1786        totalAdd += items[i].length as int
1787    }
1788
1789    const buf = new byte[totalAdd];
1790
1791    for (let i = 0; i < self.length; i++) {
1792        buf[i] = self[i];
1793    }
1794
1795    let insertTo = self.length;
1796    for (let i = 0; i < items.length; i++) {
1797        const arr = items[i]
1798        const len = arr.length as int
1799        for (let j = 0; j < len; j++) {
1800            buf[insertTo++] = arr.$_get(j)
1801        }
1802    }
1803
1804    return buf;
1805}
1806
1807/**
1808 * Takes an integer value and returns the item at that index,
1809 * allowing for positive and negative integers. Negative integers count back
1810 * from the last item in the array.
1811 *
1812 * @param index Zero-based index of the array element to be returned.
1813 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
1814 *
1815 * @returns The element in the array matching the given index.
1816 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
1817 */
1818export function at(self: byte[], index: int): Byte | undefined {
1819    let len = self.length;
1820    let k: int;
1821    if (index >= 0) {
1822        k = index;
1823    } else {
1824        k = len + index;
1825    }
1826
1827    if (k < 0 || k >= len) {
1828        return undefined;
1829    }
1830
1831    return self[k];
1832}
1833
1834/**
1835 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1836 *
1837 * @param target index at which to copy the sequence
1838 *
1839 * @param start index at which to start copying elements from
1840 *
1841 * @param end index at which to end copying elements from
1842 *
1843 * @returns this array after transformation
1844 */
1845export function copyWithin(self: byte[], target: number, start: number, end?: Number): byte[] {
1846    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
1847    return self;
1848}
1849
1850/**
1851 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1852 *
1853 * @param target index at which to copy the sequence
1854 *
1855 * @param start index at which to start copying elements from
1856 *
1857 * @param end index at which to end copying elements from
1858 *
1859 * @returns this array after transformation
1860 */
1861export function copyWithin(self: byte[], target: int, start: int, end: int): byte[] {
1862    target = normalizeIndex(target, self.length)
1863    start = normalizeIndex(start, self.length)
1864    end = normalizeIndex(end, self.length)
1865
1866    if (end <= start) {
1867        return self;
1868    }
1869
1870    if (target <= start) {
1871        while (start < end) {
1872            const read = self[start++];
1873            self[target++] = read;
1874        }
1875    } else {
1876        let len = end - start;
1877        if (target + len > self.length) {
1878            len = self.length - target
1879        }
1880        for (let i = 0; i < len; i++) {
1881            const read = self[start + len - 1 - i];
1882            self[target + len - 1 - i] = read;
1883        }
1884    }
1885
1886    return self;
1887}
1888
1889/**
1890 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1891 *
1892 * @param target index at which to copy the sequence
1893 *
1894 * @param start index at which to start copying elements from
1895 *
1896 * @returns this array after transformation
1897 */
1898export function copyWithin(self: byte[], target: int, start: int): byte[] {
1899    copyWithin(self, target, start, self.length);
1900    return self;
1901}
1902
1903/**
1904 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1905 *
1906 * @param target index at which to copy the sequence
1907 *
1908 * @returns this array after transformation
1909 */
1910export function copyWithin(self: byte[], target: int): byte[] {
1911    copyWithin(self, target, 0, self.length);
1912    return self;
1913}
1914
1915/**
1916 * Changes all elements in the Array to a static value, from a start index to an end index
1917 *
1918 * @param value to fill the array with
1919 *
1920 * @param start index at which to start filling
1921 *
1922 * @param end index at which to end filling, but not including
1923 *
1924 * @returns this array after transformation
1925 */
1926export function fill(self: byte[], value: byte, start?: Number, end?: Number): byte[] {
1927    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
1928    return self;
1929}
1930
1931/**
1932 * Changes all elements in the Array to a static value, from a start index to an end index
1933 *
1934 * @param value to fill the array with
1935 *
1936 * @param start index at which to start filling
1937 *
1938 * @param end index at which to end filling, but not including
1939 *
1940 * @returns this array after transformation
1941 */
1942export function fill(self: byte[], value: byte, start: int, end: int): byte[] {
1943    start = normalizeIndex(start, self.length);
1944    end = normalizeIndex(end, self.length)
1945
1946    for (let i = start; i < end; i++) {
1947        self[i] = value;
1948    }
1949
1950    return self;
1951}
1952
1953/**
1954 * Returns the value of the first element in the array where predicate is true, and undefined
1955 * otherwise.
1956 *
1957 * @param predicate find calls predicate once for each element of the array, in ascending
1958 * order, until it finds one where predicate returns true. If such an element is found, find
1959 * immediately returns that element value. Otherwise, find returns undefined.
1960 *
1961 * @returns the value of the first element in the array or undefined
1962 */
1963export function find(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): Byte | undefined {
1964    const res = findIndex(self, predicate)
1965    if (res == -1) {
1966        return undefined
1967    }
1968    return self[res as int];
1969}
1970
1971/**
1972 * Returns the index of the first element in the array where predicate is true, and -1
1973 * otherwise.
1974 *
1975 * @param predicate find calls predicate once for each element of the array, in ascending
1976 * order, until it finds one where predicate returns true. If such an element is found,
1977 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
1978 *
1979 * @returns found element index or -1 otherwise
1980 */
1981export function findIndex(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): number {
1982    for (let i = 0; i < self.length; i++) {
1983        if (predicate(self[i], i as number, self)) {
1984            return i;
1985        }
1986    }
1987    return -1;
1988}
1989
1990/**
1991 * Iterates the array in reverse order and returns the value of the first element
1992 * that satisfies the provided testing function
1993 *
1994 * @param predicate testing function
1995 *
1996 * @returns found element or undefined otherwise
1997 */
1998export function findLast(self: byte[], predicate: (elem: byte, index: number, array: byte[]) => boolean): Byte | undefined {
1999    for (let i = self.length - 1; i >= 0; i--) {
2000        const val = self[i];
2001        if (predicate(val, i as number, self)) {
2002            return val;
2003        }
2004    }
2005    return undefined;
2006}
2007
2008/**
2009 * Determines whether all the members of an array satisfy the specified test.
2010 *
2011 * @param predicate A function that accepts up to three arguments. The every method calls
2012 * the predicate function for each element in the array until the predicate returns a value
2013 * which is coercible to the Boolean value false, or until the end of the array.
2014 *
2015 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2016 */
2017export function every(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): boolean {
2018    for (let i = 0; i < self.length; i++) {
2019        if (!predicate(self[i], i as number, self)) {
2020            return false
2021        }
2022    }
2023    return true;
2024}
2025
2026/**
2027 * Determines whether the specified callback function returns true for any element of an array.
2028 *
2029 * @param predicate A function that accepts up to three arguments. The some method calls
2030 * the predicate function for each element in the array until the predicate returns a value
2031 * which is coercible to the Boolean value true, or until the end of the array.
2032 *
2033 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
2034 */
2035export function some(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): boolean {
2036    for (let i = 0; i < self.length; i++) {
2037        if (predicate(self[i], i as number, self)) {
2038            return true
2039        }
2040    }
2041    return false
2042}
2043
2044/**
2045 * Returns the elements of an array that meet the condition specified in a callback function.
2046 *
2047 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
2048 *
2049 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
2050 */
2051export function filter(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): byte[] {
2052    return filter(self, (value: byte, index: number): boolean => predicate(value, index, self));
2053}
2054
2055/**
2056 * Iterates the array in reverse order and returns the index of
2057 * the first element that satisfies the provided testing function.
2058 * If no elements satisfy the testing function, -1 is returned.
2059 *
2060 * @param predicate testing function
2061 *
2062 * @returns index of first element satisfying to predicate, -1 if no such element
2063 */
2064export function findLastIndex(self: byte[], predicate: (element: byte, index: number, array: byte[]) => boolean): number {
2065    for (let i = self.length - 1; i >= 0; i--) {
2066        if (predicate(self[i], i as number, self)) {
2067            return i
2068        }
2069    }
2070    return -1
2071}
2072
2073/**
2074 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2075 *
2076 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2077 *
2078 * @returns a result after applying callbackfn over all elements of the Array
2079 */
2080export function reduce(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number, array: byte[]) => byte): byte {
2081    if (self.length == 0) {
2082        throw new TypeError("Reduce of empty array with no initial value")
2083    }
2084    let acc: byte = self[0];
2085    for (let i = 1; i < self.length; i++) {
2086        acc = callbackfn(acc, self[i], i as number, self)
2087    }
2088    return acc
2089}
2090
2091/**
2092 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2093 *
2094 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2095 *
2096 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2097 *
2098 * @returns a result after applying callbackfn over all elements of the Array
2099 */
2100export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number, array: byte[]) => U, initialValue: U): U {
2101    let acc = initialValue
2102    for (let i = 0; i < self.length; i++) {
2103        acc = callbackfn(acc, self[i], i as number, self)
2104    }
2105    return acc
2106}
2107
2108/**
2109 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2110 *
2111 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2112 *
2113 * @returns a result after applying callbackfn over all elements of the Array
2114 */
2115export function reduceRight(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number, array: byte[]) => byte): byte {
2116    if (self.length == 0) {
2117        throw new TypeError("Reduce of empty array with no initial value")
2118    }
2119    let acc: byte = self[self.length - 1];
2120    for (let i = self.length - 2; i >= 0; i--) {
2121        acc = callbackfn(acc, self[i], i as number, self)
2122    }
2123    return acc
2124}
2125
2126/**
2127 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2128 *
2129 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2130 *
2131 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2132 *
2133 * @returns a result after applying callbackfn over all elements of the Array
2134 */
2135export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number, array: byte[]) => U, initialValue: U): U {
2136    let acc = initialValue
2137    for (let i = self.length - 1; i >= 0; i--) {
2138        acc = callbackfn(acc, self[i], i as number, self)
2139    }
2140    return acc
2141}
2142
2143/**
2144 * Performs the specified action for each element in an array.
2145 *
2146 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
2147 */
2148export function forEach(self: byte[], callbackfn: (value: byte, index: number, array: byte[]) => void): void {
2149    const len0 = self.length;
2150    for (let i = 0; i < len0; i++) {
2151        callbackfn(self[i], i as number, self)
2152    }
2153}
2154
2155/**
2156 * Returns the value of the first element in the array where predicate is true, and undefined
2157 * otherwise.
2158 *
2159 * @param predicate find calls predicate once for each element of the array, in ascending
2160 * order, until it finds one where predicate returns true. If such an element is found, find
2161 * immediately returns that element value. Otherwise, find returns undefined.
2162 *
2163 * @returns the value of the first element in the array or undefined
2164 */
2165export function find(self: byte[], predicate: (value: byte, index: number) => boolean): Byte | undefined {
2166    const res = findIndex(self, predicate)
2167    if (res == -1) {
2168        return undefined
2169    }
2170    return self[res as int];
2171}
2172
2173/**
2174 * Returns the index of the first element in the array where predicate is true, and -1
2175 * otherwise.
2176 *
2177 * @param predicate find calls predicate once for each element of the array, in ascending
2178 * order, until it finds one where predicate returns true. If such an element is found,
2179 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
2180 *
2181 * @returns found element index or -1 otherwise
2182 */
2183export function findIndex(self: byte[], predicate: (value: byte, index: number) => boolean): number {
2184    for (let i = 0; i < self.length; i++) {
2185        if (predicate(self[i], i as number)) {
2186            return i;
2187        }
2188    }
2189    return -1;
2190}
2191
2192/**
2193 * Iterates the array in reverse order and returns the value of the first element
2194 * that satisfies the provided testing function
2195 *
2196 * @param predicate testing function
2197 *
2198 * @returns found element or undefined otherwise
2199 */
2200export function findLast(self: byte[], predicate: (elem: byte, index: number) => boolean): Byte | undefined {
2201    for (let i = self.length - 1; i >= 0; i--) {
2202        const val = self[i];
2203        if (predicate(val, i as number)) {
2204            return val;
2205        }
2206    }
2207    return undefined;
2208}
2209
2210/**
2211 * Determines whether all the members of an array satisfy the specified test.
2212 *
2213 * @param predicate A function that accepts up to three arguments. The every method calls
2214 * the predicate function for each element in the array until the predicate returns a value
2215 * which is coercible to the Boolean value false, or until the end of the array.
2216 *
2217 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2218 */
2219export function every(self: byte[], predicate: (value: byte, index: number) => boolean): boolean {
2220    for (let i = 0; i < self.length; i++) {
2221        if (!predicate(self[i], i as number)) {
2222            return false
2223        }
2224    }
2225    return true;
2226}
2227
2228/**
2229 * Determines whether the specified callback function returns true for any element of an array.
2230 *
2231 * @param predicate A function that accepts up to three arguments. The some method calls
2232 * the predicate function for each element in the array until the predicate returns a value
2233 * which is coercible to the Boolean value true, or until the end of the array.
2234 *
2235 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
2236 */
2237export function some(self: byte[], predicate: (value: byte, index: number) => boolean): boolean {
2238    for (let i = 0; i < self.length; i++) {
2239        if (predicate(self[i], i as number)) {
2240            return true
2241        }
2242    }
2243    return false
2244}
2245
2246/**
2247 * Iterates the array in reverse order and returns the index of
2248 * the first element that satisfies the provided testing function.
2249 * If no elements satisfy the testing function, -1 is returned.
2250 *
2251 * @param predicate testing function
2252 *
2253 * @returns index of first element satisfying to predicate, -1 if no such element
2254 */
2255export function findLastIndex(self: byte[], predicate: (element: byte, index: number) => boolean): number {
2256    for (let i = self.length - 1; i >= 0; i--) {
2257        if (predicate(self[i], i as number)) {
2258            return i
2259        }
2260    }
2261    return -1
2262}
2263
2264/**
2265 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2266 *
2267 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2268 *
2269 * @returns a result after applying callbackfn over all elements of the Array
2270 */
2271export function reduce(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number) => byte): byte {
2272    if (self.length == 0) {
2273        throw new TypeError("Reduce of empty array with no initial value")
2274    }
2275    let acc: byte = self[0];
2276    for (let i = 1; i < self.length; i++) {
2277        acc = callbackfn(acc, self[i], i as number)
2278    }
2279    return acc
2280}
2281
2282/**
2283 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2284 *
2285 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2286 *
2287 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2288 *
2289 * @returns a result after applying callbackfn over all elements of the Array
2290 */
2291export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number) => U, initialValue: U): U {
2292    let acc = initialValue
2293    for (let i = 0; i < self.length; i++) {
2294        acc = callbackfn(acc, self[i], i as number)
2295    }
2296    return acc
2297}
2298
2299/**
2300 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2301 *
2302 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2303 *
2304 * @returns a result after applying callbackfn over all elements of the Array
2305 */
2306export function reduceRight(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number) => byte): byte {
2307    if (self.length == 0) {
2308        throw new TypeError("Reduce of empty array with no initial value")
2309    }
2310    let acc: byte = self[self.length - 1];
2311    for (let i = self.length - 2; i >= 0; i--) {
2312        acc = callbackfn(acc, self[i], i as number)
2313    }
2314    return acc
2315}
2316
2317/**
2318 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2319 *
2320 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2321 *
2322 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2323 *
2324 * @returns a result after applying callbackfn over all elements of the Array
2325 */
2326export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number) => U, initialValue: U): U {
2327    let acc = initialValue
2328    for (let i = self.length - 1; i >= 0; i--) {
2329        acc = callbackfn(acc, self[i], i as number)
2330    }
2331    return acc
2332}
2333
2334/**
2335 * Performs the specified action for each element in an array.
2336 *
2337 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
2338 */
2339export function forEach(self: byte[], callbackfn: (value: byte, index: number) => void): void {
2340    const len0 = self.length;
2341    for (let i = 0; i < len0; i++) {
2342        callbackfn(self[i], i as number)
2343    }
2344}
2345
2346/**
2347 * Returns the value of the first element in the array where predicate is true, and undefined
2348 * otherwise.
2349 *
2350 * @param predicate find calls predicate once for each element of the array, in ascending
2351 * order, until it finds one where predicate returns true. If such an element is found, find
2352 * immediately returns that element value. Otherwise, find returns undefined.
2353 *
2354 * @returns the value of the first element in the array or undefined
2355 */
2356export function find(self: byte[], predicate: (value: byte) => boolean): Byte | undefined {
2357    const res = findIndex(self, predicate)
2358    if (res == -1) {
2359        return undefined
2360    }
2361    return self[res as int];
2362}
2363
2364/**
2365 * Returns the index of the first element in the array where predicate is true, and -1
2366 * otherwise.
2367 *
2368 * @param predicate find calls predicate once for each element of the array, in ascending
2369 * order, until it finds one where predicate returns true. If such an element is found,
2370 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
2371 *
2372 * @returns found element index or -1 otherwise
2373 */
2374export function findIndex(self: byte[], predicate: (value: byte) => boolean): number {
2375    for (let i = 0; i < self.length; i++) {
2376        if (predicate(self[i])) {
2377            return i;
2378        }
2379    }
2380    return -1;
2381}
2382
2383/**
2384 * Iterates the array in reverse order and returns the value of the first element
2385 * that satisfies the provided testing function
2386 *
2387 * @param predicate testing function
2388 *
2389 * @returns found element or undefined otherwise
2390 */
2391export function findLast(self: byte[], predicate: (elem: byte) => boolean): Byte | undefined {
2392    for (let i = self.length - 1; i >= 0; i--) {
2393        const val = self[i];
2394        if (predicate(val)) {
2395            return val;
2396        }
2397    }
2398    return undefined;
2399}
2400
2401/**
2402 * Determines whether all the members of an array satisfy the specified test.
2403 *
2404 * @param predicate A function that accepts up to three arguments. The every method calls
2405 * the predicate function for each element in the array until the predicate returns a value
2406 * which is coercible to the Boolean value false, or until the end of the array.
2407 *
2408 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2409 */
2410export function every(self: byte[], predicate: (value: byte) => boolean): boolean {
2411    for (let i = 0; i < self.length; i++) {
2412        if (!predicate(self[i])) {
2413            return false
2414        }
2415    }
2416    return true;
2417}
2418
2419/**
2420 * Determines whether the specified callback function returns true for any element of an array.
2421 *
2422 * @param predicate A function that accepts up to three arguments. The some method calls
2423 * the predicate function for each element in the array until the predicate returns a value
2424 * which is coercible to the Boolean value true, or until the end of the array.
2425 *
2426 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
2427 */
2428export function some(self: byte[], predicate: (value: byte) => boolean): boolean {
2429    for (let i = 0; i < self.length; i++) {
2430        if (predicate(self[i])) {
2431            return true
2432        }
2433    }
2434    return false
2435}
2436
2437/**
2438 * Returns the elements of an array that meet the condition specified in a callback function.
2439 *
2440 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
2441 *
2442 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
2443 */
2444export function filter(self: byte[], predicate: (value: byte) => boolean): byte[] {
2445    return filter(self, (value: byte, index: number): boolean => predicate(value));
2446}
2447
2448/**
2449 * Iterates the array in reverse order and returns the index of
2450 * the first element that satisfies the provided testing function.
2451 * If no elements satisfy the testing function, -1 is returned.
2452 *
2453 * @param predicate testing function
2454 *
2455 * @returns index of first element satisfying to predicate, -1 if no such element
2456 */
2457export function findLastIndex(self: byte[], predicate: (element: byte) => boolean): number {
2458    for (let i = self.length - 1; i >= 0; i--) {
2459        if (predicate(self[i])) {
2460            return i
2461        }
2462    }
2463    return -1
2464}
2465
2466/**
2467 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2468 *
2469 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2470 *
2471 * @returns a result after applying callbackfn over all elements of the Array
2472 */
2473export function reduce(self: byte[], callbackfn: (previousValue: byte, currentValue: byte) => byte): byte {
2474    if (self.length == 0) {
2475        throw new TypeError("Reduce of empty array with no initial value")
2476    }
2477    let acc: byte = self[0];
2478    for (let i = 1; i < self.length; i++) {
2479        acc = callbackfn(acc, self[i])
2480    }
2481    return acc
2482}
2483
2484/**
2485 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2486 *
2487 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2488 *
2489 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2490 *
2491 * @returns a result after applying callbackfn over all elements of the Array
2492 */
2493export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U, currentValue: byte) => U, initialValue: U): U {
2494    let acc = initialValue
2495    for (let i = 0; i < self.length; i++) {
2496        acc = callbackfn(acc, self[i])
2497    }
2498    return acc
2499}
2500
2501/**
2502 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2503 *
2504 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2505 *
2506 * @returns a result after applying callbackfn over all elements of the Array
2507 */
2508export function reduceRight(self: byte[], callbackfn: (previousValue: byte, currentValue: byte) => byte): byte {
2509    if (self.length == 0) {
2510        throw new TypeError("Reduce of empty array with no initial value")
2511    }
2512    let acc: byte = self[self.length - 1];
2513    for (let i = self.length - 2; i >= 0; i--) {
2514        acc = callbackfn(acc, self[i])
2515    }
2516    return acc
2517}
2518
2519/**
2520 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2521 *
2522 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2523 *
2524 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2525 *
2526 * @returns a result after applying callbackfn over all elements of the Array
2527 */
2528export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U, currentValue: byte) => U, initialValue: U): U {
2529    let acc = initialValue
2530    for (let i = self.length - 1; i >= 0; i--) {
2531        acc = callbackfn(acc, self[i])
2532    }
2533    return acc
2534}
2535
2536/**
2537 * Performs the specified action for each element in an array.
2538 *
2539 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
2540 */
2541export function forEach(self: byte[], callbackfn: (value: byte) => void): void {
2542    const len0 = self.length;
2543    for (let i = 0; i < len0; i++) {
2544        callbackfn(self[i])
2545    }
2546}
2547
2548/**
2549 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
2550 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
2551 *
2552 * @param start zero-based index at which to start extraction
2553 *
2554 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
2555 *
2556 * @returns `Array` instance, constructed from extracted elements of `this` instance.
2557 */
2558export function slice(self: byte[], start?: Number, end?: Number): byte[] {
2559    const len: int = self.length;
2560    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
2561}
2562
2563/**
2564 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
2565 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
2566 *
2567 * @param start zero-based index at which to start extraction
2568 *
2569 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
2570 *
2571 * @returns `Array` instance, constructed from extracted elements of `this` instance.
2572 */
2573export function slice(self: byte[], start: int, end: int): byte[] {
2574    const len: int = self.length;
2575    const relStart = normalizeIndex(start, len)
2576    const relEnd = normalizeIndex(end, len)
2577
2578    let count = relEnd - relStart;
2579    if (count < 0) {
2580        count = 0;
2581    }
2582    let res = new byte[count]
2583    for (let i = 0; i < count; i++) {
2584        res[i] = self[relStart + i];
2585    }
2586
2587    return res
2588}
2589
2590/**
2591 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
2592 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
2593 *
2594 * @param start zero-based index at which to start extraction
2595 *
2596 * @returns `Array` instance, constructed from extracted elements of `this` instance.
2597 */
2598export function slice(self: byte[], start: int): byte[] {
2599    return slice(self, start, Int.MAX_VALUE as int);
2600}
2601
2602/**
2603 * Returns the last index at which a given element can be found in the array,
2604 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
2605 *
2606 * @param element element to locate in the array.
2607 * @param fromIndex zero-based index at which to start searching backwards.
2608 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
2609 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
2610 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
2611 *
2612 * @returns The last index of the element in the array; -1 if not found.
2613 */
2614export function lastIndexOf(self: byte[], element: byte, fromIndex: int): int {
2615    if (self.length == 0) {
2616        return -1;
2617    }
2618    let n = fromIndex;
2619    let k: int;
2620    if (n >= 0) {
2621        k = min(self.length - 1, n);
2622    } else {
2623        k = self.length + n;
2624    }
2625
2626    while (k >= 0) {
2627        if (__runtimeEquals(self[k], element)) {
2628            return k;
2629        }
2630        k--;
2631    }
2632    return -1;
2633}
2634
2635/**
2636 * Returns the last index at which a given element can be found in the array,
2637 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
2638 *
2639 * @param element element to locate in the array.
2640 * @param fromIndex zero-based index at which to start searching backwards.
2641 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
2642 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
2643 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
2644 *
2645 * @returns The last index of the element in the array; -1 if not found.
2646 */
2647export function lastIndexOf(self: byte[], element: byte, fromIndex?: Number): number {
2648    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
2649}
2650
2651/**
2652 * Creates and returns a new string by concatenating all of the elements in an `Array`,
2653 * separated by a specified separator string.
2654 * If the array has only one item, then that item will be returned without using the separator.
2655 *
2656 * @param sep specifies a separator
2657 *
2658 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
2659 */
2660export function join(self: byte[], sep?: String): string {
2661    if (self.length == 0) {
2662        return ""
2663    }
2664    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
2665    let sb = new StringBuilder(new String(self[0]))
2666    for (let i: int = 1; i < self.length; i++) {
2667        const tmp = self[i]
2668        sb.append(sepReal);
2669        sb.append(tmp)
2670    }
2671
2672    return sb.toString();
2673}
2674
2675/**
2676 * Returns a string representing the specified array and its elements.
2677 *
2678 * @returns string representation
2679 */
2680export function toString(self: byte[], ): string {
2681    return join(self, ",");
2682}
2683
2684/**
2685 * Returns a locale string representing the specified array and its elements.
2686 *
2687 * @param locales
2688 *
2689 * @param options
2690 *
2691 * @returns string representation
2692 */
2693export function toLocaleString(self: byte[], locales: Object, options: Object): string {
2694    throw new Error("Array.toLocaleString: not implemented")
2695}
2696
2697/**
2698 * Returns a locale string representing the specified array and its elements.
2699 *
2700 * @param options
2701 *
2702 * @returns string representation
2703 */
2704export function toLocaleString(self: byte[], locales: Object): string {
2705    return toLocaleString(self, new Object(), new Object())
2706}
2707
2708/**
2709 * Returns a locale string representing the specified array and its elements.
2710 *
2711 * @returns string representation
2712 */
2713export function toLocaleString(self: byte[], ): string {
2714    const sb = new StringBuilder()
2715    const len = self.length;
2716    for (let i = 0; i < len; i++) {
2717        if (i != 0) {
2718            sb.append(",")
2719        }
2720        let x = self[i] as NullishType;
2721        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
2722            sb.append(x!.toLocaleString())
2723        }
2724    }
2725    return sb.toString()
2726}
2727
2728/**
2729 * Copying version of the splice() method.
2730 *
2731 * @param start index
2732 *
2733 * @param delete number of items after start index
2734 *
2735 * @returns a new Array with some elements removed and/or replaced at a given index.
2736 */
2737export function toSpliced(self: byte[], start?: Number, delete?: Number): byte[] {
2738    const len = self.length;
2739    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
2740}
2741
2742/**
2743 * Copying version of the splice() method.
2744 *
2745 * @param start index
2746 *
2747 * @param delete number of items after start index
2748 *
2749 * @returns a new Array with some elements removed and/or replaced at a given index.
2750 */
2751export function toSpliced(self: byte[], start: number, delete: number, ...items: byte[]): byte[] {
2752    const len = self.length;
2753    return toSpliced(self, start as int, delete as int, ...items)
2754}
2755
2756/**
2757 * Copying version of the splice() method.
2758 *
2759 * @param start index
2760 *
2761 * @param delete number of items after start index
2762 *
2763 * @returns a new Array with some elements removed and/or replaced at a given index.
2764 */
2765export function toSpliced(self: byte[], start: int, delete: int, ...items: byte[]): byte[] {
2766    const len = self.length;
2767    start = normalizeIndex(start, len);
2768    if (delete < 0) {
2769        delete = 0;
2770    } else if (delete > len) {
2771        delete = len;
2772    }
2773    if (start > len - delete) {
2774        delete = len - start
2775    }
2776    const res = new byte[len - delete + items.length];
2777    for (let i = 0; i < start; i++) {
2778        res[i] = self[i]
2779    }
2780    for (let i = 0; i < items.length; i++) {
2781        res[start + i] = items[i]
2782    }
2783    for (let i = start + delete; i < len; i++) {
2784        res[i - delete + items.length] = self[i]
2785    }
2786    return res;
2787}
2788
2789/**
2790 * Copying version of the splice() method.
2791 *
2792 * @param start index
2793 *
2794 * @returns a new Array with some elements removed and/or replaced at a given index.
2795 */
2796export function toSpliced(self: byte[], start: int): byte[] {
2797    return toSpliced(self, start, self.length)
2798}
2799
2800/**
2801 * Checks whether an Array includes a certain value among its entries,
2802 * returning true or false as appropriate.
2803 *
2804 * @param val value to search
2805 *
2806 * @param fromIndex start index
2807 *
2808 * @returns true if val is in Array
2809 */
2810export function includes(self: byte[], val: byte, fromIndex?: Number): boolean {
2811    const len = self.length;
2812    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
2813    for (let i = fi; i < len; i++) {
2814        if (val == self[i]) {
2815            return true;
2816        }
2817    }
2818    return false;
2819}
2820
2821/**
2822 * Returns the first index at which a given element
2823 * can be found in the array, or -1 if it is not present.
2824 *
2825 * @param val value to search
2826 *
2827 * @param fromIndex index to search from
2828 *
2829 * @returns index of val, -1 otherwise
2830 */
2831export function indexOf(self: byte[], val: byte, fromIndex: int): int {
2832    fromIndex = normalizeIndex(fromIndex, self.length)
2833    for (let i = fromIndex; i < self.length; i++) {
2834        if (__runtimeEquals(val, self[i])) {
2835            return i
2836        }
2837    }
2838    return -1
2839}
2840
2841/**
2842 * Returns the first index at which a given element
2843 * can be found in the array, or -1 if it is not present.
2844 *
2845 * @param val value to search
2846 *
2847 * @param fromIndex index to search from
2848 *
2849 * @returns index of val, -1 otherwise
2850 */
2851export function indexOf(self: byte[], val: byte, fromIndex?: Number): number {
2852    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
2853}
2854
2855/**
2856 * Copying version of the sort() method.
2857 * It returns a new array with the elements sorted in ascending order.
2858 *
2859 * @returns sorted copy of hte current instance using default comparator
2860 */
2861export function toSorted(self: byte[], ): byte[] {
2862    let arr = cloneArray(self);
2863    sort(arr, )
2864    return arr
2865}
2866
2867/**
2868 * Copying version of the sort() method.
2869 * It returns a new array with the elements sorted in ascending order.
2870 *
2871 * @param comparator function to compare to elements of the Array
2872 *
2873 * @returns sorted copy of the current instance comparator
2874 */
2875export function toSorted(self: byte[], comparator: (a: byte, b: byte) => number): byte[] {
2876    let arr = cloneArray(self);
2877    sort(arr, comparator)
2878    return arr
2879}
2880
2881/**
2882 * Modifies `this` instance of `Array` class and populates
2883 * it with same elements ordered towards the direction opposite to that previously stated.
2884 *
2885 * @note Mutating method
2886 */
2887export function reverse(self: byte[], ): byte[] {
2888    for (let i = 0; i < self.length / 2; i++) {
2889        const tmp = self[i];
2890        const idx_r = self.length - 1 - i;
2891        const val_r = self[idx_r];
2892        self[i] = val_r;
2893        self[idx_r] = tmp;
2894    }
2895    return self;
2896}
2897
2898/**
2899 * Copying version of the reverse() method.
2900 * It returns a new array with the elements in reversed order.
2901 *
2902 * @returns reversed copy of the current Array
2903 */
2904export function toReversed(self: byte[], ): byte[] {
2905    let arr = new byte[self.length]
2906    for (let i = 0; i < self.length; i++) {
2907        arr[self.length - 1 - i] = self[i]
2908    }
2909    return arr
2910}
2911
2912/**
2913 * Copying version of using the bracket notation to change the value of a given index.
2914 * It returns a new Array with the element at the given index replaced with the given value.
2915 *
2916 * @param index to replace
2917 *
2918 * @param value new value
2919 *
2920 * @returns a new Array with the element at the given index replaced with the given value
2921 */
2922export function with(self: byte[], index: number, value: byte): byte[] {
2923    return with(self, index as int, value)
2924}
2925
2926/**
2927 * Copying version of using the bracket notation to change the value of a given index.
2928 * It returns a new Array with the element at the given index replaced with the given value.
2929 *
2930 * @param index to replace
2931 *
2932 * @param value new value
2933 *
2934 * @returns a new Array with the element at the given index replaced with the given value
2935 */
2936export function with(self: byte[], index: int, value: byte): byte[] {
2937    if (index < 0) {
2938        index += self.length;
2939    }
2940    if (index >= self.length) {
2941        throw new RangeError("Invalid index")
2942    }
2943    let arr = cloneArray(self);
2944    arr[index] = value;
2945    return arr
2946}
2947
2948/**
2949 * Returns an iterator over all values
2950 */
2951export function values(self: byte[], ): IterableIterator<byte> {
2952    return new ArrayValuesIterator_byte(self);
2953}
2954
2955/**
2956 * Returns an iterable of key, value pairs for every entry in the array
2957 */
2958export function entries(self: byte[], ): IterableIterator<[number, byte]> {
2959    return new ArrayEntriesIterator_byte(self);
2960}
2961
2962/**
2963 * Determines whether all the members of an array satisfy the specified test.
2964 *
2965 * @param predicate A function that accepts up to three arguments. The every method calls
2966 * the predicate function for each element in the array until the predicate returns a value
2967 * which is coercible to the Boolean value false, or until the end of the array.
2968 *
2969 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2970 */
2971export function every(self: byte[], predicate: () => boolean): boolean {
2972    for (let i = 0; i < self.length; i++) {
2973        if (!predicate()) {
2974            return false
2975        }
2976    }
2977    return true
2978}
2979
2980/**
2981 * Returns the elements of an array that meet the condition specified in a callback function.
2982 *
2983 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
2984 *
2985 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
2986 */
2987export function filter(self: byte[], predicate: () => boolean): byte[] {
2988    return filter(self, (value: byte, index: number): boolean => predicate());
2989}
2990
2991/**
2992 * Returns the value of the first element in the array where predicate is true, and undefined
2993 * otherwise.
2994 *
2995 * @param predicate find calls predicate once for each element of the array, in ascending
2996 * order, until it finds one where predicate returns true. If such an element is found, find
2997 * immediately returns that element value. Otherwise, find returns undefined.
2998 *
2999 * @returns the value of the first element in the array or undefined
3000 */
3001export function find(self: byte[], predicate: () => boolean): Byte | undefined {
3002    const res = findIndex(self, predicate)
3003    if (res == -1) {
3004        return undefined
3005    }
3006    return self[res as int];
3007}
3008
3009/**
3010 * Returns the index of the first element in the array where predicate is true, and -1
3011 * otherwise.
3012 *
3013 * @param predicate find calls predicate once for each element of the array, in ascending
3014 * order, until it finds one where predicate returns true. If such an element is found,
3015 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
3016 *
3017 * @returns found element index or -1 otherwise
3018 */
3019export function findIndex(self: byte[], predicate: () => boolean): number {
3020    for (let i = 0; i < self.length; i++) {
3021        if (predicate()) {
3022            return i;
3023        }
3024    }
3025    return -1;
3026}
3027
3028/**
3029 * Performs the specified action for each element in an array.
3030 *
3031 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
3032 */
3033export function forEach(self: byte[], callbackfn: () => void): void {
3034    const len0 = self.length;
3035    for (let i = 0; i < len0; i++) {
3036        callbackfn()
3037    }
3038}
3039
3040/**
3041 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3042 *
3043 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3044 *
3045 * @returns a result after applying callbackfn over all elements of the Array
3046 */
3047export function reduce(self: byte[], callbackfn: (previousValue: byte) => byte): byte {
3048    if (self.length == 0) {
3049        throw new TypeError("Reduce of empty array with no initial value")
3050    }
3051    let acc: byte = self[0];
3052    for (let i = 1; i < self.length; i++) {
3053        acc = callbackfn(acc)
3054    }
3055    return acc
3056}
3057
3058/**
3059 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3060 *
3061 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3062 *
3063 * @returns a result after applying callbackfn over all elements of the Array
3064 */
3065export function reduce(self: byte[], callbackfn: () => byte): byte {
3066    if (self.length == 0) {
3067        throw new TypeError("Reduce of empty array with no initial value")
3068    }
3069    let acc: byte = self[0];
3070    for (let i = 1; i < self.length; i++) {
3071        acc = callbackfn()
3072    }
3073    return acc
3074}
3075
3076/**
3077 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3078 *
3079 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3080 *
3081 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
3082 *
3083 * @returns a result after applying callbackfn over all elements of the Array
3084 */
3085export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U) => U, initialValue: U): U {
3086    let acc = initialValue
3087    for (let i = 0; i < self.length; i++) {
3088        acc = callbackfn(acc)
3089    }
3090    return acc
3091}
3092
3093/**
3094 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3095 *
3096 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3097 *
3098 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
3099 *
3100 * @returns a result after applying callbackfn over all elements of the Array
3101 */
3102export function reduce<U = byte>(self: byte[], callbackfn: () => U, initialValue: U): U {
3103    let acc = initialValue
3104    for (let i = 0; i < self.length; i++) {
3105        acc = callbackfn()
3106    }
3107    return acc
3108}
3109
3110/**
3111 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3112 *
3113 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
3114 *
3115 * @returns a result after applying callbackfn over all elements of the Array
3116 */
3117export function reduceRight(self: byte[], callbackfn: (previousValue: byte) => byte): byte {
3118    if (self.length == 0) {
3119        throw new TypeError("Reduce of empty array with no initial value")
3120    }
3121    let acc: byte = self[self.length - 1];
3122    for (let i = self.length - 2; i >= 0; i--) {
3123        acc = callbackfn(acc)
3124    }
3125    return acc
3126}
3127
3128/**
3129 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3130 *
3131 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
3132 *
3133 * @returns a result after applying callbackfn over all elements of the Array
3134 */
3135export function reduceRight(self: byte[], callbackfn: () => byte): byte {
3136    if (self.length == 0) {
3137        throw new TypeError("Reduce of empty array with no initial value")
3138    }
3139    let acc: byte = self[self.length - 1];
3140    for (let i = self.length - 2; i >= 0; i--) {
3141        acc = callbackfn()
3142    }
3143    return acc
3144}
3145
3146/**
3147 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3148 *
3149 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
3150 *
3151 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
3152 *
3153 * @returns a result after applying callbackfn over all elements of the Array
3154 */
3155export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U) => U, initialValue: U): U {
3156    let acc = initialValue
3157    for (let i = self.length - 1; i >= 0; i--) {
3158        acc = callbackfn(acc)
3159    }
3160    return acc
3161}
3162
3163/**
3164 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3165 *
3166 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
3167 *
3168 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
3169 *
3170 * @returns a result after applying callbackfn over all elements of the Array
3171 */
3172export function reduceRight<U>(self: byte[], callbackfn: () => U, initialValue: U): U {
3173    let acc = initialValue
3174    for (let i = self.length - 1; i >= 0; i--) {
3175        acc = callbackfn()
3176    }
3177    return acc
3178}
3179
3180/**
3181 * Determines whether the specified callback function returns true for any element of an array.
3182 *
3183 * @param predicate A function that accepts up to three arguments. The some method calls
3184 * the predicate function for each element in the array until the predicate returns a value
3185 * which is coercible to the Boolean value true, or until the end of the array.
3186 *
3187 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
3188 */
3189export function some(self: byte[], predicate: () => boolean): boolean {
3190    for (let i = 0; i < self.length; i++) {
3191        if (predicate()) {
3192            return true
3193        }
3194    }
3195    return false
3196}
3197
3198/**
3199 * Iterates the array in reverse order and returns the value of the first element
3200 * that satisfies the provided testing function
3201 *
3202 * @param predicate testing function
3203 *
3204 * @returns found element or undefined otherwise
3205 */
3206export function findLast(self: byte[], predicate: () => boolean): Byte | undefined {
3207    for (let i = self.length - 1; i >= 0; i--) {
3208        const val = self[i];
3209        if (predicate()) {
3210            return val;
3211        }
3212    }
3213    return undefined;
3214}
3215
3216/**
3217 * Iterates the array in reverse order and returns the index of
3218 * the first element that satisfies the provided testing function.
3219 * If no elements satisfy the testing function, -1 is returned.
3220 *
3221 * @param predicate testing function
3222 *
3223 * @returns index of first element satisfying to predicate, -1 if no such element
3224 */
3225export function findLastIndex(self: byte[], predicate: () => boolean): number {
3226    for (let i = self.length - 1; i >= 0; i--) {
3227        if (predicate()) {
3228            return i
3229        }
3230    }
3231    return -1
3232}
3233
3234/**
3235 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3236 *
3237 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
3238 *
3239 * @returns `Array` instance, constructed from `this` and given function.
3240 */
3241export function map(self: byte[], callbackfn: (value: byte, index: number, array: byte[]) => byte): byte[] {
3242    const len = self.length;
3243    let res = new byte[len];
3244    for (let i = 0; i < len; i++) {
3245        res[i] = callbackfn(self[i], i as number, self);
3246    }
3247    return res;
3248}
3249
3250/**
3251 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3252 *
3253 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
3254 *
3255 * @returns `Array` instance, constructed from `this` and given function.
3256 */
3257export function map(self: byte[], callbackfn: (value: byte, index: number) => byte): byte[] {
3258    const len = self.length;
3259    let res = new byte[len];
3260    for (let i = 0; i < len; i++) {
3261        res[i] = callbackfn(self[i], i as number);
3262    }
3263    return res;
3264}
3265
3266/**
3267 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3268 *
3269 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
3270 *
3271 * @returns `Array` instance, constructed from `this` and given function.
3272 */
3273export function map(self: byte[], callbackfn: (value: byte) => byte): byte[] {
3274    const len = self.length;
3275    let res = new byte[len];
3276    for (let i = 0; i < len; i++) {
3277        res[i] = callbackfn(self[i]);
3278    }
3279    return res;
3280}
3281
3282/**
3283 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3284 *
3285 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
3286 *
3287 * @returns `Array` instance, constructed from `this` and given function.
3288 */
3289export function map(self: byte[], callbackfn: () => byte): byte[] {
3290    const len = self.length;
3291    let res = new byte[len];
3292    for (let i = 0; i < len; i++) {
3293        res[i] = callbackfn();
3294    }
3295    return res;
3296}
3297
3298/**
3299 * Constructs a new `Array` instance and populates it with
3300 * portion of a given array, filtered down to just the elements from the
3301 * given array that pass the test implemented by the provided function.
3302 *
3303 * @param fn test function, applied to each element of an array.
3304 *
3305 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
3306 */
3307export function filter(self: byte[], fn: (v: byte, k: number) => boolean): byte[] {
3308    const mask = new boolean[self.length]
3309    let cnt = 0
3310
3311    for (let i: int = 0; i < self.length; i++) {
3312        const val = self[i];
3313        if (fn(val, i)) {
3314            mask[i] = true
3315            cnt++;
3316        }
3317    }
3318    const res = new byte[cnt];
3319    let idx_store = 0;
3320    for (let i: int = 0; i < self.length; i++) {
3321        if (mask[i]) {
3322            res[idx_store++] = self[i]
3323        }
3324    }
3325    return res;
3326}
3327
3328export function concat(self: byte[], fst: byte[], ...more: byte[][]): byte[] {
3329    const lnMin = self.length + fst.length;
3330    let ln = lnMin;
3331    for (let i = 0; i < more.length; i++) {
3332        ln += more[i].length
3333    }
3334    const r = new byte[ln];
3335    try {
3336        copyTo(self, r, 0, 0, self.length);
3337        copyTo(fst, r, self.length, 0, fst.length);
3338        let idx = lnMin;
3339        for (let i = 0; i < more.length; i++) {
3340            copyTo(more[i], r, idx, 0, more[i].length);
3341            idx += more[i].length;
3342        }
3343    } catch (e) {
3344        // impossible
3345    }
3346    return r
3347}
3348
3349/**
3350 * Reorders elements of `this` using comparator function.
3351 *
3352 * @param comparator function that defines the sort order.
3353 *
3354 * @note Mutating method
3355 */
3356export function sort(self: byte[], comparator: (a: byte, b: byte) => number): byte[] {
3357    sort_subarray(self, 0, self.length, (l: byte, r: byte): boolean => {
3358        return comparator(l, r ) < 0;
3359    });
3360    return self;
3361}
3362
3363/**
3364 * Reorders elements of `this` using comparator function.
3365 *
3366 * @param comparator function that defines the sort order.
3367 *
3368 * @note Mutating method
3369 */
3370export function sort(self: byte[], ): byte[] {
3371    sort(self, 0, self.length);
3372    return self;
3373}
3374
3375export function keys(self: byte[]): IterableIterator<number> {
3376    return new BuiltinArrayKeysIterator(self.length);
3377}
3378
3379class ArrayValuesIterator_byte implements IterableIterator<byte> {
3380    private parent: byte[]
3381    private idx: int = 0
3382
3383    constructor(parent: byte[]) {
3384        this.parent = parent
3385    }
3386
3387    override next(): IteratorResult<byte> {
3388        if (this.idx >= this.parent.length) {
3389            return new IteratorResult<byte>()
3390        }
3391        return new IteratorResult<byte>(this.parent[this.idx++])
3392    }
3393
3394    override $_iterator(): IterableIterator<byte> {
3395        return this;
3396    }
3397
3398    public __Iterator_getLength(): int {
3399        return this.parent.length as int
3400    }
3401}
3402
3403class ArrayEntriesIterator_byte implements IterableIterator<[number, byte]> {
3404    private parent: byte[]
3405    private idx: int = 0
3406
3407    constructor(parent: byte[]) {
3408        this.parent = parent
3409    }
3410
3411    override next(): IteratorResult<[number, byte]> {
3412        if (this.idx >= this.parent.length) {
3413            return new IteratorResult<[number, byte]>()
3414        }
3415        const i = this.idx++;
3416        const vl: [number, byte] = [i as number, this.parent[i]]
3417        return new IteratorResult<[number, byte]>(vl);
3418    }
3419
3420    override $_iterator(): IterableIterator<[number, byte]> {
3421        return this;
3422    }
3423
3424    public __Iterator_getLength(): int {
3425        return this.parent.length as int
3426    }
3427}
3428
3429function cloneArray(self: short[]): short[] {
3430    const ret = new short[self.length];;
3431    for (let i = 0; i < self.length; i++) {
3432        ret[i] = self[i];
3433    }
3434    return ret;
3435}
3436
3437/**
3438 * Takes an integer value and returns the item at that index,
3439 * allowing for positive and negative integers. Negative integers count back
3440 * from the last item in the array.
3441 *
3442 * @param index Zero-based index of the array element to be returned.
3443 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
3444 *
3445 * @returns The element in the array matching the given index.
3446 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
3447 */
3448export function at(self: short[], index: number): Short | undefined {
3449    return at(self, index as int)
3450}
3451
3452/**
3453 * Creates a new `Array` from this `Array` instance and given `Array` instance.
3454 *
3455 * @param other to concatenate into a new array.
3456 *
3457 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
3458 */
3459// export function concat(self: short[], ...items: (short | Concatshort[])[]): short[] {
3460//     throw new Error("not implemented")
3461// }
3462
3463export function concat(self: short[], ...items: ConcatArray<short>[]): short[] {
3464    let totalAdd = self.length;
3465    for (let i = 0; i < items.length; i++) {
3466        totalAdd += items[i].length as int
3467    }
3468
3469    const buf = new short[totalAdd];
3470
3471    for (let i = 0; i < self.length; i++) {
3472        buf[i] = self[i];
3473    }
3474
3475    let insertTo = self.length;
3476    for (let i = 0; i < items.length; i++) {
3477        const arr = items[i]
3478        const len = arr.length as int
3479        for (let j = 0; j < len; j++) {
3480            buf[insertTo++] = arr.$_get(j)
3481        }
3482    }
3483
3484    return buf;
3485}
3486
3487/**
3488 * Takes an integer value and returns the item at that index,
3489 * allowing for positive and negative integers. Negative integers count back
3490 * from the last item in the array.
3491 *
3492 * @param index Zero-based index of the array element to be returned.
3493 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
3494 *
3495 * @returns The element in the array matching the given index.
3496 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
3497 */
3498export function at(self: short[], index: int): Short | undefined {
3499    let len = self.length;
3500    let k: int;
3501    if (index >= 0) {
3502        k = index;
3503    } else {
3504        k = len + index;
3505    }
3506
3507    if (k < 0 || k >= len) {
3508        return undefined;
3509    }
3510
3511    return self[k];
3512}
3513
3514/**
3515 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
3516 *
3517 * @param target index at which to copy the sequence
3518 *
3519 * @param start index at which to start copying elements from
3520 *
3521 * @param end index at which to end copying elements from
3522 *
3523 * @returns this array after transformation
3524 */
3525export function copyWithin(self: short[], target: number, start: number, end?: Number): short[] {
3526    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
3527    return self;
3528}
3529
3530/**
3531 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
3532 *
3533 * @param target index at which to copy the sequence
3534 *
3535 * @param start index at which to start copying elements from
3536 *
3537 * @param end index at which to end copying elements from
3538 *
3539 * @returns this array after transformation
3540 */
3541export function copyWithin(self: short[], target: int, start: int, end: int): short[] {
3542    target = normalizeIndex(target, self.length)
3543    start = normalizeIndex(start, self.length)
3544    end = normalizeIndex(end, self.length)
3545
3546    if (end <= start) {
3547        return self;
3548    }
3549
3550    if (target <= start) {
3551        while (start < end) {
3552            const read = self[start++];
3553            self[target++] = read;
3554        }
3555    } else {
3556        let len = end - start;
3557        if (target + len > self.length) {
3558            len = self.length - target
3559        }
3560        for (let i = 0; i < len; i++) {
3561            const read = self[start + len - 1 - i];
3562            self[target + len - 1 - i] = read;
3563        }
3564    }
3565
3566    return self;
3567}
3568
3569/**
3570 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
3571 *
3572 * @param target index at which to copy the sequence
3573 *
3574 * @param start index at which to start copying elements from
3575 *
3576 * @returns this array after transformation
3577 */
3578export function copyWithin(self: short[], target: int, start: int): short[] {
3579    copyWithin(self, target, start, self.length);
3580    return self;
3581}
3582
3583/**
3584 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
3585 *
3586 * @param target index at which to copy the sequence
3587 *
3588 * @returns this array after transformation
3589 */
3590export function copyWithin(self: short[], target: int): short[] {
3591    copyWithin(self, target, 0, self.length);
3592    return self;
3593}
3594
3595/**
3596 * Changes all elements in the Array to a static value, from a start index to an end index
3597 *
3598 * @param value to fill the array with
3599 *
3600 * @param start index at which to start filling
3601 *
3602 * @param end index at which to end filling, but not including
3603 *
3604 * @returns this array after transformation
3605 */
3606export function fill(self: short[], value: short, start?: Number, end?: Number): short[] {
3607    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
3608    return self;
3609}
3610
3611/**
3612 * Changes all elements in the Array to a static value, from a start index to an end index
3613 *
3614 * @param value to fill the array with
3615 *
3616 * @param start index at which to start filling
3617 *
3618 * @param end index at which to end filling, but not including
3619 *
3620 * @returns this array after transformation
3621 */
3622export function fill(self: short[], value: short, start: int, end: int): short[] {
3623    start = normalizeIndex(start, self.length);
3624    end = normalizeIndex(end, self.length)
3625
3626    for (let i = start; i < end; i++) {
3627        self[i] = value;
3628    }
3629
3630    return self;
3631}
3632
3633/**
3634 * Returns the value of the first element in the array where predicate is true, and undefined
3635 * otherwise.
3636 *
3637 * @param predicate find calls predicate once for each element of the array, in ascending
3638 * order, until it finds one where predicate returns true. If such an element is found, find
3639 * immediately returns that element value. Otherwise, find returns undefined.
3640 *
3641 * @returns the value of the first element in the array or undefined
3642 */
3643export function find(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): Short | undefined {
3644    const res = findIndex(self, predicate)
3645    if (res == -1) {
3646        return undefined
3647    }
3648    return self[res as int];
3649}
3650
3651/**
3652 * Returns the index of the first element in the array where predicate is true, and -1
3653 * otherwise.
3654 *
3655 * @param predicate find calls predicate once for each element of the array, in ascending
3656 * order, until it finds one where predicate returns true. If such an element is found,
3657 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
3658 *
3659 * @returns found element index or -1 otherwise
3660 */
3661export function findIndex(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): number {
3662    for (let i = 0; i < self.length; i++) {
3663        if (predicate(self[i], i as number, self)) {
3664            return i;
3665        }
3666    }
3667    return -1;
3668}
3669
3670/**
3671 * Iterates the array in reverse order and returns the value of the first element
3672 * that satisfies the provided testing function
3673 *
3674 * @param predicate testing function
3675 *
3676 * @returns found element or undefined otherwise
3677 */
3678export function findLast(self: short[], predicate: (elem: short, index: number, array: short[]) => boolean): Short | undefined {
3679    for (let i = self.length - 1; i >= 0; i--) {
3680        const val = self[i];
3681        if (predicate(val, i as number, self)) {
3682            return val;
3683        }
3684    }
3685    return undefined;
3686}
3687
3688/**
3689 * Determines whether all the members of an array satisfy the specified test.
3690 *
3691 * @param predicate A function that accepts up to three arguments. The every method calls
3692 * the predicate function for each element in the array until the predicate returns a value
3693 * which is coercible to the Boolean value false, or until the end of the array.
3694 *
3695 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
3696 */
3697export function every(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): boolean {
3698    for (let i = 0; i < self.length; i++) {
3699        if (!predicate(self[i], i as number, self)) {
3700            return false
3701        }
3702    }
3703    return true;
3704}
3705
3706/**
3707 * Determines whether the specified callback function returns true for any element of an array.
3708 *
3709 * @param predicate A function that accepts up to three arguments. The some method calls
3710 * the predicate function for each element in the array until the predicate returns a value
3711 * which is coercible to the Boolean value true, or until the end of the array.
3712 *
3713 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
3714 */
3715export function some(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): boolean {
3716    for (let i = 0; i < self.length; i++) {
3717        if (predicate(self[i], i as number, self)) {
3718            return true
3719        }
3720    }
3721    return false
3722}
3723
3724/**
3725 * Returns the elements of an array that meet the condition specified in a callback function.
3726 *
3727 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
3728 *
3729 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
3730 */
3731export function filter(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): short[] {
3732    return filter(self, (value: short, index: number): boolean => predicate(value, index, self));
3733}
3734
3735/**
3736 * Iterates the array in reverse order and returns the index of
3737 * the first element that satisfies the provided testing function.
3738 * If no elements satisfy the testing function, -1 is returned.
3739 *
3740 * @param predicate testing function
3741 *
3742 * @returns index of first element satisfying to predicate, -1 if no such element
3743 */
3744export function findLastIndex(self: short[], predicate: (element: short, index: number, array: short[]) => boolean): number {
3745    for (let i = self.length - 1; i >= 0; i--) {
3746        if (predicate(self[i], i as number, self)) {
3747            return i
3748        }
3749    }
3750    return -1
3751}
3752
3753/**
3754 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3755 *
3756 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3757 *
3758 * @returns a result after applying callbackfn over all elements of the Array
3759 */
3760export function reduce(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number, array: short[]) => short): short {
3761    if (self.length == 0) {
3762        throw new TypeError("Reduce of empty array with no initial value")
3763    }
3764    let acc: short = self[0];
3765    for (let i = 1; i < self.length; i++) {
3766        acc = callbackfn(acc, self[i], i as number, self)
3767    }
3768    return acc
3769}
3770
3771/**
3772 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3773 *
3774 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3775 *
3776 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
3777 *
3778 * @returns a result after applying callbackfn over all elements of the Array
3779 */
3780export function reduce<U = short>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number, array: short[]) => U, initialValue: U): U {
3781    let acc = initialValue
3782    for (let i = 0; i < self.length; i++) {
3783        acc = callbackfn(acc, self[i], i as number, self)
3784    }
3785    return acc
3786}
3787
3788/**
3789 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3790 *
3791 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
3792 *
3793 * @returns a result after applying callbackfn over all elements of the Array
3794 */
3795export function reduceRight(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number, array: short[]) => short): short {
3796    if (self.length == 0) {
3797        throw new TypeError("Reduce of empty array with no initial value")
3798    }
3799    let acc: short = self[self.length - 1];
3800    for (let i = self.length - 2; i >= 0; i--) {
3801        acc = callbackfn(acc, self[i], i as number, self)
3802    }
3803    return acc
3804}
3805
3806/**
3807 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3808 *
3809 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
3810 *
3811 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
3812 *
3813 * @returns a result after applying callbackfn over all elements of the Array
3814 */
3815export function reduceRight<U>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number, array: short[]) => U, initialValue: U): U {
3816    let acc = initialValue
3817    for (let i = self.length - 1; i >= 0; i--) {
3818        acc = callbackfn(acc, self[i], i as number, self)
3819    }
3820    return acc
3821}
3822
3823/**
3824 * Performs the specified action for each element in an array.
3825 *
3826 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
3827 */
3828export function forEach(self: short[], callbackfn: (value: short, index: number, array: short[]) => void): void {
3829    const len0 = self.length;
3830    for (let i = 0; i < len0; i++) {
3831        callbackfn(self[i], i as number, self)
3832    }
3833}
3834
3835/**
3836 * Returns the value of the first element in the array where predicate is true, and undefined
3837 * otherwise.
3838 *
3839 * @param predicate find calls predicate once for each element of the array, in ascending
3840 * order, until it finds one where predicate returns true. If such an element is found, find
3841 * immediately returns that element value. Otherwise, find returns undefined.
3842 *
3843 * @returns the value of the first element in the array or undefined
3844 */
3845export function find(self: short[], predicate: (value: short, index: number) => boolean): Short | undefined {
3846    const res = findIndex(self, predicate)
3847    if (res == -1) {
3848        return undefined
3849    }
3850    return self[res as int];
3851}
3852
3853/**
3854 * Returns the index of the first element in the array where predicate is true, and -1
3855 * otherwise.
3856 *
3857 * @param predicate find calls predicate once for each element of the array, in ascending
3858 * order, until it finds one where predicate returns true. If such an element is found,
3859 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
3860 *
3861 * @returns found element index or -1 otherwise
3862 */
3863export function findIndex(self: short[], predicate: (value: short, index: number) => boolean): number {
3864    for (let i = 0; i < self.length; i++) {
3865        if (predicate(self[i], i as number)) {
3866            return i;
3867        }
3868    }
3869    return -1;
3870}
3871
3872/**
3873 * Iterates the array in reverse order and returns the value of the first element
3874 * that satisfies the provided testing function
3875 *
3876 * @param predicate testing function
3877 *
3878 * @returns found element or undefined otherwise
3879 */
3880export function findLast(self: short[], predicate: (elem: short, index: number) => boolean): Short | undefined {
3881    for (let i = self.length - 1; i >= 0; i--) {
3882        const val = self[i];
3883        if (predicate(val, i as number)) {
3884            return val;
3885        }
3886    }
3887    return undefined;
3888}
3889
3890/**
3891 * Determines whether all the members of an array satisfy the specified test.
3892 *
3893 * @param predicate A function that accepts up to three arguments. The every method calls
3894 * the predicate function for each element in the array until the predicate returns a value
3895 * which is coercible to the Boolean value false, or until the end of the array.
3896 *
3897 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
3898 */
3899export function every(self: short[], predicate: (value: short, index: number) => boolean): boolean {
3900    for (let i = 0; i < self.length; i++) {
3901        if (!predicate(self[i], i as number)) {
3902            return false
3903        }
3904    }
3905    return true;
3906}
3907
3908/**
3909 * Determines whether the specified callback function returns true for any element of an array.
3910 *
3911 * @param predicate A function that accepts up to three arguments. The some method calls
3912 * the predicate function for each element in the array until the predicate returns a value
3913 * which is coercible to the Boolean value true, or until the end of the array.
3914 *
3915 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
3916 */
3917export function some(self: short[], predicate: (value: short, index: number) => boolean): boolean {
3918    for (let i = 0; i < self.length; i++) {
3919        if (predicate(self[i], i as number)) {
3920            return true
3921        }
3922    }
3923    return false
3924}
3925
3926/**
3927 * Iterates the array in reverse order and returns the index of
3928 * the first element that satisfies the provided testing function.
3929 * If no elements satisfy the testing function, -1 is returned.
3930 *
3931 * @param predicate testing function
3932 *
3933 * @returns index of first element satisfying to predicate, -1 if no such element
3934 */
3935export function findLastIndex(self: short[], predicate: (element: short, index: number) => boolean): number {
3936    for (let i = self.length - 1; i >= 0; i--) {
3937        if (predicate(self[i], i as number)) {
3938            return i
3939        }
3940    }
3941    return -1
3942}
3943
3944/**
3945 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3946 *
3947 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3948 *
3949 * @returns a result after applying callbackfn over all elements of the Array
3950 */
3951export function reduce(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number) => short): short {
3952    if (self.length == 0) {
3953        throw new TypeError("Reduce of empty array with no initial value")
3954    }
3955    let acc: short = self[0];
3956    for (let i = 1; i < self.length; i++) {
3957        acc = callbackfn(acc, self[i], i as number)
3958    }
3959    return acc
3960}
3961
3962/**
3963 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3964 *
3965 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
3966 *
3967 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
3968 *
3969 * @returns a result after applying callbackfn over all elements of the Array
3970 */
3971export function reduce<U = short>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number) => U, initialValue: U): U {
3972    let acc = initialValue
3973    for (let i = 0; i < self.length; i++) {
3974        acc = callbackfn(acc, self[i], i as number)
3975    }
3976    return acc
3977}
3978
3979/**
3980 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3981 *
3982 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
3983 *
3984 * @returns a result after applying callbackfn over all elements of the Array
3985 */
3986export function reduceRight(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number) => short): short {
3987    if (self.length == 0) {
3988        throw new TypeError("Reduce of empty array with no initial value")
3989    }
3990    let acc: short = self[self.length - 1];
3991    for (let i = self.length - 2; i >= 0; i--) {
3992        acc = callbackfn(acc, self[i], i as number)
3993    }
3994    return acc
3995}
3996
3997/**
3998 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
3999 *
4000 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
4001 *
4002 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
4003 *
4004 * @returns a result after applying callbackfn over all elements of the Array
4005 */
4006export function reduceRight<U>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number) => U, initialValue: U): U {
4007    let acc = initialValue
4008    for (let i = self.length - 1; i >= 0; i--) {
4009        acc = callbackfn(acc, self[i], i as number)
4010    }
4011    return acc
4012}
4013
4014/**
4015 * Performs the specified action for each element in an array.
4016 *
4017 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
4018 */
4019export function forEach(self: short[], callbackfn: (value: short, index: number) => void): void {
4020    const len0 = self.length;
4021    for (let i = 0; i < len0; i++) {
4022        callbackfn(self[i], i as number)
4023    }
4024}
4025
4026/**
4027 * Returns the value of the first element in the array where predicate is true, and undefined
4028 * otherwise.
4029 *
4030 * @param predicate find calls predicate once for each element of the array, in ascending
4031 * order, until it finds one where predicate returns true. If such an element is found, find
4032 * immediately returns that element value. Otherwise, find returns undefined.
4033 *
4034 * @returns the value of the first element in the array or undefined
4035 */
4036export function find(self: short[], predicate: (value: short) => boolean): Short | undefined {
4037    const res = findIndex(self, predicate)
4038    if (res == -1) {
4039        return undefined
4040    }
4041    return self[res as int];
4042}
4043
4044/**
4045 * Returns the index of the first element in the array where predicate is true, and -1
4046 * otherwise.
4047 *
4048 * @param predicate find calls predicate once for each element of the array, in ascending
4049 * order, until it finds one where predicate returns true. If such an element is found,
4050 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
4051 *
4052 * @returns found element index or -1 otherwise
4053 */
4054export function findIndex(self: short[], predicate: (value: short) => boolean): number {
4055    for (let i = 0; i < self.length; i++) {
4056        if (predicate(self[i])) {
4057            return i;
4058        }
4059    }
4060    return -1;
4061}
4062
4063/**
4064 * Iterates the array in reverse order and returns the value of the first element
4065 * that satisfies the provided testing function
4066 *
4067 * @param predicate testing function
4068 *
4069 * @returns found element or undefined otherwise
4070 */
4071export function findLast(self: short[], predicate: (elem: short) => boolean): Short | undefined {
4072    for (let i = self.length - 1; i >= 0; i--) {
4073        const val = self[i];
4074        if (predicate(val)) {
4075            return val;
4076        }
4077    }
4078    return undefined;
4079}
4080
4081/**
4082 * Determines whether all the members of an array satisfy the specified test.
4083 *
4084 * @param predicate A function that accepts up to three arguments. The every method calls
4085 * the predicate function for each element in the array until the predicate returns a value
4086 * which is coercible to the Boolean value false, or until the end of the array.
4087 *
4088 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
4089 */
4090export function every(self: short[], predicate: (value: short) => boolean): boolean {
4091    for (let i = 0; i < self.length; i++) {
4092        if (!predicate(self[i])) {
4093            return false
4094        }
4095    }
4096    return true;
4097}
4098
4099/**
4100 * Determines whether the specified callback function returns true for any element of an array.
4101 *
4102 * @param predicate A function that accepts up to three arguments. The some method calls
4103 * the predicate function for each element in the array until the predicate returns a value
4104 * which is coercible to the Boolean value true, or until the end of the array.
4105 *
4106 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
4107 */
4108export function some(self: short[], predicate: (value: short) => boolean): boolean {
4109    for (let i = 0; i < self.length; i++) {
4110        if (predicate(self[i])) {
4111            return true
4112        }
4113    }
4114    return false
4115}
4116
4117/**
4118 * Returns the elements of an array that meet the condition specified in a callback function.
4119 *
4120 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
4121 *
4122 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
4123 */
4124export function filter(self: short[], predicate: (value: short) => boolean): short[] {
4125    return filter(self, (value: short, index: number): boolean => predicate(value));
4126}
4127
4128/**
4129 * Iterates the array in reverse order and returns the index of
4130 * the first element that satisfies the provided testing function.
4131 * If no elements satisfy the testing function, -1 is returned.
4132 *
4133 * @param predicate testing function
4134 *
4135 * @returns index of first element satisfying to predicate, -1 if no such element
4136 */
4137export function findLastIndex(self: short[], predicate: (element: short) => boolean): number {
4138    for (let i = self.length - 1; i >= 0; i--) {
4139        if (predicate(self[i])) {
4140            return i
4141        }
4142    }
4143    return -1
4144}
4145
4146/**
4147 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4148 *
4149 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
4150 *
4151 * @returns a result after applying callbackfn over all elements of the Array
4152 */
4153export function reduce(self: short[], callbackfn: (previousValue: short, currentValue: short) => short): short {
4154    if (self.length == 0) {
4155        throw new TypeError("Reduce of empty array with no initial value")
4156    }
4157    let acc: short = self[0];
4158    for (let i = 1; i < self.length; i++) {
4159        acc = callbackfn(acc, self[i])
4160    }
4161    return acc
4162}
4163
4164/**
4165 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4166 *
4167 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
4168 *
4169 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
4170 *
4171 * @returns a result after applying callbackfn over all elements of the Array
4172 */
4173export function reduce<U = short>(self: short[], callbackfn: (previousValue: U, currentValue: short) => U, initialValue: U): U {
4174    let acc = initialValue
4175    for (let i = 0; i < self.length; i++) {
4176        acc = callbackfn(acc, self[i])
4177    }
4178    return acc
4179}
4180
4181/**
4182 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4183 *
4184 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
4185 *
4186 * @returns a result after applying callbackfn over all elements of the Array
4187 */
4188export function reduceRight(self: short[], callbackfn: (previousValue: short, currentValue: short) => short): short {
4189    if (self.length == 0) {
4190        throw new TypeError("Reduce of empty array with no initial value")
4191    }
4192    let acc: short = self[self.length - 1];
4193    for (let i = self.length - 2; i >= 0; i--) {
4194        acc = callbackfn(acc, self[i])
4195    }
4196    return acc
4197}
4198
4199/**
4200 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4201 *
4202 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
4203 *
4204 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
4205 *
4206 * @returns a result after applying callbackfn over all elements of the Array
4207 */
4208export function reduceRight<U>(self: short[], callbackfn: (previousValue: U, currentValue: short) => U, initialValue: U): U {
4209    let acc = initialValue
4210    for (let i = self.length - 1; i >= 0; i--) {
4211        acc = callbackfn(acc, self[i])
4212    }
4213    return acc
4214}
4215
4216/**
4217 * Performs the specified action for each element in an array.
4218 *
4219 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
4220 */
4221export function forEach(self: short[], callbackfn: (value: short) => void): void {
4222    const len0 = self.length;
4223    for (let i = 0; i < len0; i++) {
4224        callbackfn(self[i])
4225    }
4226}
4227
4228/**
4229 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
4230 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
4231 *
4232 * @param start zero-based index at which to start extraction
4233 *
4234 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
4235 *
4236 * @returns `Array` instance, constructed from extracted elements of `this` instance.
4237 */
4238export function slice(self: short[], start?: Number, end?: Number): short[] {
4239    const len: int = self.length;
4240    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
4241}
4242
4243/**
4244 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
4245 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
4246 *
4247 * @param start zero-based index at which to start extraction
4248 *
4249 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
4250 *
4251 * @returns `Array` instance, constructed from extracted elements of `this` instance.
4252 */
4253export function slice(self: short[], start: int, end: int): short[] {
4254    const len: int = self.length;
4255    const relStart = normalizeIndex(start, len)
4256    const relEnd = normalizeIndex(end, len)
4257
4258    let count = relEnd - relStart;
4259    if (count < 0) {
4260        count = 0;
4261    }
4262    let res = new short[count]
4263    for (let i = 0; i < count; i++) {
4264        res[i] = self[relStart + i];
4265    }
4266
4267    return res
4268}
4269
4270/**
4271 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
4272 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
4273 *
4274 * @param start zero-based index at which to start extraction
4275 *
4276 * @returns `Array` instance, constructed from extracted elements of `this` instance.
4277 */
4278export function slice(self: short[], start: int): short[] {
4279    return slice(self, start, Int.MAX_VALUE as int);
4280}
4281
4282/**
4283 * Returns the last index at which a given element can be found in the array,
4284 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
4285 *
4286 * @param element element to locate in the array.
4287 * @param fromIndex zero-based index at which to start searching backwards.
4288 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
4289 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
4290 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
4291 *
4292 * @returns The last index of the element in the array; -1 if not found.
4293 */
4294export function lastIndexOf(self: short[], element: short, fromIndex: int): int {
4295    if (self.length == 0) {
4296        return -1;
4297    }
4298    let n = fromIndex;
4299    let k: int;
4300    if (n >= 0) {
4301        k = min(self.length - 1, n);
4302    } else {
4303        k = self.length + n;
4304    }
4305
4306    while (k >= 0) {
4307        if (__runtimeEquals(self[k], element)) {
4308            return k;
4309        }
4310        k--;
4311    }
4312    return -1;
4313}
4314
4315/**
4316 * Returns the last index at which a given element can be found in the array,
4317 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
4318 *
4319 * @param element element to locate in the array.
4320 * @param fromIndex zero-based index at which to start searching backwards.
4321 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
4322 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
4323 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
4324 *
4325 * @returns The last index of the element in the array; -1 if not found.
4326 */
4327export function lastIndexOf(self: short[], element: short, fromIndex?: Number): number {
4328    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
4329}
4330
4331/**
4332 * Creates and returns a new string by concatenating all of the elements in an `Array`,
4333 * separated by a specified separator string.
4334 * If the array has only one item, then that item will be returned without using the separator.
4335 *
4336 * @param sep specifies a separator
4337 *
4338 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
4339 */
4340export function join(self: short[], sep?: String): string {
4341    if (self.length == 0) {
4342        return ""
4343    }
4344    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
4345    let sb = new StringBuilder(new String(self[0]))
4346    for (let i: int = 1; i < self.length; i++) {
4347        const tmp = self[i]
4348        sb.append(sepReal);
4349        sb.append(tmp)
4350    }
4351
4352    return sb.toString();
4353}
4354
4355/**
4356 * Returns a string representing the specified array and its elements.
4357 *
4358 * @returns string representation
4359 */
4360export function toString(self: short[], ): string {
4361    return join(self, ",");
4362}
4363
4364/**
4365 * Returns a locale string representing the specified array and its elements.
4366 *
4367 * @param locales
4368 *
4369 * @param options
4370 *
4371 * @returns string representation
4372 */
4373export function toLocaleString(self: short[], locales: Object, options: Object): string {
4374    throw new Error("Array.toLocaleString: not implemented")
4375}
4376
4377/**
4378 * Returns a locale string representing the specified array and its elements.
4379 *
4380 * @param options
4381 *
4382 * @returns string representation
4383 */
4384export function toLocaleString(self: short[], locales: Object): string {
4385    return toLocaleString(self, new Object(), new Object())
4386}
4387
4388/**
4389 * Returns a locale string representing the specified array and its elements.
4390 *
4391 * @returns string representation
4392 */
4393export function toLocaleString(self: short[], ): string {
4394    const sb = new StringBuilder()
4395    const len = self.length;
4396    for (let i = 0; i < len; i++) {
4397        if (i != 0) {
4398            sb.append(",")
4399        }
4400        let x = self[i] as NullishType;
4401        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
4402            sb.append(x!.toLocaleString())
4403        }
4404    }
4405    return sb.toString()
4406}
4407
4408/**
4409 * Copying version of the splice() method.
4410 *
4411 * @param start index
4412 *
4413 * @param delete number of items after start index
4414 *
4415 * @returns a new Array with some elements removed and/or replaced at a given index.
4416 */
4417export function toSpliced(self: short[], start?: Number, delete?: Number): short[] {
4418    const len = self.length;
4419    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
4420}
4421
4422/**
4423 * Copying version of the splice() method.
4424 *
4425 * @param start index
4426 *
4427 * @param delete number of items after start index
4428 *
4429 * @returns a new Array with some elements removed and/or replaced at a given index.
4430 */
4431export function toSpliced(self: short[], start: number, delete: number, ...items: short[]): short[] {
4432    const len = self.length;
4433    return toSpliced(self, start as int, delete as int, ...items)
4434}
4435
4436/**
4437 * Copying version of the splice() method.
4438 *
4439 * @param start index
4440 *
4441 * @param delete number of items after start index
4442 *
4443 * @returns a new Array with some elements removed and/or replaced at a given index.
4444 */
4445export function toSpliced(self: short[], start: int, delete: int, ...items: short[]): short[] {
4446    const len = self.length;
4447    start = normalizeIndex(start, len);
4448    if (delete < 0) {
4449        delete = 0;
4450    } else if (delete > len) {
4451        delete = len;
4452    }
4453    if (start > len - delete) {
4454        delete = len - start
4455    }
4456    const res = new short[len - delete + items.length];
4457    for (let i = 0; i < start; i++) {
4458        res[i] = self[i]
4459    }
4460    for (let i = 0; i < items.length; i++) {
4461        res[start + i] = items[i]
4462    }
4463    for (let i = start + delete; i < len; i++) {
4464        res[i - delete + items.length] = self[i]
4465    }
4466    return res;
4467}
4468
4469/**
4470 * Copying version of the splice() method.
4471 *
4472 * @param start index
4473 *
4474 * @returns a new Array with some elements removed and/or replaced at a given index.
4475 */
4476export function toSpliced(self: short[], start: int): short[] {
4477    return toSpliced(self, start, self.length)
4478}
4479
4480/**
4481 * Checks whether an Array includes a certain value among its entries,
4482 * returning true or false as appropriate.
4483 *
4484 * @param val value to search
4485 *
4486 * @param fromIndex start index
4487 *
4488 * @returns true if val is in Array
4489 */
4490export function includes(self: short[], val: short, fromIndex?: Number): boolean {
4491    const len = self.length;
4492    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
4493    for (let i = fi; i < len; i++) {
4494        if (val == self[i]) {
4495            return true;
4496        }
4497    }
4498    return false;
4499}
4500
4501/**
4502 * Returns the first index at which a given element
4503 * can be found in the array, or -1 if it is not present.
4504 *
4505 * @param val value to search
4506 *
4507 * @param fromIndex index to search from
4508 *
4509 * @returns index of val, -1 otherwise
4510 */
4511export function indexOf(self: short[], val: short, fromIndex: int): int {
4512    fromIndex = normalizeIndex(fromIndex, self.length)
4513    for (let i = fromIndex; i < self.length; i++) {
4514        if (__runtimeEquals(val, self[i])) {
4515            return i
4516        }
4517    }
4518    return -1
4519}
4520
4521/**
4522 * Returns the first index at which a given element
4523 * can be found in the array, or -1 if it is not present.
4524 *
4525 * @param val value to search
4526 *
4527 * @param fromIndex index to search from
4528 *
4529 * @returns index of val, -1 otherwise
4530 */
4531export function indexOf(self: short[], val: short, fromIndex?: Number): number {
4532    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
4533}
4534
4535/**
4536 * Copying version of the sort() method.
4537 * It returns a new array with the elements sorted in ascending order.
4538 *
4539 * @returns sorted copy of hte current instance using default comparator
4540 */
4541export function toSorted(self: short[], ): short[] {
4542    let arr = cloneArray(self);
4543    sort(arr, )
4544    return arr
4545}
4546
4547/**
4548 * Copying version of the sort() method.
4549 * It returns a new array with the elements sorted in ascending order.
4550 *
4551 * @param comparator function to compare to elements of the Array
4552 *
4553 * @returns sorted copy of the current instance comparator
4554 */
4555export function toSorted(self: short[], comparator: (a: short, b: short) => number): short[] {
4556    let arr = cloneArray(self);
4557    sort(arr, comparator)
4558    return arr
4559}
4560
4561/**
4562 * Modifies `this` instance of `Array` class and populates
4563 * it with same elements ordered towards the direction opposite to that previously stated.
4564 *
4565 * @note Mutating method
4566 */
4567export function reverse(self: short[], ): short[] {
4568    for (let i = 0; i < self.length / 2; i++) {
4569        const tmp = self[i];
4570        const idx_r = self.length - 1 - i;
4571        const val_r = self[idx_r];
4572        self[i] = val_r;
4573        self[idx_r] = tmp;
4574    }
4575    return self;
4576}
4577
4578/**
4579 * Copying version of the reverse() method.
4580 * It returns a new array with the elements in reversed order.
4581 *
4582 * @returns reversed copy of the current Array
4583 */
4584export function toReversed(self: short[], ): short[] {
4585    let arr = new short[self.length]
4586    for (let i = 0; i < self.length; i++) {
4587        arr[self.length - 1 - i] = self[i]
4588    }
4589    return arr
4590}
4591
4592/**
4593 * Copying version of using the bracket notation to change the value of a given index.
4594 * It returns a new Array with the element at the given index replaced with the given value.
4595 *
4596 * @param index to replace
4597 *
4598 * @param value new value
4599 *
4600 * @returns a new Array with the element at the given index replaced with the given value
4601 */
4602export function with(self: short[], index: number, value: short): short[] {
4603    return with(self, index as int, value)
4604}
4605
4606/**
4607 * Copying version of using the bracket notation to change the value of a given index.
4608 * It returns a new Array with the element at the given index replaced with the given value.
4609 *
4610 * @param index to replace
4611 *
4612 * @param value new value
4613 *
4614 * @returns a new Array with the element at the given index replaced with the given value
4615 */
4616export function with(self: short[], index: int, value: short): short[] {
4617    if (index < 0) {
4618        index += self.length;
4619    }
4620    if (index >= self.length) {
4621        throw new RangeError("Invalid index")
4622    }
4623    let arr = cloneArray(self);
4624    arr[index] = value;
4625    return arr
4626}
4627
4628/**
4629 * Returns an iterator over all values
4630 */
4631export function values(self: short[], ): IterableIterator<short> {
4632    return new ArrayValuesIterator_short(self);
4633}
4634
4635/**
4636 * Returns an iterable of key, value pairs for every entry in the array
4637 */
4638export function entries(self: short[], ): IterableIterator<[number, short]> {
4639    return new ArrayEntriesIterator_short(self);
4640}
4641
4642/**
4643 * Determines whether all the members of an array satisfy the specified test.
4644 *
4645 * @param predicate A function that accepts up to three arguments. The every method calls
4646 * the predicate function for each element in the array until the predicate returns a value
4647 * which is coercible to the Boolean value false, or until the end of the array.
4648 *
4649 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
4650 */
4651export function every(self: short[], predicate: () => boolean): boolean {
4652    for (let i = 0; i < self.length; i++) {
4653        if (!predicate()) {
4654            return false
4655        }
4656    }
4657    return true
4658}
4659
4660/**
4661 * Returns the elements of an array that meet the condition specified in a callback function.
4662 *
4663 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
4664 *
4665 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
4666 */
4667export function filter(self: short[], predicate: () => boolean): short[] {
4668    return filter(self, (value: short, index: number): boolean => predicate());
4669}
4670
4671/**
4672 * Returns the value of the first element in the array where predicate is true, and undefined
4673 * otherwise.
4674 *
4675 * @param predicate find calls predicate once for each element of the array, in ascending
4676 * order, until it finds one where predicate returns true. If such an element is found, find
4677 * immediately returns that element value. Otherwise, find returns undefined.
4678 *
4679 * @returns the value of the first element in the array or undefined
4680 */
4681export function find(self: short[], predicate: () => boolean): Short | undefined {
4682    const res = findIndex(self, predicate)
4683    if (res == -1) {
4684        return undefined
4685    }
4686    return self[res as int];
4687}
4688
4689/**
4690 * Returns the index of the first element in the array where predicate is true, and -1
4691 * otherwise.
4692 *
4693 * @param predicate find calls predicate once for each element of the array, in ascending
4694 * order, until it finds one where predicate returns true. If such an element is found,
4695 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
4696 *
4697 * @returns found element index or -1 otherwise
4698 */
4699export function findIndex(self: short[], predicate: () => boolean): number {
4700    for (let i = 0; i < self.length; i++) {
4701        if (predicate()) {
4702            return i;
4703        }
4704    }
4705    return -1;
4706}
4707
4708/**
4709 * Performs the specified action for each element in an array.
4710 *
4711 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
4712 */
4713export function forEach(self: short[], callbackfn: () => void): void {
4714    const len0 = self.length;
4715    for (let i = 0; i < len0; i++) {
4716        callbackfn()
4717    }
4718}
4719
4720/**
4721 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4722 *
4723 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
4724 *
4725 * @returns a result after applying callbackfn over all elements of the Array
4726 */
4727export function reduce(self: short[], callbackfn: (previousValue: short) => short): short {
4728    if (self.length == 0) {
4729        throw new TypeError("Reduce of empty array with no initial value")
4730    }
4731    let acc: short = self[0];
4732    for (let i = 1; i < self.length; i++) {
4733        acc = callbackfn(acc)
4734    }
4735    return acc
4736}
4737
4738/**
4739 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4740 *
4741 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
4742 *
4743 * @returns a result after applying callbackfn over all elements of the Array
4744 */
4745export function reduce(self: short[], callbackfn: () => short): short {
4746    if (self.length == 0) {
4747        throw new TypeError("Reduce of empty array with no initial value")
4748    }
4749    let acc: short = self[0];
4750    for (let i = 1; i < self.length; i++) {
4751        acc = callbackfn()
4752    }
4753    return acc
4754}
4755
4756/**
4757 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4758 *
4759 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
4760 *
4761 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
4762 *
4763 * @returns a result after applying callbackfn over all elements of the Array
4764 */
4765export function reduce<U = short>(self: short[], callbackfn: (previousValue: U) => U, initialValue: U): U {
4766    let acc = initialValue
4767    for (let i = 0; i < self.length; i++) {
4768        acc = callbackfn(acc)
4769    }
4770    return acc
4771}
4772
4773/**
4774 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4775 *
4776 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
4777 *
4778 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
4779 *
4780 * @returns a result after applying callbackfn over all elements of the Array
4781 */
4782export function reduce<U = short>(self: short[], callbackfn: () => U, initialValue: U): U {
4783    let acc = initialValue
4784    for (let i = 0; i < self.length; i++) {
4785        acc = callbackfn()
4786    }
4787    return acc
4788}
4789
4790/**
4791 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4792 *
4793 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
4794 *
4795 * @returns a result after applying callbackfn over all elements of the Array
4796 */
4797export function reduceRight(self: short[], callbackfn: (previousValue: short) => short): short {
4798    if (self.length == 0) {
4799        throw new TypeError("Reduce of empty array with no initial value")
4800    }
4801    let acc: short = self[self.length - 1];
4802    for (let i = self.length - 2; i >= 0; i--) {
4803        acc = callbackfn(acc)
4804    }
4805    return acc
4806}
4807
4808/**
4809 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4810 *
4811 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
4812 *
4813 * @returns a result after applying callbackfn over all elements of the Array
4814 */
4815export function reduceRight(self: short[], callbackfn: () => short): short {
4816    if (self.length == 0) {
4817        throw new TypeError("Reduce of empty array with no initial value")
4818    }
4819    let acc: short = self[self.length - 1];
4820    for (let i = self.length - 2; i >= 0; i--) {
4821        acc = callbackfn()
4822    }
4823    return acc
4824}
4825
4826/**
4827 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4828 *
4829 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
4830 *
4831 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
4832 *
4833 * @returns a result after applying callbackfn over all elements of the Array
4834 */
4835export function reduceRight<U>(self: short[], callbackfn: (previousValue: U) => U, initialValue: U): U {
4836    let acc = initialValue
4837    for (let i = self.length - 1; i >= 0; i--) {
4838        acc = callbackfn(acc)
4839    }
4840    return acc
4841}
4842
4843/**
4844 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
4845 *
4846 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
4847 *
4848 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
4849 *
4850 * @returns a result after applying callbackfn over all elements of the Array
4851 */
4852export function reduceRight<U>(self: short[], callbackfn: () => U, initialValue: U): U {
4853    let acc = initialValue
4854    for (let i = self.length - 1; i >= 0; i--) {
4855        acc = callbackfn()
4856    }
4857    return acc
4858}
4859
4860/**
4861 * Determines whether the specified callback function returns true for any element of an array.
4862 *
4863 * @param predicate A function that accepts up to three arguments. The some method calls
4864 * the predicate function for each element in the array until the predicate returns a value
4865 * which is coercible to the Boolean value true, or until the end of the array.
4866 *
4867 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
4868 */
4869export function some(self: short[], predicate: () => boolean): boolean {
4870    for (let i = 0; i < self.length; i++) {
4871        if (predicate()) {
4872            return true
4873        }
4874    }
4875    return false
4876}
4877
4878/**
4879 * Iterates the array in reverse order and returns the value of the first element
4880 * that satisfies the provided testing function
4881 *
4882 * @param predicate testing function
4883 *
4884 * @returns found element or undefined otherwise
4885 */
4886export function findLast(self: short[], predicate: () => boolean): Short | undefined {
4887    for (let i = self.length - 1; i >= 0; i--) {
4888        const val = self[i];
4889        if (predicate()) {
4890            return val;
4891        }
4892    }
4893    return undefined;
4894}
4895
4896/**
4897 * Iterates the array in reverse order and returns the index of
4898 * the first element that satisfies the provided testing function.
4899 * If no elements satisfy the testing function, -1 is returned.
4900 *
4901 * @param predicate testing function
4902 *
4903 * @returns index of first element satisfying to predicate, -1 if no such element
4904 */
4905export function findLastIndex(self: short[], predicate: () => boolean): number {
4906    for (let i = self.length - 1; i >= 0; i--) {
4907        if (predicate()) {
4908            return i
4909        }
4910    }
4911    return -1
4912}
4913
4914/**
4915 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
4916 *
4917 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
4918 *
4919 * @returns `Array` instance, constructed from `this` and given function.
4920 */
4921export function map(self: short[], callbackfn: (value: short, index: number, array: short[]) => short): short[] {
4922    const len = self.length;
4923    let res = new short[len];
4924    for (let i = 0; i < len; i++) {
4925        res[i] = callbackfn(self[i], i as number, self);
4926    }
4927    return res;
4928}
4929
4930/**
4931 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
4932 *
4933 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
4934 *
4935 * @returns `Array` instance, constructed from `this` and given function.
4936 */
4937export function map(self: short[], callbackfn: (value: short, index: number) => short): short[] {
4938    const len = self.length;
4939    let res = new short[len];
4940    for (let i = 0; i < len; i++) {
4941        res[i] = callbackfn(self[i], i as number);
4942    }
4943    return res;
4944}
4945
4946/**
4947 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
4948 *
4949 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
4950 *
4951 * @returns `Array` instance, constructed from `this` and given function.
4952 */
4953export function map(self: short[], callbackfn: (value: short) => short): short[] {
4954    const len = self.length;
4955    let res = new short[len];
4956    for (let i = 0; i < len; i++) {
4957        res[i] = callbackfn(self[i]);
4958    }
4959    return res;
4960}
4961
4962/**
4963 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
4964 *
4965 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
4966 *
4967 * @returns `Array` instance, constructed from `this` and given function.
4968 */
4969export function map(self: short[], callbackfn: () => short): short[] {
4970    const len = self.length;
4971    let res = new short[len];
4972    for (let i = 0; i < len; i++) {
4973        res[i] = callbackfn();
4974    }
4975    return res;
4976}
4977
4978/**
4979 * Constructs a new `Array` instance and populates it with
4980 * portion of a given array, filtered down to just the elements from the
4981 * given array that pass the test implemented by the provided function.
4982 *
4983 * @param fn test function, applied to each element of an array.
4984 *
4985 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
4986 */
4987export function filter(self: short[], fn: (v: short, k: number) => boolean): short[] {
4988    const mask = new boolean[self.length]
4989    let cnt = 0
4990
4991    for (let i: int = 0; i < self.length; i++) {
4992        const val = self[i];
4993        if (fn(val, i)) {
4994            mask[i] = true
4995            cnt++;
4996        }
4997    }
4998    const res = new short[cnt];
4999    let idx_store = 0;
5000    for (let i: int = 0; i < self.length; i++) {
5001        if (mask[i]) {
5002            res[idx_store++] = self[i]
5003        }
5004    }
5005    return res;
5006}
5007
5008export function concat(self: short[], fst: short[], ...more: short[][]): short[] {
5009    const lnMin = self.length + fst.length;
5010    let ln = lnMin;
5011    for (let i = 0; i < more.length; i++) {
5012        ln += more[i].length
5013    }
5014    const r = new short[ln];
5015    try {
5016        copyTo(self, r, 0, 0, self.length);
5017        copyTo(fst, r, self.length, 0, fst.length);
5018        let idx = lnMin;
5019        for (let i = 0; i < more.length; i++) {
5020            copyTo(more[i], r, idx, 0, more[i].length);
5021            idx += more[i].length;
5022        }
5023    } catch (e) {
5024        // impossible
5025    }
5026    return r
5027}
5028
5029/**
5030 * Reorders elements of `this` using comparator function.
5031 *
5032 * @param comparator function that defines the sort order.
5033 *
5034 * @note Mutating method
5035 */
5036export function sort(self: short[], comparator: (a: short, b: short) => number): short[] {
5037    sort_subarray(self, 0, self.length, (l: short, r: short): boolean => {
5038        return comparator(l, r ) < 0;
5039    });
5040    return self;
5041}
5042
5043/**
5044 * Reorders elements of `this` using comparator function.
5045 *
5046 * @param comparator function that defines the sort order.
5047 *
5048 * @note Mutating method
5049 */
5050export function sort(self: short[], ): short[] {
5051    sort(self, 0, self.length);
5052    return self;
5053}
5054
5055export function keys(self: short[]): IterableIterator<number> {
5056    return new BuiltinArrayKeysIterator(self.length);
5057}
5058
5059class ArrayValuesIterator_short implements IterableIterator<short> {
5060    private parent: short[]
5061    private idx: int = 0
5062
5063    constructor(parent: short[]) {
5064        this.parent = parent
5065    }
5066
5067    override next(): IteratorResult<short> {
5068        if (this.idx >= this.parent.length) {
5069            return new IteratorResult<short>()
5070        }
5071        return new IteratorResult<short>(this.parent[this.idx++])
5072    }
5073
5074    override $_iterator(): IterableIterator<short> {
5075        return this;
5076    }
5077
5078    public __Iterator_getLength(): int {
5079        return this.parent.length as int
5080    }
5081}
5082
5083class ArrayEntriesIterator_short implements IterableIterator<[number, short]> {
5084    private parent: short[]
5085    private idx: int = 0
5086
5087    constructor(parent: short[]) {
5088        this.parent = parent
5089    }
5090
5091    override next(): IteratorResult<[number, short]> {
5092        if (this.idx >= this.parent.length) {
5093            return new IteratorResult<[number, short]>()
5094        }
5095        const i = this.idx++;
5096        const vl: [number, short] = [i as number, this.parent[i]]
5097        return new IteratorResult<[number, short]>(vl);
5098    }
5099
5100    override $_iterator(): IterableIterator<[number, short]> {
5101        return this;
5102    }
5103
5104    public __Iterator_getLength(): int {
5105        return this.parent.length as int
5106    }
5107}
5108
5109function cloneArray(self: int[]): int[] {
5110    const ret = new int[self.length];;
5111    for (let i = 0; i < self.length; i++) {
5112        ret[i] = self[i];
5113    }
5114    return ret;
5115}
5116
5117/**
5118 * Takes an integer value and returns the item at that index,
5119 * allowing for positive and negative integers. Negative integers count back
5120 * from the last item in the array.
5121 *
5122 * @param index Zero-based index of the array element to be returned.
5123 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
5124 *
5125 * @returns The element in the array matching the given index.
5126 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
5127 */
5128export function at(self: int[], index: number): Int | undefined {
5129    return at(self, index as int)
5130}
5131
5132/**
5133 * Creates a new `Array` from this `Array` instance and given `Array` instance.
5134 *
5135 * @param other to concatenate into a new array.
5136 *
5137 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
5138 */
5139// export function concat(self: int[], ...items: (int | Concatint[])[]): int[] {
5140//     throw new Error("not implemented")
5141// }
5142
5143export function concat(self: int[], ...items: ConcatArray<int>[]): int[] {
5144    let totalAdd = self.length;
5145    for (let i = 0; i < items.length; i++) {
5146        totalAdd += items[i].length as int
5147    }
5148
5149    const buf = new int[totalAdd];
5150
5151    for (let i = 0; i < self.length; i++) {
5152        buf[i] = self[i];
5153    }
5154
5155    let insertTo = self.length;
5156    for (let i = 0; i < items.length; i++) {
5157        const arr = items[i]
5158        const len = arr.length as int
5159        for (let j = 0; j < len; j++) {
5160            buf[insertTo++] = arr.$_get(j)
5161        }
5162    }
5163
5164    return buf;
5165}
5166
5167/**
5168 * Takes an integer value and returns the item at that index,
5169 * allowing for positive and negative integers. Negative integers count back
5170 * from the last item in the array.
5171 *
5172 * @param index Zero-based index of the array element to be returned.
5173 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
5174 *
5175 * @returns The element in the array matching the given index.
5176 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
5177 */
5178export function at(self: int[], index: int): Int | undefined {
5179    let len = self.length;
5180    let k: int;
5181    if (index >= 0) {
5182        k = index;
5183    } else {
5184        k = len + index;
5185    }
5186
5187    if (k < 0 || k >= len) {
5188        return undefined;
5189    }
5190
5191    return self[k];
5192}
5193
5194/**
5195 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5196 *
5197 * @param target index at which to copy the sequence
5198 *
5199 * @param start index at which to start copying elements from
5200 *
5201 * @param end index at which to end copying elements from
5202 *
5203 * @returns this array after transformation
5204 */
5205export function copyWithin(self: int[], target: number, start: number, end?: Number): int[] {
5206    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
5207    return self;
5208}
5209
5210/**
5211 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5212 *
5213 * @param target index at which to copy the sequence
5214 *
5215 * @param start index at which to start copying elements from
5216 *
5217 * @param end index at which to end copying elements from
5218 *
5219 * @returns this array after transformation
5220 */
5221export function copyWithin(self: int[], target: int, start: int, end: int): int[] {
5222    target = normalizeIndex(target, self.length)
5223    start = normalizeIndex(start, self.length)
5224    end = normalizeIndex(end, self.length)
5225
5226    if (end <= start) {
5227        return self;
5228    }
5229
5230    if (target <= start) {
5231        while (start < end) {
5232            const read = self[start++];
5233            self[target++] = read;
5234        }
5235    } else {
5236        let len = end - start;
5237        if (target + len > self.length) {
5238            len = self.length - target
5239        }
5240        for (let i = 0; i < len; i++) {
5241            const read = self[start + len - 1 - i];
5242            self[target + len - 1 - i] = read;
5243        }
5244    }
5245
5246    return self;
5247}
5248
5249/**
5250 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5251 *
5252 * @param target index at which to copy the sequence
5253 *
5254 * @param start index at which to start copying elements from
5255 *
5256 * @returns this array after transformation
5257 */
5258export function copyWithin(self: int[], target: int, start: int): int[] {
5259    copyWithin(self, target, start, self.length);
5260    return self;
5261}
5262
5263/**
5264 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5265 *
5266 * @param target index at which to copy the sequence
5267 *
5268 * @returns this array after transformation
5269 */
5270export function copyWithin(self: int[], target: int): int[] {
5271    copyWithin(self, target, 0, self.length);
5272    return self;
5273}
5274
5275/**
5276 * Changes all elements in the Array to a static value, from a start index to an end index
5277 *
5278 * @param value to fill the array with
5279 *
5280 * @param start index at which to start filling
5281 *
5282 * @param end index at which to end filling, but not including
5283 *
5284 * @returns this array after transformation
5285 */
5286export function fill(self: int[], value: int, start?: Number, end?: Number): int[] {
5287    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
5288    return self;
5289}
5290
5291/**
5292 * Changes all elements in the Array to a static value, from a start index to an end index
5293 *
5294 * @param value to fill the array with
5295 *
5296 * @param start index at which to start filling
5297 *
5298 * @param end index at which to end filling, but not including
5299 *
5300 * @returns this array after transformation
5301 */
5302export function fill(self: int[], value: int, start: int, end: int): int[] {
5303    start = normalizeIndex(start, self.length);
5304    end = normalizeIndex(end, self.length)
5305
5306    for (let i = start; i < end; i++) {
5307        self[i] = value;
5308    }
5309
5310    return self;
5311}
5312
5313/**
5314 * Returns the value of the first element in the array where predicate is true, and undefined
5315 * otherwise.
5316 *
5317 * @param predicate find calls predicate once for each element of the array, in ascending
5318 * order, until it finds one where predicate returns true. If such an element is found, find
5319 * immediately returns that element value. Otherwise, find returns undefined.
5320 *
5321 * @returns the value of the first element in the array or undefined
5322 */
5323export function find(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): Int | undefined {
5324    const res = findIndex(self, predicate)
5325    if (res == -1) {
5326        return undefined
5327    }
5328    return self[res as int];
5329}
5330
5331/**
5332 * Returns the index of the first element in the array where predicate is true, and -1
5333 * otherwise.
5334 *
5335 * @param predicate find calls predicate once for each element of the array, in ascending
5336 * order, until it finds one where predicate returns true. If such an element is found,
5337 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
5338 *
5339 * @returns found element index or -1 otherwise
5340 */
5341export function findIndex(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): number {
5342    for (let i = 0; i < self.length; i++) {
5343        if (predicate(self[i], i as number, self)) {
5344            return i;
5345        }
5346    }
5347    return -1;
5348}
5349
5350/**
5351 * Iterates the array in reverse order and returns the value of the first element
5352 * that satisfies the provided testing function
5353 *
5354 * @param predicate testing function
5355 *
5356 * @returns found element or undefined otherwise
5357 */
5358export function findLast(self: int[], predicate: (elem: int, index: number, array: int[]) => boolean): Int | undefined {
5359    for (let i = self.length - 1; i >= 0; i--) {
5360        const val = self[i];
5361        if (predicate(val, i as number, self)) {
5362            return val;
5363        }
5364    }
5365    return undefined;
5366}
5367
5368/**
5369 * Determines whether all the members of an array satisfy the specified test.
5370 *
5371 * @param predicate A function that accepts up to three arguments. The every method calls
5372 * the predicate function for each element in the array until the predicate returns a value
5373 * which is coercible to the Boolean value false, or until the end of the array.
5374 *
5375 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
5376 */
5377export function every(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): boolean {
5378    for (let i = 0; i < self.length; i++) {
5379        if (!predicate(self[i], i as number, self)) {
5380            return false
5381        }
5382    }
5383    return true;
5384}
5385
5386/**
5387 * Determines whether the specified callback function returns true for any element of an array.
5388 *
5389 * @param predicate A function that accepts up to three arguments. The some method calls
5390 * the predicate function for each element in the array until the predicate returns a value
5391 * which is coercible to the Boolean value true, or until the end of the array.
5392 *
5393 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
5394 */
5395export function some(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): boolean {
5396    for (let i = 0; i < self.length; i++) {
5397        if (predicate(self[i], i as number, self)) {
5398            return true
5399        }
5400    }
5401    return false
5402}
5403
5404/**
5405 * Returns the elements of an array that meet the condition specified in a callback function.
5406 *
5407 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
5408 *
5409 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
5410 */
5411export function filter(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): int[] {
5412    return filter(self, (value: int, index: number): boolean => predicate(value, index, self));
5413}
5414
5415/**
5416 * Iterates the array in reverse order and returns the index of
5417 * the first element that satisfies the provided testing function.
5418 * If no elements satisfy the testing function, -1 is returned.
5419 *
5420 * @param predicate testing function
5421 *
5422 * @returns index of first element satisfying to predicate, -1 if no such element
5423 */
5424export function findLastIndex(self: int[], predicate: (element: int, index: number, array: int[]) => boolean): number {
5425    for (let i = self.length - 1; i >= 0; i--) {
5426        if (predicate(self[i], i as number, self)) {
5427            return i
5428        }
5429    }
5430    return -1
5431}
5432
5433/**
5434 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5435 *
5436 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
5437 *
5438 * @returns a result after applying callbackfn over all elements of the Array
5439 */
5440export function reduce(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number, array: int[]) => int): int {
5441    if (self.length == 0) {
5442        throw new TypeError("Reduce of empty array with no initial value")
5443    }
5444    let acc: int = self[0];
5445    for (let i = 1; i < self.length; i++) {
5446        acc = callbackfn(acc, self[i], i as number, self)
5447    }
5448    return acc
5449}
5450
5451/**
5452 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5453 *
5454 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
5455 *
5456 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
5457 *
5458 * @returns a result after applying callbackfn over all elements of the Array
5459 */
5460export function reduce<U = int>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number, array: int[]) => U, initialValue: U): U {
5461    let acc = initialValue
5462    for (let i = 0; i < self.length; i++) {
5463        acc = callbackfn(acc, self[i], i as number, self)
5464    }
5465    return acc
5466}
5467
5468/**
5469 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5470 *
5471 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
5472 *
5473 * @returns a result after applying callbackfn over all elements of the Array
5474 */
5475export function reduceRight(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number, array: int[]) => int): int {
5476    if (self.length == 0) {
5477        throw new TypeError("Reduce of empty array with no initial value")
5478    }
5479    let acc: int = self[self.length - 1];
5480    for (let i = self.length - 2; i >= 0; i--) {
5481        acc = callbackfn(acc, self[i], i as number, self)
5482    }
5483    return acc
5484}
5485
5486/**
5487 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5488 *
5489 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
5490 *
5491 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
5492 *
5493 * @returns a result after applying callbackfn over all elements of the Array
5494 */
5495export function reduceRight<U>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number, array: int[]) => U, initialValue: U): U {
5496    let acc = initialValue
5497    for (let i = self.length - 1; i >= 0; i--) {
5498        acc = callbackfn(acc, self[i], i as number, self)
5499    }
5500    return acc
5501}
5502
5503/**
5504 * Performs the specified action for each element in an array.
5505 *
5506 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
5507 */
5508export function forEach(self: int[], callbackfn: (value: int, index: number, array: int[]) => void): void {
5509    const len0 = self.length;
5510    for (let i = 0; i < len0; i++) {
5511        callbackfn(self[i], i as number, self)
5512    }
5513}
5514
5515/**
5516 * Returns the value of the first element in the array where predicate is true, and undefined
5517 * otherwise.
5518 *
5519 * @param predicate find calls predicate once for each element of the array, in ascending
5520 * order, until it finds one where predicate returns true. If such an element is found, find
5521 * immediately returns that element value. Otherwise, find returns undefined.
5522 *
5523 * @returns the value of the first element in the array or undefined
5524 */
5525export function find(self: int[], predicate: (value: int, index: number) => boolean): Int | undefined {
5526    const res = findIndex(self, predicate)
5527    if (res == -1) {
5528        return undefined
5529    }
5530    return self[res as int];
5531}
5532
5533/**
5534 * Returns the index of the first element in the array where predicate is true, and -1
5535 * otherwise.
5536 *
5537 * @param predicate find calls predicate once for each element of the array, in ascending
5538 * order, until it finds one where predicate returns true. If such an element is found,
5539 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
5540 *
5541 * @returns found element index or -1 otherwise
5542 */
5543export function findIndex(self: int[], predicate: (value: int, index: number) => boolean): number {
5544    for (let i = 0; i < self.length; i++) {
5545        if (predicate(self[i], i as number)) {
5546            return i;
5547        }
5548    }
5549    return -1;
5550}
5551
5552/**
5553 * Iterates the array in reverse order and returns the value of the first element
5554 * that satisfies the provided testing function
5555 *
5556 * @param predicate testing function
5557 *
5558 * @returns found element or undefined otherwise
5559 */
5560export function findLast(self: int[], predicate: (elem: int, index: number) => boolean): Int | undefined {
5561    for (let i = self.length - 1; i >= 0; i--) {
5562        const val = self[i];
5563        if (predicate(val, i as number)) {
5564            return val;
5565        }
5566    }
5567    return undefined;
5568}
5569
5570/**
5571 * Determines whether all the members of an array satisfy the specified test.
5572 *
5573 * @param predicate A function that accepts up to three arguments. The every method calls
5574 * the predicate function for each element in the array until the predicate returns a value
5575 * which is coercible to the Boolean value false, or until the end of the array.
5576 *
5577 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
5578 */
5579export function every(self: int[], predicate: (value: int, index: number) => boolean): boolean {
5580    for (let i = 0; i < self.length; i++) {
5581        if (!predicate(self[i], i as number)) {
5582            return false
5583        }
5584    }
5585    return true;
5586}
5587
5588/**
5589 * Determines whether the specified callback function returns true for any element of an array.
5590 *
5591 * @param predicate A function that accepts up to three arguments. The some method calls
5592 * the predicate function for each element in the array until the predicate returns a value
5593 * which is coercible to the Boolean value true, or until the end of the array.
5594 *
5595 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
5596 */
5597export function some(self: int[], predicate: (value: int, index: number) => boolean): boolean {
5598    for (let i = 0; i < self.length; i++) {
5599        if (predicate(self[i], i as number)) {
5600            return true
5601        }
5602    }
5603    return false
5604}
5605
5606/**
5607 * Iterates the array in reverse order and returns the index of
5608 * the first element that satisfies the provided testing function.
5609 * If no elements satisfy the testing function, -1 is returned.
5610 *
5611 * @param predicate testing function
5612 *
5613 * @returns index of first element satisfying to predicate, -1 if no such element
5614 */
5615export function findLastIndex(self: int[], predicate: (element: int, index: number) => boolean): number {
5616    for (let i = self.length - 1; i >= 0; i--) {
5617        if (predicate(self[i], i as number)) {
5618            return i
5619        }
5620    }
5621    return -1
5622}
5623
5624/**
5625 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5626 *
5627 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
5628 *
5629 * @returns a result after applying callbackfn over all elements of the Array
5630 */
5631export function reduce(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number) => int): int {
5632    if (self.length == 0) {
5633        throw new TypeError("Reduce of empty array with no initial value")
5634    }
5635    let acc: int = self[0];
5636    for (let i = 1; i < self.length; i++) {
5637        acc = callbackfn(acc, self[i], i as number)
5638    }
5639    return acc
5640}
5641
5642/**
5643 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5644 *
5645 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
5646 *
5647 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
5648 *
5649 * @returns a result after applying callbackfn over all elements of the Array
5650 */
5651export function reduce<U = int>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number) => U, initialValue: U): U {
5652    let acc = initialValue
5653    for (let i = 0; i < self.length; i++) {
5654        acc = callbackfn(acc, self[i], i as number)
5655    }
5656    return acc
5657}
5658
5659/**
5660 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5661 *
5662 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
5663 *
5664 * @returns a result after applying callbackfn over all elements of the Array
5665 */
5666export function reduceRight(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number) => int): int {
5667    if (self.length == 0) {
5668        throw new TypeError("Reduce of empty array with no initial value")
5669    }
5670    let acc: int = self[self.length - 1];
5671    for (let i = self.length - 2; i >= 0; i--) {
5672        acc = callbackfn(acc, self[i], i as number)
5673    }
5674    return acc
5675}
5676
5677/**
5678 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5679 *
5680 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
5681 *
5682 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
5683 *
5684 * @returns a result after applying callbackfn over all elements of the Array
5685 */
5686export function reduceRight<U>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number) => U, initialValue: U): U {
5687    let acc = initialValue
5688    for (let i = self.length - 1; i >= 0; i--) {
5689        acc = callbackfn(acc, self[i], i as number)
5690    }
5691    return acc
5692}
5693
5694/**
5695 * Performs the specified action for each element in an array.
5696 *
5697 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
5698 */
5699export function forEach(self: int[], callbackfn: (value: int, index: number) => void): void {
5700    const len0 = self.length;
5701    for (let i = 0; i < len0; i++) {
5702        callbackfn(self[i], i as number)
5703    }
5704}
5705
5706/**
5707 * Returns the value of the first element in the array where predicate is true, and undefined
5708 * otherwise.
5709 *
5710 * @param predicate find calls predicate once for each element of the array, in ascending
5711 * order, until it finds one where predicate returns true. If such an element is found, find
5712 * immediately returns that element value. Otherwise, find returns undefined.
5713 *
5714 * @returns the value of the first element in the array or undefined
5715 */
5716export function find(self: int[], predicate: (value: int) => boolean): Int | undefined {
5717    const res = findIndex(self, predicate)
5718    if (res == -1) {
5719        return undefined
5720    }
5721    return self[res as int];
5722}
5723
5724/**
5725 * Returns the index of the first element in the array where predicate is true, and -1
5726 * otherwise.
5727 *
5728 * @param predicate find calls predicate once for each element of the array, in ascending
5729 * order, until it finds one where predicate returns true. If such an element is found,
5730 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
5731 *
5732 * @returns found element index or -1 otherwise
5733 */
5734export function findIndex(self: int[], predicate: (value: int) => boolean): number {
5735    for (let i = 0; i < self.length; i++) {
5736        if (predicate(self[i])) {
5737            return i;
5738        }
5739    }
5740    return -1;
5741}
5742
5743/**
5744 * Iterates the array in reverse order and returns the value of the first element
5745 * that satisfies the provided testing function
5746 *
5747 * @param predicate testing function
5748 *
5749 * @returns found element or undefined otherwise
5750 */
5751export function findLast(self: int[], predicate: (elem: int) => boolean): Int | undefined {
5752    for (let i = self.length - 1; i >= 0; i--) {
5753        const val = self[i];
5754        if (predicate(val)) {
5755            return val;
5756        }
5757    }
5758    return undefined;
5759}
5760
5761/**
5762 * Determines whether all the members of an array satisfy the specified test.
5763 *
5764 * @param predicate A function that accepts up to three arguments. The every method calls
5765 * the predicate function for each element in the array until the predicate returns a value
5766 * which is coercible to the Boolean value false, or until the end of the array.
5767 *
5768 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
5769 */
5770export function every(self: int[], predicate: (value: int) => boolean): boolean {
5771    for (let i = 0; i < self.length; i++) {
5772        if (!predicate(self[i])) {
5773            return false
5774        }
5775    }
5776    return true;
5777}
5778
5779/**
5780 * Determines whether the specified callback function returns true for any element of an array.
5781 *
5782 * @param predicate A function that accepts up to three arguments. The some method calls
5783 * the predicate function for each element in the array until the predicate returns a value
5784 * which is coercible to the Boolean value true, or until the end of the array.
5785 *
5786 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
5787 */
5788export function some(self: int[], predicate: (value: int) => boolean): boolean {
5789    for (let i = 0; i < self.length; i++) {
5790        if (predicate(self[i])) {
5791            return true
5792        }
5793    }
5794    return false
5795}
5796
5797/**
5798 * Returns the elements of an array that meet the condition specified in a callback function.
5799 *
5800 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
5801 *
5802 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
5803 */
5804export function filter(self: int[], predicate: (value: int) => boolean): int[] {
5805    return filter(self, (value: int, index: number): boolean => predicate(value));
5806}
5807
5808/**
5809 * Iterates the array in reverse order and returns the index of
5810 * the first element that satisfies the provided testing function.
5811 * If no elements satisfy the testing function, -1 is returned.
5812 *
5813 * @param predicate testing function
5814 *
5815 * @returns index of first element satisfying to predicate, -1 if no such element
5816 */
5817export function findLastIndex(self: int[], predicate: (element: int) => boolean): number {
5818    for (let i = self.length - 1; i >= 0; i--) {
5819        if (predicate(self[i])) {
5820            return i
5821        }
5822    }
5823    return -1
5824}
5825
5826/**
5827 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5828 *
5829 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
5830 *
5831 * @returns a result after applying callbackfn over all elements of the Array
5832 */
5833export function reduce(self: int[], callbackfn: (previousValue: int, currentValue: int) => int): int {
5834    if (self.length == 0) {
5835        throw new TypeError("Reduce of empty array with no initial value")
5836    }
5837    let acc: int = self[0];
5838    for (let i = 1; i < self.length; i++) {
5839        acc = callbackfn(acc, self[i])
5840    }
5841    return acc
5842}
5843
5844/**
5845 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5846 *
5847 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
5848 *
5849 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
5850 *
5851 * @returns a result after applying callbackfn over all elements of the Array
5852 */
5853export function reduce<U = int>(self: int[], callbackfn: (previousValue: U, currentValue: int) => U, initialValue: U): U {
5854    let acc = initialValue
5855    for (let i = 0; i < self.length; i++) {
5856        acc = callbackfn(acc, self[i])
5857    }
5858    return acc
5859}
5860
5861/**
5862 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5863 *
5864 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
5865 *
5866 * @returns a result after applying callbackfn over all elements of the Array
5867 */
5868export function reduceRight(self: int[], callbackfn: (previousValue: int, currentValue: int) => int): int {
5869    if (self.length == 0) {
5870        throw new TypeError("Reduce of empty array with no initial value")
5871    }
5872    let acc: int = self[self.length - 1];
5873    for (let i = self.length - 2; i >= 0; i--) {
5874        acc = callbackfn(acc, self[i])
5875    }
5876    return acc
5877}
5878
5879/**
5880 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
5881 *
5882 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
5883 *
5884 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
5885 *
5886 * @returns a result after applying callbackfn over all elements of the Array
5887 */
5888export function reduceRight<U>(self: int[], callbackfn: (previousValue: U, currentValue: int) => U, initialValue: U): U {
5889    let acc = initialValue
5890    for (let i = self.length - 1; i >= 0; i--) {
5891        acc = callbackfn(acc, self[i])
5892    }
5893    return acc
5894}
5895
5896/**
5897 * Performs the specified action for each element in an array.
5898 *
5899 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
5900 */
5901export function forEach(self: int[], callbackfn: (value: int) => void): void {
5902    const len0 = self.length;
5903    for (let i = 0; i < len0; i++) {
5904        callbackfn(self[i])
5905    }
5906}
5907
5908/**
5909 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
5910 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
5911 *
5912 * @param start zero-based index at which to start extraction
5913 *
5914 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
5915 *
5916 * @returns `Array` instance, constructed from extracted elements of `this` instance.
5917 */
5918export function slice(self: int[], start?: Number, end?: Number): int[] {
5919    const len: int = self.length;
5920    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
5921}
5922
5923/**
5924 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
5925 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
5926 *
5927 * @param start zero-based index at which to start extraction
5928 *
5929 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
5930 *
5931 * @returns `Array` instance, constructed from extracted elements of `this` instance.
5932 */
5933export function slice(self: int[], start: int, end: int): int[] {
5934    const len: int = self.length;
5935    const relStart = normalizeIndex(start, len)
5936    const relEnd = normalizeIndex(end, len)
5937
5938    let count = relEnd - relStart;
5939    if (count < 0) {
5940        count = 0;
5941    }
5942    let res = new int[count]
5943    for (let i = 0; i < count; i++) {
5944        res[i] = self[relStart + i];
5945    }
5946
5947    return res
5948}
5949
5950/**
5951 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
5952 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
5953 *
5954 * @param start zero-based index at which to start extraction
5955 *
5956 * @returns `Array` instance, constructed from extracted elements of `this` instance.
5957 */
5958export function slice(self: int[], start: int): int[] {
5959    return slice(self, start, Int.MAX_VALUE as int);
5960}
5961
5962/**
5963 * Returns the last index at which a given element can be found in the array,
5964 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
5965 *
5966 * @param element element to locate in the array.
5967 * @param fromIndex zero-based index at which to start searching backwards.
5968 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
5969 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
5970 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
5971 *
5972 * @returns The last index of the element in the array; -1 if not found.
5973 */
5974export function lastIndexOf(self: int[], element: int, fromIndex: int): int {
5975    if (self.length == 0) {
5976        return -1;
5977    }
5978    let n = fromIndex;
5979    let k: int;
5980    if (n >= 0) {
5981        k = min(self.length - 1, n);
5982    } else {
5983        k = self.length + n;
5984    }
5985
5986    while (k >= 0) {
5987        if (__runtimeEquals(self[k], element)) {
5988            return k;
5989        }
5990        k--;
5991    }
5992    return -1;
5993}
5994
5995/**
5996 * Returns the last index at which a given element can be found in the array,
5997 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
5998 *
5999 * @param element element to locate in the array.
6000 * @param fromIndex zero-based index at which to start searching backwards.
6001 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
6002 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
6003 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
6004 *
6005 * @returns The last index of the element in the array; -1 if not found.
6006 */
6007export function lastIndexOf(self: int[], element: int, fromIndex?: Number): number {
6008    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
6009}
6010
6011/**
6012 * Creates and returns a new string by concatenating all of the elements in an `Array`,
6013 * separated by a specified separator string.
6014 * If the array has only one item, then that item will be returned without using the separator.
6015 *
6016 * @param sep specifies a separator
6017 *
6018 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
6019 */
6020export function join(self: int[], sep?: String): string {
6021    if (self.length == 0) {
6022        return ""
6023    }
6024    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
6025    let sb = new StringBuilder(new String(self[0]))
6026    for (let i: int = 1; i < self.length; i++) {
6027        const tmp = self[i]
6028        sb.append(sepReal);
6029        sb.append(tmp)
6030    }
6031
6032    return sb.toString();
6033}
6034
6035/**
6036 * Returns a string representing the specified array and its elements.
6037 *
6038 * @returns string representation
6039 */
6040export function toString(self: int[], ): string {
6041    return join(self, ",");
6042}
6043
6044/**
6045 * Returns a locale string representing the specified array and its elements.
6046 *
6047 * @param locales
6048 *
6049 * @param options
6050 *
6051 * @returns string representation
6052 */
6053export function toLocaleString(self: int[], locales: Object, options: Object): string {
6054    throw new Error("Array.toLocaleString: not implemented")
6055}
6056
6057/**
6058 * Returns a locale string representing the specified array and its elements.
6059 *
6060 * @param options
6061 *
6062 * @returns string representation
6063 */
6064export function toLocaleString(self: int[], locales: Object): string {
6065    return toLocaleString(self, new Object(), new Object())
6066}
6067
6068/**
6069 * Returns a locale string representing the specified array and its elements.
6070 *
6071 * @returns string representation
6072 */
6073export function toLocaleString(self: int[], ): string {
6074    const sb = new StringBuilder()
6075    const len = self.length;
6076    for (let i = 0; i < len; i++) {
6077        if (i != 0) {
6078            sb.append(",")
6079        }
6080        let x = self[i] as NullishType;
6081        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
6082            sb.append(x!.toLocaleString())
6083        }
6084    }
6085    return sb.toString()
6086}
6087
6088/**
6089 * Copying version of the splice() method.
6090 *
6091 * @param start index
6092 *
6093 * @param delete number of items after start index
6094 *
6095 * @returns a new Array with some elements removed and/or replaced at a given index.
6096 */
6097export function toSpliced(self: int[], start?: Number, delete?: Number): int[] {
6098    const len = self.length;
6099    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
6100}
6101
6102/**
6103 * Copying version of the splice() method.
6104 *
6105 * @param start index
6106 *
6107 * @param delete number of items after start index
6108 *
6109 * @returns a new Array with some elements removed and/or replaced at a given index.
6110 */
6111export function toSpliced(self: int[], start: number, delete: number, ...items: int[]): int[] {
6112    const len = self.length;
6113    return toSpliced(self, start as int, delete as int, ...items)
6114}
6115
6116/**
6117 * Copying version of the splice() method.
6118 *
6119 * @param start index
6120 *
6121 * @param delete number of items after start index
6122 *
6123 * @returns a new Array with some elements removed and/or replaced at a given index.
6124 */
6125export function toSpliced(self: int[], start: int, delete: int, ...items: int[]): int[] {
6126    const len = self.length;
6127    start = normalizeIndex(start, len);
6128    if (delete < 0) {
6129        delete = 0;
6130    } else if (delete > len) {
6131        delete = len;
6132    }
6133    if (start > len - delete) {
6134        delete = len - start
6135    }
6136    const res = new int[len - delete + items.length];
6137    for (let i = 0; i < start; i++) {
6138        res[i] = self[i]
6139    }
6140    for (let i = 0; i < items.length; i++) {
6141        res[start + i] = items[i]
6142    }
6143    for (let i = start + delete; i < len; i++) {
6144        res[i - delete + items.length] = self[i]
6145    }
6146    return res;
6147}
6148
6149/**
6150 * Copying version of the splice() method.
6151 *
6152 * @param start index
6153 *
6154 * @returns a new Array with some elements removed and/or replaced at a given index.
6155 */
6156export function toSpliced(self: int[], start: int): int[] {
6157    return toSpliced(self, start, self.length)
6158}
6159
6160/**
6161 * Checks whether an Array includes a certain value among its entries,
6162 * returning true or false as appropriate.
6163 *
6164 * @param val value to search
6165 *
6166 * @param fromIndex start index
6167 *
6168 * @returns true if val is in Array
6169 */
6170export function includes(self: int[], val: int, fromIndex?: Number): boolean {
6171    const len = self.length;
6172    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
6173    for (let i = fi; i < len; i++) {
6174        if (val == self[i]) {
6175            return true;
6176        }
6177    }
6178    return false;
6179}
6180
6181/**
6182 * Returns the first index at which a given element
6183 * can be found in the array, or -1 if it is not present.
6184 *
6185 * @param val value to search
6186 *
6187 * @param fromIndex index to search from
6188 *
6189 * @returns index of val, -1 otherwise
6190 */
6191export function indexOf(self: int[], val: int, fromIndex: int): int {
6192    fromIndex = normalizeIndex(fromIndex, self.length)
6193    for (let i = fromIndex; i < self.length; i++) {
6194        if (__runtimeEquals(val, self[i])) {
6195            return i
6196        }
6197    }
6198    return -1
6199}
6200
6201/**
6202 * Returns the first index at which a given element
6203 * can be found in the array, or -1 if it is not present.
6204 *
6205 * @param val value to search
6206 *
6207 * @param fromIndex index to search from
6208 *
6209 * @returns index of val, -1 otherwise
6210 */
6211export function indexOf(self: int[], val: int, fromIndex?: Number): number {
6212    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
6213}
6214
6215/**
6216 * Copying version of the sort() method.
6217 * It returns a new array with the elements sorted in ascending order.
6218 *
6219 * @returns sorted copy of hte current instance using default comparator
6220 */
6221export function toSorted(self: int[], ): int[] {
6222    let arr = cloneArray(self);
6223    sort(arr, )
6224    return arr
6225}
6226
6227/**
6228 * Copying version of the sort() method.
6229 * It returns a new array with the elements sorted in ascending order.
6230 *
6231 * @param comparator function to compare to elements of the Array
6232 *
6233 * @returns sorted copy of the current instance comparator
6234 */
6235export function toSorted(self: int[], comparator: (a: int, b: int) => number): int[] {
6236    let arr = cloneArray(self);
6237    sort(arr, comparator)
6238    return arr
6239}
6240
6241/**
6242 * Modifies `this` instance of `Array` class and populates
6243 * it with same elements ordered towards the direction opposite to that previously stated.
6244 *
6245 * @note Mutating method
6246 */
6247export function reverse(self: int[], ): int[] {
6248    for (let i = 0; i < self.length / 2; i++) {
6249        const tmp = self[i];
6250        const idx_r = self.length - 1 - i;
6251        const val_r = self[idx_r];
6252        self[i] = val_r;
6253        self[idx_r] = tmp;
6254    }
6255    return self;
6256}
6257
6258/**
6259 * Copying version of the reverse() method.
6260 * It returns a new array with the elements in reversed order.
6261 *
6262 * @returns reversed copy of the current Array
6263 */
6264export function toReversed(self: int[], ): int[] {
6265    let arr = new int[self.length]
6266    for (let i = 0; i < self.length; i++) {
6267        arr[self.length - 1 - i] = self[i]
6268    }
6269    return arr
6270}
6271
6272/**
6273 * Copying version of using the bracket notation to change the value of a given index.
6274 * It returns a new Array with the element at the given index replaced with the given value.
6275 *
6276 * @param index to replace
6277 *
6278 * @param value new value
6279 *
6280 * @returns a new Array with the element at the given index replaced with the given value
6281 */
6282export function with(self: int[], index: number, value: int): int[] {
6283    return with(self, index as int, value)
6284}
6285
6286/**
6287 * Copying version of using the bracket notation to change the value of a given index.
6288 * It returns a new Array with the element at the given index replaced with the given value.
6289 *
6290 * @param index to replace
6291 *
6292 * @param value new value
6293 *
6294 * @returns a new Array with the element at the given index replaced with the given value
6295 */
6296export function with(self: int[], index: int, value: int): int[] {
6297    if (index < 0) {
6298        index += self.length;
6299    }
6300    if (index >= self.length) {
6301        throw new RangeError("Invalid index")
6302    }
6303    let arr = cloneArray(self);
6304    arr[index] = value;
6305    return arr
6306}
6307
6308/**
6309 * Returns an iterator over all values
6310 */
6311export function values(self: int[], ): IterableIterator<int> {
6312    return new ArrayValuesIterator_int(self);
6313}
6314
6315/**
6316 * Returns an iterable of key, value pairs for every entry in the array
6317 */
6318export function entries(self: int[], ): IterableIterator<[number, int]> {
6319    return new ArrayEntriesIterator_int(self);
6320}
6321
6322/**
6323 * Determines whether all the members of an array satisfy the specified test.
6324 *
6325 * @param predicate A function that accepts up to three arguments. The every method calls
6326 * the predicate function for each element in the array until the predicate returns a value
6327 * which is coercible to the Boolean value false, or until the end of the array.
6328 *
6329 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
6330 */
6331export function every(self: int[], predicate: () => boolean): boolean {
6332    for (let i = 0; i < self.length; i++) {
6333        if (!predicate()) {
6334            return false
6335        }
6336    }
6337    return true
6338}
6339
6340/**
6341 * Returns the elements of an array that meet the condition specified in a callback function.
6342 *
6343 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
6344 *
6345 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
6346 */
6347export function filter(self: int[], predicate: () => boolean): int[] {
6348    return filter(self, (value: int, index: number): boolean => predicate());
6349}
6350
6351/**
6352 * Returns the value of the first element in the array where predicate is true, and undefined
6353 * otherwise.
6354 *
6355 * @param predicate find calls predicate once for each element of the array, in ascending
6356 * order, until it finds one where predicate returns true. If such an element is found, find
6357 * immediately returns that element value. Otherwise, find returns undefined.
6358 *
6359 * @returns the value of the first element in the array or undefined
6360 */
6361export function find(self: int[], predicate: () => boolean): Int | undefined {
6362    const res = findIndex(self, predicate)
6363    if (res == -1) {
6364        return undefined
6365    }
6366    return self[res as int];
6367}
6368
6369/**
6370 * Returns the index of the first element in the array where predicate is true, and -1
6371 * otherwise.
6372 *
6373 * @param predicate find calls predicate once for each element of the array, in ascending
6374 * order, until it finds one where predicate returns true. If such an element is found,
6375 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
6376 *
6377 * @returns found element index or -1 otherwise
6378 */
6379export function findIndex(self: int[], predicate: () => boolean): number {
6380    for (let i = 0; i < self.length; i++) {
6381        if (predicate()) {
6382            return i;
6383        }
6384    }
6385    return -1;
6386}
6387
6388/**
6389 * Performs the specified action for each element in an array.
6390 *
6391 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
6392 */
6393export function forEach(self: int[], callbackfn: () => void): void {
6394    const len0 = self.length;
6395    for (let i = 0; i < len0; i++) {
6396        callbackfn()
6397    }
6398}
6399
6400/**
6401 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6402 *
6403 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
6404 *
6405 * @returns a result after applying callbackfn over all elements of the Array
6406 */
6407export function reduce(self: int[], callbackfn: (previousValue: int) => int): int {
6408    if (self.length == 0) {
6409        throw new TypeError("Reduce of empty array with no initial value")
6410    }
6411    let acc: int = self[0];
6412    for (let i = 1; i < self.length; i++) {
6413        acc = callbackfn(acc)
6414    }
6415    return acc
6416}
6417
6418/**
6419 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6420 *
6421 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
6422 *
6423 * @returns a result after applying callbackfn over all elements of the Array
6424 */
6425export function reduce(self: int[], callbackfn: () => int): int {
6426    if (self.length == 0) {
6427        throw new TypeError("Reduce of empty array with no initial value")
6428    }
6429    let acc: int = self[0];
6430    for (let i = 1; i < self.length; i++) {
6431        acc = callbackfn()
6432    }
6433    return acc
6434}
6435
6436/**
6437 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6438 *
6439 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
6440 *
6441 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
6442 *
6443 * @returns a result after applying callbackfn over all elements of the Array
6444 */
6445export function reduce<U = int>(self: int[], callbackfn: (previousValue: U) => U, initialValue: U): U {
6446    let acc = initialValue
6447    for (let i = 0; i < self.length; i++) {
6448        acc = callbackfn(acc)
6449    }
6450    return acc
6451}
6452
6453/**
6454 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6455 *
6456 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
6457 *
6458 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
6459 *
6460 * @returns a result after applying callbackfn over all elements of the Array
6461 */
6462export function reduce<U = int>(self: int[], callbackfn: () => U, initialValue: U): U {
6463    let acc = initialValue
6464    for (let i = 0; i < self.length; i++) {
6465        acc = callbackfn()
6466    }
6467    return acc
6468}
6469
6470/**
6471 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6472 *
6473 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
6474 *
6475 * @returns a result after applying callbackfn over all elements of the Array
6476 */
6477export function reduceRight(self: int[], callbackfn: (previousValue: int) => int): int {
6478    if (self.length == 0) {
6479        throw new TypeError("Reduce of empty array with no initial value")
6480    }
6481    let acc: int = self[self.length - 1];
6482    for (let i = self.length - 2; i >= 0; i--) {
6483        acc = callbackfn(acc)
6484    }
6485    return acc
6486}
6487
6488/**
6489 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6490 *
6491 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
6492 *
6493 * @returns a result after applying callbackfn over all elements of the Array
6494 */
6495export function reduceRight(self: int[], callbackfn: () => int): int {
6496    if (self.length == 0) {
6497        throw new TypeError("Reduce of empty array with no initial value")
6498    }
6499    let acc: int = self[self.length - 1];
6500    for (let i = self.length - 2; i >= 0; i--) {
6501        acc = callbackfn()
6502    }
6503    return acc
6504}
6505
6506/**
6507 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6508 *
6509 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
6510 *
6511 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
6512 *
6513 * @returns a result after applying callbackfn over all elements of the Array
6514 */
6515export function reduceRight<U>(self: int[], callbackfn: (previousValue: U) => U, initialValue: U): U {
6516    let acc = initialValue
6517    for (let i = self.length - 1; i >= 0; i--) {
6518        acc = callbackfn(acc)
6519    }
6520    return acc
6521}
6522
6523/**
6524 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
6525 *
6526 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
6527 *
6528 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
6529 *
6530 * @returns a result after applying callbackfn over all elements of the Array
6531 */
6532export function reduceRight<U>(self: int[], callbackfn: () => U, initialValue: U): U {
6533    let acc = initialValue
6534    for (let i = self.length - 1; i >= 0; i--) {
6535        acc = callbackfn()
6536    }
6537    return acc
6538}
6539
6540/**
6541 * Determines whether the specified callback function returns true for any element of an array.
6542 *
6543 * @param predicate A function that accepts up to three arguments. The some method calls
6544 * the predicate function for each element in the array until the predicate returns a value
6545 * which is coercible to the Boolean value true, or until the end of the array.
6546 *
6547 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
6548 */
6549export function some(self: int[], predicate: () => boolean): boolean {
6550    for (let i = 0; i < self.length; i++) {
6551        if (predicate()) {
6552            return true
6553        }
6554    }
6555    return false
6556}
6557
6558/**
6559 * Iterates the array in reverse order and returns the value of the first element
6560 * that satisfies the provided testing function
6561 *
6562 * @param predicate testing function
6563 *
6564 * @returns found element or undefined otherwise
6565 */
6566export function findLast(self: int[], predicate: () => boolean): Int | undefined {
6567    for (let i = self.length - 1; i >= 0; i--) {
6568        const val = self[i];
6569        if (predicate()) {
6570            return val;
6571        }
6572    }
6573    return undefined;
6574}
6575
6576/**
6577 * Iterates the array in reverse order and returns the index of
6578 * the first element that satisfies the provided testing function.
6579 * If no elements satisfy the testing function, -1 is returned.
6580 *
6581 * @param predicate testing function
6582 *
6583 * @returns index of first element satisfying to predicate, -1 if no such element
6584 */
6585export function findLastIndex(self: int[], predicate: () => boolean): number {
6586    for (let i = self.length - 1; i >= 0; i--) {
6587        if (predicate()) {
6588            return i
6589        }
6590    }
6591    return -1
6592}
6593
6594/**
6595 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6596 *
6597 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
6598 *
6599 * @returns `Array` instance, constructed from `this` and given function.
6600 */
6601export function map(self: int[], callbackfn: (value: int, index: number, array: int[]) => int): int[] {
6602    const len = self.length;
6603    let res = new int[len];
6604    for (let i = 0; i < len; i++) {
6605        res[i] = callbackfn(self[i], i as number, self);
6606    }
6607    return res;
6608}
6609
6610/**
6611 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6612 *
6613 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
6614 *
6615 * @returns `Array` instance, constructed from `this` and given function.
6616 */
6617export function map(self: int[], callbackfn: (value: int, index: number) => int): int[] {
6618    const len = self.length;
6619    let res = new int[len];
6620    for (let i = 0; i < len; i++) {
6621        res[i] = callbackfn(self[i], i as number);
6622    }
6623    return res;
6624}
6625
6626/**
6627 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6628 *
6629 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
6630 *
6631 * @returns `Array` instance, constructed from `this` and given function.
6632 */
6633export function map(self: int[], callbackfn: (value: int) => int): int[] {
6634    const len = self.length;
6635    let res = new int[len];
6636    for (let i = 0; i < len; i++) {
6637        res[i] = callbackfn(self[i]);
6638    }
6639    return res;
6640}
6641
6642/**
6643 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6644 *
6645 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
6646 *
6647 * @returns `Array` instance, constructed from `this` and given function.
6648 */
6649export function map(self: int[], callbackfn: () => int): int[] {
6650    const len = self.length;
6651    let res = new int[len];
6652    for (let i = 0; i < len; i++) {
6653        res[i] = callbackfn();
6654    }
6655    return res;
6656}
6657
6658/**
6659 * Constructs a new `Array` instance and populates it with
6660 * portion of a given array, filtered down to just the elements from the
6661 * given array that pass the test implemented by the provided function.
6662 *
6663 * @param fn test function, applied to each element of an array.
6664 *
6665 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
6666 */
6667export function filter(self: int[], fn: (v: int, k: number) => boolean): int[] {
6668    const mask = new boolean[self.length]
6669    let cnt = 0
6670
6671    for (let i: int = 0; i < self.length; i++) {
6672        const val = self[i];
6673        if (fn(val, i)) {
6674            mask[i] = true
6675            cnt++;
6676        }
6677    }
6678    const res = new int[cnt];
6679    let idx_store = 0;
6680    for (let i: int = 0; i < self.length; i++) {
6681        if (mask[i]) {
6682            res[idx_store++] = self[i]
6683        }
6684    }
6685    return res;
6686}
6687
6688export function concat(self: int[], fst: int[], ...more: int[][]): int[] {
6689    const lnMin = self.length + fst.length;
6690    let ln = lnMin;
6691    for (let i = 0; i < more.length; i++) {
6692        ln += more[i].length
6693    }
6694    const r = new int[ln];
6695    try {
6696        copyTo(self, r, 0, 0, self.length);
6697        copyTo(fst, r, self.length, 0, fst.length);
6698        let idx = lnMin;
6699        for (let i = 0; i < more.length; i++) {
6700            copyTo(more[i], r, idx, 0, more[i].length);
6701            idx += more[i].length;
6702        }
6703    } catch (e) {
6704        // impossible
6705    }
6706    return r
6707}
6708
6709/**
6710 * Reorders elements of `this` using comparator function.
6711 *
6712 * @param comparator function that defines the sort order.
6713 *
6714 * @note Mutating method
6715 */
6716export function sort(self: int[], comparator: (a: int, b: int) => number): int[] {
6717    sort_subarray(self, 0, self.length, (l: int, r: int): boolean => {
6718        return comparator(l, r ) < 0;
6719    });
6720    return self;
6721}
6722
6723/**
6724 * Reorders elements of `this` using comparator function.
6725 *
6726 * @param comparator function that defines the sort order.
6727 *
6728 * @note Mutating method
6729 */
6730export function sort(self: int[], ): int[] {
6731    sort(self, 0, self.length);
6732    return self;
6733}
6734
6735export function keys(self: int[]): IterableIterator<number> {
6736    return new BuiltinArrayKeysIterator(self.length);
6737}
6738
6739class ArrayValuesIterator_int implements IterableIterator<int> {
6740    private parent: int[]
6741    private idx: int = 0
6742
6743    constructor(parent: int[]) {
6744        this.parent = parent
6745    }
6746
6747    override next(): IteratorResult<int> {
6748        if (this.idx >= this.parent.length) {
6749            return new IteratorResult<int>()
6750        }
6751        return new IteratorResult<int>(this.parent[this.idx++])
6752    }
6753
6754    override $_iterator(): IterableIterator<int> {
6755        return this;
6756    }
6757
6758    public __Iterator_getLength(): int {
6759        return this.parent.length as int
6760    }
6761}
6762
6763class ArrayEntriesIterator_int implements IterableIterator<[number, int]> {
6764    private parent: int[]
6765    private idx: int = 0
6766
6767    constructor(parent: int[]) {
6768        this.parent = parent
6769    }
6770
6771    override next(): IteratorResult<[number, int]> {
6772        if (this.idx >= this.parent.length) {
6773            return new IteratorResult<[number, int]>()
6774        }
6775        const i = this.idx++;
6776        const vl: [number, int] = [i as number, this.parent[i]]
6777        return new IteratorResult<[number, int]>(vl);
6778    }
6779
6780    override $_iterator(): IterableIterator<[number, int]> {
6781        return this;
6782    }
6783
6784    public __Iterator_getLength(): int {
6785        return this.parent.length as int
6786    }
6787}
6788
6789function cloneArray(self: long[]): long[] {
6790    const ret = new long[self.length];;
6791    for (let i = 0; i < self.length; i++) {
6792        ret[i] = self[i];
6793    }
6794    return ret;
6795}
6796
6797/**
6798 * Takes an integer value and returns the item at that index,
6799 * allowing for positive and negative integers. Negative integers count back
6800 * from the last item in the array.
6801 *
6802 * @param index Zero-based index of the array element to be returned.
6803 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
6804 *
6805 * @returns The element in the array matching the given index.
6806 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
6807 */
6808export function at(self: long[], index: number): Long | undefined {
6809    return at(self, index as int)
6810}
6811
6812/**
6813 * Creates a new `Array` from this `Array` instance and given `Array` instance.
6814 *
6815 * @param other to concatenate into a new array.
6816 *
6817 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
6818 */
6819// export function concat(self: long[], ...items: (long | Concatlong[])[]): long[] {
6820//     throw new Error("not implemented")
6821// }
6822
6823export function concat(self: long[], ...items: ConcatArray<long>[]): long[] {
6824    let totalAdd = self.length;
6825    for (let i = 0; i < items.length; i++) {
6826        totalAdd += items[i].length as int
6827    }
6828
6829    const buf = new long[totalAdd];
6830
6831    for (let i = 0; i < self.length; i++) {
6832        buf[i] = self[i];
6833    }
6834
6835    let insertTo = self.length;
6836    for (let i = 0; i < items.length; i++) {
6837        const arr = items[i]
6838        const len = arr.length as int
6839        for (let j = 0; j < len; j++) {
6840            buf[insertTo++] = arr.$_get(j)
6841        }
6842    }
6843
6844    return buf;
6845}
6846
6847/**
6848 * Takes an integer value and returns the item at that index,
6849 * allowing for positive and negative integers. Negative integers count back
6850 * from the last item in the array.
6851 *
6852 * @param index Zero-based index of the array element to be returned.
6853 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
6854 *
6855 * @returns The element in the array matching the given index.
6856 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
6857 */
6858export function at(self: long[], index: int): Long | undefined {
6859    let len = self.length;
6860    let k: int;
6861    if (index >= 0) {
6862        k = index;
6863    } else {
6864        k = len + index;
6865    }
6866
6867    if (k < 0 || k >= len) {
6868        return undefined;
6869    }
6870
6871    return self[k];
6872}
6873
6874/**
6875 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6876 *
6877 * @param target index at which to copy the sequence
6878 *
6879 * @param start index at which to start copying elements from
6880 *
6881 * @param end index at which to end copying elements from
6882 *
6883 * @returns this array after transformation
6884 */
6885export function copyWithin(self: long[], target: number, start: number, end?: Number): long[] {
6886    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
6887    return self;
6888}
6889
6890/**
6891 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6892 *
6893 * @param target index at which to copy the sequence
6894 *
6895 * @param start index at which to start copying elements from
6896 *
6897 * @param end index at which to end copying elements from
6898 *
6899 * @returns this array after transformation
6900 */
6901export function copyWithin(self: long[], target: int, start: int, end: int): long[] {
6902    target = normalizeIndex(target, self.length)
6903    start = normalizeIndex(start, self.length)
6904    end = normalizeIndex(end, self.length)
6905
6906    if (end <= start) {
6907        return self;
6908    }
6909
6910    if (target <= start) {
6911        while (start < end) {
6912            const read = self[start++];
6913            self[target++] = read;
6914        }
6915    } else {
6916        let len = end - start;
6917        if (target + len > self.length) {
6918            len = self.length - target
6919        }
6920        for (let i = 0; i < len; i++) {
6921            const read = self[start + len - 1 - i];
6922            self[target + len - 1 - i] = read;
6923        }
6924    }
6925
6926    return self;
6927}
6928
6929/**
6930 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6931 *
6932 * @param target index at which to copy the sequence
6933 *
6934 * @param start index at which to start copying elements from
6935 *
6936 * @returns this array after transformation
6937 */
6938export function copyWithin(self: long[], target: int, start: int): long[] {
6939    copyWithin(self, target, start, self.length);
6940    return self;
6941}
6942
6943/**
6944 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6945 *
6946 * @param target index at which to copy the sequence
6947 *
6948 * @returns this array after transformation
6949 */
6950export function copyWithin(self: long[], target: int): long[] {
6951    copyWithin(self, target, 0, self.length);
6952    return self;
6953}
6954
6955/**
6956 * Changes all elements in the Array to a static value, from a start index to an end index
6957 *
6958 * @param value to fill the array with
6959 *
6960 * @param start index at which to start filling
6961 *
6962 * @param end index at which to end filling, but not including
6963 *
6964 * @returns this array after transformation
6965 */
6966export function fill(self: long[], value: long, start?: Number, end?: Number): long[] {
6967    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
6968    return self;
6969}
6970
6971/**
6972 * Changes all elements in the Array to a static value, from a start index to an end index
6973 *
6974 * @param value to fill the array with
6975 *
6976 * @param start index at which to start filling
6977 *
6978 * @param end index at which to end filling, but not including
6979 *
6980 * @returns this array after transformation
6981 */
6982export function fill(self: long[], value: long, start: int, end: int): long[] {
6983    start = normalizeIndex(start, self.length);
6984    end = normalizeIndex(end, self.length)
6985
6986    for (let i = start; i < end; i++) {
6987        self[i] = value;
6988    }
6989
6990    return self;
6991}
6992
6993/**
6994 * Returns the value of the first element in the array where predicate is true, and undefined
6995 * otherwise.
6996 *
6997 * @param predicate find calls predicate once for each element of the array, in ascending
6998 * order, until it finds one where predicate returns true. If such an element is found, find
6999 * immediately returns that element value. Otherwise, find returns undefined.
7000 *
7001 * @returns the value of the first element in the array or undefined
7002 */
7003export function find(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): Long | undefined {
7004    const res = findIndex(self, predicate)
7005    if (res == -1) {
7006        return undefined
7007    }
7008    return self[res as int];
7009}
7010
7011/**
7012 * Returns the index of the first element in the array where predicate is true, and -1
7013 * otherwise.
7014 *
7015 * @param predicate find calls predicate once for each element of the array, in ascending
7016 * order, until it finds one where predicate returns true. If such an element is found,
7017 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
7018 *
7019 * @returns found element index or -1 otherwise
7020 */
7021export function findIndex(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): number {
7022    for (let i = 0; i < self.length; i++) {
7023        if (predicate(self[i], i as number, self)) {
7024            return i;
7025        }
7026    }
7027    return -1;
7028}
7029
7030/**
7031 * Iterates the array in reverse order and returns the value of the first element
7032 * that satisfies the provided testing function
7033 *
7034 * @param predicate testing function
7035 *
7036 * @returns found element or undefined otherwise
7037 */
7038export function findLast(self: long[], predicate: (elem: long, index: number, array: long[]) => boolean): Long | undefined {
7039    for (let i = self.length - 1; i >= 0; i--) {
7040        const val = self[i];
7041        if (predicate(val, i as number, self)) {
7042            return val;
7043        }
7044    }
7045    return undefined;
7046}
7047
7048/**
7049 * Determines whether all the members of an array satisfy the specified test.
7050 *
7051 * @param predicate A function that accepts up to three arguments. The every method calls
7052 * the predicate function for each element in the array until the predicate returns a value
7053 * which is coercible to the Boolean value false, or until the end of the array.
7054 *
7055 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
7056 */
7057export function every(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): boolean {
7058    for (let i = 0; i < self.length; i++) {
7059        if (!predicate(self[i], i as number, self)) {
7060            return false
7061        }
7062    }
7063    return true;
7064}
7065
7066/**
7067 * Determines whether the specified callback function returns true for any element of an array.
7068 *
7069 * @param predicate A function that accepts up to three arguments. The some method calls
7070 * the predicate function for each element in the array until the predicate returns a value
7071 * which is coercible to the Boolean value true, or until the end of the array.
7072 *
7073 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
7074 */
7075export function some(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): boolean {
7076    for (let i = 0; i < self.length; i++) {
7077        if (predicate(self[i], i as number, self)) {
7078            return true
7079        }
7080    }
7081    return false
7082}
7083
7084/**
7085 * Returns the elements of an array that meet the condition specified in a callback function.
7086 *
7087 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
7088 *
7089 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
7090 */
7091export function filter(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): long[] {
7092    return filter(self, (value: long, index: number): boolean => predicate(value, index, self));
7093}
7094
7095/**
7096 * Iterates the array in reverse order and returns the index of
7097 * the first element that satisfies the provided testing function.
7098 * If no elements satisfy the testing function, -1 is returned.
7099 *
7100 * @param predicate testing function
7101 *
7102 * @returns index of first element satisfying to predicate, -1 if no such element
7103 */
7104export function findLastIndex(self: long[], predicate: (element: long, index: number, array: long[]) => boolean): number {
7105    for (let i = self.length - 1; i >= 0; i--) {
7106        if (predicate(self[i], i as number, self)) {
7107            return i
7108        }
7109    }
7110    return -1
7111}
7112
7113/**
7114 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7115 *
7116 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
7117 *
7118 * @returns a result after applying callbackfn over all elements of the Array
7119 */
7120export function reduce(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number, array: long[]) => long): long {
7121    if (self.length == 0) {
7122        throw new TypeError("Reduce of empty array with no initial value")
7123    }
7124    let acc: long = self[0];
7125    for (let i = 1; i < self.length; i++) {
7126        acc = callbackfn(acc, self[i], i as number, self)
7127    }
7128    return acc
7129}
7130
7131/**
7132 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7133 *
7134 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
7135 *
7136 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
7137 *
7138 * @returns a result after applying callbackfn over all elements of the Array
7139 */
7140export function reduce<U = long>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number, array: long[]) => U, initialValue: U): U {
7141    let acc = initialValue
7142    for (let i = 0; i < self.length; i++) {
7143        acc = callbackfn(acc, self[i], i as number, self)
7144    }
7145    return acc
7146}
7147
7148/**
7149 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7150 *
7151 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
7152 *
7153 * @returns a result after applying callbackfn over all elements of the Array
7154 */
7155export function reduceRight(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number, array: long[]) => long): long {
7156    if (self.length == 0) {
7157        throw new TypeError("Reduce of empty array with no initial value")
7158    }
7159    let acc: long = self[self.length - 1];
7160    for (let i = self.length - 2; i >= 0; i--) {
7161        acc = callbackfn(acc, self[i], i as number, self)
7162    }
7163    return acc
7164}
7165
7166/**
7167 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7168 *
7169 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
7170 *
7171 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
7172 *
7173 * @returns a result after applying callbackfn over all elements of the Array
7174 */
7175export function reduceRight<U>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number, array: long[]) => U, initialValue: U): U {
7176    let acc = initialValue
7177    for (let i = self.length - 1; i >= 0; i--) {
7178        acc = callbackfn(acc, self[i], i as number, self)
7179    }
7180    return acc
7181}
7182
7183/**
7184 * Performs the specified action for each element in an array.
7185 *
7186 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
7187 */
7188export function forEach(self: long[], callbackfn: (value: long, index: number, array: long[]) => void): void {
7189    const len0 = self.length;
7190    for (let i = 0; i < len0; i++) {
7191        callbackfn(self[i], i as number, self)
7192    }
7193}
7194
7195/**
7196 * Returns the value of the first element in the array where predicate is true, and undefined
7197 * otherwise.
7198 *
7199 * @param predicate find calls predicate once for each element of the array, in ascending
7200 * order, until it finds one where predicate returns true. If such an element is found, find
7201 * immediately returns that element value. Otherwise, find returns undefined.
7202 *
7203 * @returns the value of the first element in the array or undefined
7204 */
7205export function find(self: long[], predicate: (value: long, index: number) => boolean): Long | undefined {
7206    const res = findIndex(self, predicate)
7207    if (res == -1) {
7208        return undefined
7209    }
7210    return self[res as int];
7211}
7212
7213/**
7214 * Returns the index of the first element in the array where predicate is true, and -1
7215 * otherwise.
7216 *
7217 * @param predicate find calls predicate once for each element of the array, in ascending
7218 * order, until it finds one where predicate returns true. If such an element is found,
7219 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
7220 *
7221 * @returns found element index or -1 otherwise
7222 */
7223export function findIndex(self: long[], predicate: (value: long, index: number) => boolean): number {
7224    for (let i = 0; i < self.length; i++) {
7225        if (predicate(self[i], i as number)) {
7226            return i;
7227        }
7228    }
7229    return -1;
7230}
7231
7232/**
7233 * Iterates the array in reverse order and returns the value of the first element
7234 * that satisfies the provided testing function
7235 *
7236 * @param predicate testing function
7237 *
7238 * @returns found element or undefined otherwise
7239 */
7240export function findLast(self: long[], predicate: (elem: long, index: number) => boolean): Long | undefined {
7241    for (let i = self.length - 1; i >= 0; i--) {
7242        const val = self[i];
7243        if (predicate(val, i as number)) {
7244            return val;
7245        }
7246    }
7247    return undefined;
7248}
7249
7250/**
7251 * Determines whether all the members of an array satisfy the specified test.
7252 *
7253 * @param predicate A function that accepts up to three arguments. The every method calls
7254 * the predicate function for each element in the array until the predicate returns a value
7255 * which is coercible to the Boolean value false, or until the end of the array.
7256 *
7257 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
7258 */
7259export function every(self: long[], predicate: (value: long, index: number) => boolean): boolean {
7260    for (let i = 0; i < self.length; i++) {
7261        if (!predicate(self[i], i as number)) {
7262            return false
7263        }
7264    }
7265    return true;
7266}
7267
7268/**
7269 * Determines whether the specified callback function returns true for any element of an array.
7270 *
7271 * @param predicate A function that accepts up to three arguments. The some method calls
7272 * the predicate function for each element in the array until the predicate returns a value
7273 * which is coercible to the Boolean value true, or until the end of the array.
7274 *
7275 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
7276 */
7277export function some(self: long[], predicate: (value: long, index: number) => boolean): boolean {
7278    for (let i = 0; i < self.length; i++) {
7279        if (predicate(self[i], i as number)) {
7280            return true
7281        }
7282    }
7283    return false
7284}
7285
7286/**
7287 * Iterates the array in reverse order and returns the index of
7288 * the first element that satisfies the provided testing function.
7289 * If no elements satisfy the testing function, -1 is returned.
7290 *
7291 * @param predicate testing function
7292 *
7293 * @returns index of first element satisfying to predicate, -1 if no such element
7294 */
7295export function findLastIndex(self: long[], predicate: (element: long, index: number) => boolean): number {
7296    for (let i = self.length - 1; i >= 0; i--) {
7297        if (predicate(self[i], i as number)) {
7298            return i
7299        }
7300    }
7301    return -1
7302}
7303
7304/**
7305 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7306 *
7307 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
7308 *
7309 * @returns a result after applying callbackfn over all elements of the Array
7310 */
7311export function reduce(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number) => long): long {
7312    if (self.length == 0) {
7313        throw new TypeError("Reduce of empty array with no initial value")
7314    }
7315    let acc: long = self[0];
7316    for (let i = 1; i < self.length; i++) {
7317        acc = callbackfn(acc, self[i], i as number)
7318    }
7319    return acc
7320}
7321
7322/**
7323 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7324 *
7325 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
7326 *
7327 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
7328 *
7329 * @returns a result after applying callbackfn over all elements of the Array
7330 */
7331export function reduce<U = long>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number) => U, initialValue: U): U {
7332    let acc = initialValue
7333    for (let i = 0; i < self.length; i++) {
7334        acc = callbackfn(acc, self[i], i as number)
7335    }
7336    return acc
7337}
7338
7339/**
7340 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7341 *
7342 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
7343 *
7344 * @returns a result after applying callbackfn over all elements of the Array
7345 */
7346export function reduceRight(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number) => long): long {
7347    if (self.length == 0) {
7348        throw new TypeError("Reduce of empty array with no initial value")
7349    }
7350    let acc: long = self[self.length - 1];
7351    for (let i = self.length - 2; i >= 0; i--) {
7352        acc = callbackfn(acc, self[i], i as number)
7353    }
7354    return acc
7355}
7356
7357/**
7358 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7359 *
7360 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
7361 *
7362 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
7363 *
7364 * @returns a result after applying callbackfn over all elements of the Array
7365 */
7366export function reduceRight<U>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number) => U, initialValue: U): U {
7367    let acc = initialValue
7368    for (let i = self.length - 1; i >= 0; i--) {
7369        acc = callbackfn(acc, self[i], i as number)
7370    }
7371    return acc
7372}
7373
7374/**
7375 * Performs the specified action for each element in an array.
7376 *
7377 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
7378 */
7379export function forEach(self: long[], callbackfn: (value: long, index: number) => void): void {
7380    const len0 = self.length;
7381    for (let i = 0; i < len0; i++) {
7382        callbackfn(self[i], i as number)
7383    }
7384}
7385
7386/**
7387 * Returns the value of the first element in the array where predicate is true, and undefined
7388 * otherwise.
7389 *
7390 * @param predicate find calls predicate once for each element of the array, in ascending
7391 * order, until it finds one where predicate returns true. If such an element is found, find
7392 * immediately returns that element value. Otherwise, find returns undefined.
7393 *
7394 * @returns the value of the first element in the array or undefined
7395 */
7396export function find(self: long[], predicate: (value: long) => boolean): Long | undefined {
7397    const res = findIndex(self, predicate)
7398    if (res == -1) {
7399        return undefined
7400    }
7401    return self[res as int];
7402}
7403
7404/**
7405 * Returns the index of the first element in the array where predicate is true, and -1
7406 * otherwise.
7407 *
7408 * @param predicate find calls predicate once for each element of the array, in ascending
7409 * order, until it finds one where predicate returns true. If such an element is found,
7410 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
7411 *
7412 * @returns found element index or -1 otherwise
7413 */
7414export function findIndex(self: long[], predicate: (value: long) => boolean): number {
7415    for (let i = 0; i < self.length; i++) {
7416        if (predicate(self[i])) {
7417            return i;
7418        }
7419    }
7420    return -1;
7421}
7422
7423/**
7424 * Iterates the array in reverse order and returns the value of the first element
7425 * that satisfies the provided testing function
7426 *
7427 * @param predicate testing function
7428 *
7429 * @returns found element or undefined otherwise
7430 */
7431export function findLast(self: long[], predicate: (elem: long) => boolean): Long | undefined {
7432    for (let i = self.length - 1; i >= 0; i--) {
7433        const val = self[i];
7434        if (predicate(val)) {
7435            return val;
7436        }
7437    }
7438    return undefined;
7439}
7440
7441/**
7442 * Determines whether all the members of an array satisfy the specified test.
7443 *
7444 * @param predicate A function that accepts up to three arguments. The every method calls
7445 * the predicate function for each element in the array until the predicate returns a value
7446 * which is coercible to the Boolean value false, or until the end of the array.
7447 *
7448 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
7449 */
7450export function every(self: long[], predicate: (value: long) => boolean): boolean {
7451    for (let i = 0; i < self.length; i++) {
7452        if (!predicate(self[i])) {
7453            return false
7454        }
7455    }
7456    return true;
7457}
7458
7459/**
7460 * Determines whether the specified callback function returns true for any element of an array.
7461 *
7462 * @param predicate A function that accepts up to three arguments. The some method calls
7463 * the predicate function for each element in the array until the predicate returns a value
7464 * which is coercible to the Boolean value true, or until the end of the array.
7465 *
7466 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
7467 */
7468export function some(self: long[], predicate: (value: long) => boolean): boolean {
7469    for (let i = 0; i < self.length; i++) {
7470        if (predicate(self[i])) {
7471            return true
7472        }
7473    }
7474    return false
7475}
7476
7477/**
7478 * Returns the elements of an array that meet the condition specified in a callback function.
7479 *
7480 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
7481 *
7482 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
7483 */
7484export function filter(self: long[], predicate: (value: long) => boolean): long[] {
7485    return filter(self, (value: long, index: number): boolean => predicate(value));
7486}
7487
7488/**
7489 * Iterates the array in reverse order and returns the index of
7490 * the first element that satisfies the provided testing function.
7491 * If no elements satisfy the testing function, -1 is returned.
7492 *
7493 * @param predicate testing function
7494 *
7495 * @returns index of first element satisfying to predicate, -1 if no such element
7496 */
7497export function findLastIndex(self: long[], predicate: (element: long) => boolean): number {
7498    for (let i = self.length - 1; i >= 0; i--) {
7499        if (predicate(self[i])) {
7500            return i
7501        }
7502    }
7503    return -1
7504}
7505
7506/**
7507 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7508 *
7509 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
7510 *
7511 * @returns a result after applying callbackfn over all elements of the Array
7512 */
7513export function reduce(self: long[], callbackfn: (previousValue: long, currentValue: long) => long): long {
7514    if (self.length == 0) {
7515        throw new TypeError("Reduce of empty array with no initial value")
7516    }
7517    let acc: long = self[0];
7518    for (let i = 1; i < self.length; i++) {
7519        acc = callbackfn(acc, self[i])
7520    }
7521    return acc
7522}
7523
7524/**
7525 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7526 *
7527 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
7528 *
7529 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
7530 *
7531 * @returns a result after applying callbackfn over all elements of the Array
7532 */
7533export function reduce<U = long>(self: long[], callbackfn: (previousValue: U, currentValue: long) => U, initialValue: U): U {
7534    let acc = initialValue
7535    for (let i = 0; i < self.length; i++) {
7536        acc = callbackfn(acc, self[i])
7537    }
7538    return acc
7539}
7540
7541/**
7542 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7543 *
7544 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
7545 *
7546 * @returns a result after applying callbackfn over all elements of the Array
7547 */
7548export function reduceRight(self: long[], callbackfn: (previousValue: long, currentValue: long) => long): long {
7549    if (self.length == 0) {
7550        throw new TypeError("Reduce of empty array with no initial value")
7551    }
7552    let acc: long = self[self.length - 1];
7553    for (let i = self.length - 2; i >= 0; i--) {
7554        acc = callbackfn(acc, self[i])
7555    }
7556    return acc
7557}
7558
7559/**
7560 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
7561 *
7562 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
7563 *
7564 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
7565 *
7566 * @returns a result after applying callbackfn over all elements of the Array
7567 */
7568export function reduceRight<U>(self: long[], callbackfn: (previousValue: U, currentValue: long) => U, initialValue: U): U {
7569    let acc = initialValue
7570    for (let i = self.length - 1; i >= 0; i--) {
7571        acc = callbackfn(acc, self[i])
7572    }
7573    return acc
7574}
7575
7576/**
7577 * Performs the specified action for each element in an array.
7578 *
7579 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
7580 */
7581export function forEach(self: long[], callbackfn: (value: long) => void): void {
7582    const len0 = self.length;
7583    for (let i = 0; i < len0; i++) {
7584        callbackfn(self[i])
7585    }
7586}
7587
7588/**
7589 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
7590 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
7591 *
7592 * @param start zero-based index at which to start extraction
7593 *
7594 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
7595 *
7596 * @returns `Array` instance, constructed from extracted elements of `this` instance.
7597 */
7598export function slice(self: long[], start?: Number, end?: Number): long[] {
7599    const len: int = self.length;
7600    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
7601}
7602
7603/**
7604 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
7605 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
7606 *
7607 * @param start zero-based index at which to start extraction
7608 *
7609 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
7610 *
7611 * @returns `Array` instance, constructed from extracted elements of `this` instance.
7612 */
7613export function slice(self: long[], start: int, end: int): long[] {
7614    const len: int = self.length;
7615    const relStart = normalizeIndex(start, len)
7616    const relEnd = normalizeIndex(end, len)
7617
7618    let count = relEnd - relStart;
7619    if (count < 0) {
7620        count = 0;
7621    }
7622    let res = new long[count]
7623    for (let i = 0; i < count; i++) {
7624        res[i] = self[relStart + i];
7625    }
7626
7627    return res
7628}
7629
7630/**
7631 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
7632 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
7633 *
7634 * @param start zero-based index at which to start extraction
7635 *
7636 * @returns `Array` instance, constructed from extracted elements of `this` instance.
7637 */
7638export function slice(self: long[], start: int): long[] {
7639    return slice(self, start, Int.MAX_VALUE as int);
7640}
7641
7642/**
7643 * Returns the last index at which a given element can be found in the array,
7644 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
7645 *
7646 * @param element element to locate in the array.
7647 * @param fromIndex zero-based index at which to start searching backwards.
7648 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
7649 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
7650 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
7651 *
7652 * @returns The last index of the element in the array; -1 if not found.
7653 */
7654export function lastIndexOf(self: long[], element: long, fromIndex: int): int {
7655    if (self.length == 0) {
7656        return -1;
7657    }
7658    let n = fromIndex;
7659    let k: int;
7660    if (n >= 0) {
7661        k = min(self.length - 1, n);
7662    } else {
7663        k = self.length + n;
7664    }
7665
7666    while (k >= 0) {
7667        if (__runtimeEquals(self[k], element)) {
7668            return k;
7669        }
7670        k--;
7671    }
7672    return -1;
7673}
7674
7675/**
7676 * Returns the last index at which a given element can be found in the array,
7677 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
7678 *
7679 * @param element element to locate in the array.
7680 * @param fromIndex zero-based index at which to start searching backwards.
7681 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
7682 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
7683 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
7684 *
7685 * @returns The last index of the element in the array; -1 if not found.
7686 */
7687export function lastIndexOf(self: long[], element: long, fromIndex?: Number): number {
7688    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
7689}
7690
7691/**
7692 * Creates and returns a new string by concatenating all of the elements in an `Array`,
7693 * separated by a specified separator string.
7694 * If the array has only one item, then that item will be returned without using the separator.
7695 *
7696 * @param sep specifies a separator
7697 *
7698 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
7699 */
7700export function join(self: long[], sep?: String): string {
7701    if (self.length == 0) {
7702        return ""
7703    }
7704    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
7705    let sb = new StringBuilder(new String(self[0]))
7706    for (let i: int = 1; i < self.length; i++) {
7707        const tmp = self[i]
7708        sb.append(sepReal);
7709        sb.append(tmp)
7710    }
7711
7712    return sb.toString();
7713}
7714
7715/**
7716 * Returns a string representing the specified array and its elements.
7717 *
7718 * @returns string representation
7719 */
7720export function toString(self: long[], ): string {
7721    return join(self, ",");
7722}
7723
7724/**
7725 * Returns a locale string representing the specified array and its elements.
7726 *
7727 * @param locales
7728 *
7729 * @param options
7730 *
7731 * @returns string representation
7732 */
7733export function toLocaleString(self: long[], locales: Object, options: Object): string {
7734    throw new Error("Array.toLocaleString: not implemented")
7735}
7736
7737/**
7738 * Returns a locale string representing the specified array and its elements.
7739 *
7740 * @param options
7741 *
7742 * @returns string representation
7743 */
7744export function toLocaleString(self: long[], locales: Object): string {
7745    return toLocaleString(self, new Object(), new Object())
7746}
7747
7748/**
7749 * Returns a locale string representing the specified array and its elements.
7750 *
7751 * @returns string representation
7752 */
7753export function toLocaleString(self: long[], ): string {
7754    const sb = new StringBuilder()
7755    const len = self.length;
7756    for (let i = 0; i < len; i++) {
7757        if (i != 0) {
7758            sb.append(",")
7759        }
7760        let x = self[i] as NullishType;
7761        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
7762            sb.append(x!.toLocaleString())
7763        }
7764    }
7765    return sb.toString()
7766}
7767
7768/**
7769 * Copying version of the splice() method.
7770 *
7771 * @param start index
7772 *
7773 * @param delete number of items after start index
7774 *
7775 * @returns a new Array with some elements removed and/or replaced at a given index.
7776 */
7777export function toSpliced(self: long[], start?: Number, delete?: Number): long[] {
7778    const len = self.length;
7779    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
7780}
7781
7782/**
7783 * Copying version of the splice() method.
7784 *
7785 * @param start index
7786 *
7787 * @param delete number of items after start index
7788 *
7789 * @returns a new Array with some elements removed and/or replaced at a given index.
7790 */
7791export function toSpliced(self: long[], start: number, delete: number, ...items: long[]): long[] {
7792    const len = self.length;
7793    return toSpliced(self, start as int, delete as int, ...items)
7794}
7795
7796/**
7797 * Copying version of the splice() method.
7798 *
7799 * @param start index
7800 *
7801 * @param delete number of items after start index
7802 *
7803 * @returns a new Array with some elements removed and/or replaced at a given index.
7804 */
7805export function toSpliced(self: long[], start: int, delete: int, ...items: long[]): long[] {
7806    const len = self.length;
7807    start = normalizeIndex(start, len);
7808    if (delete < 0) {
7809        delete = 0;
7810    } else if (delete > len) {
7811        delete = len;
7812    }
7813    if (start > len - delete) {
7814        delete = len - start
7815    }
7816    const res = new long[len - delete + items.length];
7817    for (let i = 0; i < start; i++) {
7818        res[i] = self[i]
7819    }
7820    for (let i = 0; i < items.length; i++) {
7821        res[start + i] = items[i]
7822    }
7823    for (let i = start + delete; i < len; i++) {
7824        res[i - delete + items.length] = self[i]
7825    }
7826    return res;
7827}
7828
7829/**
7830 * Copying version of the splice() method.
7831 *
7832 * @param start index
7833 *
7834 * @returns a new Array with some elements removed and/or replaced at a given index.
7835 */
7836export function toSpliced(self: long[], start: int): long[] {
7837    return toSpliced(self, start, self.length)
7838}
7839
7840/**
7841 * Checks whether an Array includes a certain value among its entries,
7842 * returning true or false as appropriate.
7843 *
7844 * @param val value to search
7845 *
7846 * @param fromIndex start index
7847 *
7848 * @returns true if val is in Array
7849 */
7850export function includes(self: long[], val: long, fromIndex?: Number): boolean {
7851    const len = self.length;
7852    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
7853    for (let i = fi; i < len; i++) {
7854        if (val == self[i]) {
7855            return true;
7856        }
7857    }
7858    return false;
7859}
7860
7861/**
7862 * Returns the first index at which a given element
7863 * can be found in the array, or -1 if it is not present.
7864 *
7865 * @param val value to search
7866 *
7867 * @param fromIndex index to search from
7868 *
7869 * @returns index of val, -1 otherwise
7870 */
7871export function indexOf(self: long[], val: long, fromIndex: int): int {
7872    fromIndex = normalizeIndex(fromIndex, self.length)
7873    for (let i = fromIndex; i < self.length; i++) {
7874        if (__runtimeEquals(val, self[i])) {
7875            return i
7876        }
7877    }
7878    return -1
7879}
7880
7881/**
7882 * Returns the first index at which a given element
7883 * can be found in the array, or -1 if it is not present.
7884 *
7885 * @param val value to search
7886 *
7887 * @param fromIndex index to search from
7888 *
7889 * @returns index of val, -1 otherwise
7890 */
7891export function indexOf(self: long[], val: long, fromIndex?: Number): number {
7892    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
7893}
7894
7895/**
7896 * Copying version of the sort() method.
7897 * It returns a new array with the elements sorted in ascending order.
7898 *
7899 * @returns sorted copy of hte current instance using default comparator
7900 */
7901export function toSorted(self: long[], ): long[] {
7902    let arr = cloneArray(self);
7903    sort(arr, )
7904    return arr
7905}
7906
7907/**
7908 * Copying version of the sort() method.
7909 * It returns a new array with the elements sorted in ascending order.
7910 *
7911 * @param comparator function to compare to elements of the Array
7912 *
7913 * @returns sorted copy of the current instance comparator
7914 */
7915export function toSorted(self: long[], comparator: (a: long, b: long) => number): long[] {
7916    let arr = cloneArray(self);
7917    sort(arr, comparator)
7918    return arr
7919}
7920
7921/**
7922 * Modifies `this` instance of `Array` class and populates
7923 * it with same elements ordered towards the direction opposite to that previously stated.
7924 *
7925 * @note Mutating method
7926 */
7927export function reverse(self: long[], ): long[] {
7928    for (let i = 0; i < self.length / 2; i++) {
7929        const tmp = self[i];
7930        const idx_r = self.length - 1 - i;
7931        const val_r = self[idx_r];
7932        self[i] = val_r;
7933        self[idx_r] = tmp;
7934    }
7935    return self;
7936}
7937
7938/**
7939 * Copying version of the reverse() method.
7940 * It returns a new array with the elements in reversed order.
7941 *
7942 * @returns reversed copy of the current Array
7943 */
7944export function toReversed(self: long[], ): long[] {
7945    let arr = new long[self.length]
7946    for (let i = 0; i < self.length; i++) {
7947        arr[self.length - 1 - i] = self[i]
7948    }
7949    return arr
7950}
7951
7952/**
7953 * Copying version of using the bracket notation to change the value of a given index.
7954 * It returns a new Array with the element at the given index replaced with the given value.
7955 *
7956 * @param index to replace
7957 *
7958 * @param value new value
7959 *
7960 * @returns a new Array with the element at the given index replaced with the given value
7961 */
7962export function with(self: long[], index: number, value: long): long[] {
7963    return with(self, index as int, value)
7964}
7965
7966/**
7967 * Copying version of using the bracket notation to change the value of a given index.
7968 * It returns a new Array with the element at the given index replaced with the given value.
7969 *
7970 * @param index to replace
7971 *
7972 * @param value new value
7973 *
7974 * @returns a new Array with the element at the given index replaced with the given value
7975 */
7976export function with(self: long[], index: int, value: long): long[] {
7977    if (index < 0) {
7978        index += self.length;
7979    }
7980    if (index >= self.length) {
7981        throw new RangeError("Invalid index")
7982    }
7983    let arr = cloneArray(self);
7984    arr[index] = value;
7985    return arr
7986}
7987
7988/**
7989 * Returns an iterator over all values
7990 */
7991export function values(self: long[], ): IterableIterator<long> {
7992    return new ArrayValuesIterator_long(self);
7993}
7994
7995/**
7996 * Returns an iterable of key, value pairs for every entry in the array
7997 */
7998export function entries(self: long[], ): IterableIterator<[number, long]> {
7999    return new ArrayEntriesIterator_long(self);
8000}
8001
8002/**
8003 * Determines whether all the members of an array satisfy the specified test.
8004 *
8005 * @param predicate A function that accepts up to three arguments. The every method calls
8006 * the predicate function for each element in the array until the predicate returns a value
8007 * which is coercible to the Boolean value false, or until the end of the array.
8008 *
8009 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
8010 */
8011export function every(self: long[], predicate: () => boolean): boolean {
8012    for (let i = 0; i < self.length; i++) {
8013        if (!predicate()) {
8014            return false
8015        }
8016    }
8017    return true
8018}
8019
8020/**
8021 * Returns the elements of an array that meet the condition specified in a callback function.
8022 *
8023 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
8024 *
8025 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
8026 */
8027export function filter(self: long[], predicate: () => boolean): long[] {
8028    return filter(self, (value: long, index: number): boolean => predicate());
8029}
8030
8031/**
8032 * Returns the value of the first element in the array where predicate is true, and undefined
8033 * otherwise.
8034 *
8035 * @param predicate find calls predicate once for each element of the array, in ascending
8036 * order, until it finds one where predicate returns true. If such an element is found, find
8037 * immediately returns that element value. Otherwise, find returns undefined.
8038 *
8039 * @returns the value of the first element in the array or undefined
8040 */
8041export function find(self: long[], predicate: () => boolean): Long | undefined {
8042    const res = findIndex(self, predicate)
8043    if (res == -1) {
8044        return undefined
8045    }
8046    return self[res as int];
8047}
8048
8049/**
8050 * Returns the index of the first element in the array where predicate is true, and -1
8051 * otherwise.
8052 *
8053 * @param predicate find calls predicate once for each element of the array, in ascending
8054 * order, until it finds one where predicate returns true. If such an element is found,
8055 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
8056 *
8057 * @returns found element index or -1 otherwise
8058 */
8059export function findIndex(self: long[], predicate: () => boolean): number {
8060    for (let i = 0; i < self.length; i++) {
8061        if (predicate()) {
8062            return i;
8063        }
8064    }
8065    return -1;
8066}
8067
8068/**
8069 * Performs the specified action for each element in an array.
8070 *
8071 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
8072 */
8073export function forEach(self: long[], callbackfn: () => void): void {
8074    const len0 = self.length;
8075    for (let i = 0; i < len0; i++) {
8076        callbackfn()
8077    }
8078}
8079
8080/**
8081 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8082 *
8083 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
8084 *
8085 * @returns a result after applying callbackfn over all elements of the Array
8086 */
8087export function reduce(self: long[], callbackfn: (previousValue: long) => long): long {
8088    if (self.length == 0) {
8089        throw new TypeError("Reduce of empty array with no initial value")
8090    }
8091    let acc: long = self[0];
8092    for (let i = 1; i < self.length; i++) {
8093        acc = callbackfn(acc)
8094    }
8095    return acc
8096}
8097
8098/**
8099 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8100 *
8101 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
8102 *
8103 * @returns a result after applying callbackfn over all elements of the Array
8104 */
8105export function reduce(self: long[], callbackfn: () => long): long {
8106    if (self.length == 0) {
8107        throw new TypeError("Reduce of empty array with no initial value")
8108    }
8109    let acc: long = self[0];
8110    for (let i = 1; i < self.length; i++) {
8111        acc = callbackfn()
8112    }
8113    return acc
8114}
8115
8116/**
8117 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8118 *
8119 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
8120 *
8121 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
8122 *
8123 * @returns a result after applying callbackfn over all elements of the Array
8124 */
8125export function reduce<U = long>(self: long[], callbackfn: (previousValue: U) => U, initialValue: U): U {
8126    let acc = initialValue
8127    for (let i = 0; i < self.length; i++) {
8128        acc = callbackfn(acc)
8129    }
8130    return acc
8131}
8132
8133/**
8134 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8135 *
8136 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
8137 *
8138 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
8139 *
8140 * @returns a result after applying callbackfn over all elements of the Array
8141 */
8142export function reduce<U = long>(self: long[], callbackfn: () => U, initialValue: U): U {
8143    let acc = initialValue
8144    for (let i = 0; i < self.length; i++) {
8145        acc = callbackfn()
8146    }
8147    return acc
8148}
8149
8150/**
8151 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8152 *
8153 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
8154 *
8155 * @returns a result after applying callbackfn over all elements of the Array
8156 */
8157export function reduceRight(self: long[], callbackfn: (previousValue: long) => long): long {
8158    if (self.length == 0) {
8159        throw new TypeError("Reduce of empty array with no initial value")
8160    }
8161    let acc: long = self[self.length - 1];
8162    for (let i = self.length - 2; i >= 0; i--) {
8163        acc = callbackfn(acc)
8164    }
8165    return acc
8166}
8167
8168/**
8169 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8170 *
8171 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
8172 *
8173 * @returns a result after applying callbackfn over all elements of the Array
8174 */
8175export function reduceRight(self: long[], callbackfn: () => long): long {
8176    if (self.length == 0) {
8177        throw new TypeError("Reduce of empty array with no initial value")
8178    }
8179    let acc: long = self[self.length - 1];
8180    for (let i = self.length - 2; i >= 0; i--) {
8181        acc = callbackfn()
8182    }
8183    return acc
8184}
8185
8186/**
8187 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8188 *
8189 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
8190 *
8191 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
8192 *
8193 * @returns a result after applying callbackfn over all elements of the Array
8194 */
8195export function reduceRight<U>(self: long[], callbackfn: (previousValue: U) => U, initialValue: U): U {
8196    let acc = initialValue
8197    for (let i = self.length - 1; i >= 0; i--) {
8198        acc = callbackfn(acc)
8199    }
8200    return acc
8201}
8202
8203/**
8204 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8205 *
8206 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
8207 *
8208 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
8209 *
8210 * @returns a result after applying callbackfn over all elements of the Array
8211 */
8212export function reduceRight<U>(self: long[], callbackfn: () => U, initialValue: U): U {
8213    let acc = initialValue
8214    for (let i = self.length - 1; i >= 0; i--) {
8215        acc = callbackfn()
8216    }
8217    return acc
8218}
8219
8220/**
8221 * Determines whether the specified callback function returns true for any element of an array.
8222 *
8223 * @param predicate A function that accepts up to three arguments. The some method calls
8224 * the predicate function for each element in the array until the predicate returns a value
8225 * which is coercible to the Boolean value true, or until the end of the array.
8226 *
8227 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
8228 */
8229export function some(self: long[], predicate: () => boolean): boolean {
8230    for (let i = 0; i < self.length; i++) {
8231        if (predicate()) {
8232            return true
8233        }
8234    }
8235    return false
8236}
8237
8238/**
8239 * Iterates the array in reverse order and returns the value of the first element
8240 * that satisfies the provided testing function
8241 *
8242 * @param predicate testing function
8243 *
8244 * @returns found element or undefined otherwise
8245 */
8246export function findLast(self: long[], predicate: () => boolean): Long | undefined {
8247    for (let i = self.length - 1; i >= 0; i--) {
8248        const val = self[i];
8249        if (predicate()) {
8250            return val;
8251        }
8252    }
8253    return undefined;
8254}
8255
8256/**
8257 * Iterates the array in reverse order and returns the index of
8258 * the first element that satisfies the provided testing function.
8259 * If no elements satisfy the testing function, -1 is returned.
8260 *
8261 * @param predicate testing function
8262 *
8263 * @returns index of first element satisfying to predicate, -1 if no such element
8264 */
8265export function findLastIndex(self: long[], predicate: () => boolean): number {
8266    for (let i = self.length - 1; i >= 0; i--) {
8267        if (predicate()) {
8268            return i
8269        }
8270    }
8271    return -1
8272}
8273
8274/**
8275 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
8276 *
8277 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
8278 *
8279 * @returns `Array` instance, constructed from `this` and given function.
8280 */
8281export function map(self: long[], callbackfn: (value: long, index: number, array: long[]) => long): long[] {
8282    const len = self.length;
8283    let res = new long[len];
8284    for (let i = 0; i < len; i++) {
8285        res[i] = callbackfn(self[i], i as number, self);
8286    }
8287    return res;
8288}
8289
8290/**
8291 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
8292 *
8293 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
8294 *
8295 * @returns `Array` instance, constructed from `this` and given function.
8296 */
8297export function map(self: long[], callbackfn: (value: long, index: number) => long): long[] {
8298    const len = self.length;
8299    let res = new long[len];
8300    for (let i = 0; i < len; i++) {
8301        res[i] = callbackfn(self[i], i as number);
8302    }
8303    return res;
8304}
8305
8306/**
8307 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
8308 *
8309 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
8310 *
8311 * @returns `Array` instance, constructed from `this` and given function.
8312 */
8313export function map(self: long[], callbackfn: (value: long) => long): long[] {
8314    const len = self.length;
8315    let res = new long[len];
8316    for (let i = 0; i < len; i++) {
8317        res[i] = callbackfn(self[i]);
8318    }
8319    return res;
8320}
8321
8322/**
8323 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
8324 *
8325 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
8326 *
8327 * @returns `Array` instance, constructed from `this` and given function.
8328 */
8329export function map(self: long[], callbackfn: () => long): long[] {
8330    const len = self.length;
8331    let res = new long[len];
8332    for (let i = 0; i < len; i++) {
8333        res[i] = callbackfn();
8334    }
8335    return res;
8336}
8337
8338/**
8339 * Constructs a new `Array` instance and populates it with
8340 * portion of a given array, filtered down to just the elements from the
8341 * given array that pass the test implemented by the provided function.
8342 *
8343 * @param fn test function, applied to each element of an array.
8344 *
8345 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
8346 */
8347export function filter(self: long[], fn: (v: long, k: number) => boolean): long[] {
8348    const mask = new boolean[self.length]
8349    let cnt = 0
8350
8351    for (let i: int = 0; i < self.length; i++) {
8352        const val = self[i];
8353        if (fn(val, i)) {
8354            mask[i] = true
8355            cnt++;
8356        }
8357    }
8358    const res = new long[cnt];
8359    let idx_store = 0;
8360    for (let i: int = 0; i < self.length; i++) {
8361        if (mask[i]) {
8362            res[idx_store++] = self[i]
8363        }
8364    }
8365    return res;
8366}
8367
8368export function concat(self: long[], fst: long[], ...more: long[][]): long[] {
8369    const lnMin = self.length + fst.length;
8370    let ln = lnMin;
8371    for (let i = 0; i < more.length; i++) {
8372        ln += more[i].length
8373    }
8374    const r = new long[ln];
8375    try {
8376        copyTo(self, r, 0, 0, self.length);
8377        copyTo(fst, r, self.length, 0, fst.length);
8378        let idx = lnMin;
8379        for (let i = 0; i < more.length; i++) {
8380            copyTo(more[i], r, idx, 0, more[i].length);
8381            idx += more[i].length;
8382        }
8383    } catch (e) {
8384        // impossible
8385    }
8386    return r
8387}
8388
8389/**
8390 * Reorders elements of `this` using comparator function.
8391 *
8392 * @param comparator function that defines the sort order.
8393 *
8394 * @note Mutating method
8395 */
8396export function sort(self: long[], comparator: (a: long, b: long) => number): long[] {
8397    sort_subarray(self, 0, self.length, (l: long, r: long): boolean => {
8398        return comparator(l, r ) < 0;
8399    });
8400    return self;
8401}
8402
8403/**
8404 * Reorders elements of `this` using comparator function.
8405 *
8406 * @param comparator function that defines the sort order.
8407 *
8408 * @note Mutating method
8409 */
8410export function sort(self: long[], ): long[] {
8411    sort(self, 0, self.length);
8412    return self;
8413}
8414
8415export function keys(self: long[]): IterableIterator<number> {
8416    return new BuiltinArrayKeysIterator(self.length);
8417}
8418
8419class ArrayValuesIterator_long implements IterableIterator<long> {
8420    private parent: long[]
8421    private idx: int = 0
8422
8423    constructor(parent: long[]) {
8424        this.parent = parent
8425    }
8426
8427    override next(): IteratorResult<long> {
8428        if (this.idx >= this.parent.length) {
8429            return new IteratorResult<long>()
8430        }
8431        return new IteratorResult<long>(this.parent[this.idx++])
8432    }
8433
8434    override $_iterator(): IterableIterator<long> {
8435        return this;
8436    }
8437
8438    public __Iterator_getLength(): int {
8439        return this.parent.length as int
8440    }
8441}
8442
8443class ArrayEntriesIterator_long implements IterableIterator<[number, long]> {
8444    private parent: long[]
8445    private idx: int = 0
8446
8447    constructor(parent: long[]) {
8448        this.parent = parent
8449    }
8450
8451    override next(): IteratorResult<[number, long]> {
8452        if (this.idx >= this.parent.length) {
8453            return new IteratorResult<[number, long]>()
8454        }
8455        const i = this.idx++;
8456        const vl: [number, long] = [i as number, this.parent[i]]
8457        return new IteratorResult<[number, long]>(vl);
8458    }
8459
8460    override $_iterator(): IterableIterator<[number, long]> {
8461        return this;
8462    }
8463
8464    public __Iterator_getLength(): int {
8465        return this.parent.length as int
8466    }
8467}
8468
8469function cloneArray(self: float[]): float[] {
8470    const ret = new float[self.length];;
8471    for (let i = 0; i < self.length; i++) {
8472        ret[i] = self[i];
8473    }
8474    return ret;
8475}
8476
8477/**
8478 * Takes an integer value and returns the item at that index,
8479 * allowing for positive and negative integers. Negative integers count back
8480 * from the last item in the array.
8481 *
8482 * @param index Zero-based index of the array element to be returned.
8483 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
8484 *
8485 * @returns The element in the array matching the given index.
8486 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
8487 */
8488export function at(self: float[], index: number): Float | undefined {
8489    return at(self, index as int)
8490}
8491
8492/**
8493 * Creates a new `Array` from this `Array` instance and given `Array` instance.
8494 *
8495 * @param other to concatenate into a new array.
8496 *
8497 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
8498 */
8499// export function concat(self: float[], ...items: (float | Concatfloat[])[]): float[] {
8500//     throw new Error("not implemented")
8501// }
8502
8503export function concat(self: float[], ...items: ConcatArray<float>[]): float[] {
8504    let totalAdd = self.length;
8505    for (let i = 0; i < items.length; i++) {
8506        totalAdd += items[i].length as int
8507    }
8508
8509    const buf = new float[totalAdd];
8510
8511    for (let i = 0; i < self.length; i++) {
8512        buf[i] = self[i];
8513    }
8514
8515    let insertTo = self.length;
8516    for (let i = 0; i < items.length; i++) {
8517        const arr = items[i]
8518        const len = arr.length as int
8519        for (let j = 0; j < len; j++) {
8520            buf[insertTo++] = arr.$_get(j)
8521        }
8522    }
8523
8524    return buf;
8525}
8526
8527/**
8528 * Takes an integer value and returns the item at that index,
8529 * allowing for positive and negative integers. Negative integers count back
8530 * from the last item in the array.
8531 *
8532 * @param index Zero-based index of the array element to be returned.
8533 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
8534 *
8535 * @returns The element in the array matching the given index.
8536 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
8537 */
8538export function at(self: float[], index: int): Float | undefined {
8539    let len = self.length;
8540    let k: int;
8541    if (index >= 0) {
8542        k = index;
8543    } else {
8544        k = len + index;
8545    }
8546
8547    if (k < 0 || k >= len) {
8548        return undefined;
8549    }
8550
8551    return self[k];
8552}
8553
8554/**
8555 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8556 *
8557 * @param target index at which to copy the sequence
8558 *
8559 * @param start index at which to start copying elements from
8560 *
8561 * @param end index at which to end copying elements from
8562 *
8563 * @returns this array after transformation
8564 */
8565export function copyWithin(self: float[], target: number, start: number, end?: Number): float[] {
8566    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
8567    return self;
8568}
8569
8570/**
8571 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8572 *
8573 * @param target index at which to copy the sequence
8574 *
8575 * @param start index at which to start copying elements from
8576 *
8577 * @param end index at which to end copying elements from
8578 *
8579 * @returns this array after transformation
8580 */
8581export function copyWithin(self: float[], target: int, start: int, end: int): float[] {
8582    target = normalizeIndex(target, self.length)
8583    start = normalizeIndex(start, self.length)
8584    end = normalizeIndex(end, self.length)
8585
8586    if (end <= start) {
8587        return self;
8588    }
8589
8590    if (target <= start) {
8591        while (start < end) {
8592            const read = self[start++];
8593            self[target++] = read;
8594        }
8595    } else {
8596        let len = end - start;
8597        if (target + len > self.length) {
8598            len = self.length - target
8599        }
8600        for (let i = 0; i < len; i++) {
8601            const read = self[start + len - 1 - i];
8602            self[target + len - 1 - i] = read;
8603        }
8604    }
8605
8606    return self;
8607}
8608
8609/**
8610 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8611 *
8612 * @param target index at which to copy the sequence
8613 *
8614 * @param start index at which to start copying elements from
8615 *
8616 * @returns this array after transformation
8617 */
8618export function copyWithin(self: float[], target: int, start: int): float[] {
8619    copyWithin(self, target, start, self.length);
8620    return self;
8621}
8622
8623/**
8624 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8625 *
8626 * @param target index at which to copy the sequence
8627 *
8628 * @returns this array after transformation
8629 */
8630export function copyWithin(self: float[], target: int): float[] {
8631    copyWithin(self, target, 0, self.length);
8632    return self;
8633}
8634
8635/**
8636 * Changes all elements in the Array to a static value, from a start index to an end index
8637 *
8638 * @param value to fill the array with
8639 *
8640 * @param start index at which to start filling
8641 *
8642 * @param end index at which to end filling, but not including
8643 *
8644 * @returns this array after transformation
8645 */
8646export function fill(self: float[], value: float, start?: Number, end?: Number): float[] {
8647    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
8648    return self;
8649}
8650
8651/**
8652 * Changes all elements in the Array to a static value, from a start index to an end index
8653 *
8654 * @param value to fill the array with
8655 *
8656 * @param start index at which to start filling
8657 *
8658 * @param end index at which to end filling, but not including
8659 *
8660 * @returns this array after transformation
8661 */
8662export function fill(self: float[], value: float, start: int, end: int): float[] {
8663    start = normalizeIndex(start, self.length);
8664    end = normalizeIndex(end, self.length)
8665
8666    for (let i = start; i < end; i++) {
8667        self[i] = value;
8668    }
8669
8670    return self;
8671}
8672
8673/**
8674 * Returns the value of the first element in the array where predicate is true, and undefined
8675 * otherwise.
8676 *
8677 * @param predicate find calls predicate once for each element of the array, in ascending
8678 * order, until it finds one where predicate returns true. If such an element is found, find
8679 * immediately returns that element value. Otherwise, find returns undefined.
8680 *
8681 * @returns the value of the first element in the array or undefined
8682 */
8683export function find(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): Float | undefined {
8684    const res = findIndex(self, predicate)
8685    if (res == -1) {
8686        return undefined
8687    }
8688    return self[res as int];
8689}
8690
8691/**
8692 * Returns the index of the first element in the array where predicate is true, and -1
8693 * otherwise.
8694 *
8695 * @param predicate find calls predicate once for each element of the array, in ascending
8696 * order, until it finds one where predicate returns true. If such an element is found,
8697 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
8698 *
8699 * @returns found element index or -1 otherwise
8700 */
8701export function findIndex(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): number {
8702    for (let i = 0; i < self.length; i++) {
8703        if (predicate(self[i], i as number, self)) {
8704            return i;
8705        }
8706    }
8707    return -1;
8708}
8709
8710/**
8711 * Iterates the array in reverse order and returns the value of the first element
8712 * that satisfies the provided testing function
8713 *
8714 * @param predicate testing function
8715 *
8716 * @returns found element or undefined otherwise
8717 */
8718export function findLast(self: float[], predicate: (elem: float, index: number, array: float[]) => boolean): Float | undefined {
8719    for (let i = self.length - 1; i >= 0; i--) {
8720        const val = self[i];
8721        if (predicate(val, i as number, self)) {
8722            return val;
8723        }
8724    }
8725    return undefined;
8726}
8727
8728/**
8729 * Determines whether all the members of an array satisfy the specified test.
8730 *
8731 * @param predicate A function that accepts up to three arguments. The every method calls
8732 * the predicate function for each element in the array until the predicate returns a value
8733 * which is coercible to the Boolean value false, or until the end of the array.
8734 *
8735 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
8736 */
8737export function every(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): boolean {
8738    for (let i = 0; i < self.length; i++) {
8739        if (!predicate(self[i], i as number, self)) {
8740            return false
8741        }
8742    }
8743    return true;
8744}
8745
8746/**
8747 * Determines whether the specified callback function returns true for any element of an array.
8748 *
8749 * @param predicate A function that accepts up to three arguments. The some method calls
8750 * the predicate function for each element in the array until the predicate returns a value
8751 * which is coercible to the Boolean value true, or until the end of the array.
8752 *
8753 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
8754 */
8755export function some(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): boolean {
8756    for (let i = 0; i < self.length; i++) {
8757        if (predicate(self[i], i as number, self)) {
8758            return true
8759        }
8760    }
8761    return false
8762}
8763
8764/**
8765 * Returns the elements of an array that meet the condition specified in a callback function.
8766 *
8767 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
8768 *
8769 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
8770 */
8771export function filter(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): float[] {
8772    return filter(self, (value: float, index: number): boolean => predicate(value, index, self));
8773}
8774
8775/**
8776 * Iterates the array in reverse order and returns the index of
8777 * the first element that satisfies the provided testing function.
8778 * If no elements satisfy the testing function, -1 is returned.
8779 *
8780 * @param predicate testing function
8781 *
8782 * @returns index of first element satisfying to predicate, -1 if no such element
8783 */
8784export function findLastIndex(self: float[], predicate: (element: float, index: number, array: float[]) => boolean): number {
8785    for (let i = self.length - 1; i >= 0; i--) {
8786        if (predicate(self[i], i as number, self)) {
8787            return i
8788        }
8789    }
8790    return -1
8791}
8792
8793/**
8794 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8795 *
8796 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
8797 *
8798 * @returns a result after applying callbackfn over all elements of the Array
8799 */
8800export function reduce(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number, array: float[]) => float): float {
8801    if (self.length == 0) {
8802        throw new TypeError("Reduce of empty array with no initial value")
8803    }
8804    let acc: float = self[0];
8805    for (let i = 1; i < self.length; i++) {
8806        acc = callbackfn(acc, self[i], i as number, self)
8807    }
8808    return acc
8809}
8810
8811/**
8812 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8813 *
8814 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
8815 *
8816 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
8817 *
8818 * @returns a result after applying callbackfn over all elements of the Array
8819 */
8820export function reduce<U = float>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number, array: float[]) => U, initialValue: U): U {
8821    let acc = initialValue
8822    for (let i = 0; i < self.length; i++) {
8823        acc = callbackfn(acc, self[i], i as number, self)
8824    }
8825    return acc
8826}
8827
8828/**
8829 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8830 *
8831 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
8832 *
8833 * @returns a result after applying callbackfn over all elements of the Array
8834 */
8835export function reduceRight(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number, array: float[]) => float): float {
8836    if (self.length == 0) {
8837        throw new TypeError("Reduce of empty array with no initial value")
8838    }
8839    let acc: float = self[self.length - 1];
8840    for (let i = self.length - 2; i >= 0; i--) {
8841        acc = callbackfn(acc, self[i], i as number, self)
8842    }
8843    return acc
8844}
8845
8846/**
8847 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8848 *
8849 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
8850 *
8851 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
8852 *
8853 * @returns a result after applying callbackfn over all elements of the Array
8854 */
8855export function reduceRight<U>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number, array: float[]) => U, initialValue: U): U {
8856    let acc = initialValue
8857    for (let i = self.length - 1; i >= 0; i--) {
8858        acc = callbackfn(acc, self[i], i as number, self)
8859    }
8860    return acc
8861}
8862
8863/**
8864 * Performs the specified action for each element in an array.
8865 *
8866 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
8867 */
8868export function forEach(self: float[], callbackfn: (value: float, index: number, array: float[]) => void): void {
8869    const len0 = self.length;
8870    for (let i = 0; i < len0; i++) {
8871        callbackfn(self[i], i as number, self)
8872    }
8873}
8874
8875/**
8876 * Returns the value of the first element in the array where predicate is true, and undefined
8877 * otherwise.
8878 *
8879 * @param predicate find calls predicate once for each element of the array, in ascending
8880 * order, until it finds one where predicate returns true. If such an element is found, find
8881 * immediately returns that element value. Otherwise, find returns undefined.
8882 *
8883 * @returns the value of the first element in the array or undefined
8884 */
8885export function find(self: float[], predicate: (value: float, index: number) => boolean): Float | undefined {
8886    const res = findIndex(self, predicate)
8887    if (res == -1) {
8888        return undefined
8889    }
8890    return self[res as int];
8891}
8892
8893/**
8894 * Returns the index of the first element in the array where predicate is true, and -1
8895 * otherwise.
8896 *
8897 * @param predicate find calls predicate once for each element of the array, in ascending
8898 * order, until it finds one where predicate returns true. If such an element is found,
8899 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
8900 *
8901 * @returns found element index or -1 otherwise
8902 */
8903export function findIndex(self: float[], predicate: (value: float, index: number) => boolean): number {
8904    for (let i = 0; i < self.length; i++) {
8905        if (predicate(self[i], i as number)) {
8906            return i;
8907        }
8908    }
8909    return -1;
8910}
8911
8912/**
8913 * Iterates the array in reverse order and returns the value of the first element
8914 * that satisfies the provided testing function
8915 *
8916 * @param predicate testing function
8917 *
8918 * @returns found element or undefined otherwise
8919 */
8920export function findLast(self: float[], predicate: (elem: float, index: number) => boolean): Float | undefined {
8921    for (let i = self.length - 1; i >= 0; i--) {
8922        const val = self[i];
8923        if (predicate(val, i as number)) {
8924            return val;
8925        }
8926    }
8927    return undefined;
8928}
8929
8930/**
8931 * Determines whether all the members of an array satisfy the specified test.
8932 *
8933 * @param predicate A function that accepts up to three arguments. The every method calls
8934 * the predicate function for each element in the array until the predicate returns a value
8935 * which is coercible to the Boolean value false, or until the end of the array.
8936 *
8937 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
8938 */
8939export function every(self: float[], predicate: (value: float, index: number) => boolean): boolean {
8940    for (let i = 0; i < self.length; i++) {
8941        if (!predicate(self[i], i as number)) {
8942            return false
8943        }
8944    }
8945    return true;
8946}
8947
8948/**
8949 * Determines whether the specified callback function returns true for any element of an array.
8950 *
8951 * @param predicate A function that accepts up to three arguments. The some method calls
8952 * the predicate function for each element in the array until the predicate returns a value
8953 * which is coercible to the Boolean value true, or until the end of the array.
8954 *
8955 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
8956 */
8957export function some(self: float[], predicate: (value: float, index: number) => boolean): boolean {
8958    for (let i = 0; i < self.length; i++) {
8959        if (predicate(self[i], i as number)) {
8960            return true
8961        }
8962    }
8963    return false
8964}
8965
8966/**
8967 * Iterates the array in reverse order and returns the index of
8968 * the first element that satisfies the provided testing function.
8969 * If no elements satisfy the testing function, -1 is returned.
8970 *
8971 * @param predicate testing function
8972 *
8973 * @returns index of first element satisfying to predicate, -1 if no such element
8974 */
8975export function findLastIndex(self: float[], predicate: (element: float, index: number) => boolean): number {
8976    for (let i = self.length - 1; i >= 0; i--) {
8977        if (predicate(self[i], i as number)) {
8978            return i
8979        }
8980    }
8981    return -1
8982}
8983
8984/**
8985 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
8986 *
8987 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
8988 *
8989 * @returns a result after applying callbackfn over all elements of the Array
8990 */
8991export function reduce(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number) => float): float {
8992    if (self.length == 0) {
8993        throw new TypeError("Reduce of empty array with no initial value")
8994    }
8995    let acc: float = self[0];
8996    for (let i = 1; i < self.length; i++) {
8997        acc = callbackfn(acc, self[i], i as number)
8998    }
8999    return acc
9000}
9001
9002/**
9003 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9004 *
9005 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
9006 *
9007 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9008 *
9009 * @returns a result after applying callbackfn over all elements of the Array
9010 */
9011export function reduce<U = float>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number) => U, initialValue: U): U {
9012    let acc = initialValue
9013    for (let i = 0; i < self.length; i++) {
9014        acc = callbackfn(acc, self[i], i as number)
9015    }
9016    return acc
9017}
9018
9019/**
9020 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9021 *
9022 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9023 *
9024 * @returns a result after applying callbackfn over all elements of the Array
9025 */
9026export function reduceRight(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number) => float): float {
9027    if (self.length == 0) {
9028        throw new TypeError("Reduce of empty array with no initial value")
9029    }
9030    let acc: float = self[self.length - 1];
9031    for (let i = self.length - 2; i >= 0; i--) {
9032        acc = callbackfn(acc, self[i], i as number)
9033    }
9034    return acc
9035}
9036
9037/**
9038 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9039 *
9040 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9041 *
9042 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9043 *
9044 * @returns a result after applying callbackfn over all elements of the Array
9045 */
9046export function reduceRight<U>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number) => U, initialValue: U): U {
9047    let acc = initialValue
9048    for (let i = self.length - 1; i >= 0; i--) {
9049        acc = callbackfn(acc, self[i], i as number)
9050    }
9051    return acc
9052}
9053
9054/**
9055 * Performs the specified action for each element in an array.
9056 *
9057 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
9058 */
9059export function forEach(self: float[], callbackfn: (value: float, index: number) => void): void {
9060    const len0 = self.length;
9061    for (let i = 0; i < len0; i++) {
9062        callbackfn(self[i], i as number)
9063    }
9064}
9065
9066/**
9067 * Returns the value of the first element in the array where predicate is true, and undefined
9068 * otherwise.
9069 *
9070 * @param predicate find calls predicate once for each element of the array, in ascending
9071 * order, until it finds one where predicate returns true. If such an element is found, find
9072 * immediately returns that element value. Otherwise, find returns undefined.
9073 *
9074 * @returns the value of the first element in the array or undefined
9075 */
9076export function find(self: float[], predicate: (value: float) => boolean): Float | undefined {
9077    const res = findIndex(self, predicate)
9078    if (res == -1) {
9079        return undefined
9080    }
9081    return self[res as int];
9082}
9083
9084/**
9085 * Returns the index of the first element in the array where predicate is true, and -1
9086 * otherwise.
9087 *
9088 * @param predicate find calls predicate once for each element of the array, in ascending
9089 * order, until it finds one where predicate returns true. If such an element is found,
9090 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
9091 *
9092 * @returns found element index or -1 otherwise
9093 */
9094export function findIndex(self: float[], predicate: (value: float) => boolean): number {
9095    for (let i = 0; i < self.length; i++) {
9096        if (predicate(self[i])) {
9097            return i;
9098        }
9099    }
9100    return -1;
9101}
9102
9103/**
9104 * Iterates the array in reverse order and returns the value of the first element
9105 * that satisfies the provided testing function
9106 *
9107 * @param predicate testing function
9108 *
9109 * @returns found element or undefined otherwise
9110 */
9111export function findLast(self: float[], predicate: (elem: float) => boolean): Float | undefined {
9112    for (let i = self.length - 1; i >= 0; i--) {
9113        const val = self[i];
9114        if (predicate(val)) {
9115            return val;
9116        }
9117    }
9118    return undefined;
9119}
9120
9121/**
9122 * Determines whether all the members of an array satisfy the specified test.
9123 *
9124 * @param predicate A function that accepts up to three arguments. The every method calls
9125 * the predicate function for each element in the array until the predicate returns a value
9126 * which is coercible to the Boolean value false, or until the end of the array.
9127 *
9128 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
9129 */
9130export function every(self: float[], predicate: (value: float) => boolean): boolean {
9131    for (let i = 0; i < self.length; i++) {
9132        if (!predicate(self[i])) {
9133            return false
9134        }
9135    }
9136    return true;
9137}
9138
9139/**
9140 * Determines whether the specified callback function returns true for any element of an array.
9141 *
9142 * @param predicate A function that accepts up to three arguments. The some method calls
9143 * the predicate function for each element in the array until the predicate returns a value
9144 * which is coercible to the Boolean value true, or until the end of the array.
9145 *
9146 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
9147 */
9148export function some(self: float[], predicate: (value: float) => boolean): boolean {
9149    for (let i = 0; i < self.length; i++) {
9150        if (predicate(self[i])) {
9151            return true
9152        }
9153    }
9154    return false
9155}
9156
9157/**
9158 * Returns the elements of an array that meet the condition specified in a callback function.
9159 *
9160 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
9161 *
9162 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
9163 */
9164export function filter(self: float[], predicate: (value: float) => boolean): float[] {
9165    return filter(self, (value: float, index: number): boolean => predicate(value));
9166}
9167
9168/**
9169 * Iterates the array in reverse order and returns the index of
9170 * the first element that satisfies the provided testing function.
9171 * If no elements satisfy the testing function, -1 is returned.
9172 *
9173 * @param predicate testing function
9174 *
9175 * @returns index of first element satisfying to predicate, -1 if no such element
9176 */
9177export function findLastIndex(self: float[], predicate: (element: float) => boolean): number {
9178    for (let i = self.length - 1; i >= 0; i--) {
9179        if (predicate(self[i])) {
9180            return i
9181        }
9182    }
9183    return -1
9184}
9185
9186/**
9187 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9188 *
9189 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
9190 *
9191 * @returns a result after applying callbackfn over all elements of the Array
9192 */
9193export function reduce(self: float[], callbackfn: (previousValue: float, currentValue: float) => float): float {
9194    if (self.length == 0) {
9195        throw new TypeError("Reduce of empty array with no initial value")
9196    }
9197    let acc: float = self[0];
9198    for (let i = 1; i < self.length; i++) {
9199        acc = callbackfn(acc, self[i])
9200    }
9201    return acc
9202}
9203
9204/**
9205 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9206 *
9207 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
9208 *
9209 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9210 *
9211 * @returns a result after applying callbackfn over all elements of the Array
9212 */
9213export function reduce<U = float>(self: float[], callbackfn: (previousValue: U, currentValue: float) => U, initialValue: U): U {
9214    let acc = initialValue
9215    for (let i = 0; i < self.length; i++) {
9216        acc = callbackfn(acc, self[i])
9217    }
9218    return acc
9219}
9220
9221/**
9222 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9223 *
9224 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9225 *
9226 * @returns a result after applying callbackfn over all elements of the Array
9227 */
9228export function reduceRight(self: float[], callbackfn: (previousValue: float, currentValue: float) => float): float {
9229    if (self.length == 0) {
9230        throw new TypeError("Reduce of empty array with no initial value")
9231    }
9232    let acc: float = self[self.length - 1];
9233    for (let i = self.length - 2; i >= 0; i--) {
9234        acc = callbackfn(acc, self[i])
9235    }
9236    return acc
9237}
9238
9239/**
9240 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9241 *
9242 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9243 *
9244 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9245 *
9246 * @returns a result after applying callbackfn over all elements of the Array
9247 */
9248export function reduceRight<U>(self: float[], callbackfn: (previousValue: U, currentValue: float) => U, initialValue: U): U {
9249    let acc = initialValue
9250    for (let i = self.length - 1; i >= 0; i--) {
9251        acc = callbackfn(acc, self[i])
9252    }
9253    return acc
9254}
9255
9256/**
9257 * Performs the specified action for each element in an array.
9258 *
9259 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
9260 */
9261export function forEach(self: float[], callbackfn: (value: float) => void): void {
9262    const len0 = self.length;
9263    for (let i = 0; i < len0; i++) {
9264        callbackfn(self[i])
9265    }
9266}
9267
9268/**
9269 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
9270 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
9271 *
9272 * @param start zero-based index at which to start extraction
9273 *
9274 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
9275 *
9276 * @returns `Array` instance, constructed from extracted elements of `this` instance.
9277 */
9278export function slice(self: float[], start?: Number, end?: Number): float[] {
9279    const len: int = self.length;
9280    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
9281}
9282
9283/**
9284 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
9285 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
9286 *
9287 * @param start zero-based index at which to start extraction
9288 *
9289 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
9290 *
9291 * @returns `Array` instance, constructed from extracted elements of `this` instance.
9292 */
9293export function slice(self: float[], start: int, end: int): float[] {
9294    const len: int = self.length;
9295    const relStart = normalizeIndex(start, len)
9296    const relEnd = normalizeIndex(end, len)
9297
9298    let count = relEnd - relStart;
9299    if (count < 0) {
9300        count = 0;
9301    }
9302    let res = new float[count]
9303    for (let i = 0; i < count; i++) {
9304        res[i] = self[relStart + i];
9305    }
9306
9307    return res
9308}
9309
9310/**
9311 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
9312 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
9313 *
9314 * @param start zero-based index at which to start extraction
9315 *
9316 * @returns `Array` instance, constructed from extracted elements of `this` instance.
9317 */
9318export function slice(self: float[], start: int): float[] {
9319    return slice(self, start, Int.MAX_VALUE as int);
9320}
9321
9322/**
9323 * Returns the last index at which a given element can be found in the array,
9324 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
9325 *
9326 * @param element element to locate in the array.
9327 * @param fromIndex zero-based index at which to start searching backwards.
9328 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
9329 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
9330 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
9331 *
9332 * @returns The last index of the element in the array; -1 if not found.
9333 */
9334export function lastIndexOf(self: float[], element: float, fromIndex: int): int {
9335    if (self.length == 0) {
9336        return -1;
9337    }
9338    let n = fromIndex;
9339    let k: int;
9340    if (n >= 0) {
9341        k = min(self.length - 1, n);
9342    } else {
9343        k = self.length + n;
9344    }
9345
9346    while (k >= 0) {
9347        if (__runtimeEquals(self[k], element)) {
9348            return k;
9349        }
9350        k--;
9351    }
9352    return -1;
9353}
9354
9355/**
9356 * Returns the last index at which a given element can be found in the array,
9357 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
9358 *
9359 * @param element element to locate in the array.
9360 * @param fromIndex zero-based index at which to start searching backwards.
9361 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
9362 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
9363 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
9364 *
9365 * @returns The last index of the element in the array; -1 if not found.
9366 */
9367export function lastIndexOf(self: float[], element: float, fromIndex?: Number): number {
9368    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
9369}
9370
9371/**
9372 * Creates and returns a new string by concatenating all of the elements in an `Array`,
9373 * separated by a specified separator string.
9374 * If the array has only one item, then that item will be returned without using the separator.
9375 *
9376 * @param sep specifies a separator
9377 *
9378 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
9379 */
9380export function join(self: float[], sep?: String): string {
9381    if (self.length == 0) {
9382        return ""
9383    }
9384    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
9385    let sb = new StringBuilder(new String(self[0]))
9386    for (let i: int = 1; i < self.length; i++) {
9387        const tmp = self[i]
9388        sb.append(sepReal);
9389        sb.append(tmp)
9390    }
9391
9392    return sb.toString();
9393}
9394
9395/**
9396 * Returns a string representing the specified array and its elements.
9397 *
9398 * @returns string representation
9399 */
9400export function toString(self: float[], ): string {
9401    return join(self, ",");
9402}
9403
9404/**
9405 * Returns a locale string representing the specified array and its elements.
9406 *
9407 * @param locales
9408 *
9409 * @param options
9410 *
9411 * @returns string representation
9412 */
9413export function toLocaleString(self: float[], locales: Object, options: Object): string {
9414    throw new Error("Array.toLocaleString: not implemented")
9415}
9416
9417/**
9418 * Returns a locale string representing the specified array and its elements.
9419 *
9420 * @param options
9421 *
9422 * @returns string representation
9423 */
9424export function toLocaleString(self: float[], locales: Object): string {
9425    return toLocaleString(self, new Object(), new Object())
9426}
9427
9428/**
9429 * Returns a locale string representing the specified array and its elements.
9430 *
9431 * @returns string representation
9432 */
9433export function toLocaleString(self: float[], ): string {
9434    const sb = new StringBuilder()
9435    const len = self.length;
9436    for (let i = 0; i < len; i++) {
9437        if (i != 0) {
9438            sb.append(",")
9439        }
9440        let x = self[i] as NullishType;
9441        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
9442            sb.append(x!.toLocaleString())
9443        }
9444    }
9445    return sb.toString()
9446}
9447
9448/**
9449 * Copying version of the splice() method.
9450 *
9451 * @param start index
9452 *
9453 * @param delete number of items after start index
9454 *
9455 * @returns a new Array with some elements removed and/or replaced at a given index.
9456 */
9457export function toSpliced(self: float[], start?: Number, delete?: Number): float[] {
9458    const len = self.length;
9459    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
9460}
9461
9462/**
9463 * Copying version of the splice() method.
9464 *
9465 * @param start index
9466 *
9467 * @param delete number of items after start index
9468 *
9469 * @returns a new Array with some elements removed and/or replaced at a given index.
9470 */
9471export function toSpliced(self: float[], start: number, delete: number, ...items: float[]): float[] {
9472    const len = self.length;
9473    return toSpliced(self, start as int, delete as int, ...items)
9474}
9475
9476/**
9477 * Copying version of the splice() method.
9478 *
9479 * @param start index
9480 *
9481 * @param delete number of items after start index
9482 *
9483 * @returns a new Array with some elements removed and/or replaced at a given index.
9484 */
9485export function toSpliced(self: float[], start: int, delete: int, ...items: float[]): float[] {
9486    const len = self.length;
9487    start = normalizeIndex(start, len);
9488    if (delete < 0) {
9489        delete = 0;
9490    } else if (delete > len) {
9491        delete = len;
9492    }
9493    if (start > len - delete) {
9494        delete = len - start
9495    }
9496    const res = new float[len - delete + items.length];
9497    for (let i = 0; i < start; i++) {
9498        res[i] = self[i]
9499    }
9500    for (let i = 0; i < items.length; i++) {
9501        res[start + i] = items[i]
9502    }
9503    for (let i = start + delete; i < len; i++) {
9504        res[i - delete + items.length] = self[i]
9505    }
9506    return res;
9507}
9508
9509/**
9510 * Copying version of the splice() method.
9511 *
9512 * @param start index
9513 *
9514 * @returns a new Array with some elements removed and/or replaced at a given index.
9515 */
9516export function toSpliced(self: float[], start: int): float[] {
9517    return toSpliced(self, start, self.length)
9518}
9519
9520/**
9521 * Checks whether an Array includes a certain value among its entries,
9522 * returning true or false as appropriate.
9523 *
9524 * @param val value to search
9525 *
9526 * @param fromIndex start index
9527 *
9528 * @returns true if val is in Array
9529 */
9530export function includes(self: float[], val: float, fromIndex?: Number): boolean {
9531    const len = self.length;
9532    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
9533    if (isNaN(val)) {
9534        for (let i = fi; i < len; i++) {
9535            if (isNaN(self[i])) {
9536                return true;
9537            }
9538        }
9539        return false;
9540    }
9541    for (let i = fi; i < len; i++) {
9542        if (val == self[i]) {
9543            return true;
9544        }
9545    }
9546    return false;
9547}
9548
9549/**
9550 * Returns the first index at which a given element
9551 * can be found in the array, or -1 if it is not present.
9552 *
9553 * @param val value to search
9554 *
9555 * @param fromIndex index to search from
9556 *
9557 * @returns index of val, -1 otherwise
9558 */
9559export function indexOf(self: float[], val: float, fromIndex: int): int {
9560    fromIndex = normalizeIndex(fromIndex, self.length)
9561    for (let i = fromIndex; i < self.length; i++) {
9562        if (__runtimeEquals(val, self[i])) {
9563            return i
9564        }
9565    }
9566    return -1
9567}
9568
9569/**
9570 * Returns the first index at which a given element
9571 * can be found in the array, or -1 if it is not present.
9572 *
9573 * @param val value to search
9574 *
9575 * @param fromIndex index to search from
9576 *
9577 * @returns index of val, -1 otherwise
9578 */
9579export function indexOf(self: float[], val: float, fromIndex?: Number): number {
9580    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
9581}
9582
9583/**
9584 * Copying version of the sort() method.
9585 * It returns a new array with the elements sorted in ascending order.
9586 *
9587 * @returns sorted copy of hte current instance using default comparator
9588 */
9589export function toSorted(self: float[], ): float[] {
9590    let arr = cloneArray(self);
9591    sort(arr, )
9592    return arr
9593}
9594
9595/**
9596 * Copying version of the sort() method.
9597 * It returns a new array with the elements sorted in ascending order.
9598 *
9599 * @param comparator function to compare to elements of the Array
9600 *
9601 * @returns sorted copy of the current instance comparator
9602 */
9603export function toSorted(self: float[], comparator: (a: float, b: float) => number): float[] {
9604    let arr = cloneArray(self);
9605    sort(arr, comparator)
9606    return arr
9607}
9608
9609/**
9610 * Modifies `this` instance of `Array` class and populates
9611 * it with same elements ordered towards the direction opposite to that previously stated.
9612 *
9613 * @note Mutating method
9614 */
9615export function reverse(self: float[], ): float[] {
9616    for (let i = 0; i < self.length / 2; i++) {
9617        const tmp = self[i];
9618        const idx_r = self.length - 1 - i;
9619        const val_r = self[idx_r];
9620        self[i] = val_r;
9621        self[idx_r] = tmp;
9622    }
9623    return self;
9624}
9625
9626/**
9627 * Copying version of the reverse() method.
9628 * It returns a new array with the elements in reversed order.
9629 *
9630 * @returns reversed copy of the current Array
9631 */
9632export function toReversed(self: float[], ): float[] {
9633    let arr = new float[self.length]
9634    for (let i = 0; i < self.length; i++) {
9635        arr[self.length - 1 - i] = self[i]
9636    }
9637    return arr
9638}
9639
9640/**
9641 * Copying version of using the bracket notation to change the value of a given index.
9642 * It returns a new Array with the element at the given index replaced with the given value.
9643 *
9644 * @param index to replace
9645 *
9646 * @param value new value
9647 *
9648 * @returns a new Array with the element at the given index replaced with the given value
9649 */
9650export function with(self: float[], index: number, value: float): float[] {
9651    return with(self, index as int, value)
9652}
9653
9654/**
9655 * Copying version of using the bracket notation to change the value of a given index.
9656 * It returns a new Array with the element at the given index replaced with the given value.
9657 *
9658 * @param index to replace
9659 *
9660 * @param value new value
9661 *
9662 * @returns a new Array with the element at the given index replaced with the given value
9663 */
9664export function with(self: float[], index: int, value: float): float[] {
9665    if (index < 0) {
9666        index += self.length;
9667    }
9668    if (index >= self.length) {
9669        throw new RangeError("Invalid index")
9670    }
9671    let arr = cloneArray(self);
9672    arr[index] = value;
9673    return arr
9674}
9675
9676/**
9677 * Returns an iterator over all values
9678 */
9679export function values(self: float[], ): IterableIterator<float> {
9680    return new ArrayValuesIterator_float(self);
9681}
9682
9683/**
9684 * Returns an iterable of key, value pairs for every entry in the array
9685 */
9686export function entries(self: float[], ): IterableIterator<[number, float]> {
9687    return new ArrayEntriesIterator_float(self);
9688}
9689
9690/**
9691 * Determines whether all the members of an array satisfy the specified test.
9692 *
9693 * @param predicate A function that accepts up to three arguments. The every method calls
9694 * the predicate function for each element in the array until the predicate returns a value
9695 * which is coercible to the Boolean value false, or until the end of the array.
9696 *
9697 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
9698 */
9699export function every(self: float[], predicate: () => boolean): boolean {
9700    for (let i = 0; i < self.length; i++) {
9701        if (!predicate()) {
9702            return false
9703        }
9704    }
9705    return true
9706}
9707
9708/**
9709 * Returns the elements of an array that meet the condition specified in a callback function.
9710 *
9711 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
9712 *
9713 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
9714 */
9715export function filter(self: float[], predicate: () => boolean): float[] {
9716    return filter(self, (value: float, index: number): boolean => predicate());
9717}
9718
9719/**
9720 * Returns the value of the first element in the array where predicate is true, and undefined
9721 * otherwise.
9722 *
9723 * @param predicate find calls predicate once for each element of the array, in ascending
9724 * order, until it finds one where predicate returns true. If such an element is found, find
9725 * immediately returns that element value. Otherwise, find returns undefined.
9726 *
9727 * @returns the value of the first element in the array or undefined
9728 */
9729export function find(self: float[], predicate: () => boolean): Float | undefined {
9730    const res = findIndex(self, predicate)
9731    if (res == -1) {
9732        return undefined
9733    }
9734    return self[res as int];
9735}
9736
9737/**
9738 * Returns the index of the first element in the array where predicate is true, and -1
9739 * otherwise.
9740 *
9741 * @param predicate find calls predicate once for each element of the array, in ascending
9742 * order, until it finds one where predicate returns true. If such an element is found,
9743 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
9744 *
9745 * @returns found element index or -1 otherwise
9746 */
9747export function findIndex(self: float[], predicate: () => boolean): number {
9748    for (let i = 0; i < self.length; i++) {
9749        if (predicate()) {
9750            return i;
9751        }
9752    }
9753    return -1;
9754}
9755
9756/**
9757 * Performs the specified action for each element in an array.
9758 *
9759 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
9760 */
9761export function forEach(self: float[], callbackfn: () => void): void {
9762    const len0 = self.length;
9763    for (let i = 0; i < len0; i++) {
9764        callbackfn()
9765    }
9766}
9767
9768/**
9769 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9770 *
9771 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
9772 *
9773 * @returns a result after applying callbackfn over all elements of the Array
9774 */
9775export function reduce(self: float[], callbackfn: (previousValue: float) => float): float {
9776    if (self.length == 0) {
9777        throw new TypeError("Reduce of empty array with no initial value")
9778    }
9779    let acc: float = self[0];
9780    for (let i = 1; i < self.length; i++) {
9781        acc = callbackfn(acc)
9782    }
9783    return acc
9784}
9785
9786/**
9787 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9788 *
9789 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
9790 *
9791 * @returns a result after applying callbackfn over all elements of the Array
9792 */
9793export function reduce(self: float[], callbackfn: () => float): float {
9794    if (self.length == 0) {
9795        throw new TypeError("Reduce of empty array with no initial value")
9796    }
9797    let acc: float = self[0];
9798    for (let i = 1; i < self.length; i++) {
9799        acc = callbackfn()
9800    }
9801    return acc
9802}
9803
9804/**
9805 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9806 *
9807 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
9808 *
9809 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9810 *
9811 * @returns a result after applying callbackfn over all elements of the Array
9812 */
9813export function reduce<U = float>(self: float[], callbackfn: (previousValue: U) => U, initialValue: U): U {
9814    let acc = initialValue
9815    for (let i = 0; i < self.length; i++) {
9816        acc = callbackfn(acc)
9817    }
9818    return acc
9819}
9820
9821/**
9822 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9823 *
9824 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
9825 *
9826 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9827 *
9828 * @returns a result after applying callbackfn over all elements of the Array
9829 */
9830export function reduce<U = float>(self: float[], callbackfn: () => U, initialValue: U): U {
9831    let acc = initialValue
9832    for (let i = 0; i < self.length; i++) {
9833        acc = callbackfn()
9834    }
9835    return acc
9836}
9837
9838/**
9839 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9840 *
9841 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9842 *
9843 * @returns a result after applying callbackfn over all elements of the Array
9844 */
9845export function reduceRight(self: float[], callbackfn: (previousValue: float) => float): float {
9846    if (self.length == 0) {
9847        throw new TypeError("Reduce of empty array with no initial value")
9848    }
9849    let acc: float = self[self.length - 1];
9850    for (let i = self.length - 2; i >= 0; i--) {
9851        acc = callbackfn(acc)
9852    }
9853    return acc
9854}
9855
9856/**
9857 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9858 *
9859 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9860 *
9861 * @returns a result after applying callbackfn over all elements of the Array
9862 */
9863export function reduceRight(self: float[], callbackfn: () => float): float {
9864    if (self.length == 0) {
9865        throw new TypeError("Reduce of empty array with no initial value")
9866    }
9867    let acc: float = self[self.length - 1];
9868    for (let i = self.length - 2; i >= 0; i--) {
9869        acc = callbackfn()
9870    }
9871    return acc
9872}
9873
9874/**
9875 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9876 *
9877 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9878 *
9879 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9880 *
9881 * @returns a result after applying callbackfn over all elements of the Array
9882 */
9883export function reduceRight<U>(self: float[], callbackfn: (previousValue: U) => U, initialValue: U): U {
9884    let acc = initialValue
9885    for (let i = self.length - 1; i >= 0; i--) {
9886        acc = callbackfn(acc)
9887    }
9888    return acc
9889}
9890
9891/**
9892 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
9893 *
9894 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
9895 *
9896 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
9897 *
9898 * @returns a result after applying callbackfn over all elements of the Array
9899 */
9900export function reduceRight<U>(self: float[], callbackfn: () => U, initialValue: U): U {
9901    let acc = initialValue
9902    for (let i = self.length - 1; i >= 0; i--) {
9903        acc = callbackfn()
9904    }
9905    return acc
9906}
9907
9908/**
9909 * Determines whether the specified callback function returns true for any element of an array.
9910 *
9911 * @param predicate A function that accepts up to three arguments. The some method calls
9912 * the predicate function for each element in the array until the predicate returns a value
9913 * which is coercible to the Boolean value true, or until the end of the array.
9914 *
9915 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
9916 */
9917export function some(self: float[], predicate: () => boolean): boolean {
9918    for (let i = 0; i < self.length; i++) {
9919        if (predicate()) {
9920            return true
9921        }
9922    }
9923    return false
9924}
9925
9926/**
9927 * Iterates the array in reverse order and returns the value of the first element
9928 * that satisfies the provided testing function
9929 *
9930 * @param predicate testing function
9931 *
9932 * @returns found element or undefined otherwise
9933 */
9934export function findLast(self: float[], predicate: () => boolean): Float | undefined {
9935    for (let i = self.length - 1; i >= 0; i--) {
9936        const val = self[i];
9937        if (predicate()) {
9938            return val;
9939        }
9940    }
9941    return undefined;
9942}
9943
9944/**
9945 * Iterates the array in reverse order and returns the index of
9946 * the first element that satisfies the provided testing function.
9947 * If no elements satisfy the testing function, -1 is returned.
9948 *
9949 * @param predicate testing function
9950 *
9951 * @returns index of first element satisfying to predicate, -1 if no such element
9952 */
9953export function findLastIndex(self: float[], predicate: () => boolean): number {
9954    for (let i = self.length - 1; i >= 0; i--) {
9955        if (predicate()) {
9956            return i
9957        }
9958    }
9959    return -1
9960}
9961
9962/**
9963 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
9964 *
9965 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
9966 *
9967 * @returns `Array` instance, constructed from `this` and given function.
9968 */
9969export function map(self: float[], callbackfn: (value: float, index: number, array: float[]) => float): float[] {
9970    const len = self.length;
9971    let res = new float[len];
9972    for (let i = 0; i < len; i++) {
9973        res[i] = callbackfn(self[i], i as number, self);
9974    }
9975    return res;
9976}
9977
9978/**
9979 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
9980 *
9981 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
9982 *
9983 * @returns `Array` instance, constructed from `this` and given function.
9984 */
9985export function map(self: float[], callbackfn: (value: float, index: number) => float): float[] {
9986    const len = self.length;
9987    let res = new float[len];
9988    for (let i = 0; i < len; i++) {
9989        res[i] = callbackfn(self[i], i as number);
9990    }
9991    return res;
9992}
9993
9994/**
9995 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
9996 *
9997 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
9998 *
9999 * @returns `Array` instance, constructed from `this` and given function.
10000 */
10001export function map(self: float[], callbackfn: (value: float) => float): float[] {
10002    const len = self.length;
10003    let res = new float[len];
10004    for (let i = 0; i < len; i++) {
10005        res[i] = callbackfn(self[i]);
10006    }
10007    return res;
10008}
10009
10010/**
10011 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
10012 *
10013 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
10014 *
10015 * @returns `Array` instance, constructed from `this` and given function.
10016 */
10017export function map(self: float[], callbackfn: () => float): float[] {
10018    const len = self.length;
10019    let res = new float[len];
10020    for (let i = 0; i < len; i++) {
10021        res[i] = callbackfn();
10022    }
10023    return res;
10024}
10025
10026/**
10027 * Constructs a new `Array` instance and populates it with
10028 * portion of a given array, filtered down to just the elements from the
10029 * given array that pass the test implemented by the provided function.
10030 *
10031 * @param fn test function, applied to each element of an array.
10032 *
10033 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
10034 */
10035export function filter(self: float[], fn: (v: float, k: number) => boolean): float[] {
10036    const mask = new boolean[self.length]
10037    let cnt = 0
10038
10039    for (let i: int = 0; i < self.length; i++) {
10040        const val = self[i];
10041        if (fn(val, i)) {
10042            mask[i] = true
10043            cnt++;
10044        }
10045    }
10046    const res = new float[cnt];
10047    let idx_store = 0;
10048    for (let i: int = 0; i < self.length; i++) {
10049        if (mask[i]) {
10050            res[idx_store++] = self[i]
10051        }
10052    }
10053    return res;
10054}
10055
10056export function concat(self: float[], fst: float[], ...more: float[][]): float[] {
10057    const lnMin = self.length + fst.length;
10058    let ln = lnMin;
10059    for (let i = 0; i < more.length; i++) {
10060        ln += more[i].length
10061    }
10062    const r = new float[ln];
10063    try {
10064        copyTo(self, r, 0, 0, self.length);
10065        copyTo(fst, r, self.length, 0, fst.length);
10066        let idx = lnMin;
10067        for (let i = 0; i < more.length; i++) {
10068            copyTo(more[i], r, idx, 0, more[i].length);
10069            idx += more[i].length;
10070        }
10071    } catch (e) {
10072        // impossible
10073    }
10074    return r
10075}
10076
10077/**
10078 * Reorders elements of `this` using comparator function.
10079 *
10080 * @param comparator function that defines the sort order.
10081 *
10082 * @note Mutating method
10083 */
10084export function sort(self: float[], comparator: (a: float, b: float) => number): float[] {
10085    sort_subarray(self, 0, self.length, (l: float, r: float): boolean => {
10086        return comparator(l, r ) < 0;
10087    });
10088    return self;
10089}
10090
10091/**
10092 * Reorders elements of `this` using comparator function.
10093 *
10094 * @param comparator function that defines the sort order.
10095 *
10096 * @note Mutating method
10097 */
10098export function sort(self: float[], ): float[] {
10099    sort(self, 0, self.length);
10100    return self;
10101}
10102
10103export function keys(self: float[]): IterableIterator<number> {
10104    return new BuiltinArrayKeysIterator(self.length);
10105}
10106
10107class ArrayValuesIterator_float implements IterableIterator<float> {
10108    private parent: float[]
10109    private idx: int = 0
10110
10111    constructor(parent: float[]) {
10112        this.parent = parent
10113    }
10114
10115    override next(): IteratorResult<float> {
10116        if (this.idx >= this.parent.length) {
10117            return new IteratorResult<float>()
10118        }
10119        return new IteratorResult<float>(this.parent[this.idx++])
10120    }
10121
10122    override $_iterator(): IterableIterator<float> {
10123        return this;
10124    }
10125
10126    public __Iterator_getLength(): int {
10127        return this.parent.length as int
10128    }
10129}
10130
10131class ArrayEntriesIterator_float implements IterableIterator<[number, float]> {
10132    private parent: float[]
10133    private idx: int = 0
10134
10135    constructor(parent: float[]) {
10136        this.parent = parent
10137    }
10138
10139    override next(): IteratorResult<[number, float]> {
10140        if (this.idx >= this.parent.length) {
10141            return new IteratorResult<[number, float]>()
10142        }
10143        const i = this.idx++;
10144        const vl: [number, float] = [i as number, this.parent[i]]
10145        return new IteratorResult<[number, float]>(vl);
10146    }
10147
10148    override $_iterator(): IterableIterator<[number, float]> {
10149        return this;
10150    }
10151
10152    public __Iterator_getLength(): int {
10153        return this.parent.length as int
10154    }
10155}
10156
10157function cloneArray(self: double[]): double[] {
10158    const ret = new double[self.length];;
10159    for (let i = 0; i < self.length; i++) {
10160        ret[i] = self[i];
10161    }
10162    return ret;
10163}
10164
10165/**
10166 * Takes an integer value and returns the item at that index,
10167 * allowing for positive and negative integers. Negative integers count back
10168 * from the last item in the array.
10169 *
10170 * @param index Zero-based index of the array element to be returned.
10171 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
10172 *
10173 * @returns The element in the array matching the given index.
10174 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
10175 */
10176export function at(self: double[], index: number): Double | undefined {
10177    return at(self, index as int)
10178}
10179
10180/**
10181 * Creates a new `Array` from this `Array` instance and given `Array` instance.
10182 *
10183 * @param other to concatenate into a new array.
10184 *
10185 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
10186 */
10187// export function concat(self: double[], ...items: (double | Concatdouble[])[]): double[] {
10188//     throw new Error("not implemented")
10189// }
10190
10191export function concat(self: double[], ...items: ConcatArray<double>[]): double[] {
10192    let totalAdd = self.length;
10193    for (let i = 0; i < items.length; i++) {
10194        totalAdd += items[i].length as int
10195    }
10196
10197    const buf = new double[totalAdd];
10198
10199    for (let i = 0; i < self.length; i++) {
10200        buf[i] = self[i];
10201    }
10202
10203    let insertTo = self.length;
10204    for (let i = 0; i < items.length; i++) {
10205        const arr = items[i]
10206        const len = arr.length as int
10207        for (let j = 0; j < len; j++) {
10208            buf[insertTo++] = arr.$_get(j)
10209        }
10210    }
10211
10212    return buf;
10213}
10214
10215/**
10216 * Takes an integer value and returns the item at that index,
10217 * allowing for positive and negative integers. Negative integers count back
10218 * from the last item in the array.
10219 *
10220 * @param index Zero-based index of the array element to be returned.
10221 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
10222 *
10223 * @returns The element in the array matching the given index.
10224 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
10225 */
10226export function at(self: double[], index: int): Double | undefined {
10227    let len = self.length;
10228    let k: int;
10229    if (index >= 0) {
10230        k = index;
10231    } else {
10232        k = len + index;
10233    }
10234
10235    if (k < 0 || k >= len) {
10236        return undefined;
10237    }
10238
10239    return self[k];
10240}
10241
10242/**
10243 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10244 *
10245 * @param target index at which to copy the sequence
10246 *
10247 * @param start index at which to start copying elements from
10248 *
10249 * @param end index at which to end copying elements from
10250 *
10251 * @returns this array after transformation
10252 */
10253export function copyWithin(self: double[], target: number, start: number, end?: Number): double[] {
10254    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
10255    return self;
10256}
10257
10258/**
10259 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10260 *
10261 * @param target index at which to copy the sequence
10262 *
10263 * @param start index at which to start copying elements from
10264 *
10265 * @param end index at which to end copying elements from
10266 *
10267 * @returns this array after transformation
10268 */
10269export function copyWithin(self: double[], target: int, start: int, end: int): double[] {
10270    target = normalizeIndex(target, self.length)
10271    start = normalizeIndex(start, self.length)
10272    end = normalizeIndex(end, self.length)
10273
10274    if (end <= start) {
10275        return self;
10276    }
10277
10278    if (target <= start) {
10279        while (start < end) {
10280            const read = self[start++];
10281            self[target++] = read;
10282        }
10283    } else {
10284        let len = end - start;
10285        if (target + len > self.length) {
10286            len = self.length - target
10287        }
10288        for (let i = 0; i < len; i++) {
10289            const read = self[start + len - 1 - i];
10290            self[target + len - 1 - i] = read;
10291        }
10292    }
10293
10294    return self;
10295}
10296
10297/**
10298 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10299 *
10300 * @param target index at which to copy the sequence
10301 *
10302 * @param start index at which to start copying elements from
10303 *
10304 * @returns this array after transformation
10305 */
10306export function copyWithin(self: double[], target: int, start: int): double[] {
10307    copyWithin(self, target, start, self.length);
10308    return self;
10309}
10310
10311/**
10312 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10313 *
10314 * @param target index at which to copy the sequence
10315 *
10316 * @returns this array after transformation
10317 */
10318export function copyWithin(self: double[], target: int): double[] {
10319    copyWithin(self, target, 0, self.length);
10320    return self;
10321}
10322
10323/**
10324 * Changes all elements in the Array to a static value, from a start index to an end index
10325 *
10326 * @param value to fill the array with
10327 *
10328 * @param start index at which to start filling
10329 *
10330 * @param end index at which to end filling, but not including
10331 *
10332 * @returns this array after transformation
10333 */
10334export function fill(self: double[], value: double, start?: Number, end?: Number): double[] {
10335    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
10336    return self;
10337}
10338
10339/**
10340 * Changes all elements in the Array to a static value, from a start index to an end index
10341 *
10342 * @param value to fill the array with
10343 *
10344 * @param start index at which to start filling
10345 *
10346 * @param end index at which to end filling, but not including
10347 *
10348 * @returns this array after transformation
10349 */
10350export function fill(self: double[], value: double, start: int, end: int): double[] {
10351    start = normalizeIndex(start, self.length);
10352    end = normalizeIndex(end, self.length)
10353
10354    for (let i = start; i < end; i++) {
10355        self[i] = value;
10356    }
10357
10358    return self;
10359}
10360
10361/**
10362 * Returns the value of the first element in the array where predicate is true, and undefined
10363 * otherwise.
10364 *
10365 * @param predicate find calls predicate once for each element of the array, in ascending
10366 * order, until it finds one where predicate returns true. If such an element is found, find
10367 * immediately returns that element value. Otherwise, find returns undefined.
10368 *
10369 * @returns the value of the first element in the array or undefined
10370 */
10371export function find(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): Double | undefined {
10372    const res = findIndex(self, predicate)
10373    if (res == -1) {
10374        return undefined
10375    }
10376    return self[res as int];
10377}
10378
10379/**
10380 * Returns the index of the first element in the array where predicate is true, and -1
10381 * otherwise.
10382 *
10383 * @param predicate find calls predicate once for each element of the array, in ascending
10384 * order, until it finds one where predicate returns true. If such an element is found,
10385 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
10386 *
10387 * @returns found element index or -1 otherwise
10388 */
10389export function findIndex(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): number {
10390    for (let i = 0; i < self.length; i++) {
10391        if (predicate(self[i], i as number, self)) {
10392            return i;
10393        }
10394    }
10395    return -1;
10396}
10397
10398/**
10399 * Iterates the array in reverse order and returns the value of the first element
10400 * that satisfies the provided testing function
10401 *
10402 * @param predicate testing function
10403 *
10404 * @returns found element or undefined otherwise
10405 */
10406export function findLast(self: double[], predicate: (elem: double, index: number, array: double[]) => boolean): Double | undefined {
10407    for (let i = self.length - 1; i >= 0; i--) {
10408        const val = self[i];
10409        if (predicate(val, i as number, self)) {
10410            return val;
10411        }
10412    }
10413    return undefined;
10414}
10415
10416/**
10417 * Determines whether all the members of an array satisfy the specified test.
10418 *
10419 * @param predicate A function that accepts up to three arguments. The every method calls
10420 * the predicate function for each element in the array until the predicate returns a value
10421 * which is coercible to the Boolean value false, or until the end of the array.
10422 *
10423 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
10424 */
10425export function every(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): boolean {
10426    for (let i = 0; i < self.length; i++) {
10427        if (!predicate(self[i], i as number, self)) {
10428            return false
10429        }
10430    }
10431    return true;
10432}
10433
10434/**
10435 * Determines whether the specified callback function returns true for any element of an array.
10436 *
10437 * @param predicate A function that accepts up to three arguments. The some method calls
10438 * the predicate function for each element in the array until the predicate returns a value
10439 * which is coercible to the Boolean value true, or until the end of the array.
10440 *
10441 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
10442 */
10443export function some(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): boolean {
10444    for (let i = 0; i < self.length; i++) {
10445        if (predicate(self[i], i as number, self)) {
10446            return true
10447        }
10448    }
10449    return false
10450}
10451
10452/**
10453 * Returns the elements of an array that meet the condition specified in a callback function.
10454 *
10455 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
10456 *
10457 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
10458 */
10459export function filter(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): double[] {
10460    return filter(self, (value: double, index: number): boolean => predicate(value, index, self));
10461}
10462
10463/**
10464 * Iterates the array in reverse order and returns the index of
10465 * the first element that satisfies the provided testing function.
10466 * If no elements satisfy the testing function, -1 is returned.
10467 *
10468 * @param predicate testing function
10469 *
10470 * @returns index of first element satisfying to predicate, -1 if no such element
10471 */
10472export function findLastIndex(self: double[], predicate: (element: double, index: number, array: double[]) => boolean): number {
10473    for (let i = self.length - 1; i >= 0; i--) {
10474        if (predicate(self[i], i as number, self)) {
10475            return i
10476        }
10477    }
10478    return -1
10479}
10480
10481/**
10482 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10483 *
10484 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
10485 *
10486 * @returns a result after applying callbackfn over all elements of the Array
10487 */
10488export function reduce(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number, array: double[]) => double): double {
10489    if (self.length == 0) {
10490        throw new TypeError("Reduce of empty array with no initial value")
10491    }
10492    let acc: double = self[0];
10493    for (let i = 1; i < self.length; i++) {
10494        acc = callbackfn(acc, self[i], i as number, self)
10495    }
10496    return acc
10497}
10498
10499/**
10500 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10501 *
10502 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
10503 *
10504 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
10505 *
10506 * @returns a result after applying callbackfn over all elements of the Array
10507 */
10508export function reduce<U = double>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number, array: double[]) => U, initialValue: U): U {
10509    let acc = initialValue
10510    for (let i = 0; i < self.length; i++) {
10511        acc = callbackfn(acc, self[i], i as number, self)
10512    }
10513    return acc
10514}
10515
10516/**
10517 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10518 *
10519 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
10520 *
10521 * @returns a result after applying callbackfn over all elements of the Array
10522 */
10523export function reduceRight(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number, array: double[]) => double): double {
10524    if (self.length == 0) {
10525        throw new TypeError("Reduce of empty array with no initial value")
10526    }
10527    let acc: double = self[self.length - 1];
10528    for (let i = self.length - 2; i >= 0; i--) {
10529        acc = callbackfn(acc, self[i], i as number, self)
10530    }
10531    return acc
10532}
10533
10534/**
10535 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10536 *
10537 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
10538 *
10539 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
10540 *
10541 * @returns a result after applying callbackfn over all elements of the Array
10542 */
10543export function reduceRight<U>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number, array: double[]) => U, initialValue: U): U {
10544    let acc = initialValue
10545    for (let i = self.length - 1; i >= 0; i--) {
10546        acc = callbackfn(acc, self[i], i as number, self)
10547    }
10548    return acc
10549}
10550
10551/**
10552 * Performs the specified action for each element in an array.
10553 *
10554 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
10555 */
10556export function forEach(self: double[], callbackfn: (value: double, index: number, array: double[]) => void): void {
10557    const len0 = self.length;
10558    for (let i = 0; i < len0; i++) {
10559        callbackfn(self[i], i as number, self)
10560    }
10561}
10562
10563/**
10564 * Returns the value of the first element in the array where predicate is true, and undefined
10565 * otherwise.
10566 *
10567 * @param predicate find calls predicate once for each element of the array, in ascending
10568 * order, until it finds one where predicate returns true. If such an element is found, find
10569 * immediately returns that element value. Otherwise, find returns undefined.
10570 *
10571 * @returns the value of the first element in the array or undefined
10572 */
10573export function find(self: double[], predicate: (value: double, index: number) => boolean): Double | undefined {
10574    const res = findIndex(self, predicate)
10575    if (res == -1) {
10576        return undefined
10577    }
10578    return self[res as int];
10579}
10580
10581/**
10582 * Returns the index of the first element in the array where predicate is true, and -1
10583 * otherwise.
10584 *
10585 * @param predicate find calls predicate once for each element of the array, in ascending
10586 * order, until it finds one where predicate returns true. If such an element is found,
10587 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
10588 *
10589 * @returns found element index or -1 otherwise
10590 */
10591export function findIndex(self: double[], predicate: (value: double, index: number) => boolean): number {
10592    for (let i = 0; i < self.length; i++) {
10593        if (predicate(self[i], i as number)) {
10594            return i;
10595        }
10596    }
10597    return -1;
10598}
10599
10600/**
10601 * Iterates the array in reverse order and returns the value of the first element
10602 * that satisfies the provided testing function
10603 *
10604 * @param predicate testing function
10605 *
10606 * @returns found element or undefined otherwise
10607 */
10608export function findLast(self: double[], predicate: (elem: double, index: number) => boolean): Double | undefined {
10609    for (let i = self.length - 1; i >= 0; i--) {
10610        const val = self[i];
10611        if (predicate(val, i as number)) {
10612            return val;
10613        }
10614    }
10615    return undefined;
10616}
10617
10618/**
10619 * Determines whether all the members of an array satisfy the specified test.
10620 *
10621 * @param predicate A function that accepts up to three arguments. The every method calls
10622 * the predicate function for each element in the array until the predicate returns a value
10623 * which is coercible to the Boolean value false, or until the end of the array.
10624 *
10625 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
10626 */
10627export function every(self: double[], predicate: (value: double, index: number) => boolean): boolean {
10628    for (let i = 0; i < self.length; i++) {
10629        if (!predicate(self[i], i as number)) {
10630            return false
10631        }
10632    }
10633    return true;
10634}
10635
10636/**
10637 * Determines whether the specified callback function returns true for any element of an array.
10638 *
10639 * @param predicate A function that accepts up to three arguments. The some method calls
10640 * the predicate function for each element in the array until the predicate returns a value
10641 * which is coercible to the Boolean value true, or until the end of the array.
10642 *
10643 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
10644 */
10645export function some(self: double[], predicate: (value: double, index: number) => boolean): boolean {
10646    for (let i = 0; i < self.length; i++) {
10647        if (predicate(self[i], i as number)) {
10648            return true
10649        }
10650    }
10651    return false
10652}
10653
10654/**
10655 * Iterates the array in reverse order and returns the index of
10656 * the first element that satisfies the provided testing function.
10657 * If no elements satisfy the testing function, -1 is returned.
10658 *
10659 * @param predicate testing function
10660 *
10661 * @returns index of first element satisfying to predicate, -1 if no such element
10662 */
10663export function findLastIndex(self: double[], predicate: (element: double, index: number) => boolean): number {
10664    for (let i = self.length - 1; i >= 0; i--) {
10665        if (predicate(self[i], i as number)) {
10666            return i
10667        }
10668    }
10669    return -1
10670}
10671
10672/**
10673 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10674 *
10675 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
10676 *
10677 * @returns a result after applying callbackfn over all elements of the Array
10678 */
10679export function reduce(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number) => double): double {
10680    if (self.length == 0) {
10681        throw new TypeError("Reduce of empty array with no initial value")
10682    }
10683    let acc: double = self[0];
10684    for (let i = 1; i < self.length; i++) {
10685        acc = callbackfn(acc, self[i], i as number)
10686    }
10687    return acc
10688}
10689
10690/**
10691 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10692 *
10693 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
10694 *
10695 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
10696 *
10697 * @returns a result after applying callbackfn over all elements of the Array
10698 */
10699export function reduce<U = double>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number) => U, initialValue: U): U {
10700    let acc = initialValue
10701    for (let i = 0; i < self.length; i++) {
10702        acc = callbackfn(acc, self[i], i as number)
10703    }
10704    return acc
10705}
10706
10707/**
10708 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10709 *
10710 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
10711 *
10712 * @returns a result after applying callbackfn over all elements of the Array
10713 */
10714export function reduceRight(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number) => double): double {
10715    if (self.length == 0) {
10716        throw new TypeError("Reduce of empty array with no initial value")
10717    }
10718    let acc: double = self[self.length - 1];
10719    for (let i = self.length - 2; i >= 0; i--) {
10720        acc = callbackfn(acc, self[i], i as number)
10721    }
10722    return acc
10723}
10724
10725/**
10726 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10727 *
10728 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
10729 *
10730 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
10731 *
10732 * @returns a result after applying callbackfn over all elements of the Array
10733 */
10734export function reduceRight<U>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number) => U, initialValue: U): U {
10735    let acc = initialValue
10736    for (let i = self.length - 1; i >= 0; i--) {
10737        acc = callbackfn(acc, self[i], i as number)
10738    }
10739    return acc
10740}
10741
10742/**
10743 * Performs the specified action for each element in an array.
10744 *
10745 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
10746 */
10747export function forEach(self: double[], callbackfn: (value: double, index: number) => void): void {
10748    const len0 = self.length;
10749    for (let i = 0; i < len0; i++) {
10750        callbackfn(self[i], i as number)
10751    }
10752}
10753
10754/**
10755 * Returns the value of the first element in the array where predicate is true, and undefined
10756 * otherwise.
10757 *
10758 * @param predicate find calls predicate once for each element of the array, in ascending
10759 * order, until it finds one where predicate returns true. If such an element is found, find
10760 * immediately returns that element value. Otherwise, find returns undefined.
10761 *
10762 * @returns the value of the first element in the array or undefined
10763 */
10764export function find(self: double[], predicate: (value: double) => boolean): Double | undefined {
10765    const res = findIndex(self, predicate)
10766    if (res == -1) {
10767        return undefined
10768    }
10769    return self[res as int];
10770}
10771
10772/**
10773 * Returns the index of the first element in the array where predicate is true, and -1
10774 * otherwise.
10775 *
10776 * @param predicate find calls predicate once for each element of the array, in ascending
10777 * order, until it finds one where predicate returns true. If such an element is found,
10778 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
10779 *
10780 * @returns found element index or -1 otherwise
10781 */
10782export function findIndex(self: double[], predicate: (value: double) => boolean): number {
10783    for (let i = 0; i < self.length; i++) {
10784        if (predicate(self[i])) {
10785            return i;
10786        }
10787    }
10788    return -1;
10789}
10790
10791/**
10792 * Iterates the array in reverse order and returns the value of the first element
10793 * that satisfies the provided testing function
10794 *
10795 * @param predicate testing function
10796 *
10797 * @returns found element or undefined otherwise
10798 */
10799export function findLast(self: double[], predicate: (elem: double) => boolean): Double | undefined {
10800    for (let i = self.length - 1; i >= 0; i--) {
10801        const val = self[i];
10802        if (predicate(val)) {
10803            return val;
10804        }
10805    }
10806    return undefined;
10807}
10808
10809/**
10810 * Determines whether all the members of an array satisfy the specified test.
10811 *
10812 * @param predicate A function that accepts up to three arguments. The every method calls
10813 * the predicate function for each element in the array until the predicate returns a value
10814 * which is coercible to the Boolean value false, or until the end of the array.
10815 *
10816 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
10817 */
10818export function every(self: double[], predicate: (value: double) => boolean): boolean {
10819    for (let i = 0; i < self.length; i++) {
10820        if (!predicate(self[i])) {
10821            return false
10822        }
10823    }
10824    return true;
10825}
10826
10827/**
10828 * Determines whether the specified callback function returns true for any element of an array.
10829 *
10830 * @param predicate A function that accepts up to three arguments. The some method calls
10831 * the predicate function for each element in the array until the predicate returns a value
10832 * which is coercible to the Boolean value true, or until the end of the array.
10833 *
10834 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
10835 */
10836export function some(self: double[], predicate: (value: double) => boolean): boolean {
10837    for (let i = 0; i < self.length; i++) {
10838        if (predicate(self[i])) {
10839            return true
10840        }
10841    }
10842    return false
10843}
10844
10845/**
10846 * Returns the elements of an array that meet the condition specified in a callback function.
10847 *
10848 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
10849 *
10850 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
10851 */
10852export function filter(self: double[], predicate: (value: double) => boolean): double[] {
10853    return filter(self, (value: double, index: number): boolean => predicate(value));
10854}
10855
10856/**
10857 * Iterates the array in reverse order and returns the index of
10858 * the first element that satisfies the provided testing function.
10859 * If no elements satisfy the testing function, -1 is returned.
10860 *
10861 * @param predicate testing function
10862 *
10863 * @returns index of first element satisfying to predicate, -1 if no such element
10864 */
10865export function findLastIndex(self: double[], predicate: (element: double) => boolean): number {
10866    for (let i = self.length - 1; i >= 0; i--) {
10867        if (predicate(self[i])) {
10868            return i
10869        }
10870    }
10871    return -1
10872}
10873
10874/**
10875 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10876 *
10877 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
10878 *
10879 * @returns a result after applying callbackfn over all elements of the Array
10880 */
10881export function reduce(self: double[], callbackfn: (previousValue: double, currentValue: double) => double): double {
10882    if (self.length == 0) {
10883        throw new TypeError("Reduce of empty array with no initial value")
10884    }
10885    let acc: double = self[0];
10886    for (let i = 1; i < self.length; i++) {
10887        acc = callbackfn(acc, self[i])
10888    }
10889    return acc
10890}
10891
10892/**
10893 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10894 *
10895 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
10896 *
10897 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
10898 *
10899 * @returns a result after applying callbackfn over all elements of the Array
10900 */
10901export function reduce<U = double>(self: double[], callbackfn: (previousValue: U, currentValue: double) => U, initialValue: U): U {
10902    let acc = initialValue
10903    for (let i = 0; i < self.length; i++) {
10904        acc = callbackfn(acc, self[i])
10905    }
10906    return acc
10907}
10908
10909/**
10910 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10911 *
10912 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
10913 *
10914 * @returns a result after applying callbackfn over all elements of the Array
10915 */
10916export function reduceRight(self: double[], callbackfn: (previousValue: double, currentValue: double) => double): double {
10917    if (self.length == 0) {
10918        throw new TypeError("Reduce of empty array with no initial value")
10919    }
10920    let acc: double = self[self.length - 1];
10921    for (let i = self.length - 2; i >= 0; i--) {
10922        acc = callbackfn(acc, self[i])
10923    }
10924    return acc
10925}
10926
10927/**
10928 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
10929 *
10930 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
10931 *
10932 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
10933 *
10934 * @returns a result after applying callbackfn over all elements of the Array
10935 */
10936export function reduceRight<U>(self: double[], callbackfn: (previousValue: U, currentValue: double) => U, initialValue: U): U {
10937    let acc = initialValue
10938    for (let i = self.length - 1; i >= 0; i--) {
10939        acc = callbackfn(acc, self[i])
10940    }
10941    return acc
10942}
10943
10944/**
10945 * Performs the specified action for each element in an array.
10946 *
10947 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
10948 */
10949export function forEach(self: double[], callbackfn: (value: double) => void): void {
10950    const len0 = self.length;
10951    for (let i = 0; i < len0; i++) {
10952        callbackfn(self[i])
10953    }
10954}
10955
10956/**
10957 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
10958 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
10959 *
10960 * @param start zero-based index at which to start extraction
10961 *
10962 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
10963 *
10964 * @returns `Array` instance, constructed from extracted elements of `this` instance.
10965 */
10966export function slice(self: double[], start?: Number, end?: Number): double[] {
10967    const len: int = self.length;
10968    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
10969}
10970
10971/**
10972 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
10973 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
10974 *
10975 * @param start zero-based index at which to start extraction
10976 *
10977 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
10978 *
10979 * @returns `Array` instance, constructed from extracted elements of `this` instance.
10980 */
10981export function slice(self: double[], start: int, end: int): double[] {
10982    const len: int = self.length;
10983    const relStart = normalizeIndex(start, len)
10984    const relEnd = normalizeIndex(end, len)
10985
10986    let count = relEnd - relStart;
10987    if (count < 0) {
10988        count = 0;
10989    }
10990    let res = new double[count]
10991    for (let i = 0; i < count; i++) {
10992        res[i] = self[relStart + i];
10993    }
10994
10995    return res
10996}
10997
10998/**
10999 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
11000 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
11001 *
11002 * @param start zero-based index at which to start extraction
11003 *
11004 * @returns `Array` instance, constructed from extracted elements of `this` instance.
11005 */
11006export function slice(self: double[], start: int): double[] {
11007    return slice(self, start, Int.MAX_VALUE as int);
11008}
11009
11010/**
11011 * Returns the last index at which a given element can be found in the array,
11012 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
11013 *
11014 * @param element element to locate in the array.
11015 * @param fromIndex zero-based index at which to start searching backwards.
11016 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
11017 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
11018 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
11019 *
11020 * @returns The last index of the element in the array; -1 if not found.
11021 */
11022export function lastIndexOf(self: double[], element: double, fromIndex: int): int {
11023    if (self.length == 0) {
11024        return -1;
11025    }
11026    let n = fromIndex;
11027    let k: int;
11028    if (n >= 0) {
11029        k = min(self.length - 1, n);
11030    } else {
11031        k = self.length + n;
11032    }
11033
11034    while (k >= 0) {
11035        if (__runtimeEquals(self[k], element)) {
11036            return k;
11037        }
11038        k--;
11039    }
11040    return -1;
11041}
11042
11043/**
11044 * Returns the last index at which a given element can be found in the array,
11045 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
11046 *
11047 * @param element element to locate in the array.
11048 * @param fromIndex zero-based index at which to start searching backwards.
11049 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
11050 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
11051 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
11052 *
11053 * @returns The last index of the element in the array; -1 if not found.
11054 */
11055export function lastIndexOf(self: double[], element: double, fromIndex?: Number): number {
11056    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
11057}
11058
11059/**
11060 * Creates and returns a new string by concatenating all of the elements in an `Array`,
11061 * separated by a specified separator string.
11062 * If the array has only one item, then that item will be returned without using the separator.
11063 *
11064 * @param sep specifies a separator
11065 *
11066 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
11067 */
11068export function join(self: double[], sep?: String): string {
11069    if (self.length == 0) {
11070        return ""
11071    }
11072    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
11073    let sb = new StringBuilder(new String(self[0]))
11074    for (let i: int = 1; i < self.length; i++) {
11075        const tmp = self[i]
11076        sb.append(sepReal);
11077        sb.append(tmp)
11078    }
11079
11080    return sb.toString();
11081}
11082
11083/**
11084 * Returns a string representing the specified array and its elements.
11085 *
11086 * @returns string representation
11087 */
11088export function toString(self: double[], ): string {
11089    return join(self, ",");
11090}
11091
11092/**
11093 * Returns a locale string representing the specified array and its elements.
11094 *
11095 * @param locales
11096 *
11097 * @param options
11098 *
11099 * @returns string representation
11100 */
11101export function toLocaleString(self: double[], locales: Object, options: Object): string {
11102    throw new Error("Array.toLocaleString: not implemented")
11103}
11104
11105/**
11106 * Returns a locale string representing the specified array and its elements.
11107 *
11108 * @param options
11109 *
11110 * @returns string representation
11111 */
11112export function toLocaleString(self: double[], locales: Object): string {
11113    return toLocaleString(self, new Object(), new Object())
11114}
11115
11116/**
11117 * Returns a locale string representing the specified array and its elements.
11118 *
11119 * @returns string representation
11120 */
11121export function toLocaleString(self: double[], ): string {
11122    const sb = new StringBuilder()
11123    const len = self.length;
11124    for (let i = 0; i < len; i++) {
11125        if (i != 0) {
11126            sb.append(",")
11127        }
11128        let x = self[i] as NullishType;
11129        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
11130            sb.append(x!.toLocaleString())
11131        }
11132    }
11133    return sb.toString()
11134}
11135
11136/**
11137 * Copying version of the splice() method.
11138 *
11139 * @param start index
11140 *
11141 * @param delete number of items after start index
11142 *
11143 * @returns a new Array with some elements removed and/or replaced at a given index.
11144 */
11145export function toSpliced(self: double[], start?: Number, delete?: Number): double[] {
11146    const len = self.length;
11147    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
11148}
11149
11150/**
11151 * Copying version of the splice() method.
11152 *
11153 * @param start index
11154 *
11155 * @param delete number of items after start index
11156 *
11157 * @returns a new Array with some elements removed and/or replaced at a given index.
11158 */
11159export function toSpliced(self: double[], start: number, delete: number, ...items: double[]): double[] {
11160    const len = self.length;
11161    return toSpliced(self, start as int, delete as int, ...items)
11162}
11163
11164/**
11165 * Copying version of the splice() method.
11166 *
11167 * @param start index
11168 *
11169 * @param delete number of items after start index
11170 *
11171 * @returns a new Array with some elements removed and/or replaced at a given index.
11172 */
11173export function toSpliced(self: double[], start: int, delete: int, ...items: double[]): double[] {
11174    const len = self.length;
11175    start = normalizeIndex(start, len);
11176    if (delete < 0) {
11177        delete = 0;
11178    } else if (delete > len) {
11179        delete = len;
11180    }
11181    if (start > len - delete) {
11182        delete = len - start
11183    }
11184    const res = new double[len - delete + items.length];
11185    for (let i = 0; i < start; i++) {
11186        res[i] = self[i]
11187    }
11188    for (let i = 0; i < items.length; i++) {
11189        res[start + i] = items[i]
11190    }
11191    for (let i = start + delete; i < len; i++) {
11192        res[i - delete + items.length] = self[i]
11193    }
11194    return res;
11195}
11196
11197/**
11198 * Copying version of the splice() method.
11199 *
11200 * @param start index
11201 *
11202 * @returns a new Array with some elements removed and/or replaced at a given index.
11203 */
11204export function toSpliced(self: double[], start: int): double[] {
11205    return toSpliced(self, start, self.length)
11206}
11207
11208/**
11209 * Checks whether an Array includes a certain value among its entries,
11210 * returning true or false as appropriate.
11211 *
11212 * @param val value to search
11213 *
11214 * @param fromIndex start index
11215 *
11216 * @returns true if val is in Array
11217 */
11218export function includes(self: double[], val: double, fromIndex?: Number): boolean {
11219    const len = self.length;
11220    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
11221    if (isNaN(val)) {
11222        for (let i = fi; i < len; i++) {
11223            if (isNaN(self[i])) {
11224                return true;
11225            }
11226        }
11227        return false;
11228    }
11229    for (let i = fi; i < len; i++) {
11230        if (val == self[i]) {
11231            return true;
11232        }
11233    }
11234    return false;
11235}
11236
11237/**
11238 * Returns the first index at which a given element
11239 * can be found in the array, or -1 if it is not present.
11240 *
11241 * @param val value to search
11242 *
11243 * @param fromIndex index to search from
11244 *
11245 * @returns index of val, -1 otherwise
11246 */
11247export function indexOf(self: double[], val: double, fromIndex: int): int {
11248    fromIndex = normalizeIndex(fromIndex, self.length)
11249    for (let i = fromIndex; i < self.length; i++) {
11250        if (__runtimeEquals(val, self[i])) {
11251            return i
11252        }
11253    }
11254    return -1
11255}
11256
11257/**
11258 * Returns the first index at which a given element
11259 * can be found in the array, or -1 if it is not present.
11260 *
11261 * @param val value to search
11262 *
11263 * @param fromIndex index to search from
11264 *
11265 * @returns index of val, -1 otherwise
11266 */
11267export function indexOf(self: double[], val: double, fromIndex?: Number): number {
11268    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
11269}
11270
11271/**
11272 * Copying version of the sort() method.
11273 * It returns a new array with the elements sorted in ascending order.
11274 *
11275 * @returns sorted copy of hte current instance using default comparator
11276 */
11277export function toSorted(self: double[], ): double[] {
11278    let arr = cloneArray(self);
11279    sort(arr, )
11280    return arr
11281}
11282
11283/**
11284 * Copying version of the sort() method.
11285 * It returns a new array with the elements sorted in ascending order.
11286 *
11287 * @param comparator function to compare to elements of the Array
11288 *
11289 * @returns sorted copy of the current instance comparator
11290 */
11291export function toSorted(self: double[], comparator: (a: double, b: double) => number): double[] {
11292    let arr = cloneArray(self);
11293    sort(arr, comparator)
11294    return arr
11295}
11296
11297/**
11298 * Modifies `this` instance of `Array` class and populates
11299 * it with same elements ordered towards the direction opposite to that previously stated.
11300 *
11301 * @note Mutating method
11302 */
11303export function reverse(self: double[], ): double[] {
11304    for (let i = 0; i < self.length / 2; i++) {
11305        const tmp = self[i];
11306        const idx_r = self.length - 1 - i;
11307        const val_r = self[idx_r];
11308        self[i] = val_r;
11309        self[idx_r] = tmp;
11310    }
11311    return self;
11312}
11313
11314/**
11315 * Copying version of the reverse() method.
11316 * It returns a new array with the elements in reversed order.
11317 *
11318 * @returns reversed copy of the current Array
11319 */
11320export function toReversed(self: double[], ): double[] {
11321    let arr = new double[self.length]
11322    for (let i = 0; i < self.length; i++) {
11323        arr[self.length - 1 - i] = self[i]
11324    }
11325    return arr
11326}
11327
11328/**
11329 * Copying version of using the bracket notation to change the value of a given index.
11330 * It returns a new Array with the element at the given index replaced with the given value.
11331 *
11332 * @param index to replace
11333 *
11334 * @param value new value
11335 *
11336 * @returns a new Array with the element at the given index replaced with the given value
11337 */
11338export function with(self: double[], index: number, value: double): double[] {
11339    return with(self, index as int, value)
11340}
11341
11342/**
11343 * Copying version of using the bracket notation to change the value of a given index.
11344 * It returns a new Array with the element at the given index replaced with the given value.
11345 *
11346 * @param index to replace
11347 *
11348 * @param value new value
11349 *
11350 * @returns a new Array with the element at the given index replaced with the given value
11351 */
11352export function with(self: double[], index: int, value: double): double[] {
11353    if (index < 0) {
11354        index += self.length;
11355    }
11356    if (index >= self.length) {
11357        throw new RangeError("Invalid index")
11358    }
11359    let arr = cloneArray(self);
11360    arr[index] = value;
11361    return arr
11362}
11363
11364/**
11365 * Returns an iterator over all values
11366 */
11367export function values(self: double[], ): IterableIterator<double> {
11368    return new ArrayValuesIterator_double(self);
11369}
11370
11371/**
11372 * Returns an iterable of key, value pairs for every entry in the array
11373 */
11374export function entries(self: double[], ): IterableIterator<[number, double]> {
11375    return new ArrayEntriesIterator_double(self);
11376}
11377
11378/**
11379 * Determines whether all the members of an array satisfy the specified test.
11380 *
11381 * @param predicate A function that accepts up to three arguments. The every method calls
11382 * the predicate function for each element in the array until the predicate returns a value
11383 * which is coercible to the Boolean value false, or until the end of the array.
11384 *
11385 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
11386 */
11387export function every(self: double[], predicate: () => boolean): boolean {
11388    for (let i = 0; i < self.length; i++) {
11389        if (!predicate()) {
11390            return false
11391        }
11392    }
11393    return true
11394}
11395
11396/**
11397 * Returns the elements of an array that meet the condition specified in a callback function.
11398 *
11399 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
11400 *
11401 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
11402 */
11403export function filter(self: double[], predicate: () => boolean): double[] {
11404    return filter(self, (value: double, index: number): boolean => predicate());
11405}
11406
11407/**
11408 * Returns the value of the first element in the array where predicate is true, and undefined
11409 * otherwise.
11410 *
11411 * @param predicate find calls predicate once for each element of the array, in ascending
11412 * order, until it finds one where predicate returns true. If such an element is found, find
11413 * immediately returns that element value. Otherwise, find returns undefined.
11414 *
11415 * @returns the value of the first element in the array or undefined
11416 */
11417export function find(self: double[], predicate: () => boolean): Double | undefined {
11418    const res = findIndex(self, predicate)
11419    if (res == -1) {
11420        return undefined
11421    }
11422    return self[res as int];
11423}
11424
11425/**
11426 * Returns the index of the first element in the array where predicate is true, and -1
11427 * otherwise.
11428 *
11429 * @param predicate find calls predicate once for each element of the array, in ascending
11430 * order, until it finds one where predicate returns true. If such an element is found,
11431 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
11432 *
11433 * @returns found element index or -1 otherwise
11434 */
11435export function findIndex(self: double[], predicate: () => boolean): number {
11436    for (let i = 0; i < self.length; i++) {
11437        if (predicate()) {
11438            return i;
11439        }
11440    }
11441    return -1;
11442}
11443
11444/**
11445 * Performs the specified action for each element in an array.
11446 *
11447 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
11448 */
11449export function forEach(self: double[], callbackfn: () => void): void {
11450    const len0 = self.length;
11451    for (let i = 0; i < len0; i++) {
11452        callbackfn()
11453    }
11454}
11455
11456/**
11457 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11458 *
11459 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
11460 *
11461 * @returns a result after applying callbackfn over all elements of the Array
11462 */
11463export function reduce(self: double[], callbackfn: (previousValue: double) => double): double {
11464    if (self.length == 0) {
11465        throw new TypeError("Reduce of empty array with no initial value")
11466    }
11467    let acc: double = self[0];
11468    for (let i = 1; i < self.length; i++) {
11469        acc = callbackfn(acc)
11470    }
11471    return acc
11472}
11473
11474/**
11475 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11476 *
11477 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
11478 *
11479 * @returns a result after applying callbackfn over all elements of the Array
11480 */
11481export function reduce(self: double[], callbackfn: () => double): double {
11482    if (self.length == 0) {
11483        throw new TypeError("Reduce of empty array with no initial value")
11484    }
11485    let acc: double = self[0];
11486    for (let i = 1; i < self.length; i++) {
11487        acc = callbackfn()
11488    }
11489    return acc
11490}
11491
11492/**
11493 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11494 *
11495 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
11496 *
11497 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
11498 *
11499 * @returns a result after applying callbackfn over all elements of the Array
11500 */
11501export function reduce<U = double>(self: double[], callbackfn: (previousValue: U) => U, initialValue: U): U {
11502    let acc = initialValue
11503    for (let i = 0; i < self.length; i++) {
11504        acc = callbackfn(acc)
11505    }
11506    return acc
11507}
11508
11509/**
11510 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11511 *
11512 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
11513 *
11514 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
11515 *
11516 * @returns a result after applying callbackfn over all elements of the Array
11517 */
11518export function reduce<U = double>(self: double[], callbackfn: () => U, initialValue: U): U {
11519    let acc = initialValue
11520    for (let i = 0; i < self.length; i++) {
11521        acc = callbackfn()
11522    }
11523    return acc
11524}
11525
11526/**
11527 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11528 *
11529 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
11530 *
11531 * @returns a result after applying callbackfn over all elements of the Array
11532 */
11533export function reduceRight(self: double[], callbackfn: (previousValue: double) => double): double {
11534    if (self.length == 0) {
11535        throw new TypeError("Reduce of empty array with no initial value")
11536    }
11537    let acc: double = self[self.length - 1];
11538    for (let i = self.length - 2; i >= 0; i--) {
11539        acc = callbackfn(acc)
11540    }
11541    return acc
11542}
11543
11544/**
11545 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11546 *
11547 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
11548 *
11549 * @returns a result after applying callbackfn over all elements of the Array
11550 */
11551export function reduceRight(self: double[], callbackfn: () => double): double {
11552    if (self.length == 0) {
11553        throw new TypeError("Reduce of empty array with no initial value")
11554    }
11555    let acc: double = self[self.length - 1];
11556    for (let i = self.length - 2; i >= 0; i--) {
11557        acc = callbackfn()
11558    }
11559    return acc
11560}
11561
11562/**
11563 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11564 *
11565 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
11566 *
11567 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
11568 *
11569 * @returns a result after applying callbackfn over all elements of the Array
11570 */
11571export function reduceRight<U>(self: double[], callbackfn: (previousValue: U) => U, initialValue: U): U {
11572    let acc = initialValue
11573    for (let i = self.length - 1; i >= 0; i--) {
11574        acc = callbackfn(acc)
11575    }
11576    return acc
11577}
11578
11579/**
11580 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
11581 *
11582 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
11583 *
11584 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
11585 *
11586 * @returns a result after applying callbackfn over all elements of the Array
11587 */
11588export function reduceRight<U>(self: double[], callbackfn: () => U, initialValue: U): U {
11589    let acc = initialValue
11590    for (let i = self.length - 1; i >= 0; i--) {
11591        acc = callbackfn()
11592    }
11593    return acc
11594}
11595
11596/**
11597 * Determines whether the specified callback function returns true for any element of an array.
11598 *
11599 * @param predicate A function that accepts up to three arguments. The some method calls
11600 * the predicate function for each element in the array until the predicate returns a value
11601 * which is coercible to the Boolean value true, or until the end of the array.
11602 *
11603 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
11604 */
11605export function some(self: double[], predicate: () => boolean): boolean {
11606    for (let i = 0; i < self.length; i++) {
11607        if (predicate()) {
11608            return true
11609        }
11610    }
11611    return false
11612}
11613
11614/**
11615 * Iterates the array in reverse order and returns the value of the first element
11616 * that satisfies the provided testing function
11617 *
11618 * @param predicate testing function
11619 *
11620 * @returns found element or undefined otherwise
11621 */
11622export function findLast(self: double[], predicate: () => boolean): Double | undefined {
11623    for (let i = self.length - 1; i >= 0; i--) {
11624        const val = self[i];
11625        if (predicate()) {
11626            return val;
11627        }
11628    }
11629    return undefined;
11630}
11631
11632/**
11633 * Iterates the array in reverse order and returns the index of
11634 * the first element that satisfies the provided testing function.
11635 * If no elements satisfy the testing function, -1 is returned.
11636 *
11637 * @param predicate testing function
11638 *
11639 * @returns index of first element satisfying to predicate, -1 if no such element
11640 */
11641export function findLastIndex(self: double[], predicate: () => boolean): number {
11642    for (let i = self.length - 1; i >= 0; i--) {
11643        if (predicate()) {
11644            return i
11645        }
11646    }
11647    return -1
11648}
11649
11650/**
11651 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
11652 *
11653 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
11654 *
11655 * @returns `Array` instance, constructed from `this` and given function.
11656 */
11657export function map(self: double[], callbackfn: (value: double, index: number, array: double[]) => double): double[] {
11658    const len = self.length;
11659    let res = new double[len];
11660    for (let i = 0; i < len; i++) {
11661        res[i] = callbackfn(self[i], i as number, self);
11662    }
11663    return res;
11664}
11665
11666/**
11667 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
11668 *
11669 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
11670 *
11671 * @returns `Array` instance, constructed from `this` and given function.
11672 */
11673export function map(self: double[], callbackfn: (value: double, index: number) => double): double[] {
11674    const len = self.length;
11675    let res = new double[len];
11676    for (let i = 0; i < len; i++) {
11677        res[i] = callbackfn(self[i], i as number);
11678    }
11679    return res;
11680}
11681
11682/**
11683 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
11684 *
11685 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
11686 *
11687 * @returns `Array` instance, constructed from `this` and given function.
11688 */
11689export function map(self: double[], callbackfn: (value: double) => double): double[] {
11690    const len = self.length;
11691    let res = new double[len];
11692    for (let i = 0; i < len; i++) {
11693        res[i] = callbackfn(self[i]);
11694    }
11695    return res;
11696}
11697
11698/**
11699 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
11700 *
11701 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
11702 *
11703 * @returns `Array` instance, constructed from `this` and given function.
11704 */
11705export function map(self: double[], callbackfn: () => double): double[] {
11706    const len = self.length;
11707    let res = new double[len];
11708    for (let i = 0; i < len; i++) {
11709        res[i] = callbackfn();
11710    }
11711    return res;
11712}
11713
11714/**
11715 * Constructs a new `Array` instance and populates it with
11716 * portion of a given array, filtered down to just the elements from the
11717 * given array that pass the test implemented by the provided function.
11718 *
11719 * @param fn test function, applied to each element of an array.
11720 *
11721 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
11722 */
11723export function filter(self: double[], fn: (v: double, k: number) => boolean): double[] {
11724    const mask = new boolean[self.length]
11725    let cnt = 0
11726
11727    for (let i: int = 0; i < self.length; i++) {
11728        const val = self[i];
11729        if (fn(val, i)) {
11730            mask[i] = true
11731            cnt++;
11732        }
11733    }
11734    const res = new double[cnt];
11735    let idx_store = 0;
11736    for (let i: int = 0; i < self.length; i++) {
11737        if (mask[i]) {
11738            res[idx_store++] = self[i]
11739        }
11740    }
11741    return res;
11742}
11743
11744export function concat(self: double[], fst: double[], ...more: double[][]): double[] {
11745    const lnMin = self.length + fst.length;
11746    let ln = lnMin;
11747    for (let i = 0; i < more.length; i++) {
11748        ln += more[i].length
11749    }
11750    const r = new double[ln];
11751    try {
11752        copyTo(self, r, 0, 0, self.length);
11753        copyTo(fst, r, self.length, 0, fst.length);
11754        let idx = lnMin;
11755        for (let i = 0; i < more.length; i++) {
11756            copyTo(more[i], r, idx, 0, more[i].length);
11757            idx += more[i].length;
11758        }
11759    } catch (e) {
11760        // impossible
11761    }
11762    return r
11763}
11764
11765/**
11766 * Reorders elements of `this` using comparator function.
11767 *
11768 * @param comparator function that defines the sort order.
11769 *
11770 * @note Mutating method
11771 */
11772export function sort(self: double[], comparator: (a: double, b: double) => number): double[] {
11773    sort_subarray(self, 0, self.length, (l: double, r: double): boolean => {
11774        return comparator(l, r ) < 0;
11775    });
11776    return self;
11777}
11778
11779/**
11780 * Reorders elements of `this` using comparator function.
11781 *
11782 * @param comparator function that defines the sort order.
11783 *
11784 * @note Mutating method
11785 */
11786export function sort(self: double[], ): double[] {
11787    sort(self, 0, self.length);
11788    return self;
11789}
11790
11791export function keys(self: double[]): IterableIterator<number> {
11792    return new BuiltinArrayKeysIterator(self.length);
11793}
11794
11795class ArrayValuesIterator_double implements IterableIterator<double> {
11796    private parent: double[]
11797    private idx: int = 0
11798
11799    constructor(parent: double[]) {
11800        this.parent = parent
11801    }
11802
11803    override next(): IteratorResult<double> {
11804        if (this.idx >= this.parent.length) {
11805            return new IteratorResult<double>()
11806        }
11807        return new IteratorResult<double>(this.parent[this.idx++])
11808    }
11809
11810    override $_iterator(): IterableIterator<double> {
11811        return this;
11812    }
11813
11814    public __Iterator_getLength(): int {
11815        return this.parent.length as int
11816    }
11817}
11818
11819class ArrayEntriesIterator_double implements IterableIterator<[number, double]> {
11820    private parent: double[]
11821    private idx: int = 0
11822
11823    constructor(parent: double[]) {
11824        this.parent = parent
11825    }
11826
11827    override next(): IteratorResult<[number, double]> {
11828        if (this.idx >= this.parent.length) {
11829            return new IteratorResult<[number, double]>()
11830        }
11831        const i = this.idx++;
11832        const vl: [number, double] = [i as number, this.parent[i]]
11833        return new IteratorResult<[number, double]>(vl);
11834    }
11835
11836    override $_iterator(): IterableIterator<[number, double]> {
11837        return this;
11838    }
11839
11840    public __Iterator_getLength(): int {
11841        return this.parent.length as int
11842    }
11843}
11844
11845function cloneArray(self: char[]): char[] {
11846    const ret = new char[self.length];;
11847    for (let i = 0; i < self.length; i++) {
11848        ret[i] = self[i];
11849    }
11850    return ret;
11851}
11852
11853/**
11854 * Takes an integer value and returns the item at that index,
11855 * allowing for positive and negative integers. Negative integers count back
11856 * from the last item in the array.
11857 *
11858 * @param index Zero-based index of the array element to be returned.
11859 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
11860 *
11861 * @returns The element in the array matching the given index.
11862 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
11863 */
11864export function at(self: char[], index: number): Char | undefined {
11865    return at(self, index as int)
11866}
11867
11868/**
11869 * Creates a new `Array` from this `Array` instance and given `Array` instance.
11870 *
11871 * @param other to concatenate into a new array.
11872 *
11873 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
11874 */
11875// export function concat(self: char[], ...items: (char | Concatchar[])[]): char[] {
11876//     throw new Error("not implemented")
11877// }
11878
11879export function concat(self: char[], ...items: ConcatArray<char>[]): char[] {
11880    let totalAdd = self.length;
11881    for (let i = 0; i < items.length; i++) {
11882        totalAdd += items[i].length as int
11883    }
11884
11885    const buf = new char[totalAdd];
11886
11887    for (let i = 0; i < self.length; i++) {
11888        buf[i] = self[i];
11889    }
11890
11891    let insertTo = self.length;
11892    for (let i = 0; i < items.length; i++) {
11893        const arr = items[i]
11894        const len = arr.length as int
11895        for (let j = 0; j < len; j++) {
11896            buf[insertTo++] = arr.$_get(j)
11897        }
11898    }
11899
11900    return buf;
11901}
11902
11903/**
11904 * Takes an integer value and returns the item at that index,
11905 * allowing for positive and negative integers. Negative integers count back
11906 * from the last item in the array.
11907 *
11908 * @param index Zero-based index of the array element to be returned.
11909 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
11910 *
11911 * @returns The element in the array matching the given index.
11912 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
11913 */
11914export function at(self: char[], index: int): Char | undefined {
11915    let len = self.length;
11916    let k: int;
11917    if (index >= 0) {
11918        k = index;
11919    } else {
11920        k = len + index;
11921    }
11922
11923    if (k < 0 || k >= len) {
11924        return undefined;
11925    }
11926
11927    return self[k];
11928}
11929
11930/**
11931 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
11932 *
11933 * @param target index at which to copy the sequence
11934 *
11935 * @param start index at which to start copying elements from
11936 *
11937 * @param end index at which to end copying elements from
11938 *
11939 * @returns this array after transformation
11940 */
11941export function copyWithin(self: char[], target: number, start: number, end?: Number): char[] {
11942    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
11943    return self;
11944}
11945
11946/**
11947 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
11948 *
11949 * @param target index at which to copy the sequence
11950 *
11951 * @param start index at which to start copying elements from
11952 *
11953 * @param end index at which to end copying elements from
11954 *
11955 * @returns this array after transformation
11956 */
11957export function copyWithin(self: char[], target: int, start: int, end: int): char[] {
11958    target = normalizeIndex(target, self.length)
11959    start = normalizeIndex(start, self.length)
11960    end = normalizeIndex(end, self.length)
11961
11962    if (end <= start) {
11963        return self;
11964    }
11965
11966    if (target <= start) {
11967        while (start < end) {
11968            const read = self[start++];
11969            self[target++] = read;
11970        }
11971    } else {
11972        let len = end - start;
11973        if (target + len > self.length) {
11974            len = self.length - target
11975        }
11976        for (let i = 0; i < len; i++) {
11977            const read = self[start + len - 1 - i];
11978            self[target + len - 1 - i] = read;
11979        }
11980    }
11981
11982    return self;
11983}
11984
11985/**
11986 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
11987 *
11988 * @param target index at which to copy the sequence
11989 *
11990 * @param start index at which to start copying elements from
11991 *
11992 * @returns this array after transformation
11993 */
11994export function copyWithin(self: char[], target: int, start: int): char[] {
11995    copyWithin(self, target, start, self.length);
11996    return self;
11997}
11998
11999/**
12000 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
12001 *
12002 * @param target index at which to copy the sequence
12003 *
12004 * @returns this array after transformation
12005 */
12006export function copyWithin(self: char[], target: int): char[] {
12007    copyWithin(self, target, 0, self.length);
12008    return self;
12009}
12010
12011/**
12012 * Changes all elements in the Array to a static value, from a start index to an end index
12013 *
12014 * @param value to fill the array with
12015 *
12016 * @param start index at which to start filling
12017 *
12018 * @param end index at which to end filling, but not including
12019 *
12020 * @returns this array after transformation
12021 */
12022export function fill(self: char[], value: char, start?: Number, end?: Number): char[] {
12023    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
12024    return self;
12025}
12026
12027/**
12028 * Changes all elements in the Array to a static value, from a start index to an end index
12029 *
12030 * @param value to fill the array with
12031 *
12032 * @param start index at which to start filling
12033 *
12034 * @param end index at which to end filling, but not including
12035 *
12036 * @returns this array after transformation
12037 */
12038export function fill(self: char[], value: char, start: int, end: int): char[] {
12039    start = normalizeIndex(start, self.length);
12040    end = normalizeIndex(end, self.length)
12041
12042    for (let i = start; i < end; i++) {
12043        self[i] = value;
12044    }
12045
12046    return self;
12047}
12048
12049/**
12050 * Returns the value of the first element in the array where predicate is true, and undefined
12051 * otherwise.
12052 *
12053 * @param predicate find calls predicate once for each element of the array, in ascending
12054 * order, until it finds one where predicate returns true. If such an element is found, find
12055 * immediately returns that element value. Otherwise, find returns undefined.
12056 *
12057 * @returns the value of the first element in the array or undefined
12058 */
12059export function find(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): Char | undefined {
12060    const res = findIndex(self, predicate)
12061    if (res == -1) {
12062        return undefined
12063    }
12064    return self[res as int];
12065}
12066
12067/**
12068 * Returns the index of the first element in the array where predicate is true, and -1
12069 * otherwise.
12070 *
12071 * @param predicate find calls predicate once for each element of the array, in ascending
12072 * order, until it finds one where predicate returns true. If such an element is found,
12073 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
12074 *
12075 * @returns found element index or -1 otherwise
12076 */
12077export function findIndex(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): number {
12078    for (let i = 0; i < self.length; i++) {
12079        if (predicate(self[i], i as number, self)) {
12080            return i;
12081        }
12082    }
12083    return -1;
12084}
12085
12086/**
12087 * Iterates the array in reverse order and returns the value of the first element
12088 * that satisfies the provided testing function
12089 *
12090 * @param predicate testing function
12091 *
12092 * @returns found element or undefined otherwise
12093 */
12094export function findLast(self: char[], predicate: (elem: char, index: number, array: char[]) => boolean): Char | undefined {
12095    for (let i = self.length - 1; i >= 0; i--) {
12096        const val = self[i];
12097        if (predicate(val, i as number, self)) {
12098            return val;
12099        }
12100    }
12101    return undefined;
12102}
12103
12104/**
12105 * Determines whether all the members of an array satisfy the specified test.
12106 *
12107 * @param predicate A function that accepts up to three arguments. The every method calls
12108 * the predicate function for each element in the array until the predicate returns a value
12109 * which is coercible to the Boolean value false, or until the end of the array.
12110 *
12111 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
12112 */
12113export function every(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): boolean {
12114    for (let i = 0; i < self.length; i++) {
12115        if (!predicate(self[i], i as number, self)) {
12116            return false
12117        }
12118    }
12119    return true;
12120}
12121
12122/**
12123 * Determines whether the specified callback function returns true for any element of an array.
12124 *
12125 * @param predicate A function that accepts up to three arguments. The some method calls
12126 * the predicate function for each element in the array until the predicate returns a value
12127 * which is coercible to the Boolean value true, or until the end of the array.
12128 *
12129 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
12130 */
12131export function some(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): boolean {
12132    for (let i = 0; i < self.length; i++) {
12133        if (predicate(self[i], i as number, self)) {
12134            return true
12135        }
12136    }
12137    return false
12138}
12139
12140/**
12141 * Returns the elements of an array that meet the condition specified in a callback function.
12142 *
12143 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
12144 *
12145 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
12146 */
12147export function filter(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): char[] {
12148    return filter(self, (value: char, index: number): boolean => predicate(value, index, self));
12149}
12150
12151/**
12152 * Iterates the array in reverse order and returns the index of
12153 * the first element that satisfies the provided testing function.
12154 * If no elements satisfy the testing function, -1 is returned.
12155 *
12156 * @param predicate testing function
12157 *
12158 * @returns index of first element satisfying to predicate, -1 if no such element
12159 */
12160export function findLastIndex(self: char[], predicate: (element: char, index: number, array: char[]) => boolean): number {
12161    for (let i = self.length - 1; i >= 0; i--) {
12162        if (predicate(self[i], i as number, self)) {
12163            return i
12164        }
12165    }
12166    return -1
12167}
12168
12169/**
12170 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12171 *
12172 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
12173 *
12174 * @returns a result after applying callbackfn over all elements of the Array
12175 */
12176export function reduce(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number, array: char[]) => char): char {
12177    if (self.length == 0) {
12178        throw new TypeError("Reduce of empty array with no initial value")
12179    }
12180    let acc: char = self[0];
12181    for (let i = 1; i < self.length; i++) {
12182        acc = callbackfn(acc, self[i], i as number, self)
12183    }
12184    return acc
12185}
12186
12187/**
12188 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12189 *
12190 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
12191 *
12192 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
12193 *
12194 * @returns a result after applying callbackfn over all elements of the Array
12195 */
12196export function reduce<U = char>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number, array: char[]) => U, initialValue: U): U {
12197    let acc = initialValue
12198    for (let i = 0; i < self.length; i++) {
12199        acc = callbackfn(acc, self[i], i as number, self)
12200    }
12201    return acc
12202}
12203
12204/**
12205 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12206 *
12207 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
12208 *
12209 * @returns a result after applying callbackfn over all elements of the Array
12210 */
12211export function reduceRight(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number, array: char[]) => char): char {
12212    if (self.length == 0) {
12213        throw new TypeError("Reduce of empty array with no initial value")
12214    }
12215    let acc: char = self[self.length - 1];
12216    for (let i = self.length - 2; i >= 0; i--) {
12217        acc = callbackfn(acc, self[i], i as number, self)
12218    }
12219    return acc
12220}
12221
12222/**
12223 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12224 *
12225 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
12226 *
12227 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
12228 *
12229 * @returns a result after applying callbackfn over all elements of the Array
12230 */
12231export function reduceRight<U>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number, array: char[]) => U, initialValue: U): U {
12232    let acc = initialValue
12233    for (let i = self.length - 1; i >= 0; i--) {
12234        acc = callbackfn(acc, self[i], i as number, self)
12235    }
12236    return acc
12237}
12238
12239/**
12240 * Performs the specified action for each element in an array.
12241 *
12242 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
12243 */
12244export function forEach(self: char[], callbackfn: (value: char, index: number, array: char[]) => void): void {
12245    const len0 = self.length;
12246    for (let i = 0; i < len0; i++) {
12247        callbackfn(self[i], i as number, self)
12248    }
12249}
12250
12251/**
12252 * Returns the value of the first element in the array where predicate is true, and undefined
12253 * otherwise.
12254 *
12255 * @param predicate find calls predicate once for each element of the array, in ascending
12256 * order, until it finds one where predicate returns true. If such an element is found, find
12257 * immediately returns that element value. Otherwise, find returns undefined.
12258 *
12259 * @returns the value of the first element in the array or undefined
12260 */
12261export function find(self: char[], predicate: (value: char, index: number) => boolean): Char | undefined {
12262    const res = findIndex(self, predicate)
12263    if (res == -1) {
12264        return undefined
12265    }
12266    return self[res as int];
12267}
12268
12269/**
12270 * Returns the index of the first element in the array where predicate is true, and -1
12271 * otherwise.
12272 *
12273 * @param predicate find calls predicate once for each element of the array, in ascending
12274 * order, until it finds one where predicate returns true. If such an element is found,
12275 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
12276 *
12277 * @returns found element index or -1 otherwise
12278 */
12279export function findIndex(self: char[], predicate: (value: char, index: number) => boolean): number {
12280    for (let i = 0; i < self.length; i++) {
12281        if (predicate(self[i], i as number)) {
12282            return i;
12283        }
12284    }
12285    return -1;
12286}
12287
12288/**
12289 * Iterates the array in reverse order and returns the value of the first element
12290 * that satisfies the provided testing function
12291 *
12292 * @param predicate testing function
12293 *
12294 * @returns found element or undefined otherwise
12295 */
12296export function findLast(self: char[], predicate: (elem: char, index: number) => boolean): Char | undefined {
12297    for (let i = self.length - 1; i >= 0; i--) {
12298        const val = self[i];
12299        if (predicate(val, i as number)) {
12300            return val;
12301        }
12302    }
12303    return undefined;
12304}
12305
12306/**
12307 * Determines whether all the members of an array satisfy the specified test.
12308 *
12309 * @param predicate A function that accepts up to three arguments. The every method calls
12310 * the predicate function for each element in the array until the predicate returns a value
12311 * which is coercible to the Boolean value false, or until the end of the array.
12312 *
12313 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
12314 */
12315export function every(self: char[], predicate: (value: char, index: number) => boolean): boolean {
12316    for (let i = 0; i < self.length; i++) {
12317        if (!predicate(self[i], i as number)) {
12318            return false
12319        }
12320    }
12321    return true;
12322}
12323
12324/**
12325 * Determines whether the specified callback function returns true for any element of an array.
12326 *
12327 * @param predicate A function that accepts up to three arguments. The some method calls
12328 * the predicate function for each element in the array until the predicate returns a value
12329 * which is coercible to the Boolean value true, or until the end of the array.
12330 *
12331 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
12332 */
12333export function some(self: char[], predicate: (value: char, index: number) => boolean): boolean {
12334    for (let i = 0; i < self.length; i++) {
12335        if (predicate(self[i], i as number)) {
12336            return true
12337        }
12338    }
12339    return false
12340}
12341
12342/**
12343 * Iterates the array in reverse order and returns the index of
12344 * the first element that satisfies the provided testing function.
12345 * If no elements satisfy the testing function, -1 is returned.
12346 *
12347 * @param predicate testing function
12348 *
12349 * @returns index of first element satisfying to predicate, -1 if no such element
12350 */
12351export function findLastIndex(self: char[], predicate: (element: char, index: number) => boolean): number {
12352    for (let i = self.length - 1; i >= 0; i--) {
12353        if (predicate(self[i], i as number)) {
12354            return i
12355        }
12356    }
12357    return -1
12358}
12359
12360/**
12361 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12362 *
12363 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
12364 *
12365 * @returns a result after applying callbackfn over all elements of the Array
12366 */
12367export function reduce(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number) => char): char {
12368    if (self.length == 0) {
12369        throw new TypeError("Reduce of empty array with no initial value")
12370    }
12371    let acc: char = self[0];
12372    for (let i = 1; i < self.length; i++) {
12373        acc = callbackfn(acc, self[i], i as number)
12374    }
12375    return acc
12376}
12377
12378/**
12379 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12380 *
12381 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
12382 *
12383 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
12384 *
12385 * @returns a result after applying callbackfn over all elements of the Array
12386 */
12387export function reduce<U = char>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number) => U, initialValue: U): U {
12388    let acc = initialValue
12389    for (let i = 0; i < self.length; i++) {
12390        acc = callbackfn(acc, self[i], i as number)
12391    }
12392    return acc
12393}
12394
12395/**
12396 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12397 *
12398 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
12399 *
12400 * @returns a result after applying callbackfn over all elements of the Array
12401 */
12402export function reduceRight(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number) => char): char {
12403    if (self.length == 0) {
12404        throw new TypeError("Reduce of empty array with no initial value")
12405    }
12406    let acc: char = self[self.length - 1];
12407    for (let i = self.length - 2; i >= 0; i--) {
12408        acc = callbackfn(acc, self[i], i as number)
12409    }
12410    return acc
12411}
12412
12413/**
12414 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12415 *
12416 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
12417 *
12418 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
12419 *
12420 * @returns a result after applying callbackfn over all elements of the Array
12421 */
12422export function reduceRight<U>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number) => U, initialValue: U): U {
12423    let acc = initialValue
12424    for (let i = self.length - 1; i >= 0; i--) {
12425        acc = callbackfn(acc, self[i], i as number)
12426    }
12427    return acc
12428}
12429
12430/**
12431 * Performs the specified action for each element in an array.
12432 *
12433 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
12434 */
12435export function forEach(self: char[], callbackfn: (value: char, index: number) => void): void {
12436    const len0 = self.length;
12437    for (let i = 0; i < len0; i++) {
12438        callbackfn(self[i], i as number)
12439    }
12440}
12441
12442/**
12443 * Returns the value of the first element in the array where predicate is true, and undefined
12444 * otherwise.
12445 *
12446 * @param predicate find calls predicate once for each element of the array, in ascending
12447 * order, until it finds one where predicate returns true. If such an element is found, find
12448 * immediately returns that element value. Otherwise, find returns undefined.
12449 *
12450 * @returns the value of the first element in the array or undefined
12451 */
12452export function find(self: char[], predicate: (value: char) => boolean): Char | undefined {
12453    const res = findIndex(self, predicate)
12454    if (res == -1) {
12455        return undefined
12456    }
12457    return self[res as int];
12458}
12459
12460/**
12461 * Returns the index of the first element in the array where predicate is true, and -1
12462 * otherwise.
12463 *
12464 * @param predicate find calls predicate once for each element of the array, in ascending
12465 * order, until it finds one where predicate returns true. If such an element is found,
12466 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
12467 *
12468 * @returns found element index or -1 otherwise
12469 */
12470export function findIndex(self: char[], predicate: (value: char) => boolean): number {
12471    for (let i = 0; i < self.length; i++) {
12472        if (predicate(self[i])) {
12473            return i;
12474        }
12475    }
12476    return -1;
12477}
12478
12479/**
12480 * Iterates the array in reverse order and returns the value of the first element
12481 * that satisfies the provided testing function
12482 *
12483 * @param predicate testing function
12484 *
12485 * @returns found element or undefined otherwise
12486 */
12487export function findLast(self: char[], predicate: (elem: char) => boolean): Char | undefined {
12488    for (let i = self.length - 1; i >= 0; i--) {
12489        const val = self[i];
12490        if (predicate(val)) {
12491            return val;
12492        }
12493    }
12494    return undefined;
12495}
12496
12497/**
12498 * Determines whether all the members of an array satisfy the specified test.
12499 *
12500 * @param predicate A function that accepts up to three arguments. The every method calls
12501 * the predicate function for each element in the array until the predicate returns a value
12502 * which is coercible to the Boolean value false, or until the end of the array.
12503 *
12504 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
12505 */
12506export function every(self: char[], predicate: (value: char) => boolean): boolean {
12507    for (let i = 0; i < self.length; i++) {
12508        if (!predicate(self[i])) {
12509            return false
12510        }
12511    }
12512    return true;
12513}
12514
12515/**
12516 * Determines whether the specified callback function returns true for any element of an array.
12517 *
12518 * @param predicate A function that accepts up to three arguments. The some method calls
12519 * the predicate function for each element in the array until the predicate returns a value
12520 * which is coercible to the Boolean value true, or until the end of the array.
12521 *
12522 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
12523 */
12524export function some(self: char[], predicate: (value: char) => boolean): boolean {
12525    for (let i = 0; i < self.length; i++) {
12526        if (predicate(self[i])) {
12527            return true
12528        }
12529    }
12530    return false
12531}
12532
12533/**
12534 * Returns the elements of an array that meet the condition specified in a callback function.
12535 *
12536 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
12537 *
12538 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
12539 */
12540export function filter(self: char[], predicate: (value: char) => boolean): char[] {
12541    return filter(self, (value: char, index: number): boolean => predicate(value));
12542}
12543
12544/**
12545 * Iterates the array in reverse order and returns the index of
12546 * the first element that satisfies the provided testing function.
12547 * If no elements satisfy the testing function, -1 is returned.
12548 *
12549 * @param predicate testing function
12550 *
12551 * @returns index of first element satisfying to predicate, -1 if no such element
12552 */
12553export function findLastIndex(self: char[], predicate: (element: char) => boolean): number {
12554    for (let i = self.length - 1; i >= 0; i--) {
12555        if (predicate(self[i])) {
12556            return i
12557        }
12558    }
12559    return -1
12560}
12561
12562/**
12563 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12564 *
12565 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
12566 *
12567 * @returns a result after applying callbackfn over all elements of the Array
12568 */
12569export function reduce(self: char[], callbackfn: (previousValue: char, currentValue: char) => char): char {
12570    if (self.length == 0) {
12571        throw new TypeError("Reduce of empty array with no initial value")
12572    }
12573    let acc: char = self[0];
12574    for (let i = 1; i < self.length; i++) {
12575        acc = callbackfn(acc, self[i])
12576    }
12577    return acc
12578}
12579
12580/**
12581 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12582 *
12583 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
12584 *
12585 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
12586 *
12587 * @returns a result after applying callbackfn over all elements of the Array
12588 */
12589export function reduce<U = char>(self: char[], callbackfn: (previousValue: U, currentValue: char) => U, initialValue: U): U {
12590    let acc = initialValue
12591    for (let i = 0; i < self.length; i++) {
12592        acc = callbackfn(acc, self[i])
12593    }
12594    return acc
12595}
12596
12597/**
12598 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12599 *
12600 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
12601 *
12602 * @returns a result after applying callbackfn over all elements of the Array
12603 */
12604export function reduceRight(self: char[], callbackfn: (previousValue: char, currentValue: char) => char): char {
12605    if (self.length == 0) {
12606        throw new TypeError("Reduce of empty array with no initial value")
12607    }
12608    let acc: char = self[self.length - 1];
12609    for (let i = self.length - 2; i >= 0; i--) {
12610        acc = callbackfn(acc, self[i])
12611    }
12612    return acc
12613}
12614
12615/**
12616 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
12617 *
12618 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
12619 *
12620 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
12621 *
12622 * @returns a result after applying callbackfn over all elements of the Array
12623 */
12624export function reduceRight<U>(self: char[], callbackfn: (previousValue: U, currentValue: char) => U, initialValue: U): U {
12625    let acc = initialValue
12626    for (let i = self.length - 1; i >= 0; i--) {
12627        acc = callbackfn(acc, self[i])
12628    }
12629    return acc
12630}
12631
12632/**
12633 * Performs the specified action for each element in an array.
12634 *
12635 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
12636 */
12637export function forEach(self: char[], callbackfn: (value: char) => void): void {
12638    const len0 = self.length;
12639    for (let i = 0; i < len0; i++) {
12640        callbackfn(self[i])
12641    }
12642}
12643
12644/**
12645 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
12646 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
12647 *
12648 * @param start zero-based index at which to start extraction
12649 *
12650 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
12651 *
12652 * @returns `Array` instance, constructed from extracted elements of `this` instance.
12653 */
12654export function slice(self: char[], start?: Number, end?: Number): char[] {
12655    const len: int = self.length;
12656    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
12657}
12658
12659/**
12660 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
12661 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
12662 *
12663 * @param start zero-based index at which to start extraction
12664 *
12665 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
12666 *
12667 * @returns `Array` instance, constructed from extracted elements of `this` instance.
12668 */
12669export function slice(self: char[], start: int, end: int): char[] {
12670    const len: int = self.length;
12671    const relStart = normalizeIndex(start, len)
12672    const relEnd = normalizeIndex(end, len)
12673
12674    let count = relEnd - relStart;
12675    if (count < 0) {
12676        count = 0;
12677    }
12678    let res = new char[count]
12679    for (let i = 0; i < count; i++) {
12680        res[i] = self[relStart + i];
12681    }
12682
12683    return res
12684}
12685
12686/**
12687 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
12688 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
12689 *
12690 * @param start zero-based index at which to start extraction
12691 *
12692 * @returns `Array` instance, constructed from extracted elements of `this` instance.
12693 */
12694export function slice(self: char[], start: int): char[] {
12695    return slice(self, start, Int.MAX_VALUE as int);
12696}
12697
12698/**
12699 * Returns the last index at which a given element can be found in the array,
12700 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
12701 *
12702 * @param element element to locate in the array.
12703 * @param fromIndex zero-based index at which to start searching backwards.
12704 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
12705 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
12706 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
12707 *
12708 * @returns The last index of the element in the array; -1 if not found.
12709 */
12710export function lastIndexOf(self: char[], element: char, fromIndex: int): int {
12711    if (self.length == 0) {
12712        return -1;
12713    }
12714    let n = fromIndex;
12715    let k: int;
12716    if (n >= 0) {
12717        k = min(self.length - 1, n);
12718    } else {
12719        k = self.length + n;
12720    }
12721
12722    while (k >= 0) {
12723        if (__runtimeEquals(self[k], element)) {
12724            return k;
12725        }
12726        k--;
12727    }
12728    return -1;
12729}
12730
12731/**
12732 * Returns the last index at which a given element can be found in the array,
12733 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
12734 *
12735 * @param element element to locate in the array.
12736 * @param fromIndex zero-based index at which to start searching backwards.
12737 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
12738 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
12739 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
12740 *
12741 * @returns The last index of the element in the array; -1 if not found.
12742 */
12743export function lastIndexOf(self: char[], element: char, fromIndex?: Number): number {
12744    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
12745}
12746
12747/**
12748 * Creates and returns a new string by concatenating all of the elements in an `Array`,
12749 * separated by a specified separator string.
12750 * If the array has only one item, then that item will be returned without using the separator.
12751 *
12752 * @param sep specifies a separator
12753 *
12754 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
12755 */
12756export function join(self: char[], sep?: String): string {
12757    if (self.length == 0) {
12758        return ""
12759    }
12760    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
12761    let sb = new StringBuilder(new String(self[0]))
12762    for (let i: int = 1; i < self.length; i++) {
12763        const tmp = self[i]
12764        sb.append(sepReal);
12765        sb.append(tmp)
12766    }
12767
12768    return sb.toString();
12769}
12770
12771/**
12772 * Returns a string representing the specified array and its elements.
12773 *
12774 * @returns string representation
12775 */
12776export function toString(self: char[], ): string {
12777    return join(self, ",");
12778}
12779
12780/**
12781 * Returns a locale string representing the specified array and its elements.
12782 *
12783 * @param locales
12784 *
12785 * @param options
12786 *
12787 * @returns string representation
12788 */
12789export function toLocaleString(self: char[], locales: Object, options: Object): string {
12790    throw new Error("Array.toLocaleString: not implemented")
12791}
12792
12793/**
12794 * Returns a locale string representing the specified array and its elements.
12795 *
12796 * @param options
12797 *
12798 * @returns string representation
12799 */
12800export function toLocaleString(self: char[], locales: Object): string {
12801    return toLocaleString(self, new Object(), new Object())
12802}
12803
12804/**
12805 * Returns a locale string representing the specified array and its elements.
12806 *
12807 * @returns string representation
12808 */
12809export function toLocaleString(self: char[], ): string {
12810    const sb = new StringBuilder()
12811    const len = self.length;
12812    for (let i = 0; i < len; i++) {
12813        if (i != 0) {
12814            sb.append(",")
12815        }
12816        let x = self[i] as NullishType;
12817        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
12818            sb.append(x!.toLocaleString())
12819        }
12820    }
12821    return sb.toString()
12822}
12823
12824/**
12825 * Copying version of the splice() method.
12826 *
12827 * @param start index
12828 *
12829 * @param delete number of items after start index
12830 *
12831 * @returns a new Array with some elements removed and/or replaced at a given index.
12832 */
12833export function toSpliced(self: char[], start?: Number, delete?: Number): char[] {
12834    const len = self.length;
12835    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
12836}
12837
12838/**
12839 * Copying version of the splice() method.
12840 *
12841 * @param start index
12842 *
12843 * @param delete number of items after start index
12844 *
12845 * @returns a new Array with some elements removed and/or replaced at a given index.
12846 */
12847export function toSpliced(self: char[], start: number, delete: number, ...items: char[]): char[] {
12848    const len = self.length;
12849    return toSpliced(self, start as int, delete as int, ...items)
12850}
12851
12852/**
12853 * Copying version of the splice() method.
12854 *
12855 * @param start index
12856 *
12857 * @param delete number of items after start index
12858 *
12859 * @returns a new Array with some elements removed and/or replaced at a given index.
12860 */
12861export function toSpliced(self: char[], start: int, delete: int, ...items: char[]): char[] {
12862    const len = self.length;
12863    start = normalizeIndex(start, len);
12864    if (delete < 0) {
12865        delete = 0;
12866    } else if (delete > len) {
12867        delete = len;
12868    }
12869    if (start > len - delete) {
12870        delete = len - start
12871    }
12872    const res = new char[len - delete + items.length];
12873    for (let i = 0; i < start; i++) {
12874        res[i] = self[i]
12875    }
12876    for (let i = 0; i < items.length; i++) {
12877        res[start + i] = items[i]
12878    }
12879    for (let i = start + delete; i < len; i++) {
12880        res[i - delete + items.length] = self[i]
12881    }
12882    return res;
12883}
12884
12885/**
12886 * Copying version of the splice() method.
12887 *
12888 * @param start index
12889 *
12890 * @returns a new Array with some elements removed and/or replaced at a given index.
12891 */
12892export function toSpliced(self: char[], start: int): char[] {
12893    return toSpliced(self, start, self.length)
12894}
12895
12896/**
12897 * Checks whether an Array includes a certain value among its entries,
12898 * returning true or false as appropriate.
12899 *
12900 * @param val value to search
12901 *
12902 * @param fromIndex start index
12903 *
12904 * @returns true if val is in Array
12905 */
12906export function includes(self: char[], val: char, fromIndex?: Number): boolean {
12907    const len = self.length;
12908    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
12909    for (let i = fi; i < len; i++) {
12910        if (val == self[i]) {
12911            return true;
12912        }
12913    }
12914    return false;
12915}
12916
12917/**
12918 * Returns the first index at which a given element
12919 * can be found in the array, or -1 if it is not present.
12920 *
12921 * @param val value to search
12922 *
12923 * @param fromIndex index to search from
12924 *
12925 * @returns index of val, -1 otherwise
12926 */
12927export function indexOf(self: char[], val: char, fromIndex: int): int {
12928    fromIndex = normalizeIndex(fromIndex, self.length)
12929    for (let i = fromIndex; i < self.length; i++) {
12930        if (__runtimeEquals(val, self[i])) {
12931            return i
12932        }
12933    }
12934    return -1
12935}
12936
12937/**
12938 * Returns the first index at which a given element
12939 * can be found in the array, or -1 if it is not present.
12940 *
12941 * @param val value to search
12942 *
12943 * @param fromIndex index to search from
12944 *
12945 * @returns index of val, -1 otherwise
12946 */
12947export function indexOf(self: char[], val: char, fromIndex?: Number): number {
12948    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
12949}
12950
12951/**
12952 * Copying version of the sort() method.
12953 * It returns a new array with the elements sorted in ascending order.
12954 *
12955 * @returns sorted copy of hte current instance using default comparator
12956 */
12957export function toSorted(self: char[], ): char[] {
12958    let arr = cloneArray(self);
12959    sort(arr, )
12960    return arr
12961}
12962
12963/**
12964 * Copying version of the sort() method.
12965 * It returns a new array with the elements sorted in ascending order.
12966 *
12967 * @param comparator function to compare to elements of the Array
12968 *
12969 * @returns sorted copy of the current instance comparator
12970 */
12971export function toSorted(self: char[], comparator: (a: char, b: char) => number): char[] {
12972    let arr = cloneArray(self);
12973    sort(arr, comparator)
12974    return arr
12975}
12976
12977/**
12978 * Modifies `this` instance of `Array` class and populates
12979 * it with same elements ordered towards the direction opposite to that previously stated.
12980 *
12981 * @note Mutating method
12982 */
12983export function reverse(self: char[], ): char[] {
12984    for (let i = 0; i < self.length / 2; i++) {
12985        const tmp = self[i];
12986        const idx_r = self.length - 1 - i;
12987        const val_r = self[idx_r];
12988        self[i] = val_r;
12989        self[idx_r] = tmp;
12990    }
12991    return self;
12992}
12993
12994/**
12995 * Copying version of the reverse() method.
12996 * It returns a new array with the elements in reversed order.
12997 *
12998 * @returns reversed copy of the current Array
12999 */
13000export function toReversed(self: char[], ): char[] {
13001    let arr = new char[self.length]
13002    for (let i = 0; i < self.length; i++) {
13003        arr[self.length - 1 - i] = self[i]
13004    }
13005    return arr
13006}
13007
13008/**
13009 * Copying version of using the bracket notation to change the value of a given index.
13010 * It returns a new Array with the element at the given index replaced with the given value.
13011 *
13012 * @param index to replace
13013 *
13014 * @param value new value
13015 *
13016 * @returns a new Array with the element at the given index replaced with the given value
13017 */
13018export function with(self: char[], index: number, value: char): char[] {
13019    return with(self, index as int, value)
13020}
13021
13022/**
13023 * Copying version of using the bracket notation to change the value of a given index.
13024 * It returns a new Array with the element at the given index replaced with the given value.
13025 *
13026 * @param index to replace
13027 *
13028 * @param value new value
13029 *
13030 * @returns a new Array with the element at the given index replaced with the given value
13031 */
13032export function with(self: char[], index: int, value: char): char[] {
13033    if (index < 0) {
13034        index += self.length;
13035    }
13036    if (index >= self.length) {
13037        throw new RangeError("Invalid index")
13038    }
13039    let arr = cloneArray(self);
13040    arr[index] = value;
13041    return arr
13042}
13043
13044/**
13045 * Returns an iterator over all values
13046 */
13047export function values(self: char[], ): IterableIterator<char> {
13048    return new ArrayValuesIterator_char(self);
13049}
13050
13051/**
13052 * Returns an iterable of key, value pairs for every entry in the array
13053 */
13054export function entries(self: char[], ): IterableIterator<[number, char]> {
13055    return new ArrayEntriesIterator_char(self);
13056}
13057
13058/**
13059 * Determines whether all the members of an array satisfy the specified test.
13060 *
13061 * @param predicate A function that accepts up to three arguments. The every method calls
13062 * the predicate function for each element in the array until the predicate returns a value
13063 * which is coercible to the Boolean value false, or until the end of the array.
13064 *
13065 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
13066 */
13067export function every(self: char[], predicate: () => boolean): boolean {
13068    for (let i = 0; i < self.length; i++) {
13069        if (!predicate()) {
13070            return false
13071        }
13072    }
13073    return true
13074}
13075
13076/**
13077 * Returns the elements of an array that meet the condition specified in a callback function.
13078 *
13079 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
13080 *
13081 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
13082 */
13083export function filter(self: char[], predicate: () => boolean): char[] {
13084    return filter(self, (value: char, index: number): boolean => predicate());
13085}
13086
13087/**
13088 * Returns the value of the first element in the array where predicate is true, and undefined
13089 * otherwise.
13090 *
13091 * @param predicate find calls predicate once for each element of the array, in ascending
13092 * order, until it finds one where predicate returns true. If such an element is found, find
13093 * immediately returns that element value. Otherwise, find returns undefined.
13094 *
13095 * @returns the value of the first element in the array or undefined
13096 */
13097export function find(self: char[], predicate: () => boolean): Char | undefined {
13098    const res = findIndex(self, predicate)
13099    if (res == -1) {
13100        return undefined
13101    }
13102    return self[res as int];
13103}
13104
13105/**
13106 * Returns the index of the first element in the array where predicate is true, and -1
13107 * otherwise.
13108 *
13109 * @param predicate find calls predicate once for each element of the array, in ascending
13110 * order, until it finds one where predicate returns true. If such an element is found,
13111 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
13112 *
13113 * @returns found element index or -1 otherwise
13114 */
13115export function findIndex(self: char[], predicate: () => boolean): number {
13116    for (let i = 0; i < self.length; i++) {
13117        if (predicate()) {
13118            return i;
13119        }
13120    }
13121    return -1;
13122}
13123
13124/**
13125 * Performs the specified action for each element in an array.
13126 *
13127 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
13128 */
13129export function forEach(self: char[], callbackfn: () => void): void {
13130    const len0 = self.length;
13131    for (let i = 0; i < len0; i++) {
13132        callbackfn()
13133    }
13134}
13135
13136/**
13137 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13138 *
13139 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
13140 *
13141 * @returns a result after applying callbackfn over all elements of the Array
13142 */
13143export function reduce(self: char[], callbackfn: (previousValue: char) => char): char {
13144    if (self.length == 0) {
13145        throw new TypeError("Reduce of empty array with no initial value")
13146    }
13147    let acc: char = self[0];
13148    for (let i = 1; i < self.length; i++) {
13149        acc = callbackfn(acc)
13150    }
13151    return acc
13152}
13153
13154/**
13155 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13156 *
13157 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
13158 *
13159 * @returns a result after applying callbackfn over all elements of the Array
13160 */
13161export function reduce(self: char[], callbackfn: () => char): char {
13162    if (self.length == 0) {
13163        throw new TypeError("Reduce of empty array with no initial value")
13164    }
13165    let acc: char = self[0];
13166    for (let i = 1; i < self.length; i++) {
13167        acc = callbackfn()
13168    }
13169    return acc
13170}
13171
13172/**
13173 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13174 *
13175 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
13176 *
13177 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
13178 *
13179 * @returns a result after applying callbackfn over all elements of the Array
13180 */
13181export function reduce<U = char>(self: char[], callbackfn: (previousValue: U) => U, initialValue: U): U {
13182    let acc = initialValue
13183    for (let i = 0; i < self.length; i++) {
13184        acc = callbackfn(acc)
13185    }
13186    return acc
13187}
13188
13189/**
13190 * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13191 *
13192 * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
13193 *
13194 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
13195 *
13196 * @returns a result after applying callbackfn over all elements of the Array
13197 */
13198export function reduce<U = char>(self: char[], callbackfn: () => U, initialValue: U): U {
13199    let acc = initialValue
13200    for (let i = 0; i < self.length; i++) {
13201        acc = callbackfn()
13202    }
13203    return acc
13204}
13205
13206/**
13207 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13208 *
13209 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
13210 *
13211 * @returns a result after applying callbackfn over all elements of the Array
13212 */
13213export function reduceRight(self: char[], callbackfn: (previousValue: char) => char): char {
13214    if (self.length == 0) {
13215        throw new TypeError("Reduce of empty array with no initial value")
13216    }
13217    let acc: char = self[self.length - 1];
13218    for (let i = self.length - 2; i >= 0; i--) {
13219        acc = callbackfn(acc)
13220    }
13221    return acc
13222}
13223
13224/**
13225 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13226 *
13227 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
13228 *
13229 * @returns a result after applying callbackfn over all elements of the Array
13230 */
13231export function reduceRight(self: char[], callbackfn: () => char): char {
13232    if (self.length == 0) {
13233        throw new TypeError("Reduce of empty array with no initial value")
13234    }
13235    let acc: char = self[self.length - 1];
13236    for (let i = self.length - 2; i >= 0; i--) {
13237        acc = callbackfn()
13238    }
13239    return acc
13240}
13241
13242/**
13243 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13244 *
13245 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
13246 *
13247 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
13248 *
13249 * @returns a result after applying callbackfn over all elements of the Array
13250 */
13251export function reduceRight<U>(self: char[], callbackfn: (previousValue: U) => U, initialValue: U): U {
13252    let acc = initialValue
13253    for (let i = self.length - 1; i >= 0; i--) {
13254        acc = callbackfn(acc)
13255    }
13256    return acc
13257}
13258
13259/**
13260 * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
13261 *
13262 * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
13263 *
13264 * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
13265 *
13266 * @returns a result after applying callbackfn over all elements of the Array
13267 */
13268export function reduceRight<U>(self: char[], callbackfn: () => U, initialValue: U): U {
13269    let acc = initialValue
13270    for (let i = self.length - 1; i >= 0; i--) {
13271        acc = callbackfn()
13272    }
13273    return acc
13274}
13275
13276/**
13277 * Determines whether the specified callback function returns true for any element of an array.
13278 *
13279 * @param predicate A function that accepts up to three arguments. The some method calls
13280 * the predicate function for each element in the array until the predicate returns a value
13281 * which is coercible to the Boolean value true, or until the end of the array.
13282 *
13283 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
13284 */
13285export function some(self: char[], predicate: () => boolean): boolean {
13286    for (let i = 0; i < self.length; i++) {
13287        if (predicate()) {
13288            return true
13289        }
13290    }
13291    return false
13292}
13293
13294/**
13295 * Iterates the array in reverse order and returns the value of the first element
13296 * that satisfies the provided testing function
13297 *
13298 * @param predicate testing function
13299 *
13300 * @returns found element or undefined otherwise
13301 */
13302export function findLast(self: char[], predicate: () => boolean): Char | undefined {
13303    for (let i = self.length - 1; i >= 0; i--) {
13304        const val = self[i];
13305        if (predicate()) {
13306            return val;
13307        }
13308    }
13309    return undefined;
13310}
13311
13312/**
13313 * Iterates the array in reverse order and returns the index of
13314 * the first element that satisfies the provided testing function.
13315 * If no elements satisfy the testing function, -1 is returned.
13316 *
13317 * @param predicate testing function
13318 *
13319 * @returns index of first element satisfying to predicate, -1 if no such element
13320 */
13321export function findLastIndex(self: char[], predicate: () => boolean): number {
13322    for (let i = self.length - 1; i >= 0; i--) {
13323        if (predicate()) {
13324            return i
13325        }
13326    }
13327    return -1
13328}
13329
13330/**
13331 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13332 *
13333 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
13334 *
13335 * @returns `Array` instance, constructed from `this` and given function.
13336 */
13337export function map(self: char[], callbackfn: (value: char, index: number, array: char[]) => char): char[] {
13338    const len = self.length;
13339    let res = new char[len];
13340    for (let i = 0; i < len; i++) {
13341        res[i] = callbackfn(self[i], i as number, self);
13342    }
13343    return res;
13344}
13345
13346/**
13347 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13348 *
13349 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
13350 *
13351 * @returns `Array` instance, constructed from `this` and given function.
13352 */
13353export function map(self: char[], callbackfn: (value: char, index: number) => char): char[] {
13354    const len = self.length;
13355    let res = new char[len];
13356    for (let i = 0; i < len; i++) {
13357        res[i] = callbackfn(self[i], i as number);
13358    }
13359    return res;
13360}
13361
13362/**
13363 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13364 *
13365 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
13366 *
13367 * @returns `Array` instance, constructed from `this` and given function.
13368 */
13369export function map(self: char[], callbackfn: (value: char) => char): char[] {
13370    const len = self.length;
13371    let res = new char[len];
13372    for (let i = 0; i < len; i++) {
13373        res[i] = callbackfn(self[i]);
13374    }
13375    return res;
13376}
13377
13378/**
13379 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13380 *
13381 * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
13382 *
13383 * @returns `Array` instance, constructed from `this` and given function.
13384 */
13385export function map(self: char[], callbackfn: () => char): char[] {
13386    const len = self.length;
13387    let res = new char[len];
13388    for (let i = 0; i < len; i++) {
13389        res[i] = callbackfn();
13390    }
13391    return res;
13392}
13393
13394/**
13395 * Constructs a new `Array` instance and populates it with
13396 * portion of a given array, filtered down to just the elements from the
13397 * given array that pass the test implemented by the provided function.
13398 *
13399 * @param fn test function, applied to each element of an array.
13400 *
13401 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
13402 */
13403export function filter(self: char[], fn: (v: char, k: number) => boolean): char[] {
13404    const mask = new boolean[self.length]
13405    let cnt = 0
13406
13407    for (let i: int = 0; i < self.length; i++) {
13408        const val = self[i];
13409        if (fn(val, i)) {
13410            mask[i] = true
13411            cnt++;
13412        }
13413    }
13414    const res = new char[cnt];
13415    let idx_store = 0;
13416    for (let i: int = 0; i < self.length; i++) {
13417        if (mask[i]) {
13418            res[idx_store++] = self[i]
13419        }
13420    }
13421    return res;
13422}
13423
13424export function concat(self: char[], fst: char[], ...more: char[][]): char[] {
13425    const lnMin = self.length + fst.length;
13426    let ln = lnMin;
13427    for (let i = 0; i < more.length; i++) {
13428        ln += more[i].length
13429    }
13430    const r = new char[ln];
13431    try {
13432        copyTo(self, r, 0, 0, self.length);
13433        copyTo(fst, r, self.length, 0, fst.length);
13434        let idx = lnMin;
13435        for (let i = 0; i < more.length; i++) {
13436            copyTo(more[i], r, idx, 0, more[i].length);
13437            idx += more[i].length;
13438        }
13439    } catch (e) {
13440        // impossible
13441    }
13442    return r
13443}
13444
13445/**
13446 * Reorders elements of `this` using comparator function.
13447 *
13448 * @param comparator function that defines the sort order.
13449 *
13450 * @note Mutating method
13451 */
13452export function sort(self: char[], comparator: (a: char, b: char) => number): char[] {
13453    sort_subarray(self, 0, self.length, (l: char, r: char): boolean => {
13454        return comparator(l, r ) < 0;
13455    });
13456    return self;
13457}
13458
13459/**
13460 * Reorders elements of `this` using comparator function.
13461 *
13462 * @param comparator function that defines the sort order.
13463 *
13464 * @note Mutating method
13465 */
13466export function sort(self: char[], ): char[] {
13467    sort(self, 0, self.length);
13468    return self;
13469}
13470
13471export function keys(self: char[]): IterableIterator<number> {
13472    return new BuiltinArrayKeysIterator(self.length);
13473}
13474
13475class ArrayValuesIterator_char implements IterableIterator<char> {
13476    private parent: char[]
13477    private idx: int = 0
13478
13479    constructor(parent: char[]) {
13480        this.parent = parent
13481    }
13482
13483    override next(): IteratorResult<char> {
13484        if (this.idx >= this.parent.length) {
13485            return new IteratorResult<char>()
13486        }
13487        return new IteratorResult<char>(this.parent[this.idx++])
13488    }
13489
13490    override $_iterator(): IterableIterator<char> {
13491        return this;
13492    }
13493
13494    public __Iterator_getLength(): int {
13495        return this.parent.length as int
13496    }
13497}
13498
13499class ArrayEntriesIterator_char implements IterableIterator<[number, char]> {
13500    private parent: char[]
13501    private idx: int = 0
13502
13503    constructor(parent: char[]) {
13504        this.parent = parent
13505    }
13506
13507    override next(): IteratorResult<[number, char]> {
13508        if (this.idx >= this.parent.length) {
13509            return new IteratorResult<[number, char]>()
13510        }
13511        const i = this.idx++;
13512        const vl: [number, char] = [i as number, this.parent[i]]
13513        return new IteratorResult<[number, char]>(vl);
13514    }
13515
13516    override $_iterator(): IterableIterator<[number, char]> {
13517        return this;
13518    }
13519
13520    public __Iterator_getLength(): int {
13521        return this.parent.length as int
13522    }
13523}
13524
13525function builtin_insertion_sort<T>(arr: T[], startIndex: int, endIndex: int, comp: (lhs: T, rhs: T) => number): void {
13526    for (let i = startIndex + 1; i < endIndex; i++) {
13527        const tmp = arr[i];
13528        if (comp(tmp, arr[startIndex]) as int < 0) {
13529            for (let j = i; j > startIndex; j--) {
13530                arr[j] = arr[j - 1]
13531            }
13532            arr[startIndex] = tmp
13533        } else {
13534            let j = i - 1;
13535            while (comp(tmp, arr[j]) as int < 0) {
13536                arr[j + 1] = arr[j];
13537                j--;
13538            }
13539            arr[j + 1] = tmp;
13540        }
13541    }
13542}
13543
13544function perform_merge<T>(arr: T[], startIndex: int, midIndex: int, endIndex: int, comp: (lhs: T, rhs: T) => number): void {
13545    const len1 = midIndex - startIndex + 1;
13546    const len2 = endIndex - midIndex;
13547    let left = new T[len1];
13548    let right = new T[len2];
13549    for (let i = 0; i < len1; i++) {
13550        left[i] = arr[startIndex + i];
13551    }
13552    for (let i = 0; i < len2; i++) {
13553        right[i] = arr[midIndex + 1 + i];
13554    }
13555    let i = 0;
13556    let j = 0;
13557    let k = startIndex;
13558    while (i < len1 && j < len2) {
13559        if (comp(left[i], right[j]) as int <= 0) {
13560            arr[k] = left[i];
13561            i++;
13562        } else {
13563            arr[k] = right[j];
13564            j++;
13565        }
13566        k++;
13567    }
13568    while (i < len1) {
13569        arr[k] = left[i];
13570        k++;
13571        i++;
13572    }
13573    while (j < len2) {
13574        arr[k] = right[j];
13575        k++;
13576        j++;
13577    }
13578}
13579
13580export function sort_stable<T>(arr: T[], startIndex: int, endIndex: int, comp: (lhs: T, rhs: T) => number): void {
13581    if (endIndex <= startIndex) {
13582        return;
13583    }
13584
13585    const INS_SORT_DELTA = 16
13586    for (let i = startIndex; i < endIndex; i += INS_SORT_DELTA ) {
13587        builtin_insertion_sort<T>(arr, i, min(i + INS_SORT_DELTA , endIndex), comp)
13588    }
13589    if ((endIndex - startIndex) < INS_SORT_DELTA) {
13590        return;
13591    }
13592    for (let size = INS_SORT_DELTA; size < endIndex; size = 2 * size) {
13593        for (let left = startIndex; left < endIndex; left += 2 * size) {
13594
13595            // Find ending point of left subarray and right subarray
13596            const mid = min(left + size - 1, endIndex - 1);
13597            const right = min((left + 2 * size - 1), (endIndex - 1));
13598
13599            // Merge sub array arr[left.....mid] and arr[mid+1....right]
13600            if (mid < right) {
13601                perform_merge(arr, left, mid, right, comp);
13602            }
13603        }
13604    }
13605}
13606
13607function defaultComparatorStr(a: String, b: String): number {
13608    return a.compareTo(b)
13609}
13610
13611type buffStr = String | null
13612function stringified_insertion_sort<T>(arr: T[], arrStr: buffStr[], startIndex: int, endIndex: int): void {
13613    for (let i = startIndex + 1; i < endIndex; i++) {
13614        const tmp = arr[i]
13615        const tmpStr = arrStr[i];
13616        if (defaultComparatorStr(tmpStr!, arrStr[startIndex]!) < 0) {
13617            for (let j = i; j > startIndex; j--) {
13618                arr[j] = arr[j - 1]
13619                arrStr[j] = arrStr[j - 1]
13620            }
13621            arrStr[startIndex] = tmpStr
13622            arr[startIndex] = tmp
13623        } else {
13624            let j = i - 1;
13625            while (defaultComparatorStr(tmpStr!, arrStr[j]!) < 0) {
13626                arr[j + 1] = arr[j];
13627                arrStr[j + 1] = arrStr[j]
13628                j--;
13629            }
13630            arr[j + 1] = tmp;
13631            arrStr[j + 1] = tmpStr
13632        }
13633    }
13634}
13635
13636function stringified_perform_merge<T>(arr: T[], arrStr: buffStr[], startIndex: int, midIndex: int, endIndex: int): void {
13637    const len1 = midIndex - startIndex + 1;
13638    const len2 = endIndex - midIndex;
13639    type buffType = T | null
13640    let left = new buffType[len1]
13641    let right = new buffType[len2]
13642    let leftStr = new buffStr[len1]
13643    let rightStr = new buffStr[len2]
13644    for (let i = 0; i < len1; i++) {
13645        left[i] = arr[startIndex + i]
13646        leftStr[i] = arrStr[startIndex + i]
13647    }
13648    for (let i = 0; i < len2; i++) {
13649        right[i] = arr[midIndex + 1 + i]
13650        rightStr[i] = arrStr[midIndex + 1 + i]
13651    }
13652    let i = 0;
13653    let j = 0;
13654    let k = startIndex;
13655    while (i < len1 && j < len2) {
13656        if (defaultComparatorStr(leftStr[i]!, rightStr[j]!) <= 0) {
13657            arr[k] = left[i]!;
13658            arrStr[k] = leftStr[i]!;
13659            i++;
13660        } else {
13661            arr[k] = right[j]!;
13662            arrStr[k] = rightStr[j]!;
13663            j++;
13664        }
13665        k++;
13666    }
13667    while (i < len1) {
13668        arr[k] = left[i]!;
13669        arrStr[k] = leftStr[i]!;
13670        k++;
13671        i++;
13672    }
13673    while (j < len2) {
13674        arr[k] = right[j]!;
13675        arrStr[k] = rightStr[j]!;
13676        k++;
13677        j++;
13678    }
13679}
13680
13681export function sort_default<T>(arr: T[], arrStr: buffStr[], startIndex: int, endIndex: int): void {
13682    if (endIndex <= startIndex) {
13683        return;
13684    }
13685    const INS_SORT_DELTA = 16
13686    for (let i = startIndex; i < endIndex; i += INS_SORT_DELTA ) {
13687        stringified_insertion_sort<T>(arr, arrStr, i, min(i + INS_SORT_DELTA , endIndex))
13688    }
13689
13690    if ((endIndex - startIndex) < INS_SORT_DELTA) {
13691        return;
13692    }
13693    for (let size = INS_SORT_DELTA; size < endIndex; size = 2 * size) {
13694        for (let left = startIndex; left < endIndex; left += 2 * size) {
13695
13696            // Find ending point of left subarray and right subarray
13697            const mid = min(left + size - 1, endIndex - 1);
13698            const right = min((left + 2 * size - 1), (endIndex - 1));
13699
13700            // Merge sub array arr[left.....mid] and arr[mid+1....right]
13701            if (mid < right) {
13702                stringified_perform_merge(arr, arrStr, left, mid, right);
13703            }
13704        }
13705    }
13706}
13707