blob: c6eafeb44fdf4b3d7c7d33ff73d5572ad843994a [file] [log] [blame]
#include <algorithm>
#include <string>
#include <sstream>
#include <cmath>
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vtr_util.h"
#include "histogram.h"
std::vector<HistogramBucket> build_histogram(std::vector<float> values, size_t num_bins, float min_value, float max_value) {
std::vector<HistogramBucket> histogram;
if (values.empty()) return histogram;
if (std::isnan(min_value)) {
min_value = *std::min_element(values.begin(), values.end());
}
if (std::isnan(max_value)) {
max_value = *std::max_element(values.begin(), values.end());
}
//Determine the bin size
float range = max_value - min_value;
float bin_size = range / num_bins;
//Create the buckets
float bucket_min = min_value;
for (size_t ibucket = 0; ibucket < num_bins; ++ibucket) {
float bucket_max = bucket_min + bin_size;
histogram.emplace_back(bucket_min, bucket_max);
bucket_min = bucket_max;
}
//To avoid round-off errors we force the max value of the last bucket equal to the max value
histogram[histogram.size() - 1].max_value = max_value;
//Count the values into the buckets
auto comp = [](const HistogramBucket& bucket, float value) {
return bucket.max_value < value;
};
for (auto value : values) {
//Find the bucket who's max is less than the current slack
auto iter = std::lower_bound(histogram.begin(), histogram.end(), value, comp);
VTR_ASSERT(iter != histogram.end());
iter->count++;
}
return histogram;
}
void print_histogram(std::vector<HistogramBucket> histogram) {
size_t char_width = 80;
auto lines = format_histogram(histogram, char_width);
for (auto line : lines) {
VTR_LOG("%s\n", line.c_str());
}
}
std::vector<std::string> format_histogram(std::vector<HistogramBucket> histogram, size_t width) {
std::vector<std::string> lines;
//Determine the maximum and total count
size_t max_count = 0;
size_t total_count = 0;
for (const HistogramBucket& bucket : histogram) {
max_count = std::max(max_count, bucket.count);
total_count += bucket.count;
}
if (max_count == 0) return lines; //Nothing to do
int count_digits = ceil(log10(max_count));
//Determine the maximum prefix length
size_t bar_len = width
- (18 + 3) //bucket prefix
- count_digits
- 7 //percentage
- 2; //-2 for " |" appended after count
for (size_t ibucket = 0; ibucket < histogram.size(); ++ibucket) {
std::string line;
float pct = histogram[ibucket].count / float(total_count) * 100;
line += vtr::string_fmt("[% 9.2g:% 9.2g) %*zu (%4.1f%) |", histogram[ibucket].min_value, histogram[ibucket].max_value, count_digits, histogram[ibucket].count, pct);
size_t num_chars = std::round((double(histogram[ibucket].count) / max_count) * bar_len);
for (size_t i = 0; i < num_chars; ++i) {
line += "*";
}
lines.push_back(line);
}
return lines;
}