diff options
Diffstat (limited to 'ocaml-binary-annot/stdlib/array.ml')
| -rw-r--r-- | ocaml-binary-annot/stdlib/array.ml | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/ocaml-binary-annot/stdlib/array.ml b/ocaml-binary-annot/stdlib/array.ml new file mode 100644 index 0000000000..d1cbd65576 --- /dev/null +++ b/ocaml-binary-annot/stdlib/array.ml @@ -0,0 +1,280 @@ +(***********************************************************************) +(* *) +(* Objective Caml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. All rights reserved. This file is distributed *) +(* under the terms of the GNU Library General Public License, with *) +(* the special exception on linking described in file ../LICENSE. *) +(* *) +(***********************************************************************) + +(* $Id$ *) + +(* Array operations *) + +external length : 'a array -> int = "%array_length" +external get: 'a array -> int -> 'a = "%array_safe_get" +external set: 'a array -> int -> 'a -> unit = "%array_safe_set" +external unsafe_get: 'a array -> int -> 'a = "%array_unsafe_get" +external unsafe_set: 'a array -> int -> 'a -> unit = "%array_unsafe_set" +external make: int -> 'a -> 'a array = "caml_make_vect" +external create: int -> 'a -> 'a array = "caml_make_vect" + +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 + +let make_matrix sx sy init = + let res = create sx [||] in + for x = 0 to pred sx do + unsafe_set res x (create sy init) + done; + res + +let create_matrix = make_matrix + +let copy a = + let l = length a in + if l = 0 then [||] else begin + let res = create l (unsafe_get a 0) in + for i = 1 to pred l do + unsafe_set res i (unsafe_get a i) + done; + res + end + +let append a1 a2 = + let l1 = length a1 and l2 = length a2 in + if l1 = 0 && l2 = 0 then [||] else begin + let r = create (l1 + l2) (unsafe_get (if l1 > 0 then a1 else a2) 0) in + for i = 0 to l1 - 1 do unsafe_set r i (unsafe_get a1 i) done; + for i = 0 to l2 - 1 do unsafe_set r (i + l1) (unsafe_get a2 i) done; + r + end + +let concat_aux init al = + 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; + res +;; + +let concat al = + let rec find_init aa = + match aa with + | [] -> [||] + | a :: rem -> + if length a > 0 then concat_aux (unsafe_get a 0) aa else find_init rem + in find_init al + +let sub a ofs len = + if ofs < 0 || len < 0 || ofs > length a - len then invalid_arg "Array.sub" + else if len = 0 then [||] + else begin + let r = create len (unsafe_get a ofs) in + 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 = + if ofs < 0 || len < 0 || ofs > length a - len + 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 = + if len < 0 || ofs1 < 0 || ofs1 > length a1 - len + || ofs2 < 0 || ofs2 > length a2 - len + then invalid_arg "Array.blit" + 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 + else + (* Bottom-up copy *) + 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 + let r = create l (f(unsafe_get a 0)) in + for i = 1 to l - 1 do + unsafe_set r i (f(unsafe_get a i)) + done; + r + end + +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 + +let to_list a = + let rec tolist i res = + if i < 0 then res else tolist (i - 1) (unsafe_get a i :: res) in + tolist (length a - 1) [] + +(* Cannot use List.length here because the List module depends on Array. *) +let rec list_length accu = function + | [] -> accu + | h::t -> list_length (succ accu) t +;; + +let of_list = function + [] -> [||] + | hd::tl as l -> + let a = create (list_length 0 l) hd in + let rec fill i = function + [] -> a + | hd::tl -> unsafe_set a i hd; fill (i+1) tl in + fill 1 tl + +let fold_left f x a = + let r = ref x in + for i = 0 to length a - 1 do + r := f !r (unsafe_get a i) + done; + !r + +let fold_right f a x = + let r = ref x in + for i = length a - 1 downto 0 do + r := f (unsafe_get a i) !r + done; + !r + +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 + 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; + !x + end else + if i31+1 < l && cmp (get a i31) (get a (i31+1)) < 0 + then i31+1 + else if i31 < l then i31 else raise (Bottom i) + in + let rec trickledown l i e = + let j = maxson l i in + if cmp (get a j) e > 0 then begin + set a i (get a j); + trickledown l j e; + end else begin + set a i e; + end; + in + let rec trickle l i e = try trickledown l i e with Bottom i -> set a i e in + let rec bubbledown l i = + let j = maxson l i in + set a i (get a j); + bubbledown l j + in + let bubble l i = try bubbledown l i with Bottom i -> i in + let rec trickleup i e = + let father = (i - 1) / 3 in + assert (i <> father); + if cmp (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; + end else begin + set a i e; + end; + in + let l = length a in + for i = (l + 1) / 3 - 1 downto 0 do trickle l i (get a i); done; + for i = l - 1 downto 2 do + let e = (get a i) in + set a i (get a 0); + trickleup (bubble i 0) e; + done; + if l > 1 then (let e = (get a 1) in set a 1 (get a 0); set a 0 e); +;; + +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 + set dst d s1; + let i1 = i1 + 1 in + if i1 < src1r then + loop i1 (get a i1) i2 s2 (d + 1) + else + blit src2 i2 dst (d + 1) (src2r - i2) + end else begin + set dst d s2; + let i2 = i2 + 1 in + if i2 < src2r then + loop i1 s1 i2 (get src2 i2) (d + 1) + else + blit a i1 dst (d + 1) (src1r - i1) + end + in loop src1ofs (get a src1ofs) src2ofs (get src2 src2ofs) dstofs; + in + let isortto srcofs dst dstofs len = + for i = 0 to len - 1 do + let e = (get a (srcofs + i)) in + let j = ref (dstofs + i - 1) in + while (!j >= dstofs && cmp (get dst !j) e > 0) do + set dst (!j + 1) (get dst !j); + decr j; + done; + set dst (!j + 1) e; + done; + in + let rec sortto srcofs dst dstofs len = + if len <= cutoff then isortto srcofs dst dstofs len else begin + let l1 = len / 2 in + let l2 = len - l1 in + sortto (srcofs + l1) dst (dstofs + l1) l2; + sortto srcofs a (srcofs + l2) l1; + merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs; + end; + in + let l = length a in + if l <= cutoff then isortto 0 a 0 l else begin + let l1 = l / 2 in + let l2 = l - l1 in + let t = make l2 (get a 0) in + sortto l1 t 0 l2; + sortto 0 a l2 l1; + merge l2 l1 t 0 l2 a 0; + end; +;; + +let fast_sort = stable_sort;; |
