Ruby
2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
|
Go to the documentation of this file.
19 #include <sys/types.h>
26 #if defined(HAVE_SYS_TIME_H)
32 #elif defined HAVE_SYS_SYSCALL_H
33 #include <sys/syscall.h>
44 #include <sys/param.h>
54 genrand_real(
struct MT *mt)
57 unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
58 return int_pair_to_real_exclusive(a, b);
66 return(a*67108864.0+b)*(1.0/9007199254740992.0);
73 genrand_real2(
struct MT *mt)
76 uint32_t a = genrand_int32(mt), b = genrand_int32(mt);
77 return int_pair_to_real_inclusive(a, b);
91 #define DEFAULT_SEED_CNT 4
101 struct MT *mt = &r->
mt;
111 return &rand_start(&default_rand)->
mt;
117 struct MT *mt = default_mt();
118 return genrand_int32(mt);
124 struct MT *mt = default_mt();
125 return genrand_real(mt);
128 #define SIZEOF_INT32 (31/CHAR_BIT + 1)
135 enum {dig_u = dig-32, dig_r64 = 64-dig, bmask = ~(~0u<<(dig_r64))};
136 #if defined HAVE_UINT128_T
137 const uint128_t m = ((uint128_t)1 << dig) | 1;
138 uint128_t x = ((uint128_t)a << 32) | b;
140 #elif defined HAVE_UINT64_T && !(defined _MSC_VER && _MSC_VER <= 1200)
142 (((
uint64_t)b + (a >> dig_u)) >> dig_r64);
146 b = (b >> dig_r64) + (((a >> dig_u) + (b & bmask)) >> dig_r64);
147 r = (
double)a * (1 << dig_u) + b;
149 return ldexp(r, -dig);
155 static ID id_rand, id_bytes;
160 random_mark(
void *
ptr)
166 random_free(
void *
ptr)
168 if (
ptr != &default_rand)
173 random_memsize(
const void *
ptr)
193 return rand_start(
ptr);
200 return rand_start(&default_rand);
217 rand_init(
struct MT *mt,
VALUE seed)
235 init_genrand(mt,
buf[0]);
238 if (sign != 2 &&
buf[
len-1] == 1)
240 init_by_array(mt,
buf, (
int)
len);
264 vseed = random_seed(
obj);
271 rnd->
seed = rand_init(&rnd->
mt, vseed);
275 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int32_t))
277 #if defined(S_ISCHR) && !defined(DOSISH)
278 # define USE_DEV_URANDOM 1
280 # define USE_DEV_URANDOM 0
304 if (fd < 0)
return -1;
308 ret =
read(fd, ((
char*)seed) + offset,
size - offset);
314 }
while (offset <
size);
320 # define fill_random_bytes_urandom(seed, size) -1
323 #if defined HAVE_GETRANDOM
324 # include <sys/random.h>
325 #elif defined __linux__ && defined __NR_getrandom
326 # include <linux/random.h>
328 # ifndef GRND_NONBLOCK
329 # define GRND_NONBLOCK 0x0001
331 # define getrandom(ptr, size, flags) \
332 (ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
333 # define HAVE_GETRANDOM 1
337 #elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
338 #include <Security/Security.h>
343 int status = SecRandomCopyBytes(kSecRandomDefault,
size, seed);
345 if (status != errSecSuccess) {
347 CFStringRef s = SecCopyErrorMessageString(status,
NULL);
348 const char *m = s ? CFStringGetCStringPtr(s, kCFStringEncodingUTF8) :
NULL;
349 fprintf(
stderr,
"SecRandomCopyBytes failed: %d: %s\n", status,
357 #elif defined(HAVE_ARC4RANDOM_BUF)
361 #if (defined(__OpenBSD__) && OpenBSD >= 201411) || \
362 (defined(__NetBSD__) && __NetBSD_Version__ >= 700000000) || \
363 (defined(__FreeBSD__) && __FreeBSD_version >= 1200079)
370 #elif defined(_WIN32)
372 release_crypt(
void *p)
375 if (prov && prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
376 CryptReleaseContext(prov, 0);
383 static HCRYPTPROV perm_prov;
384 HCRYPTPROV prov = perm_prov, old_prov;
386 if (!CryptAcquireContext(&prov,
NULL,
NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
387 prov = (HCRYPTPROV)INVALID_HANDLE_VALUE;
391 if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
396 if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
397 CryptReleaseContext(prov, 0);
402 if (prov == (HCRYPTPROV)INVALID_HANDLE_VALUE)
return -1;
403 CryptGenRandom(prov,
size, seed);
406 #elif defined HAVE_GETRANDOM
415 flags = GRND_NONBLOCK;
418 ssize_t ret = getrandom(((
char*)seed) + offset,
size - offset, flags);
424 }
while (offset <
size);
430 # define fill_random_bytes_syscall(seed, size, need_secure) -1
437 if (ret == 0)
return ret;
441 #define fill_random_bytes ruby_fill_random_bytes
447 #if defined HAVE_CLOCK_GETTIME
449 #elif defined HAVE_GETTIMEOFDAY
452 size_t len =
cnt *
sizeof(*seed);
458 #if defined HAVE_CLOCK_GETTIME
460 seed[0] ^= tv.tv_nsec;
461 #elif defined HAVE_GETTIMEOFDAY
469 seed[2] ^=
getpid() ^ (
n++ << 16);
471 #if SIZEOF_VOIDP > SIZEOF_INT
532 if (
n == 0)
return buf;
568 rnd2 = get_rnd(orig);
577 mt_state(
const struct MT *mt)
580 sizeof(*mt->
state), 0,
589 return mt_state(&rnd->
mt);
596 return mt_state(&default_rand.
mt);
633 struct MT *mt = &rnd->
mt;
651 sizeof(*mt->
state), 0,
694 seed = random_seed(
obj);
700 r->
seed = rand_init(&r->
mt, seed);
706 make_mask(
unsigned long x)
720 limited_rand(
struct MT *mt,
unsigned long limit)
723 unsigned long val,
mask;
725 if (!limit)
return 0;
726 mask = make_mask(limit);
729 if (0xffffffff < limit) {
734 if ((
mask >> (
i * 32)) & 0xffffffff) {
735 val |= (
unsigned long)genrand_int32(mt) << (
i * 32);
746 val = genrand_int32(mt) &
mask;
747 }
while (limit < val);
752 limited_big_rand(
struct MT *mt,
VALUE limit)
761 uint32_t *tmp, *lim_array, *rnd_array;
768 rnd_array = tmp +
len;
775 for (
i =
len-1; 0 <=
i;
i--) {
780 rnd = genrand_int32(mt) &
mask;
809 return limited_rand(default_mt(), limit);
813 obj_random_bytes(
VALUE obj,
void *p,
long n)
831 return genrand_int32(&rnd->
mt);
840 obj_random_bytes(
obj, &x,
sizeof(x));
841 return (
unsigned int)x;
843 return random_int32(rnd);
853 obj_random_bytes(
obj, x,
sizeof(x));
858 a = random_int32(rnd);
859 b = random_int32(rnd);
862 return int_pair_to_real_exclusive(a, b);
865 return int_pair_to_real_inclusive(a, b);
884 return genrand_real(&rnd->
mt);
888 ulong_to_num_plus_1(
unsigned long n)
903 if (!limit)
return 0;
905 const int w =
sizeof(limit) *
CHAR_BIT - nlz_long(limit);
906 const int n = w > 32 ?
sizeof(
unsigned long) :
sizeof(
uint32_t);
907 const unsigned long mask = ~(~0UL << w);
908 const unsigned long full =
909 (
size_t)
n >=
sizeof(
unsigned long) ? ~0UL :
911 unsigned long val, bits = 0, rest = 0;
915 obj_random_bytes(
obj, &
buf,
n);
923 }
while (limit < val);
926 return limited_rand(&rnd->
mt, limit);
934 VALUE lim = ulong_to_num_plus_1(limit);
945 return limited_rand(&rnd->
mt, limit);
963 rnd_array[0] &=
mask;
964 for (
i = 0;
i <
len; ++
i) {
965 if (lim_array[
i] < rnd_array[
i])
967 if (rnd_array[
i] < lim_array[
i])
974 return limited_big_rand(&rnd->
mt, vmax);
1003 r = genrand_int32(&rnd->
mt);
1011 r = genrand_int32(&rnd->
mt);
1025 return obj_random_bytes(
obj,
NULL,
n);
1027 return genrand_bytes(rnd,
n);
1049 if (begp) *begp = beg;
1051 if (endp) *endp = end;
1064 if (!max)
return Qnil;
1066 if (restrictive)
return Qnil;
1069 r = random_ulong_limited(
obj, rnd, (
unsigned long)max - 1);
1076 if (restrictive)
return Qnil;
1082 if (max == -1)
return Qnil;
1083 r = random_ulong_limited(
obj, rnd, max);
1086 ret = random_ulong_limited_big(
obj, rnd, vmax);
1101 invalid_argument(
VALUE arg0)
1114 invalid_argument(
argv[0]);
1119 static inline double
1135 if ((
v = vmax = range_values(
range, &beg, &end, &excl)) ==
Qfalse)
1144 if ((max =
FIX2LONG(vmax) - excl) >= 0) {
1145 unsigned long r = random_ulong_limited(
obj, rnd, (
unsigned long)max);
1155 v = random_ulong_limited_big(
obj, rnd, vmax);
1168 else if (
isnan(max)) {
1173 r = random_real(
obj, rnd, excl);
1175 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
1179 else if (max == 0.0 && !excl) {
1241 check_random_number(
v,
argv);
1257 if (!
NIL_P(
v))
return rand_int(
obj, rnd,
v, 1);
1261 const double max = float_value(
v);
1266 double r = random_real(
obj, rnd,
TRUE);
1267 if (max > 0.0) r *= max;
1271 return rand_range(
obj, rnd, vmax);
1289 if (
NIL_P(
v))
v = rand_random(0, 0,
obj, rnd);
1290 else if (!
v) invalid_argument(
argv[0]);
1324 r2 = get_rnd(other);
1326 if ((
r1->mt.next -
r1->mt.state) != (
r2->mt.next -
r2->mt.state))
return Qfalse;
1327 if (
r1->mt.left !=
r2->mt.left)
return Qfalse;
1373 v = rand_int(
Qnil, rnd, vmax, 0);
1392 check_random_number(
v,
argv);
1396 #define SIP_HASH_STREAMING 0
1397 #define sip_hash13 ruby_sip_hash13
1398 #if !defined _WIN32 && !defined BYTE_ORDER
1399 # ifdef WORDS_BIGENDIAN
1400 # define BYTE_ORDER BIG_ENDIAN
1402 # define BYTE_ORDER LITTLE_ENDIAN
1404 # ifndef LITTLE_ENDIAN
1405 # define LITTLE_ENDIAN 1234
1408 # define BIG_ENDIAN 4321
1424 init_seed(
struct MT *mt)
1429 seed.u32[
i] = genrand_int32(mt);
1443 #ifdef HAVE_UINT64_T
1471 init_randomseed(
struct MT *mt)
1488 struct MT *mt = &r->
mt;
1492 r->
seed = init_randomseed(mt);
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
#define TypedData_Make_Struct(klass, type, data_type, sval)
void rb_include_module(VALUE klass, VALUE module)
RUBY_EXTERN void explicit_bzero(void *b, size_t len)
#define range(low, item, hi)
#define ATOMIC_PTR_EXCHANGE(var, val)
void rb_gc_register_mark_object(VALUE obj)
VALUE rb_define_module_under(VALUE outer, const char *name)
void rb_reset_random_seed(void)
#define fill_random_bytes_urandom(seed, size)
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
VALUE rb_funcallv_public(VALUE, ID, int, const VALUE *)
Calls a method.
#define type_roomof(x, y)
double rb_random_real(VALUE obj)
#define RB_TYPE_P(obj, type)
int rb_num_negative_p(VALUE)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
unsigned long long uint64_t
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
#define Data_Wrap_Struct(klass, mark, free, sval)
#define ATOMIC_PTR_CAS(var, oldval, val)
#define ATOMIC_SET(var, val)
NO_SANITIZE("unsigned-integer-overflow", extern st_index_t rb_hash_start(st_index_t h))
int rb_bigzero_p(VALUE x)
VALUE rb_big_uminus(VALUE x)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_to_float(VALUE)
Converts a Numeric object into Float.
#define INTEGER_PACK_MSWORD_FIRST
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
#define rb_check_frozen(obj)
#define ALLOCV_N(type, v, n)
NORETURN(static void domain_error(void))
unsigned int rb_random_int32(VALUE obj)
double rb_genrand_real(void)
uint32_t u32[type_roomof(seed_keys_t, uint32_t)]
VALUE rb_ary_push(VALUE ary, VALUE item)
void rb_update_max_fd(int fd)
rb_atomic_t cnt[RUBY_NSIG]
#define RARRAY_AREF(a, i)
#define TypedData_Wrap_Struct(klass, data_type, sval)
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
#define INTEGER_PACK_NATIVE_BYTE_ORDER
#define fill_random_bytes
VALUE rb_random_bytes(VALUE obj, long n)
#define genrand_initialized(mt)
VALUE rb_big_minus(VALUE x, VALUE y)
#define fill_random_bytes_syscall(seed, size, need_secure)
VALUE rb_to_int(VALUE)
Converts val into Integer.
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
int memcmp(const void *s1, const void *s2, size_t len)
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
int int_must_be_32bit_at_least[sizeof(int) *CHAR_BIT< 32 ? -1 :1]
unsigned int rb_genrand_int32(void)
RUBY_EXTERN VALUE rb_cObject
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
unsigned char buf[MIME_BUF_SIZE]
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define OBJ_INIT_COPY(obj, orig)
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
void Init_RandomSeedCore(void)
#define RUBY_TYPED_FREE_IMMEDIATELY
int clock_gettime(clockid_t, struct timespec *)
st_index_t rb_hash_start(st_index_t h)
VALUE rb_big_plus(VALUE x, VALUE y)
VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE)
void rb_define_const(VALUE, const char *, VALUE)
st_index_t rb_memhash(const void *ptr, long len)
VALUE rb_eSystemCallError
VALUE rb_big_norm(VALUE x)
void rb_gc_mark(VALUE ptr)
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
unsigned long rb_genrand_ulong_limited(unsigned long limit)
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 domain_error(msg)
#define uninit_genrand(mt)
#define INTEGER_PACK_LSWORD_FIRST
int ruby_fill_random_bytes(void *seed, size_t size, int need_secure)
int gettimeofday(struct timeval *, struct timezone *)
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
unsigned long rb_random_ulong_limited(VALUE obj, unsigned long limit)
VALUE rb_check_to_float(VALUE)
Tries to convert an object into Float.