From 4eefef07ab1c136f901d816822c79336fa89336d Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 17 Jul 2019 16:00:24 -0300 Subject: [PATCH] 'math.randomseed()' returns the seeds it used A call to 'math.randomseed()' returns the two components of the seed it set, so that they can be used to set that same seed again. --- lmathlib.c | 9 +++++++-- manual/manual.of | 3 +++ testes/all.lua | 11 ++++++++--- testes/math.lua | 11 +++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/lmathlib.c b/lmathlib.c index f6f0b426..1d310b2d 100644 --- a/lmathlib.c +++ b/lmathlib.c @@ -605,20 +605,24 @@ static void setseed (Rand64 *state, lua_Unsigned n1, lua_Unsigned n2) { static void randseed (lua_State *L, RanState *state) { lua_Unsigned seed1 = (lua_Unsigned)time(NULL); lua_Unsigned seed2 = (lua_Unsigned)(size_t)L; + lua_pushinteger(L, seed1); + lua_pushinteger(L, seed2); setseed(state->s, seed1, seed2); } static int math_randomseed (lua_State *L) { RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); - if (lua_isnone(L, 1)) + if (lua_isnone(L, 1)) { randseed(L, state); + return 2; /* return seeds */ + } else { lua_Integer n1 = luaL_checkinteger(L, 1); lua_Integer n2 = luaL_optinteger(L, 2, 0); setseed(state->s, n1, n2); + return 0; } - return 0; } @@ -635,6 +639,7 @@ static const luaL_Reg randfuncs[] = { static void setrandfunc (lua_State *L) { RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0); randseed(L, state); /* initialize with a "random" seed */ + lua_pop(L, 2); /* remove pushed seeds */ luaL_setfuncs(L, randfuncs, 1); } diff --git a/manual/manual.of b/manual/manual.of index 3d2fb4fb..7f2596fa 100644 --- a/manual/manual.of +++ b/manual/manual.of @@ -7798,6 +7798,9 @@ The default for @id{y} is zero. When called with no arguments, Lua generates a seed with a weak attempt for randomness. +In this case, +the call returns the two seed components that were used. + To ensure a required level of randomness to the initial state (or contrarily, to have a deterministic sequence, for instance when debugging a program), diff --git a/testes/all.lua b/testes/all.lua index 72121e8d..bf27f106 100644 --- a/testes/all.lua +++ b/testes/all.lua @@ -37,8 +37,6 @@ end -- tests should require debug when needed debug = nil -require"bwcoercion" - if usertests then T = nil -- no "internal" tests for user tests @@ -46,7 +44,6 @@ else T = rawget(_G, "T") -- avoid problems with 'strict' module end -math.randomseed(0) --[=[ example of a long [comment], @@ -54,6 +51,14 @@ math.randomseed(0) ]=] +print("\n\tStarting Tests") + +do + -- set random seed + local random_x, random_y = math.randomseed() + print(string.format("random seeds: %d, %d", random_x, random_y)) +end + print("current path:\n****" .. package.path .. "****\n") diff --git a/testes/math.lua b/testes/math.lua index befce12e..0c297e74 100644 --- a/testes/math.lua +++ b/testes/math.lua @@ -815,7 +815,7 @@ end -- low-level!! For the current implementation of random in Lua, -- the first call after seed 1007 should return 0x7a7040a5a323c9d6 do - -- all computations assume at most 32-bit integers + -- all computations should work with 32-bit integers local h = 0x7a7040a5 -- higher half local l = 0xa323c9d6 -- lower half @@ -840,7 +840,14 @@ do assert(rand * 2^floatbits == res) end -math.randomseed() +do + -- testing return of 'randomseed' + local x, y = math.randomseed() + local res = math.random(0) + math.randomseed(x, y) -- should repeat the state + assert(math.random(0) == res) + -- keep the random seed for following tests +end do -- test random for floats local randbits = math.min(floatbits, 64) -- at most 64 random bits