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
|
dnl -- Check for functions
|
||||||
AC_SEARCH_LIBS([floor], [m], , [AC_MSG_ERROR(bailing out)])
|
AC_CHECK_FUNCS([ftruncate gethostname getpagesize \
|
||||||
AC_CHECK_FUNCS([floor ftruncate gethostname getpagesize \
|
|
||||||
gettimeofday memset mkdir mkfifo rmdir munmap nl_langinfo setenv setlocale \
|
gettimeofday memset mkdir mkfifo rmdir munmap nl_langinfo setenv setlocale \
|
||||||
strcasecmp strchr strcspn strspn strdup strncasecmp strerror strrchr \
|
strcasecmp strchr strcspn strspn strdup strncasecmp strerror strrchr \
|
||||||
strstr strtol strtoul uname], , [AC_MSG_ERROR(bailing out)])
|
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 (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,
|
static dm_bitset_t _bitset_with_random_bits(struct dm_pool *mem, uint32_t num_bits,
|
||||||
uint32_t num_set_bits, unsigned *seed)
|
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 */
|
/* Perform loop num_set_bits times, selecting one bit each time */
|
||||||
while (i++ < num_bits) {
|
while (i++ < num_bits) {
|
||||||
/* Select a random bit between 0 and (i-1) inclusive. */
|
/* 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
|
* 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. */
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
#undef HAVE_FCNTL_H
|
#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. */
|
/* Define to 1 if you have the `fork' function. */
|
||||||
#undef HAVE_FORK
|
#undef HAVE_FORK
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user