From patchwork Mon Jul 6 12:35:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Lespiau, Damien" X-Patchwork-Id: 6723271 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C4AD89F38C for ; Mon, 6 Jul 2015 12:35:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C985C205F9 for ; Mon, 6 Jul 2015 12:35:52 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 88F1A20613 for ; Mon, 6 Jul 2015 12:35:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F2F336E86E; Mon, 6 Jul 2015 05:35:50 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTP id DF5386E86F for ; Mon, 6 Jul 2015 05:35:49 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 06 Jul 2015 05:35:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,414,1432623600"; d="scan'208";a="741420992" Received: from magarwal-mobl.amr.corp.intel.com (HELO strange.amr.corp.intel.com) ([10.254.77.111]) by fmsmga001.fm.intel.com with ESMTP; 06 Jul 2015 05:35:48 -0700 From: Damien Lespiau To: intel-gfx@lists.freedesktop.org Date: Mon, 6 Jul 2015 13:35:31 +0100 Message-Id: <1436186144-19665-4-git-send-email-damien.lespiau@intel.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1436186144-19665-1-git-send-email-damien.lespiau@intel.com> References: <1436186144-19665-1-git-send-email-damien.lespiau@intel.com> Subject: [Intel-gfx] [PATCH i-g-t 03/16] stats: Add an histogram object X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Histograms are a great way to have a look at a dataset to understand how the values are distributed. Signed-off-by: Damien Lespiau --- 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(); }