ArrRef: Remove unnecessary copy of murmur3 hash code.
This commit is contained in:
parent
e7cdd61d38
commit
0760ab745a
|
@ -131,78 +131,9 @@ when defined(isNimSkull):
|
|||
if a.len != 0:
|
||||
copyMem(result[0].addr, a.arr.addr, result.len * sizeof(T))
|
||||
|
||||
# The following is just copied straight from hashes.nim, just replacing openArray by ArrRef...
|
||||
|
||||
when defined(js):
|
||||
proc imul(a, b: uint32): uint32 =
|
||||
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
|
||||
let mask = 0xffff'u32
|
||||
var
|
||||
aHi = (a shr 16) and mask
|
||||
aLo = a and mask
|
||||
bHi = (b shr 16) and mask
|
||||
bLo = b and mask
|
||||
result = (aLo * bLo) + (aHi * bLo + aLo * bHi) shl 16
|
||||
else:
|
||||
template imul(a, b: uint32): untyped = a * b
|
||||
|
||||
proc rotl32(x: uint32, r: int): uint32 {.inline.} =
|
||||
(x shl r) or (x shr (32 - r))
|
||||
|
||||
proc hash*[T](arr: ArrRef[T]): Hash =
|
||||
# https://github.com/PeterScott/murmur3/blob/master/murmur3.c
|
||||
const
|
||||
c1 = 0xcc9e2d51'u32
|
||||
c2 = 0x1b873593'u32
|
||||
n1 = 0xe6546b64'u32
|
||||
m1 = 0x85ebca6b'u32
|
||||
m2 = 0xc2b2ae35'u32
|
||||
let
|
||||
x = arr.to byte
|
||||
size = len(x)
|
||||
stepSize = 4 # 32-bit
|
||||
n = size div stepSize
|
||||
var
|
||||
h1: uint32
|
||||
i = 0
|
||||
|
||||
# body
|
||||
while i < n * stepSize:
|
||||
var k1: uint32
|
||||
when defined(js) or defined(sparc) or defined(sparc64):
|
||||
var j = stepSize
|
||||
while j > 0:
|
||||
dec j
|
||||
k1 = (k1 shl 8) or (ord(x[i+j])).uint32
|
||||
else:
|
||||
k1 = cast[ptr uint32](unsafeAddr x[i])[]
|
||||
inc i, stepSize
|
||||
|
||||
k1 = imul(k1, c1)
|
||||
k1 = rotl32(k1, 15)
|
||||
k1 = imul(k1, c2)
|
||||
|
||||
h1 = h1 xor k1
|
||||
h1 = rotl32(h1, 13)
|
||||
h1 = h1*5 + n1
|
||||
|
||||
# tail
|
||||
var k1: uint32
|
||||
var rem = size mod stepSize
|
||||
while rem > 0:
|
||||
dec rem
|
||||
k1 = (k1 shl 8) or (ord(x[i+rem])).uint32
|
||||
k1 = imul(k1, c1)
|
||||
k1 = rotl32(k1, 15)
|
||||
k1 = imul(k1, c2)
|
||||
h1 = h1 xor k1
|
||||
|
||||
# finalization
|
||||
h1 = h1 xor size.uint32
|
||||
h1 = h1 xor (h1 shr 16)
|
||||
h1 = imul(h1, m1)
|
||||
h1 = h1 xor (h1 shr 13)
|
||||
h1 = imul(h1, m2)
|
||||
h1 = h1 xor (h1 shr 16)
|
||||
return cast[Hash](h1)
|
||||
|
||||
# Make use of stdlib's murmur3
|
||||
# NOTE: We use the size of elements in bytes instead of the actual size
|
||||
# just in case the actual size is bigger than that.
|
||||
hash(cast[ptr UncheckedArray[byte]](arr.arr.addr).toOpenArray(0, arr.len * sizeof(T) - 1))
|
||||
# TODO: for bigger elements, would a different algorithm be faster?
|
||||
|
|
Loading…
Reference in a new issue