code: private static double[] internalBuildHistogram(final DoublesSketch sketch, final double[] splitPoints) {
      final DoublesSketchAccessor sketchAccessor = DoublesSketchAccessor.wrap(sketch);
      Util.checkSplitPointsOrder(splitPoints);
  
      final int numSplitPoints = splitPoints.length;
      final int numCounters = numSplitPoints + 1;
      final double[] counters = new double[numCounters];
  
      long weight = 1;
      sketchAccessor.setLevel(DoublesSketchAccessor.BB_LVL_IDX);
      if (numSplitPoints < 50) { // empirically determined crossover
        // sort not worth it when few split points
        DoublesPmfCdfImpl.bilinearTimeIncrementHistogramCounters(
                sketchAccessor, weight, splitPoints, counters);
      } else {
        sketchAccessor.sort();
        // sort is worth it when many split points
        DoublesPmfCdfImpl.linearTimeIncrementHistogramCounters(
                sketchAccessor, weight, splitPoints, counters);
      }
  
      long myBitPattern = sketch.getBitPattern();
      final int k = sketch.getK();
      assert myBitPattern == sketch.getN() / (2L * k); // internal consistency check
      for (int lvl = 0; myBitPattern != 0L; lvl++, myBitPattern >>>= 1) {
        weight <<= 1; // double the weight
        if ((myBitPattern & 1L) > 0L) { //valid level exists
          // the levels are already sorted so we can use the fast version
          sketchAccessor.setLevel(lvl);
          DoublesPmfCdfImpl.linearTimeIncrementHistogramCounters(
                  sketchAccessor, weight, splitPoints, counters);
        }
      }
      return counters;
  
    }
docs: Shared algorithm for both PMF and CDF functions. The splitPoints must be unique, monotonically
  increasing values.
  @param sketch the given quantiles DoublesSketch
  @param splitPoints an array of <i>m</i> unique, monotonically increasing doubles
  that divide the real number line into <i>m+1</i> consecutive disjoint intervals.
  @return the unnormalized, accumulated counts of <i>m + 1</i> intervals.