ソースを参照

'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.
Roberto Ierusalimschy 6 年 前
コミット
4eefef07ab
4 ファイル変更27 行追加7 行削除
  1. 7 2
      lmathlib.c
  2. 3 0
      manual/manual.of
  3. 8 3
      testes/all.lua
  4. 9 2
      testes/math.lua

+ 7 - 2
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);
 }
 

+ 3 - 0
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),

+ 8 - 3
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")
 
 

+ 9 - 2
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 <const> h = 0x7a7040a5   -- higher half
   local <const> l = 0xa323c9d6   -- lower half
 
@@ -840,7 +840,14 @@ do
   assert(rand * 2^floatbits == res)
 end
 
-math.randomseed()
+do
+  -- testing return of 'randomseed'
+  local <const> x, <const> 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