hash_function.h - エンジンの C API リファレンス

hash_function.h
  1. #pragma once
  2. #include <stdint.h>
  3. #include <string.h>
  4. namespace stingray_plugin_foundation {
  5. // Implementation of the 64 bit murmur hash function
  6. // http://murmurhash.googlepages.com/
  7. inline uint64_t murmur_hash_64(const void * key, int len, uint64_t seed)
  8. {
  9. const uint64_t m = 0xc6a4a7935bd1e995ULL;
  10. const int r = 47;
  11. uint64_t h = seed ^ (len * m);
  12. const uint64_t * data = (const uint64_t *)key;
  13. const uint64_t * end = data + (len/8);
  14. while(data != end)
  15. {
  16. #if defined(ANDROID) || defined(IOS) || defined(WEB) // Unaligned 64bit reads not supported!
  17. uint64_t k;
  18. char *p = (char *)&k, *d = (char *)data;
  19. p[0] = d[0]; p[1] = d[1]; p[2] = d[2]; p[3] = d[3];
  20. p[4] = d[4]; p[5] = d[5]; p[6] = d[6]; p[7] = d[7];
  21. data++;
  22. #elif defined(WINDOWSPC) || defined(UWP) || defined(XBOXONE) || defined(__ORBIS__) || defined(MACOSX) || defined(LINUXPC)
  23. uint64_t k = *data++;
  24. #else
  25. #error Unaligned 64bit reads undefined!
  26. #endif
  27. k *= m;
  28. k ^= k >> r;
  29. k *= m;
  30. h ^= k;
  31. h *= m;
  32. }
  33. const unsigned char * data2 = (const unsigned char*)data;
  34. switch(len & 7)
  35. {
  36. case 7: h ^= uint64_t(data2[6]) << 48;
  37. case 6: h ^= uint64_t(data2[5]) << 40;
  38. case 5: h ^= uint64_t(data2[4]) << 32;
  39. case 4: h ^= uint64_t(data2[3]) << 24;
  40. case 3: h ^= uint64_t(data2[2]) << 16;
  41. case 2: h ^= uint64_t(data2[1]) << 8;
  42. case 1: h ^= uint64_t(data2[0]);
  43. h *= m;
  44. };
  45. h ^= h >> r;
  46. h *= m;
  47. h ^= h >> r;
  48. return h;
  49. }
  50. inline uint64_t hash64(const char *s)
  51. {
  52. return murmur_hash_64(s, int(strlen(s)), 0);
  53. }
  54. inline unsigned hash32(const char *s)
  55. {
  56. uint64_t id64 = murmur_hash_64(s, int(strlen(s)), 0);
  57. return unsigned(id64 >> 32);
  58. }
  59. inline unsigned hash32(const void * key, int len)
  60. {
  61. uint64_t id64 = murmur_hash_64(key, len, 0);
  62. return unsigned(id64 >> 32);
  63. }
  64. // A quick hash for four byte sized values based on a single
  65. // iteration of the murmur hash function.
  66. //
  67. // Another option would be to convert the bit pattern directly to
  68. // an int. That would be faster, but might lead to clustering if
  69. // the input values do not distribute evenly.
  70. inline unsigned int four_byte_hash(const void * key)
  71. {
  72. const unsigned int m = 0x5bd1e995;
  73. const int r = 24;
  74. unsigned int k = *(unsigned int *)key;
  75. k *= m;
  76. k ^= k >> r;
  77. k *= m;
  78. return k;
  79. }
  80. inline uint64_t eight_byte_hash_64(const void * key)
  81. {
  82. const uint64_t m = 0xc6a4a7935bd1e995ULL;
  83. const int r = 47;
  84. uint64_t k = *(const uint64_t *)key;
  85. k *= m;
  86. k ^= k >> r;
  87. k *= m;
  88. return k;
  89. }
  90. // Default hashing for builtin-types.
  91. template <class T> struct default_hash
  92. {
  93. static constexpr bool value = false;
  94. unsigned operator()(T t) const { static_assert(value, "default_hash not implemented for this type!"); return 0; }
  95. };
  96. template <class T> struct default_hash<T *>
  97. {
  98. unsigned operator()(T *t) const
  99. {
  100. #ifdef PLATFORM_64BIT
  101. return (unsigned)eight_byte_hash_64(&t);
  102. #else
  103. return four_byte_hash(&t);
  104. #endif
  105. }
  106. };
  107. template <class T> struct default_hash<const T *>
  108. {
  109. unsigned operator()(const T *t) const
  110. {
  111. #ifdef PLATFORM_64BIT
  112. return (unsigned)eight_byte_hash_64(&t);
  113. #else
  114. return four_byte_hash(&t);
  115. #endif
  116. }
  117. };
  118. template <> struct default_hash<unsigned>
  119. {
  120. unsigned operator()(unsigned t) const { return four_byte_hash(&t); }
  121. };
  122. template <> struct default_hash<int>
  123. {
  124. unsigned operator()(int t) const { return four_byte_hash(&t); }
  125. };
  126. template <> struct default_hash<uint64_t>
  127. {
  128. unsigned operator()(uint64_t t) const { return hash32(&t, sizeof(t)); }
  129. };
  130. template <> struct default_hash<int64_t>
  131. {
  132. unsigned operator()(int64_t t) const { return hash32(&t, sizeof(t)); }
  133. };
  134. // Utility functions
  135. inline uint64_t mix(uint64_t h, uint64_t k)
  136. {
  137. const uint64_t m = 0xc6a4a7935bd1e995ULL;
  138. const int r = 47;
  139. k *= m;
  140. k ^= k >> r;
  141. k *= m;
  142. h ^= k;
  143. h *= m;
  144. return h;
  145. }
  146. inline unsigned mix(unsigned h, unsigned k)
  147. {
  148. const unsigned int m = 0x5bd1e995;
  149. const int r = 24;
  150. k *= m;
  151. k ^= k >> r;
  152. k *= m;
  153. h *= m;
  154. h ^= k;
  155. return h;
  156. }
  157. } // namespace stingray_plugin_foundation