forked from Mirrorlandia_minetest/minetest
Simplify LuaPseudoRandom::l_next and fix docs
Also extends the allowed range on the C++ side. This has no side-effects.
This commit is contained in:
parent
d20f1182f2
commit
e824e9023f
@ -8061,7 +8061,9 @@ A 32-bit pseudorandom number generator.
|
|||||||
Uses PCG32, an algorithm of the permuted congruential generator family,
|
Uses PCG32, an algorithm of the permuted congruential generator family,
|
||||||
offering very strong randomness.
|
offering very strong randomness.
|
||||||
|
|
||||||
It can be created via `PcgRandom(seed)` or `PcgRandom(seed, sequence)`.
|
* constructor `PcgRandom(seed, [seq])`
|
||||||
|
* `seed`: 64-bit unsigned seed
|
||||||
|
* `seq`: 64-bit unsigned sequence, optional
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
@ -8156,14 +8158,15 @@ Can be obtained using `player:get_meta()`.
|
|||||||
A 16-bit pseudorandom number generator.
|
A 16-bit pseudorandom number generator.
|
||||||
Uses a well-known LCG algorithm introduced by K&R.
|
Uses a well-known LCG algorithm introduced by K&R.
|
||||||
|
|
||||||
It can be created via `PseudoRandom(seed)`.
|
* constructor `PseudoRandom(seed)`
|
||||||
|
* `seed`: 32-bit signed number
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
* `next()`: return next integer random number [`0`...`32767`]
|
* `next()`: return next integer random number [`0`...`32767`]
|
||||||
* `next(min, max)`: return next integer random number [`min`...`max`]
|
* `next(min, max)`: return next integer random number [`min`...`max`]
|
||||||
* `((max - min) == 32767) or ((max-min) <= 6553))` must be true
|
* Either `max - min == 32767` or `max - min <= 6553` must be true
|
||||||
due to the simple implementation making bad distribution otherwise.
|
due to the simple implementation making a bad distribution otherwise.
|
||||||
|
|
||||||
`Raycast`
|
`Raycast`
|
||||||
---------
|
---------
|
||||||
|
@ -6,6 +6,8 @@ local function test_random()
|
|||||||
|
|
||||||
local pr2 = PseudoRandom(-101)
|
local pr2 = PseudoRandom(-101)
|
||||||
assert(pr2:next(0, 100) == 35)
|
assert(pr2:next(0, 100) == 35)
|
||||||
|
-- unusual case that is normally disallowed:
|
||||||
|
assert(pr2:next(10000, 42767) == 12485)
|
||||||
end
|
end
|
||||||
unittests.register("test_random", test_random)
|
unittests.register("test_random", test_random)
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ public:
|
|||||||
PcgRandom, we cannot modify this RNG's range as it would change the
|
PcgRandom, we cannot modify this RNG's range as it would change the
|
||||||
output of this RNG for reverse compatibility.
|
output of this RNG for reverse compatibility.
|
||||||
*/
|
*/
|
||||||
if ((u32)(max - min) > (RANDOM_RANGE + 1) / 10)
|
if ((u32)(max - min) > (RANDOM_RANGE + 1) / 5)
|
||||||
throw PrngException("Range too large");
|
throw PrngException("Range too large");
|
||||||
|
|
||||||
return (next() % (max - min + 1)) + min;
|
return (next() % (max - min + 1)) + min;
|
||||||
|
@ -405,25 +405,22 @@ int LuaPseudoRandom::l_next(lua_State *L)
|
|||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
LuaPseudoRandom *o = checkObject<LuaPseudoRandom>(L, 1);
|
LuaPseudoRandom *o = checkObject<LuaPseudoRandom>(L, 1);
|
||||||
int min = 0;
|
int min = 0, max = PseudoRandom::RANDOM_RANGE;
|
||||||
int max = 32767;
|
|
||||||
lua_settop(L, 3);
|
|
||||||
if (lua_isnumber(L, 2))
|
if (lua_isnumber(L, 2))
|
||||||
min = luaL_checkinteger(L, 2);
|
min = luaL_checkinteger(L, 2);
|
||||||
if (lua_isnumber(L, 3))
|
if (lua_isnumber(L, 3))
|
||||||
max = luaL_checkinteger(L, 3);
|
max = luaL_checkinteger(L, 3);
|
||||||
if (max < min) {
|
|
||||||
errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
|
int val;
|
||||||
throw LuaError("PseudoRandom.next(): max < min");
|
if (max - min == PseudoRandom::RANDOM_RANGE) {
|
||||||
|
val = o->m_pseudo.next() + min;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
val = o->m_pseudo.range(min, max);
|
||||||
|
} catch (PrngException &e) {
|
||||||
|
throw LuaError(e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(max - min != 32767 && max - min > 32767/5)
|
|
||||||
throw LuaError("PseudoRandom.next() max-min is not 32767"
|
|
||||||
" and is > 32768/5. This is disallowed due to"
|
|
||||||
" the bad random distribution the"
|
|
||||||
" implementation would otherwise make.");
|
|
||||||
PseudoRandom &pseudo = o->m_pseudo;
|
|
||||||
int val = pseudo.next();
|
|
||||||
val = (val % (max-min+1)) + min;
|
|
||||||
lua_pushinteger(L, val);
|
lua_pushinteger(L, val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ void TestRandom::testPseudoRandomRange()
|
|||||||
{
|
{
|
||||||
PseudoRandom pr((int)time(NULL));
|
PseudoRandom pr((int)time(NULL));
|
||||||
|
|
||||||
EXCEPTION_CHECK(PrngException, pr.range(2000, 6000));
|
EXCEPTION_CHECK(PrngException, pr.range(2000, 8600));
|
||||||
EXCEPTION_CHECK(PrngException, pr.range(5, 1));
|
EXCEPTION_CHECK(PrngException, pr.range(5, 1));
|
||||||
|
|
||||||
for (u32 i = 0; i != 32768; i++) {
|
for (u32 i = 0; i != 32768; i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user