diff --git a/src/common/math.cpp b/src/common/math.cpp new file mode 100644 index 000000000..32cb0577f --- /dev/null +++ b/src/common/math.cpp @@ -0,0 +1,33 @@ +#include "math.h" +#include +#include + +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::infinity(); +} + +namespace love +{ + +float random_normal(float o) +{ + // number in cache? + if (last_randnormal != std::numeric_limits::infinity()) + { + float r = last_randnormal; + last_randnormal = std::numeric_limits::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 diff --git a/src/common/math.h b/src/common/math.h index 44979d4b2..b60dbdb68 100644 --- a/src/common/math.h +++ b/src/common/math.h @@ -22,6 +22,7 @@ #define LOVE_MATH_H #include // for CHAR_BIT +#include // 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(next_p2(static_cast(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