Browse Source

Add random([[min], max]) and random_normal([o]).

Little helpers for drawing numbers from bounded uniform and Gaussian
distributions.
vrld 13 years ago
parent
commit
50fd169e07
2 changed files with 69 additions and 0 deletions
  1. 33 0
      src/common/math.cpp
  2. 36 0
      src/common/math.h

+ 33 - 0
src/common/math.cpp

@@ -0,0 +1,33 @@
+#include "math.h"
+#include <limits>
+#include <cmath>
+
+namespace
+{
+	// The Box–Muller transform generates two random numbers, one of which we cache here.
+	// A value +infinity is used to signal the cache is invalid and that new numbers have
+	// to be generated.
+	float last_randnormal = std::numeric_limits<float>::infinity();
+}
+
+namespace love
+{
+
+float random_normal(float o)
+{
+	// number in cache?
+	if (last_randnormal != std::numeric_limits<float>::infinity())
+	{
+		float r = last_randnormal;
+		last_randnormal = std::numeric_limits<float>::infinity();
+		return r * o;
+	}
+
+	// else: generate numbers using the Box-Muller transform
+	float a = sqrt(-2.0f * log(random()));
+	float b = LOVE_M_PI * 2.0f * random();
+	last_randnormal = a * cos(b);
+	return a * sin(b) * o;
+}
+
+} // namespace love

+ 36 - 0
src/common/math.h

@@ -22,6 +22,7 @@
 #define LOVE_MATH_H
 
 #include <climits> // for CHAR_BIT
+#include <cstdlib> // for rand() and RAND_MAX
 
 /* Definitions of useful mathematical constants
  * M_E        - e
@@ -80,6 +81,41 @@ inline float next_p2(float x)
 	return static_cast<float>(next_p2(static_cast<int>(x)));
 }
 
+/**
+ * Draws a random number from a uniform distribution.
+ * @returns Uniformly distributed random number in [0:1).
+ */
+inline float random()
+{
+	return float(rand()) / (float(RAND_MAX) + 1.0f);
+}
+
+/**
+ * Draws a random number from a uniform distribution.
+ * @return Uniformly distributed random number in [0:max).
+ */
+inline float random(float max)
+{
+	return random() * max;
+}
+
+/**
+ * Draws a random number from a uniform distribution.
+ * @return Uniformly distributed random number in [min:max).
+ */
+inline float random(float min, float max)
+{
+	return random(max - min) + min;
+}
+
+/**
+ * Draws a random number from a normal/gaussian distribution.
+ * @param o Standard deviation of the distribution.
+ * @returns Normal distributed random number with mean 0 and variance o^2.
+ */
+float random_normal(float o = 1.);
+#define random_gaussion random_normal
+
 } // love
 
 #endif // LOVE_MATH_H