Page 3 of 4
Re: RandomLua Library
Posted: Mon Aug 22, 2011 8:30 pm
by Boolsheet
Yes, it's probably the Lua number type. Lua uses by default a double precision floating-point number and AGen seems to be using a Lua built with single precision floating-point numbers. 32-bit integers loose precision because 32-bit floats only have 22 bits for the significand.
Re: RandomLua Library
Posted: Tue Jan 03, 2012 5:34 pm
by CarSoccerRobots
linux-man, thank you for this library!
We're using it in an upcoming project and it is really quite spiffy for our simple needs. It's the first PRNG implementation in pure Lua we found which doesn't require additional bitwise operation libraries.
Re: RandomLua Library
Posted: Mon Sep 09, 2013 9:31 pm
by posfan12
I'm trying to use these scripts in Lua 4.0. Here's my attempt of doing the translation. Lua 4 doesn't have a "setmetatable" function, so I made a guess at what to do in my case.
Code: Select all
function lcg(s, r)
local temp = {}
function temp:random(a, b)
local y = mod(self.a * self.x + self.c, self.m)
self.x = y
if not a then
return y / 65536
elseif not b then
if a == 0 then
return y
else
return 1 + mod(y, a)
end
else
return a + mod(y, b - a + 1)
end
end
function temp:randomseed(s)
if not s then
s = seed()
end
self.x = mod(s, 2147483648)
end
if r then
--from Numerical Recipes
if r == 'nr' then
temp.a = 1664525
temp.c = 1013904223
temp.m = 65536
--from MVC
elseif r == 'mvc' then
temp.a = 214013
temp.c = 2531011
temp.m = 65536
end
--from Ansi C
else
temp.a = 1103515245
temp.c = 12345
temp.m = 65536
end
temp:randomseed(s)
return temp
end
print("wutwut =" .. lcg(0):random())
print("wutwut =" .. lcg(0):random())
print("wutwut =" .. lcg(0):random())
Anyway, the problem is that the script is outputting the same decimal value every time I run it. Is this because I am using the script improperly? What is the proper way of using the script? Thanks!!
Mike
Re: RandomLua Library
Posted: Tue Sep 10, 2013 2:10 am
by davisdude
Actually, Lua does have a setmetatable function:
http://www.lua.org/pil/13.html
Re: RandomLua Library
Posted: Tue Sep 10, 2013 3:10 am
by slime
metatables got added in Lua 5.0. I'm not sure why anyone would use Lua 4.0 though... Lua 5.0 was released a decade ago. Lua 5.1 seven years ago, and Lua 5.2 two years ago (and unfortunately the online version of PiL is still the first edition, for Lua 5.0.)
Re: RandomLua Library
Posted: Tue Sep 10, 2013 3:18 am
by posfan12
I'm working on a game called Homeworld 2 which was released in 2003 and uses Lua 4.0.
I had another person test my script and it worked OK in Lua 4.0.1, so I am SOL I guess unless someone has a better suggestion...
Re: RandomLua Library
Posted: Tue Sep 10, 2013 11:10 am
by Boolsheet
It is not surprising that your script prints the same line three times. You create a new generator every time with the same seed and that will obviously return the same number. Save the table and call random on that a few times.
Code: Select all
local gen = lcg(0)
print("wutwut =" .. gen:random())
print("wutwut =" .. gen:random())
print("wutwut =" .. gen:random())
If you're already aware of that, you might want to check if Homeworld 2 was compiled with a Lua that uses single-precision floating-point numbers. If so, calculations that go over 2^24 will not get the results you want. Here's a function that tests for some formats.
Code: Select all
function TestLuaNumberFormat()
local dbl = 2 ^ 53
local flt = 2 ^ 24
local int32 = 1073741823 * 2 + 1
local uint32 = 1073741823 * 4 + 3
local int64 = (1073741823 * 131072 + 131071) * 65536 + 65535
local uint64 = (1073741823 * 131072 + 131071) * 131072 + 131071
local fmt
if dbl ~= dbl - 1 and dbl == dbl + 1 then
fmt = "double-precision floating-point number"
elseif flt ~= flt - 1 and flt == flt + 1 then
fmt = "single-precision floating-point number"
elseif int32 > 0 and int32 + 1 < 0 then
fmt = "signed 32-bit integer"
elseif uint32 > 0 and uint32 + 1 == 0 and uint32 + 2 == 1 then
fmt = "unsigned 32-bit integer"
elseif int64 > 0 and int64 + 1 < 0 then
fmt = "signed 64-bit integer"
elseif uint64 > 0 and uint64 + 1 == 0 and uint64 + 2 == 1 then
fmt = "unsigned 64-bit integer"
end
if fmt then
print("Feels like " .. fmt .. ".")
else
print("Unkown format.")
end
end
Edit: Looking at it again, Lua 4.0 does not provide an easy way to change it to single precision. Unless they modified it, it's probably double precision.
Re: RandomLua Library
Posted: Tue Sep 10, 2013 4:55 pm
by posfan12
I ran TestLuaNumberFormat() and got "Feels like single-precision floating-point number".
Re: RandomLua Library
Posted: Tue Sep 10, 2013 6:50 pm
by Boolsheet
Didn't expect that. You can rewrite it a bit to get the same results with single precision.
Code: Select all
function mul16(a, b)
local a_lo, b_lo = mod(a, 2^8), mod(b, 2^8)
local a_hi, b_hi = a - a_lo, b - b_lo
return mod(a_lo * b_lo + mod(a_lo * b_hi, 2^16) + mod(a_hi * b_lo, 2^16) + mod(a_hi * b_hi, 2^16), 2^16)
end
function lcg(s, r)
local temp = {}
function temp:random(a, b)
local y = mod(mul16(self.a, self.x) + self.c, self.m)
self.x = y
if not a then
return y / 65536
elseif not b then
if a == 0 then
return y
else
return 1 + mod(y, a)
end
else
return a + mod(y, b - a + 1)
end
end
function temp:randomseed(s)
if not s then
s = seed()
end
self.x = mod(s, 2147483648)
end
-- 'Numerical Recipes' parameters
temp.a = 26125
temp.c = 62303
temp.m = 65536
temp:randomseed(s)
return temp
end
No guarantees on the statistical properties!
Re: RandomLua Library
Posted: Wed Sep 11, 2013 12:57 pm
by posfan12
This one works! No duplicate values after 10000 iterations.
I just need to figure out how to rewrite all my scripts. Currently I just pass the seeds to whatever functions need them. For instance,
Code: Select all
local my_seed_1 = {977322}
function srandom(seedobj, fVal1, fVal2)
seedobj[1] = mod(seedobj[1] * 1103515245 + 12345, 4294967296)
local temp_rand = seedobj[1] / (4294967296 - 1)
if (fVal2) then
return floor(fVal1 + 0.5 + temp_rand * (fVal2 - fVal1))
elseif (fVal1) then
return floor(temp_rand * fVal1) + 1
else
return temp_rand
end
end
print(srandom(my_seed_1))