Implemented LuaJIT FFI versions of love.math.random and RandomGenerator:random.

This commit is contained in:
Alex Szpakowski
2015-12-10 12:45:53 -04:00
parent 7ee02e8d37
commit 52b1bd78f2
6 changed files with 175 additions and 40 deletions
+46 -30
View File
@@ -23,6 +23,11 @@
#include <cmath>
#include <algorithm>
// Put the Lua code directly into a raw string literal.
static const char randomgenerator_lua[] =
#include "wrap_RandomGenerator.lua"
;
namespace love
{
namespace math
@@ -56,41 +61,16 @@ RandomGenerator::Seed luax_checkrandomseed(lua_State *L, int idx)
return s;
}
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 = (int) luaL_checknumber(L, startidx);
luaL_argcheck(L, 1 <= u, startidx, "interval is empty");
lua_pushnumber(L, floor(r * u) + 1);
break;
case 2:
l = (int) luaL_checknumber(L, startidx);
u = (int) luaL_checknumber(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<RandomGenerator>(L, idx, MATH_RANDOM_GENERATOR_ID);
}
int w_RandomGenerator_random(lua_State *L)
int w_RandomGenerator__random(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
return luax_getrandom(L, 2, rng->random());
lua_pushnumber(L, rng->random());
return 1;
}
int w_RandomGenerator_randomNormal(lua_State *L)
@@ -135,9 +115,28 @@ int w_RandomGenerator_getState(lua_State *L)
return 1;
}
// C functions in a struct, necessary for the FFI versions of RandomGenerator functions.
struct FFI_RandomGenerator
{
double (*random)(Proxy *p);
};
static FFI_RandomGenerator ffifuncs =
{
[](Proxy *p) -> double // random()
{
// FIXME: We need better type-checking...
if (!typeFlags[p->type][MATH_RANDOM_GENERATOR_ID])
return 0.0;
RandomGenerator *rng = (RandomGenerator *) p->object;
return rng->random();
}
};
static const luaL_Reg w_RandomGenerator_functions[] =
{
{ "random", w_RandomGenerator_random },
{ "_random", w_RandomGenerator__random }, // random() is defined in wrap_RandomGenerator.lua.
{ "randomNormal", w_RandomGenerator_randomNormal },
{ "setSeed", w_RandomGenerator_setSeed },
{ "getSeed", w_RandomGenerator_getSeed },
@@ -148,7 +147,24 @@ static const luaL_Reg w_RandomGenerator_functions[] =
extern "C" int luaopen_randomgenerator(lua_State *L)
{
return luax_register_type(L, MATH_RANDOM_GENERATOR_ID, "RandomGenerator", w_RandomGenerator_functions, nullptr);
int n = luax_register_type(L, MATH_RANDOM_GENERATOR_ID, "RandomGenerator", w_RandomGenerator_functions, nullptr);
luax_gettypemetatable(L, MATH_RANDOM_GENERATOR_ID);
// Load and execute wrap_RandomGenerator.lua, sending the metatable and the
// ffi functions struct pointer as arguments.
if (lua_istable(L, -1))
{
luaL_loadbuffer(L, randomgenerator_lua, sizeof(randomgenerator_lua), "wrap_RandomGenerator.lua");
lua_pushvalue(L, -2);
lua_pushlightuserdata(L, &ffifuncs);
lua_call(L, 2, 0);
}
// Pop the metatable.
lua_pop(L, 1);
return n;
}
} // math