github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/utils/hash/murmurhash3.go (about)

     1  package hash
     2  
     3  import (
     4  	"encoding/binary"
     5  	"unsafe"
     6  )
     7  
     8  func Murmurhash3Onx8632(key []byte, seed uint32) uint32 {
     9  	const (
    10  		ChunkSize = 4
    11  		C1        = 0xcc9e2d51
    12  		C2        = 0x1b872593
    13  		R1        = 15
    14  		R2        = 13
    15  		M         = 5
    16  		N         = 0xe6546b64
    17  	)
    18  	hash := seed
    19  	keyLen := len(key)
    20  	nBlock := keyLen / ChunkSize
    21  	for i := 0; i < nBlock; i++ {
    22  		k := binary.LittleEndian.Uint32(key[i*ChunkSize : i*ChunkSize+ChunkSize])
    23  		k = k * C1
    24  		k = (k << R1) | (k >> (32 - R1))
    25  		k = k * C2
    26  
    27  		hash = hash ^ k
    28  		hash = (hash << R2) | (hash >> (32 - R2))
    29  		hash = hash*M + N
    30  	}
    31  	if nBlock*ChunkSize == keyLen {
    32  		return hash
    33  	}
    34  	tail := (*[3]byte)(unsafe.Pointer(&key[nBlock*ChunkSize]))
    35  	var k1 uint32
    36  	switch keyLen & 3 {
    37  	case 3:
    38  		k1 ^= uint32(tail[2]) << 16
    39  	case 2:
    40  		k1 ^= uint32(tail[1]) << 8
    41  	case 1:
    42  		k1 ^= uint32(tail[0])
    43  		k1 *= C1
    44  		k1 = (hash << R1) | (hash >> (32 - R1))
    45  		k1 *= C2
    46  		hash ^= k1
    47  	}
    48  	hash = hash ^ uint32(keyLen)
    49  	hash = hash ^ (hash >> 16)
    50  	hash = hash * 0x85ebca6b
    51  	hash = hash ^ (hash >> 13)
    52  	hash = hash * 0xc2b2ae35
    53  	hash = hash ^ (hash >> 16)
    54  	return hash
    55  }
    56  
    57  func Murmurhash3Onx8632OnInt(key int64, seed uint32) uint32 {
    58  	keyArray := *(*[8]byte)(unsafe.Pointer(&key))
    59  	return Murmurhash3Onx8632(keyArray[:], seed)
    60  }
    61  
    62  func Murmurhash3Onx8632OnUint(key uint64, seed uint32) uint32 {
    63  	return Murmurhash3Onx8632OnInt(int64(key), seed)
    64  }