feat(rng): add deterministic splitmix64 prng
This commit is contained in:
1 parent
20caa41d37
commit
b36c304505
1 file changed
+47
+47
@@ -0,0 +1,47 @@
|
||||
-- Deterministic 64-bit PRNG (splitmix64). Same seed always yields the same
|
||||
-- stream, independent of platform and of the global math.random state.
|
||||
|
||||
local Rng = {}
|
||||
Rng.__index = Rng
|
||||
|
||||
local GOLDEN = 0x9E3779B97F4A7C15
|
||||
local MIX1 = 0xBF58476D1CE4E5B9
|
||||
local MIX2 = 0x94D049BB133111EB
|
||||
|
||||
function Rng.new(seed)
|
||||
return setmetatable({ state = math.tointeger(seed) or 0 }, Rng)
|
||||
end
|
||||
|
||||
function Rng:nextUint()
|
||||
self.state = self.state + GOLDEN
|
||||
local z = self.state
|
||||
z = (z ~ (z >> 30)) * MIX1
|
||||
z = (z ~ (z >> 27)) * MIX2
|
||||
z = z ~ (z >> 31)
|
||||
return z
|
||||
end
|
||||
|
||||
-- Inclusive integer in [lo, hi]. Modulo of a signed value by a positive span
|
||||
-- lands in [0, span) under Lua's floor-division remainder.
|
||||
function Rng:range(lo, hi)
|
||||
local span = hi - lo + 1
|
||||
return lo + self:nextUint() % span
|
||||
end
|
||||
|
||||
function Rng:chance(numerator, denominator)
|
||||
return self:range(1, denominator) <= numerator
|
||||
end
|
||||
|
||||
function Rng:pick(list)
|
||||
return list[self:range(1, #list)]
|
||||
end
|
||||
|
||||
function Rng:serialize()
|
||||
return { state = self.state }
|
||||
end
|
||||
|
||||
function Rng.deserialize(snapshot)
|
||||
return setmetatable({ state = snapshot.state }, Rng)
|
||||
end
|
||||
|
||||
return Rng
|
||||
Reference in new issue
Block a user