hash64.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package xxh3
  2. import "math/bits"
  3. // Hash returns the hash of the byte slice.
  4. func Hash(b []byte) uint64 {
  5. return hashAny(*(*str)(ptr(&b)))
  6. }
  7. // Hash returns the hash of the string slice.
  8. func HashString(s string) uint64 {
  9. return hashAny(*(*str)(ptr(&s)))
  10. }
  11. func hashAny(s str) (acc u64) {
  12. p, l := s.p, s.l
  13. switch {
  14. case l <= 16:
  15. switch {
  16. case l > 8: // 9-16
  17. inputlo := readU64(p, 0) ^ (key64_024 ^ key64_032)
  18. inputhi := readU64(p, ui(l)-8) ^ (key64_040 ^ key64_048)
  19. folded := mulFold64(inputlo, inputhi)
  20. return xxh3Avalanche(u64(l) + bits.ReverseBytes64(inputlo) + inputhi + folded)
  21. case l > 3: // 4-8
  22. input1 := readU32(p, 0)
  23. input2 := readU32(p, ui(l)-4)
  24. input64 := u64(input2) + u64(input1)<<32
  25. keyed := input64 ^ (key64_008 ^ key64_016)
  26. return rrmxmx(keyed, u64(l))
  27. case l == 3: // 3
  28. c12 := u64(readU16(p, 0))
  29. c3 := u64(readU8(p, 2))
  30. acc = c12<<16 + c3 + 3<<8
  31. case l > 1: // 2
  32. c12 := u64(readU16(p, 0))
  33. acc = c12*(1<<24+1)>>8 + 2<<8
  34. case l == 1: // 1
  35. c1 := u64(readU8(p, 0))
  36. acc = c1*(1<<24+1<<16+1) + 1<<8
  37. default: // 0
  38. return 0x2d06800538d394c2 // xxh_avalanche(key64_056 ^ key64_064)
  39. }
  40. acc ^= u64(key32_000 ^ key32_004)
  41. return xxhAvalancheSmall(acc)
  42. case l <= 128:
  43. acc = u64(l) * prime64_1
  44. if l > 32 {
  45. if l > 64 {
  46. if l > 96 {
  47. acc += mulFold64(readU64(p, 6*8)^key64_096, readU64(p, 7*8)^key64_104)
  48. acc += mulFold64(readU64(p, ui(l)-8*8)^key64_112, readU64(p, ui(l)-7*8)^key64_120)
  49. } // 96
  50. acc += mulFold64(readU64(p, 4*8)^key64_064, readU64(p, 5*8)^key64_072)
  51. acc += mulFold64(readU64(p, ui(l)-6*8)^key64_080, readU64(p, ui(l)-5*8)^key64_088)
  52. } // 64
  53. acc += mulFold64(readU64(p, 2*8)^key64_032, readU64(p, 3*8)^key64_040)
  54. acc += mulFold64(readU64(p, ui(l)-4*8)^key64_048, readU64(p, ui(l)-3*8)^key64_056)
  55. } // 32
  56. acc += mulFold64(readU64(p, 0*8)^key64_000, readU64(p, 1*8)^key64_008)
  57. acc += mulFold64(readU64(p, ui(l)-2*8)^key64_016, readU64(p, ui(l)-1*8)^key64_024)
  58. return xxh3Avalanche(acc)
  59. case l <= 240:
  60. acc = u64(l) * prime64_1
  61. acc += mulFold64(readU64(p, 0*16+0)^key64_000, readU64(p, 0*16+8)^key64_008)
  62. acc += mulFold64(readU64(p, 1*16+0)^key64_016, readU64(p, 1*16+8)^key64_024)
  63. acc += mulFold64(readU64(p, 2*16+0)^key64_032, readU64(p, 2*16+8)^key64_040)
  64. acc += mulFold64(readU64(p, 3*16+0)^key64_048, readU64(p, 3*16+8)^key64_056)
  65. acc += mulFold64(readU64(p, 4*16+0)^key64_064, readU64(p, 4*16+8)^key64_072)
  66. acc += mulFold64(readU64(p, 5*16+0)^key64_080, readU64(p, 5*16+8)^key64_088)
  67. acc += mulFold64(readU64(p, 6*16+0)^key64_096, readU64(p, 6*16+8)^key64_104)
  68. acc += mulFold64(readU64(p, 7*16+0)^key64_112, readU64(p, 7*16+8)^key64_120)
  69. // avalanche
  70. acc = xxh3Avalanche(acc)
  71. // trailing groups after 128
  72. top := ui(l) &^ 15
  73. for i := ui(8 * 16); i < top; i += 16 {
  74. acc += mulFold64(readU64(p, i+0)^readU64(key, i-125), readU64(p, i+8)^readU64(key, i-117))
  75. }
  76. // last 16 bytes
  77. acc += mulFold64(readU64(p, ui(l)-16)^key64_119, readU64(p, ui(l)-8)^key64_127)
  78. return xxh3Avalanche(acc)
  79. default:
  80. acc = u64(l) * prime64_1
  81. accs := [8]u64{
  82. prime32_3, prime64_1, prime64_2, prime64_3,
  83. prime64_4, prime32_2, prime64_5, prime32_1,
  84. }
  85. if hasAVX512 && l >= avx512Switch {
  86. accumAVX512(&accs, p, key, u64(l))
  87. } else if hasAVX2 {
  88. accumAVX2(&accs, p, key, u64(l))
  89. } else if hasSSE2 {
  90. accumSSE(&accs, p, key, u64(l))
  91. } else {
  92. accumScalar(&accs, p, key, u64(l))
  93. }
  94. // merge accs
  95. acc += mulFold64(accs[0]^key64_011, accs[1]^key64_019)
  96. acc += mulFold64(accs[2]^key64_027, accs[3]^key64_035)
  97. acc += mulFold64(accs[4]^key64_043, accs[5]^key64_051)
  98. acc += mulFold64(accs[6]^key64_059, accs[7]^key64_067)
  99. return xxh3Avalanche(acc)
  100. }
  101. }