@@ -21,6 +21,9 @@ open! Int_replace_polymorphic_compare
2121
2222(* The following is a "little endian" implementation. *)
2323
24+ (* CR mshinwell: Can we fix the traversal order by swapping endianness?
25+ What other (dis)advantages might that have? *)
26+
2427let zero_bit i bit =
2528 i land bit = 0
2629
@@ -924,12 +927,31 @@ struct
924927 let bindings s =
925928 List. sort (fun (id1 , _ ) (id2 , _ ) -> Int. compare id1 id2)
926929 (bindings_aux [] s)
927- (*
928- (* XXX still wrong *)
929- let rec merge' f t0 t1 =
930+
931+ let rec merge ' : type a b c .
932+ (key -> a option -> b option -> c option )
933+ -> a t -> b t -> c t
934+ = fun f t0 t1 ->
930935 match t0, t1 with
931- | Empty, _ -> t1
932- | _, Empty -> t0
936+ (* Empty cases, just recurse and be sure to call f on all
937+ leaf cases recursively *)
938+ | Empty , Empty -> Empty
939+ | Empty , Leaf (i , d ) ->
940+ begin match f i None (Some d) with
941+ | None -> Empty
942+ | Some d' -> Leaf (i, d')
943+ end
944+ | Leaf (i , d ), Empty ->
945+ begin match f i (Some d) None with
946+ | None -> Empty
947+ | Some d' -> Leaf (i, d')
948+ end
949+ | Empty , Branch (prefix , bit , t10 , t11 ) ->
950+ Branch (prefix, bit, merge' f t0 t10, merge' f t0 t11)
951+ | Branch (prefix , bit , t00 , t01 ), Empty ->
952+ Branch (prefix, bit, merge' f t00 t1, merge' f t01 t1)
953+
954+ (* Leaf cases *)
933955 | Leaf (i , d0 ), Leaf (j , d1 ) when i = j ->
934956 begin match f i (Some d0) (Some d1) with
935957 | None -> Empty
@@ -942,45 +964,46 @@ struct
942964 | None , Some d1 -> Leaf (j, d1)
943965 | Some d0 , Some d1 -> join i (Leaf (i, d0)) j (Leaf (j, d1))
944966 end
967+
968+ (* leaf <-> Branch cases *)
945969 | Leaf (i , d ), Branch (prefix , bit , t10 , t11 ) ->
946970 if match_prefix i prefix bit then
947971 if zero_bit i bit then
948- branch prefix bit (merge' f t0 t10) t11
972+ branch prefix bit (merge' f t0 t10) (merge' f Empty t11)
949973 else
950- branch prefix bit t10 (merge' f t0 t11)
974+ branch prefix bit (merge' f Empty t10) (merge' f t0 t11)
951975 else
952976 begin match f i (Some d) None with
953- | None -> t1
954- | Some d -> join i (Leaf(i, d)) prefix t1
977+ | None -> merge' f Empty t1
978+ | Some d -> join i (Leaf (i, d)) prefix (merge' f Empty t1)
955979 end
956980 | Branch (prefix , bit , t00 , t01 ), Leaf (i , d ) ->
957981 if match_prefix i prefix bit then
958982 let f i d0 d1 = f i d1 d0 in (* CR mshinwell: add flag to disable? *)
959983 if zero_bit i bit then
960- branch prefix bit (merge' f t1 t00) t01
984+ branch prefix bit (merge' f t1 t00) (merge' f Empty t01)
961985 else
962- branch prefix bit t00 (merge' f t1 t01)
986+ branch prefix bit (merge' f Empty t00) (merge' f t1 t01)
963987 else
964988 begin match f i None (Some d) with
965- | None -> t0
966- | Some d -> join i (Leaf(i, d)) prefix t0
989+ | None -> merge' f t0 Empty
990+ | Some d -> join i (Leaf (i, d)) prefix (merge' f t0 Empty )
967991 end
968992 | Branch (prefix0 , bit0 , t00 , t01 ), Branch (prefix1 , bit1 , t10 , t11 ) ->
969993 if equal_prefix prefix0 bit0 prefix1 bit1 then
970994 branch prefix0 bit0 (merge' f t00 t10) (merge' f t01 t11)
971995 else if includes_prefix prefix0 bit0 prefix1 bit1 then
972996 if zero_bit prefix1 bit0 then
973- branch prefix0 bit0 (merge' f t00 t1) t01
997+ branch prefix0 bit0 (merge' f t00 t1) (merge' f t01 Empty )
974998 else
975- branch prefix0 bit0 t00 (merge' f t01 t1)
999+ branch prefix0 bit0 (merge' f t00 Empty ) (merge' f t01 t1)
9761000 else if includes_prefix prefix1 bit1 prefix0 bit0 then
9771001 if zero_bit prefix0 bit1 then
978- branch prefix1 bit1 (merge' f t0 t10) t11
1002+ branch prefix1 bit1 (merge' f t0 t10) (merge' f Empty t11)
9791003 else
980- branch prefix1 bit1 t10 (merge' f t0 t11)
1004+ branch prefix1 bit1 (merge' f Empty t10) (merge' f t0 t11)
9811005 else
982- join prefix0 t0 prefix1 t1
983- *)
1006+ join prefix0 (merge' f t0 Empty ) prefix1 (merge' f Empty t1)
9841007
9851008 let find_opt t key =
9861009 match find t key with
@@ -1036,41 +1059,10 @@ struct
10361059 | Some r -> add id r map)
10371060 t empty
10381061
1039- let to_list t =
1040- let rec to_list ' t acc =
1041- match t with
1042- | Empty -> acc
1043- | Leaf (id , v ) -> (id, v) :: acc
1044- | Branch (_ , _ , t0 , t1 ) -> to_list' t0 (to_list' t1 acc)
1045- in
1046- List. sort (fun (id1 , _ ) (id2 , _ ) -> Int. compare id1 id2)
1047- (to_list' t [] )
1048-
10491062 let of_list l =
10501063 List. fold_left (fun map (id , v ) -> add id v map) empty l
10511064
1052- let merge f t0 t1 =
1053- let l1 = to_list t0 in
1054- let l2 = to_list t1 in
1055- let rec loop l1 l2 acc =
1056- let accum id a b =
1057- match f id a b with
1058- | None -> acc
1059- | Some v -> add id v acc
1060- in
1061- match l1, l2 with
1062- | [] , [] -> acc
1063- | (id , h1 ) :: t1 , [] -> loop t1 [] (accum id (Some h1) None )
1064- | [] , (id , h2 ) :: t2 -> loop [] t2 (accum id None (Some h2))
1065- | (id1 , h1 ) :: t1 , (id2 , h2 ) :: t2 ->
1066- if id1 = id2 then
1067- loop t1 t2 (accum id1 (Some h1) (Some h2))
1068- else if id1 < id2 then
1069- loop t1 l2 (accum id1 (Some h1) None )
1070- else
1071- loop l1 t2 (accum id2 None (Some h2))
1072- in
1073- loop l1 l2 Empty
1065+ let merge f t0 t1 = merge' f t0 t1
10741066
10751067 (* CR mshinwell: fix this *)
10761068 let disjoint_union ?eq ?print t1 t2 =
0 commit comments