diff --git a/Makefile b/Makefile index 50fce33..3a556b0 100644 --- a/Makefile +++ b/Makefile @@ -1,38 +1,47 @@ # makefile for random library for Lua # change these to reflect your Lua installation -LUA= /tmp/lhf/lua-5.0 -LUAINC= $(LUA)/include -LUALIB= $(LUA)/lib -LUABIN= $(LUA)/bin - -# no need to change anything below here +LUA= /tmp/lhf/lua-5.1.4 +LUAINC= $(LUA)/src +LUALIB= $(LUA)/src +LUABIN= $(LUA)/src + +# these will probably work if Lua has been installed globally +#LUA= /usr/local +#LUAINC= $(LUA)/include +#LUALIB= $(LUA)/lib +#LUABIN= $(LUA)/bin + +# probably no need to change anything below here +CC= gcc CFLAGS= $(INCS) $(WARN) -O2 $G WARN= -ansi -pedantic -Wall INCS= -I$(LUAINC) +MAKESO= $(CC) -shared +#MAKESO= env MACOSX_DEPLOYMENT_TARGET=10.3 $(CC) -bundle -undefined dynamic_lookup MYNAME= random MYLIB= l$(MYNAME) -T= $(MYLIB).so +T= $(MYNAME).so OBJS= $(MYLIB).o TEST= test.lua all: test test: $T - $(LUABIN)/lua -l$(MYNAME) $(TEST) + $(LUABIN)/lua $(TEST) o: $(MYLIB).o so: $T $T: $(OBJS) - $(CC) -o $@ -shared $(OBJS) + $(MAKESO) -o $@ $(OBJS) $(OBJS): random.c clean: - rm -f $(OBJS) $T core core.* a.out + rm -f $(OBJS) $T core core.* doc: @echo "$(MYNAME) library:" @@ -40,20 +49,20 @@ doc: # distribution -FTP= $(HOME)/public/ftp/lua/5.0 +FTP= www:www/ftp/lua/5.1 +F= http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/5.1/$A D= $(MYNAME) A= $(MYLIB).tar.gz -TOTAR= Makefile,README,$(MYLIB).c,$(MYNAME).lua,test.lua,random.c +TOTAR= Makefile,README,$(MYLIB).c,test.lua,random.c -tar: clean +distr: clean tar zcvf $A -C .. $D/{$(TOTAR)} - -distr: tar touch -r $A .stamp - mv $A $(FTP) + scp -p $A $(FTP) diff: clean - tar zxf $(FTP)/$A + wget -q -N $F + tar zxf $A diff $D . # eof diff --git a/README b/README index c6bee98..8714259 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is a random-number library for Lua 5.0. It is based on the Mersenne +This is a random-number library for Lua 5.1. It is based on the Mersenne Twister random number generator available at http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html @@ -18,8 +18,8 @@ Please send comments, suggestions, and bug reports to lhf@tecgraf.puc-rio.br . ------------------------------------------------------------------------------- random library: - clone(c) tostring(c) valuex(c) - new([seed]) value(c) version - seed(c,[seed]) valuei(c,a,[b]) + __call(c) new([seed]) version + __tostring(c) seed(c,[seed]) + clone(c) value(c,[a,b]) ------------------------------------------------------------------------------- diff --git a/lrandom.c b/lrandom.c index 685ba8d..db10d9f 100644 --- a/lrandom.c +++ b/lrandom.c @@ -1,8 +1,8 @@ /* * lrandom.c -* random interface for Lua 5.0 +* random-number library for Lua 5.1 based on the Mersenne Twister * Luiz Henrique de Figueiredo -* 09 Jun 2006 21:09:17 +* 18 Nov 2010 19:11:40 * This code is hereby placed in the public domain. */ @@ -12,17 +12,19 @@ #include "lua.h" #include "lauxlib.h" +/* #define GENRAND32 if you want a 32-bit generator instead of a 53-bit one */ +#include "random.c" + #define MYNAME "random" -#define MYVERSION MYNAME " library for " LUA_VERSION " / Jun 2006" +#define MYVERSION MYNAME " library for " LUA_VERSION " / Nov 2010 / "\ + "using " AUTHOR #define MYTYPE MYNAME " handle" -#define SEED 2004UL -#include "random.c" +#define SEED 2010UL static MT *Pget(lua_State *L, int i) { - if (luaL_checkudata(L,i,MYTYPE)==NULL) luaL_typerror(L,i,MYTYPE); - return lua_touserdata(L,i); + return luaL_checkudata(L,i,MYTYPE); } static MT *Pnew(lua_State *L) @@ -35,8 +37,9 @@ static MT *Pnew(lua_State *L) static int Lnew(lua_State *L) /** new([seed]) */ { + lua_Number seed=luaL_optnumber(L,1,SEED); MT *c=Pnew(L); - init_genrand(c,luaL_optlong(L,1,SEED)); + init_genrand(c,seed); return 1; } @@ -51,75 +54,69 @@ static int Lclone(lua_State *L) /** clone(c) */ static int Lseed(lua_State *L) /** seed(c,[seed]) */ { MT *c=Pget(L,1); - init_genrand(c,luaL_optlong(L,2,SEED)); - return 0; -} - -static int Lvalue(lua_State *L) /** value(c) */ -{ - MT *c=Pget(L,1); - lua_pushnumber(L,genrand_real1(c)); + init_genrand(c,luaL_optnumber(L,2,SEED)); + lua_settop(L,1); return 1; } -static int Lvaluei(lua_State *L) /** valuei(c,a,[b]) */ +static int Lvalue(lua_State *L) /** value(c,[a,b]) */ { MT *c=Pget(L,1); - int a,b; - if (lua_gettop(L)==2) + double a,b,r=genrand(c); + switch (lua_gettop(L)) { - a=1; - b=luaL_checkint(L,2); + case 1: + lua_pushnumber(L,r); + return 1; + case 2: + a=1; + b=luaL_checknumber(L,2); + break; + default: + a=luaL_checknumber(L,2); + b=luaL_checknumber(L,3); + break; } - else - { - a=luaL_checkint(L,2); - b=luaL_checkint(L,3); - } - lua_pushnumber(L,floor(a+genrand_real2(c)*(b-a+1))); + if (a>b) { double t=a; a=b; b=t; } + a=ceil(a); + b=floor(b); + if (a>b) return 0; + r=a+floor(r*(b-a+1)); + lua_pushnumber(L,r); return 1; } -static int Lvaluex(lua_State *L) /** valuex(c) */ +static int Ltostring(lua_State *L) { MT *c=Pget(L,1); - lua_pushnumber(L,genrand_res53(c)); + lua_pushfstring(L,"%s %p",MYTYPE,(void*)c); return 1; } -static int Ltostring(lua_State *L) /** tostring(c) */ +static const luaL_Reg R[] = { - MT *c=Pget(L,1); - char s[64]; - sprintf(s,"%s %p",MYTYPE,(void*)c); - lua_pushstring(L,s); - return 1; -} - -static const luaL_reg R[] = -{ - { "__tostring", Ltostring }, + { "__tostring", Ltostring }, /** __tostring(c) */ { "clone", Lclone }, { "new", Lnew }, { "seed", Lseed }, - { "tostring", Ltostring }, { "value", Lvalue }, - { "valuei", Lvaluei }, - { "valuex", Lvaluex }, { NULL, NULL } }; LUALIB_API int luaopen_random(lua_State *L) { - lua_pushliteral(L,MYNAME); luaL_newmetatable(L,MYTYPE); - luaL_openlib(L,NULL,R,0); + lua_setglobal(L,MYNAME); + luaL_register(L,MYNAME,R); lua_pushliteral(L,"version"); /** version */ lua_pushliteral(L,MYVERSION); lua_settable(L,-3); lua_pushliteral(L,"__index"); lua_pushvalue(L,-2); lua_settable(L,-3); - lua_rawset(L,LUA_GLOBALSINDEX); + lua_pushliteral(L,"__call"); /** __call(c) */ + lua_pushliteral(L,"value"); + lua_gettable(L,-3); + lua_settable(L,-3); return 1; } diff --git a/random.c b/random.c index 3c76139..16686de 100644 --- a/random.c +++ b/random.c @@ -2,7 +2,7 @@ * random.c * Mersenne Twister random number generator * Luiz Henrique de Figueiredo -* 26 Jun 2004 10:14:59 +* 18 Nov 2010 19:10:52 * slightly modified from mt19937ar.c available at * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html */ @@ -119,24 +119,24 @@ static unsigned long genrand_int32(MT *o) return y; } -/* generates a random number on [0,1]-real-interval */ -static double genrand_real1(MT *o) -{ - return genrand_int32(o)*(1.0/4294967295.0); - /* divided by 2^32-1 */ -} +/* These real versions are due to Isaku Wada, 2002/01/09 added */ +#ifdef GENRAND32 /* generates a random number on [0,1)-real-interval */ static double genrand_real2(MT *o) { return genrand_int32(o)*(1.0/4294967296.0); /* divided by 2^32 */ } - +#define genrand genrand_real2 +#else /* generates a random number on [0,1) with 53-bit resolution*/ static double genrand_res53(MT *o) { unsigned long a=genrand_int32(o)>>5, b=genrand_int32(o)>>6; return(a*67108864.0+b)*(1.0/9007199254740992.0); } -/* These real versions are due to Isaku Wada, 2002/01/09 added */ +#define genrand genrand_res53 +#endif + +#define AUTHOR "Mersenne Twister" diff --git a/random.lua b/random.lua deleted file mode 100644 index b3ccc3e..0000000 --- a/random.lua +++ /dev/null @@ -1,10 +0,0 @@ --- random.lua --- support code for random library --- usage lua -lrandom ... - -local function so(x) - local SOPATH= os.getenv"LUA_SOPATH" or "./" - assert(loadlib(SOPATH.."l"..x..".so","luaopen_"..x))() -end - -so"random" diff --git a/test.lua b/test.lua index 874aae2..30137a5 100644 --- a/test.lua +++ b/test.lua @@ -1,42 +1,74 @@ -- test random library +require"random" + print(random.version) print"" -r=random.new(1234) +function test(w,r) + print(w,r(),r(),r()) +end -print("new",r:value(),r:value(),r:value()) -s=r:clone() -print("more",r:value(),r:value(),r:value()) -r:seed(5678) -print("seed",r:value(),r:value(),r:value()) -r:seed(1234) -print("seed",r:value(),r:value(),r:value()) -print("more",r:value(),r:value(),r:value()) -print("clone",s:value(),s:value(),s:value()) +r=random.new(12345) +test("new",r) +test("more",r) +test("reset",r:seed(12345)) +test("seed",r:seed(56789)) +test("seed",r:seed(3063121584)) +test("seed",r:seed(2428144928)) +s=r:seed():clone() +test("seed",r) +test("more",r) +test("clone",s) r:seed(os.time()) N=100000 +print"" +print("range","","distribution",N) +print("","",1,2,3,4,5,6,7,8) -S={0,0,0,0,0,0,0,0,0,0,0} -for i=1,N do - local i=r:valuei(8) - S[i]=S[i]+1 +function test(N,a,b) + local S={0,0,0,0,0,0,0,0,0,0,0} + for i=1,N do + local i=r:value(a,b) + if i~=nil then S[i]=S[i]+1 end + end + for i=1,9 do + S[i]=math.floor(100*S[i]/N+0.5) + end + print(a..":"..b,"",S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[8]) end -for i=1,9 do - S[i]=math.floor(100*S[i]/N+0.5) -end -print("1..8",S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[8]) -S={0,0,0,0,0,0,0,0,0,0,0} -for i=1,N do - local i=r:valuei(2,4) - S[i]=S[i]+1 -end -for i=1,9 do - S[i]=math.floor(100*S[i]/N+0.5) +test(N,1,8) +test(N,2,4) +test(N,3,7) +test(N,7,3) +test(N,1.2,4.6) +test(N,4.6,1.2) +test(N,7.1,2.9) +test(N,2.9,7.1) +test(N,2.1,2.2) +test(N,2.2,2.1) + +function test(w,f) + local t=os.clock() + for i=1,N do + f() + end + t=os.clock()-t + print(w,math.floor(N/t/1000),N,t) end -print("2..4",S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[8]) + +N=4*N +print"" +print("","1000/s","N","time") +test("math",function () return math.random() end) +test("math",math.random) +test("random",function () return random.value(r) end) +test("random",function () return r:value() end) +test("random",r) print"" print(random.version) + +-- eof