shithub: libmujs

Download patch

ref: d3feec43652e759fc5186fab93bdded2f939f1b5
parent: 43c844510b4fa4a83d53068bf4dc5c17773815d4
author: Tor Andersson <tor.andersson@artifex.com>
date: Mon Feb 25 07:15:56 EST 2019

Issue #85: Use explicit seed in Math.random().

--- a/jsi.h
+++ b/jsi.h
@@ -203,6 +203,8 @@
 	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 */
--- a/jsmath.c
+++ b/jsmath.c
@@ -4,6 +4,32 @@
 
 #include <time.h>
 
+#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_random(js_State *J)
 {
-	js_pushnumber(J, rand() / (RAND_MAX + 1.0));
+	js_pushnumber(J, jsM_rand_r(&J->seed) / (JS_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);
-}
-
 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 @@
 
 void jsB_initmath(js_State *J)
 {
-	srand(time(NULL));
+	J->seed = time(NULL);
 
 	js_pushobject(J, jsV_newobject(J, JS_CMATH, J->Object_prototype));
 	{