1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Objective Caml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the GNU Library General Public License. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Array operations *)
|
|
|
|
|
|
|
|
external length : 'a array -> int = "%array_length"
|
1995-07-10 02:48:27 -07:00
|
|
|
external get: 'a array -> int -> 'a = "%array_safe_get"
|
|
|
|
external set: 'a array -> int -> 'a -> unit = "%array_safe_set"
|
1995-06-15 01:10:01 -07:00
|
|
|
external unsafe_get: 'a array -> int -> 'a = "%array_unsafe_get"
|
|
|
|
external unsafe_set: 'a array -> int -> 'a -> unit = "%array_unsafe_set"
|
1997-09-11 08:10:23 -07:00
|
|
|
external make: int -> 'a -> 'a array = "make_vect"
|
1996-04-22 04:15:41 -07:00
|
|
|
external create: int -> 'a -> 'a array = "make_vect"
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-11-12 00:56:35 -08:00
|
|
|
let init l f =
|
|
|
|
if l = 0 then [||] else
|
|
|
|
let res = create l (f 0) in
|
|
|
|
for i = 1 to pred l do
|
|
|
|
unsafe_set res i (f i)
|
|
|
|
done;
|
|
|
|
res
|
|
|
|
|
1997-09-11 08:10:23 -07:00
|
|
|
let make_matrix sx sy init =
|
1996-04-22 04:15:41 -07:00
|
|
|
let res = create sx [||] in
|
1995-05-04 03:15:53 -07:00
|
|
|
for x = 0 to pred sx do
|
1996-04-22 04:15:41 -07:00
|
|
|
unsafe_set res x (create sy init)
|
1995-05-04 03:15:53 -07:00
|
|
|
done;
|
|
|
|
res
|
|
|
|
|
1997-09-11 08:10:23 -07:00
|
|
|
let create_matrix = make_matrix
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let copy a =
|
|
|
|
let l = length a in
|
|
|
|
if l = 0 then [||] else begin
|
1997-11-12 00:56:35 -08:00
|
|
|
let res = create l (unsafe_get a 0) in
|
|
|
|
for i = 1 to pred l do
|
|
|
|
unsafe_set res i (unsafe_get a i)
|
1995-05-04 03:15:53 -07:00
|
|
|
done;
|
1997-11-12 00:56:35 -08:00
|
|
|
res
|
1995-05-04 03:15:53 -07:00
|
|
|
end
|
|
|
|
|
1995-06-05 06:42:38 -07:00
|
|
|
let append a1 a2 =
|
1995-05-04 03:15:53 -07:00
|
|
|
let l1 = length a1 and l2 = length a2 in
|
1998-04-27 02:55:50 -07:00
|
|
|
if l1 = 0 && l2 = 0 then [||] else begin
|
1996-04-22 04:15:41 -07:00
|
|
|
let r = create (l1 + l2) (unsafe_get (if l1 > 0 then a1 else a2) 0) in
|
1995-05-04 03:15:53 -07:00
|
|
|
for i = 0 to l1 - 1 do unsafe_set r i (unsafe_get a1 i) done;
|
1995-06-15 01:10:01 -07:00
|
|
|
for i = 0 to l2 - 1 do unsafe_set r (i + l1) (unsafe_get a2 i) done;
|
1995-05-04 03:15:53 -07:00
|
|
|
r
|
|
|
|
end
|
|
|
|
|
1995-06-05 06:42:38 -07:00
|
|
|
let concat_aux init al =
|
2000-04-14 03:05:33 -07:00
|
|
|
let rec size accu = function
|
|
|
|
| [] -> accu
|
|
|
|
| h::t -> size (accu + length h) t
|
|
|
|
in
|
|
|
|
let res = create (size 0 al) init in
|
|
|
|
let rec fill pos = function
|
|
|
|
| [] -> ()
|
|
|
|
| h::t ->
|
|
|
|
for i = 0 to length h - 1 do
|
|
|
|
unsafe_set res (pos + i) (unsafe_get h i);
|
|
|
|
done;
|
|
|
|
fill (pos + length h) t;
|
|
|
|
in
|
|
|
|
fill 0 al;
|
1995-06-05 06:42:38 -07:00
|
|
|
res
|
2000-04-14 03:05:33 -07:00
|
|
|
;;
|
1995-06-05 06:42:38 -07:00
|
|
|
|
|
|
|
let concat al =
|
|
|
|
let rec find_init = function
|
|
|
|
[] -> [||]
|
|
|
|
| a :: rem ->
|
|
|
|
if length a > 0 then concat_aux (unsafe_get a 0) al else find_init rem
|
|
|
|
in find_init al
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let sub a ofs len =
|
2000-12-28 05:07:42 -08:00
|
|
|
if ofs < 0 || len < 0 || ofs + len > length a then invalid_arg "Array.sub"
|
1995-05-04 03:15:53 -07:00
|
|
|
else if len = 0 then [||]
|
|
|
|
else begin
|
1996-04-22 04:15:41 -07:00
|
|
|
let r = create len (unsafe_get a ofs) in
|
1995-05-04 03:15:53 -07:00
|
|
|
for i = 1 to len - 1 do unsafe_set r i (unsafe_get a (ofs + i)) done;
|
|
|
|
r
|
|
|
|
end
|
|
|
|
|
|
|
|
let fill a ofs len v =
|
2000-12-28 05:07:42 -08:00
|
|
|
if ofs < 0 || len < 0 || ofs + len > length a
|
1995-05-04 03:15:53 -07:00
|
|
|
then invalid_arg "Array.fill"
|
|
|
|
else for i = ofs to ofs + len - 1 do unsafe_set a i v done
|
|
|
|
|
|
|
|
let blit a1 ofs1 a2 ofs2 len =
|
2000-12-28 05:07:42 -08:00
|
|
|
if len < 0 || ofs1 < 0 || ofs1 + len > length a1
|
|
|
|
|| ofs2 < 0 || ofs2 + len > length a2
|
1995-05-04 03:15:53 -07:00
|
|
|
then invalid_arg "Array.blit"
|
1996-05-22 09:21:16 -07:00
|
|
|
else if ofs1 < ofs2 then
|
|
|
|
(* Top-down copy *)
|
|
|
|
for i = len - 1 downto 0 do
|
|
|
|
unsafe_set a2 (ofs2 + i) (unsafe_get a1 (ofs1 + i))
|
|
|
|
done
|
1995-05-04 03:15:53 -07:00
|
|
|
else
|
1996-05-22 09:21:16 -07:00
|
|
|
(* Bottom-up copy *)
|
1995-05-04 03:15:53 -07:00
|
|
|
for i = 0 to len - 1 do
|
|
|
|
unsafe_set a2 (ofs2 + i) (unsafe_get a1 (ofs1 + i))
|
|
|
|
done
|
|
|
|
|
|
|
|
let iter f a =
|
|
|
|
for i = 0 to length a - 1 do f(unsafe_get a i) done
|
|
|
|
|
|
|
|
let map f a =
|
|
|
|
let l = length a in
|
|
|
|
if l = 0 then [||] else begin
|
1996-04-22 04:15:41 -07:00
|
|
|
let r = create l (f(unsafe_get a 0)) in
|
1995-05-04 03:15:53 -07:00
|
|
|
for i = 1 to l - 1 do
|
|
|
|
unsafe_set r i (f(unsafe_get a i))
|
|
|
|
done;
|
|
|
|
r
|
|
|
|
end
|
|
|
|
|
1997-10-24 08:54:07 -07:00
|
|
|
let iteri f a =
|
|
|
|
for i = 0 to length a - 1 do f i (unsafe_get a i) done
|
|
|
|
|
|
|
|
let mapi f a =
|
|
|
|
let l = length a in
|
|
|
|
if l = 0 then [||] else begin
|
|
|
|
let r = create l (f 0 (unsafe_get a 0)) in
|
|
|
|
for i = 1 to l - 1 do
|
|
|
|
unsafe_set r i (f i (unsafe_get a i))
|
|
|
|
done;
|
|
|
|
r
|
|
|
|
end
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let to_list a =
|
1997-07-26 05:20:44 -07:00
|
|
|
let rec tolist i res =
|
|
|
|
if i < 0 then res else tolist (i - 1) (unsafe_get a i :: res) in
|
|
|
|
tolist (length a - 1) []
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2000-04-14 03:05:33 -07:00
|
|
|
let rec list_length accu = function
|
|
|
|
| [] -> accu
|
|
|
|
| h::t -> list_length (succ accu) t
|
|
|
|
;;
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let of_list = function
|
|
|
|
[] -> [||]
|
2000-04-14 03:05:33 -07:00
|
|
|
| hd::tl as l ->
|
|
|
|
let a = create (list_length 0 l) hd in
|
1995-05-04 03:15:53 -07:00
|
|
|
let rec fill i = function
|
|
|
|
[] -> a
|
|
|
|
| hd::tl -> unsafe_set a i hd; fill (i+1) tl in
|
|
|
|
fill 1 tl
|
1997-10-24 08:54:07 -07:00
|
|
|
|
|
|
|
let fold_left f x a =
|
|
|
|
let r = ref x in
|
1997-11-06 09:28:16 -08:00
|
|
|
for i = 0 to length a - 1 do
|
1997-10-24 08:54:07 -07:00
|
|
|
r := f !r (unsafe_get a i)
|
|
|
|
done;
|
|
|
|
!r
|
|
|
|
|
|
|
|
let fold_right f a x =
|
|
|
|
let r = ref x in
|
1997-11-06 09:28:16 -08:00
|
|
|
for i = length a - 1 downto 0 do
|
1997-10-24 08:54:07 -07:00
|
|
|
r := f (unsafe_get a i) !r
|
|
|
|
done;
|
|
|
|
!r
|
2000-04-14 03:05:33 -07:00
|
|
|
|
|
|
|
exception Bottom of int;;
|
|
|
|
let sort cmp a =
|
|
|
|
let maxson l i =
|
|
|
|
let i31 = i+i+i+1 in
|
|
|
|
let x = ref i31 in
|
|
|
|
if i31+2 < l then begin
|
2000-04-17 08:15:59 -07:00
|
|
|
if cmp (get a i31) (get a (i31+1)) < 0 then x := i31+1;
|
|
|
|
if cmp (get a !x) (get a (i31+2)) < 0 then x := i31+2;
|
2000-04-14 03:05:33 -07:00
|
|
|
!x
|
|
|
|
end else
|
2000-04-17 08:15:59 -07:00
|
|
|
if i31+1 < l && cmp (get a i31) (get a (i31+1)) < 0
|
2000-04-14 03:05:33 -07:00
|
|
|
then i31+1
|
|
|
|
else if i31 < l then i31 else raise (Bottom i)
|
|
|
|
in
|
|
|
|
let rec trickledown l i e =
|
|
|
|
let j = maxson l i in
|
2000-04-17 08:15:59 -07:00
|
|
|
if cmp (get a j) e > 0 then begin
|
|
|
|
set a i (get a j);
|
2000-04-14 03:05:33 -07:00
|
|
|
trickledown l j e;
|
|
|
|
end else begin
|
2000-04-17 08:15:59 -07:00
|
|
|
set a i e;
|
2000-04-14 03:05:33 -07:00
|
|
|
end;
|
|
|
|
in
|
2000-04-17 08:15:59 -07:00
|
|
|
let rec trickle l i e = try trickledown l i e with Bottom i -> set a i e in
|
2000-04-14 03:05:33 -07:00
|
|
|
let rec bubbledown l i =
|
|
|
|
let j = maxson l i in
|
2000-04-17 08:15:59 -07:00
|
|
|
set a i (get a j);
|
2000-04-14 03:05:33 -07:00
|
|
|
bubbledown l j;
|
|
|
|
in
|
|
|
|
let bubble l i = try bubbledown l i with Bottom i -> i in
|
|
|
|
let rec trickleup i e =
|
|
|
|
let father = (i - 1) / 3 in
|
|
|
|
assert (i <> father);
|
2000-04-17 08:15:59 -07:00
|
|
|
if cmp (get a father) e < 0 then begin
|
|
|
|
set a i (get a father);
|
|
|
|
if father > 0 then trickleup father e else set a 0 e;
|
2000-04-14 03:05:33 -07:00
|
|
|
end else begin
|
2000-04-17 08:15:59 -07:00
|
|
|
set a i e;
|
2000-04-14 03:05:33 -07:00
|
|
|
end;
|
|
|
|
in
|
|
|
|
let l = length a in
|
2000-04-17 08:15:59 -07:00
|
|
|
for i = (l + 1) / 3 - 1 downto 0 do trickle l i (get a i); done;
|
2000-04-14 03:05:33 -07:00
|
|
|
for i = l - 1 downto 2 do
|
2000-04-17 08:15:59 -07:00
|
|
|
let e = (get a i) in
|
|
|
|
set a i (get a 0);
|
2000-04-14 03:05:33 -07:00
|
|
|
trickleup (bubble i 0) e;
|
|
|
|
done;
|
2000-04-17 08:15:59 -07:00
|
|
|
if l > 1 then (let e = (get a 1) in set a 1 (get a 0); set a 0 e);
|
2000-04-14 03:05:33 -07:00
|
|
|
;;
|
|
|
|
|
|
|
|
let cutoff = 5;;
|
|
|
|
let stable_sort cmp a =
|
|
|
|
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
|
|
|
|
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
|
|
|
|
let rec loop i1 s1 i2 s2 d =
|
|
|
|
if cmp s1 s2 <= 0 then begin
|
2000-04-17 08:15:59 -07:00
|
|
|
set dst d s1;
|
2000-04-14 03:05:33 -07:00
|
|
|
let i1 = i1 + 1 in
|
|
|
|
if i1 < src1r then
|
2000-04-17 08:15:59 -07:00
|
|
|
loop i1 (get a i1) i2 s2 (d + 1)
|
2000-04-14 03:05:33 -07:00
|
|
|
else
|
|
|
|
blit src2 i2 dst (d + 1) (src2r - i2)
|
|
|
|
end else begin
|
2000-04-17 08:15:59 -07:00
|
|
|
set dst d s2;
|
2000-04-14 03:05:33 -07:00
|
|
|
let i2 = i2 + 1 in
|
|
|
|
if i2 < src2r then
|
2000-04-17 08:15:59 -07:00
|
|
|
loop i1 s1 i2 (get src2 i2) (d + 1)
|
2000-04-14 03:05:33 -07:00
|
|
|
else
|
|
|
|
blit a i1 dst (d + 1) (src1r - i1)
|
|
|
|
end
|
2000-04-17 08:15:59 -07:00
|
|
|
in loop src1ofs (get a src1ofs) src2ofs (get src2 src2ofs) dstofs;
|
2000-04-14 03:05:33 -07:00
|
|
|
in
|
|
|
|
let isortto srcofs dst dstofs len =
|
|
|
|
for i = 0 to len - 1 do
|
2000-04-17 08:15:59 -07:00
|
|
|
let e = (get a (srcofs + i)) in
|
2000-04-14 03:05:33 -07:00
|
|
|
let j = ref (dstofs + i - 1) in
|
2000-04-17 08:15:59 -07:00
|
|
|
while (!j >= dstofs && cmp (get dst !j) e > 0) do
|
|
|
|
set dst (!j + 1) (get dst !j);
|
2000-04-14 03:05:33 -07:00
|
|
|
decr j;
|
|
|
|
done;
|
2000-04-17 08:15:59 -07:00
|
|
|
set dst (!j + 1) e;
|
2000-04-14 03:05:33 -07:00
|
|
|
done;
|
|
|
|
in
|
|
|
|
let rec sortto srcofs dst dstofs len =
|
|
|
|
if len <= cutoff then isortto srcofs dst dstofs len else begin
|
|
|
|
let l1 = len / 2 in
|
|
|
|
let l2 = len - l1 in
|
|
|
|
sortto (srcofs + l1) dst (dstofs + l1) l2;
|
|
|
|
sortto srcofs a (srcofs + l2) l1;
|
|
|
|
merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs;
|
|
|
|
end;
|
|
|
|
in
|
|
|
|
let l = length a in
|
|
|
|
if l <= cutoff then isortto 0 a 0 l else begin
|
|
|
|
let l1 = l / 2 in
|
|
|
|
let l2 = l - l1 in
|
2000-04-17 08:15:59 -07:00
|
|
|
let t = make l2 (get a 0) in
|
2000-04-14 03:05:33 -07:00
|
|
|
sortto l1 t 0 l2;
|
|
|
|
sortto 0 a l2 l1;
|
|
|
|
merge l2 l1 t 0 l2 a 0;
|
|
|
|
end;
|
|
|
|
;;
|