aboutsummaryrefslogtreecommitdiff
path: root/lmathlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-11 11:34:47 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-11 11:34:47 -0200
commit51316f9df7aacb54633a3e9b910a070590ac6259 (patch)
tree954c50a7b11ace095e8a2ca70e31832230e902cb /lmathlib.c
parent46beca5bed8a7700b18100fe48a78373be5055f9 (diff)
downloadlua-51316f9df7aacb54633a3e9b910a070590ac6259.tar.gz
lua-51316f9df7aacb54633a3e9b910a070590ac6259.tar.bz2
lua-51316f9df7aacb54633a3e9b910a070590ac6259.zip
'math.rand()' uses higher bits to produce float value
The call 'math.rand()' converts the higher bits of the internal unsigned integer random to a float, instead of its lower bits. That ensures that Lua compiled with different float precisions always generates equal (up to the available precision) random numbers when given the same seed.
Diffstat (limited to 'lmathlib.c')
-rw-r--r--lmathlib.c58
1 files changed, 38 insertions, 20 deletions
diff --git a/lmathlib.c b/lmathlib.c
index e8e88e7a..f2bfff9b 100644
--- a/lmathlib.c
+++ b/lmathlib.c
@@ -323,14 +323,18 @@ static Rand64 nextrand (Rand64 *state) {
323 323
324/* 324/*
325** Convert bits from a random integer into a float in the 325** Convert bits from a random integer into a float in the
326** interval [0,1). 326** interval [0,1), getting the higher FIG bits from the
327** random unsigned integer and converting that to a float.
327*/ 328*/
328#define maskFIG (~(~(Rand64)1 << (FIGS - 1))) /* use FIGS bits */ 329
329#define shiftFIG \ 330/* must throw out the extra (64 - FIGS) bits */
330 (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1))) /* 2^(-FIGS) */ 331#define shift64_FIG (64 - FIGS)
332
333/* to scale to [0, 1), multiply by scaleFIG = 2^(-FIGS) */
334#define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))
331 335
332static lua_Number I2d (Rand64 x) { 336static lua_Number I2d (Rand64 x) {
333 return (lua_Number)(x & maskFIG) * shiftFIG; 337 return (lua_Number)(trim64(x) >> shift64_FIG) * scaleFIG;
334} 338}
335 339
336/* convert a 'Rand64' to a 'lua_Unsigned' */ 340/* convert a 'Rand64' to a 'lua_Unsigned' */
@@ -449,35 +453,49 @@ static Rand64 nextrand (Rand64 *state) {
449/* an unsigned 1 with proper type */ 453/* an unsigned 1 with proper type */
450#define UONE ((lu_int32)1) 454#define UONE ((lu_int32)1)
451 455
456
452#if FIGS <= 32 457#if FIGS <= 32
453 458
454#define maskHI 0 /* do not need bits from higher half */ 459/* 2^(-FIGS) */
455#define maskLOW (~(~UONE << (FIGS - 1))) /* use FIGS bits */ 460#define scaleFIG (l_mathop(0.5) / (UONE << (FIGS - 1)))
456#define shiftFIG (l_mathop(0.5) / (UONE << (FIGS - 1))) /* 2^(-FIGS) */ 461
462/*
463** get up to 32 bits from higher half, shifting right to
464** throw out the extra bits.
465*/
466static lua_Number I2d (Rand64 x) {
467 lua_Number h = (lua_Number)(trim32(x.h) >> (32 - FIGS));
468 return h * scaleFIG;
469}
457 470
458#else /* 32 < FIGS <= 64 */ 471#else /* 32 < FIGS <= 64 */
459 472
460/* must take care to not shift stuff by more than 31 slots */ 473/* must take care to not shift stuff by more than 31 slots */
461 474
462/* use FIGS - 32 bits from higher half */ 475/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */
463#define maskHI (~(~UONE << (FIGS - 33))) 476#define scaleFIG \
477 ((lua_Number)1.0 / (UONE << 30) / 8.0 / (UONE << (FIGS - 33)))
464 478
465/* use 32 bits from lower half */ 479/*
466#define maskLOW (~(~UONE << 31)) 480** use FIGS - 32 bits from lower half, throwing out the other
467 481** (32 - (FIGS - 32)) = (64 - FIGS) bits
468/* 2^(-FIGS) == (1 / 2^33) / 2^(FIGS-33) */ 482*/
469#define shiftFIG ((lua_Number)(1.0 / 8589934592.0) / (UONE << (FIGS - 33))) 483#define shiftLOW (64 - FIGS)
470 484
471#endif 485/*
486** higher 32 bits go after those (FIGS - 32) bits: shiftHI = 2^(FIGS - 32)
487*/
488#define shiftHI ((lua_Number)(UONE << (FIGS - 33)) * 2.0)
472 489
473#define twoto32 l_mathop(4294967296.0) /* 2^32 */
474 490
475static lua_Number I2d (Rand64 x) { 491static lua_Number I2d (Rand64 x) {
476 lua_Number h = (lua_Number)(x.h & maskHI); 492 lua_Number h = (lua_Number)trim32(x.h) * shiftHI;
477 lua_Number l = (lua_Number)(x.l & maskLOW); 493 lua_Number l = (lua_Number)(trim32(x.l) >> shiftLOW);
478 return (h * twoto32 + l) * shiftFIG; 494 return (h + l) * scaleFIG;
479} 495}
480 496
497#endif
498
481 499
482/* convert a 'Rand64' to a 'lua_Unsigned' */ 500/* convert a 'Rand64' to a 'lua_Unsigned' */
483static lua_Unsigned I2UInt (Rand64 x) { 501static lua_Unsigned I2UInt (Rand64 x) {