Histograms are a great way to have a look at a dataset to understand how the values are distributed. Signed-off-by: Damien Lespiau <damien.lespiau@xxxxxxxxx> --- lib/igt_stats.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_stats.h | 23 +++++++++++ lib/tests/igt_stats.c | 24 ++++++++++++ 3 files changed, 152 insertions(+) diff --git a/lib/igt_stats.c b/lib/igt_stats.c index 1103a7b..d757fc6 100644 --- a/lib/igt_stats.c +++ b/lib/igt_stats.c @@ -639,3 +639,108 @@ double igt_stats_get_trimean(igt_stats_t *stats) igt_stats_get_quartiles(stats, &q1, &q2, &q3); return (q1 + 2*q2 + q3) / 4; } + +/** + * igt_histogram_init: + * @hist: An #igt_histogram_t instance + * @stats: Input data + * + * Initializes an igt_histogram_t object. Use igt_histogram_fini() when finished + * with it. + */ +void igt_histogram_init(igt_histogram_t *hist, igt_stats_t *stats) +{ + memset(hist, 0, sizeof(*hist)); + hist->stats = stats; + hist->n_bins = 10; +} + +/** + * igt_histogram_fini: + * @hist: An #igt_histogram_t instance + * + * Frees resources allocated during the life time of @hist. + */ +void igt_histogram_fini(igt_histogram_t *hist) +{ + free(hist->frequencies); +} + +/* XXX: we should probably use an automatic binning algorithm */ + +/** + * igt_histogram_set_n_bins: + * @hist: An #igt_histogram_t instance + * @n_bins: Number of bins + * + * Set how many bins should be use to classify the input data. + * + * The default is 10. + */ +void igt_histogram_set_n_bins(igt_histogram_t *hist, unsigned int n_bins) +{ + if (hist->n_bins == n_bins) + return; + + hist->n_bins = n_bins; + free(hist->frequencies); + hist->frequencies = NULL; +} + +/** + * igt_histogram_set_density: + * @hist: An #igt_histogram_t instance + * @density: The new density setting + * + * Whether the histogram should represent a density distribution (integral over + * the range of the input data is 1) or simply contain the number of data + * points in each bin. + * + * By default density is #false. + * + */ +void igt_histogram_set_density(igt_histogram_t *hist, bool density) +{ + if (hist->compute_density == density) + return; + + hist->compute_density = density; + free(hist->frequencies); + hist->frequencies = NULL; +} + +double *igt_histogram_get_frequencies(igt_histogram_t *hist) +{ + igt_stats_t *stats = hist->stats; + unsigned int i; + uint64_t min, max; + double bin_length; + + /* + * XXX: we could cache frequencies with a way to know if stats has + * changed since the last time. + */ + free(hist->frequencies); + hist->frequencies = calloc(hist->n_bins, sizeof(double)); + + min = igt_stats_get_min(stats); + max = igt_stats_get_max(stats); + bin_length = (max - min) / (double)hist->n_bins; + + for (i = 0; i < stats->n_values; i++) { + unsigned int bin; + + bin = (stats->values[i] - min) / bin_length; + if (bin >= hist->n_bins) + bin--; + hist->frequencies[bin]++; + } + + if (!hist->compute_density) + return hist->frequencies; + + for (i = 0; i < hist->n_bins; i++) + hist->frequencies[i] /= stats->n_values; + + return hist->frequencies; +} diff --git a/lib/igt_stats.h b/lib/igt_stats.h index d6eb48f..46b7019 100644 --- a/lib/igt_stats.h +++ b/lib/igt_stats.h @@ -73,4 +73,27 @@ double igt_stats_get_median(igt_stats_t *stats); double igt_stats_get_variance(igt_stats_t *stats); double igt_stats_get_std_deviation(igt_stats_t *stats); +/** + * igt_histogram_t: + * + * An histogram will split the input data containted in an #igt_stats_t object + * in a number of bins and, depending on the density property, either: + * - Compute the number of data points in each bin, + * - Normalize the data such as the histogram represents a density function, + * the integral over the range is 1. + */ +typedef struct { + /*< private >*/ + igt_stats_t *stats; + unsigned int n_bins; + double *frequencies; + bool compute_density; +} igt_histogram_t; + +void igt_histogram_init(igt_histogram_t *hist, igt_stats_t *stats); +void igt_histogram_fini(igt_histogram_t *hist); +void igt_histogram_set_n_bins(igt_histogram_t *hist, unsigned int n_bins); +void igt_histogram_set_density(igt_histogram_t *hist, bool density); +double *igt_histogram_get_frequencies(igt_histogram_t *hist); + #endif /* __IGT_STATS_H__ */ diff --git a/lib/tests/igt_stats.c b/lib/tests/igt_stats.c index 12778e2..480321f 100644 --- a/lib/tests/igt_stats.c +++ b/lib/tests/igt_stats.c @@ -227,6 +227,29 @@ static void test_reallocation(void) igt_stats_fini(&stats); } +static void test_histogram(void) +{ + static const uint64_t s1[] = { 10, 12, 14, 16, 87, 53, 90, 72 }; + igt_stats_t stats; + igt_histogram_t hist; + double *freqs; + + igt_stats_init_from_array(&stats, s1, ARRAY_SIZE(s1)); + igt_histogram_init(&hist, &stats); + igt_histogram_set_n_bins(&hist, 2); + + freqs = igt_histogram_get_frequencies(&hist); + igt_assert_eq_double(freqs[0], 4); + igt_assert_eq_double(freqs[1], 4); + + igt_histogram_set_density(&hist, true); + freqs = igt_histogram_get_frequencies(&hist); + igt_assert_eq_double(freqs[0], 0.5); + igt_assert_eq_double(freqs[1], 0.5); + + igt_histogram_fini(&hist); +} + igt_simple_main { test_init_zero(); @@ -239,4 +262,5 @@ igt_simple_main test_invalidate_mean(); test_std_deviation(); test_reallocation(); + test_histogram(); } -- 2.1.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx