/* * Copyright 2019 Magnus Madsen, Stephen Tetley * Copyright 2024 Jonathan Lindegaard Starup * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */instanceIndexable[Array[a, r]] {typeIdx = Int32typeElm = atypeAef = r + OutOfBoundspubdefget(t: Array[a, r], i: Int32): a \ r + OutOfBounds = {if (0<=iandi<Array.length(t))Array.get(i, t)elseOutOfBounds.outOfBounds("index ${i} is out of bounds for Array of length ${Array.length(t)}" ) }}instanceIndexableMut[Array[a, r]] {typeAef = r + OutOfBoundspubdefput(t: Array[a, r], i: Int32, v: a): Unit \ r + OutOfBounds = {if (0<=iandi<Array.length(t))Array.put(v, i, t)elseOutOfBounds.outOfBounds("index ${i} is out of bounds for Array of length ${Array.length(t)}" ) }}instanceIterable[Array[a, r]] {typeElm = atypeAef = rpubdefiterator(rc: Region[r1], a: Array[a, r]): Iterator[a, r + r1, r1] \ (r + r1) =checked_ecast(Array.iterator(rc, a))}instanceForEach[Array[a, r]] {typeElm = atypeAef = rpubdefforEach(f: a -> Unit \ ef, a: Array[a, r]): Unit \ ef + r = Array.forEach(f, a)}instanceFormattable[Array[a, r]] withFormattable[a] {typeAef = Formattable.Aef[a] + rpubdefformat(x: Array[a, r]): RichString \ (Formattable.Aef[a] + r) =use RichString.{fromString, joinWith};fromString("Array#{") +joinWith(Formattable.format, fromString(", "), Array.toList(x)) +fromString("}")}pubmod Array {use Math.Shuffleimport java.lang.Objectimport java.lang.Systemimport java.util.Arrays////// Compares `a` and `b` lexicographically.///pubdefcompare(a: Array[v, r1], b: Array[v, r2]): Comparison \ { r1, r2 } withOrder[v] =letlen = Int32.min(Array.length(a), Array.length(b));defloop(i) = {if (i<len) {letcmp = get(i, a) <=>get(i, b);if (cmp== Comparison.EqualTo)loop(i+1)elsecmp } elseif (i<Array.length(a)) { Comparison.GreaterThan } elseif (i<Array.length(b)) { Comparison.LessThan } else { Comparison.EqualTo } };loop(0)////// Returns a string representation of the given array `a`.///pubdeftoString(a: Array[a, r]): String \ rwithToString[a] = regionrc {"Array#{"+ (Array.iterator(rc, a) |> Iterator.join(", ")) +"}" }////// Returns a new uninitialized array of length `l` in the region `r`.///pubdefempty(rc: Region[r], l: Int32): Array[a, r] \ Heap[r] = %%ARRAY_NEW%%(rc, Reflect.default(), l)////// Retrieves the value at position `i` in the array `a`.///pubdefget(i: Int32, a: Array[a, r]): a \ r = %%ARRAY_LOAD%%(a, i)////// Stores the value `x` at position `i` in the array `a`.///pubdefput(x: a, i: Int32, a: Array[a, r]): Unit \ r = %%ARRAY_STORE%%(a, i, x)////// Optionally returns the element at position `i` in the array `a`.///pubdefnth(i: Int32, a: Array[a, r]): Option[a] \ r =if (0<=iandi<length(a)) Some(get(i, a))else None////// Returns `true` if the given array `a` is empty.///pubdefisEmpty(a: Array[a, r]): Bool = length(a) ==0////// Returns `true` if the given array `a` is non-empty.///pubdefnonEmpty(a: Array[a, r]): Bool = notisEmpty(a)////// Returns the number of elements in the array `a`.///pubdeflength(a: Array[a, r]): Int32 = %%ARRAY_LENGTH%%(a)////// Returns the number of elements in the array `a`.///pubdefsize(a: Array[a, r]): Int32 = length(a)////// Returns a fresh array with the elements from the array `a` from index `start` (inclusive) until index `end` (exclusive).///pubdefslice(rc1: Region[r1], start: {start = Int32}, end: {end = Int32}, a: Array[a, r]): Array[a, r1] \ { r, r1 } =copyOfRange(rc1, start#start, end#end, a)////// Returns the array `a` as a list.///pubdeftoList(a: Array[a, r]): List[a] \ r =defloop(i, acc) = {if (i==0) {acc } else {letx = get(i-1, a);loop(i-1, x :: acc) } };loop(length(a), Nil)////// Optionally returns the array `arr` as a non-empty list.////// If `arr` is empty return `None`, otherwise return the Nel wrapped in `Some`.///pubdeftoNel(arr: Array[a, r]): Option[Nel[a]] \ r =defloop(i, acc) = {if (i==0) {acc } else {letx = get(i-1, arr);loop(i-1, Nel.cons(x, acc)) } };if (Array.isEmpty(arr)) { None } else {leti = length(arr) -1; Some(loop(i, Nel.singleton(get(i, arr)))) }////// Returns the array `arr` as a chain.///pubdeftoChain(arr: Array[a, r]): Chain[a] \ r =defloop(i, acc) = {if (i==0) {acc } else {letx = get(i-1, arr);loop(i-1, Chain.cons(x, acc)) } };loop(length(arr), Chain.empty())////// Optionally returns the array `arr` as a non-empty chain.////// If `arr` is empty return `None`, otherwise return the Nec wrapped in `Some`.///pubdeftoNec(arr: Array[a, r]): Option[Nec[a]] \ r =defloop(i, acc) = {if (i==0) {acc } else {letx = get(i-1, arr);loop(i-1, Nec.cons(x, acc)) } };if (Array.isEmpty(arr)) { None } else {leti = length(arr) -1; Some(loop(i, Nec.singleton(get(i, arr)))) }////// Returns `a` as a Vector.///pubdeftoVector(a: Array[a, r]): Vector[a] \ r = regionrc {letarr1 = copyOfRange(rc, 0, length(a), a);unchecked_cast(arr1asVector[a]) }////// Returns `Some(x)` if `x` is the first element of `a`.////// Returns `None` if `a` is empty.///pubdefhead(a: Array[a, r]): Option[a] \ r =if (length(a) >0) Some(get(0, a)) else None////// Returns `Some(x)` if `x` is the last element of `a`.////// Returns `None` if `a` is empty.///pubdeflast(a: Array[a, r]): Option[a] \ r =letlen = length(a);if (len>0) Some(get(len-1, a)) else None////// Return a new array, appending the elements `b` to elements of `a`.///pubdefappend(rc3: Region[r3], a: Array[a, r1], b: Array[a, r2]): Array[a, r3] \ { r1, r2, r3 } =letlen1 = length(a);letlen2 = length(b);if (len1==0)copyOfRange(rc3, 0, len2, b)else {letout = copyOfRange(rc3, 0, len1+len2, a);updateSequence(len1, b, out);out }////// Returns `true` if and only if `a` contains the element `x`.///pubdefmemberOf(x: a, a: Array[a, r]): Bool \ rwithEq[a] =exists(y -> y==x, a)////// Optionally finds the smallest element of `a` according to the `Order` on `a`.////// Returns `None` if `a` is empty.///pubdefminimum(a: Array[a, r]): Option[a] \ rwithOrder[a] =reduceLeft(Order.min, a)////// Optionally finds the smallest element of `a` according to the given comparator `cmp`.////// Returns `None` if `a` is empty.///pubdefminimumBy(cmp: (a, a) -> Comparison, a: Array[a, r]): Option[a] \ r =reduceLeft(Order.minBy(cmp), a)////// Optionally finds the largest element of `a` according to the `Order` on `a`.////// Returns `None` if `a` is empty.///pubdefmaximum(a: Array[a, r]): Option[a] \ rwithOrder[a] =reduceLeft(Order.max, a)////// Optionally finds the largest element of `a` according to the given comparator `cmp`.////// Returns `None` if `a` is empty.///pubdefmaximumBy(cmp: (a, a) -> Comparison, a: Array[a, r]): Option[a] \ r =reduceLeft(Order.maxBy(cmp), a)////// Alias for `indexOfLeft`///pubdefindexOf(x: a, a: Array[a, r]): Option[Int32] \ rwithEq[a] =indexOfLeft(x, a)////// Optionally returns the position of the first occurrence of `a` in `arr`/// searching from left to right.///pubdefindexOfLeft(a: a, arr: Array[a, r]): Option[Int32] \ rwithEq[a] =defloop(i) = {if (i>=length(arr)) -1elseif (get(i, arr) ==a)ielseloop(i+1) };leti = loop(0);if (i<0) None else Some(i)////// Optionally returns the position of the first occurrence of `a` in `arr`/// searching from right to left.///pubdefindexOfRight(a: a, arr: Array[a, r]): Option[Int32] \ rwithEq[a] =defloop(i) = {if (i<0) -1elseif (get(i, arr) ==a)ielseloop(i-1) };leti = loop(length(arr) -1);if (i<0) None else Some(i)////// Return the positions of the all the occurrences of `a` in `arr`.///pubdefindicesOf(a: a, arr: Array[a, r]): Vector[Int32] \ rwithEq[a] =findIndices(b -> a==b, arr)////// Returns a range of all valid indices of the array `arr`.///pubdefindices(arr: Array[a, r]): Range[Int32] = Range.Range(0, length(arr))////// Alias for `findLeft`.///pubdeffind(f: a -> Bool \ ef, arr: Array[a, r]): Option[a] \ { ef, r } =findLeft(f, arr)////// Optionally returns the first element of `a` that satisfies the predicate `f` when searching from left to right.///pubdeffindLeft(f: a -> Bool \ ef, arr: Array[a, r]): Option[a] \ { ef, r } =matchfindIndexOfLeft(f, arr) {case None => Nonecase Some(i) => Some(get(i, arr)) }////// Optionally returns the first element of `xs` that satisfies the predicate `f` when searching from right to left.///pubdeffindRight(f: a -> Bool \ ef, arr: Array[a, r]): Option[a] \ { ef, r } =matchfindIndexOfRight(x -> f(x), arr) {case None => Nonecase Some(i) => Some(get(i, arr)) }////// Returns an array of all integers between `b` (inclusive) and `e` (exclusive).////// Returns `[]` if `b >= e`.///pubdefrange(rc: Region[r], b: Int32, e: Int32): Array[Int32, r] \ r =if (b>=e) Array#{} @ rcelse {letf = x -> x+b;init(rc, f, e-b) }////// Returns an array with the element `x` repeated `n` times.////// Returns the empty array if `n <= 0`.///pubdefrepeat(rc: Region[r], n: Int32, x: a): Array[a, r] \ r =if (n<=0) Array#{} @ rcelse %%ARRAY_NEW%%(rc, x, n)////// Alias for `scanLeft`.///pubdefscan(rc: Region[r], f: (b, a) -> b \ ef, s: b, arr: Array[a, r]): Array[b, r] \ { ef, r } =scanLeft(rc, f, s, arr)////// Accumulates the result of applying `f` to `arr` going left to right.////// That is, the result is of the form: `[s , f(s, x1), f(f(s, x1), x2), ...]`.///pubdefscanLeft(rc: Region[r], f: (b, a) -> b \ ef, s: b, arr: Array[a, r]): Array[b, r] \ { ef, r } =letlen = length(arr) +1;letb = repeat(rc, len, s);defloop(i, acc) = {if (i>=len)()else {lets1 = f(acc, get(i-1, arr));Array.put(s1, i, b);loop(i+1, s1) } };loop(1, s);b////// Accumulates the result of applying `f` to `xs` going right to left.////// That is, the result is of the form: `[..., f(xn-1, f(xn, s)), f(xn, s), s]`.///pubdefscanRight(rc: Region[r], f: (a, b) -> b \ ef, s: b, a: Array[a, r]): Array[b, r] \ { ef, r } =letlen = length(a);letb = repeat(rc, len+1, s);defloop(i, acc) = {if (i<0)()else {lets1 = f(get(i, a), acc);Array.put(s1, i, b);loop(i-1, s1) } };loop(len-1, s);b////// Returns the result of applying `f` to every element in `a`.///pubdefmap(rc1: Region[r1], f: a -> b \ ef, a: Array[a, r]): Array[b, r1] \ { ef, r, r1 } =letlen = length(a);init(rc1, i -> f(get(i, a)), len)////// Apply `f` to every element in array `arr`. Array `arr` is mutated.///pubdeftransform(f: a -> a \ ef, arr: Array[a, r]): Unit \ { ef, r } =letlen = length(arr);defloop(i) = {if (i>=len)()else {Array.put(f(get(i, arr)), i, arr);loop(i+1) } };loop(0)////// Returns the result of applying `f` to every element in `a` along with that element's index.////// That is, the result is of the form: `[ f(0, a[0]), f(1, a[1]), ... ]`.///pubdefmapWithIndex(rc1: Region[r1], f: (Int32, a) -> b \ ef, a: Array[a, r]): Array[b, r1] \ { ef, r, r1 } =letlen = length(a);init(rc1, i -> f(i, get(i, a)), len)////// Apply `f` to every element in array `a` along with that element's index. Array `a` is mutated.///pubdeftransformWithIndex(f: (Int32, a) -> a \ ef, arr: Array[a, r]): Unit \ { ef, r } =letlen = length(arr);defloop(i) = {if (i>=len)()else {Array.put(f(i, get(i, arr)), i, arr);loop(i+1) } };loop(0)////// Returns the result of applying `f` to every element in `a` and concatenating the results.///pubdefflatMap(rc1: Region[r1], f: a -> Array[b, r1] \ ef, a: Array[a, r]): Array[b, r1] \ { ef, r, r1 } =letlen = length(a);init(rc1, i -> f(get(i, a)), len) |> flatten(rc1)////// Reverse the array `arr`, mutating it in place.///pubdefreverse(arr: Array[a, r]): Unit \ r =letlen = length(arr);lethalflen = len/2;defloop(i, j) = {if (i>=halflen)()else {letx = get(i, arr);lety = get(j, arr);put(y, i, arr);put(x, j, arr);loop(i+1, j-1) } };loop(0, len-1)////// Rotate the contents of array `arr` by `n` steps to the left.///pubdefrotateLeft(rc2: Region[r2], n: Int32, arr: Array[a, r1]): Array[a, r2] \ { r1, r2 } =letlen = length(arr);if (len<1) Array#{} @ rc2elseif (n<0)rotateRightHelper(rc2, Int32.abs(n), arr)elserotateLeftHelper(rc2, n, arr)////// Helper function for `rotateLeft` and `rotateRight`.////// Precondition: `n` must be positive.////// This is an explicit helper to avoid code duplication.///defrotateLeftHelper(rc2: Region[r2], n: Int32, arr: Array[a, r1]): Array[a, r2] \ { r1, r2 } =letlen = length(arr);letf = i -> { leti1 = n+i; get(i1`Int32.remainder`len, arr) };init(rc2, f, len)////// Rotate the contents of array `arr` by `n` steps to the right.///pubdefrotateRight(rc2: Region[r2], n: Int32, arr: Array[a, r1]): Array[a, r2] \ { r1, r2 } =if (length(arr) <1) Array#{} @ rc2elseif (n<0)rotateLeftHelper(rc2, Int32.abs(n), arr)elserotateRightHelper(rc2, n, arr)////// Helper function for `rotateRight` and `rotateLeft`.////// Precondition: `n` must be positive.////// This is an explicit helper to avoid code duplication.///defrotateRightHelper(rc2: Region[r2], n: Int32, a: Array[a, r1]): Array[a, r2] \ { r1, r2 } =letlen = length(a);letn1 = n`Int32.remainder`len;letstart = len-n1;letf = i -> { leti1 = start+i; get(i1`Int32.remainder`len, a) };init(rc2, f, len)////// Returns a copy of `a` with the element at index `i` replaced by `x`.////// Returns a shallow copy of `a` if `i < 0` or `i > length(xs)-1`.///pubdefupdate(rc1: Region[r1], i: Int32, x: a, a: Array[a, r]): Array[a, r1] \ { r, r1 } =letlen = length(a);letf = ix -> if (ix==i) xelseget(ix, a);init(rc1, f, len)////// Replace every occurrence of `src` by `dst` in the array `a`, mutating it in place.///pubdefreplace(src: {src = a}, dst: {dst = a}, a: Array[a, r]): Unit \ rwithEq[a] =transform(e -> if (e==src#src) dst#dst elsee, a)////// Update the mutable array `b` replacing `n` elements starting at index `i` with the corresponding elements of array `a`.////// If any of the indices `i, i+1, i+2, ... , i+n-1` are out of range in `b` then no patching is done at these indices./// If `a` becomes depleted then no further patching is done./// If patching occurs at index `i+j` in `b`, then the element at index `j` in `a` is used.///pubdefpatch(i: Int32, n: Int32, a: Array[a, r1], b: Array[a, r2]): Unit \ { r1, r2 } = regionrc3 {letlen1 = length(a);letsize = if (n>len1) len1elsen;letsub = copyOfRange(rc3, 0, size, a);updateSequence(i, sub, b) }////// Returns `a` with `x` inserted between every two adjacent elements.///pubdefintersperse(rc1: Region[r1], x: a, a: Array[a, r]): Array[a, r1] \ { r, r1 } =letlen1 = length(a);letlen2 = len1+len1-1;if (len2<=0) Array#{} @ rc1else {letb = repeat(rc1, len2, x);letf = { (i, v) -> letj = i+i; Array.put(v, j, b) };forEachWithIndex(f, a);b }////// Returns the concatenation of the elements in `arrs` with the elements of `sep` inserted between every two adjacent elements.///pubdefintercalate(rc1: Region[r1], sep: Array[a, r], arrs: Array[Array[a, r], r]): Array[a, r1] \ { r, r1 } =letcount = length(arrs);letsepLength = length(sep);letsepCount = if (count<2) 0elsecount-1;letlen = sumLengths(arrs) + (sepCount*sepLength);matchheadArrays(arrs) {case None => Array#{} @ rc1case Some(x) =>letout = repeat(rc1, len, x);letoverwrite = { (st, a) ->let (pos, i) = st;if (i==0) {letpos1 = arrayWrites(0, a, out); (pos1, 1) } else {letpos1 = arrayWrites(pos, sep, out);letpos2 = arrayWrites(pos1, a, out); (pos2, i+1) } };discardfoldLeft(overwrite, (0, 0), arrs);out }////// Imperatively write `sub` at position `pos` in array `out`////// Return the new write position which is `pos + length(sub)`.////// Helper function for `intercalate` which needs to do successive writing.///defarrayWrites(pos: Int32, sub: Array[a, r1], out: Array[a, r2]): Int32 \ { r1, r2 } =updateSequence(pos, sub, out);pos+length(sub)////// Sum the lengths of an array of arrays.////// Helper function for `intercalate` and `flatten`.///defsumLengths(arrs: Array[Array[a, r1], r2]): Int32 \ r2 =foldLeft((acc, a) -> acc+length(a), 0, arrs)////// Find the first non-empty array of an array of arrays (left-to-right).////// Helper function for `intercalate` and `flatten`.///defheadArrays(arrs: Array[Array[a, r1], r2]): Option[a] \ { r1, r2 } =letlen = length(arrs);defloop(i) = {if (i>=len) Noneelsematchhead(get(i, arrs)) {case Some(x) => Some(x)case None => loop(i+1) } };loop(0)////// Returns the transpose of `a`.////// Returns `a` if the dimensions of the elements of `a` are mismatched.///pubdeftranspose(rc3: Region[r3], a: Array[Array[a, r1], r2]): Array[Array[a, r3], r3] \ { r1, r2, r3 } =letilen = length(a);if (ilen==0) Array#{} @ rc3else {letjlen = length(get(0, a));if (jlen==0oruniformHelper(a, jlen))// Non-transposing nested copyinit(rc3, i -> copyOfRange(rc3, 0, length(get(i, a)), get(i, a)), ilen)elseinit(rc3, i -> init(rc3, j -> a |> get(j) |> get(i), ilen), jlen) }////// Helper function for `transpose`.///defuniformHelper(a: Array[Array[a, r1], r2], l: Int32): Bool \ r2 =exists(x -> length(x) !=l, a)////// Returns `true` if and only if `a1` is a prefix of `a2`.///pubdefisPrefixOf(a1: Array[a, r1], a2: Array[a, r2]): Bool \ { r1, r2 } withEq[a] =letlen1 = length(a1);if (len1>length(a2))falseelsedefloop(i) = {if (i>=len1)trueelseif (get(i, a1) !=get(i, a2))falseelseloop(i+1) };loop(0)////// Returns `true` if and only if `a1` is an infix of `a2`.///pubdefisInfixOf(a1: Array[a, r1], a2: Array[a, r2]): Bool \ { r1, r2 } withEq[a] =letlen1 = length(a1);letlen2 = length(a2);if (len1>len2)falseelseif (len1==0)trueelseisInfixOfSearch(a1, a2, len1, len2, 0)////// Helper function for `isInfixOf` - scan a2 to find a match with first element of a1.////// Precondition: len1 (length of a1) > 0///defisInfixOfSearch(a1: Array[a, r1], a2: Array[a, r2], len1: Int32, len2: Int32, j: Int32): Bool \ { r1, r2 } withEq[a] =if (j>=len2)falseelseif (get(0, a1) ==get(j, a2))isInfixOfCheck(a1, a2, len1, len2, 1, j+1)elseisInfixOfSearch(a1, a2, len1, len2, j+1)////// Helper function for `isInfixOf` - a1 has started matching, scan to see if it all matches.///defisInfixOfCheck(a1: Array[a, r1], a2: Array[a, r2], len1: Int32, len2: Int32, i: Int32, j: Int32): Bool \ { r1, r2 } withEq[a] =if (i>=len1)// a1 exhausted, so successtrueelseif (j>=len2)// a2 exhausted, a1 still trying to match, so failurefalseelseif (get(i, a1) ==get(j, a2))isInfixOfCheck(a1, a2, len1, len2, i+1, j+1)elseisInfixOfSearch(a1, a2, len1, len2, j+1)////// Returns `true` if and only if `a1` is a suffix of `a2`.///pubdefisSuffixOf(a1: Array[a, r1], a2: Array[a, r2]): Bool \ { r1, r2 } withEq[a] =letlen1 = length(a1);letlen2 = length(a2);if (len1>len2)falseelsedefloop(i, j) = {if (i<0)trueelseif (get(i, a1) !=get(j, a2))falseelseloop(i-1, j-1) };loop(len1-1, len2-1)////// Returns the result of applying `combine` to all the elements in `a`, using `empty` as the initial value.///pubdeffold(arr: Array[a, r]): a \ rwithMonoid[a] = foldLeft(Monoid.combine, Monoid.empty(), arr)////// Applies `f` to a start value `s` and all elements in `a` going from left to right.////// That is, the result is of the form: `f(...f(f(s, a[0]), a[1])..., xn)`.///pubdeffoldLeft(f: (b, a) -> b \ ef, s: b, arr: Array[a, r]): b \ { ef, r } =letlen = length(arr);defloop(i, acc) = {if (i>=len)accelseloop(i+1, f(acc, get(i, arr))) };loop(0, s)////// Applies `f` to a start value `s` and all elements in `a` going from right to left.////// That is, the result is of the form: `f(a[0], ...f(a[n-1], f(a[n], s))...)`.///pubdeffoldRight(f: (a, b) -> b \ ef, s: b, arr: Array[a, r]): b \ { ef, r } =defloop(i, acc) = {if (i<0)accelseloop(i-1, f(get(i, arr), acc)) };loop(length(arr) -1, s)////// Returns the result of mapping each element and combining the results.///pubdeffoldMap(f: a -> b \ ef, arr: Array[a, r]): b \ { ef, r } withMonoid[b] =foldLeft((acc, x) -> Monoid.combine(acc, f(x)), Monoid.empty(), arr)////// Applies `f` to all elements in `a` going from left to right until a single value `v` is obtained. Returns `Some(v)`.////// Returns `None` if `a` is empty.///pubdefreduceLeft(f: (a, a) -> a \ ef, a: Array[a, r]): Option[a] \ { ef, r } =letlen = length(a);defloop(i, acc) = {if (i>=len)accelseloop(i+1, f(acc, get(i, a))) };if (len==0) Noneelse Some(loop(1, get(0, a)))////// Applies `f` to all elements in `arr` going from right to left until a single value `v` is obtained. Returns `Some(v)`.////// Returns `None` if `arr` is empty.///pubdefreduceRight(f: (a, a) -> a \ ef, arr: Array[a, r]): Option[a] \ { ef, r } =letlen = length(arr);defloop(i, acc) = {if (i<0)accelseloop(i-1, f(get(i, arr), acc)) };if (len==0) Noneelse Some(loop(len-2, get(len-1, arr)))////// Returns the number of elements in `a` that satisfy the predicate `f`.///pubdefcount(f: a -> Bool \ ef, a: Array[a, r]): Int32 \ { ef, r } =foldLeft((b, x) -> if (f(x)) b+1elseb, 0, a)////// Returns the sum of all elements in the array `a`.///pubdefsum(a: Array[Int32, r]): Int32 \ r =foldLeft((+), 0, a)////// Returns the sum of all elements in the array `a` according to the function `f`.///pubdefsumWith(f: a -> Int32 \ ef, a: Array[a, r]): Int32 \ { ef, r } =foldLeft((acc, x) -> acc+f(x), 0, a)////// Returns the concatenation of the arrays of in the array `arrs`.///pubdefflatten(rc1: Region[r1], arrs: Array[Array[a, r], r]): Array[a, r1] \ { r, r1 } =letlen = sumLengths(arrs);matchheadArrays(arrs) {case None => Array#{} @ rc1case Some(x) => {letout = repeat(rc1, len, x);discardfoldLeft((pos, a) -> arrayWrites(pos, a, out), 0, arrs);out } }////// Returns `true` if and only if at least one element in `arr` satisfies the predicate `f`.////// Returns `false` if `arr` is empty.///pubdefexists(f: a -> Bool \ ef, arr: Array[a, r]): Bool \ { ef, r } =letlen = length(arr);defloop(i) = {if (i>=len)falseelseif (f(get(i, arr)))trueelseloop(i+1) };loop(0)////// Returns `true` if and only if all elements in `arr` satisfy the predicate `f`.////// Returns `true` if `arr` is empty.///pubdefforAll(f: a -> Bool \ ef, arr: Array[a, r]): Bool \ { ef, r } =letlen = length(arr);defloop(i) = {if (i>=len)trueelseif (f(get(i, arr)))loop(i+1)elsefalse };loop(0)////// Returns an array of every element in `arr` that satisfies the predicate `f`.///pubdeffilter(rc1: Region[r1], f: a -> Bool \ ef, arr: Array[a, r]): Array[a, r1] \ { ef, r, r1 } =letlen = length(arr);if (len<1) { Array#{} @ rc1 } else {letout = empty(rc1, len);defloop(i, j) = {if (i>=len)jelse {letx = get(i, arr);if (f(x)) {Array.put(x, j, out);loop(i+1, j+1) } else {loop(i+1, j) } } };letendPos = loop(0, 0);copyOfRange(rc1, 0, endPos, out) }////// Returns a pair of arrays `(a1, a2)`.////// `a1` contains all elements of `a` that satisfy the predicate `f`./// `a2` contains all elements of `a` that do not satisfy the predicate `f`.///pubdefpartition(rc1: Region[r1], rc2: Region[r2], f: a -> Bool \ ef, a: Array[a, r]): (Array[a, r1], Array[a, r2]) \ { ef, r, r1, r2 } =letstep = {x -> match (a1, a2) ->if (f(x)) (x :: a1, a2) else (a1, x :: a2) };let (xs, ys) = foldRight(step, (Nil, Nil), a); (List.toArray(rc1, xs), List.toArray(rc2, ys))////// Returns a pair of arrays `(a1, a2)`.////// `a1` is the longest prefix of `a` that satisfies the predicate `f`./// `a2` is the remainder of `a`.///pubdefspan(rc1: Region[r1], rc2: Region[r2], f: a -> Bool \ ef, a: Array[a, r]): (Array[a, r1], Array[a, r2]) \ { ef, r, r1, r2 } =matchfindIndexOfLeft(x -> not (f(x)), a) {case None => (takeLeft(rc1, length(a), a), Array#{} @ rc2)case Some(i) => (takeLeft(rc1, i, a), dropLeft(rc2, i, a)) }////// Alias for `dropLeft`.///pubdefdrop(rc1: Region[r1], n: Int32, a: Array[a, r]): Array[a, r1] \ { r, r1 } =dropLeft(rc1, n, a)////// Returns a copy of array `a`, dropping the first `n` elements.////// Returns `[]` if `n > length(a)`.///pubdefdropLeft(rc1: Region[r1], n: Int32, a: Array[a, r]): Array[a, r1] \ { r, r1 } =letlen = length(a);if (n>len) Array#{} @ rc1else {letstart = if (n<0) 0elsen;copyOfRange(rc1, start, len, a) }////// Returns a copy of array `a`, dropping the last `n` elements.////// Returns `[]` if `n > length(a)`.///pubdefdropRight(rc1: Region[r1], n: Int32, a: Array[a, r]): Array[a, r1] \ { r, r1 } =letlen = length(a);if (n>=len) Array#{} @ rc1else {letend = if (n<0) lenelselen-n;copyOfRange(rc1, 0, end, a) }////// Alias for `dropWhileLeft`.///pubdefdropWhile(rc1: Region[r1], f: a -> Bool \ ef, a: Array[a, r]): Array[a, r1] \ { ef, r, r1 } =dropWhileLeft(rc1, f, a)////// Returns copy of array `a` without the longest prefix that satisfies the predicate `f`.///pubdefdropWhileLeft(rc1: Region[r1], f: a -> Bool \ ef, a: Array[a, r]): Array[a, r1] \ { ef, r, r1 } =matchfindIndexOfLeft(x -> not (f(x)), a) {case None => Array#{} @ rc1case Some(i) => dropLeft(rc1, i, a) }////// Returns copy of array `a` without the longest suffix that satisfies the predicate `f`.///pubdefdropWhileRight(rc1: Region[r1], f: a -> Bool \ ef, a: Array[a, r]): Array[a, r1] \ { ef, r, r1 } =matchfindIndexOfRight(x -> not (f(x)), a) {case None => Array#{} @ rc1case Some(i) => copyOfRange(rc1, 0, i+1, a) }////// Alias for `takeLeft`.///pubdeftake(rc1: Region[r1], n: Int32, a: Array[a, r]): Array[a, r1] \ { r, r1 } =takeLeft(rc1, n, a)////// Returns a fresh array taking first `n` elements of `a`.////// Returns `a` if `n > length(xs)`.///pubdeftakeLeft(rc1: Region[r1], n: Int32, a: Array[a, r]): Array[a, r1] \ { r, r1 } =if (n<=0) Array#{} @ rc1else {letlen = length(a);letend = if (n>len) lenelsen;copyOfRange(rc1, 0, end, a) }////// Returns a fresh array taking last `n` elements of `a`.////// Returns `a` if `n > length(xs)`.///pubdeftakeRight(rc1: Region[r1], n: Int32, a: Array[a, r]): Array[a, r1] \ { r, r1 } =if (n<=0) Array#{} @ rc1else {letlen = length(a);letstart = if (n>len) 0elselen-n;copyOfRange(rc1, start, len, a) }////// Alias for `takeWhileLeft`.///pubdeftakeWhile(rc1: Region[r1], f: a -> Bool \ ef, a: Array[a, r]): Array[a, r1] \ { ef, r, r1 } =takeWhileLeft(rc1, f, a)////// Returns the longest prefix of `a` that satisfies the predicate `f`.///pubdeftakeWhileLeft(rc1: Region[r1], f: a -> Bool \ ef, a: Array[a, r]): Array[a, r1] \ { ef, r, r1 } =matchfindIndexOfLeft(x -> not (f(x)), a) {case None => copyOfRange(rc1, 0, length(a), a)case Some(i) => takeLeft(rc1, i, a) }////// Returns the longest suffix of `a` that satisfies the predicate `f`.///pubdeftakeWhileRight(rc1: Region[r1], f: a -> Bool \ ef, a: Array[a, r]): Array[a, r1] \ { ef, r, r1 } =matchfindIndexOfRight(x -> not (f(x)), a) {case None => copyOfRange(rc1, 0, length(a), a)case Some(i) => copyOfRange(rc1, i+1, length(a), a) }////// Partitions `a` into subarrays such that for any two elements `x` and `y` in a subarray, `f(x, y)` is true.////// A subarray is created by iterating through the remaining elements of `a` from left to right and adding an/// element to the subarray if and only if doing so creates no conflicts with the elements already in the subarray.////// The function `f` must be pure and define an equivalence relation.///pubdefgroupWith(rc1: Region[r1], f: (a, a) -> Bool, a: Array[a, r2]): Array[Array[a, r1], r1] \ { r2, r1 } =letxs = toList(a);groupByHelper(rc1, f, xs, Nil) |> List.toArray(rc1)////// Partitions `a` into subarrays such that for any two elements `x` and `y` in a subarray,/// if `f(x)` and `f(y)` are equal according to `Eq` on `b`.////// A subarray is created by iterating through the remaining elements of `a` from left to right and adding an/// element to the subarray if and only if doing so creates no conflicts with the elements already in the subarray.///pubdefgroupBy(rc1: Region[r2], f: a -> b, a: Array[a, r1]): Array[Array[a, r2], r2] \ { r1, r2 } withEq[b] =groupWith(rc1, Eq.eq`on`f, a)////// Helper function for `groupWith`.///defgroupByHelper(rc: Region[r], f: (a, a) -> Bool, xs: List[a], ac: List[Array[a, r]]): List[Array[a, r]] \ r = matchxs {case Nil => List.reverse(ac)casex :: rs =>let (rc1, rc2) = extractHelper(rc, f, rs, Nel.singleton(x), Nil);groupByHelper(rc, f, rc2, rc1 :: ac) }////// Helper function for `groupWith`.///defextractHelper(rc: Region[r], f: (a, a) -> Bool, xs: List[a], ps: Nel[a], ns: List[a]): (Array[a, r], List[a]) \ r = matchxs {case Nil => {leta = Nel.reverse(ps); (Nel.toArray(rc, a), List.reverse(ns)) }casex :: rs =>if (f(x, Nel.head(ps)))extractHelper(rc, f, rs, Nel.cons(x, ps), ns)elseextractHelper(rc, f, rs, ps, x :: ns) }////// Returns an array where the element at index `i` is `(x, y)` where/// `x` is the element at index `i` in `a` and `y` is the element at index `i` in `b`.////// If either `a` or `b` becomes depleted, then no further elements are added to the resulting array.///pubdefzip(rc3: Region[r3], a: Array[a, r1], b: Array[b, r2]): Array[(a, b), r3] \ { r1, r2, r3 } =letlen = Int32.min(length(a), length(b));init(rc3, i -> (get(i, a), get(i, b)), len)////// Returns an array where the element at index `i` is `f(x, y)` where/// `x` is the element at index `i` in `a` and `y` is the element at index `i` in `b`.////// If either `a` or `b` becomes depleted, then no further elements are added to the resulting array.///pubdefzipWith(rc3: Region[r3], f: (a, b) -> c \ ef, a: Array[a, r1], b: Array[b, r2]): Array[c, r3] \ { ef, r1, r2, r3 } =letlen = Int32.min(length(a), length(b));init(rc3, i -> f(get(i, a), get(i, b)), len)////// Returns a pair of arrays, the first containing all first components in `a`/// and the second containing all second components in `a`.///pubdefunzip(rc1: Region[r1], rc2: Region[r2], a: Array[(a, b), r3]): (Array[a, r1], Array[b, r2]) \ { r1, r2, r3 } =letlen = length(a);if (len<=0) (Array#{} @ rc1, Array#{} @ rc2)else {let (x, y) = get(0, a);letarr = repeat(rc1, len, x);letbrr = repeat(rc2, len, y);defloop(i) = {if (i<len) {let (l, r) = get(i, a);Array.put(l, i, arr);Array.put(r, i, brr);loop(i+1) } else() };loop(1); (arr, brr) }////// Alias for `foldLeft2`.///pubdeffold2(f: (c, a, b) -> c \ ef, c: c, a: Array[a, r1], b: Array[b, r2]): c \ { ef, r1, r2 } =foldLeft2(f, c, a, b)////// Accumulates the result of applying `f` pairwise to the elements of `a` and `b`/// starting with the initial value `c` and going from left to right.///pubdeffoldLeft2(f: (c, a, b) -> c \ ef, c: c, a: Array[a, r1], b: Array[b, r2]): c \ { ef, r1, r2 } =letlena = length(a);letlenb = length(b);defloop(i, acc) = {if (i>=lenaori>=lenb)accelseloop(i+1, f(acc, get(i, a), get(i, b))) };loop(0, c)////// Accumulates the result of applying `f` pairwise to the elements of `a` and `b`/// starting with the initial value `c` and going from right to left.///pubdeffoldRight2(f: (a, b, c) -> c \ ef, c: c, a: Array[a, r1], b: Array[b, r2]): c \ { ef, r1, r2 } =defloop(i, j, acc) = {if (i<0orj<0)accelseloop(i-1, j-1, f(get(i, a), get(j, b), acc)) };letstarta = length(a) -1;letstartb = length(b) -1;loop(starta, startb, c)////// Collects the results of applying the partial function `f` to every element in `a`.///pubdeffilterMap(rc1: Region[r1], f: a -> Option[b] \ ef, a: Array[a, r]): Array[b, r1] \ { ef, r, r1 } =foldRight( (x, xs) -> matchf(x) {case None => xscase Some(b) => b :: xs }, Nil,a ) |> List.toArray(rc1)////// Returns the first non-None result of applying the partial function `f` to each element of `xs`.////// Returns `None` if every element of `xs` is `None`.///pubdeffindMap(f: a -> Option[b] \ ef, a: Array[a, r]): Option[b] \ { ef, r } =letlen = length(a);defloop(i) = {if (i>=len) Noneelseletx = f(get(i, a));matchx {case Some(v) => Some(v)case None => loop(i+1) } };loop(0)////// Returns the array `a` as a set.///pubdeftoSet(a: Array[a, r]): Set[a] \ rwithOrder[a] =foldRight(Set.insert, Set.empty(), a)////// Returns the association list `xs` as a map.////// If `xs` contains multiple mappings with the same key, `toMap` does not/// make any guarantees about which mapping will be in the resulting map.///pubdeftoMap(a: Array[(a, b), r]): Map[a, b] \ rwithOrder[a] =foldRight((x, m) -> Map.insert(fst(x), snd(x), m), Map.empty(), a)////// Alias for `findIndexOfLeft`.///pubdeffindIndexOf(f: a -> Bool \ ef, a: Array[a, r]): Option[Int32] \ { ef, r } =findIndexOfLeft(f, a)////// Optionally returns the position of the first element in `x` satisfying `f`.///pubdeffindIndexOfLeft(f: a -> Bool \ ef, a: Array[a, r]): Option[Int32] \ { ef, r } =letlen = length(a);if (len<1) Noneelse {defloop(i) = {if (i>=len) -1elseif (f(get(i, a)))ielseloop(i+1) };leti = loop(0);if (i<0) None else Some(i) }////// Optionally returns the position of the first element in `a` satisfying `f`/// searching from right to left.///pubdeffindIndexOfRight(f: a -> Bool \ ef, a: Array[a, r]): Option[Int32] \ { ef, r } =letlen = length(a);defloop(i) = {if (i<0) -1elseif (f(get(i, a)))ielseloop(i-1) };leti = loop(len-1);if (i<0) None else Some(i)////// Returns the positions of the all the elements in `a` satisfying `f`.///pubdeffindIndices(f: a -> Bool \ ef, a: Array[a, r]): Vector[Int32] \ { ef, r } = regionrc {letlen = length(a);letl = MutList.empty(rc);defloop(i) = {if (i>=len)()else {if (f(get(i, a))) { MutList.push(i, l) };loop(i+1) } };loop(0);MutList.toVector(l) }////// Build an array of length `len` by applying `f` to the successive indices.///pubdefinit(rc: Region[r], f: Int32 -> a \ ef, len: Int32): Array[a, r] \ { ef, r } =if (len<=0) Array#{} @ rcelse {letx = f(0);leta = Array.repeat(rc, len, x);defloop(i) = {if (i<len) {Array.put(f(i), i, a);loop(i+1) } else() };loop(1);a }////// Returns `true` if arrays `a` and `b` have the same elements in the same order, i.e. are structurally equal.///pubdefsameElements(a: Array[a, r1], b: Array[a, r2]): Bool \ { r1, r2 } withEq[a] =letalen = length(a);letblen = length(b);defloop(i) = {if (i>=alen)trueelseif (get(i, a) !=get(i, b))falseelseloop(i+1) };if (alen==blen)loop(0)elsefalse////// Returns an iterator over `a`////// Modifying `a` while using an iterator has undefined behavior and is dangerous.///pubdefiterator(rc: Region[r1], a: Array[a, r2]): Iterator[a, r1 + r2, r1] \ r1 =Iterator.range(rc, 0, length(a)) |> Iterator.map(i -> Array.get(i, a))////// Apply the effectful function `f` to all the elements in the array `a`.///pubdefforEach(f: a -> Unit \ ef, a: Array[a, r]): Unit \ { ef, r } =letlen = length(a);defloop(i) = {if (i>=len)()else {f(get(i, a));loop(i+1) } };loop(0)////// Apply the effectful function `f` to all the elements in the array `a`.///pubdefforEachWithIndex(f: (Int32, a) -> Unit \ ef, a: Array[a, r]): Unit \ { ef, r } =letlen = length(a);defloop(i) = {if (i>=len)()else {f(i, get(i, a));loop(i+1) } };loop(0)////// Update the mutable array `a` with the elements starting at index `i` replaced by `sub`.///pubdefupdateSequence(i: Int32, sub: Array[a, r1], a: Array[a, r2]): Unit \ { r1, r2 } =letend = i+length(sub);letf = { (ix, _) ->if (ix>=iandix<end)Array.put(get(ix-i, sub), ix, a)else() };forEachWithIndex(f, a)////// Returns the concatenation of the string representation/// of each element in `a` with `sep` inserted between each element.///pubdefjoin(sep: String, a: Array[a, r]): String \ rwithToString[a] = regionrc {Array.iterator(rc, a) |> Iterator.join(sep) }////// Returns the concatenation of the string representation/// of each element in `a` according to `f` with `sep` inserted between each element.///pubdefjoinWith(f: a -> String \ ef, sep: String, a: Array[a, r]): String \ { ef, r } = regionrc {Array.iterator(rc, a) |> Iterator.joinWith(f, sep) }////// Sort array `a` so that elements are ordered from low to high according to their `Order` instance./// The array is mutated in-place.////// The sort is not stable, i.e., equal elements may appear in a different order than in the input `a`.////// The sort implementation is a Quicksort.///pubdefsort(a: Array[a, r]): Unit \ rwithOrder[a] =sortWith(Order.compare, a)////// Sort array `a` so that elements are ordered from low to high according to the `Order` instance for/// the values obtained by applying `f` to each element. The array is mutated in-place.////// The sort is not stable, i.e., equal elements may appear in a different order than in the input `a`.////// The sort implementation is a Quicksort.///pubdefsortBy(f: a -> b, a: Array[a, r]): Unit \ rwithOrder[b] =sortWith(Order.compare`on`f, a)////// Sort array `a` so that elements are ordered from low to high according to the comparison function `cmp`./// The array is mutated in-place.////// The sort is not stable, i.e., equal elements may appear in a different order than in the input `a`.////// The sort implementation is a Quicksort.///pubdefsortWith(cmp: (a, a) -> Comparison, a: Array[a, r]): Unit \ r =sortWithin(cmp, 0, length(a) -1, a)////// Sort array `a` between the indices `lo` and `hi` (both inclusive) so that elements in that range are ordered/// from low to high according to the comparison function `cmp`. The array is mutated in-place where elements/// outside the specified range are not changed. If `lo >= hi`, this does nothing.////// The sort is not stable, i.e., equal elements may appear in a different order than in the input `a`.////// The sort implementation is a Quicksort.///pubdefsortWithin(cmp: (a, a) -> Comparison, lo: Int32, hi: Int32, a: Array[a, r]): Unit \ r =if (lo>=hi)()else {letp = quicksortPartition(cmp, a, lo, hi);sortWithin(cmp, lo, p-1, a);sortWithin(cmp, p+1, hi, a) }////// Swap the elements at `i` and `j` (helper for sorting).////// Precondition: `i` and `j` are within bounds.///pubdefswap(i: Int32, j: Int32, a: Array[a, r]): Unit \ r =letx = get(i, a);lety = get(j, a);Array.put(y, i, a);Array.put(x, j, a)////// Partition step of the Quicksort algorithm.///defquicksortPartition(cmp: (a, a) -> Comparison, a: Array[a, r], lo: Int32, hi: Int32): Int32 \ r =letpivot = get(hi, a);leti = forWithAccum(lo,hi-1,lo, (j, ix) ->if (cmp(get(j, a), pivot) == Comparison.LessThan) {swap(ix, j, a);ix+1 } elseix );swap(i, hi, a);i////// A for loop with an accumulator (helper for sorting).////// precondition: lo <= hi///defforWithAccum(lo: Int32, hi: Int32, ac: a, f: (Int32, a) -> a \ ef): a \ ef =if (lo>hi)acelseif (lo==hi)f(lo, ac)else {letac1 = f(lo, ac);forWithAccum(lo+1, hi, ac1, f) }////// Perform a binary search for `x` on the sorted array `a` and returns the position of `x`.////// Returns `None` if `a` does not contain `x`. Otherwise returns `Some(i)`,/// where `Array.get(i, a) == x`.////// Assumes `a` is sorted. If this is not the case the result is undefined.////// If `a` contains multiple `x`-values then the index of one of them will be returned.///pubdefbinarySearch(x: a, a: Array[a, r]): Option[Int32] \ rwithOrder[a] =deff(lo, hi) = {if (lo<=hi) {letmid = (lo+hi) `Int32.rightShift`1; // Shifting by 1 is slightly faster than dividing by 2.matchget(mid, a) <=>x {case Comparison.LessThan => f(mid+1, hi)case Comparison.GreaterThan => f(lo, mid-1)case Comparison.EqualTo => Some(mid) } } else None };letlen = length(a);f(0, len-1)////// Copies the range between `srcPos` (inclusive) to `srcPos + len` (exclusive) of `src` into `dst` starting from `dstPos` (inclusive)./// A valid range has the following properties:/// 0 <= len./// 0 <= `srcPos`./// 0 <= `dstPos`./// `srcPos + len` <= `length(src)`./// `dstPos + len` <= `length(dst)`.////// If `src` and `dst` refer to the same array the result will be as though the range was copied to a separate array before pasting to the `dst` array.pubdefcopyInto(srcPos: {srcPos = Int32}, dstPos: {dstPos = Int32}, len: {len = Int32}, src: {src = Array[a, r1]}, dst: Array[a, r2]): Unit \ { r1, r2 } =letsrcObj: Object = checked_cast(src#src);letdstObj: Object = checked_cast(dst);unsafeIOas { r1, r2 } { System.arraycopy(srcObj, srcPos#srcPos, dstObj, dstPos#dstPos, len#len) }////// Returns a shallow copy of the array `a`.///pubdefcopy(rc: Region[r2], a: Array[a, r1]): Array[a, r2] \ { r1, r2 } =copyOfRange(rc, 0, length(a), a)////// Copies the range between `b` (inclusive) and `e` (exclusive) of a into an empty array.////// A valid range has the following properties:/// - 0 <= `b` <= `length(a)`./// - `e` >= `b`./// If the range is valid and greater than the length of `a`, the resulting array will have the length of the range/// and include the specified range of `a`.///pubdefcopyOfRange(_: Region[r2], b: Int32, e: Int32, a: Array[a, r1]): Array[a, r2] \ { r1, r2 } = {use Reflect.JvmType;// All of the below casts are required to cast the type to `Array[a, ...]`.matchReflect.reflectType((Proxy.Proxy: Proxy[a])) {// The casts here are used to both modify the java method type and to simulate GADT typingcase JvmType.JvmBool =>letarr = unchecked_cast(aasArray[Bool, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmChar =>letarr = unchecked_cast(aasArray[Char, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmInt8 =>letarr = unchecked_cast(aasArray[Int8, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmInt16 =>letarr = unchecked_cast(aasArray[Int16, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmInt32 =>letarr = unchecked_cast(aasArray[Int32, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmInt64 =>letarr = unchecked_cast(aasArray[Int64, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmFloat32 =>letarr = unchecked_cast(aasArray[Float32, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmFloat64 =>letarr = unchecked_cast(aasArray[Float64, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 })case JvmType.JvmObject =>letarr = unchecked_cast(aasArray[Object, r1]);unchecked_cast(Arrays.copyOfRange(arr, b, e) asArray[a, r2] \ { r1, r2 }) } }////// Shuffles `a` using a random permutation.///pubdefshuffle(a: Array[a, r]): Unit \ { r, Shuffle } = {letlen = Array.length(a);// Compute a random permutation.letperm = Shuffle.permutation(len);// Apply the permutation: result[i] = a[perm[i]].letresult = Vector.init(i -> Array.get(Vector.get(i, perm), a), len);// Write the result back into a.Vector.forEachWithIndex((i, v) -> Array.put(v, i, a), result) }}