mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Implemented LuaJIT FFI versions of love.math.random and RandomGenerator:random.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user