```(*
** Course: Concepts of Programming Languages (BU CAS CS 320)
** Semester: Summer I, 2009
** Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
*)

//
// author: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
//

(* ****** ****** *)

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
// end of [extern]

implement{a}
array_ptr_shuffle
(pf | p, n) = loop (pf | p, n) where {
#define i2sz size1_of_int1; #define sz2i int1_of_size1
(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
// nothing
end // end of [if]
// end of [loop]
} (* end of [array_ptr_shuffle] *)

(* ****** ****** *)

(*

// this is for shuffling a persistent array
extern fun{a:t@ype} array0_shuffle (A: array0 a):<!ref> void

implement{a} array0_shuffle (A) = let
val r = array0_get_arraysize_ref {a} (A)
val (vbox pf_asz | p_asz) = ref_get_view_ptr {Arraysize a} (r)
in
array_ptr_shuffle<a> (p_asz->1 | p_asz->2, p_asz->3)
end // end of [array0_shuffle]

*)

(* ****** ****** *)

extern
fun{a:t@ype}
list0_shuffle (xs: list0 a):<> list0 a

implement{a}
list0_shuffle (xs) =
list0_of_list (xs) where {
val [n:int] xs = list_of_list0 (xs)
val n = list_length (xs); val n = size1_of_int1 (n)
var !p_arr with pf_arr = @[a][n]() // stack allocation
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
// end of [loop]
} (* end of [val] *)
} (* end of [list0_shuffle] *)

(* ****** ****** *)

(* end of [list0_shuffle.dats] *)
```