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(); }