Example #1
0
continuous_bins continuous_result::get_bins(flex_int num_bins) const {
  if (num_bins < 1) {
    log_and_throw("num_bins must be positive.");
  }
  continuous_bins ret;

  // determine the bin range that covers min to max
  size_t first_bin = get_bin_idx(min, scale_min, scale_max);
  size_t last_bin = get_bin_idx(max, scale_min, scale_max);
  size_t effective_bins = (last_bin - first_bin) + 1;

  // Might end up with fewer effective bins due to very small
  // number of unique values. For now, comment out this assert.
  // TODO -- what should we assert here instead, to make sure we have enough
  // effective range for the desired number of bins? Or should we force
  // discrete histogram for very low cardinality? (At which point, we keep
  // this assertion).
  //DASSERT_GE(effective_bins, (MAX_BINS/4));

  if (num_bins > (MAX_BINS/4)) {
    log_and_throw("num_bins must be less than or equal to the effective number of bins available.");
  }

  // rescale to desired bins, taking more than the effective range if
  // necessary in order to get to num_bins total without resampling
  size_t bins_per_bin = effective_bins / num_bins;
  size_t overflow = effective_bins % num_bins;
  size_t before = 0;
  size_t after = 0;
  if (overflow) {
    overflow = num_bins - overflow;
    bins_per_bin = (effective_bins + overflow) / num_bins;
    before = overflow / 2;
    after = (overflow / 2) + (overflow % 2);
  }

  ret.bins = flex_list(num_bins, 0); // initialize empty
  ret.min = get_value_at_bin(std::max<ssize_t>(0, first_bin - before), scale_min, scale_max, MAX_BINS);
  ret.max = get_value_at_bin(std::min<ssize_t>(last_bin + after + 1, MAX_BINS), scale_min, scale_max, MAX_BINS);
  for (size_t i=0; i<num_bins; i++) {
    for (size_t j=0; j<bins_per_bin; j++) {
      ssize_t idx = (i * bins_per_bin) + j + (first_bin - before);
      if (idx < 0 || idx >= MAX_BINS) {
        // don't try to get values below 0, or past MAX_BINS, that would be silly
        continue;
      }
      ret.bins[i] += this->bins[idx];
    }
  }
  return ret;
}
 inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(flex_undefined t) const { return flex_list(); }
 inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(T t) const { FLEX_TYPE_ASSERT(false); return flex_list(); }