docs: private static final HllSketchImpl unionImpl(final HllSketchImpl incomingImpl,
        final HllSketchImpl gadgetImpl, final int lgMaxK) {
      assert gadgetImpl.getTgtHllType() == HLL_8;
      HllSketchImpl srcImpl = incomingImpl; //default
      HllSketchImpl dstImpl = gadgetImpl; //default
      if ((incomingImpl == null) || incomingImpl.isEmpty()) { return gadgetImpl; }
  
      final int hi2bits = (gadgetImpl.isEmpty()) ? 3 : gadgetImpl.getCurMode().ordinal();
      final int lo2bits = incomingImpl.getCurMode().ordinal();
  
      final int sw = (hi2bits << 2) | lo2bits;
  
      switch (sw) {
        case 0: { //src: LIST, gadget: LIST
          final PairIterator srcItr = srcImpl.iterator(); //LIST
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          //whichever is True wins:
          dstImpl.putOutOfOrderFlag(dstImpl.isOutOfOrderFlag() | srcImpl.isOutOfOrderFlag());
          break;
        }
        case 1: { //src: SET, gadget: LIST
          //consider a swap here
          final PairIterator srcItr = srcImpl.iterator(); //SET
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(true); //SET oooFlag is always true
          break;
        }
        case 2: { //src: HLL, gadget: LIST
          //swap so that src is gadget-LIST, tgt is HLL
          //use lgMaxK because LIST has effective K of 2^26
          srcImpl = gadgetImpl;
          dstImpl = copyOrDownsampleHll(incomingImpl, lgMaxK);
          final PairIterator srcItr = srcImpl.iterator();
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          //whichever is True wins:
          dstImpl.putOutOfOrderFlag(srcImpl.isOutOfOrderFlag() | dstImpl.isOutOfOrderFlag());
          break;
        }
        case 4: { //src: LIST, gadget: SET
          final PairIterator srcItr = srcImpl.iterator(); //LIST
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(true); //SET oooFlag is always true
          break;
        }
        case 5: { //src: SET, gadget: SET
          final PairIterator srcItr = srcImpl.iterator(); //SET
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(true); //SET oooFlag is always true
          break;
        }
        case 6: { //src: HLL, gadget: SET
          //swap so that src is gadget-SET, tgt is HLL
          //use lgMaxK because LIST has effective K of 2^26
          srcImpl = gadgetImpl;
          dstImpl = copyOrDownsampleHll(incomingImpl, lgMaxK);
          final PairIterator srcItr = srcImpl.iterator(); //LIST
          assert dstImpl.getCurMode() == HLL;
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(true); //merging SET into non-empty HLL -> true
          break;
        }
        case 8: { //src: LIST, gadget: HLL
          assert dstImpl.getCurMode() == HLL;
          final PairIterator srcItr = srcImpl.iterator(); //LIST
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          //whichever is True wins:
          dstImpl.putOutOfOrderFlag(dstImpl.isOutOfOrderFlag() | srcImpl.isOutOfOrderFlag());
          break;
        }
        case 9: { //src: SET, gadget: HLL
          assert dstImpl.getCurMode() == HLL;
          final PairIterator srcItr = srcImpl.iterator(); //SET
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(true); //merging SET into existing HLL -> true
          break;
        }
        case 10: { //src: HLL, gadget: HLL
          final int srcLgK = srcImpl.getLgConfigK();
          final int dstLgK = dstImpl.getLgConfigK();
          if ((srcLgK < dstLgK) || (dstImpl.getTgtHllType() != HLL_8)) {
            dstImpl = copyOrDownsampleHll(dstImpl, min(dstLgK, srcLgK)); //TODO Fix for off-heap
          }
          final PairIterator srcItr = srcImpl.iterator(); //HLL
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(true); //union of two HLL modes is always true
          break;
        }
        case 12: { //src: LIST, gadget: empty
          final PairIterator srcItr = srcImpl.iterator(); //LIST
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(srcImpl.isOutOfOrderFlag()); //whatever source is
          break;
        }
        case 13: { //src: SET, gadget: empty
          final PairIterator srcItr = srcImpl.iterator(); //SET
          while (srcItr.nextValid()) {
            dstImpl = dstImpl.couponUpdate(srcItr.getPair()); //assignment required
          }
          dstImpl.putOutOfOrderFlag(true); //SET oooFlag is always true
          break;
        }
        case 14: { //src: HLL, gadget: empty
          dstImpl = copyOrDownsampleHll(srcImpl, lgMaxK);
          dstImpl.putOutOfOrderFlag(srcImpl.isOutOfOrderFlag()); //whatever source is.
          break;
        }
      }
      if (gadgetImpl.isMemory() && !dstImpl.isMemory()) {
        //dstImpl is on heap, gadget is Memory; we have to put dstImpl back into the gadget
        final WritableMemory gadgetWmem = gadgetImpl.getWritableMemory();
        assert gadgetWmem != null;
        final int bytes =
            HllSketch.getMaxUpdatableSerializationBytes(dstImpl.getLgConfigK(), HLL_8);
        gadgetWmem.clear(0, bytes);
        final byte[] dstByteArr = dstImpl.toUpdatableByteArray();
        gadgetWmem.putByteArray(0, dstByteArr, 0, dstByteArr.length);
        dstImpl = HllSketch.writableWrap(gadgetWmem).hllSketchImpl;
      }
      return dstImpl;
    }