diff options
-rw-r--r-- | lib/cArray.ml | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/lib/cArray.ml b/lib/cArray.ml index ab3a4ba51..81ac87477 100644 --- a/lib/cArray.ml +++ b/lib/cArray.ml @@ -313,15 +313,14 @@ let smartmap f (ar : 'a array) = done; if !i < len then begin (** The array is not the same as the original one *) - let ans : 'a array = Array.make len (Array.unsafe_get ar 0) in - (** TODO: use unsafe_blit in 4.01 *) - Array.blit ar 0 ans 0 !i; + 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 - Array.unsafe_set ans !i (f v); + let v' = f v in + if v != v' then Array.unsafe_set ans !i v'; incr i done; ans @@ -346,9 +345,7 @@ let smartfoldmap f accu (ar : 'a array) = end done; if !i < len then begin - let ans : 'a array = Array.make len (Array.unsafe_get ar 0) in - (** TODO: use unsafe_blit in 4.01 *) - Array.blit ar 0 ans 0 !i; + 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; @@ -356,7 +353,7 @@ let smartfoldmap f accu (ar : 'a array) = let v = Array.unsafe_get ar !i in let (accu, v') = f !r v in r := accu; - Array.unsafe_set ans !i v'; + if v != v' then Array.unsafe_set ans !i v'; incr i done; !r, ans @@ -483,28 +480,34 @@ struct done; ans - exception Local of int * Obj.t - - let smartmap f arg v = - let len = Array.length v in - try - for i = 0 to len - 1 do - let x = uget v i in - let y = f arg x in - if x != y then (* pointer (in)equality *) - raise (Local (i, Obj.repr y)) - done; - v - with Local (i, x) -> - (** FIXME: use Array.unsafe_blit from OCAML 4.00 *) - let ans : 'a array = Array.make len (uget v 0) in - let () = Array.blit v 0 ans 0 i in - let () = Array.unsafe_set ans i (Obj.obj x) in - for j = succ i to pred len do - let y = f arg (uget v j) in - Array.unsafe_set ans j y + let smartmap 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 ar !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 let iter f arg v = let len = Array.length v in |