aboutsummaryrefslogtreecommitdiffhomepage
path: root/clib
diff options
context:
space:
mode:
authorGravatar Hugo Herbelin <Hugo.Herbelin@inria.fr>2018-04-05 11:33:30 +0200
committerGravatar Hugo Herbelin <Hugo.Herbelin@inria.fr>2018-05-23 18:50:10 +0200
commitb81fafbb8fbcba0cd54ea93fd44e6bd69540324a (patch)
tree6023b7dab6db62d1102fa5436c40bb66984d7c7a /clib
parentb74d9500e5943317f1baf4f36b3d979d40f6105f (diff)
CArray: adding combinators.
Diffstat (limited to 'clib')
-rw-r--r--clib/cArray.ml82
-rw-r--r--clib/cArray.mli10
2 files changed, 92 insertions, 0 deletions
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