1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

sys/random: fix distribution of random_uint32_range()

This commit is contained in:
PeterKietzmann 2018-06-25 09:05:54 +02:00
parent 42c4460daf
commit ec5fb4fbda
2 changed files with 28 additions and 4 deletions

View File

@ -92,10 +92,7 @@ void random_bytes(uint8_t *buf, size_t size);
*
* @return a random number on [a,b)-interval
*/
static inline uint32_t random_uint32_range(uint32_t a, uint32_t b)
{
return (random_uint32() % (b - a)) + a;
}
uint32_t random_uint32_range(uint32_t a, uint32_t b);
#if PRNG_FLOAT
/* These real versions are due to Isaku Wada, 2002/01/09 added */

View File

@ -54,3 +54,30 @@ void random_bytes(uint8_t *target, size_t n)
*target++ = *random_pos++;
}
}
uint32_t random_uint32_range(uint32_t a, uint32_t b)
{
assert(a < b);
uint32_t divisor, rand_val, range = b - a;
uint8_t range_msb = bitarithm_msb(range);
/* check if range is a power of two */
if (!(range & (range - 1))) {
divisor = (1 << range_msb) - 1;
}
else if (range_msb < 31) {
/* leftshift for next power of two interval */
divisor = (1 << (range_msb + 1)) -1;
}
else {
/* disable modulo operation in loop below */
divisor = UINT32_MAX;
}
/* get random numbers until value is smaller than range */
do {
rand_val = (random_uint32() & divisor);
} while (rand_val >= range);
/* return random in range [a,b] */
return (rand_val + a);
}