• 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    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
982    let sb = new StringBuilder()
983    for (let i: int = 0; i < self.length; i++) {
984        const tmp = self[i]
985        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
986        if (i != 0) {
987            sb.append(sepReal);
988        }
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
1719class ArrayEntriesIterator_boolean implements IterableIterator<[number, boolean]> {
1720    private parent: boolean[]
1721    private idx: int = 0
1722
1723    constructor(parent: boolean[]) {
1724        this.parent = parent
1725    }
1726
1727    override next(): IteratorResult<[number, boolean]> {
1728        if (this.idx >= this.parent.length) {
1729            return new IteratorResult<[number, boolean]>()
1730        }
1731        const i = this.idx++;
1732        const vl: [number, boolean] = [i as number, this.parent[i]]
1733        return new IteratorResult<[number, boolean]>(vl);
1734    }
1735
1736    override $_iterator(): IterableIterator<[number, boolean]> {
1737        return this;
1738    }
1739}
1740
1741function cloneArray(self: byte[]): byte[] {
1742    const ret = new byte[self.length];;
1743    for (let i = 0; i < self.length; i++) {
1744        ret[i] = self[i];
1745    }
1746    return ret;
1747}
1748
1749/**
1750 * Takes an integer value and returns the item at that index,
1751 * allowing for positive and negative integers. Negative integers count back
1752 * from the last item in the array.
1753 *
1754 * @param index Zero-based index of the array element to be returned.
1755 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
1756 *
1757 * @returns The element in the array matching the given index.
1758 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
1759 */
1760export function at(self: byte[], index: number): Byte | undefined {
1761    return at(self, index as int)
1762}
1763
1764/**
1765 * Creates a new `Array` from this `Array` instance and given `Array` instance.
1766 *
1767 * @param other to concatenate into a new array.
1768 *
1769 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
1770 */
1771// export function concat(self: byte[], ...items: (byte | Concatbyte[])[]): byte[] {
1772//     throw new Error("not implemented")
1773// }
1774
1775export function concat(self: byte[], ...items: ConcatArray<byte>[]): byte[] {
1776    let totalAdd = self.length;
1777    for (let i = 0; i < items.length; i++) {
1778        totalAdd += items[i].length as int
1779    }
1780
1781    const buf = new byte[totalAdd];
1782
1783    for (let i = 0; i < self.length; i++) {
1784        buf[i] = self[i];
1785    }
1786
1787    let insertTo = self.length;
1788    for (let i = 0; i < items.length; i++) {
1789        const arr = items[i]
1790        const len = arr.length as int
1791        for (let j = 0; j < len; j++) {
1792            buf[insertTo++] = arr.$_get(j)
1793        }
1794    }
1795
1796    return buf;
1797}
1798
1799/**
1800 * Takes an integer value and returns the item at that index,
1801 * allowing for positive and negative integers. Negative integers count back
1802 * from the last item in the array.
1803 *
1804 * @param index Zero-based index of the array element to be returned.
1805 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
1806 *
1807 * @returns The element in the array matching the given index.
1808 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
1809 */
1810export function at(self: byte[], index: int): Byte | undefined {
1811    let len = self.length;
1812    let k: int;
1813    if (index >= 0) {
1814        k = index;
1815    } else {
1816        k = len + index;
1817    }
1818
1819    if (k < 0 || k >= len) {
1820        return undefined;
1821    }
1822
1823    return self[k];
1824}
1825
1826/**
1827 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1828 *
1829 * @param target index at which to copy the sequence
1830 *
1831 * @param start index at which to start copying elements from
1832 *
1833 * @param end index at which to end copying elements from
1834 *
1835 * @returns this array after transformation
1836 */
1837export function copyWithin(self: byte[], target: number, start: number, end?: Number): byte[] {
1838    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
1839    return self;
1840}
1841
1842/**
1843 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1844 *
1845 * @param target index at which to copy the sequence
1846 *
1847 * @param start index at which to start copying elements from
1848 *
1849 * @param end index at which to end copying elements from
1850 *
1851 * @returns this array after transformation
1852 */
1853export function copyWithin(self: byte[], target: int, start: int, end: int): byte[] {
1854    target = normalizeIndex(target, self.length)
1855    start = normalizeIndex(start, self.length)
1856    end = normalizeIndex(end, self.length)
1857
1858    if (end <= start) {
1859        return self;
1860    }
1861
1862    if (target <= start) {
1863        while (start < end) {
1864            const read = self[start++];
1865            self[target++] = read;
1866        }
1867    } else {
1868        let len = end - start;
1869        if (target + len > self.length) {
1870            len = self.length - target
1871        }
1872        for (let i = 0; i < len; i++) {
1873            const read = self[start + len - 1 - i];
1874            self[target + len - 1 - i] = read;
1875        }
1876    }
1877
1878    return self;
1879}
1880
1881/**
1882 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1883 *
1884 * @param target index at which to copy the sequence
1885 *
1886 * @param start index at which to start copying elements from
1887 *
1888 * @returns this array after transformation
1889 */
1890export function copyWithin(self: byte[], target: int, start: int): byte[] {
1891    copyWithin(self, target, start, self.length);
1892    return self;
1893}
1894
1895/**
1896 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
1897 *
1898 * @param target index at which to copy the sequence
1899 *
1900 * @returns this array after transformation
1901 */
1902export function copyWithin(self: byte[], target: int): byte[] {
1903    copyWithin(self, target, 0, self.length);
1904    return self;
1905}
1906
1907/**
1908 * Changes all elements in the Array to a static value, from a start index to an end index
1909 *
1910 * @param value to fill the array with
1911 *
1912 * @param start index at which to start filling
1913 *
1914 * @param end index at which to end filling, but not including
1915 *
1916 * @returns this array after transformation
1917 */
1918export function fill(self: byte[], value: byte, start?: Number, end?: Number): byte[] {
1919    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
1920    return self;
1921}
1922
1923/**
1924 * Changes all elements in the Array to a static value, from a start index to an end index
1925 *
1926 * @param value to fill the array with
1927 *
1928 * @param start index at which to start filling
1929 *
1930 * @param end index at which to end filling, but not including
1931 *
1932 * @returns this array after transformation
1933 */
1934export function fill(self: byte[], value: byte, start: int, end: int): byte[] {
1935    start = normalizeIndex(start, self.length);
1936    end = normalizeIndex(end, self.length)
1937
1938    for (let i = start; i < end; i++) {
1939        self[i] = value;
1940    }
1941
1942    return self;
1943}
1944
1945/**
1946 * Returns the value of the first element in the array where predicate is true, and undefined
1947 * otherwise.
1948 *
1949 * @param predicate find calls predicate once for each element of the array, in ascending
1950 * order, until it finds one where predicate returns true. If such an element is found, find
1951 * immediately returns that element value. Otherwise, find returns undefined.
1952 *
1953 * @returns the value of the first element in the array or undefined
1954 */
1955export function find(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): Byte | undefined {
1956    const res = findIndex(self, predicate)
1957    if (res == -1) {
1958        return undefined
1959    }
1960    return self[res as int];
1961}
1962
1963/**
1964 * Returns the index of the first element in the array where predicate is true, and -1
1965 * otherwise.
1966 *
1967 * @param predicate find calls predicate once for each element of the array, in ascending
1968 * order, until it finds one where predicate returns true. If such an element is found,
1969 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
1970 *
1971 * @returns found element index or -1 otherwise
1972 */
1973export function findIndex(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): number {
1974    for (let i = 0; i < self.length; i++) {
1975        if (predicate(self[i], i as number, self)) {
1976            return i;
1977        }
1978    }
1979    return -1;
1980}
1981
1982/**
1983 * Iterates the array in reverse order and returns the value of the first element
1984 * that satisfies the provided testing function
1985 *
1986 * @param predicate testing function
1987 *
1988 * @returns found element or undefined otherwise
1989 */
1990export function findLast(self: byte[], predicate: (elem: byte, index: number, array: byte[]) => boolean): Byte | undefined {
1991    for (let i = self.length - 1; i >= 0; i--) {
1992        const val = self[i];
1993        if (predicate(val, i as number, self)) {
1994            return val;
1995        }
1996    }
1997    return undefined;
1998}
1999
2000/**
2001 * Determines whether all the members of an array satisfy the specified test.
2002 *
2003 * @param predicate A function that accepts up to three arguments. The every method calls
2004 * the predicate function for each element in the array until the predicate returns a value
2005 * which is coercible to the Boolean value false, or until the end of the array.
2006 *
2007 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2008 */
2009export function every(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): boolean {
2010    for (let i = 0; i < self.length; i++) {
2011        if (!predicate(self[i], i as number, self)) {
2012            return false
2013        }
2014    }
2015    return true;
2016}
2017
2018/**
2019 * Determines whether the specified callback function returns true for any element of an array.
2020 *
2021 * @param predicate A function that accepts up to three arguments. The some method calls
2022 * the predicate function for each element in the array until the predicate returns a value
2023 * which is coercible to the Boolean value true, or until the end of the array.
2024 *
2025 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
2026 */
2027export function some(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): boolean {
2028    for (let i = 0; i < self.length; i++) {
2029        if (predicate(self[i], i as number, self)) {
2030            return true
2031        }
2032    }
2033    return false
2034}
2035
2036/**
2037 * Returns the elements of an array that meet the condition specified in a callback function.
2038 *
2039 * @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.
2040 *
2041 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
2042 */
2043export function filter(self: byte[], predicate: (value: byte, index: number, array: byte[]) => boolean): byte[] {
2044    return filter(self, (value: byte, index: number): boolean => predicate(value, index, self));
2045}
2046
2047/**
2048 * Iterates the array in reverse order and returns the index of
2049 * the first element that satisfies the provided testing function.
2050 * If no elements satisfy the testing function, -1 is returned.
2051 *
2052 * @param predicate testing function
2053 *
2054 * @returns index of first element satisfying to predicate, -1 if no such element
2055 */
2056export function findLastIndex(self: byte[], predicate: (element: byte, index: number, array: byte[]) => boolean): number {
2057    for (let i = self.length - 1; i >= 0; i--) {
2058        if (predicate(self[i], i as number, self)) {
2059            return i
2060        }
2061    }
2062    return -1
2063}
2064
2065/**
2066 * 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.
2067 *
2068 * @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.
2069 *
2070 * @returns a result after applying callbackfn over all elements of the Array
2071 */
2072export function reduce(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number, array: byte[]) => byte): byte {
2073    if (self.length == 0) {
2074        throw new TypeError("Reduce of empty array with no initial value")
2075    }
2076    let acc: byte = self[0];
2077    for (let i = 1; i < self.length; i++) {
2078        acc = callbackfn(acc, self[i], i as number, self)
2079    }
2080    return acc
2081}
2082
2083/**
2084 * 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.
2085 *
2086 * @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.
2087 *
2088 * @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.
2089 *
2090 * @returns a result after applying callbackfn over all elements of the Array
2091 */
2092export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number, array: byte[]) => U, initialValue: U): U {
2093    let acc = initialValue
2094    for (let i = 0; i < self.length; i++) {
2095        acc = callbackfn(acc, self[i], i as number, self)
2096    }
2097    return acc
2098}
2099
2100/**
2101 * 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.
2102 *
2103 * @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.
2104 *
2105 * @returns a result after applying callbackfn over all elements of the Array
2106 */
2107export function reduceRight(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number, array: byte[]) => byte): byte {
2108    if (self.length == 0) {
2109        throw new TypeError("Reduce of empty array with no initial value")
2110    }
2111    let acc: byte = self[self.length - 1];
2112    for (let i = self.length - 2; i >= 0; i--) {
2113        acc = callbackfn(acc, self[i], i as number, self)
2114    }
2115    return acc
2116}
2117
2118/**
2119 * 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.
2120 *
2121 * @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.
2122 *
2123 * @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.
2124 *
2125 * @returns a result after applying callbackfn over all elements of the Array
2126 */
2127export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number, array: byte[]) => U, initialValue: U): U {
2128    let acc = initialValue
2129    for (let i = self.length - 1; i >= 0; i--) {
2130        acc = callbackfn(acc, self[i], i as number, self)
2131    }
2132    return acc
2133}
2134
2135/**
2136 * Performs the specified action for each element in an array.
2137 *
2138 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
2139 */
2140export function forEach(self: byte[], callbackfn: (value: byte, index: number, array: byte[]) => void): void {
2141    const len0 = self.length;
2142    for (let i = 0; i < len0; i++) {
2143        callbackfn(self[i], i as number, self)
2144    }
2145}
2146
2147/**
2148 * Returns the value of the first element in the array where predicate is true, and undefined
2149 * otherwise.
2150 *
2151 * @param predicate find calls predicate once for each element of the array, in ascending
2152 * order, until it finds one where predicate returns true. If such an element is found, find
2153 * immediately returns that element value. Otherwise, find returns undefined.
2154 *
2155 * @returns the value of the first element in the array or undefined
2156 */
2157export function find(self: byte[], predicate: (value: byte, index: number) => boolean): Byte | undefined {
2158    const res = findIndex(self, predicate)
2159    if (res == -1) {
2160        return undefined
2161    }
2162    return self[res as int];
2163}
2164
2165/**
2166 * Returns the index of the first element in the array where predicate is true, and -1
2167 * otherwise.
2168 *
2169 * @param predicate find calls predicate once for each element of the array, in ascending
2170 * order, until it finds one where predicate returns true. If such an element is found,
2171 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
2172 *
2173 * @returns found element index or -1 otherwise
2174 */
2175export function findIndex(self: byte[], predicate: (value: byte, index: number) => boolean): number {
2176    for (let i = 0; i < self.length; i++) {
2177        if (predicate(self[i], i as number)) {
2178            return i;
2179        }
2180    }
2181    return -1;
2182}
2183
2184/**
2185 * Iterates the array in reverse order and returns the value of the first element
2186 * that satisfies the provided testing function
2187 *
2188 * @param predicate testing function
2189 *
2190 * @returns found element or undefined otherwise
2191 */
2192export function findLast(self: byte[], predicate: (elem: byte, index: number) => boolean): Byte | undefined {
2193    for (let i = self.length - 1; i >= 0; i--) {
2194        const val = self[i];
2195        if (predicate(val, i as number)) {
2196            return val;
2197        }
2198    }
2199    return undefined;
2200}
2201
2202/**
2203 * Determines whether all the members of an array satisfy the specified test.
2204 *
2205 * @param predicate A function that accepts up to three arguments. The every method calls
2206 * the predicate function for each element in the array until the predicate returns a value
2207 * which is coercible to the Boolean value false, or until the end of the array.
2208 *
2209 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2210 */
2211export function every(self: byte[], predicate: (value: byte, index: number) => boolean): boolean {
2212    for (let i = 0; i < self.length; i++) {
2213        if (!predicate(self[i], i as number)) {
2214            return false
2215        }
2216    }
2217    return true;
2218}
2219
2220/**
2221 * Determines whether the specified callback function returns true for any element of an array.
2222 *
2223 * @param predicate A function that accepts up to three arguments. The some method calls
2224 * the predicate function for each element in the array until the predicate returns a value
2225 * which is coercible to the Boolean value true, or until the end of the array.
2226 *
2227 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
2228 */
2229export function some(self: byte[], predicate: (value: byte, index: number) => boolean): boolean {
2230    for (let i = 0; i < self.length; i++) {
2231        if (predicate(self[i], i as number)) {
2232            return true
2233        }
2234    }
2235    return false
2236}
2237
2238/**
2239 * Iterates the array in reverse order and returns the index of
2240 * the first element that satisfies the provided testing function.
2241 * If no elements satisfy the testing function, -1 is returned.
2242 *
2243 * @param predicate testing function
2244 *
2245 * @returns index of first element satisfying to predicate, -1 if no such element
2246 */
2247export function findLastIndex(self: byte[], predicate: (element: byte, index: number) => boolean): number {
2248    for (let i = self.length - 1; i >= 0; i--) {
2249        if (predicate(self[i], i as number)) {
2250            return i
2251        }
2252    }
2253    return -1
2254}
2255
2256/**
2257 * 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.
2258 *
2259 * @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.
2260 *
2261 * @returns a result after applying callbackfn over all elements of the Array
2262 */
2263export function reduce(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number) => byte): byte {
2264    if (self.length == 0) {
2265        throw new TypeError("Reduce of empty array with no initial value")
2266    }
2267    let acc: byte = self[0];
2268    for (let i = 1; i < self.length; i++) {
2269        acc = callbackfn(acc, self[i], i as number)
2270    }
2271    return acc
2272}
2273
2274/**
2275 * 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.
2276 *
2277 * @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.
2278 *
2279 * @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.
2280 *
2281 * @returns a result after applying callbackfn over all elements of the Array
2282 */
2283export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number) => U, initialValue: U): U {
2284    let acc = initialValue
2285    for (let i = 0; i < self.length; i++) {
2286        acc = callbackfn(acc, self[i], i as number)
2287    }
2288    return acc
2289}
2290
2291/**
2292 * 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.
2293 *
2294 * @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.
2295 *
2296 * @returns a result after applying callbackfn over all elements of the Array
2297 */
2298export function reduceRight(self: byte[], callbackfn: (previousValue: byte, currentValue: byte, index: number) => byte): byte {
2299    if (self.length == 0) {
2300        throw new TypeError("Reduce of empty array with no initial value")
2301    }
2302    let acc: byte = self[self.length - 1];
2303    for (let i = self.length - 2; i >= 0; i--) {
2304        acc = callbackfn(acc, self[i], i as number)
2305    }
2306    return acc
2307}
2308
2309/**
2310 * 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.
2311 *
2312 * @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.
2313 *
2314 * @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.
2315 *
2316 * @returns a result after applying callbackfn over all elements of the Array
2317 */
2318export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U, currentValue: byte, index: number) => U, initialValue: U): U {
2319    let acc = initialValue
2320    for (let i = self.length - 1; i >= 0; i--) {
2321        acc = callbackfn(acc, self[i], i as number)
2322    }
2323    return acc
2324}
2325
2326/**
2327 * Performs the specified action for each element in an array.
2328 *
2329 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
2330 */
2331export function forEach(self: byte[], callbackfn: (value: byte, index: number) => void): void {
2332    const len0 = self.length;
2333    for (let i = 0; i < len0; i++) {
2334        callbackfn(self[i], i as number)
2335    }
2336}
2337
2338/**
2339 * Returns the value of the first element in the array where predicate is true, and undefined
2340 * otherwise.
2341 *
2342 * @param predicate find calls predicate once for each element of the array, in ascending
2343 * order, until it finds one where predicate returns true. If such an element is found, find
2344 * immediately returns that element value. Otherwise, find returns undefined.
2345 *
2346 * @returns the value of the first element in the array or undefined
2347 */
2348export function find(self: byte[], predicate: (value: byte) => boolean): Byte | undefined {
2349    const res = findIndex(self, predicate)
2350    if (res == -1) {
2351        return undefined
2352    }
2353    return self[res as int];
2354}
2355
2356/**
2357 * Returns the index of the first element in the array where predicate is true, and -1
2358 * otherwise.
2359 *
2360 * @param predicate find calls predicate once for each element of the array, in ascending
2361 * order, until it finds one where predicate returns true. If such an element is found,
2362 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
2363 *
2364 * @returns found element index or -1 otherwise
2365 */
2366export function findIndex(self: byte[], predicate: (value: byte) => boolean): number {
2367    for (let i = 0; i < self.length; i++) {
2368        if (predicate(self[i])) {
2369            return i;
2370        }
2371    }
2372    return -1;
2373}
2374
2375/**
2376 * Iterates the array in reverse order and returns the value of the first element
2377 * that satisfies the provided testing function
2378 *
2379 * @param predicate testing function
2380 *
2381 * @returns found element or undefined otherwise
2382 */
2383export function findLast(self: byte[], predicate: (elem: byte) => boolean): Byte | undefined {
2384    for (let i = self.length - 1; i >= 0; i--) {
2385        const val = self[i];
2386        if (predicate(val)) {
2387            return val;
2388        }
2389    }
2390    return undefined;
2391}
2392
2393/**
2394 * Determines whether all the members of an array satisfy the specified test.
2395 *
2396 * @param predicate A function that accepts up to three arguments. The every method calls
2397 * the predicate function for each element in the array until the predicate returns a value
2398 * which is coercible to the Boolean value false, or until the end of the array.
2399 *
2400 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2401 */
2402export function every(self: byte[], predicate: (value: byte) => boolean): boolean {
2403    for (let i = 0; i < self.length; i++) {
2404        if (!predicate(self[i])) {
2405            return false
2406        }
2407    }
2408    return true;
2409}
2410
2411/**
2412 * Determines whether the specified callback function returns true for any element of an array.
2413 *
2414 * @param predicate A function that accepts up to three arguments. The some method calls
2415 * the predicate function for each element in the array until the predicate returns a value
2416 * which is coercible to the Boolean value true, or until the end of the array.
2417 *
2418 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
2419 */
2420export function some(self: byte[], predicate: (value: byte) => boolean): boolean {
2421    for (let i = 0; i < self.length; i++) {
2422        if (predicate(self[i])) {
2423            return true
2424        }
2425    }
2426    return false
2427}
2428
2429/**
2430 * Returns the elements of an array that meet the condition specified in a callback function.
2431 *
2432 * @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.
2433 *
2434 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
2435 */
2436export function filter(self: byte[], predicate: (value: byte) => boolean): byte[] {
2437    return filter(self, (value: byte, index: number): boolean => predicate(value));
2438}
2439
2440/**
2441 * Iterates the array in reverse order and returns the index of
2442 * the first element that satisfies the provided testing function.
2443 * If no elements satisfy the testing function, -1 is returned.
2444 *
2445 * @param predicate testing function
2446 *
2447 * @returns index of first element satisfying to predicate, -1 if no such element
2448 */
2449export function findLastIndex(self: byte[], predicate: (element: byte) => boolean): number {
2450    for (let i = self.length - 1; i >= 0; i--) {
2451        if (predicate(self[i])) {
2452            return i
2453        }
2454    }
2455    return -1
2456}
2457
2458/**
2459 * 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.
2460 *
2461 * @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.
2462 *
2463 * @returns a result after applying callbackfn over all elements of the Array
2464 */
2465export function reduce(self: byte[], callbackfn: (previousValue: byte, currentValue: byte) => byte): byte {
2466    if (self.length == 0) {
2467        throw new TypeError("Reduce of empty array with no initial value")
2468    }
2469    let acc: byte = self[0];
2470    for (let i = 1; i < self.length; i++) {
2471        acc = callbackfn(acc, self[i])
2472    }
2473    return acc
2474}
2475
2476/**
2477 * 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.
2478 *
2479 * @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.
2480 *
2481 * @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.
2482 *
2483 * @returns a result after applying callbackfn over all elements of the Array
2484 */
2485export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U, currentValue: byte) => U, initialValue: U): U {
2486    let acc = initialValue
2487    for (let i = 0; i < self.length; i++) {
2488        acc = callbackfn(acc, self[i])
2489    }
2490    return acc
2491}
2492
2493/**
2494 * 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.
2495 *
2496 * @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.
2497 *
2498 * @returns a result after applying callbackfn over all elements of the Array
2499 */
2500export function reduceRight(self: byte[], callbackfn: (previousValue: byte, currentValue: byte) => byte): byte {
2501    if (self.length == 0) {
2502        throw new TypeError("Reduce of empty array with no initial value")
2503    }
2504    let acc: byte = self[self.length - 1];
2505    for (let i = self.length - 2; i >= 0; i--) {
2506        acc = callbackfn(acc, self[i])
2507    }
2508    return acc
2509}
2510
2511/**
2512 * 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.
2513 *
2514 * @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.
2515 *
2516 * @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.
2517 *
2518 * @returns a result after applying callbackfn over all elements of the Array
2519 */
2520export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U, currentValue: byte) => U, initialValue: U): U {
2521    let acc = initialValue
2522    for (let i = self.length - 1; i >= 0; i--) {
2523        acc = callbackfn(acc, self[i])
2524    }
2525    return acc
2526}
2527
2528/**
2529 * Performs the specified action for each element in an array.
2530 *
2531 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
2532 */
2533export function forEach(self: byte[], callbackfn: (value: byte) => void): void {
2534    const len0 = self.length;
2535    for (let i = 0; i < len0; i++) {
2536        callbackfn(self[i])
2537    }
2538}
2539
2540/**
2541 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
2542 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
2543 *
2544 * @param start zero-based index at which to start extraction
2545 *
2546 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
2547 *
2548 * @returns `Array` instance, constructed from extracted elements of `this` instance.
2549 */
2550export function slice(self: byte[], start?: Number, end?: Number): byte[] {
2551    const len: int = self.length;
2552    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
2553}
2554
2555/**
2556 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
2557 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
2558 *
2559 * @param start zero-based index at which to start extraction
2560 *
2561 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
2562 *
2563 * @returns `Array` instance, constructed from extracted elements of `this` instance.
2564 */
2565export function slice(self: byte[], start: int, end: int): byte[] {
2566    const len: int = self.length;
2567    const relStart = normalizeIndex(start, len)
2568    const relEnd = normalizeIndex(end, len)
2569
2570    let count = relEnd - relStart;
2571    if (count < 0) {
2572        count = 0;
2573    }
2574    let res = new byte[count]
2575    for (let i = 0; i < count; i++) {
2576        res[i] = self[relStart + i];
2577    }
2578
2579    return res
2580}
2581
2582/**
2583 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
2584 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
2585 *
2586 * @param start zero-based index at which to start extraction
2587 *
2588 * @returns `Array` instance, constructed from extracted elements of `this` instance.
2589 */
2590export function slice(self: byte[], start: int): byte[] {
2591    return slice(self, start, Int.MAX_VALUE as int);
2592}
2593
2594/**
2595 * Returns the last index at which a given element can be found in the array,
2596 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
2597 *
2598 * @param element element to locate in the array.
2599 * @param fromIndex zero-based index at which to start searching backwards.
2600 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
2601 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
2602 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
2603 *
2604 * @returns The last index of the element in the array; -1 if not found.
2605 */
2606export function lastIndexOf(self: byte[], element: byte, fromIndex: int): int {
2607    if (self.length == 0) {
2608        return -1;
2609    }
2610    let n = fromIndex;
2611    let k: int;
2612    if (n >= 0) {
2613        k = min(self.length - 1, n);
2614    } else {
2615        k = self.length + n;
2616    }
2617
2618    while (k >= 0) {
2619        if (__runtimeEquals(self[k], element)) {
2620            return k;
2621        }
2622        k--;
2623    }
2624    return -1;
2625}
2626
2627/**
2628 * Returns the last index at which a given element can be found in the array,
2629 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
2630 *
2631 * @param element element to locate in the array.
2632 * @param fromIndex zero-based index at which to start searching backwards.
2633 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
2634 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
2635 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
2636 *
2637 * @returns The last index of the element in the array; -1 if not found.
2638 */
2639export function lastIndexOf(self: byte[], element: byte, fromIndex?: Number): number {
2640    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
2641}
2642
2643/**
2644 * Creates and returns a new string by concatenating all of the elements in an `Array`,
2645 * separated by a specified separator string.
2646 * If the array has only one item, then that item will be returned without using the separator.
2647 *
2648 * @param sep specifies a separator
2649 *
2650 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
2651 */
2652export function join(self: byte[], sep?: String): string {
2653    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
2654    let sb = new StringBuilder()
2655    for (let i: int = 0; i < self.length; i++) {
2656        const tmp = self[i]
2657        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
2658        if (i != 0) {
2659            sb.append(sepReal);
2660        }
2661        sb.append(tmp)
2662    }
2663
2664    return sb.toString();
2665}
2666
2667/**
2668 * Returns a string representing the specified array and its elements.
2669 *
2670 * @returns string representation
2671 */
2672export function toString(self: byte[], ): string {
2673    return join(self, ",");
2674}
2675
2676/**
2677 * Returns a locale string representing the specified array and its elements.
2678 *
2679 * @param locales
2680 *
2681 * @param options
2682 *
2683 * @returns string representation
2684 */
2685export function toLocaleString(self: byte[], locales: Object, options: Object): string {
2686    throw new Error("Array.toLocaleString: not implemented")
2687}
2688
2689/**
2690 * Returns a locale string representing the specified array and its elements.
2691 *
2692 * @param options
2693 *
2694 * @returns string representation
2695 */
2696export function toLocaleString(self: byte[], locales: Object): string {
2697    return toLocaleString(self, new Object(), new Object())
2698}
2699
2700/**
2701 * Returns a locale string representing the specified array and its elements.
2702 *
2703 * @returns string representation
2704 */
2705export function toLocaleString(self: byte[], ): string {
2706    const sb = new StringBuilder()
2707    const len = self.length;
2708    for (let i = 0; i < len; i++) {
2709        if (i != 0) {
2710            sb.append(",")
2711        }
2712        let x = self[i] as NullishType;
2713        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
2714            sb.append(x!.toLocaleString())
2715        }
2716    }
2717    return sb.toString()
2718}
2719
2720/**
2721 * Copying version of the splice() method.
2722 *
2723 * @param start index
2724 *
2725 * @param delete number of items after start index
2726 *
2727 * @returns a new Array with some elements removed and/or replaced at a given index.
2728 */
2729export function toSpliced(self: byte[], start?: Number, delete?: Number): byte[] {
2730    const len = self.length;
2731    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
2732}
2733
2734/**
2735 * Copying version of the splice() method.
2736 *
2737 * @param start index
2738 *
2739 * @param delete number of items after start index
2740 *
2741 * @returns a new Array with some elements removed and/or replaced at a given index.
2742 */
2743export function toSpliced(self: byte[], start: number, delete: number, ...items: byte[]): byte[] {
2744    const len = self.length;
2745    return toSpliced(self, start as int, delete as int, ...items)
2746}
2747
2748/**
2749 * Copying version of the splice() method.
2750 *
2751 * @param start index
2752 *
2753 * @param delete number of items after start index
2754 *
2755 * @returns a new Array with some elements removed and/or replaced at a given index.
2756 */
2757export function toSpliced(self: byte[], start: int, delete: int, ...items: byte[]): byte[] {
2758    const len = self.length;
2759    start = normalizeIndex(start, len);
2760    if (delete < 0) {
2761        delete = 0;
2762    } else if (delete > len) {
2763        delete = len;
2764    }
2765    if (start > len - delete) {
2766        delete = len - start
2767    }
2768    const res = new byte[len - delete + items.length];
2769    for (let i = 0; i < start; i++) {
2770        res[i] = self[i]
2771    }
2772    for (let i = 0; i < items.length; i++) {
2773        res[start + i] = items[i]
2774    }
2775    for (let i = start + delete; i < len; i++) {
2776        res[i - delete + items.length] = self[i]
2777    }
2778    return res;
2779}
2780
2781/**
2782 * Copying version of the splice() method.
2783 *
2784 * @param start index
2785 *
2786 * @returns a new Array with some elements removed and/or replaced at a given index.
2787 */
2788export function toSpliced(self: byte[], start: int): byte[] {
2789    return toSpliced(self, start, self.length)
2790}
2791
2792/**
2793 * Checks whether an Array includes a certain value among its entries,
2794 * returning true or false as appropriate.
2795 *
2796 * @param val value to search
2797 *
2798 * @param fromIndex start index
2799 *
2800 * @returns true if val is in Array
2801 */
2802export function includes(self: byte[], val: byte, fromIndex?: Number): boolean {
2803    const len = self.length;
2804    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
2805    for (let i = fi; i < len; i++) {
2806        if (val == self[i]) {
2807            return true;
2808        }
2809    }
2810    return false;
2811}
2812
2813/**
2814 * Returns the first index at which a given element
2815 * can be found in the array, or -1 if it is not present.
2816 *
2817 * @param val value to search
2818 *
2819 * @param fromIndex index to search from
2820 *
2821 * @returns index of val, -1 otherwise
2822 */
2823export function indexOf(self: byte[], val: byte, fromIndex: int): int {
2824    fromIndex = normalizeIndex(fromIndex, self.length)
2825    for (let i = fromIndex; i < self.length; i++) {
2826        if (__runtimeEquals(val, self[i])) {
2827            return i
2828        }
2829    }
2830    return -1
2831}
2832
2833/**
2834 * Returns the first index at which a given element
2835 * can be found in the array, or -1 if it is not present.
2836 *
2837 * @param val value to search
2838 *
2839 * @param fromIndex index to search from
2840 *
2841 * @returns index of val, -1 otherwise
2842 */
2843export function indexOf(self: byte[], val: byte, fromIndex?: Number): number {
2844    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
2845}
2846
2847/**
2848 * Copying version of the sort() method.
2849 * It returns a new array with the elements sorted in ascending order.
2850 *
2851 * @returns sorted copy of hte current instance using default comparator
2852 */
2853export function toSorted(self: byte[], ): byte[] {
2854    let arr = cloneArray(self);
2855    sort(arr, )
2856    return arr
2857}
2858
2859/**
2860 * Copying version of the sort() method.
2861 * It returns a new array with the elements sorted in ascending order.
2862 *
2863 * @param comparator function to compare to elements of the Array
2864 *
2865 * @returns sorted copy of the current instance comparator
2866 */
2867export function toSorted(self: byte[], comparator: (a: byte, b: byte) => number): byte[] {
2868    let arr = cloneArray(self);
2869    sort(arr, comparator)
2870    return arr
2871}
2872
2873/**
2874 * Modifies `this` instance of `Array` class and populates
2875 * it with same elements ordered towards the direction opposite to that previously stated.
2876 *
2877 * @note Mutating method
2878 */
2879export function reverse(self: byte[], ): byte[] {
2880    for (let i = 0; i < self.length / 2; i++) {
2881        const tmp = self[i];
2882        const idx_r = self.length - 1 - i;
2883        const val_r = self[idx_r];
2884        self[i] = val_r;
2885        self[idx_r] = tmp;
2886    }
2887    return self;
2888}
2889
2890/**
2891 * Copying version of the reverse() method.
2892 * It returns a new array with the elements in reversed order.
2893 *
2894 * @returns reversed copy of the current Array
2895 */
2896export function toReversed(self: byte[], ): byte[] {
2897    let arr = new byte[self.length]
2898    for (let i = 0; i < self.length; i++) {
2899        arr[self.length - 1 - i] = self[i]
2900    }
2901    return arr
2902}
2903
2904/**
2905 * Copying version of using the bracket notation to change the value of a given index.
2906 * It returns a new Array with the element at the given index replaced with the given value.
2907 *
2908 * @param index to replace
2909 *
2910 * @param value new value
2911 *
2912 * @returns a new Array with the element at the given index replaced with the given value
2913 */
2914export function with(self: byte[], index: number, value: byte): byte[] {
2915    return with(self, index as int, value)
2916}
2917
2918/**
2919 * Copying version of using the bracket notation to change the value of a given index.
2920 * It returns a new Array with the element at the given index replaced with the given value.
2921 *
2922 * @param index to replace
2923 *
2924 * @param value new value
2925 *
2926 * @returns a new Array with the element at the given index replaced with the given value
2927 */
2928export function with(self: byte[], index: int, value: byte): byte[] {
2929    if (index < 0) {
2930        index += self.length;
2931    }
2932    if (index >= self.length) {
2933        throw new RangeError("Invalid index")
2934    }
2935    let arr = cloneArray(self);
2936    arr[index] = value;
2937    return arr
2938}
2939
2940/**
2941 * Returns an iterator over all values
2942 */
2943export function values(self: byte[], ): IterableIterator<byte> {
2944    return new ArrayValuesIterator_byte(self);
2945}
2946
2947/**
2948 * Returns an iterable of key, value pairs for every entry in the array
2949 */
2950export function entries(self: byte[], ): IterableIterator<[number, byte]> {
2951    return new ArrayEntriesIterator_byte(self);
2952}
2953
2954/**
2955 * Determines whether all the members of an array satisfy the specified test.
2956 *
2957 * @param predicate A function that accepts up to three arguments. The every method calls
2958 * the predicate function for each element in the array until the predicate returns a value
2959 * which is coercible to the Boolean value false, or until the end of the array.
2960 *
2961 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
2962 */
2963export function every(self: byte[], predicate: () => boolean): boolean {
2964    for (let i = 0; i < self.length; i++) {
2965        if (!predicate()) {
2966            return false
2967        }
2968    }
2969    return true
2970}
2971
2972/**
2973 * Returns the elements of an array that meet the condition specified in a callback function.
2974 *
2975 * @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.
2976 *
2977 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
2978 */
2979export function filter(self: byte[], predicate: () => boolean): byte[] {
2980    return filter(self, (value: byte, index: number): boolean => predicate());
2981}
2982
2983/**
2984 * Returns the value of the first element in the array where predicate is true, and undefined
2985 * otherwise.
2986 *
2987 * @param predicate find calls predicate once for each element of the array, in ascending
2988 * order, until it finds one where predicate returns true. If such an element is found, find
2989 * immediately returns that element value. Otherwise, find returns undefined.
2990 *
2991 * @returns the value of the first element in the array or undefined
2992 */
2993export function find(self: byte[], predicate: () => boolean): Byte | undefined {
2994    const res = findIndex(self, predicate)
2995    if (res == -1) {
2996        return undefined
2997    }
2998    return self[res as int];
2999}
3000
3001/**
3002 * Returns the index of the first element in the array where predicate is true, and -1
3003 * otherwise.
3004 *
3005 * @param predicate find calls predicate once for each element of the array, in ascending
3006 * order, until it finds one where predicate returns true. If such an element is found,
3007 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
3008 *
3009 * @returns found element index or -1 otherwise
3010 */
3011export function findIndex(self: byte[], predicate: () => boolean): number {
3012    for (let i = 0; i < self.length; i++) {
3013        if (predicate()) {
3014            return i;
3015        }
3016    }
3017    return -1;
3018}
3019
3020/**
3021 * Performs the specified action for each element in an array.
3022 *
3023 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
3024 */
3025export function forEach(self: byte[], callbackfn: () => void): void {
3026    const len0 = self.length;
3027    for (let i = 0; i < len0; i++) {
3028        callbackfn()
3029    }
3030}
3031
3032/**
3033 * 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.
3034 *
3035 * @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.
3036 *
3037 * @returns a result after applying callbackfn over all elements of the Array
3038 */
3039export function reduce(self: byte[], callbackfn: (previousValue: byte) => byte): byte {
3040    if (self.length == 0) {
3041        throw new TypeError("Reduce of empty array with no initial value")
3042    }
3043    let acc: byte = self[0];
3044    for (let i = 1; i < self.length; i++) {
3045        acc = callbackfn(acc)
3046    }
3047    return acc
3048}
3049
3050/**
3051 * 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.
3052 *
3053 * @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.
3054 *
3055 * @returns a result after applying callbackfn over all elements of the Array
3056 */
3057export function reduce(self: byte[], callbackfn: () => byte): byte {
3058    if (self.length == 0) {
3059        throw new TypeError("Reduce of empty array with no initial value")
3060    }
3061    let acc: byte = self[0];
3062    for (let i = 1; i < self.length; i++) {
3063        acc = callbackfn()
3064    }
3065    return acc
3066}
3067
3068/**
3069 * 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.
3070 *
3071 * @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.
3072 *
3073 * @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.
3074 *
3075 * @returns a result after applying callbackfn over all elements of the Array
3076 */
3077export function reduce<U = byte>(self: byte[], callbackfn: (previousValue: U) => U, initialValue: U): U {
3078    let acc = initialValue
3079    for (let i = 0; i < self.length; i++) {
3080        acc = callbackfn(acc)
3081    }
3082    return acc
3083}
3084
3085/**
3086 * 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.
3087 *
3088 * @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.
3089 *
3090 * @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.
3091 *
3092 * @returns a result after applying callbackfn over all elements of the Array
3093 */
3094export function reduce<U = byte>(self: byte[], callbackfn: () => U, initialValue: U): U {
3095    let acc = initialValue
3096    for (let i = 0; i < self.length; i++) {
3097        acc = callbackfn()
3098    }
3099    return acc
3100}
3101
3102/**
3103 * 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.
3104 *
3105 * @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.
3106 *
3107 * @returns a result after applying callbackfn over all elements of the Array
3108 */
3109export function reduceRight(self: byte[], callbackfn: (previousValue: byte) => byte): byte {
3110    if (self.length == 0) {
3111        throw new TypeError("Reduce of empty array with no initial value")
3112    }
3113    let acc: byte = self[self.length - 1];
3114    for (let i = self.length - 2; i >= 0; i--) {
3115        acc = callbackfn(acc)
3116    }
3117    return acc
3118}
3119
3120/**
3121 * 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.
3122 *
3123 * @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.
3124 *
3125 * @returns a result after applying callbackfn over all elements of the Array
3126 */
3127export function reduceRight(self: byte[], callbackfn: () => byte): byte {
3128    if (self.length == 0) {
3129        throw new TypeError("Reduce of empty array with no initial value")
3130    }
3131    let acc: byte = self[self.length - 1];
3132    for (let i = self.length - 2; i >= 0; i--) {
3133        acc = callbackfn()
3134    }
3135    return acc
3136}
3137
3138/**
3139 * 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.
3140 *
3141 * @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.
3142 *
3143 * @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.
3144 *
3145 * @returns a result after applying callbackfn over all elements of the Array
3146 */
3147export function reduceRight<U>(self: byte[], callbackfn: (previousValue: U) => U, initialValue: U): U {
3148    let acc = initialValue
3149    for (let i = self.length - 1; i >= 0; i--) {
3150        acc = callbackfn(acc)
3151    }
3152    return acc
3153}
3154
3155/**
3156 * 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.
3157 *
3158 * @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.
3159 *
3160 * @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.
3161 *
3162 * @returns a result after applying callbackfn over all elements of the Array
3163 */
3164export function reduceRight<U>(self: byte[], callbackfn: () => U, initialValue: U): U {
3165    let acc = initialValue
3166    for (let i = self.length - 1; i >= 0; i--) {
3167        acc = callbackfn()
3168    }
3169    return acc
3170}
3171
3172/**
3173 * Determines whether the specified callback function returns true for any element of an array.
3174 *
3175 * @param predicate A function that accepts up to three arguments. The some method calls
3176 * the predicate function for each element in the array until the predicate returns a value
3177 * which is coercible to the Boolean value true, or until the end of the array.
3178 *
3179 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
3180 */
3181export function some(self: byte[], predicate: () => boolean): boolean {
3182    for (let i = 0; i < self.length; i++) {
3183        if (predicate()) {
3184            return true
3185        }
3186    }
3187    return false
3188}
3189
3190/**
3191 * Iterates the array in reverse order and returns the value of the first element
3192 * that satisfies the provided testing function
3193 *
3194 * @param predicate testing function
3195 *
3196 * @returns found element or undefined otherwise
3197 */
3198export function findLast(self: byte[], predicate: () => boolean): Byte | undefined {
3199    for (let i = self.length - 1; i >= 0; i--) {
3200        const val = self[i];
3201        if (predicate()) {
3202            return val;
3203        }
3204    }
3205    return undefined;
3206}
3207
3208/**
3209 * Iterates the array in reverse order and returns the index of
3210 * the first element that satisfies the provided testing function.
3211 * If no elements satisfy the testing function, -1 is returned.
3212 *
3213 * @param predicate testing function
3214 *
3215 * @returns index of first element satisfying to predicate, -1 if no such element
3216 */
3217export function findLastIndex(self: byte[], predicate: () => boolean): number {
3218    for (let i = self.length - 1; i >= 0; i--) {
3219        if (predicate()) {
3220            return i
3221        }
3222    }
3223    return -1
3224}
3225
3226/**
3227 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3228 *
3229 * @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.
3230 *
3231 * @returns `Array` instance, constructed from `this` and given function.
3232 */
3233export function map(self: byte[], callbackfn: (value: byte, index: number, array: byte[]) => byte): byte[] {
3234    const len = self.length;
3235    let res = new byte[len];
3236    for (let i = 0; i < len; i++) {
3237        res[i] = callbackfn(self[i], i as number, self);
3238    }
3239    return res;
3240}
3241
3242/**
3243 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3244 *
3245 * @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.
3246 *
3247 * @returns `Array` instance, constructed from `this` and given function.
3248 */
3249export function map(self: byte[], callbackfn: (value: byte, index: number) => byte): byte[] {
3250    const len = self.length;
3251    let res = new byte[len];
3252    for (let i = 0; i < len; i++) {
3253        res[i] = callbackfn(self[i], i as number);
3254    }
3255    return res;
3256}
3257
3258/**
3259 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3260 *
3261 * @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.
3262 *
3263 * @returns `Array` instance, constructed from `this` and given function.
3264 */
3265export function map(self: byte[], callbackfn: (value: byte) => byte): byte[] {
3266    const len = self.length;
3267    let res = new byte[len];
3268    for (let i = 0; i < len; i++) {
3269        res[i] = callbackfn(self[i]);
3270    }
3271    return res;
3272}
3273
3274/**
3275 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
3276 *
3277 * @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.
3278 *
3279 * @returns `Array` instance, constructed from `this` and given function.
3280 */
3281export function map(self: byte[], callbackfn: () => byte): byte[] {
3282    const len = self.length;
3283    let res = new byte[len];
3284    for (let i = 0; i < len; i++) {
3285        res[i] = callbackfn();
3286    }
3287    return res;
3288}
3289
3290/**
3291 * Constructs a new `Array` instance and populates it with
3292 * portion of a given array, filtered down to just the elements from the
3293 * given array that pass the test implemented by the provided function.
3294 *
3295 * @param fn test function, applied to each element of an array.
3296 *
3297 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
3298 */
3299export function filter(self: byte[], fn: (v: byte, k: number) => boolean): byte[] {
3300    const mask = new boolean[self.length]
3301    let cnt = 0
3302
3303    for (let i: int = 0; i < self.length; i++) {
3304        const val = self[i];
3305        if (fn(val, i)) {
3306            mask[i] = true
3307            cnt++;
3308        }
3309    }
3310    const res = new byte[cnt];
3311    let idx_store = 0;
3312    for (let i: int = 0; i < self.length; i++) {
3313        if (mask[i]) {
3314            res[idx_store++] = self[i]
3315        }
3316    }
3317    return res;
3318}
3319
3320export function concat(self: byte[], fst: byte[], ...more: byte[][]): byte[] {
3321    const lnMin = self.length + fst.length;
3322    let ln = lnMin;
3323    for (let i = 0; i < more.length; i++) {
3324        ln += more[i].length
3325    }
3326    const r = new byte[ln];
3327    try {
3328        copyTo(self, r, 0, 0, self.length);
3329        copyTo(fst, r, self.length, 0, fst.length);
3330        let idx = lnMin;
3331        for (let i = 0; i < more.length; i++) {
3332            copyTo(more[i], r, idx, 0, more[i].length);
3333            idx += more[i].length;
3334        }
3335    } catch (e) {
3336        // impossible
3337    }
3338    return r
3339}
3340
3341/**
3342 * Reorders elements of `this` using comparator function.
3343 *
3344 * @param comparator function that defines the sort order.
3345 *
3346 * @note Mutating method
3347 */
3348export function sort(self: byte[], comparator: (a: byte, b: byte) => number): byte[] {
3349    sort_subarray(self, 0, self.length, (l: byte, r: byte): boolean => {
3350        return comparator(l, r ) < 0;
3351    });
3352    return self;
3353}
3354
3355/**
3356 * Reorders elements of `this` using comparator function.
3357 *
3358 * @param comparator function that defines the sort order.
3359 *
3360 * @note Mutating method
3361 */
3362export function sort(self: byte[], ): byte[] {
3363    sort(self, 0, self.length);
3364    return self;
3365}
3366
3367export function keys(self: byte[]): IterableIterator<number> {
3368    return new BuiltinArrayKeysIterator(self.length);
3369}
3370
3371class ArrayValuesIterator_byte implements IterableIterator<byte> {
3372    private parent: byte[]
3373    private idx: int = 0
3374
3375    constructor(parent: byte[]) {
3376        this.parent = parent
3377    }
3378
3379    override next(): IteratorResult<byte> {
3380        if (this.idx >= this.parent.length) {
3381            return new IteratorResult<byte>()
3382        }
3383        return new IteratorResult<byte>(this.parent[this.idx++])
3384    }
3385
3386    override $_iterator(): IterableIterator<byte> {
3387        return this;
3388    }
3389}
3390
3391class ArrayEntriesIterator_byte implements IterableIterator<[number, byte]> {
3392    private parent: byte[]
3393    private idx: int = 0
3394
3395    constructor(parent: byte[]) {
3396        this.parent = parent
3397    }
3398
3399    override next(): IteratorResult<[number, byte]> {
3400        if (this.idx >= this.parent.length) {
3401            return new IteratorResult<[number, byte]>()
3402        }
3403        const i = this.idx++;
3404        const vl: [number, byte] = [i as number, this.parent[i]]
3405        return new IteratorResult<[number, byte]>(vl);
3406    }
3407
3408    override $_iterator(): IterableIterator<[number, byte]> {
3409        return this;
3410    }
3411}
3412
3413function cloneArray(self: short[]): short[] {
3414    const ret = new short[self.length];;
3415    for (let i = 0; i < self.length; i++) {
3416        ret[i] = self[i];
3417    }
3418    return ret;
3419}
3420
3421/**
3422 * Takes an integer value and returns the item at that index,
3423 * allowing for positive and negative integers. Negative integers count back
3424 * from the last item in the array.
3425 *
3426 * @param index Zero-based index of the array element to be returned.
3427 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
3428 *
3429 * @returns The element in the array matching the given index.
3430 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
3431 */
3432export function at(self: short[], index: number): Short | undefined {
3433    return at(self, index as int)
3434}
3435
3436/**
3437 * Creates a new `Array` from this `Array` instance and given `Array` instance.
3438 *
3439 * @param other to concatenate into a new array.
3440 *
3441 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
3442 */
3443// export function concat(self: short[], ...items: (short | Concatshort[])[]): short[] {
3444//     throw new Error("not implemented")
3445// }
3446
3447export function concat(self: short[], ...items: ConcatArray<short>[]): short[] {
3448    let totalAdd = self.length;
3449    for (let i = 0; i < items.length; i++) {
3450        totalAdd += items[i].length as int
3451    }
3452
3453    const buf = new short[totalAdd];
3454
3455    for (let i = 0; i < self.length; i++) {
3456        buf[i] = self[i];
3457    }
3458
3459    let insertTo = self.length;
3460    for (let i = 0; i < items.length; i++) {
3461        const arr = items[i]
3462        const len = arr.length as int
3463        for (let j = 0; j < len; j++) {
3464            buf[insertTo++] = arr.$_get(j)
3465        }
3466    }
3467
3468    return buf;
3469}
3470
3471/**
3472 * Takes an integer value and returns the item at that index,
3473 * allowing for positive and negative integers. Negative integers count back
3474 * from the last item in the array.
3475 *
3476 * @param index Zero-based index of the array element to be returned.
3477 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
3478 *
3479 * @returns The element in the array matching the given index.
3480 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
3481 */
3482export function at(self: short[], index: int): Short | undefined {
3483    let len = self.length;
3484    let k: int;
3485    if (index >= 0) {
3486        k = index;
3487    } else {
3488        k = len + index;
3489    }
3490
3491    if (k < 0 || k >= len) {
3492        return undefined;
3493    }
3494
3495    return self[k];
3496}
3497
3498/**
3499 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
3500 *
3501 * @param target index at which to copy the sequence
3502 *
3503 * @param start index at which to start copying elements from
3504 *
3505 * @param end index at which to end copying elements from
3506 *
3507 * @returns this array after transformation
3508 */
3509export function copyWithin(self: short[], target: number, start: number, end?: Number): short[] {
3510    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
3511    return self;
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: int, start: int, end: int): short[] {
3526    target = normalizeIndex(target, self.length)
3527    start = normalizeIndex(start, self.length)
3528    end = normalizeIndex(end, self.length)
3529
3530    if (end <= start) {
3531        return self;
3532    }
3533
3534    if (target <= start) {
3535        while (start < end) {
3536            const read = self[start++];
3537            self[target++] = read;
3538        }
3539    } else {
3540        let len = end - start;
3541        if (target + len > self.length) {
3542            len = self.length - target
3543        }
3544        for (let i = 0; i < len; i++) {
3545            const read = self[start + len - 1 - i];
3546            self[target + len - 1 - i] = read;
3547        }
3548    }
3549
3550    return self;
3551}
3552
3553/**
3554 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
3555 *
3556 * @param target index at which to copy the sequence
3557 *
3558 * @param start index at which to start copying elements from
3559 *
3560 * @returns this array after transformation
3561 */
3562export function copyWithin(self: short[], target: int, start: int): short[] {
3563    copyWithin(self, target, start, self.length);
3564    return self;
3565}
3566
3567/**
3568 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
3569 *
3570 * @param target index at which to copy the sequence
3571 *
3572 * @returns this array after transformation
3573 */
3574export function copyWithin(self: short[], target: int): short[] {
3575    copyWithin(self, target, 0, self.length);
3576    return self;
3577}
3578
3579/**
3580 * Changes all elements in the Array to a static value, from a start index to an end index
3581 *
3582 * @param value to fill the array with
3583 *
3584 * @param start index at which to start filling
3585 *
3586 * @param end index at which to end filling, but not including
3587 *
3588 * @returns this array after transformation
3589 */
3590export function fill(self: short[], value: short, start?: Number, end?: Number): short[] {
3591    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, 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: int, end: int): short[] {
3607    start = normalizeIndex(start, self.length);
3608    end = normalizeIndex(end, self.length)
3609
3610    for (let i = start; i < end; i++) {
3611        self[i] = value;
3612    }
3613
3614    return self;
3615}
3616
3617/**
3618 * Returns the value of the first element in the array where predicate is true, and undefined
3619 * otherwise.
3620 *
3621 * @param predicate find calls predicate once for each element of the array, in ascending
3622 * order, until it finds one where predicate returns true. If such an element is found, find
3623 * immediately returns that element value. Otherwise, find returns undefined.
3624 *
3625 * @returns the value of the first element in the array or undefined
3626 */
3627export function find(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): Short | undefined {
3628    const res = findIndex(self, predicate)
3629    if (res == -1) {
3630        return undefined
3631    }
3632    return self[res as int];
3633}
3634
3635/**
3636 * Returns the index of the first element in the array where predicate is true, and -1
3637 * otherwise.
3638 *
3639 * @param predicate find calls predicate once for each element of the array, in ascending
3640 * order, until it finds one where predicate returns true. If such an element is found,
3641 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
3642 *
3643 * @returns found element index or -1 otherwise
3644 */
3645export function findIndex(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): number {
3646    for (let i = 0; i < self.length; i++) {
3647        if (predicate(self[i], i as number, self)) {
3648            return i;
3649        }
3650    }
3651    return -1;
3652}
3653
3654/**
3655 * Iterates the array in reverse order and returns the value of the first element
3656 * that satisfies the provided testing function
3657 *
3658 * @param predicate testing function
3659 *
3660 * @returns found element or undefined otherwise
3661 */
3662export function findLast(self: short[], predicate: (elem: short, index: number, array: short[]) => boolean): Short | undefined {
3663    for (let i = self.length - 1; i >= 0; i--) {
3664        const val = self[i];
3665        if (predicate(val, i as number, self)) {
3666            return val;
3667        }
3668    }
3669    return undefined;
3670}
3671
3672/**
3673 * Determines whether all the members of an array satisfy the specified test.
3674 *
3675 * @param predicate A function that accepts up to three arguments. The every method calls
3676 * the predicate function for each element in the array until the predicate returns a value
3677 * which is coercible to the Boolean value false, or until the end of the array.
3678 *
3679 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
3680 */
3681export function every(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): boolean {
3682    for (let i = 0; i < self.length; i++) {
3683        if (!predicate(self[i], i as number, self)) {
3684            return false
3685        }
3686    }
3687    return true;
3688}
3689
3690/**
3691 * Determines whether the specified callback function returns true for any element of an array.
3692 *
3693 * @param predicate A function that accepts up to three arguments. The some method calls
3694 * the predicate function for each element in the array until the predicate returns a value
3695 * which is coercible to the Boolean value true, or until the end of the array.
3696 *
3697 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
3698 */
3699export function some(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): boolean {
3700    for (let i = 0; i < self.length; i++) {
3701        if (predicate(self[i], i as number, self)) {
3702            return true
3703        }
3704    }
3705    return false
3706}
3707
3708/**
3709 * Returns the elements of an array that meet the condition specified in a callback function.
3710 *
3711 * @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.
3712 *
3713 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
3714 */
3715export function filter(self: short[], predicate: (value: short, index: number, array: short[]) => boolean): short[] {
3716    return filter(self, (value: short, index: number): boolean => predicate(value, index, self));
3717}
3718
3719/**
3720 * Iterates the array in reverse order and returns the index of
3721 * the first element that satisfies the provided testing function.
3722 * If no elements satisfy the testing function, -1 is returned.
3723 *
3724 * @param predicate testing function
3725 *
3726 * @returns index of first element satisfying to predicate, -1 if no such element
3727 */
3728export function findLastIndex(self: short[], predicate: (element: short, index: number, array: short[]) => boolean): number {
3729    for (let i = self.length - 1; i >= 0; i--) {
3730        if (predicate(self[i], i as number, self)) {
3731            return i
3732        }
3733    }
3734    return -1
3735}
3736
3737/**
3738 * 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.
3739 *
3740 * @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.
3741 *
3742 * @returns a result after applying callbackfn over all elements of the Array
3743 */
3744export function reduce(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number, array: short[]) => short): short {
3745    if (self.length == 0) {
3746        throw new TypeError("Reduce of empty array with no initial value")
3747    }
3748    let acc: short = self[0];
3749    for (let i = 1; i < self.length; i++) {
3750        acc = callbackfn(acc, self[i], i as number, self)
3751    }
3752    return acc
3753}
3754
3755/**
3756 * 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.
3757 *
3758 * @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.
3759 *
3760 * @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.
3761 *
3762 * @returns a result after applying callbackfn over all elements of the Array
3763 */
3764export function reduce<U = short>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number, array: short[]) => U, initialValue: U): U {
3765    let acc = initialValue
3766    for (let i = 0; i < self.length; i++) {
3767        acc = callbackfn(acc, self[i], i as number, self)
3768    }
3769    return acc
3770}
3771
3772/**
3773 * 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.
3774 *
3775 * @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.
3776 *
3777 * @returns a result after applying callbackfn over all elements of the Array
3778 */
3779export function reduceRight(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number, array: short[]) => short): short {
3780    if (self.length == 0) {
3781        throw new TypeError("Reduce of empty array with no initial value")
3782    }
3783    let acc: short = self[self.length - 1];
3784    for (let i = self.length - 2; i >= 0; i--) {
3785        acc = callbackfn(acc, self[i], i as number, self)
3786    }
3787    return acc
3788}
3789
3790/**
3791 * 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.
3792 *
3793 * @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.
3794 *
3795 * @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.
3796 *
3797 * @returns a result after applying callbackfn over all elements of the Array
3798 */
3799export function reduceRight<U>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number, array: short[]) => U, initialValue: U): U {
3800    let acc = initialValue
3801    for (let i = self.length - 1; i >= 0; i--) {
3802        acc = callbackfn(acc, self[i], i as number, self)
3803    }
3804    return acc
3805}
3806
3807/**
3808 * Performs the specified action for each element in an array.
3809 *
3810 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
3811 */
3812export function forEach(self: short[], callbackfn: (value: short, index: number, array: short[]) => void): void {
3813    const len0 = self.length;
3814    for (let i = 0; i < len0; i++) {
3815        callbackfn(self[i], i as number, self)
3816    }
3817}
3818
3819/**
3820 * Returns the value of the first element in the array where predicate is true, and undefined
3821 * otherwise.
3822 *
3823 * @param predicate find calls predicate once for each element of the array, in ascending
3824 * order, until it finds one where predicate returns true. If such an element is found, find
3825 * immediately returns that element value. Otherwise, find returns undefined.
3826 *
3827 * @returns the value of the first element in the array or undefined
3828 */
3829export function find(self: short[], predicate: (value: short, index: number) => boolean): Short | undefined {
3830    const res = findIndex(self, predicate)
3831    if (res == -1) {
3832        return undefined
3833    }
3834    return self[res as int];
3835}
3836
3837/**
3838 * Returns the index of the first element in the array where predicate is true, and -1
3839 * otherwise.
3840 *
3841 * @param predicate find calls predicate once for each element of the array, in ascending
3842 * order, until it finds one where predicate returns true. If such an element is found,
3843 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
3844 *
3845 * @returns found element index or -1 otherwise
3846 */
3847export function findIndex(self: short[], predicate: (value: short, index: number) => boolean): number {
3848    for (let i = 0; i < self.length; i++) {
3849        if (predicate(self[i], i as number)) {
3850            return i;
3851        }
3852    }
3853    return -1;
3854}
3855
3856/**
3857 * Iterates the array in reverse order and returns the value of the first element
3858 * that satisfies the provided testing function
3859 *
3860 * @param predicate testing function
3861 *
3862 * @returns found element or undefined otherwise
3863 */
3864export function findLast(self: short[], predicate: (elem: short, index: number) => boolean): Short | undefined {
3865    for (let i = self.length - 1; i >= 0; i--) {
3866        const val = self[i];
3867        if (predicate(val, i as number)) {
3868            return val;
3869        }
3870    }
3871    return undefined;
3872}
3873
3874/**
3875 * Determines whether all the members of an array satisfy the specified test.
3876 *
3877 * @param predicate A function that accepts up to three arguments. The every method calls
3878 * the predicate function for each element in the array until the predicate returns a value
3879 * which is coercible to the Boolean value false, or until the end of the array.
3880 *
3881 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
3882 */
3883export function every(self: short[], predicate: (value: short, index: number) => boolean): boolean {
3884    for (let i = 0; i < self.length; i++) {
3885        if (!predicate(self[i], i as number)) {
3886            return false
3887        }
3888    }
3889    return true;
3890}
3891
3892/**
3893 * Determines whether the specified callback function returns true for any element of an array.
3894 *
3895 * @param predicate A function that accepts up to three arguments. The some method calls
3896 * the predicate function for each element in the array until the predicate returns a value
3897 * which is coercible to the Boolean value true, or until the end of the array.
3898 *
3899 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
3900 */
3901export function some(self: short[], predicate: (value: short, index: number) => boolean): boolean {
3902    for (let i = 0; i < self.length; i++) {
3903        if (predicate(self[i], i as number)) {
3904            return true
3905        }
3906    }
3907    return false
3908}
3909
3910/**
3911 * Iterates the array in reverse order and returns the index of
3912 * the first element that satisfies the provided testing function.
3913 * If no elements satisfy the testing function, -1 is returned.
3914 *
3915 * @param predicate testing function
3916 *
3917 * @returns index of first element satisfying to predicate, -1 if no such element
3918 */
3919export function findLastIndex(self: short[], predicate: (element: short, index: number) => boolean): number {
3920    for (let i = self.length - 1; i >= 0; i--) {
3921        if (predicate(self[i], i as number)) {
3922            return i
3923        }
3924    }
3925    return -1
3926}
3927
3928/**
3929 * 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.
3930 *
3931 * @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.
3932 *
3933 * @returns a result after applying callbackfn over all elements of the Array
3934 */
3935export function reduce(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number) => short): short {
3936    if (self.length == 0) {
3937        throw new TypeError("Reduce of empty array with no initial value")
3938    }
3939    let acc: short = self[0];
3940    for (let i = 1; i < self.length; i++) {
3941        acc = callbackfn(acc, self[i], i as number)
3942    }
3943    return acc
3944}
3945
3946/**
3947 * 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.
3948 *
3949 * @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.
3950 *
3951 * @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.
3952 *
3953 * @returns a result after applying callbackfn over all elements of the Array
3954 */
3955export function reduce<U = short>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number) => U, initialValue: U): U {
3956    let acc = initialValue
3957    for (let i = 0; i < self.length; i++) {
3958        acc = callbackfn(acc, self[i], i as number)
3959    }
3960    return acc
3961}
3962
3963/**
3964 * 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.
3965 *
3966 * @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.
3967 *
3968 * @returns a result after applying callbackfn over all elements of the Array
3969 */
3970export function reduceRight(self: short[], callbackfn: (previousValue: short, currentValue: short, index: number) => short): short {
3971    if (self.length == 0) {
3972        throw new TypeError("Reduce of empty array with no initial value")
3973    }
3974    let acc: short = self[self.length - 1];
3975    for (let i = self.length - 2; i >= 0; i--) {
3976        acc = callbackfn(acc, self[i], i as number)
3977    }
3978    return acc
3979}
3980
3981/**
3982 * 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.
3983 *
3984 * @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.
3985 *
3986 * @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.
3987 *
3988 * @returns a result after applying callbackfn over all elements of the Array
3989 */
3990export function reduceRight<U>(self: short[], callbackfn: (previousValue: U, currentValue: short, index: number) => U, initialValue: U): U {
3991    let acc = initialValue
3992    for (let i = self.length - 1; i >= 0; i--) {
3993        acc = callbackfn(acc, self[i], i as number)
3994    }
3995    return acc
3996}
3997
3998/**
3999 * Performs the specified action for each element in an array.
4000 *
4001 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
4002 */
4003export function forEach(self: short[], callbackfn: (value: short, index: number) => void): void {
4004    const len0 = self.length;
4005    for (let i = 0; i < len0; i++) {
4006        callbackfn(self[i], i as number)
4007    }
4008}
4009
4010/**
4011 * Returns the value of the first element in the array where predicate is true, and undefined
4012 * otherwise.
4013 *
4014 * @param predicate find calls predicate once for each element of the array, in ascending
4015 * order, until it finds one where predicate returns true. If such an element is found, find
4016 * immediately returns that element value. Otherwise, find returns undefined.
4017 *
4018 * @returns the value of the first element in the array or undefined
4019 */
4020export function find(self: short[], predicate: (value: short) => boolean): Short | undefined {
4021    const res = findIndex(self, predicate)
4022    if (res == -1) {
4023        return undefined
4024    }
4025    return self[res as int];
4026}
4027
4028/**
4029 * Returns the index of the first element in the array where predicate is true, and -1
4030 * otherwise.
4031 *
4032 * @param predicate find calls predicate once for each element of the array, in ascending
4033 * order, until it finds one where predicate returns true. If such an element is found,
4034 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
4035 *
4036 * @returns found element index or -1 otherwise
4037 */
4038export function findIndex(self: short[], predicate: (value: short) => boolean): number {
4039    for (let i = 0; i < self.length; i++) {
4040        if (predicate(self[i])) {
4041            return i;
4042        }
4043    }
4044    return -1;
4045}
4046
4047/**
4048 * Iterates the array in reverse order and returns the value of the first element
4049 * that satisfies the provided testing function
4050 *
4051 * @param predicate testing function
4052 *
4053 * @returns found element or undefined otherwise
4054 */
4055export function findLast(self: short[], predicate: (elem: short) => boolean): Short | undefined {
4056    for (let i = self.length - 1; i >= 0; i--) {
4057        const val = self[i];
4058        if (predicate(val)) {
4059            return val;
4060        }
4061    }
4062    return undefined;
4063}
4064
4065/**
4066 * Determines whether all the members of an array satisfy the specified test.
4067 *
4068 * @param predicate A function that accepts up to three arguments. The every method calls
4069 * the predicate function for each element in the array until the predicate returns a value
4070 * which is coercible to the Boolean value false, or until the end of the array.
4071 *
4072 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
4073 */
4074export function every(self: short[], predicate: (value: short) => boolean): boolean {
4075    for (let i = 0; i < self.length; i++) {
4076        if (!predicate(self[i])) {
4077            return false
4078        }
4079    }
4080    return true;
4081}
4082
4083/**
4084 * Determines whether the specified callback function returns true for any element of an array.
4085 *
4086 * @param predicate A function that accepts up to three arguments. The some method calls
4087 * the predicate function for each element in the array until the predicate returns a value
4088 * which is coercible to the Boolean value true, or until the end of the array.
4089 *
4090 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
4091 */
4092export function some(self: short[], predicate: (value: short) => boolean): boolean {
4093    for (let i = 0; i < self.length; i++) {
4094        if (predicate(self[i])) {
4095            return true
4096        }
4097    }
4098    return false
4099}
4100
4101/**
4102 * Returns the elements of an array that meet the condition specified in a callback function.
4103 *
4104 * @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.
4105 *
4106 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
4107 */
4108export function filter(self: short[], predicate: (value: short) => boolean): short[] {
4109    return filter(self, (value: short, index: number): boolean => predicate(value));
4110}
4111
4112/**
4113 * Iterates the array in reverse order and returns the index of
4114 * the first element that satisfies the provided testing function.
4115 * If no elements satisfy the testing function, -1 is returned.
4116 *
4117 * @param predicate testing function
4118 *
4119 * @returns index of first element satisfying to predicate, -1 if no such element
4120 */
4121export function findLastIndex(self: short[], predicate: (element: short) => boolean): number {
4122    for (let i = self.length - 1; i >= 0; i--) {
4123        if (predicate(self[i])) {
4124            return i
4125        }
4126    }
4127    return -1
4128}
4129
4130/**
4131 * 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.
4132 *
4133 * @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.
4134 *
4135 * @returns a result after applying callbackfn over all elements of the Array
4136 */
4137export function reduce(self: short[], callbackfn: (previousValue: short, currentValue: short) => short): short {
4138    if (self.length == 0) {
4139        throw new TypeError("Reduce of empty array with no initial value")
4140    }
4141    let acc: short = self[0];
4142    for (let i = 1; i < self.length; i++) {
4143        acc = callbackfn(acc, self[i])
4144    }
4145    return acc
4146}
4147
4148/**
4149 * 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.
4150 *
4151 * @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.
4152 *
4153 * @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.
4154 *
4155 * @returns a result after applying callbackfn over all elements of the Array
4156 */
4157export function reduce<U = short>(self: short[], callbackfn: (previousValue: U, currentValue: short) => U, initialValue: U): U {
4158    let acc = initialValue
4159    for (let i = 0; i < self.length; i++) {
4160        acc = callbackfn(acc, self[i])
4161    }
4162    return acc
4163}
4164
4165/**
4166 * 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.
4167 *
4168 * @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.
4169 *
4170 * @returns a result after applying callbackfn over all elements of the Array
4171 */
4172export function reduceRight(self: short[], callbackfn: (previousValue: short, currentValue: short) => short): short {
4173    if (self.length == 0) {
4174        throw new TypeError("Reduce of empty array with no initial value")
4175    }
4176    let acc: short = self[self.length - 1];
4177    for (let i = self.length - 2; i >= 0; i--) {
4178        acc = callbackfn(acc, self[i])
4179    }
4180    return acc
4181}
4182
4183/**
4184 * 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.
4185 *
4186 * @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.
4187 *
4188 * @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.
4189 *
4190 * @returns a result after applying callbackfn over all elements of the Array
4191 */
4192export function reduceRight<U>(self: short[], callbackfn: (previousValue: U, currentValue: short) => U, initialValue: U): U {
4193    let acc = initialValue
4194    for (let i = self.length - 1; i >= 0; i--) {
4195        acc = callbackfn(acc, self[i])
4196    }
4197    return acc
4198}
4199
4200/**
4201 * Performs the specified action for each element in an array.
4202 *
4203 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
4204 */
4205export function forEach(self: short[], callbackfn: (value: short) => void): void {
4206    const len0 = self.length;
4207    for (let i = 0; i < len0; i++) {
4208        callbackfn(self[i])
4209    }
4210}
4211
4212/**
4213 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
4214 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
4215 *
4216 * @param start zero-based index at which to start extraction
4217 *
4218 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
4219 *
4220 * @returns `Array` instance, constructed from extracted elements of `this` instance.
4221 */
4222export function slice(self: short[], start?: Number, end?: Number): short[] {
4223    const len: int = self.length;
4224    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
4225}
4226
4227/**
4228 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
4229 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
4230 *
4231 * @param start zero-based index at which to start extraction
4232 *
4233 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
4234 *
4235 * @returns `Array` instance, constructed from extracted elements of `this` instance.
4236 */
4237export function slice(self: short[], start: int, end: int): short[] {
4238    const len: int = self.length;
4239    const relStart = normalizeIndex(start, len)
4240    const relEnd = normalizeIndex(end, len)
4241
4242    let count = relEnd - relStart;
4243    if (count < 0) {
4244        count = 0;
4245    }
4246    let res = new short[count]
4247    for (let i = 0; i < count; i++) {
4248        res[i] = self[relStart + i];
4249    }
4250
4251    return res
4252}
4253
4254/**
4255 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
4256 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
4257 *
4258 * @param start zero-based index at which to start extraction
4259 *
4260 * @returns `Array` instance, constructed from extracted elements of `this` instance.
4261 */
4262export function slice(self: short[], start: int): short[] {
4263    return slice(self, start, Int.MAX_VALUE as int);
4264}
4265
4266/**
4267 * Returns the last index at which a given element can be found in the array,
4268 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
4269 *
4270 * @param element element to locate in the array.
4271 * @param fromIndex zero-based index at which to start searching backwards.
4272 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
4273 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
4274 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
4275 *
4276 * @returns The last index of the element in the array; -1 if not found.
4277 */
4278export function lastIndexOf(self: short[], element: short, fromIndex: int): int {
4279    if (self.length == 0) {
4280        return -1;
4281    }
4282    let n = fromIndex;
4283    let k: int;
4284    if (n >= 0) {
4285        k = min(self.length - 1, n);
4286    } else {
4287        k = self.length + n;
4288    }
4289
4290    while (k >= 0) {
4291        if (__runtimeEquals(self[k], element)) {
4292            return k;
4293        }
4294        k--;
4295    }
4296    return -1;
4297}
4298
4299/**
4300 * Returns the last index at which a given element can be found in the array,
4301 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
4302 *
4303 * @param element element to locate in the array.
4304 * @param fromIndex zero-based index at which to start searching backwards.
4305 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
4306 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
4307 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
4308 *
4309 * @returns The last index of the element in the array; -1 if not found.
4310 */
4311export function lastIndexOf(self: short[], element: short, fromIndex?: Number): number {
4312    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
4313}
4314
4315/**
4316 * Creates and returns a new string by concatenating all of the elements in an `Array`,
4317 * separated by a specified separator string.
4318 * If the array has only one item, then that item will be returned without using the separator.
4319 *
4320 * @param sep specifies a separator
4321 *
4322 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
4323 */
4324export function join(self: short[], sep?: String): string {
4325    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
4326    let sb = new StringBuilder()
4327    for (let i: int = 0; i < self.length; i++) {
4328        const tmp = self[i]
4329        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
4330        if (i != 0) {
4331            sb.append(sepReal);
4332        }
4333        sb.append(tmp)
4334    }
4335
4336    return sb.toString();
4337}
4338
4339/**
4340 * Returns a string representing the specified array and its elements.
4341 *
4342 * @returns string representation
4343 */
4344export function toString(self: short[], ): string {
4345    return join(self, ",");
4346}
4347
4348/**
4349 * Returns a locale string representing the specified array and its elements.
4350 *
4351 * @param locales
4352 *
4353 * @param options
4354 *
4355 * @returns string representation
4356 */
4357export function toLocaleString(self: short[], locales: Object, options: Object): string {
4358    throw new Error("Array.toLocaleString: not implemented")
4359}
4360
4361/**
4362 * Returns a locale string representing the specified array and its elements.
4363 *
4364 * @param options
4365 *
4366 * @returns string representation
4367 */
4368export function toLocaleString(self: short[], locales: Object): string {
4369    return toLocaleString(self, new Object(), new Object())
4370}
4371
4372/**
4373 * Returns a locale string representing the specified array and its elements.
4374 *
4375 * @returns string representation
4376 */
4377export function toLocaleString(self: short[], ): string {
4378    const sb = new StringBuilder()
4379    const len = self.length;
4380    for (let i = 0; i < len; i++) {
4381        if (i != 0) {
4382            sb.append(",")
4383        }
4384        let x = self[i] as NullishType;
4385        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
4386            sb.append(x!.toLocaleString())
4387        }
4388    }
4389    return sb.toString()
4390}
4391
4392/**
4393 * Copying version of the splice() method.
4394 *
4395 * @param start index
4396 *
4397 * @param delete number of items after start index
4398 *
4399 * @returns a new Array with some elements removed and/or replaced at a given index.
4400 */
4401export function toSpliced(self: short[], start?: Number, delete?: Number): short[] {
4402    const len = self.length;
4403    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
4404}
4405
4406/**
4407 * Copying version of the splice() method.
4408 *
4409 * @param start index
4410 *
4411 * @param delete number of items after start index
4412 *
4413 * @returns a new Array with some elements removed and/or replaced at a given index.
4414 */
4415export function toSpliced(self: short[], start: number, delete: number, ...items: short[]): short[] {
4416    const len = self.length;
4417    return toSpliced(self, start as int, delete as int, ...items)
4418}
4419
4420/**
4421 * Copying version of the splice() method.
4422 *
4423 * @param start index
4424 *
4425 * @param delete number of items after start index
4426 *
4427 * @returns a new Array with some elements removed and/or replaced at a given index.
4428 */
4429export function toSpliced(self: short[], start: int, delete: int, ...items: short[]): short[] {
4430    const len = self.length;
4431    start = normalizeIndex(start, len);
4432    if (delete < 0) {
4433        delete = 0;
4434    } else if (delete > len) {
4435        delete = len;
4436    }
4437    if (start > len - delete) {
4438        delete = len - start
4439    }
4440    const res = new short[len - delete + items.length];
4441    for (let i = 0; i < start; i++) {
4442        res[i] = self[i]
4443    }
4444    for (let i = 0; i < items.length; i++) {
4445        res[start + i] = items[i]
4446    }
4447    for (let i = start + delete; i < len; i++) {
4448        res[i - delete + items.length] = self[i]
4449    }
4450    return res;
4451}
4452
4453/**
4454 * Copying version of the splice() method.
4455 *
4456 * @param start index
4457 *
4458 * @returns a new Array with some elements removed and/or replaced at a given index.
4459 */
4460export function toSpliced(self: short[], start: int): short[] {
4461    return toSpliced(self, start, self.length)
4462}
4463
4464/**
4465 * Checks whether an Array includes a certain value among its entries,
4466 * returning true or false as appropriate.
4467 *
4468 * @param val value to search
4469 *
4470 * @param fromIndex start index
4471 *
4472 * @returns true if val is in Array
4473 */
4474export function includes(self: short[], val: short, fromIndex?: Number): boolean {
4475    const len = self.length;
4476    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
4477    for (let i = fi; i < len; i++) {
4478        if (val == self[i]) {
4479            return true;
4480        }
4481    }
4482    return false;
4483}
4484
4485/**
4486 * Returns the first index at which a given element
4487 * can be found in the array, or -1 if it is not present.
4488 *
4489 * @param val value to search
4490 *
4491 * @param fromIndex index to search from
4492 *
4493 * @returns index of val, -1 otherwise
4494 */
4495export function indexOf(self: short[], val: short, fromIndex: int): int {
4496    fromIndex = normalizeIndex(fromIndex, self.length)
4497    for (let i = fromIndex; i < self.length; i++) {
4498        if (__runtimeEquals(val, self[i])) {
4499            return i
4500        }
4501    }
4502    return -1
4503}
4504
4505/**
4506 * Returns the first index at which a given element
4507 * can be found in the array, or -1 if it is not present.
4508 *
4509 * @param val value to search
4510 *
4511 * @param fromIndex index to search from
4512 *
4513 * @returns index of val, -1 otherwise
4514 */
4515export function indexOf(self: short[], val: short, fromIndex?: Number): number {
4516    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
4517}
4518
4519/**
4520 * Copying version of the sort() method.
4521 * It returns a new array with the elements sorted in ascending order.
4522 *
4523 * @returns sorted copy of hte current instance using default comparator
4524 */
4525export function toSorted(self: short[], ): short[] {
4526    let arr = cloneArray(self);
4527    sort(arr, )
4528    return arr
4529}
4530
4531/**
4532 * Copying version of the sort() method.
4533 * It returns a new array with the elements sorted in ascending order.
4534 *
4535 * @param comparator function to compare to elements of the Array
4536 *
4537 * @returns sorted copy of the current instance comparator
4538 */
4539export function toSorted(self: short[], comparator: (a: short, b: short) => number): short[] {
4540    let arr = cloneArray(self);
4541    sort(arr, comparator)
4542    return arr
4543}
4544
4545/**
4546 * Modifies `this` instance of `Array` class and populates
4547 * it with same elements ordered towards the direction opposite to that previously stated.
4548 *
4549 * @note Mutating method
4550 */
4551export function reverse(self: short[], ): short[] {
4552    for (let i = 0; i < self.length / 2; i++) {
4553        const tmp = self[i];
4554        const idx_r = self.length - 1 - i;
4555        const val_r = self[idx_r];
4556        self[i] = val_r;
4557        self[idx_r] = tmp;
4558    }
4559    return self;
4560}
4561
4562/**
4563 * Copying version of the reverse() method.
4564 * It returns a new array with the elements in reversed order.
4565 *
4566 * @returns reversed copy of the current Array
4567 */
4568export function toReversed(self: short[], ): short[] {
4569    let arr = new short[self.length]
4570    for (let i = 0; i < self.length; i++) {
4571        arr[self.length - 1 - i] = self[i]
4572    }
4573    return arr
4574}
4575
4576/**
4577 * Copying version of using the bracket notation to change the value of a given index.
4578 * It returns a new Array with the element at the given index replaced with the given value.
4579 *
4580 * @param index to replace
4581 *
4582 * @param value new value
4583 *
4584 * @returns a new Array with the element at the given index replaced with the given value
4585 */
4586export function with(self: short[], index: number, value: short): short[] {
4587    return with(self, index as int, value)
4588}
4589
4590/**
4591 * Copying version of using the bracket notation to change the value of a given index.
4592 * It returns a new Array with the element at the given index replaced with the given value.
4593 *
4594 * @param index to replace
4595 *
4596 * @param value new value
4597 *
4598 * @returns a new Array with the element at the given index replaced with the given value
4599 */
4600export function with(self: short[], index: int, value: short): short[] {
4601    if (index < 0) {
4602        index += self.length;
4603    }
4604    if (index >= self.length) {
4605        throw new RangeError("Invalid index")
4606    }
4607    let arr = cloneArray(self);
4608    arr[index] = value;
4609    return arr
4610}
4611
4612/**
4613 * Returns an iterator over all values
4614 */
4615export function values(self: short[], ): IterableIterator<short> {
4616    return new ArrayValuesIterator_short(self);
4617}
4618
4619/**
4620 * Returns an iterable of key, value pairs for every entry in the array
4621 */
4622export function entries(self: short[], ): IterableIterator<[number, short]> {
4623    return new ArrayEntriesIterator_short(self);
4624}
4625
4626/**
4627 * Determines whether all the members of an array satisfy the specified test.
4628 *
4629 * @param predicate A function that accepts up to three arguments. The every method calls
4630 * the predicate function for each element in the array until the predicate returns a value
4631 * which is coercible to the Boolean value false, or until the end of the array.
4632 *
4633 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
4634 */
4635export function every(self: short[], predicate: () => boolean): boolean {
4636    for (let i = 0; i < self.length; i++) {
4637        if (!predicate()) {
4638            return false
4639        }
4640    }
4641    return true
4642}
4643
4644/**
4645 * Returns the elements of an array that meet the condition specified in a callback function.
4646 *
4647 * @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.
4648 *
4649 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
4650 */
4651export function filter(self: short[], predicate: () => boolean): short[] {
4652    return filter(self, (value: short, index: number): boolean => predicate());
4653}
4654
4655/**
4656 * Returns the value of the first element in the array where predicate is true, and undefined
4657 * otherwise.
4658 *
4659 * @param predicate find calls predicate once for each element of the array, in ascending
4660 * order, until it finds one where predicate returns true. If such an element is found, find
4661 * immediately returns that element value. Otherwise, find returns undefined.
4662 *
4663 * @returns the value of the first element in the array or undefined
4664 */
4665export function find(self: short[], predicate: () => boolean): Short | undefined {
4666    const res = findIndex(self, predicate)
4667    if (res == -1) {
4668        return undefined
4669    }
4670    return self[res as int];
4671}
4672
4673/**
4674 * Returns the index of the first element in the array where predicate is true, and -1
4675 * otherwise.
4676 *
4677 * @param predicate find calls predicate once for each element of the array, in ascending
4678 * order, until it finds one where predicate returns true. If such an element is found,
4679 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
4680 *
4681 * @returns found element index or -1 otherwise
4682 */
4683export function findIndex(self: short[], predicate: () => boolean): number {
4684    for (let i = 0; i < self.length; i++) {
4685        if (predicate()) {
4686            return i;
4687        }
4688    }
4689    return -1;
4690}
4691
4692/**
4693 * Performs the specified action for each element in an array.
4694 *
4695 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
4696 */
4697export function forEach(self: short[], callbackfn: () => void): void {
4698    const len0 = self.length;
4699    for (let i = 0; i < len0; i++) {
4700        callbackfn()
4701    }
4702}
4703
4704/**
4705 * 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.
4706 *
4707 * @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.
4708 *
4709 * @returns a result after applying callbackfn over all elements of the Array
4710 */
4711export function reduce(self: short[], callbackfn: (previousValue: short) => short): short {
4712    if (self.length == 0) {
4713        throw new TypeError("Reduce of empty array with no initial value")
4714    }
4715    let acc: short = self[0];
4716    for (let i = 1; i < self.length; i++) {
4717        acc = callbackfn(acc)
4718    }
4719    return acc
4720}
4721
4722/**
4723 * 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.
4724 *
4725 * @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.
4726 *
4727 * @returns a result after applying callbackfn over all elements of the Array
4728 */
4729export function reduce(self: short[], callbackfn: () => short): short {
4730    if (self.length == 0) {
4731        throw new TypeError("Reduce of empty array with no initial value")
4732    }
4733    let acc: short = self[0];
4734    for (let i = 1; i < self.length; i++) {
4735        acc = callbackfn()
4736    }
4737    return acc
4738}
4739
4740/**
4741 * 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.
4742 *
4743 * @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.
4744 *
4745 * @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.
4746 *
4747 * @returns a result after applying callbackfn over all elements of the Array
4748 */
4749export function reduce<U = short>(self: short[], callbackfn: (previousValue: U) => U, initialValue: U): U {
4750    let acc = initialValue
4751    for (let i = 0; i < self.length; i++) {
4752        acc = callbackfn(acc)
4753    }
4754    return acc
4755}
4756
4757/**
4758 * 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.
4759 *
4760 * @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.
4761 *
4762 * @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.
4763 *
4764 * @returns a result after applying callbackfn over all elements of the Array
4765 */
4766export function reduce<U = short>(self: short[], callbackfn: () => U, initialValue: U): U {
4767    let acc = initialValue
4768    for (let i = 0; i < self.length; i++) {
4769        acc = callbackfn()
4770    }
4771    return acc
4772}
4773
4774/**
4775 * 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.
4776 *
4777 * @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.
4778 *
4779 * @returns a result after applying callbackfn over all elements of the Array
4780 */
4781export function reduceRight(self: short[], callbackfn: (previousValue: short) => short): short {
4782    if (self.length == 0) {
4783        throw new TypeError("Reduce of empty array with no initial value")
4784    }
4785    let acc: short = self[self.length - 1];
4786    for (let i = self.length - 2; i >= 0; i--) {
4787        acc = callbackfn(acc)
4788    }
4789    return acc
4790}
4791
4792/**
4793 * 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.
4794 *
4795 * @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.
4796 *
4797 * @returns a result after applying callbackfn over all elements of the Array
4798 */
4799export function reduceRight(self: short[], callbackfn: () => short): short {
4800    if (self.length == 0) {
4801        throw new TypeError("Reduce of empty array with no initial value")
4802    }
4803    let acc: short = self[self.length - 1];
4804    for (let i = self.length - 2; i >= 0; i--) {
4805        acc = callbackfn()
4806    }
4807    return acc
4808}
4809
4810/**
4811 * 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.
4812 *
4813 * @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.
4814 *
4815 * @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.
4816 *
4817 * @returns a result after applying callbackfn over all elements of the Array
4818 */
4819export function reduceRight<U>(self: short[], callbackfn: (previousValue: U) => U, initialValue: U): U {
4820    let acc = initialValue
4821    for (let i = self.length - 1; i >= 0; i--) {
4822        acc = callbackfn(acc)
4823    }
4824    return acc
4825}
4826
4827/**
4828 * 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.
4829 *
4830 * @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.
4831 *
4832 * @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.
4833 *
4834 * @returns a result after applying callbackfn over all elements of the Array
4835 */
4836export function reduceRight<U>(self: short[], callbackfn: () => U, initialValue: U): U {
4837    let acc = initialValue
4838    for (let i = self.length - 1; i >= 0; i--) {
4839        acc = callbackfn()
4840    }
4841    return acc
4842}
4843
4844/**
4845 * Determines whether the specified callback function returns true for any element of an array.
4846 *
4847 * @param predicate A function that accepts up to three arguments. The some method calls
4848 * the predicate function for each element in the array until the predicate returns a value
4849 * which is coercible to the Boolean value true, or until the end of the array.
4850 *
4851 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
4852 */
4853export function some(self: short[], predicate: () => boolean): boolean {
4854    for (let i = 0; i < self.length; i++) {
4855        if (predicate()) {
4856            return true
4857        }
4858    }
4859    return false
4860}
4861
4862/**
4863 * Iterates the array in reverse order and returns the value of the first element
4864 * that satisfies the provided testing function
4865 *
4866 * @param predicate testing function
4867 *
4868 * @returns found element or undefined otherwise
4869 */
4870export function findLast(self: short[], predicate: () => boolean): Short | undefined {
4871    for (let i = self.length - 1; i >= 0; i--) {
4872        const val = self[i];
4873        if (predicate()) {
4874            return val;
4875        }
4876    }
4877    return undefined;
4878}
4879
4880/**
4881 * Iterates the array in reverse order and returns the index of
4882 * the first element that satisfies the provided testing function.
4883 * If no elements satisfy the testing function, -1 is returned.
4884 *
4885 * @param predicate testing function
4886 *
4887 * @returns index of first element satisfying to predicate, -1 if no such element
4888 */
4889export function findLastIndex(self: short[], predicate: () => boolean): number {
4890    for (let i = self.length - 1; i >= 0; i--) {
4891        if (predicate()) {
4892            return i
4893        }
4894    }
4895    return -1
4896}
4897
4898/**
4899 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
4900 *
4901 * @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.
4902 *
4903 * @returns `Array` instance, constructed from `this` and given function.
4904 */
4905export function map(self: short[], callbackfn: (value: short, index: number, array: short[]) => short): short[] {
4906    const len = self.length;
4907    let res = new short[len];
4908    for (let i = 0; i < len; i++) {
4909        res[i] = callbackfn(self[i], i as number, self);
4910    }
4911    return res;
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) => 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);
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) => 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]);
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: () => 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();
4958    }
4959    return res;
4960}
4961
4962/**
4963 * Constructs a new `Array` instance and populates it with
4964 * portion of a given array, filtered down to just the elements from the
4965 * given array that pass the test implemented by the provided function.
4966 *
4967 * @param fn test function, applied to each element of an array.
4968 *
4969 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
4970 */
4971export function filter(self: short[], fn: (v: short, k: number) => boolean): short[] {
4972    const mask = new boolean[self.length]
4973    let cnt = 0
4974
4975    for (let i: int = 0; i < self.length; i++) {
4976        const val = self[i];
4977        if (fn(val, i)) {
4978            mask[i] = true
4979            cnt++;
4980        }
4981    }
4982    const res = new short[cnt];
4983    let idx_store = 0;
4984    for (let i: int = 0; i < self.length; i++) {
4985        if (mask[i]) {
4986            res[idx_store++] = self[i]
4987        }
4988    }
4989    return res;
4990}
4991
4992export function concat(self: short[], fst: short[], ...more: short[][]): short[] {
4993    const lnMin = self.length + fst.length;
4994    let ln = lnMin;
4995    for (let i = 0; i < more.length; i++) {
4996        ln += more[i].length
4997    }
4998    const r = new short[ln];
4999    try {
5000        copyTo(self, r, 0, 0, self.length);
5001        copyTo(fst, r, self.length, 0, fst.length);
5002        let idx = lnMin;
5003        for (let i = 0; i < more.length; i++) {
5004            copyTo(more[i], r, idx, 0, more[i].length);
5005            idx += more[i].length;
5006        }
5007    } catch (e) {
5008        // impossible
5009    }
5010    return r
5011}
5012
5013/**
5014 * Reorders elements of `this` using comparator function.
5015 *
5016 * @param comparator function that defines the sort order.
5017 *
5018 * @note Mutating method
5019 */
5020export function sort(self: short[], comparator: (a: short, b: short) => number): short[] {
5021    sort_subarray(self, 0, self.length, (l: short, r: short): boolean => {
5022        return comparator(l, r ) < 0;
5023    });
5024    return self;
5025}
5026
5027/**
5028 * Reorders elements of `this` using comparator function.
5029 *
5030 * @param comparator function that defines the sort order.
5031 *
5032 * @note Mutating method
5033 */
5034export function sort(self: short[], ): short[] {
5035    sort(self, 0, self.length);
5036    return self;
5037}
5038
5039export function keys(self: short[]): IterableIterator<number> {
5040    return new BuiltinArrayKeysIterator(self.length);
5041}
5042
5043class ArrayValuesIterator_short implements IterableIterator<short> {
5044    private parent: short[]
5045    private idx: int = 0
5046
5047    constructor(parent: short[]) {
5048        this.parent = parent
5049    }
5050
5051    override next(): IteratorResult<short> {
5052        if (this.idx >= this.parent.length) {
5053            return new IteratorResult<short>()
5054        }
5055        return new IteratorResult<short>(this.parent[this.idx++])
5056    }
5057
5058    override $_iterator(): IterableIterator<short> {
5059        return this;
5060    }
5061}
5062
5063class ArrayEntriesIterator_short implements IterableIterator<[number, short]> {
5064    private parent: short[]
5065    private idx: int = 0
5066
5067    constructor(parent: short[]) {
5068        this.parent = parent
5069    }
5070
5071    override next(): IteratorResult<[number, short]> {
5072        if (this.idx >= this.parent.length) {
5073            return new IteratorResult<[number, short]>()
5074        }
5075        const i = this.idx++;
5076        const vl: [number, short] = [i as number, this.parent[i]]
5077        return new IteratorResult<[number, short]>(vl);
5078    }
5079
5080    override $_iterator(): IterableIterator<[number, short]> {
5081        return this;
5082    }
5083}
5084
5085function cloneArray(self: int[]): int[] {
5086    const ret = new int[self.length];;
5087    for (let i = 0; i < self.length; i++) {
5088        ret[i] = self[i];
5089    }
5090    return ret;
5091}
5092
5093/**
5094 * Takes an integer value and returns the item at that index,
5095 * allowing for positive and negative integers. Negative integers count back
5096 * from the last item in the array.
5097 *
5098 * @param index Zero-based index of the array element to be returned.
5099 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
5100 *
5101 * @returns The element in the array matching the given index.
5102 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
5103 */
5104export function at(self: int[], index: number): Int | undefined {
5105    return at(self, index as int)
5106}
5107
5108/**
5109 * Creates a new `Array` from this `Array` instance and given `Array` instance.
5110 *
5111 * @param other to concatenate into a new array.
5112 *
5113 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
5114 */
5115// export function concat(self: int[], ...items: (int | Concatint[])[]): int[] {
5116//     throw new Error("not implemented")
5117// }
5118
5119export function concat(self: int[], ...items: ConcatArray<int>[]): int[] {
5120    let totalAdd = self.length;
5121    for (let i = 0; i < items.length; i++) {
5122        totalAdd += items[i].length as int
5123    }
5124
5125    const buf = new int[totalAdd];
5126
5127    for (let i = 0; i < self.length; i++) {
5128        buf[i] = self[i];
5129    }
5130
5131    let insertTo = self.length;
5132    for (let i = 0; i < items.length; i++) {
5133        const arr = items[i]
5134        const len = arr.length as int
5135        for (let j = 0; j < len; j++) {
5136            buf[insertTo++] = arr.$_get(j)
5137        }
5138    }
5139
5140    return buf;
5141}
5142
5143/**
5144 * Takes an integer value and returns the item at that index,
5145 * allowing for positive and negative integers. Negative integers count back
5146 * from the last item in the array.
5147 *
5148 * @param index Zero-based index of the array element to be returned.
5149 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
5150 *
5151 * @returns The element in the array matching the given index.
5152 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
5153 */
5154export function at(self: int[], index: int): Int | undefined {
5155    let len = self.length;
5156    let k: int;
5157    if (index >= 0) {
5158        k = index;
5159    } else {
5160        k = len + index;
5161    }
5162
5163    if (k < 0 || k >= len) {
5164        return undefined;
5165    }
5166
5167    return self[k];
5168}
5169
5170/**
5171 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5172 *
5173 * @param target index at which to copy the sequence
5174 *
5175 * @param start index at which to start copying elements from
5176 *
5177 * @param end index at which to end copying elements from
5178 *
5179 * @returns this array after transformation
5180 */
5181export function copyWithin(self: int[], target: number, start: number, end?: Number): int[] {
5182    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
5183    return self;
5184}
5185
5186/**
5187 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5188 *
5189 * @param target index at which to copy the sequence
5190 *
5191 * @param start index at which to start copying elements from
5192 *
5193 * @param end index at which to end copying elements from
5194 *
5195 * @returns this array after transformation
5196 */
5197export function copyWithin(self: int[], target: int, start: int, end: int): int[] {
5198    target = normalizeIndex(target, self.length)
5199    start = normalizeIndex(start, self.length)
5200    end = normalizeIndex(end, self.length)
5201
5202    if (end <= start) {
5203        return self;
5204    }
5205
5206    if (target <= start) {
5207        while (start < end) {
5208            const read = self[start++];
5209            self[target++] = read;
5210        }
5211    } else {
5212        let len = end - start;
5213        if (target + len > self.length) {
5214            len = self.length - target
5215        }
5216        for (let i = 0; i < len; i++) {
5217            const read = self[start + len - 1 - i];
5218            self[target + len - 1 - i] = read;
5219        }
5220    }
5221
5222    return self;
5223}
5224
5225/**
5226 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5227 *
5228 * @param target index at which to copy the sequence
5229 *
5230 * @param start index at which to start copying elements from
5231 *
5232 * @returns this array after transformation
5233 */
5234export function copyWithin(self: int[], target: int, start: int): int[] {
5235    copyWithin(self, target, start, self.length);
5236    return self;
5237}
5238
5239/**
5240 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
5241 *
5242 * @param target index at which to copy the sequence
5243 *
5244 * @returns this array after transformation
5245 */
5246export function copyWithin(self: int[], target: int): int[] {
5247    copyWithin(self, target, 0, self.length);
5248    return self;
5249}
5250
5251/**
5252 * Changes all elements in the Array to a static value, from a start index to an end index
5253 *
5254 * @param value to fill the array with
5255 *
5256 * @param start index at which to start filling
5257 *
5258 * @param end index at which to end filling, but not including
5259 *
5260 * @returns this array after transformation
5261 */
5262export function fill(self: int[], value: int, start?: Number, end?: Number): int[] {
5263    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
5264    return self;
5265}
5266
5267/**
5268 * Changes all elements in the Array to a static value, from a start index to an end index
5269 *
5270 * @param value to fill the array with
5271 *
5272 * @param start index at which to start filling
5273 *
5274 * @param end index at which to end filling, but not including
5275 *
5276 * @returns this array after transformation
5277 */
5278export function fill(self: int[], value: int, start: int, end: int): int[] {
5279    start = normalizeIndex(start, self.length);
5280    end = normalizeIndex(end, self.length)
5281
5282    for (let i = start; i < end; i++) {
5283        self[i] = value;
5284    }
5285
5286    return self;
5287}
5288
5289/**
5290 * Returns the value of the first element in the array where predicate is true, and undefined
5291 * otherwise.
5292 *
5293 * @param predicate find calls predicate once for each element of the array, in ascending
5294 * order, until it finds one where predicate returns true. If such an element is found, find
5295 * immediately returns that element value. Otherwise, find returns undefined.
5296 *
5297 * @returns the value of the first element in the array or undefined
5298 */
5299export function find(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): Int | undefined {
5300    const res = findIndex(self, predicate)
5301    if (res == -1) {
5302        return undefined
5303    }
5304    return self[res as int];
5305}
5306
5307/**
5308 * Returns the index of the first element in the array where predicate is true, and -1
5309 * otherwise.
5310 *
5311 * @param predicate find calls predicate once for each element of the array, in ascending
5312 * order, until it finds one where predicate returns true. If such an element is found,
5313 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
5314 *
5315 * @returns found element index or -1 otherwise
5316 */
5317export function findIndex(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): number {
5318    for (let i = 0; i < self.length; i++) {
5319        if (predicate(self[i], i as number, self)) {
5320            return i;
5321        }
5322    }
5323    return -1;
5324}
5325
5326/**
5327 * Iterates the array in reverse order and returns the value of the first element
5328 * that satisfies the provided testing function
5329 *
5330 * @param predicate testing function
5331 *
5332 * @returns found element or undefined otherwise
5333 */
5334export function findLast(self: int[], predicate: (elem: int, index: number, array: int[]) => boolean): Int | undefined {
5335    for (let i = self.length - 1; i >= 0; i--) {
5336        const val = self[i];
5337        if (predicate(val, i as number, self)) {
5338            return val;
5339        }
5340    }
5341    return undefined;
5342}
5343
5344/**
5345 * Determines whether all the members of an array satisfy the specified test.
5346 *
5347 * @param predicate A function that accepts up to three arguments. The every method calls
5348 * the predicate function for each element in the array until the predicate returns a value
5349 * which is coercible to the Boolean value false, or until the end of the array.
5350 *
5351 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
5352 */
5353export function every(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): boolean {
5354    for (let i = 0; i < self.length; i++) {
5355        if (!predicate(self[i], i as number, self)) {
5356            return false
5357        }
5358    }
5359    return true;
5360}
5361
5362/**
5363 * Determines whether the specified callback function returns true for any element of an array.
5364 *
5365 * @param predicate A function that accepts up to three arguments. The some method calls
5366 * the predicate function for each element in the array until the predicate returns a value
5367 * which is coercible to the Boolean value true, or until the end of the array.
5368 *
5369 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
5370 */
5371export function some(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): boolean {
5372    for (let i = 0; i < self.length; i++) {
5373        if (predicate(self[i], i as number, self)) {
5374            return true
5375        }
5376    }
5377    return false
5378}
5379
5380/**
5381 * Returns the elements of an array that meet the condition specified in a callback function.
5382 *
5383 * @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.
5384 *
5385 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
5386 */
5387export function filter(self: int[], predicate: (value: int, index: number, array: int[]) => boolean): int[] {
5388    return filter(self, (value: int, index: number): boolean => predicate(value, index, self));
5389}
5390
5391/**
5392 * Iterates the array in reverse order and returns the index of
5393 * the first element that satisfies the provided testing function.
5394 * If no elements satisfy the testing function, -1 is returned.
5395 *
5396 * @param predicate testing function
5397 *
5398 * @returns index of first element satisfying to predicate, -1 if no such element
5399 */
5400export function findLastIndex(self: int[], predicate: (element: int, index: number, array: int[]) => boolean): number {
5401    for (let i = self.length - 1; i >= 0; i--) {
5402        if (predicate(self[i], i as number, self)) {
5403            return i
5404        }
5405    }
5406    return -1
5407}
5408
5409/**
5410 * 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.
5411 *
5412 * @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.
5413 *
5414 * @returns a result after applying callbackfn over all elements of the Array
5415 */
5416export function reduce(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number, array: int[]) => int): int {
5417    if (self.length == 0) {
5418        throw new TypeError("Reduce of empty array with no initial value")
5419    }
5420    let acc: int = self[0];
5421    for (let i = 1; i < self.length; i++) {
5422        acc = callbackfn(acc, self[i], i as number, self)
5423    }
5424    return acc
5425}
5426
5427/**
5428 * 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.
5429 *
5430 * @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.
5431 *
5432 * @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.
5433 *
5434 * @returns a result after applying callbackfn over all elements of the Array
5435 */
5436export function reduce<U = int>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number, array: int[]) => U, initialValue: U): U {
5437    let acc = initialValue
5438    for (let i = 0; i < self.length; i++) {
5439        acc = callbackfn(acc, self[i], i as number, self)
5440    }
5441    return acc
5442}
5443
5444/**
5445 * 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.
5446 *
5447 * @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.
5448 *
5449 * @returns a result after applying callbackfn over all elements of the Array
5450 */
5451export function reduceRight(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number, array: int[]) => int): int {
5452    if (self.length == 0) {
5453        throw new TypeError("Reduce of empty array with no initial value")
5454    }
5455    let acc: int = self[self.length - 1];
5456    for (let i = self.length - 2; i >= 0; i--) {
5457        acc = callbackfn(acc, self[i], i as number, self)
5458    }
5459    return acc
5460}
5461
5462/**
5463 * 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.
5464 *
5465 * @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.
5466 *
5467 * @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.
5468 *
5469 * @returns a result after applying callbackfn over all elements of the Array
5470 */
5471export function reduceRight<U>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number, array: int[]) => U, initialValue: U): U {
5472    let acc = initialValue
5473    for (let i = self.length - 1; i >= 0; i--) {
5474        acc = callbackfn(acc, self[i], i as number, self)
5475    }
5476    return acc
5477}
5478
5479/**
5480 * Performs the specified action for each element in an array.
5481 *
5482 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
5483 */
5484export function forEach(self: int[], callbackfn: (value: int, index: number, array: int[]) => void): void {
5485    const len0 = self.length;
5486    for (let i = 0; i < len0; i++) {
5487        callbackfn(self[i], i as number, self)
5488    }
5489}
5490
5491/**
5492 * Returns the value of the first element in the array where predicate is true, and undefined
5493 * otherwise.
5494 *
5495 * @param predicate find calls predicate once for each element of the array, in ascending
5496 * order, until it finds one where predicate returns true. If such an element is found, find
5497 * immediately returns that element value. Otherwise, find returns undefined.
5498 *
5499 * @returns the value of the first element in the array or undefined
5500 */
5501export function find(self: int[], predicate: (value: int, index: number) => boolean): Int | undefined {
5502    const res = findIndex(self, predicate)
5503    if (res == -1) {
5504        return undefined
5505    }
5506    return self[res as int];
5507}
5508
5509/**
5510 * Returns the index of the first element in the array where predicate is true, and -1
5511 * otherwise.
5512 *
5513 * @param predicate find calls predicate once for each element of the array, in ascending
5514 * order, until it finds one where predicate returns true. If such an element is found,
5515 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
5516 *
5517 * @returns found element index or -1 otherwise
5518 */
5519export function findIndex(self: int[], predicate: (value: int, index: number) => boolean): number {
5520    for (let i = 0; i < self.length; i++) {
5521        if (predicate(self[i], i as number)) {
5522            return i;
5523        }
5524    }
5525    return -1;
5526}
5527
5528/**
5529 * Iterates the array in reverse order and returns the value of the first element
5530 * that satisfies the provided testing function
5531 *
5532 * @param predicate testing function
5533 *
5534 * @returns found element or undefined otherwise
5535 */
5536export function findLast(self: int[], predicate: (elem: int, index: number) => boolean): Int | undefined {
5537    for (let i = self.length - 1; i >= 0; i--) {
5538        const val = self[i];
5539        if (predicate(val, i as number)) {
5540            return val;
5541        }
5542    }
5543    return undefined;
5544}
5545
5546/**
5547 * Determines whether all the members of an array satisfy the specified test.
5548 *
5549 * @param predicate A function that accepts up to three arguments. The every method calls
5550 * the predicate function for each element in the array until the predicate returns a value
5551 * which is coercible to the Boolean value false, or until the end of the array.
5552 *
5553 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
5554 */
5555export function every(self: int[], predicate: (value: int, index: number) => boolean): boolean {
5556    for (let i = 0; i < self.length; i++) {
5557        if (!predicate(self[i], i as number)) {
5558            return false
5559        }
5560    }
5561    return true;
5562}
5563
5564/**
5565 * Determines whether the specified callback function returns true for any element of an array.
5566 *
5567 * @param predicate A function that accepts up to three arguments. The some method calls
5568 * the predicate function for each element in the array until the predicate returns a value
5569 * which is coercible to the Boolean value true, or until the end of the array.
5570 *
5571 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
5572 */
5573export function some(self: int[], predicate: (value: int, index: number) => boolean): boolean {
5574    for (let i = 0; i < self.length; i++) {
5575        if (predicate(self[i], i as number)) {
5576            return true
5577        }
5578    }
5579    return false
5580}
5581
5582/**
5583 * Iterates the array in reverse order and returns the index of
5584 * the first element that satisfies the provided testing function.
5585 * If no elements satisfy the testing function, -1 is returned.
5586 *
5587 * @param predicate testing function
5588 *
5589 * @returns index of first element satisfying to predicate, -1 if no such element
5590 */
5591export function findLastIndex(self: int[], predicate: (element: int, index: number) => boolean): number {
5592    for (let i = self.length - 1; i >= 0; i--) {
5593        if (predicate(self[i], i as number)) {
5594            return i
5595        }
5596    }
5597    return -1
5598}
5599
5600/**
5601 * 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.
5602 *
5603 * @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.
5604 *
5605 * @returns a result after applying callbackfn over all elements of the Array
5606 */
5607export function reduce(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number) => int): int {
5608    if (self.length == 0) {
5609        throw new TypeError("Reduce of empty array with no initial value")
5610    }
5611    let acc: int = self[0];
5612    for (let i = 1; i < self.length; i++) {
5613        acc = callbackfn(acc, self[i], i as number)
5614    }
5615    return acc
5616}
5617
5618/**
5619 * 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.
5620 *
5621 * @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.
5622 *
5623 * @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.
5624 *
5625 * @returns a result after applying callbackfn over all elements of the Array
5626 */
5627export function reduce<U = int>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number) => U, initialValue: U): U {
5628    let acc = initialValue
5629    for (let i = 0; i < self.length; i++) {
5630        acc = callbackfn(acc, self[i], i as number)
5631    }
5632    return acc
5633}
5634
5635/**
5636 * 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.
5637 *
5638 * @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.
5639 *
5640 * @returns a result after applying callbackfn over all elements of the Array
5641 */
5642export function reduceRight(self: int[], callbackfn: (previousValue: int, currentValue: int, index: number) => int): int {
5643    if (self.length == 0) {
5644        throw new TypeError("Reduce of empty array with no initial value")
5645    }
5646    let acc: int = self[self.length - 1];
5647    for (let i = self.length - 2; i >= 0; i--) {
5648        acc = callbackfn(acc, self[i], i as number)
5649    }
5650    return acc
5651}
5652
5653/**
5654 * 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.
5655 *
5656 * @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.
5657 *
5658 * @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.
5659 *
5660 * @returns a result after applying callbackfn over all elements of the Array
5661 */
5662export function reduceRight<U>(self: int[], callbackfn: (previousValue: U, currentValue: int, index: number) => U, initialValue: U): U {
5663    let acc = initialValue
5664    for (let i = self.length - 1; i >= 0; i--) {
5665        acc = callbackfn(acc, self[i], i as number)
5666    }
5667    return acc
5668}
5669
5670/**
5671 * Performs the specified action for each element in an array.
5672 *
5673 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
5674 */
5675export function forEach(self: int[], callbackfn: (value: int, index: number) => void): void {
5676    const len0 = self.length;
5677    for (let i = 0; i < len0; i++) {
5678        callbackfn(self[i], i as number)
5679    }
5680}
5681
5682/**
5683 * Returns the value of the first element in the array where predicate is true, and undefined
5684 * otherwise.
5685 *
5686 * @param predicate find calls predicate once for each element of the array, in ascending
5687 * order, until it finds one where predicate returns true. If such an element is found, find
5688 * immediately returns that element value. Otherwise, find returns undefined.
5689 *
5690 * @returns the value of the first element in the array or undefined
5691 */
5692export function find(self: int[], predicate: (value: int) => boolean): Int | undefined {
5693    const res = findIndex(self, predicate)
5694    if (res == -1) {
5695        return undefined
5696    }
5697    return self[res as int];
5698}
5699
5700/**
5701 * Returns the index of the first element in the array where predicate is true, and -1
5702 * otherwise.
5703 *
5704 * @param predicate find calls predicate once for each element of the array, in ascending
5705 * order, until it finds one where predicate returns true. If such an element is found,
5706 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
5707 *
5708 * @returns found element index or -1 otherwise
5709 */
5710export function findIndex(self: int[], predicate: (value: int) => boolean): number {
5711    for (let i = 0; i < self.length; i++) {
5712        if (predicate(self[i])) {
5713            return i;
5714        }
5715    }
5716    return -1;
5717}
5718
5719/**
5720 * Iterates the array in reverse order and returns the value of the first element
5721 * that satisfies the provided testing function
5722 *
5723 * @param predicate testing function
5724 *
5725 * @returns found element or undefined otherwise
5726 */
5727export function findLast(self: int[], predicate: (elem: int) => boolean): Int | undefined {
5728    for (let i = self.length - 1; i >= 0; i--) {
5729        const val = self[i];
5730        if (predicate(val)) {
5731            return val;
5732        }
5733    }
5734    return undefined;
5735}
5736
5737/**
5738 * Determines whether all the members of an array satisfy the specified test.
5739 *
5740 * @param predicate A function that accepts up to three arguments. The every method calls
5741 * the predicate function for each element in the array until the predicate returns a value
5742 * which is coercible to the Boolean value false, or until the end of the array.
5743 *
5744 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
5745 */
5746export function every(self: int[], predicate: (value: int) => boolean): boolean {
5747    for (let i = 0; i < self.length; i++) {
5748        if (!predicate(self[i])) {
5749            return false
5750        }
5751    }
5752    return true;
5753}
5754
5755/**
5756 * Determines whether the specified callback function returns true for any element of an array.
5757 *
5758 * @param predicate A function that accepts up to three arguments. The some method calls
5759 * the predicate function for each element in the array until the predicate returns a value
5760 * which is coercible to the Boolean value true, or until the end of the array.
5761 *
5762 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
5763 */
5764export function some(self: int[], predicate: (value: int) => boolean): boolean {
5765    for (let i = 0; i < self.length; i++) {
5766        if (predicate(self[i])) {
5767            return true
5768        }
5769    }
5770    return false
5771}
5772
5773/**
5774 * Returns the elements of an array that meet the condition specified in a callback function.
5775 *
5776 * @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.
5777 *
5778 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
5779 */
5780export function filter(self: int[], predicate: (value: int) => boolean): int[] {
5781    return filter(self, (value: int, index: number): boolean => predicate(value));
5782}
5783
5784/**
5785 * Iterates the array in reverse order and returns the index of
5786 * the first element that satisfies the provided testing function.
5787 * If no elements satisfy the testing function, -1 is returned.
5788 *
5789 * @param predicate testing function
5790 *
5791 * @returns index of first element satisfying to predicate, -1 if no such element
5792 */
5793export function findLastIndex(self: int[], predicate: (element: int) => boolean): number {
5794    for (let i = self.length - 1; i >= 0; i--) {
5795        if (predicate(self[i])) {
5796            return i
5797        }
5798    }
5799    return -1
5800}
5801
5802/**
5803 * 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.
5804 *
5805 * @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.
5806 *
5807 * @returns a result after applying callbackfn over all elements of the Array
5808 */
5809export function reduce(self: int[], callbackfn: (previousValue: int, currentValue: int) => int): int {
5810    if (self.length == 0) {
5811        throw new TypeError("Reduce of empty array with no initial value")
5812    }
5813    let acc: int = self[0];
5814    for (let i = 1; i < self.length; i++) {
5815        acc = callbackfn(acc, self[i])
5816    }
5817    return acc
5818}
5819
5820/**
5821 * 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.
5822 *
5823 * @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.
5824 *
5825 * @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.
5826 *
5827 * @returns a result after applying callbackfn over all elements of the Array
5828 */
5829export function reduce<U = int>(self: int[], callbackfn: (previousValue: U, currentValue: int) => U, initialValue: U): U {
5830    let acc = initialValue
5831    for (let i = 0; i < self.length; i++) {
5832        acc = callbackfn(acc, self[i])
5833    }
5834    return acc
5835}
5836
5837/**
5838 * 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.
5839 *
5840 * @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.
5841 *
5842 * @returns a result after applying callbackfn over all elements of the Array
5843 */
5844export function reduceRight(self: int[], callbackfn: (previousValue: int, currentValue: int) => int): int {
5845    if (self.length == 0) {
5846        throw new TypeError("Reduce of empty array with no initial value")
5847    }
5848    let acc: int = self[self.length - 1];
5849    for (let i = self.length - 2; i >= 0; i--) {
5850        acc = callbackfn(acc, self[i])
5851    }
5852    return acc
5853}
5854
5855/**
5856 * 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.
5857 *
5858 * @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.
5859 *
5860 * @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.
5861 *
5862 * @returns a result after applying callbackfn over all elements of the Array
5863 */
5864export function reduceRight<U>(self: int[], callbackfn: (previousValue: U, currentValue: int) => U, initialValue: U): U {
5865    let acc = initialValue
5866    for (let i = self.length - 1; i >= 0; i--) {
5867        acc = callbackfn(acc, self[i])
5868    }
5869    return acc
5870}
5871
5872/**
5873 * Performs the specified action for each element in an array.
5874 *
5875 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
5876 */
5877export function forEach(self: int[], callbackfn: (value: int) => void): void {
5878    const len0 = self.length;
5879    for (let i = 0; i < len0; i++) {
5880        callbackfn(self[i])
5881    }
5882}
5883
5884/**
5885 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
5886 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
5887 *
5888 * @param start zero-based index at which to start extraction
5889 *
5890 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
5891 *
5892 * @returns `Array` instance, constructed from extracted elements of `this` instance.
5893 */
5894export function slice(self: int[], start?: Number, end?: Number): int[] {
5895    const len: int = self.length;
5896    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
5897}
5898
5899/**
5900 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
5901 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
5902 *
5903 * @param start zero-based index at which to start extraction
5904 *
5905 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
5906 *
5907 * @returns `Array` instance, constructed from extracted elements of `this` instance.
5908 */
5909export function slice(self: int[], start: int, end: int): int[] {
5910    const len: int = self.length;
5911    const relStart = normalizeIndex(start, len)
5912    const relEnd = normalizeIndex(end, len)
5913
5914    let count = relEnd - relStart;
5915    if (count < 0) {
5916        count = 0;
5917    }
5918    let res = new int[count]
5919    for (let i = 0; i < count; i++) {
5920        res[i] = self[relStart + i];
5921    }
5922
5923    return res
5924}
5925
5926/**
5927 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
5928 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
5929 *
5930 * @param start zero-based index at which to start extraction
5931 *
5932 * @returns `Array` instance, constructed from extracted elements of `this` instance.
5933 */
5934export function slice(self: int[], start: int): int[] {
5935    return slice(self, start, Int.MAX_VALUE as int);
5936}
5937
5938/**
5939 * Returns the last index at which a given element can be found in the array,
5940 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
5941 *
5942 * @param element element to locate in the array.
5943 * @param fromIndex zero-based index at which to start searching backwards.
5944 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
5945 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
5946 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
5947 *
5948 * @returns The last index of the element in the array; -1 if not found.
5949 */
5950export function lastIndexOf(self: int[], element: int, fromIndex: int): int {
5951    if (self.length == 0) {
5952        return -1;
5953    }
5954    let n = fromIndex;
5955    let k: int;
5956    if (n >= 0) {
5957        k = min(self.length - 1, n);
5958    } else {
5959        k = self.length + n;
5960    }
5961
5962    while (k >= 0) {
5963        if (__runtimeEquals(self[k], element)) {
5964            return k;
5965        }
5966        k--;
5967    }
5968    return -1;
5969}
5970
5971/**
5972 * Returns the last index at which a given element can be found in the array,
5973 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
5974 *
5975 * @param element element to locate in the array.
5976 * @param fromIndex zero-based index at which to start searching backwards.
5977 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
5978 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
5979 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
5980 *
5981 * @returns The last index of the element in the array; -1 if not found.
5982 */
5983export function lastIndexOf(self: int[], element: int, fromIndex?: Number): number {
5984    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
5985}
5986
5987/**
5988 * Creates and returns a new string by concatenating all of the elements in an `Array`,
5989 * separated by a specified separator string.
5990 * If the array has only one item, then that item will be returned without using the separator.
5991 *
5992 * @param sep specifies a separator
5993 *
5994 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
5995 */
5996export function join(self: int[], sep?: String): string {
5997    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
5998    let sb = new StringBuilder()
5999    for (let i: int = 0; i < self.length; i++) {
6000        const tmp = self[i]
6001        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
6002        if (i != 0) {
6003            sb.append(sepReal);
6004        }
6005        sb.append(tmp)
6006    }
6007
6008    return sb.toString();
6009}
6010
6011/**
6012 * Returns a string representing the specified array and its elements.
6013 *
6014 * @returns string representation
6015 */
6016export function toString(self: int[], ): string {
6017    return join(self, ",");
6018}
6019
6020/**
6021 * Returns a locale string representing the specified array and its elements.
6022 *
6023 * @param locales
6024 *
6025 * @param options
6026 *
6027 * @returns string representation
6028 */
6029export function toLocaleString(self: int[], locales: Object, options: Object): string {
6030    throw new Error("Array.toLocaleString: not implemented")
6031}
6032
6033/**
6034 * Returns a locale string representing the specified array and its elements.
6035 *
6036 * @param options
6037 *
6038 * @returns string representation
6039 */
6040export function toLocaleString(self: int[], locales: Object): string {
6041    return toLocaleString(self, new Object(), new Object())
6042}
6043
6044/**
6045 * Returns a locale string representing the specified array and its elements.
6046 *
6047 * @returns string representation
6048 */
6049export function toLocaleString(self: int[], ): string {
6050    const sb = new StringBuilder()
6051    const len = self.length;
6052    for (let i = 0; i < len; i++) {
6053        if (i != 0) {
6054            sb.append(",")
6055        }
6056        let x = self[i] as NullishType;
6057        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
6058            sb.append(x!.toLocaleString())
6059        }
6060    }
6061    return sb.toString()
6062}
6063
6064/**
6065 * Copying version of the splice() method.
6066 *
6067 * @param start index
6068 *
6069 * @param delete number of items after start index
6070 *
6071 * @returns a new Array with some elements removed and/or replaced at a given index.
6072 */
6073export function toSpliced(self: int[], start?: Number, delete?: Number): int[] {
6074    const len = self.length;
6075    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
6076}
6077
6078/**
6079 * Copying version of the splice() method.
6080 *
6081 * @param start index
6082 *
6083 * @param delete number of items after start index
6084 *
6085 * @returns a new Array with some elements removed and/or replaced at a given index.
6086 */
6087export function toSpliced(self: int[], start: number, delete: number, ...items: int[]): int[] {
6088    const len = self.length;
6089    return toSpliced(self, start as int, delete as int, ...items)
6090}
6091
6092/**
6093 * Copying version of the splice() method.
6094 *
6095 * @param start index
6096 *
6097 * @param delete number of items after start index
6098 *
6099 * @returns a new Array with some elements removed and/or replaced at a given index.
6100 */
6101export function toSpliced(self: int[], start: int, delete: int, ...items: int[]): int[] {
6102    const len = self.length;
6103    start = normalizeIndex(start, len);
6104    if (delete < 0) {
6105        delete = 0;
6106    } else if (delete > len) {
6107        delete = len;
6108    }
6109    if (start > len - delete) {
6110        delete = len - start
6111    }
6112    const res = new int[len - delete + items.length];
6113    for (let i = 0; i < start; i++) {
6114        res[i] = self[i]
6115    }
6116    for (let i = 0; i < items.length; i++) {
6117        res[start + i] = items[i]
6118    }
6119    for (let i = start + delete; i < len; i++) {
6120        res[i - delete + items.length] = self[i]
6121    }
6122    return res;
6123}
6124
6125/**
6126 * Copying version of the splice() method.
6127 *
6128 * @param start index
6129 *
6130 * @returns a new Array with some elements removed and/or replaced at a given index.
6131 */
6132export function toSpliced(self: int[], start: int): int[] {
6133    return toSpliced(self, start, self.length)
6134}
6135
6136/**
6137 * Checks whether an Array includes a certain value among its entries,
6138 * returning true or false as appropriate.
6139 *
6140 * @param val value to search
6141 *
6142 * @param fromIndex start index
6143 *
6144 * @returns true if val is in Array
6145 */
6146export function includes(self: int[], val: int, fromIndex?: Number): boolean {
6147    const len = self.length;
6148    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
6149    for (let i = fi; i < len; i++) {
6150        if (val == self[i]) {
6151            return true;
6152        }
6153    }
6154    return false;
6155}
6156
6157/**
6158 * Returns the first index at which a given element
6159 * can be found in the array, or -1 if it is not present.
6160 *
6161 * @param val value to search
6162 *
6163 * @param fromIndex index to search from
6164 *
6165 * @returns index of val, -1 otherwise
6166 */
6167export function indexOf(self: int[], val: int, fromIndex: int): int {
6168    fromIndex = normalizeIndex(fromIndex, self.length)
6169    for (let i = fromIndex; i < self.length; i++) {
6170        if (__runtimeEquals(val, self[i])) {
6171            return i
6172        }
6173    }
6174    return -1
6175}
6176
6177/**
6178 * Returns the first index at which a given element
6179 * can be found in the array, or -1 if it is not present.
6180 *
6181 * @param val value to search
6182 *
6183 * @param fromIndex index to search from
6184 *
6185 * @returns index of val, -1 otherwise
6186 */
6187export function indexOf(self: int[], val: int, fromIndex?: Number): number {
6188    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
6189}
6190
6191/**
6192 * Copying version of the sort() method.
6193 * It returns a new array with the elements sorted in ascending order.
6194 *
6195 * @returns sorted copy of hte current instance using default comparator
6196 */
6197export function toSorted(self: int[], ): int[] {
6198    let arr = cloneArray(self);
6199    sort(arr, )
6200    return arr
6201}
6202
6203/**
6204 * Copying version of the sort() method.
6205 * It returns a new array with the elements sorted in ascending order.
6206 *
6207 * @param comparator function to compare to elements of the Array
6208 *
6209 * @returns sorted copy of the current instance comparator
6210 */
6211export function toSorted(self: int[], comparator: (a: int, b: int) => number): int[] {
6212    let arr = cloneArray(self);
6213    sort(arr, comparator)
6214    return arr
6215}
6216
6217/**
6218 * Modifies `this` instance of `Array` class and populates
6219 * it with same elements ordered towards the direction opposite to that previously stated.
6220 *
6221 * @note Mutating method
6222 */
6223export function reverse(self: int[], ): int[] {
6224    for (let i = 0; i < self.length / 2; i++) {
6225        const tmp = self[i];
6226        const idx_r = self.length - 1 - i;
6227        const val_r = self[idx_r];
6228        self[i] = val_r;
6229        self[idx_r] = tmp;
6230    }
6231    return self;
6232}
6233
6234/**
6235 * Copying version of the reverse() method.
6236 * It returns a new array with the elements in reversed order.
6237 *
6238 * @returns reversed copy of the current Array
6239 */
6240export function toReversed(self: int[], ): int[] {
6241    let arr = new int[self.length]
6242    for (let i = 0; i < self.length; i++) {
6243        arr[self.length - 1 - i] = self[i]
6244    }
6245    return arr
6246}
6247
6248/**
6249 * Copying version of using the bracket notation to change the value of a given index.
6250 * It returns a new Array with the element at the given index replaced with the given value.
6251 *
6252 * @param index to replace
6253 *
6254 * @param value new value
6255 *
6256 * @returns a new Array with the element at the given index replaced with the given value
6257 */
6258export function with(self: int[], index: number, value: int): int[] {
6259    return with(self, index as int, value)
6260}
6261
6262/**
6263 * Copying version of using the bracket notation to change the value of a given index.
6264 * It returns a new Array with the element at the given index replaced with the given value.
6265 *
6266 * @param index to replace
6267 *
6268 * @param value new value
6269 *
6270 * @returns a new Array with the element at the given index replaced with the given value
6271 */
6272export function with(self: int[], index: int, value: int): int[] {
6273    if (index < 0) {
6274        index += self.length;
6275    }
6276    if (index >= self.length) {
6277        throw new RangeError("Invalid index")
6278    }
6279    let arr = cloneArray(self);
6280    arr[index] = value;
6281    return arr
6282}
6283
6284/**
6285 * Returns an iterator over all values
6286 */
6287export function values(self: int[], ): IterableIterator<int> {
6288    return new ArrayValuesIterator_int(self);
6289}
6290
6291/**
6292 * Returns an iterable of key, value pairs for every entry in the array
6293 */
6294export function entries(self: int[], ): IterableIterator<[number, int]> {
6295    return new ArrayEntriesIterator_int(self);
6296}
6297
6298/**
6299 * Determines whether all the members of an array satisfy the specified test.
6300 *
6301 * @param predicate A function that accepts up to three arguments. The every method calls
6302 * the predicate function for each element in the array until the predicate returns a value
6303 * which is coercible to the Boolean value false, or until the end of the array.
6304 *
6305 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
6306 */
6307export function every(self: int[], predicate: () => boolean): boolean {
6308    for (let i = 0; i < self.length; i++) {
6309        if (!predicate()) {
6310            return false
6311        }
6312    }
6313    return true
6314}
6315
6316/**
6317 * Returns the elements of an array that meet the condition specified in a callback function.
6318 *
6319 * @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.
6320 *
6321 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
6322 */
6323export function filter(self: int[], predicate: () => boolean): int[] {
6324    return filter(self, (value: int, index: number): boolean => predicate());
6325}
6326
6327/**
6328 * Returns the value of the first element in the array where predicate is true, and undefined
6329 * otherwise.
6330 *
6331 * @param predicate find calls predicate once for each element of the array, in ascending
6332 * order, until it finds one where predicate returns true. If such an element is found, find
6333 * immediately returns that element value. Otherwise, find returns undefined.
6334 *
6335 * @returns the value of the first element in the array or undefined
6336 */
6337export function find(self: int[], predicate: () => boolean): Int | undefined {
6338    const res = findIndex(self, predicate)
6339    if (res == -1) {
6340        return undefined
6341    }
6342    return self[res as int];
6343}
6344
6345/**
6346 * Returns the index of the first element in the array where predicate is true, and -1
6347 * otherwise.
6348 *
6349 * @param predicate find calls predicate once for each element of the array, in ascending
6350 * order, until it finds one where predicate returns true. If such an element is found,
6351 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
6352 *
6353 * @returns found element index or -1 otherwise
6354 */
6355export function findIndex(self: int[], predicate: () => boolean): number {
6356    for (let i = 0; i < self.length; i++) {
6357        if (predicate()) {
6358            return i;
6359        }
6360    }
6361    return -1;
6362}
6363
6364/**
6365 * Performs the specified action for each element in an array.
6366 *
6367 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
6368 */
6369export function forEach(self: int[], callbackfn: () => void): void {
6370    const len0 = self.length;
6371    for (let i = 0; i < len0; i++) {
6372        callbackfn()
6373    }
6374}
6375
6376/**
6377 * 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.
6378 *
6379 * @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.
6380 *
6381 * @returns a result after applying callbackfn over all elements of the Array
6382 */
6383export function reduce(self: int[], callbackfn: (previousValue: int) => int): int {
6384    if (self.length == 0) {
6385        throw new TypeError("Reduce of empty array with no initial value")
6386    }
6387    let acc: int = self[0];
6388    for (let i = 1; i < self.length; i++) {
6389        acc = callbackfn(acc)
6390    }
6391    return acc
6392}
6393
6394/**
6395 * 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.
6396 *
6397 * @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.
6398 *
6399 * @returns a result after applying callbackfn over all elements of the Array
6400 */
6401export function reduce(self: int[], callbackfn: () => int): int {
6402    if (self.length == 0) {
6403        throw new TypeError("Reduce of empty array with no initial value")
6404    }
6405    let acc: int = self[0];
6406    for (let i = 1; i < self.length; i++) {
6407        acc = callbackfn()
6408    }
6409    return acc
6410}
6411
6412/**
6413 * 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.
6414 *
6415 * @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.
6416 *
6417 * @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.
6418 *
6419 * @returns a result after applying callbackfn over all elements of the Array
6420 */
6421export function reduce<U = int>(self: int[], callbackfn: (previousValue: U) => U, initialValue: U): U {
6422    let acc = initialValue
6423    for (let i = 0; i < self.length; i++) {
6424        acc = callbackfn(acc)
6425    }
6426    return acc
6427}
6428
6429/**
6430 * 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.
6431 *
6432 * @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.
6433 *
6434 * @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.
6435 *
6436 * @returns a result after applying callbackfn over all elements of the Array
6437 */
6438export function reduce<U = int>(self: int[], callbackfn: () => U, initialValue: U): U {
6439    let acc = initialValue
6440    for (let i = 0; i < self.length; i++) {
6441        acc = callbackfn()
6442    }
6443    return acc
6444}
6445
6446/**
6447 * 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.
6448 *
6449 * @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.
6450 *
6451 * @returns a result after applying callbackfn over all elements of the Array
6452 */
6453export function reduceRight(self: int[], callbackfn: (previousValue: int) => int): int {
6454    if (self.length == 0) {
6455        throw new TypeError("Reduce of empty array with no initial value")
6456    }
6457    let acc: int = self[self.length - 1];
6458    for (let i = self.length - 2; i >= 0; i--) {
6459        acc = callbackfn(acc)
6460    }
6461    return acc
6462}
6463
6464/**
6465 * 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.
6466 *
6467 * @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.
6468 *
6469 * @returns a result after applying callbackfn over all elements of the Array
6470 */
6471export function reduceRight(self: int[], callbackfn: () => int): int {
6472    if (self.length == 0) {
6473        throw new TypeError("Reduce of empty array with no initial value")
6474    }
6475    let acc: int = self[self.length - 1];
6476    for (let i = self.length - 2; i >= 0; i--) {
6477        acc = callbackfn()
6478    }
6479    return acc
6480}
6481
6482/**
6483 * 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.
6484 *
6485 * @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.
6486 *
6487 * @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.
6488 *
6489 * @returns a result after applying callbackfn over all elements of the Array
6490 */
6491export function reduceRight<U>(self: int[], callbackfn: (previousValue: U) => U, initialValue: U): U {
6492    let acc = initialValue
6493    for (let i = self.length - 1; i >= 0; i--) {
6494        acc = callbackfn(acc)
6495    }
6496    return acc
6497}
6498
6499/**
6500 * 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.
6501 *
6502 * @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.
6503 *
6504 * @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.
6505 *
6506 * @returns a result after applying callbackfn over all elements of the Array
6507 */
6508export function reduceRight<U>(self: int[], callbackfn: () => U, initialValue: U): U {
6509    let acc = initialValue
6510    for (let i = self.length - 1; i >= 0; i--) {
6511        acc = callbackfn()
6512    }
6513    return acc
6514}
6515
6516/**
6517 * Determines whether the specified callback function returns true for any element of an array.
6518 *
6519 * @param predicate A function that accepts up to three arguments. The some method calls
6520 * the predicate function for each element in the array until the predicate returns a value
6521 * which is coercible to the Boolean value true, or until the end of the array.
6522 *
6523 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
6524 */
6525export function some(self: int[], predicate: () => boolean): boolean {
6526    for (let i = 0; i < self.length; i++) {
6527        if (predicate()) {
6528            return true
6529        }
6530    }
6531    return false
6532}
6533
6534/**
6535 * Iterates the array in reverse order and returns the value of the first element
6536 * that satisfies the provided testing function
6537 *
6538 * @param predicate testing function
6539 *
6540 * @returns found element or undefined otherwise
6541 */
6542export function findLast(self: int[], predicate: () => boolean): Int | undefined {
6543    for (let i = self.length - 1; i >= 0; i--) {
6544        const val = self[i];
6545        if (predicate()) {
6546            return val;
6547        }
6548    }
6549    return undefined;
6550}
6551
6552/**
6553 * Iterates the array in reverse order and returns the index of
6554 * the first element that satisfies the provided testing function.
6555 * If no elements satisfy the testing function, -1 is returned.
6556 *
6557 * @param predicate testing function
6558 *
6559 * @returns index of first element satisfying to predicate, -1 if no such element
6560 */
6561export function findLastIndex(self: int[], predicate: () => boolean): number {
6562    for (let i = self.length - 1; i >= 0; i--) {
6563        if (predicate()) {
6564            return i
6565        }
6566    }
6567    return -1
6568}
6569
6570/**
6571 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6572 *
6573 * @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.
6574 *
6575 * @returns `Array` instance, constructed from `this` and given function.
6576 */
6577export function map(self: int[], callbackfn: (value: int, index: number, array: int[]) => int): int[] {
6578    const len = self.length;
6579    let res = new int[len];
6580    for (let i = 0; i < len; i++) {
6581        res[i] = callbackfn(self[i], i as number, self);
6582    }
6583    return res;
6584}
6585
6586/**
6587 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6588 *
6589 * @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.
6590 *
6591 * @returns `Array` instance, constructed from `this` and given function.
6592 */
6593export function map(self: int[], callbackfn: (value: int, index: number) => int): int[] {
6594    const len = self.length;
6595    let res = new int[len];
6596    for (let i = 0; i < len; i++) {
6597        res[i] = callbackfn(self[i], i as number);
6598    }
6599    return res;
6600}
6601
6602/**
6603 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6604 *
6605 * @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.
6606 *
6607 * @returns `Array` instance, constructed from `this` and given function.
6608 */
6609export function map(self: int[], callbackfn: (value: int) => int): int[] {
6610    const len = self.length;
6611    let res = new int[len];
6612    for (let i = 0; i < len; i++) {
6613        res[i] = callbackfn(self[i]);
6614    }
6615    return res;
6616}
6617
6618/**
6619 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
6620 *
6621 * @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.
6622 *
6623 * @returns `Array` instance, constructed from `this` and given function.
6624 */
6625export function map(self: int[], callbackfn: () => int): int[] {
6626    const len = self.length;
6627    let res = new int[len];
6628    for (let i = 0; i < len; i++) {
6629        res[i] = callbackfn();
6630    }
6631    return res;
6632}
6633
6634/**
6635 * Constructs a new `Array` instance and populates it with
6636 * portion of a given array, filtered down to just the elements from the
6637 * given array that pass the test implemented by the provided function.
6638 *
6639 * @param fn test function, applied to each element of an array.
6640 *
6641 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
6642 */
6643export function filter(self: int[], fn: (v: int, k: number) => boolean): int[] {
6644    const mask = new boolean[self.length]
6645    let cnt = 0
6646
6647    for (let i: int = 0; i < self.length; i++) {
6648        const val = self[i];
6649        if (fn(val, i)) {
6650            mask[i] = true
6651            cnt++;
6652        }
6653    }
6654    const res = new int[cnt];
6655    let idx_store = 0;
6656    for (let i: int = 0; i < self.length; i++) {
6657        if (mask[i]) {
6658            res[idx_store++] = self[i]
6659        }
6660    }
6661    return res;
6662}
6663
6664export function concat(self: int[], fst: int[], ...more: int[][]): int[] {
6665    const lnMin = self.length + fst.length;
6666    let ln = lnMin;
6667    for (let i = 0; i < more.length; i++) {
6668        ln += more[i].length
6669    }
6670    const r = new int[ln];
6671    try {
6672        copyTo(self, r, 0, 0, self.length);
6673        copyTo(fst, r, self.length, 0, fst.length);
6674        let idx = lnMin;
6675        for (let i = 0; i < more.length; i++) {
6676            copyTo(more[i], r, idx, 0, more[i].length);
6677            idx += more[i].length;
6678        }
6679    } catch (e) {
6680        // impossible
6681    }
6682    return r
6683}
6684
6685/**
6686 * Reorders elements of `this` using comparator function.
6687 *
6688 * @param comparator function that defines the sort order.
6689 *
6690 * @note Mutating method
6691 */
6692export function sort(self: int[], comparator: (a: int, b: int) => number): int[] {
6693    sort_subarray(self, 0, self.length, (l: int, r: int): boolean => {
6694        return comparator(l, r ) < 0;
6695    });
6696    return self;
6697}
6698
6699/**
6700 * Reorders elements of `this` using comparator function.
6701 *
6702 * @param comparator function that defines the sort order.
6703 *
6704 * @note Mutating method
6705 */
6706export function sort(self: int[], ): int[] {
6707    sort(self, 0, self.length);
6708    return self;
6709}
6710
6711export function keys(self: int[]): IterableIterator<number> {
6712    return new BuiltinArrayKeysIterator(self.length);
6713}
6714
6715class ArrayValuesIterator_int implements IterableIterator<int> {
6716    private parent: int[]
6717    private idx: int = 0
6718
6719    constructor(parent: int[]) {
6720        this.parent = parent
6721    }
6722
6723    override next(): IteratorResult<int> {
6724        if (this.idx >= this.parent.length) {
6725            return new IteratorResult<int>()
6726        }
6727        return new IteratorResult<int>(this.parent[this.idx++])
6728    }
6729
6730    override $_iterator(): IterableIterator<int> {
6731        return this;
6732    }
6733}
6734
6735class ArrayEntriesIterator_int implements IterableIterator<[number, int]> {
6736    private parent: int[]
6737    private idx: int = 0
6738
6739    constructor(parent: int[]) {
6740        this.parent = parent
6741    }
6742
6743    override next(): IteratorResult<[number, int]> {
6744        if (this.idx >= this.parent.length) {
6745            return new IteratorResult<[number, int]>()
6746        }
6747        const i = this.idx++;
6748        const vl: [number, int] = [i as number, this.parent[i]]
6749        return new IteratorResult<[number, int]>(vl);
6750    }
6751
6752    override $_iterator(): IterableIterator<[number, int]> {
6753        return this;
6754    }
6755}
6756
6757function cloneArray(self: long[]): long[] {
6758    const ret = new long[self.length];;
6759    for (let i = 0; i < self.length; i++) {
6760        ret[i] = self[i];
6761    }
6762    return ret;
6763}
6764
6765/**
6766 * Takes an integer value and returns the item at that index,
6767 * allowing for positive and negative integers. Negative integers count back
6768 * from the last item in the array.
6769 *
6770 * @param index Zero-based index of the array element to be returned.
6771 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
6772 *
6773 * @returns The element in the array matching the given index.
6774 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
6775 */
6776export function at(self: long[], index: number): Long | undefined {
6777    return at(self, index as int)
6778}
6779
6780/**
6781 * Creates a new `Array` from this `Array` instance and given `Array` instance.
6782 *
6783 * @param other to concatenate into a new array.
6784 *
6785 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
6786 */
6787// export function concat(self: long[], ...items: (long | Concatlong[])[]): long[] {
6788//     throw new Error("not implemented")
6789// }
6790
6791export function concat(self: long[], ...items: ConcatArray<long>[]): long[] {
6792    let totalAdd = self.length;
6793    for (let i = 0; i < items.length; i++) {
6794        totalAdd += items[i].length as int
6795    }
6796
6797    const buf = new long[totalAdd];
6798
6799    for (let i = 0; i < self.length; i++) {
6800        buf[i] = self[i];
6801    }
6802
6803    let insertTo = self.length;
6804    for (let i = 0; i < items.length; i++) {
6805        const arr = items[i]
6806        const len = arr.length as int
6807        for (let j = 0; j < len; j++) {
6808            buf[insertTo++] = arr.$_get(j)
6809        }
6810    }
6811
6812    return buf;
6813}
6814
6815/**
6816 * Takes an integer value and returns the item at that index,
6817 * allowing for positive and negative integers. Negative integers count back
6818 * from the last item in the array.
6819 *
6820 * @param index Zero-based index of the array element to be returned.
6821 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
6822 *
6823 * @returns The element in the array matching the given index.
6824 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
6825 */
6826export function at(self: long[], index: int): Long | undefined {
6827    let len = self.length;
6828    let k: int;
6829    if (index >= 0) {
6830        k = index;
6831    } else {
6832        k = len + index;
6833    }
6834
6835    if (k < 0 || k >= len) {
6836        return undefined;
6837    }
6838
6839    return self[k];
6840}
6841
6842/**
6843 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6844 *
6845 * @param target index at which to copy the sequence
6846 *
6847 * @param start index at which to start copying elements from
6848 *
6849 * @param end index at which to end copying elements from
6850 *
6851 * @returns this array after transformation
6852 */
6853export function copyWithin(self: long[], target: number, start: number, end?: Number): long[] {
6854    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
6855    return self;
6856}
6857
6858/**
6859 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6860 *
6861 * @param target index at which to copy the sequence
6862 *
6863 * @param start index at which to start copying elements from
6864 *
6865 * @param end index at which to end copying elements from
6866 *
6867 * @returns this array after transformation
6868 */
6869export function copyWithin(self: long[], target: int, start: int, end: int): long[] {
6870    target = normalizeIndex(target, self.length)
6871    start = normalizeIndex(start, self.length)
6872    end = normalizeIndex(end, self.length)
6873
6874    if (end <= start) {
6875        return self;
6876    }
6877
6878    if (target <= start) {
6879        while (start < end) {
6880            const read = self[start++];
6881            self[target++] = read;
6882        }
6883    } else {
6884        let len = end - start;
6885        if (target + len > self.length) {
6886            len = self.length - target
6887        }
6888        for (let i = 0; i < len; i++) {
6889            const read = self[start + len - 1 - i];
6890            self[target + len - 1 - i] = read;
6891        }
6892    }
6893
6894    return self;
6895}
6896
6897/**
6898 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6899 *
6900 * @param target index at which to copy the sequence
6901 *
6902 * @param start index at which to start copying elements from
6903 *
6904 * @returns this array after transformation
6905 */
6906export function copyWithin(self: long[], target: int, start: int): long[] {
6907    copyWithin(self, target, start, self.length);
6908    return self;
6909}
6910
6911/**
6912 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
6913 *
6914 * @param target index at which to copy the sequence
6915 *
6916 * @returns this array after transformation
6917 */
6918export function copyWithin(self: long[], target: int): long[] {
6919    copyWithin(self, target, 0, self.length);
6920    return self;
6921}
6922
6923/**
6924 * Changes all elements in the Array to a static value, from a start index to an end index
6925 *
6926 * @param value to fill the array with
6927 *
6928 * @param start index at which to start filling
6929 *
6930 * @param end index at which to end filling, but not including
6931 *
6932 * @returns this array after transformation
6933 */
6934export function fill(self: long[], value: long, start?: Number, end?: Number): long[] {
6935    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
6936    return self;
6937}
6938
6939/**
6940 * Changes all elements in the Array to a static value, from a start index to an end index
6941 *
6942 * @param value to fill the array with
6943 *
6944 * @param start index at which to start filling
6945 *
6946 * @param end index at which to end filling, but not including
6947 *
6948 * @returns this array after transformation
6949 */
6950export function fill(self: long[], value: long, start: int, end: int): long[] {
6951    start = normalizeIndex(start, self.length);
6952    end = normalizeIndex(end, self.length)
6953
6954    for (let i = start; i < end; i++) {
6955        self[i] = value;
6956    }
6957
6958    return self;
6959}
6960
6961/**
6962 * Returns the value of the first element in the array where predicate is true, and undefined
6963 * otherwise.
6964 *
6965 * @param predicate find calls predicate once for each element of the array, in ascending
6966 * order, until it finds one where predicate returns true. If such an element is found, find
6967 * immediately returns that element value. Otherwise, find returns undefined.
6968 *
6969 * @returns the value of the first element in the array or undefined
6970 */
6971export function find(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): Long | undefined {
6972    const res = findIndex(self, predicate)
6973    if (res == -1) {
6974        return undefined
6975    }
6976    return self[res as int];
6977}
6978
6979/**
6980 * Returns the index of the first element in the array where predicate is true, and -1
6981 * otherwise.
6982 *
6983 * @param predicate find calls predicate once for each element of the array, in ascending
6984 * order, until it finds one where predicate returns true. If such an element is found,
6985 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
6986 *
6987 * @returns found element index or -1 otherwise
6988 */
6989export function findIndex(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): number {
6990    for (let i = 0; i < self.length; i++) {
6991        if (predicate(self[i], i as number, self)) {
6992            return i;
6993        }
6994    }
6995    return -1;
6996}
6997
6998/**
6999 * Iterates the array in reverse order and returns the value of the first element
7000 * that satisfies the provided testing function
7001 *
7002 * @param predicate testing function
7003 *
7004 * @returns found element or undefined otherwise
7005 */
7006export function findLast(self: long[], predicate: (elem: long, index: number, array: long[]) => boolean): Long | undefined {
7007    for (let i = self.length - 1; i >= 0; i--) {
7008        const val = self[i];
7009        if (predicate(val, i as number, self)) {
7010            return val;
7011        }
7012    }
7013    return undefined;
7014}
7015
7016/**
7017 * Determines whether all the members of an array satisfy the specified test.
7018 *
7019 * @param predicate A function that accepts up to three arguments. The every method calls
7020 * the predicate function for each element in the array until the predicate returns a value
7021 * which is coercible to the Boolean value false, or until the end of the array.
7022 *
7023 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
7024 */
7025export function every(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): boolean {
7026    for (let i = 0; i < self.length; i++) {
7027        if (!predicate(self[i], i as number, self)) {
7028            return false
7029        }
7030    }
7031    return true;
7032}
7033
7034/**
7035 * Determines whether the specified callback function returns true for any element of an array.
7036 *
7037 * @param predicate A function that accepts up to three arguments. The some method calls
7038 * the predicate function for each element in the array until the predicate returns a value
7039 * which is coercible to the Boolean value true, or until the end of the array.
7040 *
7041 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
7042 */
7043export function some(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): boolean {
7044    for (let i = 0; i < self.length; i++) {
7045        if (predicate(self[i], i as number, self)) {
7046            return true
7047        }
7048    }
7049    return false
7050}
7051
7052/**
7053 * Returns the elements of an array that meet the condition specified in a callback function.
7054 *
7055 * @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.
7056 *
7057 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
7058 */
7059export function filter(self: long[], predicate: (value: long, index: number, array: long[]) => boolean): long[] {
7060    return filter(self, (value: long, index: number): boolean => predicate(value, index, self));
7061}
7062
7063/**
7064 * Iterates the array in reverse order and returns the index of
7065 * the first element that satisfies the provided testing function.
7066 * If no elements satisfy the testing function, -1 is returned.
7067 *
7068 * @param predicate testing function
7069 *
7070 * @returns index of first element satisfying to predicate, -1 if no such element
7071 */
7072export function findLastIndex(self: long[], predicate: (element: long, index: number, array: long[]) => boolean): number {
7073    for (let i = self.length - 1; i >= 0; i--) {
7074        if (predicate(self[i], i as number, self)) {
7075            return i
7076        }
7077    }
7078    return -1
7079}
7080
7081/**
7082 * 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.
7083 *
7084 * @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.
7085 *
7086 * @returns a result after applying callbackfn over all elements of the Array
7087 */
7088export function reduce(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number, array: long[]) => long): long {
7089    if (self.length == 0) {
7090        throw new TypeError("Reduce of empty array with no initial value")
7091    }
7092    let acc: long = self[0];
7093    for (let i = 1; i < self.length; i++) {
7094        acc = callbackfn(acc, self[i], i as number, self)
7095    }
7096    return acc
7097}
7098
7099/**
7100 * 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.
7101 *
7102 * @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.
7103 *
7104 * @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.
7105 *
7106 * @returns a result after applying callbackfn over all elements of the Array
7107 */
7108export function reduce<U = long>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number, array: long[]) => U, initialValue: U): U {
7109    let acc = initialValue
7110    for (let i = 0; i < self.length; i++) {
7111        acc = callbackfn(acc, self[i], i as number, self)
7112    }
7113    return acc
7114}
7115
7116/**
7117 * 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.
7118 *
7119 * @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.
7120 *
7121 * @returns a result after applying callbackfn over all elements of the Array
7122 */
7123export function reduceRight(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number, array: long[]) => long): long {
7124    if (self.length == 0) {
7125        throw new TypeError("Reduce of empty array with no initial value")
7126    }
7127    let acc: long = self[self.length - 1];
7128    for (let i = self.length - 2; i >= 0; i--) {
7129        acc = callbackfn(acc, self[i], i as number, self)
7130    }
7131    return acc
7132}
7133
7134/**
7135 * 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.
7136 *
7137 * @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.
7138 *
7139 * @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.
7140 *
7141 * @returns a result after applying callbackfn over all elements of the Array
7142 */
7143export function reduceRight<U>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number, array: long[]) => U, initialValue: U): U {
7144    let acc = initialValue
7145    for (let i = self.length - 1; i >= 0; i--) {
7146        acc = callbackfn(acc, self[i], i as number, self)
7147    }
7148    return acc
7149}
7150
7151/**
7152 * Performs the specified action for each element in an array.
7153 *
7154 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
7155 */
7156export function forEach(self: long[], callbackfn: (value: long, index: number, array: long[]) => void): void {
7157    const len0 = self.length;
7158    for (let i = 0; i < len0; i++) {
7159        callbackfn(self[i], i as number, self)
7160    }
7161}
7162
7163/**
7164 * Returns the value of the first element in the array where predicate is true, and undefined
7165 * otherwise.
7166 *
7167 * @param predicate find calls predicate once for each element of the array, in ascending
7168 * order, until it finds one where predicate returns true. If such an element is found, find
7169 * immediately returns that element value. Otherwise, find returns undefined.
7170 *
7171 * @returns the value of the first element in the array or undefined
7172 */
7173export function find(self: long[], predicate: (value: long, index: number) => boolean): Long | undefined {
7174    const res = findIndex(self, predicate)
7175    if (res == -1) {
7176        return undefined
7177    }
7178    return self[res as int];
7179}
7180
7181/**
7182 * Returns the index of the first element in the array where predicate is true, and -1
7183 * otherwise.
7184 *
7185 * @param predicate find calls predicate once for each element of the array, in ascending
7186 * order, until it finds one where predicate returns true. If such an element is found,
7187 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
7188 *
7189 * @returns found element index or -1 otherwise
7190 */
7191export function findIndex(self: long[], predicate: (value: long, index: number) => boolean): number {
7192    for (let i = 0; i < self.length; i++) {
7193        if (predicate(self[i], i as number)) {
7194            return i;
7195        }
7196    }
7197    return -1;
7198}
7199
7200/**
7201 * Iterates the array in reverse order and returns the value of the first element
7202 * that satisfies the provided testing function
7203 *
7204 * @param predicate testing function
7205 *
7206 * @returns found element or undefined otherwise
7207 */
7208export function findLast(self: long[], predicate: (elem: long, index: number) => boolean): Long | undefined {
7209    for (let i = self.length - 1; i >= 0; i--) {
7210        const val = self[i];
7211        if (predicate(val, i as number)) {
7212            return val;
7213        }
7214    }
7215    return undefined;
7216}
7217
7218/**
7219 * Determines whether all the members of an array satisfy the specified test.
7220 *
7221 * @param predicate A function that accepts up to three arguments. The every method calls
7222 * the predicate function for each element in the array until the predicate returns a value
7223 * which is coercible to the Boolean value false, or until the end of the array.
7224 *
7225 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
7226 */
7227export function every(self: long[], predicate: (value: long, index: number) => boolean): boolean {
7228    for (let i = 0; i < self.length; i++) {
7229        if (!predicate(self[i], i as number)) {
7230            return false
7231        }
7232    }
7233    return true;
7234}
7235
7236/**
7237 * Determines whether the specified callback function returns true for any element of an array.
7238 *
7239 * @param predicate A function that accepts up to three arguments. The some method calls
7240 * the predicate function for each element in the array until the predicate returns a value
7241 * which is coercible to the Boolean value true, or until the end of the array.
7242 *
7243 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
7244 */
7245export function some(self: long[], predicate: (value: long, index: number) => boolean): boolean {
7246    for (let i = 0; i < self.length; i++) {
7247        if (predicate(self[i], i as number)) {
7248            return true
7249        }
7250    }
7251    return false
7252}
7253
7254/**
7255 * Iterates the array in reverse order and returns the index of
7256 * the first element that satisfies the provided testing function.
7257 * If no elements satisfy the testing function, -1 is returned.
7258 *
7259 * @param predicate testing function
7260 *
7261 * @returns index of first element satisfying to predicate, -1 if no such element
7262 */
7263export function findLastIndex(self: long[], predicate: (element: long, index: number) => boolean): number {
7264    for (let i = self.length - 1; i >= 0; i--) {
7265        if (predicate(self[i], i as number)) {
7266            return i
7267        }
7268    }
7269    return -1
7270}
7271
7272/**
7273 * 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.
7274 *
7275 * @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.
7276 *
7277 * @returns a result after applying callbackfn over all elements of the Array
7278 */
7279export function reduce(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number) => long): long {
7280    if (self.length == 0) {
7281        throw new TypeError("Reduce of empty array with no initial value")
7282    }
7283    let acc: long = self[0];
7284    for (let i = 1; i < self.length; i++) {
7285        acc = callbackfn(acc, self[i], i as number)
7286    }
7287    return acc
7288}
7289
7290/**
7291 * 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.
7292 *
7293 * @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.
7294 *
7295 * @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.
7296 *
7297 * @returns a result after applying callbackfn over all elements of the Array
7298 */
7299export function reduce<U = long>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number) => U, initialValue: U): U {
7300    let acc = initialValue
7301    for (let i = 0; i < self.length; i++) {
7302        acc = callbackfn(acc, self[i], i as number)
7303    }
7304    return acc
7305}
7306
7307/**
7308 * 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.
7309 *
7310 * @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.
7311 *
7312 * @returns a result after applying callbackfn over all elements of the Array
7313 */
7314export function reduceRight(self: long[], callbackfn: (previousValue: long, currentValue: long, index: number) => long): long {
7315    if (self.length == 0) {
7316        throw new TypeError("Reduce of empty array with no initial value")
7317    }
7318    let acc: long = self[self.length - 1];
7319    for (let i = self.length - 2; i >= 0; i--) {
7320        acc = callbackfn(acc, self[i], i as number)
7321    }
7322    return acc
7323}
7324
7325/**
7326 * 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.
7327 *
7328 * @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.
7329 *
7330 * @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.
7331 *
7332 * @returns a result after applying callbackfn over all elements of the Array
7333 */
7334export function reduceRight<U>(self: long[], callbackfn: (previousValue: U, currentValue: long, index: number) => U, initialValue: U): U {
7335    let acc = initialValue
7336    for (let i = self.length - 1; i >= 0; i--) {
7337        acc = callbackfn(acc, self[i], i as number)
7338    }
7339    return acc
7340}
7341
7342/**
7343 * Performs the specified action for each element in an array.
7344 *
7345 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
7346 */
7347export function forEach(self: long[], callbackfn: (value: long, index: number) => void): void {
7348    const len0 = self.length;
7349    for (let i = 0; i < len0; i++) {
7350        callbackfn(self[i], i as number)
7351    }
7352}
7353
7354/**
7355 * Returns the value of the first element in the array where predicate is true, and undefined
7356 * otherwise.
7357 *
7358 * @param predicate find calls predicate once for each element of the array, in ascending
7359 * order, until it finds one where predicate returns true. If such an element is found, find
7360 * immediately returns that element value. Otherwise, find returns undefined.
7361 *
7362 * @returns the value of the first element in the array or undefined
7363 */
7364export function find(self: long[], predicate: (value: long) => boolean): Long | undefined {
7365    const res = findIndex(self, predicate)
7366    if (res == -1) {
7367        return undefined
7368    }
7369    return self[res as int];
7370}
7371
7372/**
7373 * Returns the index of the first element in the array where predicate is true, and -1
7374 * otherwise.
7375 *
7376 * @param predicate find calls predicate once for each element of the array, in ascending
7377 * order, until it finds one where predicate returns true. If such an element is found,
7378 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
7379 *
7380 * @returns found element index or -1 otherwise
7381 */
7382export function findIndex(self: long[], predicate: (value: long) => boolean): number {
7383    for (let i = 0; i < self.length; i++) {
7384        if (predicate(self[i])) {
7385            return i;
7386        }
7387    }
7388    return -1;
7389}
7390
7391/**
7392 * Iterates the array in reverse order and returns the value of the first element
7393 * that satisfies the provided testing function
7394 *
7395 * @param predicate testing function
7396 *
7397 * @returns found element or undefined otherwise
7398 */
7399export function findLast(self: long[], predicate: (elem: long) => boolean): Long | undefined {
7400    for (let i = self.length - 1; i >= 0; i--) {
7401        const val = self[i];
7402        if (predicate(val)) {
7403            return val;
7404        }
7405    }
7406    return undefined;
7407}
7408
7409/**
7410 * Determines whether all the members of an array satisfy the specified test.
7411 *
7412 * @param predicate A function that accepts up to three arguments. The every method calls
7413 * the predicate function for each element in the array until the predicate returns a value
7414 * which is coercible to the Boolean value false, or until the end of the array.
7415 *
7416 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
7417 */
7418export function every(self: long[], predicate: (value: long) => boolean): boolean {
7419    for (let i = 0; i < self.length; i++) {
7420        if (!predicate(self[i])) {
7421            return false
7422        }
7423    }
7424    return true;
7425}
7426
7427/**
7428 * Determines whether the specified callback function returns true for any element of an array.
7429 *
7430 * @param predicate A function that accepts up to three arguments. The some method calls
7431 * the predicate function for each element in the array until the predicate returns a value
7432 * which is coercible to the Boolean value true, or until the end of the array.
7433 *
7434 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
7435 */
7436export function some(self: long[], predicate: (value: long) => boolean): boolean {
7437    for (let i = 0; i < self.length; i++) {
7438        if (predicate(self[i])) {
7439            return true
7440        }
7441    }
7442    return false
7443}
7444
7445/**
7446 * Returns the elements of an array that meet the condition specified in a callback function.
7447 *
7448 * @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.
7449 *
7450 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
7451 */
7452export function filter(self: long[], predicate: (value: long) => boolean): long[] {
7453    return filter(self, (value: long, index: number): boolean => predicate(value));
7454}
7455
7456/**
7457 * Iterates the array in reverse order and returns the index of
7458 * the first element that satisfies the provided testing function.
7459 * If no elements satisfy the testing function, -1 is returned.
7460 *
7461 * @param predicate testing function
7462 *
7463 * @returns index of first element satisfying to predicate, -1 if no such element
7464 */
7465export function findLastIndex(self: long[], predicate: (element: long) => boolean): number {
7466    for (let i = self.length - 1; i >= 0; i--) {
7467        if (predicate(self[i])) {
7468            return i
7469        }
7470    }
7471    return -1
7472}
7473
7474/**
7475 * 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.
7476 *
7477 * @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.
7478 *
7479 * @returns a result after applying callbackfn over all elements of the Array
7480 */
7481export function reduce(self: long[], callbackfn: (previousValue: long, currentValue: long) => long): long {
7482    if (self.length == 0) {
7483        throw new TypeError("Reduce of empty array with no initial value")
7484    }
7485    let acc: long = self[0];
7486    for (let i = 1; i < self.length; i++) {
7487        acc = callbackfn(acc, self[i])
7488    }
7489    return acc
7490}
7491
7492/**
7493 * 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.
7494 *
7495 * @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.
7496 *
7497 * @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.
7498 *
7499 * @returns a result after applying callbackfn over all elements of the Array
7500 */
7501export function reduce<U = long>(self: long[], callbackfn: (previousValue: U, currentValue: long) => U, initialValue: U): U {
7502    let acc = initialValue
7503    for (let i = 0; i < self.length; i++) {
7504        acc = callbackfn(acc, self[i])
7505    }
7506    return acc
7507}
7508
7509/**
7510 * 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.
7511 *
7512 * @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.
7513 *
7514 * @returns a result after applying callbackfn over all elements of the Array
7515 */
7516export function reduceRight(self: long[], callbackfn: (previousValue: long, currentValue: long) => long): long {
7517    if (self.length == 0) {
7518        throw new TypeError("Reduce of empty array with no initial value")
7519    }
7520    let acc: long = self[self.length - 1];
7521    for (let i = self.length - 2; i >= 0; i--) {
7522        acc = callbackfn(acc, self[i])
7523    }
7524    return acc
7525}
7526
7527/**
7528 * 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.
7529 *
7530 * @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.
7531 *
7532 * @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.
7533 *
7534 * @returns a result after applying callbackfn over all elements of the Array
7535 */
7536export function reduceRight<U>(self: long[], callbackfn: (previousValue: U, currentValue: long) => U, initialValue: U): U {
7537    let acc = initialValue
7538    for (let i = self.length - 1; i >= 0; i--) {
7539        acc = callbackfn(acc, self[i])
7540    }
7541    return acc
7542}
7543
7544/**
7545 * Performs the specified action for each element in an array.
7546 *
7547 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
7548 */
7549export function forEach(self: long[], callbackfn: (value: long) => void): void {
7550    const len0 = self.length;
7551    for (let i = 0; i < len0; i++) {
7552        callbackfn(self[i])
7553    }
7554}
7555
7556/**
7557 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
7558 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
7559 *
7560 * @param start zero-based index at which to start extraction
7561 *
7562 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
7563 *
7564 * @returns `Array` instance, constructed from extracted elements of `this` instance.
7565 */
7566export function slice(self: long[], start?: Number, end?: Number): long[] {
7567    const len: int = self.length;
7568    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
7569}
7570
7571/**
7572 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
7573 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
7574 *
7575 * @param start zero-based index at which to start extraction
7576 *
7577 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
7578 *
7579 * @returns `Array` instance, constructed from extracted elements of `this` instance.
7580 */
7581export function slice(self: long[], start: int, end: int): long[] {
7582    const len: int = self.length;
7583    const relStart = normalizeIndex(start, len)
7584    const relEnd = normalizeIndex(end, len)
7585
7586    let count = relEnd - relStart;
7587    if (count < 0) {
7588        count = 0;
7589    }
7590    let res = new long[count]
7591    for (let i = 0; i < count; i++) {
7592        res[i] = self[relStart + i];
7593    }
7594
7595    return res
7596}
7597
7598/**
7599 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
7600 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
7601 *
7602 * @param start zero-based index at which to start extraction
7603 *
7604 * @returns `Array` instance, constructed from extracted elements of `this` instance.
7605 */
7606export function slice(self: long[], start: int): long[] {
7607    return slice(self, start, Int.MAX_VALUE as int);
7608}
7609
7610/**
7611 * Returns the last index at which a given element can be found in the array,
7612 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
7613 *
7614 * @param element element to locate in the array.
7615 * @param fromIndex zero-based index at which to start searching backwards.
7616 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
7617 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
7618 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
7619 *
7620 * @returns The last index of the element in the array; -1 if not found.
7621 */
7622export function lastIndexOf(self: long[], element: long, fromIndex: int): int {
7623    if (self.length == 0) {
7624        return -1;
7625    }
7626    let n = fromIndex;
7627    let k: int;
7628    if (n >= 0) {
7629        k = min(self.length - 1, n);
7630    } else {
7631        k = self.length + n;
7632    }
7633
7634    while (k >= 0) {
7635        if (__runtimeEquals(self[k], element)) {
7636            return k;
7637        }
7638        k--;
7639    }
7640    return -1;
7641}
7642
7643/**
7644 * Returns the last index at which a given element can be found in the array,
7645 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
7646 *
7647 * @param element element to locate in the array.
7648 * @param fromIndex zero-based index at which to start searching backwards.
7649 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
7650 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
7651 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
7652 *
7653 * @returns The last index of the element in the array; -1 if not found.
7654 */
7655export function lastIndexOf(self: long[], element: long, fromIndex?: Number): number {
7656    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
7657}
7658
7659/**
7660 * Creates and returns a new string by concatenating all of the elements in an `Array`,
7661 * separated by a specified separator string.
7662 * If the array has only one item, then that item will be returned without using the separator.
7663 *
7664 * @param sep specifies a separator
7665 *
7666 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
7667 */
7668export function join(self: long[], sep?: String): string {
7669    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
7670    let sb = new StringBuilder()
7671    for (let i: int = 0; i < self.length; i++) {
7672        const tmp = self[i]
7673        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
7674        if (i != 0) {
7675            sb.append(sepReal);
7676        }
7677        sb.append(tmp)
7678    }
7679
7680    return sb.toString();
7681}
7682
7683/**
7684 * Returns a string representing the specified array and its elements.
7685 *
7686 * @returns string representation
7687 */
7688export function toString(self: long[], ): string {
7689    return join(self, ",");
7690}
7691
7692/**
7693 * Returns a locale string representing the specified array and its elements.
7694 *
7695 * @param locales
7696 *
7697 * @param options
7698 *
7699 * @returns string representation
7700 */
7701export function toLocaleString(self: long[], locales: Object, options: Object): string {
7702    throw new Error("Array.toLocaleString: not implemented")
7703}
7704
7705/**
7706 * Returns a locale string representing the specified array and its elements.
7707 *
7708 * @param options
7709 *
7710 * @returns string representation
7711 */
7712export function toLocaleString(self: long[], locales: Object): string {
7713    return toLocaleString(self, new Object(), new Object())
7714}
7715
7716/**
7717 * Returns a locale string representing the specified array and its elements.
7718 *
7719 * @returns string representation
7720 */
7721export function toLocaleString(self: long[], ): string {
7722    const sb = new StringBuilder()
7723    const len = self.length;
7724    for (let i = 0; i < len; i++) {
7725        if (i != 0) {
7726            sb.append(",")
7727        }
7728        let x = self[i] as NullishType;
7729        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
7730            sb.append(x!.toLocaleString())
7731        }
7732    }
7733    return sb.toString()
7734}
7735
7736/**
7737 * Copying version of the splice() method.
7738 *
7739 * @param start index
7740 *
7741 * @param delete number of items after start index
7742 *
7743 * @returns a new Array with some elements removed and/or replaced at a given index.
7744 */
7745export function toSpliced(self: long[], start?: Number, delete?: Number): long[] {
7746    const len = self.length;
7747    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
7748}
7749
7750/**
7751 * Copying version of the splice() method.
7752 *
7753 * @param start index
7754 *
7755 * @param delete number of items after start index
7756 *
7757 * @returns a new Array with some elements removed and/or replaced at a given index.
7758 */
7759export function toSpliced(self: long[], start: number, delete: number, ...items: long[]): long[] {
7760    const len = self.length;
7761    return toSpliced(self, start as int, delete as int, ...items)
7762}
7763
7764/**
7765 * Copying version of the splice() method.
7766 *
7767 * @param start index
7768 *
7769 * @param delete number of items after start index
7770 *
7771 * @returns a new Array with some elements removed and/or replaced at a given index.
7772 */
7773export function toSpliced(self: long[], start: int, delete: int, ...items: long[]): long[] {
7774    const len = self.length;
7775    start = normalizeIndex(start, len);
7776    if (delete < 0) {
7777        delete = 0;
7778    } else if (delete > len) {
7779        delete = len;
7780    }
7781    if (start > len - delete) {
7782        delete = len - start
7783    }
7784    const res = new long[len - delete + items.length];
7785    for (let i = 0; i < start; i++) {
7786        res[i] = self[i]
7787    }
7788    for (let i = 0; i < items.length; i++) {
7789        res[start + i] = items[i]
7790    }
7791    for (let i = start + delete; i < len; i++) {
7792        res[i - delete + items.length] = self[i]
7793    }
7794    return res;
7795}
7796
7797/**
7798 * Copying version of the splice() method.
7799 *
7800 * @param start index
7801 *
7802 * @returns a new Array with some elements removed and/or replaced at a given index.
7803 */
7804export function toSpliced(self: long[], start: int): long[] {
7805    return toSpliced(self, start, self.length)
7806}
7807
7808/**
7809 * Checks whether an Array includes a certain value among its entries,
7810 * returning true or false as appropriate.
7811 *
7812 * @param val value to search
7813 *
7814 * @param fromIndex start index
7815 *
7816 * @returns true if val is in Array
7817 */
7818export function includes(self: long[], val: long, fromIndex?: Number): boolean {
7819    const len = self.length;
7820    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
7821    for (let i = fi; i < len; i++) {
7822        if (val == self[i]) {
7823            return true;
7824        }
7825    }
7826    return false;
7827}
7828
7829/**
7830 * Returns the first index at which a given element
7831 * can be found in the array, or -1 if it is not present.
7832 *
7833 * @param val value to search
7834 *
7835 * @param fromIndex index to search from
7836 *
7837 * @returns index of val, -1 otherwise
7838 */
7839export function indexOf(self: long[], val: long, fromIndex: int): int {
7840    fromIndex = normalizeIndex(fromIndex, self.length)
7841    for (let i = fromIndex; i < self.length; i++) {
7842        if (__runtimeEquals(val, self[i])) {
7843            return i
7844        }
7845    }
7846    return -1
7847}
7848
7849/**
7850 * Returns the first index at which a given element
7851 * can be found in the array, or -1 if it is not present.
7852 *
7853 * @param val value to search
7854 *
7855 * @param fromIndex index to search from
7856 *
7857 * @returns index of val, -1 otherwise
7858 */
7859export function indexOf(self: long[], val: long, fromIndex?: Number): number {
7860    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
7861}
7862
7863/**
7864 * Copying version of the sort() method.
7865 * It returns a new array with the elements sorted in ascending order.
7866 *
7867 * @returns sorted copy of hte current instance using default comparator
7868 */
7869export function toSorted(self: long[], ): long[] {
7870    let arr = cloneArray(self);
7871    sort(arr, )
7872    return arr
7873}
7874
7875/**
7876 * Copying version of the sort() method.
7877 * It returns a new array with the elements sorted in ascending order.
7878 *
7879 * @param comparator function to compare to elements of the Array
7880 *
7881 * @returns sorted copy of the current instance comparator
7882 */
7883export function toSorted(self: long[], comparator: (a: long, b: long) => number): long[] {
7884    let arr = cloneArray(self);
7885    sort(arr, comparator)
7886    return arr
7887}
7888
7889/**
7890 * Modifies `this` instance of `Array` class and populates
7891 * it with same elements ordered towards the direction opposite to that previously stated.
7892 *
7893 * @note Mutating method
7894 */
7895export function reverse(self: long[], ): long[] {
7896    for (let i = 0; i < self.length / 2; i++) {
7897        const tmp = self[i];
7898        const idx_r = self.length - 1 - i;
7899        const val_r = self[idx_r];
7900        self[i] = val_r;
7901        self[idx_r] = tmp;
7902    }
7903    return self;
7904}
7905
7906/**
7907 * Copying version of the reverse() method.
7908 * It returns a new array with the elements in reversed order.
7909 *
7910 * @returns reversed copy of the current Array
7911 */
7912export function toReversed(self: long[], ): long[] {
7913    let arr = new long[self.length]
7914    for (let i = 0; i < self.length; i++) {
7915        arr[self.length - 1 - i] = self[i]
7916    }
7917    return arr
7918}
7919
7920/**
7921 * Copying version of using the bracket notation to change the value of a given index.
7922 * It returns a new Array with the element at the given index replaced with the given value.
7923 *
7924 * @param index to replace
7925 *
7926 * @param value new value
7927 *
7928 * @returns a new Array with the element at the given index replaced with the given value
7929 */
7930export function with(self: long[], index: number, value: long): long[] {
7931    return with(self, index as int, value)
7932}
7933
7934/**
7935 * Copying version of using the bracket notation to change the value of a given index.
7936 * It returns a new Array with the element at the given index replaced with the given value.
7937 *
7938 * @param index to replace
7939 *
7940 * @param value new value
7941 *
7942 * @returns a new Array with the element at the given index replaced with the given value
7943 */
7944export function with(self: long[], index: int, value: long): long[] {
7945    if (index < 0) {
7946        index += self.length;
7947    }
7948    if (index >= self.length) {
7949        throw new RangeError("Invalid index")
7950    }
7951    let arr = cloneArray(self);
7952    arr[index] = value;
7953    return arr
7954}
7955
7956/**
7957 * Returns an iterator over all values
7958 */
7959export function values(self: long[], ): IterableIterator<long> {
7960    return new ArrayValuesIterator_long(self);
7961}
7962
7963/**
7964 * Returns an iterable of key, value pairs for every entry in the array
7965 */
7966export function entries(self: long[], ): IterableIterator<[number, long]> {
7967    return new ArrayEntriesIterator_long(self);
7968}
7969
7970/**
7971 * Determines whether all the members of an array satisfy the specified test.
7972 *
7973 * @param predicate A function that accepts up to three arguments. The every method calls
7974 * the predicate function for each element in the array until the predicate returns a value
7975 * which is coercible to the Boolean value false, or until the end of the array.
7976 *
7977 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
7978 */
7979export function every(self: long[], predicate: () => boolean): boolean {
7980    for (let i = 0; i < self.length; i++) {
7981        if (!predicate()) {
7982            return false
7983        }
7984    }
7985    return true
7986}
7987
7988/**
7989 * Returns the elements of an array that meet the condition specified in a callback function.
7990 *
7991 * @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.
7992 *
7993 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
7994 */
7995export function filter(self: long[], predicate: () => boolean): long[] {
7996    return filter(self, (value: long, index: number): boolean => predicate());
7997}
7998
7999/**
8000 * Returns the value of the first element in the array where predicate is true, and undefined
8001 * otherwise.
8002 *
8003 * @param predicate find calls predicate once for each element of the array, in ascending
8004 * order, until it finds one where predicate returns true. If such an element is found, find
8005 * immediately returns that element value. Otherwise, find returns undefined.
8006 *
8007 * @returns the value of the first element in the array or undefined
8008 */
8009export function find(self: long[], predicate: () => boolean): Long | undefined {
8010    const res = findIndex(self, predicate)
8011    if (res == -1) {
8012        return undefined
8013    }
8014    return self[res as int];
8015}
8016
8017/**
8018 * Returns the index of the first element in the array where predicate is true, and -1
8019 * otherwise.
8020 *
8021 * @param predicate find calls predicate once for each element of the array, in ascending
8022 * order, until it finds one where predicate returns true. If such an element is found,
8023 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
8024 *
8025 * @returns found element index or -1 otherwise
8026 */
8027export function findIndex(self: long[], predicate: () => boolean): number {
8028    for (let i = 0; i < self.length; i++) {
8029        if (predicate()) {
8030            return i;
8031        }
8032    }
8033    return -1;
8034}
8035
8036/**
8037 * Performs the specified action for each element in an array.
8038 *
8039 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
8040 */
8041export function forEach(self: long[], callbackfn: () => void): void {
8042    const len0 = self.length;
8043    for (let i = 0; i < len0; i++) {
8044        callbackfn()
8045    }
8046}
8047
8048/**
8049 * 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.
8050 *
8051 * @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.
8052 *
8053 * @returns a result after applying callbackfn over all elements of the Array
8054 */
8055export function reduce(self: long[], callbackfn: (previousValue: long) => long): long {
8056    if (self.length == 0) {
8057        throw new TypeError("Reduce of empty array with no initial value")
8058    }
8059    let acc: long = self[0];
8060    for (let i = 1; i < self.length; i++) {
8061        acc = callbackfn(acc)
8062    }
8063    return acc
8064}
8065
8066/**
8067 * 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.
8068 *
8069 * @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.
8070 *
8071 * @returns a result after applying callbackfn over all elements of the Array
8072 */
8073export function reduce(self: long[], callbackfn: () => long): long {
8074    if (self.length == 0) {
8075        throw new TypeError("Reduce of empty array with no initial value")
8076    }
8077    let acc: long = self[0];
8078    for (let i = 1; i < self.length; i++) {
8079        acc = callbackfn()
8080    }
8081    return acc
8082}
8083
8084/**
8085 * 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.
8086 *
8087 * @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.
8088 *
8089 * @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.
8090 *
8091 * @returns a result after applying callbackfn over all elements of the Array
8092 */
8093export function reduce<U = long>(self: long[], callbackfn: (previousValue: U) => U, initialValue: U): U {
8094    let acc = initialValue
8095    for (let i = 0; i < self.length; i++) {
8096        acc = callbackfn(acc)
8097    }
8098    return acc
8099}
8100
8101/**
8102 * 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.
8103 *
8104 * @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.
8105 *
8106 * @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.
8107 *
8108 * @returns a result after applying callbackfn over all elements of the Array
8109 */
8110export function reduce<U = long>(self: long[], callbackfn: () => U, initialValue: U): U {
8111    let acc = initialValue
8112    for (let i = 0; i < self.length; i++) {
8113        acc = callbackfn()
8114    }
8115    return acc
8116}
8117
8118/**
8119 * 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.
8120 *
8121 * @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.
8122 *
8123 * @returns a result after applying callbackfn over all elements of the Array
8124 */
8125export function reduceRight(self: long[], callbackfn: (previousValue: long) => long): long {
8126    if (self.length == 0) {
8127        throw new TypeError("Reduce of empty array with no initial value")
8128    }
8129    let acc: long = self[self.length - 1];
8130    for (let i = self.length - 2; i >= 0; i--) {
8131        acc = callbackfn(acc)
8132    }
8133    return acc
8134}
8135
8136/**
8137 * 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.
8138 *
8139 * @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.
8140 *
8141 * @returns a result after applying callbackfn over all elements of the Array
8142 */
8143export function reduceRight(self: long[], callbackfn: () => long): long {
8144    if (self.length == 0) {
8145        throw new TypeError("Reduce of empty array with no initial value")
8146    }
8147    let acc: long = self[self.length - 1];
8148    for (let i = self.length - 2; i >= 0; i--) {
8149        acc = callbackfn()
8150    }
8151    return acc
8152}
8153
8154/**
8155 * 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.
8156 *
8157 * @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.
8158 *
8159 * @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.
8160 *
8161 * @returns a result after applying callbackfn over all elements of the Array
8162 */
8163export function reduceRight<U>(self: long[], callbackfn: (previousValue: U) => U, initialValue: U): U {
8164    let acc = initialValue
8165    for (let i = self.length - 1; i >= 0; i--) {
8166        acc = callbackfn(acc)
8167    }
8168    return acc
8169}
8170
8171/**
8172 * 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.
8173 *
8174 * @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.
8175 *
8176 * @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.
8177 *
8178 * @returns a result after applying callbackfn over all elements of the Array
8179 */
8180export function reduceRight<U>(self: long[], callbackfn: () => U, initialValue: U): U {
8181    let acc = initialValue
8182    for (let i = self.length - 1; i >= 0; i--) {
8183        acc = callbackfn()
8184    }
8185    return acc
8186}
8187
8188/**
8189 * Determines whether the specified callback function returns true for any element of an array.
8190 *
8191 * @param predicate A function that accepts up to three arguments. The some method calls
8192 * the predicate function for each element in the array until the predicate returns a value
8193 * which is coercible to the Boolean value true, or until the end of the array.
8194 *
8195 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
8196 */
8197export function some(self: long[], predicate: () => boolean): boolean {
8198    for (let i = 0; i < self.length; i++) {
8199        if (predicate()) {
8200            return true
8201        }
8202    }
8203    return false
8204}
8205
8206/**
8207 * Iterates the array in reverse order and returns the value of the first element
8208 * that satisfies the provided testing function
8209 *
8210 * @param predicate testing function
8211 *
8212 * @returns found element or undefined otherwise
8213 */
8214export function findLast(self: long[], predicate: () => boolean): Long | undefined {
8215    for (let i = self.length - 1; i >= 0; i--) {
8216        const val = self[i];
8217        if (predicate()) {
8218            return val;
8219        }
8220    }
8221    return undefined;
8222}
8223
8224/**
8225 * Iterates the array in reverse order and returns the index of
8226 * the first element that satisfies the provided testing function.
8227 * If no elements satisfy the testing function, -1 is returned.
8228 *
8229 * @param predicate testing function
8230 *
8231 * @returns index of first element satisfying to predicate, -1 if no such element
8232 */
8233export function findLastIndex(self: long[], predicate: () => boolean): number {
8234    for (let i = self.length - 1; i >= 0; i--) {
8235        if (predicate()) {
8236            return i
8237        }
8238    }
8239    return -1
8240}
8241
8242/**
8243 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
8244 *
8245 * @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.
8246 *
8247 * @returns `Array` instance, constructed from `this` and given function.
8248 */
8249export function map(self: long[], callbackfn: (value: long, index: number, array: long[]) => long): long[] {
8250    const len = self.length;
8251    let res = new long[len];
8252    for (let i = 0; i < len; i++) {
8253        res[i] = callbackfn(self[i], i as number, self);
8254    }
8255    return res;
8256}
8257
8258/**
8259 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
8260 *
8261 * @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.
8262 *
8263 * @returns `Array` instance, constructed from `this` and given function.
8264 */
8265export function map(self: long[], callbackfn: (value: long, index: number) => long): long[] {
8266    const len = self.length;
8267    let res = new long[len];
8268    for (let i = 0; i < len; i++) {
8269        res[i] = callbackfn(self[i], i as number);
8270    }
8271    return res;
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) => 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]);
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: () => 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();
8302    }
8303    return res;
8304}
8305
8306/**
8307 * Constructs a new `Array` instance and populates it with
8308 * portion of a given array, filtered down to just the elements from the
8309 * given array that pass the test implemented by the provided function.
8310 *
8311 * @param fn test function, applied to each element of an array.
8312 *
8313 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
8314 */
8315export function filter(self: long[], fn: (v: long, k: number) => boolean): long[] {
8316    const mask = new boolean[self.length]
8317    let cnt = 0
8318
8319    for (let i: int = 0; i < self.length; i++) {
8320        const val = self[i];
8321        if (fn(val, i)) {
8322            mask[i] = true
8323            cnt++;
8324        }
8325    }
8326    const res = new long[cnt];
8327    let idx_store = 0;
8328    for (let i: int = 0; i < self.length; i++) {
8329        if (mask[i]) {
8330            res[idx_store++] = self[i]
8331        }
8332    }
8333    return res;
8334}
8335
8336export function concat(self: long[], fst: long[], ...more: long[][]): long[] {
8337    const lnMin = self.length + fst.length;
8338    let ln = lnMin;
8339    for (let i = 0; i < more.length; i++) {
8340        ln += more[i].length
8341    }
8342    const r = new long[ln];
8343    try {
8344        copyTo(self, r, 0, 0, self.length);
8345        copyTo(fst, r, self.length, 0, fst.length);
8346        let idx = lnMin;
8347        for (let i = 0; i < more.length; i++) {
8348            copyTo(more[i], r, idx, 0, more[i].length);
8349            idx += more[i].length;
8350        }
8351    } catch (e) {
8352        // impossible
8353    }
8354    return r
8355}
8356
8357/**
8358 * Reorders elements of `this` using comparator function.
8359 *
8360 * @param comparator function that defines the sort order.
8361 *
8362 * @note Mutating method
8363 */
8364export function sort(self: long[], comparator: (a: long, b: long) => number): long[] {
8365    sort_subarray(self, 0, self.length, (l: long, r: long): boolean => {
8366        return comparator(l, r ) < 0;
8367    });
8368    return self;
8369}
8370
8371/**
8372 * Reorders elements of `this` using comparator function.
8373 *
8374 * @param comparator function that defines the sort order.
8375 *
8376 * @note Mutating method
8377 */
8378export function sort(self: long[], ): long[] {
8379    sort(self, 0, self.length);
8380    return self;
8381}
8382
8383export function keys(self: long[]): IterableIterator<number> {
8384    return new BuiltinArrayKeysIterator(self.length);
8385}
8386
8387class ArrayValuesIterator_long implements IterableIterator<long> {
8388    private parent: long[]
8389    private idx: int = 0
8390
8391    constructor(parent: long[]) {
8392        this.parent = parent
8393    }
8394
8395    override next(): IteratorResult<long> {
8396        if (this.idx >= this.parent.length) {
8397            return new IteratorResult<long>()
8398        }
8399        return new IteratorResult<long>(this.parent[this.idx++])
8400    }
8401
8402    override $_iterator(): IterableIterator<long> {
8403        return this;
8404    }
8405}
8406
8407class ArrayEntriesIterator_long implements IterableIterator<[number, long]> {
8408    private parent: long[]
8409    private idx: int = 0
8410
8411    constructor(parent: long[]) {
8412        this.parent = parent
8413    }
8414
8415    override next(): IteratorResult<[number, long]> {
8416        if (this.idx >= this.parent.length) {
8417            return new IteratorResult<[number, long]>()
8418        }
8419        const i = this.idx++;
8420        const vl: [number, long] = [i as number, this.parent[i]]
8421        return new IteratorResult<[number, long]>(vl);
8422    }
8423
8424    override $_iterator(): IterableIterator<[number, long]> {
8425        return this;
8426    }
8427}
8428
8429function cloneArray(self: float[]): float[] {
8430    const ret = new float[self.length];;
8431    for (let i = 0; i < self.length; i++) {
8432        ret[i] = self[i];
8433    }
8434    return ret;
8435}
8436
8437/**
8438 * Takes an integer value and returns the item at that index,
8439 * allowing for positive and negative integers. Negative integers count back
8440 * from the last item in the array.
8441 *
8442 * @param index Zero-based index of the array element to be returned.
8443 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
8444 *
8445 * @returns The element in the array matching the given index.
8446 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
8447 */
8448export function at(self: float[], index: number): Float | undefined {
8449    return at(self, index as int)
8450}
8451
8452/**
8453 * Creates a new `Array` from this `Array` instance and given `Array` instance.
8454 *
8455 * @param other to concatenate into a new array.
8456 *
8457 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
8458 */
8459// export function concat(self: float[], ...items: (float | Concatfloat[])[]): float[] {
8460//     throw new Error("not implemented")
8461// }
8462
8463export function concat(self: float[], ...items: ConcatArray<float>[]): float[] {
8464    let totalAdd = self.length;
8465    for (let i = 0; i < items.length; i++) {
8466        totalAdd += items[i].length as int
8467    }
8468
8469    const buf = new float[totalAdd];
8470
8471    for (let i = 0; i < self.length; i++) {
8472        buf[i] = self[i];
8473    }
8474
8475    let insertTo = self.length;
8476    for (let i = 0; i < items.length; i++) {
8477        const arr = items[i]
8478        const len = arr.length as int
8479        for (let j = 0; j < len; j++) {
8480            buf[insertTo++] = arr.$_get(j)
8481        }
8482    }
8483
8484    return buf;
8485}
8486
8487/**
8488 * Takes an integer value and returns the item at that index,
8489 * allowing for positive and negative integers. Negative integers count back
8490 * from the last item in the array.
8491 *
8492 * @param index Zero-based index of the array element to be returned.
8493 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
8494 *
8495 * @returns The element in the array matching the given index.
8496 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
8497 */
8498export function at(self: float[], index: int): Float | undefined {
8499    let len = self.length;
8500    let k: int;
8501    if (index >= 0) {
8502        k = index;
8503    } else {
8504        k = len + index;
8505    }
8506
8507    if (k < 0 || k >= len) {
8508        return undefined;
8509    }
8510
8511    return self[k];
8512}
8513
8514/**
8515 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8516 *
8517 * @param target index at which to copy the sequence
8518 *
8519 * @param start index at which to start copying elements from
8520 *
8521 * @param end index at which to end copying elements from
8522 *
8523 * @returns this array after transformation
8524 */
8525export function copyWithin(self: float[], target: number, start: number, end?: Number): float[] {
8526    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
8527    return self;
8528}
8529
8530/**
8531 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8532 *
8533 * @param target index at which to copy the sequence
8534 *
8535 * @param start index at which to start copying elements from
8536 *
8537 * @param end index at which to end copying elements from
8538 *
8539 * @returns this array after transformation
8540 */
8541export function copyWithin(self: float[], target: int, start: int, end: int): float[] {
8542    target = normalizeIndex(target, self.length)
8543    start = normalizeIndex(start, self.length)
8544    end = normalizeIndex(end, self.length)
8545
8546    if (end <= start) {
8547        return self;
8548    }
8549
8550    if (target <= start) {
8551        while (start < end) {
8552            const read = self[start++];
8553            self[target++] = read;
8554        }
8555    } else {
8556        let len = end - start;
8557        if (target + len > self.length) {
8558            len = self.length - target
8559        }
8560        for (let i = 0; i < len; i++) {
8561            const read = self[start + len - 1 - i];
8562            self[target + len - 1 - i] = read;
8563        }
8564    }
8565
8566    return self;
8567}
8568
8569/**
8570 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8571 *
8572 * @param target index at which to copy the sequence
8573 *
8574 * @param start index at which to start copying elements from
8575 *
8576 * @returns this array after transformation
8577 */
8578export function copyWithin(self: float[], target: int, start: int): float[] {
8579    copyWithin(self, target, start, self.length);
8580    return self;
8581}
8582
8583/**
8584 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
8585 *
8586 * @param target index at which to copy the sequence
8587 *
8588 * @returns this array after transformation
8589 */
8590export function copyWithin(self: float[], target: int): float[] {
8591    copyWithin(self, target, 0, self.length);
8592    return self;
8593}
8594
8595/**
8596 * Changes all elements in the Array to a static value, from a start index to an end index
8597 *
8598 * @param value to fill the array with
8599 *
8600 * @param start index at which to start filling
8601 *
8602 * @param end index at which to end filling, but not including
8603 *
8604 * @returns this array after transformation
8605 */
8606export function fill(self: float[], value: float, start?: Number, end?: Number): float[] {
8607    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
8608    return self;
8609}
8610
8611/**
8612 * Changes all elements in the Array to a static value, from a start index to an end index
8613 *
8614 * @param value to fill the array with
8615 *
8616 * @param start index at which to start filling
8617 *
8618 * @param end index at which to end filling, but not including
8619 *
8620 * @returns this array after transformation
8621 */
8622export function fill(self: float[], value: float, start: int, end: int): float[] {
8623    start = normalizeIndex(start, self.length);
8624    end = normalizeIndex(end, self.length)
8625
8626    for (let i = start; i < end; i++) {
8627        self[i] = value;
8628    }
8629
8630    return self;
8631}
8632
8633/**
8634 * Returns the value of the first element in the array where predicate is true, and undefined
8635 * otherwise.
8636 *
8637 * @param predicate find calls predicate once for each element of the array, in ascending
8638 * order, until it finds one where predicate returns true. If such an element is found, find
8639 * immediately returns that element value. Otherwise, find returns undefined.
8640 *
8641 * @returns the value of the first element in the array or undefined
8642 */
8643export function find(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): Float | undefined {
8644    const res = findIndex(self, predicate)
8645    if (res == -1) {
8646        return undefined
8647    }
8648    return self[res as int];
8649}
8650
8651/**
8652 * Returns the index of the first element in the array where predicate is true, and -1
8653 * otherwise.
8654 *
8655 * @param predicate find calls predicate once for each element of the array, in ascending
8656 * order, until it finds one where predicate returns true. If such an element is found,
8657 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
8658 *
8659 * @returns found element index or -1 otherwise
8660 */
8661export function findIndex(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): number {
8662    for (let i = 0; i < self.length; i++) {
8663        if (predicate(self[i], i as number, self)) {
8664            return i;
8665        }
8666    }
8667    return -1;
8668}
8669
8670/**
8671 * Iterates the array in reverse order and returns the value of the first element
8672 * that satisfies the provided testing function
8673 *
8674 * @param predicate testing function
8675 *
8676 * @returns found element or undefined otherwise
8677 */
8678export function findLast(self: float[], predicate: (elem: float, index: number, array: float[]) => boolean): Float | undefined {
8679    for (let i = self.length - 1; i >= 0; i--) {
8680        const val = self[i];
8681        if (predicate(val, i as number, self)) {
8682            return val;
8683        }
8684    }
8685    return undefined;
8686}
8687
8688/**
8689 * Determines whether all the members of an array satisfy the specified test.
8690 *
8691 * @param predicate A function that accepts up to three arguments. The every method calls
8692 * the predicate function for each element in the array until the predicate returns a value
8693 * which is coercible to the Boolean value false, or until the end of the array.
8694 *
8695 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
8696 */
8697export function every(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): boolean {
8698    for (let i = 0; i < self.length; i++) {
8699        if (!predicate(self[i], i as number, self)) {
8700            return false
8701        }
8702    }
8703    return true;
8704}
8705
8706/**
8707 * Determines whether the specified callback function returns true for any element of an array.
8708 *
8709 * @param predicate A function that accepts up to three arguments. The some method calls
8710 * the predicate function for each element in the array until the predicate returns a value
8711 * which is coercible to the Boolean value true, or until the end of the array.
8712 *
8713 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
8714 */
8715export function some(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): boolean {
8716    for (let i = 0; i < self.length; i++) {
8717        if (predicate(self[i], i as number, self)) {
8718            return true
8719        }
8720    }
8721    return false
8722}
8723
8724/**
8725 * Returns the elements of an array that meet the condition specified in a callback function.
8726 *
8727 * @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.
8728 *
8729 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
8730 */
8731export function filter(self: float[], predicate: (value: float, index: number, array: float[]) => boolean): float[] {
8732    return filter(self, (value: float, index: number): boolean => predicate(value, index, self));
8733}
8734
8735/**
8736 * Iterates the array in reverse order and returns the index of
8737 * the first element that satisfies the provided testing function.
8738 * If no elements satisfy the testing function, -1 is returned.
8739 *
8740 * @param predicate testing function
8741 *
8742 * @returns index of first element satisfying to predicate, -1 if no such element
8743 */
8744export function findLastIndex(self: float[], predicate: (element: float, index: number, array: float[]) => boolean): number {
8745    for (let i = self.length - 1; i >= 0; i--) {
8746        if (predicate(self[i], i as number, self)) {
8747            return i
8748        }
8749    }
8750    return -1
8751}
8752
8753/**
8754 * 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.
8755 *
8756 * @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.
8757 *
8758 * @returns a result after applying callbackfn over all elements of the Array
8759 */
8760export function reduce(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number, array: float[]) => float): float {
8761    if (self.length == 0) {
8762        throw new TypeError("Reduce of empty array with no initial value")
8763    }
8764    let acc: float = self[0];
8765    for (let i = 1; i < self.length; i++) {
8766        acc = callbackfn(acc, self[i], i as number, self)
8767    }
8768    return acc
8769}
8770
8771/**
8772 * 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.
8773 *
8774 * @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.
8775 *
8776 * @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.
8777 *
8778 * @returns a result after applying callbackfn over all elements of the Array
8779 */
8780export function reduce<U = float>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number, array: float[]) => U, initialValue: U): U {
8781    let acc = initialValue
8782    for (let i = 0; i < self.length; i++) {
8783        acc = callbackfn(acc, self[i], i as number, self)
8784    }
8785    return acc
8786}
8787
8788/**
8789 * 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.
8790 *
8791 * @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.
8792 *
8793 * @returns a result after applying callbackfn over all elements of the Array
8794 */
8795export function reduceRight(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number, array: float[]) => float): float {
8796    if (self.length == 0) {
8797        throw new TypeError("Reduce of empty array with no initial value")
8798    }
8799    let acc: float = self[self.length - 1];
8800    for (let i = self.length - 2; i >= 0; i--) {
8801        acc = callbackfn(acc, self[i], i as number, self)
8802    }
8803    return acc
8804}
8805
8806/**
8807 * 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.
8808 *
8809 * @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.
8810 *
8811 * @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.
8812 *
8813 * @returns a result after applying callbackfn over all elements of the Array
8814 */
8815export function reduceRight<U>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number, array: float[]) => U, initialValue: U): U {
8816    let acc = initialValue
8817    for (let i = self.length - 1; i >= 0; i--) {
8818        acc = callbackfn(acc, self[i], i as number, self)
8819    }
8820    return acc
8821}
8822
8823/**
8824 * Performs the specified action for each element in an array.
8825 *
8826 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
8827 */
8828export function forEach(self: float[], callbackfn: (value: float, index: number, array: float[]) => void): void {
8829    const len0 = self.length;
8830    for (let i = 0; i < len0; i++) {
8831        callbackfn(self[i], i as number, self)
8832    }
8833}
8834
8835/**
8836 * Returns the value of the first element in the array where predicate is true, and undefined
8837 * otherwise.
8838 *
8839 * @param predicate find calls predicate once for each element of the array, in ascending
8840 * order, until it finds one where predicate returns true. If such an element is found, find
8841 * immediately returns that element value. Otherwise, find returns undefined.
8842 *
8843 * @returns the value of the first element in the array or undefined
8844 */
8845export function find(self: float[], predicate: (value: float, index: number) => boolean): Float | undefined {
8846    const res = findIndex(self, predicate)
8847    if (res == -1) {
8848        return undefined
8849    }
8850    return self[res as int];
8851}
8852
8853/**
8854 * Returns the index of the first element in the array where predicate is true, and -1
8855 * otherwise.
8856 *
8857 * @param predicate find calls predicate once for each element of the array, in ascending
8858 * order, until it finds one where predicate returns true. If such an element is found,
8859 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
8860 *
8861 * @returns found element index or -1 otherwise
8862 */
8863export function findIndex(self: float[], predicate: (value: float, index: number) => boolean): number {
8864    for (let i = 0; i < self.length; i++) {
8865        if (predicate(self[i], i as number)) {
8866            return i;
8867        }
8868    }
8869    return -1;
8870}
8871
8872/**
8873 * Iterates the array in reverse order and returns the value of the first element
8874 * that satisfies the provided testing function
8875 *
8876 * @param predicate testing function
8877 *
8878 * @returns found element or undefined otherwise
8879 */
8880export function findLast(self: float[], predicate: (elem: float, index: number) => boolean): Float | undefined {
8881    for (let i = self.length - 1; i >= 0; i--) {
8882        const val = self[i];
8883        if (predicate(val, i as number)) {
8884            return val;
8885        }
8886    }
8887    return undefined;
8888}
8889
8890/**
8891 * Determines whether all the members of an array satisfy the specified test.
8892 *
8893 * @param predicate A function that accepts up to three arguments. The every method calls
8894 * the predicate function for each element in the array until the predicate returns a value
8895 * which is coercible to the Boolean value false, or until the end of the array.
8896 *
8897 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
8898 */
8899export function every(self: float[], predicate: (value: float, index: number) => boolean): boolean {
8900    for (let i = 0; i < self.length; i++) {
8901        if (!predicate(self[i], i as number)) {
8902            return false
8903        }
8904    }
8905    return true;
8906}
8907
8908/**
8909 * Determines whether the specified callback function returns true for any element of an array.
8910 *
8911 * @param predicate A function that accepts up to three arguments. The some method calls
8912 * the predicate function for each element in the array until the predicate returns a value
8913 * which is coercible to the Boolean value true, or until the end of the array.
8914 *
8915 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
8916 */
8917export function some(self: float[], predicate: (value: float, index: number) => boolean): boolean {
8918    for (let i = 0; i < self.length; i++) {
8919        if (predicate(self[i], i as number)) {
8920            return true
8921        }
8922    }
8923    return false
8924}
8925
8926/**
8927 * Iterates the array in reverse order and returns the index of
8928 * the first element that satisfies the provided testing function.
8929 * If no elements satisfy the testing function, -1 is returned.
8930 *
8931 * @param predicate testing function
8932 *
8933 * @returns index of first element satisfying to predicate, -1 if no such element
8934 */
8935export function findLastIndex(self: float[], predicate: (element: float, index: number) => boolean): number {
8936    for (let i = self.length - 1; i >= 0; i--) {
8937        if (predicate(self[i], i as number)) {
8938            return i
8939        }
8940    }
8941    return -1
8942}
8943
8944/**
8945 * 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.
8946 *
8947 * @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.
8948 *
8949 * @returns a result after applying callbackfn over all elements of the Array
8950 */
8951export function reduce(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number) => float): float {
8952    if (self.length == 0) {
8953        throw new TypeError("Reduce of empty array with no initial value")
8954    }
8955    let acc: float = self[0];
8956    for (let i = 1; i < self.length; i++) {
8957        acc = callbackfn(acc, self[i], i as number)
8958    }
8959    return acc
8960}
8961
8962/**
8963 * 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.
8964 *
8965 * @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.
8966 *
8967 * @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.
8968 *
8969 * @returns a result after applying callbackfn over all elements of the Array
8970 */
8971export function reduce<U = float>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number) => U, initialValue: U): U {
8972    let acc = initialValue
8973    for (let i = 0; i < self.length; i++) {
8974        acc = callbackfn(acc, self[i], i as number)
8975    }
8976    return acc
8977}
8978
8979/**
8980 * 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.
8981 *
8982 * @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.
8983 *
8984 * @returns a result after applying callbackfn over all elements of the Array
8985 */
8986export function reduceRight(self: float[], callbackfn: (previousValue: float, currentValue: float, index: number) => float): float {
8987    if (self.length == 0) {
8988        throw new TypeError("Reduce of empty array with no initial value")
8989    }
8990    let acc: float = self[self.length - 1];
8991    for (let i = self.length - 2; i >= 0; i--) {
8992        acc = callbackfn(acc, self[i], i as number)
8993    }
8994    return acc
8995}
8996
8997/**
8998 * 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.
8999 *
9000 * @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.
9001 *
9002 * @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.
9003 *
9004 * @returns a result after applying callbackfn over all elements of the Array
9005 */
9006export function reduceRight<U>(self: float[], callbackfn: (previousValue: U, currentValue: float, index: number) => U, initialValue: U): U {
9007    let acc = initialValue
9008    for (let i = self.length - 1; i >= 0; i--) {
9009        acc = callbackfn(acc, self[i], i as number)
9010    }
9011    return acc
9012}
9013
9014/**
9015 * Performs the specified action for each element in an array.
9016 *
9017 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
9018 */
9019export function forEach(self: float[], callbackfn: (value: float, index: number) => void): void {
9020    const len0 = self.length;
9021    for (let i = 0; i < len0; i++) {
9022        callbackfn(self[i], i as number)
9023    }
9024}
9025
9026/**
9027 * Returns the value of the first element in the array where predicate is true, and undefined
9028 * otherwise.
9029 *
9030 * @param predicate find calls predicate once for each element of the array, in ascending
9031 * order, until it finds one where predicate returns true. If such an element is found, find
9032 * immediately returns that element value. Otherwise, find returns undefined.
9033 *
9034 * @returns the value of the first element in the array or undefined
9035 */
9036export function find(self: float[], predicate: (value: float) => boolean): Float | undefined {
9037    const res = findIndex(self, predicate)
9038    if (res == -1) {
9039        return undefined
9040    }
9041    return self[res as int];
9042}
9043
9044/**
9045 * Returns the index of the first element in the array where predicate is true, and -1
9046 * otherwise.
9047 *
9048 * @param predicate find calls predicate once for each element of the array, in ascending
9049 * order, until it finds one where predicate returns true. If such an element is found,
9050 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
9051 *
9052 * @returns found element index or -1 otherwise
9053 */
9054export function findIndex(self: float[], predicate: (value: float) => boolean): number {
9055    for (let i = 0; i < self.length; i++) {
9056        if (predicate(self[i])) {
9057            return i;
9058        }
9059    }
9060    return -1;
9061}
9062
9063/**
9064 * Iterates the array in reverse order and returns the value of the first element
9065 * that satisfies the provided testing function
9066 *
9067 * @param predicate testing function
9068 *
9069 * @returns found element or undefined otherwise
9070 */
9071export function findLast(self: float[], predicate: (elem: float) => boolean): Float | undefined {
9072    for (let i = self.length - 1; i >= 0; i--) {
9073        const val = self[i];
9074        if (predicate(val)) {
9075            return val;
9076        }
9077    }
9078    return undefined;
9079}
9080
9081/**
9082 * Determines whether all the members of an array satisfy the specified test.
9083 *
9084 * @param predicate A function that accepts up to three arguments. The every method calls
9085 * the predicate function for each element in the array until the predicate returns a value
9086 * which is coercible to the Boolean value false, or until the end of the array.
9087 *
9088 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
9089 */
9090export function every(self: float[], predicate: (value: float) => boolean): boolean {
9091    for (let i = 0; i < self.length; i++) {
9092        if (!predicate(self[i])) {
9093            return false
9094        }
9095    }
9096    return true;
9097}
9098
9099/**
9100 * Determines whether the specified callback function returns true for any element of an array.
9101 *
9102 * @param predicate A function that accepts up to three arguments. The some method calls
9103 * the predicate function for each element in the array until the predicate returns a value
9104 * which is coercible to the Boolean value true, or until the end of the array.
9105 *
9106 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
9107 */
9108export function some(self: float[], predicate: (value: float) => boolean): boolean {
9109    for (let i = 0; i < self.length; i++) {
9110        if (predicate(self[i])) {
9111            return true
9112        }
9113    }
9114    return false
9115}
9116
9117/**
9118 * Returns the elements of an array that meet the condition specified in a callback function.
9119 *
9120 * @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.
9121 *
9122 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
9123 */
9124export function filter(self: float[], predicate: (value: float) => boolean): float[] {
9125    return filter(self, (value: float, index: number): boolean => predicate(value));
9126}
9127
9128/**
9129 * Iterates the array in reverse order and returns the index of
9130 * the first element that satisfies the provided testing function.
9131 * If no elements satisfy the testing function, -1 is returned.
9132 *
9133 * @param predicate testing function
9134 *
9135 * @returns index of first element satisfying to predicate, -1 if no such element
9136 */
9137export function findLastIndex(self: float[], predicate: (element: float) => boolean): number {
9138    for (let i = self.length - 1; i >= 0; i--) {
9139        if (predicate(self[i])) {
9140            return i
9141        }
9142    }
9143    return -1
9144}
9145
9146/**
9147 * 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.
9148 *
9149 * @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.
9150 *
9151 * @returns a result after applying callbackfn over all elements of the Array
9152 */
9153export function reduce(self: float[], callbackfn: (previousValue: float, currentValue: float) => float): float {
9154    if (self.length == 0) {
9155        throw new TypeError("Reduce of empty array with no initial value")
9156    }
9157    let acc: float = self[0];
9158    for (let i = 1; i < self.length; i++) {
9159        acc = callbackfn(acc, self[i])
9160    }
9161    return acc
9162}
9163
9164/**
9165 * 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.
9166 *
9167 * @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.
9168 *
9169 * @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.
9170 *
9171 * @returns a result after applying callbackfn over all elements of the Array
9172 */
9173export function reduce<U = float>(self: float[], callbackfn: (previousValue: U, currentValue: float) => U, initialValue: U): U {
9174    let acc = initialValue
9175    for (let i = 0; i < self.length; i++) {
9176        acc = callbackfn(acc, self[i])
9177    }
9178    return acc
9179}
9180
9181/**
9182 * 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.
9183 *
9184 * @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.
9185 *
9186 * @returns a result after applying callbackfn over all elements of the Array
9187 */
9188export function reduceRight(self: float[], callbackfn: (previousValue: float, currentValue: float) => float): float {
9189    if (self.length == 0) {
9190        throw new TypeError("Reduce of empty array with no initial value")
9191    }
9192    let acc: float = self[self.length - 1];
9193    for (let i = self.length - 2; i >= 0; i--) {
9194        acc = callbackfn(acc, self[i])
9195    }
9196    return acc
9197}
9198
9199/**
9200 * 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.
9201 *
9202 * @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.
9203 *
9204 * @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.
9205 *
9206 * @returns a result after applying callbackfn over all elements of the Array
9207 */
9208export function reduceRight<U>(self: float[], callbackfn: (previousValue: U, currentValue: float) => U, initialValue: U): U {
9209    let acc = initialValue
9210    for (let i = self.length - 1; i >= 0; i--) {
9211        acc = callbackfn(acc, self[i])
9212    }
9213    return acc
9214}
9215
9216/**
9217 * Performs the specified action for each element in an array.
9218 *
9219 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
9220 */
9221export function forEach(self: float[], callbackfn: (value: float) => void): void {
9222    const len0 = self.length;
9223    for (let i = 0; i < len0; i++) {
9224        callbackfn(self[i])
9225    }
9226}
9227
9228/**
9229 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
9230 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
9231 *
9232 * @param start zero-based index at which to start extraction
9233 *
9234 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
9235 *
9236 * @returns `Array` instance, constructed from extracted elements of `this` instance.
9237 */
9238export function slice(self: float[], start?: Number, end?: Number): float[] {
9239    const len: int = self.length;
9240    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
9241}
9242
9243/**
9244 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
9245 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
9246 *
9247 * @param start zero-based index at which to start extraction
9248 *
9249 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
9250 *
9251 * @returns `Array` instance, constructed from extracted elements of `this` instance.
9252 */
9253export function slice(self: float[], start: int, end: int): float[] {
9254    const len: int = self.length;
9255    const relStart = normalizeIndex(start, len)
9256    const relEnd = normalizeIndex(end, len)
9257
9258    let count = relEnd - relStart;
9259    if (count < 0) {
9260        count = 0;
9261    }
9262    let res = new float[count]
9263    for (let i = 0; i < count; i++) {
9264        res[i] = self[relStart + i];
9265    }
9266
9267    return res
9268}
9269
9270/**
9271 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
9272 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
9273 *
9274 * @param start zero-based index at which to start extraction
9275 *
9276 * @returns `Array` instance, constructed from extracted elements of `this` instance.
9277 */
9278export function slice(self: float[], start: int): float[] {
9279    return slice(self, start, Int.MAX_VALUE as int);
9280}
9281
9282/**
9283 * Returns the last index at which a given element can be found in the array,
9284 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
9285 *
9286 * @param element element to locate in the array.
9287 * @param fromIndex zero-based index at which to start searching backwards.
9288 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
9289 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
9290 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
9291 *
9292 * @returns The last index of the element in the array; -1 if not found.
9293 */
9294export function lastIndexOf(self: float[], element: float, fromIndex: int): int {
9295    if (self.length == 0) {
9296        return -1;
9297    }
9298    let n = fromIndex;
9299    let k: int;
9300    if (n >= 0) {
9301        k = min(self.length - 1, n);
9302    } else {
9303        k = self.length + n;
9304    }
9305
9306    while (k >= 0) {
9307        if (__runtimeEquals(self[k], element)) {
9308            return k;
9309        }
9310        k--;
9311    }
9312    return -1;
9313}
9314
9315/**
9316 * Returns the last index at which a given element can be found in the array,
9317 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
9318 *
9319 * @param element element to locate in the array.
9320 * @param fromIndex zero-based index at which to start searching backwards.
9321 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
9322 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
9323 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
9324 *
9325 * @returns The last index of the element in the array; -1 if not found.
9326 */
9327export function lastIndexOf(self: float[], element: float, fromIndex?: Number): number {
9328    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
9329}
9330
9331/**
9332 * Creates and returns a new string by concatenating all of the elements in an `Array`,
9333 * separated by a specified separator string.
9334 * If the array has only one item, then that item will be returned without using the separator.
9335 *
9336 * @param sep specifies a separator
9337 *
9338 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
9339 */
9340export function join(self: float[], sep?: String): string {
9341    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
9342    let sb = new StringBuilder()
9343    for (let i: int = 0; i < self.length; i++) {
9344        const tmp = self[i]
9345        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
9346        if (i != 0) {
9347            sb.append(sepReal);
9348        }
9349        sb.append(tmp)
9350    }
9351
9352    return sb.toString();
9353}
9354
9355/**
9356 * Returns a string representing the specified array and its elements.
9357 *
9358 * @returns string representation
9359 */
9360export function toString(self: float[], ): string {
9361    return join(self, ",");
9362}
9363
9364/**
9365 * Returns a locale string representing the specified array and its elements.
9366 *
9367 * @param locales
9368 *
9369 * @param options
9370 *
9371 * @returns string representation
9372 */
9373export function toLocaleString(self: float[], locales: Object, options: Object): string {
9374    throw new Error("Array.toLocaleString: not implemented")
9375}
9376
9377/**
9378 * Returns a locale string representing the specified array and its elements.
9379 *
9380 * @param options
9381 *
9382 * @returns string representation
9383 */
9384export function toLocaleString(self: float[], locales: Object): string {
9385    return toLocaleString(self, new Object(), new Object())
9386}
9387
9388/**
9389 * Returns a locale string representing the specified array and its elements.
9390 *
9391 * @returns string representation
9392 */
9393export function toLocaleString(self: float[], ): string {
9394    const sb = new StringBuilder()
9395    const len = self.length;
9396    for (let i = 0; i < len; i++) {
9397        if (i != 0) {
9398            sb.append(",")
9399        }
9400        let x = self[i] as NullishType;
9401        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
9402            sb.append(x!.toLocaleString())
9403        }
9404    }
9405    return sb.toString()
9406}
9407
9408/**
9409 * Copying version of the splice() method.
9410 *
9411 * @param start index
9412 *
9413 * @param delete number of items after start index
9414 *
9415 * @returns a new Array with some elements removed and/or replaced at a given index.
9416 */
9417export function toSpliced(self: float[], start?: Number, delete?: Number): float[] {
9418    const len = self.length;
9419    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
9420}
9421
9422/**
9423 * Copying version of the splice() method.
9424 *
9425 * @param start index
9426 *
9427 * @param delete number of items after start index
9428 *
9429 * @returns a new Array with some elements removed and/or replaced at a given index.
9430 */
9431export function toSpliced(self: float[], start: number, delete: number, ...items: float[]): float[] {
9432    const len = self.length;
9433    return toSpliced(self, start as int, delete as int, ...items)
9434}
9435
9436/**
9437 * Copying version of the splice() method.
9438 *
9439 * @param start index
9440 *
9441 * @param delete number of items after start index
9442 *
9443 * @returns a new Array with some elements removed and/or replaced at a given index.
9444 */
9445export function toSpliced(self: float[], start: int, delete: int, ...items: float[]): float[] {
9446    const len = self.length;
9447    start = normalizeIndex(start, len);
9448    if (delete < 0) {
9449        delete = 0;
9450    } else if (delete > len) {
9451        delete = len;
9452    }
9453    if (start > len - delete) {
9454        delete = len - start
9455    }
9456    const res = new float[len - delete + items.length];
9457    for (let i = 0; i < start; i++) {
9458        res[i] = self[i]
9459    }
9460    for (let i = 0; i < items.length; i++) {
9461        res[start + i] = items[i]
9462    }
9463    for (let i = start + delete; i < len; i++) {
9464        res[i - delete + items.length] = self[i]
9465    }
9466    return res;
9467}
9468
9469/**
9470 * Copying version of the splice() method.
9471 *
9472 * @param start index
9473 *
9474 * @returns a new Array with some elements removed and/or replaced at a given index.
9475 */
9476export function toSpliced(self: float[], start: int): float[] {
9477    return toSpliced(self, start, self.length)
9478}
9479
9480/**
9481 * Checks whether an Array includes a certain value among its entries,
9482 * returning true or false as appropriate.
9483 *
9484 * @param val value to search
9485 *
9486 * @param fromIndex start index
9487 *
9488 * @returns true if val is in Array
9489 */
9490export function includes(self: float[], val: float, fromIndex?: Number): boolean {
9491    const len = self.length;
9492    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
9493    if (isNaN(val)) {
9494        for (let i = fi; i < len; i++) {
9495            if (isNaN(self[i])) {
9496                return true;
9497            }
9498        }
9499        return false;
9500    }
9501    for (let i = fi; i < len; i++) {
9502        if (val == self[i]) {
9503            return true;
9504        }
9505    }
9506    return false;
9507}
9508
9509/**
9510 * Returns the first index at which a given element
9511 * can be found in the array, or -1 if it is not present.
9512 *
9513 * @param val value to search
9514 *
9515 * @param fromIndex index to search from
9516 *
9517 * @returns index of val, -1 otherwise
9518 */
9519export function indexOf(self: float[], val: float, fromIndex: int): int {
9520    fromIndex = normalizeIndex(fromIndex, self.length)
9521    for (let i = fromIndex; i < self.length; i++) {
9522        if (__runtimeEquals(val, self[i])) {
9523            return i
9524        }
9525    }
9526    return -1
9527}
9528
9529/**
9530 * Returns the first index at which a given element
9531 * can be found in the array, or -1 if it is not present.
9532 *
9533 * @param val value to search
9534 *
9535 * @param fromIndex index to search from
9536 *
9537 * @returns index of val, -1 otherwise
9538 */
9539export function indexOf(self: float[], val: float, fromIndex?: Number): number {
9540    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
9541}
9542
9543/**
9544 * Copying version of the sort() method.
9545 * It returns a new array with the elements sorted in ascending order.
9546 *
9547 * @returns sorted copy of hte current instance using default comparator
9548 */
9549export function toSorted(self: float[], ): float[] {
9550    let arr = cloneArray(self);
9551    sort(arr, )
9552    return arr
9553}
9554
9555/**
9556 * Copying version of the sort() method.
9557 * It returns a new array with the elements sorted in ascending order.
9558 *
9559 * @param comparator function to compare to elements of the Array
9560 *
9561 * @returns sorted copy of the current instance comparator
9562 */
9563export function toSorted(self: float[], comparator: (a: float, b: float) => number): float[] {
9564    let arr = cloneArray(self);
9565    sort(arr, comparator)
9566    return arr
9567}
9568
9569/**
9570 * Modifies `this` instance of `Array` class and populates
9571 * it with same elements ordered towards the direction opposite to that previously stated.
9572 *
9573 * @note Mutating method
9574 */
9575export function reverse(self: float[], ): float[] {
9576    for (let i = 0; i < self.length / 2; i++) {
9577        const tmp = self[i];
9578        const idx_r = self.length - 1 - i;
9579        const val_r = self[idx_r];
9580        self[i] = val_r;
9581        self[idx_r] = tmp;
9582    }
9583    return self;
9584}
9585
9586/**
9587 * Copying version of the reverse() method.
9588 * It returns a new array with the elements in reversed order.
9589 *
9590 * @returns reversed copy of the current Array
9591 */
9592export function toReversed(self: float[], ): float[] {
9593    let arr = new float[self.length]
9594    for (let i = 0; i < self.length; i++) {
9595        arr[self.length - 1 - i] = self[i]
9596    }
9597    return arr
9598}
9599
9600/**
9601 * Copying version of using the bracket notation to change the value of a given index.
9602 * It returns a new Array with the element at the given index replaced with the given value.
9603 *
9604 * @param index to replace
9605 *
9606 * @param value new value
9607 *
9608 * @returns a new Array with the element at the given index replaced with the given value
9609 */
9610export function with(self: float[], index: number, value: float): float[] {
9611    return with(self, index as int, value)
9612}
9613
9614/**
9615 * Copying version of using the bracket notation to change the value of a given index.
9616 * It returns a new Array with the element at the given index replaced with the given value.
9617 *
9618 * @param index to replace
9619 *
9620 * @param value new value
9621 *
9622 * @returns a new Array with the element at the given index replaced with the given value
9623 */
9624export function with(self: float[], index: int, value: float): float[] {
9625    if (index < 0) {
9626        index += self.length;
9627    }
9628    if (index >= self.length) {
9629        throw new RangeError("Invalid index")
9630    }
9631    let arr = cloneArray(self);
9632    arr[index] = value;
9633    return arr
9634}
9635
9636/**
9637 * Returns an iterator over all values
9638 */
9639export function values(self: float[], ): IterableIterator<float> {
9640    return new ArrayValuesIterator_float(self);
9641}
9642
9643/**
9644 * Returns an iterable of key, value pairs for every entry in the array
9645 */
9646export function entries(self: float[], ): IterableIterator<[number, float]> {
9647    return new ArrayEntriesIterator_float(self);
9648}
9649
9650/**
9651 * Determines whether all the members of an array satisfy the specified test.
9652 *
9653 * @param predicate A function that accepts up to three arguments. The every method calls
9654 * the predicate function for each element in the array until the predicate returns a value
9655 * which is coercible to the Boolean value false, or until the end of the array.
9656 *
9657 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
9658 */
9659export function every(self: float[], predicate: () => boolean): boolean {
9660    for (let i = 0; i < self.length; i++) {
9661        if (!predicate()) {
9662            return false
9663        }
9664    }
9665    return true
9666}
9667
9668/**
9669 * Returns the elements of an array that meet the condition specified in a callback function.
9670 *
9671 * @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.
9672 *
9673 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
9674 */
9675export function filter(self: float[], predicate: () => boolean): float[] {
9676    return filter(self, (value: float, index: number): boolean => predicate());
9677}
9678
9679/**
9680 * Returns the value of the first element in the array where predicate is true, and undefined
9681 * otherwise.
9682 *
9683 * @param predicate find calls predicate once for each element of the array, in ascending
9684 * order, until it finds one where predicate returns true. If such an element is found, find
9685 * immediately returns that element value. Otherwise, find returns undefined.
9686 *
9687 * @returns the value of the first element in the array or undefined
9688 */
9689export function find(self: float[], predicate: () => boolean): Float | undefined {
9690    const res = findIndex(self, predicate)
9691    if (res == -1) {
9692        return undefined
9693    }
9694    return self[res as int];
9695}
9696
9697/**
9698 * Returns the index of the first element in the array where predicate is true, and -1
9699 * otherwise.
9700 *
9701 * @param predicate find calls predicate once for each element of the array, in ascending
9702 * order, until it finds one where predicate returns true. If such an element is found,
9703 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
9704 *
9705 * @returns found element index or -1 otherwise
9706 */
9707export function findIndex(self: float[], predicate: () => boolean): number {
9708    for (let i = 0; i < self.length; i++) {
9709        if (predicate()) {
9710            return i;
9711        }
9712    }
9713    return -1;
9714}
9715
9716/**
9717 * Performs the specified action for each element in an array.
9718 *
9719 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
9720 */
9721export function forEach(self: float[], callbackfn: () => void): void {
9722    const len0 = self.length;
9723    for (let i = 0; i < len0; i++) {
9724        callbackfn()
9725    }
9726}
9727
9728/**
9729 * 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.
9730 *
9731 * @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.
9732 *
9733 * @returns a result after applying callbackfn over all elements of the Array
9734 */
9735export function reduce(self: float[], callbackfn: (previousValue: float) => float): float {
9736    if (self.length == 0) {
9737        throw new TypeError("Reduce of empty array with no initial value")
9738    }
9739    let acc: float = self[0];
9740    for (let i = 1; i < self.length; i++) {
9741        acc = callbackfn(acc)
9742    }
9743    return acc
9744}
9745
9746/**
9747 * 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.
9748 *
9749 * @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.
9750 *
9751 * @returns a result after applying callbackfn over all elements of the Array
9752 */
9753export function reduce(self: float[], callbackfn: () => float): float {
9754    if (self.length == 0) {
9755        throw new TypeError("Reduce of empty array with no initial value")
9756    }
9757    let acc: float = self[0];
9758    for (let i = 1; i < self.length; i++) {
9759        acc = callbackfn()
9760    }
9761    return acc
9762}
9763
9764/**
9765 * 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.
9766 *
9767 * @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.
9768 *
9769 * @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.
9770 *
9771 * @returns a result after applying callbackfn over all elements of the Array
9772 */
9773export function reduce<U = float>(self: float[], callbackfn: (previousValue: U) => U, initialValue: U): U {
9774    let acc = initialValue
9775    for (let i = 0; i < self.length; i++) {
9776        acc = callbackfn(acc)
9777    }
9778    return acc
9779}
9780
9781/**
9782 * 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.
9783 *
9784 * @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.
9785 *
9786 * @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.
9787 *
9788 * @returns a result after applying callbackfn over all elements of the Array
9789 */
9790export function reduce<U = float>(self: float[], callbackfn: () => U, initialValue: U): U {
9791    let acc = initialValue
9792    for (let i = 0; i < self.length; i++) {
9793        acc = callbackfn()
9794    }
9795    return acc
9796}
9797
9798/**
9799 * 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.
9800 *
9801 * @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.
9802 *
9803 * @returns a result after applying callbackfn over all elements of the Array
9804 */
9805export function reduceRight(self: float[], callbackfn: (previousValue: float) => float): float {
9806    if (self.length == 0) {
9807        throw new TypeError("Reduce of empty array with no initial value")
9808    }
9809    let acc: float = self[self.length - 1];
9810    for (let i = self.length - 2; i >= 0; i--) {
9811        acc = callbackfn(acc)
9812    }
9813    return acc
9814}
9815
9816/**
9817 * 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.
9818 *
9819 * @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.
9820 *
9821 * @returns a result after applying callbackfn over all elements of the Array
9822 */
9823export function reduceRight(self: float[], callbackfn: () => float): float {
9824    if (self.length == 0) {
9825        throw new TypeError("Reduce of empty array with no initial value")
9826    }
9827    let acc: float = self[self.length - 1];
9828    for (let i = self.length - 2; i >= 0; i--) {
9829        acc = callbackfn()
9830    }
9831    return acc
9832}
9833
9834/**
9835 * 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.
9836 *
9837 * @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.
9838 *
9839 * @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.
9840 *
9841 * @returns a result after applying callbackfn over all elements of the Array
9842 */
9843export function reduceRight<U>(self: float[], callbackfn: (previousValue: U) => U, initialValue: U): U {
9844    let acc = initialValue
9845    for (let i = self.length - 1; i >= 0; i--) {
9846        acc = callbackfn(acc)
9847    }
9848    return acc
9849}
9850
9851/**
9852 * 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.
9853 *
9854 * @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.
9855 *
9856 * @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.
9857 *
9858 * @returns a result after applying callbackfn over all elements of the Array
9859 */
9860export function reduceRight<U>(self: float[], callbackfn: () => U, initialValue: U): U {
9861    let acc = initialValue
9862    for (let i = self.length - 1; i >= 0; i--) {
9863        acc = callbackfn()
9864    }
9865    return acc
9866}
9867
9868/**
9869 * Determines whether the specified callback function returns true for any element of an array.
9870 *
9871 * @param predicate A function that accepts up to three arguments. The some method calls
9872 * the predicate function for each element in the array until the predicate returns a value
9873 * which is coercible to the Boolean value true, or until the end of the array.
9874 *
9875 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
9876 */
9877export function some(self: float[], predicate: () => boolean): boolean {
9878    for (let i = 0; i < self.length; i++) {
9879        if (predicate()) {
9880            return true
9881        }
9882    }
9883    return false
9884}
9885
9886/**
9887 * Iterates the array in reverse order and returns the value of the first element
9888 * that satisfies the provided testing function
9889 *
9890 * @param predicate testing function
9891 *
9892 * @returns found element or undefined otherwise
9893 */
9894export function findLast(self: float[], predicate: () => boolean): Float | undefined {
9895    for (let i = self.length - 1; i >= 0; i--) {
9896        const val = self[i];
9897        if (predicate()) {
9898            return val;
9899        }
9900    }
9901    return undefined;
9902}
9903
9904/**
9905 * Iterates the array in reverse order and returns the index of
9906 * the first element that satisfies the provided testing function.
9907 * If no elements satisfy the testing function, -1 is returned.
9908 *
9909 * @param predicate testing function
9910 *
9911 * @returns index of first element satisfying to predicate, -1 if no such element
9912 */
9913export function findLastIndex(self: float[], predicate: () => boolean): number {
9914    for (let i = self.length - 1; i >= 0; i--) {
9915        if (predicate()) {
9916            return i
9917        }
9918    }
9919    return -1
9920}
9921
9922/**
9923 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
9924 *
9925 * @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.
9926 *
9927 * @returns `Array` instance, constructed from `this` and given function.
9928 */
9929export function map(self: float[], callbackfn: (value: float, index: number, array: float[]) => float): float[] {
9930    const len = self.length;
9931    let res = new float[len];
9932    for (let i = 0; i < len; i++) {
9933        res[i] = callbackfn(self[i], i as number, self);
9934    }
9935    return res;
9936}
9937
9938/**
9939 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
9940 *
9941 * @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.
9942 *
9943 * @returns `Array` instance, constructed from `this` and given function.
9944 */
9945export function map(self: float[], callbackfn: (value: float, index: number) => float): float[] {
9946    const len = self.length;
9947    let res = new float[len];
9948    for (let i = 0; i < len; i++) {
9949        res[i] = callbackfn(self[i], i as number);
9950    }
9951    return res;
9952}
9953
9954/**
9955 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
9956 *
9957 * @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.
9958 *
9959 * @returns `Array` instance, constructed from `this` and given function.
9960 */
9961export function map(self: float[], callbackfn: (value: float) => float): float[] {
9962    const len = self.length;
9963    let res = new float[len];
9964    for (let i = 0; i < len; i++) {
9965        res[i] = callbackfn(self[i]);
9966    }
9967    return res;
9968}
9969
9970/**
9971 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
9972 *
9973 * @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.
9974 *
9975 * @returns `Array` instance, constructed from `this` and given function.
9976 */
9977export function map(self: float[], callbackfn: () => float): float[] {
9978    const len = self.length;
9979    let res = new float[len];
9980    for (let i = 0; i < len; i++) {
9981        res[i] = callbackfn();
9982    }
9983    return res;
9984}
9985
9986/**
9987 * Constructs a new `Array` instance and populates it with
9988 * portion of a given array, filtered down to just the elements from the
9989 * given array that pass the test implemented by the provided function.
9990 *
9991 * @param fn test function, applied to each element of an array.
9992 *
9993 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
9994 */
9995export function filter(self: float[], fn: (v: float, k: number) => boolean): float[] {
9996    const mask = new boolean[self.length]
9997    let cnt = 0
9998
9999    for (let i: int = 0; i < self.length; i++) {
10000        const val = self[i];
10001        if (fn(val, i)) {
10002            mask[i] = true
10003            cnt++;
10004        }
10005    }
10006    const res = new float[cnt];
10007    let idx_store = 0;
10008    for (let i: int = 0; i < self.length; i++) {
10009        if (mask[i]) {
10010            res[idx_store++] = self[i]
10011        }
10012    }
10013    return res;
10014}
10015
10016export function concat(self: float[], fst: float[], ...more: float[][]): float[] {
10017    const lnMin = self.length + fst.length;
10018    let ln = lnMin;
10019    for (let i = 0; i < more.length; i++) {
10020        ln += more[i].length
10021    }
10022    const r = new float[ln];
10023    try {
10024        copyTo(self, r, 0, 0, self.length);
10025        copyTo(fst, r, self.length, 0, fst.length);
10026        let idx = lnMin;
10027        for (let i = 0; i < more.length; i++) {
10028            copyTo(more[i], r, idx, 0, more[i].length);
10029            idx += more[i].length;
10030        }
10031    } catch (e) {
10032        // impossible
10033    }
10034    return r
10035}
10036
10037/**
10038 * Reorders elements of `this` using comparator function.
10039 *
10040 * @param comparator function that defines the sort order.
10041 *
10042 * @note Mutating method
10043 */
10044export function sort(self: float[], comparator: (a: float, b: float) => number): float[] {
10045    sort_subarray(self, 0, self.length, (l: float, r: float): boolean => {
10046        return comparator(l, r ) < 0;
10047    });
10048    return self;
10049}
10050
10051/**
10052 * Reorders elements of `this` using comparator function.
10053 *
10054 * @param comparator function that defines the sort order.
10055 *
10056 * @note Mutating method
10057 */
10058export function sort(self: float[], ): float[] {
10059    sort(self, 0, self.length);
10060    return self;
10061}
10062
10063export function keys(self: float[]): IterableIterator<number> {
10064    return new BuiltinArrayKeysIterator(self.length);
10065}
10066
10067class ArrayValuesIterator_float implements IterableIterator<float> {
10068    private parent: float[]
10069    private idx: int = 0
10070
10071    constructor(parent: float[]) {
10072        this.parent = parent
10073    }
10074
10075    override next(): IteratorResult<float> {
10076        if (this.idx >= this.parent.length) {
10077            return new IteratorResult<float>()
10078        }
10079        return new IteratorResult<float>(this.parent[this.idx++])
10080    }
10081
10082    override $_iterator(): IterableIterator<float> {
10083        return this;
10084    }
10085}
10086
10087class ArrayEntriesIterator_float implements IterableIterator<[number, float]> {
10088    private parent: float[]
10089    private idx: int = 0
10090
10091    constructor(parent: float[]) {
10092        this.parent = parent
10093    }
10094
10095    override next(): IteratorResult<[number, float]> {
10096        if (this.idx >= this.parent.length) {
10097            return new IteratorResult<[number, float]>()
10098        }
10099        const i = this.idx++;
10100        const vl: [number, float] = [i as number, this.parent[i]]
10101        return new IteratorResult<[number, float]>(vl);
10102    }
10103
10104    override $_iterator(): IterableIterator<[number, float]> {
10105        return this;
10106    }
10107}
10108
10109function cloneArray(self: double[]): double[] {
10110    const ret = new double[self.length];;
10111    for (let i = 0; i < self.length; i++) {
10112        ret[i] = self[i];
10113    }
10114    return ret;
10115}
10116
10117/**
10118 * Takes an integer value and returns the item at that index,
10119 * allowing for positive and negative integers. Negative integers count back
10120 * from the last item in the array.
10121 *
10122 * @param index Zero-based index of the array element to be returned.
10123 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
10124 *
10125 * @returns The element in the array matching the given index.
10126 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
10127 */
10128export function at(self: double[], index: number): Double | undefined {
10129    return at(self, index as int)
10130}
10131
10132/**
10133 * Creates a new `Array` from this `Array` instance and given `Array` instance.
10134 *
10135 * @param other to concatenate into a new array.
10136 *
10137 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
10138 */
10139// export function concat(self: double[], ...items: (double | Concatdouble[])[]): double[] {
10140//     throw new Error("not implemented")
10141// }
10142
10143export function concat(self: double[], ...items: ConcatArray<double>[]): double[] {
10144    let totalAdd = self.length;
10145    for (let i = 0; i < items.length; i++) {
10146        totalAdd += items[i].length as int
10147    }
10148
10149    const buf = new double[totalAdd];
10150
10151    for (let i = 0; i < self.length; i++) {
10152        buf[i] = self[i];
10153    }
10154
10155    let insertTo = self.length;
10156    for (let i = 0; i < items.length; i++) {
10157        const arr = items[i]
10158        const len = arr.length as int
10159        for (let j = 0; j < len; j++) {
10160            buf[insertTo++] = arr.$_get(j)
10161        }
10162    }
10163
10164    return buf;
10165}
10166
10167/**
10168 * Takes an integer value and returns the item at that index,
10169 * allowing for positive and negative integers. Negative integers count back
10170 * from the last item in the array.
10171 *
10172 * @param index Zero-based index of the array element to be returned.
10173 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
10174 *
10175 * @returns The element in the array matching the given index.
10176 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
10177 */
10178export function at(self: double[], index: int): Double | undefined {
10179    let len = self.length;
10180    let k: int;
10181    if (index >= 0) {
10182        k = index;
10183    } else {
10184        k = len + index;
10185    }
10186
10187    if (k < 0 || k >= len) {
10188        return undefined;
10189    }
10190
10191    return self[k];
10192}
10193
10194/**
10195 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10196 *
10197 * @param target index at which to copy the sequence
10198 *
10199 * @param start index at which to start copying elements from
10200 *
10201 * @param end index at which to end copying elements from
10202 *
10203 * @returns this array after transformation
10204 */
10205export function copyWithin(self: double[], target: number, start: number, end?: Number): double[] {
10206    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
10207    return self;
10208}
10209
10210/**
10211 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10212 *
10213 * @param target index at which to copy the sequence
10214 *
10215 * @param start index at which to start copying elements from
10216 *
10217 * @param end index at which to end copying elements from
10218 *
10219 * @returns this array after transformation
10220 */
10221export function copyWithin(self: double[], target: int, start: int, end: int): double[] {
10222    target = normalizeIndex(target, self.length)
10223    start = normalizeIndex(start, self.length)
10224    end = normalizeIndex(end, self.length)
10225
10226    if (end <= start) {
10227        return self;
10228    }
10229
10230    if (target <= start) {
10231        while (start < end) {
10232            const read = self[start++];
10233            self[target++] = read;
10234        }
10235    } else {
10236        let len = end - start;
10237        if (target + len > self.length) {
10238            len = self.length - target
10239        }
10240        for (let i = 0; i < len; i++) {
10241            const read = self[start + len - 1 - i];
10242            self[target + len - 1 - i] = read;
10243        }
10244    }
10245
10246    return self;
10247}
10248
10249/**
10250 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10251 *
10252 * @param target index at which to copy the sequence
10253 *
10254 * @param start index at which to start copying elements from
10255 *
10256 * @returns this array after transformation
10257 */
10258export function copyWithin(self: double[], target: int, start: int): double[] {
10259    copyWithin(self, target, start, self.length);
10260    return self;
10261}
10262
10263/**
10264 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
10265 *
10266 * @param target index at which to copy the sequence
10267 *
10268 * @returns this array after transformation
10269 */
10270export function copyWithin(self: double[], target: int): double[] {
10271    copyWithin(self, target, 0, self.length);
10272    return self;
10273}
10274
10275/**
10276 * Changes all elements in the Array to a static value, from a start index to an end index
10277 *
10278 * @param value to fill the array with
10279 *
10280 * @param start index at which to start filling
10281 *
10282 * @param end index at which to end filling, but not including
10283 *
10284 * @returns this array after transformation
10285 */
10286export function fill(self: double[], value: double, start?: Number, end?: Number): double[] {
10287    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
10288    return self;
10289}
10290
10291/**
10292 * Changes all elements in the Array to a static value, from a start index to an end index
10293 *
10294 * @param value to fill the array with
10295 *
10296 * @param start index at which to start filling
10297 *
10298 * @param end index at which to end filling, but not including
10299 *
10300 * @returns this array after transformation
10301 */
10302export function fill(self: double[], value: double, start: int, end: int): double[] {
10303    start = normalizeIndex(start, self.length);
10304    end = normalizeIndex(end, self.length)
10305
10306    for (let i = start; i < end; i++) {
10307        self[i] = value;
10308    }
10309
10310    return self;
10311}
10312
10313/**
10314 * Returns the value of the first element in the array where predicate is true, and undefined
10315 * otherwise.
10316 *
10317 * @param predicate find calls predicate once for each element of the array, in ascending
10318 * order, until it finds one where predicate returns true. If such an element is found, find
10319 * immediately returns that element value. Otherwise, find returns undefined.
10320 *
10321 * @returns the value of the first element in the array or undefined
10322 */
10323export function find(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): Double | undefined {
10324    const res = findIndex(self, predicate)
10325    if (res == -1) {
10326        return undefined
10327    }
10328    return self[res as int];
10329}
10330
10331/**
10332 * Returns the index of the first element in the array where predicate is true, and -1
10333 * otherwise.
10334 *
10335 * @param predicate find calls predicate once for each element of the array, in ascending
10336 * order, until it finds one where predicate returns true. If such an element is found,
10337 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
10338 *
10339 * @returns found element index or -1 otherwise
10340 */
10341export function findIndex(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): number {
10342    for (let i = 0; i < self.length; i++) {
10343        if (predicate(self[i], i as number, self)) {
10344            return i;
10345        }
10346    }
10347    return -1;
10348}
10349
10350/**
10351 * Iterates the array in reverse order and returns the value of the first element
10352 * that satisfies the provided testing function
10353 *
10354 * @param predicate testing function
10355 *
10356 * @returns found element or undefined otherwise
10357 */
10358export function findLast(self: double[], predicate: (elem: double, index: number, array: double[]) => boolean): Double | undefined {
10359    for (let i = self.length - 1; i >= 0; i--) {
10360        const val = self[i];
10361        if (predicate(val, i as number, self)) {
10362            return val;
10363        }
10364    }
10365    return undefined;
10366}
10367
10368/**
10369 * Determines whether all the members of an array satisfy the specified test.
10370 *
10371 * @param predicate A function that accepts up to three arguments. The every method calls
10372 * the predicate function for each element in the array until the predicate returns a value
10373 * which is coercible to the Boolean value false, or until the end of the array.
10374 *
10375 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
10376 */
10377export function every(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): boolean {
10378    for (let i = 0; i < self.length; i++) {
10379        if (!predicate(self[i], i as number, self)) {
10380            return false
10381        }
10382    }
10383    return true;
10384}
10385
10386/**
10387 * Determines whether the specified callback function returns true for any element of an array.
10388 *
10389 * @param predicate A function that accepts up to three arguments. The some method calls
10390 * the predicate function for each element in the array until the predicate returns a value
10391 * which is coercible to the Boolean value true, or until the end of the array.
10392 *
10393 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
10394 */
10395export function some(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): boolean {
10396    for (let i = 0; i < self.length; i++) {
10397        if (predicate(self[i], i as number, self)) {
10398            return true
10399        }
10400    }
10401    return false
10402}
10403
10404/**
10405 * Returns the elements of an array that meet the condition specified in a callback function.
10406 *
10407 * @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.
10408 *
10409 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
10410 */
10411export function filter(self: double[], predicate: (value: double, index: number, array: double[]) => boolean): double[] {
10412    return filter(self, (value: double, index: number): boolean => predicate(value, index, self));
10413}
10414
10415/**
10416 * Iterates the array in reverse order and returns the index of
10417 * the first element that satisfies the provided testing function.
10418 * If no elements satisfy the testing function, -1 is returned.
10419 *
10420 * @param predicate testing function
10421 *
10422 * @returns index of first element satisfying to predicate, -1 if no such element
10423 */
10424export function findLastIndex(self: double[], predicate: (element: double, index: number, array: double[]) => boolean): number {
10425    for (let i = self.length - 1; i >= 0; i--) {
10426        if (predicate(self[i], i as number, self)) {
10427            return i
10428        }
10429    }
10430    return -1
10431}
10432
10433/**
10434 * 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.
10435 *
10436 * @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.
10437 *
10438 * @returns a result after applying callbackfn over all elements of the Array
10439 */
10440export function reduce(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number, array: double[]) => double): double {
10441    if (self.length == 0) {
10442        throw new TypeError("Reduce of empty array with no initial value")
10443    }
10444    let acc: double = self[0];
10445    for (let i = 1; i < self.length; i++) {
10446        acc = callbackfn(acc, self[i], i as number, self)
10447    }
10448    return acc
10449}
10450
10451/**
10452 * 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.
10453 *
10454 * @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.
10455 *
10456 * @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.
10457 *
10458 * @returns a result after applying callbackfn over all elements of the Array
10459 */
10460export function reduce<U = double>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number, array: double[]) => U, initialValue: U): U {
10461    let acc = initialValue
10462    for (let i = 0; i < self.length; i++) {
10463        acc = callbackfn(acc, self[i], i as number, self)
10464    }
10465    return acc
10466}
10467
10468/**
10469 * 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.
10470 *
10471 * @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.
10472 *
10473 * @returns a result after applying callbackfn over all elements of the Array
10474 */
10475export function reduceRight(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number, array: double[]) => double): double {
10476    if (self.length == 0) {
10477        throw new TypeError("Reduce of empty array with no initial value")
10478    }
10479    let acc: double = self[self.length - 1];
10480    for (let i = self.length - 2; i >= 0; i--) {
10481        acc = callbackfn(acc, self[i], i as number, self)
10482    }
10483    return acc
10484}
10485
10486/**
10487 * 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.
10488 *
10489 * @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.
10490 *
10491 * @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.
10492 *
10493 * @returns a result after applying callbackfn over all elements of the Array
10494 */
10495export function reduceRight<U>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number, array: double[]) => U, initialValue: U): U {
10496    let acc = initialValue
10497    for (let i = self.length - 1; i >= 0; i--) {
10498        acc = callbackfn(acc, self[i], i as number, self)
10499    }
10500    return acc
10501}
10502
10503/**
10504 * Performs the specified action for each element in an array.
10505 *
10506 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
10507 */
10508export function forEach(self: double[], callbackfn: (value: double, index: number, array: double[]) => void): void {
10509    const len0 = self.length;
10510    for (let i = 0; i < len0; i++) {
10511        callbackfn(self[i], i as number, self)
10512    }
10513}
10514
10515/**
10516 * Returns the value of the first element in the array where predicate is true, and undefined
10517 * otherwise.
10518 *
10519 * @param predicate find calls predicate once for each element of the array, in ascending
10520 * order, until it finds one where predicate returns true. If such an element is found, find
10521 * immediately returns that element value. Otherwise, find returns undefined.
10522 *
10523 * @returns the value of the first element in the array or undefined
10524 */
10525export function find(self: double[], predicate: (value: double, index: number) => boolean): Double | undefined {
10526    const res = findIndex(self, predicate)
10527    if (res == -1) {
10528        return undefined
10529    }
10530    return self[res as int];
10531}
10532
10533/**
10534 * Returns the index of the first element in the array where predicate is true, and -1
10535 * otherwise.
10536 *
10537 * @param predicate find calls predicate once for each element of the array, in ascending
10538 * order, until it finds one where predicate returns true. If such an element is found,
10539 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
10540 *
10541 * @returns found element index or -1 otherwise
10542 */
10543export function findIndex(self: double[], predicate: (value: double, index: number) => boolean): number {
10544    for (let i = 0; i < self.length; i++) {
10545        if (predicate(self[i], i as number)) {
10546            return i;
10547        }
10548    }
10549    return -1;
10550}
10551
10552/**
10553 * Iterates the array in reverse order and returns the value of the first element
10554 * that satisfies the provided testing function
10555 *
10556 * @param predicate testing function
10557 *
10558 * @returns found element or undefined otherwise
10559 */
10560export function findLast(self: double[], predicate: (elem: double, index: number) => boolean): Double | undefined {
10561    for (let i = self.length - 1; i >= 0; i--) {
10562        const val = self[i];
10563        if (predicate(val, i as number)) {
10564            return val;
10565        }
10566    }
10567    return undefined;
10568}
10569
10570/**
10571 * Determines whether all the members of an array satisfy the specified test.
10572 *
10573 * @param predicate A function that accepts up to three arguments. The every method calls
10574 * the predicate function for each element in the array until the predicate returns a value
10575 * which is coercible to the Boolean value false, or until the end of the array.
10576 *
10577 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
10578 */
10579export function every(self: double[], predicate: (value: double, index: number) => boolean): boolean {
10580    for (let i = 0; i < self.length; i++) {
10581        if (!predicate(self[i], i as number)) {
10582            return false
10583        }
10584    }
10585    return true;
10586}
10587
10588/**
10589 * Determines whether the specified callback function returns true for any element of an array.
10590 *
10591 * @param predicate A function that accepts up to three arguments. The some method calls
10592 * the predicate function for each element in the array until the predicate returns a value
10593 * which is coercible to the Boolean value true, or until the end of the array.
10594 *
10595 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
10596 */
10597export function some(self: double[], predicate: (value: double, index: number) => boolean): boolean {
10598    for (let i = 0; i < self.length; i++) {
10599        if (predicate(self[i], i as number)) {
10600            return true
10601        }
10602    }
10603    return false
10604}
10605
10606/**
10607 * Iterates the array in reverse order and returns the index of
10608 * the first element that satisfies the provided testing function.
10609 * If no elements satisfy the testing function, -1 is returned.
10610 *
10611 * @param predicate testing function
10612 *
10613 * @returns index of first element satisfying to predicate, -1 if no such element
10614 */
10615export function findLastIndex(self: double[], predicate: (element: double, index: number) => boolean): number {
10616    for (let i = self.length - 1; i >= 0; i--) {
10617        if (predicate(self[i], i as number)) {
10618            return i
10619        }
10620    }
10621    return -1
10622}
10623
10624/**
10625 * 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.
10626 *
10627 * @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.
10628 *
10629 * @returns a result after applying callbackfn over all elements of the Array
10630 */
10631export function reduce(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number) => double): double {
10632    if (self.length == 0) {
10633        throw new TypeError("Reduce of empty array with no initial value")
10634    }
10635    let acc: double = self[0];
10636    for (let i = 1; i < self.length; i++) {
10637        acc = callbackfn(acc, self[i], i as number)
10638    }
10639    return acc
10640}
10641
10642/**
10643 * 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.
10644 *
10645 * @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.
10646 *
10647 * @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.
10648 *
10649 * @returns a result after applying callbackfn over all elements of the Array
10650 */
10651export function reduce<U = double>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number) => U, initialValue: U): U {
10652    let acc = initialValue
10653    for (let i = 0; i < self.length; i++) {
10654        acc = callbackfn(acc, self[i], i as number)
10655    }
10656    return acc
10657}
10658
10659/**
10660 * 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.
10661 *
10662 * @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.
10663 *
10664 * @returns a result after applying callbackfn over all elements of the Array
10665 */
10666export function reduceRight(self: double[], callbackfn: (previousValue: double, currentValue: double, index: number) => double): double {
10667    if (self.length == 0) {
10668        throw new TypeError("Reduce of empty array with no initial value")
10669    }
10670    let acc: double = self[self.length - 1];
10671    for (let i = self.length - 2; i >= 0; i--) {
10672        acc = callbackfn(acc, self[i], i as number)
10673    }
10674    return acc
10675}
10676
10677/**
10678 * 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.
10679 *
10680 * @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.
10681 *
10682 * @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.
10683 *
10684 * @returns a result after applying callbackfn over all elements of the Array
10685 */
10686export function reduceRight<U>(self: double[], callbackfn: (previousValue: U, currentValue: double, index: number) => U, initialValue: U): U {
10687    let acc = initialValue
10688    for (let i = self.length - 1; i >= 0; i--) {
10689        acc = callbackfn(acc, self[i], i as number)
10690    }
10691    return acc
10692}
10693
10694/**
10695 * Performs the specified action for each element in an array.
10696 *
10697 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
10698 */
10699export function forEach(self: double[], callbackfn: (value: double, index: number) => void): void {
10700    const len0 = self.length;
10701    for (let i = 0; i < len0; i++) {
10702        callbackfn(self[i], i as number)
10703    }
10704}
10705
10706/**
10707 * Returns the value of the first element in the array where predicate is true, and undefined
10708 * otherwise.
10709 *
10710 * @param predicate find calls predicate once for each element of the array, in ascending
10711 * order, until it finds one where predicate returns true. If such an element is found, find
10712 * immediately returns that element value. Otherwise, find returns undefined.
10713 *
10714 * @returns the value of the first element in the array or undefined
10715 */
10716export function find(self: double[], predicate: (value: double) => boolean): Double | undefined {
10717    const res = findIndex(self, predicate)
10718    if (res == -1) {
10719        return undefined
10720    }
10721    return self[res as int];
10722}
10723
10724/**
10725 * Returns the index of the first element in the array where predicate is true, and -1
10726 * otherwise.
10727 *
10728 * @param predicate find calls predicate once for each element of the array, in ascending
10729 * order, until it finds one where predicate returns true. If such an element is found,
10730 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
10731 *
10732 * @returns found element index or -1 otherwise
10733 */
10734export function findIndex(self: double[], predicate: (value: double) => boolean): number {
10735    for (let i = 0; i < self.length; i++) {
10736        if (predicate(self[i])) {
10737            return i;
10738        }
10739    }
10740    return -1;
10741}
10742
10743/**
10744 * Iterates the array in reverse order and returns the value of the first element
10745 * that satisfies the provided testing function
10746 *
10747 * @param predicate testing function
10748 *
10749 * @returns found element or undefined otherwise
10750 */
10751export function findLast(self: double[], predicate: (elem: double) => boolean): Double | undefined {
10752    for (let i = self.length - 1; i >= 0; i--) {
10753        const val = self[i];
10754        if (predicate(val)) {
10755            return val;
10756        }
10757    }
10758    return undefined;
10759}
10760
10761/**
10762 * Determines whether all the members of an array satisfy the specified test.
10763 *
10764 * @param predicate A function that accepts up to three arguments. The every method calls
10765 * the predicate function for each element in the array until the predicate returns a value
10766 * which is coercible to the Boolean value false, or until the end of the array.
10767 *
10768 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
10769 */
10770export function every(self: double[], predicate: (value: double) => boolean): boolean {
10771    for (let i = 0; i < self.length; i++) {
10772        if (!predicate(self[i])) {
10773            return false
10774        }
10775    }
10776    return true;
10777}
10778
10779/**
10780 * Determines whether the specified callback function returns true for any element of an array.
10781 *
10782 * @param predicate A function that accepts up to three arguments. The some method calls
10783 * the predicate function for each element in the array until the predicate returns a value
10784 * which is coercible to the Boolean value true, or until the end of the array.
10785 *
10786 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
10787 */
10788export function some(self: double[], predicate: (value: double) => boolean): boolean {
10789    for (let i = 0; i < self.length; i++) {
10790        if (predicate(self[i])) {
10791            return true
10792        }
10793    }
10794    return false
10795}
10796
10797/**
10798 * Returns the elements of an array that meet the condition specified in a callback function.
10799 *
10800 * @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.
10801 *
10802 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
10803 */
10804export function filter(self: double[], predicate: (value: double) => boolean): double[] {
10805    return filter(self, (value: double, index: number): boolean => predicate(value));
10806}
10807
10808/**
10809 * Iterates the array in reverse order and returns the index of
10810 * the first element that satisfies the provided testing function.
10811 * If no elements satisfy the testing function, -1 is returned.
10812 *
10813 * @param predicate testing function
10814 *
10815 * @returns index of first element satisfying to predicate, -1 if no such element
10816 */
10817export function findLastIndex(self: double[], predicate: (element: double) => boolean): number {
10818    for (let i = self.length - 1; i >= 0; i--) {
10819        if (predicate(self[i])) {
10820            return i
10821        }
10822    }
10823    return -1
10824}
10825
10826/**
10827 * 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.
10828 *
10829 * @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.
10830 *
10831 * @returns a result after applying callbackfn over all elements of the Array
10832 */
10833export function reduce(self: double[], callbackfn: (previousValue: double, currentValue: double) => double): double {
10834    if (self.length == 0) {
10835        throw new TypeError("Reduce of empty array with no initial value")
10836    }
10837    let acc: double = self[0];
10838    for (let i = 1; i < self.length; i++) {
10839        acc = callbackfn(acc, self[i])
10840    }
10841    return acc
10842}
10843
10844/**
10845 * 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.
10846 *
10847 * @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.
10848 *
10849 * @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.
10850 *
10851 * @returns a result after applying callbackfn over all elements of the Array
10852 */
10853export function reduce<U = double>(self: double[], callbackfn: (previousValue: U, currentValue: double) => U, initialValue: U): U {
10854    let acc = initialValue
10855    for (let i = 0; i < self.length; i++) {
10856        acc = callbackfn(acc, self[i])
10857    }
10858    return acc
10859}
10860
10861/**
10862 * 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.
10863 *
10864 * @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.
10865 *
10866 * @returns a result after applying callbackfn over all elements of the Array
10867 */
10868export function reduceRight(self: double[], callbackfn: (previousValue: double, currentValue: double) => double): double {
10869    if (self.length == 0) {
10870        throw new TypeError("Reduce of empty array with no initial value")
10871    }
10872    let acc: double = self[self.length - 1];
10873    for (let i = self.length - 2; i >= 0; i--) {
10874        acc = callbackfn(acc, self[i])
10875    }
10876    return acc
10877}
10878
10879/**
10880 * 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.
10881 *
10882 * @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.
10883 *
10884 * @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.
10885 *
10886 * @returns a result after applying callbackfn over all elements of the Array
10887 */
10888export function reduceRight<U>(self: double[], callbackfn: (previousValue: U, currentValue: double) => U, initialValue: U): U {
10889    let acc = initialValue
10890    for (let i = self.length - 1; i >= 0; i--) {
10891        acc = callbackfn(acc, self[i])
10892    }
10893    return acc
10894}
10895
10896/**
10897 * Performs the specified action for each element in an array.
10898 *
10899 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
10900 */
10901export function forEach(self: double[], callbackfn: (value: double) => void): void {
10902    const len0 = self.length;
10903    for (let i = 0; i < len0; i++) {
10904        callbackfn(self[i])
10905    }
10906}
10907
10908/**
10909 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
10910 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
10911 *
10912 * @param start zero-based index at which to start extraction
10913 *
10914 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
10915 *
10916 * @returns `Array` instance, constructed from extracted elements of `this` instance.
10917 */
10918export function slice(self: double[], start?: Number, end?: Number): double[] {
10919    const len: int = self.length;
10920    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
10921}
10922
10923/**
10924 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
10925 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
10926 *
10927 * @param start zero-based index at which to start extraction
10928 *
10929 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
10930 *
10931 * @returns `Array` instance, constructed from extracted elements of `this` instance.
10932 */
10933export function slice(self: double[], start: int, end: int): double[] {
10934    const len: int = self.length;
10935    const relStart = normalizeIndex(start, len)
10936    const relEnd = normalizeIndex(end, len)
10937
10938    let count = relEnd - relStart;
10939    if (count < 0) {
10940        count = 0;
10941    }
10942    let res = new double[count]
10943    for (let i = 0; i < count; i++) {
10944        res[i] = self[relStart + i];
10945    }
10946
10947    return res
10948}
10949
10950/**
10951 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
10952 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
10953 *
10954 * @param start zero-based index at which to start extraction
10955 *
10956 * @returns `Array` instance, constructed from extracted elements of `this` instance.
10957 */
10958export function slice(self: double[], start: int): double[] {
10959    return slice(self, start, Int.MAX_VALUE as int);
10960}
10961
10962/**
10963 * Returns the last index at which a given element can be found in the array,
10964 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
10965 *
10966 * @param element element to locate in the array.
10967 * @param fromIndex zero-based index at which to start searching backwards.
10968 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
10969 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
10970 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
10971 *
10972 * @returns The last index of the element in the array; -1 if not found.
10973 */
10974export function lastIndexOf(self: double[], element: double, fromIndex: int): int {
10975    if (self.length == 0) {
10976        return -1;
10977    }
10978    let n = fromIndex;
10979    let k: int;
10980    if (n >= 0) {
10981        k = min(self.length - 1, n);
10982    } else {
10983        k = self.length + n;
10984    }
10985
10986    while (k >= 0) {
10987        if (__runtimeEquals(self[k], element)) {
10988            return k;
10989        }
10990        k--;
10991    }
10992    return -1;
10993}
10994
10995/**
10996 * Returns the last index at which a given element can be found in the array,
10997 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
10998 *
10999 * @param element element to locate in the array.
11000 * @param fromIndex zero-based index at which to start searching backwards.
11001 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
11002 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
11003 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
11004 *
11005 * @returns The last index of the element in the array; -1 if not found.
11006 */
11007export function lastIndexOf(self: double[], element: double, fromIndex?: Number): number {
11008    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
11009}
11010
11011/**
11012 * Creates and returns a new string by concatenating all of the elements in an `Array`,
11013 * separated by a specified separator string.
11014 * If the array has only one item, then that item will be returned without using the separator.
11015 *
11016 * @param sep specifies a separator
11017 *
11018 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
11019 */
11020export function join(self: double[], sep?: String): string {
11021    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
11022    let sb = new StringBuilder()
11023    for (let i: int = 0; i < self.length; i++) {
11024        const tmp = self[i]
11025        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
11026        if (i != 0) {
11027            sb.append(sepReal);
11028        }
11029        sb.append(tmp)
11030    }
11031
11032    return sb.toString();
11033}
11034
11035/**
11036 * Returns a string representing the specified array and its elements.
11037 *
11038 * @returns string representation
11039 */
11040export function toString(self: double[], ): string {
11041    return join(self, ",");
11042}
11043
11044/**
11045 * Returns a locale string representing the specified array and its elements.
11046 *
11047 * @param locales
11048 *
11049 * @param options
11050 *
11051 * @returns string representation
11052 */
11053export function toLocaleString(self: double[], locales: Object, options: Object): string {
11054    throw new Error("Array.toLocaleString: not implemented")
11055}
11056
11057/**
11058 * Returns a locale string representing the specified array and its elements.
11059 *
11060 * @param options
11061 *
11062 * @returns string representation
11063 */
11064export function toLocaleString(self: double[], locales: Object): string {
11065    return toLocaleString(self, new Object(), new Object())
11066}
11067
11068/**
11069 * Returns a locale string representing the specified array and its elements.
11070 *
11071 * @returns string representation
11072 */
11073export function toLocaleString(self: double[], ): string {
11074    const sb = new StringBuilder()
11075    const len = self.length;
11076    for (let i = 0; i < len; i++) {
11077        if (i != 0) {
11078            sb.append(",")
11079        }
11080        let x = self[i] as NullishType;
11081        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
11082            sb.append(x!.toLocaleString())
11083        }
11084    }
11085    return sb.toString()
11086}
11087
11088/**
11089 * Copying version of the splice() method.
11090 *
11091 * @param start index
11092 *
11093 * @param delete number of items after start index
11094 *
11095 * @returns a new Array with some elements removed and/or replaced at a given index.
11096 */
11097export function toSpliced(self: double[], start?: Number, delete?: Number): double[] {
11098    const len = self.length;
11099    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
11100}
11101
11102/**
11103 * Copying version of the splice() method.
11104 *
11105 * @param start index
11106 *
11107 * @param delete number of items after start index
11108 *
11109 * @returns a new Array with some elements removed and/or replaced at a given index.
11110 */
11111export function toSpliced(self: double[], start: number, delete: number, ...items: double[]): double[] {
11112    const len = self.length;
11113    return toSpliced(self, start as int, delete as int, ...items)
11114}
11115
11116/**
11117 * Copying version of the splice() method.
11118 *
11119 * @param start index
11120 *
11121 * @param delete number of items after start index
11122 *
11123 * @returns a new Array with some elements removed and/or replaced at a given index.
11124 */
11125export function toSpliced(self: double[], start: int, delete: int, ...items: double[]): double[] {
11126    const len = self.length;
11127    start = normalizeIndex(start, len);
11128    if (delete < 0) {
11129        delete = 0;
11130    } else if (delete > len) {
11131        delete = len;
11132    }
11133    if (start > len - delete) {
11134        delete = len - start
11135    }
11136    const res = new double[len - delete + items.length];
11137    for (let i = 0; i < start; i++) {
11138        res[i] = self[i]
11139    }
11140    for (let i = 0; i < items.length; i++) {
11141        res[start + i] = items[i]
11142    }
11143    for (let i = start + delete; i < len; i++) {
11144        res[i - delete + items.length] = self[i]
11145    }
11146    return res;
11147}
11148
11149/**
11150 * Copying version of the splice() method.
11151 *
11152 * @param start index
11153 *
11154 * @returns a new Array with some elements removed and/or replaced at a given index.
11155 */
11156export function toSpliced(self: double[], start: int): double[] {
11157    return toSpliced(self, start, self.length)
11158}
11159
11160/**
11161 * Checks whether an Array includes a certain value among its entries,
11162 * returning true or false as appropriate.
11163 *
11164 * @param val value to search
11165 *
11166 * @param fromIndex start index
11167 *
11168 * @returns true if val is in Array
11169 */
11170export function includes(self: double[], val: double, fromIndex?: Number): boolean {
11171    const len = self.length;
11172    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
11173    if (isNaN(val)) {
11174        for (let i = fi; i < len; i++) {
11175            if (isNaN(self[i])) {
11176                return true;
11177            }
11178        }
11179        return false;
11180    }
11181    for (let i = fi; i < len; i++) {
11182        if (val == self[i]) {
11183            return true;
11184        }
11185    }
11186    return false;
11187}
11188
11189/**
11190 * Returns the first index at which a given element
11191 * can be found in the array, or -1 if it is not present.
11192 *
11193 * @param val value to search
11194 *
11195 * @param fromIndex index to search from
11196 *
11197 * @returns index of val, -1 otherwise
11198 */
11199export function indexOf(self: double[], val: double, fromIndex: int): int {
11200    fromIndex = normalizeIndex(fromIndex, self.length)
11201    for (let i = fromIndex; i < self.length; i++) {
11202        if (__runtimeEquals(val, self[i])) {
11203            return i
11204        }
11205    }
11206    return -1
11207}
11208
11209/**
11210 * Returns the first index at which a given element
11211 * can be found in the array, or -1 if it is not present.
11212 *
11213 * @param val value to search
11214 *
11215 * @param fromIndex index to search from
11216 *
11217 * @returns index of val, -1 otherwise
11218 */
11219export function indexOf(self: double[], val: double, fromIndex?: Number): number {
11220    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
11221}
11222
11223/**
11224 * Copying version of the sort() method.
11225 * It returns a new array with the elements sorted in ascending order.
11226 *
11227 * @returns sorted copy of hte current instance using default comparator
11228 */
11229export function toSorted(self: double[], ): double[] {
11230    let arr = cloneArray(self);
11231    sort(arr, )
11232    return arr
11233}
11234
11235/**
11236 * Copying version of the sort() method.
11237 * It returns a new array with the elements sorted in ascending order.
11238 *
11239 * @param comparator function to compare to elements of the Array
11240 *
11241 * @returns sorted copy of the current instance comparator
11242 */
11243export function toSorted(self: double[], comparator: (a: double, b: double) => number): double[] {
11244    let arr = cloneArray(self);
11245    sort(arr, comparator)
11246    return arr
11247}
11248
11249/**
11250 * Modifies `this` instance of `Array` class and populates
11251 * it with same elements ordered towards the direction opposite to that previously stated.
11252 *
11253 * @note Mutating method
11254 */
11255export function reverse(self: double[], ): double[] {
11256    for (let i = 0; i < self.length / 2; i++) {
11257        const tmp = self[i];
11258        const idx_r = self.length - 1 - i;
11259        const val_r = self[idx_r];
11260        self[i] = val_r;
11261        self[idx_r] = tmp;
11262    }
11263    return self;
11264}
11265
11266/**
11267 * Copying version of the reverse() method.
11268 * It returns a new array with the elements in reversed order.
11269 *
11270 * @returns reversed copy of the current Array
11271 */
11272export function toReversed(self: double[], ): double[] {
11273    let arr = new double[self.length]
11274    for (let i = 0; i < self.length; i++) {
11275        arr[self.length - 1 - i] = self[i]
11276    }
11277    return arr
11278}
11279
11280/**
11281 * Copying version of using the bracket notation to change the value of a given index.
11282 * It returns a new Array with the element at the given index replaced with the given value.
11283 *
11284 * @param index to replace
11285 *
11286 * @param value new value
11287 *
11288 * @returns a new Array with the element at the given index replaced with the given value
11289 */
11290export function with(self: double[], index: number, value: double): double[] {
11291    return with(self, index as int, value)
11292}
11293
11294/**
11295 * Copying version of using the bracket notation to change the value of a given index.
11296 * It returns a new Array with the element at the given index replaced with the given value.
11297 *
11298 * @param index to replace
11299 *
11300 * @param value new value
11301 *
11302 * @returns a new Array with the element at the given index replaced with the given value
11303 */
11304export function with(self: double[], index: int, value: double): double[] {
11305    if (index < 0) {
11306        index += self.length;
11307    }
11308    if (index >= self.length) {
11309        throw new RangeError("Invalid index")
11310    }
11311    let arr = cloneArray(self);
11312    arr[index] = value;
11313    return arr
11314}
11315
11316/**
11317 * Returns an iterator over all values
11318 */
11319export function values(self: double[], ): IterableIterator<double> {
11320    return new ArrayValuesIterator_double(self);
11321}
11322
11323/**
11324 * Returns an iterable of key, value pairs for every entry in the array
11325 */
11326export function entries(self: double[], ): IterableIterator<[number, double]> {
11327    return new ArrayEntriesIterator_double(self);
11328}
11329
11330/**
11331 * Determines whether all the members of an array satisfy the specified test.
11332 *
11333 * @param predicate A function that accepts up to three arguments. The every method calls
11334 * the predicate function for each element in the array until the predicate returns a value
11335 * which is coercible to the Boolean value false, or until the end of the array.
11336 *
11337 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
11338 */
11339export function every(self: double[], predicate: () => boolean): boolean {
11340    for (let i = 0; i < self.length; i++) {
11341        if (!predicate()) {
11342            return false
11343        }
11344    }
11345    return true
11346}
11347
11348/**
11349 * Returns the elements of an array that meet the condition specified in a callback function.
11350 *
11351 * @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.
11352 *
11353 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
11354 */
11355export function filter(self: double[], predicate: () => boolean): double[] {
11356    return filter(self, (value: double, index: number): boolean => predicate());
11357}
11358
11359/**
11360 * Returns the value of the first element in the array where predicate is true, and undefined
11361 * otherwise.
11362 *
11363 * @param predicate find calls predicate once for each element of the array, in ascending
11364 * order, until it finds one where predicate returns true. If such an element is found, find
11365 * immediately returns that element value. Otherwise, find returns undefined.
11366 *
11367 * @returns the value of the first element in the array or undefined
11368 */
11369export function find(self: double[], predicate: () => boolean): Double | undefined {
11370    const res = findIndex(self, predicate)
11371    if (res == -1) {
11372        return undefined
11373    }
11374    return self[res as int];
11375}
11376
11377/**
11378 * Returns the index of the first element in the array where predicate is true, and -1
11379 * otherwise.
11380 *
11381 * @param predicate find calls predicate once for each element of the array, in ascending
11382 * order, until it finds one where predicate returns true. If such an element is found,
11383 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
11384 *
11385 * @returns found element index or -1 otherwise
11386 */
11387export function findIndex(self: double[], predicate: () => boolean): number {
11388    for (let i = 0; i < self.length; i++) {
11389        if (predicate()) {
11390            return i;
11391        }
11392    }
11393    return -1;
11394}
11395
11396/**
11397 * Performs the specified action for each element in an array.
11398 *
11399 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
11400 */
11401export function forEach(self: double[], callbackfn: () => void): void {
11402    const len0 = self.length;
11403    for (let i = 0; i < len0; i++) {
11404        callbackfn()
11405    }
11406}
11407
11408/**
11409 * 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.
11410 *
11411 * @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.
11412 *
11413 * @returns a result after applying callbackfn over all elements of the Array
11414 */
11415export function reduce(self: double[], callbackfn: (previousValue: double) => double): double {
11416    if (self.length == 0) {
11417        throw new TypeError("Reduce of empty array with no initial value")
11418    }
11419    let acc: double = self[0];
11420    for (let i = 1; i < self.length; i++) {
11421        acc = callbackfn(acc)
11422    }
11423    return acc
11424}
11425
11426/**
11427 * 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.
11428 *
11429 * @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.
11430 *
11431 * @returns a result after applying callbackfn over all elements of the Array
11432 */
11433export function reduce(self: double[], callbackfn: () => double): double {
11434    if (self.length == 0) {
11435        throw new TypeError("Reduce of empty array with no initial value")
11436    }
11437    let acc: double = self[0];
11438    for (let i = 1; i < self.length; i++) {
11439        acc = callbackfn()
11440    }
11441    return acc
11442}
11443
11444/**
11445 * 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.
11446 *
11447 * @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.
11448 *
11449 * @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.
11450 *
11451 * @returns a result after applying callbackfn over all elements of the Array
11452 */
11453export function reduce<U = double>(self: double[], callbackfn: (previousValue: U) => U, initialValue: U): U {
11454    let acc = initialValue
11455    for (let i = 0; i < self.length; i++) {
11456        acc = callbackfn(acc)
11457    }
11458    return acc
11459}
11460
11461/**
11462 * 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.
11463 *
11464 * @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.
11465 *
11466 * @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.
11467 *
11468 * @returns a result after applying callbackfn over all elements of the Array
11469 */
11470export function reduce<U = double>(self: double[], callbackfn: () => U, initialValue: U): U {
11471    let acc = initialValue
11472    for (let i = 0; i < self.length; i++) {
11473        acc = callbackfn()
11474    }
11475    return acc
11476}
11477
11478/**
11479 * 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.
11480 *
11481 * @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.
11482 *
11483 * @returns a result after applying callbackfn over all elements of the Array
11484 */
11485export function reduceRight(self: double[], callbackfn: (previousValue: double) => double): double {
11486    if (self.length == 0) {
11487        throw new TypeError("Reduce of empty array with no initial value")
11488    }
11489    let acc: double = self[self.length - 1];
11490    for (let i = self.length - 2; i >= 0; i--) {
11491        acc = callbackfn(acc)
11492    }
11493    return acc
11494}
11495
11496/**
11497 * 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.
11498 *
11499 * @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.
11500 *
11501 * @returns a result after applying callbackfn over all elements of the Array
11502 */
11503export function reduceRight(self: double[], callbackfn: () => double): double {
11504    if (self.length == 0) {
11505        throw new TypeError("Reduce of empty array with no initial value")
11506    }
11507    let acc: double = self[self.length - 1];
11508    for (let i = self.length - 2; i >= 0; i--) {
11509        acc = callbackfn()
11510    }
11511    return acc
11512}
11513
11514/**
11515 * 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.
11516 *
11517 * @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.
11518 *
11519 * @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.
11520 *
11521 * @returns a result after applying callbackfn over all elements of the Array
11522 */
11523export function reduceRight<U>(self: double[], callbackfn: (previousValue: U) => U, initialValue: U): U {
11524    let acc = initialValue
11525    for (let i = self.length - 1; i >= 0; i--) {
11526        acc = callbackfn(acc)
11527    }
11528    return acc
11529}
11530
11531/**
11532 * 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.
11533 *
11534 * @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.
11535 *
11536 * @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.
11537 *
11538 * @returns a result after applying callbackfn over all elements of the Array
11539 */
11540export function reduceRight<U>(self: double[], callbackfn: () => U, initialValue: U): U {
11541    let acc = initialValue
11542    for (let i = self.length - 1; i >= 0; i--) {
11543        acc = callbackfn()
11544    }
11545    return acc
11546}
11547
11548/**
11549 * Determines whether the specified callback function returns true for any element of an array.
11550 *
11551 * @param predicate A function that accepts up to three arguments. The some method calls
11552 * the predicate function for each element in the array until the predicate returns a value
11553 * which is coercible to the Boolean value true, or until the end of the array.
11554 *
11555 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
11556 */
11557export function some(self: double[], predicate: () => boolean): boolean {
11558    for (let i = 0; i < self.length; i++) {
11559        if (predicate()) {
11560            return true
11561        }
11562    }
11563    return false
11564}
11565
11566/**
11567 * Iterates the array in reverse order and returns the value of the first element
11568 * that satisfies the provided testing function
11569 *
11570 * @param predicate testing function
11571 *
11572 * @returns found element or undefined otherwise
11573 */
11574export function findLast(self: double[], predicate: () => boolean): Double | undefined {
11575    for (let i = self.length - 1; i >= 0; i--) {
11576        const val = self[i];
11577        if (predicate()) {
11578            return val;
11579        }
11580    }
11581    return undefined;
11582}
11583
11584/**
11585 * Iterates the array in reverse order and returns the index of
11586 * the first element that satisfies the provided testing function.
11587 * If no elements satisfy the testing function, -1 is returned.
11588 *
11589 * @param predicate testing function
11590 *
11591 * @returns index of first element satisfying to predicate, -1 if no such element
11592 */
11593export function findLastIndex(self: double[], predicate: () => boolean): number {
11594    for (let i = self.length - 1; i >= 0; i--) {
11595        if (predicate()) {
11596            return i
11597        }
11598    }
11599    return -1
11600}
11601
11602/**
11603 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
11604 *
11605 * @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.
11606 *
11607 * @returns `Array` instance, constructed from `this` and given function.
11608 */
11609export function map(self: double[], callbackfn: (value: double, index: number, array: double[]) => double): double[] {
11610    const len = self.length;
11611    let res = new double[len];
11612    for (let i = 0; i < len; i++) {
11613        res[i] = callbackfn(self[i], i as number, self);
11614    }
11615    return res;
11616}
11617
11618/**
11619 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
11620 *
11621 * @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.
11622 *
11623 * @returns `Array` instance, constructed from `this` and given function.
11624 */
11625export function map(self: double[], callbackfn: (value: double, index: number) => double): double[] {
11626    const len = self.length;
11627    let res = new double[len];
11628    for (let i = 0; i < len; i++) {
11629        res[i] = callbackfn(self[i], i as number);
11630    }
11631    return res;
11632}
11633
11634/**
11635 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
11636 *
11637 * @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.
11638 *
11639 * @returns `Array` instance, constructed from `this` and given function.
11640 */
11641export function map(self: double[], callbackfn: (value: double) => double): double[] {
11642    const len = self.length;
11643    let res = new double[len];
11644    for (let i = 0; i < len; i++) {
11645        res[i] = callbackfn(self[i]);
11646    }
11647    return res;
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: () => 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();
11662    }
11663    return res;
11664}
11665
11666/**
11667 * Constructs a new `Array` instance and populates it with
11668 * portion of a given array, filtered down to just the elements from the
11669 * given array that pass the test implemented by the provided function.
11670 *
11671 * @param fn test function, applied to each element of an array.
11672 *
11673 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
11674 */
11675export function filter(self: double[], fn: (v: double, k: number) => boolean): double[] {
11676    const mask = new boolean[self.length]
11677    let cnt = 0
11678
11679    for (let i: int = 0; i < self.length; i++) {
11680        const val = self[i];
11681        if (fn(val, i)) {
11682            mask[i] = true
11683            cnt++;
11684        }
11685    }
11686    const res = new double[cnt];
11687    let idx_store = 0;
11688    for (let i: int = 0; i < self.length; i++) {
11689        if (mask[i]) {
11690            res[idx_store++] = self[i]
11691        }
11692    }
11693    return res;
11694}
11695
11696export function concat(self: double[], fst: double[], ...more: double[][]): double[] {
11697    const lnMin = self.length + fst.length;
11698    let ln = lnMin;
11699    for (let i = 0; i < more.length; i++) {
11700        ln += more[i].length
11701    }
11702    const r = new double[ln];
11703    try {
11704        copyTo(self, r, 0, 0, self.length);
11705        copyTo(fst, r, self.length, 0, fst.length);
11706        let idx = lnMin;
11707        for (let i = 0; i < more.length; i++) {
11708            copyTo(more[i], r, idx, 0, more[i].length);
11709            idx += more[i].length;
11710        }
11711    } catch (e) {
11712        // impossible
11713    }
11714    return r
11715}
11716
11717/**
11718 * Reorders elements of `this` using comparator function.
11719 *
11720 * @param comparator function that defines the sort order.
11721 *
11722 * @note Mutating method
11723 */
11724export function sort(self: double[], comparator: (a: double, b: double) => number): double[] {
11725    sort_subarray(self, 0, self.length, (l: double, r: double): boolean => {
11726        return comparator(l, r ) < 0;
11727    });
11728    return self;
11729}
11730
11731/**
11732 * Reorders elements of `this` using comparator function.
11733 *
11734 * @param comparator function that defines the sort order.
11735 *
11736 * @note Mutating method
11737 */
11738export function sort(self: double[], ): double[] {
11739    sort(self, 0, self.length);
11740    return self;
11741}
11742
11743export function keys(self: double[]): IterableIterator<number> {
11744    return new BuiltinArrayKeysIterator(self.length);
11745}
11746
11747class ArrayValuesIterator_double implements IterableIterator<double> {
11748    private parent: double[]
11749    private idx: int = 0
11750
11751    constructor(parent: double[]) {
11752        this.parent = parent
11753    }
11754
11755    override next(): IteratorResult<double> {
11756        if (this.idx >= this.parent.length) {
11757            return new IteratorResult<double>()
11758        }
11759        return new IteratorResult<double>(this.parent[this.idx++])
11760    }
11761
11762    override $_iterator(): IterableIterator<double> {
11763        return this;
11764    }
11765}
11766
11767class ArrayEntriesIterator_double implements IterableIterator<[number, double]> {
11768    private parent: double[]
11769    private idx: int = 0
11770
11771    constructor(parent: double[]) {
11772        this.parent = parent
11773    }
11774
11775    override next(): IteratorResult<[number, double]> {
11776        if (this.idx >= this.parent.length) {
11777            return new IteratorResult<[number, double]>()
11778        }
11779        const i = this.idx++;
11780        const vl: [number, double] = [i as number, this.parent[i]]
11781        return new IteratorResult<[number, double]>(vl);
11782    }
11783
11784    override $_iterator(): IterableIterator<[number, double]> {
11785        return this;
11786    }
11787}
11788
11789function cloneArray(self: char[]): char[] {
11790    const ret = new char[self.length];;
11791    for (let i = 0; i < self.length; i++) {
11792        ret[i] = self[i];
11793    }
11794    return ret;
11795}
11796
11797/**
11798 * Takes an integer value and returns the item at that index,
11799 * allowing for positive and negative integers. Negative integers count back
11800 * from the last item in the array.
11801 *
11802 * @param index Zero-based index of the array element to be returned.
11803 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
11804 *
11805 * @returns The element in the array matching the given index.
11806 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
11807 */
11808export function at(self: char[], index: number): Char | undefined {
11809    return at(self, index as int)
11810}
11811
11812/**
11813 * Creates a new `Array` from this `Array` instance and given `Array` instance.
11814 *
11815 * @param other to concatenate into a new array.
11816 *
11817 * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
11818 */
11819// export function concat(self: char[], ...items: (char | Concatchar[])[]): char[] {
11820//     throw new Error("not implemented")
11821// }
11822
11823export function concat(self: char[], ...items: ConcatArray<char>[]): char[] {
11824    let totalAdd = self.length;
11825    for (let i = 0; i < items.length; i++) {
11826        totalAdd += items[i].length as int
11827    }
11828
11829    const buf = new char[totalAdd];
11830
11831    for (let i = 0; i < self.length; i++) {
11832        buf[i] = self[i];
11833    }
11834
11835    let insertTo = self.length;
11836    for (let i = 0; i < items.length; i++) {
11837        const arr = items[i]
11838        const len = arr.length as int
11839        for (let j = 0; j < len; j++) {
11840            buf[insertTo++] = arr.$_get(j)
11841        }
11842    }
11843
11844    return buf;
11845}
11846
11847/**
11848 * Takes an integer value and returns the item at that index,
11849 * allowing for positive and negative integers. Negative integers count back
11850 * from the last item in the array.
11851 *
11852 * @param index Zero-based index of the array element to be returned.
11853 * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
11854 *
11855 * @returns The element in the array matching the given index.
11856 * Returns undefined if `index` < `-length()` or `index` >= `length()`.
11857 */
11858export function at(self: char[], index: int): Char | undefined {
11859    let len = self.length;
11860    let k: int;
11861    if (index >= 0) {
11862        k = index;
11863    } else {
11864        k = len + index;
11865    }
11866
11867    if (k < 0 || k >= len) {
11868        return undefined;
11869    }
11870
11871    return self[k];
11872}
11873
11874/**
11875 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
11876 *
11877 * @param target index at which to copy the sequence
11878 *
11879 * @param start index at which to start copying elements from
11880 *
11881 * @param end index at which to end copying elements from
11882 *
11883 * @returns this array after transformation
11884 */
11885export function copyWithin(self: char[], target: number, start: number, end?: Number): char[] {
11886    copyWithin(self, target as int, start as int, asIntOrDefault(end, self.length));
11887    return self;
11888}
11889
11890/**
11891 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
11892 *
11893 * @param target index at which to copy the sequence
11894 *
11895 * @param start index at which to start copying elements from
11896 *
11897 * @param end index at which to end copying elements from
11898 *
11899 * @returns this array after transformation
11900 */
11901export function copyWithin(self: char[], target: int, start: int, end: int): char[] {
11902    target = normalizeIndex(target, self.length)
11903    start = normalizeIndex(start, self.length)
11904    end = normalizeIndex(end, self.length)
11905
11906    if (end <= start) {
11907        return self;
11908    }
11909
11910    if (target <= start) {
11911        while (start < end) {
11912            const read = self[start++];
11913            self[target++] = read;
11914        }
11915    } else {
11916        let len = end - start;
11917        if (target + len > self.length) {
11918            len = self.length - target
11919        }
11920        for (let i = 0; i < len; i++) {
11921            const read = self[start + len - 1 - i];
11922            self[target + len - 1 - i] = read;
11923        }
11924    }
11925
11926    return self;
11927}
11928
11929/**
11930 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
11931 *
11932 * @param target index at which to copy the sequence
11933 *
11934 * @param start index at which to start copying elements from
11935 *
11936 * @returns this array after transformation
11937 */
11938export function copyWithin(self: char[], target: int, start: int): char[] {
11939    copyWithin(self, target, start, self.length);
11940    return self;
11941}
11942
11943/**
11944 * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
11945 *
11946 * @param target index at which to copy the sequence
11947 *
11948 * @returns this array after transformation
11949 */
11950export function copyWithin(self: char[], target: int): char[] {
11951    copyWithin(self, target, 0, self.length);
11952    return self;
11953}
11954
11955/**
11956 * Changes all elements in the Array to a static value, from a start index to an end index
11957 *
11958 * @param value to fill the array with
11959 *
11960 * @param start index at which to start filling
11961 *
11962 * @param end index at which to end filling, but not including
11963 *
11964 * @returns this array after transformation
11965 */
11966export function fill(self: char[], value: char, start?: Number, end?: Number): char[] {
11967    fill(self, value, asIntOrDefault(start, 0), asIntOrDefault(end, self.length));
11968    return self;
11969}
11970
11971/**
11972 * Changes all elements in the Array to a static value, from a start index to an end index
11973 *
11974 * @param value to fill the array with
11975 *
11976 * @param start index at which to start filling
11977 *
11978 * @param end index at which to end filling, but not including
11979 *
11980 * @returns this array after transformation
11981 */
11982export function fill(self: char[], value: char, start: int, end: int): char[] {
11983    start = normalizeIndex(start, self.length);
11984    end = normalizeIndex(end, self.length)
11985
11986    for (let i = start; i < end; i++) {
11987        self[i] = value;
11988    }
11989
11990    return self;
11991}
11992
11993/**
11994 * Returns the value of the first element in the array where predicate is true, and undefined
11995 * otherwise.
11996 *
11997 * @param predicate find calls predicate once for each element of the array, in ascending
11998 * order, until it finds one where predicate returns true. If such an element is found, find
11999 * immediately returns that element value. Otherwise, find returns undefined.
12000 *
12001 * @returns the value of the first element in the array or undefined
12002 */
12003export function find(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): Char | undefined {
12004    const res = findIndex(self, predicate)
12005    if (res == -1) {
12006        return undefined
12007    }
12008    return self[res as int];
12009}
12010
12011/**
12012 * Returns the index of the first element in the array where predicate is true, and -1
12013 * otherwise.
12014 *
12015 * @param predicate find calls predicate once for each element of the array, in ascending
12016 * order, until it finds one where predicate returns true. If such an element is found,
12017 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
12018 *
12019 * @returns found element index or -1 otherwise
12020 */
12021export function findIndex(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): number {
12022    for (let i = 0; i < self.length; i++) {
12023        if (predicate(self[i], i as number, self)) {
12024            return i;
12025        }
12026    }
12027    return -1;
12028}
12029
12030/**
12031 * Iterates the array in reverse order and returns the value of the first element
12032 * that satisfies the provided testing function
12033 *
12034 * @param predicate testing function
12035 *
12036 * @returns found element or undefined otherwise
12037 */
12038export function findLast(self: char[], predicate: (elem: char, index: number, array: char[]) => boolean): Char | undefined {
12039    for (let i = self.length - 1; i >= 0; i--) {
12040        const val = self[i];
12041        if (predicate(val, i as number, self)) {
12042            return val;
12043        }
12044    }
12045    return undefined;
12046}
12047
12048/**
12049 * Determines whether all the members of an array satisfy the specified test.
12050 *
12051 * @param predicate A function that accepts up to three arguments. The every method calls
12052 * the predicate function for each element in the array until the predicate returns a value
12053 * which is coercible to the Boolean value false, or until the end of the array.
12054 *
12055 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
12056 */
12057export function every(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): boolean {
12058    for (let i = 0; i < self.length; i++) {
12059        if (!predicate(self[i], i as number, self)) {
12060            return false
12061        }
12062    }
12063    return true;
12064}
12065
12066/**
12067 * Determines whether the specified callback function returns true for any element of an array.
12068 *
12069 * @param predicate A function that accepts up to three arguments. The some method calls
12070 * the predicate function for each element in the array until the predicate returns a value
12071 * which is coercible to the Boolean value true, or until the end of the array.
12072 *
12073 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
12074 */
12075export function some(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): boolean {
12076    for (let i = 0; i < self.length; i++) {
12077        if (predicate(self[i], i as number, self)) {
12078            return true
12079        }
12080    }
12081    return false
12082}
12083
12084/**
12085 * Returns the elements of an array that meet the condition specified in a callback function.
12086 *
12087 * @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.
12088 *
12089 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
12090 */
12091export function filter(self: char[], predicate: (value: char, index: number, array: char[]) => boolean): char[] {
12092    return filter(self, (value: char, index: number): boolean => predicate(value, index, self));
12093}
12094
12095/**
12096 * Iterates the array in reverse order and returns the index of
12097 * the first element that satisfies the provided testing function.
12098 * If no elements satisfy the testing function, -1 is returned.
12099 *
12100 * @param predicate testing function
12101 *
12102 * @returns index of first element satisfying to predicate, -1 if no such element
12103 */
12104export function findLastIndex(self: char[], predicate: (element: char, index: number, array: char[]) => boolean): number {
12105    for (let i = self.length - 1; i >= 0; i--) {
12106        if (predicate(self[i], i as number, self)) {
12107            return i
12108        }
12109    }
12110    return -1
12111}
12112
12113/**
12114 * 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.
12115 *
12116 * @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.
12117 *
12118 * @returns a result after applying callbackfn over all elements of the Array
12119 */
12120export function reduce(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number, array: char[]) => char): char {
12121    if (self.length == 0) {
12122        throw new TypeError("Reduce of empty array with no initial value")
12123    }
12124    let acc: char = self[0];
12125    for (let i = 1; i < self.length; i++) {
12126        acc = callbackfn(acc, self[i], i as number, self)
12127    }
12128    return acc
12129}
12130
12131/**
12132 * 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.
12133 *
12134 * @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.
12135 *
12136 * @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.
12137 *
12138 * @returns a result after applying callbackfn over all elements of the Array
12139 */
12140export function reduce<U = char>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number, array: char[]) => U, initialValue: U): U {
12141    let acc = initialValue
12142    for (let i = 0; i < self.length; i++) {
12143        acc = callbackfn(acc, self[i], i as number, self)
12144    }
12145    return acc
12146}
12147
12148/**
12149 * 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.
12150 *
12151 * @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.
12152 *
12153 * @returns a result after applying callbackfn over all elements of the Array
12154 */
12155export function reduceRight(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number, array: char[]) => char): char {
12156    if (self.length == 0) {
12157        throw new TypeError("Reduce of empty array with no initial value")
12158    }
12159    let acc: char = self[self.length - 1];
12160    for (let i = self.length - 2; i >= 0; i--) {
12161        acc = callbackfn(acc, self[i], i as number, self)
12162    }
12163    return acc
12164}
12165
12166/**
12167 * 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.
12168 *
12169 * @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.
12170 *
12171 * @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.
12172 *
12173 * @returns a result after applying callbackfn over all elements of the Array
12174 */
12175export function reduceRight<U>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number, array: char[]) => U, initialValue: U): U {
12176    let acc = initialValue
12177    for (let i = self.length - 1; i >= 0; i--) {
12178        acc = callbackfn(acc, self[i], i as number, self)
12179    }
12180    return acc
12181}
12182
12183/**
12184 * Performs the specified action for each element in an array.
12185 *
12186 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
12187 */
12188export function forEach(self: char[], callbackfn: (value: char, index: number, array: char[]) => void): void {
12189    const len0 = self.length;
12190    for (let i = 0; i < len0; i++) {
12191        callbackfn(self[i], i as number, self)
12192    }
12193}
12194
12195/**
12196 * Returns the value of the first element in the array where predicate is true, and undefined
12197 * otherwise.
12198 *
12199 * @param predicate find calls predicate once for each element of the array, in ascending
12200 * order, until it finds one where predicate returns true. If such an element is found, find
12201 * immediately returns that element value. Otherwise, find returns undefined.
12202 *
12203 * @returns the value of the first element in the array or undefined
12204 */
12205export function find(self: char[], predicate: (value: char, index: number) => boolean): Char | undefined {
12206    const res = findIndex(self, predicate)
12207    if (res == -1) {
12208        return undefined
12209    }
12210    return self[res as int];
12211}
12212
12213/**
12214 * Returns the index of the first element in the array where predicate is true, and -1
12215 * otherwise.
12216 *
12217 * @param predicate find calls predicate once for each element of the array, in ascending
12218 * order, until it finds one where predicate returns true. If such an element is found,
12219 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
12220 *
12221 * @returns found element index or -1 otherwise
12222 */
12223export function findIndex(self: char[], predicate: (value: char, index: number) => boolean): number {
12224    for (let i = 0; i < self.length; i++) {
12225        if (predicate(self[i], i as number)) {
12226            return i;
12227        }
12228    }
12229    return -1;
12230}
12231
12232/**
12233 * Iterates the array in reverse order and returns the value of the first element
12234 * that satisfies the provided testing function
12235 *
12236 * @param predicate testing function
12237 *
12238 * @returns found element or undefined otherwise
12239 */
12240export function findLast(self: char[], predicate: (elem: char, index: number) => boolean): Char | undefined {
12241    for (let i = self.length - 1; i >= 0; i--) {
12242        const val = self[i];
12243        if (predicate(val, i as number)) {
12244            return val;
12245        }
12246    }
12247    return undefined;
12248}
12249
12250/**
12251 * Determines whether all the members of an array satisfy the specified test.
12252 *
12253 * @param predicate A function that accepts up to three arguments. The every method calls
12254 * the predicate function for each element in the array until the predicate returns a value
12255 * which is coercible to the Boolean value false, or until the end of the array.
12256 *
12257 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
12258 */
12259export function every(self: char[], predicate: (value: char, index: number) => boolean): boolean {
12260    for (let i = 0; i < self.length; i++) {
12261        if (!predicate(self[i], i as number)) {
12262            return false
12263        }
12264    }
12265    return true;
12266}
12267
12268/**
12269 * Determines whether the specified callback function returns true for any element of an array.
12270 *
12271 * @param predicate A function that accepts up to three arguments. The some method calls
12272 * the predicate function for each element in the array until the predicate returns a value
12273 * which is coercible to the Boolean value true, or until the end of the array.
12274 *
12275 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
12276 */
12277export function some(self: char[], predicate: (value: char, index: number) => boolean): boolean {
12278    for (let i = 0; i < self.length; i++) {
12279        if (predicate(self[i], i as number)) {
12280            return true
12281        }
12282    }
12283    return false
12284}
12285
12286/**
12287 * Iterates the array in reverse order and returns the index of
12288 * the first element that satisfies the provided testing function.
12289 * If no elements satisfy the testing function, -1 is returned.
12290 *
12291 * @param predicate testing function
12292 *
12293 * @returns index of first element satisfying to predicate, -1 if no such element
12294 */
12295export function findLastIndex(self: char[], predicate: (element: char, index: number) => boolean): number {
12296    for (let i = self.length - 1; i >= 0; i--) {
12297        if (predicate(self[i], i as number)) {
12298            return i
12299        }
12300    }
12301    return -1
12302}
12303
12304/**
12305 * 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.
12306 *
12307 * @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.
12308 *
12309 * @returns a result after applying callbackfn over all elements of the Array
12310 */
12311export function reduce(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number) => char): char {
12312    if (self.length == 0) {
12313        throw new TypeError("Reduce of empty array with no initial value")
12314    }
12315    let acc: char = self[0];
12316    for (let i = 1; i < self.length; i++) {
12317        acc = callbackfn(acc, self[i], i as number)
12318    }
12319    return acc
12320}
12321
12322/**
12323 * 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.
12324 *
12325 * @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.
12326 *
12327 * @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.
12328 *
12329 * @returns a result after applying callbackfn over all elements of the Array
12330 */
12331export function reduce<U = char>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number) => U, initialValue: U): U {
12332    let acc = initialValue
12333    for (let i = 0; i < self.length; i++) {
12334        acc = callbackfn(acc, self[i], i as number)
12335    }
12336    return acc
12337}
12338
12339/**
12340 * 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.
12341 *
12342 * @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.
12343 *
12344 * @returns a result after applying callbackfn over all elements of the Array
12345 */
12346export function reduceRight(self: char[], callbackfn: (previousValue: char, currentValue: char, index: number) => char): char {
12347    if (self.length == 0) {
12348        throw new TypeError("Reduce of empty array with no initial value")
12349    }
12350    let acc: char = self[self.length - 1];
12351    for (let i = self.length - 2; i >= 0; i--) {
12352        acc = callbackfn(acc, self[i], i as number)
12353    }
12354    return acc
12355}
12356
12357/**
12358 * 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.
12359 *
12360 * @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.
12361 *
12362 * @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.
12363 *
12364 * @returns a result after applying callbackfn over all elements of the Array
12365 */
12366export function reduceRight<U>(self: char[], callbackfn: (previousValue: U, currentValue: char, index: number) => U, initialValue: U): U {
12367    let acc = initialValue
12368    for (let i = self.length - 1; i >= 0; i--) {
12369        acc = callbackfn(acc, self[i], i as number)
12370    }
12371    return acc
12372}
12373
12374/**
12375 * Performs the specified action for each element in an array.
12376 *
12377 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
12378 */
12379export function forEach(self: char[], callbackfn: (value: char, index: number) => void): void {
12380    const len0 = self.length;
12381    for (let i = 0; i < len0; i++) {
12382        callbackfn(self[i], i as number)
12383    }
12384}
12385
12386/**
12387 * Returns the value of the first element in the array where predicate is true, and undefined
12388 * otherwise.
12389 *
12390 * @param predicate find calls predicate once for each element of the array, in ascending
12391 * order, until it finds one where predicate returns true. If such an element is found, find
12392 * immediately returns that element value. Otherwise, find returns undefined.
12393 *
12394 * @returns the value of the first element in the array or undefined
12395 */
12396export function find(self: char[], predicate: (value: char) => boolean): Char | undefined {
12397    const res = findIndex(self, predicate)
12398    if (res == -1) {
12399        return undefined
12400    }
12401    return self[res as int];
12402}
12403
12404/**
12405 * Returns the index of the first element in the array where predicate is true, and -1
12406 * otherwise.
12407 *
12408 * @param predicate find calls predicate once for each element of the array, in ascending
12409 * order, until it finds one where predicate returns true. If such an element is found,
12410 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
12411 *
12412 * @returns found element index or -1 otherwise
12413 */
12414export function findIndex(self: char[], predicate: (value: char) => boolean): number {
12415    for (let i = 0; i < self.length; i++) {
12416        if (predicate(self[i])) {
12417            return i;
12418        }
12419    }
12420    return -1;
12421}
12422
12423/**
12424 * Iterates the array in reverse order and returns the value of the first element
12425 * that satisfies the provided testing function
12426 *
12427 * @param predicate testing function
12428 *
12429 * @returns found element or undefined otherwise
12430 */
12431export function findLast(self: char[], predicate: (elem: char) => boolean): Char | undefined {
12432    for (let i = self.length - 1; i >= 0; i--) {
12433        const val = self[i];
12434        if (predicate(val)) {
12435            return val;
12436        }
12437    }
12438    return undefined;
12439}
12440
12441/**
12442 * Determines whether all the members of an array satisfy the specified test.
12443 *
12444 * @param predicate A function that accepts up to three arguments. The every method calls
12445 * the predicate function for each element in the array until the predicate returns a value
12446 * which is coercible to the Boolean value false, or until the end of the array.
12447 *
12448 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
12449 */
12450export function every(self: char[], predicate: (value: char) => boolean): boolean {
12451    for (let i = 0; i < self.length; i++) {
12452        if (!predicate(self[i])) {
12453            return false
12454        }
12455    }
12456    return true;
12457}
12458
12459/**
12460 * Determines whether the specified callback function returns true for any element of an array.
12461 *
12462 * @param predicate A function that accepts up to three arguments. The some method calls
12463 * the predicate function for each element in the array until the predicate returns a value
12464 * which is coercible to the Boolean value true, or until the end of the array.
12465 *
12466 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
12467 */
12468export function some(self: char[], predicate: (value: char) => boolean): boolean {
12469    for (let i = 0; i < self.length; i++) {
12470        if (predicate(self[i])) {
12471            return true
12472        }
12473    }
12474    return false
12475}
12476
12477/**
12478 * Returns the elements of an array that meet the condition specified in a callback function.
12479 *
12480 * @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.
12481 *
12482 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
12483 */
12484export function filter(self: char[], predicate: (value: char) => boolean): char[] {
12485    return filter(self, (value: char, index: number): boolean => predicate(value));
12486}
12487
12488/**
12489 * Iterates the array in reverse order and returns the index of
12490 * the first element that satisfies the provided testing function.
12491 * If no elements satisfy the testing function, -1 is returned.
12492 *
12493 * @param predicate testing function
12494 *
12495 * @returns index of first element satisfying to predicate, -1 if no such element
12496 */
12497export function findLastIndex(self: char[], predicate: (element: char) => boolean): number {
12498    for (let i = self.length - 1; i >= 0; i--) {
12499        if (predicate(self[i])) {
12500            return i
12501        }
12502    }
12503    return -1
12504}
12505
12506/**
12507 * 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.
12508 *
12509 * @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.
12510 *
12511 * @returns a result after applying callbackfn over all elements of the Array
12512 */
12513export function reduce(self: char[], callbackfn: (previousValue: char, currentValue: char) => char): char {
12514    if (self.length == 0) {
12515        throw new TypeError("Reduce of empty array with no initial value")
12516    }
12517    let acc: char = self[0];
12518    for (let i = 1; i < self.length; i++) {
12519        acc = callbackfn(acc, self[i])
12520    }
12521    return acc
12522}
12523
12524/**
12525 * 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.
12526 *
12527 * @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.
12528 *
12529 * @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.
12530 *
12531 * @returns a result after applying callbackfn over all elements of the Array
12532 */
12533export function reduce<U = char>(self: char[], callbackfn: (previousValue: U, currentValue: char) => U, initialValue: U): U {
12534    let acc = initialValue
12535    for (let i = 0; i < self.length; i++) {
12536        acc = callbackfn(acc, self[i])
12537    }
12538    return acc
12539}
12540
12541/**
12542 * 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.
12543 *
12544 * @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.
12545 *
12546 * @returns a result after applying callbackfn over all elements of the Array
12547 */
12548export function reduceRight(self: char[], callbackfn: (previousValue: char, currentValue: char) => char): char {
12549    if (self.length == 0) {
12550        throw new TypeError("Reduce of empty array with no initial value")
12551    }
12552    let acc: char = self[self.length - 1];
12553    for (let i = self.length - 2; i >= 0; i--) {
12554        acc = callbackfn(acc, self[i])
12555    }
12556    return acc
12557}
12558
12559/**
12560 * 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.
12561 *
12562 * @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.
12563 *
12564 * @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.
12565 *
12566 * @returns a result after applying callbackfn over all elements of the Array
12567 */
12568export function reduceRight<U>(self: char[], callbackfn: (previousValue: U, currentValue: char) => U, initialValue: U): U {
12569    let acc = initialValue
12570    for (let i = self.length - 1; i >= 0; i--) {
12571        acc = callbackfn(acc, self[i])
12572    }
12573    return acc
12574}
12575
12576/**
12577 * Performs the specified action for each element in an array.
12578 *
12579 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
12580 */
12581export function forEach(self: char[], callbackfn: (value: char) => void): void {
12582    const len0 = self.length;
12583    for (let i = 0; i < len0; i++) {
12584        callbackfn(self[i])
12585    }
12586}
12587
12588/**
12589 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
12590 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
12591 *
12592 * @param start zero-based index at which to start extraction
12593 *
12594 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
12595 *
12596 * @returns `Array` instance, constructed from extracted elements of `this` instance.
12597 */
12598export function slice(self: char[], start?: Number, end?: Number): char[] {
12599    const len: int = self.length;
12600    return slice(self, asIntOrDefault(start, 0), asIntOrDefault(end, len))
12601}
12602
12603/**
12604 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
12605 * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
12606 *
12607 * @param start zero-based index at which to start extraction
12608 *
12609 * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
12610 *
12611 * @returns `Array` instance, constructed from extracted elements of `this` instance.
12612 */
12613export function slice(self: char[], start: int, end: int): char[] {
12614    const len: int = self.length;
12615    const relStart = normalizeIndex(start, len)
12616    const relEnd = normalizeIndex(end, len)
12617
12618    let count = relEnd - relStart;
12619    if (count < 0) {
12620        count = 0;
12621    }
12622    let res = new char[count]
12623    for (let i = 0; i < count; i++) {
12624        res[i] = self[relStart + i];
12625    }
12626
12627    return res
12628}
12629
12630/**
12631 * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
12632 * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
12633 *
12634 * @param start zero-based index at which to start extraction
12635 *
12636 * @returns `Array` instance, constructed from extracted elements of `this` instance.
12637 */
12638export function slice(self: char[], start: int): char[] {
12639    return slice(self, start, Int.MAX_VALUE as int);
12640}
12641
12642/**
12643 * Returns the last index at which a given element can be found in the array,
12644 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
12645 *
12646 * @param element element to locate in the array.
12647 * @param fromIndex zero-based index at which to start searching backwards.
12648 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
12649 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
12650 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
12651 *
12652 * @returns The last index of the element in the array; -1 if not found.
12653 */
12654export function lastIndexOf(self: char[], element: char, fromIndex: int): int {
12655    if (self.length == 0) {
12656        return -1;
12657    }
12658    let n = fromIndex;
12659    let k: int;
12660    if (n >= 0) {
12661        k = min(self.length - 1, n);
12662    } else {
12663        k = self.length + n;
12664    }
12665
12666    while (k >= 0) {
12667        if (__runtimeEquals(self[k], element)) {
12668            return k;
12669        }
12670        k--;
12671    }
12672    return -1;
12673}
12674
12675/**
12676 * Returns the last index at which a given element can be found in the array,
12677 * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
12678 *
12679 * @param element element to locate in the array.
12680 * @param fromIndex zero-based index at which to start searching backwards.
12681 * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
12682 * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
12683 * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
12684 *
12685 * @returns The last index of the element in the array; -1 if not found.
12686 */
12687export function lastIndexOf(self: char[], element: char, fromIndex?: Number): number {
12688    return lastIndexOf(self, element, asIntOrDefault(fromIndex, self.length - 1));
12689}
12690
12691/**
12692 * Creates and returns a new string by concatenating all of the elements in an `Array`,
12693 * separated by a specified separator string.
12694 * If the array has only one item, then that item will be returned without using the separator.
12695 *
12696 * @param sep specifies a separator
12697 *
12698 * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
12699 */
12700export function join(self: char[], sep?: String): string {
12701    const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
12702    let sb = new StringBuilder()
12703    for (let i: int = 0; i < self.length; i++) {
12704        const tmp = self[i]
12705        // NOTE(aleksander-sotov) We can't move if from loop due to 18709
12706        if (i != 0) {
12707            sb.append(sepReal);
12708        }
12709        sb.append(tmp)
12710    }
12711
12712    return sb.toString();
12713}
12714
12715/**
12716 * Returns a string representing the specified array and its elements.
12717 *
12718 * @returns string representation
12719 */
12720export function toString(self: char[], ): string {
12721    return join(self, ",");
12722}
12723
12724/**
12725 * Returns a locale string representing the specified array and its elements.
12726 *
12727 * @param locales
12728 *
12729 * @param options
12730 *
12731 * @returns string representation
12732 */
12733export function toLocaleString(self: char[], locales: Object, options: Object): string {
12734    throw new Error("Array.toLocaleString: not implemented")
12735}
12736
12737/**
12738 * Returns a locale string representing the specified array and its elements.
12739 *
12740 * @param options
12741 *
12742 * @returns string representation
12743 */
12744export function toLocaleString(self: char[], locales: Object): string {
12745    return toLocaleString(self, new Object(), new Object())
12746}
12747
12748/**
12749 * Returns a locale string representing the specified array and its elements.
12750 *
12751 * @returns string representation
12752 */
12753export function toLocaleString(self: char[], ): string {
12754    const sb = new StringBuilder()
12755    const len = self.length;
12756    for (let i = 0; i < len; i++) {
12757        if (i != 0) {
12758            sb.append(",")
12759        }
12760        let x = self[i] as NullishType;
12761        if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
12762            sb.append(x!.toLocaleString())
12763        }
12764    }
12765    return sb.toString()
12766}
12767
12768/**
12769 * Copying version of the splice() method.
12770 *
12771 * @param start index
12772 *
12773 * @param delete number of items after start index
12774 *
12775 * @returns a new Array with some elements removed and/or replaced at a given index.
12776 */
12777export function toSpliced(self: char[], start?: Number, delete?: Number): char[] {
12778    const len = self.length;
12779    return toSpliced(self, asIntOrDefault(start, len), asIntOrDefault(delete, len))
12780}
12781
12782/**
12783 * Copying version of the splice() method.
12784 *
12785 * @param start index
12786 *
12787 * @param delete number of items after start index
12788 *
12789 * @returns a new Array with some elements removed and/or replaced at a given index.
12790 */
12791export function toSpliced(self: char[], start: number, delete: number, ...items: char[]): char[] {
12792    const len = self.length;
12793    return toSpliced(self, start as int, delete as int, ...items)
12794}
12795
12796/**
12797 * Copying version of the splice() method.
12798 *
12799 * @param start index
12800 *
12801 * @param delete number of items after start index
12802 *
12803 * @returns a new Array with some elements removed and/or replaced at a given index.
12804 */
12805export function toSpliced(self: char[], start: int, delete: int, ...items: char[]): char[] {
12806    const len = self.length;
12807    start = normalizeIndex(start, len);
12808    if (delete < 0) {
12809        delete = 0;
12810    } else if (delete > len) {
12811        delete = len;
12812    }
12813    if (start > len - delete) {
12814        delete = len - start
12815    }
12816    const res = new char[len - delete + items.length];
12817    for (let i = 0; i < start; i++) {
12818        res[i] = self[i]
12819    }
12820    for (let i = 0; i < items.length; i++) {
12821        res[start + i] = items[i]
12822    }
12823    for (let i = start + delete; i < len; i++) {
12824        res[i - delete + items.length] = self[i]
12825    }
12826    return res;
12827}
12828
12829/**
12830 * Copying version of the splice() method.
12831 *
12832 * @param start index
12833 *
12834 * @returns a new Array with some elements removed and/or replaced at a given index.
12835 */
12836export function toSpliced(self: char[], start: int): char[] {
12837    return toSpliced(self, start, self.length)
12838}
12839
12840/**
12841 * Checks whether an Array includes a certain value among its entries,
12842 * returning true or false as appropriate.
12843 *
12844 * @param val value to search
12845 *
12846 * @param fromIndex start index
12847 *
12848 * @returns true if val is in Array
12849 */
12850export function includes(self: char[], val: char, fromIndex?: Number): boolean {
12851    const len = self.length;
12852    const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
12853    for (let i = fi; i < len; i++) {
12854        if (val == self[i]) {
12855            return true;
12856        }
12857    }
12858    return false;
12859}
12860
12861/**
12862 * Returns the first index at which a given element
12863 * can be found in the array, or -1 if it is not present.
12864 *
12865 * @param val value to search
12866 *
12867 * @param fromIndex index to search from
12868 *
12869 * @returns index of val, -1 otherwise
12870 */
12871export function indexOf(self: char[], val: char, fromIndex: int): int {
12872    fromIndex = normalizeIndex(fromIndex, self.length)
12873    for (let i = fromIndex; i < self.length; i++) {
12874        if (__runtimeEquals(val, self[i])) {
12875            return i
12876        }
12877    }
12878    return -1
12879}
12880
12881/**
12882 * Returns the first index at which a given element
12883 * can be found in the array, or -1 if it is not present.
12884 *
12885 * @param val value to search
12886 *
12887 * @param fromIndex index to search from
12888 *
12889 * @returns index of val, -1 otherwise
12890 */
12891export function indexOf(self: char[], val: char, fromIndex?: Number): number {
12892    return indexOf(self, val, asIntOrDefault(fromIndex, 0))
12893}
12894
12895/**
12896 * Copying version of the sort() method.
12897 * It returns a new array with the elements sorted in ascending order.
12898 *
12899 * @returns sorted copy of hte current instance using default comparator
12900 */
12901export function toSorted(self: char[], ): char[] {
12902    let arr = cloneArray(self);
12903    sort(arr, )
12904    return arr
12905}
12906
12907/**
12908 * Copying version of the sort() method.
12909 * It returns a new array with the elements sorted in ascending order.
12910 *
12911 * @param comparator function to compare to elements of the Array
12912 *
12913 * @returns sorted copy of the current instance comparator
12914 */
12915export function toSorted(self: char[], comparator: (a: char, b: char) => number): char[] {
12916    let arr = cloneArray(self);
12917    sort(arr, comparator)
12918    return arr
12919}
12920
12921/**
12922 * Modifies `this` instance of `Array` class and populates
12923 * it with same elements ordered towards the direction opposite to that previously stated.
12924 *
12925 * @note Mutating method
12926 */
12927export function reverse(self: char[], ): char[] {
12928    for (let i = 0; i < self.length / 2; i++) {
12929        const tmp = self[i];
12930        const idx_r = self.length - 1 - i;
12931        const val_r = self[idx_r];
12932        self[i] = val_r;
12933        self[idx_r] = tmp;
12934    }
12935    return self;
12936}
12937
12938/**
12939 * Copying version of the reverse() method.
12940 * It returns a new array with the elements in reversed order.
12941 *
12942 * @returns reversed copy of the current Array
12943 */
12944export function toReversed(self: char[], ): char[] {
12945    let arr = new char[self.length]
12946    for (let i = 0; i < self.length; i++) {
12947        arr[self.length - 1 - i] = self[i]
12948    }
12949    return arr
12950}
12951
12952/**
12953 * Copying version of using the bracket notation to change the value of a given index.
12954 * It returns a new Array with the element at the given index replaced with the given value.
12955 *
12956 * @param index to replace
12957 *
12958 * @param value new value
12959 *
12960 * @returns a new Array with the element at the given index replaced with the given value
12961 */
12962export function with(self: char[], index: number, value: char): char[] {
12963    return with(self, index as int, value)
12964}
12965
12966/**
12967 * Copying version of using the bracket notation to change the value of a given index.
12968 * It returns a new Array with the element at the given index replaced with the given value.
12969 *
12970 * @param index to replace
12971 *
12972 * @param value new value
12973 *
12974 * @returns a new Array with the element at the given index replaced with the given value
12975 */
12976export function with(self: char[], index: int, value: char): char[] {
12977    if (index < 0) {
12978        index += self.length;
12979    }
12980    if (index >= self.length) {
12981        throw new RangeError("Invalid index")
12982    }
12983    let arr = cloneArray(self);
12984    arr[index] = value;
12985    return arr
12986}
12987
12988/**
12989 * Returns an iterator over all values
12990 */
12991export function values(self: char[], ): IterableIterator<char> {
12992    return new ArrayValuesIterator_char(self);
12993}
12994
12995/**
12996 * Returns an iterable of key, value pairs for every entry in the array
12997 */
12998export function entries(self: char[], ): IterableIterator<[number, char]> {
12999    return new ArrayEntriesIterator_char(self);
13000}
13001
13002/**
13003 * Determines whether all the members of an array satisfy the specified test.
13004 *
13005 * @param predicate A function that accepts up to three arguments. The every method calls
13006 * the predicate function for each element in the array until the predicate returns a value
13007 * which is coercible to the Boolean value false, or until the end of the array.
13008 *
13009 * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
13010 */
13011export function every(self: char[], predicate: () => boolean): boolean {
13012    for (let i = 0; i < self.length; i++) {
13013        if (!predicate()) {
13014            return false
13015        }
13016    }
13017    return true
13018}
13019
13020/**
13021 * Returns the elements of an array that meet the condition specified in a callback function.
13022 *
13023 * @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.
13024 *
13025 * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
13026 */
13027export function filter(self: char[], predicate: () => boolean): char[] {
13028    return filter(self, (value: char, index: number): boolean => predicate());
13029}
13030
13031/**
13032 * Returns the value of the first element in the array where predicate is true, and undefined
13033 * otherwise.
13034 *
13035 * @param predicate find calls predicate once for each element of the array, in ascending
13036 * order, until it finds one where predicate returns true. If such an element is found, find
13037 * immediately returns that element value. Otherwise, find returns undefined.
13038 *
13039 * @returns the value of the first element in the array or undefined
13040 */
13041export function find(self: char[], predicate: () => boolean): Char | undefined {
13042    const res = findIndex(self, predicate)
13043    if (res == -1) {
13044        return undefined
13045    }
13046    return self[res as int];
13047}
13048
13049/**
13050 * Returns the index of the first element in the array where predicate is true, and -1
13051 * otherwise.
13052 *
13053 * @param predicate find calls predicate once for each element of the array, in ascending
13054 * order, until it finds one where predicate returns true. If such an element is found,
13055 * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
13056 *
13057 * @returns found element index or -1 otherwise
13058 */
13059export function findIndex(self: char[], predicate: () => boolean): number {
13060    for (let i = 0; i < self.length; i++) {
13061        if (predicate()) {
13062            return i;
13063        }
13064    }
13065    return -1;
13066}
13067
13068/**
13069 * Performs the specified action for each element in an array.
13070 *
13071 * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
13072 */
13073export function forEach(self: char[], callbackfn: () => void): void {
13074    const len0 = self.length;
13075    for (let i = 0; i < len0; i++) {
13076        callbackfn()
13077    }
13078}
13079
13080/**
13081 * 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.
13082 *
13083 * @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.
13084 *
13085 * @returns a result after applying callbackfn over all elements of the Array
13086 */
13087export function reduce(self: char[], callbackfn: (previousValue: char) => char): char {
13088    if (self.length == 0) {
13089        throw new TypeError("Reduce of empty array with no initial value")
13090    }
13091    let acc: char = self[0];
13092    for (let i = 1; i < self.length; i++) {
13093        acc = callbackfn(acc)
13094    }
13095    return acc
13096}
13097
13098/**
13099 * 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.
13100 *
13101 * @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.
13102 *
13103 * @returns a result after applying callbackfn over all elements of the Array
13104 */
13105export function reduce(self: char[], callbackfn: () => char): char {
13106    if (self.length == 0) {
13107        throw new TypeError("Reduce of empty array with no initial value")
13108    }
13109    let acc: char = self[0];
13110    for (let i = 1; i < self.length; i++) {
13111        acc = callbackfn()
13112    }
13113    return acc
13114}
13115
13116/**
13117 * 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.
13118 *
13119 * @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.
13120 *
13121 * @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.
13122 *
13123 * @returns a result after applying callbackfn over all elements of the Array
13124 */
13125export function reduce<U = char>(self: char[], callbackfn: (previousValue: U) => U, initialValue: U): U {
13126    let acc = initialValue
13127    for (let i = 0; i < self.length; i++) {
13128        acc = callbackfn(acc)
13129    }
13130    return acc
13131}
13132
13133/**
13134 * 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.
13135 *
13136 * @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.
13137 *
13138 * @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.
13139 *
13140 * @returns a result after applying callbackfn over all elements of the Array
13141 */
13142export function reduce<U = char>(self: char[], callbackfn: () => U, initialValue: U): U {
13143    let acc = initialValue
13144    for (let i = 0; i < self.length; i++) {
13145        acc = callbackfn()
13146    }
13147    return acc
13148}
13149
13150/**
13151 * 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.
13152 *
13153 * @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.
13154 *
13155 * @returns a result after applying callbackfn over all elements of the Array
13156 */
13157export function reduceRight(self: char[], callbackfn: (previousValue: char) => char): char {
13158    if (self.length == 0) {
13159        throw new TypeError("Reduce of empty array with no initial value")
13160    }
13161    let acc: char = self[self.length - 1];
13162    for (let i = self.length - 2; i >= 0; i--) {
13163        acc = callbackfn(acc)
13164    }
13165    return acc
13166}
13167
13168/**
13169 * 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.
13170 *
13171 * @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.
13172 *
13173 * @returns a result after applying callbackfn over all elements of the Array
13174 */
13175export function reduceRight(self: char[], callbackfn: () => char): char {
13176    if (self.length == 0) {
13177        throw new TypeError("Reduce of empty array with no initial value")
13178    }
13179    let acc: char = self[self.length - 1];
13180    for (let i = self.length - 2; i >= 0; i--) {
13181        acc = callbackfn()
13182    }
13183    return acc
13184}
13185
13186/**
13187 * 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.
13188 *
13189 * @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.
13190 *
13191 * @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.
13192 *
13193 * @returns a result after applying callbackfn over all elements of the Array
13194 */
13195export function reduceRight<U>(self: char[], callbackfn: (previousValue: U) => U, initialValue: U): U {
13196    let acc = initialValue
13197    for (let i = self.length - 1; i >= 0; i--) {
13198        acc = callbackfn(acc)
13199    }
13200    return acc
13201}
13202
13203/**
13204 * 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.
13205 *
13206 * @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.
13207 *
13208 * @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.
13209 *
13210 * @returns a result after applying callbackfn over all elements of the Array
13211 */
13212export function reduceRight<U>(self: char[], callbackfn: () => U, initialValue: U): U {
13213    let acc = initialValue
13214    for (let i = self.length - 1; i >= 0; i--) {
13215        acc = callbackfn()
13216    }
13217    return acc
13218}
13219
13220/**
13221 * Determines whether the specified callback function returns true for any element of an array.
13222 *
13223 * @param predicate A function that accepts up to three arguments. The some method calls
13224 * the predicate function for each element in the array until the predicate returns a value
13225 * which is coercible to the Boolean value true, or until the end of the array.
13226 *
13227 * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
13228 */
13229export function some(self: char[], predicate: () => boolean): boolean {
13230    for (let i = 0; i < self.length; i++) {
13231        if (predicate()) {
13232            return true
13233        }
13234    }
13235    return false
13236}
13237
13238/**
13239 * Iterates the array in reverse order and returns the value of the first element
13240 * that satisfies the provided testing function
13241 *
13242 * @param predicate testing function
13243 *
13244 * @returns found element or undefined otherwise
13245 */
13246export function findLast(self: char[], predicate: () => boolean): Char | undefined {
13247    for (let i = self.length - 1; i >= 0; i--) {
13248        const val = self[i];
13249        if (predicate()) {
13250            return val;
13251        }
13252    }
13253    return undefined;
13254}
13255
13256/**
13257 * Iterates the array in reverse order and returns the index of
13258 * the first element that satisfies the provided testing function.
13259 * If no elements satisfy the testing function, -1 is returned.
13260 *
13261 * @param predicate testing function
13262 *
13263 * @returns index of first element satisfying to predicate, -1 if no such element
13264 */
13265export function findLastIndex(self: char[], predicate: () => boolean): number {
13266    for (let i = self.length - 1; i >= 0; i--) {
13267        if (predicate()) {
13268            return i
13269        }
13270    }
13271    return -1
13272}
13273
13274/**
13275 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13276 *
13277 * @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.
13278 *
13279 * @returns `Array` instance, constructed from `this` and given function.
13280 */
13281export function map(self: char[], callbackfn: (value: char, index: number, array: char[]) => char): char[] {
13282    const len = self.length;
13283    let res = new char[len];
13284    for (let i = 0; i < len; i++) {
13285        res[i] = callbackfn(self[i], i as number, self);
13286    }
13287    return res;
13288}
13289
13290/**
13291 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13292 *
13293 * @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.
13294 *
13295 * @returns `Array` instance, constructed from `this` and given function.
13296 */
13297export function map(self: char[], callbackfn: (value: char, index: number) => char): char[] {
13298    const len = self.length;
13299    let res = new char[len];
13300    for (let i = 0; i < len; i++) {
13301        res[i] = callbackfn(self[i], i as number);
13302    }
13303    return res;
13304}
13305
13306/**
13307 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13308 *
13309 * @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.
13310 *
13311 * @returns `Array` instance, constructed from `this` and given function.
13312 */
13313export function map(self: char[], callbackfn: (value: char) => char): char[] {
13314    const len = self.length;
13315    let res = new char[len];
13316    for (let i = 0; i < len; i++) {
13317        res[i] = callbackfn(self[i]);
13318    }
13319    return res;
13320}
13321
13322/**
13323 * Calls a defined callback function on each element of an array, and returns an array that contains the results.
13324 *
13325 * @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.
13326 *
13327 * @returns `Array` instance, constructed from `this` and given function.
13328 */
13329export function map(self: char[], callbackfn: () => char): char[] {
13330    const len = self.length;
13331    let res = new char[len];
13332    for (let i = 0; i < len; i++) {
13333        res[i] = callbackfn();
13334    }
13335    return res;
13336}
13337
13338/**
13339 * Constructs a new `Array` instance and populates it with
13340 * portion of a given array, filtered down to just the elements from the
13341 * given array that pass the test implemented by the provided function.
13342 *
13343 * @param fn test function, applied to each element of an array.
13344 *
13345 * @returns New `Array` instance constructed from `this` with elements filtered using test function `fn`.
13346 */
13347export function filter(self: char[], fn: (v: char, k: number) => boolean): char[] {
13348    const mask = new boolean[self.length]
13349    let cnt = 0
13350
13351    for (let i: int = 0; i < self.length; i++) {
13352        const val = self[i];
13353        if (fn(val, i)) {
13354            mask[i] = true
13355            cnt++;
13356        }
13357    }
13358    const res = new char[cnt];
13359    let idx_store = 0;
13360    for (let i: int = 0; i < self.length; i++) {
13361        if (mask[i]) {
13362            res[idx_store++] = self[i]
13363        }
13364    }
13365    return res;
13366}
13367
13368export function concat(self: char[], fst: char[], ...more: char[][]): char[] {
13369    const lnMin = self.length + fst.length;
13370    let ln = lnMin;
13371    for (let i = 0; i < more.length; i++) {
13372        ln += more[i].length
13373    }
13374    const r = new char[ln];
13375    try {
13376        copyTo(self, r, 0, 0, self.length);
13377        copyTo(fst, r, self.length, 0, fst.length);
13378        let idx = lnMin;
13379        for (let i = 0; i < more.length; i++) {
13380            copyTo(more[i], r, idx, 0, more[i].length);
13381            idx += more[i].length;
13382        }
13383    } catch (e) {
13384        // impossible
13385    }
13386    return r
13387}
13388
13389/**
13390 * Reorders elements of `this` using comparator function.
13391 *
13392 * @param comparator function that defines the sort order.
13393 *
13394 * @note Mutating method
13395 */
13396export function sort(self: char[], comparator: (a: char, b: char) => number): char[] {
13397    sort_subarray(self, 0, self.length, (l: char, r: char): boolean => {
13398        return comparator(l, r ) < 0;
13399    });
13400    return self;
13401}
13402
13403/**
13404 * Reorders elements of `this` using comparator function.
13405 *
13406 * @param comparator function that defines the sort order.
13407 *
13408 * @note Mutating method
13409 */
13410export function sort(self: char[], ): char[] {
13411    sort(self, 0, self.length);
13412    return self;
13413}
13414
13415export function keys(self: char[]): IterableIterator<number> {
13416    return new BuiltinArrayKeysIterator(self.length);
13417}
13418
13419class ArrayValuesIterator_char implements IterableIterator<char> {
13420    private parent: char[]
13421    private idx: int = 0
13422
13423    constructor(parent: char[]) {
13424        this.parent = parent
13425    }
13426
13427    override next(): IteratorResult<char> {
13428        if (this.idx >= this.parent.length) {
13429            return new IteratorResult<char>()
13430        }
13431        return new IteratorResult<char>(this.parent[this.idx++])
13432    }
13433
13434    override $_iterator(): IterableIterator<char> {
13435        return this;
13436    }
13437}
13438
13439class ArrayEntriesIterator_char implements IterableIterator<[number, char]> {
13440    private parent: char[]
13441    private idx: int = 0
13442
13443    constructor(parent: char[]) {
13444        this.parent = parent
13445    }
13446
13447    override next(): IteratorResult<[number, char]> {
13448        if (this.idx >= this.parent.length) {
13449            return new IteratorResult<[number, char]>()
13450        }
13451        const i = this.idx++;
13452        const vl: [number, char] = [i as number, this.parent[i]]
13453        return new IteratorResult<[number, char]>(vl);
13454    }
13455
13456    override $_iterator(): IterableIterator<[number, char]> {
13457        return this;
13458    }
13459}
13460
13461function builtin_insertion_sort<T>(arr: T[], startIndex: int, endIndex: int, comp: (lhs: T, rhs: T) => number): void {
13462    for (let i = startIndex + 1; i < endIndex; i++) {
13463        const tmp = arr[i];
13464        if (comp(tmp, arr[startIndex]) as int < 0) {
13465            for (let j = i; j > startIndex; j--) {
13466                arr[j] = arr[j - 1]
13467            }
13468            arr[startIndex] = tmp
13469        } else {
13470            let j = i - 1;
13471            while (comp(tmp, arr[j]) as int < 0) {
13472                arr[j + 1] = arr[j];
13473                j--;
13474            }
13475            arr[j + 1] = tmp;
13476        }
13477    }
13478}
13479
13480function perform_merge<T>(arr: T[], startIndex: int, midIndex: int, endIndex: int, comp: (lhs: T, rhs: T) => number): void {
13481    const len1 = midIndex - startIndex + 1;
13482    const len2 = endIndex - midIndex;
13483    let left = new T[len1];
13484    let right = new T[len2];
13485    for (let i = 0; i < len1; i++) {
13486        left[i] = arr[startIndex + i];
13487    }
13488    for (let i = 0; i < len2; i++) {
13489        right[i] = arr[midIndex + 1 + i];
13490    }
13491    let i = 0;
13492    let j = 0;
13493    let k = startIndex;
13494    while (i < len1 && j < len2) {
13495        if (comp(left[i], right[j]) as int <= 0) {
13496            arr[k] = left[i];
13497            i++;
13498        } else {
13499            arr[k] = right[j];
13500            j++;
13501        }
13502        k++;
13503    }
13504    while (i < len1) {
13505        arr[k] = left[i];
13506        k++;
13507        i++;
13508    }
13509    while (j < len2) {
13510        arr[k] = right[j];
13511        k++;
13512        j++;
13513    }
13514}
13515
13516export function sort_stable<T>(arr: T[], startIndex: int, endIndex: int, comp: (lhs: T, rhs: T) => number): void {
13517    if (endIndex <= startIndex) {
13518        return;
13519    }
13520
13521    const INS_SORT_DELTA = 16
13522    for (let i = startIndex; i < endIndex; i += INS_SORT_DELTA ) {
13523        builtin_insertion_sort<T>(arr, i, min(i + INS_SORT_DELTA , endIndex), comp)
13524    }
13525    if ((endIndex - startIndex) < INS_SORT_DELTA) {
13526        return;
13527    }
13528    for (let size = INS_SORT_DELTA; size < endIndex; size = 2 * size) {
13529        for (let left = startIndex; left < endIndex; left += 2 * size) {
13530
13531            // Find ending point of left subarray and right subarray
13532            const mid = min(left + size - 1, endIndex - 1);
13533            const right = min((left + 2 * size - 1), (endIndex - 1));
13534
13535            // Merge sub array arr[left.....mid] and arr[mid+1....right]
13536            if (mid < right) {
13537                perform_merge(arr, left, mid, right, comp);
13538            }
13539        }
13540    }
13541}
13542
13543function defaultComparatorStr(a: String, b: String): number {
13544    return a.compareTo(b)
13545}
13546
13547type buffStr = String | null
13548function stringified_insertion_sort<T>(arr: T[], arrStr: buffStr[], startIndex: int, endIndex: int): void {
13549    for (let i = startIndex + 1; i < endIndex; i++) {
13550        const tmp = arr[i]
13551        const tmpStr = arrStr[i];
13552        if (defaultComparatorStr(tmpStr!, arrStr[startIndex]!) < 0) {
13553            for (let j = i; j > startIndex; j--) {
13554                arr[j] = arr[j - 1]
13555                arrStr[j] = arrStr[j - 1]
13556            }
13557            arrStr[startIndex] = tmpStr
13558            arr[startIndex] = tmp
13559        } else {
13560            let j = i - 1;
13561            while (defaultComparatorStr(tmpStr!, arrStr[j]!) < 0) {
13562                arr[j + 1] = arr[j];
13563                arrStr[j + 1] = arrStr[j]
13564                j--;
13565            }
13566            arr[j + 1] = tmp;
13567            arrStr[j + 1] = tmpStr
13568        }
13569    }
13570}
13571
13572function stringified_perform_merge<T>(arr: T[], arrStr: buffStr[], startIndex: int, midIndex: int, endIndex: int): void {
13573    const len1 = midIndex - startIndex + 1;
13574    const len2 = endIndex - midIndex;
13575    type buffType = T | null
13576    let left = new buffType[len1]
13577    let right = new buffType[len2]
13578    let leftStr = new buffStr[len1]
13579    let rightStr = new buffStr[len2]
13580    for (let i = 0; i < len1; i++) {
13581        left[i] = arr[startIndex + i]
13582        leftStr[i] = arrStr[startIndex + i]
13583    }
13584    for (let i = 0; i < len2; i++) {
13585        right[i] = arr[midIndex + 1 + i]
13586        rightStr[i] = arrStr[midIndex + 1 + i]
13587    }
13588    let i = 0;
13589    let j = 0;
13590    let k = startIndex;
13591    while (i < len1 && j < len2) {
13592        if (defaultComparatorStr(leftStr[i]!, rightStr[j]!) <= 0) {
13593            arr[k] = left[i]!;
13594            arrStr[k] = leftStr[i]!;
13595            i++;
13596        } else {
13597            arr[k] = right[j]!;
13598            arrStr[k] = rightStr[j]!;
13599            j++;
13600        }
13601        k++;
13602    }
13603    while (i < len1) {
13604        arr[k] = left[i]!;
13605        arrStr[k] = leftStr[i]!;
13606        k++;
13607        i++;
13608    }
13609    while (j < len2) {
13610        arr[k] = right[j]!;
13611        arrStr[k] = rightStr[j]!;
13612        k++;
13613        j++;
13614    }
13615}
13616
13617export function sort_default<T>(arr: T[], arrStr: buffStr[], startIndex: int, endIndex: int): void {
13618    if (endIndex <= startIndex) {
13619        return;
13620    }
13621    const INS_SORT_DELTA = 16
13622    for (let i = startIndex; i < endIndex; i += INS_SORT_DELTA ) {
13623        stringified_insertion_sort<T>(arr, arrStr, i, min(i + INS_SORT_DELTA , endIndex))
13624    }
13625
13626    if ((endIndex - startIndex) < INS_SORT_DELTA) {
13627        return;
13628    }
13629    for (let size = INS_SORT_DELTA; size < endIndex; size = 2 * size) {
13630        for (let left = startIndex; left < endIndex; left += 2 * size) {
13631
13632            // Find ending point of left subarray and right subarray
13633            const mid = min(left + size - 1, endIndex - 1);
13634            const right = min((left + 2 * size - 1), (endIndex - 1));
13635
13636            // Merge sub array arr[left.....mid] and arr[mid+1....right]
13637            if (mid < right) {
13638                stringified_perform_merge(arr, arrStr, left, mid, right);
13639            }
13640        }
13641    }
13642}
13643