hash64_seed.go 4.3 KB

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