~ubuntu-branches/debian/sid/ocaml/sid

« back to all changes in this revision

Viewing changes to testsuite/tests/misc/sorts.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu
  • Date: 2011-04-21 21:35:08 UTC
  • mfrom: (1.1.11 upstream) (12.1.14 sid)
  • Revision ID: james.westby@ubuntu.com-20110421213508-kg34453aqmb0moha
* Fixes related to -output-obj with g++ (in debian/patches):
  - add Declare-primitive-name-table-as-const-char
  - add Avoid-multiple-declarations-in-generated-.c-files-in
  - fix Embed-bytecode-in-C-object-when-using-custom: the closing
    brace for extern "C" { ... } was missing in some cases

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(* Test bench for sorting algorithms. *)
 
2
 
 
3
 
 
4
(*
 
5
  ocamlopt -noassert sorts.ml -cclib -lunix
 
6
*)
 
7
 
 
8
open Printf;;
 
9
 
 
10
(*
 
11
  Criteres:
 
12
  0. overhead en pile: doit etre logn au maximum.
 
13
  1. stable ou non.
 
14
  2. overhead en espace.
 
15
  3. vitesse.
 
16
*)
 
17
 
 
18
(************************************************************************)
 
19
(* auxiliary functions *)
 
20
 
 
21
let rec exp2 n = if n <= 0 then 1 else 2 * exp2 (n-1);;
 
22
let id x = x;;
 
23
let postl x y = Array.of_list y;;
 
24
let posta x y = x;;
 
25
 
 
26
let mkconst n = Array.make n 0;;
 
27
let chkconst _ n a = (a = mkconst n);;
 
28
 
 
29
let mksorted n =
 
30
  let a = Array.make n 0 in
 
31
  for i = 0 to n - 1 do
 
32
    a.(i) <- i;
 
33
  done;
 
34
  a
 
35
;;
 
36
let chksorted _ n a = (a = mksorted n);;
 
37
 
 
38
let mkrev n =
 
39
  let a = Array.make n 0 in
 
40
  for i = 0 to n - 1 do
 
41
    a.(i) <- n - 1 - i;
 
42
  done;
 
43
  a
 
44
;;
 
45
let chkrev _ n a = (a = mksorted n);;
 
46
 
 
47
let seed = ref 0;;
 
48
let random_reinit () = Random.init !seed;;
 
49
 
 
50
let random_get_state () =
 
51
  let a = Array.make 55 0 in
 
52
  for i = 0 to 54 do a.(i) <- Random.bits (); done;
 
53
  Random.full_init a;
 
54
  a
 
55
;;
 
56
let random_set_state a = Random.full_init a;;
 
57
 
 
58
let chkgen mke cmp rstate n a =
 
59
  let marks = Array.make n (-1) in
 
60
  let skipmarks l =
 
61
    if marks.(l) = -1 then l else begin
 
62
      let m = ref marks.(l) in
 
63
      while marks.(!m) <> -1 do incr m; done;
 
64
      marks.(l) <- !m;
 
65
      !m
 
66
    end
 
67
  in
 
68
  let linear e l =
 
69
    let l = skipmarks l in
 
70
    let rec loop l =
 
71
      if cmp a.(l) e > 0 then raise Exit
 
72
      else if e = a.(l) then marks.(l) <- l+1
 
73
      else loop (l+1)
 
74
    in loop l
 
75
  in
 
76
  let rec dicho e l r =
 
77
    if l = r then linear e l
 
78
    else begin
 
79
      assert (l < r);
 
80
      let m = (l + r) / 2 in
 
81
      if cmp a.(m) e >= 0 then dicho e l m else dicho e (m + 1) r
 
82
    end
 
83
  in
 
84
  try
 
85
    for i = 0 to n-2 do if cmp a.(i) a.(i+1) > 0 then raise Exit; done;
 
86
    random_set_state rstate;
 
87
    for i = 0 to n-1 do dicho (mke i) 0 (Array.length a - 1); done;
 
88
    true
 
89
  with Exit | Invalid_argument _ -> false;
 
90
;;
 
91
 
 
92
let mkrand_dup n =
 
93
  let a = Array.make n 0 in
 
94
  for i = 0 to (n-1) do a.(i) <- Random.int n; done;
 
95
  a
 
96
;;
 
97
 
 
98
let chkrand_dup rstate n a =
 
99
  chkgen (fun i -> Random.int n) compare rstate n a
 
100
;;
 
101
 
 
102
let mkrand_nodup n =
 
103
  let a = Array.make n 0 in
 
104
  for i = 0 to (n-1) do a.(i) <- Random.bits (); done;
 
105
  a
 
106
;;
 
107
 
 
108
let chkrand_nodup rstate n a =
 
109
  chkgen (fun i -> Random.bits ()) compare rstate n a
 
110
;;
 
111
 
 
112
let mkfloats n =
 
113
  let a = Array.make n 0.0 in
 
114
  for i = 0 to (n-1) do a.(i) <- Random.float 1.0; done;
 
115
  a
 
116
;;
 
117
 
 
118
let chkfloats rstate n a =
 
119
  chkgen (fun i -> Random.float 1.0) compare rstate n a
 
120
;;
 
121
 
 
122
type record = {
 
123
  s1 : string;
 
124
  s2 : string;
 
125
  i1 : int;
 
126
  i2 : int;
 
127
};;
 
128
 
 
129
let rand_string () =
 
130
  let len = Random.int 10 in
 
131
  let s = String.create len in
 
132
  for i = 0 to len-1 do
 
133
    s.[i] <- Char.chr (Random.int 256);
 
134
  done;
 
135
  s
 
136
;;
 
137
 
 
138
let mkrec1 b i = {
 
139
  s1 = rand_string ();
 
140
  s2 = rand_string ();
 
141
  i1 = Random.int b;
 
142
  i2 = i;
 
143
};;
 
144
 
 
145
let mkrecs b n = Array.init n (mkrec1 b);;
 
146
 
 
147
let mkrec1_rev b i = {
 
148
  s1 = rand_string ();
 
149
  s2 = rand_string ();
 
150
  i1 = - i;
 
151
  i2 = i;
 
152
};;
 
153
 
 
154
let mkrecs_rev n = Array.init n (mkrec1_rev 0);;
 
155
 
 
156
let cmpstr r1 r2 =
 
157
  let c1 = compare r1.s1 r2.s1 in
 
158
  if c1 = 0 then compare r1.s2 r2.s2 else c1
 
159
;;
 
160
let lestr r1 r2 =
 
161
  let c1 = compare r1.s1 r2.s1 in
 
162
  if c1 = 0 then r1.s2 <= r2.s2 else (c1 < 0)
 
163
;;
 
164
let chkstr b rstate n a = chkgen (mkrec1 b) cmpstr rstate n a;;
 
165
 
 
166
let cmpint r1 r2 = compare r1.i1 r2.i1;;
 
167
let leint r1 r2 = r1.i1 <= r2.i1;;
 
168
let chkint b rstate n a = chkgen (mkrec1 b) cmpint rstate n a;;
 
169
 
 
170
let cmplex r1 r2 =
 
171
  let c1 = compare r1.i1 r2.i1 in
 
172
  if c1 = 0 then compare r1.i2 r2.i2 else c1
 
173
;;
 
174
let lelex r1 r2 =
 
175
  let c1 = compare r1.i1 r2.i1 in
 
176
  if c1 = 0 then r1.i2 <= r2.i2 else (c1 < 0)
 
177
;;
 
178
let chklex b rstate n a = chkgen (mkrec1 b) cmplex rstate n a;;
 
179
 
 
180
(************************************************************************)
 
181
 
 
182
let lens = [
 
183
  0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 28;
 
184
  100; 127; 128; 129; 191; 192; 193; 506;
 
185
  1000; 1023; 1024; 1025; 1535; 1536; 1537; 2323;
 
186
  4000; 4094; 4096; 4098; 5123;
 
187
];;
 
188
 
 
189
type ('a, 'b, 'c, 'd) aux = {
 
190
  prepf : ('a -> 'a -> int) -> ('a -> 'a -> bool) -> 'b;
 
191
  prepd : 'a array -> 'c;
 
192
  postd : 'a array -> 'd -> 'a array;
 
193
};;
 
194
 
 
195
let ll = { prepf = (fun x y -> y); prepd = Array.to_list; postd = postl };;
 
196
let lc = { prepf = (fun x y -> x); prepd = Array.to_list; postd = postl };;
 
197
let al = { prepf = (fun x y -> y); prepd = id; postd = posta };;
 
198
let ac = { prepf = (fun x y -> x); prepd = id; postd = posta };;
 
199
 
 
200
type 'a outcome = Value of 'a | Exception of exn;;
 
201
 
 
202
let numfailed = ref 0;;
 
203
 
 
204
let test1 name f prepdata postdata cmp desc mk chk =
 
205
  random_reinit ();
 
206
  printf "  %s with %s" name desc;
 
207
  let i = ref 0 in
 
208
  List.iter (fun n ->
 
209
      if !i = 0 then printf "\n    "; incr i; if !i > 11 then i := 0;
 
210
      printf "%5d" n; flush stdout;
 
211
      let rstate = random_get_state () in
 
212
      let a = mk n in
 
213
      let input = prepdata a in
 
214
      let output = try Value (f cmp input) with e -> Exception e in
 
215
      printf "."; flush stdout;
 
216
      begin match output with
 
217
      | Value v ->
 
218
         if not (chk rstate n (postdata a v))
 
219
         then (incr numfailed; printf "\n*** FAIL\n")
 
220
      | Exception e ->
 
221
         incr numfailed; printf "\n*** %s\n" (Printexc.to_string e)
 
222
      end;
 
223
      flush stdout;
 
224
    ) lens;
 
225
  printf "\n";
 
226
;;
 
227
 
 
228
let test name stable f1 f2 aux1 aux2 =
 
229
  printf "Testing %s...\n" name;
 
230
  let t a b c d = test1 name f1 aux1.prepd aux1.postd a b c d in
 
231
  let cmp = aux1.prepf compare (<=) in
 
232
  t cmp "constant ints" mkconst chkconst;
 
233
  t cmp "sorted ints" mksorted chksorted;
 
234
  t cmp "reverse-sorted ints" mkrev chkrev;
 
235
  t cmp "random ints (many dups)" mkrand_dup chkrand_dup;
 
236
  t cmp "random ints (few dups)" mkrand_nodup chkrand_nodup;
 
237
(*
 
238
  let t a b c d = test1 name f3 aux3.prepd aux3.postd a b c d in
 
239
  t cmp "random floats" mkfloats chkfloats;
 
240
*)
 
241
  let t a b c d = test1 name f2 aux2.prepd aux2.postd a b c d in
 
242
  let cmp = aux2.prepf cmpstr lestr in
 
243
  t cmp "records (str)" (mkrecs 1) (chkstr 1);
 
244
  let cmp = aux2.prepf cmpint leint in
 
245
  List.iter (fun m -> t cmp (sprintf "records (int[%d])" m) (mkrecs m)
 
246
                        (chkint m)
 
247
            ) [1; 10; 100; 1000];
 
248
  if stable then
 
249
    List.iter (fun m -> t cmp (sprintf "records (int[%d]) [stable]" m)
 
250
                          (mkrecs m) (chklex m)
 
251
              ) [1; 10; 100; 1000];
 
252
;;
 
253
 
 
254
(************************************************************************)
 
255
 
 
256
(* Warning: rpt_timer cannot be used for the array sorts because
 
257
   the sorting functions have effects.
 
258
*)
 
259
 
 
260
let rpt_timer1 repeat f x =
 
261
  Gc.compact ();
 
262
  ignore (f x);
 
263
  let st = Sys.time () in
 
264
  for i = 1 to repeat do ignore (f x); done;
 
265
  let en = Sys.time () in
 
266
  en -. st
 
267
;;
 
268
 
 
269
let rpt_timer f x =
 
270
  let repeat = ref 1 in
 
271
  let t = ref (rpt_timer1 !repeat f x) in
 
272
  while !t < 0.2 do
 
273
    repeat := 10 * !repeat;
 
274
    t := rpt_timer1 !repeat f x;
 
275
  done;
 
276
  if !t < 2.0 then begin
 
277
    repeat := (int_of_float (10. *. (float !repeat) /. !t) + 1);
 
278
    t := rpt_timer1 !repeat f x;
 
279
  end;
 
280
  !t /. (float !repeat)
 
281
;;
 
282
 
 
283
let timer f x =
 
284
  let st = Sys.time () in
 
285
  ignore (f x);
 
286
  let en = Sys.time () in
 
287
  (en -. st)
 
288
;;
 
289
 
 
290
let table1 limit f mkarg =
 
291
  printf "  %10s  %9s  %9s  %9s  %9s  %9s\n" "n" "t1" "t2" "t3" "t4" "t5";
 
292
  let sz = ref 49151 in
 
293
  while !sz < int_of_float (2. ** float limit) do
 
294
    begin try
 
295
      printf "  %10d  " !sz; flush stdout;
 
296
      for i = 0 to 4 do
 
297
        let arg = mkarg !sz in
 
298
        let t = timer f arg in
 
299
        printf " %.2e   " t; flush stdout;
 
300
      done;
 
301
      printf "\n";
 
302
    with e -> printf "*** %s\n" (Printexc.to_string e);
 
303
    end;
 
304
    flush stdout;
 
305
    sz := 2 * !sz + 1;
 
306
  done;
 
307
;;
 
308
 
 
309
let table2 limit f mkarg =
 
310
  printf "  %10s  %9s  %9s  %9s  %9s  %9s\n"
 
311
         " n" "t" "t/n" "t/nlogn" "t/nlog^2n" "t/n^2";
 
312
  let sz = ref 49151 in
 
313
  while float !sz < 2. ** float limit do
 
314
    begin try
 
315
      printf "  %10d   " !sz; flush stdout;
 
316
      Gc.compact ();
 
317
      let arg = mkarg !sz in
 
318
      let t = timer f arg in
 
319
      let n = float !sz in
 
320
      let logn = log (float !sz) /. log 2. in
 
321
      printf "%.2e   %.2e   %.2e   %.2e   %.2e\n"
 
322
             t (t/.n) (t/.n/.logn) (t/.n/.logn/.logn) (t/.n/.n);
 
323
    with e -> printf "*** %s\n" (Printexc.to_string e);
 
324
    end;
 
325
    flush stdout;
 
326
    sz := 2 * !sz + 1;
 
327
  done;
 
328
;;
 
329
 
 
330
let table3 limit f mkarg =
 
331
  printf "  %10s  %9s  %9s  %9s  %9s  %9s\n" "n" "t1" "t2" "t3" "t4" "t5";
 
332
  let sz = ref 2 in
 
333
  while float !sz < 2. ** float limit do
 
334
    begin try
 
335
      printf "  %10d  " !sz; flush stdout;
 
336
      for i = 0 to 4 do
 
337
        let arg = mkarg !sz in
 
338
        let t = rpt_timer f arg in
 
339
        printf " %.2e   " t; flush stdout;
 
340
      done;
 
341
      printf "\n";
 
342
    with e -> printf "*** %s\n" (Printexc.to_string e);
 
343
    end;
 
344
    flush stdout;
 
345
    sz := 2 * !sz + 1;
 
346
  done;
 
347
;;
 
348
 
 
349
(************************************************************************)
 
350
 
 
351
(* benchmarks:
 
352
   1a. random records, sorted with two keys
 
353
   1b. random integers
 
354
   1c. random floats
 
355
 
 
356
   2a. integers, constant
 
357
   2b. integers, already sorted
 
358
   2c. integers, reverse sorted
 
359
 
 
360
   only for short lists:
 
361
   3a. random records, sorted with two keys
 
362
   3b. random integers
 
363
   3c. random floats
 
364
*)
 
365
let bench1a limit name f aux =
 
366
 
 
367
  (* Don't do benchmarks with assertions enabled. *)
 
368
  assert (not true);
 
369
 
 
370
  random_reinit ();
 
371
 
 
372
  printf "\n%s with random records [10]:\n" name;
 
373
  let cmp = aux.prepf cmplex lelex in
 
374
  table1 limit (f cmp) (fun n -> aux.prepd (mkrecs 10 n));
 
375
;;
 
376
 
 
377
let bench1b limit name f aux =
 
378
 
 
379
  (* Don't do benchmarks with assertions enabled. *)
 
380
  assert (not true);
 
381
 
 
382
  random_reinit ();
 
383
 
 
384
  printf "\n%s with random integers:\n" name;
 
385
  let cmp = aux.prepf (-) (<=) in
 
386
  table1 limit (f cmp) (fun n -> aux.prepd (mkrand_nodup n));
 
387
;;
 
388
 
 
389
let bench1c limit name f aux =
 
390
 
 
391
  (* Don't do benchmarks with assertions enabled. *)
 
392
  assert (not true);
 
393
 
 
394
  random_reinit ();
 
395
 
 
396
  printf "\n%s with random floats:\n" name;
 
397
  let cmp = aux.prepf compare (<=) in
 
398
  table1 limit (f cmp) (fun n -> aux.prepd (mkfloats n));
 
399
;;
 
400
 
 
401
let bench2 limit name f aux =
 
402
 
 
403
  (* Don't do benchmarks with assertions enabled. *)
 
404
  assert (not true);
 
405
 
 
406
  printf "\n%s with constant integers:\n" name;
 
407
  let cmp = aux.prepf compare (<=) in
 
408
  table2 limit (f cmp) (fun n -> aux.prepd (mkconst n));
 
409
 
 
410
  printf "\n%s with sorted integers:\n" name;
 
411
  let cmp = aux.prepf compare (<=) in
 
412
  table2 limit (f cmp) (fun n -> aux.prepd (mksorted n));
 
413
 
 
414
  printf "\n%s with reverse-sorted integers:\n" name;
 
415
  let cmp = aux.prepf compare (<=) in
 
416
  table2 limit (f cmp) (fun n -> aux.prepd (mkrev n));
 
417
;;
 
418
 
 
419
let bench3a limit name f aux =
 
420
 
 
421
  (* Don't do benchmarks with assertions enabled. *)
 
422
  assert (not true);
 
423
 
 
424
  random_reinit ();
 
425
 
 
426
  printf "\n%s with random records [10]:\n" name;
 
427
  let cmp = aux.prepf cmplex lelex in
 
428
  table3 limit (f cmp) (fun n -> aux.prepd (mkrecs 10 n));
 
429
;;
 
430
 
 
431
let bench3b limit name f aux =
 
432
 
 
433
  (* Don't do benchmarks with assertions enabled. *)
 
434
  assert (not true);
 
435
 
 
436
  random_reinit ();
 
437
 
 
438
  printf "\n%s with random integers:\n" name;
 
439
  let cmp = aux.prepf (-) (<=) in
 
440
  table3 limit (f cmp) (fun n -> aux.prepd (mkrand_nodup n));
 
441
;;
 
442
 
 
443
let bench3c limit name f aux =
 
444
 
 
445
  (* Don't do benchmarks with assertions enabled. *)
 
446
  assert (not true);
 
447
 
 
448
  random_reinit ();
 
449
 
 
450
  printf "\n%s with random floats:\n" name;
 
451
  let cmp = aux.prepf compare (<=) in
 
452
  table3 limit (f cmp) (fun n -> aux.prepd (mkfloats n));
 
453
;;
 
454
 
 
455
(************************************************************************)
 
456
(* merge sort on lists *)
 
457
 
 
458
(* FIXME to do: cutoff
 
459
         to do: cascader les pattern-matchings (enlever les paires)
 
460
         to do: fermeture intermediaire pour merge
 
461
*)
 
462
let (@@) = List.rev_append;;
 
463
 
 
464
let lmerge_1a cmp l =
 
465
  let rec init accu = function
 
466
    | [] -> accu
 
467
    | e::rest -> init ([e] :: accu) rest
 
468
  in
 
469
  let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
 
470
                                           accu,accu2 are rev *)
 
471
    match l1, l2 with
 
472
    | []    , _      -> mergepairs ((l2 @@ accu)::accu2) rest
 
473
    | _     , []     -> mergepairs ((l1 @@ accu)::accu2) rest
 
474
    | h1::t1, h2::t2 -> if cmp h1 h2 <= 0
 
475
                        then merge rest accu2 (h1::accu) t1 l2
 
476
                        else merge rest accu2 (h2::accu) l1 t2
 
477
  and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
 
478
                                           l1,l2,rest are rev *)
 
479
    match l1, l2 with
 
480
    | []    , _      -> mergepairs_rev ((l2 @@ accu)::accu2) rest
 
481
    | _     , []     -> mergepairs_rev ((l1 @@ accu)::accu2) rest
 
482
    | h1::t1, h2::t2 -> if cmp h2 h1 <= 0
 
483
                        then merge_rev rest accu2 (h1::accu) t1 l2
 
484
                        else merge_rev rest accu2 (h2::accu) l1 t2
 
485
  and mergepairs accu = function       (* accu is rev, arg is forward *)
 
486
    | [] -> mergeall_rev accu
 
487
    | [l] -> mergeall_rev ((List.rev l)::accu)
 
488
    | l1::l2::rest -> merge rest accu [] l1 l2
 
489
  and mergepairs_rev accu = function   (* accu is forward, arg is rev *)
 
490
    | [] -> mergeall accu
 
491
    | [l] -> mergeall ((List.rev l)::accu)
 
492
    | l1::l2::rest -> merge_rev rest accu [] l1 l2
 
493
  and mergeall = function              (* arg is forward *)
 
494
    | [] -> []
 
495
    | [l] -> l
 
496
    | llist -> mergepairs [] llist
 
497
  and mergeall_rev = function          (* arg is rev *)
 
498
    | [] -> []
 
499
    | [l] -> List.rev l
 
500
    | llist -> mergepairs_rev [] llist
 
501
  in
 
502
  mergeall_rev (init [] l)
 
503
;;
 
504
 
 
505
let lmerge_1b cmp l =
 
506
  let rec init accu = function
 
507
    | [] -> accu
 
508
    | [e] -> [e] :: accu
 
509
    | e1::e2::rest ->
 
510
        init ((if cmp e1 e2 <= 0 then [e2;e1] else [e1;e2])::accu) rest
 
511
  in
 
512
  let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
 
513
                                           accu,accu2 are rev *)
 
514
    match l1, l2 with
 
515
    | []    , _      -> mergepairs ((l2 @@ accu)::accu2) rest
 
516
    | _     , []     -> mergepairs ((l1 @@ accu)::accu2) rest
 
517
    | h1::t1, h2::t2 -> if cmp h1 h2 <= 0
 
518
                        then merge rest accu2 (h1::accu) t1 l2
 
519
                        else merge rest accu2 (h2::accu) l1 t2
 
520
  and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
 
521
                                           l1,l2,rest are rev *)
 
522
    match l1, l2 with
 
523
    | []    , _      -> mergepairs_rev ((l2 @@ accu)::accu2) rest
 
524
    | _     , []     -> mergepairs_rev ((l1 @@ accu)::accu2) rest
 
525
    | h1::t1, h2::t2 -> if cmp h2 h1 <= 0
 
526
                        then merge_rev rest accu2 (h1::accu) t1 l2
 
527
                        else merge_rev rest accu2 (h2::accu) l1 t2
 
528
  and mergepairs accu = function       (* accu is rev, arg is forward *)
 
529
    | [] -> mergeall_rev accu
 
530
    | [l] -> mergeall_rev ((List.rev l)::accu)
 
531
    | l1::l2::rest -> merge rest accu [] l1 l2
 
532
  and mergepairs_rev accu = function   (* accu is forward, arg is rev *)
 
533
    | [] -> mergeall accu
 
534
    | [l] -> mergeall ((List.rev l)::accu)
 
535
    | l1::l2::rest -> merge_rev rest accu [] l1 l2
 
536
  and mergeall = function              (* arg is forward *)
 
537
    | [] -> []
 
538
    | [l] -> l
 
539
    | llist -> mergepairs [] llist
 
540
  and mergeall_rev = function          (* arg is rev *)
 
541
    | [] -> []
 
542
    | [l] -> List.rev l
 
543
    | llist -> mergepairs_rev [] llist
 
544
  in
 
545
  mergeall_rev (init [] l)
 
546
;;
 
547
 
 
548
let lmerge_1c cmp l =
 
549
  let rec init accu = function
 
550
    | [] -> accu
 
551
    | [e] -> [e] :: accu
 
552
    | e1::e2::rest ->
 
553
        init ((if cmp e1 e2 <= 0 then [e2;e1] else [e1;e2])::accu) rest
 
554
  in
 
555
  let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
 
556
                                           accu,accu2 are rev *)
 
557
    match l1 with
 
558
    | [] -> mergepairs ((l2 @@ accu)::accu2) rest
 
559
    | h1::t1 ->
 
560
       match l2 with
 
561
       | []     -> mergepairs ((l1 @@ accu)::accu2) rest
 
562
       | h2::t2 -> if cmp h1 h2 <= 0
 
563
                   then merge rest accu2 (h1::accu) t1 l2
 
564
                   else merge rest accu2 (h2::accu) l1 t2
 
565
  and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
 
566
                                           l1,l2,rest are rev *)
 
567
    match l1 with
 
568
    | [] -> mergepairs_rev ((l2 @@ accu)::accu2) rest
 
569
    | h1::t1 ->
 
570
       match l2 with
 
571
       | []     -> mergepairs_rev ((l1 @@ accu)::accu2) rest
 
572
       | h2::t2 -> if cmp h2 h1 <= 0
 
573
                   then merge_rev rest accu2 (h1::accu) t1 l2
 
574
                   else merge_rev rest accu2 (h2::accu) l1 t2
 
575
  and mergepairs accu = function       (* accu is rev, arg is forward *)
 
576
    | [] -> mergeall_rev accu
 
577
    | [l] -> mergeall_rev ((List.rev l)::accu)
 
578
    | l1::l2::rest -> merge rest accu [] l1 l2
 
579
  and mergepairs_rev accu = function   (* accu is forward, arg is rev *)
 
580
    | [] -> mergeall accu
 
581
    | [l] -> mergeall ((List.rev l)::accu)
 
582
    | l1::l2::rest -> merge_rev rest accu [] l1 l2
 
583
  and mergeall = function              (* arg is forward *)
 
584
    | [] -> []
 
585
    | [l] -> l
 
586
    | llist -> mergepairs [] llist
 
587
  and mergeall_rev = function          (* arg is rev *)
 
588
    | [] -> []
 
589
    | [l] -> List.rev l
 
590
    | llist -> mergepairs_rev [] llist
 
591
  in
 
592
  mergeall_rev (init [] l)
 
593
;;
 
594
 
 
595
let lmerge_1d cmp l =
 
596
  let rec init accu = function
 
597
    | [] -> accu
 
598
    | [e] -> [e] :: accu
 
599
    | e1::e2::rest ->
 
600
        init ((if cmp e1 e2 <= 0 then [e2;e1] else [e1;e2])::accu) rest
 
601
  in
 
602
  let rec merge rest accu2 accu l1 l2 = (* l1,l2,rest are forward;
 
603
                                           accu,accu2 are rev *)
 
604
    let merge_rest_accu2 accu l1 l2 =
 
605
      match l1 with
 
606
      | [] -> mergepairs ((l2 @@ accu)::accu2) rest
 
607
      | h1::t1 ->
 
608
         match l2 with
 
609
         | []     -> mergepairs ((l1 @@ accu)::accu2) rest
 
610
         | h2::t2 -> if cmp h1 h2 <= 0
 
611
                     then merge rest accu2 (h1::accu) t1 l2
 
612
                     else merge rest accu2 (h2::accu) l1 t2
 
613
    in merge_rest_accu2 accu l1 l2
 
614
  and merge_rev rest accu2 accu l1 l2 = (* accu, accu2 are forward;
 
615
                                           l1,l2,rest are rev *)
 
616
    let merge_rev_rest_accu2 accu l1 l2 =
 
617
      match l1 with
 
618
      | [] -> mergepairs_rev ((l2 @@ accu)::accu2) rest
 
619
      | h1::t1 ->
 
620
         match l2 with
 
621
         | []     -> mergepairs_rev ((l1 @@ accu)::accu2) rest
 
622
         | h2::t2 -> if cmp h2 h1 <= 0
 
623
                     then merge_rev rest accu2 (h1::accu) t1 l2
 
624
                     else merge_rev rest accu2 (h2::accu) l1 t2
 
625
    in merge_rev_rest_accu2 accu l1 l2
 
626
  and mergepairs accu = function       (* accu is rev, arg is forward *)
 
627
    | [] -> mergeall_rev accu
 
628
    | [l] -> mergeall_rev ((List.rev l)::accu)
 
629
    | l1::l2::rest -> merge rest accu [] l1 l2
 
630
  and mergepairs_rev accu = function   (* accu is forward, arg is rev *)
 
631
    | [] -> mergeall accu
 
632
    | [l] -> mergeall ((List.rev l)::accu)
 
633
    | l1::l2::rest -> merge_rev rest accu [] l1 l2
 
634
  and mergeall = function              (* arg is forward *)
 
635
    | [] -> []
 
636
    | [l] -> l
 
637
    | llist -> mergepairs [] llist
 
638
  and mergeall_rev = function          (* arg is rev *)
 
639
    | [] -> []
 
640
    | [l] -> List.rev l
 
641
    | llist -> mergepairs_rev [] llist
 
642
  in
 
643
  mergeall_rev (init [] l)
 
644
;;
 
645
 
 
646
(************************************************************************)
 
647
(* merge sort on lists, user-contributed (NOT STABLE) *)
 
648
 
 
649
(* BEGIN code contributed by Yann Coscoy *)
 
650
 
 
651
  let rec rev_merge_append order l1 l2 acc =
 
652
    match l1 with
 
653
      [] ->  List.rev_append l2 acc
 
654
    | h1 :: t1 ->
 
655
        match l2 with
 
656
          [] -> List.rev_append l1 acc
 
657
        | h2 :: t2 ->
 
658
            if order h1 h2
 
659
            then  rev_merge_append order t1 l2 (h1::acc)
 
660
            else  rev_merge_append order l1 t2 (h2::acc)
 
661
 
 
662
  let rev_merge order l1 l2 = rev_merge_append order l1 l2 []
 
663
 
 
664
  let rec rev_merge_append' order l1 l2 acc =
 
665
    match l1 with
 
666
    | [] ->  List.rev_append l2 acc
 
667
    | h1 :: t1 ->
 
668
        match l2 with
 
669
          | [] -> List.rev_append l1 acc
 
670
          | h2 :: t2 ->
 
671
              if order h2 h1
 
672
              then  rev_merge_append' order t1 l2 (h1::acc)
 
673
              else  rev_merge_append' order l1 t2 (h2::acc)
 
674
 
 
675
  let rev_merge' order l1 l2 = rev_merge_append' order l1 l2 []
 
676
 
 
677
  let lmerge_3 order l =
 
678
    let rec initlist l acc = match l with
 
679
      | e1::e2::rest ->
 
680
          initlist rest
 
681
           ((if order e1 e2 then [e1;e2] else [e2;e1])::acc)
 
682
      | [e] -> [e]::acc
 
683
      | [] -> acc
 
684
    in
 
685
    let rec merge2 ll acc  = match ll with
 
686
      | [] -> acc
 
687
      | [l] -> [List.rev l]@acc
 
688
      | l1::l2::rest ->
 
689
          merge2 rest (rev_merge order l1 l2::acc)
 
690
    in
 
691
    let rec merge2' ll acc  = match ll with
 
692
      | [] -> acc
 
693
      | [l] -> [List.rev l]@acc
 
694
      | l1::l2::rest ->
 
695
          merge2' rest (rev_merge' order l1 l2::acc)
 
696
    in
 
697
    let rec mergeall rev = function
 
698
      | [] -> []
 
699
      | [l] -> if rev then List.rev l else l
 
700
      | llist ->
 
701
          mergeall
 
702
          (not rev) ((if rev then merge2' else merge2) llist [])
 
703
    in
 
704
    mergeall false (initlist l [])
 
705
 
 
706
(* END code contributed by Yann Coscoy *)
 
707
 
 
708
(************************************************************************)
 
709
(* merge sort on short lists, Francois Pottier *)
 
710
 
 
711
(* BEGIN code contributed by Francois Pottier *)
 
712
 
 
713
  (* [chop k l] returns the list [l] deprived of its [k] first
 
714
     elements. The length of the list [l] must be [k] at least. *)
 
715
 
 
716
  let rec chop k l =
 
717
    match k, l with
 
718
    | 0, _ -> l
 
719
    | _, x :: l -> chop (k-1) l
 
720
    | _, _ -> assert false
 
721
  ;;
 
722
 
 
723
  let rec merge order l1 l2 =
 
724
    match l1 with
 
725
      [] -> l2
 
726
    | h1 :: t1 ->
 
727
        match l2 with
 
728
          [] -> l1
 
729
        | h2 :: t2 ->
 
730
            if order h1 h2
 
731
            then h1 :: merge order t1 l2
 
732
            else h2 :: merge order l1 t2
 
733
  ;;
 
734
 
 
735
  let rec lmerge_4a order l =
 
736
    match l with
 
737
    | []
 
738
    | [ _ ] -> l
 
739
    | _ ->
 
740
        let rec sort k l = (* k > 1 *)
 
741
          match k, l with
 
742
          | 2, x1 :: x2 :: _ ->
 
743
              if order x1 x2 then [ x1; x2 ] else [ x2; x1 ]
 
744
          | 3, x1 :: x2 :: x3 :: _ ->
 
745
              if order x1 x2 then
 
746
                if order x2 x3 then
 
747
                  [ x1 ; x2 ; x3 ]
 
748
                else
 
749
                  if order x1 x3 then [ x1 ; x3 ; x2 ] else [ x3; x1; x2 ]
 
750
              else
 
751
                if order x1 x3 then
 
752
                  [ x2; x1; x3 ]
 
753
                else
 
754
                  if order x2 x3 then [ x2; x3; x1 ] else [ x3; x2; x1 ]
 
755
          | _, _ ->
 
756
              let k1 = k / 2 in
 
757
              let k2 = k - k1 in
 
758
              merge order (sort k1 l) (sort k2 (chop k1 l))
 
759
        in
 
760
        sort (List.length l) l
 
761
  ;;
 
762
(* END code contributed by Francois Pottier *)
 
763
 
 
764
(************************************************************************)
 
765
(* merge sort on short lists, Francois Pottier,
 
766
   adapted to new-style interface *)
 
767
 
 
768
(* BEGIN code contributed by Francois Pottier *)
 
769
 
 
770
  (* [chop k l] returns the list [l] deprived of its [k] first
 
771
     elements. The length of the list [l] must be [k] at least. *)
 
772
 
 
773
  let rec chop k l =
 
774
    match k, l with
 
775
    | 0, _ -> l
 
776
    | _, x :: l -> chop (k-1) l
 
777
    | _, _ -> assert false
 
778
  ;;
 
779
 
 
780
  let rec merge order l1 l2 =
 
781
    match l1 with
 
782
      [] -> l2
 
783
    | h1 :: t1 ->
 
784
        match l2 with
 
785
          [] -> l1
 
786
        | h2 :: t2 ->
 
787
            if order h1 h2 <= 0
 
788
            then h1 :: merge order t1 l2
 
789
            else h2 :: merge order l1 t2
 
790
  ;;
 
791
 
 
792
  let rec lmerge_4b order l =
 
793
    match l with
 
794
    | []
 
795
    | [ _ ] -> l
 
796
    | _ ->
 
797
        let rec sort k l = (* k > 1 *)
 
798
          match k, l with
 
799
          | 2, x1 :: x2 :: _ ->
 
800
              if order x1 x2 <= 0 then [ x1; x2 ] else [ x2; x1 ]
 
801
          | 3, x1 :: x2 :: x3 :: _ ->
 
802
              if order x1 x2 <= 0 then
 
803
                if order x2 x3 <= 0 then
 
804
                  [ x1 ; x2 ; x3 ]
 
805
                else
 
806
                  if order x1 x3 <= 0 then [ x1 ; x3 ; x2 ] else [ x3; x1; x2 ]
 
807
              else
 
808
                if order x1 x3 <= 0 then
 
809
                  [ x2; x1; x3 ]
 
810
                else
 
811
                  if order x2 x3 <= 0 then [ x2; x3; x1 ] else [ x3; x2; x1 ]
 
812
          | _, _ ->
 
813
              let k1 = k / 2 in
 
814
              let k2 = k - k1 in
 
815
              merge order (sort k1 l) (sort k2 (chop k1 l))
 
816
        in
 
817
        sort (List.length l) l
 
818
  ;;
 
819
(* END code contributed by Francois Pottier *)
 
820
 
 
821
(************************************************************************)
 
822
(* merge sort on short lists a la Pottier, modified merge *)
 
823
 
 
824
let rec chop k l =
 
825
  if k = 0 then l else begin
 
826
    match l with
 
827
    | x::t -> chop (k-1) t
 
828
    | _ -> assert false
 
829
  end
 
830
;;
 
831
 
 
832
let lmerge_4c cmp l =
 
833
  let rec merge1 h1 t1 l2 =
 
834
    match l2 with
 
835
    | [] -> h1 :: t1
 
836
    | h2 :: t2 ->
 
837
        if cmp h1 h2 <= 0
 
838
        then h1 :: (merge2 t1 h2 t2)
 
839
        else h2 :: (merge1 h1 t1 t2)
 
840
  and merge2 l1 h2 t2 =
 
841
    match l1 with
 
842
    | [] -> h2 :: t2
 
843
    | h1 :: t1 ->
 
844
        if cmp h1 h2 <= 0
 
845
        then h1 :: (merge2 t1 h2 t2)
 
846
        else h2 :: (merge1 h1 t1 t2)
 
847
  in
 
848
  let merge l1 = function
 
849
    | [] -> l1
 
850
    | h2 :: t2 -> merge2 l1 h2 t2
 
851
  in
 
852
  let rec sort n l =
 
853
    match n, l with
 
854
    | 2, x1 :: x2 :: _ ->
 
855
       if cmp x1 x2 <= 0 then [x1; x2] else [x2; x1]
 
856
    | 3, x1 :: x2 :: x3 :: _ ->
 
857
       if cmp x1 x2 <= 0 then begin
 
858
         if cmp x2 x3 <= 0 then [x1; x2; x3]
 
859
         else if cmp x1 x3 <= 0 then [x1; x3; x2]
 
860
         else [x3; x1; x2]
 
861
       end else begin
 
862
         if cmp x1 x3 <= 0 then [x2; x1; x3]
 
863
         else if cmp x2 x3 <= 0 then [x2; x3; x1]
 
864
         else [x3; x2; x1]
 
865
       end
 
866
    | n, l ->
 
867
       let n1 = n asr 1 in
 
868
       let n2 = n - n1 in
 
869
       merge (sort n1 l) (sort n2 (chop n1 l))
 
870
  in
 
871
  let len = List.length l in
 
872
  if len < 2 then l else sort len l
 
873
;;
 
874
 
 
875
(************************************************************************)
 
876
(* merge sort on short lists a la Pottier, logarithmic stack space *)
 
877
 
 
878
let rec chop k l =
 
879
  if k = 0 then l else begin
 
880
    match l with
 
881
    | x::t -> chop (k-1) t
 
882
    | _ -> assert false
 
883
  end
 
884
;;
 
885
 
 
886
let lmerge_4d cmp l =
 
887
  let rec rev_merge l1 l2 accu =
 
888
    match l1, l2 with
 
889
    | [], l2 -> l2 @@ accu
 
890
    | l1, [] -> l1 @@ accu
 
891
    | h1::t1, h2::t2 ->
 
892
        if cmp h1 h2 <= 0
 
893
        then rev_merge t1 l2 (h1::accu)
 
894
        else rev_merge l1 t2 (h2::accu)
 
895
  in
 
896
  let rec rev_merge_rev l1 l2 accu =
 
897
    match l1, l2 with
 
898
    | [], l2 -> l2 @@ accu
 
899
    | l1, [] -> l1 @@ accu
 
900
    | h1::t1, h2::t2 ->
 
901
        if cmp h1 h2 > 0
 
902
        then rev_merge_rev t1 l2 (h1::accu)
 
903
        else rev_merge_rev l1 t2 (h2::accu)
 
904
  in
 
905
  let rec sort n l =
 
906
    match n, l with
 
907
    | 2, x1 :: x2 :: _ ->
 
908
       if cmp x1 x2 <= 0 then [x1; x2] else [x2; x1]
 
909
    | 3, x1 :: x2 :: x3 :: _ ->
 
910
       if cmp x1 x2 <= 0 then begin
 
911
         if cmp x2 x3 <= 0 then [x1; x2; x3]
 
912
         else if cmp x1 x3 <= 0 then [x1; x3; x2]
 
913
         else [x3; x1; x2]
 
914
       end else begin
 
915
         if cmp x1 x3 <= 0 then [x2; x1; x3]
 
916
         else if cmp x2 x3 <= 0 then [x2; x3; x1]
 
917
         else [x3; x2; x1]
 
918
       end
 
919
    | n, l ->
 
920
       let n1 = n asr 1 in
 
921
       let n2 = n - n1 in
 
922
       rev_merge_rev (rev_sort n1 l) (rev_sort n2 (chop n1 l)) []
 
923
  and rev_sort n l =
 
924
    match n, l with
 
925
    | 2, x1 :: x2 :: _ ->
 
926
       if cmp x1 x2 > 0 then [x1; x2] else [x2; x1]
 
927
    | 3, x1 :: x2 :: x3 :: _ ->
 
928
       if cmp x1 x2 > 0 then begin
 
929
         if cmp x2 x3 > 0 then [x1; x2; x3]
 
930
         else if cmp x1 x3 > 0 then [x1; x3; x2]
 
931
         else [x3; x1; x2]
 
932
       end else begin
 
933
         if cmp x1 x3 > 0 then [x2; x1; x3]
 
934
         else if cmp x2 x3 > 0 then [x2; x3; x1]
 
935
         else [x3; x2; x1]
 
936
       end
 
937
    | n, l ->
 
938
       let n1 = n asr 1 in
 
939
       let n2 = n - n1 in
 
940
       rev_merge (sort n1 l) (sort n2 (chop n1 l)) []
 
941
  in
 
942
  let len = List.length l in
 
943
  if len < 2 then l else sort len l
 
944
;;
 
945
 
 
946
 
 
947
(************************************************************************)
 
948
(* merge sort on short lists a la Pottier, logarithmic stack space,
 
949
   in place: input list is freed as the output is being computed. *)
 
950
 
 
951
let rec chop k l =
 
952
  if k = 0 then l else begin
 
953
    match l with
 
954
    | x::t -> chop (k-1) t
 
955
    | _ -> assert false
 
956
  end
 
957
;;
 
958
 
 
959
let lmerge_4e cmp l =
 
960
  let rec rev_merge l1 l2 accu =
 
961
    match l1, l2 with
 
962
    | [], l2 -> l2 @@ accu
 
963
    | l1, [] -> l1 @@ accu
 
964
    | h1::t1, h2::t2 ->
 
965
        if cmp h1 h2 <= 0
 
966
        then rev_merge t1 l2 (h1::accu)
 
967
        else rev_merge l1 t2 (h2::accu)
 
968
  in
 
969
  let rec rev_merge_rev l1 l2 accu =
 
970
    match l1, l2 with
 
971
    | [], l2 -> l2 @@ accu
 
972
    | l1, [] -> l1 @@ accu
 
973
    | h1::t1, h2::t2 ->
 
974
        if cmp h1 h2 > 0
 
975
        then rev_merge_rev t1 l2 (h1::accu)
 
976
        else rev_merge_rev l1 t2 (h2::accu)
 
977
  in
 
978
  let rec sort n l =
 
979
    match n, l with
 
980
    | 2, x1 :: x2 :: _ ->
 
981
       if cmp x1 x2 <= 0 then [x1; x2] else [x2; x1]
 
982
    | 3, x1 :: x2 :: x3 :: _ ->
 
983
       if cmp x1 x2 <= 0 then begin
 
984
         if cmp x2 x3 <= 0 then [x1; x2; x3]
 
985
         else if cmp x1 x3 <= 0 then [x1; x3; x2]
 
986
         else [x3; x1; x2]
 
987
       end else begin
 
988
         if cmp x1 x3 <= 0 then [x2; x1; x3]
 
989
         else if cmp x2 x3 <= 0 then [x2; x3; x1]
 
990
         else [x3; x2; x1]
 
991
       end
 
992
    | n, l ->
 
993
       let n1 = n asr 1 in
 
994
       let n2 = n - n1 in
 
995
       let l2 = chop n1 l in
 
996
       let s1 = rev_sort n1 l in
 
997
       let s2 = rev_sort n2 l2 in
 
998
       rev_merge_rev s1 s2 []
 
999
  and rev_sort n l =
 
1000
    match n, l with
 
1001
    | 2, x1 :: x2 :: _ ->
 
1002
       if cmp x1 x2 > 0 then [x1; x2] else [x2; x1]
 
1003
    | 3, x1 :: x2 :: x3 :: _ ->
 
1004
       if cmp x1 x2 > 0 then begin
 
1005
         if cmp x2 x3 > 0 then [x1; x2; x3]
 
1006
         else if cmp x1 x3 > 0 then [x1; x3; x2]
 
1007
         else [x3; x1; x2]
 
1008
       end else begin
 
1009
         if cmp x1 x3 > 0 then [x2; x1; x3]
 
1010
         else if cmp x2 x3 > 0 then [x2; x3; x1]
 
1011
         else [x3; x2; x1]
 
1012
       end
 
1013
    | n, l ->
 
1014
       let n1 = n asr 1 in
 
1015
       let n2 = n - n1 in
 
1016
       let l2 = chop n1 l in
 
1017
       let s1 = sort n1 l in
 
1018
       let s2 = sort n2 l2 in
 
1019
       rev_merge s1 s2 []
 
1020
  in
 
1021
  let len = List.length l in
 
1022
  if len < 2 then l else sort len l
 
1023
;;
 
1024
 
 
1025
(************************************************************************)
 
1026
(* chop-free version of Pottier's code, binary version *)
 
1027
 
 
1028
let rec merge cmp l1 l2 =
 
1029
  match l1, l2 with
 
1030
  | [], l2 -> l2
 
1031
  | l1, [] -> l1
 
1032
  | h1 :: t1, h2 :: t2 ->
 
1033
      if cmp h1 h2 <= 0
 
1034
      then h1 :: merge cmp t1 l2
 
1035
      else h2 :: merge cmp l1 t2
 
1036
;;
 
1037
 
 
1038
let lmerge_5a cmp l =
 
1039
  let rem = ref l in
 
1040
  let rec sort_prefix n =
 
1041
    if n <= 1 then begin
 
1042
      match !rem with
 
1043
      | [] -> []
 
1044
      | [x] as l -> rem := []; l
 
1045
      | x::y::t -> rem := t; if cmp x y <= 0 then [x;y] else [y;x]
 
1046
    end else if !rem = [] then []
 
1047
    else begin
 
1048
      let l1 = sort_prefix (n-1) in
 
1049
      let l2 = sort_prefix (n-1) in
 
1050
      merge cmp l1 l2
 
1051
    end
 
1052
  in
 
1053
  let len = ref (List.length l) in
 
1054
  let i = ref 0 in
 
1055
  while !len > 0 do incr i; len := !len lsr 1; done;
 
1056
  sort_prefix !i
 
1057
;;
 
1058
 
 
1059
(************************************************************************)
 
1060
(* chop-free version of Pottier's code, dichotomic version,
 
1061
   ground cases 1 & 2 *)
 
1062
 
 
1063
let rec merge cmp l1 l2 =
 
1064
  match l1, l2 with
 
1065
  | [], l2 -> l2
 
1066
  | l1, [] -> l1
 
1067
  | h1 :: t1, h2 :: t2 ->
 
1068
      if cmp h1 h2 <= 0
 
1069
      then h1 :: merge cmp t1 l2
 
1070
      else h2 :: merge cmp l1 t2
 
1071
;;
 
1072
 
 
1073
let lmerge_5b cmp l =
 
1074
  let rem = ref l in
 
1075
  let rec sort_prefix n =
 
1076
    match n, !rem with
 
1077
    | 1, x::t -> rem := t; [x]
 
1078
    | 2, x::y::t -> rem := t; if cmp x y <= 0 then [x;y] else [y;x]
 
1079
    | n, _ ->
 
1080
       let n1 = n/2 in
 
1081
       let n2 = n - n1 in
 
1082
       let l1 = sort_prefix n1 in
 
1083
       let l2 = sort_prefix n2 in
 
1084
       merge cmp l1 l2
 
1085
  in
 
1086
  let len = List.length l in
 
1087
  if len <= 1 then l else sort_prefix len
 
1088
;;
 
1089
 
 
1090
(************************************************************************)
 
1091
(* chop-free version of Pottier's code, dichotomic version,
 
1092
   ground cases 2 & 3 *)
 
1093
 
 
1094
let rec merge cmp l1 l2 =
 
1095
  match l1, l2 with
 
1096
  | [], l2 -> l2
 
1097
  | l1, [] -> l1
 
1098
  | h1 :: t1, h2 :: t2 ->
 
1099
      if cmp h1 h2 <= 0
 
1100
      then h1 :: merge cmp t1 l2
 
1101
      else h2 :: merge cmp l1 t2
 
1102
;;
 
1103
 
 
1104
let lmerge_5c cmp l =
 
1105
  let rem = ref l in
 
1106
  let rec sort_prefix n =
 
1107
    match n, !rem with
 
1108
    | 2, x::y::t -> rem := t; if cmp x y <= 0 then [x;y] else [y;x]
 
1109
    | 3, x::y::z::t ->
 
1110
       rem := t;
 
1111
       if cmp x y <= 0 then
 
1112
         if cmp y z <= 0 then [x; y; z]
 
1113
         else if cmp x z <= 0 then [x; z; y]
 
1114
         else [z; x; y]
 
1115
       else
 
1116
         if cmp x z <= 0 then [y; x; z]
 
1117
         else if cmp y z <= 0 then [y; z; x]
 
1118
         else [z; y; x]
 
1119
    | n, _ ->
 
1120
       let n1 = n/2 in
 
1121
       let n2 = n - n1 in
 
1122
       let l1 = sort_prefix n1 in
 
1123
       let l2 = sort_prefix n2 in
 
1124
       merge cmp l1 l2
 
1125
  in
 
1126
  let len = List.length l in
 
1127
  if len <= 1 then l else sort_prefix len
 
1128
;;
 
1129
 
 
1130
(************************************************************************)
 
1131
(* chop-free, ref-free version of Pottier's code, dichotomic version,
 
1132
   ground cases 2 & 3, modified merge *)
 
1133
 
 
1134
let lmerge_5d cmp l =
 
1135
  let rec merge1 h1 t1 l2 =
 
1136
    match l2 with
 
1137
    | [] -> h1::t1
 
1138
    | h2 :: t2 ->
 
1139
        if cmp h1 h2 <= 0
 
1140
        then h1 :: merge2 t1 h2 t2
 
1141
        else h2 :: merge1 h1 t1 t2
 
1142
  and merge2 l1 h2 t2 =
 
1143
    match l1 with
 
1144
    | [] -> h2::t2
 
1145
    | h1 :: t1 ->
 
1146
        if cmp h1 h2 <= 0
 
1147
        then h1 :: merge2 t1 h2 t2
 
1148
        else h2 :: merge1 h1 t1 t2
 
1149
  in
 
1150
  let rec sort_prefix n l =
 
1151
    match n, l with
 
1152
    | 2, x::y::t -> ((if cmp x y <= 0 then [x;y] else [y;x]), t)
 
1153
    | 3, x::y::z::t ->
 
1154
       ((if cmp x y <= 0 then
 
1155
           if cmp y z <= 0 then [x; y; z]
 
1156
           else if cmp x z <= 0 then [x; z; y]
 
1157
           else [z; x; y]
 
1158
         else
 
1159
           if cmp x z <= 0 then [y; x; z]
 
1160
           else if cmp y z <= 0 then [y; z; x]
 
1161
           else [z; y; x]),
 
1162
        t)
 
1163
    | n, _ ->
 
1164
       let n1 = n/2 in
 
1165
       let n2 = n - n1 in
 
1166
       let (l1, rest1) = sort_prefix n1 l in
 
1167
       match sort_prefix n2 rest1 with
 
1168
       | (h2::t2, rest2) -> ((merge2 l1 h2 t2), rest2)
 
1169
       | _ -> assert false
 
1170
  in
 
1171
  let len = List.length l in
 
1172
  if len <= 1 then l else fst (sort_prefix len l)
 
1173
;;
 
1174
 
 
1175
(************************************************************************)
 
1176
(* merge sort on arrays, merge with tail-rec function *)
 
1177
 
 
1178
let amerge_1a cmp a =
 
1179
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1180
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1181
    let rec loop i1 s1 i2 s2 d =
 
1182
      if cmp s1 s2 <= 0 then begin
 
1183
        dst.(d) <- s1;
 
1184
        let i1 = i1 + 1 in
 
1185
        if i1 < src1r then
 
1186
          loop i1 a.(i1) i2 s2 (d + 1)
 
1187
        else
 
1188
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1189
      end else begin
 
1190
        dst.(d) <- s2;
 
1191
        let i2 = i2 + 1 in
 
1192
        if i2 < src2r then
 
1193
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1194
        else
 
1195
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1196
      end
 
1197
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1198
  in
 
1199
  let rec sortto srcofs dst dstofs len =
 
1200
    assert (len > 0);
 
1201
    if len = 1 then dst.(dstofs) <- a.(srcofs)
 
1202
    else begin
 
1203
      let l1 = len / 2 in
 
1204
      let l2 = len - l1 in
 
1205
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1206
      sortto srcofs a (srcofs + l2) l1;
 
1207
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1208
    end;
 
1209
  in
 
1210
  let l = Array.length a in
 
1211
  if l <= 1 then ()
 
1212
  else begin
 
1213
    let l1 = l / 2 in
 
1214
    let l2 = l - l1 in
 
1215
    let t = Array.make l2 a.(0) in
 
1216
    sortto l1 t 0 l2;
 
1217
    sortto 0 a l2 l1;
 
1218
    merge l2 l1 t 0 l2 a 0;
 
1219
  end;
 
1220
;;
 
1221
 
 
1222
let amerge_1b cmp a =
 
1223
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1224
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1225
    let rec loop i1 s1 i2 s2 d =
 
1226
      if cmp s1 s2 <= 0 then begin
 
1227
        dst.(d) <- s1;
 
1228
        let i1 = i1 + 1 in
 
1229
        if i1 < src1r then
 
1230
          loop i1 a.(i1) i2 s2 (d + 1)
 
1231
        else
 
1232
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1233
      end else begin
 
1234
        dst.(d) <- s2;
 
1235
        let i2 = i2 + 1 in
 
1236
        if i2 < src2r then
 
1237
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1238
        else
 
1239
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1240
      end
 
1241
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1242
  in
 
1243
  let rec sortto srcofs dst dstofs len =
 
1244
    assert (len > 0);
 
1245
    if len = 1 then dst.(dstofs) <- a.(srcofs)
 
1246
    else if len = 2 then begin
 
1247
      if cmp a.(srcofs) a.(srcofs+1) <= 0 then begin
 
1248
        dst.(dstofs) <- a.(srcofs);
 
1249
        dst.(dstofs+1) <- a.(srcofs+1);
 
1250
      end else begin
 
1251
        dst.(dstofs) <- a.(srcofs+1);
 
1252
        dst.(dstofs+1) <- a.(srcofs);
 
1253
      end;
 
1254
    end else begin
 
1255
      let l1 = len / 2 in
 
1256
      let l2 = len - l1 in
 
1257
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1258
      sortto srcofs a (srcofs + l2) l1;
 
1259
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1260
    end;
 
1261
  in
 
1262
  let l = Array.length a in
 
1263
  if l <= 1 then ()
 
1264
  else if l = 2 then begin
 
1265
    if cmp a.(0) a.(1) > 0 then begin
 
1266
      let e = a.(0) in
 
1267
      a.(0) <- a.(1);
 
1268
      a.(1) <- e;
 
1269
    end;
 
1270
  end else begin
 
1271
    let l1 = l / 2 in
 
1272
    let l2 = l - l1 in
 
1273
    let t = Array.make l2 a.(0) in
 
1274
    sortto l1 t 0 l2;
 
1275
    sortto 0 a l2 l1;
 
1276
    merge l2 l1 t 0 l2 a 0;
 
1277
  end;
 
1278
;;
 
1279
 
 
1280
let cutoff = 3;;
 
1281
let amerge_1c cmp a =
 
1282
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1283
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1284
    let rec loop i1 s1 i2 s2 d =
 
1285
      if cmp s1 s2 <= 0 then begin
 
1286
        dst.(d) <- s1;
 
1287
        let i1 = i1 + 1 in
 
1288
        if i1 < src1r then
 
1289
          loop i1 a.(i1) i2 s2 (d + 1)
 
1290
        else
 
1291
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1292
      end else begin
 
1293
        dst.(d) <- s2;
 
1294
        let i2 = i2 + 1 in
 
1295
        if i2 < src2r then
 
1296
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1297
        else
 
1298
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1299
      end
 
1300
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1301
  in
 
1302
  let isortto srcofs dst dstofs len =
 
1303
    for i = 0 to len - 1 do
 
1304
      let e = a.(srcofs + i) in
 
1305
      let j = ref (dstofs + i - 1) in
 
1306
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1307
        dst.(!j + 1) <- dst.(!j);
 
1308
        decr j;
 
1309
      done;
 
1310
      dst.(!j + 1) <- e;
 
1311
    done;
 
1312
  in
 
1313
  let rec sortto srcofs dst dstofs len =
 
1314
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1315
      let l1 = len / 2 in
 
1316
      let l2 = len - l1 in
 
1317
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1318
      sortto srcofs a (srcofs + l2) l1;
 
1319
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1320
    end;
 
1321
  in
 
1322
  let l = Array.length a in
 
1323
  if l <= cutoff then isortto 0 a 0 l else begin
 
1324
    let l1 = l / 2 in
 
1325
    let l2 = l - l1 in
 
1326
    let t = Array.make l2 a.(0) in
 
1327
    sortto l1 t 0 l2;
 
1328
    sortto 0 a l2 l1;
 
1329
    merge l2 l1 t 0 l2 a 0;
 
1330
  end;
 
1331
;;
 
1332
 
 
1333
let cutoff = 4;;
 
1334
let amerge_1d cmp a =
 
1335
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1336
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1337
    let rec loop i1 s1 i2 s2 d =
 
1338
      if cmp s1 s2 <= 0 then begin
 
1339
        dst.(d) <- s1;
 
1340
        let i1 = i1 + 1 in
 
1341
        if i1 < src1r then
 
1342
          loop i1 a.(i1) i2 s2 (d + 1)
 
1343
        else
 
1344
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1345
      end else begin
 
1346
        dst.(d) <- s2;
 
1347
        let i2 = i2 + 1 in
 
1348
        if i2 < src2r then
 
1349
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1350
        else
 
1351
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1352
      end
 
1353
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1354
  in
 
1355
  let isortto srcofs dst dstofs len =
 
1356
    for i = 0 to len - 1 do
 
1357
      let e = a.(srcofs + i) in
 
1358
      let j = ref (dstofs + i - 1) in
 
1359
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1360
        dst.(!j + 1) <- dst.(!j);
 
1361
        decr j;
 
1362
      done;
 
1363
      dst.(!j + 1) <- e;
 
1364
    done;
 
1365
  in
 
1366
  let rec sortto srcofs dst dstofs len =
 
1367
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1368
      let l1 = len / 2 in
 
1369
      let l2 = len - l1 in
 
1370
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1371
      sortto srcofs a (srcofs + l2) l1;
 
1372
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1373
    end;
 
1374
  in
 
1375
  let l = Array.length a in
 
1376
  if l <= cutoff then isortto 0 a 0 l else begin
 
1377
    let l1 = l / 2 in
 
1378
    let l2 = l - l1 in
 
1379
    let t = Array.make l2 a.(0) in
 
1380
    sortto l1 t 0 l2;
 
1381
    sortto 0 a l2 l1;
 
1382
    merge l2 l1 t 0 l2 a 0;
 
1383
  end;
 
1384
;;
 
1385
 
 
1386
let cutoff = 5;;
 
1387
let amerge_1e cmp a =
 
1388
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1389
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1390
    let rec loop i1 s1 i2 s2 d =
 
1391
      if cmp s1 s2 <= 0 then begin
 
1392
        dst.(d) <- s1;
 
1393
        let i1 = i1 + 1 in
 
1394
        if i1 < src1r then
 
1395
          loop i1 a.(i1) i2 s2 (d + 1)
 
1396
        else
 
1397
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1398
      end else begin
 
1399
        dst.(d) <- s2;
 
1400
        let i2 = i2 + 1 in
 
1401
        if i2 < src2r then
 
1402
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1403
        else
 
1404
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1405
      end
 
1406
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1407
  in
 
1408
  let isortto srcofs dst dstofs len =
 
1409
    for i = 0 to len - 1 do
 
1410
      let e = a.(srcofs + i) in
 
1411
      let j = ref (dstofs + i - 1) in
 
1412
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1413
        dst.(!j + 1) <- dst.(!j);
 
1414
        decr j;
 
1415
      done;
 
1416
      dst.(!j + 1) <- e;
 
1417
    done;
 
1418
  in
 
1419
  let rec sortto srcofs dst dstofs len =
 
1420
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1421
      let l1 = len / 2 in
 
1422
      let l2 = len - l1 in
 
1423
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1424
      sortto srcofs a (srcofs + l2) l1;
 
1425
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1426
    end;
 
1427
  in
 
1428
  let l = Array.length a in
 
1429
  if l <= cutoff then isortto 0 a 0 l else begin
 
1430
    let l1 = l / 2 in
 
1431
    let l2 = l - l1 in
 
1432
    let t = Array.make l2 a.(0) in
 
1433
    sortto l1 t 0 l2;
 
1434
    sortto 0 a l2 l1;
 
1435
    merge l2 l1 t 0 l2 a 0;
 
1436
  end;
 
1437
;;
 
1438
 
 
1439
let cutoff = 6;;
 
1440
let amerge_1f cmp a =
 
1441
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1442
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1443
    let rec loop i1 s1 i2 s2 d =
 
1444
      if cmp s1 s2 <= 0 then begin
 
1445
        dst.(d) <- s1;
 
1446
        let i1 = i1 + 1 in
 
1447
        if i1 < src1r then
 
1448
          loop i1 a.(i1) i2 s2 (d + 1)
 
1449
        else
 
1450
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1451
      end else begin
 
1452
        dst.(d) <- s2;
 
1453
        let i2 = i2 + 1 in
 
1454
        if i2 < src2r then
 
1455
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1456
        else
 
1457
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1458
      end
 
1459
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1460
  in
 
1461
  let isortto srcofs dst dstofs len =
 
1462
    for i = 0 to len - 1 do
 
1463
      let e = a.(srcofs + i) in
 
1464
      let j = ref (dstofs + i - 1) in
 
1465
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1466
        dst.(!j + 1) <- dst.(!j);
 
1467
        decr j;
 
1468
      done;
 
1469
      dst.(!j + 1) <- e;
 
1470
    done;
 
1471
  in
 
1472
  let rec sortto srcofs dst dstofs len =
 
1473
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1474
      let l1 = len / 2 in
 
1475
      let l2 = len - l1 in
 
1476
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1477
      sortto srcofs a (srcofs + l2) l1;
 
1478
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1479
    end;
 
1480
  in
 
1481
  let l = Array.length a in
 
1482
  if l <= cutoff then isortto 0 a 0 l else begin
 
1483
    let l1 = l / 2 in
 
1484
    let l2 = l - l1 in
 
1485
    let t = Array.make l2 a.(0) in
 
1486
    sortto l1 t 0 l2;
 
1487
    sortto 0 a l2 l1;
 
1488
    merge l2 l1 t 0 l2 a 0;
 
1489
  end;
 
1490
;;
 
1491
 
 
1492
let cutoff = 7;;
 
1493
let amerge_1g cmp a =
 
1494
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1495
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1496
    let rec loop i1 s1 i2 s2 d =
 
1497
      if cmp s1 s2 <= 0 then begin
 
1498
        dst.(d) <- s1;
 
1499
        let i1 = i1 + 1 in
 
1500
        if i1 < src1r then
 
1501
          loop i1 a.(i1) i2 s2 (d + 1)
 
1502
        else
 
1503
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1504
      end else begin
 
1505
        dst.(d) <- s2;
 
1506
        let i2 = i2 + 1 in
 
1507
        if i2 < src2r then
 
1508
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1509
        else
 
1510
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1511
      end
 
1512
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1513
  in
 
1514
  let isortto srcofs dst dstofs len =
 
1515
    for i = 0 to len - 1 do
 
1516
      let e = a.(srcofs + i) in
 
1517
      let j = ref (dstofs + i - 1) in
 
1518
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1519
        dst.(!j + 1) <- dst.(!j);
 
1520
        decr j;
 
1521
      done;
 
1522
      dst.(!j + 1) <- e;
 
1523
    done;
 
1524
  in
 
1525
  let rec sortto srcofs dst dstofs len =
 
1526
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1527
      let l1 = len / 2 in
 
1528
      let l2 = len - l1 in
 
1529
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1530
      sortto srcofs a (srcofs + l2) l1;
 
1531
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1532
    end;
 
1533
  in
 
1534
  let l = Array.length a in
 
1535
  if l <= cutoff then isortto 0 a 0 l else begin
 
1536
    let l1 = l / 2 in
 
1537
    let l2 = l - l1 in
 
1538
    let t = Array.make l2 a.(0) in
 
1539
    sortto l1 t 0 l2;
 
1540
    sortto 0 a l2 l1;
 
1541
    merge l2 l1 t 0 l2 a 0;
 
1542
  end;
 
1543
;;
 
1544
 
 
1545
let cutoff = 8;;
 
1546
let amerge_1h cmp a =
 
1547
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1548
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1549
    let rec loop i1 s1 i2 s2 d =
 
1550
      if cmp s1 s2 <= 0 then begin
 
1551
        dst.(d) <- s1;
 
1552
        let i1 = i1 + 1 in
 
1553
        if i1 < src1r then
 
1554
          loop i1 a.(i1) i2 s2 (d + 1)
 
1555
        else
 
1556
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1557
      end else begin
 
1558
        dst.(d) <- s2;
 
1559
        let i2 = i2 + 1 in
 
1560
        if i2 < src2r then
 
1561
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1562
        else
 
1563
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1564
      end
 
1565
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1566
  in
 
1567
  let isortto srcofs dst dstofs len =
 
1568
    for i = 0 to len - 1 do
 
1569
      let e = a.(srcofs + i) in
 
1570
      let j = ref (dstofs + i - 1) in
 
1571
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1572
        dst.(!j + 1) <- dst.(!j);
 
1573
        decr j;
 
1574
      done;
 
1575
      dst.(!j + 1) <- e;
 
1576
    done;
 
1577
  in
 
1578
  let rec sortto srcofs dst dstofs len =
 
1579
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1580
      let l1 = len / 2 in
 
1581
      let l2 = len - l1 in
 
1582
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1583
      sortto srcofs a (srcofs + l2) l1;
 
1584
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1585
    end;
 
1586
  in
 
1587
  let l = Array.length a in
 
1588
  if l <= cutoff then isortto 0 a 0 l else begin
 
1589
    let l1 = l / 2 in
 
1590
    let l2 = l - l1 in
 
1591
    let t = Array.make l2 a.(0) in
 
1592
    sortto l1 t 0 l2;
 
1593
    sortto 0 a l2 l1;
 
1594
    merge l2 l1 t 0 l2 a 0;
 
1595
  end;
 
1596
;;
 
1597
 
 
1598
let cutoff = 9;;
 
1599
let amerge_1i cmp a =
 
1600
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1601
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1602
    let rec loop i1 s1 i2 s2 d =
 
1603
      if cmp s1 s2 <= 0 then begin
 
1604
        dst.(d) <- s1;
 
1605
        let i1 = i1 + 1 in
 
1606
        if i1 < src1r then
 
1607
          loop i1 a.(i1) i2 s2 (d + 1)
 
1608
        else
 
1609
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1610
      end else begin
 
1611
        dst.(d) <- s2;
 
1612
        let i2 = i2 + 1 in
 
1613
        if i2 < src2r then
 
1614
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1615
        else
 
1616
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1617
      end
 
1618
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1619
  in
 
1620
  let isortto srcofs dst dstofs len =
 
1621
    for i = 0 to len - 1 do
 
1622
      let e = a.(srcofs + i) in
 
1623
      let j = ref (dstofs + i - 1) in
 
1624
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1625
        dst.(!j + 1) <- dst.(!j);
 
1626
        decr j;
 
1627
      done;
 
1628
      dst.(!j + 1) <- e;
 
1629
    done;
 
1630
  in
 
1631
  let rec sortto srcofs dst dstofs len =
 
1632
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1633
      let l1 = len / 2 in
 
1634
      let l2 = len - l1 in
 
1635
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1636
      sortto srcofs a (srcofs + l2) l1;
 
1637
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1638
    end;
 
1639
  in
 
1640
  let l = Array.length a in
 
1641
  if l <= cutoff then isortto 0 a 0 l else begin
 
1642
    let l1 = l / 2 in
 
1643
    let l2 = l - l1 in
 
1644
    let t = Array.make l2 a.(0) in
 
1645
    sortto l1 t 0 l2;
 
1646
    sortto 0 a l2 l1;
 
1647
    merge l2 l1 t 0 l2 a 0;
 
1648
  end;
 
1649
;;
 
1650
 
 
1651
let cutoff = 10;;
 
1652
let amerge_1j cmp a =
 
1653
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1654
    let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
 
1655
    let rec loop i1 s1 i2 s2 d =
 
1656
      if cmp s1 s2 <= 0 then begin
 
1657
        dst.(d) <- s1;
 
1658
        let i1 = i1 + 1 in
 
1659
        if i1 < src1r then
 
1660
          loop i1 a.(i1) i2 s2 (d + 1)
 
1661
        else
 
1662
          Array.blit src2 i2 dst (d + 1) (src2r - i2)
 
1663
      end else begin
 
1664
        dst.(d) <- s2;
 
1665
        let i2 = i2 + 1 in
 
1666
        if i2 < src2r then
 
1667
          loop i1 s1 i2 src2.(i2) (d + 1)
 
1668
        else
 
1669
          Array.blit a i1 dst (d + 1) (src1r - i1)
 
1670
      end
 
1671
    in loop src1ofs a.(src1ofs) src2ofs src2.(src2ofs) dstofs;
 
1672
  in
 
1673
  let isortto srcofs dst dstofs len =
 
1674
    for i = 0 to len - 1 do
 
1675
      let e = a.(srcofs + i) in
 
1676
      let j = ref (dstofs + i - 1) in
 
1677
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1678
        dst.(!j + 1) <- dst.(!j);
 
1679
        decr j;
 
1680
      done;
 
1681
      dst.(!j + 1) <- e;
 
1682
    done;
 
1683
  in
 
1684
  let rec sortto srcofs dst dstofs len =
 
1685
    if len <= cutoff then isortto srcofs dst dstofs len else begin
 
1686
      let l1 = len / 2 in
 
1687
      let l2 = len - l1 in
 
1688
      sortto (srcofs + l1) dst (dstofs + l1) l2;
 
1689
      sortto srcofs a (srcofs + l2) l1;
 
1690
      merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
 
1691
    end;
 
1692
  in
 
1693
  let l = Array.length a in
 
1694
  if l <= cutoff then isortto 0 a 0 l else begin
 
1695
    let l1 = l / 2 in
 
1696
    let l2 = l - l1 in
 
1697
    let t = Array.make l2 a.(0) in
 
1698
    sortto l1 t 0 l2;
 
1699
    sortto 0 a l2 l1;
 
1700
    merge l2 l1 t 0 l2 a 0;
 
1701
  end;
 
1702
;;
 
1703
 
 
1704
(* FIXME a essayer: *)
 
1705
(* list->array->list direct et array->list->array direct *)
 
1706
(* overhead = 1/3, 1/4, etc. *)
 
1707
(* overhead = sqrt (n) *)
 
1708
(* overhead = n/3 jusqu'a 30k, 30k jusqu'a 900M, sqrt (n) au-dela *)
 
1709
 
 
1710
(************************************************************************)
 
1711
(* merge sort on arrays, merge with loop *)
 
1712
 
 
1713
(* cutoff = 1 *)
 
1714
let amerge_3a cmp a =
 
1715
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1716
    let i1 = ref src1ofs
 
1717
    and i2 = ref src2ofs
 
1718
    and d = ref dstofs
 
1719
    and src1r = src1ofs + src1len
 
1720
    and src2r = src2ofs + src2len
 
1721
    in
 
1722
    while !i1 < src1r && !i2 < src2r do
 
1723
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
1724
      if cmp s1 s2 <= 0 then begin
 
1725
        dst.(!d) <- s1;
 
1726
        incr i1;
 
1727
      end else begin
 
1728
        dst.(!d) <- s2;
 
1729
        incr i2;
 
1730
      end;
 
1731
      incr d;
 
1732
    done;
 
1733
    if !i1 < src1r then
 
1734
      Array.blit a !i1 dst !d (src1r - !i1)
 
1735
    else
 
1736
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
1737
  in
 
1738
  let rec sortto srcofs dst dstofs len =
 
1739
    assert (len > 0);
 
1740
    if len = 1 then dst.(dstofs) <- a.(srcofs) else
 
1741
    let l1 = len / 2 in
 
1742
    let l2 = len - l1 in
 
1743
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
1744
    sortto srcofs a (srcofs+l2) l1;
 
1745
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
1746
  in
 
1747
  let l = Array.length a in
 
1748
  if l <= 1 then () else begin
 
1749
    let l1 = l / 2 in
 
1750
    let l2 = l - l1 in
 
1751
    let t = Array.make l2 a.(0) in
 
1752
    sortto l1 t 0 l2;
 
1753
    sortto 0 a l2 l1;
 
1754
    merge l2 l1 t 0 l2 a 0;
 
1755
  end;
 
1756
;;
 
1757
 
 
1758
let amerge_3b cmp a =
 
1759
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1760
    let i1 = ref src1ofs
 
1761
    and i2 = ref src2ofs
 
1762
    and d = ref dstofs
 
1763
    and src1r = src1ofs + src1len
 
1764
    and src2r = src2ofs + src2len
 
1765
    in
 
1766
    while !i1 < src1r && !i2 < src2r do
 
1767
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
1768
      if cmp s1 s2 <= 0 then begin
 
1769
        dst.(!d) <- s1;
 
1770
        incr i1;
 
1771
      end else begin
 
1772
        dst.(!d) <- s2;
 
1773
        incr i2;
 
1774
      end;
 
1775
      incr d;
 
1776
    done;
 
1777
    if !i1 < src1r then
 
1778
      Array.blit a !i1 dst !d (src1r - !i1)
 
1779
    else
 
1780
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
1781
  in
 
1782
  let rec sortto srcofs dst dstofs len =
 
1783
    assert (len > 0);
 
1784
    if len = 1 then dst.(dstofs) <- a.(srcofs)
 
1785
    else if len = 2 then begin
 
1786
      if cmp a.(srcofs) a.(srcofs+1) <= 0 then begin
 
1787
        dst.(dstofs) <- a.(srcofs);
 
1788
        dst.(dstofs+1) <- a.(srcofs+1);
 
1789
      end else begin
 
1790
        dst.(dstofs) <- a.(srcofs+1);
 
1791
        dst.(dstofs+1) <- a.(srcofs);
 
1792
      end
 
1793
    end else begin
 
1794
      let l1 = len / 2 in
 
1795
      let l2 = len - l1 in
 
1796
      sortto (srcofs+l1) dst (dstofs+l1) l2;
 
1797
      sortto srcofs a (srcofs+l2) l1;
 
1798
      merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
1799
    end
 
1800
  in
 
1801
  let l = Array.length a in
 
1802
  if l <= 1 then ()
 
1803
  else if l = 2 then begin
 
1804
    if cmp a.(0) a.(1) > 0 then begin
 
1805
      let e = a.(0) in
 
1806
      a.(0) <- a.(1);
 
1807
      a.(1) <- e;
 
1808
    end;
 
1809
  end else begin
 
1810
    let l1 = l / 2 in
 
1811
    let l2 = l - l1 in
 
1812
    let t = Array.make l2 a.(0) in
 
1813
    sortto l1 t 0 l2;
 
1814
    sortto 0 a l2 l1;
 
1815
    merge l2 l1 t 0 l2 a 0;
 
1816
  end;
 
1817
;;
 
1818
 
 
1819
let cutoff = 3;;
 
1820
let amerge_3c cmp a =
 
1821
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1822
    let i1 = ref src1ofs
 
1823
    and i2 = ref src2ofs
 
1824
    and d = ref dstofs
 
1825
    and src1r = src1ofs + src1len
 
1826
    and src2r = src2ofs + src2len
 
1827
    in
 
1828
    while !i1 < src1r && !i2 < src2r do
 
1829
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
1830
      if cmp s1 s2 <= 0 then begin
 
1831
        dst.(!d) <- s1;
 
1832
        incr i1;
 
1833
      end else begin
 
1834
        dst.(!d) <- s2;
 
1835
        incr i2;
 
1836
      end;
 
1837
      incr d;
 
1838
    done;
 
1839
    if !i1 < src1r then
 
1840
      Array.blit a !i1 dst !d (src1r - !i1)
 
1841
    else
 
1842
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
1843
  in
 
1844
  let isortto srcofs dst dstofs len =
 
1845
    for i = 0 to len-1 do
 
1846
      let e = a.(srcofs+i) in
 
1847
      let j = ref (dstofs+i-1) in
 
1848
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1849
        dst.(!j + 1) <- dst.(!j);
 
1850
        decr j;
 
1851
      done;
 
1852
      dst.(!j + 1) <- e;
 
1853
    done;
 
1854
  in
 
1855
  let rec sortto srcofs dst dstofs len =
 
1856
    if len <= cutoff then isortto srcofs dst dstofs len else
 
1857
    let l1 = len / 2 in
 
1858
    let l2 = len - l1 in
 
1859
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
1860
    sortto srcofs a (srcofs+l2) l1;
 
1861
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
1862
  in
 
1863
  let l = Array.length a in
 
1864
  if l <= cutoff then isortto 0 a 0 l else begin
 
1865
    let l1 = l / 2 in
 
1866
    let l2 = l - l1 in
 
1867
    let t = Array.make l2 a.(0) in
 
1868
    sortto l1 t 0 l2;
 
1869
    sortto 0 a l2 l1;
 
1870
    merge l2 l1 t 0 l2 a 0;
 
1871
  end;
 
1872
;;
 
1873
 
 
1874
let cutoff = 4;;
 
1875
let amerge_3d cmp a =
 
1876
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1877
    let i1 = ref src1ofs
 
1878
    and i2 = ref src2ofs
 
1879
    and d = ref dstofs
 
1880
    and src1r = src1ofs + src1len
 
1881
    and src2r = src2ofs + src2len
 
1882
    in
 
1883
    while !i1 < src1r && !i2 < src2r do
 
1884
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
1885
      if cmp s1 s2 <= 0 then begin
 
1886
        dst.(!d) <- s1;
 
1887
        incr i1;
 
1888
      end else begin
 
1889
        dst.(!d) <- s2;
 
1890
        incr i2;
 
1891
      end;
 
1892
      incr d;
 
1893
    done;
 
1894
    if !i1 < src1r then
 
1895
      Array.blit a !i1 dst !d (src1r - !i1)
 
1896
    else
 
1897
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
1898
  in
 
1899
  let isortto srcofs dst dstofs len =
 
1900
    for i = 0 to len-1 do
 
1901
      let e = a.(srcofs+i) in
 
1902
      let j = ref (dstofs+i-1) in
 
1903
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1904
        dst.(!j + 1) <- dst.(!j);
 
1905
        decr j;
 
1906
      done;
 
1907
      dst.(!j + 1) <- e;
 
1908
    done;
 
1909
  in
 
1910
  let rec sortto srcofs dst dstofs len =
 
1911
    if len <= cutoff then isortto srcofs dst dstofs len else
 
1912
    let l1 = len / 2 in
 
1913
    let l2 = len - l1 in
 
1914
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
1915
    sortto srcofs a (srcofs+l2) l1;
 
1916
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
1917
  in
 
1918
  let l = Array.length a in
 
1919
  if l <= cutoff then isortto 0 a 0 l else begin
 
1920
    let l1 = l / 2 in
 
1921
    let l2 = l - l1 in
 
1922
    let t = Array.make l2 a.(0) in
 
1923
    sortto l1 t 0 l2;
 
1924
    sortto 0 a l2 l1;
 
1925
    merge l2 l1 t 0 l2 a 0;
 
1926
  end;
 
1927
;;
 
1928
 
 
1929
let cutoff = 5;;
 
1930
let amerge_3e cmp a =
 
1931
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1932
    let i1 = ref src1ofs
 
1933
    and i2 = ref src2ofs
 
1934
    and d = ref dstofs
 
1935
    and src1r = src1ofs + src1len
 
1936
    and src2r = src2ofs + src2len
 
1937
    in
 
1938
    while !i1 < src1r && !i2 < src2r do
 
1939
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
1940
      if cmp s1 s2 <= 0 then begin
 
1941
        dst.(!d) <- s1;
 
1942
        incr i1;
 
1943
      end else begin
 
1944
        dst.(!d) <- s2;
 
1945
        incr i2;
 
1946
      end;
 
1947
      incr d;
 
1948
    done;
 
1949
    if !i1 < src1r then
 
1950
      Array.blit a !i1 dst !d (src1r - !i1)
 
1951
    else
 
1952
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
1953
  in
 
1954
  let isortto srcofs dst dstofs len =
 
1955
    for i = 0 to len-1 do
 
1956
      let e = a.(srcofs+i) in
 
1957
      let j = ref (dstofs+i-1) in
 
1958
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
1959
        dst.(!j + 1) <- dst.(!j);
 
1960
        decr j;
 
1961
      done;
 
1962
      dst.(!j + 1) <- e;
 
1963
    done;
 
1964
  in
 
1965
  let rec sortto srcofs dst dstofs len =
 
1966
    if len <= cutoff then isortto srcofs dst dstofs len else
 
1967
    let l1 = len / 2 in
 
1968
    let l2 = len - l1 in
 
1969
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
1970
    sortto srcofs a (srcofs+l2) l1;
 
1971
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
1972
  in
 
1973
  let l = Array.length a in
 
1974
  if l <= cutoff then isortto 0 a 0 l else begin
 
1975
    let l1 = l / 2 in
 
1976
    let l2 = l - l1 in
 
1977
    let t = Array.make l2 a.(0) in
 
1978
    sortto l1 t 0 l2;
 
1979
    sortto 0 a l2 l1;
 
1980
    merge l2 l1 t 0 l2 a 0;
 
1981
  end;
 
1982
;;
 
1983
 
 
1984
let cutoff = 6;;
 
1985
let amerge_3f cmp a =
 
1986
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
1987
    let i1 = ref src1ofs
 
1988
    and i2 = ref src2ofs
 
1989
    and d = ref dstofs
 
1990
    and src1r = src1ofs + src1len
 
1991
    and src2r = src2ofs + src2len
 
1992
    in
 
1993
    while !i1 < src1r && !i2 < src2r do
 
1994
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
1995
      if cmp s1 s2 <= 0 then begin
 
1996
        dst.(!d) <- s1;
 
1997
        incr i1;
 
1998
      end else begin
 
1999
        dst.(!d) <- s2;
 
2000
        incr i2;
 
2001
      end;
 
2002
      incr d;
 
2003
    done;
 
2004
    if !i1 < src1r then
 
2005
      Array.blit a !i1 dst !d (src1r - !i1)
 
2006
    else
 
2007
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
2008
  in
 
2009
  let isortto srcofs dst dstofs len =
 
2010
    for i = 0 to len-1 do
 
2011
      let e = a.(srcofs+i) in
 
2012
      let j = ref (dstofs+i-1) in
 
2013
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
2014
        dst.(!j + 1) <- dst.(!j);
 
2015
        decr j;
 
2016
      done;
 
2017
      dst.(!j + 1) <- e;
 
2018
    done;
 
2019
  in
 
2020
  let rec sortto srcofs dst dstofs len =
 
2021
    if len <= cutoff then isortto srcofs dst dstofs len else
 
2022
    let l1 = len / 2 in
 
2023
    let l2 = len - l1 in
 
2024
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
2025
    sortto srcofs a (srcofs+l2) l1;
 
2026
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
2027
  in
 
2028
  let l = Array.length a in
 
2029
  if l <= cutoff then isortto 0 a 0 l else begin
 
2030
    let l1 = l / 2 in
 
2031
    let l2 = l - l1 in
 
2032
    let t = Array.make l2 a.(0) in
 
2033
    sortto l1 t 0 l2;
 
2034
    sortto 0 a l2 l1;
 
2035
    merge l2 l1 t 0 l2 a 0;
 
2036
  end;
 
2037
;;
 
2038
 
 
2039
let cutoff = 7;;
 
2040
let amerge_3g cmp a =
 
2041
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
2042
    let i1 = ref src1ofs
 
2043
    and i2 = ref src2ofs
 
2044
    and d = ref dstofs
 
2045
    and src1r = src1ofs + src1len
 
2046
    and src2r = src2ofs + src2len
 
2047
    in
 
2048
    while !i1 < src1r && !i2 < src2r do
 
2049
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
2050
      if cmp s1 s2 <= 0 then begin
 
2051
        dst.(!d) <- s1;
 
2052
        incr i1;
 
2053
      end else begin
 
2054
        dst.(!d) <- s2;
 
2055
        incr i2;
 
2056
      end;
 
2057
      incr d;
 
2058
    done;
 
2059
    if !i1 < src1r then
 
2060
      Array.blit a !i1 dst !d (src1r - !i1)
 
2061
    else
 
2062
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
2063
  in
 
2064
  let isortto srcofs dst dstofs len =
 
2065
    for i = 0 to len-1 do
 
2066
      let e = a.(srcofs+i) in
 
2067
      let j = ref (dstofs+i-1) in
 
2068
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
2069
        dst.(!j + 1) <- dst.(!j);
 
2070
        decr j;
 
2071
      done;
 
2072
      dst.(!j + 1) <- e;
 
2073
    done;
 
2074
  in
 
2075
  let rec sortto srcofs dst dstofs len =
 
2076
    if len <= cutoff then isortto srcofs dst dstofs len else
 
2077
    let l1 = len / 2 in
 
2078
    let l2 = len - l1 in
 
2079
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
2080
    sortto srcofs a (srcofs+l2) l1;
 
2081
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
2082
  in
 
2083
  let l = Array.length a in
 
2084
  if l <= cutoff then isortto 0 a 0 l else begin
 
2085
    let l1 = l / 2 in
 
2086
    let l2 = l - l1 in
 
2087
    let t = Array.make l2 a.(0) in
 
2088
    sortto l1 t 0 l2;
 
2089
    sortto 0 a l2 l1;
 
2090
    merge l2 l1 t 0 l2 a 0;
 
2091
  end;
 
2092
;;
 
2093
 
 
2094
let cutoff = 8;;
 
2095
let amerge_3h cmp a =
 
2096
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
2097
    let i1 = ref src1ofs
 
2098
    and i2 = ref src2ofs
 
2099
    and d = ref dstofs
 
2100
    and src1r = src1ofs + src1len
 
2101
    and src2r = src2ofs + src2len
 
2102
    in
 
2103
    while !i1 < src1r && !i2 < src2r do
 
2104
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
2105
      if cmp s1 s2 <= 0 then begin
 
2106
        dst.(!d) <- s1;
 
2107
        incr i1;
 
2108
      end else begin
 
2109
        dst.(!d) <- s2;
 
2110
        incr i2;
 
2111
      end;
 
2112
      incr d;
 
2113
    done;
 
2114
    if !i1 < src1r then
 
2115
      Array.blit a !i1 dst !d (src1r - !i1)
 
2116
    else
 
2117
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
2118
  in
 
2119
  let isortto srcofs dst dstofs len =
 
2120
    for i = 0 to len-1 do
 
2121
      let e = a.(srcofs+i) in
 
2122
      let j = ref (dstofs+i-1) in
 
2123
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
2124
        dst.(!j + 1) <- dst.(!j);
 
2125
        decr j;
 
2126
      done;
 
2127
      dst.(!j + 1) <- e;
 
2128
    done;
 
2129
  in
 
2130
  let rec sortto srcofs dst dstofs len =
 
2131
    if len <= cutoff then isortto srcofs dst dstofs len else
 
2132
    let l1 = len / 2 in
 
2133
    let l2 = len - l1 in
 
2134
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
2135
    sortto srcofs a (srcofs+l2) l1;
 
2136
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
2137
  in
 
2138
  let l = Array.length a in
 
2139
  if l <= cutoff then isortto 0 a 0 l else begin
 
2140
    let l1 = l / 2 in
 
2141
    let l2 = l - l1 in
 
2142
    let t = Array.make l2 a.(0) in
 
2143
    sortto l1 t 0 l2;
 
2144
    sortto 0 a l2 l1;
 
2145
    merge l2 l1 t 0 l2 a 0;
 
2146
  end;
 
2147
;;
 
2148
 
 
2149
let cutoff = 9;;
 
2150
let amerge_3i cmp a =
 
2151
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
2152
    let i1 = ref src1ofs
 
2153
    and i2 = ref src2ofs
 
2154
    and d = ref dstofs
 
2155
    and src1r = src1ofs + src1len
 
2156
    and src2r = src2ofs + src2len
 
2157
    in
 
2158
    while !i1 < src1r && !i2 < src2r do
 
2159
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
2160
      if cmp s1 s2 <= 0 then begin
 
2161
        dst.(!d) <- s1;
 
2162
        incr i1;
 
2163
      end else begin
 
2164
        dst.(!d) <- s2;
 
2165
        incr i2;
 
2166
      end;
 
2167
      incr d;
 
2168
    done;
 
2169
    if !i1 < src1r then
 
2170
      Array.blit a !i1 dst !d (src1r - !i1)
 
2171
    else
 
2172
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
2173
  in
 
2174
  let isortto srcofs dst dstofs len =
 
2175
    for i = 0 to len-1 do
 
2176
      let e = a.(srcofs+i) in
 
2177
      let j = ref (dstofs+i-1) in
 
2178
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
2179
        dst.(!j + 1) <- dst.(!j);
 
2180
        decr j;
 
2181
      done;
 
2182
      dst.(!j + 1) <- e;
 
2183
    done;
 
2184
  in
 
2185
  let rec sortto srcofs dst dstofs len =
 
2186
    if len <= cutoff then isortto srcofs dst dstofs len else
 
2187
    let l1 = len / 2 in
 
2188
    let l2 = len - l1 in
 
2189
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
2190
    sortto srcofs a (srcofs+l2) l1;
 
2191
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
2192
  in
 
2193
  let l = Array.length a in
 
2194
  if l <= cutoff then isortto 0 a 0 l else begin
 
2195
    let l1 = l / 2 in
 
2196
    let l2 = l - l1 in
 
2197
    let t = Array.make l2 a.(0) in
 
2198
    sortto l1 t 0 l2;
 
2199
    sortto 0 a l2 l1;
 
2200
    merge l2 l1 t 0 l2 a 0;
 
2201
  end;
 
2202
;;
 
2203
 
 
2204
let cutoff = 10;;
 
2205
let amerge_3j cmp a =
 
2206
  let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
 
2207
    let i1 = ref src1ofs
 
2208
    and i2 = ref src2ofs
 
2209
    and d = ref dstofs
 
2210
    and src1r = src1ofs + src1len
 
2211
    and src2r = src2ofs + src2len
 
2212
    in
 
2213
    while !i1 < src1r && !i2 < src2r do
 
2214
      let s1 = a.(!i1) and s2 = src2.(!i2) in
 
2215
      if cmp s1 s2 <= 0 then begin
 
2216
        dst.(!d) <- s1;
 
2217
        incr i1;
 
2218
      end else begin
 
2219
        dst.(!d) <- s2;
 
2220
        incr i2;
 
2221
      end;
 
2222
      incr d;
 
2223
    done;
 
2224
    if !i1 < src1r then
 
2225
      Array.blit a !i1 dst !d (src1r - !i1)
 
2226
    else
 
2227
      Array.blit src2 !i2 dst !d (src2r - !i2)
 
2228
  in
 
2229
  let isortto srcofs dst dstofs len =
 
2230
    for i = 0 to len-1 do
 
2231
      let e = a.(srcofs+i) in
 
2232
      let j = ref (dstofs+i-1) in
 
2233
      while (!j >= dstofs && cmp dst.(!j) e > 0) do
 
2234
        dst.(!j + 1) <- dst.(!j);
 
2235
        decr j;
 
2236
      done;
 
2237
      dst.(!j + 1) <- e;
 
2238
    done;
 
2239
  in
 
2240
  let rec sortto srcofs dst dstofs len =
 
2241
    if len <= cutoff then isortto srcofs dst dstofs len else
 
2242
    let l1 = len / 2 in
 
2243
    let l2 = len - l1 in
 
2244
    sortto (srcofs+l1) dst (dstofs+l1) l2;
 
2245
    sortto srcofs a (srcofs+l2) l1;
 
2246
    merge (srcofs+l2) l1 dst (dstofs+l1) l2 dst dstofs;
 
2247
  in
 
2248
  let l = Array.length a in
 
2249
  if l <= cutoff then isortto 0 a 0 l else begin
 
2250
    let l1 = l / 2 in
 
2251
    let l2 = l - l1 in
 
2252
    let t = Array.make l2 a.(0) in
 
2253
    sortto l1 t 0 l2;
 
2254
    sortto 0 a l2 l1;
 
2255
    merge l2 l1 t 0 l2 a 0;
 
2256
  end;
 
2257
;;
 
2258
 
 
2259
(* FIXME essayer bottom-up merge on arrays ? *)
 
2260
 
 
2261
(************************************************************************)
 
2262
(* Shell sort on arrays *)
 
2263
 
 
2264
let ashell_1 cmp a =
 
2265
  let l = Array.length a in
 
2266
  let step = ref 1 in
 
2267
  while !step < l do step := !step * 3 + 1; done;
 
2268
  step := !step / 3;
 
2269
  while !step > 0 do
 
2270
    for j = !step to l-1 do
 
2271
      let e = a.(j) in
 
2272
      let k = ref (j - !step) in
 
2273
      let k1 = ref j in
 
2274
      while !k >= 0 && cmp a.(!k) e > 0 do
 
2275
        a.(!k1) <- a.(!k);
 
2276
        k1 := !k;
 
2277
        k := !k - !step;
 
2278
      done;
 
2279
      a.(!k1) <- e;
 
2280
    done;
 
2281
    step := !step / 3;
 
2282
  done;
 
2283
;;
 
2284
 
 
2285
let ashell_2 cmp a =
 
2286
  let l = Array.length a in
 
2287
  let step = ref 1 in
 
2288
  while !step < l do step := !step * 3 + 1; done;
 
2289
  step := !step / 3;
 
2290
  while !step > 0 do
 
2291
    for j = !step to l-1 do
 
2292
      let e = a.(j) in
 
2293
      let k = ref (j - !step) in
 
2294
      while !k >= 0 && cmp a.(!k) e > 0 do
 
2295
        a.(!k + !step) <- a.(!k);
 
2296
        k := !k - !step;
 
2297
      done;
 
2298
      a.(!k + !step) <- e;
 
2299
    done;
 
2300
    step := !step / 3;
 
2301
  done;
 
2302
;;
 
2303
 
 
2304
let ashell_3 cmp a =
 
2305
  let l = Array.length a in
 
2306
  let step = ref 1 in
 
2307
  while !step < l do step := !step * 3 + 1; done;
 
2308
  step := !step / 3;
 
2309
  while !step > 0 do
 
2310
    for i = 0 to !step - 1 do
 
2311
      let j = ref (i + !step) in
 
2312
      while !j < l do
 
2313
        let e = ref a.(!j) in
 
2314
        let k = ref (!j - !step) in
 
2315
        if cmp !e a.(i) < 0 then begin
 
2316
          let x = !e in e := a.(i); a.(i) <- x;
 
2317
        end;
 
2318
        while cmp a.(!k) !e > 0 do
 
2319
          a.(!k + !step) <- a.(!k);
 
2320
          k := !k - !step;
 
2321
        done;
 
2322
        a.(!k + !step) <- !e;
 
2323
        j := !j + !step;
 
2324
      done;
 
2325
    done;
 
2326
    step := !step / 3;
 
2327
  done;
 
2328
;;
 
2329
 
 
2330
let force = Lazy.force;;
 
2331
 
 
2332
type iilist = Cons of int * iilist Lazy.t;;
 
2333
 
 
2334
let rec mult n (Cons (x,l)) = Cons (n*x, lazy (mult n (force l)))
 
2335
 
 
2336
let rec merge (Cons (x1, t1) as l1) (Cons (x2, t2) as l2) =
 
2337
  if x1 = x2 then Cons (x1, lazy (merge (force t1) (force t2)))
 
2338
  else if x1 < x2 then Cons (x1, lazy (merge (force t1) l2))
 
2339
  else Cons (x2, lazy (merge l1 (force t2)))
 
2340
;;
 
2341
 
 
2342
let rec scale = Cons (1, lazy (merge (mult 2 scale) (mult 3 scale)));;
 
2343
 
 
2344
let ashell_4 cmp a =
 
2345
  let l = Array.length a in
 
2346
  let rec loop1 accu (Cons (x, t)) =
 
2347
    if x > l then accu else loop1 (x::accu) (force t)
 
2348
  in
 
2349
  let sc = loop1 [] scale in
 
2350
  let rec loop2 = function
 
2351
    | [] -> ()
 
2352
    | step::t ->
 
2353
      for i = 0 to step - 1 do
 
2354
        let j = ref (i + step) in
 
2355
        while !j < l do
 
2356
          let e = a.(!j) in
 
2357
          let k = ref (!j - step) in
 
2358
          while !k >= 0 && cmp a.(!k) e > 0 do
 
2359
            a.(!k + step) <- a.(!k);
 
2360
            k := !k - step;
 
2361
          done;
 
2362
          a.(!k + step) <- e;
 
2363
          j := !j + step;
 
2364
        done;
 
2365
      done;
 
2366
      loop2 t;
 
2367
  in
 
2368
  loop2 sc;
 
2369
;;
 
2370
 
 
2371
(************************************************************************)
 
2372
(* Quicksort on arrays *)
 
2373
let cutoff = 1;;
 
2374
let aquick_1a cmp a =
 
2375
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2376
    let m = (l + r) / 2 in
 
2377
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2378
    let pivot = if cmp al am <= 0 then
 
2379
                  if cmp am ar <= 0 then am
 
2380
                  else if cmp al ar <= 0 then ar
 
2381
                  else al
 
2382
                else
 
2383
                  if cmp al ar <= 0 then al
 
2384
                  else if cmp am ar <= 0 then ar
 
2385
                  else am
 
2386
    in
 
2387
    let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
 
2388
    while !p2 <= !p3 do
 
2389
      let e = a.(!p3) in
 
2390
      let c = cmp e pivot in
 
2391
      if c > 0 then begin
 
2392
        decr p3;
 
2393
      end else if c < 0 then begin
 
2394
        a.(!p3) <- a.(!p2);
 
2395
        a.(!p2) <- a.(!p1);
 
2396
        a.(!p1) <- e;
 
2397
        incr p1;
 
2398
        incr p2;
 
2399
      end else begin
 
2400
        a.(!p3) <- a.(!p2);
 
2401
        a.(!p2) <- e;
 
2402
        incr p2;
 
2403
      end;
 
2404
    done;
 
2405
    incr p3;
 
2406
    let len1 = !p1 - l and len2 = r - !p3 in
 
2407
    if len1 > cutoff then
 
2408
      if len2 > cutoff then begin
 
2409
        if len1 < len2
 
2410
        then (qsort l !p1; qsort !p3 r)
 
2411
        else (qsort !p3 r; qsort l !p1)
 
2412
      end else qsort l !p1
 
2413
    else if len2 > cutoff then qsort !p3 r;
 
2414
  in
 
2415
  let l = Array.length a in
 
2416
  if l > 1 then begin
 
2417
    qsort 0 l;
 
2418
    let mini = ref 0 in
 
2419
    for i = 1 to (min l cutoff) - 1 do
 
2420
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2421
    done;
 
2422
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2423
    for i = 1 to l - 1 do
 
2424
      let e = a.(i) in
 
2425
      let j = ref (i - 1) in
 
2426
      while cmp a.(!j) e > 0 do
 
2427
        a.(!j + 1) <- a.(!j);
 
2428
        decr j;
 
2429
      done;
 
2430
      a.(!j + 1) <- e;
 
2431
    done;
 
2432
  end;
 
2433
;;
 
2434
 
 
2435
let cutoff = 2;;
 
2436
let aquick_1b cmp a =
 
2437
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2438
    let m = (l + r) / 2 in
 
2439
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2440
    let pivot = if cmp al am <= 0 then
 
2441
                  if cmp am ar <= 0 then am
 
2442
                  else if cmp al ar <= 0 then ar
 
2443
                  else al
 
2444
                else
 
2445
                  if cmp al ar <= 0 then al
 
2446
                  else if cmp am ar <= 0 then ar
 
2447
                  else am
 
2448
    in
 
2449
    let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
 
2450
    while !p2 <= !p3 do
 
2451
      let e = a.(!p3) in
 
2452
      let c = cmp e pivot in
 
2453
      if c > 0 then begin
 
2454
        decr p3;
 
2455
      end else if c < 0 then begin
 
2456
        a.(!p3) <- a.(!p2);
 
2457
        a.(!p2) <- a.(!p1);
 
2458
        a.(!p1) <- e;
 
2459
        incr p1;
 
2460
        incr p2;
 
2461
      end else begin
 
2462
        a.(!p3) <- a.(!p2);
 
2463
        a.(!p2) <- e;
 
2464
        incr p2;
 
2465
      end;
 
2466
    done;
 
2467
    incr p3;
 
2468
    let len1 = !p1 - l and len2 = r - !p3 in
 
2469
    if len1 > cutoff then
 
2470
      if len2 > cutoff then begin
 
2471
        if len1 < len2
 
2472
        then (qsort l !p1; qsort !p3 r)
 
2473
        else (qsort !p3 r; qsort l !p1)
 
2474
      end else qsort l !p1
 
2475
    else if len2 > cutoff then qsort !p3 r;
 
2476
  in
 
2477
  let l = Array.length a in
 
2478
  if l > 1 then begin
 
2479
    qsort 0 l;
 
2480
    let mini = ref 0 in
 
2481
    for i = 1 to (min l cutoff) - 1 do
 
2482
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2483
    done;
 
2484
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2485
    for i = 1 to l - 1 do
 
2486
      let e = a.(i) in
 
2487
      let j = ref (i - 1) in
 
2488
      while cmp a.(!j) e > 0 do
 
2489
        a.(!j + 1) <- a.(!j);
 
2490
        decr j;
 
2491
      done;
 
2492
      a.(!j + 1) <- e;
 
2493
    done;
 
2494
  end;
 
2495
;;
 
2496
 
 
2497
let cutoff = 3;;
 
2498
let aquick_1c cmp a =
 
2499
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2500
    let m = (l + r) / 2 in
 
2501
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2502
    let pivot = if cmp al am <= 0 then
 
2503
                  if cmp am ar <= 0 then am
 
2504
                  else if cmp al ar <= 0 then ar
 
2505
                  else al
 
2506
                else
 
2507
                  if cmp al ar <= 0 then al
 
2508
                  else if cmp am ar <= 0 then ar
 
2509
                  else am
 
2510
    in
 
2511
    let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
 
2512
    while !p2 <= !p3 do
 
2513
      let e = a.(!p3) in
 
2514
      let c = cmp e pivot in
 
2515
      if c > 0 then begin
 
2516
        decr p3;
 
2517
      end else if c < 0 then begin
 
2518
        a.(!p3) <- a.(!p2);
 
2519
        a.(!p2) <- a.(!p1);
 
2520
        a.(!p1) <- e;
 
2521
        incr p1;
 
2522
        incr p2;
 
2523
      end else begin
 
2524
        a.(!p3) <- a.(!p2);
 
2525
        a.(!p2) <- e;
 
2526
        incr p2;
 
2527
      end;
 
2528
    done;
 
2529
    incr p3;
 
2530
    let len1 = !p1 - l and len2 = r - !p3 in
 
2531
    if len1 > cutoff then
 
2532
      if len2 > cutoff then begin
 
2533
        if len1 < len2
 
2534
        then (qsort l !p1; qsort !p3 r)
 
2535
        else (qsort !p3 r; qsort l !p1)
 
2536
      end else qsort l !p1
 
2537
    else if len2 > cutoff then qsort !p3 r;
 
2538
  in
 
2539
  let l = Array.length a in
 
2540
  if l > 1 then begin
 
2541
    qsort 0 l;
 
2542
    let mini = ref 0 in
 
2543
    for i = 1 to (min l cutoff) - 1 do
 
2544
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2545
    done;
 
2546
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2547
    for i = 1 to l - 1 do
 
2548
      let e = a.(i) in
 
2549
      let j = ref (i - 1) in
 
2550
      while cmp a.(!j) e > 0 do
 
2551
        a.(!j + 1) <- a.(!j);
 
2552
        decr j;
 
2553
      done;
 
2554
      a.(!j + 1) <- e;
 
2555
    done;
 
2556
  end;
 
2557
;;
 
2558
 
 
2559
let cutoff = 4;;
 
2560
let aquick_1d cmp a =
 
2561
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2562
    let m = (l + r) / 2 in
 
2563
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2564
    let pivot = if cmp al am <= 0 then
 
2565
                  if cmp am ar <= 0 then am
 
2566
                  else if cmp al ar <= 0 then ar
 
2567
                  else al
 
2568
                else
 
2569
                  if cmp al ar <= 0 then al
 
2570
                  else if cmp am ar <= 0 then ar
 
2571
                  else am
 
2572
    in
 
2573
    let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
 
2574
    while !p2 <= !p3 do
 
2575
      let e = a.(!p3) in
 
2576
      let c = cmp e pivot in
 
2577
      if c > 0 then begin
 
2578
        decr p3;
 
2579
      end else if c < 0 then begin
 
2580
        a.(!p3) <- a.(!p2);
 
2581
        a.(!p2) <- a.(!p1);
 
2582
        a.(!p1) <- e;
 
2583
        incr p1;
 
2584
        incr p2;
 
2585
      end else begin
 
2586
        a.(!p3) <- a.(!p2);
 
2587
        a.(!p2) <- e;
 
2588
        incr p2;
 
2589
      end;
 
2590
    done;
 
2591
    incr p3;
 
2592
    let len1 = !p1 - l and len2 = r - !p3 in
 
2593
    if len1 > cutoff then
 
2594
      if len2 > cutoff then begin
 
2595
        if len1 < len2
 
2596
        then (qsort l !p1; qsort !p3 r)
 
2597
        else (qsort !p3 r; qsort l !p1)
 
2598
      end else qsort l !p1
 
2599
    else if len2 > cutoff then qsort !p3 r;
 
2600
  in
 
2601
  let l = Array.length a in
 
2602
  if l > 1 then begin
 
2603
    qsort 0 l;
 
2604
    let mini = ref 0 in
 
2605
    for i = 1 to (min l cutoff) - 1 do
 
2606
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2607
    done;
 
2608
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2609
    for i = 1 to l - 1 do
 
2610
      let e = a.(i) in
 
2611
      let j = ref (i - 1) in
 
2612
      while cmp a.(!j) e > 0 do
 
2613
        a.(!j + 1) <- a.(!j);
 
2614
        decr j;
 
2615
      done;
 
2616
      a.(!j + 1) <- e;
 
2617
    done;
 
2618
  end;
 
2619
;;
 
2620
 
 
2621
let cutoff = 5;;
 
2622
let aquick_1e cmp a =
 
2623
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2624
    let m = (l + r) / 2 in
 
2625
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2626
    let pivot = if cmp al am <= 0 then
 
2627
                  if cmp am ar <= 0 then am
 
2628
                  else if cmp al ar <= 0 then ar
 
2629
                  else al
 
2630
                else
 
2631
                  if cmp al ar <= 0 then al
 
2632
                  else if cmp am ar <= 0 then ar
 
2633
                  else am
 
2634
    in
 
2635
    let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
 
2636
    while !p2 <= !p3 do
 
2637
      let e = a.(!p3) in
 
2638
      let c = cmp e pivot in
 
2639
      if c > 0 then begin
 
2640
        decr p3;
 
2641
      end else if c < 0 then begin
 
2642
        a.(!p3) <- a.(!p2);
 
2643
        a.(!p2) <- a.(!p1);
 
2644
        a.(!p1) <- e;
 
2645
        incr p1;
 
2646
        incr p2;
 
2647
      end else begin
 
2648
        a.(!p3) <- a.(!p2);
 
2649
        a.(!p2) <- e;
 
2650
        incr p2;
 
2651
      end;
 
2652
    done;
 
2653
    incr p3;
 
2654
    let len1 = !p1 - l and len2 = r - !p3 in
 
2655
    if len1 > cutoff then
 
2656
      if len2 > cutoff then begin
 
2657
        if len1 < len2
 
2658
        then (qsort l !p1; qsort !p3 r)
 
2659
        else (qsort !p3 r; qsort l !p1)
 
2660
      end else qsort l !p1
 
2661
    else if len2 > cutoff then qsort !p3 r;
 
2662
  in
 
2663
  let l = Array.length a in
 
2664
  if l > 1 then begin
 
2665
    qsort 0 l;
 
2666
    let mini = ref 0 in
 
2667
    for i = 1 to (min l cutoff) - 1 do
 
2668
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2669
    done;
 
2670
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2671
    for i = 1 to l - 1 do
 
2672
      let e = a.(i) in
 
2673
      let j = ref (i - 1) in
 
2674
      while cmp a.(!j) e > 0 do
 
2675
        a.(!j + 1) <- a.(!j);
 
2676
        decr j;
 
2677
      done;
 
2678
      a.(!j + 1) <- e;
 
2679
    done;
 
2680
  end;
 
2681
;;
 
2682
 
 
2683
let cutoff = 6;;
 
2684
let aquick_1f cmp a =
 
2685
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2686
    let m = (l + r) / 2 in
 
2687
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2688
    let pivot = if cmp al am <= 0 then
 
2689
                  if cmp am ar <= 0 then am
 
2690
                  else if cmp al ar <= 0 then ar
 
2691
                  else al
 
2692
                else
 
2693
                  if cmp al ar <= 0 then al
 
2694
                  else if cmp am ar <= 0 then ar
 
2695
                  else am
 
2696
    in
 
2697
    let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
 
2698
    while !p2 <= !p3 do
 
2699
      let e = a.(!p3) in
 
2700
      let c = cmp e pivot in
 
2701
      if c > 0 then begin
 
2702
        decr p3;
 
2703
      end else if c < 0 then begin
 
2704
        a.(!p3) <- a.(!p2);
 
2705
        a.(!p2) <- a.(!p1);
 
2706
        a.(!p1) <- e;
 
2707
        incr p1;
 
2708
        incr p2;
 
2709
      end else begin
 
2710
        a.(!p3) <- a.(!p2);
 
2711
        a.(!p2) <- e;
 
2712
        incr p2;
 
2713
      end;
 
2714
    done;
 
2715
    incr p3;
 
2716
    let len1 = !p1 - l and len2 = r - !p3 in
 
2717
    if len1 > cutoff then
 
2718
      if len2 > cutoff then begin
 
2719
        if len1 < len2
 
2720
        then (qsort l !p1; qsort !p3 r)
 
2721
        else (qsort !p3 r; qsort l !p1)
 
2722
      end else qsort l !p1
 
2723
    else if len2 > cutoff then qsort !p3 r;
 
2724
  in
 
2725
  let l = Array.length a in
 
2726
  if l > 1 then begin
 
2727
    qsort 0 l;
 
2728
    let mini = ref 0 in
 
2729
    for i = 1 to (min l cutoff) - 1 do
 
2730
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2731
    done;
 
2732
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2733
    for i = 1 to l - 1 do
 
2734
      let e = a.(i) in
 
2735
      let j = ref (i - 1) in
 
2736
      while cmp a.(!j) e > 0 do
 
2737
        a.(!j + 1) <- a.(!j);
 
2738
        decr j;
 
2739
      done;
 
2740
      a.(!j + 1) <- e;
 
2741
    done;
 
2742
  end;
 
2743
;;
 
2744
 
 
2745
let cutoff = 7;;
 
2746
let aquick_1g cmp a =
 
2747
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2748
    let m = (l + r) / 2 in
 
2749
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2750
    let pivot = if cmp al am <= 0 then
 
2751
                  if cmp am ar <= 0 then am
 
2752
                  else if cmp al ar <= 0 then ar
 
2753
                  else al
 
2754
                else
 
2755
                  if cmp al ar <= 0 then al
 
2756
                  else if cmp am ar <= 0 then ar
 
2757
                  else am
 
2758
    in
 
2759
    let p1 = ref l and p2 = ref l and p3 = ref (r - 1) in
 
2760
    while !p2 <= !p3 do
 
2761
      let e = a.(!p3) in
 
2762
      let c = cmp e pivot in
 
2763
      if c > 0 then begin
 
2764
        decr p3;
 
2765
      end else if c < 0 then begin
 
2766
        a.(!p3) <- a.(!p2);
 
2767
        a.(!p2) <- a.(!p1);
 
2768
        a.(!p1) <- e;
 
2769
        incr p1;
 
2770
        incr p2;
 
2771
      end else begin
 
2772
        a.(!p3) <- a.(!p2);
 
2773
        a.(!p2) <- e;
 
2774
        incr p2;
 
2775
      end;
 
2776
    done;
 
2777
    incr p3;
 
2778
    let len1 = !p1 - l and len2 = r - !p3 in
 
2779
    if len1 > cutoff then
 
2780
      if len2 > cutoff then begin
 
2781
        if len1 < len2
 
2782
        then (qsort l !p1; qsort !p3 r)
 
2783
        else (qsort !p3 r; qsort l !p1)
 
2784
      end else qsort l !p1
 
2785
    else if len2 > cutoff then qsort !p3 r;
 
2786
  in
 
2787
  let l = Array.length a in
 
2788
  if l > 1 then begin
 
2789
    qsort 0 l;
 
2790
    let mini = ref 0 in
 
2791
    for i = 1 to (min l cutoff) - 1 do
 
2792
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2793
    done;
 
2794
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2795
    for i = 1 to l - 1 do
 
2796
      let e = a.(i) in
 
2797
      let j = ref (i - 1) in
 
2798
      while cmp a.(!j) e > 0 do
 
2799
        a.(!j + 1) <- a.(!j);
 
2800
        decr j;
 
2801
      done;
 
2802
      a.(!j + 1) <- e;
 
2803
    done;
 
2804
  end;
 
2805
;;
 
2806
 
 
2807
let cutoff = 1;;
 
2808
let aquick_2a cmp a =
 
2809
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2810
    let m = (l + r) / 2 in
 
2811
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2812
    let pivot = if cmp al am <= 0 then
 
2813
                  if cmp am ar <= 0 then am
 
2814
                  else if cmp al ar <= 0 then ar
 
2815
                  else al
 
2816
                else
 
2817
                  if cmp al ar <= 0 then al
 
2818
                  else if cmp am ar <= 0 then ar
 
2819
                  else am
 
2820
    in
 
2821
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
2822
    while !p2 < !p3 do
 
2823
      let e = a.(!p2) in
 
2824
      let c = cmp e pivot in
 
2825
      if c > 0 then begin
 
2826
        decr p3;
 
2827
        a.(!p2) <- a.(!p3);
 
2828
        a.(!p3) <- e;
 
2829
      end else if c < 0 then begin
 
2830
        a.(!p2) <- a.(!p1);
 
2831
        a.(!p1) <- e;
 
2832
        incr p1;
 
2833
        incr p2;
 
2834
      end else begin
 
2835
        incr p2;
 
2836
      end;
 
2837
    done;
 
2838
    let len1 = !p1 - l and len2 = r - !p3 in
 
2839
    if len1 > cutoff then
 
2840
      if len2 > cutoff then begin
 
2841
        if len1 < len2
 
2842
        then (qsort l !p1; qsort !p3 r)
 
2843
        else (qsort !p3 r; qsort l !p1)
 
2844
      end else qsort l !p1
 
2845
    else if len2 > cutoff then qsort !p3 r;
 
2846
  in
 
2847
  let l = Array.length a in
 
2848
  if l > 1 then begin
 
2849
    qsort 0 l;
 
2850
    let mini = ref 0 in
 
2851
    for i = 0 to (min l cutoff) - 1 do
 
2852
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2853
    done;
 
2854
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2855
    for i = 1 to l - 1 do
 
2856
      let e = a.(i) in
 
2857
      let j = ref (i - 1) in
 
2858
      while cmp a.(!j) e > 0 do
 
2859
        a.(!j + 1) <- a.(!j);
 
2860
        decr j;
 
2861
      done;
 
2862
      a.(!j + 1) <- e;
 
2863
    done;
 
2864
  end;
 
2865
;;
 
2866
 
 
2867
let cutoff = 2;;
 
2868
let aquick_2b cmp a =
 
2869
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2870
    let m = (l + r) / 2 in
 
2871
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2872
    let pivot = if cmp al am <= 0 then
 
2873
                  if cmp am ar <= 0 then am
 
2874
                  else if cmp al ar <= 0 then ar
 
2875
                  else al
 
2876
                else
 
2877
                  if cmp al ar <= 0 then al
 
2878
                  else if cmp am ar <= 0 then ar
 
2879
                  else am
 
2880
    in
 
2881
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
2882
    while !p2 < !p3 do
 
2883
      let e = a.(!p2) in
 
2884
      let c = cmp e pivot in
 
2885
      if c > 0 then begin
 
2886
        decr p3;
 
2887
        a.(!p2) <- a.(!p3);
 
2888
        a.(!p3) <- e;
 
2889
      end else if c < 0 then begin
 
2890
        a.(!p2) <- a.(!p1);
 
2891
        a.(!p1) <- e;
 
2892
        incr p1;
 
2893
        incr p2;
 
2894
      end else begin
 
2895
        incr p2;
 
2896
      end;
 
2897
    done;
 
2898
    let len1 = !p1 - l and len2 = r - !p3 in
 
2899
    if len1 > cutoff then
 
2900
      if len2 > cutoff then begin
 
2901
        if len1 < len2
 
2902
        then (qsort l !p1; qsort !p3 r)
 
2903
        else (qsort !p3 r; qsort l !p1)
 
2904
      end else qsort l !p1
 
2905
    else if len2 > cutoff then qsort !p3 r;
 
2906
  in
 
2907
  let l = Array.length a in
 
2908
  if l > 1 then begin
 
2909
    qsort 0 l;
 
2910
    let mini = ref 0 in
 
2911
    for i = 0 to (min l cutoff) - 1 do
 
2912
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2913
    done;
 
2914
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2915
    for i = 1 to l - 1 do
 
2916
      let e = a.(i) in
 
2917
      let j = ref (i - 1) in
 
2918
      while cmp a.(!j) e > 0 do
 
2919
        a.(!j + 1) <- a.(!j);
 
2920
        decr j;
 
2921
      done;
 
2922
      a.(!j + 1) <- e;
 
2923
    done;
 
2924
  end;
 
2925
;;
 
2926
 
 
2927
let cutoff = 3;;
 
2928
let aquick_2c cmp a =
 
2929
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2930
    let m = (l + r) / 2 in
 
2931
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2932
    let pivot = if cmp al am <= 0 then
 
2933
                  if cmp am ar <= 0 then am
 
2934
                  else if cmp al ar <= 0 then ar
 
2935
                  else al
 
2936
                else
 
2937
                  if cmp al ar <= 0 then al
 
2938
                  else if cmp am ar <= 0 then ar
 
2939
                  else am
 
2940
    in
 
2941
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
2942
    while !p2 < !p3 do
 
2943
      let e = a.(!p2) in
 
2944
      let c = cmp e pivot in
 
2945
      if c > 0 then begin
 
2946
        decr p3;
 
2947
        a.(!p2) <- a.(!p3);
 
2948
        a.(!p3) <- e;
 
2949
      end else if c < 0 then begin
 
2950
        a.(!p2) <- a.(!p1);
 
2951
        a.(!p1) <- e;
 
2952
        incr p1;
 
2953
        incr p2;
 
2954
      end else begin
 
2955
        incr p2;
 
2956
      end;
 
2957
    done;
 
2958
    let len1 = !p1 - l and len2 = r - !p3 in
 
2959
    if len1 > cutoff then
 
2960
      if len2 > cutoff then begin
 
2961
        if len1 < len2
 
2962
        then (qsort l !p1; qsort !p3 r)
 
2963
        else (qsort !p3 r; qsort l !p1)
 
2964
      end else qsort l !p1
 
2965
    else if len2 > cutoff then qsort !p3 r;
 
2966
  in
 
2967
  let l = Array.length a in
 
2968
  if l > 1 then begin
 
2969
    qsort 0 l;
 
2970
    let mini = ref 0 in
 
2971
    for i = 0 to (min l cutoff) - 1 do
 
2972
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
2973
    done;
 
2974
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
2975
    for i = 1 to l - 1 do
 
2976
      let e = a.(i) in
 
2977
      let j = ref (i - 1) in
 
2978
      while cmp a.(!j) e > 0 do
 
2979
        a.(!j + 1) <- a.(!j);
 
2980
        decr j;
 
2981
      done;
 
2982
      a.(!j + 1) <- e;
 
2983
    done;
 
2984
  end;
 
2985
;;
 
2986
 
 
2987
let cutoff = 4;;
 
2988
let aquick_2d cmp a =
 
2989
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
2990
    let m = (l + r) / 2 in
 
2991
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
2992
    let pivot = if cmp al am <= 0 then
 
2993
                  if cmp am ar <= 0 then am
 
2994
                  else if cmp al ar <= 0 then ar
 
2995
                  else al
 
2996
                else
 
2997
                  if cmp al ar <= 0 then al
 
2998
                  else if cmp am ar <= 0 then ar
 
2999
                  else am
 
3000
    in
 
3001
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3002
    while !p2 < !p3 do
 
3003
      let e = a.(!p2) in
 
3004
      let c = cmp e pivot in
 
3005
      if c > 0 then begin
 
3006
        decr p3;
 
3007
        a.(!p2) <- a.(!p3);
 
3008
        a.(!p3) <- e;
 
3009
      end else if c < 0 then begin
 
3010
        a.(!p2) <- a.(!p1);
 
3011
        a.(!p1) <- e;
 
3012
        incr p1;
 
3013
        incr p2;
 
3014
      end else begin
 
3015
        incr p2;
 
3016
      end;
 
3017
    done;
 
3018
    let len1 = !p1 - l and len2 = r - !p3 in
 
3019
    if len1 > cutoff then
 
3020
      if len2 > cutoff then begin
 
3021
        if len1 < len2
 
3022
        then (qsort l !p1; qsort !p3 r)
 
3023
        else (qsort !p3 r; qsort l !p1)
 
3024
      end else qsort l !p1
 
3025
    else if len2 > cutoff then qsort !p3 r;
 
3026
  in
 
3027
  let l = Array.length a in
 
3028
  if l > 1 then begin
 
3029
    qsort 0 l;
 
3030
    let mini = ref 0 in
 
3031
    for i = 0 to (min l cutoff) - 1 do
 
3032
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3033
    done;
 
3034
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3035
    for i = 1 to l - 1 do
 
3036
      let e = a.(i) in
 
3037
      let j = ref (i - 1) in
 
3038
      while cmp a.(!j) e > 0 do
 
3039
        a.(!j + 1) <- a.(!j);
 
3040
        decr j;
 
3041
      done;
 
3042
      a.(!j + 1) <- e;
 
3043
    done;
 
3044
  end;
 
3045
;;
 
3046
 
 
3047
let cutoff = 5;;
 
3048
let aquick_2e cmp a =
 
3049
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3050
    let m = (l + r) / 2 in
 
3051
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3052
    let pivot = if cmp al am <= 0 then
 
3053
                  if cmp am ar <= 0 then am
 
3054
                  else if cmp al ar <= 0 then ar
 
3055
                  else al
 
3056
                else
 
3057
                  if cmp al ar <= 0 then al
 
3058
                  else if cmp am ar <= 0 then ar
 
3059
                  else am
 
3060
    in
 
3061
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3062
    while !p2 < !p3 do
 
3063
      let e = a.(!p2) in
 
3064
      let c = cmp e pivot in
 
3065
      if c > 0 then begin
 
3066
        decr p3;
 
3067
        a.(!p2) <- a.(!p3);
 
3068
        a.(!p3) <- e;
 
3069
      end else if c < 0 then begin
 
3070
        a.(!p2) <- a.(!p1);
 
3071
        a.(!p1) <- e;
 
3072
        incr p1;
 
3073
        incr p2;
 
3074
      end else begin
 
3075
        incr p2;
 
3076
      end;
 
3077
    done;
 
3078
    let len1 = !p1 - l and len2 = r - !p3 in
 
3079
    if len1 > cutoff then
 
3080
      if len2 > cutoff then begin
 
3081
        if len1 < len2
 
3082
        then (qsort l !p1; qsort !p3 r)
 
3083
        else (qsort !p3 r; qsort l !p1)
 
3084
      end else qsort l !p1
 
3085
    else if len2 > cutoff then qsort !p3 r;
 
3086
  in
 
3087
  let l = Array.length a in
 
3088
  if l > 1 then begin
 
3089
    qsort 0 l;
 
3090
    let mini = ref 0 in
 
3091
    for i = 0 to (min l cutoff) - 1 do
 
3092
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3093
    done;
 
3094
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3095
    for i = 1 to l - 1 do
 
3096
      let e = a.(i) in
 
3097
      let j = ref (i - 1) in
 
3098
      while cmp a.(!j) e > 0 do
 
3099
        a.(!j + 1) <- a.(!j);
 
3100
        decr j;
 
3101
      done;
 
3102
      a.(!j + 1) <- e;
 
3103
    done;
 
3104
  end;
 
3105
;;
 
3106
 
 
3107
let cutoff = 6;;
 
3108
let aquick_2f cmp a =
 
3109
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3110
    let m = (l + r) / 2 in
 
3111
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3112
    let pivot = if cmp al am <= 0 then
 
3113
                  if cmp am ar <= 0 then am
 
3114
                  else if cmp al ar <= 0 then ar
 
3115
                  else al
 
3116
                else
 
3117
                  if cmp al ar <= 0 then al
 
3118
                  else if cmp am ar <= 0 then ar
 
3119
                  else am
 
3120
    in
 
3121
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3122
    while !p2 < !p3 do
 
3123
      let e = a.(!p2) in
 
3124
      let c = cmp e pivot in
 
3125
      if c > 0 then begin
 
3126
        decr p3;
 
3127
        a.(!p2) <- a.(!p3);
 
3128
        a.(!p3) <- e;
 
3129
      end else if c < 0 then begin
 
3130
        a.(!p2) <- a.(!p1);
 
3131
        a.(!p1) <- e;
 
3132
        incr p1;
 
3133
        incr p2;
 
3134
      end else begin
 
3135
        incr p2;
 
3136
      end;
 
3137
    done;
 
3138
    let len1 = !p1 - l and len2 = r - !p3 in
 
3139
    if len1 > cutoff then
 
3140
      if len2 > cutoff then begin
 
3141
        if len1 < len2
 
3142
        then (qsort l !p1; qsort !p3 r)
 
3143
        else (qsort !p3 r; qsort l !p1)
 
3144
      end else qsort l !p1
 
3145
    else if len2 > cutoff then qsort !p3 r;
 
3146
  in
 
3147
  let l = Array.length a in
 
3148
  if l > 1 then begin
 
3149
    qsort 0 l;
 
3150
    let mini = ref 0 in
 
3151
    for i = 0 to (min l cutoff) - 1 do
 
3152
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3153
    done;
 
3154
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3155
    for i = 1 to l - 1 do
 
3156
      let e = a.(i) in
 
3157
      let j = ref (i - 1) in
 
3158
      while cmp a.(!j) e > 0 do
 
3159
        a.(!j + 1) <- a.(!j);
 
3160
        decr j;
 
3161
      done;
 
3162
      a.(!j + 1) <- e;
 
3163
    done;
 
3164
  end;
 
3165
;;
 
3166
 
 
3167
let cutoff = 7;;
 
3168
let aquick_2g cmp a =
 
3169
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3170
    let m = (l + r) / 2 in
 
3171
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3172
    let pivot = if cmp al am <= 0 then
 
3173
                  if cmp am ar <= 0 then am
 
3174
                  else if cmp al ar <= 0 then ar
 
3175
                  else al
 
3176
                else
 
3177
                  if cmp al ar <= 0 then al
 
3178
                  else if cmp am ar <= 0 then ar
 
3179
                  else am
 
3180
    in
 
3181
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3182
    while !p2 < !p3 do
 
3183
      let e = a.(!p2) in
 
3184
      let c = cmp e pivot in
 
3185
      if c > 0 then begin
 
3186
        decr p3;
 
3187
        a.(!p2) <- a.(!p3);
 
3188
        a.(!p3) <- e;
 
3189
      end else if c < 0 then begin
 
3190
        a.(!p2) <- a.(!p1);
 
3191
        a.(!p1) <- e;
 
3192
        incr p1;
 
3193
        incr p2;
 
3194
      end else begin
 
3195
        incr p2;
 
3196
      end;
 
3197
    done;
 
3198
    let len1 = !p1 - l and len2 = r - !p3 in
 
3199
    if len1 > cutoff then
 
3200
      if len2 > cutoff then begin
 
3201
        if len1 < len2
 
3202
        then (qsort l !p1; qsort !p3 r)
 
3203
        else (qsort !p3 r; qsort l !p1)
 
3204
      end else qsort l !p1
 
3205
    else if len2 > cutoff then qsort !p3 r;
 
3206
  in
 
3207
  let l = Array.length a in
 
3208
  if l > 1 then begin
 
3209
    qsort 0 l;
 
3210
    let mini = ref 0 in
 
3211
    for i = 0 to (min l cutoff) - 1 do
 
3212
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3213
    done;
 
3214
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3215
    for i = 1 to l - 1 do
 
3216
      let e = a.(i) in
 
3217
      let j = ref (i - 1) in
 
3218
      while cmp a.(!j) e > 0 do
 
3219
        a.(!j + 1) <- a.(!j);
 
3220
        decr j;
 
3221
      done;
 
3222
      a.(!j + 1) <- e;
 
3223
    done;
 
3224
  end;
 
3225
;;
 
3226
 
 
3227
let cutoff = 1;;
 
3228
let aquick_3a cmp a =
 
3229
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3230
    let m = (l + r) / 2 in
 
3231
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3232
    let pivot = if cmp al am <= 0 then
 
3233
                  if cmp am ar <= 0 then am
 
3234
                  else if cmp al ar <= 0 then ar
 
3235
                  else al
 
3236
                else
 
3237
                  if cmp al ar <= 0 then al
 
3238
                  else if cmp am ar <= 0 then ar
 
3239
                  else am
 
3240
    in
 
3241
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3242
    while !p2 < !p3 do
 
3243
      let e = a.(!p2) in
 
3244
      let c = cmp e pivot in
 
3245
      if c > 0 then begin
 
3246
        decr p3;
 
3247
        a.(!p2) <- a.(!p3);
 
3248
        a.(!p3) <- e;
 
3249
      end else if c < 0 then begin
 
3250
        incr p2;
 
3251
      end else begin
 
3252
        a.(!p2) <- a.(!p1);
 
3253
        a.(!p1) <- e;
 
3254
        incr p1;
 
3255
        incr p2;
 
3256
      end
 
3257
    done;
 
3258
    while !p1 > l do
 
3259
      decr p1;
 
3260
      decr p2;
 
3261
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3262
    done;
 
3263
    let len1 = !p2 - l and len2 = r - !p3 in
 
3264
    if len1 > cutoff then
 
3265
      if len2 > cutoff then begin
 
3266
        if len1 < len2
 
3267
        then (qsort l !p2; qsort !p3 r)
 
3268
        else (qsort !p3 r; qsort l !p2)
 
3269
      end else qsort l !p2
 
3270
    else if len2 > cutoff then qsort !p3 r;
 
3271
  in
 
3272
  let l = Array.length a in
 
3273
  if l > 1 then begin
 
3274
    qsort 0 l;
 
3275
    let mini = ref 0 in
 
3276
    for i = 0 to (min l cutoff) - 1 do
 
3277
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3278
    done;
 
3279
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3280
    for i = 1 to l - 1 do
 
3281
      let e = a.(i) in
 
3282
      let j = ref (i - 1) in
 
3283
      while cmp a.(!j) e > 0 do
 
3284
        a.(!j + 1) <- a.(!j);
 
3285
        decr j;
 
3286
      done;
 
3287
      a.(!j + 1) <- e;
 
3288
    done;
 
3289
  end;
 
3290
;;
 
3291
 
 
3292
let cutoff = 2;;
 
3293
let aquick_3b cmp a =
 
3294
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3295
    let m = (l + r) / 2 in
 
3296
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3297
    let pivot = if cmp al am <= 0 then
 
3298
                  if cmp am ar <= 0 then am
 
3299
                  else if cmp al ar <= 0 then ar
 
3300
                  else al
 
3301
                else
 
3302
                  if cmp al ar <= 0 then al
 
3303
                  else if cmp am ar <= 0 then ar
 
3304
                  else am
 
3305
    in
 
3306
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3307
    while !p2 < !p3 do
 
3308
      let e = a.(!p2) in
 
3309
      let c = cmp e pivot in
 
3310
      if c > 0 then begin
 
3311
        decr p3;
 
3312
        a.(!p2) <- a.(!p3);
 
3313
        a.(!p3) <- e;
 
3314
      end else if c < 0 then begin
 
3315
        incr p2;
 
3316
      end else begin
 
3317
        a.(!p2) <- a.(!p1);
 
3318
        a.(!p1) <- e;
 
3319
        incr p1;
 
3320
        incr p2;
 
3321
      end
 
3322
    done;
 
3323
    while !p1 > l do
 
3324
      decr p1;
 
3325
      decr p2;
 
3326
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3327
    done;
 
3328
    let len1 = !p2 - l and len2 = r - !p3 in
 
3329
    if len1 > cutoff then
 
3330
      if len2 > cutoff then begin
 
3331
        if len1 < len2
 
3332
        then (qsort l !p2; qsort !p3 r)
 
3333
        else (qsort !p3 r; qsort l !p2)
 
3334
      end else qsort l !p2
 
3335
    else if len2 > cutoff then qsort !p3 r;
 
3336
  in
 
3337
  let l = Array.length a in
 
3338
  if l > 1 then begin
 
3339
    qsort 0 l;
 
3340
    let mini = ref 0 in
 
3341
    for i = 0 to (min l cutoff) - 1 do
 
3342
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3343
    done;
 
3344
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3345
    for i = 1 to l - 1 do
 
3346
      let e = a.(i) in
 
3347
      let j = ref (i - 1) in
 
3348
      while cmp a.(!j) e > 0 do
 
3349
        a.(!j + 1) <- a.(!j);
 
3350
        decr j;
 
3351
      done;
 
3352
      a.(!j + 1) <- e;
 
3353
    done;
 
3354
  end;
 
3355
;;
 
3356
 
 
3357
let cutoff = 3;;
 
3358
let aquick_3c cmp a =
 
3359
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3360
    let m = (l + r) / 2 in
 
3361
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3362
    let pivot = if cmp al am <= 0 then
 
3363
                  if cmp am ar <= 0 then am
 
3364
                  else if cmp al ar <= 0 then ar
 
3365
                  else al
 
3366
                else
 
3367
                  if cmp al ar <= 0 then al
 
3368
                  else if cmp am ar <= 0 then ar
 
3369
                  else am
 
3370
    in
 
3371
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3372
    while !p2 < !p3 do
 
3373
      let e = a.(!p2) in
 
3374
      let c = cmp e pivot in
 
3375
      if c > 0 then begin
 
3376
        decr p3;
 
3377
        a.(!p2) <- a.(!p3);
 
3378
        a.(!p3) <- e;
 
3379
      end else if c < 0 then begin
 
3380
        incr p2;
 
3381
      end else begin
 
3382
        a.(!p2) <- a.(!p1);
 
3383
        a.(!p1) <- e;
 
3384
        incr p1;
 
3385
        incr p2;
 
3386
      end
 
3387
    done;
 
3388
    while !p1 > l do
 
3389
      decr p1;
 
3390
      decr p2;
 
3391
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3392
    done;
 
3393
    let len1 = !p2 - l and len2 = r - !p3 in
 
3394
    if len1 > cutoff then
 
3395
      if len2 > cutoff then begin
 
3396
        if len1 < len2
 
3397
        then (qsort l !p2; qsort !p3 r)
 
3398
        else (qsort !p3 r; qsort l !p2)
 
3399
      end else qsort l !p2
 
3400
    else if len2 > cutoff then qsort !p3 r;
 
3401
  in
 
3402
  let l = Array.length a in
 
3403
  if l > 1 then begin
 
3404
    qsort 0 l;
 
3405
    let mini = ref 0 in
 
3406
    for i = 0 to (min l cutoff) - 1 do
 
3407
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3408
    done;
 
3409
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3410
    for i = 1 to l - 1 do
 
3411
      let e = a.(i) in
 
3412
      let j = ref (i - 1) in
 
3413
      while cmp a.(!j) e > 0 do
 
3414
        a.(!j + 1) <- a.(!j);
 
3415
        decr j;
 
3416
      done;
 
3417
      a.(!j + 1) <- e;
 
3418
    done;
 
3419
  end;
 
3420
;;
 
3421
 
 
3422
let cutoff = 4;;
 
3423
let aquick_3d cmp a =
 
3424
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3425
    let m = (l + r) / 2 in
 
3426
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3427
    let pivot = if cmp al am <= 0 then
 
3428
                  if cmp am ar <= 0 then am
 
3429
                  else if cmp al ar <= 0 then ar
 
3430
                  else al
 
3431
                else
 
3432
                  if cmp al ar <= 0 then al
 
3433
                  else if cmp am ar <= 0 then ar
 
3434
                  else am
 
3435
    in
 
3436
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3437
    while !p2 < !p3 do
 
3438
      let e = a.(!p2) in
 
3439
      let c = cmp e pivot in
 
3440
      if c > 0 then begin
 
3441
        decr p3;
 
3442
        a.(!p2) <- a.(!p3);
 
3443
        a.(!p3) <- e;
 
3444
      end else if c < 0 then begin
 
3445
        incr p2;
 
3446
      end else begin
 
3447
        a.(!p2) <- a.(!p1);
 
3448
        a.(!p1) <- e;
 
3449
        incr p1;
 
3450
        incr p2;
 
3451
      end
 
3452
    done;
 
3453
    while !p1 > l do
 
3454
      decr p1;
 
3455
      decr p2;
 
3456
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3457
    done;
 
3458
    let len1 = !p2 - l and len2 = r - !p3 in
 
3459
    if len1 > cutoff then
 
3460
      if len2 > cutoff then begin
 
3461
        if len1 < len2
 
3462
        then (qsort l !p2; qsort !p3 r)
 
3463
        else (qsort !p3 r; qsort l !p2)
 
3464
      end else qsort l !p2
 
3465
    else if len2 > cutoff then qsort !p3 r;
 
3466
  in
 
3467
  let l = Array.length a in
 
3468
  if l > 1 then begin
 
3469
    qsort 0 l;
 
3470
    let mini = ref 0 in
 
3471
    for i = 0 to (min l cutoff) - 1 do
 
3472
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3473
    done;
 
3474
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3475
    for i = 1 to l - 1 do
 
3476
      let e = a.(i) in
 
3477
      let j = ref (i - 1) in
 
3478
      while cmp a.(!j) e > 0 do
 
3479
        a.(!j + 1) <- a.(!j);
 
3480
        decr j;
 
3481
      done;
 
3482
      a.(!j + 1) <- e;
 
3483
    done;
 
3484
  end;
 
3485
;;
 
3486
 
 
3487
let cutoff = 5;;
 
3488
let aquick_3e cmp a =
 
3489
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3490
    let m = (l + r) / 2 in
 
3491
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3492
    let pivot = if cmp al am <= 0 then
 
3493
                  if cmp am ar <= 0 then am
 
3494
                  else if cmp al ar <= 0 then ar
 
3495
                  else al
 
3496
                else
 
3497
                  if cmp al ar <= 0 then al
 
3498
                  else if cmp am ar <= 0 then ar
 
3499
                  else am
 
3500
    in
 
3501
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3502
    while !p2 < !p3 do
 
3503
      let e = a.(!p2) in
 
3504
      let c = cmp e pivot in
 
3505
      if c > 0 then begin
 
3506
        decr p3;
 
3507
        a.(!p2) <- a.(!p3);
 
3508
        a.(!p3) <- e;
 
3509
      end else if c < 0 then begin
 
3510
        incr p2;
 
3511
      end else begin
 
3512
        a.(!p2) <- a.(!p1);
 
3513
        a.(!p1) <- e;
 
3514
        incr p1;
 
3515
        incr p2;
 
3516
      end
 
3517
    done;
 
3518
    while !p1 > l do
 
3519
      decr p1;
 
3520
      decr p2;
 
3521
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3522
    done;
 
3523
    let len1 = !p2 - l and len2 = r - !p3 in
 
3524
    if len1 > cutoff then
 
3525
      if len2 > cutoff then begin
 
3526
        if len1 < len2
 
3527
        then (qsort l !p2; qsort !p3 r)
 
3528
        else (qsort !p3 r; qsort l !p2)
 
3529
      end else qsort l !p2
 
3530
    else if len2 > cutoff then qsort !p3 r;
 
3531
  in
 
3532
  let l = Array.length a in
 
3533
  if l > 1 then begin
 
3534
    qsort 0 l;
 
3535
    let mini = ref 0 in
 
3536
    for i = 0 to (min l cutoff) - 1 do
 
3537
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3538
    done;
 
3539
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3540
    for i = 1 to l - 1 do
 
3541
      let e = a.(i) in
 
3542
      let j = ref (i - 1) in
 
3543
      while cmp a.(!j) e > 0 do
 
3544
        a.(!j + 1) <- a.(!j);
 
3545
        decr j;
 
3546
      done;
 
3547
      a.(!j + 1) <- e;
 
3548
    done;
 
3549
  end;
 
3550
;;
 
3551
 
 
3552
let cutoff = 6;;
 
3553
let aquick_3f cmp a =
 
3554
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3555
    let m = (l + r) / 2 in
 
3556
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3557
    let pivot = if cmp al am <= 0 then
 
3558
                  if cmp am ar <= 0 then am
 
3559
                  else if cmp al ar <= 0 then ar
 
3560
                  else al
 
3561
                else
 
3562
                  if cmp al ar <= 0 then al
 
3563
                  else if cmp am ar <= 0 then ar
 
3564
                  else am
 
3565
    in
 
3566
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3567
    while !p2 < !p3 do
 
3568
      let e = a.(!p2) in
 
3569
      let c = cmp e pivot in
 
3570
      if c > 0 then begin
 
3571
        decr p3;
 
3572
        a.(!p2) <- a.(!p3);
 
3573
        a.(!p3) <- e;
 
3574
      end else if c < 0 then begin
 
3575
        incr p2;
 
3576
      end else begin
 
3577
        a.(!p2) <- a.(!p1);
 
3578
        a.(!p1) <- e;
 
3579
        incr p1;
 
3580
        incr p2;
 
3581
      end
 
3582
    done;
 
3583
    while !p1 > l do
 
3584
      decr p1;
 
3585
      decr p2;
 
3586
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3587
    done;
 
3588
    let len1 = !p2 - l and len2 = r - !p3 in
 
3589
    if len1 > cutoff then
 
3590
      if len2 > cutoff then begin
 
3591
        if len1 < len2
 
3592
        then (qsort l !p2; qsort !p3 r)
 
3593
        else (qsort !p3 r; qsort l !p2)
 
3594
      end else qsort l !p2
 
3595
    else if len2 > cutoff then qsort !p3 r;
 
3596
  in
 
3597
  let l = Array.length a in
 
3598
  if l > 1 then begin
 
3599
    qsort 0 l;
 
3600
    let mini = ref 0 in
 
3601
    for i = 0 to (min l cutoff) - 1 do
 
3602
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3603
    done;
 
3604
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3605
    for i = 1 to l - 1 do
 
3606
      let e = a.(i) in
 
3607
      let j = ref (i - 1) in
 
3608
      while cmp a.(!j) e > 0 do
 
3609
        a.(!j + 1) <- a.(!j);
 
3610
        decr j;
 
3611
      done;
 
3612
      a.(!j + 1) <- e;
 
3613
    done;
 
3614
  end;
 
3615
;;
 
3616
 
 
3617
let cutoff = 7;;
 
3618
let aquick_3g cmp a =
 
3619
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3620
    let m = (l + r) / 2 in
 
3621
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3622
    let pivot = if cmp al am <= 0 then
 
3623
                  if cmp am ar <= 0 then am
 
3624
                  else if cmp al ar <= 0 then ar
 
3625
                  else al
 
3626
                else
 
3627
                  if cmp al ar <= 0 then al
 
3628
                  else if cmp am ar <= 0 then ar
 
3629
                  else am
 
3630
    in
 
3631
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3632
    while !p2 < !p3 do
 
3633
      let e = a.(!p2) in
 
3634
      let c = cmp e pivot in
 
3635
      if c > 0 then begin
 
3636
        decr p3;
 
3637
        a.(!p2) <- a.(!p3);
 
3638
        a.(!p3) <- e;
 
3639
      end else if c < 0 then begin
 
3640
        incr p2;
 
3641
      end else begin
 
3642
        a.(!p2) <- a.(!p1);
 
3643
        a.(!p1) <- e;
 
3644
        incr p1;
 
3645
        incr p2;
 
3646
      end
 
3647
    done;
 
3648
    while !p1 > l do
 
3649
      decr p1;
 
3650
      decr p2;
 
3651
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3652
    done;
 
3653
    let len1 = !p2 - l and len2 = r - !p3 in
 
3654
    if len1 > cutoff then
 
3655
      if len2 > cutoff then begin
 
3656
        if len1 < len2
 
3657
        then (qsort l !p2; qsort !p3 r)
 
3658
        else (qsort !p3 r; qsort l !p2)
 
3659
      end else qsort l !p2
 
3660
    else if len2 > cutoff then qsort !p3 r;
 
3661
  in
 
3662
  let l = Array.length a in
 
3663
  if l > 1 then begin
 
3664
    qsort 0 l;
 
3665
    let mini = ref 0 in
 
3666
    for i = 0 to (min l cutoff) - 1 do
 
3667
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3668
    done;
 
3669
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3670
    for i = 1 to l - 1 do
 
3671
      let e = a.(i) in
 
3672
      let j = ref (i - 1) in
 
3673
      while cmp a.(!j) e > 0 do
 
3674
        a.(!j + 1) <- a.(!j);
 
3675
        decr j;
 
3676
      done;
 
3677
      a.(!j + 1) <- e;
 
3678
    done;
 
3679
  end;
 
3680
;;
 
3681
 
 
3682
let cutoff = 8;;
 
3683
let aquick_3h cmp a =
 
3684
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3685
    let m = (l + r) / 2 in
 
3686
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3687
    let pivot = if cmp al am <= 0 then
 
3688
                  if cmp am ar <= 0 then am
 
3689
                  else if cmp al ar <= 0 then ar
 
3690
                  else al
 
3691
                else
 
3692
                  if cmp al ar <= 0 then al
 
3693
                  else if cmp am ar <= 0 then ar
 
3694
                  else am
 
3695
    in
 
3696
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3697
    while !p2 < !p3 do
 
3698
      let e = a.(!p2) in
 
3699
      let c = cmp e pivot in
 
3700
      if c > 0 then begin
 
3701
        decr p3;
 
3702
        a.(!p2) <- a.(!p3);
 
3703
        a.(!p3) <- e;
 
3704
      end else if c < 0 then begin
 
3705
        incr p2;
 
3706
      end else begin
 
3707
        a.(!p2) <- a.(!p1);
 
3708
        a.(!p1) <- e;
 
3709
        incr p1;
 
3710
        incr p2;
 
3711
      end
 
3712
    done;
 
3713
    while !p1 > l do
 
3714
      decr p1;
 
3715
      decr p2;
 
3716
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3717
    done;
 
3718
    let len1 = !p2 - l and len2 = r - !p3 in
 
3719
    if len1 > cutoff then
 
3720
      if len2 > cutoff then begin
 
3721
        if len1 < len2
 
3722
        then (qsort l !p2; qsort !p3 r)
 
3723
        else (qsort !p3 r; qsort l !p2)
 
3724
      end else qsort l !p2
 
3725
    else if len2 > cutoff then qsort !p3 r;
 
3726
  in
 
3727
  let l = Array.length a in
 
3728
  if l > 1 then begin
 
3729
    qsort 0 l;
 
3730
    let mini = ref 0 in
 
3731
    for i = 0 to (min l cutoff) - 1 do
 
3732
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3733
    done;
 
3734
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3735
    for i = 1 to l - 1 do
 
3736
      let e = a.(i) in
 
3737
      let j = ref (i - 1) in
 
3738
      while cmp a.(!j) e > 0 do
 
3739
        a.(!j + 1) <- a.(!j);
 
3740
        decr j;
 
3741
      done;
 
3742
      a.(!j + 1) <- e;
 
3743
    done;
 
3744
  end;
 
3745
;;
 
3746
 
 
3747
let cutoff = 9;;
 
3748
let aquick_3i cmp a =
 
3749
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3750
    let m = (l + r) / 2 in
 
3751
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3752
    let pivot = if cmp al am <= 0 then
 
3753
                  if cmp am ar <= 0 then am
 
3754
                  else if cmp al ar <= 0 then ar
 
3755
                  else al
 
3756
                else
 
3757
                  if cmp al ar <= 0 then al
 
3758
                  else if cmp am ar <= 0 then ar
 
3759
                  else am
 
3760
    in
 
3761
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3762
    while !p2 < !p3 do
 
3763
      let e = a.(!p2) in
 
3764
      let c = cmp e pivot in
 
3765
      if c > 0 then begin
 
3766
        decr p3;
 
3767
        a.(!p2) <- a.(!p3);
 
3768
        a.(!p3) <- e;
 
3769
      end else if c < 0 then begin
 
3770
        incr p2;
 
3771
      end else begin
 
3772
        a.(!p2) <- a.(!p1);
 
3773
        a.(!p1) <- e;
 
3774
        incr p1;
 
3775
        incr p2;
 
3776
      end
 
3777
    done;
 
3778
    while !p1 > l do
 
3779
      decr p1;
 
3780
      decr p2;
 
3781
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3782
    done;
 
3783
    let len1 = !p2 - l and len2 = r - !p3 in
 
3784
    if len1 > cutoff then
 
3785
      if len2 > cutoff then begin
 
3786
        if len1 < len2
 
3787
        then (qsort l !p2; qsort !p3 r)
 
3788
        else (qsort !p3 r; qsort l !p2)
 
3789
      end else qsort l !p2
 
3790
    else if len2 > cutoff then qsort !p3 r;
 
3791
  in
 
3792
  let l = Array.length a in
 
3793
  if l > 1 then begin
 
3794
    qsort 0 l;
 
3795
    let mini = ref 0 in
 
3796
    for i = 0 to (min l cutoff) - 1 do
 
3797
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3798
    done;
 
3799
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3800
    for i = 1 to l - 1 do
 
3801
      let e = a.(i) in
 
3802
      let j = ref (i - 1) in
 
3803
      while cmp a.(!j) e > 0 do
 
3804
        a.(!j + 1) <- a.(!j);
 
3805
        decr j;
 
3806
      done;
 
3807
      a.(!j + 1) <- e;
 
3808
    done;
 
3809
  end;
 
3810
;;
 
3811
 
 
3812
let cutoff = 10;;
 
3813
let aquick_3j cmp a =
 
3814
  let rec qsort l r =     (* ASSUMES r - l >= 2 *)
 
3815
    let m = (l + r) / 2 in
 
3816
    let al = a.(l) and am = a.(m) and ar = a.(r - 1) in
 
3817
    let pivot = if cmp al am <= 0 then
 
3818
                  if cmp am ar <= 0 then am
 
3819
                  else if cmp al ar <= 0 then ar
 
3820
                  else al
 
3821
                else
 
3822
                  if cmp al ar <= 0 then al
 
3823
                  else if cmp am ar <= 0 then ar
 
3824
                  else am
 
3825
    in
 
3826
    let p1 = ref l and p2 = ref l and p3 = ref r in
 
3827
    while !p2 < !p3 do
 
3828
      let e = a.(!p2) in
 
3829
      let c = cmp e pivot in
 
3830
      if c > 0 then begin
 
3831
        decr p3;
 
3832
        a.(!p2) <- a.(!p3);
 
3833
        a.(!p3) <- e;
 
3834
      end else if c < 0 then begin
 
3835
        incr p2;
 
3836
      end else begin
 
3837
        a.(!p2) <- a.(!p1);
 
3838
        a.(!p1) <- e;
 
3839
        incr p1;
 
3840
        incr p2;
 
3841
      end
 
3842
    done;
 
3843
    while !p1 > l do
 
3844
      decr p1;
 
3845
      decr p2;
 
3846
      let e = a.(!p1) in a.(!p1) <- a.(!p2); a.(!p2) <- e;
 
3847
    done;
 
3848
    let len1 = !p2 - l and len2 = r - !p3 in
 
3849
    if len1 > cutoff then
 
3850
      if len2 > cutoff then begin
 
3851
        if len1 < len2
 
3852
        then (qsort l !p2; qsort !p3 r)
 
3853
        else (qsort !p3 r; qsort l !p2)
 
3854
      end else qsort l !p2
 
3855
    else if len2 > cutoff then qsort !p3 r;
 
3856
  in
 
3857
  let l = Array.length a in
 
3858
  if l > 1 then begin
 
3859
    qsort 0 l;
 
3860
    let mini = ref 0 in
 
3861
    for i = 0 to (min l cutoff) - 1 do
 
3862
      if cmp a.(i) a.(!mini) < 0 then mini := i;
 
3863
    done;
 
3864
    let e = a.(0) in a.(0) <- a.(!mini); a.(!mini) <- e;
 
3865
    for i = 1 to l - 1 do
 
3866
      let e = a.(i) in
 
3867
      let j = ref (i - 1) in
 
3868
      while cmp a.(!j) e > 0 do
 
3869
        a.(!j + 1) <- a.(!j);
 
3870
        decr j;
 
3871
      done;
 
3872
      a.(!j + 1) <- e;
 
3873
    done;
 
3874
  end;
 
3875
;;
 
3876
 
 
3877
(************************************************************************)
 
3878
(* Heap sort on arrays (top-down, ternary) *)
 
3879
 
 
3880
let aheap_1 cmp a =
 
3881
  let l = ref (Array.length a) in
 
3882
  let l3 = ref ((!l + 1) / 3) in   (* l3 is the first element without sons *)
 
3883
  let maxson i =                   (* ASSUMES i < !l3 *)
 
3884
    let i31 = i+i+i+1 in
 
3885
    let x = ref i31 in
 
3886
    if i31+2 < !l then begin
 
3887
      if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
 
3888
      if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
 
3889
      !x
 
3890
    end else begin
 
3891
      if i31+1 < !l && cmp a.(i31) a.(i31+1) < 0
 
3892
      then i31+1
 
3893
      else i31
 
3894
    end
 
3895
  in
 
3896
  let rec trickledown i e =    (* ASSUMES i < !l3 *)
 
3897
    let j = maxson i in
 
3898
    if cmp a.(j) e > 0 then begin
 
3899
      a.(i) <- a.(j);
 
3900
      if j < !l3 then trickledown j e else a.(j) <- e;
 
3901
    end else begin
 
3902
      a.(i) <- e;
 
3903
    end;
 
3904
  in
 
3905
  for i = !l3 - 1 downto 0 do trickledown i a.(i); done;
 
3906
  let m = ref (!l + 1 - 3 * !l3) in
 
3907
  while !l > 2 do
 
3908
    decr l;
 
3909
    if !m = 0 then (m := 2; decr l3) else decr m;
 
3910
    let e = a.(!l) in
 
3911
    a.(!l) <- a.(0);
 
3912
    trickledown 0 e;
 
3913
  done;
 
3914
  if !l > 1 then begin let e = a.(1) in a.(1) <- a.(0); a.(0) <- e; end;
 
3915
;;
 
3916
 
 
3917
(************************************************************************)
 
3918
(* Heap sort on arrays (top-down, binary) *)
 
3919
 
 
3920
(* FIXME essayer application partielle de trickledown (merge avec down) *)
 
3921
(* FIXME essayer expanser maxson dans trickledown; supprimer l'exception. *)
 
3922
 
 
3923
let aheap_2 cmp a =
 
3924
  let maxson l i e =
 
3925
    let i21 = i + i + 1 in
 
3926
    if i21 + 1 < l && cmp a.(i21) a.(i21+1) < 0
 
3927
    then i21 + 1
 
3928
    else if i21 < l then i21 else (a.(i) <- e; raise Exit)
 
3929
  in
 
3930
  let rec trickledown l i e =
 
3931
    let j = maxson l i e in
 
3932
    if cmp a.(j) e > 0 then begin
 
3933
      a.(i) <- a.(j);
 
3934
      trickledown l j e;
 
3935
    end else begin
 
3936
      a.(i) <- e;
 
3937
    end;
 
3938
  in
 
3939
  let down l i e = try trickledown l i e with Exit -> () in
 
3940
  let l = Array.length a in
 
3941
  for i = l / 2 -1 downto 0 do down l i a.(i); done;
 
3942
  for i = l - 1 downto 1 do
 
3943
    let e = a.(i) in
 
3944
    a.(i) <- a.(0);
 
3945
    down i 0 e;
 
3946
  done;
 
3947
;;
 
3948
 
 
3949
(************************************************************************)
 
3950
(* Heap sort on arrays (bottom-up, ternary) *)
 
3951
 
 
3952
exception Bottom of int;;
 
3953
 
 
3954
let aheap_3 cmp a =
 
3955
  let maxson l i =
 
3956
    let i31 = i+i+i+1 in
 
3957
    let x = ref i31 in
 
3958
    if i31+2 < l then begin
 
3959
      if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
 
3960
      if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
 
3961
      !x
 
3962
    end else
 
3963
      if i31+1 < l && cmp a.(i31) a.(i31+1) < 0
 
3964
      then i31+1
 
3965
      else if i31 < l then i31 else raise (Bottom i)
 
3966
  in
 
3967
  let rec trickledown l i e =
 
3968
    let j = maxson l i in
 
3969
    if cmp a.(j) e > 0 then begin
 
3970
      a.(i) <- a.(j);
 
3971
      trickledown l j e;
 
3972
    end else begin
 
3973
      a.(i) <- e;
 
3974
    end;
 
3975
  in
 
3976
  let rec trickle l i e = try trickledown l i e with Bottom i -> a.(i) <- e in
 
3977
  let rec bubbledown l i =
 
3978
    let j = maxson l i in
 
3979
    a.(i) <- a.(j);
 
3980
    bubbledown l j;
 
3981
  in
 
3982
  let bubble l i = try bubbledown l i with Bottom i -> i in
 
3983
  let rec trickleup i e =
 
3984
    let father = (i - 1) / 3 in
 
3985
    assert (i <> father);
 
3986
    if cmp a.(father) e < 0 then begin
 
3987
      a.(i) <- a.(father);
 
3988
      if father > 0 then trickleup father e else a.(0) <- e;
 
3989
    end else begin
 
3990
      a.(i) <- e;
 
3991
    end;
 
3992
  in
 
3993
  let l = Array.length a in
 
3994
  for i = (l + 1) / 3 - 1 downto 0 do trickle l i a.(i); done;
 
3995
  for i = l - 1 downto 2 do
 
3996
    let e = a.(i) in
 
3997
    a.(i) <- a.(0);
 
3998
    trickleup (bubble i 0) e;
 
3999
  done;
 
4000
  if l > 1 then (let e = a.(1) in a.(1) <- a.(0); a.(0) <- e);
 
4001
;;
 
4002
 
 
4003
(************************************************************************)
 
4004
(* Heap sort on arrays (bottom-up, binary) *)
 
4005
 
 
4006
let aheap_4 cmp a =
 
4007
  let maxson l i =
 
4008
    let i21 = i + i + 1 in
 
4009
    if i21 + 1 < l && cmp a.(i21) a.(i21 + 1) < 0
 
4010
    then i21 + 1
 
4011
    else if i21 < l then i21 else raise (Bottom i)
 
4012
  in
 
4013
  let rec trickledown l i e =
 
4014
    let j = maxson l i in
 
4015
    if cmp a.(j) e > 0 then begin
 
4016
      a.(i) <- a.(j);
 
4017
      trickledown l j e;
 
4018
    end else begin
 
4019
      a.(i) <- e;
 
4020
    end;
 
4021
  in
 
4022
  let trickle l i e = try trickledown l i e with Bottom i -> a.(i) <- e in
 
4023
  let rec bubbledown l i =
 
4024
    let j = maxson l i in
 
4025
    a.(i) <- a.(j);
 
4026
    bubbledown l j;
 
4027
  in
 
4028
  let bubble l i = try bubbledown l i with Bottom i -> i in
 
4029
  let rec trickleup i e =
 
4030
    let father = (i - 1) / 2 in
 
4031
    assert (i <> father);
 
4032
    if cmp a.(father) e < 0 then begin
 
4033
      a.(i) <- a.(father);
 
4034
      if father > 0 then trickleup father e else a.(0) <- e;
 
4035
    end else begin
 
4036
      a.(i) <- e;
 
4037
    end;
 
4038
  in
 
4039
  let l = Array.length a in
 
4040
  for i = l / 2 - 1 downto 0 do trickle l i a.(i); done;
 
4041
  for i = l - 1 downto 2 do
 
4042
    let e = a.(i) in
 
4043
    a.(i) <- a.(0);
 
4044
    trickleup (bubble i 0) e;
 
4045
  done;
 
4046
  if l > 1 then (let e = a.(1) in a.(1) <- a.(0); a.(0) <- e);
 
4047
;;
 
4048
 
 
4049
(************************************************************************)
 
4050
(* heap sort, top-down, ternary, recursive final loop *)
 
4051
 
 
4052
let aheap_5 cmp a =
 
4053
  let maxson l i =                 (* ASSUMES i < (l+1)/3 *)
 
4054
    let i31 = i+i+i+1 in
 
4055
    let x = ref i31 in
 
4056
    if i31+2 < l then begin
 
4057
      if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
 
4058
      if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
 
4059
      !x
 
4060
    end else begin
 
4061
      if i31+1 < l && cmp a.(i31) a.(i31+1) < 0
 
4062
      then i31+1
 
4063
      else i31
 
4064
    end
 
4065
  in
 
4066
  let rec trickledown l l3 i e =    (* ASSUMES i < l3 *)
 
4067
    let j = maxson l i in
 
4068
    if cmp a.(j) e > 0 then begin
 
4069
      a.(i) <- a.(j);
 
4070
      if j < l3 then trickledown l l3 j e else a.(j) <- e;
 
4071
    end else begin
 
4072
      a.(i) <- e;
 
4073
    end;
 
4074
  in
 
4075
  let l = Array.length a in
 
4076
  let l3 = (l + 1) / 3 in
 
4077
  for i = l3 - 1 downto 0 do trickledown l l3 i a.(i); done;
 
4078
  let rec loop0 l l3 =
 
4079
    let e = a.(l) in
 
4080
    a.(l) <- a.(0);
 
4081
    trickledown l l3 0 e;
 
4082
    loop2 (l-1) (l3-1);
 
4083
  and loop1 l l3 =
 
4084
    let e = a.(l) in
 
4085
    a.(l) <- a.(0);
 
4086
    trickledown l l3 0 e;
 
4087
    loop0 (l-1) l3;
 
4088
  and loop2 l l3 =
 
4089
    if l > 1 then begin
 
4090
      let e = a.(l) in
 
4091
      a.(l) <- a.(0);
 
4092
      trickledown l l3 0 e;
 
4093
      loop1 (l-1) l3;
 
4094
    end else begin
 
4095
      let e = a.(1) in a.(1) <- a.(0); a.(0) <- e;
 
4096
    end;
 
4097
  in
 
4098
  if l > 1 then
 
4099
    match l + 1 - 3 * l3 with
 
4100
    | 0 -> loop2 (l-1) (l3-1);
 
4101
    | 1 -> loop0 (l-1) l3;
 
4102
    | 2 -> loop1 (l-1) l3;
 
4103
    | _ -> assert false;
 
4104
;;
 
4105
 
 
4106
(************************************************************************)
 
4107
(* heap sort, top-down, ternary, with exception *)
 
4108
 
 
4109
let aheap_6 cmp a =
 
4110
  let maxson e l i =
 
4111
    let i31 = i + i + i + 1 in
 
4112
    let x = ref i31 in
 
4113
    if i31+2 < l then begin
 
4114
      if cmp a.(i31) a.(i31+1) < 0 then x := i31+1;
 
4115
      if cmp a.(!x) a.(i31+2) < 0 then x := i31+2;
 
4116
      !x
 
4117
    end else begin
 
4118
      if i31+1 < l && cmp a.(i31) a.(i31+1) < 0
 
4119
      then i31+1
 
4120
      else if i31 < l then i31 else (a.(i) <- e; raise Exit)
 
4121
    end
 
4122
  in
 
4123
  let rec trickledown e l i =
 
4124
    let j = maxson e l i in
 
4125
    if cmp a.(j) e > 0 then begin
 
4126
      a.(i) <- a.(j);
 
4127
      trickledown e l j;
 
4128
    end else begin
 
4129
      a.(i) <- e;
 
4130
    end;
 
4131
  in
 
4132
  let down e l i = try trickledown e l i with Exit -> (); in
 
4133
  let l = Array.length a in
 
4134
  for i = (l + 1) / 3 - 1 downto 0 do down a.(i) l i; done;
 
4135
  for i = l - 1 downto 2 do
 
4136
    let e = a.(i) in
 
4137
    a.(i) <- a.(0);
 
4138
    down e i 0;
 
4139
  done;
 
4140
  if l > 1 then (let e = a.(1) in a.(1) <- a.(0); a.(0) <- e);
 
4141
;;
 
4142
 
 
4143
(* FIXME essayer cutoff pour heapsort *)
 
4144
 
 
4145
(************************************************************************)
 
4146
(* Insertion sort with dichotomic search *)
 
4147
 
 
4148
let ainsertion_1 cmp a =
 
4149
  let rec dicho l r e =
 
4150
    if l = r then l else begin
 
4151
      let m = (l + r) / 2 in
 
4152
      if cmp a.(m) e <= 0
 
4153
      then dicho (m+1) r e
 
4154
      else dicho l m e
 
4155
    end
 
4156
  in
 
4157
  for i = 1 to Array.length a - 1 do
 
4158
    let e = a.(i) in
 
4159
    let j = dicho 0 i e in
 
4160
    Array.blit a j a (j + 1) (i - j);
 
4161
    a.(j) <- e;
 
4162
  done;
 
4163
;;
 
4164
 
 
4165
(************************************************************************)
 
4166
(* merge sort on lists via arrays *)
 
4167
 
 
4168
let array_to_list_in_place a =
 
4169
  let l = Array.length a in
 
4170
  let rec loop accu n p =
 
4171
    if p <= 0 then accu else begin
 
4172
      if p = n then begin
 
4173
        Obj.truncate (Obj.repr a) p;
 
4174
        loop (a.(p-1) :: accu) (n-1000) (p-1)
 
4175
      end else begin
 
4176
        loop (a.(p-1) :: accu) n (p-1)
 
4177
      end
 
4178
    end
 
4179
  in
 
4180
  loop [] l l
 
4181
;;
 
4182
 
 
4183
let array_of_list l len =
 
4184
  match l with
 
4185
  | [] -> [| |]
 
4186
  | h::t ->
 
4187
      let a = Array.make len h in
 
4188
      let rec loop i l =
 
4189
        match l with
 
4190
        | [] -> ()
 
4191
        | h::t -> a.(i) <- h; loop (i+1) t
 
4192
      in
 
4193
      loop 1 t;
 
4194
      a
 
4195
;;
 
4196
 
 
4197
let lmerge_0a cmp l =
 
4198
  let a = Array.of_list l in
 
4199
  amerge_1e cmp a;
 
4200
  array_to_list_in_place a
 
4201
;;
 
4202
 
 
4203
let lmerge_0b cmp l =
 
4204
  let len = List.length l in
 
4205
  if len > 256 then Gc.minor ();
 
4206
  let a = array_of_list l len in
 
4207
  amerge_1e cmp a;
 
4208
  array_to_list_in_place a
 
4209
;;
 
4210
 
 
4211
let lshell_0 cmp l =
 
4212
  let a = Array.of_list l in
 
4213
  ashell_2 cmp a;
 
4214
  array_to_list_in_place a
 
4215
;;
 
4216
 
 
4217
let lquick_0 cmp l =
 
4218
  let a = Array.of_list l in
 
4219
  aquick_3f cmp a;
 
4220
  array_to_list_in_place a
 
4221
;;
 
4222
 
 
4223
(************************************************************************)
 
4224
(* merge sort on arrays via lists *)
 
4225
 
 
4226
let amerge_0 cmp a =    (* cutoff is not yet used *)
 
4227
  let l = lmerge_4e cmp (Array.to_list a) in
 
4228
  let rec loop i = function
 
4229
  | [] -> ()
 
4230
  | h::t -> a.(i) <- h; loop (i + 1) t
 
4231
  in
 
4232
  loop 0 l
 
4233
;;
 
4234
 
 
4235
(************************************************************************)
 
4236
 
 
4237
let lold = [
 
4238
  "Sort.list", Sort.list, true;
 
4239
  "lmerge_3", lmerge_3, false;
 
4240
  "lmerge_4a", lmerge_4a, true;
 
4241
];;
 
4242
 
 
4243
let lnew = [
 
4244
  "List.stable_sort", List.stable_sort, true;
 
4245
 
 
4246
  "lmerge_0a", lmerge_0a, true;
 
4247
  "lmerge_0b", lmerge_0b, true;
 
4248
  "lshell_0", lshell_0, false;
 
4249
  "lquick_0", lquick_0, false;
 
4250
 
 
4251
  "lmerge_1a", lmerge_1a, true;
 
4252
  "lmerge_1b", lmerge_1b, true;
 
4253
  "lmerge_1c", lmerge_1c, true;
 
4254
  "lmerge_1d", lmerge_1d, true;
 
4255
 
 
4256
  "lmerge_4b", lmerge_4b, true;
 
4257
  "lmerge_4c", lmerge_4c, true;
 
4258
  "lmerge_4d", lmerge_4d, true;
 
4259
  "lmerge_4e", lmerge_4e, true;
 
4260
 
 
4261
  "lmerge_5a", lmerge_5a, true;
 
4262
  "lmerge_5b", lmerge_5b, true;
 
4263
  "lmerge_5c", lmerge_5c, true;
 
4264
  "lmerge_5d", lmerge_5d, true;
 
4265
];;
 
4266
let anew = [
 
4267
  "Array.stable_sort", Array.stable_sort, true;
 
4268
  "Array.sort", Array.sort, false;
 
4269
 
 
4270
  "amerge_0", amerge_0, true;
 
4271
 
 
4272
  "amerge_1a", amerge_1a, true;
 
4273
  "amerge_1b", amerge_1b, true;
 
4274
  "amerge_1c", amerge_1c, true;
 
4275
  "amerge_1d", amerge_1d, true;
 
4276
  "amerge_1e", amerge_1e, true;
 
4277
  "amerge_1f", amerge_1f, true;
 
4278
  "amerge_1g", amerge_1g, true;
 
4279
  "amerge_1h", amerge_1h, true;
 
4280
  "amerge_1i", amerge_1i, true;
 
4281
  "amerge_1j", amerge_1j, true;
 
4282
 
 
4283
  "amerge_3a", amerge_3a, true;
 
4284
  "amerge_3b", amerge_3b, true;
 
4285
  "amerge_3c", amerge_3c, true;
 
4286
  "amerge_3d", amerge_3d, true;
 
4287
  "amerge_3e", amerge_3e, true;
 
4288
  "amerge_3f", amerge_3f, true;
 
4289
  "amerge_3g", amerge_3g, true;
 
4290
  "amerge_3h", amerge_3h, true;
 
4291
  "amerge_3i", amerge_3i, true;
 
4292
  "amerge_3j", amerge_3j, true;
 
4293
 
 
4294
  "ashell_1", ashell_1, false;
 
4295
  "ashell_2", ashell_2, false;
 
4296
  "ashell_3", ashell_3, false;
 
4297
  "ashell_4", ashell_4, false;
 
4298
 
 
4299
  "aquick_1a", aquick_1a, false;
 
4300
  "aquick_1b", aquick_1b, false;
 
4301
  "aquick_1c", aquick_1c, false;
 
4302
  "aquick_1d", aquick_1d, false;
 
4303
  "aquick_1e", aquick_1e, false;
 
4304
  "aquick_1f", aquick_1f, false;
 
4305
  "aquick_1g", aquick_1g, false;
 
4306
 
 
4307
  "aquick_2a", aquick_2a, false;
 
4308
  "aquick_2b", aquick_2b, false;
 
4309
  "aquick_2c", aquick_2c, false;
 
4310
  "aquick_2d", aquick_2d, false;
 
4311
  "aquick_2e", aquick_2e, false;
 
4312
  "aquick_2f", aquick_2f, false;
 
4313
  "aquick_2g", aquick_2g, false;
 
4314
 
 
4315
  "aquick_3a", aquick_3a, false;
 
4316
  "aquick_3b", aquick_3b, false;
 
4317
  "aquick_3c", aquick_3c, false;
 
4318
  "aquick_3d", aquick_3d, false;
 
4319
  "aquick_3e", aquick_3e, false;
 
4320
  "aquick_3f", aquick_3f, false;
 
4321
  "aquick_3g", aquick_3g, false;
 
4322
  "aquick_3h", aquick_3h, false;
 
4323
  "aquick_3i", aquick_3i, false;
 
4324
  "aquick_3j", aquick_3j, false;
 
4325
 
 
4326
  "aheap_1", aheap_1, false;
 
4327
  "aheap_2", aheap_2, false;
 
4328
  "aheap_3", aheap_3, false;
 
4329
  "aheap_4", aheap_4, false;
 
4330
  "aheap_5", aheap_5, false;
 
4331
  "aheap_6", aheap_6, false;
 
4332
 
 
4333
  "ainsertion_1", ainsertion_1, true;
 
4334
];;
 
4335
 
 
4336
(************************************************************************)
 
4337
(* main program *)
 
4338
 
 
4339
type mode = Test_std | Test | Bench1 | Bench2 | Bench3;;
 
4340
 
 
4341
let size = ref 22
 
4342
and mem = ref 0
 
4343
and mode = ref Test_std
 
4344
and only = ref []
 
4345
;;
 
4346
 
 
4347
let usage = "Usage: sorts [-size <table size>] [-mem <memory size>]\n\
 
4348
          \032            [-seed <random seed>] [-test|-bench]"
 
4349
;;
 
4350
 
 
4351
let options = [
 
4352
  "-size", Arg.Int ((:=) size), "   Maximum size for benchmarks (default 22)";
 
4353
  "-meg",Arg.Int ((:=) mem),"    How many megabytes to preallocate (default 0)";
 
4354
  "-seed", Arg.Int ((:=) seed), "   PRNG seed (default 0)";
 
4355
  "-teststd", Arg.Unit (fun () -> mode := Test_std), "   Test stdlib (default)";
 
4356
  "-test", Arg.Unit (fun () -> mode := Test), "   Select test mode";
 
4357
  "-bench1", Arg.Unit (fun () -> mode := Bench1), "  Select bench mode 1";
 
4358
  "-bench2", Arg.Unit (fun () -> mode := Bench2), "  Select bench mode 2";
 
4359
  "-bench3", Arg.Unit (fun () -> mode := Bench3), "  Select bench mode 3";
 
4360
  "-fn", Arg.String (fun x -> only := x :: !only),
 
4361
                         " <function>  Test/Bench this function (default all)";
 
4362
];;
 
4363
let anonymous x = raise (Arg.Bad ("unrecognised option "^x));;
 
4364
 
 
4365
let main () =
 
4366
  Arg.parse options anonymous usage;
 
4367
 
 
4368
  Printf.printf "Command line arguments are:";
 
4369
  for i = 1 to Array.length Sys.argv - 1 do
 
4370
    Printf.printf " %s" Sys.argv.(i);
 
4371
  done;
 
4372
  Printf.printf "\n";
 
4373
 
 
4374
  ignore (String.create (1048576 * !mem));
 
4375
  Gc.full_major ();
 
4376
(*
 
4377
  let a2l = Array.to_list in
 
4378
  let l2ak x y = Array.of_list x in
 
4379
  let id = fun x -> x in
 
4380
  let fst x y = x in
 
4381
  let snd x y = y in
 
4382
*)
 
4383
  let benchonly f x y z t =
 
4384
    match !only with
 
4385
    | [] -> f x y z t
 
4386
    | l -> if List.mem y l then f x y z t
 
4387
  in
 
4388
  let testonly x1 x2 x3 x4 x5 x6 =
 
4389
    match !only with
 
4390
    | [] -> test x1 x2 x3 x4 x5 x6
 
4391
    | l -> if List.mem x1 l then test x1 x2 x3 x4 x5 x6
 
4392
  in
 
4393
 
 
4394
  match !mode with
 
4395
  | Test_std -> begin
 
4396
      testonly "List.sort" false List.sort List.sort lc lc;
 
4397
      testonly "List.stable_sort" true List.stable_sort List.stable_sort lc lc;
 
4398
      testonly "Array.sort" false Array.sort Array.sort ac ac;
 
4399
      testonly "Array.stable_sort" true Array.stable_sort Array.stable_sort
 
4400
               ac ac;
 
4401
      printf "Number of tests failed: %d\n" !numfailed;
 
4402
    end;
 
4403
  | Test -> begin
 
4404
      for i = 0 to List.length lold - 1 do
 
4405
        let (name, f1, stable) = List.nth lold i in
 
4406
        let (_, f2, _) = List.nth lold i in
 
4407
        testonly name stable f1 f2 ll ll;
 
4408
      done;
 
4409
      testonly "Sort.array" false Sort.array Sort.array al al;
 
4410
      for i = 0 to List.length lnew - 1 do
 
4411
        let (name, f1, stable) = List.nth lnew i in
 
4412
        let (_, f2, _) = List.nth lnew i in
 
4413
        testonly name stable f1 f2 lc lc;
 
4414
      done;
 
4415
      for i = 0 to List.length anew - 1 do
 
4416
        let (name, f1, stable) = List.nth anew i in
 
4417
        let (_, f2, _) = List.nth anew i in
 
4418
        testonly name stable f1 f2 ac ac;
 
4419
      done;
 
4420
      printf "Number of tests failed: %d\n" !numfailed;
 
4421
    end;
 
4422
  | Bench1 -> begin
 
4423
      let ba = fun x y z -> benchonly bench1a !size x y z
 
4424
      and bb = fun x y z -> benchonly bench1b !size x y z
 
4425
      and bc = fun x y z -> benchonly bench1c !size x y z
 
4426
      in
 
4427
      for i = 0 to List.length lold - 1 do
 
4428
        let (name, f, stable) = List.nth lold i in ba name f ll;
 
4429
        let (name, f, stable) = List.nth lold i in bb name f ll;
 
4430
        let (name, f, stable) = List.nth lold i in bc name f ll;
 
4431
      done;
 
4432
      ba "Sort.array" Sort.array al;
 
4433
      bb "Sort.array" Sort.array al;
 
4434
      bc "Sort.array" Sort.array al;
 
4435
      for i = 0 to List.length lnew - 1 do
 
4436
        let (name, f, stable) = List.nth lnew i in ba name f lc;
 
4437
        let (name, f, stable) = List.nth lnew i in bb name f lc;
 
4438
        let (name, f, stable) = List.nth lnew i in bc name f lc;
 
4439
      done;
 
4440
      for i = 0 to List.length anew - 1 do
 
4441
        let (name, f, stable) = List.nth anew i in ba name f ac;
 
4442
        let (name, f, stable) = List.nth anew i in bb name f ac;
 
4443
        let (name, f, stable) = List.nth anew i in bc name f ac;
 
4444
      done;
 
4445
    end;
 
4446
  | Bench2 -> begin
 
4447
      let b = fun x y z -> benchonly bench2 !size x y z in
 
4448
      for i = 0 to List.length lold - 1 do
 
4449
        let (name, f, stable) = List.nth lold i in b name f ll;
 
4450
      done;
 
4451
      b "Sort.array" Sort.array al;
 
4452
      for i = 0 to List.length lnew - 1 do
 
4453
        let (name, f, stable) = List.nth lnew i in b name f lc;
 
4454
      done;
 
4455
      for i = 0 to List.length anew - 1 do
 
4456
        let (name, f, stable) = List.nth anew i in b name f ac;
 
4457
      done;
 
4458
    end;
 
4459
  | Bench3 -> begin
 
4460
      let ba = fun x y z -> benchonly bench3a !size x y z
 
4461
      and bb = fun x y z -> benchonly bench3b !size x y z
 
4462
      and bc = fun x y z -> benchonly bench3c !size x y z
 
4463
      in
 
4464
      for i = 0 to List.length lold - 1 do
 
4465
        let (name, f, stable) = List.nth lold i in ba name f ll;
 
4466
        let (name, f, stable) = List.nth lold i in bb name f ll;
 
4467
        let (name, f, stable) = List.nth lold i in bc name f ll;
 
4468
      done;
 
4469
      for i = 0 to List.length lnew - 1 do
 
4470
        let (name, f, stable) = List.nth lnew i in ba name f lc;
 
4471
        let (name, f, stable) = List.nth lnew i in bb name f lc;
 
4472
        let (name, f, stable) = List.nth lnew i in bc name f lc;
 
4473
      done;
 
4474
    end;
 
4475
;;
 
4476
 
 
4477
if not !Sys.interactive then Printexc.catch main ();;
 
4478
 
 
4479
(* $Id: sorts.ml 4955 2002-06-26 14:55:37Z doligez $ *)