github.com/songzhibin97/gkit@v1.2.13/sys/xxhash3/hash128.go (about) 1 // Package xxhash3 implements https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h 2 package xxhash3 3 4 import ( 5 "github.com/songzhibin97/gkit/internal/hack" 6 "github.com/songzhibin97/gkit/internal/runtimex" 7 "math/bits" 8 "unsafe" 9 ) 10 11 // Hash128 returns the hash value of the byte slice in 128bits. 12 func Hash128(data []byte) [2]uint64 { 13 funcPointer := hashSmall 14 15 if len(data) > 16 { 16 funcPointer = hashLarge 17 } 18 return hashfunc128[funcPointer](*(*unsafe.Pointer)(unsafe.Pointer(&data)), len(data)) 19 20 } 21 22 // Hash128String returns the hash value of the string in 128bits. 23 func Hash128String(s string) [2]uint64 { 24 return Hash128(hack.StringToBytes(s)) 25 } 26 27 func xxh3HashSmall128(xinput unsafe.Pointer, l int) [2]uint64 { 28 length := uint64(l) 29 var h128Low64 uint64 30 var h128High64 uint64 31 32 if length > 8 { 33 bitflipl := xsecret_032 ^ xsecret_040 34 bitfliph := xsecret_048 ^ xsecret_056 35 inputLow := runtimex.ReadUnaligned64(xinput) 36 inputHigh := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput) + uintptr(length) - 8)) 37 m128High64, m128Low64 := bits.Mul64(inputLow^inputHigh^bitflipl, prime64_1) 38 39 m128Low64 += uint64(length-1) << 54 40 inputHigh ^= bitfliph 41 42 m128High64 += inputHigh + uint64(uint32(inputHigh))*(prime32_2-1) 43 m128Low64 ^= bits.ReverseBytes64(m128High64) 44 45 h128High64, h128Low64 = bits.Mul64(m128Low64, prime64_2) 46 h128High64 += m128High64 * prime64_2 47 48 h128Low64 = xxh3Avalanche(h128Low64) 49 h128High64 = xxh3Avalanche(h128High64) 50 51 return [2]uint64{h128High64, h128Low64} 52 } else if length >= 4 { 53 inputLow := runtimex.ReadUnaligned32(xinput) 54 inputHigh := runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xinput) + uintptr(length) - 4)) 55 input64 := inputLow + (uint64(inputHigh) << 32) 56 bitflip := xsecret_016 ^ xsecret_024 57 keyed := input64 ^ bitflip 58 59 h128High64, h128Low64 = bits.Mul64(keyed, prime64_1+(length)<<2) 60 h128High64 += h128Low64 << 1 61 h128Low64 ^= h128High64 >> 3 62 63 h128Low64 ^= h128Low64 >> 35 64 h128Low64 *= 0x9fb21c651e98df25 65 h128Low64 ^= h128Low64 >> 28 66 67 h128High64 = xxh3Avalanche(h128High64) 68 return [2]uint64{h128High64, h128Low64} 69 } else if length == 3 { 70 c12 := runtimex.ReadUnaligned16(xinput) 71 c3 := uint64(*(*uint8)(unsafe.Pointer(uintptr(xinput) + 2))) 72 h128Low64 = c12<<16 + c3 + 3<<8 73 } else if length == 2 { 74 c12 := runtimex.ReadUnaligned16(xinput) 75 h128Low64 = c12*(1<<24+1)>>8 + 2<<8 76 } else if length == 1 { 77 c1 := uint64(*(*uint8)(xinput)) 78 h128Low64 = c1*(1<<24+1<<16+1) + 1<<8 79 } else if length == 0 { 80 return [2]uint64{0x99aa06d3014798d8, 0x6001c324468d497f} 81 } 82 h128High64 = uint64(bits.RotateLeft32(bits.ReverseBytes32(uint32(h128Low64)), 13)) 83 bitflipl := uint64(xsecret32_000 ^ xsecret32_004) 84 bitfliph := uint64(xsecret32_008 ^ xsecret32_012) 85 86 h128Low64 = h128Low64 ^ bitflipl 87 h128High64 = h128High64 ^ bitfliph 88 89 h128Low64 = xxh64Avalanche(h128Low64) 90 h128High64 = xxh64Avalanche(h128High64) 91 return [2]uint64{h128High64, h128Low64} 92 } 93 94 func xxh3HashLarge128(xinput unsafe.Pointer, l int) (acc [2]uint64) { 95 length := uintptr(l) 96 97 if length <= 128 { 98 99 accHigh := uint64(0) 100 accLow := uint64(length * prime64_1) 101 102 if length > 32 { 103 if length > 64 { 104 if length > 96 { 105 accLow += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+48))^xsecret_096, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+56))^xsecret_104) 106 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-64))) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-56))) 107 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-64)))^xsecret_112, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-56)))^xsecret_120) 108 accHigh ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+48)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+56)) 109 } 110 accLow += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32))^xsecret_064, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+40))^xsecret_072) 111 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-48))) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-40))) 112 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-48)))^xsecret_080, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-40)))^xsecret_088) 113 accHigh ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+40)) 114 } 115 accLow += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16))^xsecret_032, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+3*8))^xsecret_040) 116 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-32))) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-3*8))) 117 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-32)))^xsecret_048, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-3*8)))^xsecret_056) 118 accHigh ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+3*8)) 119 } 120 121 accLow += mix(runtimex.ReadUnaligned64(xinput)^xsecret_000, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8))^xsecret_008) 122 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-16))) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-8))) 123 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-16)))^xsecret_016, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-8)))^xsecret_024) 124 accHigh ^= runtimex.ReadUnaligned64(xinput) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8)) 125 126 h128Low := accHigh + accLow 127 h128High := (accLow * prime64_1) + (accHigh * prime64_4) + uint64(length*prime64_2) 128 129 h128Low = xxh3Avalanche(h128Low) 130 h128High = -xxh3Avalanche(h128High) 131 132 return [2]uint64{h128High, h128Low} 133 } else if length <= 240 { 134 accLow64 := uint64(length * prime64_1) 135 accHigh64 := uint64(0) 136 137 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*0))^xsecret_000, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8))^xsecret_008) 138 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*0+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+24)) 139 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*0+16))^xsecret_016, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+24))^xsecret_024) 140 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*0)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8)) 141 142 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*1))^xsecret_032, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*1+8))^xsecret_040) 143 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*1+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*1+24)) 144 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*1+16))^xsecret_048, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*1+24))^xsecret_056) 145 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*1)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(32*1)+8)) 146 147 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2))^xsecret_064, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2+8))^xsecret_072) 148 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2+24)) 149 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2+16))^xsecret_080, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2+24))^xsecret_088) 150 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*2+8)) 151 152 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3))^xsecret_096, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3+8))^xsecret_104) 153 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3+24)) 154 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3+16))^xsecret_112, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3+24))^xsecret_120) 155 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*3+8)) 156 157 accLow64 = xxh3Avalanche(accLow64) 158 accHigh64 = xxh3Avalanche(accHigh64) 159 160 nbRounds := uintptr(length >> 5 << 5) 161 for i := uintptr(4 * 32); i < nbRounds; i += 32 { 162 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i+16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+i-109)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i+24))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+i-101))) 163 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i+8)) 164 165 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+i-125)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+i-117))) 166 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+i+24)) 167 } 168 169 // last 32 bytes 170 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16))^xsecret_103, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8))^xsecret_111) 171 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-32)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-24)) 172 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-32))^xsecret_119, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-24))^xsecret_127) 173 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8)) 174 175 accHigh64, accLow64 = (accLow64*prime64_1)+(accHigh64*prime64_4)+uint64(length*prime64_2), accHigh64+accLow64 176 177 accLow64 = xxh3Avalanche(accLow64) 178 accHigh64 = -xxh3Avalanche(accHigh64) 179 180 return [2]uint64{accHigh64, accLow64} 181 } 182 183 var xacc = [8]uint64{ 184 prime32_3, prime64_1, prime64_2, prime64_3, 185 prime64_4, prime32_2, prime64_5, prime32_1} 186 187 acc[1] = uint64(length * prime64_1) 188 acc[0] = uint64(^(length * prime64_2)) 189 190 accum(&xacc, xinput, xsecret, length) 191 192 // merge xacc 193 acc[1] += mix(xacc[0]^xsecret_011, xacc[1]^xsecret_019) 194 acc[1] += mix(xacc[2]^xsecret_027, xacc[3]^xsecret_035) 195 acc[1] += mix(xacc[4]^xsecret_043, xacc[5]^xsecret_051) 196 acc[1] += mix(xacc[6]^xsecret_059, xacc[7]^xsecret_067) 197 acc[1] = xxh3Avalanche(acc[1]) 198 199 acc[0] += mix(xacc[0]^xsecret_117, xacc[1]^xsecret_125) 200 acc[0] += mix(xacc[2]^xsecret_133, xacc[3]^xsecret_141) 201 acc[0] += mix(xacc[4]^xsecret_149, xacc[5]^xsecret_157) 202 acc[0] += mix(xacc[6]^xsecret_165, xacc[7]^xsecret_173) 203 acc[0] = xxh3Avalanche(acc[0]) 204 205 return acc 206 }