void decreaseKBy1()

in src/main/java/org/apache/datasketches/sampling/VarOptItemsSketch.java [865:920]


  void decreaseKBy1() {
    if (k_ <= 1) {
      throw new SketchesStateException("Cannot decrease k below 1 in union");
    }

    if ((h_ == 0) && (r_ == 0)) {
      // exact mode, but no data yet; this reduction is somewhat gratuitous
      --k_;
    } else if ((h_ > 0) && (r_ == 0)) {
      // exact mode, but we have some data
      --k_;
      if (h_ > k_) {
        transitionFromWarmup();
      }
    } else if ((h_ > 0) && (r_ > 0)) {
      // reservoir mode, but we have some exact samples.
      // Our strategy will be to pull an item out of H (which we are allowed to do since it's
      // still just data), reduce k, and then re-insert the item

      // first, slide the R zone to the left by 1, temporarily filling the gap
      final int oldGapIdx = h_;
      final int oldFinalRIdx = (h_ + 1 + r_) - 1;

      assert oldFinalRIdx == k_;
      swapValues(oldFinalRIdx, oldGapIdx);

      // now we pull an item out of H; any item is ok, but if we grab the rightmost and then
      // reduce h_, the heap invariant will be preserved (and the gap will be restored), plus
      // the push() of the item that will probably happen later will be cheap.

      final int pulledIdx = h_ - 1;
      final T pulledItem = data_.get(pulledIdx);
      final double pulledWeight = weights_.get(pulledIdx);
      final boolean pulledMark = marks_.get(pulledIdx);

      if (pulledMark) { --numMarksInH_; }
      weights_.set(pulledIdx, -1.0); // to make bugs easier to spot

      --h_;
      --k_;
      --n_; // will be re-incremented with the update

      update(pulledItem, pulledWeight, pulledMark);
    } else if ((h_ == 0) && (r_ > 0)) {
      // pure reservoir mode, so can simply eject a randomly chosen sample from the reservoir
      assert r_ >= 2;

      final int rIdxToDelete = 1 + SamplingUtil.rand().nextInt(r_); // 1 for the gap
      final int rightmostRIdx = (1 + r_) - 1;
      swapValues(rIdxToDelete, rightmostRIdx);
      weights_.set(rightmostRIdx, -1.0);

      --k_;
      --r_;
    }
  }