Skip to content

Commit

Permalink
Merge pull request #7 from fxamacker/fxamacker/add-hash64uint64x2
Browse files Browse the repository at this point in the history
Add Hash64Uint64x2 and rename HashString64
  • Loading branch information
fxamacker authored Oct 26, 2021
2 parents bc3ab78 + 47cdddb commit f6cc188
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 10 deletions.
20 changes: 16 additions & 4 deletions circlehash64.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@

package circlehash

import (
"unsafe"
)

// Hash64 returns a 64-bit digest of data.
// Digest is compatible with CircleHash64f.
func Hash64(b []byte, seed uint64) uint64 {
return uint64(circle64f(*(*ptr)(ptr(&b)), seed, uint64(len(b))))
return uint64(circle64f(*(*unsafe.Pointer)(unsafe.Pointer(&b)), seed, uint64(len(b))))
}

// Hash64String returns a 64-bit digest of s.
// Digest is compatible with Hash64.
func Hash64String(s string, seed uint64) uint64 {
return uint64(circle64f(*(*unsafe.Pointer)(unsafe.Pointer(&s)), seed, uint64(len(s))))
}

// HashString64 returns a 64-bit digest of string s.
func HashString64(s string, seed uint64) uint64 {
return uint64(circle64f(*(*ptr)(ptr(&s)), seed, uint64(len(s))))
// Hash64Uint64x2 returns a 64-bit digest of a and b.
// Digest is compatible with Hash64 with byte slice of len 16.
func Hash64Uint64x2(a uint64, b uint64, seed uint64) uint64 {
return circle64fUint64x2(a, b, seed)
}
13 changes: 11 additions & 2 deletions circlehash64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,18 @@ func nonUniformBytes16KiB() []byte {
// countedCircleHash64 calls Hash64 and increments countCircleHash64.
func countedCircleHash64(t *testing.T, data []byte, seed uint64) uint64 {
digest := Hash64(data, seed)
digest2 := HashString64(string(data), seed)
digest2 := Hash64String(string(data), seed)
if digest != digest2 {
t.Errorf("Hash64() 0x%x != HashString64() 0x%x", digest, digest2)
t.Errorf("Hash64() 0x%x != Hash64String() 0x%x", digest, digest2)
}

if len(data) == 16 {
a := binary.LittleEndian.Uint64(data)
b := binary.LittleEndian.Uint64(data[8:])
digest3 := Hash64Uint64x2(a, b, seed)
if digest != digest3 {
t.Errorf("Hash64() 0x%x != Hash64Uint64x2() 0x%x", digest, digest3)
}
}

collisions[digest]++
Expand Down
10 changes: 10 additions & 0 deletions circlehash64f.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,13 @@ func circle64f(p unsafe.Pointer, seed uint64, dlen uint64) uint64 {
z := pi4 ^ startingLength // wyhash reuses salt1 here, but CircleHash64 (like Go 1.17) avoids reusing it here
return mix64(w, z)
}

// circle64fUint64x2 produces a 64-bit digest from a, b, and seed.
// Digest is compatible with circlehash64f with byte slice of len 16.
func circle64fUint64x2(a uint64, b uint64, seed uint64) uint64 {
const dataLen = uint64(16)
currentState := seed ^ pi0
w := mix64(a^pi1, b^currentState)
z := pi4 ^ dataLen
return mix64(w, z)
}
4 changes: 0 additions & 4 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ import (
"unsafe"
)

type (
ptr = unsafe.Pointer
)

func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
return unsafe.Pointer(uintptr(p) + x)
}
Expand Down

0 comments on commit f6cc188

Please sign in to comment.