aboutsummaryrefslogtreecommitdiffhomepage
path: root/clib
diff options
context:
space:
mode:
authorGravatar Hugo Herbelin <Hugo.Herbelin@inria.fr>2018-05-23 13:34:22 +0200
committerGravatar Hugo Herbelin <Hugo.Herbelin@inria.fr>2018-05-23 18:50:10 +0200
commitf2ab2825077bf8344d2e55be433efb1891212589 (patch)
treed666574c6b964fed33a0b50cece1648f67d9917f /clib
parent4e207da568b31fb3fd097fb584f4722bd7166fcf (diff)
Collecting Array.smart_* functions into a module Array.Smart.
Diffstat (limited to 'clib')
-rw-r--r--clib/cArray.ml327
-rw-r--r--clib/cArray.mli55
2 files changed, 213 insertions, 169 deletions
diff --git a/clib/cArray.ml b/clib/cArray.ml
index c1013dff4..6ea46655f 100644
--- a/clib/cArray.ml
+++ b/clib/cArray.ml
@@ -50,9 +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
+ [@@ocaml.deprecated "Same as [Smart.map]"]
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
+ [@@ocaml.deprecated "Same as [Smart.fold_left_map]"]
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 :
@@ -74,6 +74,13 @@ sig
val rev_of_list : 'a list -> 'a array
val rev_to_list : 'a array -> 'a list
val filter_with : bool list -> 'a array -> 'a array
+ module Smart :
+ sig
+ val map : ('a -> 'a) -> 'a array -> 'a array
+ val map2 : ('a -> 'b -> 'b) -> 'a array -> 'b array -> 'b array
+ val fold_left_map : ('a -> 'b -> 'a * 'b) -> 'a -> 'b array -> 'a * 'b array
+ val fold_left2_map : ('a -> 'b -> 'c -> 'a * 'c) -> 'a -> 'b array -> 'c array -> 'a * 'c array
+ end
end
include Array
@@ -328,142 +335,6 @@ let chop n v =
if n > vlen then failwith "Array.chop";
(Array.sub v 0 n, Array.sub v n (vlen-n))
-(* If none of the elements is changed by f we return ar itself.
- The while loop looks for the first such an element.
- If found, we break here and the new array is produced,
- but f is not re-applied to elements that are already checked *)
-let smartmap f (ar : 'a array) =
- let len = Array.length ar 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 v' = f 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 v' = f v in
- if v != v' then Array.unsafe_set ans !i v';
- incr i
- done;
- 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
- 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 (accu, v') = f !r 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 (accu, v') = f !r v in
- r := accu;
- if v != v' then Array.unsafe_set ans !i v';
- incr i
- done;
- !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
@@ -580,29 +451,53 @@ let rev_to_list a =
let filter_with filter v =
Array.of_list (CList.filter_with filter (Array.to_list v))
-module Fun1 =
+module Smart =
struct
- let map f arg v = match v with
- | [| |] -> [| |]
- | _ ->
- let len = Array.length v in
- let x0 = Array.unsafe_get v 0 in
- let ans = Array.make len (f arg x0) in
- for i = 1 to pred len do
- let x = Array.unsafe_get v i in
- Array.unsafe_set ans i (f arg x)
+ (* If none of the elements is changed by f we return ar itself.
+ The while loop looks for the first such an element.
+ If found, we break here and the new array is produced,
+ but f is not re-applied to elements that are already checked *)
+ let map f (ar : 'a array) =
+ let len = Array.length ar 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 v' = f v in
+ if v == v' then incr i
+ else begin
+ break := false;
+ temp := Some v';
+ end
done;
- ans
+ 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 v' = f v in
+ if v != v' then Array.unsafe_set ans !i v';
+ incr i
+ done;
+ ans
+ end else ar
- let smartmap f arg (ar : 'a array) =
+ let map2 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.Smart.map2" 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 v' = f arg v 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;
@@ -617,13 +512,105 @@ struct
incr i;
while !i < len do
let v = Array.unsafe_get ans !i in
- let v' = f arg v 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 [Smart.map] but threads a state meanwhile *)
+ let fold_left_map f accu (ar : 'a array) =
+ let len = Array.length ar 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 (accu, v') = f !r 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 (accu, v') = f !r v in
+ r := accu;
+ if v != v' then Array.unsafe_set ans !i v';
+ incr i
+ done;
+ !r, ans
+ end else !r, ar
+
+ (** Same as [Smart.map2] but threads a state meanwhile *)
+ let fold_left2_map 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.Smart.fold_left2_map" 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
+
+end
+
+(* Deprecated aliases *)
+let smartmap = Smart.map
+let smartfoldmap = Smart.fold_left_map
+
+module Fun1 =
+struct
+
+ let map f arg v = match v with
+ | [| |] -> [| |]
+ | _ ->
+ let len = Array.length v in
+ let x0 = Array.unsafe_get v 0 in
+ let ans = Array.make len (f arg x0) in
+ for i = 1 to pred len do
+ let x = Array.unsafe_get v i in
+ Array.unsafe_set ans i (f arg x)
+ done;
+ ans
+
let iter f arg v =
let len = Array.length v in
for i = 0 to pred len do
@@ -641,4 +628,40 @@ struct
f arg x1 x2
done
+ module Smart =
+ struct
+
+ let map f arg (ar : 'a array) =
+ let len = Array.length ar 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 v' = f arg 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 v' = f arg v in
+ if v != v' then Array.unsafe_set ans !i v';
+ incr i
+ done;
+ ans
+ end else ar
+
+ end
+
+ let smartmap = Smart.map
+
end
diff --git a/clib/cArray.mli b/clib/cArray.mli
index c461d856b..d800e79ed 100644
--- a/clib/cArray.mli
+++ b/clib/cArray.mli
@@ -83,24 +83,14 @@ sig
Raise [Failure "Array.chop"] if [i] is not a valid index. *)
val smartmap : ('a -> 'a) -> 'a array -> 'a array
- (** [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. *)
+ [@@ocaml.deprecated "Same as [Smart.map]"]
val smartfoldmap : ('r -> 'a -> 'r * 'a) -> 'r -> 'a array -> 'r * 'a array
- (** [smartfoldmap f a b] behaves as [fold_left_map] but
- returns [b] as second component instead of a copy of [b] when
- the output array is pointwise the same as the input array [b] *)
-
- val smartfoldmap2 : ('r -> 'a -> 'b -> 'r * 'b) -> 'r -> 'a array -> 'b array -> 'r * 'b array
- (** [smartfoldmap2 f a b c] behaves as [fold_left2_map] but
- returns [c] as second component instead of a copy of [c] when
- the output array is pointwise the same as the input array [c] *)
+ [@@ocaml.deprecated "Same as [Smart.fold_left_map]"]
val map2 : ('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array
+ (** See also [Smart.map2] *)
+
val map2_i : (int -> 'a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array
val map3 :
('a -> 'b -> 'c -> 'd) -> 'a array -> 'b array -> 'c array -> 'd array
@@ -113,13 +103,13 @@ sig
val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b array -> 'a * 'c array
(** [fold_left_map f e_0 [|l_1...l_n|] = e_n,[|k_1...k_n|]]
- where [(e_i,k_i)=f e_{i-1} l_i] *)
+ where [(e_i,k_i)=f e_{i-1} l_i]; see also [Smart.fold_left_map] *)
val fold_right_map : ('a -> 'c -> 'b * 'c) -> 'a array -> 'c -> 'b array * 'c
(** Same, folding on the right *)
val fold_left2_map : ('a -> 'b -> 'c -> 'a * 'd) -> 'a -> 'b array -> 'c array -> 'a * 'd array
- (** Same with two arrays, folding on the left *)
+ (** Same with two arrays, folding on the left; see also [Smart.fold_left2_map] *)
val fold_right2_map : ('a -> 'b -> 'c -> 'd * 'c) -> 'a array -> 'b array -> 'c -> 'd array * 'c
(** Same with two arrays, folding on the left *)
@@ -148,6 +138,31 @@ sig
(** [filter_with b a] selects elements of [a] whose corresponding element in
[b] is [true]. Raise [Invalid_argument _] when sizes differ. *)
+ module Smart :
+ sig
+ val map : ('a -> 'a) -> 'a array -> 'a array
+ (** [Smart.map f a] behaves as [map f a] but returns [a] instead of a copy when
+ [f x == x] for all [x] in [a]. *)
+
+ val map2 : ('a -> 'b -> 'b) -> 'a array -> 'b array -> 'b array
+ (** [Smart.map2 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 fold_left_map : ('a -> 'b -> 'a * 'b) -> 'a -> 'b array -> 'a * 'b array
+ (** [Smart.fold_left_mapf a b] behaves as [fold_left_map] but
+ returns [b] as second component instead of a copy of [b] when
+ the output array is pointwise the same as the input array [b] *)
+
+ val fold_left2_map : ('a -> 'b -> 'c -> 'a * 'c) -> 'a -> 'b array -> 'c array -> 'a * 'c array
+ (** [Smart.fold_left2_map f a b c] behaves as [fold_left2_map] but
+ returns [c] as second component instead of a copy of [c] when
+ the output array is pointwise the same as the input array [c] *)
+
+ end
+ (** The functions defined in this module are optimized specializations
+ of the main ones, when the returned array is of same type as one of
+ the original array. *)
+
end
include ExtS
@@ -158,7 +173,7 @@ sig
(** [Fun1.map f x v = map (f x) v] *)
val smartmap : ('r -> 'a -> 'a) -> 'r -> 'a array -> 'a array
- (** [Fun1.smartmap f x v = smartmap (f x) v] *)
+ [@@ocaml.deprecated "Same as [Fun1.Smart.map]"]
val iter : ('r -> 'a -> unit) -> 'r -> 'a array -> unit
(** [Fun1.iter f x v = iter (f x) v] *)
@@ -166,6 +181,12 @@ sig
val iter2 : ('r -> 'a -> 'b -> unit) -> 'r -> 'a array -> 'b array -> unit
(** [Fun1.iter2 f x v1 v2 = iter (f x) v1 v2] *)
+ module Smart :
+ sig
+ val map : ('r -> 'a -> 'a) -> 'r -> 'a array -> 'a array
+ (** [Fun1.Smart.map f x v = Smart.map (f x) v] *)
+ end
+
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