in src/main/java/org/apache/datasketches/sampling/EbppsItemsSketch.java [117:210]
public static <T> EbppsItemsSketch<T> heapify(final Memory srcMem,
final ArrayOfItemsSerDe<T> serDe)
{
final int numPreLongs = PreambleUtil.getAndCheckPreLongs(srcMem);
final int serVer = PreambleUtil.extractSerVer(srcMem);
final int familyId = PreambleUtil.extractFamilyID(srcMem);
final int flags = PreambleUtil.extractFlags(srcMem);
final boolean isEmpty = (flags & EMPTY_FLAG_MASK) != 0;
final boolean hasPartialItem = (flags & HAS_PARTIAL_ITEM_MASK) != 0;
// Check values
if (isEmpty) {
if (numPreLongs != Family.EBPPS.getMinPreLongs()) {
throw new SketchesArgumentException("Possible corruption: Must be " + Family.EBPPS.getMinPreLongs()
+ " for an empty sketch. Found: " + numPreLongs);
}
} else {
if (numPreLongs != Family.EBPPS.getMaxPreLongs()) {
throw new SketchesArgumentException("Possible corruption: Must be "
+ Family.EBPPS.getMaxPreLongs() + " for a non-empty sketch. Found: " + numPreLongs);
}
}
if (serVer != EBPPS_SER_VER) {
throw new SketchesArgumentException(
"Possible Corruption: Ser Ver must be " + EBPPS_SER_VER + ": " + serVer);
}
final int reqFamilyId = Family.EBPPS.getID();
if (familyId != reqFamilyId) {
throw new SketchesArgumentException(
"Possible Corruption: FamilyID must be " + reqFamilyId + ": " + familyId);
}
final int k = PreambleUtil.extractK(srcMem);
if (k < 1 || k > MAX_K) {
throw new SketchesArgumentException("Possible Corruption: k must be at least 1 "
+ "and less than " + MAX_K + ". Found: " + k);
}
if (isEmpty) {
return new EbppsItemsSketch<>(k);
}
final long n = PreambleUtil.extractN(srcMem);
if (n < 0) {
throw new SketchesArgumentException("Possible Corruption: n cannot be negative: " + n);
}
final double cumWt = PreambleUtil.extractEbppsCumulativeWeight(srcMem);
if (cumWt < 0.0 || Double.isNaN(cumWt) || Double.isInfinite(cumWt)) {
throw new SketchesArgumentException("Possible Corruption: cumWt must be nonnegative and finite: " + cumWt);
}
final double maxWt = PreambleUtil.extractEbppsMaxWeight(srcMem);
if (maxWt < 0.0 || Double.isNaN(maxWt) || Double.isInfinite(maxWt)) {
throw new SketchesArgumentException("Possible Corruption: maxWt must be nonnegative and finite: " + maxWt);
}
final double rho = PreambleUtil.extractEbppsRho(srcMem);
if (rho < 0.0 || rho > 1.0 || Double.isNaN(rho) || Double.isInfinite(rho)) {
throw new SketchesArgumentException("Possible Corruption: rho must be in [0.0, 1.0]: " + rho);
}
// extract C (part of sample_, not the preamble)
// due to numeric precision issues, c may occasionally be very slightly larger than k
final double c = srcMem.getDouble(EBPPS_C_DOUBLE);
if (c < 0 || c >= (k + 1) || Double.isNaN(c) || Double.isInfinite(c)) {
throw new SketchesArgumentException("Possible Corruption: c must be between 0 and k: " + c);
}
// extract items
final int numTotalItems = (int) Math.ceil(c);
final int numFullItems = (int) Math.floor(c); // floor() not strictly necessary
final int offsetBytes = EBPPS_ITEMS_START;
final T[] rawItems = serDe.deserializeFromMemory(
srcMem.region(offsetBytes, srcMem.getCapacity() - offsetBytes), 0, numTotalItems);
final List<T> itemsList = Arrays.asList(rawItems);
final ArrayList<T> data;
final T partialItem;
if (hasPartialItem) {
if (numFullItems >= numTotalItems) {
throw new SketchesArgumentException("Possible Corruption: Expected partial item but none found");
}
data = new ArrayList<>(itemsList.subList(0, numFullItems));
partialItem = itemsList.get(numFullItems); // 0-based, so last item
} else {
data = new ArrayList<>(itemsList);
partialItem = null; // just to be explicit
}
final EbppsItemsSample<T> sample = new EbppsItemsSample<>(data, partialItem, c);
return new EbppsItemsSketch<>(sample, k, n, cumWt, maxWt, rho);
}