20 #ifndef _AUXHASHMAP_INTERNAL_HPP_
21 #define _AUXHASHMAP_INTERNAL_HPP_
25 #include "HllUtil.hpp"
26 #include "AuxHashMap.hpp"
31 AuxHashMap<A>::AuxHashMap(uint8_t lgAuxArrInts, uint8_t lgConfigK,
const A& allocator):
33 lgAuxArrInts(lgAuxArrInts),
35 entries(1ULL << lgAuxArrInts, 0, allocator)
39 AuxHashMap<A>* AuxHashMap<A>::newAuxHashMap(uint8_t lgAuxArrInts, uint8_t lgConfigK,
const A& allocator) {
40 return new (ahmAlloc(allocator).allocate(1)) AuxHashMap<A>(lgAuxArrInts, lgConfigK, allocator);
44 AuxHashMap<A>* AuxHashMap<A>::newAuxHashMap(
const AuxHashMap& that) {
45 return new (ahmAlloc(that.entries.get_allocator()).allocate(1)) AuxHashMap<A>(that);
49 AuxHashMap<A>* AuxHashMap<A>::deserialize(
const void* bytes,
size_t len,
51 uint32_t auxCount, uint8_t lgAuxArrInts,
52 bool srcCompact,
const A& allocator) {
53 uint8_t lgArrInts = lgAuxArrInts;
55 lgArrInts = HllUtil<A>::computeLgArrInts(HLL, auxCount, lgConfigK);
57 lgArrInts = lgAuxArrInts;
60 const uint32_t configKmask = (1 << lgConfigK) - 1;
62 AuxHashMap<A>* auxHashMap;
63 const uint32_t* auxPtr =
static_cast<const uint32_t*
>(bytes);
65 if (len < auxCount *
sizeof(
int)) {
66 throw std::out_of_range(
"Input array too small to hold AuxHashMap image");
68 auxHashMap =
new (ahmAlloc(allocator).allocate(1)) AuxHashMap<A>(lgArrInts, lgConfigK, allocator);
69 for (uint32_t i = 0; i < auxCount; ++i) {
70 const uint32_t pair = auxPtr[i];
71 const uint32_t slotNo = HllUtil<A>::getLow26(pair) & configKmask;
72 const uint8_t value = HllUtil<A>::getValue(pair);
73 auxHashMap->mustAdd(slotNo, value);
76 uint32_t itemsToRead = 1 << lgAuxArrInts;
77 if (len < itemsToRead *
sizeof(uint32_t)) {
78 throw std::out_of_range(
"Input array too small to hold AuxHashMap image");
80 auxHashMap =
new (ahmAlloc(allocator).allocate(1)) AuxHashMap<A>(lgArrInts, lgConfigK, allocator);
81 for (uint32_t i = 0; i < itemsToRead; ++i) {
82 const uint32_t pair = auxPtr[i];
83 if (pair == hll_constants::EMPTY) {
continue; }
84 const uint32_t slotNo = HllUtil<A>::getLow26(pair) & configKmask;
85 const uint8_t value = HllUtil<A>::getValue(pair);
86 auxHashMap->mustAdd(slotNo, value);
90 if (auxHashMap->getAuxCount() != auxCount) {
91 make_deleter()(auxHashMap);
92 throw std::invalid_argument(
"Deserialized AuxHashMap has wrong number of entries");
99 AuxHashMap<A>* AuxHashMap<A>::deserialize(std::istream& is, uint8_t lgConfigK,
100 uint32_t auxCount, uint8_t lgAuxArrInts,
101 bool srcCompact,
const A& allocator) {
102 uint8_t lgArrInts = lgAuxArrInts;
104 lgArrInts = HllUtil<A>::computeLgArrInts(HLL, auxCount, lgConfigK);
106 lgArrInts = lgAuxArrInts;
109 AuxHashMap<A>* auxHashMap =
new (ahmAlloc(allocator).allocate(1)) AuxHashMap<A>(lgArrInts, lgConfigK, allocator);
110 typedef std::unique_ptr<AuxHashMap<A>, std::function<void(AuxHashMap<A>*)>> aux_hash_map_ptr;
111 aux_hash_map_ptr aux_ptr(auxHashMap, auxHashMap->make_deleter());
113 const uint32_t configKmask = (1 << lgConfigK) - 1;
116 for (uint32_t i = 0; i < auxCount; ++i) {
117 const auto pair = read<int>(is);
118 uint32_t slotNo = HllUtil<A>::getLow26(pair) & configKmask;
119 uint8_t value = HllUtil<A>::getValue(pair);
120 auxHashMap->mustAdd(slotNo, value);
123 const uint32_t itemsToRead = 1 << lgAuxArrInts;
124 for (uint32_t i = 0; i < itemsToRead; ++i) {
125 const auto pair = read<int>(is);
126 if (pair == hll_constants::EMPTY) {
continue; }
127 const uint32_t slotNo = HllUtil<A>::getLow26(pair) & configKmask;
128 const uint8_t value = HllUtil<A>::getValue(pair);
129 auxHashMap->mustAdd(slotNo, value);
133 if (auxHashMap->getAuxCount() != auxCount) {
134 make_deleter()(auxHashMap);
135 throw std::invalid_argument(
"Deserialized AuxHashMap has wrong number of entries");
138 return aux_ptr.release();
142 std::function<void(AuxHashMap<A>*)> AuxHashMap<A>::make_deleter() {
143 return [](AuxHashMap<A>* ptr) {
144 ahmAlloc alloc(ptr->entries.get_allocator());
146 alloc.deallocate(ptr, 1);
151 AuxHashMap<A>* AuxHashMap<A>::copy()
const {
152 return new (ahmAlloc(entries.get_allocator()).allocate(1)) AuxHashMap<A>(*
this);
156 uint32_t AuxHashMap<A>::getAuxCount()
const {
161 uint32_t* AuxHashMap<A>::getAuxIntArr(){
162 return entries.data();
166 uint8_t AuxHashMap<A>::getLgAuxArrInts()
const {
171 uint32_t AuxHashMap<A>::getCompactSizeBytes()
const {
172 return auxCount << 2;
176 uint32_t AuxHashMap<A>::getUpdatableSizeBytes()
const {
177 return 4 << lgAuxArrInts;
181 void AuxHashMap<A>::mustAdd(uint32_t slotNo, uint8_t value) {
182 const int32_t index = find(entries.data(), lgAuxArrInts, lgConfigK, slotNo);
183 const uint32_t entry_pair = HllUtil<A>::pair(slotNo, value);
185 throw std::invalid_argument(
"Found a slotNo that should not be there: SlotNo: "
186 + std::to_string(slotNo) +
", Value: " + std::to_string(value));
190 entries[~index] = entry_pair;
196 uint8_t AuxHashMap<A>::mustFindValueFor(uint32_t slotNo)
const {
197 const int32_t index = find(entries.data(), lgAuxArrInts, lgConfigK, slotNo);
199 return HllUtil<A>::getValue(entries[index]);
202 throw std::invalid_argument(
"slotNo not found: " + std::to_string(slotNo));
206 void AuxHashMap<A>::mustReplace(uint32_t slotNo, uint8_t value) {
207 const int32_t idx = find(entries.data(), lgAuxArrInts, lgConfigK, slotNo);
209 entries[idx] = HllUtil<A>::pair(slotNo, value);
213 throw std::invalid_argument(
"Pair not found: SlotNo: " + std::to_string(slotNo)
214 +
", Value: " + std::to_string(value));
218 void AuxHashMap<A>::checkGrow() {
219 if ((hll_constants::RESIZE_DENOM * auxCount) > (hll_constants::RESIZE_NUMER * (1 << lgAuxArrInts))) {
225 void AuxHashMap<A>::growAuxSpace() {
226 const int configKmask = (1 << lgConfigK) - 1;
227 const int newArrLen = 1 << ++lgAuxArrInts;
228 vector_int entries_new(newArrLen, 0, entries.get_allocator());
229 for (
size_t i = 0; i < entries.size(); ++i) {
230 const uint32_t fetched = entries[i];
231 if (fetched != hll_constants::EMPTY) {
233 const int32_t idx = find(entries_new.data(), lgAuxArrInts, lgConfigK, fetched & configKmask);
234 entries_new[~idx] = fetched;
237 entries = std::move(entries_new);
246 int32_t AuxHashMap<A>::find(
const uint32_t* auxArr, uint8_t lgAuxArrInts, uint8_t lgConfigK, uint32_t slotNo) {
247 const uint32_t auxArrMask = (1 << lgAuxArrInts) - 1;
248 const uint32_t configKmask = (1 << lgConfigK) - 1;
249 uint32_t probe = slotNo & auxArrMask;
250 const uint32_t loopIndex = probe;
252 const uint32_t arrVal = auxArr[probe];
253 if (arrVal == hll_constants::EMPTY) {
256 else if (slotNo == (arrVal & configKmask)) {
259 const uint32_t stride = (slotNo >> lgAuxArrInts) | 1;
260 probe = (probe + stride) & auxArrMask;
261 }
while (probe != loopIndex);
262 throw std::runtime_error(
"Key not found and no empty slots!");
266 coupon_iterator<A> AuxHashMap<A>::begin(
bool all)
const {
267 return coupon_iterator<A>(entries.data(), 1ULL << lgAuxArrInts, 0, all);
271 coupon_iterator<A> AuxHashMap<A>::end()
const {
272 return coupon_iterator<A>(entries.data(), 1ULL << lgAuxArrInts, 1ULL << lgAuxArrInts,
false);
DataSketches namespace.
Definition: binomial_bounds.hpp:38