opt_cmetrohash64_1.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. // Original: metrohash64.cpp
  2. // Port to C: Frank Denis (jedisct1@github)
  3. // Optimized variants: Paul G (paulie-g@github, paulg@perforge.net)
  4. //
  5. //
  6. // The MIT License (MIT)
  7. //
  8. // Copyright (c) 2015 J. Andrew Rogers
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining a copy
  11. // of this software and associated documentation files (the "Software"), to deal
  12. // in the Software without restriction, including without limitation the rights
  13. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. // copies of the Software, and to permit persons to whom the Software is
  15. // furnished to do so, subject to the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be included in all
  18. // copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  26. // SOFTWARE.
  27. //
  28. #include "cmetrohash.h"
  29. #include "opt_cmetrohash.h"
  30. #define DO_16 {\
  31. register uint64_t v0 = hash + (cread_u64(ptr) * k0); ptr += 8; v0 = crotate_right(v0,33) * k1;\
  32. register uint64_t v1 = hash + (cread_u64(ptr) * k1); ptr += 8; v1 = crotate_right(v1,33) * k2;\
  33. v0 ^= crotate_right(v0 * k0, 35) + v1;\
  34. v1 ^= crotate_right(v1 * k3, 35) + v0;\
  35. hash += v1;\
  36. }
  37. #define DO_8 {\
  38. hash += cread_u64(ptr) * k3; ptr += 8;\
  39. hash ^= crotate_right(hash, 33) * k1;\
  40. }
  41. #define DO_4 {\
  42. hash += cread_u32(ptr) * k3; ptr += 4;\
  43. hash ^= crotate_right(hash, 15) * k1;\
  44. }
  45. #define DO_2 {\
  46. hash += cread_u16(ptr) * k3; ptr += 2;\
  47. hash ^= crotate_right(hash, 13) * k1;\
  48. }
  49. #define DO_1 {\
  50. hash += cread_u8 (ptr) * k3;\
  51. hash ^= crotate_right(hash, 25) * k1;\
  52. }
  53. #define OUT {\
  54. hash ^= crotate_right(hash, 33);\
  55. hash *= k0;\
  56. hash ^= crotate_right(hash, 33);\
  57. memcpy(out, &hash, 8);\
  58. return;\
  59. }
  60. void cmetrohash64_1_optshort(const uint8_t * key, uint64_t len, uint32_t seed, uint8_t * out)
  61. {
  62. static const uint64_t k0 = 0xC83A91E1;
  63. static const uint64_t k1 = 0x8648DBDB;
  64. static const uint64_t k2 = 0x7BDEC03B;
  65. static const uint64_t k3 = 0x2F5870A5;
  66. const uint8_t * ptr = key;
  67. const uint8_t * const end = ptr + len;
  68. uint64_t hash = ((((uint64_t) seed) + k2) * k0) + len;
  69. switch (len) {
  70. default:
  71. if (len >= 32)
  72. {
  73. uint64_t v[4];
  74. v[0] = hash;
  75. v[1] = hash;
  76. v[2] = hash;
  77. v[3] = hash;
  78. do
  79. {
  80. v[0] += cread_u64(ptr) * k0; ptr += 8; v[0] = crotate_right(v[0], 29) + v[2];
  81. v[1] += cread_u64(ptr) * k1; ptr += 8; v[1] = crotate_right(v[1], 29) + v[3];
  82. v[2] += cread_u64(ptr) * k2; ptr += 8; v[2] = crotate_right(v[2], 29) + v[0];
  83. v[3] += cread_u64(ptr) * k3; ptr += 8; v[3] = crotate_right(v[3], 29) + v[1];
  84. } while (ptr <= (end - 32));
  85. v[2] ^= crotate_right(((v[0] + v[3]) * k0) + v[1], 33) * k1;
  86. v[3] ^= crotate_right(((v[1] + v[2]) * k1) + v[0], 33) * k0;
  87. v[0] ^= crotate_right(((v[0] + v[2]) * k0) + v[3], 33) * k1;
  88. v[1] ^= crotate_right(((v[1] + v[3]) * k1) + v[2], 33) * k0;
  89. hash += v[0] ^ v[1];
  90. }
  91. if ((end - ptr) >= 16)
  92. {
  93. uint64_t v0 = hash + (cread_u64(ptr) * k0); ptr += 8; v0 = crotate_right(v0, 33) * k1;
  94. uint64_t v1 = hash + (cread_u64(ptr) * k1); ptr += 8; v1 = crotate_right(v1, 33) * k2;
  95. v0 ^= crotate_right(v0 * k0, 35) + v1;
  96. v1 ^= crotate_right(v1 * k3, 35) + v0;
  97. hash += v1;
  98. }
  99. if ((end - ptr) >= 8)
  100. {
  101. hash += cread_u64(ptr) * k3; ptr += 8;
  102. hash ^= crotate_right(hash, 33) * k1;
  103. }
  104. if ((end - ptr) >= 4)
  105. {
  106. hash += cread_u32(ptr) * k3; ptr += 4;
  107. hash ^= crotate_right(hash, 15) * k1;
  108. }
  109. if ((end - ptr) >= 2)
  110. {
  111. hash += cread_u16(ptr) * k3; ptr += 2;
  112. hash ^= crotate_right(hash, 13) * k1;
  113. }
  114. if ((end - ptr) >= 1)
  115. {
  116. hash += cread_u8(ptr) * k3;
  117. hash ^= crotate_right(hash, 25) * k1;
  118. }
  119. hash ^= crotate_right(hash, 33);
  120. hash *= k0;
  121. hash ^= crotate_right(hash, 33);
  122. memcpy(out, &hash, 8);
  123. return;
  124. case 31:
  125. DO_16
  126. DO_8
  127. DO_4
  128. DO_2
  129. DO_1
  130. OUT
  131. case 30:
  132. DO_16
  133. DO_8
  134. DO_4
  135. DO_2
  136. OUT
  137. case 29:
  138. DO_16
  139. DO_8
  140. DO_4
  141. DO_1
  142. OUT
  143. case 28:
  144. DO_16
  145. DO_8
  146. DO_4
  147. OUT
  148. case 27:
  149. DO_16
  150. DO_8
  151. DO_2
  152. DO_1
  153. OUT
  154. case 26:
  155. DO_16
  156. DO_8
  157. DO_2
  158. OUT
  159. case 25:
  160. DO_16
  161. DO_8
  162. DO_1
  163. OUT
  164. case 24:
  165. DO_16
  166. DO_8
  167. OUT
  168. case 23:
  169. DO_16
  170. DO_4
  171. DO_2
  172. DO_1
  173. OUT
  174. case 22:
  175. DO_16
  176. DO_4
  177. DO_2
  178. OUT
  179. case 21:
  180. DO_16
  181. DO_4
  182. DO_1
  183. OUT
  184. case 20:
  185. DO_16
  186. DO_4
  187. OUT
  188. case 19:
  189. DO_16
  190. DO_2
  191. DO_1
  192. OUT
  193. case 18:
  194. DO_16
  195. DO_2
  196. OUT
  197. case 17:
  198. DO_16
  199. DO_1
  200. OUT
  201. case 16:
  202. DO_16
  203. OUT
  204. case 15:
  205. DO_8
  206. DO_4
  207. DO_2
  208. DO_1
  209. OUT
  210. case 14:
  211. DO_8
  212. DO_4
  213. DO_2
  214. OUT
  215. case 13:
  216. DO_8
  217. DO_4
  218. DO_1
  219. OUT
  220. case 12:
  221. DO_8
  222. DO_4
  223. OUT
  224. case 11:
  225. DO_8
  226. DO_2
  227. DO_1
  228. OUT
  229. case 10:
  230. DO_8
  231. DO_2
  232. OUT
  233. case 9:
  234. DO_8
  235. DO_1
  236. OUT
  237. case 8:
  238. DO_8
  239. OUT
  240. case 7:
  241. DO_4
  242. DO_2
  243. DO_1
  244. OUT
  245. case 6:
  246. DO_4
  247. DO_2
  248. OUT
  249. case 5:
  250. DO_4
  251. DO_1
  252. OUT
  253. case 4:
  254. DO_4
  255. OUT
  256. case 3:
  257. DO_2
  258. DO_1
  259. OUT
  260. case 2:
  261. DO_2
  262. OUT
  263. case 1:
  264. DO_1
  265. case 0:
  266. OUT
  267. }
  268. }