diff --git a/include/stdlib.h b/include/stdlib.h index f186dc5245..b29e59a5bd 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -132,6 +132,7 @@ extern "C" void srand(unsigned int seed); int rand(void); +int rand_r(FAR unsigned int *seedp); void lcong48(FAR unsigned short int param[7]); FAR unsigned short int *seed48(FAR unsigned short int seed16v[3]); void srand48(long int seedval); diff --git a/libs/libc/stdlib/lib_srand.c b/libs/libc/stdlib/lib_srand.c index 80df76fe5e..4e0d157d8b 100644 --- a/libs/libc/stdlib/lib_srand.c +++ b/libs/libc/stdlib/lib_srand.c @@ -67,9 +67,9 @@ typedef double float_t; /* First order congruential generators */ -static inline unsigned long fgenerate1(void); +static inline unsigned long fgenerate1(FAR unsigned long *seed); #if (CONFIG_LIBC_RAND_ORDER == 1) -static float_t frand1(void); +static float_t frand1(FAR unsigned long *seed); #endif /* Second order congruential generators */ @@ -106,7 +106,7 @@ static unsigned long g_randint3; /* First order congruential generators */ -static inline unsigned long fgenerate1(void) +static inline unsigned long fgenerate1(FAR unsigned long *seed) { unsigned long randint; @@ -115,17 +115,17 @@ static inline unsigned long fgenerate1(void) * the first order random number generator. */ - randint = (RND1_CONSTK * g_randint1) % RND1_CONSTP; - g_randint1 = (randint == 0 ? 1 : randint); + randint = (RND1_CONSTK * (*seed)) % RND1_CONSTP; + *seed = (randint == 0 ? 1 : randint); return randint; } #if (CONFIG_LIBC_RAND_ORDER == 1) -static float_t frand1(void) +static float_t frand1(FAR unsigned long *seed) { /* First order congruential generator. */ - unsigned long randint = fgenerate1(); + unsigned long randint = fgenerate1(seed); /* Construct an floating point value in the range from 0.0 up to 1.0 */ @@ -215,40 +215,8 @@ static float_t frand3(void) #endif #endif -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: srand - * - * Description: - * Seed the congruential random number generator. - * - ****************************************************************************/ - -void srand(unsigned int seed) -{ - g_randint1 = seed; -#if (CONFIG_LIBC_RAND_ORDER > 1) - g_randint2 = seed; - fgenerate1(); -#if (CONFIG_LIBC_RAND_ORDER > 2) - g_randint3 = seed; - fgenerate2(); -#endif -#endif -} - -/**************************************************************************** - * Name: nrand - * - * Description: - * Return a random, unsigned long value in the range of 0 to (limit - 1) - * - ****************************************************************************/ - -unsigned long nrand(unsigned long limit) +static unsigned long nrand_r(unsigned long limit, + FAR unsigned long *seed) { unsigned long result; float_t ratio; @@ -260,7 +228,7 @@ unsigned long nrand(unsigned long limit) /* Get a random integer in the range 0.0 - 1.0 */ #if (CONFIG_LIBC_RAND_ORDER == 1) - ratio = frand1(); + ratio = frand1(seed); #elif (CONFIG_LIBC_RAND_ORDER == 2) ratio = frand2(); #else /* if (CONFIG_LIBC_RAND_ORDER > 2) */ @@ -279,3 +247,65 @@ unsigned long nrand(unsigned long limit) return result; } + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: srand + * + * Description: + * Seed the congruential random number generator. + * + ****************************************************************************/ + +void srand(unsigned int seed) +{ + g_randint1 = seed; +#if (CONFIG_LIBC_RAND_ORDER > 1) + g_randint2 = seed; + fgenerate1(&g_randint1); +#if (CONFIG_LIBC_RAND_ORDER > 2) + g_randint3 = seed; + fgenerate2(); +#endif +#endif +} + +/**************************************************************************** + * Name: nrand + * + * Description: + * Return a random, unsigned long value in the range of 0 to (limit - 1) + * + ****************************************************************************/ + +unsigned long nrand(unsigned long limit) +{ + return nrand_r(limit, &g_randint1); +} + +/**************************************************************************** + * Name: rand_r + * + * Description: + * The function rand() is not reentrant, since it uses hidden state that + * is modified on each call. This might just be the seed value to be used + * by the next call, or it might be something more elaborate. In order to + * get reproducible behavior in a threaded application, this state must be + * made explicit; this can be done using the reentrant function rand_r(). + * + * Return a random, int value in the range of 0 to INT_MAX. + * + ****************************************************************************/ + +int rand_r(FAR unsigned int *seedp) +{ + unsigned long seed = *seedp; + unsigned long rand; + + rand = nrand_r(INT_MAX, &seed); + *seedp = (unsigned int)seed; + return (int)rand; +}