github.com/cilium/cilium@v1.16.2/pkg/murmur3/murmur3.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package murmur3
     5  
     6  import (
     7  	"unsafe"
     8  )
     9  
    10  // Hash128 calculates a 128 bits hash for the given data. It returns different
    11  // results when running on big-endian and little-endian machines.
    12  //
    13  // The code is intended to be as close as possible to the reference implementation
    14  // https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp.
    15  func Hash128(data []byte, seed uint32) (uint64, uint64) {
    16  	const (
    17  		c1 = uint64(0x87c37b91114253d5)
    18  		c2 = uint64(0x4cf5ad432745937f)
    19  	)
    20  
    21  	nblocks := len(data) / 16
    22  
    23  	h1 := uint64(seed)
    24  	h2 := uint64(seed)
    25  
    26  	for i := 0; i < nblocks; i++ {
    27  		tmp := (*[2]uint64)(unsafe.Pointer(&data[i*16]))
    28  		k1 := tmp[0]
    29  		k2 := tmp[1]
    30  
    31  		k1 *= c1
    32  		k1 = rotl64(k1, 31)
    33  		k1 *= c2
    34  		h1 ^= k1
    35  		h1 = rotl64(h1, 27)
    36  		h1 += h2
    37  		h1 = h1*5 + 0x52dce729
    38  		k2 *= c2
    39  		k2 = rotl64(k2, 33)
    40  		k2 *= c1
    41  		h2 ^= k2
    42  		h2 = rotl64(h2, 31)
    43  		h2 += h1
    44  		h2 = h2*5 + 0x38495ab5
    45  	}
    46  
    47  	k1 := uint64(0)
    48  	k2 := uint64(0)
    49  
    50  	tail := data[nblocks*16:]
    51  
    52  	switch len(tail) & 15 {
    53  	case 15:
    54  		k2 ^= uint64(tail[14]) << 48
    55  		fallthrough
    56  	case 14:
    57  		k2 ^= uint64(tail[13]) << 40
    58  		fallthrough
    59  	case 13:
    60  		k2 ^= uint64(tail[12]) << 32
    61  		fallthrough
    62  	case 12:
    63  		k2 ^= uint64(tail[11]) << 24
    64  		fallthrough
    65  	case 11:
    66  		k2 ^= uint64(tail[10]) << 16
    67  		fallthrough
    68  	case 10:
    69  		k2 ^= uint64(tail[9]) << 8
    70  		fallthrough
    71  	case 9:
    72  		k2 ^= uint64(tail[8]) << 0
    73  		k2 *= c2
    74  		k2 = rotl64(k2, 33)
    75  		k2 *= c1
    76  		h2 ^= k2
    77  		fallthrough
    78  	case 8:
    79  		k1 ^= uint64(tail[7]) << 56
    80  		fallthrough
    81  	case 7:
    82  		k1 ^= uint64(tail[6]) << 48
    83  		fallthrough
    84  	case 6:
    85  		k1 ^= uint64(tail[5]) << 40
    86  		fallthrough
    87  	case 5:
    88  		k1 ^= uint64(tail[4]) << 32
    89  		fallthrough
    90  	case 4:
    91  		k1 ^= uint64(tail[3]) << 24
    92  		fallthrough
    93  	case 3:
    94  		k1 ^= uint64(tail[2]) << 16
    95  		fallthrough
    96  	case 2:
    97  		k1 ^= uint64(tail[1]) << 8
    98  		fallthrough
    99  	case 1:
   100  		k1 ^= uint64(tail[0]) << 0
   101  		k1 *= c1
   102  		k1 = rotl64(k1, 31)
   103  		k1 *= c2
   104  		h1 ^= k1
   105  	}
   106  
   107  	h1 ^= uint64(len(data))
   108  	h2 ^= uint64(len(data))
   109  	h1 += h2
   110  	h2 += h1
   111  	h1 = fmix64(h1)
   112  	h2 = fmix64(h2)
   113  	h1 += h2
   114  	h2 += h1
   115  
   116  	return h1, h2
   117  }
   118  
   119  func rotl64(x uint64, r int8) uint64 {
   120  	return (x << r) | (x >> (64 - r))
   121  }
   122  
   123  func fmix64(k uint64) uint64 {
   124  	k ^= k >> 33
   125  	k *= 0xff51afd7ed558ccd
   126  	k ^= k >> 33
   127  	k *= 0xc4ceb9fe1a85ec53
   128  	k ^= k >> 33
   129  
   130  	return k
   131  }