github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/sys/xxhash3/internal/xxh3_raw/xxh3_raw.go (about) 1 package xxh3_raw 2 3 import ( 4 "math/bits" 5 "unsafe" 6 7 "github.com/songzhibin97/go-baseutils/internal/runtimex" 8 ) 9 10 const ( 11 _stripe = 64 12 _block = 1024 13 14 prime32_1 = 2654435761 15 prime32_2 = 2246822519 16 prime32_3 = 3266489917 17 18 prime64_1 = 11400714785074694791 19 prime64_2 = 14029467366897019727 20 prime64_3 = 1609587929392839161 21 prime64_4 = 9650029242287828579 22 prime64_5 = 2870177450012600261 23 ) 24 25 var xsecret = unsafe.Pointer(&[192]uint8{ 26 /* 0 */ 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, 27 /* 16 */ 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, 28 /* 32 */ 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, 29 /* 48 */ 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, 30 /* 64 */ 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, 31 /* 80 */ 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, 32 /* 96 */ 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, 33 /* 112 */ 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, 34 /* 128 */ 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, 35 /* 144 */ 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, 36 /* 160 */ 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, 37 /* 176 */ 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, 38 }) 39 40 // Hash returns the hash value of the byte slice in 64bits. 41 func Hash(data []byte) uint64 { 42 length := uint64(len(data)) 43 xinput := *(*unsafe.Pointer)(unsafe.Pointer(&data)) 44 45 if length > 240 { 46 return hashLarge(xinput, length) 47 } else if length > 128 { 48 return xxh3Len129To240_64b(xinput, length) 49 } else if length > 16 { 50 return xxh3Len17To128_64b(xinput, length) 51 } else { 52 return xxh3Len0To16_64b(xinput, length) 53 } 54 } 55 56 // HashString returns the hash value of the string in 64bits. 57 func HashString(s string) uint64 { 58 return Hash([]byte(s)) 59 } 60 61 // Hash128 returns the hash value of the byte slice in 128bits. 62 func Hash128(data []byte) [2]uint64 { 63 length := uint64(len(data)) 64 xinput := *(*unsafe.Pointer)(unsafe.Pointer(&data)) 65 66 if length > 240 { 67 return hashLarge128(xinput, length) 68 } else if length > 128 { 69 return xxh3Len129To240_128b(xinput, length) 70 } else if length > 16 { 71 return xxh3Len17To128_128b(xinput, length) 72 } else { 73 return xxh3Len0To16_128b(xinput, length) 74 } 75 } 76 77 // Hash128String returns the hash value of the string in 128bits. 78 func Hash128String(s string) [2]uint64 { 79 return Hash128([]byte(s)) 80 } 81 82 func xxh3Len0To16_64b(xinput unsafe.Pointer, len uint64) uint64 { 83 length := uintptr(len) 84 85 if length > 8 { 86 inputlo := runtimex.ReadUnaligned64(xinput) ^ (runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+24)) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32))) 87 inputhi := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8)) ^ (runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret) + 40))) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+48)) 88 acc := len + bits.ReverseBytes64(inputlo) + inputhi + mix(inputlo, inputhi) 89 return xxh3Avalanche(acc) 90 } else if length >= 4 { 91 input1 := runtimex.ReadUnaligned32(xinput) 92 input2 := runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xinput) + length - 4)) 93 input64 := input2 + input1<<32 94 keyed := input64 ^ (runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret) + 8))) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16)) 95 return xxh3RRMXMX(keyed, len) 96 } else if length > 0 { 97 q := (*[4]byte)(xinput) 98 combined := (uint64(q[0]) << 16) | (uint64(q[len>>1]) << 24) | (uint64(q[len-1]) << 0) | len<<8 99 combined ^= runtimex.ReadUnaligned32(xsecret) ^ runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xsecret)+4)) 100 return xxh64Avalanche(combined) 101 } else { 102 return xxh64Avalanche(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+56)) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+64))) 103 } 104 } 105 106 func xxh3Len17To128_64b(xinput unsafe.Pointer, len uint64) uint64 { 107 length := uintptr(len) 108 109 acc := len * prime64_1 110 if length > 32 { 111 if length > 64 { 112 if length > 96 { 113 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+48))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+96)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+56))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+104))) 114 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-64))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+112)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-56))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+120))) 115 } 116 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+64)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+40))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+72))) 117 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-48))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+80)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-40))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+88))) 118 } 119 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+24))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+40))) 120 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-32))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+48)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-24))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+56))) 121 } 122 acc += mix(runtimex.ReadUnaligned64(xinput)^runtimex.ReadUnaligned64(xsecret), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+8))) 123 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+24))) 124 125 return xxh3Avalanche(acc) 126 } 127 128 func xxh3Len129To240_64b(xinput unsafe.Pointer, len uint64) uint64 { 129 length := uintptr(len) 130 131 acc := len * prime64_1 132 133 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*0))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*0)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*0+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*0+8))) 134 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*1))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*1)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*1+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*1+8))) 135 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*2))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*2)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*2+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*2+8))) 136 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*3))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*3)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*3+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*3+8))) 137 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*4))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*4)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*4+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*4+8))) 138 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*5))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*5)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*5+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*5+8))) 139 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*6))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*6)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*6+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*6+8))) 140 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*7))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*7)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*7+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*7+8))) 141 142 acc = xxh3Avalanche(acc) 143 nbRounds := uintptr(length >> 4) 144 145 for i := uintptr(8); i < nbRounds; i++ { 146 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*i))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*i-125)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*i+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16*i-117))) 147 } 148 149 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+119)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+127))) 150 151 return xxh3Avalanche(acc) 152 } 153 154 func hashLarge(p unsafe.Pointer, length uint64) (acc uint64) { 155 acc = length * prime64_1 156 157 xacc := [8]uint64{ 158 prime32_3, prime64_1, prime64_2, prime64_3, 159 prime64_4, prime32_2, prime64_5, prime32_1} 160 161 accumScalar(&xacc, p, xsecret, length) 162 //merge xacc 163 acc += mix(xacc[0]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+11)), xacc[1]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+19))) 164 acc += mix(xacc[2]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+27)), xacc[3]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+35))) 165 acc += mix(xacc[4]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+43)), xacc[5]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+51))) 166 acc += mix(xacc[6]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+59)), xacc[7]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+67))) 167 168 return xxh3Avalanche(acc) 169 } 170 171 func xxh3Len0To16_128b(xinput unsafe.Pointer, len uint64) [2]uint64 { 172 length := uintptr(len) 173 174 if length > 8 { 175 bitflipl := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32)) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+40)) 176 bitfliph := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+48)) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+56)) 177 inputLow := runtimex.ReadUnaligned64(xinput) 178 inputHigh := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput) + length - 8)) 179 m128High64, m128Low64 := bits.Mul64(inputLow^inputHigh^bitflipl, prime64_1) 180 181 m128Low64 += uint64(length-1) << 54 182 inputHigh ^= bitfliph 183 184 m128High64 += inputHigh + uint64(uint32(inputHigh))*(prime32_2-1) 185 m128Low64 ^= bits.ReverseBytes64(m128High64) 186 187 h128High64, h128Low64 := bits.Mul64(m128Low64, prime64_2) 188 h128High64 += m128High64 * prime64_2 189 190 h128Low64 = xxh3Avalanche(h128Low64) 191 h128High64 = xxh3Avalanche(h128High64) 192 193 return [2]uint64{h128High64, h128Low64} 194 195 } else if length >= 4 { 196 inputLow := runtimex.ReadUnaligned32(xinput) 197 inputHigh := runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xinput) + uintptr(length-4))) 198 input64 := inputLow + (uint64(inputHigh) << 32) 199 bitflip := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16)) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+24)) 200 keyed := input64 ^ bitflip 201 202 m128High64, m128Low64 := bits.Mul64(keyed, prime64_1+(len)<<2) 203 m128High64 += m128Low64 << 1 204 m128Low64 ^= m128High64 >> 3 205 206 m128Low64 ^= m128Low64 >> 35 207 m128Low64 *= 0x9fb21c651e98df25 208 m128Low64 ^= m128Low64 >> 28 209 210 m128High64 = xxh3Avalanche(m128High64) 211 return [2]uint64{m128High64, m128Low64} 212 213 } else if length >= 1 { 214 q := (*[4]byte)(xinput) 215 combinedl := (uint64(q[0]) << 16) | (uint64(q[len>>1]) << 24) | (uint64(q[len-1]) << 0) | len<<8 216 combinedh := uint64(bits.RotateLeft32(bits.ReverseBytes32(uint32(combinedl)), 13)) 217 218 bitflipl := runtimex.ReadUnaligned32(xsecret) ^ runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xsecret)+4)) 219 bitfliph := runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xsecret)+8)) ^ runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xsecret)+12)) 220 221 keyedLow := combinedl ^ bitflipl 222 keyedHigh := combinedh ^ bitfliph 223 224 keyedLow = combinedl ^ bitflipl 225 keyedHigh = combinedh ^ bitfliph 226 227 h128Low64 := xxh64Avalanche(keyedLow) 228 h128High64 := xxh64Avalanche(keyedHigh) 229 return [2]uint64{h128High64, h128Low64} 230 } 231 bitflipl := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+64)) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+72)) 232 bitfliph := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+80)) ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+88)) 233 234 h128High64 := xxh64Avalanche(bitfliph) 235 h128Low64 := xxh64Avalanche(bitflipl) 236 237 return [2]uint64{h128High64, h128Low64} 238 } 239 240 func xxh3Len17To128_128b(xinput unsafe.Pointer, len uint64) [2]uint64 { 241 length := uintptr(len) 242 243 accHigh := uint64(0) 244 accLow := len * prime64_1 245 246 if length > 32 { 247 if length > 64 { 248 if length > 96 { 249 accLow += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+48))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+96)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+56))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+104))) 250 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-64)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-56)) 251 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-64))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+112)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-56))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+120))) 252 accHigh ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+48)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+56)) 253 } 254 accLow += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+64)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+40))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+72))) 255 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-48)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-40)) 256 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-48))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+80)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-40))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+88))) 257 accHigh ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+40)) 258 } 259 accLow += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+3*8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+40))) 260 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-32)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-3*8)) 261 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-32))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+48)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-3*8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+56))) 262 accHigh ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+3*8)) 263 } 264 265 accLow += mix(runtimex.ReadUnaligned64(xinput)^runtimex.ReadUnaligned64(xsecret), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+8))) 266 accLow ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8)) 267 accHigh += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+16)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+24))) 268 accHigh ^= runtimex.ReadUnaligned64(xinput) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8)) 269 270 h128Low := accHigh + accLow 271 h128High := (accLow * prime64_1) + (accHigh * prime64_4) + (len * prime64_2) 272 273 h128Low = xxh3Avalanche(h128Low) 274 h128High = -xxh3Avalanche(h128High) 275 276 return [2]uint64{h128High, h128Low} 277 } 278 279 func xxh3Len129To240_128b(xinput unsafe.Pointer, len uint64) [2]uint64 { 280 length := uintptr(len) 281 nbRounds := length &^ 31 / 32 282 accLow64 := len * prime64_1 283 accHigh64 := uint64(0) 284 285 for i := uintptr(0); i < 4; i++ { 286 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i+8))) 287 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+24)) 288 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i+16)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+24))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i+24))) 289 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+8)) 290 } 291 292 accLow64 = xxh3Avalanche(accLow64) 293 accHigh64 = xxh3Avalanche(accHigh64) 294 295 for i := uintptr(4); i < nbRounds; i++ { 296 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i-109)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+24))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i-101))) 297 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+8)) 298 299 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i-125)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+32*i-117))) 300 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32*i+24)) 301 } 302 303 // last 32 bytes 304 accLow64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+103)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+111))) 305 accLow64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-32)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-24)) 306 accHigh64 += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-32))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+119)), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-24))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+127))) 307 accHigh64 ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-16)) + runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+length-8)) 308 309 accHigh64, accLow64 = (accLow64*prime64_1)+(accHigh64*prime64_4)+(len*prime64_2), accHigh64+accLow64 310 311 accLow64 = xxh3Avalanche(accLow64) 312 accHigh64 = -xxh3Avalanche(accHigh64) 313 314 return [2]uint64{accHigh64, accLow64} 315 } 316 317 func hashLarge128(p unsafe.Pointer, length uint64) (acc [2]uint64) { 318 acc[1] = length * prime64_1 319 acc[0] = ^(length * prime64_2) 320 321 xacc := [8]uint64{ 322 prime32_3, prime64_1, prime64_2, prime64_3, 323 prime64_4, prime32_2, prime64_5, prime32_1} 324 325 accumScalar(&xacc, p, xsecret, length) 326 // merge xacc 327 acc[1] += mix(xacc[0]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+11)), xacc[1]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+19))) 328 acc[1] += mix(xacc[2]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+27)), xacc[3]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+35))) 329 acc[1] += mix(xacc[4]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+43)), xacc[5]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+51))) 330 acc[1] += mix(xacc[6]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+59)), xacc[7]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+67))) 331 332 acc[1] = xxh3Avalanche(acc[1]) 333 334 acc[0] += mix(xacc[0]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+117)), xacc[1]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+125))) 335 acc[0] += mix(xacc[2]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+133)), xacc[3]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+141))) 336 acc[0] += mix(xacc[4]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+149)), xacc[5]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+157))) 337 acc[0] += mix(xacc[6]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+165)), xacc[7]^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+173))) 338 acc[0] = xxh3Avalanche(acc[0]) 339 340 return acc 341 } 342 343 func accumScalar(xacc *[8]uint64, xinput, xsecret unsafe.Pointer, l uint64) { 344 j := uint64(0) 345 346 // Loops over block, process 16*8*8=1024 bytes of data each iteration 347 for ; j < (l-1)/1024; j++ { 348 k := xsecret 349 for i := 0; i < 16; i++ { 350 for j := uintptr(0); j < 8; j++ { 351 dataVec := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput) + 8*j)) 352 keyVec := dataVec ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(k)+8*j)) 353 xacc[j^1] += dataVec 354 xacc[j] += (keyVec & 0xffffffff) * (keyVec >> 32) 355 } 356 xinput, k = unsafe.Pointer(uintptr(xinput)+_stripe), unsafe.Pointer(uintptr(k)+8) 357 } 358 359 // scramble xacc 360 for j := uintptr(0); j < 8; j++ { 361 xacc[j] ^= xacc[j] >> 47 362 xacc[j] ^= runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret) + 128 + 8*j)) 363 xacc[j] *= prime32_1 364 } 365 } 366 l -= _block * j 367 368 // last partial block (1024 bytes) 369 if l > 0 { 370 k := xsecret 371 i := uint64(0) 372 for ; i < (l-1)/_stripe; i++ { 373 for j := uintptr(0); j < 8; j++ { 374 dataVec := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput) + 8*j)) 375 keyVec := dataVec ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(k)+8*j)) 376 xacc[j^1] += dataVec 377 xacc[j] += (keyVec & 0xffffffff) * (keyVec >> 32) 378 } 379 xinput, k = unsafe.Pointer(uintptr(xinput)+_stripe), unsafe.Pointer(uintptr(k)+8) 380 } 381 l -= _stripe * i 382 383 // last stripe (64 bytes) 384 if l > 0 { 385 xinput = unsafe.Pointer(uintptr(xinput) - uintptr(_stripe-l)) 386 k = unsafe.Pointer(uintptr(xsecret) + 121) 387 388 for j := uintptr(0); j < 8; j++ { 389 dataVec := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput) + 8*j)) 390 keyVec := dataVec ^ runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(k)+8*j)) 391 xacc[j^1] += dataVec 392 xacc[j] += (keyVec & 0xffffffff) * (keyVec >> 32) 393 } 394 } 395 } 396 } 397 398 func mix(a, b uint64) uint64 { 399 hi, lo := bits.Mul64(a, b) 400 return hi ^ lo 401 } 402 403 func xxh3RRMXMX(h64 uint64, length uint64) uint64 { 404 h64 ^= bits.RotateLeft64(h64, 49) ^ bits.RotateLeft64(h64, 24) 405 h64 *= 0x9fb21c651e98df25 406 h64 ^= (h64 >> 35) + length 407 h64 *= 0x9fb21c651e98df25 408 h64 ^= (h64 >> 28) 409 return h64 410 } 411 412 func xxh64Avalanche(h64 uint64) uint64 { 413 h64 ^= h64 >> 33 414 h64 *= prime64_2 415 h64 ^= h64 >> 29 416 h64 *= prime64_3 417 h64 ^= h64 >> 32 418 return h64 419 } 420 421 func xxh3Avalanche(x uint64) uint64 { 422 x ^= x >> 37 423 x *= 0x165667919e3779f9 424 x ^= x >> 32 425 return x 426 }