Skip to content

Commit f6cc188

Browse files
authored
Merge pull request #7 from fxamacker/fxamacker/add-hash64uint64x2
Add Hash64Uint64x2 and rename HashString64
2 parents bc3ab78 + 47cdddb commit f6cc188

File tree

4 files changed

+37
-10
lines changed

4 files changed

+37
-10
lines changed

circlehash64.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,24 @@
1414

1515
package circlehash
1616

17+
import (
18+
"unsafe"
19+
)
20+
1721
// Hash64 returns a 64-bit digest of data.
22+
// Digest is compatible with CircleHash64f.
1823
func Hash64(b []byte, seed uint64) uint64 {
19-
return uint64(circle64f(*(*ptr)(ptr(&b)), seed, uint64(len(b))))
24+
return uint64(circle64f(*(*unsafe.Pointer)(unsafe.Pointer(&b)), seed, uint64(len(b))))
25+
}
26+
27+
// Hash64String returns a 64-bit digest of s.
28+
// Digest is compatible with Hash64.
29+
func Hash64String(s string, seed uint64) uint64 {
30+
return uint64(circle64f(*(*unsafe.Pointer)(unsafe.Pointer(&s)), seed, uint64(len(s))))
2031
}
2132

22-
// HashString64 returns a 64-bit digest of string s.
23-
func HashString64(s string, seed uint64) uint64 {
24-
return uint64(circle64f(*(*ptr)(ptr(&s)), seed, uint64(len(s))))
33+
// Hash64Uint64x2 returns a 64-bit digest of a and b.
34+
// Digest is compatible with Hash64 with byte slice of len 16.
35+
func Hash64Uint64x2(a uint64, b uint64, seed uint64) uint64 {
36+
return circle64fUint64x2(a, b, seed)
2537
}

circlehash64_test.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,18 @@ func nonUniformBytes16KiB() []byte {
302302
// countedCircleHash64 calls Hash64 and increments countCircleHash64.
303303
func countedCircleHash64(t *testing.T, data []byte, seed uint64) uint64 {
304304
digest := Hash64(data, seed)
305-
digest2 := HashString64(string(data), seed)
305+
digest2 := Hash64String(string(data), seed)
306306
if digest != digest2 {
307-
t.Errorf("Hash64() 0x%x != HashString64() 0x%x", digest, digest2)
307+
t.Errorf("Hash64() 0x%x != Hash64String() 0x%x", digest, digest2)
308+
}
309+
310+
if len(data) == 16 {
311+
a := binary.LittleEndian.Uint64(data)
312+
b := binary.LittleEndian.Uint64(data[8:])
313+
digest3 := Hash64Uint64x2(a, b, seed)
314+
if digest != digest3 {
315+
t.Errorf("Hash64() 0x%x != Hash64Uint64x2() 0x%x", digest, digest3)
316+
}
308317
}
309318

310319
collisions[digest]++

circlehash64f.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,13 @@ func circle64f(p unsafe.Pointer, seed uint64, dlen uint64) uint64 {
9696
z := pi4 ^ startingLength // wyhash reuses salt1 here, but CircleHash64 (like Go 1.17) avoids reusing it here
9797
return mix64(w, z)
9898
}
99+
100+
// circle64fUint64x2 produces a 64-bit digest from a, b, and seed.
101+
// Digest is compatible with circlehash64f with byte slice of len 16.
102+
func circle64fUint64x2(a uint64, b uint64, seed uint64) uint64 {
103+
const dataLen = uint64(16)
104+
currentState := seed ^ pi0
105+
w := mix64(a^pi1, b^currentState)
106+
z := pi4 ^ dataLen
107+
return mix64(w, z)
108+
}

utils.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ import (
1919
"unsafe"
2020
)
2121

22-
type (
23-
ptr = unsafe.Pointer
24-
)
25-
2622
func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
2723
return unsafe.Pointer(uintptr(p) + x)
2824
}

0 commit comments

Comments
 (0)