Source file PatMapSharing.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
# 1 "maxtrie/PatMap.ml"
type key = int
type 'a t =
| Empty
| Node of { k: int; v: 'a; mutable l: 'a t; mutable r: 'a t }
let msb = Bit_lib.extract_msb
let lt_msb = Bit_lib.lt_msb
let check_key fn k =
if k < 0 then invalid_arg ("PatMap." ^ fn ^ ": negative key")
let empty = Empty
let is_empty = function Empty -> true | Node _ -> false
let[@inline] leaf k v = Node {k; v; l = Empty; r = Empty}
let singleton k v =
check_key "singleton" k;
leaf k v
let rec node_at k t =
match t with
| Empty -> Empty
| Node n ->
if k >= n.k then
if k = n.k then t else Empty
else
let m = msb n.k in
if k land m <> 0
then node_at (k lxor m) n.l
else node_at k n.r
let rec push k v t =
match t with
| Empty -> leaf k v
| Node n ->
let m = msb k in
if n.k land m <> 0
then Node {k; v; l = push (n.k lxor m) n.v n.l; r = n.r}
else Node {k; v; l = Empty; r = t}
let rec join k l r =
match l with
| Empty -> r
| Node n -> Node {k = msb k lor n.k; v = n.v; l = join n.k n.l n.r; r}
let[@inline] node t k v l r =
match t with
| Node n when n.v == v && n.l == l && n.r == r -> t
| _ -> Node {k; v; l; r}
let[@inline] rebuild t k o l r =
match o with
| None -> join k l r
| Some v -> node t k v l r
let[@inline] with_l t l =
match t with
| Node n when n.l != l -> Node {n with l}
| _ -> t
let[@inline] with_r t r =
match t with
| Node n when n.r != r -> Node {n with r}
| _ -> t
let rec find k = function
| Empty -> raise Not_found
| Node n ->
if k >= n.k then
if k = n.k then n.v else raise Not_found
else
let m = msb n.k in
if k land m <> 0 then find (k lxor m) n.l else find k n.r
let find k t = if k < 0 then raise Not_found else find k t
let find_opt k t =
if k < 0 then None else
match node_at k t with
| Empty -> None
| Node n -> Some n.v
let mem k t =
k >= 0 && match node_at k t with Empty -> false | Node _ -> true
let rec add k v t =
match t with
| Empty -> leaf k v
| Node n ->
if k >= n.k then
if k = n.k then
if n.v == v then t else Node {n with v}
else
push k v t
else
let m = msb n.k in
if k land m <> 0
then with_l t (add (k lxor m) v n.l)
else with_r t (add k v n.r)
let add k v t =
check_key "add" k;
add k v t
let rec remove k t =
match t with
| Empty -> t
| Node n ->
if k >= n.k then
if k = n.k then join n.k n.l n.r else t
else
let m = msb n.k in
if k land m <> 0
then with_l t (remove (k lxor m) n.l)
else with_r t (remove k n.r)
let remove k t = if k < 0 then t else remove k t
let rec update k f t =
match t with
| Empty ->
(match f None with None -> t | Some v -> leaf k v)
| Node n ->
if k >= n.k then
if k = n.k then
match f (Some n.v) with
| None -> join n.k n.l n.r
| Some v -> if v == n.v then t else Node {n with v}
else
match f None with
| None -> t
| Some v -> push k v t
else
let m = msb n.k in
if k land m <> 0
then with_l t (update (k lxor m) f n.l)
else with_r t (update k f n.r)
let update k f t =
check_key "update" k;
update k f t
let cardinal t =
let rec loop t acc =
match t with
| Empty -> acc
| Node n -> loop n.r (loop n.l (acc + 1))
in
loop t 0
let is_singleton = function
| Node {l = Empty; r = Empty; _} -> true
| _ -> false
let rec min_binding pre n =
match n with
| Empty -> assert false
| Node {r = Node _ as r; _} -> min_binding pre r
| Node {k; l = Node _ as l; _} -> min_binding (pre lor msb k) l
| Node {k; v; _} -> (pre lor k, v)
let min_binding = function
| Empty -> raise Not_found
| t -> min_binding 0 t
let min_binding_opt = function
| Empty -> None
| t -> Some (min_binding t)
let max_binding = function
| Empty -> raise Not_found
| Node n -> (n.k, n.v)
let max_binding_opt = function
| Empty -> None
| Node n -> Some (n.k, n.v)
let choose = max_binding
let choose_opt = max_binding_opt
let rec iter f pre = function
| Empty -> ()
| Node n ->
iter f pre n.r;
iter f (pre lor msb n.k) n.l;
f (pre lor n.k) n.v
let iter f t = iter f 0 t
let rec fold f pre t acc =
match t with
| Empty -> acc
| Node n ->
let acc = fold f pre n.r acc in
let acc = fold f (pre lor msb n.k) n.l acc in
f (pre lor n.k) n.v acc
let fold f t acc = fold f 0 t acc
let rec fold_right f pre t acc =
match t with
| Empty -> acc
| Node n ->
let acc = f (pre lor n.k) n.v acc in
let acc = fold_right f (pre lor msb n.k) n.l acc in
fold_right f pre n.r acc
let bindings t = fold_right (fun k v acc -> (k, v) :: acc) 0 t []
let rec for_all p pre = function
| Empty -> true
| Node n ->
for_all p pre n.r &&
for_all p (pre lor msb n.k) n.l &&
p (pre lor n.k) n.v
let for_all p t = for_all p 0 t
let rec exists p pre = function
| Empty -> false
| Node n ->
exists p pre n.r ||
exists p (pre lor msb n.k) n.l ||
p (pre lor n.k) n.v
let exists p t = exists p 0 t
exception Found
let find_first_opt p t =
let result = ref None in
(try iter (fun k v -> if p k then (result := Some (k, v); raise Found)) t
with Found -> ());
!result
let find_first p t =
match find_first_opt p t with
| None -> raise Not_found
| Some b -> b
let rec map f = function
| Empty -> Empty
| Node n ->
let r = map f n.r in
let l = map f n.l in
Node {k = n.k; v = f n.v; l; r}
let rec mapi f pre = function
| Empty -> Empty
| Node n ->
let r = mapi f pre n.r in
let l = mapi f (pre lor msb n.k) n.l in
Node {k = n.k; v = f (pre lor n.k) n.v; l; r}
let mapi f t = mapi f 0 t
let rec filter p pre t =
match t with
| Empty -> t
| Node n ->
let r = filter p pre n.r in
let l = filter p (pre lor msb n.k) n.l in
if p (pre lor n.k) n.v
then node t n.k n.v l r
else join n.k l r
let filter p t = filter p 0 t
let rec filter_map f pre = function
| Empty -> Empty
| Node n ->
let r = filter_map f pre n.r in
let l = filter_map f (pre lor msb n.k) n.l in
match f (pre lor n.k) n.v with
| None -> join n.k l r
| Some v -> Node {k = n.k; v; l; r}
let filter_map f t = filter_map f 0 t
let rec partition p pre t =
match t with
| Empty -> t, t
| Node n ->
let r1, r2 = partition p pre n.r in
let l1, l2 = partition p (pre lor msb n.k) n.l in
if p (pre lor n.k) n.v
then node t n.k n.v l1 r1, join n.k l2 r2
else join n.k l1 r1, node t n.k n.v l2 r2
let partition p t = partition p 0 t
let rec equal eq a b =
a == b ||
match a, b with
| Node a, Node b ->
a.k = b.k && eq a.v b.v && equal eq a.l b.l && equal eq a.r b.r
| _ -> false
let rec compare cmp a b =
if a == b then 0 else
match a, b with
| Empty, _ -> -1
| _, Empty -> 1
| Node a, Node b ->
let c = Int.compare a.k b.k in
if c <> 0 then c else
let c = cmp a.v b.v in
if c <> 0 then c else
let c = compare cmp a.l b.l in
if c <> 0 then c else
compare cmp a.r b.r
let[@inline] vtail s p = if p then s else Empty
let[@inline] vmax h s p mk =
if h != s then (match h with Node n -> n.k land mk | Empty -> -1)
else if p then (match s with Node n -> n.k | Empty -> -1)
else -1
let rec materialize h s p mk =
if h == s then vtail s p
else match h with
| Node n -> push (n.k land mk) n.v (materialize n.l s p mk)
| Empty -> assert false
let rec first_low m c s =
if c == s then c
else match c with
| Node n when n.k land m <> 0 -> first_low m n.l s
| _ -> c
let[@inline] joins m s p =
p && match s with Node n -> n.k land m <> 0 | Empty -> false
let[@inline] left = function Node n -> n.l | Empty -> Empty
let[@inline] right = function Node n -> n.r | Empty -> Empty
let[@inline] merge_o f sw key vx vy =
if sw then f key vy vx else f key vx vy
let rec add_with f sw pre k v t =
match t with
| Empty -> leaf k v
| Node n ->
if k >= n.k then
if k = n.k then rebuild t k (merge_o f sw (pre lor k) n.v v) n.l n.r
else push k v t
else
let m = msb n.k in
if k land m <> 0
then with_l t (add_with f sw (pre lor m) (k lxor m) v n.l)
else with_r t (add_with f sw pre k v n.r)
let rec union f pre a b =
match a, b with
| Empty, _ -> b
| _, Empty -> a
| Node na, Node nb ->
let ka = na.k and kb = nb.k in
if ka = kb then
let m = msb ka in
let l = union f (pre lor m) na.l nb.l in
let r = union f pre na.r nb.r in
rebuild b kb (f (pre lor ka) na.v nb.v) l r
else if lt_msb ka kb then
with_r b (union f pre a nb.r)
else if lt_msb kb ka then
with_r a (union f pre na.r b)
else
let m = msb ka in
let r = union f pre na.r nb.r in
if ka > kb then
let l = union_push f false (pre lor m) na.l b (kb lxor m) in
node a ka na.v l r
else
let l = union_push f true (pre lor m) nb.l a (ka lxor m) in
node b kb nb.v l r
and union_o f sw pre x y =
if sw then union f pre y x else union f pre x y
and union_push f sw pre x h k =
match h with
| Empty -> assert false
| Node nh ->
let v = nh.v and y = nh.l in
match x with
| Empty -> push k v y
| Node nx ->
let kx = nx.k in
if kx = k then
let m = msb k in
let l, r =
match y with
| Node ny when ny.k land m <> 0 ->
union_push f sw (pre lor m) nx.l y (ny.k lxor m),
union_o f sw pre nx.r ny.r
| _ ->
nx.l, union_o f sw pre nx.r y
in
rebuild x k (merge_o f sw (pre lor k) nx.v v) l r
else if lt_msb kx k then
let m = msb k in
match y with
| Node ny when ny.k land m <> 0 ->
Node {k; v; l = push (ny.k lxor m) ny.v ny.l;
r = union_o f sw pre x ny.r}
| _ ->
Node {k; v; l = Empty; r = union_o f sw pre x y}
else if lt_msb k kx then
with_r x (union_push f sw pre nx.r h k)
else
let m = msb k in
let pre' = pre lor m in
match y with
| Node ny when ny.k land m <> 0 ->
let r = union_o f sw pre nx.r ny.r in
if kx > k then
let l =
if sw then vunion f pre' h ny.l true nx.l nx.l true (m - 1)
else vunion f pre' nx.l nx.l true h ny.l true (m - 1)
in
node x kx nx.v l r
else
let l =
if sw then vunion f pre' y ny.l true x nx.l true (m - 1)
else vunion f pre' x nx.l true y ny.l true (m - 1)
in
Node {k; v; l; r}
| _ ->
let r = union_o f sw pre nx.r y in
if kx > k then
node x kx nx.v (add_with f sw pre' (k lxor m) v nx.l) r
else
Node {k; v; l = push (kx lxor m) nx.v nx.l; r}
and vunion f pre ha sa pa hb sb pb mk =
if ha == sa then
if hb == sb then union f pre (vtail sa pa) (vtail sb pb)
else match hb with
| Node nb when nb.l == sb ->
if pb then union_push f false pre (vtail sa pa) hb (nb.k land mk)
else add_with f false pre (nb.k land mk) nb.v (vtail sa pa)
| _ -> vunion_gen f pre ha sa pa hb sb pb mk
else if hb == sb then
match ha with
| Node na when na.l == sa ->
if pa then union_push f true pre (vtail sb pb) ha (na.k land mk)
else add_with f true pre (na.k land mk) na.v (vtail sb pb)
| _ -> vunion_gen f pre ha sa pa hb sb pb mk
else vunion_gen f pre ha sa pa hb sb pb mk
and vunion_gen f pre ha sa pa hb sb pb mk =
let ka = vmax ha sa pa mk and kb = vmax hb sb pb mk in
if ka < 0 then materialize hb sb pb mk
else if kb < 0 then materialize ha sa pa mk
else if lt_msb ka kb then vunion_below f pre ha sa pa hb sb pb mk kb false
else if lt_msb kb ka then vunion_below f pre hb sb pb ha sa pa mk ka true
else vunion_same f pre ha sa pa hb sb pb ka kb
and vunion_below f pre hx sx px hy sy py mk ky sw =
match hy with
| Empty -> assert false
| Node ny ->
if hy == sy then
let r =
if sw then vunion f pre ny.r ny.r true hx sx px mk
else vunion f pre hx sx px ny.r ny.r true mk
in
with_r sy r
else
let m = msb ky in
let mk = m - 1 in
let h = ny.l in
let c = first_low m h sy in
let j = c == sy && joins m sy py in
let l = materialize h (if j then left sy else c) j mk in
let r =
if c != sy then
if sw then vunion f pre c sy py hx sx px mk
else vunion f pre hx sx px c sy py mk
else
let t = if j then right sy else vtail sy py in
if sw then vunion f pre t t true hx sx px mk
else vunion f pre hx sx px t t true mk
in
Node {k = ky; v = ny.v; l; r}
and vunion_same f pre ha sa pa hb sb pb ka kb =
let k = if ka > kb then ka else kb in
let m = msb k in
let uha, usa, upa, lha, lsa, lpa =
if ka = k && ha == sa then
left sa, left sa, true, right sa, right sa, true
else
let h = if ka = k then left ha else ha in
let c = first_low m h sa in
if c != sa then h, c, false, c, sa, pa
else if joins m sa pa then h, left sa, true, right sa, right sa, true
else h, sa, false, sa, sa, pa
in
let uhb, usb, upb, lhb, lsb, lpb =
if kb = k && hb == sb then
left sb, left sb, true, right sb, right sb, true
else
let h = if kb = k then left hb else hb in
let c = first_low m h sb in
if c != sb then h, c, false, c, sb, pb
else if joins m sb pb then h, left sb, true, right sb, right sb, true
else h, sb, false, sb, sb, pb
in
let value t = match t with Node n -> n.v | Empty -> assert false in
let o =
if ka = kb then f (pre lor k) (value ha) (value hb)
else if ka = k then Some (value ha) else Some (value hb)
in
let l = vunion f (pre lor m) uha usa upa uhb usb upb (m - 1) in
let r = vunion f pre lha lsa lpa lhb lsb lpb (m - 1) in
match o with
| None -> join k l r
| Some v ->
if kb = k && hb == sb then node sb k v l r
else if ka = k && ha == sa then node sa k v l r
else Node {k; v; l; r}
let union f a b = union f 0 a b
let rec inter f pre a b =
match a, b with
| Empty, _ | _, Empty -> Empty
| Node na, Node nb ->
let ka = na.k and kb = nb.k in
if ka = kb then
let l = inter f (pre lor msb ka) na.l nb.l in
let r = inter f pre na.r nb.r in
match f (pre lor ka) na.v nb.v with
| None -> join ka l r
| Some v -> Node {k = ka; v; l; r}
else if lt_msb ka kb then inter f pre a nb.r
else if lt_msb kb ka then inter f pre na.r b
else if ka < kb then
let m = msb kb in
let l = inter f (pre lor m) na.l nb.l in
let r = inter f pre na.r nb.r in
match node_at (ka lxor m) nb.l with
| Node n ->
(match f (pre lor ka) na.v n.v with
| Some v -> Node {k = ka; v; l; r}
| None -> join ka l r)
| Empty -> join ka l r
else
let m = msb ka in
let l = inter f (pre lor m) na.l nb.l in
let r = inter f pre na.r nb.r in
match node_at (kb lxor m) na.l with
| Node n ->
(match f (pre lor kb) n.v nb.v with
| Some v -> Node {k = kb; v; l; r}
| None -> join kb l r)
| Empty -> join kb l r
let inter f a b = inter f 0 a b
let rec diff a b =
match a, b with
| Empty, _ -> a
| _, Empty -> a
| Node na, Node nb ->
let ka = na.k and kb = nb.k in
if ka = kb then
join ka (diff na.l nb.l) (diff na.r nb.r)
else if lt_msb ka kb then diff a nb.r
else if lt_msb kb ka then with_r a (diff na.r b)
else
let m = msb ka in
let r = diff na.r nb.r in
if ka > kb then
node a ka na.v (diff_push na.l b (kb lxor m)) r
else
let l = diff na.l nb.l in
match node_at (ka lxor m) nb.l with
| Node _ -> join ka l r
| Empty -> node a ka na.v l r
and diff_push x h k =
match x, h with
| Empty, _ | _, Empty -> x
| Node nx, Node nh ->
let y = nh.l in
let kx = nx.k in
let m = msb k in
if kx = k then
let l, r =
match y with
| Node ny when ny.k land m <> 0 -> diff_push nx.l y (ny.k lxor m), diff nx.r ny.r
| _ -> nx.l, diff nx.r y
in
join k l r
else if lt_msb kx k then
diff x (match y with Node ny when ny.k land m <> 0 -> ny.r | _ -> y)
else if lt_msb k kx then
with_r x (diff_push nx.r h k)
else if kx < k then
diff x y
else
match y with
| Node ny when ny.k land m <> 0 ->
let r = diff nx.r ny.r in
node x kx nx.v (vdiff nx.l h ny.l true (m - 1)) r
| _ ->
let r = diff nx.r y in
node x kx nx.v (remove (k lxor m) nx.l) r
and vdiff x hb sb pb mk =
if hb == sb then diff x (vtail sb pb) else
match x, hb with
| Empty, _ | _, Empty -> x
| Node nx, Node nh ->
if nh.l == sb then
if pb then diff_push x hb (nh.k land mk)
else remove (nh.k land mk) x
else
let kb = nh.k land mk and kx = nx.k in
if kx = kb || (not (lt_msb kx kb) && not (lt_msb kb kx) && kx > kb) then
let m = msb kx in
let h = if kx = kb then nh.l else hb in
let c = first_low m h sb in
let l, r =
if c != sb then vdiff nx.l h c false (m - 1), vdiff nx.r c sb pb (m - 1)
else if joins m sb pb then
vdiff nx.l h (left sb) true (m - 1), diff nx.r (right sb)
else
vdiff nx.l h sb false (m - 1), diff nx.r (vtail sb pb)
in
if kx = kb then join kx l r else node x kx nx.v l r
else if lt_msb kx kb then
let m = msb kb in
let c = first_low m hb sb in
if c != sb then vdiff x c sb pb (m - 1)
else if joins m sb pb then diff x (right sb)
else diff x (vtail sb pb)
else if lt_msb kb kx then
with_r x (vdiff nx.r hb sb pb mk)
else
vdiff x nh.l sb pb mk
let disjoint a b =
let rec disjoint : 'a 'b. 'a t -> 'b t -> bool = fun a b ->
match a, b with
| Empty, _ | _, Empty -> true
| Node na, Node nb ->
Obj.repr a != Obj.repr b &&
let ka = na.k and kb = nb.k in
if ka = kb then false
else if lt_msb ka kb then disjoint a nb.r
else if lt_msb kb ka then disjoint na.r b
else if ka < kb then
node_at (ka lxor msb kb) nb.l == Empty &&
disjoint na.l nb.l && disjoint na.r nb.r
else
node_at (kb lxor msb ka) na.l == Empty &&
disjoint na.l nb.l && disjoint na.r nb.r
in
disjoint a b
let rec report f side pre t =
match t with
| Empty -> ()
| Node n ->
report f side pre n.r;
report f side (pre lor msb n.k) n.l;
if side then f (pre lor n.k) (Some n.v) None
else f (pre lor n.k) None (Some n.v)
let rec vreport f side pre h s p mk =
if h == s then report f side pre (vtail s p)
else match h with
| Empty -> assert false
| Node n ->
vreport f side pre n.l s p mk;
let k = pre lor (n.k land mk) in
if side then f k (Some n.v) None else f k None (Some n.v)
let rec changes f pre a b =
if a != b then
match a, b with
| Empty, _ -> report f false pre b
| _, Empty -> report f true pre a
| Node na, Node nb ->
let ka = na.k and kb = nb.k in
if ka = kb then begin
changes f pre na.r nb.r;
changes f (pre lor msb ka) na.l nb.l;
if na.v != nb.v then f (pre lor ka) (Some na.v) (Some nb.v)
end
else if lt_msb ka kb then begin
changes f pre a nb.r;
report f false (pre lor msb kb) nb.l;
f (pre lor kb) None (Some nb.v)
end
else if lt_msb kb ka then begin
changes f pre na.r b;
report f true (pre lor msb ka) na.l;
f (pre lor ka) (Some na.v) None
end
else begin
let m = msb ka in
changes f pre na.r nb.r;
if ka > kb then begin
vchanges f (pre lor m) na.l na.l true b nb.l true (m - 1);
f (pre lor ka) (Some na.v) None
end else begin
vchanges f (pre lor m) a na.l true nb.l nb.l true (m - 1);
f (pre lor kb) None (Some nb.v)
end
end
and vchanges f pre ha sa pa hb sb pb mk =
if ha == sa && hb == sb then changes f pre (vtail sa pa) (vtail sb pb) else
let ka = vmax ha sa pa mk and kb = vmax hb sb pb mk in
if ka < 0 then vreport f false pre hb sb pb mk
else if kb < 0 then vreport f true pre ha sa pa mk
else if lt_msb ka kb then vchanges_below f pre ha sa pa hb sb pb kb false
else if lt_msb kb ka then vchanges_below f pre hb sb pb ha sa pa ka true
else vchanges_same f pre ha sa pa hb sb pb ka kb
and vchanges_below f pre hx sx px hy sy py ky sw =
let m = msb ky in
let vy = match hy with Node n -> n.v | Empty -> assert false in
let lh, ls, lp, up =
if hy == sy then
right sy, right sy, true, false
else
let c = first_low m (left hy) sy in
if c != sy then c, sy, py, true
else if joins m sy py then right sy, right sy, true, true
else sy, sy, py, true
in
if sw then vchanges f pre lh ls lp hx sx px (m - 1)
else vchanges f pre hx sx px lh ls lp (m - 1);
if not up then report f sw (pre lor m) (left sy)
else begin
let h = left hy in
let c = first_low m h sy in
let j = c == sy && joins m sy py in
vreport f sw (pre lor m) h (if j then left sy else c) j (m - 1)
end;
if sw then f (pre lor ky) (Some vy) None else f (pre lor ky) None (Some vy)
and vchanges_same f pre ha sa pa hb sb pb ka kb =
let k = if ka > kb then ka else kb in
let m = msb k in
let uha, usa, upa, lha, lsa, lpa =
if ka = k && ha == sa then
left sa, left sa, true, right sa, right sa, true
else
let h = if ka = k then left ha else ha in
let c = first_low m h sa in
if c != sa then h, c, false, c, sa, pa
else if joins m sa pa then h, left sa, true, right sa, right sa, true
else h, sa, false, sa, sa, pa
in
let uhb, usb, upb, lhb, lsb, lpb =
if kb = k && hb == sb then
left sb, left sb, true, right sb, right sb, true
else
let h = if kb = k then left hb else hb in
let c = first_low m h sb in
if c != sb then h, c, false, c, sb, pb
else if joins m sb pb then h, left sb, true, right sb, right sb, true
else h, sb, false, sb, sb, pb
in
vchanges f pre lha lsa lpa lhb lsb lpb (m - 1);
vchanges f (pre lor m) uha usa upa uhb usb upb (m - 1);
match ha, hb with
| Node na, Node nb ->
if ka = kb then (if na.v != nb.v then f (pre lor k) (Some na.v) (Some nb.v))
else if ka = k then f (pre lor k) (Some na.v) None
else f (pre lor k) None (Some nb.v)
| _ -> assert false
let changes f a b = changes f 0 a b
let rec above k t =
match t with
| Empty -> t
| Node n ->
if n.k <= k then Empty
else
let m = msb n.k in
if k land m <> 0 then
let l = above (k lxor m) n.l in
(match n.r with
| Empty when l == n.l -> t
| _ -> Node {n with l; r = Empty})
else
with_r t (above k n.r)
let rec below k t =
match t with
| Empty -> t
| Node n ->
if n.k < k then t
else if n.k = k then join k n.l n.r
else
let m = msb n.k in
if k land m <> 0
then join n.k (below (k lxor m) n.l) n.r
else below k n.r
let split k t =
if k < 0 then Empty, None, t
else below k t, find_opt k t, above k t
type 'a enum =
| End
| More of int * 'a t * 'a enum
| Binding of int * 'a * 'a enum
let rec seq_of_enum e () =
match e with
| End -> Seq.Nil
| Binding (k, v, e) -> Seq.Cons ((k, v), seq_of_enum e)
| More (_, Empty, e) -> seq_of_enum e ()
| More (pre, Node n, e) ->
seq_of_enum
(More (pre, n.r,
More (pre lor msb n.k, n.l, Binding (pre lor n.k, n.v, e)))) ()
let to_seq t = seq_of_enum (More (0, t, End))
let rec rev_seq pre t rest () =
match t with
| Empty -> rest ()
| Node n ->
Seq.Cons ((pre lor n.k, n.v),
rev_seq (pre lor msb n.k) n.l (rev_seq pre n.r rest))
let to_rev_seq t = rev_seq 0 t Seq.empty
let add_seq s t = Seq.fold_left (fun t (k, v) -> add k v t) t s
let of_seq s = add_seq s empty
let of_list l = List.fold_left (fun t (k, v) -> add k v t) empty l
let check t =
let fail fmt = Printf.ksprintf failwith ("PatMap.check: " ^^ fmt) in
let rec check t bound =
match t with
| Empty -> ()
| Node n ->
if n.k < 0 then fail "negative key %d" n.k;
if bound >= 0 && n.k >= bound then
fail "key %d is out of its bound %d" n.k bound;
let m = msb n.k in
check n.l (n.k - m);
check n.r m
in
check t (-1)
module Sharing = struct
let[@inline] keep_first (a : 'a t) (b : 'a t) = Bit_lib.share_choose a b == a
let rec equal eq a b =
a == b ||
match a, b with
| Node na, Node nb ->
na.k = nb.k && eq na.v nb.v &&
(na.l == nb.l ||
(equal eq na.l nb.l &&
(if keep_first na.l nb.l then nb.l <- na.l else na.l <- nb.l; true))) &&
(na.r == nb.r ||
(equal eq na.r nb.r &&
(if keep_first na.r nb.r then nb.r <- na.r else na.r <- nb.r; true)))
| _ -> false
let rec compare cmp a b =
if a == b then 0 else
match a, b with
| Empty, _ -> -1
| _, Empty -> 1
| Node na, Node nb ->
let c = Int.compare na.k nb.k in
if c <> 0 then c else
let c = cmp na.v nb.v in
if c <> 0 then c else
let c = if na.l == nb.l then 0 else compare cmp na.l nb.l in
if c <> 0 then c else begin
if na.l != nb.l then
(if keep_first na.l nb.l then nb.l <- na.l else na.l <- nb.l);
let c = if na.r == nb.r then 0 else compare cmp na.r nb.r in
if c = 0 && na.r != nb.r then
(if keep_first na.r nb.r then nb.r <- na.r else na.r <- nb.r);
c
end
end