MurmurHash1.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. //-----------------------------------------------------------------------------
  2. // MurmurHash was written by Austin Appleby, and is placed in the public
  3. // domain. The author hereby disclaims copyright to this source code.
  4. // Note - This code makes a few assumptions about how your machine behaves -
  5. // 1. We can read a 4-byte value from any address without crashing
  6. // 2. sizeof(int) == 4
  7. // And it has a few limitations -
  8. // 1. It will not work incrementally.
  9. // 2. It will not produce the same results on little-endian and big-endian
  10. // machines.
  11. #include "MurmurHash1.h"
  12. //-----------------------------------------------------------------------------
  13. uint32_t MurmurHash1 ( const void * key, int len, uint32_t seed )
  14. {
  15. const unsigned int m = 0xc6a4a793;
  16. const int r = 16;
  17. unsigned int h = seed ^ (len * m);
  18. //----------
  19. const unsigned char * data = (const unsigned char *)key;
  20. while(len >= 4)
  21. {
  22. unsigned int k = *(unsigned int *)data;
  23. h += k;
  24. h *= m;
  25. h ^= h >> 16;
  26. data += 4;
  27. len -= 4;
  28. }
  29. //----------
  30. switch(len)
  31. {
  32. case 3:
  33. h += data[2] << 16;
  34. case 2:
  35. h += data[1] << 8;
  36. case 1:
  37. h += data[0];
  38. h *= m;
  39. h ^= h >> r;
  40. };
  41. //----------
  42. h *= m;
  43. h ^= h >> 10;
  44. h *= m;
  45. h ^= h >> 17;
  46. return h;
  47. }
  48. //-----------------------------------------------------------------------------
  49. // MurmurHash1Aligned, by Austin Appleby
  50. // Same algorithm as MurmurHash1, but only does aligned reads - should be safer
  51. // on certain platforms.
  52. // Performance should be equal to or better than the simple version.
  53. unsigned int MurmurHash1Aligned ( const void * key, int len, unsigned int seed )
  54. {
  55. const unsigned int m = 0xc6a4a793;
  56. const int r = 16;
  57. const unsigned char * data = (const unsigned char *)key;
  58. unsigned int h = seed ^ (len * m);
  59. int align = (uint64_t)data & 3;
  60. if(align && (len >= 4))
  61. {
  62. // Pre-load the temp registers
  63. unsigned int t = 0, d = 0;
  64. switch(align)
  65. {
  66. case 1: t |= data[2] << 16;
  67. case 2: t |= data[1] << 8;
  68. case 3: t |= data[0];
  69. }
  70. t <<= (8 * align);
  71. data += 4-align;
  72. len -= 4-align;
  73. int sl = 8 * (4-align);
  74. int sr = 8 * align;
  75. // Mix
  76. while(len >= 4)
  77. {
  78. d = *(unsigned int *)data;
  79. t = (t >> sr) | (d << sl);
  80. h += t;
  81. h *= m;
  82. h ^= h >> r;
  83. t = d;
  84. data += 4;
  85. len -= 4;
  86. }
  87. // Handle leftover data in temp registers
  88. int pack = len < align ? len : align;
  89. d = 0;
  90. switch(pack)
  91. {
  92. case 3: d |= data[2] << 16;
  93. case 2: d |= data[1] << 8;
  94. case 1: d |= data[0];
  95. case 0: h += (t >> sr) | (d << sl);
  96. h *= m;
  97. h ^= h >> r;
  98. }
  99. data += pack;
  100. len -= pack;
  101. }
  102. else
  103. {
  104. while(len >= 4)
  105. {
  106. h += *(unsigned int *)data;
  107. h *= m;
  108. h ^= h >> r;
  109. data += 4;
  110. len -= 4;
  111. }
  112. }
  113. //----------
  114. // Handle tail bytes
  115. switch(len)
  116. {
  117. case 3: h += data[2] << 16;
  118. case 2: h += data[1] << 8;
  119. case 1: h += data[0];
  120. h *= m;
  121. h ^= h >> r;
  122. };
  123. h *= m;
  124. h ^= h >> 10;
  125. h *= m;
  126. h ^= h >> 17;
  127. return h;
  128. }