From d3feec43652e759fc5186fab93bdded2f939f1b5 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 25 Feb 2019 12:15:56 +0100 Subject: [PATCH] Issue #85: Use explicit seed in Math.random(). --- jsi.h | 2 ++ jsmath.c | 42 +++++++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/jsi.h b/jsi.h index 20e0df6..ea70daa 100644 --- a/jsi.h +++ b/jsi.h @@ -203,6 +203,8 @@ struct js_State js_Object *TypeError_prototype; js_Object *URIError_prototype; + unsigned int seed; /* Math.random seed */ + int nextref; /* for js_ref use */ js_Object *R; /* registry of hidden values */ js_Object *G; /* the global object */ diff --git a/jsmath.c b/jsmath.c index e904e08..cbc6612 100644 --- a/jsmath.c +++ b/jsmath.c @@ -4,6 +4,32 @@ #include +#define JS_RAND_MAX (0x7fffffff) + +static unsigned int jsM_rand_temper(unsigned int x) +{ + x ^= x>>11; + x ^= x<<7 & 0x9D2C5680; + x ^= x<<15 & 0xEFC60000; + x ^= x>>18; + return x; +} + +static int jsM_rand_r(unsigned int *seed) +{ + return jsM_rand_temper(*seed = *seed * 1103515245 + 12345)/2; +} + +static double jsM_round(double x) +{ + if (isnan(x)) return x; + if (isinf(x)) return x; + if (x == 0) return x; + if (x > 0 && x < 0.5) return 0; + if (x < 0 && x >= -0.5) return -0; + return floor(x + 0.5); +} + static void Math_abs(js_State *J) { js_pushnumber(J, fabs(js_tonumber(J, 1))); @@ -68,23 +94,13 @@ static void Math_pow(js_State *J) static void Math_random(js_State *J) { - js_pushnumber(J, rand() / (RAND_MAX + 1.0)); -} - -static double do_round(double x) -{ - if (isnan(x)) return x; - if (isinf(x)) return x; - if (x == 0) return x; - if (x > 0 && x < 0.5) return 0; - if (x < 0 && x >= -0.5) return -0; - return floor(x + 0.5); + js_pushnumber(J, jsM_rand_r(&J->seed) / (JS_RAND_MAX + 1.0)); } static void Math_round(js_State *J) { double x = js_tonumber(J, 1); - js_pushnumber(J, do_round(x)); + js_pushnumber(J, jsM_round(x)); } static void Math_sin(js_State *J) @@ -140,7 +156,7 @@ static void Math_min(js_State *J) void jsB_initmath(js_State *J) { - srand(time(NULL)); + J->seed = time(NULL); js_pushobject(J, jsV_newobject(J, JS_CMATH, J->Object_prototype)); {