Ensure that Math.random() really covers [0,1) interval (#1417)
Legacy implementation made incorrect assumptions on how many bits of useful information is returned by libc's `rand()`. If `RAND_MAX` had more than 16 useful bits, it assumed that `rand()` could return 32 useful random bits. However, e.g., jerry-libc's `RAND_MAX` is `0x7fffffff`, which denotes 31 useful bits only. The consequence was that `Math.random()` covered only the lower half of the standard-mandated `[0,1)` interval. This path fixes the error and always uses the exact value of `RAND_MAX` to compute the random value, which will thus fully cover `[0,1)`. Fixes #1414 JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu
This commit is contained in:
@@ -507,28 +507,11 @@ static ecma_value_t
|
||||
ecma_builtin_math_object_random (ecma_value_t this_arg) /**< 'this' argument */
|
||||
{
|
||||
JERRY_UNUSED (this_arg);
|
||||
uint32_t rnd = 1;
|
||||
uint32_t reps_count;
|
||||
#if RAND_MAX < 0x100
|
||||
reps_count = 4;
|
||||
#elif RAND_MAX < 0x10000
|
||||
reps_count = 2;
|
||||
#else /* RAND_MAX >= 0x10000 */
|
||||
reps_count = 1;
|
||||
#endif /* RAND_MAX < 0x100 */
|
||||
|
||||
for (uint32_t i = 0; i < reps_count; i++)
|
||||
{
|
||||
uint32_t next_rand = (uint32_t) rand ();
|
||||
rnd *= next_rand;
|
||||
}
|
||||
const ecma_number_t rand_max = (ecma_number_t) RAND_MAX;
|
||||
const ecma_number_t rand_max_min_1 = (ecma_number_t) (RAND_MAX - 1);
|
||||
|
||||
const uint32_t max_uint32 = (uint32_t) -1;
|
||||
ecma_number_t rand = (ecma_number_t) rnd;
|
||||
rand /= (ecma_number_t) max_uint32;
|
||||
rand *= (ecma_number_t) (max_uint32 - 1) / (ecma_number_t) max_uint32;
|
||||
|
||||
return ecma_make_number_value (rand);
|
||||
return ecma_make_number_value (((ecma_number_t) rand ()) / rand_max * rand_max_min_1 / rand_max);
|
||||
} /* ecma_builtin_math_object_random */
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user