Skip to content

Instantly share code, notes, and snippets.

@inmatarian
Created January 11, 2017 17:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inmatarian/9635d0d03eeec943acac13a2bff25b96 to your computer and use it in GitHub Desktop.
Save inmatarian/9635d0d03eeec943acac13a2bff25b96 to your computer and use it in GitHub Desktop.
Linear Feedback Shift Register pseudorandom number generator in lua
-- LFSRs are good for games where you want a random number generator with a short period,
-- so that speed runners can device tactics to control the RNG's state.
-- Otherwise they're a bit of an obsolete piece of tech.
-- See: https://en.wikipedia.org/wiki/Linear-feedback_shift_register
-- LFSRs work by shifting all of the bits to the right by one, and using the shifted
-- out bit to XOR in at specific taps. Another way to put it is that they first check
-- if the state is odd, then divides by two, and if it was odd, Exclusive-Ors in a value.
-- The bit shifted out is suitably random. Want more bits, cycle the generator more.
-- Note: Uses bit library and not bit32, would need minor conversion between the two.
require 'bit'
LFSR = {
value = 46080, -- taps 16 14 13 11
state = 44257
}
LFSR.__index = LFSR
function LFSR:seed(state)
self.state = bit.band(state, 65535)
if self.state <= 0 then self.state = 1 end
end
function LFSR:randBits(n)
n = n or 8
local state, value, ret, b = self.state, self.value, 0
repeat
b = bit.band(state, 1)
state = bit.bxor(bit.rshift(state, 1), bit.band(-b, value))
ret, n = bit.lshift(ret, 1) + b, n - 1
until n <= 0
self.state = state
return ret
end
--
function calculatePeriod(R)
local start, iter = R.state, 0, 0
repeat
R:randBits(1)
iter = iter + 1
assert(iter < 10000000)
until R.state == start
return iter
end
function showSample(R)
for i = 1, 16 do
for j = 1, 12 do
io.write(R:randBits(8), '\t')
end
io.write('\n')
end
end
print("Period:", calculatePeriod(setmetatable({}, LFSR)))
showSample(setmetatable({}, LFSR))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment