From 3046981fce35a5374266123c97911626d2f4fcb3 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 14 Apr 2013 23:02:44 -0300 Subject: [PATCH] Added love.math.newRandomGenerator. Returns a RNG object with its own seed and random methods. --HG-- branch : math-randobject --- .../love-framework.xcodeproj/project.pbxproj | 16 +++ src/common/types.h | 6 + src/modules/math/MathModule.cpp | 52 +------- src/modules/math/MathModule.h | 90 ++++++------- src/modules/math/RandomGenerator.cpp | 87 +++++++++++++ src/modules/math/RandomGenerator.h | 111 ++++++++++++++++ src/modules/math/wrap_Math.cpp | 53 +++----- src/modules/math/wrap_Math.h | 1 + src/modules/math/wrap_RandomGenerator.cpp | 122 ++++++++++++++++++ src/modules/math/wrap_RandomGenerator.h | 47 +++++++ 10 files changed, 463 insertions(+), 122 deletions(-) create mode 100644 src/modules/math/RandomGenerator.cpp create mode 100644 src/modules/math/RandomGenerator.h create mode 100644 src/modules/math/wrap_RandomGenerator.cpp create mode 100644 src/modules/math/wrap_RandomGenerator.h diff --git a/platform/macosx/love-framework.xcodeproj/project.pbxproj b/platform/macosx/love-framework.xcodeproj/project.pbxproj index 88abbfb3c..9ec6def61 100644 --- a/platform/macosx/love-framework.xcodeproj/project.pbxproj +++ b/platform/macosx/love-framework.xcodeproj/project.pbxproj @@ -224,6 +224,10 @@ FA577ACB16C7514400860150 /* physfs.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A7316C719F900860150 /* physfs.framework */; }; FA577ACC16C7514700860150 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A7516C719FF00860150 /* SDL.framework */; }; FA577ACD16C7514C00860150 /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A7716C71A0800860150 /* Vorbis.framework */; }; + FA636D8A171B70920065623F /* RandomGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA636D88171B70920065623F /* RandomGenerator.cpp */; }; + FA636D8B171B70920065623F /* RandomGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FA636D89171B70920065623F /* RandomGenerator.h */; }; + FA636D8E171B72A70065623F /* wrap_RandomGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA636D8C171B72A70065623F /* wrap_RandomGenerator.cpp */; }; + FA636D8F171B72A70065623F /* wrap_RandomGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FA636D8D171B72A70065623F /* wrap_RandomGenerator.h */; }; FA7C937A16DCC6C2006F2BEE /* wrap_Math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7C937516DCC6C2006F2BEE /* wrap_Math.cpp */; }; FA7C937B16DCC6C2006F2BEE /* wrap_Math.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7C937616DCC6C2006F2BEE /* wrap_Math.h */; }; FAAC6B02170A373B008A61C5 /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAAC6B00170A373A008A61C5 /* CompressedData.cpp */; }; @@ -715,6 +719,10 @@ FA577A8D16C71D3600860150 /* boot.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = boot.lua; sourceTree = ""; }; FA577A8E16C71D3600860150 /* graphics.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = graphics.lua; sourceTree = ""; }; FA577AAF16C7507900860150 /* love.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FA636D88171B70920065623F /* RandomGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RandomGenerator.cpp; sourceTree = ""; }; + FA636D89171B70920065623F /* RandomGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomGenerator.h; sourceTree = ""; }; + FA636D8C171B72A70065623F /* wrap_RandomGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_RandomGenerator.cpp; sourceTree = ""; }; + FA636D8D171B72A70065623F /* wrap_RandomGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_RandomGenerator.h; sourceTree = ""; }; FA7C937516DCC6C2006F2BEE /* wrap_Math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Math.cpp; sourceTree = ""; }; FA7C937616DCC6C2006F2BEE /* wrap_Math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Math.h; sourceTree = ""; }; FAAC6B00170A373A008A61C5 /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = ""; }; @@ -1653,8 +1661,12 @@ children = ( FA5454C016F1310000D30303 /* MathModule.cpp */, FA5454C116F1310000D30303 /* MathModule.h */, + FA636D88171B70920065623F /* RandomGenerator.cpp */, + FA636D89171B70920065623F /* RandomGenerator.h */, FA7C937516DCC6C2006F2BEE /* wrap_Math.cpp */, FA7C937616DCC6C2006F2BEE /* wrap_Math.h */, + FA636D8C171B72A70065623F /* wrap_RandomGenerator.cpp */, + FA636D8D171B72A70065623F /* wrap_RandomGenerator.h */, ); path = math; sourceTree = ""; @@ -1705,6 +1717,8 @@ FA0CDE3D1710F9A50056E8D7 /* FormatHandler.h in Headers */, FAEC808B1710FEA60057279A /* ImageData.h in Headers */, FAEC808F1711E76C0057279A /* CompressedData.h in Headers */, + FA636D8B171B70920065623F /* RandomGenerator.h in Headers */, + FA636D8F171B72A70065623F /* wrap_RandomGenerator.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1986,6 +2000,8 @@ FAE010E4170DF75C006F29D0 /* wrap_CompressedData.cpp in Sources */, FAEC808A1710FEA60057279A /* ImageData.cpp in Sources */, FAEC808E1711E76C0057279A /* CompressedData.cpp in Sources */, + FA636D8A171B70920065623F /* RandomGenerator.cpp in Sources */, + FA636D8E171B72A70065623F /* wrap_RandomGenerator.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/common/types.h b/src/common/types.h index b8e151f53..03f74d089 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -58,6 +58,9 @@ enum Type IMAGE_IMAGE_DATA_ID, IMAGE_COMPRESSED_DATA_ID, + // Math + MATH_RANDOM_GENERATOR_ID, + // Audio AUDIO_SOURCE_ID, @@ -130,6 +133,9 @@ const bits GRAPHICS_SHADER_T = (bits(1) << GRAPHICS_SHADER_ID) | OBJECT_T; const bits IMAGE_IMAGE_DATA_T = (bits(1) << IMAGE_IMAGE_DATA_ID) | DATA_T; const bits IMAGE_COMPRESSED_DATA_T = (bits(1) << IMAGE_COMPRESSED_DATA_ID) | DATA_T; +// Math. +const bits MATH_RANDOM_GENERATOR_T = (bits(1) << MATH_RANDOM_GENERATOR_ID) | OBJECT_T; + // Audio. const bits AUDIO_SOURCE_T = (bits(1) << AUDIO_SOURCE_ID) | OBJECT_T; diff --git a/src/modules/math/MathModule.cpp b/src/modules/math/MathModule.cpp index 3615e0c23..8a1fc5ee9 100644 --- a/src/modules/math/MathModule.cpp +++ b/src/modules/math/MathModule.cpp @@ -18,7 +18,7 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#include "modules/math/MathModule.h" +#include "MathModule.h" #include "common/math.h" #include @@ -81,60 +81,22 @@ namespace math Math Math::instance; -// 64 bit Xorshift implementation taken from the end of Sec. 3 (page 4) in -// George Marsaglia, "Xorshift RNGs", Journal of Statistical Software, Vol.8 (Issue 14), 2003 Math::Math() - : last_randnormal(numeric_limits::infinity()) + : rng(newRandomGenerator()) { - // because it is too big for some compilers to handle ... if you know what - // i mean - union - { - uint64 b64; - struct - { - uint32 a; - uint32 b; - } b32; - } converter; - -#ifdef LOVE_BIG_ENDIAN - converter.b32.a = 0x0139408D; - converter.b32.b = 0xCBBF7A44; -#else - converter.b32.b = 0x0139408D; - converter.b32.a = 0xCBBF7A44; -#endif - rng_state = converter.b64; - // prevent the runtime from free()-ing this retain(); } -uint64 Math::rand() +Math::~Math() { - rng_state ^= (rng_state << 13); - rng_state ^= (rng_state >> 7); - rng_state ^= (rng_state << 17); - return rng_state; + if (rng) + rng->release(); } -// Box–Muller transform -double Math::randnormal(double stddev) +RandomGenerator *Math::newRandomGenerator() { - // use cached number if possible - if (last_randnormal != numeric_limits::infinity()) - { - double r = last_randnormal; - last_randnormal = numeric_limits::infinity(); - return r * stddev; - } - - double r = sqrt(-2.0 * log(1. - random())); - double phi = 2.0 * LOVE_M_PI * (1. - random()); - - last_randnormal = r * cos(phi); - return r * sin(phi) * stddev; + return new RandomGenerator(); } vector Math::triangulate(const vector &polygon) diff --git a/src/modules/math/MathModule.h b/src/modules/math/MathModule.h index c19214133..88ac0b337 100644 --- a/src/modules/math/MathModule.h +++ b/src/modules/math/MathModule.h @@ -21,6 +21,8 @@ #ifndef LOVE_MATH_MODMATH_H #define LOVE_MATH_MODMATH_H +#include "RandomGenerator.h" + // LOVE #include "common/Module.h" #include "common/math.h" @@ -28,7 +30,6 @@ // STL #include -#include #include namespace love @@ -38,80 +39,79 @@ namespace math class Math : public Module { -public: - virtual ~Math() - {} +private: - /** Set pseudo random seed. - * - * It's up to the implementation how to use this. - * - * @param seed The random seed. - */ - inline void randomseed(uint64_t seed) + RandomGenerator *rng; + +public: + + virtual ~Math(); + + /** + * @copydoc RandomGenerator::randomseed() + **/ + inline void randomseed(uint64 seed) { - rng_state = seed; + rng->randomseed(seed); } - /** Return uniformly distributed pseudo random integer. - * - * @returns Pseudo random integer in [0,2^64). - */ - uint64 rand(); - - /** Get uniformly distributed pseudo random number in [0,1). - * - * @returns Pseudo random number in [0,1). - */ + /** + * @copydoc RandomGenerator::random() + **/ inline double random() { - return double(rand()) / (double(std::numeric_limits::max()) + 1.0); + return rng->random(); } - /** Get uniformly distributed pseudo random number in [0,max). - * - * @returns Pseudo random number in [0,max). - */ + /** + * @copydoc RandomGenerator::random(double) + **/ inline double random(double max) { - return random() * max; + return rng->random(max); } - /** Get uniformly distributed pseudo random number in [min, max). - * - * @returns Pseudo random number in [min, max). - */ + /** + * @copydoc RandomGenerator::random(double,double) + **/ inline double random(double min, double max) { - return random() * (max - min) + min; + return rng->random(min, max); } - /** Get normally distributed pseudo random number. - * - * @param stddev Standard deviation of the distribution. - * @returns Normally distributed random number with mean 0 and variance (stddev)². - */ - double randnormal(double stddev); + /** + * @copydoc RandomGenerator::randnormal() + **/ + inline double randnormal(double stddev) + { + return rng->randnormal(stddev); + } + + /** + * Create a new random number generator. + **/ + RandomGenerator *newRandomGenerator(); virtual const char *getName() const { return "love.math"; } - /** Triangulate a simple polygon. + /** + * Triangulate a simple polygon. + * * @param polygon Polygon to triangulate. Must not intersect itself. - * @returns List of triangles the polygon is composed of. - */ + * @return List of triangles the polygon is composed of. + **/ std::vector triangulate(const std::vector &polygon); static Math instance; private: + Math(); - uint64 rng_state; - double last_randnormal; -}; +}; // Math } // math } // love diff --git a/src/modules/math/RandomGenerator.cpp b/src/modules/math/RandomGenerator.cpp new file mode 100644 index 000000000..4752aef07 --- /dev/null +++ b/src/modules/math/RandomGenerator.cpp @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#include "RandomGenerator.h" + +// STL +#include + +namespace love +{ +namespace math +{ + +// 64 bit Xorshift implementation taken from the end of Sec. 3 (page 4) in +// George Marsaglia, "Xorshift RNGs", Journal of Statistical Software, Vol.8 (Issue 14), 2003 + +RandomGenerator::RandomGenerator() + : last_randnormal(std::numeric_limits::infinity()) +{ + // because it is too big for some compilers to handle ... if you know what + // i mean + union + { + uint64 b64; + struct + { + uint32 a; + uint32 b; + } b32; + } converter; + +#ifdef LOVE_BIG_ENDIAN + converter.b32.a = 0x0139408D; + converter.b32.b = 0xCBBF7A44; +#else + converter.b32.b = 0x0139408D; + converter.b32.a = 0xCBBF7A44; +#endif + + rng_state = converter.b64; +} + +uint64 RandomGenerator::rand() +{ + rng_state ^= (rng_state << 13); + rng_state ^= (rng_state >> 7); + rng_state ^= (rng_state << 17); + return rng_state; +} + +// Box–Muller transform +double RandomGenerator::randnormal(double stddev) +{ + // use cached number if possible + if (last_randnormal != std::numeric_limits::infinity()) + { + double r = last_randnormal; + last_randnormal = std::numeric_limits::infinity(); + return r * stddev; + } + + double r = sqrt(-2.0 * log(1. - random())); + double phi = 2.0 * LOVE_M_PI * (1. - random()); + + last_randnormal = r * cos(phi); + return r * sin(phi) * stddev; +} + +} // math +} // love diff --git a/src/modules/math/RandomGenerator.h b/src/modules/math/RandomGenerator.h new file mode 100644 index 000000000..b7fd7f53e --- /dev/null +++ b/src/modules/math/RandomGenerator.h @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#ifndef LOVE_MATH_RANDOM_GENERATOR_H +#define LOVE_MATH_RANDOM_GENERATOR_H + +// LOVE +#include "common/math.h" +#include "common/int.h" +#include "common/Object.h" + +// STL +#include + +namespace love +{ +namespace math +{ + +class RandomGenerator : public Object +{ +public: + + RandomGenerator(); + + virtual ~RandomGenerator() {}; + + /** + * Set pseudo random seed. + * It's up to the implementation how to use this. + * + * @param seed The random seed. + **/ + inline void randomseed(uint64 seed) + { + rng_state = seed; + } + + /** + * Return uniformly distributed pseudo random integer. + * + * @return Pseudo random integer in [0,2^64). + **/ + uint64 rand(); + + /** + * Get uniformly distributed pseudo random number in [0,1). + * + * @return Pseudo random number in [0,1). + **/ + inline double random() + { + return double(rand()) / (double(std::numeric_limits::max()) + 1.0); + } + + /** + * Get uniformly distributed pseudo random number in [0,max). + * + * @return Pseudo random number in [0,max). + **/ + inline double random(double max) + { + return random() * max; + } + + /** + * Get uniformly distributed pseudo random number in [min, max). + * + * @return Pseudo random number in [min, max). + **/ + inline double random(double min, double max) + { + return random() * (max - min) + min; + } + + /** + * Get normally distributed pseudo random number. + * + * @param stddev Standard deviation of the distribution. + * @return Normally distributed random number with mean 0 and variance (stddev)². + **/ + double randnormal(double stddev); + +private: + + uint64 rng_state; + double last_randnormal; + +}; // RandomGenerator + +} // math +} // love + +#endif // LOVE_MATH_RANDOM_GENERATOR_H diff --git a/src/modules/math/wrap_Math.cpp b/src/modules/math/wrap_Math.cpp index b2737c7f7..88409bc64 100644 --- a/src/modules/math/wrap_Math.cpp +++ b/src/modules/math/wrap_Math.cpp @@ -19,7 +19,8 @@ **/ #include "wrap_Math.h" -#include "modules/math/MathModule.h" +#include "wrap_RandomGenerator.h" +#include "MathModule.h" #include #include @@ -31,42 +32,14 @@ namespace math int w_randomseed(lua_State *L) { - union - { - double seed_double; - uint64_t seed_uint; - } s; - - s.seed_double = luaL_checknumber(L, 1); - Math::instance.randomseed(s.seed_uint); + uint64 seed = luax_checkrandomseed(L, 1); + Math::instance.randomseed(seed); return 0; } int w_random(lua_State *L) { - double r = Math::instance.random(); - int l, u; - // verbatim from lua 5.1.4 source code: lmathlib.c:185 ff. - switch (lua_gettop(L)) - { - case 0: - lua_pushnumber(L, r); - break; - case 1: - u = luaL_checkint(L, 1); - luaL_argcheck(L, 1 <= u, 1, "interval is empty"); - lua_pushnumber(L, floor(r * u) + 1); - break; - case 2: - l = luaL_checkint(L, 1); - u = luaL_checkint(L, 2); - luaL_argcheck(L, l <= u, 2, "interval is empty"); - lua_pushnumber(L, floor(r * (u - l + 1)) + l); - break; - default: - return luaL_error(L, "wrong number of arguments"); - } - return 1; + return luax_getrandom(L, 1, Math::instance.random()); } int w_randnormal(lua_State *L) @@ -87,6 +60,20 @@ int w_randnormal(lua_State *L) return 1; } +int w_newRandomGenerator(lua_State *L) +{ + RandomGenerator *t = Math::instance.newRandomGenerator(); + + if (lua_gettop(L) > 0) + { + uint64 seed = luax_checkrandomseed(L, 1); + t->randomseed(seed); + } + + luax_newtype(L, "RandomGenerator", MATH_RANDOM_GENERATOR_T, (void *) t); + return 1; +} + int w_triangulate(lua_State *L) { std::vector vertices; @@ -167,12 +154,14 @@ static const luaL_Reg functions[] = { "randomseed", w_randomseed }, { "random", w_random }, { "randnormal", w_randnormal }, + { "newRandomGenerator", w_newRandomGenerator }, { "triangulate", w_triangulate }, { 0, 0 } }; static const lua_CFunction types[] = { + luaopen_randomgenerator, 0 }; diff --git a/src/modules/math/wrap_Math.h b/src/modules/math/wrap_Math.h index f9cecb93f..3fefbcb30 100644 --- a/src/modules/math/wrap_Math.h +++ b/src/modules/math/wrap_Math.h @@ -33,6 +33,7 @@ namespace math int w_randomseed(lua_State *L); int w_random(lua_State *L); int w_randnormal(lua_State *L); +int w_newRandomGenerator(lua_State *L); int w_triangulate(lua_State *L); extern "C" LOVE_EXPORT int luaopen_love_math(lua_State *L); diff --git a/src/modules/math/wrap_RandomGenerator.cpp b/src/modules/math/wrap_RandomGenerator.cpp new file mode 100644 index 000000000..348eb77cd --- /dev/null +++ b/src/modules/math/wrap_RandomGenerator.cpp @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#include "wrap_RandomGenerator.h" + +#include + +namespace love +{ +namespace math +{ + +uint64 luax_checkrandomseed(lua_State *L, int idx) +{ + union + { + double seed_double; + uint64 seed_uint; + } s; + + s.seed_double = luaL_checknumber(L, idx); + + return s.seed_uint; +} + +int luax_getrandom(lua_State *L, int startidx, double r) +{ + int l, u; + // from lua 5.1.4 source code: lmathlib.c:185 ff. + switch (lua_gettop(L) - (startidx - 1)) + { + case 0: + lua_pushnumber(L, r); + break; + case 1: + u = luaL_checkint(L, startidx); + luaL_argcheck(L, 1 <= u, startidx, "interval is empty"); + lua_pushnumber(L, floor(r * u) + 1); + break; + case 2: + l = luaL_checkint(L, startidx); + u = luaL_checkint(L, startidx + 1); + luaL_argcheck(L, l <= u, startidx + 1, "interval is empty"); + lua_pushnumber(L, floor(r * (u - l + 1)) + l); + break; + default: + return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + +RandomGenerator *luax_checkrandomgenerator(lua_State *L, int idx) +{ + return luax_checktype(L, idx, "RandomGenerator", MATH_RANDOM_GENERATOR_T); +} + +int w_RandomGenerator_randomseed(lua_State *L) +{ + RandomGenerator *rng = luax_checkrandomgenerator(L, 1); + uint64 seed = luax_checkrandomseed(L, 2); + rng->randomseed(seed); + return 0; +} + +int w_RandomGenerator_random(lua_State *L) +{ + RandomGenerator *rng = luax_checkrandomgenerator(L, 1); + return luax_getrandom(L, 2, rng->random()); +} + +int w_RandomGenerator_randnormal(lua_State *L) +{ + RandomGenerator *rng = luax_checkrandomgenerator(L, 1); + + double mean = 0.0, stddev = 1.0; + if (lua_gettop(L) > 2) + { + mean = luaL_checknumber(L, 2); + stddev = luaL_checknumber(L, 3); + } + else + { + stddev = luaL_optnumber(L, 2, 1.0); + } + + double r = rng->randnormal(stddev); + lua_pushnumber(L, r + mean); + return 1; +} + +static const luaL_Reg functions[] = +{ + { "randomseed", w_RandomGenerator_randomseed }, + { "random", w_RandomGenerator_random }, + { "randnormal", w_RandomGenerator_randnormal }, + { 0, 0 } +}; + +extern "C" int luaopen_randomgenerator(lua_State *L) +{ + return luax_register_type(L, "RandomGenerator", functions); +} + +} // math +} // love diff --git a/src/modules/math/wrap_RandomGenerator.h b/src/modules/math/wrap_RandomGenerator.h new file mode 100644 index 000000000..9482fa589 --- /dev/null +++ b/src/modules/math/wrap_RandomGenerator.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#ifndef LOVE_MATH_WRAP_RANDOM_GENERATOR_H +#define LOVE_MATH_WRAP_RANDOM_GENERATOR_H + +// LOVE +#include "RandomGenerator.h" +#include "common/config.h" +#include "common/runtime.h" + +namespace love +{ +namespace math +{ + +// Helper functions. +uint64 luax_checkrandomseed(lua_State *L, int idx); +int luax_getrandom(lua_State *L, int startidx, double r); + +RandomGenerator *luax_checkrandomgenerator(lua_State *L, int idx); +int w_RandomGenerator_randomseed(lua_State *L); +int w_RandomGenerator_random(lua_State *L); +int w_RandomGenerator_randnormal(lua_State *L); +extern "C" int luaopen_randomgenerator(lua_State *L); + +} // math +} // love + +#endif // LOVE_MATH_WRAP_RANDOM_GENERATOR_H