69 #include <sys/types.h> 76 #if defined(HAVE_SYS_TIME_H) 82 #elif defined HAVE_SYS_SYSCALL_H 83 #include <sys/syscall.h> 97 #define MATRIX_A 0x9908b0dfU 98 #define UMASK 0x80000000U 99 #define LMASK 0x7fffffffU 100 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) 101 #define TWIST(u,v) ((MIXBITS((u),(v)) >> 1) ^ ((v)&1U ? MATRIX_A : 0U)) 112 #define genrand_initialized(mt) ((mt)->next != 0) 113 #define uninit_genrand(mt) ((mt)->next = 0) 117 init_genrand(
struct MT *mt,
unsigned int s)
120 mt->
state[0] = s & 0xffffffff
U;
121 for (j=1; j<
N; j++) {
122 mt->
state[j] = (1812433253U * (mt->
state[j-1] ^ (mt->
state[j-1] >> 30)) + j);
127 mt->
state[j] &= 0xffffffff;
138 init_by_array(
struct MT *mt,
const uint32_t init_key[],
int key_length)
141 init_genrand(mt, 19650218
U);
143 k = (
N>key_length ?
N : key_length);
147 mt->
state[i] &= 0xffffffff
U;
150 if (j>=key_length) j=0;
152 for (k=
N-1; k; k--) {
155 mt->
state[i] &= 0xffffffff
U;
160 mt->
state[0] = 0x80000000
U;
164 next_state(
struct MT *mt)
172 for (j=
N-
M+1; --j; p++)
173 *p = p[
M] ^
TWIST(p[0], p[1]);
176 *p = p[
M-
N] ^
TWIST(p[0], p[1]);
183 genrand_int32(
struct MT *mt)
188 if (--mt->
left <= 0) next_state(mt);
193 y ^= (y << 7) & 0x9d2c5680;
194 y ^= (y << 15) & 0xefc60000;
203 genrand_real(
struct MT *mt)
206 unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
207 return int_pair_to_real_exclusive(a, b);
215 return(a*67108864.0+b)*(1.0/9007199254740992.0);
222 genrand_real2(
struct MT *mt)
225 uint32_t a = genrand_int32(mt), b = genrand_int32(mt);
226 return int_pair_to_real_inclusive(a, b);
240 #define DEFAULT_SEED_CNT 4 245 static VALUE random_seed(
void);
250 struct MT *mt = &r->
mt;
252 r->
seed = rand_init(mt, random_seed());
260 return &rand_start(&default_rand)->
mt;
266 struct MT *mt = default_mt();
267 return genrand_int32(mt);
273 struct MT *mt = default_mt();
274 return genrand_real(mt);
277 #define SIZEOF_INT32 (31/CHAR_BIT + 1) 284 enum {dig_u = dig-32, dig_r64 = 64-dig, bmask = ~(~0u<<(dig_r64))};
285 #if defined HAVE_UINT128_T 286 const uint128_t m = ((uint128_t)1 << dig) | 1;
287 uint128_t x = ((uint128_t)a << 32) | b;
288 r = (double)(
uint64_t)((x * m) >> 64);
289 #elif defined HAVE_UINT64_T && !(defined _MSC_VER && _MSC_VER <= 1200) 291 (((
uint64_t)b + (a >> dig_u)) >> dig_r64);
295 b = (b >> dig_r64) + (((a >> dig_u) + (b & bmask)) >> dig_r64);
296 r = (double)a * (1 << dig_u) + b;
298 return ldexp(r, -dig);
304 static ID id_rand, id_bytes;
308 random_mark(
void *ptr)
314 random_free(
void *ptr)
316 if (ptr != &default_rand)
321 random_memsize(
const void *ptr)
341 return rand_start(ptr);
345 try_get_rnd(
VALUE obj)
347 if (obj == rb_cRandom) {
348 return rand_start(&default_rand);
356 random_alloc(
VALUE klass)
365 rand_init(
struct MT *mt,
VALUE seed)
383 init_genrand(mt, buf[0]);
386 if (sign != 2 && buf[len-1] == 1)
388 init_by_array(mt, buf, (
int)len);
391 if (buf != buf0)
xfree(buf);
412 vseed = random_seed();
419 rnd->
seed = rand_init(&rnd->
mt, vseed);
423 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int32_t)) 425 #if defined(S_ISCHR) && !defined(DOSISH) 426 # define USE_DEV_URANDOM 1 428 # define USE_DEV_URANDOM 0 451 if (fd < 0)
return -1;
453 if (
fstat(fd, &statbuf) == 0 &&
S_ISCHR(statbuf.st_mode)) {
454 ret = read(fd, seed, size);
457 if (ret < 0 || (
size_t)ret < size)
return -1;
461 # define fill_random_bytes_urandom(seed, size) -1 465 #elif defined(HAVE_ARC4RANDOM_BUF) 469 arc4random_buf(buf, size);
472 #elif defined(_WIN32) 474 release_crypt(
void *p)
477 if (prov && prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
478 CryptReleaseContext(prov, 0);
485 static HCRYPTPROV perm_prov;
486 HCRYPTPROV prov = perm_prov, old_prov;
488 if (!CryptAcquireContext(&prov,
NULL,
NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
489 prov = (HCRYPTPROV)INVALID_HANDLE_VALUE;
493 if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
498 if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
499 CryptReleaseContext(prov, 0);
504 if (prov == (HCRYPTPROV)INVALID_HANDLE_VALUE)
return -1;
505 CryptGenRandom(prov, size, seed);
508 #elif defined __linux__ && defined __NR_getrandom 509 #include <linux/random.h> 511 # ifndef GRND_NONBLOCK 512 # define GRND_NONBLOCK 0x0001 523 flags = GRND_NONBLOCK;
525 ret = syscall(__NR_getrandom, seed, size, flags);
526 if (
errno == ENOSYS) {
530 if ((
size_t)ret == size)
return 0;
535 # define fill_random_bytes_syscall(seed, size, need_secure) -1 539 fill_random_bytes(
void *seed,
size_t size,
int need_secure)
542 if (ret == 0)
return ret;
551 size_t len = cnt *
sizeof(*seed);
553 memset(seed, 0, len);
555 fill_random_bytes(seed, len,
TRUE);
560 #
if SIZEOF_TIME_T > SIZEOF_INT
563 seed[2] ^= getpid() ^ (n++ << 16);
565 #if SIZEOF_VOIDP > SIZEOF_INT 575 if (ptr[len-1] <= 1) {
626 if (n == 0)
return buf;
647 random_get_seed(
VALUE obj)
649 return get_rnd(obj)->
seed;
662 rnd2 = get_rnd(orig);
671 mt_state(
const struct MT *mt)
674 sizeof(*mt->
state), 0,
680 random_state(
VALUE obj)
683 return mt_state(&rnd->
mt);
688 random_s_state(
VALUE klass)
690 return mt_state(&default_rand.
mt);
695 random_left(
VALUE obj)
703 random_s_left(
VALUE klass)
710 random_dump(
VALUE obj)
727 struct MT *mt = &rnd->
mt;
747 sizeof(*mt->
state), 0,
753 mt->
left = (
unsigned int)x;
790 seed = random_seed();
796 r->
seed = rand_init(&r->
mt, seed);
802 make_mask(
unsigned long x)
816 limited_rand(
struct MT *mt,
unsigned long limit)
819 unsigned long val, mask;
821 if (!limit)
return 0;
822 mask = make_mask(limit);
825 if (0xffffffff < limit) {
830 if ((mask >> (i * 32)) & 0xffffffff) {
831 val |= (
unsigned long)genrand_int32(mt) << (i * 32);
842 val = genrand_int32(mt) & mask;
843 }
while (limit < val);
848 limited_big_rand(
struct MT *mt,
VALUE limit)
857 uint32_t *tmp, *lim_array, *rnd_array;
864 rnd_array = tmp +
len;
871 for (i = len-1; 0 <= i; i--) {
874 mask = mask ? 0xffffffff : (
uint32_t)make_mask(lim);
876 rnd = genrand_int32(mt) & mask;
905 return limited_rand(default_mt(), limit);
909 obj_random_bytes(
VALUE obj,
void *p,
long n)
927 return genrand_int32(&rnd->
mt);
936 obj_random_bytes(obj, &x,
sizeof(x));
937 return (
unsigned int)x;
939 return random_int32(rnd);
949 obj_random_bytes(obj, x,
sizeof(x));
954 a = random_int32(rnd);
955 b = random_int32(rnd);
958 return int_pair_to_real_exclusive(a, b);
961 return int_pair_to_real_inclusive(a, b);
980 return genrand_real(&rnd->
mt);
984 ulong_to_num_plus_1(
unsigned long n)
987 return ULL2NUM((LONG_LONG)n+1);
989 if (n >= ULONG_MAX) {
999 if (!limit)
return 0;
1001 const int w =
sizeof(limit) *
CHAR_BIT - nlz_long(limit);
1002 const int n = w > 32 ?
sizeof(
unsigned long) :
sizeof(
uint32_t);
1003 const unsigned long mask = ~(~0UL << w);
1004 const unsigned long full =
1005 (size_t)n >=
sizeof(
unsigned long) ? ~0UL :
1007 unsigned long val, bits = 0, rest = 0;
1011 obj_random_bytes(obj, &
buf, n);
1019 }
while (limit < val);
1022 return limited_rand(&rnd->
mt, limit);
1030 VALUE lim = ulong_to_num_plus_1(limit);
1041 return limited_rand(&rnd->
mt, limit);
1058 obj_random_bytes(obj, rnd_array, len *
sizeof(
uint32_t));
1059 rnd_array[0] &= mask;
1060 for (i = 0; i <
len; ++i) {
1061 if (lim_array[i] < rnd_array[i])
1063 if (rnd_array[i] < lim_array[i])
1070 return limited_big_rand(&rnd->
mt, vmax);
1099 r = genrand_int32(&rnd->
mt);
1107 r = genrand_int32(&rnd->
mt);
1121 return obj_random_bytes(obj,
NULL, n);
1123 return genrand_bytes(rnd, n);
1132 if (endp) *endp = end;
1147 if (!max)
return Qnil;
1149 if (restrictive)
return Qnil;
1152 r = random_ulong_limited(obj, rnd, (
unsigned long)max - 1);
1159 if (restrictive)
return Qnil;
1165 if (max == -1)
return Qnil;
1166 r = random_ulong_limited(obj, rnd, max);
1169 ret = random_ulong_limited_big(obj, rnd, vmax);
1185 invalid_argument(
VALUE arg0)
1191 check_random_number(
VALUE v,
const VALUE *argv)
1198 invalid_argument(argv[0]);
1203 static inline double 1204 float_value(
VALUE v)
1219 if ((v = vmax = range_values(range, &beg, &end, &excl)) ==
Qfalse)
1227 if ((max =
FIX2LONG(vmax) - excl) >= 0) {
1228 unsigned long r = random_ulong_limited(obj, rnd, (
unsigned long)max);
1238 v = random_ulong_limited_big(obj, rnd, vmax);
1251 else if (
isnan(max)) {
1256 r = random_real(obj, rnd, excl);
1258 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
1262 else if (max == 0.0 && !excl) {
1321 random_rand(
int argc,
VALUE *argv,
VALUE obj)
1323 VALUE v = rand_random(argc, argv, obj, get_rnd(obj));
1324 check_random_number(v, argv);
1340 if (!
NIL_P(v))
return rand_int(obj, rnd, v, 1);
1344 const double max = float_value(v);
1349 double r = random_real(obj, rnd,
TRUE);
1350 if (max > 0.0) r *= max;
1354 return rand_range(obj, rnd, vmax);
1358 rand_random_number(
int argc,
VALUE *argv,
VALUE obj)
1361 VALUE v = rand_random(argc, argv, obj, rnd);
1362 if (
NIL_P(v)) v = rand_random(0, 0, obj, rnd);
1363 else if (!v) invalid_argument(argv[0]);
1397 r2 = get_rnd(other);
1443 if (v !=
Qfalse)
return v;
1446 v = rand_int(
Qnil, rnd, vmax, 0);
1447 if (!
NIL_P(v))
return v;
1462 random_s_rand(
int argc,
VALUE *argv,
VALUE obj)
1464 VALUE v = rand_random(argc, argv,
Qnil, rand_start(&default_rand));
1465 check_random_number(v, argv);
1469 #define SIP_HASH_STREAMING 0 1470 #define sip_hash13 ruby_sip_hash13 1471 #if !defined _WIN32 && !defined BYTE_ORDER 1472 # ifdef WORDS_BIGENDIAN 1473 # define BYTE_ORDER BIG_ENDIAN 1475 # define BYTE_ORDER LITTLE_ENDIAN 1477 # ifndef LITTLE_ENDIAN 1478 # define LITTLE_ENDIAN 1234 1481 # define BIG_ENDIAN 4321 1497 init_seed(
struct MT *mt)
1501 for (i = 0; i <
numberof(seed.u32); ++i)
1502 seed.u32[i] = genrand_int32(mt);
1515 #ifdef HAVE_UINT64_T 1543 init_randomseed(
struct MT *mt)
1557 Init_Random_default(
void)
1560 struct MT *mt = &r->
mt;
1564 r->
seed = init_randomseed(mt);
1622 VALUE rand_default = Init_Random_default();
int rb_bigzero_p(VALUE x)
VALUE rb_check_to_float(VALUE)
Tries to convert an object into Float.
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
int gettimeofday(struct timeval *, struct timezone *)
#define RUBY_TYPED_FREE_IMMEDIATELY
void rb_update_max_fd(int fd)
#define INTEGER_PACK_LSWORD_FIRST
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
#define type_roomof(x, y)
VALUE rb_random_bytes(VALUE obj, long n)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
void rb_raise(VALUE exc, const char *fmt,...)
#define ATOMIC_PTR_CAS(var, oldval, val)
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define OBJ_INIT_COPY(obj, orig)
#define TypedData_Get_Struct(obj, type, data_type, sval)
VALUE rb_big_plus(VALUE x, VALUE y)
uint32_t u32[type_roomof(seed_keys_t, uint32_t)]
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
VALUE rb_ary_push(VALUE ary, VALUE item)
#define INTEGER_PACK_NATIVE_BYTE_ORDER
st_index_t st_hash_start(st_index_t h)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_include_module(VALUE klass, VALUE module)
void rb_gc_mark(VALUE ptr)
#define ATOMIC_PTR_EXCHANGE(var, val)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
RUBY_EXTERN void explicit_bzero(void *b, size_t len)
#define fill_random_bytes_syscall(seed, size, need_secure)
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
#define Data_Wrap_Struct(klass, mark, free, sval)
VALUE rb_to_float(VALUE)
Converts a Numeric object into Float.
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
#define RB_TYPE_P(obj, type)
#define ATOMIC_SET(var, val)
unsigned long long uint64_t
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
RUBY_EXTERN VALUE rb_cObject
int rb_num_negative_p(VALUE)
unsigned int rb_genrand_int32(void)
unsigned int rb_random_int32(VALUE obj)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
void rb_define_const(VALUE, const char *, VALUE)
rb_atomic_t cnt[RUBY_NSIG]
void Init_RandomSeedCore(void)
#define ALLOCV_N(type, v, n)
#define range(low, item, hi)
void rb_gc_register_mark_object(VALUE obj)
#define genrand_initialized(mt)
RUBY_EXTERN int isinf(double)
#define uninit_genrand(mt)
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
st_index_t rb_memhash(const void *ptr, long len)
int int_must_be_32bit_at_least[sizeof(int) *CHAR_BIT< 32 ? -1 :1]
VALUE rb_big_minus(VALUE x, VALUE y)
VALUE rb_funcallv_public(VALUE, ID, int, const VALUE *)
Calls a method.
#define RARRAY_CONST_PTR(a)
void rb_reset_random_seed(void)
unsigned char buf[MIME_BUF_SIZE]
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
#define domain_error(msg)
VALUE rb_eSystemCallError
#define INTEGER_PACK_MSWORD_FIRST
int memcmp(const void *s1, const void *s2, size_t len)
unsigned long rb_genrand_ulong_limited(unsigned long limit)
int rb_respond_to(VALUE, ID)
register unsigned int len
VALUE rb_define_module_under(VALUE outer, const char *name)
VALUE rb_big_uminus(VALUE x)
double rb_genrand_real(void)
VALUE rb_big_norm(VALUE x)
void rb_check_copyable(VALUE obj, VALUE orig)
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
#define fill_random_bytes_urandom(seed, size)
NORETURN(static void domain_error(void))
#define TypedData_Make_Struct(klass, type, data_type, sval)
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
#define rb_check_frozen(obj)
double rb_random_real(VALUE obj)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_to_int(VALUE)
Converts val into Integer.
st_index_t rb_hash_start(st_index_t h)
unsigned long rb_random_ulong_limited(VALUE obj, unsigned long limit)
VALUE rb_str_new(const char *, long)