login

<     >

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}