(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) (* to deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) (* and/or sell copies of the Software, and to permit persons to whom the *) (* Software is furnished to do so, subject to the following conditions: *) (* *) (* The above copyright notice and this permission notice shall be included *) (* in all copies or substantial portions of the Software. *) (* *) (* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) (* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) (* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) (* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) (* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) (* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) module Ptree_sig = struct module type Value = sig type t val equal : t -> t -> bool val hash : t -> int end type prefix_order = | Equal | Shorter | Longer | Different module type Prefix = sig type key (* bit sequence *) type prefix (* prefix of a bit sequence *) type mask (* integer length of a bit sequence *) val equal_key : key -> key -> bool val equal_mask : mask -> mask -> bool val equal_prefix : prefix -> prefix -> bool val hash_key : key -> int val hash_mask : mask -> int val hash_prefix : prefix -> int val full_length_mask : mask val strictly_shorter_mask : mask -> mask -> bool val key_prefix : key -> prefix (* Full lenght prefix *) val prefix_key : prefix -> mask -> key (* Some key matching the prefix with the given mask *) val match_prefix : key:key -> prefix:prefix -> mask:mask -> bool (* Does the prefix of length [mask] of [key] equals to [prefix] *) val select_bit : prefix:prefix -> mask:mask -> bool (* Get the bit of [prefix] at position [mask] assumes that [mask] is less than the length of prefix *) val common_mask : prefix -> prefix -> mask (* The length of the common part of given prefixes *) val apply_mask : prefix -> mask -> prefix (* Cut the prefix to the given length *) val compare_prefix : mask -> prefix -> mask -> prefix -> prefix_order (* [compare_prefix m1 p1 m2 p2]: let p1' (resp p2') be the sub-prefix of length m1 of p1 (resp m2 of p2) The result is Equal if p1' equal p2' Shorter if p1' is a prefix of p2' Longer if p2' is a prefix of p1' Different if those not ordered *) end module type S = sig type key type prefix type mask type value type not_empty = TNot_empty type empty = TEmpty type _ t = private | Leaf : { mutable id: int; (* Mutable to get a good sharing semantics *) mask : mask; key : key; value : value; } -> not_empty t | Node : { mutable id : int; mask : mask; prefix : prefix; true_ : not_empty t; false_ : not_empty t; } -> not_empty t | Empty : empty t val leaf : key:key -> mask:mask -> value -> not_empty t val node : prefix:prefix -> mask:mask -> true_:not_empty t -> false_:not_empty t -> not_empty t val empty : empty t val equal : not_empty t -> not_empty t -> bool val fast_partial_equal : not_empty t -> not_empty t -> bool (* if [fast_partial_equal x y] is true, then [equal x y] is true, but if fast_partial_equal returns false, nothing can be asserted. *) val id : not_empty t -> int end end module Shared_tree : sig module Hash_consed_tree(P:Ptree_sig.Prefix)(V:Ptree_sig.Value) : Ptree_sig.S with type value = V.t and type key = P.key and type prefix = P.prefix and type mask = P.mask module Simple_tree(P:Ptree_sig.Prefix)(V:sig type t val equal : t -> t -> bool end) : Ptree_sig.S with type value = V.t and type key = P.key and type prefix = P.prefix and type mask = P.mask end = struct open Ptree_sig (* type int2 = { mutable i1 : int; mutable i2 : int } let h2 = { i1 = 0; i2 = 0 } let hash2int x1 x2 = h2.i1 <- x1; h2.i2 <- x2; Hashtbl.hash h2 *) type int3 = { mutable i1 : int; mutable i2 : int; mutable i3 : int } let h3 = { i1 = 0; i2 = 0; i3 = 0 } let hash3int x1 x2 x3 = h3.i1 <- x1; h3.i2 <- x2; h3.i3 <- x3; Hashtbl.hash h3 type int4 = { mutable i1 : int; mutable i2 : int; mutable i3 : int; mutable i4 : int } let h4 = { i1 = 0; i2 = 0; i3 = 0; i4 = 0 } let hash4int x1 x2 x3 x4 = h4.i1 <- x1; h4.i2 <- x2; h4.i3 <- x3; h4.i4 <- x4; Hashtbl.hash h4 module Hash_consed_tree(P:Prefix)(V:Value) : S with type value = V.t and type key = P.key and type prefix = P.prefix and type mask = P.mask = struct type key = P.key type mask = P.mask type prefix = P.prefix type value = V.t type not_empty = TNot_empty type empty = TEmpty type _ t = | Leaf : { mutable id: int; (* Mutable to get a good sharing semantics *) mask : mask; key : key; value : value; } -> not_empty t | Node : { mutable id : int; mask : mask; prefix : prefix; true_ : not_empty t; false_ : not_empty t; } -> not_empty t | Empty : empty t let id : not_empty t -> int = function | Leaf { id ; _ } -> id | Node { id ; _ } -> id let set_id (n : not_empty t) id = match n with | Leaf r -> r.id <- id | Node r -> r.id <- id (*let mask : not_empty t -> mask = function | Leaf { mask ; _ } -> mask | Node { mask ; _ } -> mask *) (* let prefix_table = WeakPrefixTbl.create 20 *) module Tree : Hashtbl.HashedType with type t = not_empty t = struct type nonrec t = not_empty t let equal (t1 : t) (t2 : t) = match t1, t2 with | Leaf _, Node _ | Node _, Leaf _-> false | Leaf { key = p1; value = v1; mask = m1 ; _ }, Leaf { key = p2; value = v2; mask = m2 ; _ } -> P.equal_key p1 p2 && P.equal_mask m1 m2 && V.equal v1 v2 | Node { prefix = p1; mask = m1; true_ = t1; false_ = f1 ; _ }, Node { prefix = p2; mask = m2; true_ = t2; false_ = f2 ; _ } -> (* Assumes that only the head can be unshared: this means that structural equality implies physical one on children *) P.equal_prefix p1 p2 && P.equal_mask m1 m2 && t1 == t2 && f1 == f2 let hash : t -> int = function | Leaf { key; value; mask ; _ } -> hash3int (P.hash_key key) (V.hash value) (P.hash_mask mask) | Node { mask; prefix; true_; false_ ; _ } -> hash4int (P.hash_mask mask) (P.hash_prefix prefix) (id true_) (id false_) end module WeakTreeTbl = Weak.Make(Tree) (* Or move that to a state ? *) let weak_tree_tbl = WeakTreeTbl.create 10 let next = let r = ref 0 in fun () -> incr r; !r let leaf ~key ~mask value = let l = Leaf { id = 0; key; value; mask } in match WeakTreeTbl.find_opt weak_tree_tbl l with | None -> set_id l (next ()); WeakTreeTbl.add weak_tree_tbl l; l | Some l -> l let node ~prefix ~mask ~true_ ~false_ = let l = Node { id = 0; mask; prefix; true_; false_ } in match WeakTreeTbl.find_opt weak_tree_tbl l with | None -> set_id l (next ()); WeakTreeTbl.add weak_tree_tbl l; l | Some l -> l let empty = Empty let equal (x:not_empty t) (y:not_empty t) = x == y let fast_partial_equal = equal end [@@inline] module Simple_tree(P:Ptree_sig.Prefix)(V:sig type t val equal : t -> t -> bool end) : S with type value = V.t and type key = P.key and type prefix = P.prefix and type mask = P.mask = struct type key = P.key type mask = P.mask type prefix = P.prefix type value = V.t type not_empty = TNot_empty type empty = TEmpty type _ t = | Leaf : { mutable id: int; (* Mutable to get a good sharing semantics *) mask : mask; key : key; value : value; } -> not_empty t | Node : { mutable id : int; mask : mask; prefix : prefix; true_ : not_empty t; false_ : not_empty t; } -> not_empty t | Empty : empty t let id : not_empty t -> int = function | Leaf { id ; _ } -> id | Node { id ; _ } -> id (*let set_id (n : not_empty t) id = match n with | Leaf r -> r.id <- id | Node r -> r.id <- id let mask : not_empty t -> mask = function | Leaf { mask ; _ } -> mask | Node { mask ; _ } -> mask *) let leaf ~key ~mask value = Leaf { id = 0; key; value; mask } let node ~prefix ~mask ~true_ ~false_ = Node { id = 0; mask; prefix; true_; false_ } let empty = Empty let rec equal_not_empty (x:not_empty t) (y:not_empty t) = x == y || match x, y with | Leaf l1, Leaf l2 -> P.equal_key l1.key l2.key && V.equal l1.value l2.value | Node n1, Node n2 -> P.equal_prefix n1.prefix n2.prefix && P.equal_mask n1.mask n2.mask && equal_not_empty n1.true_ n2.true_ && equal_not_empty n1.false_ n2.false_ | Node _, Leaf _ | Leaf _, Node _ -> false let equal : type a b. a t -> b t -> bool = fun x y -> match x, y with | Empty, Empty -> true | Leaf _, Leaf _ -> equal_not_empty x y | Node _, Node _ -> equal_not_empty x y | _, _ -> false let fast_partial_equal (x:not_empty t) (y:not_empty t) = x == y end [@@inline] end module type Value = sig type t val equal : t -> t -> bool val hash : t -> int end module type Bits = sig type t val lnot : t -> t val (land) : t -> t -> t val (lxor) : t -> t -> t val (lor) : t -> t -> t val (lsr) : t -> int -> t val (lsl) : t -> int -> t val pred : t -> t val less_than : t -> t -> bool val highest_bit : t -> t val equal : t -> t -> bool val hash : t -> int val zero : t val one : t val size : int end module type Size = sig val size : int end module Bits(S:Size) = struct type t = Z.t let size = S.size let higher_bit = Z.shift_left Z.one size let mask = Z.pred higher_bit let mark n = Z.logor higher_bit n let unmark n = Z.logxor higher_bit n let one = mark Z.one let zero = higher_bit let hash = Z.hash let equal = Z.equal let less_than = Z.lt let highest_bit_unmarked n = if Z.equal Z.zero n then Z.zero else Z.(Z.one lsl (Pervasives.pred (numbits n))) let highest_bit n = mark (highest_bit_unmarked (unmark n)) let lnot x = Z.logor (Z.lognot x) higher_bit let (land) = Z.logand let (lxor) a b = Z.logor (Z.logxor a b) higher_bit let (lor) = Z.logor let (lsr) a n = Z.logor (Z.shift_right_trunc (Z.logxor a higher_bit) n) higher_bit let (lsl) a n = Z.logor (Z.logand (Z.shift_left a n) mask) higher_bit let pred = Z.pred let of_z n = mark n let to_z n = unmark n end module BE_gen_prefix(Bits:Bits) : Ptree_sig.Prefix with type key = Bits.t and type prefix = Bits.t and type mask = Bits.t = struct type key = Bits.t type mask = Bits.t (* Only a single bit set *) type prefix = Bits.t let equal_key = Bits.equal let equal_mask = Bits.equal let equal_prefix = Bits.equal let hash_key x = Bits.hash x let hash_mask x = Bits.hash x let hash_prefix x = Bits.hash x open Bits let full_length_mask = Bits.one let strictly_shorter_mask (m1:mask) m2 = Bits.less_than m2 m1 let select_bit ~prefix ~mask = not (Bits.equal (prefix land mask) Bits.zero) let apply_mask prefix mask = prefix land (lnot (pred mask)) let match_prefix ~key ~prefix ~mask = equal_prefix (apply_mask key mask) prefix let common_mask p0 p1 = (Bits.highest_bit (* [@inlined] *)) (p0 lxor p1) let key_prefix x = x let prefix_key p _m = p let smaller_set_mask m1 m2 = (lnot (pred m1)) land (lnot (pred m2)) let compare_prefix m1 p1 m2 p2 = let min_mask = smaller_set_mask m1 m2 in let applied_p1 = p1 land min_mask in let applied_p2 = p2 land min_mask in if applied_p1 = applied_p2 then if m1 > m2 then Ptree_sig.Shorter else if m1 < m2 then Ptree_sig.Longer else Ptree_sig.Equal else Ptree_sig.Different end module LE_prefix : Ptree_sig.Prefix with type key = int and type prefix = int and type mask = int = struct type key = int type mask = int (* Only a single bit set *) type prefix = int let equal_key = (==) let equal_mask = (==) let equal_prefix = (==) let hash_key x = x let hash_mask x = x let hash_prefix x = x let full_length_mask = (-1) lxor ((-1) lsr 1) let strictly_shorter_mask (m1:mask) m2 = m1 < m2 let select_bit ~prefix ~mask = (prefix land mask) != 0 let apply_mask prefix mask = prefix land (mask-1) let match_prefix ~key ~prefix ~mask = (apply_mask key mask) == prefix let lowest_bit x = x land (-x) let common_mask p0 p1 = lowest_bit (p0 lxor p1) let key_prefix x = x let prefix_key p _m = p let smaller_set_mask m1 m2 = (m1-1) land (m2-1) let compare_prefix m1 p1 m2 p2 = let min_mask = smaller_set_mask m1 m2 in let applied_p1 = p1 land min_mask in let applied_p2 = p2 land min_mask in if applied_p1 = applied_p2 then if m1 < m2 then Ptree_sig.Shorter else if m1 > m2 then Ptree_sig.Longer else Ptree_sig.Equal else Ptree_sig.Different end module BE_prefix : Ptree_sig.Prefix with type key = int and type prefix = int and type mask = int = struct type key = int type mask = int (* Only a single bit set *) type prefix = int let equal_key = (==) let equal_mask = (==) let equal_prefix = (==) let hash_key x = x let hash_mask x = x let hash_prefix x = x let full_length_mask = 1 let strictly_shorter_mask (m1:mask) m2 = m1 > m2 let select_bit ~prefix ~mask = (prefix land mask) != 0 module Nativeint_infix = struct let (lor) = Nativeint.logor (*let (lsl) = Nativeint.shift_left*) let (lsr) = Nativeint.shift_right_logical (*let (asr) = Nativeint.shift_right*) let (land) = Nativeint.logand let (lnot) = Nativeint.lognot let (lxor) = Nativeint.logxor let (-) = Nativeint.sub end let apply_mask prefix mask = let open Nativeint_infix in let prefix = Nativeint.of_int prefix in let mask = Nativeint.of_int mask in Nativeint.to_int ( prefix land (lnot (mask - 1n)) ) let match_prefix ~key ~prefix ~mask = (apply_mask key mask) == prefix let highest_bit x = Nativeint_infix.( let x = x lor (x lsr 1) in let x = x lor (x lsr 2) in let x = x lor (x lsr 4) in let x = x lor (x lsr 8) in let x = x lor (x lsr 16) in let x = if Sys.word_size > 32 then x lor (x lsr 32) else x in Nativeint.to_int (x - (x lsr 1)) ) let common_mask p0 p1 = let open Nativeint_infix in let p0 = Nativeint.of_int p0 in let p1 = Nativeint.of_int p1 in highest_bit (p0 lxor p1) let key_prefix x = x let prefix_key p _m = p let smaller_set_mask m1 m2 = let open Nativeint_infix in (lnot (m1 - 1n)) land (lnot (m2 - 1n)) let compare_prefix m1 p1 m2 p2 = let open Nativeint_infix in let m1 = Nativeint.of_int m1 in let m2 = Nativeint.of_int m2 in let p1 = Nativeint.of_int p1 in let p2 = Nativeint.of_int p2 in let min_mask = smaller_set_mask m1 m2 in let applied_p1 = p1 land min_mask in let applied_p2 = p2 land min_mask in if applied_p1 = applied_p2 then if m1 > m2 then Ptree_sig.Shorter else if m1 < m2 then Ptree_sig.Longer else Ptree_sig.Equal else Ptree_sig.Different end module Make(P:Ptree_sig.Prefix)(V:Value) = struct module T = Shared_tree.Hash_consed_tree(P)(V) type t = E : 'a T.t -> t [@@ocaml.unboxed] type key = T.key type value = T.value type mask = T.mask (* let (=) = `Do_not_use_polymorphic_equality let (<=) = `Do_not_use_polymorphic_comparison let (>=) = `Do_not_use_polymorphic_comparison let (<) = `Do_not_use_polymorphic_comparison let (>) = `Do_not_use_polymorphic_comparison let compare = `Do_not_use_polymorphic_comparison *) let equal (E t1) (E t2) = match t1, t2 with | T.Empty, T.Empty -> true | T.Empty, T.Leaf _ -> false | T.Empty, T.Node _ -> false | T.Leaf _, T.Empty -> false | T.Node _, T.Empty -> false | T.Node _, T.Node _ -> T.equal t1 t2 | T.Node _, T.Leaf _ -> T.equal t1 t2 | T.Leaf _, T.Node _ -> T.equal t1 t2 | T.Leaf _, T.Leaf _ -> T.equal t1 t2 let select_key_bit k m = P.select_bit ~prefix:(P.key_prefix k) ~mask:m let matching_key k1 k2 mask = let p1 = P.apply_mask (P.key_prefix k1) mask in let p2 = P.apply_mask (P.key_prefix k2) mask in P.equal_prefix p1 p2 let rec mem : type k. key -> k T.t -> bool = fun k -> function | T.Empty -> false | T.Leaf { key; mask ; _} -> matching_key key k mask | T.Node { prefix = _; mask; true_; false_ ; _ } -> mem k (if select_key_bit k mask then true_ else false_) let rec mem_exact : type k. key -> k T.t -> bool = fun k -> function | T.Empty -> false | T.Leaf { key; mask ; _ } -> P.equal_key k key && P.equal_mask mask P.full_length_mask | T.Node { prefix = _; mask; true_; false_ ; _ } -> mem_exact k (if select_key_bit k mask then true_ else false_) let rec find_ne k (t: T.not_empty T.t) = match t with | T.Leaf { key; value; mask ; _ } -> if matching_key key k mask then Some value else None | T.Node { prefix = _; mask; true_; false_ ; _ } -> find_ne k (if select_key_bit k mask then true_ else false_) let find : type k. key -> k T.t -> value option = fun k -> function | T.Empty -> None | T.Leaf _ as t -> find_ne k t | T.Node _ as t -> find_ne k t let singleton ~key ~value ~mask = T.leaf ~key value ~mask let join ~mask p0 t0 p1 t1 = (* assumes p0 <> p1 *) let c_mask = P.common_mask p0 p1 in let mask = if P.strictly_shorter_mask c_mask mask then c_mask else mask in let prefix = P.apply_mask p1 mask in let true_, false_ = if P.select_bit ~prefix:p0 ~mask then t0, t1 else t1, t0 in T.node ~prefix ~mask ~true_ ~false_ let rebuild_ne_branch node prefix mask ~node_true ~node_false ~true_ ~false_ = if T.fast_partial_equal node_true true_ && T.fast_partial_equal node_false false_ then node else T.node ~prefix ~mask ~true_ ~false_ let rec add_ne combine ~key ~value ?(mask=P.full_length_mask) t = match t with | T.Leaf leaf -> if P.equal_key key leaf.key && P.equal_mask leaf.mask P.full_length_mask then if value == leaf.value then t else T.leaf ~key (combine value leaf.value) ~mask else if P.strictly_shorter_mask leaf.mask mask && P.match_prefix ~key ~prefix:(P.key_prefix leaf.key) ~mask:leaf.mask then (* The previous leaf shadows the new one: no modification *) t else if P.strictly_shorter_mask mask leaf.mask && P.match_prefix ~key:leaf.key ~prefix:(P.key_prefix key) ~mask then (* The new leaf shadows the previous one: replace *) T.leaf ~key (combine value leaf.value) ~mask else join ~mask (P.key_prefix key) (T.leaf ~key value ~mask) (P.key_prefix leaf.key) t | T.Node node -> if P.match_prefix ~key ~prefix:node.prefix ~mask:node.mask then let true_, false_ = if select_key_bit key node.mask then add_ne combine ~key ~value ~mask node.true_, node.false_ else node.true_, add_ne combine ~key ~value ~mask node.false_ in rebuild_ne_branch t node.prefix node.mask ~node_false:node.false_ ~node_true:node.true_ ~true_ ~false_ else join ~mask (P.key_prefix key) (T.leaf ~key value ~mask) node.prefix t let add : type k. (value -> value -> value) -> key:key -> value:value -> ?mask:P.mask -> k T.t -> T.not_empty T.t = fun combine ~key ~value ?(mask=P.full_length_mask) -> function | T.Empty -> singleton ~key ~value ~mask (* Should be merged by matcher *) | T.Leaf _ as t -> add_ne combine ~key ~value ~mask t | T.Node _ as t -> add_ne combine ~key ~value ~mask t let empty = E T.empty let rebuild_branch node prefix mask ~node_true ~node_false ~true_:(E true_) ~false_:(E false_) = match true_, false_ with | T.Empty, T.Empty -> empty | T.Empty, t -> E t | t, T.Empty -> E t | T.Leaf _ as true_, (T.Leaf _ as false_) -> E (rebuild_ne_branch node prefix mask ~node_true ~node_false ~true_ ~false_) | T.Leaf _ as true_, (T.Node _ as false_) -> E (rebuild_ne_branch node prefix mask ~node_true ~node_false ~true_ ~false_) | T.Node _ as true_, (T.Leaf _ as false_) -> E (rebuild_ne_branch node prefix mask ~node_true ~node_false ~true_ ~false_) | T.Node _ as true_, (T.Node _ as false_) -> E (rebuild_ne_branch node prefix mask ~node_true ~node_false ~true_ ~false_) let rec remove_ne : key -> T.not_empty T.t -> t = fun key t -> match t with | T.Leaf leaf -> if matching_key leaf.key key leaf.mask then E T.empty else E t | T.Node node -> if P.match_prefix ~key ~prefix:node.prefix ~mask:node.mask then let true_, false_ = if select_key_bit key node.mask then remove_ne key node.true_, E node.false_ else E node.true_, remove_ne key node.false_ in rebuild_branch t node.prefix node.mask ~node_true:node.true_ ~node_false:node.false_ ~true_ ~false_ else E t let remove key (E t) = match t with | T.Empty -> empty | T.Leaf _ as t -> remove_ne key t | T.Node _ as t -> remove_ne key t let rec remove_prefix_ne : key -> mask -> T.not_empty T.t -> t = fun key mask t -> match t with | T.Leaf leaf -> if matching_key key leaf.key mask then E T.empty else E t | T.Node node -> match P.compare_prefix mask (P.key_prefix key) node.mask node.prefix with | Different -> E t | Equal -> E T.empty | Shorter -> E T.empty | Longer -> let true_, false_ = if select_key_bit key node.mask then remove_prefix_ne key mask node.true_, E node.false_ else E node.true_, remove_prefix_ne key mask node.false_ in rebuild_branch t node.prefix node.mask ~node_true:node.true_ ~node_false:node.false_ ~true_ ~false_ let remove_prefix key mask (E t) = match t with | T.Empty -> empty | T.Leaf _ as t -> remove_prefix_ne key mask t | T.Node _ as t -> remove_prefix_ne key mask t let rec remove_ne_exact : key -> T.not_empty T.t -> t = fun key t -> match t with | T.Leaf leaf -> if P.equal_key leaf.key key && P.equal_mask leaf.mask P.full_length_mask then E T.empty else E t | T.Node node -> if P.match_prefix ~key ~prefix:node.prefix ~mask:node.mask then let true_, false_ = if select_key_bit key node.mask then remove_ne_exact key node.true_, E node.false_ else E node.true_, remove_ne_exact key node.false_ in rebuild_branch t node.prefix node.mask ~node_true:node.true_ ~node_false:node.false_ ~true_ ~false_ else E t let remove_exact key (E t) = match t with | T.Empty -> empty | T.Leaf _ as t -> remove_ne_exact key t | T.Node _ as t -> remove_ne_exact key t let rec replace_subtree_ne ~key ~id value t = match t with | T.Leaf leaf -> if leaf.id == id then T.leaf ~key:leaf.key ~mask:leaf.mask value else t | T.Node node -> if node.id == id then T.leaf ~key:(P.prefix_key node.prefix node.mask) ~mask:node.mask value else if P.match_prefix ~key ~prefix:node.prefix ~mask:node.mask then let true_, false_ = if select_key_bit key node.mask then replace_subtree_ne ~key ~id value node.true_, node.false_ else node.true_, replace_subtree_ne ~key ~id value node.false_ in rebuild_ne_branch t node.prefix node.mask ~node_true:node.true_ ~node_false:node.false_ ~true_ ~false_ else t let replace_subtree ~replaced:(E replaced) value t = let replace_subtree_aux ~key ~id value (E t) = match t with | T.Empty -> empty | T.Leaf _ as t -> E (replace_subtree_ne ~key ~id value t) | T.Node _ as t -> E (replace_subtree_ne ~key ~id value t) in match replaced with | T.Empty -> t | T.Leaf leaf -> replace_subtree_aux ~key:leaf.key ~id:leaf.id value t | T.Node node -> replace_subtree_aux ~key:(P.prefix_key node.prefix node.mask) ~id:node.id value t let rec fold_ne : (key -> mask -> value -> 'a -> 'a) -> T.not_empty T.t -> 'a -> 'a = fun f t acc -> match t with | T.Leaf {key; mask; value; _} -> f key mask value acc | T.Node node -> let acc = fold_ne f node.false_ acc in fold_ne f node.true_ acc let fold f (E t) acc = match t with | T.Empty -> acc | T.Leaf _ as t -> fold_ne f t acc | T.Node _ as t -> fold_ne f t acc module T_id = struct type t = T.not_empty T.t let hash = T.id let equal t1 t2 = T.id t1 == T.id t2 end module Map_cache = Ephemeron.K1.Make(T_id) module type Map_Reduce = sig type result val default : result val map : t -> key -> T.value -> result val reduce : t -> result -> result -> result end module Map_Reduce(M:Map_Reduce) = struct let cache : M.result Map_cache.t = Map_cache.create 10 let rec map_reduce_ne t = match Map_cache.find_opt cache t with | Some v -> v | None -> let v = match t with | T.Leaf leaf -> M.map (E t) leaf.key leaf.value | T.Node node -> let v_true = map_reduce_ne node.true_ in let v_false = map_reduce_ne node.false_ in M.reduce (E t) v_true v_false in Map_cache.add cache t v; v let run (E t) = match t with | T.Empty -> M.default | T.Leaf _ as t -> map_reduce_ne t | T.Node _ as t -> map_reduce_ne t let rec filter_ne f t = let result = map_reduce_ne t in if f result then E t else match t with | T.Leaf _ -> empty | T.Node node -> let true_ = filter_ne f node.true_ in let false_ = filter_ne f node.false_ in rebuild_branch t node.prefix node.mask ~node_true:node.true_ ~node_false:node.false_ ~true_ ~false_ let filter f (E t) = match t with | T.Empty -> empty | T.Leaf _ as t -> filter_ne f t | T.Node _ as t -> filter_ne f t end (* Packing in the existential *) let mem key (E t) = mem key t let mem_exact key (E t) = mem_exact key t let find key (E t) = find key t let singleton ~key ~value ~mask = E (singleton ~key ~value ~mask) let add combine ~key ~value ?mask (E t) = E (add combine ~key ~value ?mask t) end [@@inline] module type S = sig type key type value type mask type t val equal : t -> t -> bool val empty : t val singleton : key:key -> value:value -> mask:mask -> t val add : (value -> value -> value) -> key:key -> value:value -> ?mask:mask -> t -> t val remove : key -> t -> t val remove_exact : key -> t -> t val remove_prefix : key -> mask -> t -> t val mem : key -> t -> bool val mem_exact : key -> t -> bool val find : key -> t -> value option val replace_subtree : replaced:t -> value -> t -> t val fold : (key -> mask -> value -> 'a -> 'a) -> t -> 'a -> 'a module type Map_Reduce = sig type result val default : result val map : t -> key -> value -> result val reduce : t -> result -> result -> result end module Map_Reduce(M:Map_Reduce) : sig val run : t -> M.result val filter : (M.result -> bool) -> t -> t end end module Make_LE(V:Value) = Make(LE_prefix)(V) module Make_BE(V:Value) = Make(BE_prefix)(V) module Make_BE_gen(V:Value)(B:Bits) = Make(BE_gen_prefix(B))(V) module Make_BE_sized(V:Value)(S:Size) = Make(BE_gen_prefix(Bits(S)))(V)