Skip to content

Commit d64a46e

Browse files
Move random number generator from Math.random to jerry-libc, replace the logic with call to rand in Math.random.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent 98789f3 commit d64a46e

File tree

3 files changed

+69
-19
lines changed

3 files changed

+69
-19
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
#include "ecma-objects.h"
2626
#include "ecma-objects-general.h"
2727
#include "ecma-try-catch-macro.h"
28-
#include "jrt.h"
2928
#include "fdlibm-math.h"
29+
#include "jrt.h"
30+
#include "jrt-libc-includes.h"
3031

3132
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_MATH_BUILTIN
3233

@@ -528,26 +529,24 @@ ecma_builtin_math_object_pow (ecma_value_t this_arg __attr_unused___, /**< 'this
528529
static ecma_completion_value_t
529530
ecma_builtin_math_object_random (ecma_value_t this_arg __attr_unused___) /**< 'this' argument */
530531
{
531-
/* Implementation of George Marsaglia's XorShift random number generator */
532-
TODO (/* Check for license issues */);
533-
534-
static uint32_t word1 = 1455997910;
535-
static uint32_t word2 = 1999515274;
536-
static uint32_t word3 = 1234451287;
537-
static uint32_t word4 = 1949149569;
538-
539-
uint32_t intermediate = word1 ^ (word1 << 11);
540-
intermediate ^= intermediate >> 8;
541-
542-
word1 = word2;
543-
word2 = word3;
544-
word3 = word4;
545-
546-
word4 ^= word4 >> 19;
547-
word4 ^= intermediate;
532+
uint32_t rnd = 1;
533+
uint32_t reps_count;
534+
#if RAND_MAX < 0x100
535+
reps_count = 4;
536+
#elif RAND_MAX < 0x10000
537+
reps_count = 2;
538+
#else /* RAND_MAX < 0x10000 */
539+
reps_count = 1;
540+
#endif /* RAND_MAX >= 0x10000 */
541+
542+
for (uint32_t i = 0; i < reps_count; i++)
543+
{
544+
uint32_t next_rand = (uint32_t) rand ();
545+
rnd *= next_rand;
546+
}
548547

549548
const uint32_t max_uint32 = (uint32_t) -1;
550-
ecma_number_t rand = (ecma_number_t) word4;
549+
ecma_number_t rand = (ecma_number_t) rnd;
551550
rand /= (ecma_number_t) max_uint32;
552551
rand *= (ecma_number_t) (max_uint32 - 1) / (ecma_number_t) max_uint32;
553552

jerry-libc/include/stdlib.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,15 @@
2525
extern EXTERN_C void __attribute__ ((noreturn)) exit (int);
2626
extern EXTERN_C void __attribute__ ((noreturn)) abort (void);
2727

28+
/**
29+
* Maximum integer that could be returned by random number generator
30+
*
31+
* See also:
32+
* rand
33+
*/
34+
#define RAND_MAX (0x7fffffffu)
35+
36+
extern EXTERN_C int rand (void);
37+
extern EXTERN_C void srand (unsigned int);
38+
2839
#endif /* !JERRY_LIBC_STDLIB_H */

jerry-libc/jerry-libc.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424

2525
#include "jerry-libc-defs.h"
2626

27+
/**
28+
* State of pseudo-random number generator
29+
*/
30+
static unsigned int libc_random_gen_state[4] = { 1455997910, 1999515274, 1234451287, 1949149569 };
31+
2732
/**
2833
* Standard file descriptors
2934
*/
@@ -326,3 +331,38 @@ isxdigit (int c)
326331
{
327332
return isdigit (c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
328333
}
334+
335+
/**
336+
* Generate pseudo-random integer
337+
*
338+
* Note:
339+
* The function implements George Marsaglia's XorShift random number generator
340+
*
341+
* @return integer in range [0; RAND_MAX]
342+
*/
343+
int
344+
rand (void)
345+
{
346+
uint32_t intermediate = libc_random_gen_state[0] ^ (libc_random_gen_state[0] << 11);
347+
intermediate ^= intermediate >> 8;
348+
349+
libc_random_gen_state[0] = libc_random_gen_state[1];
350+
libc_random_gen_state[1] = libc_random_gen_state[2];
351+
libc_random_gen_state[2] = libc_random_gen_state[3];
352+
353+
libc_random_gen_state[3] ^= libc_random_gen_state[3] >> 19;
354+
libc_random_gen_state[3] ^= intermediate;
355+
356+
uint32_t ret = libc_random_gen_state[3] % (RAND_MAX + 1u);
357+
358+
return (int32_t) ret;
359+
} /* rand */
360+
361+
/**
362+
* Initialize pseudo-random number generator with the specified seed value
363+
*/
364+
void
365+
srand (unsigned int seed) /**< new seed */
366+
{
367+
libc_random_gen_state[3] = seed;
368+
} /* srand */

0 commit comments

Comments
 (0)