2023-11-13 11:00:27 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
add rand module
diff --git a/lib/arco.lua b/lib/arco.lua index 8d2522e..3eb1655 100644 --- a/lib/arco.lua +++ b/lib/arco.lua @@ -1,4 +1,5 @@ local arco = {} arco.sdl = require "arco.sdl2" arco.net = require "arco.enet" +arco.rand = require "arco.rand" return arco diff --git a/lib/arco/rand.lua b/lib/arco/rand.lua new file mode 100644 index 0000000..9f0a43e --- /dev/null +++ b/lib/arco/rand.lua @@ -0,0 +1,51 @@ +local bit = require "bit" + +local floor = math.floor +local xor = bit.bxor +local lshift, rshift = bit.lshift, bit.rshift + +local PRNG = {} +PRNG.__index = PRNG + +function PRNG:rand32() + -- XorShift32 + local x = self.state + local x = xor(x, lshift(x, 13)) + local x = xor(x, rshift(x, 17)) + local x = xor(x, lshift(x, 5)) + self.state = x + return x +end + +function PRNG:rand() + return (self:rand32() / 2147483648 + 1) / 2 +end + +function PRNG:randint(a, b) + return floor(self:rand() * (b-a+1) + a) +end + +function PRNG:shuffle(t) + -- Fisher-Yates + for i = 1, #t-1 do + local j = self:randint(i, #t) + t[i], t[j] = t[j], t[i] + end +end + +-- reduce seed bias +function PRNG:_warmup() + for i = 1, 256 do + self:rand32() + end +end + +local function new_prng(seed) + assert(seed ~= 0, "random seed cannot be zero") + seed = seed or os.time() + local self = setmetatable({state=seed}, PRNG) + self:_warmup() + return self +end + +return {new_prng=new_prng}