From 8808864e56f29b83c42ae2de192f766ee5333606 Mon Sep 17 00:00:00 2001 From: Allanis <allanis@saracraft.net> Date: Thu, 28 Mar 2013 13:25:53 +0000 Subject: [PATCH] [Add] Now we can use mersenne twister instead of rand(), you are welcome. :) --- bin/Makefile | 6 ++- src/rng.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/rng.h | 8 ++-- 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/bin/Makefile b/bin/Makefile index 7787544..ee05d6f 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -1,6 +1,8 @@ # OPTIONS. DEBUG = 1 -APPNAME = Lephisto + +OS := LINUX +#OS := WIN32 # VERSION. VMAJOR = 0 @@ -22,7 +24,7 @@ CTTF = $(shell freetype-config --cflags) CAL = -lopenal CVORBIS = CGL = -CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(CAL) $(CVORBIS) $(VERSION) +CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(CAL) $(CVORBIS) $(VERSION) -D$(OS) ifdef DEBUG CFLAGS += -W -Wall -g3 -DDEBUG -DLUA_USE_APICHECK -std=c99 else diff --git a/src/rng.c b/src/rng.c index 528ab0a..daf6b65 100644 --- a/src/rng.c +++ b/src/rng.c @@ -1,8 +1,112 @@ +#include <stdint.h> +#include <math.h> #include <unistd.h> +#include <time.h> +#ifdef LINUX +#include <sys/time.h> +#include <fcntl.h> +#endif #include <SDL.h> + #include "rng.h" +#include "log.h" + +// Mersenne twister state. +static uint32_t MT[624]; +static uint32_t mt_y; +static int mt_pos = 0; // Current number. + +static uint32_t rng_timeEntropy(void); +// Mersenne twister. +static void mt_initArray(uint32_t seed); +static void mt_genArray(void); +static uint32_t mt_getInt(void); void rng_init(void) { - srand(getpid() + SDL_GetTicks()); + uint32_t i; + +#ifdef LINUX + int fd; char buf[4]; + fd = open("/dev/random", O_RDONLY); + if(fd != -1) { + if(read(fd, buf, 4) < 4) + memcpy(&i, buf, 4); + else + i = rng_timeEntropy(); + close(fd); + } else + i = rng_timeEntropy(); +#else + i = rng_timeEntropy(); +#endif + mt_initArray(i); + for(i = 0; i < 10; i++) + // Generate numbers to get away from poor initial values. + mt_genArray(); +} + +// Use the time as source of entropy. +static uint32_t rng_timeEntropy(void) { + int i; + +#ifdef WIN32 + struct _timeb tb; + _ftime(&tb); + i = tb.time * 1000 + tb.millitm; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + i = tv.tv_sec * 1000000 + tv.tv_usec; +#endif + return i; +} + +// Generates the initial mersenne twister based on seed. +static void mt_initArray(uint32_t seed) { + int i; + MT[0] = seed; + for(i = 1; i < 624; i++) + MT[i] = 1812433253 * (MT[i-1] ^ (((MT[i-1])) + i) >> 30); + mt_pos = 0; +} + +// Generate an array of numbers. +static void mt_genArray(void) { + int i; + for(i = 0; i < 624; i++) { + mt_y = (MT[i] & 0x80000000) + ((MT[i] % 624) & 0x7FFFFFFF); + if(mt_y % 2) + // Odd. + MT[i] = (MT[(i+397) % 624] ^ (mt_y >> 1)) ^ 2567483615; + else + // Even. + MT[i] = MT[(i+397) % 624] ^ (mt_y >> 1); + } + mt_pos = 0; +} + +// Get the next int. +static uint32_t mt_getInt(void) { + if(mt_pos >= 624) mt_genArray(); + + mt_y = MT[mt_pos++]; + mt_y ^= mt_y >> 11; + mt_y ^= (mt_y << 7) & 2636928640; + mt_y ^= (mt_y << 15) & 4022730752; + mt_y ^= (mt_y >> 18); + + return mt_y; +} + +// Return a random int. +unsigned int randint(void) { + return mt_getInt(); +} + +// Return a random double. +static double m_div = (double)(0xFFFFFFFF) + 1.; +double randfp(void) { + double m = (double)mt_getInt(); + return m / m_div; } diff --git a/src/rng.h b/src/rng.h index 1d2b053..e017a75 100644 --- a/src/rng.h +++ b/src/rng.h @@ -1,8 +1,10 @@ #pragma once -#include <stdlib.h> +#include <limits.h> -#define RNG(L,H) ((int)L + (int)((double)(H-L+1) * (rand()/(RAND_MAX+1.)))) -#define RNGF() (rand()/(RAND_MAX+1.)) +#define RNG(L,H) ((int)L + (int)((double)(H-L+1) * (randfp())) +#define RNGF() (randfp()) void rng_init(void); +unsigned int randint(void); +double randfp(void);