Skip to content

Commit f2b7963

Browse files
committed
regular hashmap semantics/normal add
1 parent 8f313b3 commit f2b7963

22 files changed

+952
-912
lines changed

jscomp/others/.depend

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ bs_internalBucketsType.cmj : bs_Array.cmj
2727
bs_internalSetBuckets.cmj : bs_internalBucketsType.cmj bs_Array.cmj bs.cmj
2828
bs_internalBuckets.cmj : bs_internalBucketsType.cmj bs_Array.cmj bs.cmj
2929
bs_HashMap.cmj : bs_internalBucketsType.cmj bs_internalBuckets.cmj \
30-
bs_Hash.cmj bs_Bag.cmj bs_Array.cmj bs_HashMap.cmi
30+
bs_Hash.cmj bs_Bag.cmj bs_Array.cmj bs.cmj bs_HashMap.cmi
3131
bs_HashMultiMap.cmj : bs_internalBucketsType.cmj bs_internalBuckets.cmj \
3232
bs_Hash.cmj bs_Bag.cmj bs_Array.cmj bs_HashMultiMap.cmi
3333
bs_HashSet.cmj : bs_internalSetBuckets.cmj bs_internalBucketsType.cmj \

jscomp/others/bs_Array.ml

+25-2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ let makeMatrix sx sy init =
6767
let copy a =
6868
let l = length a in if l = 0 then [||] else unsafe_sub a 0 l
6969

70+
let zip xs ys =
71+
let lenx, leny = length xs, length ys in
72+
let len = Pervasives.min lenx leny in
73+
let s = makeUninitializedUnsafe len in
74+
for i = 0 to len - 1 do
75+
unsafe_set s i (unsafe_get xs i, unsafe_get ys i)
76+
done ;
77+
s
78+
7079
let append a1 a2 =
7180
let l1 = length a1 in
7281
if l1 = 0 then copy a2
@@ -156,7 +165,7 @@ let foldRight f a x =
156165
!r
157166

158167
exception Bottom of int;;
159-
let sort cmp a =
168+
let sort a cmp =
160169
let maxson l i =
161170
let i31 = i+i+i+1 in
162171
let x = ref i31 in
@@ -206,7 +215,7 @@ let sort cmp a =
206215
;;
207216

208217
let cutoff = 5;;
209-
let stableSort cmp a =
218+
let stableSort a cmp =
210219
let merge src1ofs src1len src2 src2ofs src2len dst dstofs =
211220
let src1r = src1ofs + src1len and src2r = src2ofs + src2len in
212221
let rec loop i1 s1 i2 s2 d =
@@ -259,3 +268,17 @@ let stableSort cmp a =
259268
;;
260269

261270
let fastSort = stableSort;;
271+
272+
let sortCont xs cmp =
273+
sort xs cmp ;
274+
xs
275+
276+
let rec forAllAux arr i b len =
277+
if i = len then true
278+
else if b (unsafe_get arr i) [@bs] then
279+
forAllAux arr (i + 1) b len
280+
else false
281+
282+
let forAll arr b =
283+
let len = length arr in
284+
forAllAux arr 0 b len

jscomp/others/bs_Array.mli

+7-3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ val init : int -> (int -> 'a [@bs]) -> 'a array
6060

6161
val shuffleInPlace : 'a array -> unit
6262

63+
val zip : 'a array -> 'b array -> ('a * 'b) array
6364
val makeMatrix : int -> int -> 'a -> 'a array array
6465
(** [Array.make_matrix dimx dimy e] returns a two-dimensional array
6566
(an array of arrays) with first dimension [dimx] and
@@ -157,7 +158,7 @@ external makeFloat: int -> float array = "caml_make_float_vect"
157158
(** {6 Sorting} *)
158159

159160

160-
val sort : ('a -> 'a -> int [@bs]) -> 'a array -> unit
161+
val sort : 'a array -> ('a -> 'a -> int [@bs]) -> unit
161162
(** Sort an array in increasing order according to a comparison
162163
function. The comparison function must return 0 if its arguments
163164
compare as equal, a positive integer if the first is greater,
@@ -183,7 +184,7 @@ val sort : ('a -> 'a -> int [@bs]) -> 'a array -> unit
183184
- [cmp a.(i) a.(j)] >= 0 if and only if i >= j
184185
*)
185186

186-
val stableSort : ('a -> 'a -> int [@bs]) -> 'a array -> unit
187+
val stableSort : 'a array -> ('a -> 'a -> int [@bs]) -> unit
187188
(** Same as {!Array.sort}, but the sorting algorithm is stable (i.e.
188189
elements that compare equal are kept in their original order) and
189190
not guaranteed to run in constant heap space.
@@ -193,11 +194,13 @@ val stableSort : ('a -> 'a -> int [@bs]) -> 'a array -> unit
193194
It is usually faster than the current implementation of {!Array.sort}.
194195
*)
195196

196-
val fastSort : ('a -> 'a -> int [@bs]) -> 'a array -> unit
197+
val fastSort : 'a array -> ('a -> 'a -> int [@bs]) -> unit
197198
(** Same as {!Array.sort} or {!Array.stable_sort}, whichever is faster
198199
on typical input.
199200
*)
200201

202+
val sortCont : 'a array -> ('a -> 'a -> int [@bs]) -> 'a array
203+
val forAll : 'a array -> ('a -> bool [@bs]) -> bool
201204

202205
(**/**)
203206
(** {6 Undocumented functions} *)
@@ -206,3 +209,4 @@ val fastSort : ('a -> 'a -> int [@bs]) -> 'a array -> unit
206209

207210
external unsafe_get : 'a array -> int -> 'a = "%array_unsafe_get"
208211
external unsafe_set : 'a array -> int -> 'a -> unit = "%array_unsafe_set"
212+

jscomp/others/bs_HashMap.ml

+105-103
Original file line numberDiff line numberDiff line change
@@ -60,67 +60,81 @@ let resize ~hash h =
6060
done
6161
end
6262

63-
64-
let add0 ~hash h key value =
65-
let h_buckets = C.buckets h in
66-
let h_buckets_lenth = Array.length h_buckets in
67-
let i = (Bs_Hash.getHash hash) key [@bs] land (h_buckets_lenth - 1) in
68-
let bucket =
69-
N.bucket ~key ~value ~next:(Bs_Array.unsafe_get h_buckets i) in
70-
Bs_Array.unsafe_set h_buckets i (C.return bucket);
71-
let h_new_size = C.size h + 1 in
72-
C.sizeSet h h_new_size;
73-
if h_new_size > h_buckets_lenth lsl 1 then resize ~hash h
74-
75-
76-
let rec remove_bucket ~eq h h_buckets i key prec buckets =
77-
match C.toOpt buckets with
63+
let rec replace_in_bucket ~eq key info cell =
64+
if (Bs_Hash.getEq eq) (N.key cell) key [@bs]
65+
then
66+
begin
67+
N.keySet cell key;
68+
N.valueSet cell info;
69+
false
70+
end
71+
else
72+
match C.toOpt (N.next cell) with
73+
| None -> true
74+
| Some cell ->
75+
replace_in_bucket ~eq key info cell
76+
77+
(* if [key] already exists, replace it, otherwise add it
78+
Here we add it to the head, it could be tail
79+
*)
80+
let add0 ~hash ~eq h key value =
81+
let h_buckets = C.buckets h in
82+
let i = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
83+
let l = Array.unsafe_get h_buckets i in
84+
match C.toOpt l with
85+
| None ->
86+
Bs_Array.unsafe_set h_buckets i (C.return
87+
(N.bucket ~key ~value ~next:l));
88+
C.sizeSet h (C.size h + 1);
89+
if C.size h > Array.length (C.buckets h) lsl 1 then resize ~hash h
90+
(* do we really need resize here ? *)
91+
| Some bucket ->
92+
begin
93+
if replace_in_bucket ~eq key value bucket then begin
94+
Bs_Array.unsafe_set h_buckets i (C.return
95+
(N.bucket ~key ~value ~next:l));
96+
C.sizeSet h (C.size h + 1);
97+
if C.size h > Array.length (C.buckets h) lsl 1 then resize ~hash h
98+
(* TODO: duplicate bucklets ? *)
99+
end
100+
end
101+
102+
let rec remove_bucket ~eq h h_buckets i key prec bucket =
103+
match C.toOpt bucket with
78104
| None -> ()
79105
| Some cell ->
80106
let cell_next = N.next cell in
81107
if (Bs_Hash.getEq eq) (N.key cell) key [@bs]
82108
then
83-
begin
84-
(match C.toOpt prec with
85-
| None -> Bs_Array.unsafe_set h_buckets i cell_next
86-
| Some c -> N.nextSet c cell_next);
109+
begin
110+
N.nextSet prec cell_next ;
87111
C.sizeSet h (C.size h - 1);
88112
end
89-
else remove_bucket ~eq h h_buckets i key buckets cell_next
113+
else remove_bucket ~eq h h_buckets i key cell cell_next
90114

91115
let remove0 ~hash ~eq h key =
92116
let h_buckets = C.buckets h in
93117
let i = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
94-
remove_bucket ~eq h h_buckets i key C.emptyOpt (Bs_Array.unsafe_get h_buckets i)
95-
96-
let rec removeAllBuckets ~eq h h_buckets i key prec buckets =
97-
match C.toOpt buckets with
118+
let bucket = Bs_Array.unsafe_get h_buckets i in
119+
match C.toOpt bucket with
98120
| None -> ()
99-
| Some cell ->
100-
let cell_next = N.next cell in
101-
if (Bs_Hash.getEq eq) (N.key cell) key [@bs]
102-
then
103-
begin
104-
(match C.toOpt prec with
105-
| None -> Bs_Array.unsafe_set h_buckets i cell_next
106-
| Some c -> N.nextSet c cell_next);
107-
C.sizeSet h (C.size h - 1);
108-
end;
109-
removeAllBuckets ~eq h h_buckets i key buckets cell_next
110-
111-
let removeAll0 ~hash ~eq h key =
112-
let h_buckets = C.buckets h in
113-
let i = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
114-
removeAllBuckets ~eq h h_buckets i key C.emptyOpt (Bs_Array.unsafe_get h_buckets i)
121+
| Some cell ->
122+
if (Bs_Hash.getEq eq) (N.key cell ) key [@bs] then
123+
begin
124+
Bs_Array.unsafe_set h_buckets i (N.next cell);
125+
C.sizeSet h (C.size h - 1)
126+
end
127+
else
128+
remove_bucket ~eq h h_buckets i key cell (N.next cell)
115129

116130

117-
let rec find_rec ~eq key buckets =
131+
let rec findAux ~eq key buckets =
118132
match C.toOpt buckets with
119133
| None ->
120134
None
121135
| Some cell ->
122136
if (Bs_Hash.getEq eq) key (N.key cell) [@bs] then Some (N.value cell)
123-
else find_rec ~eq key (N.next cell)
137+
else findAux ~eq key (N.next cell)
124138

125139
let findOpt0 ~hash ~eq h key =
126140
let h_buckets = C.buckets h in
@@ -144,62 +158,24 @@ let findOpt0 ~hash ~eq h key =
144158
(N.key cell3) [@bs] then
145159
Some (N.value cell3)
146160
else
147-
find_rec ~eq key (N.next cell3)
148-
149-
150-
let findAll0 ~hash ~eq h key =
151-
let rec find_in_bucket buckets =
152-
match C.toOpt buckets with
153-
| None ->
154-
[]
155-
| Some cell ->
156-
if (Bs_Hash.getEq eq)
157-
(N.key cell) key [@bs]
158-
then (N.value cell) :: find_in_bucket (N.next cell)
159-
else find_in_bucket (N.next cell) in
160-
let h_buckets = C.buckets h in
161-
let nid = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
162-
find_in_bucket (Bs_Array.unsafe_get h_buckets nid)
161+
findAux ~eq key (N.next cell3)
162+
163+
163164

164-
let rec replace_bucket ~eq key info buckets =
165-
match C.toOpt buckets with
166-
| None ->
167-
true
168-
| Some cell ->
169-
if (Bs_Hash.getEq eq) (N.key cell) key [@bs]
170-
then
171-
begin
172-
N.keySet cell key;
173-
N.valueSet cell info;
174-
false
175-
end
176-
else
177-
replace_bucket ~eq key info (N.next cell)
178165

179-
let replace0 ~hash ~eq h key info =
180-
let h_buckets = C.buckets h in
181-
let i = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
182-
let l = Array.unsafe_get h_buckets i in
183-
if replace_bucket ~eq key info l then begin
184-
Bs_Array.unsafe_set h_buckets i (C.return
185-
(N.bucket ~key ~value:info ~next:l));
186-
C.sizeSet h (C.size h + 1);
187-
if C.size h > Array.length (C.buckets h) lsl 1 then resize ~hash h
188-
(* TODO: duplicate bucklets ? *)
189-
end
190166

191167
let rec mem_in_bucket ~eq key cell =
192-
(Bs_Hash.getEq eq)
193-
(N.key cell) key [@bs] ||
194-
(match C.toOpt (N.next cell) with
195-
| None -> false
196-
| Some nextCell ->
197-
mem_in_bucket ~eq key nextCell)
168+
(Bs_Hash.getEq eq)
169+
(N.key cell) key [@bs] ||
170+
(match C.toOpt (N.next cell) with
171+
| None -> false
172+
| Some nextCell ->
173+
mem_in_bucket ~eq key nextCell)
198174

199175
let mem0 ~hash ~eq h key =
200176
let h_buckets = C.buckets h in
201177
let nid = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
202-
let bucket = (Bs_Array.unsafe_get h_buckets nid) in
178+
let bucket = Bs_Array.unsafe_get h_buckets nid in
203179
match C.toOpt bucket with
204180
| None -> false
205181
| Some bucket ->
@@ -214,6 +190,7 @@ let iter0 = N.iter0
214190
let fold0 = N.fold0
215191
let logStats0 = N.logStats0
216192
let filterMapInplace0 = N.filterMapInplace0
193+
let toArray0 = N.toArray0
217194

218195
(* Wrapper *)
219196
let create dict initialize_size =
@@ -229,32 +206,21 @@ let logStats h = logStats0 (B.data h)
229206
let add (type a) (type b ) (type id) (h : (a,b,id) t) (key:a) (info:b) =
230207
let dict,data = B.(dict h, data h) in
231208
let module M = (val dict) in
232-
add0 ~hash:M.hash data key info
209+
add0 ~hash:M.hash ~eq:M.eq data key info
233210

234211
let remove (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
235212
let dict,data = B.(dict h, data h) in
236213
let module M = (val dict) in
237214
remove0 ~hash:M.hash ~eq:M.eq data key
238215

239-
let removeAll (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
240-
let dict,data = B.(dict h, data h) in
241-
let module M = (val dict) in
242-
removeAll0 ~hash:M.hash ~eq:M.eq data key
243216

244217
let findOpt (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
245218
let dict,data = B.(dict h, data h) in
246219
let module M = (val dict) in
247220
findOpt0 ~hash:M.hash ~eq:M.eq data key
248221

249-
let findAll (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
250-
let dict,data = B.(dict h, data h) in
251-
let module M = (val dict) in
252-
findAll0 ~hash:M.hash ~eq:M.eq data key
253222

254-
let replace (type a) (type b) (type id) (h : (a,b,id) t) (key : a) (info : b) =
255-
let dict,data = B.(dict h, data h) in
256-
let module M = (val dict) in
257-
replace0 ~hash:M.hash ~eq:M.eq data key info
223+
258224

259225
let mem (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
260226
let dict,data = B.(dict h, data h) in
@@ -263,3 +229,39 @@ let mem (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
263229

264230
let filterMapInplace h f =
265231
filterMapInplace0 (B.data h) f
232+
let toArray (type a) (type b) (type id) (h : (a,b,id) t) =
233+
toArray0 (B.data h)
234+
let ofArray0 ~hash ~eq arr =
235+
let len = Bs.Array.length arr in
236+
let v = create0 len in
237+
for i = 0 to len - 1 do
238+
let key,value = (Bs.Array.unsafe_get arr i) in
239+
add0 ~eq ~hash v key value
240+
done ;
241+
v
242+
243+
(* TOOD: optimize heuristics for resizing *)
244+
let addArray0 ~hash ~eq h arr =
245+
let len = Bs.Array.length arr in
246+
for i = 0 to len - 1 do
247+
let key,value = (Bs_Array.unsafe_get arr i) in
248+
add0 h ~eq ~hash key value
249+
done
250+
251+
let ofArray (type a) (type id)
252+
~dict:(dict:(a,id) Bs_Hash.t) arr =
253+
let module M = (val dict) in
254+
B.bag ~dict
255+
~data:M.(ofArray0 ~eq~hash arr)
256+
257+
let addArray (type a) (type b) (type id)
258+
(h : (a,b,id) t) arr =
259+
let dict,data = B.(dict h, data h) in
260+
let module M = (val dict) in
261+
M.(addArray0 ~hash ~eq data arr)
262+
263+
let keys0 = N.keys0
264+
let keys h =
265+
keys0 (B.data h)
266+
let values0 = N.values0
267+
let values h = N.values0 (B.data h)

0 commit comments

Comments
 (0)