murmur3_64.gno
2.11 Kb · 82 lines
1package murmur3
2
3import "hash"
4
5const hashSize64 = 8
6
7type digest64 struct {
8 d1 digest32
9 d2 digest32
10}
11
12// New64 returns a new hash.Hash64 computing a 64-bit MurmurHash3
13// hash using two 32-bit hashes with different seeds.
14// It can generate 2 to the power of 64 unique 64-bit values.
15// Hash is not collision safe, so it's recommended to handle potential
16// collisions when dealing with more than 4_294_967_296 values which is
17// when probability raises.
18func New64() hash.Hash64 {
19 return &digest64{
20 d1: digest32{},
21 d2: digest32{seed: 1, h1: 1},
22 }
23}
24
25// NewWithSeed64 returns a new hash.Hash64 computing a 64-bit
26// MurmurHash3 hash. The first 32-bit hash uses seed1 and the
27// second uses seed2. The two seeds should ideally be different.
28// It can generate 2 to the power of 64 unique 64-bit values.
29// Hash is not collision safe, so it's recommended to handle potential
30// collisions when dealing with more than 4_294_967_296 values which is
31// when provability raises.
32func NewWithSeed64(seed1, seed2 uint32) hash.Hash64 {
33 return &digest64{
34 d1: digest32{seed: seed1, h1: seed1},
35 d2: digest32{seed: seed2, h1: seed2},
36 }
37}
38
39// Sum64 returns the 64-bit MurmurHash3 hash of the specified data.
40func Sum64(data []byte) uint64 {
41 return Sum64WithSeed(data, 0, 1)
42}
43
44// Sum64WithSeed returns the 64-bit MurmurHash3 hash of the specified
45// data using the given seeds.
46func Sum64WithSeed(data []byte, seed1, seed2 uint32) uint64 {
47 h := NewWithSeed64(seed1, seed2)
48 h.Write(data)
49 return h.Sum64()
50}
51
52func (digest64) BlockSize() int {
53 // Use a 32-bit hash block size because writes are
54 // done to two hash32 hashes using the same data.
55 return blockSize32
56}
57
58func (digest64) Size() int {
59 return hashSize64
60}
61
62func (d *digest64) Reset() {
63 d.d1.Reset()
64 d.d2.Reset()
65}
66
67func (d *digest64) Write(bz []byte) (int, error) {
68 d.d1.Write(bz)
69 return d.d2.Write(bz)
70}
71
72func (d digest64) Sum64() uint64 {
73 return uint64(d.d1.Sum32())<<32 | uint64(d.d2.Sum32())
74}
75
76func (d digest64) Sum(bz []byte) []byte {
77 s := d.Sum64()
78 return append(bz,
79 byte(s), byte(s>>8), byte(s>>16), byte(s>>24),
80 byte(s>>32), byte(s>>40), byte(s>>48), byte(s>>56),
81 )
82}