Skip to content

Commit b01145a

Browse files
committed
better union/inter/diff algorithm
1 parent 2599661 commit b01145a

File tree

5 files changed

+629
-477
lines changed

5 files changed

+629
-477
lines changed

jscomp/others/bs_internalSetInt.ml

Lines changed: 93 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -35,39 +35,6 @@ let rec add (t : t) (x : elt) : t =
3535

3636

3737

38-
(* Splitting. split x s returns a triple (l, present, r) where
39-
- l is the set of elements of s that are < x
40-
- r is the set of elements of s that are > x
41-
- present is false if s contains no element equal to x,
42-
or true if s contains an element equal to x. *)
43-
44-
let rec splitAux (n : _ N.node) (x : elt) : t * bool * t =
45-
let l,v,r = N.(left n , key n, right n) in
46-
if x = v then (l, true, r)
47-
else if x < v then
48-
match N.toOpt l with
49-
| None ->
50-
N.(empty , false, return n)
51-
| Some l ->
52-
let (ll, pres, rl) = splitAux l x in
53-
ll, pres, N.join rl v r
54-
else
55-
match N.toOpt r with
56-
| None ->
57-
N.return n, false, N.empty
58-
| Some r ->
59-
let (lr, pres, rr) = splitAux r x in
60-
N.join l v lr, pres, rr
61-
62-
63-
let split (t : t) (x : elt) : t * bool * t =
64-
match N.toOpt t with
65-
None ->
66-
N.(empty, false, empty)
67-
| Some n ->
68-
splitAux n x
69-
70-
7138
let rec mem (t : t) (x : elt) =
7239
match N.toOpt t with
7340
| None -> false
@@ -98,6 +65,83 @@ let rec remove (t : t) (x : elt) : t =
9865
if rr == r then t
9966
else N.bal l v rr
10067

68+
69+
let rec compare_aux e1 e2 =
70+
match (e1, e2) with
71+
(End, End) -> 0
72+
| (End, _) -> -1
73+
| (_, End) -> 1
74+
| (More(v1, r1, e1), More(v2, r2, e2)) ->
75+
if (v1 : elt) <> v2
76+
then if v1 < v2 then -1 else 1
77+
else compare_aux (N.toEnum r1 e1) (N.toEnum r2 e2)
78+
79+
let cmp s1 s2 =
80+
compare_aux (N.toEnum s1 End) (N.toEnum s2 End)
81+
82+
let rec eqAux (e1 : enumeration) e2 =
83+
match (e1, e2) with
84+
(End, End) -> true
85+
| (End, More _) -> false
86+
| (More _, End) -> false
87+
| (More(v1, r1, e1), More(v2, r2, e2)) ->
88+
v1 = v2 &&
89+
eqAux (N.toEnum r1 e1) (N.toEnum r2 e2)
90+
91+
let eq s1 s2 =
92+
eqAux (N.toEnum s1 End) (N.toEnum s2 End)
93+
94+
let rec splitAuxNoPivot (n : _ N.node) (x : elt) : t * t =
95+
let l,v,r = N.(left n , key n, right n) in
96+
if x = v then l, r
97+
else if x < v then
98+
match N.toOpt l with
99+
| None ->
100+
N.empty , N.return n
101+
| Some l ->
102+
let ll, rl = splitAuxNoPivot l x in
103+
ll, N.join rl v r
104+
else
105+
match N.toOpt r with
106+
| None ->
107+
N.return n, N.empty
108+
| Some r ->
109+
let lr, rr = splitAuxNoPivot r x in
110+
N.join l v lr, rr
111+
112+
113+
let rec splitAuxPivot (n : _ N.node) (x : elt) pres : t * t =
114+
let l,v,r = N.(left n , key n, right n) in
115+
if x = v then begin
116+
pres := true;
117+
(l, r)
118+
end
119+
else if x < v then
120+
match N.toOpt l with
121+
| None ->
122+
N.empty, N.return n
123+
| Some l ->
124+
let ll, rl = splitAuxPivot l x pres in
125+
ll, N.join rl v r
126+
else
127+
match N.toOpt r with
128+
| None ->
129+
N.return n, N.empty
130+
| Some r ->
131+
let lr, rr = splitAuxPivot r x pres in
132+
N.join l v lr, rr
133+
134+
(* TODO: fix me, change the api to (t * t ) * bool *)
135+
let split (t : t) (x : elt) : t * bool * t =
136+
match N.toOpt t with
137+
None ->
138+
N.empty, false, N.empty
139+
| Some n ->
140+
let pres = ref false in
141+
let l,r = splitAuxPivot n x pres in
142+
l, !pres, r
143+
144+
101145
let rec union (s1 : t) (s2 : t) =
102146
match N.(toOpt s1, toOpt s2) with
103147
(None, _) -> s2
@@ -107,65 +151,43 @@ let rec union (s1 : t) (s2 : t) =
107151
if h1 >= h2 then
108152
if h2 = 1 then add s1 (N.key n2) else begin
109153
let l1, v1, r1 = N.(left n1, key n1, right n1) in
110-
let (l2, _, r2) = splitAux n2 v1 in
154+
let (l2, r2) = splitAuxNoPivot n2 v1 in
111155
N.join (union l1 l2) v1 (union r1 r2)
112156
end
113157
else
114158
if h1 = 1 then add s2 (N.key n1) else begin
115159
let l2, v2, r2 = N.(left n2 , key n2, right n2) in
116-
let (l1, _, r1) = splitAux n1 v2 in
160+
let (l1, r1) = splitAuxNoPivot n1 v2 in
117161
N.join (union l1 l2) v2 (union r1 r2)
118162
end
119163

120164
let rec inter (s1 : t) (s2 : t) =
121165
match N.(toOpt s1, toOpt s2) with
122-
(None, _) -> s1
123-
| (_, None) -> s2
166+
(None, _)
167+
| (_, None) -> N.empty
124168
| Some n1, Some n2 (* (Node(l1, v1, r1, _), t2) *) ->
125169
let l1,v1,r1 = N.(left n1, key n1, right n1) in
126-
match splitAux n2 v1 with
127-
(l2, false, r2) ->
128-
N.concat (inter l1 l2) (inter r1 r2)
129-
| (l2, true, r2) ->
130-
N.join (inter l1 l2) v1 (inter r1 r2)
170+
let pres = ref false in
171+
let l2,r2 = splitAuxPivot n2 v1 pres in
172+
let ll = inter l1 l2 in
173+
let rr = inter r1 r2 in
174+
if !pres then N.join ll v1 rr
175+
else N.concat ll rr
131176

132177
let rec diff (s1 : t) (s2 : t) =
133178
match N.(toOpt s1, toOpt s2) with
134179
| (None, _)
135180
| (_, None) -> s1
136181
| Some n1, Some n2 (* (Node(l1, v1, r1, _), t2) *) ->
137182
let l1,v1,r1 = N.(left n1, key n1, right n1) in
138-
match splitAux n2 v1 with
139-
(l2, false, r2) ->
140-
N.join (diff l1 l2) v1 (diff r1 r2)
141-
| (l2, true, r2) ->
142-
N.concat (diff l1 l2) (diff r1 r2)
183+
let pres = ref false in
184+
let l2, r2 = splitAuxPivot n2 v1 pres in
185+
let ll = diff l1 l2 in
186+
let rr = diff r1 r2 in
187+
if !pres then N.concat ll rr
188+
else N.join ll v1 rr
143189

144190

145-
let rec compare_aux e1 e2 =
146-
match (e1, e2) with
147-
(End, End) -> 0
148-
| (End, _) -> -1
149-
| (_, End) -> 1
150-
| (More(v1, r1, e1), More(v2, r2, e2)) ->
151-
if (v1 : elt) <> v2
152-
then if v1 < v2 then -1 else 1
153-
else compare_aux (N.toEnum r1 e1) (N.toEnum r2 e2)
154-
155-
let cmp s1 s2 =
156-
compare_aux (N.toEnum s1 End) (N.toEnum s2 End)
157-
158-
let rec eqAux (e1 : enumeration) e2 =
159-
match (e1, e2) with
160-
(End, End) -> true
161-
| (End, More _) -> false
162-
| (More _, End) -> false
163-
| (More(v1, r1, e1), More(v2, r2, e2)) ->
164-
v1 = v2 &&
165-
eqAux (N.toEnum r1 e1) (N.toEnum r2 e2)
166-
167-
let eq s1 s2 =
168-
eqAux (N.toEnum s1 End) (N.toEnum s2 End)
169191

170192
(* This algorithm applies to BST, it does not need to be balanced tree *)
171193
let rec subset (s1 : t) (s2 : t) =

0 commit comments

Comments
 (0)