summaryrefslogtreecommitdiff
path: root/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'random.c')
-rw-r--r--random.c247
1 files changed, 139 insertions, 108 deletions
diff --git a/random.c b/random.c
index f6f63e4cff..ad7cbca426 100644
--- a/random.c
+++ b/random.c
@@ -142,18 +142,21 @@ static const rb_random_interface_t random_mt_if = {
};
static rb_random_mt_t *
-rand_mt_start(rb_random_mt_t *r)
+rand_mt_start(rb_random_mt_t *r, VALUE obj)
{
if (!genrand_initialized(&r->mt)) {
r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef));
+ if (obj) {
+ RB_OBJ_WRITTEN(obj, Qundef, r->base.seed);
+ }
}
return r;
}
static rb_random_t *
-rand_start(rb_random_mt_t *r)
+rand_start(rb_random_mt_t *r, VALUE obj)
{
- return &rand_mt_start(r)->base;
+ return &rand_mt_start(r, obj)->base;
}
static rb_ractor_local_key_t default_rand_key;
@@ -192,7 +195,13 @@ default_rand(void)
static rb_random_mt_t *
default_mt(void)
{
- return rand_mt_start(default_rand());
+ return rand_mt_start(default_rand(), Qfalse);
+}
+
+static rb_random_t *
+default_rand_start(void)
+{
+ return &default_mt()->base;
}
unsigned int
@@ -221,7 +230,7 @@ int_pair_to_real_inclusive(uint32_t a, uint32_t b)
const uint128_t m = ((uint128_t)1 << dig) | 1;
uint128_t x = ((uint128_t)a << 32) | b;
r = (double)(uint64_t)((x * m) >> 64);
-#elif defined HAVE_UINT64_T && !MSC_VERSION_BEFORE(1300)
+#elif defined HAVE_UINT64_T
uint64_t x = ((uint64_t)a << dig_u) +
(((uint64_t)b + (a >> dig_u)) >> dig_r64);
r = (double)x;
@@ -263,7 +272,7 @@ const rb_data_type_t rb_random_data_type = {
random_free,
random_memsize,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
#define random_mt_mark rb_random_mark
@@ -284,7 +293,7 @@ static const rb_data_type_t random_mt_type = {
},
&rb_random_data_type,
(void *)&random_mt_if,
- RUBY_TYPED_FREE_IMMEDIATELY
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static rb_random_t *
@@ -293,7 +302,7 @@ get_rnd(VALUE obj)
rb_random_t *ptr;
TypedData_Get_Struct(obj, rb_random_t, &rb_random_data_type, ptr);
if (RTYPEDDATA_TYPE(obj) == &random_mt_type)
- return rand_start((rb_random_mt_t *)ptr);
+ return rand_start((rb_random_mt_t *)ptr, obj);
return ptr;
}
@@ -306,31 +315,24 @@ get_rnd_mt(VALUE obj)
}
static rb_random_t *
-try_get_rnd(VALUE obj)
+try_get_rnd(VALUE obj, const rb_random_interface_t **rng_p)
{
if (obj == rb_cRandom) {
- return rand_start(default_rand());
+ *rng_p = &random_mt_if;
+ return default_rand_start();
}
if (!rb_typeddata_is_kind_of(obj, &rb_random_data_type)) return NULL;
- if (RTYPEDDATA_TYPE(obj) == &random_mt_type)
- return rand_start(DATA_PTR(obj));
- rb_random_t *rnd = DATA_PTR(obj);
+ const struct rb_data_type_struct *type = RTYPEDDATA_TYPE(obj);
+ *rng_p = type->data;
+ void *rnd = DATA_PTR(obj);
if (!rnd) {
rb_raise(rb_eArgError, "uninitialized random: %s",
RTYPEDDATA_TYPE(obj)->wrap_struct_name);
}
+ if (type == &random_mt_type) rnd = rand_start(rnd, obj);
return rnd;
}
-static const rb_random_interface_t *
-try_rand_if(VALUE obj, rb_random_t *rnd)
-{
- if (rnd == &default_rand()->base) {
- return &random_mt_if;
- }
- return rb_rand_if(obj);
-}
-
/* :nodoc: */
void
rb_random_base_init(rb_random_t *rnd)
@@ -403,8 +405,8 @@ rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed)
static VALUE
random_init(int argc, VALUE *argv, VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
- const rb_random_interface_t *rng = rb_rand_if(obj);
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rng) {
rb_raise(rb_eTypeError, "undefined random interface: %s",
@@ -422,10 +424,10 @@ random_init(int argc, VALUE *argv, VALUE obj)
argc = rb_check_arity(argc, 0, 1);
rb_check_frozen(obj);
if (argc == 0) {
- rnd->seed = rand_init_default(rng, rnd);
+ RB_OBJ_WRITE(obj, &rnd->seed, rand_init_default(rng, rnd));
}
else {
- rnd->seed = rand_init(rng, rnd, rb_to_int(argv[0]));
+ RB_OBJ_WRITE(obj, &rnd->seed, rand_init(rng, rnd, rb_to_int(argv[0])));
}
return obj;
}
@@ -438,23 +440,17 @@ random_init(int argc, VALUE *argv, VALUE obj)
# define USE_DEV_URANDOM 0
#endif
-#ifdef HAVE_GETENTROPY
-# define MAX_SEED_LEN_PER_READ 256
-static int
-fill_random_bytes_urandom(void *seed, size_t size)
-{
- unsigned char *p = (unsigned char *)seed;
- while (size) {
- size_t len = size < MAX_SEED_LEN_PER_READ ? size : MAX_SEED_LEN_PER_READ;
- if (getentropy(p, len) != 0) {
- return -1;
- }
- p += len;
- size -= len;
- }
- return 0;
-}
-#elif USE_DEV_URANDOM
+#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom
+# ifndef GRND_NONBLOCK
+# define GRND_NONBLOCK 0x0001 /* not defined in musl libc */
+# endif
+# define getrandom(ptr, size, flags) \
+ (ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
+# define HAVE_GETRANDOM 1
+#endif
+
+/* fill random bytes by reading random device directly */
+#if USE_DEV_URANDOM
static int
fill_random_bytes_urandom(void *seed, size_t size)
{
@@ -494,15 +490,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
# define fill_random_bytes_urandom(seed, size) -1
#endif
-#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom
-# ifndef GRND_NONBLOCK
-# define GRND_NONBLOCK 0x0001 /* not defined in musl libc */
-# endif
-# define getrandom(ptr, size, flags) \
- (ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
-# define HAVE_GETRANDOM 1
-#endif
-
+/* fill random bytes by library */
#if 0
#elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
@@ -520,7 +508,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
# endif
static int
-fill_random_bytes_syscall(void *seed, size_t size, int unused)
+fill_random_bytes_lib(void *seed, size_t size)
{
#if USE_COMMON_RANDOM
CCRNGStatus status = CCRandomGenerateBytes(seed, size);
@@ -547,18 +535,16 @@ fill_random_bytes_syscall(void *seed, size_t size, int unused)
}
return 0;
}
-#elif defined(HAVE_ARC4RANDOM_BUF)
+#elif defined(HAVE_ARC4RANDOM_BUF) && \
+ ((defined(__OpenBSD__) && OpenBSD >= 201411) || \
+ (defined(__NetBSD__) && __NetBSD_Version__ >= 700000000) || \
+ (defined(__FreeBSD__) && __FreeBSD_version >= 1200079))
+// [Bug #15039] arc4random_buf(3) should used only if we know it is fork-safe
static int
-fill_random_bytes_syscall(void *buf, size_t size, int unused)
+fill_random_bytes_lib(void *buf, size_t size)
{
-#if (defined(__OpenBSD__) && OpenBSD >= 201411) || \
- (defined(__NetBSD__) && __NetBSD_Version__ >= 700000000) || \
- (defined(__FreeBSD__) && __FreeBSD_version >= 1200079)
arc4random_buf(buf, size);
return 0;
-#else
- return -1;
-#endif
}
#elif defined(_WIN32)
@@ -638,11 +624,17 @@ fill_random_bytes_bcrypt(void *seed, size_t size)
}
static int
-fill_random_bytes_syscall(void *seed, size_t size, int unused)
+fill_random_bytes_lib(void *seed, size_t size)
{
if (fill_random_bytes_bcrypt(seed, size) == 0) return 0;
return fill_random_bytes_crypt(seed, size);
}
+#else
+# define fill_random_bytes_lib(seed, size) -1
+#endif
+
+/* fill random bytes by dedicated syscall */
+#if 0
#elif defined HAVE_GETRANDOM
static int
fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
@@ -666,6 +658,31 @@ fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
}
return -1;
}
+#elif defined(HAVE_GETENTROPY)
+/*
+ * The Open Group Base Specifications Issue 8 - IEEE Std 1003.1-2024
+ * https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
+ *
+ * NOTE: `getentropy`(3) on Linux is implemented using `getrandom`(2),
+ * prefer the latter over this if both are defined.
+ */
+#ifndef GETENTROPY_MAX
+# define GETENTROPY_MAX 256
+#endif
+static int
+fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
+{
+ unsigned char *p = (unsigned char *)seed;
+ while (size) {
+ size_t len = size < GETENTROPY_MAX ? size : GETENTROPY_MAX;
+ if (getentropy(p, len) != 0) {
+ return -1;
+ }
+ p += len;
+ size -= len;
+ }
+ return 0;
+}
#else
# define fill_random_bytes_syscall(seed, size, need_secure) -1
#endif
@@ -675,6 +692,7 @@ ruby_fill_random_bytes(void *seed, size_t size, int need_secure)
{
int ret = fill_random_bytes_syscall(seed, size, need_secure);
if (ret == 0) return ret;
+ if (fill_random_bytes_lib(seed, size) == 0) return 0;
return fill_random_bytes_urandom(seed, size);
}
@@ -813,6 +831,7 @@ rand_mt_copy(VALUE obj, VALUE orig)
mt = &rnd1->mt;
*rnd1 = *rnd2;
+ RB_OBJ_WRITTEN(obj, Qundef, rnd1->base.seed);
mt->next = mt->state + numberof(mt->state) - mt->left + 1;
return obj;
}
@@ -900,7 +919,7 @@ rand_mt_load(VALUE obj, VALUE dump)
}
mt->left = (unsigned int)x;
mt->next = mt->state + numberof(mt->state) - x + 1;
- rnd->base.seed = rb_to_int(seed);
+ RB_OBJ_WRITE(obj, &rnd->base.seed, rb_to_int(seed));
return obj;
}
@@ -959,7 +978,7 @@ static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
- rb_random_mt_t *r = rand_mt_start(default_rand());
+ rb_random_mt_t *r = default_mt();
if (rb_check_arity(argc, 0, 1) == 0) {
seed = random_seed(obj);
@@ -1104,17 +1123,18 @@ random_int32(const rb_random_interface_t *rng, rb_random_t *rnd)
unsigned int
rb_random_int32(VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
uint32_t x;
obj_random_bytes(obj, &x, sizeof(x));
return (unsigned int)x;
}
- return random_int32(try_rand_if(obj, rnd), rnd);
+ return random_int32(rng, rnd);
}
static double
-random_real(VALUE obj, rb_random_t *rnd, int excl)
+random_real(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, int excl)
{
uint32_t a, b;
@@ -1125,7 +1145,6 @@ random_real(VALUE obj, rb_random_t *rnd, int excl)
b = x[1];
}
else {
- const rb_random_interface_t *rng = try_rand_if(obj, rnd);
if (rng->get_real) return rng->get_real(rnd, excl);
a = random_int32(rng, rnd);
b = random_int32(rng, rnd);
@@ -1147,7 +1166,8 @@ rb_int_pair_to_real(uint32_t a, uint32_t b, int excl)
double
rb_random_real(VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
VALUE v = rb_funcallv(obj, id_rand, 0, 0);
double d = NUM2DBL(v);
@@ -1159,7 +1179,7 @@ rb_random_real(VALUE obj)
}
return d;
}
- return random_real(obj, rnd, TRUE);
+ return random_real(obj, rng, rnd, TRUE);
}
static inline VALUE
@@ -1176,7 +1196,7 @@ ulong_to_num_plus_1(unsigned long n)
}
static unsigned long
-random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit)
+random_ulong_limited(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, unsigned long limit)
{
if (!limit) return 0;
if (!rnd) {
@@ -1201,13 +1221,14 @@ random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit)
} while (limit < val);
return val;
}
- return limited_rand(try_rand_if(obj, rnd), rnd, limit);
+ return limited_rand(rng, rnd, limit);
}
unsigned long
rb_random_ulong_limited(VALUE obj, unsigned long limit)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
VALUE lim = ulong_to_num_plus_1(limit);
VALUE v = rb_to_int(rb_funcallv_public(obj, id_rand, 1, &lim));
@@ -1220,11 +1241,11 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit)
}
return r;
}
- return limited_rand(try_rand_if(obj, rnd), rnd, limit);
+ return limited_rand(rng, rnd, limit);
}
static VALUE
-random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax)
+random_ulong_limited_big(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, VALUE vmax)
{
if (!rnd) {
VALUE v, vtmp;
@@ -1249,7 +1270,7 @@ random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax)
ALLOCV_END(vtmp);
return v;
}
- return limited_big_rand(try_rand_if(obj, rnd), rnd, vmax);
+ return limited_big_rand(rng, rnd, vmax);
}
static VALUE
@@ -1275,8 +1296,9 @@ rand_bytes(const rb_random_interface_t *rng, rb_random_t *rnd, long n)
static VALUE
random_bytes(VALUE obj, VALUE len)
{
- rb_random_t *rnd = try_get_rnd(obj);
- return rand_bytes(rb_rand_if(obj), rnd, NUM2LONG(rb_to_int(len)));
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
+ return rand_bytes(rng, rnd, NUM2LONG(rb_to_int(len)));
}
void
@@ -1305,11 +1327,12 @@ rb_rand_bytes_int32(rb_random_get_int32_func *get_int32,
VALUE
rb_random_bytes(VALUE obj, long n)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
return obj_random_bytes(obj, NULL, n);
}
- return rand_bytes(try_rand_if(obj, rnd), rnd, n);
+ return rand_bytes(rng, rnd, n);
}
/*
@@ -1321,7 +1344,7 @@ rb_random_bytes(VALUE obj, long n)
static VALUE
random_s_bytes(VALUE obj, VALUE len)
{
- rb_random_t *rnd = rand_start(default_rand());
+ rb_random_t *rnd = default_rand_start();
return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
}
@@ -1343,7 +1366,7 @@ random_s_bytes(VALUE obj, VALUE len)
static VALUE
random_s_seed(VALUE obj)
{
- rb_random_mt_t *rnd = rand_mt_start(default_rand());
+ rb_random_mt_t *rnd = default_mt();
return rnd->base.seed;
}
@@ -1361,7 +1384,7 @@ range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
}
static VALUE
-rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
+rand_int(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, VALUE vmax, int restrictive)
{
/* mt must be initialized */
unsigned long r;
@@ -1373,7 +1396,7 @@ rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
if (restrictive) return Qnil;
max = -max;
}
- r = random_ulong_limited(obj, rnd, (unsigned long)max - 1);
+ r = random_ulong_limited(obj, rng, rnd, (unsigned long)max - 1);
return ULONG2NUM(r);
}
else {
@@ -1387,10 +1410,10 @@ rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
if (FIXNUM_P(vmax)) {
long max = FIX2LONG(vmax);
if (max == -1) return Qnil;
- r = random_ulong_limited(obj, rnd, max);
+ r = random_ulong_limited(obj, rng, rnd, max);
return LONG2NUM(r);
}
- ret = random_ulong_limited_big(obj, rnd, vmax);
+ ret = random_ulong_limited_big(obj, rng, rnd, vmax);
RB_GC_GUARD(vmax);
return ret;
}
@@ -1434,7 +1457,7 @@ float_value(VALUE v)
}
static inline VALUE
-rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
+rand_range(VALUE obj, const rb_random_interface_t *rng, rb_random_t* rnd, VALUE range)
{
VALUE beg = Qundef, end = Qundef, vmax, v;
int excl = 0;
@@ -1449,7 +1472,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
fixnum:
if (FIXNUM_P(vmax)) {
if ((max = FIX2LONG(vmax) - excl) >= 0) {
- unsigned long r = random_ulong_limited(obj, rnd, (unsigned long)max);
+ unsigned long r = random_ulong_limited(obj, rng, rnd, (unsigned long)max);
v = ULONG2NUM(r);
}
}
@@ -1459,7 +1482,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
excl = 0;
goto fixnum;
}
- v = random_ulong_limited_big(obj, rnd, vmax);
+ v = random_ulong_limited_big(obj, rng, rnd, vmax);
}
}
else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
@@ -1477,7 +1500,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
}
v = Qnil;
if (max > 0.0) {
- r = random_real(obj, rnd, excl);
+ r = random_real(obj, rng, rnd, excl);
if (scale > 1) {
return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
}
@@ -1510,7 +1533,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
return v;
}
-static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
+static VALUE rand_random(int argc, VALUE *argv, VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd);
/*
* call-seq:
@@ -1526,9 +1549,11 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
* prng.rand(100) # => 42
*
* When +max+ is a Float, +rand+ returns a random floating point number
- * between 0.0 and +max+, including 0.0 and excluding +max+.
+ * between 0.0 and +max+, including 0.0 and excluding +max+. Note that it
+ * behaves differently from Kernel.rand.
*
- * prng.rand(1.5) # => 1.4600282860034115
+ * prng.rand(1.5) # => 1.4600282860034115
+ * rand(1.5) # => 0
*
* When +range+ is a Range, +rand+ returns a random number where
* <code>range.member?(number) == true</code>.
@@ -1545,24 +1570,26 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
static VALUE
random_rand(int argc, VALUE *argv, VALUE obj)
{
- VALUE v = rand_random(argc, argv, obj, try_get_rnd(obj));
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
+ VALUE v = rand_random(argc, argv, obj, rng, rnd);
check_random_number(v, argv);
return v;
}
static VALUE
-rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
+rand_random(int argc, VALUE *argv, VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd)
{
VALUE vmax, v;
if (rb_check_arity(argc, 0, 1) == 0) {
- return rb_float_new(random_real(obj, rnd, TRUE));
+ return rb_float_new(random_real(obj, rng, rnd, TRUE));
}
vmax = argv[0];
if (NIL_P(vmax)) return Qnil;
if (!RB_FLOAT_TYPE_P(vmax)) {
v = rb_check_to_int(vmax);
- if (!NIL_P(v)) return rand_int(obj, rnd, v, 1);
+ if (!NIL_P(v)) return rand_int(obj, rng, rnd, v, 1);
}
v = rb_check_to_float(vmax);
if (!NIL_P(v)) {
@@ -1571,12 +1598,12 @@ rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
return Qnil;
}
else {
- double r = random_real(obj, rnd, TRUE);
+ double r = random_real(obj, rng, rnd, TRUE);
if (max > 0.0) r *= max;
return rb_float_new(r);
}
}
- return rand_range(obj, rnd, vmax);
+ return rand_range(obj, rng, rnd, vmax);
}
/*
@@ -1594,9 +1621,10 @@ rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
static VALUE
rand_random_number(int argc, VALUE *argv, VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
- VALUE v = rand_random(argc, argv, obj, rnd);
- if (NIL_P(v)) v = rand_random(0, 0, obj, rnd);
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
+ VALUE v = rand_random(argc, argv, obj, rng, rnd);
+ if (NIL_P(v)) v = rand_random(0, 0, obj, rng, rnd);
else if (!v) invalid_argument(argv[0]);
return v;
}
@@ -1666,25 +1694,28 @@ rand_mt_equal(VALUE self, VALUE other)
* Kernel.srand may be used to ensure that sequences of random numbers are
* reproducible between different runs of a program.
*
- * See also Random.rand.
+ * Related: Random.rand.
+ * rand(100.0) # => 64 (Integer because max.to_i is 100)
+ * Random.rand(100.0) # => 30.315320967824523
*/
static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE vmax;
- rb_random_t *rnd = rand_start(default_rand());
+ const rb_random_interface_t *rng = &random_mt_if;
+ rb_random_t *rnd = default_rand_start();
if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
- VALUE v = rand_range(obj, rnd, vmax);
+ VALUE v = rand_range(obj, rng, rnd, vmax);
if (v != Qfalse) return v;
vmax = rb_to_int(vmax);
if (vmax != INT2FIX(0)) {
- v = rand_int(obj, rnd, vmax, 0);
+ v = rand_int(obj, rng, rnd, vmax, 0);
if (!NIL_P(v)) return v;
}
}
- return DBL2NUM(random_real(obj, rnd, TRUE));
+ return DBL2NUM(random_real(obj, rng, rnd, TRUE));
}
/*
@@ -1700,7 +1731,7 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj)
static VALUE
random_s_rand(int argc, VALUE *argv, VALUE obj)
{
- VALUE v = rand_random(argc, argv, Qnil, rand_start(default_rand()));
+ VALUE v = rand_random(argc, argv, Qnil, &random_mt_if, default_rand_start());
check_random_number(v, argv);
return v;
}