github.com/moontrade/nogc@v0.1.7/hash/metro.go (about) 1 package hash 2 3 import "math/bits" 4 5 func Metro32(v uint32) uint32 { 6 const ( 7 k0 uint64 = 0xD6D018F5 8 k1 uint64 = 0xA2AA033B 9 k2 uint64 = 0x62992FC1 10 k3 uint64 = 0x30BC5B29 11 seed uint64 = 979532 12 ) 13 hash := (seed + k2) * k0 14 hash += uint64(v) * k3 15 hash ^= bits.RotateLeft64(hash, -26) * k1 16 hash ^= bits.RotateLeft64(hash, -28) 17 hash *= k0 18 hash ^= bits.RotateLeft64(hash, -29) 19 return uint32(hash) 20 } 21 22 func Metro64(v uint64) uint64 { 23 const ( 24 k0 uint64 = 0xD6D018F5 25 k1 uint64 = 0xA2AA033B 26 k2 uint64 = 0x62992FC1 27 k3 uint64 = 0x30BC5B29 28 seed uint64 = 979532 29 ) 30 hash := (seed + k2) * k0 31 hash += v * k3 32 hash ^= bits.RotateLeft64(hash, -26) * k1 33 hash ^= bits.RotateLeft64(hash, -28) 34 hash *= k0 35 hash ^= bits.RotateLeft64(hash, -29) 36 return hash 37 } 38 39 func Metro(buffer []byte, seed uint64) uint64 { 40 const ( 41 k0 = 0xD6D018F5 42 k1 = 0xA2AA033B 43 k2 = 0x62992FC1 44 k3 = 0x30BC5B29 45 ) 46 47 var ( 48 ptr = buffer 49 hash = (seed + k2) * k0 50 ) 51 if len(ptr) >= 32 { 52 v0, v1, v2, v3 := hash, hash, hash, hash 53 54 for len(ptr) >= 32 { 55 v0 += toUint64LE(ptr[:8]) * k0 56 v0 = bits.RotateLeft64(v0, -29) + v2 57 v1 += toUint64LE(ptr[8:16]) * k1 58 v1 = bits.RotateLeft64(v1, -29) + v3 59 v2 += toUint64LE(ptr[16:24]) * k2 60 v2 = bits.RotateLeft64(v2, -29) + v0 61 v3 += toUint64LE(ptr[24:32]) * k3 62 v3 = bits.RotateLeft64(v3, -29) + v1 63 ptr = ptr[32:] 64 } 65 66 v2 ^= bits.RotateLeft64(((v0+v3)*k0)+v1, -37) * k1 67 v3 ^= bits.RotateLeft64(((v1+v2)*k1)+v0, -37) * k0 68 v0 ^= bits.RotateLeft64(((v0+v2)*k0)+v3, -37) * k1 69 v1 ^= bits.RotateLeft64(((v1+v3)*k1)+v2, -37) * k0 70 hash += v0 ^ v1 71 } 72 if len(ptr) >= 16 { 73 v0 := hash + (toUint64LE(ptr[:8]) * k2) 74 v0 = bits.RotateLeft64(v0, -29) * k3 75 v1 := hash + (toUint64LE(ptr[8:16]) * k2) 76 v1 = bits.RotateLeft64(v1, -29) * k3 77 v0 ^= bits.RotateLeft64(v0*k0, -21) + v1 78 v1 ^= bits.RotateLeft64(v1*k3, -21) + v0 79 hash += v1 80 ptr = ptr[16:] 81 } 82 if len(ptr) >= 8 { 83 hash += toUint64LE(ptr[:8]) * k3 84 ptr = ptr[8:] 85 hash ^= bits.RotateLeft64(hash, -55) * k1 86 } 87 if len(ptr) >= 4 { 88 hash += uint64(toUint32LE(ptr[:4])) * k3 89 hash ^= bits.RotateLeft64(hash, -26) * k1 90 ptr = ptr[4:] 91 } 92 if len(ptr) >= 2 { 93 hash += uint64(toUint16LE(ptr[:2])) * k3 94 ptr = ptr[2:] 95 hash ^= bits.RotateLeft64(hash, -48) * k1 96 } 97 if len(ptr) >= 1 { 98 hash += uint64(ptr[0]) * k3 99 hash ^= bits.RotateLeft64(hash, -37) * k1 100 } 101 102 hash ^= bits.RotateLeft64(hash, -28) 103 hash *= k0 104 hash ^= bits.RotateLeft64(hash, -29) 105 106 return hash 107 }