From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: Ilya Kosarev <i.kosarev@tarantool.org>
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH v3] core: introduce evenly distributed int64 random in range
Date: Mon, 2 Nov 2020 22:38:42 +0100 [thread overview]
Message-ID: <59b0d6c4-acca-db29-1cf8-223841d664bd@tarantool.org> (raw)
In-Reply-To: <20201023211220.13166-1-i.kosarev@tarantool.org>
Hi! Thanks for the patch!
Almost finished!
See 5 comments below.
> diff --git a/src/lib/core/random.c b/src/lib/core/random.c
> index f4fa75b1c..cfca2b7a9 100644
> --- a/src/lib/core/random.c
> +++ b/src/lib/core/random.c
> @@ -97,3 +102,85 @@ rand:
> while (generated < size)
> buf[generated++] = rand();
> }
> +
> +uint64_t
> +real_random(void)
> +{
> + uint64_t result;
> + random_bytes((char *)(&result), sizeof(result));
1. Why do you need () around &result?
> + return result;
> +}
> +
> +uint64_t *
> +xoshiro_state(void)
> +{
> + return state;
> +}
> +
> +size_t
> +xoshiro_state_size(void)
> +{
> + return sizeof(state) / sizeof(state[0]);
> +}
2. Or instead of these two functions it could be simpler
to implement xoshiro_state_str(), which would return
its 4 uint64 numbers as tt_sprintf(). Anyway we need to
print the state in a human readable format.
> +
> +int64_t
> +real_random_in_range(int64_t min, int64_t max)
> +{
> + assert(max >= min);
> + uint64_t range = (uint64_t)max - min;
3. This is UB, if max is negative.
> + uint64_t mask = UINT64_MAX >> bit_clz_u64(range | 1);
> + uint64_t result;
> + do {
> + result = real_random() & mask;
> + } while (result > range);
> + return min + result;
> +}
> +
> +int64_t
> +pseudo_random_in_range(int64_t min, int64_t max)
> +{
> + assert(max >= min);
> + uint64_t range = (uint64_t)max - min;
> + uint64_t mask = UINT64_MAX >> bit_clz_u64(range | 1);
> + uint64_t result;
> + do {
> + result = xoshiro_random() & mask;
> + } while (result > range);
> + return min + result;
> +}
> diff --git a/test/unit/random.c b/test/unit/random.c
> new file mode 100644
> index 000000000..3d7416988
> --- /dev/null
> +++ b/test/unit/random.c
> @@ -0,0 +1,48 @@
> +#include <core/random.h>
> +
> +#include <stdio.h>
> +#include <assert.h>
> +
> +#include "unit.h"
> +
> +static void
> +test_xoshiro_random_in_range_one(int64_t min, int64_t max)
> +{
> + int64_t result = pseudo_random_in_range(min, max);
> + assert(min <= result && result <= max);
> + if (min == max)
> + printf("pseudo_random_in_range(%lld, %lld) = %lld\n",
> + (long long)min, (long long)max, (long long)result);
> +}
4. Why no tests for real random?
> diff --git a/test/unit/swim_test_utils.c b/test/unit/swim_test_utils.c
> index 9dbd28a9f..590ce97a1 100644
> --- a/test/unit/swim_test_utils.c
> +++ b/test/unit/swim_test_utils.c
> @@ -875,7 +875,15 @@ swim_run_test(const char *log_file, fiber_func test)
> * Print the seed to be able to reproduce a bug with the
> * same seed.
> */
> - say_info("Random seed = %llu", (unsigned long long) seed);
> + say_info("Random seed = %llu", (unsigned long long)seed);
> + uint64_t *state = xoshiro_state();
> + char state_buf[100] = "";
> + int filled = 0;
> + for (size_t i = 0; i < xoshiro_state_size(); i++)
> + filled += snprintf(state_buf + filled,
> + sizeof(state_buf) - filled,
> + " %llu", (unsigned long long)state[i]);
> + say_info("xoshiro random state =%s", state_buf);
5. snprintf() returns number of bytes that would have been
printed if the buffer would be long enough. It means, that
"sizeof(state_buf) - filled" may become negative with such
accumulation. If state size will even become bigger,
for example. And since snprintf()'s second argument is
size_t, it will overflow to a huge value, leading to the
stack corruption.
Better return a string on tt_sprintf() right from random.c,
so as not to care about snprintf specifics in the tests.
>
> struct fiber *main_fiber = fiber_new("main", test);
> fiber_set_joinable(main_fiber, true);
>
next prev parent reply other threads:[~2020-11-02 21:38 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-23 21:12 Ilya Kosarev
2020-11-02 21:38 ` Vladislav Shpilevoy [this message]
2020-11-05 11:07 ` Ilya Kosarev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=59b0d6c4-acca-db29-1cf8-223841d664bd@tarantool.org \
--to=v.shpilevoy@tarantool.org \
--cc=i.kosarev@tarantool.org \
--cc=tarantool-patches@dev.tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH v3] core: introduce evenly distributed int64 random in range' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox