libc/rand_r: support rand_r api

refs to https://pubs.opengroup.org/onlinepubs/7908799/xsh/rand.html

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2023-06-28 12:29:03 +08:00 committed by Xiang Xiao
parent 97a2528de9
commit 5d09b4cbd0
2 changed files with 73 additions and 42 deletions

View File

@ -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);

View File

@ -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;
}