github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/sys/xxhash3/hash.go (about) 1 // Package xxhash3 implements https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h 2 package xxhash3 3 4 import ( 5 "math/bits" 6 "unsafe" 7 8 "github.com/songzhibin97/go-baseutils/internal/hack" 9 "github.com/songzhibin97/go-baseutils/internal/runtimex" 10 ) 11 12 // Hash returns the hash value of the byte slice in 64bits. 13 func Hash(data []byte) uint64 { 14 funcPointer := hashSmall 15 16 if len(data) > 16 { 17 funcPointer = hashLarge 18 } 19 return hashfunc[funcPointer](*(*unsafe.Pointer)(unsafe.Pointer(&data)), len(data)) 20 21 } 22 23 // HashString returns the hash value of the string in 64bits. 24 func HashString(s string) uint64 { 25 return Hash(hack.StringToBytes(s)) 26 } 27 28 func xxh3HashSmall(xinput unsafe.Pointer, length int) uint64 { 29 30 if length > 8 { 31 inputlo := runtimex.ReadUnaligned64(xinput) ^ xsecret_024 ^ xsecret_032 32 inputhi := runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-8))) ^ xsecret_040 ^ xsecret_048 33 return xxh3Avalanche(uint64(length) + bits.ReverseBytes64(inputlo) + inputhi + mix(inputlo, inputhi)) 34 } else if length >= 4 { 35 input1 := runtimex.ReadUnaligned32(xinput) 36 input2 := runtimex.ReadUnaligned32(unsafe.Pointer(uintptr(xinput) + uintptr(length-4))) 37 input64 := input2 + input1<<32 38 keyed := input64 ^ xsecret_008 ^ xsecret_016 39 return xxh3RRMXMX(keyed, uint64(length)) 40 } else if length == 3 { 41 c12 := runtimex.ReadUnaligned16(xinput) 42 c3 := uint64(*(*uint8)(unsafe.Pointer(uintptr(xinput) + 2))) 43 acc := c12<<16 + c3 + 3<<8 44 acc ^= uint64(xsecret32_000 ^ xsecret32_004) 45 return xxh64Avalanche(acc) 46 } else if length == 2 { 47 c12 := runtimex.ReadUnaligned16(xinput) 48 acc := c12*(1<<24+1)>>8 + 2<<8 49 acc ^= uint64(xsecret32_000 ^ xsecret32_004) 50 return xxh64Avalanche(acc) 51 } else if length == 1 { 52 c1 := uint64(*(*uint8)(xinput)) 53 acc := c1*(1<<24+1<<16+1) + 1<<8 54 acc ^= uint64(xsecret32_000 ^ xsecret32_004) 55 return xxh64Avalanche(acc) 56 } 57 return 0x2d06800538d394c2 58 } 59 60 func xxh3HashLarge(xinput unsafe.Pointer, l int) (acc uint64) { 61 length := uintptr(l) 62 63 if length <= 128 { 64 acc := uint64(length * prime64_1) 65 if length > 32 { 66 if length > 64 { 67 if length > 96 { 68 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+48))^xsecret_096, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+56))^xsecret_104) 69 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-64)))^xsecret_112, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-56)))^xsecret_120) 70 } 71 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+32))^xsecret_064, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+40))^xsecret_072) 72 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-48)))^xsecret_080, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-40)))^xsecret_088) 73 } 74 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16))^xsecret_032, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+24))^xsecret_040) 75 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-32)))^xsecret_048, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-24)))^xsecret_056) 76 } 77 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+0))^xsecret_000, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+8))^xsecret_008) 78 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-16)))^xsecret_016, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-8)))^xsecret_024) 79 80 return xxh3Avalanche(acc) 81 82 } else if length <= 240 { 83 acc := uint64(length * prime64_1) 84 85 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*0))^xsecret_000, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*0+8))^xsecret_008) 86 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*1))^xsecret_016, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*1+8))^xsecret_024) 87 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*2))^xsecret_032, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*2+8))^xsecret_040) 88 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*3))^xsecret_048, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*3+8))^xsecret_056) 89 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*4))^xsecret_064, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*4+8))^xsecret_072) 90 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*5))^xsecret_080, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*5+8))^xsecret_088) 91 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*6))^xsecret_096, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*6+8))^xsecret_104) 92 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*7))^xsecret_112, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+16*7+8))^xsecret_120) 93 94 acc = xxh3Avalanche(acc) 95 nbRounds := uint64(length >> 4 << 4) 96 97 for i := uint64(8 * 16); i < nbRounds; i += 16 { 98 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(i)))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+uintptr(i-125))), runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(i+8)))^runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xsecret)+uintptr(i-117)))) 99 } 100 101 acc += mix(runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-16)))^xsecret_119, runtimex.ReadUnaligned64(unsafe.Pointer(uintptr(xinput)+uintptr(length-8)))^xsecret_127) 102 103 return xxh3Avalanche(acc) 104 } 105 106 var xacc = [8]uint64{ 107 prime32_3, prime64_1, prime64_2, prime64_3, 108 prime64_4, prime32_2, prime64_5, prime32_1} 109 110 acc = uint64(length * prime64_1) 111 112 accum(&xacc, xinput, xsecret, length) 113 114 //merge xacc 115 acc += mix(xacc[0]^xsecret_011, xacc[1]^xsecret_019) 116 acc += mix(xacc[2]^xsecret_027, xacc[3]^xsecret_035) 117 acc += mix(xacc[4]^xsecret_043, xacc[5]^xsecret_051) 118 acc += mix(xacc[6]^xsecret_059, xacc[7]^xsecret_067) 119 120 return xxh3Avalanche(acc) 121 }