Skip to content

Instantly share code, notes, and snippets.

@windreamer
Created October 12, 2013 13:57
Show Gist options
  • Save windreamer/6950270 to your computer and use it in GitHub Desktop.
Save windreamer/6950270 to your computer and use it in GitHub Desktop.
Portable hash in Cython
from libc.stdint cimport int64_t
cdef tuple_hash(obj):
cdef int64_t mul = 1000003, l = len(obj), value = 0x345678, v
for i in obj:
l -= 1
v = portable_hash(i)
if v == -1:
return -1
value = (value ^ v) * mul
mul += <int64_t> (82520 + l * 2)
value += 97531
if value == -1:
value = -2
return value
cdef string_hash(obj):
cdef char* s = obj
cdef char c
cdef int64_t l = len(obj), value
if l == 0:
return 0
value = s[0] << 7
for c in s:
value = (1000003 * value) ^ c
value ^= l
if value == -1:
value = -2
return value
def portable_hash(obj):
if obj is None:
return 1315925605
elif isinstance(obj, basestring):
return string_hash(obj)
elif isinstance(obj, tuple):
return tuple_hash(obj)
elif isinstance(obj, (int, long, float)):
return hash(obj)
else:
raise TypeError('unhashable by portable_hash')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment