staload "libc/SATS/random.sats"
staload "libats/SATS/ilistp.sats"
stadef nil = ilist_nil
stadef cons = ilist_cons
abst@ype E (a: t@ype, x:int) = a
extern castfn encode {a:t@ype} (x: a):<> [x:pos] E (a, x)
extern castfn decode {a:t@ype} {x:int} (x: E (a, x)):<> a
extern
fun{a:t@ype}
lte_elt_elt {x,y:nat} (x: E(a, x), y: E (a, y)):<> bool (x <= y)
overload <= with lte_elt_elt
datatype list (a:t@ype, ilist) =
| nil (a, nil) of ()
| {x:pos} {xs: ilist} cons (a, cons (x, xs)) of (E (a, x), list (a, xs))
typedef list (a:t@ype) = [xs:ilist] list (a, xs)
extern
fun{a:t@ype}
quicksort {xs:ilist}
(xs: list (a, xs)): [ys:ilist] (PERMUTE (xs, ys) | list (a, ys))
extern
fun{a:t@ype}
append {xs1,xs2:ilist}
(xs1: list (a, xs1), xs2: list (a, xs2))
: [xs3: ilist] (APPEND (xs1, xs2, xs3) | list (a, xs3))
implement{a}
append {xs1,xs2}
(xs1, xs2) = case+ xs1 of
| cons {x1} (x1, xs11) => let
val [xs31:ilist] (pf1 | xs31) = append (xs11, xs2)
in
(APPENDcons (pf1) | cons (x1, xs31))
end | nil () => (APPENDnil () | xs2)
propdef
MUNION (xs1:ilist, xs2:ilist, xs3:ilist) =
{x0:int} {n1,n2:nat}
(MSETCNT (x0, xs1, n1), MSETCNT (x0, xs2, n2)) -<prf> MSETCNT (x0, xs3, n1+n2)
extern
prfun append_munion_lemma
{xs,ys,zs:ilist} (pf: APPEND (xs,ys,zs)): MUNION (xs, ys, zs)
implement
append_munion_lemma
(pf) = lemma (pf) where {
prfun lemma {xs,ys,zs:ilist} .<xs>.
(pf: APPEND (xs,ys,zs)): MUNION (xs, ys, zs) =
case+ pf of
| APPENDcons (pf) => let
prval fpf = lemma (pf) in
lam (pf1, pf2) => let
prval MSETCNTcons pf1 = pf1 in MSETCNTcons (fpf (pf1, pf2))
end end
| APPENDnil () =>
lam (pf1, pf2) => let
prval MSETCNTnil () = pf1 in pf2
end
}
propdef PART (
x: int, xs0: ilist, xs1: ilist, xs2: ilist, xs: ilist
) = {x0:int} {n0,n1,n2:nat} (
MSETCNT (x0, xs0, n0), MSETCNT (x0, xs1, n1), MSETCNT (x0, xs2, n2)
) -<prf> MSETCNT (x0, xs, n0+n1+n2+b2i(x0==x))
fun{a:t@ype}
qsrt {xs:ilist} (
xs: list (a, xs)
) : [ys:ilist] (PERMUTE (xs, ys) | list (a, ys)) =
case+ xs of
| cons {x} {xs1} (x, xs1) => let
val [ys:ilist] (fpf | ys) = part (x, xs1, nil (), nil ())
prval fpf = lam {x0:int} {n:nat}
(pf: MSETCNT (x0, xs, n)): MSETCNT (x0, ys, n) =<prf> let
prval MSETCNTcons pf = pf
in
fpf (pf, MSETCNTnil, MSETCNTnil)
end in
(fpf | ys)
end | nil () => (permute_refl {ilist_nil} () | nil ())
and
part {x:pos}
{xs,xs1,xs2:ilist} (
x: E (a, x)
, xs: list (a, xs)
, xs1: list (a, xs1)
, xs2: list (a, xs2)
) : [ys:ilist] (PART (x, xs, xs1, xs2, ys) | list (a, ys)) =
case xs of
| cons (x_, xs_) => (
if (x_ <= x) then let
val [ys:ilist] (fpf | ys) = part (x, xs_, cons (x_, xs1), xs2)
prval fpf = lam {x0:int} {n0,n1,n2:nat}
(pf0: MSETCNT (x0, xs, n0), pf1: MSETCNT (x0, xs1, n1), pf2: MSETCNT (x0, xs2, n2))
: MSETCNT (x0, ys, n0+n1+n2+b2i(x0==x)) =<prf> let
prval MSETCNTcons pf0 = pf0
prval pf1 = MSETCNTcons (pf1)
in
fpf (pf0, pf1, pf2)
end in
(fpf | ys)
end else let
val [ys:ilist] (fpf | ys) = part (x, xs_, xs1, cons (x_, xs2))
prval fpf = lam {x0:int} {n0,n1,n2:nat}
(pf0: MSETCNT (x0, xs, n0), pf1: MSETCNT (x0, xs1, n1), pf2: MSETCNT (x0, xs2, n2))
: MSETCNT (x0, ys, n0+n1+n2+b2i(x0==x)) =<prf> let
prval MSETCNTcons pf0 = pf0
prval pf2 = MSETCNTcons (pf2)
in
fpf (pf0, pf1, pf2)
end in
(fpf | ys)
end ) | nil () => let
val [ys1:ilist] (fpf1 | ys1) = qsrt (xs1)
val [ys2:ilist] (fpf2 | ys2) = qsrt (xs2)
val [ys:ilist] (pf3 | ys) = append (ys1, cons (x, ys2))
prval fpf3 = append_munion_lemma (pf3)
prval fpf = lam {x0:int} {n0,n1,n2:nat}
(pf0: MSETCNT (x0, xs, n0), pf1: MSETCNT (x0, xs1, n1), pf2: MSETCNT (x0, xs2, n2))
: MSETCNT (x0, ys, n0+n1+n2+b2i(x0==x)) =<prf> let
prval MSETCNTnil () = pf0
prval pf1 = fpf1 (pf1) prval pf2 = fpf2 (pf2) in
fpf3 (pf1, MSETCNTcons (pf2))
end in
(fpf | ys)
end
implement{a} quicksort (xs) = qsrt<a> (xs)
implement
lte_elt_elt<double>
{x,y} (x, y) = let
val x = decode (x) and y = decode(y)
extern castfn __cast (_: bool):<> bool (x <= y)
in
__cast (lte_double_double (x, y))
end
fn print_list (
xs: list (double)
) : void = let
fun aux (
xs: list (double), i: int
) : void = begin
case+ xs of
| cons (x, xs) => let
val x = decode (x)
in
if i > 0 then print ", "; printf ("%.2f", @(x)); aux (xs, i+1)
end | nil () => ()
end in
aux (xs, 0)
end
fun randgen_list
{n:nat} .<n>.
(n: int n): list (double) =
if n > 0 then let
val x = drand48 ()
val x = encode (x)
in
cons {double} (x, randgen_list (n-1))
end else nil ()
implement main () = let
val () = srand48_with_time ()
val xs = randgen_list (20)
val () = (print "xs = "; print_list xs; print_newline ())
val (_fpf | ys) = quicksort (xs)
val () = (print "ys = "; print_list ys; print_newline ())
in
end