Skip to content

Commit 49c3785

Browse files
committed
Add simple smooth and tail-recursive mergesorts in OCaml
1 parent df2a48d commit 49c3785

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

benchmark/ocaml/mergesort_ocaml.ml

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,8 @@ let rec sort_rec (<=) n xs =
104104
let s2, xs2 = sort_rec (<=) n2 xs1 in
105105
(merge (<=) s1 s2, xs2)
106106

107-
let sort (<=) = function
108-
| [] -> []
109-
| xs -> fst (sort_rec (<=) (length xs) xs)
107+
let sort (<=) xs =
108+
if xs = [] then [] else fst (sort_rec (<=) (length xs) xs)
110109

111110
end;;
112111

@@ -131,6 +130,66 @@ let sort (<=) s = sort_rec (<=) 0 [] s
131130

132131
end;;
133132

133+
module Smooth = struct
134+
135+
open NTRMerge
136+
137+
let rec push (<=) xs k stack =
138+
match k mod 2, stack with
139+
| 0, _ -> xs :: stack
140+
| 1, ys :: stack -> push (<=) (merge (<=) ys xs) (k / 2) stack
141+
142+
let rec pop (<=) xs = function
143+
| [] -> xs
144+
| ys :: stack -> pop (<=) (merge (<=) ys xs) stack
145+
146+
let rec sort_rec (<=) k stack s =
147+
let rec sort_rec' mode accu x s =
148+
let accu = x :: accu in
149+
match s with
150+
| y :: s when (x <= y) = mode -> sort_rec' mode accu y s
151+
| _ -> sort_rec (<=) (k + 1)
152+
(push (<=) (if mode then rev accu else accu) k stack) s
153+
in
154+
match s with
155+
| x :: y :: s -> sort_rec' (x <= y) [x] y s
156+
| _ -> pop (<=) s stack
157+
158+
let sort (<=) s = sort_rec (<=) 0 [] s
159+
160+
end;;
161+
162+
module TailRec = struct
163+
164+
open TRMerge
165+
166+
let rec push (<=) mode xs k stack =
167+
let (>=) x y = (<=) y x in
168+
match k mod 2, stack with
169+
| 0, _ -> xs :: stack
170+
| 1, ys :: stack ->
171+
push (<=) (not mode)
172+
(if mode then rev_merge (>=) xs ys [] else rev_merge (<=) ys xs [])
173+
(k / 2) stack
174+
175+
let rec pop (<=) mode xs k stack =
176+
match k mod 2, stack with
177+
| _, [] -> if mode then rev xs else xs
178+
| 0, _ -> pop (<=) (not mode) (rev xs) (k / 2) stack
179+
| 1, ys :: stack ->
180+
pop (<=) (not mode)
181+
(if mode then rev_merge (>=) xs ys [] else rev_merge (<=) ys xs [])
182+
(k / 2) stack
183+
184+
let rec sort_rec (<=) k stack =
185+
function
186+
| x :: s -> sort_rec (<=) (k + 1) (push (<=) false [x] k stack) s
187+
| [] -> pop (<=) false [] k stack
188+
189+
let sort (<=) s = sort_rec (<=) 0 [] s
190+
191+
end;;
192+
134193
(* Stack-based bottom-up non-tail-recursive mergesorts *)
135194
module NTRStack = struct
136195

benchmark/ocaml/mergesort_ocaml.mli

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ module BottomUp : sig
1414
val sort : ('a1 -> 'a1 -> bool) -> 'a1 list -> 'a1 list
1515
end
1616

17+
module Smooth : sig
18+
val sort : ('a1 -> 'a1 -> bool) -> 'a1 list -> 'a1 list
19+
end
20+
21+
module TailRec : sig
22+
val sort : ('a1 -> 'a1 -> bool) -> 'a1 list -> 'a1 list
23+
end
24+
1725
module NTRStack : sig
1826
val sort3 : ('a1 -> 'a1 -> bool) -> 'a1 list -> 'a1 list
1927
val sortN : ('a1 -> 'a1 -> bool) -> 'a1 list -> 'a1 list

benchmark/ocaml/test_stability.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ QCheck.Test.check_exn (test_stability NaiveTopDown.sort);;
1212
QCheck.Test.check_exn (test_stability NaiveBottomUp.sort);;
1313
QCheck.Test.check_exn (test_stability TopDown.sort);;
1414
QCheck.Test.check_exn (test_stability BottomUp.sort);;
15+
QCheck.Test.check_exn (test_stability Smooth.sort);;
16+
QCheck.Test.check_exn (test_stability TailRec.sort);;
1517
QCheck.Test.check_exn (test_stability NTRStack.sort3);;
1618
QCheck.Test.check_exn (test_stability NTRStack.sortN);;
1719
QCheck.Test.check_exn (test_stability NTRStack.sort3N);;

0 commit comments

Comments
 (0)