Last active
August 16, 2016 12:12
-
-
Save wyozi/c3bacf3e2d1a14ee0f8dba446869fc6f to your computer and use it in GitHub Desktop.
Mersenne twister using bit lib (orig: https://github.com/rangercyh/chance)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local N = 624 | |
local M = 397 | |
local MATRIX_A = 0x9908b0df | |
local UPPER_MASK = 0x80000000 | |
local LOWER_MASK = 0x7fffffff | |
local band, bor, bxor, blshift, brshift = bit.band, bit.bor, bit.bxor, bit.lshift, bit.rshift | |
-- initializes mt[N] with a seed | |
local function init_genrand(o, s) | |
o.mt[0] = band(s, 0xffffffff) | |
for i = 1, N - 1 do | |
o.mt[i] = (1812433253 * bxor(o.mt[i - 1], brshift(o.mt[i - 1], 30))) + i | |
-- See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. | |
-- In the previous versions, MSBs of the seed affect | |
-- only MSBs of the array mt[]. | |
-- 2002/01/09 modified by Makoto Matsumoto | |
o.mt[i] = band(o.mt[i], 0xffffffff) | |
-- for >32 bit machines | |
end | |
o.mti = N | |
end | |
-- generates a random number on [0,0xffffffff]-interval | |
local function genrand_int32(o) | |
local y | |
local mag01 = {} -- mag01[x] = x * MATRIX_A for x=0,1 | |
mag01[0] = 0x0 | |
mag01[1] = MATRIX_A | |
if o.mti >= N then -- generate N words at one time | |
if o.mti == N + 1 then -- if init_genrand() has not been called, | |
init_genrand(o, 5489) -- a default initial seed is used | |
end | |
for kk = 0, N - M - 1 do | |
y = bor(band(o.mt[kk], UPPER_MASK), band(o.mt[kk + 1], LOWER_MASK)) | |
o.mt[kk] = bxor(bxor(o.mt[kk + M], brshift(y, 1)), mag01[band(y, 0x1)]) | |
end | |
for kk = N - M, N - 2 do | |
y = bor(band(o.mt[kk], UPPER_MASK), band(o.mt[kk + 1], LOWER_MASK)) | |
o.mt[kk] = bxor(bxor(o.mt[kk + (M - N)], brshift(y, 1)), mag01[band(y, 0x1)]) | |
end | |
y = bor(band(o.mt[N - 1], UPPER_MASK), band(o.mt[0], LOWER_MASK)) | |
o.mt[N - 1] = bxor(bxor(o.mt[M - 1], brshift(y, 1)), mag01[band(y, 0x1)]) | |
o.mti = 0 | |
end | |
y = o.mt[o.mti] | |
o.mti = o.mti + 1 | |
-- Tempering | |
y = bxor(y, brshift(y, 11)) | |
y = bxor(y, band(blshift(y, 7), 0x9d2c5680)) | |
y = bxor(y, band(blshift(y, 15), 0xefc60000)) | |
y = bxor(y, brshift(y, 18)) | |
return y | |
end | |
local MersenneTwister = {} | |
MersenneTwister.mt = {} | |
MersenneTwister.mti = N + 1 | |
local Random = {} | |
-- set new random seed | |
function Random.seed(seed) | |
init_genrand(MersenneTwister, seed) | |
end | |
-- generates a random number on [0,1)-real-interval | |
function Random.random() | |
return genrand_int32(MersenneTwister) * (1.0 / 4294967296.0) | |
end | |
--[[ | |
return a random integer | |
NOTE the min and max are INCLUDED in the range. | |
the max integer in lua is math.maxinteger | |
the min is math.mininteger | |
]] | |
function Random.integer(min, max) | |
assert(max >= min, "max must bigger than min") | |
return math.floor(Random.random() * (max - min + 1) + min) | |
end | |
return Random |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment