in src/main/java/org/apache/datasketches/kll/KllDoublesHelper.java [38:139]
static void mergeDoubleImpl(final KllDoublesSketch mySketch, final KllSketch other) {
final KllDoublesSketch otherDblSk = (KllDoublesSketch) other;
if (otherDblSk.isEmpty()) { return; }
mySketch.nullSortedView();
final long finalN = mySketch.getN() + otherDblSk.getN();
final int otherNumLevels = otherDblSk.getNumLevels();
final int[] otherLevelsArr = otherDblSk.getLevelsArray();
final double[] otherDoubleItemsArr;
//capture my min & max, minK
final double myMin = mySketch.isEmpty() ? Double.NaN : mySketch.getMinDoubleItem();
final double myMax = mySketch.isEmpty() ? Double.NaN : mySketch.getMaxDoubleItem();
final int myMinK = mySketch.getMinK();
//update this sketch with level0 items from the other sketch
if (otherDblSk.isCompactSingleItem()) {
updateDouble(mySketch, otherDblSk.getDoubleSingleItem());
otherDoubleItemsArr = new double[0];
} else {
otherDoubleItemsArr = otherDblSk.getDoubleItemsArray();
for (int i = otherLevelsArr[0]; i < otherLevelsArr[1]; i++) {
updateDouble(mySketch, otherDoubleItemsArr[i]);
}
}
// after the level 0 update, we capture the state of levels and items arrays
final int myCurNumLevels = mySketch.getNumLevels();
final int[] myCurLevelsArr = mySketch.getLevelsArray();
final double[] myCurDoubleItemsArr = mySketch.getDoubleItemsArray();
int myNewNumLevels = myCurNumLevels;
int[] myNewLevelsArr = myCurLevelsArr;
double[] myNewDoubleItemsArr = myCurDoubleItemsArr;
if (otherNumLevels > 1 && !otherDblSk.isCompactSingleItem()) { //now merge higher levels if they exist
final int tmpSpaceNeeded = mySketch.getNumRetained()
+ KllHelper.getNumRetainedAboveLevelZero(otherNumLevels, otherLevelsArr);
final double[] workbuf = new double[tmpSpaceNeeded];
final int ub = KllHelper.ubOnNumLevels(finalN);
final int[] worklevels = new int[ub + 2]; // ub+1 does not work
final int[] outlevels = new int[ub + 2];
final int provisionalNumLevels = max(myCurNumLevels, otherNumLevels);
populateDoubleWorkArrays(workbuf, worklevels, provisionalNumLevels,
myCurNumLevels, myCurLevelsArr, myCurDoubleItemsArr,
otherNumLevels, otherLevelsArr, otherDoubleItemsArr);
// notice that workbuf is being used as both the input and output
final int[] result = generalDoublesCompress(mySketch.getK(), mySketch.getM(), provisionalNumLevels,
workbuf, worklevels, workbuf, outlevels, mySketch.isLevelZeroSorted(), KllSketch.random);
final int targetItemCount = result[1]; //was finalCapacity. Max size given k, m, numLevels
final int curItemCount = result[2]; //was finalPop
// now we need to finalize the results for the "self" sketch
//THE NEW NUM LEVELS
myNewNumLevels = result[0]; //was finalNumLevels
assert myNewNumLevels <= ub; // ub may be much bigger
// THE NEW ITEMS ARRAY (was newbuf)
myNewDoubleItemsArr = (targetItemCount == myCurDoubleItemsArr.length)
? myCurDoubleItemsArr
: new double[targetItemCount];
final int freeSpaceAtBottom = targetItemCount - curItemCount;
//shift the new items array
System.arraycopy(workbuf, outlevels[0], myNewDoubleItemsArr, freeSpaceAtBottom, curItemCount);
final int theShift = freeSpaceAtBottom - outlevels[0];
//calculate the new levels array length
final int finalLevelsArrLen;
if (myCurLevelsArr.length < myNewNumLevels + 1) { finalLevelsArrLen = myNewNumLevels + 1; }
else { finalLevelsArrLen = myCurLevelsArr.length; }
//THE NEW LEVELS ARRAY
myNewLevelsArr = new int[finalLevelsArrLen];
for (int lvl = 0; lvl < myNewNumLevels + 1; lvl++) { // includes the "extra" index
myNewLevelsArr[lvl] = outlevels[lvl] + theShift;
}
//MEMORY SPACE MANAGEMENT
if (mySketch.serialVersionUpdatable) {
mySketch.wmem = KllHelper.memorySpaceMgmt(mySketch, myNewLevelsArr.length, myNewDoubleItemsArr.length);
}
}
//Update Preamble:
mySketch.setN(finalN);
if (otherDblSk.isEstimationMode()) { //otherwise the merge brings over exact items.
mySketch.setMinK(min(myMinK, otherDblSk.getMinK()));
}
//Update numLevels, levelsArray, items
mySketch.setNumLevels(myNewNumLevels);
mySketch.setLevelsArray(myNewLevelsArr);
mySketch.setDoubleItemsArray(myNewDoubleItemsArr);
//Update min, max items
final double otherMin = otherDblSk.getMinDoubleItem();
final double otherMax = otherDblSk.getMaxDoubleItem();
mySketch.setMinDoubleItem(resolveDoubleMinItem(myMin, otherMin));
mySketch.setMaxDoubleItem(resolveDoubleMaxItem(myMax, otherMax));
assert KllHelper.sumTheSampleWeights(mySketch.getNumLevels(), mySketch.getLevelsArray()) == mySketch.getN();
}