From 32985129e0afbf2b5d5e8b8923acc3d2cf1e8758 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 22 Apr 2013 18:32:23 +0200 Subject: [PATCH] update of Vector, with more functions (length, rev, append_seq...) and better performance (using unsafe_set/unsafe_get in Array) --- vector.ml | 85 +++++++++++++++++++++++++++++++++++++----------------- vector.mli | 14 +++++++++ 2 files changed, 73 insertions(+), 26 deletions(-) diff --git a/vector.ml b/vector.ml index 5fcaf4de..8d9060a2 100644 --- a/vector.ml +++ b/vector.ml @@ -40,40 +40,45 @@ let create i = (** resize the underlying array so that it can contains the given number of elements *) let resize v newcapacity = - let newcapacity = min newcapacity Sys.max_array_length in - if newcapacity <= Array.length v.vec - then () (* already big enough *) - else begin - assert (newcapacity >= v.size); - let new_vec = Array.create newcapacity (Obj.magic None) in - Array.blit v.vec 0 new_vec 0 v.size; - v.vec <- new_vec; - end + assert (newcapacity >= v.size); + let new_vec = Array.create newcapacity (Obj.magic None) in + Array.blit v.vec 0 new_vec 0 v.size; + v.vec <- new_vec; + () + +(** Be sure that [v] can contain [size] elements, resize it if needed. *) +let ensure v size = + if v.size < size + then + let size' = min (2 * v.size) Sys.max_array_length in + resize v size' let clear v = - v.size <- 0; - if Array.length v.vec > 1024 (* shrink if too large *) - then (v.vec <- Array.create 10 (Obj.magic None)) + v.size <- 0 let is_empty v = v.size = 0 let push v x = - (if Array.length v.vec = v.size - then resize v (2 * v.size)); - v.vec.(v.size) <- x; + (if v.size = Array.length v.vec then resize v (2 * v.size)); + Array.unsafe_set v.vec v.size x; v.size <- v.size + 1 (** add all elements of b to a *) let append a b = - resize a (a.size + b.size); + (if Array.length a.vec < a.size + b.size + then resize a (2 * (a.size + b.size))); Array.blit b.vec 0 a.vec a.size b.size; a.size <- a.size + b.size let append_array a b = - resize a (a.size + Array.length b); + (if Array.length a.vec < a.size + Array.length b + then resize a (2 * (a.size + Array.length b))); Array.blit b 0 a.vec a.size (Array.length b); a.size <- a.size + Array.length b +let append_seq a seq = + Sequence.iter (fun x -> push a x) seq + let pop v = (if v.size = 0 then failwith "Vector.pop on empty vector"); v.size <- v.size - 1; @@ -87,7 +92,9 @@ let copy v = v' let shrink v n = - if n > v.size then failwith "cannot shrink to bigger size" else v.size <- n + if n > v.size + then failwith "cannot shrink to bigger size" + else v.size <- n let member ?(eq=(=)) v x = let n = v.size in @@ -120,32 +127,36 @@ let uniq_sort ?(cmp=compare) v = let iter v k = for i = 0 to v.size -1 do - k v.vec.(i) + k (Array.unsafe_get v.vec i) done let iteri v k = for i = 0 to v.size -1 do - k i v.vec.(i) + k i (Array.unsafe_get v.vec i) done let map v f = let v' = create v.size in for i = 0 to v.size - 1 do - push v' (f v.vec.(i)); + let x = f (Array.unsafe_get v.vec i) in + Array.unsafe_set v'.vec i x done; + v'.size <- v.size; v' let filter v f = let v' = create v.size in for i = 0 to v.size - 1 do - if f v.vec.(i) then push v' v.vec.(i); + let x = Array.unsafe_get v.vec i in + if f x then push v' x; done; v' let fold v acc f = let acc = ref acc in for i = 0 to v.size - 1 do - acc := f !acc v.vec.(i); + let x = Array.unsafe_get v.vec i in + acc := f !acc x; done; !acc @@ -175,23 +186,45 @@ let find v p = let get v i = (if i < 0 || i >= v.size then failwith "Vector.get"); - v.vec.(i) + Array.unsafe_get v.vec i let set v i x = (if i < 0 || i >= v.size then failwith "Vector.set"); - v.vec.(i) <- x + Array.unsafe_set v.vec i x + +let rev v = + let n = v.size in + let vec = v.vec in + for i = 0 to (n-1)/2 do + let x = Array.unsafe_get vec i in + let y = Array.unsafe_get vec (n-i-1) in + Array.unsafe_set vec i y; + Array.unsafe_set vec (n-i-1) x; + done let size v = v.size +let length v = v.size + let unsafe_get_array v = v.vec let of_seq ?(init=create 10) seq = - Sequence.iter (fun x -> push init x) seq; + append_seq init seq; init let to_seq t = Sequence.from_iter (fun k -> iter t k) +let slice v start len = + assert (start >= 0 && len >= 0); + Sequence.from_iter + (fun k -> + assert (start+len < v.size); + for i = start to start+len do + let x = Array.unsafe_get v.vec i in + k x + done) + let from_array a = let c = Array.length a in let v = create c in diff --git a/vector.mli b/vector.mli index 4db846f1..4205e5b1 100644 --- a/vector.mli +++ b/vector.mli @@ -46,6 +46,9 @@ val append : 'a t -> 'a t -> unit val append_array : 'a t -> 'a array -> unit (** same as append, with an array *) +val append_seq : 'a t -> 'a Sequence.t -> unit + (** Append content of sequence *) + val pop : 'a t -> 'a (** remove last element, or raise a Failure if empty *) @@ -94,17 +97,28 @@ val get : 'a t -> int -> 'a val set : 'a t -> int -> 'a -> unit (** access element, or Failure if bad index *) +val rev : 'a t -> unit + (** Reverse array in place *) + val size : 'a t -> int (** number of elements in vector *) +val length : _ t -> int + (** Synonym for {! size} *) + val unsafe_get_array : 'a t -> 'a array (** Access the underlying *shared* array (do not modify!). [unsafe_get_array v] is longer than [size v], but elements at higher index than [size v] are undefined (do not access!). *) val of_seq : ?init:'a t -> 'a Sequence.t -> 'a t + val to_seq : 'a t -> 'a Sequence.t +val slice : 'a t -> int -> int -> 'a Sequence.t + (** [slice v start len] is the sequence of elements from [v.(start)] + to [v.(start+len)] included. *) + val from_array : 'a array -> 'a t val from_list : 'a list -> 'a t val to_array : 'a t -> 'a array