22 #ifndef U32_TABLE_IMPL_HPP_
23 #define U32_TABLE_IMPL_HPP_
32 u32_table<A>::u32_table(
const A& allocator):
40 u32_table<A>::u32_table(uint8_t lg_size, uint8_t num_valid_bits,
const A& allocator):
42 num_valid_bits(num_valid_bits),
44 slots(1ULL << lg_size, UINT32_MAX, allocator)
46 if (lg_size < 2)
throw std::invalid_argument(
"lg_size must be >= 2");
47 if (num_valid_bits < 1 || num_valid_bits > 32)
throw std::invalid_argument(
"num_valid_bits must be between 1 and 32");
51 uint32_t u32_table<A>::get_num_items()
const {
56 const uint32_t* u32_table<A>::get_slots()
const {
61 uint8_t u32_table<A>::get_lg_size()
const {
66 void u32_table<A>::clear() {
67 std::fill(slots.begin(), slots.end(), UINT32_MAX);
72 bool u32_table<A>::maybe_insert(uint32_t item) {
73 const uint32_t index = lookup(item);
74 if (slots[index] == item)
return false;
75 if (slots[index] != UINT32_MAX)
throw std::logic_error(
"could not insert");
78 if (U32_TABLE_UPSIZE_DENOM * num_items > U32_TABLE_UPSIZE_NUMER * (1 << lg_size)) {
85 bool u32_table<A>::maybe_delete(uint32_t item) {
86 const uint32_t index = lookup(item);
87 if (slots[index] == UINT32_MAX)
return false;
88 if (slots[index] != item)
throw std::logic_error(
"item does not exist");
89 if (num_items == 0)
throw std::logic_error(
"delete error");
91 slots[index] = UINT32_MAX;
95 const size_t mask = (1 << lg_size) - 1;
96 size_t probe = (index + 1) & mask;
97 uint32_t fetched = slots[probe];
98 while (fetched != UINT32_MAX) {
99 slots[probe] = UINT32_MAX;
100 must_insert(fetched);
101 probe = (probe + 1) & mask;
102 fetched = slots[probe];
105 if (U32_TABLE_DOWNSIZE_DENOM * num_items < U32_TABLE_DOWNSIZE_NUMER * (1 << lg_size) && lg_size > 2) {
106 rebuild(lg_size - 1);
113 u32_table<A> u32_table<A>::make_from_pairs(
const uint32_t* pairs, uint32_t num_pairs, uint8_t lg_k,
const A& allocator) {
114 uint8_t lg_num_slots = 2;
115 while (U32_TABLE_UPSIZE_DENOM * num_pairs > U32_TABLE_UPSIZE_NUMER * (1 << lg_num_slots)) lg_num_slots++;
116 u32_table<A> table(lg_num_slots, 6 + lg_k, allocator);
119 for (
size_t i = 0; i < num_pairs; i++) {
120 table.must_insert(pairs[i]);
122 table.num_items = num_pairs;
127 uint32_t u32_table<A>::lookup(uint32_t item)
const {
128 const uint32_t size = 1 << lg_size;
129 const uint32_t mask = size - 1;
130 const uint8_t shift = num_valid_bits - lg_size;
131 uint32_t probe = item >> shift;
132 if (probe > mask)
throw std::logic_error(
"probe out of range");
133 while (slots[probe] != item && slots[probe] != UINT32_MAX) {
134 probe = (probe + 1) & mask;
141 void u32_table<A>::must_insert(uint32_t item) {
142 const uint32_t index = lookup(item);
143 if (slots[index] == item)
throw std::logic_error(
"item exists");
144 if (slots[index] != UINT32_MAX)
throw std::logic_error(
"could not insert");
149 void u32_table<A>::rebuild(uint8_t new_lg_size) {
150 if (new_lg_size < 2)
throw std::logic_error(
"lg_size must be >= 2");
151 const uint32_t old_size = 1 << lg_size;
152 const uint32_t new_size = 1 << new_lg_size;
153 if (new_size <= num_items)
throw std::logic_error(
"new_size <= num_items");
154 vector_u32 old_slots = std::move(slots);
155 slots = vector_u32(new_size, UINT32_MAX, old_slots.get_allocator());
156 lg_size = new_lg_size;
157 for (uint32_t i = 0; i < old_size; i++) {
158 if (old_slots[i] != UINT32_MAX) {
159 must_insert(old_slots[i]);
171 auto u32_table<A>::unwrapping_get_items() const -> vector_u32 {
172 if (num_items == 0)
return vector_u32(slots.get_allocator());
173 const uint32_t table_size = 1 << lg_size;
174 vector_u32 result(num_items, 0, slots.get_allocator());
177 size_t r = num_items - 1;
180 uint32_t hi_bit = 1 << (num_valid_bits - 1);
181 while (i < table_size && slots[i] != UINT32_MAX) {
182 const uint32_t item = slots[i++];
183 if (item & hi_bit) { result[r--] = item; }
184 else { result[l++] = item; }
188 while (i < table_size) {
189 const uint32_t item = slots[i++];
190 if (item != UINT32_MAX) result[l++] = item;
192 if (l != r + 1)
throw std::logic_error(
"unwrapping error");
198 void u32_table<A>::merge(
199 const uint32_t* arr_a,
size_t start_a,
size_t length_a,
200 const uint32_t* arr_b,
size_t start_b,
size_t length_b,
201 uint32_t* arr_c,
size_t start_c
203 const size_t length_c = length_a + length_b;
204 const size_t lim_a = start_a + length_a;
205 const size_t lim_b = start_b + length_b;
206 const size_t lim_c = start_c + length_c;
210 for ( ; c < lim_c ; c++) {
211 if (b >= lim_b) { arr_c[c] = arr_a[a++]; }
212 else if (a >= lim_a) { arr_c[c] = arr_b[b++]; }
213 else if (arr_a[a] < arr_b[b]) { arr_c[c] = arr_a[a++]; }
214 else { arr_c[c] = arr_b[b++]; }
216 if (a != lim_a || b != lim_b)
throw std::logic_error(
"merging error");
227 void u32_table<A>::introspective_insertion_sort(uint32_t* a,
size_t l,
size_t r) {
228 const size_t length = r - l;
229 const size_t cost_limit = 8 * length;
231 for (
size_t i = l + 1; i < r; i++) {
234 while (j >= l + 1 && v < a[j - 1]) {
240 if (cost > cost_limit) {
241 knuth_shell_sort3(a, l, r);
248 void u32_table<A>::knuth_shell_sort3(uint32_t* a,
size_t l,
size_t r) {
250 for (h = 1; h < (r - l) / 9; h = 3 * h + 1);
251 for ( ; h > 0; h /= 3) {
252 for (
size_t i = l + h; i < r; i++) {
254 const uint32_t v = a[i];
255 while (j >= l + h && v < a[j - h]) {
DataSketches namespace.
Definition: binomial_bounds.hpp:38