extern fun{a:t@ype} array_ptr_shuffle
{n:nat} {l:addr} (pf: !array_v (a, n, l) | p: ptr l, n: size_t n):<> void
staload RAND = "libc/SATS/random.sats"
implement{a} array_ptr_shuffle
(pf | p, n) = loop (pf | p, n) where {
#define i2sz size1_of_int1; #define sz2i int1_of_size1
fun loop {n:nat} {l:addr} .<n>.
(pf: !array_v (a, n, l) | p: ptr l, n: size_t n):<> void =
if n >= 2 then let
val i = $effmask_ref ($RAND.randint (sz2i n))
val () = if i <> 0 then array_ptr_exch<a> (!p, 0, i2sz i)
prval (pf1, pf2) = array_v_uncons {a} (pf)
val () = loop (pf2 | p + sizeof<a>, n-1)
prval () = pf := array_v_cons {a} (pf1, pf2)
in
end }
extern fun{a:t@ype} list0_shuffle (xs: list0 a):<> list0 a
implement{a}
list0_shuffle (xs) = list0_of_list1 (xs) where {
val [n:int] xs = list1_of_list0 (xs)
val n = list_length (xs); val n = size1_of_int1 (n)
var !p_arr with pf_arr = @[a][n]() val () = array_ptr_initialize_lst<a> (!p_arr, xs)
val () = array_ptr_shuffle (pf_arr | p_arr, n)
val xs = loop (!p_arr, n, list_nil) where {
fun loop {i:nat | i <= n} .<i>.
(A: & @[a][n], i: size_t i, res: list (a, n-i)):<> list (a, n) =
if i > 0 then let
val i = i - 1 in loop (A, i, list_cons (A.[i], res))
end else res
}
}