murmurhash3.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: LGPL-2.1+
  2. /*
  3. * MurmurHash3 was written by Austin Appleby, and is placed in the public
  4. * domain. The author hereby disclaims copyright to this source code.
  5. *
  6. * Adapted by John Wiele (jwiele@redhat.com).
  7. */
  8. #include "murmurhash3.h"
  9. #include <linux/unaligned.h>
  10. static inline u64 rotl64(u64 x, s8 r)
  11. {
  12. return (x << r) | (x >> (64 - r));
  13. }
  14. #define ROTL64(x, y) rotl64(x, y)
  15. /* Finalization mix - force all bits of a hash block to avalanche */
  16. static __always_inline u64 fmix64(u64 k)
  17. {
  18. k ^= k >> 33;
  19. k *= 0xff51afd7ed558ccdLLU;
  20. k ^= k >> 33;
  21. k *= 0xc4ceb9fe1a85ec53LLU;
  22. k ^= k >> 33;
  23. return k;
  24. }
  25. void murmurhash3_128(const void *key, const int len, const u32 seed, void *out)
  26. {
  27. const u8 *data = key;
  28. const int nblocks = len / 16;
  29. u64 h1 = seed;
  30. u64 h2 = seed;
  31. const u64 c1 = 0x87c37b91114253d5LLU;
  32. const u64 c2 = 0x4cf5ad432745937fLLU;
  33. u64 *hash_out = out;
  34. /* body */
  35. const u64 *blocks = (const u64 *)(data);
  36. int i;
  37. for (i = 0; i < nblocks; i++) {
  38. u64 k1 = get_unaligned_le64(&blocks[i * 2]);
  39. u64 k2 = get_unaligned_le64(&blocks[i * 2 + 1]);
  40. k1 *= c1;
  41. k1 = ROTL64(k1, 31);
  42. k1 *= c2;
  43. h1 ^= k1;
  44. h1 = ROTL64(h1, 27);
  45. h1 += h2;
  46. h1 = h1 * 5 + 0x52dce729;
  47. k2 *= c2;
  48. k2 = ROTL64(k2, 33);
  49. k2 *= c1;
  50. h2 ^= k2;
  51. h2 = ROTL64(h2, 31);
  52. h2 += h1;
  53. h2 = h2 * 5 + 0x38495ab5;
  54. }
  55. /* tail */
  56. {
  57. const u8 *tail = (const u8 *)(data + nblocks * 16);
  58. u64 k1 = 0;
  59. u64 k2 = 0;
  60. switch (len & 15) {
  61. case 15:
  62. k2 ^= ((u64)tail[14]) << 48;
  63. fallthrough;
  64. case 14:
  65. k2 ^= ((u64)tail[13]) << 40;
  66. fallthrough;
  67. case 13:
  68. k2 ^= ((u64)tail[12]) << 32;
  69. fallthrough;
  70. case 12:
  71. k2 ^= ((u64)tail[11]) << 24;
  72. fallthrough;
  73. case 11:
  74. k2 ^= ((u64)tail[10]) << 16;
  75. fallthrough;
  76. case 10:
  77. k2 ^= ((u64)tail[9]) << 8;
  78. fallthrough;
  79. case 9:
  80. k2 ^= ((u64)tail[8]) << 0;
  81. k2 *= c2;
  82. k2 = ROTL64(k2, 33);
  83. k2 *= c1;
  84. h2 ^= k2;
  85. fallthrough;
  86. case 8:
  87. k1 ^= ((u64)tail[7]) << 56;
  88. fallthrough;
  89. case 7:
  90. k1 ^= ((u64)tail[6]) << 48;
  91. fallthrough;
  92. case 6:
  93. k1 ^= ((u64)tail[5]) << 40;
  94. fallthrough;
  95. case 5:
  96. k1 ^= ((u64)tail[4]) << 32;
  97. fallthrough;
  98. case 4:
  99. k1 ^= ((u64)tail[3]) << 24;
  100. fallthrough;
  101. case 3:
  102. k1 ^= ((u64)tail[2]) << 16;
  103. fallthrough;
  104. case 2:
  105. k1 ^= ((u64)tail[1]) << 8;
  106. fallthrough;
  107. case 1:
  108. k1 ^= ((u64)tail[0]) << 0;
  109. k1 *= c1;
  110. k1 = ROTL64(k1, 31);
  111. k1 *= c2;
  112. h1 ^= k1;
  113. break;
  114. default:
  115. break;
  116. }
  117. }
  118. /* finalization */
  119. h1 ^= len;
  120. h2 ^= len;
  121. h1 += h2;
  122. h2 += h1;
  123. h1 = fmix64(h1);
  124. h2 = fmix64(h2);
  125. h1 += h2;
  126. h2 += h1;
  127. put_unaligned_le64(h1, &hash_out[0]);
  128. put_unaligned_le64(h2, &hash_out[1]);
  129. }