static void downSamplingMergeInto()

in src/main/java/org/apache/datasketches/quantiles/ItemsMergeImpl.java [137:204]


  static <T> void downSamplingMergeInto(final ItemsSketch<T> src, final ItemsSketch<T> tgt) {
    final int sourceK = src.getK();
    final int targetK = tgt.getK();

    if ((sourceK % targetK) != 0) {
      throw new SketchesArgumentException(
          "source.getK() must equal target.getK() * 2^(nonnegative integer).");
    }

    final int downFactor = sourceK / targetK;
    checkIfPowerOf2(downFactor, "source.getK()/target.getK() ratio");
    final int lgDownFactor = Integer.numberOfTrailingZeros(downFactor);

    final Object[] sourceLevels     = src.getCombinedBuffer(); // aliasing is a bit dangerous
    final Object[] sourceBaseBuffer = src.getCombinedBuffer(); // aliasing is a bit dangerous

    final long nFinal = tgt.getN() + src.getN();

    for (int i = 0; i < src.getBaseBufferCount(); i++) {
      tgt.update((T) sourceBaseBuffer[i]);
    }

    ItemsUpdateImpl.maybeGrowLevels(tgt, nFinal);

    final Object[] scratchBuf = new Object[2 * targetK];
    final Object[] downBuf    = new Object[targetK];

    long srcBitPattern = src.getBitPattern();
    for (int srcLvl = 0; srcBitPattern != 0L; srcLvl++, srcBitPattern >>>= 1) {
      if ((srcBitPattern & 1L) > 0L) {
        ItemsMergeImpl.justZipWithStride(
            sourceLevels, (2 + srcLvl) * sourceK,
            downBuf, 0,
            targetK,
            downFactor
        );
        ItemsUpdateImpl.inPlacePropagateCarry(
            srcLvl + lgDownFactor,
            (T[]) downBuf, 0,
            (T[]) scratchBuf, 0,
            false, tgt
        );
        // won't update target.n_ until the very end
      }
    }
    tgt.n_ = nFinal;

    assert (tgt.getN() / (2L * targetK)) == tgt.getBitPattern(); // internal consistency check

    final T srcMax = src.isEmpty() ? null : src.getMaxItem();
    final T srcMin = src.isEmpty() ? null : src.getMinItem();
    final T tgtMax = tgt.isEmpty() ? null : tgt.getMaxItem();
    final T tgtMin = tgt.isEmpty() ? null : tgt.getMinItem();

    if ((srcMax != null) && (tgtMax != null)) {
      tgt.maxItem_ = (src.getComparator().compare(srcMax, tgtMax) > 0) ? srcMax : tgtMax;
    } //only one could be null
    else if (tgtMax == null) { //if srcMax were null we would leave tgt alone
      tgt.maxItem_ = srcMax;
    }

    if ((srcMin != null) && (tgtMin != null)) {
      tgt.minItem_ = (src.getComparator().compare(srcMin, tgtMin) > 0) ? tgtMin : srcMin;
    } //only one could be null
    else if (tgtMin == null) { //if srcMin were null we would leave tgt alone
      tgt.minItem_ = srcMin;
    }
  }