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  }