@@ -74,3 +74,132 @@ def fmix(current_hash):
7474
7575 unsigned_val = fmix (hash1 ^ length )
7676 return unsigned_val
77+
78+ def hash128_x64 (key , seed ):
79+ """
80+ Pure python implementation of murmurhash3-128.
81+
82+ borrowed from: https://github.com/wc-duck/pymmh3/blob/master/pymmh3.py
83+ """
84+ key = bytearray (key , 'utf-8' )
85+
86+ def fmix (k ):
87+ k ^= k >> 33
88+ k = (k * 0xff51afd7ed558ccd ) & 0xFFFFFFFFFFFFFFFF
89+ k ^= k >> 33
90+ k = (k * 0xc4ceb9fe1a85ec53 ) & 0xFFFFFFFFFFFFFFFF
91+ k ^= k >> 33
92+ return k
93+
94+ length = len (key )
95+ nblocks = int (length / 16 )
96+
97+ h1 = seed
98+ h2 = seed
99+
100+ c1 = 0x87c37b91114253d5
101+ c2 = 0x4cf5ad432745937f
102+
103+ #body
104+ for block_start in range (0 , nblocks * 8 , 8 ):
105+ # ??? big endian?
106+ k1 = key [2 * block_start + 7 ] << 56 | \
107+ key [2 * block_start + 6 ] << 48 | \
108+ key [2 * block_start + 5 ] << 40 | \
109+ key [2 * block_start + 4 ] << 32 | \
110+ key [2 * block_start + 3 ] << 24 | \
111+ key [2 * block_start + 2 ] << 16 | \
112+ key [2 * block_start + 1 ] << 8 | \
113+ key [2 * block_start + 0 ]
114+
115+ k2 = key [2 * block_start + 15 ] << 56 | \
116+ key [2 * block_start + 14 ] << 48 | \
117+ key [2 * block_start + 13 ] << 40 | \
118+ key [2 * block_start + 12 ] << 32 | \
119+ key [2 * block_start + 11 ] << 24 | \
120+ key [2 * block_start + 10 ] << 16 | \
121+ key [2 * block_start + 9 ] << 8 | \
122+ key [2 * block_start + 8 ]
123+
124+ k1 = (c1 * k1 ) & 0xFFFFFFFFFFFFFFFF
125+ k1 = (k1 << 31 | k1 >> 33 ) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64
126+ k1 = (c2 * k1 ) & 0xFFFFFFFFFFFFFFFF
127+ h1 ^= k1
128+
129+ h1 = (h1 << 27 | h1 >> 37 ) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64
130+ h1 = (h1 + h2 ) & 0xFFFFFFFFFFFFFFFF
131+ h1 = (h1 * 5 + 0x52dce729 ) & 0xFFFFFFFFFFFFFFFF
132+
133+ k2 = (c2 * k2 ) & 0xFFFFFFFFFFFFFFFF
134+ k2 = (k2 << 33 | k2 >> 31 ) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64
135+ k2 = (c1 * k2 ) & 0xFFFFFFFFFFFFFFFF
136+ h2 ^= k2
137+
138+ h2 = (h2 << 31 | h2 >> 33 ) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64
139+ h2 = (h1 + h2 ) & 0xFFFFFFFFFFFFFFFF
140+ h2 = (h2 * 5 + 0x38495ab5 ) & 0xFFFFFFFFFFFFFFFF
141+
142+ #tail
143+ tail_index = nblocks * 16
144+ k1 = 0
145+ k2 = 0
146+ tail_size = length & 15
147+
148+ if tail_size >= 15 :
149+ k2 ^= key [tail_index + 14 ] << 48
150+ if tail_size >= 14 :
151+ k2 ^= key [tail_index + 13 ] << 40
152+ if tail_size >= 13 :
153+ k2 ^= key [tail_index + 12 ] << 32
154+ if tail_size >= 12 :
155+ k2 ^= key [tail_index + 11 ] << 24
156+ if tail_size >= 11 :
157+ k2 ^= key [tail_index + 10 ] << 16
158+ if tail_size >= 10 :
159+ k2 ^= key [tail_index + 9 ] << 8
160+ if tail_size >= 9 :
161+ k2 ^= key [tail_index + 8 ]
162+
163+ if tail_size > 8 :
164+ k2 = (k2 * c2 ) & 0xFFFFFFFFFFFFFFFF
165+ k2 = (k2 << 33 | k2 >> 31 ) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64
166+ k2 = (k2 * c1 ) & 0xFFFFFFFFFFFFFFFF
167+ h2 ^= k2
168+
169+ if tail_size >= 8 :
170+ k1 ^= key [tail_index + 7 ] << 56
171+ if tail_size >= 7 :
172+ k1 ^= key [tail_index + 6 ] << 48
173+ if tail_size >= 6 :
174+ k1 ^= key [tail_index + 5 ] << 40
175+ if tail_size >= 5 :
176+ k1 ^= key [tail_index + 4 ] << 32
177+ if tail_size >= 4 :
178+ k1 ^= key [tail_index + 3 ] << 24
179+ if tail_size >= 3 :
180+ k1 ^= key [tail_index + 2 ] << 16
181+ if tail_size >= 2 :
182+ k1 ^= key [tail_index + 1 ] << 8
183+ if tail_size >= 1 :
184+ k1 ^= key [tail_index + 0 ]
185+
186+ if tail_size > 0 :
187+ k1 = (k1 * c1 ) & 0xFFFFFFFFFFFFFFFF
188+ k1 = (k1 << 31 | k1 >> 33 ) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64
189+ k1 = (k1 * c2 ) & 0xFFFFFFFFFFFFFFFF
190+ h1 ^= k1
191+
192+ #finalization
193+ h1 ^= length
194+ h2 ^= length
195+
196+ h1 = (h1 + h2 ) & 0xFFFFFFFFFFFFFFFF
197+ h2 = (h1 + h2 ) & 0xFFFFFFFFFFFFFFFF
198+
199+ h1 = fmix (h1 )
200+ h2 = fmix (h2 )
201+
202+ h1 = (h1 + h2 ) & 0xFFFFFFFFFFFFFFFF
203+ h2 = (h1 + h2 ) & 0xFFFFFFFFFFFFFFFF
204+
205+ return [h1 , h2 ]
0 commit comments