From b81fafbb8fbcba0cd54ea93fd44e6bd69540324a Mon Sep 17 00:00:00 2001 From: Hugo Herbelin Date: Thu, 5 Apr 2018 11:33:30 +0200 Subject: CArray: adding combinators. --- clib/cArray.ml | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ clib/cArray.mli | 10 +++++++ 2 files changed, 92 insertions(+) (limited to 'clib') diff --git a/clib/cArray.ml b/clib/cArray.ml index 071f4689b..c1013dff4 100644 --- a/clib/cArray.ml +++ b/clib/cArray.ml @@ -50,7 +50,9 @@ sig val map_of_list : ('a -> 'b) -> 'a list -> 'b array val chop : int -> 'a array -> 'a array * 'a array val smartmap : ('a -> 'a) -> 'a array -> 'a array + val smartmap2 : ('a -> 'b -> 'b) -> 'a array -> 'b array -> 'b array val smartfoldmap : ('r -> 'a -> 'r * 'a) -> 'r -> 'a array -> 'r * 'a array + val smartfoldmap2 : ('r -> 'a -> 'b -> 'r * 'b) -> 'r -> 'a array -> 'b array -> 'r * 'b array val map2 : ('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array val map2_i : (int -> 'a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array val map3 : @@ -359,6 +361,39 @@ let smartmap f (ar : 'a array) = ans end else ar +let smartmap2 f aux_ar ar = + let len = Array.length ar in + let aux_len = Array.length aux_ar in + let () = if not (Int.equal len aux_len) then invalid_arg "Array.smartmap2" in + let i = ref 0 in + let break = ref true in + let temp = ref None in + while !break && (!i < len) do + let v = Array.unsafe_get ar !i in + let w = Array.unsafe_get aux_ar !i in + let v' = f w v in + if v == v' then incr i + else begin + break := false; + temp := Some v'; + end + done; + if !i < len then begin + (** The array is not the same as the original one *) + let ans : 'a array = Array.copy ar in + let v = match !temp with None -> assert false | Some x -> x in + Array.unsafe_set ans !i v; + incr i; + while !i < len do + let v = Array.unsafe_get ans !i in + let w = Array.unsafe_get aux_ar !i in + let v' = f w v in + if v != v' then Array.unsafe_set ans !i v'; + incr i + done; + ans + end else ar + (** Same as [smartmap] but threads a state meanwhile *) let smartfoldmap f accu (ar : 'a array) = let len = Array.length ar in @@ -392,6 +427,43 @@ let smartfoldmap f accu (ar : 'a array) = !r, ans end else !r, ar +(** Same as [smartmap2] but threads a state meanwhile *) +let smartfoldmap2 f accu aux_ar ar = + let len = Array.length ar in + let aux_len = Array.length aux_ar in + let () = if not (Int.equal len aux_len) then invalid_arg "Array.smartfoldmap2" in + let i = ref 0 in + let break = ref true in + let r = ref accu in + (** This variable is never accessed unset *) + let temp = ref None in + while !break && (!i < len) do + let v = Array.unsafe_get ar !i in + let w = Array.unsafe_get aux_ar !i in + let (accu, v') = f !r w v in + r := accu; + if v == v' then incr i + else begin + break := false; + temp := Some v'; + end + done; + if !i < len then begin + let ans : 'a array = Array.copy ar in + let v = match !temp with None -> assert false | Some x -> x in + Array.unsafe_set ans !i v; + incr i; + while !i < len do + let v = Array.unsafe_get ar !i in + let w = Array.unsafe_get aux_ar !i in + let (accu, v') = f !r w v in + r := accu; + if v != v' then Array.unsafe_set ans !i v'; + incr i + done; + !r, ans + end else !r, ar + let map2 f v1 v2 = let len1 = Array.length v1 in let len2 = Array.length v2 in @@ -559,4 +631,14 @@ struct f arg x done + let iter2 f arg v1 v2 = + let len1 = Array.length v1 in + let len2 = Array.length v2 in + let () = if not (Int.equal len2 len1) then invalid_arg "Array.Fun1.iter2" in + for i = 0 to pred len1 do + let x1 = uget v1 i in + let x2 = uget v2 i in + f arg x1 x2 + done + end diff --git a/clib/cArray.mli b/clib/cArray.mli index 9c2f521f4..56cc3656d 100644 --- a/clib/cArray.mli +++ b/clib/cArray.mli @@ -86,9 +86,16 @@ sig (** [smartmap f a] behaves as [map f a] but returns [a] instead of a copy when [f x == x] for all [x] in [a]. *) + val smartmap2 : ('a -> 'b -> 'b) -> 'a array -> 'b array -> 'b array + (** [smartmap2 f a b] behaves as [map2 f a b] but returns [a] instead of a copy when + [f x y == y] for all [x] in [a] and [y] in [b] pointwise. *) + val smartfoldmap : ('r -> 'a -> 'r * 'a) -> 'r -> 'a array -> 'r * 'a array (** Same as [smartmap] but threads an additional state left-to-right. *) + val smartfoldmap2 : ('r -> 'a -> 'b -> 'r * 'b) -> 'r -> 'a array -> 'b array -> 'r * 'b array + (** Same as [smartmap2] but threads an additional state left-to-right. *) + val map2 : ('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array val map2_i : (int -> 'a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array val map3 : @@ -152,6 +159,9 @@ sig val iter : ('r -> 'a -> unit) -> 'r -> 'a array -> unit (** [Fun1.iter f x v = iter (f x) v] *) + val iter2 : ('r -> 'a -> 'b -> unit) -> 'r -> 'a array -> 'b array -> unit + (** [Fun1.iter2 f x v1 v2 = iter (f x) v1 v2] *) + end (** The functions defined in this module are the same as the main ones, except that they are all higher-order, and their function arguments have an -- cgit v1.2.3