Source file hash.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
external unbox_float
: (float[@local_opt])
-> (float#[@unboxed] [@local_opt])
@@ portable
= "%unbox_float"
external int_of_int32_u
: (int32#[@unboxed] [@local_opt])
-> int
@@ portable
= "%int_of_int32#"
external unbox_int64
: (int64[@local_opt])
-> (int64#[@unboxed] [@local_opt])
@@ portable
= "%unbox_int64"
external int64_u_of_nativeint_u
: (nativeint#[@unboxed])
-> (int64#[@unboxed] [@local_opt])
@@ portable
= "%int64#_of_nativeint#"
let fold_unit_u s #() = s
let int_of_bool_u = function
| #false -> 0
| #true -> 1
;;
external int_of_char_u : (char#[@unboxed]) -> int @@ portable = "%int_of_int8#"
[@@warning "-187"]
let code_of_char_u x = int_of_char_u x land 255
open Basement.Or_null_shim.Export
include Hash_intf
(** Builtin folding-style hash functions, abstracted over [Hash_intf.S] *)
module Folding (Hash : Hash_intf.S) :
Hash_intf.Builtin_intf
with type state = Hash.state
and type hash_value = Hash.hash_value = struct
type state = Hash.state
type hash_value = Hash.hash_value
type ('a : any) folder = state -> 'a -> state
let hash_fold_unit s () = s
let hash_fold_unit_u = fold_unit_u
let hash_fold_int = Hash.fold_int
let hash_fold_int64_u = Hash.fold_int64_u
let hash_fold_int64 s x = hash_fold_int64_u s (unbox_int64 x)
let hash_fold_float_u = Hash.fold_float_u
let hash_fold_float s x = hash_fold_float_u s (unbox_float x)
let hash_fold_string = Hash.fold_string
let as_int f s x = hash_fold_int s (f x)
let hash_fold_int32 = as_int Stdlib.Int32.to_int
let hash_fold_int32_u s x = hash_fold_int s (int_of_int32_u x)
let hash_fold_char = as_int Char.code
let hash_fold_char_u s x = hash_fold_int s (code_of_char_u x)
let hash_fold_bool =
as_int (function
| true -> 1
| false -> 0)
;;
let hash_fold_bool_u s x = hash_fold_int s (int_of_bool_u x)
let hash_fold_nativeint s x = hash_fold_int64 s (Stdlib.Int64.of_nativeint x)
let hash_fold_nativeint_u s x = hash_fold_int64_u s (int64_u_of_nativeint_u x)
let hash_fold_option hash_fold_elem s = function
| None -> hash_fold_int s 0
| Some x -> hash_fold_elem (hash_fold_int s 1) x
;;
let hash_fold_or_null hash_fold_elem s = function
| Null -> hash_fold_int s 0
| This x -> hash_fold_elem (hash_fold_int s 1) x
;;
let rec hash_fold_list_body hash_fold_elem s list =
match list with
| [] -> s
| x :: xs -> hash_fold_list_body hash_fold_elem (hash_fold_elem s x) xs
;;
let hash_fold_list hash_fold_elem s list =
let s = hash_fold_int s (List.length list) in
let s = hash_fold_list_body hash_fold_elem s list in
s
;;
let hash_fold_lazy_t hash_fold_elem s x = hash_fold_elem s (Stdlib.Lazy.force x)
let hash_fold_ref_frozen hash_fold_elem s x = hash_fold_elem s !x
let rec hash_fold_array_frozen_i hash_fold_elem s array i =
if i = Array.length array
then s
else (
let e = Array.unsafe_get array i in
hash_fold_array_frozen_i hash_fold_elem (hash_fold_elem s e) array (i + 1))
;;
let hash_fold_array_frozen hash_fold_elem s array =
hash_fold_array_frozen_i
hash_fold_elem
(hash_fold_int s (Array.length array))
array
0
;;
let hash_nativeint x =
Hash.get_hash_value (hash_fold_nativeint (Hash.reset (Hash.alloc ())) x)
;;
let hash_nativeint_u x =
Hash.get_hash_value (hash_fold_nativeint_u (Hash.reset (Hash.alloc ())) x)
;;
let hash_int64 x = Hash.get_hash_value (hash_fold_int64 (Hash.reset (Hash.alloc ())) x)
let hash_int64_u x =
Hash.get_hash_value (hash_fold_int64_u (Hash.reset (Hash.alloc ())) x)
;;
let hash_int32 x = Hash.get_hash_value (hash_fold_int32 (Hash.reset (Hash.alloc ())) x)
let hash_int32_u x =
Hash.get_hash_value (hash_fold_int32_u (Hash.reset (Hash.alloc ())) x)
;;
let hash_char x = Hash.get_hash_value (hash_fold_char (Hash.reset (Hash.alloc ())) x)
let hash_char_u x =
Hash.get_hash_value (hash_fold_char_u (Hash.reset (Hash.alloc ())) x)
;;
let hash_int x = Hash.get_hash_value (hash_fold_int (Hash.reset (Hash.alloc ())) x)
let hash_bool x = Hash.get_hash_value (hash_fold_bool (Hash.reset (Hash.alloc ())) x)
let hash_bool_u x =
Hash.get_hash_value (hash_fold_bool_u (Hash.reset (Hash.alloc ())) x)
;;
let hash_string x =
Hash.get_hash_value (hash_fold_string (Hash.reset (Hash.alloc ())) x)
;;
let hash_float x = Hash.get_hash_value (hash_fold_float (Hash.reset (Hash.alloc ())) x)
let hash_float_u x =
Hash.get_hash_value (hash_fold_float_u (Hash.reset (Hash.alloc ())) x)
;;
let hash_unit x = Hash.get_hash_value (hash_fold_unit (Hash.reset (Hash.alloc ())) x)
let hash_unit_u x =
Hash.get_hash_value (hash_fold_unit_u (Hash.reset (Hash.alloc ())) x)
;;
end
module F (Hash : Hash_intf.S) :
Hash_intf.Full
with type hash_value = Hash.hash_value
and type state = Hash.state
and type seed = Hash.seed = struct
include Hash
type ('a : any) folder = state -> 'a -> state
let create ?seed () = reset ?seed (alloc ())
let of_fold hash_fold_t t = get_hash_value (hash_fold_t (create ()) t)
module Builtin = Folding (Hash)
let run ?seed folder x =
Hash.get_hash_value (folder (Hash.reset ?seed (Hash.alloc ())) x)
;;
end
module Internalhash : sig @@ portable
include
Hash_intf.S
with type state = Base_internalhash_types.state
and type seed = Base_internalhash_types.seed
and type hash_value = Base_internalhash_types.hash_value
external fold_int64
: state
-> (int64[@unboxed])
-> state
= "Base_internalhash_fold_int64" "Base_internalhash_fold_int64_unboxed"
[@@noalloc]
external fold_int : state -> int -> state = "Base_internalhash_fold_int" [@@noalloc]
external fold_float
: state
-> (float[@unboxed])
-> state
= "Base_internalhash_fold_float" "Base_internalhash_fold_float_unboxed"
[@@noalloc]
external fold_string : state -> string -> state = "Base_internalhash_fold_string"
[@@noalloc]
external get_hash_value : state -> hash_value = "Base_internalhash_get_hash_value"
[@@noalloc]
end = struct
let description = "internalhash"
include Base_internalhash_types
let alloc () = create_seeded 0
let reset ?(seed = 0) _t = create_seeded seed
module For_tests = struct
let compare_state = Base_internalhash_types.compare_state
let state_to_string = Base_internalhash_types.state_to_string
end
end
module T = struct
include Internalhash
type ('a : any) folder = state -> 'a -> state
let create ?seed () = reset ?seed (alloc ())
let run ?seed folder x = get_hash_value (folder (reset ?seed (alloc ())) x)
let of_fold hash_fold_t t = get_hash_value (hash_fold_t (create ()) t)
module Builtin = struct
module Folding = struct
include Folding (Internalhash)
let hash_fold_string = Internalhash.fold_string
let hash_fold_float = Internalhash.fold_float
let hash_fold_int = Internalhash.fold_int
let hash_fold_int64 = Internalhash.fold_int64
end
include Folding
let hash_char = Char.code
let[@inline always] hash_int (t : int) =
let t = lnot t + (t lsl 21) in
let t = t lxor (t lsr 24) in
let t = t + (t lsl 3) + (t lsl 8) in
let t = t lxor (t lsr 14) in
let t = t + (t lsl 2) + (t lsl 4) in
let t = t lxor (t lsr 28) in
t + (t lsl 31)
;;
let hash_bool x = if x then 1 else 0
external hash_float
: (float[@unboxed])
-> int
@@ portable
= "Base_hash_double" "Base_hash_double_unboxed"
[@@noalloc]
let hash_unit () = 0
end
end
include T