murmur3.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. #ifndef BOOST_HASH2_MURMUR3_HPP_INCLUDED
  2. #define BOOST_HASH2_MURMUR3_HPP_INCLUDED
  3. // Copyright 2017, 2018 Peter Dimov.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. //
  7. // MurmurHash3, https://github.com/aappleby/smhasher/wiki/MurmurHash3
  8. #include <boost/hash2/detail/read.hpp>
  9. #include <boost/hash2/detail/write.hpp>
  10. #include <boost/hash2/detail/rot.hpp>
  11. #include <boost/assert.hpp>
  12. #include <cstdint>
  13. #include <array>
  14. #include <cstring>
  15. #include <cstddef>
  16. namespace boost
  17. {
  18. namespace hash2
  19. {
  20. class murmur3_32
  21. {
  22. private:
  23. std::uint32_t h_;
  24. unsigned char buffer_[ 4 ];
  25. std::size_t m_; // == n_ % 4
  26. std::size_t n_;
  27. private:
  28. static const std::uint32_t c1 = 0xcc9e2d51u;
  29. static const std::uint32_t c2 = 0x1b873593u;
  30. private:
  31. static BOOST_FORCEINLINE void mix( std::uint32_t & h, std::uint32_t k )
  32. {
  33. k *= c1;
  34. k = detail::rotl( k, 15 );
  35. k *= c2;
  36. h ^= k;
  37. h = detail::rotl( h, 13 );
  38. h = h * 5 + 0xe6546b64;
  39. }
  40. void update_( unsigned char const * p, std::size_t m )
  41. {
  42. std::uint32_t h = h_;
  43. for( std::size_t i = 0; i < m; ++i, p += 4 )
  44. {
  45. std::uint32_t k = detail::read32le( p );
  46. mix( h, k );
  47. }
  48. h_ = h;
  49. }
  50. public:
  51. typedef std::uint32_t result_type;
  52. typedef std::uint32_t size_type;
  53. explicit murmur3_32( std::uint64_t seed = 0 ): m_( 0 ), n_( 0 )
  54. {
  55. h_ = static_cast<std::uint32_t>( seed );
  56. std::uint32_t k = static_cast<std::uint32_t>( seed >> 32 );
  57. if( k != 0 )
  58. {
  59. mix( h_, k );
  60. }
  61. }
  62. murmur3_32( unsigned char const * p, std::size_t n ): m_( 0 ), n_( 0 )
  63. {
  64. if( n == 0 )
  65. {
  66. h_ = 0;
  67. }
  68. else if( n <= 4 )
  69. {
  70. unsigned char q[ 4 ] = {};
  71. std::memcpy( q, p, n );
  72. h_ = detail::read32le( q );
  73. }
  74. else
  75. {
  76. h_ = detail::read32le( p );
  77. p += 4;
  78. n -= 4;
  79. update( p, n );
  80. result();
  81. }
  82. }
  83. void update( void const * pv, std::size_t n )
  84. {
  85. unsigned char const* p = static_cast<unsigned char const*>( pv );
  86. BOOST_ASSERT( m_ == n_ % 4 );
  87. if( n == 0 ) return;
  88. n_ += n;
  89. if( m_ > 0 )
  90. {
  91. std::size_t k = 4 - m_;
  92. if( n < k )
  93. {
  94. k = n;
  95. }
  96. std::memcpy( buffer_ + m_, p, k );
  97. p += k;
  98. n -= k;
  99. m_ += k;
  100. if( m_ < 4 ) return;
  101. BOOST_ASSERT( m_ == 4 );
  102. update_( buffer_, 1 );
  103. m_ = 0;
  104. }
  105. BOOST_ASSERT( m_ == 0 );
  106. {
  107. std::size_t k = n / 4;
  108. update_( p, k );
  109. p += 4 * k;
  110. n -= 4 * k;
  111. }
  112. BOOST_ASSERT( n < 4 );
  113. if( n > 0 )
  114. {
  115. std::memcpy( buffer_, p, n );
  116. m_ = n;
  117. }
  118. BOOST_ASSERT( m_ == n_ % 4 );
  119. }
  120. std::uint32_t result()
  121. {
  122. BOOST_ASSERT( m_ == n_ % 4 );
  123. // std::memset( buffer_ + m_, 0, 4 - m_ );
  124. // std::uint32_t k = detail::read32le( buffer_ );
  125. std::uint32_t k = 0;
  126. switch( m_ )
  127. {
  128. case 1:
  129. k = buffer_[0];
  130. break;
  131. case 2:
  132. k = buffer_[0] + (buffer_[1] << 8);
  133. break;
  134. case 3:
  135. k = buffer_[0] + (buffer_[1] << 8) + (buffer_[2] << 16);
  136. break;
  137. }
  138. k *= c1;
  139. k = detail::rotl( k, 15 );
  140. k *= c2;
  141. std::uint32_t h = h_;
  142. h ^= k;
  143. h ^= static_cast<std::uint32_t>( n_ );
  144. h ^= h >> 16;
  145. h *= 0x85ebca6b;
  146. h ^= h >> 13;
  147. h *= 0xc2b2ae35;
  148. h ^= h >> 16;
  149. n_ += 4 - m_;
  150. m_ = 0;
  151. // clear buffered plaintext
  152. std::memset( buffer_, 0, 4 );
  153. return h;
  154. }
  155. };
  156. class murmur3_128
  157. {
  158. private:
  159. std::uint64_t h1_, h2_;
  160. unsigned char buffer_[ 16 ];
  161. std::size_t m_; // == n_ % 16
  162. std::size_t n_;
  163. private:
  164. static const std::uint64_t c1 = 0x87c37b91114253d5ull;
  165. static const std::uint64_t c2 = 0x4cf5ad432745937full;
  166. private:
  167. void update_( unsigned char const * p, std::size_t k )
  168. {
  169. std::uint64_t h1 = h1_, h2 = h2_;
  170. for( std::size_t i = 0; i < k; ++i, p += 16 )
  171. {
  172. std::uint64_t k1 = detail::read64le( p + 0 );
  173. std::uint64_t k2 = detail::read64le( p + 8 );
  174. k1 *= c1; k1 = detail::rotl( k1, 31 ); k1 *= c2; h1 ^= k1;
  175. h1 = detail::rotl( h1, 27 ); h1 += h2; h1 = h1 * 5 + 0x52dce729;
  176. k2 *= c2; k2 = detail::rotl( k2, 33 ); k2 *= c1; h2 ^= k2;
  177. h2 = detail::rotl( h2, 31 ); h2 += h1; h2 = h2 * 5 + 0x38495ab5;
  178. }
  179. h1_ = h1; h2_ = h2;
  180. }
  181. static std::uint64_t fmix( std::uint64_t k )
  182. {
  183. k ^= k >> 33;
  184. k *= 0xff51afd7ed558ccdull;
  185. k ^= k >> 33;
  186. k *= 0xc4ceb9fe1a85ec53ull;
  187. k ^= k >> 33;
  188. return k;
  189. }
  190. public:
  191. typedef std::array<unsigned char, 16> result_type;
  192. typedef std::uint64_t size_type;
  193. explicit murmur3_128( std::uint64_t seed = 0 ): m_( 0 ), n_( 0 )
  194. {
  195. h1_ = seed;
  196. h2_ = seed;
  197. }
  198. murmur3_128( std::uint64_t seed1, std::uint64_t seed2 ): m_( 0 ), n_( 0 )
  199. {
  200. h1_ = seed1;
  201. h2_ = seed2;
  202. }
  203. murmur3_128( unsigned char const * p, std::size_t n ): m_( 0 ), n_( 0 )
  204. {
  205. if( n == 0 )
  206. {
  207. h1_ = h2_ = 0;
  208. }
  209. else if( n <= 8 )
  210. {
  211. unsigned char q[ 8 ] = {};
  212. std::memcpy( q, p, n );
  213. h1_ = h2_ = detail::read64le( q );
  214. }
  215. else if( n <= 16 )
  216. {
  217. unsigned char q[ 18 ] = {};
  218. std::memcpy( q, p, n );
  219. h1_ = detail::read64le( q + 0 );
  220. h2_ = detail::read64le( q + 8 );
  221. }
  222. else
  223. {
  224. h1_ = detail::read64le( p + 0 );
  225. h2_ = detail::read64le( p + 8 );
  226. p += 16;
  227. n -= 16;
  228. update( p, n );
  229. result();
  230. }
  231. }
  232. void update( void const * pv, std::size_t n )
  233. {
  234. unsigned char const* p = static_cast<unsigned char const*>( pv );
  235. BOOST_ASSERT( m_ == n_ % 16 );
  236. if( n == 0 ) return;
  237. n_ += n;
  238. if( m_ > 0 )
  239. {
  240. std::size_t k = 16 - m_;
  241. if( n < k )
  242. {
  243. k = n;
  244. }
  245. std::memcpy( buffer_ + m_, p, k );
  246. p += k;
  247. n -= k;
  248. m_ += k;
  249. if( m_ < 16 ) return;
  250. BOOST_ASSERT( m_ == 16 );
  251. update_( buffer_, 1 );
  252. m_ = 0;
  253. }
  254. BOOST_ASSERT( m_ == 0 );
  255. {
  256. std::size_t k = n / 16;
  257. update_( p, k );
  258. p += 16 * k;
  259. n -= 16 * k;
  260. }
  261. BOOST_ASSERT( n < 16 );
  262. if( n > 0 )
  263. {
  264. std::memcpy( buffer_, p, n );
  265. m_ = n;
  266. }
  267. BOOST_ASSERT( m_ == n_ % 16 );
  268. }
  269. result_type result()
  270. {
  271. BOOST_ASSERT( m_ == n_ % 16 );
  272. std::memset( buffer_ + m_, 0, 16 - m_ );
  273. std::uint64_t h1 = h1_, h2 = h2_;
  274. std::uint64_t k1 = detail::read64le( buffer_ + 0 );
  275. std::uint64_t k2 = detail::read64le( buffer_ + 8 );
  276. k1 *= c1; k1 = detail::rotl( k1, 31 ); k1 *= c2; h1 ^= k1;
  277. k2 *= c2; k2 = detail::rotl( k2, 33 ); k2 *= c1; h2 ^= k2;
  278. h1 ^= n_;
  279. h2 ^= n_;
  280. h1 += h2;
  281. h2 += h1;
  282. h1 = fmix( h1 );
  283. h2 = fmix( h2 );
  284. h1 += h2;
  285. h2 += h1;
  286. n_ += 16 - m_;
  287. m_ = 0;
  288. // clear buffered plaintext
  289. std::memset( buffer_, 0, 16 );
  290. result_type r;
  291. detail::write64le( &r[ 0 ], h1 );
  292. detail::write64le( &r[ 8 ], h2 );
  293. return r;
  294. }
  295. };
  296. } // namespace hash2
  297. } // namespace boost
  298. #endif // #ifndef BOOST_HASH2_MURMUR3_HPP_INCLUDED