13# include <AvailabilityMacros.h>
30#if defined(HAVE_SYS_TIME_H)
36#elif defined HAVE_SYS_SYSCALL_H
37#include <sys/syscall.h>
58genrand_real(
struct MT *mt)
61 unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
62 return int_pair_to_real_exclusive(a, b);
70 return(a*67108864.0+b)*(1.0/9007199254740992.0);
77genrand_real2(
struct MT *mt)
80 uint32_t a = genrand_int32(mt), b = genrand_int32(mt);
81 return int_pair_to_real_inclusive(a, b);
95#define DEFAULT_SEED_CNT 4
105 struct MT *mt = &r->
mt;
115 return &rand_start(&default_rand)->
mt;
121 struct MT *mt = default_mt();
122 return genrand_int32(mt);
128 struct MT *mt = default_mt();
129 return genrand_real(mt);
132#define SIZEOF_INT32 (31/CHAR_BIT + 1)
139 enum {dig_u = dig-32, dig_r64 = 64-dig, bmask = ~(~0u<<(dig_r64))};
140#if defined HAVE_UINT128_T
144#elif defined HAVE_UINT64_T && !(defined _MSC_VER && _MSC_VER <= 1200)
146 (((
uint64_t)b + (a >> dig_u)) >> dig_r64);
150 b = (b >> dig_r64) + (((a >> dig_u) + (b & bmask)) >> dig_r64);
151 r = (
double)a * (1 << dig_u) + b;
153 return ldexp(r, -dig);
159static ID id_rand, id_bytes;
164random_mark(
void *
ptr)
170random_free(
void *
ptr)
172 if (
ptr != &default_rand)
177random_memsize(
const void *
ptr)
197 return rand_start(
ptr);
204 return rand_start(&default_rand);
221rand_init(
struct MT *mt,
VALUE seed)
239 init_genrand(mt,
buf[0]);
242 if (sign != 2 &&
buf[
len-1] == 1)
244 init_by_array(mt,
buf, (
int)
len);
268 vseed = random_seed(
obj);
275 rnd->
seed = rand_init(&rnd->
mt, vseed);
279#define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int32_t))
281#if defined(S_ISCHR) && !defined(DOSISH)
282# define USE_DEV_URANDOM 1
284# define USE_DEV_URANDOM 0
308 if (fd < 0)
return -1;
312 ret =
read(fd, ((
char*)seed) + offset,
size - offset);
318 }
while (offset <
size);
324# define fill_random_bytes_urandom(seed, size) -1
327#if defined HAVE_GETRANDOM
328# include <sys/random.h>
329#elif defined __linux__ && defined __NR_getrandom
330# include <linux/random.h>
332# ifndef GRND_NONBLOCK
333# define GRND_NONBLOCK 0x0001
335# define getrandom(ptr, size, flags) \
336 (ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
337# define HAVE_GETRANDOM 1
341#elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
342#include <Security/Security.h>
347 int status = SecRandomCopyBytes(kSecRandomDefault,
size, seed);
349 if (status != errSecSuccess) {
351 CFStringRef s = SecCopyErrorMessageString(status,
NULL);
352 const char *m = s ? CFStringGetCStringPtr(s, kCFStringEncodingUTF8) :
NULL;
353 fprintf(
stderr,
"SecRandomCopyBytes failed: %d: %s\n", status,
361#elif defined(HAVE_ARC4RANDOM_BUF)
365#if (defined(__OpenBSD__) && OpenBSD >= 201411) || \
366 (defined(__NetBSD__) && __NetBSD_Version__ >= 700000000) || \
367 (defined(__FreeBSD__) && __FreeBSD_version >= 1200079)
376release_crypt(
void *p)
379 if (prov && prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
380 CryptReleaseContext(prov, 0);
387 static HCRYPTPROV perm_prov;
388 HCRYPTPROV prov = perm_prov, old_prov;
390 if (!CryptAcquireContext(&prov,
NULL,
NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
391 prov = (HCRYPTPROV)INVALID_HANDLE_VALUE;
395 if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
400 if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
401 CryptReleaseContext(prov, 0);
406 if (prov == (HCRYPTPROV)INVALID_HANDLE_VALUE)
return -1;
407 CryptGenRandom(prov,
size, seed);
410#elif defined HAVE_GETRANDOM
419 flags = GRND_NONBLOCK;
422 ssize_t ret = getrandom(((
char*)seed) + offset,
size - offset, flags);
428 }
while (offset <
size);
434# define fill_random_bytes_syscall(seed, size, need_secure) -1
441 if (ret == 0)
return ret;
445#define fill_random_bytes ruby_fill_random_bytes
451#if defined HAVE_CLOCK_GETTIME
453#elif defined HAVE_GETTIMEOFDAY
456 size_t len =
cnt *
sizeof(*seed);
462#if defined HAVE_CLOCK_GETTIME
465#elif defined HAVE_GETTIMEOFDAY
467 seed[0] ^= tv.tv_usec;
473 seed[2] ^=
getpid() ^ (
n++ << 16);
475#if SIZEOF_VOIDP > SIZEOF_INT
536 if (
n == 0)
return buf;
572 rnd2 = get_rnd(orig);
581mt_state(
const struct MT *mt)
584 sizeof(*mt->
state), 0,
593 return mt_state(&rnd->
mt);
600 return mt_state(&default_rand.
mt);
637 struct MT *mt = &rnd->
mt;
655 sizeof(*mt->
state), 0,
698 seed = random_seed(
obj);
704 r->
seed = rand_init(&r->
mt, seed);
710make_mask(
unsigned long x)
724limited_rand(
struct MT *mt,
unsigned long limit)
727 unsigned long val,
mask;
729 if (!limit)
return 0;
730 mask = make_mask(limit);
733 if (0xffffffff < limit) {
738 if ((
mask >> (
i * 32)) & 0xffffffff) {
739 val |= (
unsigned long)genrand_int32(mt) << (
i * 32);
750 val = genrand_int32(mt) &
mask;
751 }
while (limit < val);
756limited_big_rand(
struct MT *mt,
VALUE limit)
765 uint32_t *tmp, *lim_array, *rnd_array;
772 rnd_array = tmp +
len;
779 for (
i =
len-1; 0 <=
i;
i--) {
784 rnd = genrand_int32(mt) &
mask;
813 return limited_rand(default_mt(), limit);
817obj_random_bytes(
VALUE obj,
void *p,
long n)
835 return genrand_int32(&rnd->
mt);
844 obj_random_bytes(
obj, &x,
sizeof(x));
845 return (
unsigned int)x;
847 return random_int32(rnd);
857 obj_random_bytes(
obj, x,
sizeof(x));
862 a = random_int32(rnd);
863 b = random_int32(rnd);
866 return int_pair_to_real_exclusive(a, b);
869 return int_pair_to_real_inclusive(a, b);
888 return genrand_real(&rnd->
mt);
892ulong_to_num_plus_1(
unsigned long n)
907 if (!limit)
return 0;
909 const int w =
sizeof(limit) *
CHAR_BIT - nlz_long(limit);
910 const int n = w > 32 ?
sizeof(
unsigned long) :
sizeof(
uint32_t);
911 const unsigned long mask = ~(~0UL << w);
912 const unsigned long full =
913 (
size_t)
n >=
sizeof(
unsigned long) ? ~0UL :
915 unsigned long val, bits = 0, rest = 0;
919 obj_random_bytes(
obj, &
buf,
n);
927 }
while (limit < val);
930 return limited_rand(&rnd->
mt, limit);
938 VALUE lim = ulong_to_num_plus_1(limit);
949 return limited_rand(&rnd->
mt, limit);
967 rnd_array[0] &=
mask;
968 for (
i = 0;
i <
len; ++
i) {
969 if (lim_array[
i] < rnd_array[
i])
971 if (rnd_array[
i] < lim_array[
i])
978 return limited_big_rand(&rnd->
mt, vmax);
1007 r = genrand_int32(&rnd->
mt);
1015 r = genrand_int32(&rnd->
mt);
1029 return obj_random_bytes(
obj,
NULL,
n);
1031 return genrand_bytes(rnd,
n);
1053 if (begp) *begp = beg;
1055 if (endp) *endp = end;
1068 if (!max)
return Qnil;
1070 if (restrictive)
return Qnil;
1073 r = random_ulong_limited(
obj, rnd, (
unsigned long)max - 1);
1080 if (restrictive)
return Qnil;
1086 if (max == -1)
return Qnil;
1087 r = random_ulong_limited(
obj, rnd, max);
1090 ret = random_ulong_limited_big(
obj, rnd, vmax);
1105invalid_argument(
VALUE arg0)
1118 invalid_argument(
argv[0]);
1139 if ((
v = vmax = range_values(
range, &beg, &end, &excl)) ==
Qfalse)
1148 if ((max =
FIX2LONG(vmax) - excl) >= 0) {
1149 unsigned long r = random_ulong_limited(
obj, rnd, (
unsigned long)max);
1159 v = random_ulong_limited_big(
obj, rnd, vmax);
1172 else if (
isnan(max)) {
1177 r = random_real(
obj, rnd, excl);
1179 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
1183 else if (max == 0.0 && !excl) {
1245 check_random_number(
v,
argv);
1261 if (!
NIL_P(
v))
return rand_int(
obj, rnd,
v, 1);
1265 const double max = float_value(
v);
1270 double r = random_real(
obj, rnd,
TRUE);
1271 if (max > 0.0) r *= max;
1275 return rand_range(
obj, rnd, vmax);
1293 if (
NIL_P(
v))
v = rand_random(0, 0,
obj, rnd);
1294 else if (!
v) invalid_argument(
argv[0]);
1328 r2 = get_rnd(other);
1330 if ((
r1->mt.next -
r1->mt.state) != (
r2->mt.next -
r2->mt.state))
return Qfalse;
1331 if (
r1->mt.left !=
r2->mt.left)
return Qfalse;
1377 v = rand_int(
Qnil, rnd, vmax, 0);
1396 check_random_number(
v,
argv);
1400#define SIP_HASH_STREAMING 0
1401#define sip_hash13 ruby_sip_hash13
1402#if !defined _WIN32 && !defined BYTE_ORDER
1403# ifdef WORDS_BIGENDIAN
1404# define BYTE_ORDER BIG_ENDIAN
1406# define BYTE_ORDER LITTLE_ENDIAN
1408# ifndef LITTLE_ENDIAN
1409# define LITTLE_ENDIAN 1234
1412# define BIG_ENDIAN 4321
1428init_seed(
struct MT *mt)
1433 seed.u32[
i] = genrand_int32(mt);
1475init_randomseed(
struct MT *mt)
1492 struct MT *mt = &r->
mt;
1496 r->
seed = init_randomseed(mt);
#define range(low, item, hi)
void rb_include_module(VALUE, VALUE)
void rb_extend_object(VALUE, VALUE)
Extend the object with the module.
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
VALUE rb_define_module_under(VALUE, const char *)
VALUE rb_cObject
Object class.
void rb_raise(VALUE exc, const char *fmt,...)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
void rb_check_copyable(VALUE obj, VALUE orig)
VALUE rb_eSystemCallError
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_check_to_float(VALUE)
Tries to convert an object into Float.
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
VALUE rb_to_float(VALUE)
Converts a Numeric object into Float.
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
VALUE rb_to_int(VALUE)
Converts val into Integer.
#define domain_error(msg)
#define genrand_initialized(mt)
#define uninit_genrand(mt)
unsigned char buf[MIME_BUF_SIZE]
#define fill_random_bytes_syscall(seed, size, need_secure)
double rb_random_real(VALUE obj)
uint32_t u32[type_roomof(seed_keys_t, uint32_t)]
void Init_RandomSeedCore(void)
st_index_t rb_memhash(const void *ptr, long len)
void rb_reset_random_seed(void)
VALUE rb_random_bytes(VALUE obj, long n)
unsigned long rb_genrand_ulong_limited(unsigned long limit)
double rb_genrand_real(void)
unsigned long rb_random_ulong_limited(VALUE obj, unsigned long limit)
int ruby_fill_random_bytes(void *seed, size_t size, int need_secure)
NORETURN(static void domain_error(void))
NO_SANITIZE("unsigned-integer-overflow", extern st_index_t rb_hash_start(st_index_t h))
unsigned int rb_genrand_int32(void)
st_index_t rb_hash_start(st_index_t h)
int int_must_be_32bit_at_least[sizeof(int) *CHAR_BIT< 32 ? -1 :1]
#define fill_random_bytes_urandom(seed, size)
unsigned int rb_random_int32(VALUE obj)
#define fill_random_bytes
rb_atomic_t cnt[RUBY_NSIG]
int gettimeofday(struct timeval *, struct timezone *)