A small tweak to lua random
This commit is contained in:
@@ -157,6 +157,10 @@ uint64_t hash_ints(uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
|
||||
return h1;
|
||||
}
|
||||
|
||||
double hash_to_double(uint64_t hash) {
|
||||
return (hash >> (64-53)) * 0x1p-53;
|
||||
}
|
||||
|
||||
StringVec split(const eng::string &s, char sep) {
|
||||
StringVec result;
|
||||
int start = 0;
|
||||
@@ -498,6 +502,10 @@ LuaDefine(unittests_util, "", "some unit tests") {
|
||||
LuaAssertStrEq(L, util::hash_to_hex(util::HashValue(0x1234,0x789a)),
|
||||
"0000000000001234000000000000789a");
|
||||
|
||||
// Test hash_to_double
|
||||
LuaAssert(L, util::hash_to_double(0x1000000000000000) == 1.0/16.0);
|
||||
LuaAssert(L, util::hash_to_double(0x7000000000000000) == 7.0/16.0);
|
||||
LuaAssert(L, util::hash_to_double(0xF000000000000000) == 15.0/16.0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ eng::string hash_to_hex(const HashValue &hash);
|
||||
// This is a good hash, but not cryptographically good.
|
||||
uint64_t hash_ints(uint64_t n1, uint64_t n2, uint64_t n3, uint64_t n4);
|
||||
|
||||
// Convert a 64-bit hash value into a floating point number between 0 and 1.
|
||||
double hash_to_double(uint64_t hash);
|
||||
|
||||
// Split a string into multiple strings
|
||||
StringVec split(const eng::string &s, char sep);
|
||||
|
||||
|
||||
@@ -412,12 +412,15 @@ LuaDefine(math_random, "(args...)",
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the hash and convert to a lua_Number.
|
||||
uint64_t hash = util::hash_ints(seed, count, salt, 456);
|
||||
if (!have_range) {
|
||||
double result = (hash & LuaStack::MAXINT) * 0x1p-53;
|
||||
lua_pushnumber(L, result);
|
||||
// Generate the hash and convert to a double.
|
||||
uint64_t hash = util::hash_ints(seed, count, salt, 456);
|
||||
lua_pushnumber(L, util::hash_to_double(hash));
|
||||
} else {
|
||||
// Generate the hash and scale it into the desired range.
|
||||
// This code is not quite right: the results are not quite
|
||||
// uniform, this is especially true for very long ranges.
|
||||
uint64_t hash = util::hash_ints(seed, count, salt, 456);
|
||||
uint64_t range = (high - low) + 1;
|
||||
uint64_t offset = (hash & 0x7FFFFFFFFFFFFFFF) % range;
|
||||
int64_t result = low + int64_t(offset);
|
||||
|
||||
Reference in New Issue
Block a user