code: static void linearTimeIncrementHistogramCounters(final DoublesBufferAccessor samples, final long weight,
        final double[] splitPoints, final double[] counters) {
      int i = 0;
      int j = 0;
      while (i < samples.numItems() && j < splitPoints.length) {
        if (samples.get(i) < splitPoints[j]) {
          counters[j] += weight; // this sample goes into this bucket
          i++; // move on to next sample and see whether it also goes into this bucket
        } else {
          j++; // no more samples for this bucket. move on the next bucket.
        }
      }
  
      // now either i == numSamples(we are out of samples), or
      // j == numSplitPoints(out of buckets, but there are more samples remaining)
      // we only need to do something in the latter case.
      if (j == splitPoints.length) {
        counters[j] += (weight * (samples.numItems() - i));
      }
    }
docs: This one does a linear time simultaneous walk of the samples and splitPoints. Because this
  internal procedure is called multiple times, we require the caller to ensure these 3 properties:
  <ol>
  <li>samples array must be sorted.</li>
  <li>splitPoints must be unique and sorted</li>
  <li>number of SplitPoints + 1 == counters.length</li>
  </ol>
  @param samples DoublesBufferAccessor holding an array of samples
  @param weight of the samples
  @param splitPoints must be unique and sorted. Number of splitPoints + 1 = counters.length.
  @param counters array of counters