-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmurmur3.wat
122 lines (115 loc) · 3.88 KB
/
murmur3.wat
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
(module
(import "console" "log" (func $log (param i32)))
(memory $mem (export "mem") 1)
(func $murmur3_32 (export "murmur3_32") (param $len i32) (param $seed i32) (result i32)
(local $c1 i32)
(local $c2 i32)
(local $r1 i32)
(local $r2 i32)
(local $m i32)
(local $n i32)
(local $k i32)
(local $hash i32)
(local $nblocks i32)
(local $tail i32)
(local $i i32)
(local $rem i32)
(set_local $c1 (i32.const 0xcc9e2d51))
(set_local $c2 (i32.const 0x1b873593))
(set_local $r1 (i32.const 15))
(set_local $r2 (i32.const 13))
(set_local $m (i32.const 5))
(set_local $n (i32.const 0xe6546b64))
(set_local $hash (get_local $seed))
(set_local $nblocks (i32.div_s (get_local $len)(i32.const 4))) ;; number of blocks
(set_local $tail (i32.mul (get_local $nblocks)(i32.const 4)))
(set_local $i (i32.const 0))
;; Process each full 4-byte chunk of key
(if (i32.ne (get_local $nblocks)(i32.const 0)) (then
(loop $process
;; k ← one fourByteChunk
(set_local $k (i32.load (get_local $i)))
;; k ← k × c1
(set_local $k (i32.mul (get_local $k)(get_local $c1)))
;; k ← (k ROL r1)
(set_local $k
(i32.or
(i32.shl (get_local $k)(i32.const 15))
(i32.shr_u (get_local $k)(i32.const 17))
)
)
;; k ← k × c2
(set_local $k (i32.mul (get_local $k)(get_local $c2)))
;; hash ← hash XOR k
(set_local $hash (i32.xor (get_local $hash)(get_local $k)))
;; hash ← (hash ROL r2)
(set_local $hash
(i32.or
(i32.shl (get_local $hash)(i32.const 13))
(i32.shr_u (get_local $hash)(i32.const 19))
)
)
;; hash ← hash × m + n
(set_local $hash
(i32.add
(i32.mul (get_local $hash)(get_local $m))
(get_local $n)
)
)
(set_local $i (i32.add (get_local $i)(i32.const 4)))
(br_if $process (i32.lt_s (get_local $i)(get_local $tail)))
)
))
;; k ← 0
(set_local $k (i32.const 0))
;; rem - remainder (x % 4 ~ x & 00000011 ~ x & 3)
(set_local $rem (i32.and (get_local $len)(i32.const 3)))
;; k ^= (tail[2] << 16)
(if (i32.eq (get_local $rem)(i32.const 3)) (then
(set_local $k (i32.xor
(get_local $k)
(i32.shl
(i32.load8_u (i32.add (get_local $tail)(i32.const 2)))
(i32.const 16)
)
))
))
;; k ^= (tail[1] << 8)
(if (i32.ge_s (get_local $rem)(i32.const 2)) (then
(set_local $k (i32.xor
(get_local $k)
(i32.shl
(i32.load8_u (i32.add (get_local $tail)(i32.const 1)))
(i32.const 8)
)
))
))
(if (i32.ge_s (get_local $rem)(i32.const 1)) (then
(set_local $k (i32.xor
(get_local $k)
(i32.load8_u (get_local $tail))
))
;; k ← k × c1
(set_local $k (i32.mul (get_local $k)(get_local $c1)))
;; k ← (k ROL r1)
(set_local $k
(i32.or
(i32.shl (get_local $k)(i32.const 15))
(i32.shr_u (get_local $k)(i32.const 17))
)
)
;; k ← k × c2
(set_local $k (i32.mul (get_local $k)(get_local $c2)))
;; hash ← hash XOR k
(set_local $hash (i32.xor (get_local $hash)(get_local $k)))
))
(set_local $hash (i32.xor (get_local $hash)(get_local $len)))
(set_local $hash (i32.xor (get_local $hash)(i32.shr_u (get_local $hash)(i32.const 16))))
(set_local $hash (i32.mul (get_local $hash)(i32.const 0x85ebca6b)))
(set_local $hash (i32.xor (get_local $hash)(i32.shr_u (get_local $hash)(i32.const 13))))
(set_local $hash (i32.mul (get_local $hash)(i32.const 0xc2b2ae35)))
(set_local $hash (i32.xor (get_local $hash)(i32.shr_u (get_local $hash)(i32.const 16))))
;; (call $log (get_local $hash))
(get_local $hash)
)
)