docs: void materialize() {
      // already materialized?
      if (cachefill < 0) {
        return;
      }
      // Compute minimum and maximum
      double min = Double.MAX_VALUE, max = Double.MIN_VALUE;
      for (int i = 0; i < cachefill; i++) {
        min = Math.min(min, cachec[i]);
        max = Math.max(max, cachec[i]);
      }
      // use the LinearScale magic to round to "likely suiteable" step sizes.
      // TODO: extract into a reusable function?
      LinearScale scale = new LinearScale(min, max);
      min = scale.getMin();
      max = scale.getMax();
      this.base = min;
      this.max = max;
      this.binsize = (max - min) / this.destsize;
      // initialize array
      this.data = new double[this.destsize << 1];
      size = destsize;
      // re-insert data we have
      final int end = cachefill;
      cachefill = -1; // So reinsert works!
      for (int i = 0; i < end; i++) {
        increment(cachec[i], cachev[i]);
      }
      // delete cache, signal that we're initialized
      cachec = null;
      cachev = null;
    }