diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp index 7b472442a..061cc1e60 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp @@ -25,8 +25,9 @@ #include "ecma-objects.h" #include "ecma-objects-general.h" #include "ecma-try-catch-macro.h" -#include "jrt.h" #include "fdlibm-math.h" +#include "jrt.h" +#include "jrt-libc-includes.h" #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_MATH_BUILTIN @@ -528,26 +529,24 @@ ecma_builtin_math_object_pow (ecma_value_t this_arg __attr_unused___, /**< 'this static ecma_completion_value_t ecma_builtin_math_object_random (ecma_value_t this_arg __attr_unused___) /**< 'this' argument */ { - /* Implementation of George Marsaglia's XorShift random number generator */ - TODO (/* Check for license issues */); + 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 >= 0x10000 */ - static uint32_t word1 = 1455997910; - static uint32_t word2 = 1999515274; - static uint32_t word3 = 1234451287; - static uint32_t word4 = 1949149569; - - uint32_t intermediate = word1 ^ (word1 << 11); - intermediate ^= intermediate >> 8; - - word1 = word2; - word2 = word3; - word3 = word4; - - word4 ^= word4 >> 19; - word4 ^= intermediate; + for (uint32_t i = 0; i < reps_count; i++) + { + uint32_t next_rand = (uint32_t) rand (); + rnd *= next_rand; + } const uint32_t max_uint32 = (uint32_t) -1; - ecma_number_t rand = (ecma_number_t) word4; + 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; diff --git a/jerry-libc/include/stdlib.h b/jerry-libc/include/stdlib.h index c9cfe6a17..0c3f2e5ef 100644 --- a/jerry-libc/include/stdlib.h +++ b/jerry-libc/include/stdlib.h @@ -25,4 +25,15 @@ extern EXTERN_C void __attribute__ ((noreturn)) exit (int); extern EXTERN_C void __attribute__ ((noreturn)) abort (void); +/** + * Maximum integer that could be returned by random number generator + * + * See also: + * rand + */ +#define RAND_MAX (0x7fffffffu) + +extern EXTERN_C int rand (void); +extern EXTERN_C void srand (unsigned int); + #endif /* !JERRY_LIBC_STDLIB_H */ diff --git a/jerry-libc/jerry-libc.c b/jerry-libc/jerry-libc.c index 53fa2f334..16ccd3201 100644 --- a/jerry-libc/jerry-libc.c +++ b/jerry-libc/jerry-libc.c @@ -24,6 +24,11 @@ #include "jerry-libc-defs.h" +/** + * State of pseudo-random number generator + */ +static unsigned int libc_random_gen_state[4] = { 1455997910, 1999515274, 1234451287, 1949149569 }; + /** * Standard file descriptors */ @@ -326,3 +331,38 @@ isxdigit (int c) { return isdigit (c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } + +/** + * Generate pseudo-random integer + * + * Note: + * The function implements George Marsaglia's XorShift random number generator + * + * @return integer in range [0; RAND_MAX] + */ +int +rand (void) +{ + uint32_t intermediate = libc_random_gen_state[0] ^ (libc_random_gen_state[0] << 11); + intermediate ^= intermediate >> 8; + + libc_random_gen_state[0] = libc_random_gen_state[1]; + libc_random_gen_state[1] = libc_random_gen_state[2]; + libc_random_gen_state[2] = libc_random_gen_state[3]; + + libc_random_gen_state[3] ^= libc_random_gen_state[3] >> 19; + libc_random_gen_state[3] ^= intermediate; + + uint32_t ret = libc_random_gen_state[3] % (RAND_MAX + 1u); + + return (int32_t) ret; +} /* rand */ + +/** + * Initialize pseudo-random number generator with the specified seed value + */ +void +srand (unsigned int seed) /**< new seed */ +{ + libc_random_gen_state[3] = seed; +} /* srand */