in hll/include/Hll4Array-internal.hpp [245:332]
void Hll4Array<A>::shiftToBiggerCurMin() {
const uint8_t newCurMin = this->curMin_ + 1;
const uint32_t configK = 1 << this->lgConfigK_;
const uint32_t configKmask = configK - 1;
uint32_t numAtNewCurMin = 0;
uint32_t numAuxTokens = 0;
// Walk through the slots of 4-bit array decrementing stored values by one unless it
// equals AUX_TOKEN, where it is left alone but counted to be checked later.
// If oldStoredValue is 0 it is an error.
// If the decremented value is 0, we increment numAtNewCurMin.
// Because getNibble is masked to 4 bits oldStoredValue can never be > 15 or negative
for (uint32_t i = 0; i < configK; i++) { //724
uint8_t oldStoredValue = getSlot(i);
if (oldStoredValue == 0) {
throw std::runtime_error("Array slots cannot be 0 at this point.");
}
if (oldStoredValue < hll_constants::AUX_TOKEN) {
putSlot(i, --oldStoredValue);
if (oldStoredValue == 0) { numAtNewCurMin++; }
} else { //oldStoredValue == AUX_TOKEN
numAuxTokens++;
if (auxHashMap_ == nullptr) {
throw std::logic_error("auxHashMap cannot be null at this point");
}
}
}
// If old AuxHashMap exists, walk through it updating some slots and build a new AuxHashMap
// if needed.
AuxHashMap<A>* newAuxMap = nullptr;
if (auxHashMap_ != nullptr) {
uint32_t slotNum;
uint8_t oldActualVal;
uint8_t newShiftedVal;
for (const auto coupon: *auxHashMap_) {
slotNum = HllUtil<A>::getLow26(coupon) & configKmask;
oldActualVal = HllUtil<A>::getValue(coupon);
if (oldActualVal < newCurMin) {
throw std::logic_error("oldActualVal < newCurMin when incrementing curMin");
}
newShiftedVal = oldActualVal - newCurMin;
if (getSlot(slotNum) != hll_constants::AUX_TOKEN) {
throw std::logic_error("getSlot(slotNum) != AUX_TOKEN for item in auxiliary hash map");
}
// Array slot != AUX_TOKEN at getSlot(slotNum);
if (newShiftedVal < hll_constants::AUX_TOKEN) { // 756
if (newShiftedVal != 14) {
throw std::logic_error("newShiftedVal != 14 for item in old auxHashMap despite curMin increment");
}
// The former exception value isn't one anymore, so it stays out of new AuxHashMap.
// Correct the AUX_TOKEN value in the HLL array to the newShiftedVal (14).
putSlot(slotNum, newShiftedVal);
numAuxTokens--;
} else { //newShiftedVal >= AUX_TOKEN
// the former exception remains an exception, so must be added to the newAuxMap
if (newAuxMap == nullptr) {
newAuxMap = AuxHashMap<A>::newAuxHashMap(hll_constants::LG_AUX_ARR_INTS[this->lgConfigK_],
this->lgConfigK_, this->getAllocator());
}
newAuxMap->mustAdd(slotNum, oldActualVal);
}
} //end scan of oldAuxMap
} //end if (auxHashMap != null)
else { // oldAuxMap == null
if (numAuxTokens != 0) {
throw std::logic_error("No auxiliary hash map, but numAuxTokens != 0");
}
}
if (newAuxMap != nullptr) {
if (newAuxMap->getAuxCount() != numAuxTokens) {
throw std::runtime_error("Inconsistent counts: auxCount: " + std::to_string(newAuxMap->getAuxCount())
+ ", HLL tokesn: " + std::to_string(numAuxTokens));
}
}
if (auxHashMap_ != nullptr) {
AuxHashMap<A>::make_deleter()(auxHashMap_);
}
auxHashMap_ = newAuxMap;
this->curMin_ = newCurMin;
this->numAtCurMin_ = numAtNewCurMin;
}