General Purpose library for Freestanding C++ and POSIX systems
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

209 líneas
4.0 KiB

  1. #pragma once
  2. #include <gp/algorithm/tmp_manip.hpp>
  3. #include <gp/array.hpp>
  4. #include <gp/exception.hpp>
  5. #include <atomic>
  6. #include <stdint.h>
  7. namespace gp {
  8. struct linear_skipstone {
  9. constexpr static size_t ccbits = 1;
  10. constexpr static size_t cclast = 1;
  11. size_t ret = 0;
  12. void next() {
  13. ++ret;
  14. }
  15. operator size_t() {
  16. return ret;
  17. }
  18. };
  19. struct stepcache_skipstone {
  20. constexpr static size_t ccbits = 7;
  21. constexpr static size_t cclast = 127;
  22. constexpr static size_t list[128] = {
  23. 0, 1, 2, 3,
  24. 8, 9, 10, 11,
  25. 20, 21, 22, 23,
  26. 36, 37, 38, 39,
  27. 56, 57, 58, 59,
  28. 80, 81, 82, 83,
  29. 108, 109, 110, 111,
  30. 140, 141, 142, 143,
  31. 176, 177, 178, 179,
  32. 216, 217, 218, 219,
  33. 260, 261, 262, 263,
  34. 308, 309, 310, 311,
  35. 360, 361, 362, 363,
  36. 416, 417, 418, 419,
  37. 476, 477, 478, 479,
  38. 540, 541, 542, 543,
  39. 608, 609, 610, 611,
  40. 680, 681, 682, 683,
  41. 756, 757, 758, 759,
  42. 836, 837, 838, 839,
  43. 920, 921, 922, 923,
  44. 1008, 1009, 1010, 1011,
  45. 1100, 1101, 1102, 1103,
  46. 1196, 1197, 1198, 1199,
  47. 1296, 1297, 1298, 1299,
  48. 1400, 1401, 1402, 1403,
  49. 1508, 1509, 1510, 1511,
  50. 1736, 1737, 1738, 1739,
  51. 1856, 1857, 1858, 1859,
  52. 1980, 1981, 1982, 1983,
  53. 2108, 2109, 2110, 2111,
  54. 2240, 2241, 2242, 2243
  55. };
  56. size_t ret = 0;
  57. void next() {
  58. ++ret;
  59. }
  60. operator size_t() {
  61. [[unlikely]] if ( ret >= 128 )
  62. return ret+list[127];
  63. return list[ret];
  64. }
  65. };
  66. template<typename hash_type = uint32_t, uint8_t magnitude = 20, uint8_t remainder = (8*sizeof(hash_type))-magnitude, typename skipstone_t = linear_skipstone>
  67. class quotient_filter {
  68. constexpr static size_t phys_size = (1 << magnitude) / 32;
  69. using rem_t = typename gp::either<(remainder<=16), uint16_t, uint32_t>::type;
  70. struct node{
  71. //rem_t ccount : skipstone_t::ccbits;
  72. rem_t is_occupied : 1;
  73. rem_t is_deleted : 1;
  74. rem_t r : remainder;
  75. };
  76. gp::array<
  77. node,
  78. 1 << magnitude
  79. > data;
  80. void skipstone_killswitch(size_t q, size_t skip)
  81. {
  82. if(q == (q+skip)%data.size())
  83. {
  84. if constexpr (gp_config::has_exceptions)
  85. {
  86. throw gp::runtime_error("infinite skiploop detected");
  87. }
  88. else
  89. {
  90. exit((int)gp_errorcodes::infinite_skipstone);
  91. }
  92. }
  93. }
  94. public:
  95. void set_hash(hash_type v)
  96. {
  97. const size_t q = v & ((1 << magnitude)-1);
  98. const size_t r = (v >> magnitude) & ((1 << remainder)-1);
  99. skipstone_t skip;
  100. for(;;)
  101. {
  102. auto& slot = data[(q+skip)%data.size()];
  103. if(slot.is_occupied)
  104. {
  105. if(slot.is_deleted)
  106. {
  107. slot.r = r;
  108. slot.is_deleted = false;
  109. for(;;)
  110. {
  111. skip.next();
  112. slot = data[(q+skip)%data.size()];
  113. if(!slot.is_occupied)
  114. {
  115. return;
  116. }
  117. else if(slot.r == r)
  118. {
  119. slot.is_deleted = true;
  120. }
  121. skipstone_killswitch(q, skip);
  122. }
  123. }
  124. if(slot.r == r)
  125. {
  126. return;
  127. }
  128. skip.next();
  129. }
  130. else
  131. {
  132. slot.r = r;
  133. slot.is_occupied = true;
  134. slot.is_deleted = false;
  135. return;
  136. }
  137. skipstone_killswitch(q, skip);
  138. }
  139. }
  140. bool test_hash(hash_type v)
  141. {
  142. const size_t q = v & ((1 << magnitude)-1);
  143. const size_t r = (v >> magnitude) & ((1 << remainder)-1);
  144. skipstone_t skip;
  145. for(;;)
  146. {
  147. auto& slot = data[(q+skip)%data.size()];
  148. if(slot.is_occupied)
  149. {
  150. if(!slot.is_deleted)
  151. {
  152. if(slot.r == r)
  153. {
  154. return true;
  155. }
  156. }
  157. skip.next();
  158. }
  159. else
  160. {
  161. return false;
  162. }
  163. skipstone_killswitch(q, skip);
  164. }
  165. }
  166. void remove_hash(hash_type v)
  167. {
  168. const size_t q = v & ((1 << magnitude)-1);
  169. const size_t r = (v >> magnitude) & ((1 << remainder)-1);
  170. skipstone_t skip;
  171. for(;;)
  172. {
  173. auto& slot = data[(q+skip)%data.size()];
  174. if(slot.is_occupied)
  175. {
  176. if(!slot.is_deleted)
  177. {
  178. if(slot.r == r)
  179. {
  180. slot.is_deleted = true;
  181. slot.is_occupied = false;
  182. }
  183. }
  184. skip.next();
  185. }
  186. else
  187. {
  188. return;
  189. }
  190. skipstone_killswitch(q, skip);
  191. }
  192. }
  193. };
  194. }