[Bug #19100] Add init_int32
function to rb_random_interface_t
Distinguish initialization by single word from initialization by array.
This commit is contained in:
parent
6eaed20e14
commit
b7e8876704
@ -20,6 +20,9 @@ bad_version_init(rb_random_t *rnd, const uint32_t *buf, size_t len)
|
||||
must_not_reach();
|
||||
}
|
||||
|
||||
NORETURN(static void bad_version_init_int32(rb_random_t *, uint32_t));
|
||||
RB_RANDOM_DEFINE_INIT_INT32_FUNC(bad_version)
|
||||
|
||||
NORETURN(static void bad_version_get_bytes(rb_random_t *, void *, size_t));
|
||||
static void
|
||||
bad_version_get_bytes(rb_random_t *rnd, void *p, size_t n)
|
||||
|
@ -13,6 +13,7 @@ static const rb_random_interface_t random_loop_if = {
|
||||
RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(loop)
|
||||
};
|
||||
|
||||
RB_RANDOM_DEFINE_INIT_INT32_FUNC(loop);
|
||||
static size_t
|
||||
random_loop_memsize(const void *ptr)
|
||||
{
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* version
|
||||
* 0: before versioning; deprecated
|
||||
* 1: added version and flags
|
||||
* 1: added version, flags and init_32bit function
|
||||
*/
|
||||
#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR 1
|
||||
#define RUBY_RANDOM_INTERFACE_VERSION_MINOR 0
|
||||
@ -66,6 +66,17 @@ RBIMPL_ATTR_NONNULL(())
|
||||
*/
|
||||
typedef void rb_random_init_func(rb_random_t *rng, const uint32_t *buf, size_t len);
|
||||
|
||||
RBIMPL_ATTR_NONNULL(())
|
||||
/**
|
||||
* This is the type of functions called when your random object is initialised.
|
||||
* Passed data is the seed integer.
|
||||
*
|
||||
* @param[out] rng Your random struct to fill in.
|
||||
* @param[in] data Seed, single word.
|
||||
* @post `rng` is initialised using the passed seeds.
|
||||
*/
|
||||
typedef void rb_random_init_int32_func(rb_random_t *rng, uint32_t data);
|
||||
|
||||
RBIMPL_ATTR_NONNULL(())
|
||||
/**
|
||||
* This is the type of functions called from your object's `#rand` method.
|
||||
@ -116,9 +127,12 @@ typedef struct {
|
||||
*/
|
||||
uint16_t flags;
|
||||
|
||||
/** Initialiser function. */
|
||||
/** Function to initialize from uint32_t array. */
|
||||
rb_random_init_func *init;
|
||||
|
||||
/** Function to initialize from single uint32_t. */
|
||||
rb_random_init_int32_func *init_int32;
|
||||
|
||||
/** Function to obtain a random integer. */
|
||||
rb_random_get_int32_func *get_int32;
|
||||
|
||||
@ -162,11 +176,12 @@ typedef struct {
|
||||
} rb_random_interface_t;
|
||||
|
||||
/**
|
||||
* This utility macro defines 3 functions named prefix_init, prefix_get_int32,
|
||||
* prefix_get_bytes.
|
||||
* This utility macro defines 4 functions named prefix_init, prefix_init_int32,
|
||||
* prefix_get_int32, prefix_get_bytes.
|
||||
*/
|
||||
#define RB_RANDOM_INTERFACE_DECLARE(prefix) \
|
||||
static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \
|
||||
static void prefix##_init_int32(rb_random_t *, uint32_t); \
|
||||
static unsigned int prefix##_get_int32(rb_random_t *); \
|
||||
static void prefix##_get_bytes(rb_random_t *, void *, size_t)
|
||||
|
||||
@ -195,6 +210,7 @@ typedef struct {
|
||||
#define RB_RANDOM_INTERFACE_DEFINE(prefix) \
|
||||
RUBY_RANDOM_INTERFACE_VERSION_INITIALIZER, 0, \
|
||||
prefix##_init, \
|
||||
prefix##_init_int32, \
|
||||
prefix##_get_int32, \
|
||||
prefix##_get_bytes
|
||||
|
||||
@ -206,6 +222,12 @@ typedef struct {
|
||||
RB_RANDOM_INTERFACE_DEFINE(prefix), \
|
||||
prefix##_get_real
|
||||
|
||||
#define RB_RANDOM_DEFINE_INIT_INT32_FUNC(prefix) \
|
||||
static void prefix##_init_int32(rb_random_t *rnd, uint32_t data) \
|
||||
{ \
|
||||
prefix##_init(rnd, &data, 1); \
|
||||
}
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
typedef rb_data_type_t rb_random_data_type_t;
|
||||
# define RB_RANDOM_PARENT 0
|
||||
|
21
random.c
21
random.c
@ -371,11 +371,14 @@ rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed)
|
||||
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
|
||||
if (sign < 0)
|
||||
sign = -sign;
|
||||
if (len > 1) {
|
||||
if (len <= 1) {
|
||||
rng->init_int32(rnd, len ? buf[0] : 0);
|
||||
}
|
||||
else {
|
||||
if (sign != 2 && buf[len-1] == 1) /* remove leading-zero-guard */
|
||||
len--;
|
||||
rng->init(rnd, buf, len);
|
||||
}
|
||||
rng->init(rnd, buf, len);
|
||||
explicit_bzero(buf, len * sizeof(*buf));
|
||||
ALLOCV_END(buf0);
|
||||
return seed;
|
||||
@ -891,16 +894,18 @@ rand_mt_load(VALUE obj, VALUE dump)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
rand_mt_init_int32(rb_random_t *rnd, uint32_t data)
|
||||
{
|
||||
struct MT *mt = &((rb_random_mt_t *)rnd)->mt;
|
||||
init_genrand(mt, data);
|
||||
}
|
||||
|
||||
static void
|
||||
rand_mt_init(rb_random_t *rnd, const uint32_t *buf, size_t len)
|
||||
{
|
||||
struct MT *mt = &((rb_random_mt_t *)rnd)->mt;
|
||||
if (len <= 1) {
|
||||
init_genrand(mt, len ? buf[0] : 0);
|
||||
}
|
||||
else {
|
||||
init_by_array(mt, buf, (int)len);
|
||||
}
|
||||
init_by_array(mt, buf, (int)len);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
|
@ -336,6 +336,14 @@ class TestRand < Test::Unit::TestCase
|
||||
}
|
||||
end
|
||||
|
||||
def test_seed_leading_zero_guard
|
||||
guard = 1<<32
|
||||
range = 0...(1<<32)
|
||||
all_assertions_foreach(nil, 0, 1, 2) do |i|
|
||||
assert_not_equal(Random.new(i).rand(range), Random.new(i+guard).rand(range))
|
||||
end
|
||||
end
|
||||
|
||||
def test_marshal
|
||||
bug3656 = '[ruby-core:31622]'
|
||||
assert_raise(TypeError, bug3656) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user