diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-11 11:34:47 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-11 11:34:47 -0200 |
commit | 51316f9df7aacb54633a3e9b910a070590ac6259 (patch) | |
tree | 954c50a7b11ace095e8a2ca70e31832230e902cb /lmathlib.c | |
parent | 46beca5bed8a7700b18100fe48a78373be5055f9 (diff) | |
download | lua-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.c | 58 |
1 files changed, 38 insertions, 20 deletions
@@ -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 | ||
332 | static lua_Number I2d (Rand64 x) { | 336 | static 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 | */ | ||
466 | static 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 | ||
475 | static lua_Number I2d (Rand64 x) { | 491 | static 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' */ |
483 | static lua_Unsigned I2UInt (Rand64 x) { | 501 | static lua_Unsigned I2UInt (Rand64 x) { |