hash_test.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2012 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #include "util/hash.h"
  10. #include <cstring>
  11. #include <type_traits>
  12. #include <vector>
  13. #include "test_util/testharness.h"
  14. #include "util/coding.h"
  15. #include "util/coding_lean.h"
  16. #include "util/hash128.h"
  17. #include "util/math.h"
  18. #include "util/math128.h"
  19. using ROCKSDB_NAMESPACE::BijectiveHash2x64;
  20. using ROCKSDB_NAMESPACE::BijectiveUnhash2x64;
  21. using ROCKSDB_NAMESPACE::DecodeFixed64;
  22. using ROCKSDB_NAMESPACE::EncodeFixed32;
  23. using ROCKSDB_NAMESPACE::EndianSwapValue;
  24. using ROCKSDB_NAMESPACE::GetSliceHash64;
  25. using ROCKSDB_NAMESPACE::Hash;
  26. using ROCKSDB_NAMESPACE::Hash128;
  27. using ROCKSDB_NAMESPACE::Hash2x64;
  28. using ROCKSDB_NAMESPACE::Hash64;
  29. using ROCKSDB_NAMESPACE::Lower32of64;
  30. using ROCKSDB_NAMESPACE::Lower64of128;
  31. using ROCKSDB_NAMESPACE::ReverseBits;
  32. using ROCKSDB_NAMESPACE::Slice;
  33. using ROCKSDB_NAMESPACE::Unsigned128;
  34. using ROCKSDB_NAMESPACE::Upper32of64;
  35. using ROCKSDB_NAMESPACE::Upper64of128;
  36. // The hash algorithm is part of the file format, for example for the Bloom
  37. // filters. Test that the hash values are stable for a set of random strings of
  38. // varying lengths.
  39. TEST(HashTest, Values) {
  40. constexpr uint32_t kSeed = 0xbc9f1d34; // Same as BloomHash.
  41. EXPECT_EQ(Hash("", 0, kSeed), 3164544308u);
  42. EXPECT_EQ(Hash("\x08", 1, kSeed), 422599524u);
  43. EXPECT_EQ(Hash("\x17", 1, kSeed), 3168152998u);
  44. EXPECT_EQ(Hash("\x9a", 1, kSeed), 3195034349u);
  45. EXPECT_EQ(Hash("\x1c", 1, kSeed), 2651681383u);
  46. EXPECT_EQ(Hash("\x4d\x76", 2, kSeed), 2447836956u);
  47. EXPECT_EQ(Hash("\x52\xd5", 2, kSeed), 3854228105u);
  48. EXPECT_EQ(Hash("\x91\xf7", 2, kSeed), 31066776u);
  49. EXPECT_EQ(Hash("\xd6\x27", 2, kSeed), 1806091603u);
  50. EXPECT_EQ(Hash("\x30\x46\x0b", 3, kSeed), 3808221797u);
  51. EXPECT_EQ(Hash("\x56\xdc\xd6", 3, kSeed), 2157698265u);
  52. EXPECT_EQ(Hash("\xd4\x52\x33", 3, kSeed), 1721992661u);
  53. EXPECT_EQ(Hash("\x6a\xb5\xf4", 3, kSeed), 2469105222u);
  54. EXPECT_EQ(Hash("\x67\x53\x81\x1c", 4, kSeed), 118283265u);
  55. EXPECT_EQ(Hash("\x69\xb8\xc0\x88", 4, kSeed), 3416318611u);
  56. EXPECT_EQ(Hash("\x1e\x84\xaf\x2d", 4, kSeed), 3315003572u);
  57. EXPECT_EQ(Hash("\x46\xdc\x54\xbe", 4, kSeed), 447346355u);
  58. EXPECT_EQ(Hash("\xd0\x7a\x6e\xea\x56", 5, kSeed), 4255445370u);
  59. EXPECT_EQ(Hash("\x86\x83\xd5\xa4\xd8", 5, kSeed), 2390603402u);
  60. EXPECT_EQ(Hash("\xb7\x46\xbb\x77\xce", 5, kSeed), 2048907743u);
  61. EXPECT_EQ(Hash("\x6c\xa8\xbc\xe5\x99", 5, kSeed), 2177978500u);
  62. EXPECT_EQ(Hash("\x5c\x5e\xe1\xa0\x73\x81", 6, kSeed), 1036846008u);
  63. EXPECT_EQ(Hash("\x08\x5d\x73\x1c\xe5\x2e", 6, kSeed), 229980482u);
  64. EXPECT_EQ(Hash("\x42\xfb\xf2\x52\xb4\x10", 6, kSeed), 3655585422u);
  65. EXPECT_EQ(Hash("\x73\xe1\xff\x56\x9c\xce", 6, kSeed), 3502708029u);
  66. EXPECT_EQ(Hash("\x5c\xbe\x97\x75\x54\x9a\x52", 7, kSeed), 815120748u);
  67. EXPECT_EQ(Hash("\x16\x82\x39\x49\x88\x2b\x36", 7, kSeed), 3056033698u);
  68. EXPECT_EQ(Hash("\x59\x77\xf0\xa7\x24\xf4\x78", 7, kSeed), 587205227u);
  69. EXPECT_EQ(Hash("\xd3\xa5\x7c\x0e\xc0\x02\x07", 7, kSeed), 2030937252u);
  70. EXPECT_EQ(Hash("\x31\x1b\x98\x75\x96\x22\xd3\x9a", 8, kSeed), 469635402u);
  71. EXPECT_EQ(Hash("\x38\xd6\xf7\x28\x20\xb4\x8a\xe9", 8, kSeed), 3530274698u);
  72. EXPECT_EQ(Hash("\xbb\x18\x5d\xf4\x12\x03\xf7\x99", 8, kSeed), 1974545809u);
  73. EXPECT_EQ(Hash("\x80\xd4\x3b\x3b\xae\x22\xa2\x78", 8, kSeed), 3563570120u);
  74. EXPECT_EQ(Hash("\x1a\xb5\xd0\xfe\xab\xc3\x61\xb2\x99", 9, kSeed),
  75. 2706087434u);
  76. EXPECT_EQ(Hash("\x8e\x4a\xc3\x18\x20\x2f\x06\xe6\x3c", 9, kSeed),
  77. 1534654151u);
  78. EXPECT_EQ(Hash("\xb6\xc0\xdd\x05\x3f\xc4\x86\x4c\xef", 9, kSeed),
  79. 2355554696u);
  80. EXPECT_EQ(Hash("\x9a\x5f\x78\x0d\xaf\x50\xe1\x1f\x55", 9, kSeed),
  81. 1400800912u);
  82. EXPECT_EQ(Hash("\x22\x6f\x39\x1f\xf8\xdd\x4f\x52\x17\x94", 10, kSeed),
  83. 3420325137u);
  84. EXPECT_EQ(Hash("\x32\x89\x2a\x75\x48\x3a\x4a\x02\x69\xdd", 10, kSeed),
  85. 3427803584u);
  86. EXPECT_EQ(Hash("\x06\x92\x5c\xf4\x88\x0e\x7e\x68\x38\x3e", 10, kSeed),
  87. 1152407945u);
  88. EXPECT_EQ(Hash("\xbd\x2c\x63\x38\xbf\xe9\x78\xb7\xbf\x15", 10, kSeed),
  89. 3382479516u);
  90. }
  91. // The hash algorithm is part of the file format, for example for the Bloom
  92. // filters.
  93. TEST(HashTest, Hash64Misc) {
  94. constexpr uint32_t kSeed = 0; // Same as GetSliceHash64
  95. for (char fill : {'\0', 'a', '1', '\xff'}) {
  96. const size_t max_size = 1000;
  97. const std::string str(max_size, fill);
  98. for (size_t size = 0; size <= max_size; ++size) {
  99. uint64_t here = Hash64(str.data(), size, kSeed);
  100. // Must be same as unseeded Hash64 and GetSliceHash64
  101. EXPECT_EQ(here, Hash64(str.data(), size));
  102. EXPECT_EQ(here, GetSliceHash64(Slice(str.data(), size)));
  103. // Upper and Lower must reconstruct hash
  104. EXPECT_EQ(here, (uint64_t{Upper32of64(here)} << 32) | Lower32of64(here));
  105. EXPECT_EQ(here, (uint64_t{Upper32of64(here)} << 32) + Lower32of64(here));
  106. EXPECT_EQ(here, (uint64_t{Upper32of64(here)} << 32) ^ Lower32of64(here));
  107. // Seed changes hash value (with high probability)
  108. for (uint64_t var_seed = 1; var_seed != 0; var_seed <<= 1) {
  109. EXPECT_NE(here, Hash64(str.data(), size, var_seed));
  110. }
  111. // Size changes hash value (with high probability)
  112. size_t max_smaller_by = std::min(size_t{30}, size);
  113. for (size_t smaller_by = 1; smaller_by <= max_smaller_by; ++smaller_by) {
  114. EXPECT_NE(here, Hash64(str.data(), size - smaller_by, kSeed));
  115. }
  116. }
  117. }
  118. }
  119. // Test that hash values are "non-trivial" for "trivial" inputs
  120. TEST(HashTest, Hash64Trivial) {
  121. // Thorough test too slow for regression testing
  122. constexpr bool thorough = false;
  123. // For various seeds, make sure hash of empty string is not zero.
  124. constexpr uint64_t max_seed = thorough ? 0x1000000 : 0x10000;
  125. for (uint64_t seed = 0; seed < max_seed; ++seed) {
  126. uint64_t here = Hash64("", 0, seed);
  127. EXPECT_NE(Lower32of64(here), 0u);
  128. EXPECT_NE(Upper32of64(here), 0u);
  129. }
  130. // For standard seed, make sure hash of small strings are not zero
  131. constexpr uint32_t kSeed = 0; // Same as GetSliceHash64
  132. char input[4];
  133. constexpr int max_len = thorough ? 3 : 2;
  134. for (int len = 1; len <= max_len; ++len) {
  135. for (uint32_t i = 0; (i >> (len * 8)) == 0; ++i) {
  136. EncodeFixed32(input, i);
  137. uint64_t here = Hash64(input, len, kSeed);
  138. EXPECT_NE(Lower32of64(here), 0u);
  139. EXPECT_NE(Upper32of64(here), 0u);
  140. }
  141. }
  142. }
  143. // Test that the hash values are stable for a set of random strings of
  144. // varying small lengths.
  145. TEST(HashTest, Hash64SmallValueSchema) {
  146. constexpr uint32_t kSeed = 0; // Same as GetSliceHash64
  147. EXPECT_EQ(Hash64("", 0, kSeed), uint64_t{5999572062939766020u});
  148. EXPECT_EQ(Hash64("\x08", 1, kSeed), uint64_t{583283813901344696u});
  149. EXPECT_EQ(Hash64("\x17", 1, kSeed), uint64_t{16175549975585474943u});
  150. EXPECT_EQ(Hash64("\x9a", 1, kSeed), uint64_t{16322991629225003903u});
  151. EXPECT_EQ(Hash64("\x1c", 1, kSeed), uint64_t{13269285487706833447u});
  152. EXPECT_EQ(Hash64("\x4d\x76", 2, kSeed), uint64_t{6859542833406258115u});
  153. EXPECT_EQ(Hash64("\x52\xd5", 2, kSeed), uint64_t{4919611532550636959u});
  154. EXPECT_EQ(Hash64("\x91\xf7", 2, kSeed), uint64_t{14199427467559720719u});
  155. EXPECT_EQ(Hash64("\xd6\x27", 2, kSeed), uint64_t{12292689282614532691u});
  156. EXPECT_EQ(Hash64("\x30\x46\x0b", 3, kSeed), uint64_t{11404699285340020889u});
  157. EXPECT_EQ(Hash64("\x56\xdc\xd6", 3, kSeed), uint64_t{12404347133785524237u});
  158. EXPECT_EQ(Hash64("\xd4\x52\x33", 3, kSeed), uint64_t{15853805298481534034u});
  159. EXPECT_EQ(Hash64("\x6a\xb5\xf4", 3, kSeed), uint64_t{16863488758399383382u});
  160. EXPECT_EQ(Hash64("\x67\x53\x81\x1c", 4, kSeed),
  161. uint64_t{9010661983527562386u});
  162. EXPECT_EQ(Hash64("\x69\xb8\xc0\x88", 4, kSeed),
  163. uint64_t{6611781377647041447u});
  164. EXPECT_EQ(Hash64("\x1e\x84\xaf\x2d", 4, kSeed),
  165. uint64_t{15290969111616346501u});
  166. EXPECT_EQ(Hash64("\x46\xdc\x54\xbe", 4, kSeed),
  167. uint64_t{7063754590279313623u});
  168. EXPECT_EQ(Hash64("\xd0\x7a\x6e\xea\x56", 5, kSeed),
  169. uint64_t{6384167718754869899u});
  170. EXPECT_EQ(Hash64("\x86\x83\xd5\xa4\xd8", 5, kSeed),
  171. uint64_t{16874407254108011067u});
  172. EXPECT_EQ(Hash64("\xb7\x46\xbb\x77\xce", 5, kSeed),
  173. uint64_t{16809880630149135206u});
  174. EXPECT_EQ(Hash64("\x6c\xa8\xbc\xe5\x99", 5, kSeed),
  175. uint64_t{1249038833153141148u});
  176. EXPECT_EQ(Hash64("\x5c\x5e\xe1\xa0\x73\x81", 6, kSeed),
  177. uint64_t{17358142495308219330u});
  178. EXPECT_EQ(Hash64("\x08\x5d\x73\x1c\xe5\x2e", 6, kSeed),
  179. uint64_t{4237646583134806322u});
  180. EXPECT_EQ(Hash64("\x42\xfb\xf2\x52\xb4\x10", 6, kSeed),
  181. uint64_t{4373664924115234051u});
  182. EXPECT_EQ(Hash64("\x73\xe1\xff\x56\x9c\xce", 6, kSeed),
  183. uint64_t{12012981210634596029u});
  184. EXPECT_EQ(Hash64("\x5c\xbe\x97\x75\x54\x9a\x52", 7, kSeed),
  185. uint64_t{5716522398211028826u});
  186. EXPECT_EQ(Hash64("\x16\x82\x39\x49\x88\x2b\x36", 7, kSeed),
  187. uint64_t{15604531309862565013u});
  188. EXPECT_EQ(Hash64("\x59\x77\xf0\xa7\x24\xf4\x78", 7, kSeed),
  189. uint64_t{8601330687345614172u});
  190. EXPECT_EQ(Hash64("\xd3\xa5\x7c\x0e\xc0\x02\x07", 7, kSeed),
  191. uint64_t{8088079329364056942u});
  192. EXPECT_EQ(Hash64("\x31\x1b\x98\x75\x96\x22\xd3\x9a", 8, kSeed),
  193. uint64_t{9844314944338447628u});
  194. EXPECT_EQ(Hash64("\x38\xd6\xf7\x28\x20\xb4\x8a\xe9", 8, kSeed),
  195. uint64_t{10973293517982163143u});
  196. EXPECT_EQ(Hash64("\xbb\x18\x5d\xf4\x12\x03\xf7\x99", 8, kSeed),
  197. uint64_t{9986007080564743219u});
  198. EXPECT_EQ(Hash64("\x80\xd4\x3b\x3b\xae\x22\xa2\x78", 8, kSeed),
  199. uint64_t{1729303145008254458u});
  200. EXPECT_EQ(Hash64("\x1a\xb5\xd0\xfe\xab\xc3\x61\xb2\x99", 9, kSeed),
  201. uint64_t{13253403748084181481u});
  202. EXPECT_EQ(Hash64("\x8e\x4a\xc3\x18\x20\x2f\x06\xe6\x3c", 9, kSeed),
  203. uint64_t{7768754303876232188u});
  204. EXPECT_EQ(Hash64("\xb6\xc0\xdd\x05\x3f\xc4\x86\x4c\xef", 9, kSeed),
  205. uint64_t{12439346786701492u});
  206. EXPECT_EQ(Hash64("\x9a\x5f\x78\x0d\xaf\x50\xe1\x1f\x55", 9, kSeed),
  207. uint64_t{10841838338450144690u});
  208. EXPECT_EQ(Hash64("\x22\x6f\x39\x1f\xf8\xdd\x4f\x52\x17\x94", 10, kSeed),
  209. uint64_t{12883919702069153152u});
  210. EXPECT_EQ(Hash64("\x32\x89\x2a\x75\x48\x3a\x4a\x02\x69\xdd", 10, kSeed),
  211. uint64_t{12692903507676842188u});
  212. EXPECT_EQ(Hash64("\x06\x92\x5c\xf4\x88\x0e\x7e\x68\x38\x3e", 10, kSeed),
  213. uint64_t{6540985900674032620u});
  214. EXPECT_EQ(Hash64("\xbd\x2c\x63\x38\xbf\xe9\x78\xb7\xbf\x15", 10, kSeed),
  215. uint64_t{10551812464348219044u});
  216. }
  217. std::string Hash64TestDescriptor(const char *repeat, size_t limit) {
  218. const char *mod61_encode =
  219. "abcdefghijklmnopqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  220. std::string input;
  221. while (input.size() < limit) {
  222. input.append(repeat);
  223. }
  224. std::string rv;
  225. for (size_t i = 0; i < limit; ++i) {
  226. uint64_t h = GetSliceHash64(Slice(input.data(), i));
  227. rv.append(1, mod61_encode[static_cast<size_t>(h % 61)]);
  228. }
  229. return rv;
  230. }
  231. // XXPH3 changes its algorithm for various sizes up through 250 bytes, so
  232. // we need to check the stability of larger sizes also.
  233. TEST(HashTest, Hash64LargeValueSchema) {
  234. // Each of these derives a "descriptor" from the hash values for all
  235. // lengths up to 430.
  236. // Note that "c" is common for the zero-length string.
  237. EXPECT_EQ(
  238. Hash64TestDescriptor("foo", 430),
  239. "cRhyWsY67B6klRA1udmOuiYuX7IthyGBKqbeosz2hzVglWCmQx8nEdnpkvPfYX56Up2OWOTV"
  240. "lTzfAoYwvtqKzjD8E9xttR2unelbXbIV67NUe6bOO23BxaSFRcA3njGu5cUWfgwOqNoTsszp"
  241. "uPvKRP6qaUR5VdoBkJUCFIefd7edlNK5mv6JYWaGdwxehg65hTkTmjZoPKxTZo4PLyzbL9U4"
  242. "xt12ITSfeP2MfBHuLI2z2pDlBb44UQKVMx27LEoAHsdLp3WfWfgH3sdRBRCHm33UxCM4QmE2"
  243. "xJ7gqSvNwTeH7v9GlC8zWbGroyD3UVNeShMLx29O7tH1biemLULwAHyIw8zdtLMDpEJ8m2ic"
  244. "l6Lb4fDuuFNAs1GCVUthjK8CV8SWI8Rsz5THSwn5CGhpqUwSZcFknjwWIl5rNCvDxXJqYr");
  245. // Note that "1EeRk" is common for "Rocks"
  246. EXPECT_EQ(
  247. Hash64TestDescriptor("Rocks", 430),
  248. "c1EeRkrzgOYWLA8PuhJrwTePJewoB44WdXYDfhbk3ZxTqqg25WlPExDl7IKIQLJvnA6gJxxn"
  249. "9TCSLkFGfJeXehaSS1GBqWSzfhEH4VXiXIUCuxJXxtKXcSC6FrNIQGTZbYDiUOLD6Y5inzrF"
  250. "9etwQhXUBanw55xAUdNMFQAm2GjJ6UDWp2mISLiMMkLjANWMKLaZMqaFLX37qB4MRO1ooVRv"
  251. "zSvaNRSCLxlggQCasQq8icWjzf3HjBlZtU6pd4rkaUxSzHqmo9oM5MghbU5Rtxg8wEfO7lVN"
  252. "5wdMONYecslQTwjZUpO1K3LDf3K3XK6sUXM6ShQQ3RHmMn2acB4YtTZ3QQcHYJSOHn2DuWpa"
  253. "Q8RqzX5lab92YmOLaCdOHq1BPsM7SIBzMdLgePNsJ1vvMALxAaoDUHPxoFLO2wx18IXnyX");
  254. EXPECT_EQ(
  255. Hash64TestDescriptor("RocksDB", 430),
  256. "c1EeRkukbkb28wLTahwD2sfUhZzaBEnF8SVrxnPVB6A7b8CaAl3UKsDZISF92GSq2wDCukOq"
  257. "Jgrsp7A3KZhDiLW8dFXp8UPqPxMCRlMdZeVeJ2dJxrmA6cyt99zkQFj7ELbut6jAeVqARFnw"
  258. "fnWVXOsaLrq7bDCbMcns2DKvTaaqTCLMYxI7nhtLpFN1jR755FRQFcOzrrDbh7QhypjdvlYw"
  259. "cdAMSZgp9JMHxbM23wPSuH6BOFgxejz35PScZfhDPvTOxIy1jc3MZsWrMC3P324zNolO7JdW"
  260. "CX2I5UDKjjaEJfxbgVgJIXxtQGlmj2xkO5sPpjULQV4X2HlY7FQleJ4QRaJIB4buhCA4vUTF"
  261. "eMFlxCIYUpTCsal2qsmnGOWa8WCcefrohMjDj1fjzSvSaQwlpyR1GZHF2uPOoQagiCpHpm");
  262. }
  263. TEST(HashTest, Hash128Misc) {
  264. constexpr uint32_t kSeed = 0; // Same as GetSliceHash128
  265. for (char fill : {'\0', 'a', '1', '\xff', 'e'}) {
  266. const size_t max_size = 1000;
  267. std::string str(max_size, fill);
  268. if (fill == 'e') {
  269. // Use different characters to check endianness handling
  270. for (size_t i = 0; i < str.size(); ++i) {
  271. str[i] += static_cast<char>(i);
  272. }
  273. }
  274. for (size_t size = 0; size <= max_size; ++size) {
  275. Unsigned128 here = Hash128(str.data(), size, kSeed);
  276. // Must be same as unseeded Hash128 and GetSliceHash128
  277. EXPECT_EQ(here, Hash128(str.data(), size));
  278. EXPECT_EQ(here, GetSliceHash128(Slice(str.data(), size)));
  279. {
  280. uint64_t hi, lo;
  281. Hash2x64(str.data(), size, &hi, &lo);
  282. EXPECT_EQ(Lower64of128(here), lo);
  283. EXPECT_EQ(Upper64of128(here), hi);
  284. }
  285. if (size == 16) {
  286. const uint64_t in_hi = DecodeFixed64(str.data() + 8);
  287. const uint64_t in_lo = DecodeFixed64(str.data());
  288. uint64_t hi, lo;
  289. BijectiveHash2x64(in_hi, in_lo, &hi, &lo);
  290. EXPECT_EQ(Lower64of128(here), lo);
  291. EXPECT_EQ(Upper64of128(here), hi);
  292. uint64_t un_hi, un_lo;
  293. BijectiveUnhash2x64(hi, lo, &un_hi, &un_lo);
  294. EXPECT_EQ(in_lo, un_lo);
  295. EXPECT_EQ(in_hi, un_hi);
  296. }
  297. // Upper and Lower must reconstruct hash
  298. EXPECT_EQ(here,
  299. (Unsigned128{Upper64of128(here)} << 64) | Lower64of128(here));
  300. EXPECT_EQ(here,
  301. (Unsigned128{Upper64of128(here)} << 64) ^ Lower64of128(here));
  302. // Seed changes hash value (with high probability)
  303. for (uint64_t var_seed = 1; var_seed != 0; var_seed <<= 1) {
  304. Unsigned128 seeded = Hash128(str.data(), size, var_seed);
  305. EXPECT_NE(here, seeded);
  306. // Must match seeded Hash2x64
  307. {
  308. uint64_t hi, lo;
  309. Hash2x64(str.data(), size, var_seed, &hi, &lo);
  310. EXPECT_EQ(Lower64of128(seeded), lo);
  311. EXPECT_EQ(Upper64of128(seeded), hi);
  312. }
  313. if (size == 16) {
  314. const uint64_t in_hi = DecodeFixed64(str.data() + 8);
  315. const uint64_t in_lo = DecodeFixed64(str.data());
  316. uint64_t hi, lo;
  317. BijectiveHash2x64(in_hi, in_lo, var_seed, &hi, &lo);
  318. EXPECT_EQ(Lower64of128(seeded), lo);
  319. EXPECT_EQ(Upper64of128(seeded), hi);
  320. uint64_t un_hi, un_lo;
  321. BijectiveUnhash2x64(hi, lo, var_seed, &un_hi, &un_lo);
  322. EXPECT_EQ(in_lo, un_lo);
  323. EXPECT_EQ(in_hi, un_hi);
  324. }
  325. }
  326. // Size changes hash value (with high probability)
  327. size_t max_smaller_by = std::min(size_t{30}, size);
  328. for (size_t smaller_by = 1; smaller_by <= max_smaller_by; ++smaller_by) {
  329. EXPECT_NE(here, Hash128(str.data(), size - smaller_by, kSeed));
  330. }
  331. }
  332. }
  333. }
  334. // Test that hash values are "non-trivial" for "trivial" inputs
  335. TEST(HashTest, Hash128Trivial) {
  336. // Thorough test too slow for regression testing
  337. constexpr bool thorough = false;
  338. // For various seeds, make sure hash of empty string is not zero.
  339. constexpr uint64_t max_seed = thorough ? 0x1000000 : 0x10000;
  340. for (uint64_t seed = 0; seed < max_seed; ++seed) {
  341. Unsigned128 here = Hash128("", 0, seed);
  342. EXPECT_NE(Lower64of128(here), 0u);
  343. EXPECT_NE(Upper64of128(here), 0u);
  344. }
  345. // For standard seed, make sure hash of small strings are not zero
  346. constexpr uint32_t kSeed = 0; // Same as GetSliceHash128
  347. char input[4];
  348. constexpr int max_len = thorough ? 3 : 2;
  349. for (int len = 1; len <= max_len; ++len) {
  350. for (uint32_t i = 0; (i >> (len * 8)) == 0; ++i) {
  351. EncodeFixed32(input, i);
  352. Unsigned128 here = Hash128(input, len, kSeed);
  353. EXPECT_NE(Lower64of128(here), 0u);
  354. EXPECT_NE(Upper64of128(here), 0u);
  355. }
  356. }
  357. }
  358. std::string Hash128TestDescriptor(const char *repeat, size_t limit) {
  359. const char *mod61_encode =
  360. "abcdefghijklmnopqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  361. std::string input;
  362. while (input.size() < limit) {
  363. input.append(repeat);
  364. }
  365. std::string rv;
  366. for (size_t i = 0; i < limit; ++i) {
  367. auto h = GetSliceHash128(Slice(input.data(), i));
  368. uint64_t h2 = Upper64of128(h) + Lower64of128(h);
  369. rv.append(1, mod61_encode[static_cast<size_t>(h2 % 61)]);
  370. }
  371. return rv;
  372. }
  373. // XXH3 changes its algorithm for various sizes up through 250 bytes, so
  374. // we need to check the stability of larger sizes also.
  375. TEST(HashTest, Hash128ValueSchema) {
  376. // Each of these derives a "descriptor" from the hash values for all
  377. // lengths up to 430.
  378. // Note that "b" is common for the zero-length string.
  379. EXPECT_EQ(
  380. Hash128TestDescriptor("foo", 430),
  381. "bUMA3As8n9I4vNGhThXlEevxZlyMcbb6TYAlIKJ2f5ponsv99q962rYclQ7u3gfnRdCDQ5JI"
  382. "2LrGUaCycbXrvLFe4SjgRb9RQwCfrnmNQ7VSEwSKMnkGCK3bDbXSrnIh5qLXdtvIZklbJpGH"
  383. "Dqr93BlqF9ubTnOSYkSdx89XvQqflMIW8bjfQp9BPjQejWOeEQspnN1D3sfgVdFhpaQdHYA5"
  384. "pI2XcPlCMFPxvrFuRr7joaDvjNe9IUZaunLPMewuXmC3EL95h52Ju3D7y9RNKhgYxMTrA84B"
  385. "yJrMvyjdm3vlBxet4EN7v2GEyjbGuaZW9UL6lrX6PghJDg7ACfLGdxNbH3qXM4zaiG2RKnL5"
  386. "S3WXKR78RBB5fRFQ8KDIEQjHFvSNsc3GrAEi6W8P2lv8JMTzjBODO2uN4wadVQFT9wpGfV");
  387. // Note that "35D2v" is common for "Rocks"
  388. EXPECT_EQ(
  389. Hash128TestDescriptor("Rocks", 430),
  390. "b35D2vzvklFVDqJmyLRXyApwGGO3EAT3swhe8XJAN3mY2UVPglzdmydxcba6JI2tSvwO6zSu"
  391. "ANpjSM7tc9G5iMhsa7R8GfyCXRO1TnLg7HvdWNdgGGBirxZR68BgT7TQsYJt6zyEyISeXI1n"
  392. "MXA48Xo7dWfJeYN6Z4KWlqZY7TgFXGbks9AX4ehZNSGtIhdO5i58qlgVX1bEejeOVaCcjC79"
  393. "67DrMfOKds7rUQzjBa77sMPcoPW1vu6ljGJPZH3XkRyDMZ1twxXKkNxN3tE8nR7JHwyqBAxE"
  394. "fTcjbOWrLZ1irWxRSombD8sGDEmclgF11IxqEhe3Rt7gyofO3nExGckKkS9KfRqsCHbiUyva"
  395. "JGkJwUHRXaZnh58b4i1Ei9aQKZjXlvIVDixoZrjcNaH5XJIJlRZce9Z9t82wYapTpckYSg");
  396. EXPECT_EQ(
  397. Hash128TestDescriptor("RocksDB", 430),
  398. "b35D2vFUst3XDZCRlSrhmYYakmqImV97LbBsV6EZlOEQpUPH1d1sD3xMKAPlA5UErHehg5O7"
  399. "n966fZqhAf3hRc24kGCLfNAWjyUa7vSNOx3IcPoTyVRFZeFlcCtfl7t1QJumHOCpS33EBmBF"
  400. "hvK13QjBbDWYWeHQhJhgV9Mqbx17TIcvUkEnYZxb8IzWNmjVsJG44Z7v52DjGj1ZzS62S2Vv"
  401. "qWcDO7apvH5VHg68E9Wl6nXP21vlmUqEH9GeWRehfWVvY7mUpsAg5drHHQyDSdiMceiUuUxJ"
  402. "XJqHFcDdzbbPk7xDvbLgWCKvH8k3MpQNWOmbSSRDdAP6nGlDjoTToYkcqVREHJzztSWAAq5h"
  403. "GHSUNJ6OxsMHhf8EhXfHtKyUzRmPtjYyeckQcGmrQfFFLidc6cjMDKCdBG6c6HVBrS7H2R");
  404. }
  405. TEST(FastRange32Test, Values) {
  406. using ROCKSDB_NAMESPACE::FastRange32;
  407. // Zero range
  408. EXPECT_EQ(FastRange32(0, 0), 0U);
  409. EXPECT_EQ(FastRange32(123, 0), 0U);
  410. EXPECT_EQ(FastRange32(0xffffffff, 0), 0U);
  411. // One range
  412. EXPECT_EQ(FastRange32(0, 1), 0U);
  413. EXPECT_EQ(FastRange32(123, 1), 0U);
  414. EXPECT_EQ(FastRange32(0xffffffff, 1), 0U);
  415. // Two range
  416. EXPECT_EQ(FastRange32(0, 2), 0U);
  417. EXPECT_EQ(FastRange32(123, 2), 0U);
  418. EXPECT_EQ(FastRange32(0x7fffffff, 2), 0U);
  419. EXPECT_EQ(FastRange32(0x80000000, 2), 1U);
  420. EXPECT_EQ(FastRange32(0xffffffff, 2), 1U);
  421. // Seven range
  422. EXPECT_EQ(FastRange32(0, 7), 0U);
  423. EXPECT_EQ(FastRange32(123, 7), 0U);
  424. EXPECT_EQ(FastRange32(613566756, 7), 0U);
  425. EXPECT_EQ(FastRange32(613566757, 7), 1U);
  426. EXPECT_EQ(FastRange32(1227133513, 7), 1U);
  427. EXPECT_EQ(FastRange32(1227133514, 7), 2U);
  428. // etc.
  429. EXPECT_EQ(FastRange32(0xffffffff, 7), 6U);
  430. // Big
  431. EXPECT_EQ(FastRange32(1, 0x80000000), 0U);
  432. EXPECT_EQ(FastRange32(2, 0x80000000), 1U);
  433. EXPECT_EQ(FastRange32(4, 0x7fffffff), 1U);
  434. EXPECT_EQ(FastRange32(4, 0x80000000), 2U);
  435. EXPECT_EQ(FastRange32(0xffffffff, 0x7fffffff), 0x7ffffffeU);
  436. EXPECT_EQ(FastRange32(0xffffffff, 0x80000000), 0x7fffffffU);
  437. }
  438. TEST(FastRange64Test, Values) {
  439. using ROCKSDB_NAMESPACE::FastRange64;
  440. // Zero range
  441. EXPECT_EQ(FastRange64(0, 0), 0U);
  442. EXPECT_EQ(FastRange64(123, 0), 0U);
  443. EXPECT_EQ(FastRange64(0xffffFFFF, 0), 0U);
  444. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 0), 0U);
  445. // One range
  446. EXPECT_EQ(FastRange64(0, 1), 0U);
  447. EXPECT_EQ(FastRange64(123, 1), 0U);
  448. EXPECT_EQ(FastRange64(0xffffFFFF, 1), 0U);
  449. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 1), 0U);
  450. // Two range
  451. EXPECT_EQ(FastRange64(0, 2), 0U);
  452. EXPECT_EQ(FastRange64(123, 2), 0U);
  453. EXPECT_EQ(FastRange64(0xffffFFFF, 2), 0U);
  454. EXPECT_EQ(FastRange64(0x7fffFFFFffffFFFF, 2), 0U);
  455. EXPECT_EQ(FastRange64(0x8000000000000000, 2), 1U);
  456. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 2), 1U);
  457. // Seven range
  458. EXPECT_EQ(FastRange64(0, 7), 0U);
  459. EXPECT_EQ(FastRange64(123, 7), 0U);
  460. EXPECT_EQ(FastRange64(0xffffFFFF, 7), 0U);
  461. EXPECT_EQ(FastRange64(2635249153387078802, 7), 0U);
  462. EXPECT_EQ(FastRange64(2635249153387078803, 7), 1U);
  463. EXPECT_EQ(FastRange64(5270498306774157604, 7), 1U);
  464. EXPECT_EQ(FastRange64(5270498306774157605, 7), 2U);
  465. EXPECT_EQ(FastRange64(0x7fffFFFFffffFFFF, 7), 3U);
  466. EXPECT_EQ(FastRange64(0x8000000000000000, 7), 3U);
  467. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 7), 6U);
  468. // Big but 32-bit range
  469. EXPECT_EQ(FastRange64(0x100000000, 0x80000000), 0U);
  470. EXPECT_EQ(FastRange64(0x200000000, 0x80000000), 1U);
  471. EXPECT_EQ(FastRange64(0x400000000, 0x7fffFFFF), 1U);
  472. EXPECT_EQ(FastRange64(0x400000000, 0x80000000), 2U);
  473. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 0x7fffFFFF), 0x7fffFFFEU);
  474. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 0x80000000), 0x7fffFFFFU);
  475. // Big, > 32-bit range
  476. #if SIZE_MAX == UINT64_MAX
  477. EXPECT_EQ(FastRange64(0x7fffFFFFffffFFFF, 0x4200000002), 0x2100000000U);
  478. EXPECT_EQ(FastRange64(0x8000000000000000, 0x4200000002), 0x2100000001U);
  479. EXPECT_EQ(FastRange64(0x0000000000000000, 420000000002), 0U);
  480. EXPECT_EQ(FastRange64(0x7fffFFFFffffFFFF, 420000000002), 210000000000U);
  481. EXPECT_EQ(FastRange64(0x8000000000000000, 420000000002), 210000000001U);
  482. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 420000000002), 420000000001U);
  483. EXPECT_EQ(FastRange64(0xffffFFFFffffFFFF, 0xffffFFFFffffFFFF),
  484. 0xffffFFFFffffFFFEU);
  485. #endif
  486. }
  487. TEST(FastRangeGenericTest, Values) {
  488. using ROCKSDB_NAMESPACE::FastRangeGeneric;
  489. // Generic (including big and small)
  490. // Note that FastRangeGeneric is also tested indirectly above via
  491. // FastRange32 and FastRange64.
  492. EXPECT_EQ(
  493. FastRangeGeneric(uint64_t{0x8000000000000000}, uint64_t{420000000002}),
  494. uint64_t{210000000001});
  495. EXPECT_EQ(FastRangeGeneric(uint64_t{0x8000000000000000}, uint16_t{12468}),
  496. uint16_t{6234});
  497. EXPECT_EQ(FastRangeGeneric(uint32_t{0x80000000}, uint16_t{12468}),
  498. uint16_t{6234});
  499. // Not recommended for typical use because for example this could fail on
  500. // some platforms and pass on others:
  501. // EXPECT_EQ(FastRangeGeneric(static_cast<unsigned long>(0x80000000),
  502. // uint16_t{12468}),
  503. // uint16_t{6234});
  504. }
  505. // for inspection of disassembly
  506. uint32_t FastRange32(uint32_t hash, uint32_t range) {
  507. return ROCKSDB_NAMESPACE::FastRange32(hash, range);
  508. }
  509. // for inspection of disassembly
  510. size_t FastRange64(uint64_t hash, size_t range) {
  511. return ROCKSDB_NAMESPACE::FastRange64(hash, range);
  512. }
  513. // Tests for math.h / math128.h (not worth a separate test binary)
  514. using ROCKSDB_NAMESPACE::BitParity;
  515. using ROCKSDB_NAMESPACE::BitsSetToOne;
  516. using ROCKSDB_NAMESPACE::BitwiseAnd;
  517. using ROCKSDB_NAMESPACE::BottomNBits;
  518. using ROCKSDB_NAMESPACE::ConstexprFloorLog2;
  519. using ROCKSDB_NAMESPACE::CountTrailingZeroBits;
  520. using ROCKSDB_NAMESPACE::DecodeFixed128;
  521. using ROCKSDB_NAMESPACE::DecodeFixedGeneric;
  522. using ROCKSDB_NAMESPACE::DownwardInvolution;
  523. using ROCKSDB_NAMESPACE::EncodeFixed128;
  524. using ROCKSDB_NAMESPACE::EncodeFixedGeneric;
  525. using ROCKSDB_NAMESPACE::FloorLog2;
  526. using ROCKSDB_NAMESPACE::Lower64of128;
  527. using ROCKSDB_NAMESPACE::Multiply64to128;
  528. using ROCKSDB_NAMESPACE::Unsigned128;
  529. using ROCKSDB_NAMESPACE::Upper64of128;
  530. int blah(int x) { return DownwardInvolution(x); }
  531. template <typename T1, typename T2>
  532. static void test_BitwiseAnd(T1 v1, T2 v2) {
  533. auto a = BitwiseAnd(v1, v2);
  534. // Essentially repeating the implementation :-/
  535. if constexpr (sizeof(T1) < sizeof(T2)) {
  536. static_assert(std::is_same_v<decltype(a), T1>);
  537. EXPECT_EQ(a, static_cast<T1>(v1 & v2));
  538. } else {
  539. static_assert(std::is_same_v<decltype(a), T2>);
  540. EXPECT_EQ(a, static_cast<T2>(v1 & v2));
  541. }
  542. }
  543. template <typename T>
  544. static void test_BitOps() {
  545. // This complex code is to generalize to 128-bit values. Otherwise
  546. // we could just use = static_cast<T>(0x5555555555555555ULL);
  547. T everyOtherBit = 0;
  548. for (unsigned i = 0; i < sizeof(T); ++i) {
  549. everyOtherBit = (everyOtherBit << 8) | T{0x55};
  550. }
  551. // This one built using bit operations, as our 128-bit layer
  552. // might not implement arithmetic such as subtraction.
  553. T vm1 = 0; // "v minus one"
  554. for (int i = 0; i < int{8 * sizeof(T)}; ++i) {
  555. T v = T{1} << i;
  556. // If we could directly use arithmetic:
  557. // T vm1 = static_cast<T>(v - 1);
  558. // BottomNBits
  559. {
  560. // An essentially full length value
  561. T x = everyOtherBit;
  562. if (i > 2) {
  563. // Make it slightly irregular
  564. x = x ^ (T{1} << (i / 2));
  565. }
  566. auto a = BottomNBits(x, i);
  567. auto b = BottomNBits(~x, i);
  568. EXPECT_EQ(x | a, x);
  569. EXPECT_EQ(a | b, vm1);
  570. EXPECT_EQ(a & b, T{0});
  571. EXPECT_EQ(BottomNBits(x ^ a, i), T{0});
  572. }
  573. // FloorLog2
  574. if (v > 0) {
  575. EXPECT_EQ(FloorLog2(v), i);
  576. EXPECT_EQ(ConstexprFloorLog2(v), i);
  577. }
  578. if (vm1 > 0) {
  579. EXPECT_EQ(FloorLog2(vm1), i - 1);
  580. EXPECT_EQ(ConstexprFloorLog2(vm1), i - 1);
  581. EXPECT_EQ(FloorLog2(everyOtherBit & vm1), (i - 1) & ~1);
  582. EXPECT_EQ(ConstexprFloorLog2(everyOtherBit & vm1), (i - 1) & ~1);
  583. }
  584. // CountTrailingZeroBits
  585. if (v != 0) {
  586. EXPECT_EQ(CountTrailingZeroBits(v), i);
  587. }
  588. if (vm1 != 0) {
  589. EXPECT_EQ(CountTrailingZeroBits(vm1), 0);
  590. }
  591. if (i < int{8 * sizeof(T)} - 1) {
  592. EXPECT_EQ(CountTrailingZeroBits(~vm1 & everyOtherBit), (i + 1) & ~1);
  593. }
  594. // BitsSetToOne
  595. EXPECT_EQ(BitsSetToOne(v), 1);
  596. EXPECT_EQ(BitsSetToOne(vm1), i);
  597. EXPECT_EQ(BitsSetToOne(vm1 & everyOtherBit), (i + 1) / 2);
  598. // BitParity
  599. EXPECT_EQ(BitParity(v), 1);
  600. EXPECT_EQ(BitParity(vm1), i & 1);
  601. EXPECT_EQ(BitParity(vm1 & everyOtherBit), ((i + 1) / 2) & 1);
  602. // EndianSwapValue
  603. T ev = T{1} << (((sizeof(T) - 1 - (i / 8)) * 8) + i % 8);
  604. EXPECT_EQ(EndianSwapValue(v), ev);
  605. // ReverseBits
  606. EXPECT_EQ(ReverseBits(v), static_cast<T>(T{1} << (8 * sizeof(T) - 1 - i)));
  607. #ifdef HAVE_UINT128_EXTENSION // Uses multiplication
  608. if (std::is_unsigned<T>::value) { // Technical UB on signed type
  609. T rv = T{1} << (8 * sizeof(T) - 1 - i);
  610. EXPECT_EQ(ReverseBits(vm1), static_cast<T>(rv * ~T{1}));
  611. }
  612. #endif
  613. // DownwardInvolution
  614. {
  615. T misc = static_cast<T>(/*random*/ 0xc682cd153d0e3279U +
  616. i * /*random*/ 0x9b3972f3bea0baa3U);
  617. if constexpr (sizeof(T) > 8) {
  618. misc = (misc << 64) | (/*random*/ 0x52af031a38ced62dU +
  619. i * /*random*/ 0x936f803d9752ddc3U);
  620. }
  621. T misc_masked = misc & vm1;
  622. EXPECT_LE(misc_masked, vm1);
  623. T di_misc_masked = DownwardInvolution(misc_masked);
  624. EXPECT_LE(di_misc_masked, vm1);
  625. if (misc_masked > 0) {
  626. // Highest-order 1 in same position
  627. EXPECT_EQ(FloorLog2(misc_masked), FloorLog2(di_misc_masked));
  628. }
  629. // Validate involution property on short value
  630. EXPECT_EQ(DownwardInvolution(di_misc_masked), misc_masked);
  631. // Validate involution property on large value
  632. T di_misc = DownwardInvolution(misc);
  633. EXPECT_EQ(DownwardInvolution(di_misc), misc);
  634. // Highest-order 1 in same position
  635. if (misc > 0) {
  636. EXPECT_EQ(FloorLog2(misc), FloorLog2(di_misc));
  637. }
  638. // Validate distributes over xor.
  639. // static_casts to avoid numerical promotion effects.
  640. EXPECT_EQ(DownwardInvolution(static_cast<T>(misc_masked ^ vm1)),
  641. static_cast<T>(di_misc_masked ^ DownwardInvolution(vm1)));
  642. T misc2 = static_cast<T>(misc >> 1);
  643. EXPECT_EQ(DownwardInvolution(static_cast<T>(misc ^ misc2)),
  644. static_cast<T>(di_misc ^ DownwardInvolution(misc2)));
  645. // Choose some small number of bits to pull off to test combined
  646. // uniqueness guarantee
  647. int in_bits = i % 7;
  648. unsigned in_mask = (unsigned{1} << in_bits) - 1U;
  649. // IMPLICIT: int out_bits = 8 - in_bits;
  650. std::vector<bool> seen(256, false);
  651. for (int j = 0; j < 255; ++j) {
  652. T t_in = misc ^ static_cast<T>(j);
  653. unsigned in = static_cast<unsigned>(t_in);
  654. unsigned out = static_cast<unsigned>(DownwardInvolution(t_in));
  655. unsigned val = ((out << in_bits) | (in & in_mask)) & 255U;
  656. EXPECT_FALSE(seen[val]);
  657. seen[val] = true;
  658. }
  659. if (i + 8 < int{8 * sizeof(T)}) {
  660. // Also test manipulating bits in the middle of input is
  661. // bijective in bottom of output
  662. seen = std::vector<bool>(256, false);
  663. for (int j = 0; j < 255; ++j) {
  664. T in = misc ^ (static_cast<T>(j) << i);
  665. unsigned val = static_cast<unsigned>(DownwardInvolution(in)) & 255U;
  666. EXPECT_FALSE(seen[val]);
  667. seen[val] = true;
  668. }
  669. }
  670. }
  671. // BitwiseAnd
  672. {
  673. test_BitwiseAnd(vm1, static_cast<char>(0x99));
  674. test_BitwiseAnd(v, static_cast<char>(0x99));
  675. test_BitwiseAnd(char{0x66}, vm1);
  676. test_BitwiseAnd(char{0x66}, v);
  677. test_BitwiseAnd(v, int16_t{0x6699});
  678. test_BitwiseAnd(v, uint16_t{0x9966});
  679. test_BitwiseAnd(int64_t{0x1234234534564567}, v);
  680. test_BitwiseAnd(uint64_t{0x9876876576545432}, v);
  681. }
  682. vm1 = (vm1 << 1) | 1;
  683. }
  684. // ConstexprFloorLog2
  685. EXPECT_EQ(ConstexprFloorLog2(T{1}), 0);
  686. EXPECT_EQ(ConstexprFloorLog2(T{2}), 1);
  687. EXPECT_EQ(ConstexprFloorLog2(T{3}), 1);
  688. EXPECT_EQ(ConstexprFloorLog2(T{42}), 5);
  689. }
  690. TEST(MathTest, BitOps) {
  691. test_BitOps<uint32_t>();
  692. test_BitOps<uint64_t>();
  693. test_BitOps<uint16_t>();
  694. test_BitOps<uint8_t>();
  695. test_BitOps<unsigned char>();
  696. test_BitOps<unsigned short>();
  697. test_BitOps<unsigned int>();
  698. test_BitOps<unsigned long>();
  699. test_BitOps<unsigned long long>();
  700. test_BitOps<char>();
  701. test_BitOps<size_t>();
  702. test_BitOps<int32_t>();
  703. test_BitOps<int64_t>();
  704. test_BitOps<int16_t>();
  705. test_BitOps<int8_t>();
  706. test_BitOps<signed char>();
  707. test_BitOps<short>();
  708. test_BitOps<int>();
  709. test_BitOps<long>();
  710. test_BitOps<long long>();
  711. test_BitOps<ptrdiff_t>();
  712. }
  713. TEST(MathTest, BitOps128) { test_BitOps<Unsigned128>(); }
  714. TEST(MathTest, Math128) {
  715. const Unsigned128 sixteenHexOnes = 0x1111111111111111U;
  716. const Unsigned128 thirtyHexOnes = (sixteenHexOnes << 56) | sixteenHexOnes;
  717. const Unsigned128 sixteenHexTwos = 0x2222222222222222U;
  718. const Unsigned128 thirtyHexTwos = (sixteenHexTwos << 56) | sixteenHexTwos;
  719. // v will slide from all hex ones to all hex twos
  720. Unsigned128 v = thirtyHexOnes;
  721. for (int i = 0; i <= 30; ++i) {
  722. // Test bitwise operations
  723. EXPECT_EQ(BitsSetToOne(v), 30);
  724. EXPECT_EQ(BitsSetToOne(~v), 128 - 30);
  725. EXPECT_EQ(BitsSetToOne(v & thirtyHexOnes), 30 - i);
  726. EXPECT_EQ(BitsSetToOne(v | thirtyHexOnes), 30 + i);
  727. EXPECT_EQ(BitsSetToOne(v ^ thirtyHexOnes), 2 * i);
  728. EXPECT_EQ(BitsSetToOne(v & thirtyHexTwos), i);
  729. EXPECT_EQ(BitsSetToOne(v | thirtyHexTwos), 60 - i);
  730. EXPECT_EQ(BitsSetToOne(v ^ thirtyHexTwos), 60 - 2 * i);
  731. // Test comparisons
  732. EXPECT_EQ(v == thirtyHexOnes, i == 0);
  733. EXPECT_EQ(v == thirtyHexTwos, i == 30);
  734. EXPECT_EQ(v > thirtyHexOnes, i > 0);
  735. EXPECT_EQ(v > thirtyHexTwos, false);
  736. EXPECT_EQ(v >= thirtyHexOnes, true);
  737. EXPECT_EQ(v >= thirtyHexTwos, i == 30);
  738. EXPECT_EQ(v < thirtyHexOnes, false);
  739. EXPECT_EQ(v < thirtyHexTwos, i < 30);
  740. EXPECT_EQ(v <= thirtyHexOnes, i == 0);
  741. EXPECT_EQ(v <= thirtyHexTwos, true);
  742. // Update v, clearing upper-most byte
  743. v = ((v << 12) >> 8) | 0x2;
  744. }
  745. for (int i = 0; i < 128; ++i) {
  746. // Test shifts
  747. Unsigned128 sl = thirtyHexOnes << i;
  748. Unsigned128 sr = thirtyHexOnes >> i;
  749. EXPECT_EQ(BitsSetToOne(sl), std::min(30, 32 - i / 4));
  750. EXPECT_EQ(BitsSetToOne(sr), std::max(0, 30 - (i + 3) / 4));
  751. EXPECT_EQ(BitsSetToOne(sl & sr), i % 2 ? 0 : std::max(0, 30 - i / 2));
  752. }
  753. // Test 64x64->128 multiply
  754. Unsigned128 product =
  755. Multiply64to128(0x1111111111111111U, 0x2222222222222222U);
  756. EXPECT_EQ(Lower64of128(product), 2295594818061633090U);
  757. EXPECT_EQ(Upper64of128(product), 163971058432973792U);
  758. }
  759. TEST(MathTest, Coding128) {
  760. const char *in = "_1234567890123456";
  761. // Note: in + 1 is likely unaligned
  762. Unsigned128 decoded = DecodeFixed128(in + 1);
  763. EXPECT_EQ(Lower64of128(decoded), 0x3837363534333231U);
  764. EXPECT_EQ(Upper64of128(decoded), 0x3635343332313039U);
  765. char out[18];
  766. out[0] = '_';
  767. EncodeFixed128(out + 1, decoded);
  768. out[17] = '\0';
  769. EXPECT_EQ(std::string(in), std::string(out));
  770. }
  771. TEST(MathTest, CodingGeneric) {
  772. const char *in = "_1234567890123456";
  773. // Decode
  774. // Note: in + 1 is likely unaligned
  775. Unsigned128 decoded128 = DecodeFixedGeneric<Unsigned128>(in + 1);
  776. EXPECT_EQ(Lower64of128(decoded128), 0x3837363534333231U);
  777. EXPECT_EQ(Upper64of128(decoded128), 0x3635343332313039U);
  778. uint64_t decoded64 = DecodeFixedGeneric<uint64_t>(in + 1);
  779. EXPECT_EQ(decoded64, 0x3837363534333231U);
  780. uint32_t decoded32 = DecodeFixedGeneric<uint32_t>(in + 1);
  781. EXPECT_EQ(decoded32, 0x34333231U);
  782. uint16_t decoded16 = DecodeFixedGeneric<uint16_t>(in + 1);
  783. EXPECT_EQ(decoded16, 0x3231U);
  784. // Encode
  785. char out[18];
  786. out[0] = '_';
  787. memset(out + 1, '\0', 17);
  788. EncodeFixedGeneric(out + 1, decoded128);
  789. EXPECT_EQ(std::string(in), std::string(out));
  790. memset(out + 1, '\0', 9);
  791. EncodeFixedGeneric(out + 1, decoded64);
  792. EXPECT_EQ(std::string("_12345678"), std::string(out));
  793. memset(out + 1, '\0', 5);
  794. EncodeFixedGeneric(out + 1, decoded32);
  795. EXPECT_EQ(std::string("_1234"), std::string(out));
  796. memset(out + 1, '\0', 3);
  797. EncodeFixedGeneric(out + 1, decoded16);
  798. EXPECT_EQ(std::string("_12"), std::string(out));
  799. }
  800. int main(int argc, char **argv) {
  801. fprintf(stderr, "NPHash64 id: %x\n",
  802. static_cast<int>(ROCKSDB_NAMESPACE::GetSliceNPHash64("RocksDB")));
  803. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  804. ::testing::InitGoogleTest(&argc, argv);
  805. return RUN_ALL_TESTS();
  806. }