func()

in kll/items_sketch.go [707:833]


func (s *ItemsSketch[C]) mergeItemsSketch(other *ItemsSketch[C]) {
	if other.IsEmpty() {
		return
	}
	// capture my key mutable fields before doing any merging
	myEmpty := s.IsEmpty()
	var myMin, myMax C
	var err error
	if !myEmpty {
		myMin, err = s.GetMinItem()
		if err != nil {
			panic(err)
		}
		myMax, err = s.GetMaxItem()
		if err != nil {
			panic(err)
		}
	}
	myMinK := s.minK
	finalN := s.n + other.n

	// buffers that are referenced multiple times
	otherNumLevels := other.numLevels
	otherLevelsArr := other.levels
	var otherItemsArr []C

	// MERGE: update this sketch with level0 items from the other sketch
	otherItemsArr = other.GetTotalItemsArray()
	for i := otherLevelsArr[0]; i < otherLevelsArr[1]; i++ {
		s.updateItem(otherItemsArr[i], s.compareFn)
	}

	// After the level 0 update, we capture the intermediate state of levels and items arrays...
	myCurNumLevels := s.numLevels
	myCurLevelsArr := s.levels
	myCurItemsArr := s.GetTotalItemsArray()

	// then rename them and initialize in case there are no higher levels
	myNewNumLevels := myCurNumLevels
	myNewLevelsArr := myCurLevelsArr
	myNewItemsArr := myCurItemsArr

	//merge higher levels if they exist
	if otherNumLevels > 1 {
		tmpSpaceNeeded := s.GetNumRetained() + getNumRetainedAboveLevelZero(otherNumLevels, otherLevelsArr)
		workbuf := make([]C, tmpSpaceNeeded)
		ub := ubOnNumLevels(finalN)
		worklevels := make([]uint32, ub+2) // ub+1 does not work
		outlevels := make([]uint32, ub+2)

		provisionalNumLevels := max(myCurNumLevels, otherNumLevels)

		populateItemWorkArrays(workbuf, worklevels, provisionalNumLevels,
			myCurNumLevels, myCurLevelsArr, myCurItemsArr,
			otherNumLevels, otherLevelsArr, otherItemsArr, s.compareFn)

		// notice that workbuf is being used as both the input and output
		result := generalItemsCompress(s.k, s.m, provisionalNumLevels, workbuf, worklevels, workbuf, outlevels, s.isLevelZeroSorted, s.compareFn, s.deterministicOffsetForTest)
		targetItemCount := result[1] //was finalCapacity. Max size given k, m, numLevels
		curItemCount := result[2]    //was finalPop

		// now we need to finalize the results for mySketch

		//THE NEW NUM LEVELS
		myNewNumLevels = uint8(result[0])

		// THE NEW ITEMS ARRAY
		if int(targetItemCount) == len(myCurItemsArr) {
			myNewItemsArr = myCurItemsArr
		} else {
			myNewItemsArr = make([]C, targetItemCount)
		}
		freeSpaceAtBottom := targetItemCount - curItemCount

		//shift the new items array create space at bottom
		for i := uint32(0); i < uint32(curItemCount); i++ {
			myNewItemsArr[uint32(freeSpaceAtBottom)+i] = workbuf[outlevels[0]+i]
		}
		theShift := uint32(freeSpaceAtBottom) - outlevels[0]

		//calculate the new levels array length
		var finalLevelsArrLen uint32
		if uint32(len(myCurLevelsArr)) < uint32(myNewNumLevels+1) {
			finalLevelsArrLen = uint32(myNewNumLevels + 1)
		} else {
			finalLevelsArrLen = uint32(len(myCurLevelsArr))
		}

		//THE NEW LEVELS ARRAY
		myNewLevelsArr = make([]uint32, finalLevelsArrLen)
		for lvl := uint8(0); lvl < myNewNumLevels+1; lvl++ { // includes the "extra" index
			myNewLevelsArr[lvl] = outlevels[lvl] + theShift
		}

		//MEMORY SPACE MANAGEMENT
		//not used
	}

	// Update Preamble:
	s.n = finalN
	if other.IsEstimationMode() { //otherwise the merge brings over exact items.
		s.minK = min(myMinK, other.minK)
	}

	// Update numLevels, levelsArray, items
	s.numLevels = myNewNumLevels
	s.levels = myNewLevelsArr
	s.items = myNewItemsArr

	// Update min, max items
	if myEmpty {
		s.minItem = other.minItem
		s.maxItem = other.maxItem
	} else {
		if s.compareFn(myMin, *other.minItem) {
			s.minItem = &myMin
		} else {
			s.minItem = other.minItem
		}

		if s.compareFn(*other.maxItem, myMax) {
			s.maxItem = &myMax
		} else {
			s.maxItem = other.maxItem
		}
	}
}