mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Don't use floor() in _bitset_with_random_bits
Use _even_rand() function instead of floor() in _bitset_with_random_bits(). floor() function is missing in dietlibc (on architectures other than x86). Moreover using floor() to clip rand results does not assure even result distribution. _even_rand() uses integer arithmetic only and is designed to return evenly distributed results. > Looks OK to me. It took a while to decipher what is the exact meaning of > the loop in _even_rand (to a non-pseudorandomness-expert) but I am > fairly comfortable with it now. If I understand this correctly, it > rejects numbers that come from an "incomplete" slice of the RAND_MAX > space (considering the number space [0, RAND_MAX] is divided into some > "max"-sized slices and at most a single smaller slice, between [n*max, > RAND_MAX] for suitable n -- numbers from this last slice are discarded > because they could distort the distribution in favour of smaller > numbers). Signed-off-by: Przemyslaw Iskra <sparky <at> pld-linux.org> Reviewed-by: Petr Rockai <prockai <at> redhat.com>
This commit is contained in:
parent
bbdd3d40bd
commit
7c9fd3ea84
@ -125,8 +125,7 @@ AC_STRUCT_TM
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for functions
|
||||
AC_SEARCH_LIBS([floor], [m], , [AC_MSG_ERROR(bailing out)])
|
||||
AC_CHECK_FUNCS([floor ftruncate gethostname getpagesize \
|
||||
AC_CHECK_FUNCS([ftruncate gethostname getpagesize \
|
||||
gettimeofday memset mkdir mkfifo rmdir munmap nl_langinfo setenv setlocale \
|
||||
strcasecmp strchr strcspn strspn strdup strncasecmp strerror strrchr \
|
||||
strstr strtol strtoul uname], , [AC_MSG_ERROR(bailing out)])
|
||||
|
@ -1015,6 +1015,29 @@ uint64_t extents_from_size(struct cmd_context *cmd, uint64_t size,
|
||||
return (uint64_t) size / extent_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return random integer in [0,max) interval
|
||||
*
|
||||
* The loop rejects numbers that come from an "incomplete" slice of the
|
||||
* RAND_MAX space (considering the number space [0, RAND_MAX] is divided
|
||||
* into some "max"-sized slices and at most a single smaller slice,
|
||||
* between [n*max, RAND_MAX] for suitable n -- numbers from this last slice
|
||||
* are discarded because they could distort the distribution in favour of
|
||||
* smaller numbers.
|
||||
*/
|
||||
static unsigned _even_rand( unsigned *seed, unsigned max )
|
||||
{
|
||||
unsigned r, ret;
|
||||
|
||||
/* make sure distribution is even */
|
||||
do {
|
||||
r = (unsigned) rand_r( seed );
|
||||
ret = r % max;
|
||||
} while ( r - ret > RAND_MAX - max );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static dm_bitset_t _bitset_with_random_bits(struct dm_pool *mem, uint32_t num_bits,
|
||||
uint32_t num_set_bits, unsigned *seed)
|
||||
{
|
||||
@ -1037,7 +1060,7 @@ static dm_bitset_t _bitset_with_random_bits(struct dm_pool *mem, uint32_t num_bi
|
||||
/* Perform loop num_set_bits times, selecting one bit each time */
|
||||
while (i++ < num_bits) {
|
||||
/* Select a random bit between 0 and (i-1) inclusive. */
|
||||
bit_selected = (unsigned) floor(i * (rand_r(seed) / (RAND_MAX + 1.0)));
|
||||
bit_selected = _even_rand(seed, i);
|
||||
|
||||
/*
|
||||
* If the bit was already set, set the new bit that became
|
||||
|
@ -111,9 +111,6 @@
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#undef HAVE_FLOOR
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user