From d242d12a27d84971f5e89405bb09fc36def77510 Mon Sep 17 00:00:00 2001 From: Vasilis Papavasileiou Date: Thu, 22 Oct 2015 14:34:52 +0200 Subject: [PATCH 1/2] Linear-time patch operation, if the patch format permits --- src/reactiveData.ml | 55 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/reactiveData.ml b/src/reactiveData.ml index 06e81e0..9886ec3 100644 --- a/src/reactiveData.ml +++ b/src/reactiveData.ml @@ -206,7 +206,60 @@ module DataList = struct end; Array.to_list a - let merge p l = List.fold_left (fun l x -> merge_p x l) l p + (* accumulates into acc i unmodified elements from l *) + let rec linear_merge_fwd i l ~acc = + assert (i >= 0); + if i > 0 then + match l with + | h :: l -> + let acc = h :: acc in + linear_merge_fwd (i - 1) l ~acc + | [] -> + failwith "linear_merge_fwd" + else + l, acc + + let rec linear_merge ?(acc = []) i0 p l = + let l, acc = + match p with + | (I (i, _) | R i | U (i, _)) :: _ when i > i0 -> + linear_merge_fwd (i - i0) l ~acc + | _ -> + l, acc + in + match p, l with + | I (i, x) :: p, _ -> + linear_merge ~acc i p (x :: l) + | R i :: p, _ :: l -> + linear_merge ~acc i p l + | R _ :: _, [] -> + failwith "ReactiveData.RList.linear_merge: remove from empty" + | U (i, x) :: p, _ :: l -> + linear_merge ~acc i p (x :: l) + | U (_, _) :: _, [] -> + failwith "ReactiveData.RList.linear_merge: update empty" + | [], l -> + List.rev_append acc l + | X (_, _) :: _, _ -> + failwith "ReactiveData.RList.linear_merge: X not supported" + + let rec linear_mergeable ?(n = 0) p = + assert (n >= 0); + match p with + | (I (i, _) | R i | U (i, _)) :: p when i >= n -> + (* negative i's ruled out (among others) *) + linear_mergeable ~n:i p + | _ :: _ -> + false + | [] -> + true + + let merge p l = + if linear_mergeable p then + linear_merge 0 p l + else + List.fold_left (fun l x -> merge_p x l) l p + end module RList = struct From 113f5b3ea6ecb96af47d31ae52d0eca8507da9d9 Mon Sep 17 00:00:00 2001 From: Vasilis Papavasileiou Date: Wed, 28 Oct 2015 14:57:38 +0100 Subject: [PATCH 2/2] linear_merge: invalid_arg where applicable; all args non-optional --- src/reactiveData.ml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/reactiveData.ml b/src/reactiveData.ml index 9886ec3..dc4db93 100644 --- a/src/reactiveData.ml +++ b/src/reactiveData.ml @@ -215,11 +215,11 @@ module DataList = struct let acc = h :: acc in linear_merge_fwd (i - 1) l ~acc | [] -> - failwith "linear_merge_fwd" + invalid_arg "invalid index" else l, acc - let rec linear_merge ?(acc = []) i0 p l = + let rec linear_merge i0 p l ~acc = let l, acc = match p with | (I (i, _) | R i | U (i, _)) :: _ when i > i0 -> @@ -229,34 +229,34 @@ module DataList = struct in match p, l with | I (i, x) :: p, _ -> - linear_merge ~acc i p (x :: l) + linear_merge i p (x :: l) ~acc | R i :: p, _ :: l -> - linear_merge ~acc i p l + linear_merge i p l ~acc | R _ :: _, [] -> - failwith "ReactiveData.RList.linear_merge: remove from empty" + invalid_arg "merge: invalid index" | U (i, x) :: p, _ :: l -> - linear_merge ~acc i p (x :: l) + linear_merge i p (x :: l) ~acc | U (_, _) :: _, [] -> - failwith "ReactiveData.RList.linear_merge: update empty" + invalid_arg "merge: invalid index" | [], l -> List.rev_append acc l | X (_, _) :: _, _ -> - failwith "ReactiveData.RList.linear_merge: X not supported" + failwith "linear_merge: X not supported" - let rec linear_mergeable ?(n = 0) p = + let rec linear_mergeable p ~n = assert (n >= 0); match p with | (I (i, _) | R i | U (i, _)) :: p when i >= n -> (* negative i's ruled out (among others) *) - linear_mergeable ~n:i p + linear_mergeable p ~n:i | _ :: _ -> false | [] -> true let merge p l = - if linear_mergeable p then - linear_merge 0 p l + if linear_mergeable p ~n:0 then + linear_merge 0 p l ~acc:[] else List.fold_left (fun l x -> merge_p x l) l p