diff mbox

[i-g-t,01/16] stats: Add a way to generate values following a normal distribution

Message ID 1436186144-19665-2-git-send-email-damien.lespiau@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lespiau, Damien July 6, 2015, 12:35 p.m. UTC
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
---
 lib/igt_stats.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_stats.h |  3 +++
 2 files changed, 71 insertions(+)
diff mbox

Patch

diff --git a/lib/igt_stats.c b/lib/igt_stats.c
index 70650ec..37fcc23 100644
--- a/lib/igt_stats.c
+++ b/lib/igt_stats.c
@@ -25,6 +25,7 @@ 
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #include "igt_core.h"
 #include "igt_stats.h"
@@ -132,6 +133,73 @@  void igt_stats_init_with_size(igt_stats_t *stats, unsigned int capacity)
 	stats->max = 0;
 }
 
+/* https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform */
+static double rand_normal(double mean, double stddev)
+{
+	static double n2 = 0.0;
+	static bool n2_cached = 0;
+	double d, n1;
+
+	if (!n2_cached) {
+		double x, y, r;
+
+		do {
+			x = 2.0 * rand() / RAND_MAX - 1;
+			y = 2.0 * rand() / RAND_MAX - 1;
+
+			r = x * x + y * y;
+		} while (r == 0.0 || r > 1.0);
+
+		d = sqrt(-2.0 * log(r) / r);
+		n1 = x * d;
+		n2 = y * d;
+
+		n2_cached = 1;
+		return  n1 * stddev + mean;
+	} else {
+		n2_cached = 0;
+		return n2 * stddev + mean;
+	}
+}
+
+static double *
+igt_vector_normal(double mean, double sigma, unsigned int n_values)
+{
+	double *v;
+	unsigned int i;
+
+	v = malloc(n_values * sizeof(double));
+	srand(time(NULL));
+	for (i = 0; i < n_values; i++)
+		v[i] = rand_normal(mean, sigma);
+
+	return v;
+}
+
+/**
+ * igt_stats_init_normal:
+ * @stats: An #igt_stats_t instance
+ * @mean: Mean of the distribution
+ * @std_deviation: Standard deviation of the distribution
+ * @n_values: Number of values to generate
+ *
+ * Generates @n_values numbers following a normal distribution defined by
+ * (@mean, @std_deviation).
+ */
+void igt_stats_init_normal(igt_stats_t *stats,
+			   double mean, double std_deviation,
+			   unsigned int n_values)
+{
+	double *v;
+	unsigned int i;
+
+	v = igt_vector_normal(mean, std_deviation, n_values);
+	igt_stats_init_with_size(stats, n_values);
+	for (i = 0; i < n_values; i++)
+		igt_stats_push(stats, v[i]);
+	free(v);
+}
+
 /**
  * igt_stats_fini:
  * @stats: An #igt_stats_t instance
diff --git a/lib/igt_stats.h b/lib/igt_stats.h
index 554ab15..e1757b7 100644
--- a/lib/igt_stats.h
+++ b/lib/igt_stats.h
@@ -49,6 +49,9 @@  typedef struct {
 
 void igt_stats_init(igt_stats_t *stats);
 void igt_stats_init_with_size(igt_stats_t *stats, unsigned int capacity);
+void igt_stats_init_normal(igt_stats_t *stats,
+			   double mean, double std_deviation,
+			   unsigned int n_values);
 void igt_stats_fini(igt_stats_t *stats);
 bool igt_stats_is_population(igt_stats_t *stats);
 void igt_stats_set_population(igt_stats_t *stats, bool full_population);