ocaml/test/Moretest/sorts.ml

3837 lines
104 KiB
OCaml
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

(*
ocamlopt -noassert sorts.ml -cclib -lunix
*)
open Printf;;
(*
Criteres:
0. overhead en pile: doit etre logn au maximum.
1. stable ou non.
2. overhead en espace.
3. vitesse.
*)
(* FIXME: faire des tests sur des longueurs non puissances de 2 *)
(* FIXME: faire des tests sur des flottants avec une machine 32 bits *)
(* FIXME: merge sort avec listes mutables *)
(* FIXME: merge sort avec listes initiales maximales *)
(************************************************************************)
(* auxiliary functions *)
let rec exp2 n = if n <= 0 then 1 else 2 * exp2 (n-1);;
let id x = x;;
let postl x y = Array.of_list y;;
let posta x y = x;;
let mkconst n = Array.make n 0;;
let chkconst _ n a = (a = mkconst n);;
let mksorted n =
let a = Array.make n 0 in
for i = 0 to n - 1 do
a.(i) <- i;
done;
a
;;
let chksorted _ n a = (a = mksorted n);;
let mkrev n =
let a = Array.make n 0 in
for i = 0 to n - 1 do
a.(i) <- n - 1 - i;
done;
a
;;
let chkrev _ n a = (a = mksorted n);;
let seed = ref 0;;
let random_reinit () = Random.init !seed;;
let random_get_state () =
let a = Array.make 55 0 in
for i = 0 to 54 do a.(i) <- Random.bits (); done;
Random.full_init a;
a
;;
let random_set_state a = Random.full_init a;;
let chkgen mke cmp rstate n a =
let marks = Array.make n (-1) in
let skipmarks l =
if marks.(l) = -1 then l else begin
let m = ref marks.(l) in
while marks.(!m) <> -1 do incr m; done;
marks.(l) <- !m;
!m
end
in
let linear e l =
let l = skipmarks l in
let rec loop l =
if cmp a.(l) e > 0 then raise Exit
else if e = a.(l) then marks.(l) <- l+1
else loop (l+1)
in loop l
in
let rec dicho e l r =
if l = r then linear e l
else begin
assert (l < r);
let m = (l + r) / 2 in
if cmp a.(m) e >= 0 then dicho e l m else dicho e (m + 1) r
end
in
try
for i = 0 to n-2 do if cmp a.(i) a.(i+1) > 0 then raise Exit; done;
random_set_state rstate;
for i = 0 to n-1 do dicho (mke i) 0 (Array.length a - 1); done;
true
with Exit | Invalid_argument _ -> false;
;;
let mkrand_dup n =
let a = Array.make n 0 in
for i = 0 to (n-1) do a.(i) <- Random.int n; done;
a
;;
let chkrand_dup rstate n a =
chkgen (fun i -> Random.int n) compare rstate n a
;;
let mkrand_nodup n =
let a = Array.make n 0 in
for i = 0 to (n-1) do a.(i) <- Random.bits (); done;
a
;;
let chkrand_nodup rstate n a =
chkgen (fun i -> Random.bits ()) compare rstate n a
;;
type record = {
s1 : string;
s2 : string;
i1 : int;
i2 : int;
};;
let rand_string () =
let len = Random.int 10 in
let s = String.create len in
for i = 0 to len-1 do
s.[i] <- Char.chr (Random.int 256);
done;
s
;;
let mkrec1 b i = {
s1 = rand_string ();
s2 = rand_string ();
i1 = Random.int b;
i2 = i;
};;
let mkrecs b n = Array.init n (mkrec1 b);;
let mkrec1_rev b i = {
s1 = rand_string ();
s2 = rand_string ();
i1 = - i;
i2 = i;
};;
let mkrecs_rev n = Array.init n (mkrec1_rev 0);;
let cmpstr r1 r2 =
let c1 = compare r1.s1 r2.s1 in
if c1 = 0 then compare r1.s2 r2.s2 else c1
;;
let lestr r1 r2 =
let c1 = compare r1.s1 r2.s1 in
if c1 = 0 then r1.s2 <= r2.s2 else (c1 < 0)
;;
let chkstr b rstate n a = chkgen (mkrec1 b) cmpstr rstate n a;;
let cmpint r1 r2 = compare r1.i1 r2.i1;;
let leint r1 r2 = r1.i1 <= r2.i1;;
let chkint b rstate n a = chkgen (mkrec1 b) cmpint rstate n a;;
let cmplex r1 r2 =
let c1 = compare r1.i1 r2.i1 in
if c1 = 0 then compare r1.i2 r2.i2 else c1
;;
let lelex r1 r2 =
let c1 = compare r1.i1 r2.i1 in
if c1 = 0 then r1.i2 <= r2.i2 else (c1 < 0)
;;
let chklex b rstate n a = chkgen (mkrec1 b) cmplex rstate n a;;
(************************************************************************)
let lens = [
0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 28;
100; 127; 128; 129; 191; 192; 193; 506;
1000; 1023; 1024; 1025; 1535; 1536; 1537; 2323;
4000; 4094; 4096; 4098; 5123;
];;
type ('a, 'b, 'c, 'd) aux = {
prepf : ('a -> 'a -> int) -> ('a -> 'a -> bool) -> 'b;
prepd : 'a array -> 'c;
postd : 'a array -> 'd -> 'a array;
};;
let ll = { prepf = (fun x y -> y); prepd = Array.to_list; postd = postl };;
let lc = { prepf = (fun x y -> x); prepd = Array.to_list; postd = postl };;
let al = { prepf = (fun x y -> y); prepd = id; postd = posta };;
let ac = { prepf = (fun x y -> x); prepd = id; postd = posta };;
type 'a outcome = Value of 'a | Exception of exn;;
let numfailed = ref 0;;
let test1 name f prepdata postdata cmp desc mk chk =
random_reinit ();
printf " %s with %s" name desc;
let i = ref 0 in
List.iter (fun n ->
if !i = 0 then printf "\n "; incr i; if !i > 11 then i := 0;
printf "%5d" n; flush stdout;
let rstate = random_get_state () in
let a = mk n in
let input = prepdata a in
let output = try Value (f cmp input) with e -> Exception e in
printf "."; flush stdout;
begin match output with
| Value v ->
if not (chk rstate n (postdata a v))
then (incr numfailed; printf "\n*** FAIL\n")
| Exception e ->
incr numfailed; printf "\n*** %s\n" (Printexc.to_string e)
end;
flush stdout;
) lens;
printf "\n";
;;
let test name stable f1 f2 aux1 aux2 =
printf "Testing %s...\n" name;
let t a b c d = test1 name f1 aux1.prepd aux1.postd a b c d in
let cmp = aux1.prepf compare (<=) in
t cmp "constant ints" mkconst chkconst;
t cmp "sorted ints" mksorted chksorted;
t cmp "reverse-sorted ints" mkrev chkrev;
t cmp "random ints (many dups)" mkrand_dup chkrand_dup;
t cmp "random ints (few dups)" mkrand_nodup chkrand_nodup;
let t a b c d = test1 name f2 aux2.prepd aux2.postd a b c d in
let cmp = aux2.prepf cmpstr lestr in
t cmp "records (str)" (mkrecs 1) (chkstr 1);
let cmp = aux2.prepf cmpint leint in
List.iter (fun m -> t cmp (sprintf "records (int[%d])" m) (mkrecs m)
(chkint m)
) [1; 10; 100; 1000];
if stable then
List.iter (fun m -> t cmp (sprintf "records (int[%d]) [stable]" m)
(mkrecs m) (chklex m)
) [1; 10; 100; 1000];
;;
(************************************************************************)
(* bug: effet de bord sur l'argument: on ne peut pas repeter la fonction. *)
(*
let timer1 repeat f x =
Gc.full_major ();
ignore (f x);
let st = Unix.times().tms_utime in
for i = 1 to repeat do ignore (f x); done;
let en = Unix.times().tms_utime in
en -. st
;;
let timer f x =
let repeat = ref 1 in
let t = ref (timer1 !repeat f x) in
while !t < 0.2 do
repeat := 10 * !repeat;
t := timer1 !repeat f x;
done;
if !t < 2.0 then begin
repeat := (int_of_float (10. *. (float !repeat) /. !t) + 1);
t := timer1 !repeat f x;
end;
!t /. (float !repeat)
;;
*)
let timer f x =
let st = Sys.time () in
ignore (f x);
let en = Sys.time () in
(en -. st)
;;
let table1 limit f mkarg =
printf " %10s %9s %9s %9s\n" "n" "t1" "t2" "t3";
let sz = ref 49151 in
while !sz < int_of_float (2. ** float limit) do
begin try
printf " %10d " !sz; flush stdout;
for i = 0 to 2 do
let arg = mkarg !sz in
let t = timer f arg in
printf " %.2e " t; flush stdout;
done;
printf "\n";
with e -> printf "*** %s\n" (Printexc.to_string e);
end;
flush stdout;
sz := (3 * !sz + 1) / 2
done;
;;
let table2 limit f mkarg =
printf " %10s %9s %9s %9s %9s %9s\n"
" n" "t" "t/n" "t/nlogn" "t/nlog^2n" "t/n^2";
let sz = ref 49151 in
while !sz < int_of_float (2. ** float limit) do
begin try
printf " %10d " !sz; flush stdout;
Gc.compact ();
let arg = mkarg !sz in
let t = timer f arg in
let n = float !sz in
let logn = log (float !sz) /. log 2. in
printf "%.2e %.2e %.2e %.2e %.2e\n"
t (t/.n) (t/.n/.logn) (t/.n/.logn/.logn) (t/.n/.n);
with e -> printf "*** %s\n" (Printexc.to_string e);
end;
flush stdout;
sz := (3 * !sz + 1) / 2
done;
;;
(************************************************************************)
(* benchmarks:
1. random records, sorted with two keys
2a. integers, constant
2b. integers, already sorted
2c. integers, reverse sorted
*)
let bench1 limit name f aux =
(* Don't do benchmarks with assertions enabled. *)
assert (not true);
printf "\n%s with random records [1000000000]:\n" name;
random_reinit ();
let cmp = aux.prepf cmpstr lestr in
table1 limit (f cmp) (fun n -> aux.prepd (mkrecs 1000000000 n));
;;
let bench2 limit name f aux =
(* Don't do benchmarks with assertions enabled. *)
assert (not true);
printf "\n%s with constant integers:\n" name;
let cmp = aux.prepf compare (<=) in
table2 limit (f cmp) (fun n -> aux.prepd (mkconst n));
printf "\n%s with sorted integers:\n" name;
let cmp = aux.prepf compare (<=) in
table2 limit (f cmp) (fun n -> aux.prepd (mksorted n));
printf "\n%s with reverse-sorted integers:\n" name;
let cmp = aux.prepf compare (<=) in
table2 limit (f cmp) (fun n -> aux.prepd (mkrev n));
;;
(************************************************************************)
(* merge sort on lists *)
(* FIXME to do: cutoff
to do: cascader les pattern-matchings (enlever les paires)
to do: fermeture intermediaire pour merge
*)
let (@@) = List.rev_append;;
let lmerge_1a cmp l =
let rec init accu = function
| [] -> accu
| e::rest -> init ([e] :: accu) rest
in
let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
accu,accu2 are rev *)
match l1, l2 with
| [] , _ -> mergepairs ((l2 @@ accu)::accu2) rest
| _ , [] -> mergepairs ((l1 @@ accu)::accu2) rest
| h1::t1, h2::t2 -> if cmp h1 h2 <= 0
then merge rest accu2 (h1::accu) t1 l2
else merge rest accu2 (h2::accu) l1 t2
and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
l1,l2,rest are rev *)
match l1, l2 with
| [] , _ -> mergepairs_rev ((l2 @@ accu)::accu2) rest
| _ , [] -> mergepairs_rev ((l1 @@ accu)::accu2) rest
| h1::t1, h2::t2 -> if cmp h2 h1 <= 0
then merge_rev rest accu2 (h1::accu) t1 l2
else merge_rev rest accu2 (h2::accu) l1 t2
and mergepairs accu = function (* accu is rev, arg is forward *)
| [] -> mergeall_rev accu
| [l] -> mergeall_rev ((List.rev l)::accu)
| l1::l2::rest -> merge rest accu [] l1 l2
and mergepairs_rev accu = function (* accu is forward, arg is rev *)
| [] -> mergeall accu
| [l] -> mergeall ((List.rev l)::accu)
| l1::l2::rest -> merge_rev rest accu [] l1 l2
and mergeall = function (* arg is forward *)
| [] -> []
| [l] -> l
| llist -> mergepairs [] llist
and mergeall_rev = function (* arg is rev *)
| [] -> []
| [l] -> List.rev l
| llist -> mergepairs_rev [] llist
in
mergeall_rev (init [] l)
;;
let lmerge_1b cmp l =
let rec init accu = function
| [] -> accu
| [e] -> [e] :: accu
| e1::e2::rest ->
init ((if cmp e1 e2 <= 0 then [e2;e1] else [e1;e2])::accu) rest
in
let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
accu,accu2 are rev *)
match l1, l2 with
| [] , _ -> mergepairs ((l2 @@ accu)::accu2) rest
| _ , [] -> mergepairs ((l1 @@ accu)::accu2) rest
| h1::t1, h2::t2 -> if cmp h1 h2 <= 0
then merge rest accu2 (h1::accu) t1 l2
else merge rest accu2 (h2::accu) l1 t2
and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
l1,l2,rest are rev *)
match l1, l2 with
| [] , _ -> mergepairs_rev ((l2 @@ accu)::accu2) rest
| _ , [] -> mergepairs_rev ((l1 @@ accu)::accu2) rest
| h1::t1, h2::t2 -> if cmp h2 h1 <= 0
then merge_rev rest accu2 (h1::accu) t1 l2
else merge_rev rest accu2 (h2::accu) l1 t2
and mergepairs accu = function (* accu is rev, arg is forward *)
| [] -> mergeall_rev accu
| [l] -> mergeall_rev ((List.rev l)::accu)
| l1::l2::rest -> merge rest accu [] l1 l2
and mergepairs_rev accu = function (* accu is forward, arg is rev *)
| [] -> mergeall accu
| [l] -> mergeall ((List.rev l)::accu)
| l1::l2::rest -> merge_rev rest accu [] l1 l2
and mergeall = function (* arg is forward *)
| [] -> []
| [l] -> l
| llist -> mergepairs [] llist
and mergeall_rev = function (* arg is rev *)
| [] -> []
| [l] -> List.rev l
| llist -> mergepairs_rev [] llist
in
mergeall_rev (init [] l)
;;
let lmerge_1c cmp l =
let rec init accu = function
| [] -> accu
| [e] -> [e] :: accu
| e1::e2::rest ->
init ((if cmp e1 e2 <= 0 then [e2;e1] else [e1;e2])::accu) rest
in
let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
accu,accu2 are rev *)
match l1 with
| [] -> mergepairs ((l2 @@ accu)::accu2) rest
| h1::t1 ->
match l2 with
| [] -> mergepairs ((l1 @@ accu)::accu2) rest
| h2::t2 -> if cmp h1 h2 <= 0
then merge rest accu2 (h1::accu) t1 l2
else merge rest accu2 (h2::accu) l1 t2
and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
l1,l2,rest are rev *)
match l1 with
| [] -> mergepairs_rev ((l2 @@ accu)::accu2) rest
| h1::t1 ->
match l2 with
| [] -> mergepairs_rev ((l1 @@ accu)::accu2) rest
| h2::t2 -> if cmp h2 h1 <= 0
then merge_rev rest accu2 (h1::accu) t1 l2
else merge_rev rest accu2 (h2::accu) l1 t2
and mergepairs accu = function (* accu is rev, arg is forward *)
| [] -> mergeall_rev accu
| [l] -> mergeall_rev ((List.rev l)::accu)
| l1::l2::rest -> merge rest accu [] l1 l2
and mergepairs_rev accu = function (* accu is forward, arg is rev *)
| [] -> mergeall accu
| [l] -> mergeall ((List.rev l)::accu)
| l1::l2::rest -> merge_rev rest accu [] l1 l2
and mergeall = function (* arg is forward *)
| [] -> []
| [l] -> l
| llist -> mergepairs [] llist
and mergeall_rev = function (* arg is rev *)
| [] -> []
| [l] -> List.rev l
| llist -> mergepairs_rev [] llist
in
mergeall_rev (init [] l)
;;
let lmerge_1d cmp l =
let rec init accu = function
| [] -> accu
| [e] -> [e] :: accu
| e1::e2::rest ->
init ((if cmp e1 e2 <= 0 then [e2;e1] else [e1;e2])::accu) rest
in
let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
accu,accu2 are rev *)
let merge_rest_accu2 accu l1 l2 =
match l1 with
| [] -> mergepairs ((l2 @@ accu)::accu2) rest
| h1::t1 ->
match l2 with
| [] -> mergepairs ((l1 @@ accu)::accu2) rest
| h2::t2 -> if cmp h1 h2 <= 0
then merge rest accu2 (h1::accu) t1 l2
else merge rest accu2 (h2::accu) l1 t2
in merge_rest_accu2 accu l1 l2
and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
l1,l2,rest are rev *)
let merge_rev_rest_accu2 accu l1 l2 =
match l1 with
| [] -> mergepairs_rev ((l2 @@ accu)::accu2) rest
| h1::t1 ->
match l2 with
| [] -> mergepairs_rev ((l1 @@ accu)::accu2) rest
| h2::t2 -> if cmp h2 h1 <= 0
then merge_rev rest accu2 (h1::accu) t1 l2
else merge_rev rest accu2 (h2::accu) l1 t2
in merge_rev_rest_accu2 accu l1 l2
and mergepairs accu = function (* accu is rev, arg is forward *)
| [] -> mergeall_rev accu
| [l] -> mergeall_rev ((List.rev l)::accu)
| l1::l2::rest -> merge rest accu [] l1 l2
and mergepairs_rev accu = function (* accu is forward, arg is rev *)
| [] -> mergeall accu
| [l] -> mergeall ((List.rev l)::accu)
| l1::l2::rest -> merge_rev rest accu [] l1 l2
and mergeall = function (* arg is forward *)
| [] -> []
| [l] -> l
| llist -> mergepairs [] llist
and mergeall_rev = function (* arg is rev *)
| [] -> []
| [l] -> List.rev l
| llist -> mergepairs_rev [] llist
in
mergeall_rev (init [] l)
;;
(************************************************************************)
(* merge sort on lists, user-contributed (NOT STABLE) *)
(* BEGIN code contributed by Yann Coscoy *)
let rec rev_merge_append order l1 l2 acc =
match l1 with
[] -> List.rev_append l2 acc
| h1 :: t1 ->
match l2 with
[] -> List.rev_append l1 acc
| h2 :: t2 ->
if order h1 h2
then rev_merge_append order t1 l2 (h1::acc)
else rev_merge_append order l1 t2 (h2::acc)
let rev_merge order l1 l2 = rev_merge_append order l1 l2 []
let rec rev_merge_append' order l1 l2 acc =
match l1 with
| [] -> List.rev_append l2 acc
| h1 :: t1 ->
match l2 with
| [] -> List.rev_append l1 acc
| h2 :: t2 ->
if order h2 h1
then rev_merge_append' order t1 l2 (h1::acc)
else rev_merge_append' order l1 t2 (h2::acc)
let rev_merge' order l1 l2 = rev_merge_append' order l1 l2 []
let lmerge_3 order l =
let rec initlist l acc = match l with
| e1::e2::rest ->
initlist rest
((if order e1 e2 then [e1;e2] else [e2;e1])::acc)
| [e] -> [e]::acc
| [] -> acc
in
let rec merge2 ll acc = match ll with
| [] -> acc
| [l] -> [List.rev l]@acc
| l1::l2::rest ->
merge2 rest (rev_merge order l1 l2::acc)
in
let rec merge2' ll acc = match ll with
| [] -> acc
| [l] -> [List.rev l]@acc
| l1::l2::rest ->
merge2' rest (rev_merge' order l1 l2::acc)
in
let rec mergeall rev = function
| [] -> []
| [l] -> if rev then List.rev l else l
| llist ->
mergeall
(not rev) ((if rev then merge2' else merge2) llist [])
in
mergeall false (initlist l [])
(* END code contributed by Yann Coscoy *)
(************************************************************************)
(* merge sort on arrays, merge with tail-rec function *)
let amerge_1a cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let rec sortto srcofs dst dstofs len =
assert (len > 0);
if len = 1 then dst.(dstofs) <- a.(srcofs)
else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= 1 then ()
else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let amerge_1b cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let rec sortto srcofs dst dstofs len =
assert (len > 0);
if len = 1 then dst.(dstofs) <- a.(srcofs)
else if len = 2 then begin
if cmp a.(srcofs) a.(srcofs+1) <= 0 then begin
dst.(dstofs) <- a.(srcofs);
dst.(dstofs+1) <- a.(srcofs+1);
end else begin
dst.(dstofs) <- a.(srcofs+1);
dst.(dstofs+1) <- a.(srcofs);
end;
end else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= 1 then ()
else if l = 2 then begin
if cmp a.(0) a.(1) > 0 then begin
let e = a.(0) in
a.(0) <- a.(1);
a.(1) <- e;
end;
end else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 3;;
let amerge_1c cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 4;;
let amerge_1d cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 5;;
let amerge_1e cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 6;;
let amerge_1f cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 7;;
let amerge_1g cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 8;;
let amerge_1h cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 9;;
let amerge_1i cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 10;;
let amerge_1j cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
let rec loop i1 s1 i2 s2 d =
if cmp s1 s2 <= 0 then begin
dst.(d) <- s1;
let i1 = i1 + 1 in
if i1 < src1r then
loop i1 a.(i1) i2 s2 (d + 1)
else
Array.blit src2 i2 dst (d + 1) (src2r - i2)
end else begin
dst.(d) <- s2;
let i2 = i2 + 1 in
if i2 < src2r then
loop i1 s1 i2 src2.(i2) (d + 1)
else
Array.blit a i1 dst (d + 1) (src1r - i1)
end
in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
in
let isortto srcofs dst dstofs len =
for i = 0 to len - 1 do
let e = a.(srcofs + i) in
let j = ref (dstofs + i - 1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs + l1) dst (dstofs + l1) l2;
sortto srcofs a (srcofs + l2) l1;
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
end;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
(* FIXME: list->array->list direct and array->list->array direct *)
(* FIXME: overhead = 1/3, 1/4, etc. *)
(* FIXME: overhead = sqrt (n) *)
(* FIXME: overhead = n/3 jusqu'a 30k, 30k jusqu'a 900M, sqrt (n) au-dela *)
(************************************************************************)
(* merge sort on arrays, merge with loop *)
(* cutoff = 1 *)
let amerge_3a cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let rec sortto srcofs dst dstofs len =
assert (len > 0);
if len = 1 then dst.(dstofs) <- a.(srcofs) else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= 1 then () else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let amerge_3b cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let rec sortto srcofs dst dstofs len =
assert (len > 0);
if len = 1 then dst.(dstofs) <- a.(srcofs)
else if len = 2 then begin
if cmp a.(srcofs) a.(srcofs+1) <= 0 then begin
dst.(dstofs) <- a.(srcofs);
dst.(dstofs+1) <- a.(srcofs+1);
end else begin
dst.(dstofs) <- a.(srcofs+1);
dst.(dstofs+1) <- a.(srcofs);
end
end else begin
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
end
in
let l = Array.length a in
if l <= 1 then ()
else if l = 2 then begin
if cmp a.(0) a.(1) > 0 then begin
let e = a.(0) in
a.(0) <- a.(1);
a.(1) <- e;
end;
end else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 3;;
let amerge_3c cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 4;;
let amerge_3d cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 5;;
let amerge_3e cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 6;;
let amerge_3f cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 7;;
let amerge_3g cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 8;;
let amerge_3h cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 9;;
let amerge_3i cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
let cutoff = 10;;
let amerge_3j cmp a =
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
let i1 = ref src1ofs
and i2 = ref src2ofs
and d = ref dstofs
and src1r = src1ofs + src1len
and src2r = src2ofs + src2len
in
while !i1 < src1r && !i2 < src2r do
let s1 = a.(!i1) and s2 = src2.(!i2) in
if cmp s1 s2 <= 0 then begin
dst.(!d) <- s1;
incr i1;
end else begin
dst.(!d) <- s2;
incr i2;
end;
incr d;
done;
if !i1 < src1r then
Array.blit a !i1 dst !d (src1r - !i1)
else
Array.blit src2 !i2 dst !d (src2r - !i2)
in
let isortto srcofs dst dstofs len =
for i = 0 to len-1 do
let e = a.(srcofs+i) in
let j = ref (dstofs+i-1) in
while (!j >= dstofs && cmp dst.(!j) e > 0) do
dst.(!j + 1) <- dst.(!j);
decr j;
done;
dst.(!j + 1) <- e;
done;
in
let rec sortto srcofs dst dstofs len =
if len <= cutoff then isortto srcofs dst dstofs len else
let l1 = len / 2 in
let l2 = len - l1 in
sortto (srcofs+l1) dst (dstofs+l1) l2;
sortto srcofs a (srcofs+l2) l1;
merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
in
let l = Array.length a in
if l <= cutoff then isortto 0 a 0 l else begin
let l1 = l / 2 in
let l2 = l - l1 in
let t = Array.make l2 a.(0) in
sortto l1 t 0 l2;
sortto 0 a l2 l1;
merge l2 l1 t 0 l2 a 0;
end;
;;
(* FIXME: bottom-up merge on arrays ? *)
(* FIXME: top-down merge on lists ? *)
(************************************************************************)
(* Shell sort on arrays *)
let ashell_1 cmp a =
let l = Array.length a in
let step = ref 1 in
while !step < l do step := !step * 3 + 1; done;
step := !step / 3;
while !step > 0 do
for j = !step to l-1 do
let e = a.(j) in
let k = ref (j - !step) in
let k1 = ref j in
while !k >= 0 && cmp a.(!k) e > 0 do
a.(!k1) <- a.(!k);
k1 := !k;
k := !k - !step;
done;
a.(!k1) <- e;
done;
step := !step / 3;
done;
;;
let ashell_2 cmp a =
let l = Array.length a in
let step = ref 1 in
while !step < l do step := !step * 3 + 1; done;
step := !step / 3;
while !step > 0 do
for j = !step to l-1 do
let e = a.(j) in
let k = ref (j - !step) in
while !k >= 0 && cmp a.(!k) e > 0 do
a.(!k + !step) <- a.(!k);
k := !k - !step;
done;
a.(!k + !step) <- e;
done;
step := !step / 3;
done;
;;
let ashell_3 cmp a =
let l = Array.length a in
let step = ref 1 in
while !step < l do step := !step * 3 + 1; done;
step := !step / 3;
while !step > 0 do
for i = 0 to !step - 1 do
let j = ref (i + !step) in
while !j < l do
let e = ref a.(!j) in
let k = ref (!j - !step) in
if cmp !e a.(i) < 0 then begin
let x = !e in e := a.(i); a.(i) <- x;
end;
while cmp a.(!k) !e > 0 do
a.(!k + !step) <- a.(!k);
k := !k - !step;
done;
a.(!k + !step) <- !e;
j := !j + !step;
done;
done;
step := !step / 3;
done;
;;
let force = Lazy.force;;
type iilist = Cons of int * iilist Lazy.t;;
let rec mult n (Cons (x,l)) = Cons (n*x, lazy (mult n (force l)))
let rec merge (Cons (x1, t1) as l1) (Cons (x2, t2) as l2) =
if x1 = x2 then Cons (x1, lazy (merge (force t1) (force t2)))
else if x1 < x2 then Cons (x1, lazy (merge (force t1) l2))
else Cons (x2, lazy (merge l1 (force t2)))
;;
let rec scale = Cons (1, lazy (merge (mult 2 scale) (mult 3 scale)));;
let ashell_4 cmp a =
let l = Array.length a in
let rec loop1 accu (Cons (x, t)) =
if x > l then accu else loop1 (x::accu) (force t)
in
let sc = loop1 [] scale in
let rec loop2 = function
| [] -> ()
| step::t ->
for i = 0 to step - 1 do
let j = ref (i + step) in
while !j < l do
let e = a.(!j) in
let k = ref (!j - step) in
while !k >= 0 && cmp a.(!k) e > 0 do
a.(!k + step) <- a.(!k);
k := !k - step;
done;
a.(!k + step) <- e;
j := !j + step;
done;
done;
loop2 t;
in
loop2 sc;
;;
(************************************************************************)
(* Quicksort on arrays *)
let cutoff = 1;;
let aquick_1a cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
while !p2 <= !p3 do
let e = a.(!p3) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
end else if c < 0 then begin
a.(!p3) <- a.(!p2);
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
a.(!p3) <- a.(!p2);
a.(!p2) <- e;
incr p2;
end;
done;
incr p3;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 1 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 2;;
let aquick_1b cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
while !p2 <= !p3 do
let e = a.(!p3) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
end else if c < 0 then begin
a.(!p3) <- a.(!p2);
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
a.(!p3) <- a.(!p2);
a.(!p2) <- e;
incr p2;
end;
done;
incr p3;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 1 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 3;;
let aquick_1c cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
while !p2 <= !p3 do
let e = a.(!p3) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
end else if c < 0 then begin
a.(!p3) <- a.(!p2);
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
a.(!p3) <- a.(!p2);
a.(!p2) <- e;
incr p2;
end;
done;
incr p3;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 1 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 4;;
let aquick_1d cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
while !p2 <= !p3 do
let e = a.(!p3) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
end else if c < 0 then begin
a.(!p3) <- a.(!p2);
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
a.(!p3) <- a.(!p2);
a.(!p2) <- e;
incr p2;
end;
done;
incr p3;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 1 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 5;;
let aquick_1e cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
while !p2 <= !p3 do
let e = a.(!p3) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
end else if c < 0 then begin
a.(!p3) <- a.(!p2);
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
a.(!p3) <- a.(!p2);
a.(!p2) <- e;
incr p2;
end;
done;
incr p3;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 1 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 6;;
let aquick_1f cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
while !p2 <= !p3 do
let e = a.(!p3) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
end else if c < 0 then begin
a.(!p3) <- a.(!p2);
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
a.(!p3) <- a.(!p2);
a.(!p2) <- e;
incr p2;
end;
done;
incr p3;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 1 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 7;;
let aquick_1g cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
while !p2 <= !p3 do
let e = a.(!p3) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
end else if c < 0 then begin
a.(!p3) <- a.(!p2);
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
a.(!p3) <- a.(!p2);
a.(!p2) <- e;
incr p2;
end;
done;
incr p3;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 1 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 1;;
let aquick_2a cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
incr p2;
end;
done;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 2;;
let aquick_2b cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
incr p2;
end;
done;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 3;;
let aquick_2c cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
incr p2;
end;
done;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 4;;
let aquick_2d cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
incr p2;
end;
done;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 5;;
let aquick_2e cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
incr p2;
end;
done;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 6;;
let aquick_2f cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
incr p2;
end;
done;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 7;;
let aquick_2g cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end else begin
incr p2;
end;
done;
let len1 = !p1 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p1; qsort !p3 r)
else (qsort !p3 r; qsort l !p1)
end else qsort l !p1
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 1;;
let aquick_3a cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 2;;
let aquick_3b cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 3;;
let aquick_3c cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 4;;
let aquick_3d cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 5;;
let aquick_3e cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 6;;
let aquick_3f cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 7;;
let aquick_3g cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 8;;
let aquick_3h cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 9;;
let aquick_3i cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
let cutoff = 10;;
let aquick_3j cmp a =
let rec qsort l r = (* ASSUMES r - l >= 2 *)
let m = (l + r) / 2 in
let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
let pivot = if cmp al am <= 0 then
if cmp am ar <= 0 then am
else if cmp al ar <= 0 then ar
else al
else
if cmp al ar <= 0 then al
else if cmp am ar <= 0 then ar
else am
in
let p1 = ref l and p2 = ref l and p3 = ref r in
while !p2 < !p3 do
let e = a.(!p2) in
let c = cmp e pivot in
if c > 0 then begin
decr p3;
a.(!p2) <- a.(!p3);
a.(!p3) <- e;
end else if c < 0 then begin
incr p2;
end else begin
a.(!p2) <- a.(!p1);
a.(!p1) <- e;
incr p1;
incr p2;
end
done;
while !p1 > l do
decr p1;
decr p2;
let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
done;
let len1 = !p2 - l and len2 = r - !p3 in
if len1 > cutoff then
if len2 > cutoff then begin
if len1 < len2
then (qsort l !p2; qsort !p3 r)
else (qsort !p3 r; qsort l !p2)
end else qsort l !p2
else if len2 > cutoff then qsort !p3 r;
in
let l = Array.length a in
if l > 1 then begin
qsort 0 l;
let mini = ref 0 in
for i = 0 to (min l cutoff) - 1 do
if cmp a.(i) a.(!mini) < 0 then mini := i;
done;
let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
for i = 1 to l - 1 do
let e = a.(i) in
let j = ref (i - 1) in
while cmp a.(!j) e > 0 do
a.(!j + 1) <- a.(!j);
decr j;
done;
a.(!j + 1) <- e;
done;
end;
;;
(************************************************************************)
(* Heap sort on arrays (top-down, ternary) *)
let aheap_1 cmp a =
let l = ref (Array.length a) in
let l3 = ref ((!l + 1) / 3) in (* l3 is the first element without sons *)
let maxson i = (* ASSUMES i < !l3 *)
let i31 = i+i+i+1 in
let x = ref i31 in
if i31+2 < !l then begin
if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
!x
end else begin
if i31+1 < !l && cmp a.(i31) a.(i31+1) < 0
then i31+1
else i31
end
in
let rec trickledown i e = (* ASSUMES i < !l3 *)
let j = maxson i in
if cmp a.(j) e > 0 then begin
a.(i) <- a.(j);
if j < !l3 then trickledown j e else a.(j) <- e;
end else begin
a.(i) <- e;
end;
in
for i = !l3 - 1 downto 0 do trickledown i a.(i); done;
let m = ref (!l + 1 - 3 * !l3) in
while !l > 2 do
decr l;
if !m = 0 then (m := 2; decr l3) else decr m;
let e = a.(!l) in
a.(!l) <- a.(0);
trickledown 0 e;
done;
if !l > 1 then begin let e = a.(1) in a.(1) <- a.(0); a.(0) <- e; end;
;;
(************************************************************************)
(* Heap sort on arrays (top-down, binary) *)
(* FIXME to do: application partielle de trickledown (merge avec down) *)
(* FIXME to do: expanser maxson dans trickledown; supprimer l'exception. *)
let aheap_2 cmp a =
let maxson l i e =
let i21 = i + i + 1 in
if i21 + 1 < l && cmp a.(i21) a.(i21+1) < 0
then i21 + 1
else if i21 < l then i21 else (a.(i) <- e; raise Exit)
in
let rec trickledown l i e =
let j = maxson l i e in
if cmp a.(j) e > 0 then begin
a.(i) <- a.(j);
trickledown l j e;
end else begin
a.(i) <- e;
end;
in
let down l i e = try trickledown l i e with Exit -> () in
let l = Array.length a in
for i = l / 2 -1 downto 0 do down l i a.(i); done;
for i = l - 1 downto 1 do
let e = a.(i) in
a.(i) <- a.(0);
down i 0 e;
done;
;;
(************************************************************************)
(* Heap sort on arrays (bottom-up, ternary) *)
exception Bottom of int;;
let aheap_3 cmp a =
let maxson l i =
let i31 = i+i+i+1 in
let x = ref i31 in
if i31+2 < l then begin
if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
!x
end else
if i31+1 < l && cmp a.(i31) a.(i31+1) < 0
then i31+1
else if i31 < l then i31 else raise (Bottom i)
in
let rec trickledown l i e =
let j = maxson l i in
if cmp a.(j) e > 0 then begin
a.(i) <- a.(j);
trickledown l j e;
end else begin
a.(i) <- e;
end;
in
let rec trickle l i e = try trickledown l i e with Bottom i -> a.(i) <- e in
let rec bubbledown l i =
let j = maxson l i in
a.(i) <- a.(j);
bubbledown l j;
in
let bubble l i = try bubbledown l i with Bottom i -> i in
let rec trickleup i e =
let father = (i - 1) / 3 in
assert (i <> father);
if cmp a.(father) e < 0 then begin
a.(i) <- a.(father);
if father > 0 then trickleup father e else a.(0) <- e;
end else begin
a.(i) <- e;
end;
in
let l = Array.length a in
for i = (l + 1) / 3 - 1 downto 0 do trickle l i a.(i); done;
for i = l - 1 downto 2 do
let e = a.(i) in
a.(i) <- a.(0);
trickleup (bubble i 0) e;
done;
if l > 1 then (let e = a.(1) in a.(1) <- a.(0); a.(0) <- e);
;;
(************************************************************************)
(* Heap sort on arrays (bottom-up, binary) *)
let aheap_4 cmp a =
let maxson l i =
let i21 = i + i + 1 in
if i21 + 1 < l && cmp a.(i21) a.(i21 + 1) < 0
then i21 + 1
else if i21 < l then i21 else raise (Bottom i)
in
let rec trickledown l i e =
let j = maxson l i in
if cmp a.(j) e > 0 then begin
a.(i) <- a.(j);
trickledown l j e;
end else begin
a.(i) <- e;
end;
in
let trickle l i e = try trickledown l i e with Bottom i -> a.(i) <- e in
let rec bubbledown l i =
let j = maxson l i in
a.(i) <- a.(j);
bubbledown l j;
in
let bubble l i = try bubbledown l i with Bottom i -> i in
let rec trickleup i e =
let father = (i - 1) / 2 in
assert (i <> father);
if cmp a.(father) e < 0 then begin
a.(i) <- a.(father);
if father > 0 then trickleup father e else a.(0) <- e;
end else begin
a.(i) <- e;
end;
in
let l = Array.length a in
for i = l / 2 - 1 downto 0 do trickle l i a.(i); done;
for i = l - 1 downto 2 do
let e = a.(i) in
a.(i) <- a.(0);
trickleup (bubble i 0) e;
done;
if l > 1 then (let e = a.(1) in a.(1) <- a.(0); a.(0) <- e);
;;
(************************************************************************)
(* heap sort, top-down, ternary, recursive final loop *)
let aheap_5 cmp a =
let maxson l i = (* ASSUMES i < (l+1)/3 *)
let i31 = i+i+i+1 in
let x = ref i31 in
if i31+2 < l then begin
if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
!x
end else begin
if i31+1 < l && cmp a.(i31) a.(i31+1) < 0
then i31+1
else i31
end
in
let rec trickledown l l3 i e = (* ASSUMES i < l3 *)
let j = maxson l i in
if cmp a.(j) e > 0 then begin
a.(i) <- a.(j);
if j < l3 then trickledown l l3 j e else a.(j) <- e;
end else begin
a.(i) <- e;
end;
in
let l = Array.length a in
let l3 = (l + 1) / 3 in
for i = l3 - 1 downto 0 do trickledown l l3 i a.(i); done;
let rec loop0 l l3 =
let e = a.(l) in
a.(l) <- a.(0);
trickledown l l3 0 e;
loop2 (l-1) (l3-1);
and loop1 l l3 =
let e = a.(l) in
a.(l) <- a.(0);
trickledown l l3 0 e;
loop0 (l-1) l3;
and loop2 l l3 =
if l > 1 then begin
let e = a.(l) in
a.(l) <- a.(0);
trickledown l l3 0 e;
loop1 (l-1) l3;
end else begin
let e = a.(1) in a.(1) <- a.(0); a.(0) <- e;
end;
in
if l > 1 then
match l + 1 - 3 * l3 with
| 0 -> loop2 (l-1) (l3-1);
| 1 -> loop0 (l-1) l3;
| 2 -> loop1 (l-1) l3;
| _ -> assert false;
;;
(************************************************************************)
(* heap sort, top-down, ternary, with exception *)
let aheap_6 cmp a =
let maxson e l i =
let i31 = i + i + i + 1 in
let x = ref i31 in
if i31+2 < l then begin
if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
!x
end else begin
if i31+1 < l && cmp a.(i31) a.(i31+1) < 0
then i31+1
else if i31 < l then i31 else (a.(i) <- e; raise Exit)
end
in
let rec trickledown e l i =
let j = maxson e l i in
if cmp a.(j) e > 0 then begin
a.(i) <- a.(j);
trickledown e l j;
end else begin
a.(i) <- e;
end;
in
let down e l i = try trickledown e l i with Exit -> (); in
let l = Array.length a in
for i = (l + 1) / 3 - 1 downto 0 do down a.(i) l i; done;
for i = l - 1 downto 2 do
let e = a.(i) in
a.(i) <- a.(0);
down e i 0;
done;
if l > 1 then (let e = a.(1) in a.(1) <- a.(0); a.(0) <- e);
;;
(* FIXME cutoff pour heapsort ? *)
(************************************************************************)
(* Insertion sort with dichotomic search *)
let ainsertion_1 cmp a =
let rec dicho l r e =
if l = r then l else begin
let m = (l + r) / 2 in
if cmp a.(m) e <= 0
then dicho (m+1) r e
else dicho l m e
end
in
for i = 1 to Array.length a - 1 do
let e = a.(i) in
let j = dicho 0 i e in
Array.blit a j a (j + 1) (i - j);
a.(j) <- e;
done;
;;
(************************************************************************)
(* merge sort on lists via arrays *)
let array_to_list_in_place a =
let l = Array.length a in
let rec loop accu n p =
if p <= 0 then accu else begin
if p = n then begin
Obj.truncate (Obj.repr a) p;
loop (a.(p-1) :: accu) (n-1000) (p-1)
end else begin
loop (a.(p-1) :: accu) n (p-1)
end
end
in
loop [] l l
;;
let lmerge_0 cmp l =
let a = Array.of_list l in
amerge_1e cmp a;
array_to_list_in_place a
;;
let lshell_0 cmp l =
let a = Array.of_list l in
ashell_2 cmp a;
array_to_list_in_place a
;;
let lquick_0 cmp l =
let a = Array.of_list l in
aquick_3f cmp a;
array_to_list_in_place a
;;
(************************************************************************)
(* merge sort on arrays via lists *)
let amerge_0 cmp a = (* cutoff is not yet used *)
let l = lmerge_1a cmp (Array.to_list a) in
let rec loop i = function
| [] -> ()
| h::t -> a.(i) <- h; loop (i + 1) t
in
loop 0 l
;;
(************************************************************************)
let lnew = [
"lmerge_0", lmerge_0, true;
(*
"lshell_0", lshell_0, false;
"lquick_0", lquick_0, false;
"lmerge_1a", lmerge_1a, true;
"lmerge_1b", lmerge_1b, true;
"lmerge_1c", lmerge_1c, true;
"lmerge_1d", lmerge_1d, true;
*)
];;
let anew = [
(*
"amerge_0", amerge_0, true;
"amerge_1a", amerge_1a, true;
"amerge_1b", amerge_1b, true;
"amerge_1c", amerge_1c, true;
"amerge_1d", amerge_1d, true;
*)
"amerge_1e", amerge_1e, true;
(*
"amerge_1f", amerge_1f, true;
"amerge_1g", amerge_1g, true;
"amerge_1h", amerge_1h, true;
"amerge_1i", amerge_1i, true;
"amerge_1j", amerge_1j, true;
"amerge_3a", amerge_3a, true;
"amerge_3b", amerge_3b, true;
"amerge_3c", amerge_3c, true;
"amerge_3d", amerge_3d, true;
"amerge_3e", amerge_3e, true;
"amerge_3f", amerge_3f, true;
"amerge_3g", amerge_3g, true;
"amerge_3h", amerge_3h, true;
"amerge_3i", amerge_3i, true;
"amerge_3j", amerge_3j, true;
"ashell_1", ashell_1, false;
"ashell_2", ashell_2, false;
"ashell_3", ashell_3, false;
"ashell_4", ashell_4, false;
"aquick_1a", aquick_1a, false;
"aquick_1b", aquick_1b, false;
"aquick_1c", aquick_1c, false;
"aquick_1d", aquick_1d, false;
"aquick_1e", aquick_1e, false;
"aquick_1f", aquick_1f, false;
"aquick_1g", aquick_1g, false;
"aquick_2a", aquick_2a, false;
"aquick_2b", aquick_2b, false;
"aquick_2c", aquick_2c, false;
"aquick_2d", aquick_2d, false;
"aquick_2e", aquick_2e, false;
"aquick_2f", aquick_2f, false;
"aquick_2g", aquick_2g, false;
"aquick_3a", aquick_3a, false;
"aquick_3b", aquick_3b, false;
"aquick_3c", aquick_3c, false;
"aquick_3d", aquick_3d, false;
"aquick_3e", aquick_3e, false;
"aquick_3f", aquick_3f, false;
"aquick_3g", aquick_3g, false;
"aquick_3h", aquick_3h, false;
"aquick_3i", aquick_3i, false;
"aquick_3j", aquick_3j, false;
"aheap_1", aheap_1, false;
"aheap_2", aheap_2, false;
*)
"aheap_3", aheap_3, false;
(*
"aheap_4", aheap_4, false;
"aheap_5", aheap_5, false;
"aheap_6", aheap_6, false;
"ainsertion_1", ainsertion_1, true;
*)
];;
(************************************************************************)
(* main program *)
type mode = Test_std | Test | Bench1 | Bench2;;
let size = ref 22
and mem = ref 0
and mode = ref Test_std
;;
let usage = "Usage: sorts [-size <table size>] [-mem <memory size>]\n\
\032 [-seed <random seed>] [-test|-bench]"
;;
let options = [
"-size", Arg.Int ((:=) size), " Maximum size for benchmarks (default 22)";
"-meg",Arg.Int ((:=) mem)," How many megabytes to preallocate (default 0)";
"-seed", Arg.Int ((:=) seed), " PRNG seed (default 0)";
"-teststd", Arg.Unit (fun () -> mode := Test_std), " Test stdlib (default)";
"-test", Arg.Unit (fun () -> mode := Test), " Select test mode";
"-bench1", Arg.Unit (fun () -> mode := Bench1), " Select bench mode 1";
"-bench2", Arg.Unit (fun () -> mode := Bench2), " Select bench mode 2";
];;
let anonymous x = raise (Arg.Bad ("unrecognised option "^x));;
let main () =
Arg.parse options anonymous usage;
Printf.printf "Command line is:";
for i = 0 to Array.length Sys.argv - 1 do
Printf.printf " %s" Sys.argv.(i);
done;
Printf.printf "\n";
ignore (String.create (1048576 * !mem));
Gc.full_major ();
let limit = !size in
let a2l = Array.to_list in
let l2ak x y = Array.of_list x in
let id = fun x -> x in
let fst x y = x in
let snd x y = y in
match !mode with
| Test_std -> begin
test "List.sort" false List.sort List.sort lc lc;
test "List.stable_sort" true List.stable_sort List.stable_sort lc lc;
test "Array.sort" false Array.sort Array.sort ac ac;
test "Array.stable_sort" true Array.stable_sort Array.stable_sort ac ac;
printf "Number of tests failed: %d\n" !numfailed;
end;
| Test -> begin
test "Sort.list" true Sort.list Sort.list ll ll;
test "Sort.array" false Sort.array Sort.array al al;
test "lmerge_3" false lmerge_3 lmerge_3 ll ll;
for i = 0 to List.length lnew - 1 do
let (name, f1, stable) = List.nth lnew i in
let (_, f2, _) = List.nth lnew i in
test name stable f1 f2 lc lc;
done;
for i = 0 to List.length anew - 1 do
let (name, f1, stable) = List.nth anew i in
let (_, f2, _) = List.nth anew i in
test name stable f1 f2 ac ac;
done;
printf "Number of tests failed: %d\n" !numfailed;
end;
| Bench1 -> begin
let b = bench1 in
(*
b limit "Sort.list" Sort.list ll;
b limit "Sort.array" Sort.array al;
b limit "lmerge_3" lmerge_3 ll;
*)
for i = 0 to List.length lnew - 1 do
let (name, f, stable) = List.nth lnew i in
b limit name f lc;
done;
for i = 0 to List.length anew - 1 do
let (name, f, stable) = List.nth anew i in
b limit name f ac;
done;
end;
| Bench2 -> begin
let b = bench2 in
(*
b limit "Sort.list" Sort.list ll;
b limit "Sort.array" Sort.array al;
b limit "lmerge_3" lmerge_3 ll;
*)
for i = 0 to List.length lnew - 1 do
let (name, f, stable) = List.nth lnew i in
b limit name f lc;
done;
for i = 0 to List.length anew - 1 do
let (name, f, stable) = List.nth anew i in
b limit name f ac;
done;
end;
;;
if not !Sys.interactive then Printexc.catch main ();;
(* $Id$ *)