diff --git a/src/hll/Math.c b/src/hll/Math.c index e6a263a..d3e07c8 100644 --- a/src/hll/Math.c +++ b/src/hll/Math.c @@ -23,9 +23,23 @@ #define M_PI (3.14159265358979323846) #endif +#include "system4/mt19937int.h" + #include "hll.h" #include "vm/page.h" +static struct mt19937 mt; +static bool mt_initialized; + +static uint32_t math_genrand(void) +{ + if (!mt_initialized) { + mt19937_init(&mt, 4357); + mt_initialized = true; + } + return mt19937_genrand(&mt); +} + struct shuffle_table { int id; struct shuffle_table *next; @@ -64,9 +78,16 @@ static float Math_Tan(float x) return tanf(deg2rad(x)); } +static void Math_SetSeed(int seed) +{ + mt19937_init(&mt, (uint32_t)seed | 1); + mt19937_genrand(&mt); // the original engine discards the first value + mt_initialized = true; +} + static void Math_SetSeedByCurrentTime(void) { - srand(time(NULL)); + Math_SetSeed(time(NULL)); } static int Math_Min(int a, int b) @@ -105,9 +126,14 @@ static void Math_SwapF(float *a, float *b) //void Math_SetRandMode(int mode); +static int Math_Rand(void) +{ + return math_genrand() & 0x7fffffff; +} + static float Math_RandF(void) { - return rand() * (1.0 / (RAND_MAX + 1U)); + return (float)(math_genrand() * (1.0 / 4294967296.0)); } static void shuffle_array(int *a, int len) @@ -192,10 +218,10 @@ HLL_LIBRARY(Math, HLL_EXPORT(Abs, abs), HLL_EXPORT(AbsF, fabsf), HLL_EXPORT(Pow, powf), - HLL_EXPORT(SetSeed, srand), + HLL_EXPORT(SetSeed, Math_SetSeed), HLL_EXPORT(SetSeedByCurrentTime, Math_SetSeedByCurrentTime), //HLL_EXPORT(SetRandMode, Math_SetRandMode), - HLL_EXPORT(Rand, rand), + HLL_EXPORT(Rand, Math_Rand), HLL_EXPORT(RandF, Math_RandF), HLL_EXPORT(RandTableInit, Math_RandTableInit), HLL_EXPORT(RandTable, Math_RandTable), diff --git a/test/Run/test.ain b/test/Run/test.ain index 77fd2ee..af7afe5 100644 Binary files a/test/Run/test.ain and b/test/Run/test.ain differ diff --git a/test/Source/math.jaf b/test/Source/math.jaf index 7db4057..ec903db 100755 --- a/test/Source/math.jaf +++ b/test/Source/math.jaf @@ -31,6 +31,25 @@ void test_math(void) test_float("Math.SwapF(a, b), a", fa, 2.0); test_float("Math.SwapF(a, b), b", fb, 1.0); + // The default seed is 4357. This must run before any other random + // number is drawn. + test_equal("Math.Rand() #1 (default seed)", Math.Rand(), 1362922229); + test_equal("Math.Rand() #2 (default seed)", Math.Rand(), 2143450242); + + Math.SetSeed(12345); + test_equal("Math.Rand() #1 (seed 12345)", Math.Rand(), 2120104832); + test_equal("Math.Rand() #2 (seed 12345)", Math.Rand(), 377474682); + + // SetSeed ORs the seed with 1. + Math.SetSeed(12344); + test_equal("Math.Rand() #1 (seed 12344)", Math.Rand(), 2120104832); + test_equal("Math.Rand() #2 (seed 12344)", Math.Rand(), 377474682); + + Math.SetSeed(12345); + test_float("Math.RandF() #1", Math.RandF(), 0.993625); + test_float("Math.RandF() #2", Math.RandF(), 0.587888); + test_float("Math.RandF() #3", Math.RandF(), 0.857469); + Math.RandTableInit(42, 10); for (i = 0; i < 10; i++) { ar[Math.RandTable(42)] = 1;