@@ -27,7 +27,7 @@ type ('data, 'tag) node = 'data data_node * 'tag tag_node
2727
2828 Non-invariants:
2929 1. The tag trie need not be minimum.
30- 2. This implementation prefers removing tag_default_child.
30+ 2. This module prefers removing tag_default_child.
3131*)
3232
3333type ('data, 'tag) t = ('data , 'tag ) node option
@@ -53,6 +53,20 @@ let mk_tag_node' d t : _ tag_node = mk_tag_node d (t, (t, SegMap.empty))
5353let mk_node d tag_params : _ node = d, mk_tag_node d tag_params
5454let mk_node' d tag : _ node = d, mk_tag_node' d tag
5555
56+ (* invariants: the input is already valid *)
57+ let drop_tag_default_child (d , t ) =
58+ if t.tag_default_child = None then (d, t) else
59+ let tag_children =
60+ SegMap. merge
61+ (fun _ child tag_child ->
62+ match child, tag_child with
63+ | None , _ -> assert false
64+ | Some d , None -> Some (mk_tag_node' d t.tag_default_child)
65+ | Some _ , Some t -> Some t)
66+ d.children t.tag_children
67+ in
68+ d, { t with tag_default_child = None ; tag_children }
69+
5670(* invariants: input tag tree must be a subset (if default tags were ignored) *)
5771let mk_tree (root , children ) tag_params : _ t =
5872 if Option. is_none root && SegMap. is_empty children
@@ -84,15 +98,15 @@ let get_children_node (d, t) =
8498 SegMap. merge
8599 (fun _ d' t' ->
86100 match d', t' with
87- | None , _ -> None
101+ | None , _ -> assert false
88102 | Some d , None -> Some (d, mk_tag_node' d t.tag_default_child)
89103 | Some d , Some t -> Some (d, t))
90104 d.children t.tag_children
91105let get_children_node2 (d , t1 , t2 ) =
92106 SegMap. merge
93107 (fun _ d_t1 t2' ->
94108 match d_t1, t2' with
95- | None , _ -> None
109+ | None , _ -> assert false
96110 | Some (d , t1 ), None -> Some (d, t1, mk_tag_node' d t2.tag_default_child)
97111 | Some (d , t1 ), Some t2 -> Some (d, t1, t2))
98112 (get_children_node (d, t1)) t2.tag_children
@@ -191,15 +205,32 @@ let union_option m r1 r2 =
191205 | Some r , None | None , Some r -> Some r
192206 | Some r1 , Some r2 -> Some (m r1 r2)
193207
208+ (* this function is optimized for the cases where the merging is rare *)
194209let rec union_node ~prefix m n1 n2 =
210+ let (nd1, nt1) as n1 = drop_tag_default_child n1
211+ and (nd2, nt2) as n2 = drop_tag_default_child n2
212+ in
195213 let root, tag_root = split_option @@
196214 union_option (m prefix) (find_root_node n1) (find_root_node n2)
197215 in
198- let children, tag_children =
199- split_children @@ SegMap. union
200- (fun seg n1 n2 -> Some (union_node ~prefix: (prefix #< seg) m n1 n2))
201- (get_children_node n1) (get_children_node n2)
216+ let tag_exclusive_children =
217+ SegMap. union
218+ (fun _seg _t1 _t2 -> None )
219+ nt1.tag_children nt2.tag_children
220+ in
221+ let tag_overlapping_children = ref SegMap. empty in
222+ let children =
223+ SegMap. union
224+ (fun seg d1 d2 ->
225+ let t1 = SegMap. find seg nt1.tag_children
226+ and t2 = SegMap. find seg nt2.tag_children
227+ in
228+ let d, t = union_node ~prefix: (prefix #< seg) m (d1, t1) (d2, t2) in
229+ tag_overlapping_children := SegMap. add seg t ! tag_overlapping_children;
230+ Some d)
231+ nd1.children nd2.children
202232 in
233+ let tag_children = SegMap. union (fun _ _ _ -> assert false ) tag_exclusive_children ! tag_overlapping_children in
203234 {root; children}, {tag_root; tag_default_child = None ; tag_children}
204235
205236let union_ ~prefix m = union_option (union_node ~prefix m)
0 commit comments