docs: @SuppressWarnings("unchecked") //also used by ItemsSketch and ItemsUnion
    static <T> void downSamplingMergeInto(final ItemsSketch<T> src, final ItemsSketch<T> tgt) {
      final int targetK = tgt.getK();
      final int sourceK = src.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.getMaxValue();
      final T srcMin = src.getMinValue();
      final T tgtMax = tgt.getMaxValue();
      final T tgtMin = tgt.getMinValue();
  
      if ((srcMax != null) && (tgtMax != null)) {
        tgt.maxValue_ = (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.maxValue_ = srcMax;
      }
  
      if ((srcMin != null) && (tgtMin != null)) {
        tgt.minValue_ = (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.minValue_ = srcMin;
      }
    }