in hll/union.go [365:455]
func mergeHlltoHLLmode(src HllSketch, tgt HllSketch, srcLgK int, tgtLgK int) error {
sw := 0
if srcLgK > tgtLgK {
sw |= 4
}
if src.GetTgtHllType() != TgtHllTypeHll8 {
sw |= 8
}
srcK := 1 << srcLgK
switch sw {
case 0: //HLL_8, srcLgK=tgtLgK, src=heap, tgt=heap
{
srcArr := src.(*hllSketchState).sketch.(*hll8ArrayImpl).hllByteArr
tgtArr := tgt.(*hllSketchState).sketch.(*hll8ArrayImpl).hllByteArr
// Hack to trigger the bound check only once on tgtArr
_ = tgtArr[len(srcArr)-1]
for i, srcV := range srcArr {
if srcV > tgtArr[i] {
tgtArr[i] = srcV
}
}
}
case 8, 9: //!HLL_8, srcLgK=tgtLgK, src=heap, tgt=heap/mem
{
tgtAbsHllArr := tgt.(*hllSketchState).sketch.(*hll8ArrayImpl)
if src.GetTgtHllType() == TgtHllTypeHll4 {
src4 := src.(*hllSketchState).sketch.(*hll4ArrayImpl)
auxHashMap := src4.auxHashMap
curMin := src4.curMin
i := 0
j := 0
for j < srcK {
b := src4.hllByteArr[i]
i++
value := uint(b) & loNibbleMask
if value == auxToken {
v, err := auxHashMap.mustFindValueFor(j)
if err != nil {
return err
}
tgtAbsHllArr.updateSlotNoKxQ(j, v)
} else {
tgtAbsHllArr.updateSlotNoKxQ(j, int(value)+curMin)
}
j++
value = uint(b) >> 4
if value == auxToken {
v, err := auxHashMap.mustFindValueFor(j)
if err != nil {
return err
}
tgtAbsHllArr.updateSlotNoKxQ(j, v)
} else {
tgtAbsHllArr.updateSlotNoKxQ(j, int(value)+curMin)
}
j++
}
} else {
src6 := src.(*hllSketchState).sketch.(*hll6ArrayImpl)
i := 0
j := 0
for j < srcK {
b1 := src6.hllByteArr[i]
b2 := src6.hllByteArr[i+1]
b3 := src6.hllByteArr[i+2]
i += 3
value := uint(b1) & 0x3f
tgtAbsHllArr.updateSlotNoKxQ(j, int(value))
j++
value = uint(b1) >> 6
value |= (uint(b2) & 0x0f) << 2
tgtAbsHllArr.updateSlotNoKxQ(j, int(value))
j++
value = uint(b2) >> 4
value |= (uint(b3) & 3) << 4
tgtAbsHllArr.updateSlotNoKxQ(j, int(value))
j++
value = uint(b3) >> 2
tgtAbsHllArr.updateSlotNoKxQ(j, int(value))
j++
}
}
}
// TODO continue implementing
default:
return fmt.Errorf("not implemented")
}
tgt.(*hllSketchState).sketch.putRebuildCurMinNumKxQFlag(true)
return nil
}