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;
|
return h1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double hash_to_double(uint64_t hash) {
|
||||||
|
return (hash >> (64-53)) * 0x1p-53;
|
||||||
|
}
|
||||||
|
|
||||||
StringVec split(const eng::string &s, char sep) {
|
StringVec split(const eng::string &s, char sep) {
|
||||||
StringVec result;
|
StringVec result;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
@@ -498,6 +502,10 @@ LuaDefine(unittests_util, "", "some unit tests") {
|
|||||||
LuaAssertStrEq(L, util::hash_to_hex(util::HashValue(0x1234,0x789a)),
|
LuaAssertStrEq(L, util::hash_to_hex(util::HashValue(0x1234,0x789a)),
|
||||||
"0000000000001234000000000000789a");
|
"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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ eng::string hash_to_hex(const HashValue &hash);
|
|||||||
// This is a good hash, but not cryptographically good.
|
// 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);
|
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
|
// Split a string into multiple strings
|
||||||
StringVec split(const eng::string &s, char sep);
|
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) {
|
if (!have_range) {
|
||||||
double result = (hash & LuaStack::MAXINT) * 0x1p-53;
|
// Generate the hash and convert to a double.
|
||||||
lua_pushnumber(L, result);
|
uint64_t hash = util::hash_ints(seed, count, salt, 456);
|
||||||
|
lua_pushnumber(L, util::hash_to_double(hash));
|
||||||
} else {
|
} 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 range = (high - low) + 1;
|
||||||
uint64_t offset = (hash & 0x7FFFFFFFFFFFFFFF) % range;
|
uint64_t offset = (hash & 0x7FFFFFFFFFFFFFFF) % range;
|
||||||
int64_t result = low + int64_t(offset);
|
int64_t result = low + int64_t(offset);
|
||||||
|
|||||||
Reference in New Issue
Block a user