-
Notifications
You must be signed in to change notification settings - Fork 0
/
tab.sml
57 lines (49 loc) · 1.36 KB
/
tab.sml
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
val size = 300000000
val grain = 65536
val par = ForkJoin.fork
fun for (lo, hi) (f : int -> unit) : unit =
if lo >= hi then () else (f lo; for (lo+1, hi) f)
fun parfor (lo, hi) (f : int -> unit) : unit =
if hi - lo <= grain
then for (lo, hi) f
else let
val mid = lo + (hi - lo) div 2
in
par (fn _ => parfor (lo, mid) f, fn _ => parfor (mid, hi) f);
()
end
fun tab f n =
let
val a = Unsafe.Array.alloc n
in
parfor (0, n) (fn i => Array.update (a, i, f i));
a
end
fun hash i =
let
open Word64
infix 2 >> infix 2 << infix 2 xorb infix 2 andb
val v = fromInt(i) * 0w3935559000370003845 + 0w2691343689449507681
val v = v xorb (v >> 0w21)
val v = v xorb (v << 0w37)
val v = v xorb (v >> 0w4)
val v = v * 0w4768777513237032717
val v = v xorb (v << 0w20)
val v = v xorb (v >> 0w41)
val v = v xorb (v << 0w5)
in
Word64.toInt (v andb ((0w1 << 0w31) - 0w1))
end
val t0 = Time.now ()
val r = tab hash size
val t1 = Time.now ()
val _ = print (LargeInt.toString (Time.toMilliseconds (Time.- (t1, t0))) ^ " ms\n")
val itos = Int.toString
val _ =
case Array.findi (fn (i, x) => hash i <> x) r of
NONE => print "correct\n"
| SOME (i, x) =>
print (String.concat
[ "incorrect. index ", itos i, " is ", itos x
, " but should be ", itos (hash i), "\n"
])