Skip to content

Commit 6ba36e4

Browse files
committed
Improve Math.random randomness.
Largest possible MLCG that only uses integer arithmetic with doubles. Parameters from Pierre l'Ecuyers paper "Tables of linear congruential generators of different sizes and good lattice structure".
1 parent 1cbf19e commit 6ba36e4

File tree

2 files changed

+12
-17
lines changed

2 files changed

+12
-17
lines changed

jsi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ struct js_State
239239
js_Object *TypeError_prototype;
240240
js_Object *URIError_prototype;
241241

242-
unsigned int seed; /* Math.random seed */
242+
double seed; /* Math.random seed */
243243

244244
int nextref; /* for js_ref use */
245245
js_Object *R; /* registry of hidden values */

jsmath.c

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@
22
#include "jsvalue.h"
33
#include "jsbuiltin.h"
44

5-
#if defined(_MSC_VER) && (_MSC_VER < 1700) /* VS2012 has stdint.h */
6-
typedef unsigned int uint32_t;
7-
typedef unsigned __int64 uint64_t;
8-
#else
9-
#include <stdint.h>
10-
#endif
11-
125
#include <time.h>
136

147
static double jsM_round(double x)
@@ -85,21 +78,23 @@ static void Math_pow(js_State *J)
8578

8679
static void Math_random(js_State *J)
8780
{
88-
/* Lehmer generator with a=48271 and m=2^31-1 */
89-
/* Park & Miller (1988). Random Number Generators: Good ones are hard to find. */
90-
J->seed = (uint64_t) J->seed * 48271 % 0x7fffffff;
91-
js_pushnumber(J, (double) J->seed / 0x7fffffff);
81+
// A Lehmer (MLCG) RNG using doubles.
82+
// Parameters from Pierre l'Ecuyer's paper:
83+
// https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
84+
// m = 2^35 - 31
85+
J->seed = J->seed * fmod(200105.0, 34359738337.0);
86+
js_pushnumber(J, J->seed / 34359738337.0);
9287
}
9388

9489
static void Math_init_random(js_State *J)
9590
{
9691
/* Pick initial seed by scrambling current time with Xorshift. */
9792
/* Marsaglia (2003). Xorshift RNGs. */
98-
J->seed = time(0) + 123;
99-
J->seed ^= J->seed << 13;
100-
J->seed ^= J->seed >> 17;
101-
J->seed ^= J->seed << 5;
102-
J->seed %= 0x7fffffff;
93+
unsigned int seed = time(0) + 123;
94+
seed ^= seed << 13;
95+
seed ^= seed >> 17;
96+
seed ^= seed << 5;
97+
J->seed = seed;
10398
}
10499

105100
static void Math_round(js_State *J)

0 commit comments

Comments
 (0)