in hll/hll_4update.go [128:225]
func shiftToBiggerCurMin(h *hll4ArrayImpl) error {
var (
oldCurMin = h.curMin
newCurMin = oldCurMin + 1
lgConfigK = h.lgConfigK
configK = 1 << lgConfigK
configKmask = configK - 1
numAtNewCurMin = 0
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 i := 0; i < configK; i++ { //724
oldStoredNibble := uint64(h.getNibble(i))
if oldStoredNibble == 0 {
return fmt.Errorf("array slots cannot be 0 at this point")
}
if oldStoredNibble < auxToken {
oldStoredNibble--
h.putNibble(i, byte(oldStoredNibble))
if oldStoredNibble == 0 {
numAtNewCurMin++
}
} else { //oldStoredNibble == AUX_TOKEN
numAuxTokens++
if h.auxHashMap == nil {
return fmt.Errorf("auxHashMap cannot be nil at this point")
}
}
}
// If old auxHashMap exists, walk through it updating some slots and build a new auxHashMap
// if needed.
var (
newAuxMap *auxHashMap
oldAuxMap = h.auxHashMap
)
if oldAuxMap != nil {
var (
slotNum int
oldActualVal int
newShiftedVal int
err error
)
itr := oldAuxMap.iterator()
for itr.nextValid() {
slotNum = itr.getKey() & configKmask
oldActualVal, err = itr.getValue()
if err != nil {
return err
}
newShiftedVal = oldActualVal - newCurMin
if newShiftedVal < 0 {
return fmt.Errorf("newShiftedVal < 0")
}
if h.getNibble(slotNum) != auxToken {
return fmt.Errorf(fmt.Sprintf("Array slot != AUX_TOKEN %d", h.getNibble(slotNum)))
}
if newShiftedVal < auxToken {
if newShiftedVal != 14 {
return fmt.Errorf("newShiftedVal != 14")
}
// 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).
h.putNibble(slotNum, byte(newShiftedVal))
numAuxTokens--
} else { // newShiftedVal >= AUX_TOKEN
// the former exception remains an exception, so must be added to the newAuxMap
if newAuxMap == nil {
newAuxMap = h.getNewAuxHashMap()
}
err := newAuxMap.mustAdd(slotNum, oldActualVal)
if err != nil {
return err
}
}
}
} else {
if numAuxTokens != 0 {
return fmt.Errorf("numAuxTokens != 0")
}
}
if newAuxMap != nil {
if newAuxMap.getAuxCount() != numAuxTokens {
return fmt.Errorf("newAuxMap.getAuxCount() != numAuxTokens")
}
}
h.auxHashMap = newAuxMap
h.curMin = newCurMin
h.numAtCurMin = numAtNewCurMin
return nil
}