00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #include "ruby/ruby.h"
00063 #include "internal.h"
00064
00065 #include <limits.h>
00066 #ifdef HAVE_UNISTD_H
00067 #include <unistd.h>
00068 #endif
00069 #include <time.h>
00070 #include <sys/types.h>
00071 #include <sys/stat.h>
00072 #ifdef HAVE_FCNTL_H
00073 #include <fcntl.h>
00074 #endif
00075 #include <math.h>
00076 #include <errno.h>
00077 #if defined(HAVE_SYS_TIME_H)
00078 #include <sys/time.h>
00079 #endif
00080
00081 #ifdef _WIN32
00082 # if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0400
00083 # undef _WIN32_WINNT
00084 # define _WIN32_WINNT 0x400
00085 # undef __WINCRYPT_H__
00086 # endif
00087 #include <wincrypt.h>
00088 #endif
00089
00090 typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1];
00091
00092
00093 #define N 624
00094 #define M 397
00095 #define MATRIX_A 0x9908b0dfU
00096 #define UMASK 0x80000000U
00097 #define LMASK 0x7fffffffU
00098 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
00099 #define TWIST(u,v) ((MIXBITS((u),(v)) >> 1) ^ ((v)&1U ? MATRIX_A : 0U))
00100
00101 enum {MT_MAX_STATE = N};
00102
00103 struct MT {
00104
00105 unsigned int state[N];
00106 unsigned int *next;
00107 int left;
00108 };
00109
00110 #define genrand_initialized(mt) ((mt)->next != 0)
00111 #define uninit_genrand(mt) ((mt)->next = 0)
00112
00113
00114 static void
00115 init_genrand(struct MT *mt, unsigned int s)
00116 {
00117 int j;
00118 mt->state[0] = s & 0xffffffffU;
00119 for (j=1; j<N; j++) {
00120 mt->state[j] = (1812433253U * (mt->state[j-1] ^ (mt->state[j-1] >> 30)) + j);
00121
00122
00123
00124
00125 mt->state[j] &= 0xffffffff;
00126 }
00127 mt->left = 1;
00128 mt->next = mt->state + N;
00129 }
00130
00131
00132
00133
00134
00135 static void
00136 init_by_array(struct MT *mt, unsigned int init_key[], int key_length)
00137 {
00138 int i, j, k;
00139 init_genrand(mt, 19650218U);
00140 i=1; j=0;
00141 k = (N>key_length ? N : key_length);
00142 for (; k; k--) {
00143 mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1664525U))
00144 + init_key[j] + j;
00145 mt->state[i] &= 0xffffffffU;
00146 i++; j++;
00147 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
00148 if (j>=key_length) j=0;
00149 }
00150 for (k=N-1; k; k--) {
00151 mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1566083941U))
00152 - i;
00153 mt->state[i] &= 0xffffffffU;
00154 i++;
00155 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
00156 }
00157
00158 mt->state[0] = 0x80000000U;
00159 }
00160
00161 static void
00162 next_state(struct MT *mt)
00163 {
00164 unsigned int *p = mt->state;
00165 int j;
00166
00167 mt->left = N;
00168 mt->next = mt->state;
00169
00170 for (j=N-M+1; --j; p++)
00171 *p = p[M] ^ TWIST(p[0], p[1]);
00172
00173 for (j=M; --j; p++)
00174 *p = p[M-N] ^ TWIST(p[0], p[1]);
00175
00176 *p = p[M-N] ^ TWIST(p[0], mt->state[0]);
00177 }
00178
00179
00180 static unsigned int
00181 genrand_int32(struct MT *mt)
00182 {
00183
00184 unsigned int y;
00185
00186 if (--mt->left <= 0) next_state(mt);
00187 y = *mt->next++;
00188
00189
00190 y ^= (y >> 11);
00191 y ^= (y << 7) & 0x9d2c5680;
00192 y ^= (y << 15) & 0xefc60000;
00193 y ^= (y >> 18);
00194
00195 return y;
00196 }
00197
00198
00199 static double
00200 genrand_real(struct MT *mt)
00201 {
00202
00203 unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
00204 return(a*67108864.0+b)*(1.0/9007199254740992.0);
00205 }
00206
00207
00208 static double int_pair_to_real_inclusive(uint32_t a, uint32_t b);
00209 static double
00210 genrand_real2(struct MT *mt)
00211 {
00212
00213 uint32_t a = genrand_int32(mt), b = genrand_int32(mt);
00214 return int_pair_to_real_inclusive(a, b);
00215 }
00216
00217
00218
00219 #undef N
00220 #undef M
00221
00222 typedef struct {
00223 VALUE seed;
00224 struct MT mt;
00225 } rb_random_t;
00226
00227 #define DEFAULT_SEED_CNT 4
00228
00229 static rb_random_t default_rand;
00230
00231 static VALUE rand_init(struct MT *mt, VALUE vseed);
00232 static VALUE random_seed(void);
00233
00234 static rb_random_t *
00235 rand_start(rb_random_t *r)
00236 {
00237 struct MT *mt = &r->mt;
00238 if (!genrand_initialized(mt)) {
00239 r->seed = rand_init(mt, random_seed());
00240 }
00241 return r;
00242 }
00243
00244 static struct MT *
00245 default_mt(void)
00246 {
00247 return &rand_start(&default_rand)->mt;
00248 }
00249
00250 unsigned int
00251 rb_genrand_int32(void)
00252 {
00253 struct MT *mt = default_mt();
00254 return genrand_int32(mt);
00255 }
00256
00257 double
00258 rb_genrand_real(void)
00259 {
00260 struct MT *mt = default_mt();
00261 return genrand_real(mt);
00262 }
00263
00264 #define SIZEOF_INT32 (31/CHAR_BIT + 1)
00265
00266 static double
00267 int_pair_to_real_inclusive(uint32_t a, uint32_t b)
00268 {
00269 VALUE x;
00270 VALUE m;
00271 uint32_t xary[2], mary[2];
00272 double r;
00273
00274
00275 xary[0] = a;
00276 xary[1] = b;
00277 x = rb_integer_unpack(xary, 2, sizeof(uint32_t), 0,
00278 INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
00279 INTEGER_PACK_FORCE_BIGNUM);
00280
00281
00282 mary[0] = 0x00200000;
00283 mary[1] = 0x00000001;
00284 m = rb_integer_unpack(mary, 2, sizeof(uint32_t), 0,
00285 INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
00286 INTEGER_PACK_FORCE_BIGNUM);
00287
00288 x = rb_big_mul(x, m);
00289 if (FIXNUM_P(x)) {
00290 #if CHAR_BIT * SIZEOF_LONG > 64
00291 r = (double)(FIX2ULONG(x) >> 64);
00292 #else
00293 return 0.0;
00294 #endif
00295 }
00296 else {
00297 uint32_t uary[4];
00298 rb_integer_pack(x, uary, numberof(uary), sizeof(uint32_t), 0,
00299 INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
00300
00301 r = (double)uary[0] * (0x10000 * (double)0x10000) + (double)uary[1];
00302 }
00303 return ldexp(r, -53);
00304 }
00305
00306 VALUE rb_cRandom;
00307 #define id_minus '-'
00308 #define id_plus '+'
00309 static ID id_rand, id_bytes;
00310
00311
00312 static void
00313 random_mark(void *ptr)
00314 {
00315 rb_gc_mark(((rb_random_t *)ptr)->seed);
00316 }
00317
00318 static void
00319 random_free(void *ptr)
00320 {
00321 if (ptr != &default_rand)
00322 xfree(ptr);
00323 }
00324
00325 static size_t
00326 random_memsize(const void *ptr)
00327 {
00328 return ptr ? sizeof(rb_random_t) : 0;
00329 }
00330
00331 static const rb_data_type_t random_data_type = {
00332 "random",
00333 {
00334 random_mark,
00335 random_free,
00336 random_memsize,
00337 },
00338 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
00339 };
00340
00341 static rb_random_t *
00342 get_rnd(VALUE obj)
00343 {
00344 rb_random_t *ptr;
00345 TypedData_Get_Struct(obj, rb_random_t, &random_data_type, ptr);
00346 return ptr;
00347 }
00348
00349 static rb_random_t *
00350 try_get_rnd(VALUE obj)
00351 {
00352 if (obj == rb_cRandom) {
00353 return rand_start(&default_rand);
00354 }
00355 if (!rb_typeddata_is_kind_of(obj, &random_data_type)) return NULL;
00356 return DATA_PTR(obj);
00357 }
00358
00359
00360 static VALUE
00361 random_alloc(VALUE klass)
00362 {
00363 rb_random_t *rnd;
00364 VALUE obj = TypedData_Make_Struct(klass, rb_random_t, &random_data_type, rnd);
00365 rnd->seed = INT2FIX(0);
00366 return obj;
00367 }
00368
00369 static VALUE
00370 rand_init(struct MT *mt, VALUE vseed)
00371 {
00372 volatile VALUE seed;
00373 uint32_t buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0;
00374 size_t len;
00375 int sign;
00376
00377 seed = rb_to_int(vseed);
00378
00379 len = rb_absint_numwords(seed, 32, NULL);
00380 if (len > numberof(buf0))
00381 buf = ALLOC_N(unsigned int, len);
00382 sign = rb_integer_pack(seed, buf, len, sizeof(uint32_t), 0,
00383 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
00384 if (sign < 0)
00385 sign = -sign;
00386 if (len == 0) {
00387 buf[0] = 0;
00388 len = 1;
00389 }
00390 if (len <= 1) {
00391 init_genrand(mt, buf[0]);
00392 }
00393 else {
00394 if (sign != 2 && buf[len-1] == 1)
00395 len--;
00396 init_by_array(mt, buf, (int)len);
00397 }
00398 if (buf != buf0) xfree(buf);
00399 return seed;
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 static VALUE
00412 random_init(int argc, VALUE *argv, VALUE obj)
00413 {
00414 VALUE vseed;
00415 rb_random_t *rnd = get_rnd(obj);
00416
00417 if (argc == 0) {
00418 rb_check_frozen(obj);
00419 vseed = random_seed();
00420 }
00421 else {
00422 rb_scan_args(argc, argv, "01", &vseed);
00423 rb_check_copyable(obj, vseed);
00424 }
00425 rnd->seed = rand_init(&rnd->mt, vseed);
00426 return obj;
00427 }
00428
00429 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int32_t))
00430
00431 #if defined(S_ISCHR) && !defined(DOSISH)
00432 # define USE_DEV_URANDOM 1
00433 #else
00434 # define USE_DEV_URANDOM 0
00435 #endif
00436
00437 static void
00438 fill_random_seed(uint32_t seed[DEFAULT_SEED_CNT])
00439 {
00440 static int n = 0;
00441 struct timeval tv;
00442 #if USE_DEV_URANDOM
00443 int fd;
00444 struct stat statbuf;
00445 #elif defined(_WIN32)
00446 HCRYPTPROV prov;
00447 #endif
00448
00449 memset(seed, 0, DEFAULT_SEED_LEN);
00450
00451 #if USE_DEV_URANDOM
00452 if ((fd = rb_cloexec_open("/dev/urandom", O_RDONLY
00453 #ifdef O_NONBLOCK
00454 |O_NONBLOCK
00455 #endif
00456 #ifdef O_NOCTTY
00457 |O_NOCTTY
00458 #endif
00459 , 0)) >= 0) {
00460 rb_update_max_fd(fd);
00461 if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
00462 if (read(fd, seed, DEFAULT_SEED_LEN) < DEFAULT_SEED_LEN) {
00463 ;
00464 }
00465 }
00466 close(fd);
00467 }
00468 #elif defined(_WIN32)
00469 if (CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
00470 CryptGenRandom(prov, DEFAULT_SEED_LEN, (void *)seed);
00471 CryptReleaseContext(prov, 0);
00472 }
00473 #endif
00474
00475 gettimeofday(&tv, 0);
00476 seed[0] ^= tv.tv_usec;
00477 seed[1] ^= (unsigned int)tv.tv_sec;
00478 #if SIZEOF_TIME_T > SIZEOF_INT
00479 seed[0] ^= (unsigned int)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT);
00480 #endif
00481 seed[2] ^= getpid() ^ (n++ << 16);
00482 seed[3] ^= (unsigned int)(VALUE)&seed;
00483 #if SIZEOF_VOIDP > SIZEOF_INT
00484 seed[2] ^= (unsigned int)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT);
00485 #endif
00486 }
00487
00488 static VALUE
00489 make_seed_value(const uint32_t *ptr)
00490 {
00491 VALUE seed;
00492 size_t len;
00493 uint32_t buf[DEFAULT_SEED_CNT+1];
00494
00495 if (ptr[DEFAULT_SEED_CNT-1] <= 1) {
00496
00497 MEMCPY(buf, ptr, uint32_t, DEFAULT_SEED_CNT);
00498 buf[DEFAULT_SEED_CNT] = 1;
00499 ptr = buf;
00500 len = DEFAULT_SEED_CNT+1;
00501 }
00502 else {
00503 len = DEFAULT_SEED_CNT;
00504 }
00505
00506 seed = rb_integer_unpack(ptr, len, sizeof(uint32_t), 0,
00507 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
00508
00509 return seed;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 static VALUE
00521 random_seed(void)
00522 {
00523 uint32_t buf[DEFAULT_SEED_CNT];
00524 fill_random_seed(buf);
00525 return make_seed_value(buf);
00526 }
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 static VALUE
00543 random_get_seed(VALUE obj)
00544 {
00545 return get_rnd(obj)->seed;
00546 }
00547
00548
00549 static VALUE
00550 random_copy(VALUE obj, VALUE orig)
00551 {
00552 rb_random_t *rnd1, *rnd2;
00553 struct MT *mt;
00554
00555 if (!OBJ_INIT_COPY(obj, orig)) return obj;
00556
00557 rnd1 = get_rnd(obj);
00558 rnd2 = get_rnd(orig);
00559 mt = &rnd1->mt;
00560
00561 *rnd1 = *rnd2;
00562 mt->next = mt->state + numberof(mt->state) - mt->left + 1;
00563 return obj;
00564 }
00565
00566 static VALUE
00567 mt_state(const struct MT *mt)
00568 {
00569 return rb_integer_unpack(mt->state, numberof(mt->state),
00570 sizeof(*mt->state), 0,
00571 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
00572 }
00573
00574
00575 static VALUE
00576 random_state(VALUE obj)
00577 {
00578 rb_random_t *rnd = get_rnd(obj);
00579 return mt_state(&rnd->mt);
00580 }
00581
00582
00583 static VALUE
00584 random_s_state(VALUE klass)
00585 {
00586 return mt_state(&default_rand.mt);
00587 }
00588
00589
00590 static VALUE
00591 random_left(VALUE obj)
00592 {
00593 rb_random_t *rnd = get_rnd(obj);
00594 return INT2FIX(rnd->mt.left);
00595 }
00596
00597
00598 static VALUE
00599 random_s_left(VALUE klass)
00600 {
00601 return INT2FIX(default_rand.mt.left);
00602 }
00603
00604
00605 static VALUE
00606 random_dump(VALUE obj)
00607 {
00608 rb_random_t *rnd = get_rnd(obj);
00609 VALUE dump = rb_ary_new2(3);
00610
00611 rb_ary_push(dump, mt_state(&rnd->mt));
00612 rb_ary_push(dump, INT2FIX(rnd->mt.left));
00613 rb_ary_push(dump, rnd->seed);
00614
00615 return dump;
00616 }
00617
00618
00619 static VALUE
00620 random_load(VALUE obj, VALUE dump)
00621 {
00622 rb_random_t *rnd = get_rnd(obj);
00623 struct MT *mt = &rnd->mt;
00624 VALUE state, left = INT2FIX(1), seed = INT2FIX(0);
00625 const VALUE *ary;
00626 unsigned long x;
00627
00628 rb_check_copyable(obj, dump);
00629 Check_Type(dump, T_ARRAY);
00630 ary = RARRAY_CONST_PTR(dump);
00631 switch (RARRAY_LEN(dump)) {
00632 case 3:
00633 seed = ary[2];
00634 case 2:
00635 left = ary[1];
00636 case 1:
00637 state = ary[0];
00638 break;
00639 default:
00640 rb_raise(rb_eArgError, "wrong dump data");
00641 }
00642 rb_integer_pack(state, mt->state, numberof(mt->state),
00643 sizeof(*mt->state), 0,
00644 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
00645 x = NUM2ULONG(left);
00646 if (x > numberof(mt->state)) {
00647 rb_raise(rb_eArgError, "wrong value");
00648 }
00649 mt->left = (unsigned int)x;
00650 mt->next = mt->state + numberof(mt->state) - x + 1;
00651 rnd->seed = rb_to_int(seed);
00652
00653 return obj;
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 static VALUE
00680 rb_f_srand(int argc, VALUE *argv, VALUE obj)
00681 {
00682 VALUE seed, old;
00683 rb_random_t *r = &default_rand;
00684
00685 if (argc == 0) {
00686 seed = random_seed();
00687 }
00688 else {
00689 rb_scan_args(argc, argv, "01", &seed);
00690 }
00691 old = r->seed;
00692 r->seed = rand_init(&r->mt, seed);
00693
00694 return old;
00695 }
00696
00697 static unsigned long
00698 make_mask(unsigned long x)
00699 {
00700 x = x | x >> 1;
00701 x = x | x >> 2;
00702 x = x | x >> 4;
00703 x = x | x >> 8;
00704 x = x | x >> 16;
00705 #if 4 < SIZEOF_LONG
00706 x = x | x >> 32;
00707 #endif
00708 return x;
00709 }
00710
00711 static unsigned long
00712 limited_rand(struct MT *mt, unsigned long limit)
00713 {
00714
00715 int i;
00716 unsigned long val, mask;
00717
00718 if (!limit) return 0;
00719 mask = make_mask(limit);
00720 retry:
00721 val = 0;
00722 for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) {
00723 if ((mask >> (i * 32)) & 0xffffffff) {
00724 val |= (unsigned long)genrand_int32(mt) << (i * 32);
00725 val &= mask;
00726 if (limit < val)
00727 goto retry;
00728 }
00729 }
00730 return val;
00731 }
00732
00733 static VALUE
00734 limited_big_rand(struct MT *mt, VALUE limit)
00735 {
00736
00737
00738 uint32_t mask;
00739 long i;
00740 int boundary;
00741
00742 size_t len;
00743 uint32_t *tmp, *lim_array, *rnd_array;
00744 VALUE vtmp;
00745 VALUE val;
00746
00747 len = rb_absint_numwords(limit, 32, NULL);
00748 tmp = ALLOCV_N(uint32_t, vtmp, len*2);
00749 lim_array = tmp;
00750 rnd_array = tmp + len;
00751 rb_integer_pack(limit, lim_array, len, sizeof(uint32_t), 0,
00752 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
00753
00754 retry:
00755 mask = 0;
00756 boundary = 1;
00757 for (i = len-1; 0 <= i; i--) {
00758 uint32_t rnd;
00759 uint32_t lim = lim_array[i];
00760 mask = mask ? 0xffffffff : (uint32_t)make_mask(lim);
00761 if (mask) {
00762 rnd = genrand_int32(mt) & mask;
00763 if (boundary) {
00764 if (lim < rnd)
00765 goto retry;
00766 if (rnd < lim)
00767 boundary = 0;
00768 }
00769 }
00770 else {
00771 rnd = 0;
00772 }
00773 rnd_array[i] = rnd;
00774 }
00775 val = rb_integer_unpack(rnd_array, len, sizeof(uint32_t), 0,
00776 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
00777 ALLOCV_END(vtmp);
00778
00779 return val;
00780 }
00781
00782
00783
00784
00785
00786
00787
00788 unsigned long
00789 rb_genrand_ulong_limited(unsigned long limit)
00790 {
00791 return limited_rand(default_mt(), limit);
00792 }
00793
00794 unsigned int
00795 rb_random_int32(VALUE obj)
00796 {
00797 rb_random_t *rnd = try_get_rnd(obj);
00798 if (!rnd) {
00799 #if SIZEOF_LONG * CHAR_BIT > 32
00800 VALUE lim = ULONG2NUM(0x100000000UL);
00801 #elif defined HAVE_LONG_LONG
00802 VALUE lim = ULL2NUM((LONG_LONG)0xffffffff+1);
00803 #else
00804 VALUE lim = rb_big_plus(ULONG2NUM(0xffffffff), INT2FIX(1));
00805 #endif
00806 return (unsigned int)NUM2ULONG(rb_funcall2(obj, id_rand, 1, &lim));
00807 }
00808 return genrand_int32(&rnd->mt);
00809 }
00810
00811 double
00812 rb_random_real(VALUE obj)
00813 {
00814 rb_random_t *rnd = try_get_rnd(obj);
00815 if (!rnd) {
00816 VALUE v = rb_funcall2(obj, id_rand, 0, 0);
00817 double d = NUM2DBL(v);
00818 if (d < 0.0) {
00819 rb_raise(rb_eRangeError, "random number too small %g", d);
00820 }
00821 else if (d >= 1.0) {
00822 rb_raise(rb_eRangeError, "random number too big %g", d);
00823 }
00824 return d;
00825 }
00826 return genrand_real(&rnd->mt);
00827 }
00828
00829 static inline VALUE
00830 ulong_to_num_plus_1(unsigned long n)
00831 {
00832 #if HAVE_LONG_LONG
00833 return ULL2NUM((LONG_LONG)n+1);
00834 #else
00835 if (n >= ULONG_MAX) {
00836 return rb_big_plus(ULONG2NUM(n), INT2FIX(1));
00837 }
00838 return ULONG2NUM(n+1);
00839 #endif
00840 }
00841
00842 unsigned long
00843 rb_random_ulong_limited(VALUE obj, unsigned long limit)
00844 {
00845 rb_random_t *rnd = try_get_rnd(obj);
00846 if (!rnd) {
00847 extern int rb_num_negative_p(VALUE);
00848 VALUE lim = ulong_to_num_plus_1(limit);
00849 VALUE v = rb_to_int(rb_funcall2(obj, id_rand, 1, &lim));
00850 unsigned long r = NUM2ULONG(v);
00851 if (rb_num_negative_p(v)) {
00852 rb_raise(rb_eRangeError, "random number too small %ld", r);
00853 }
00854 if (r > limit) {
00855 rb_raise(rb_eRangeError, "random number too big %ld", r);
00856 }
00857 return r;
00858 }
00859 return limited_rand(&rnd->mt, limit);
00860 }
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870 static VALUE
00871 random_bytes(VALUE obj, VALUE len)
00872 {
00873 return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
00874 }
00875
00876 VALUE
00877 rb_random_bytes(VALUE obj, long n)
00878 {
00879 rb_random_t *rnd = try_get_rnd(obj);
00880 VALUE bytes;
00881 char *ptr;
00882 unsigned int r, i;
00883
00884 if (!rnd) {
00885 VALUE len = LONG2NUM(n);
00886 return rb_funcall2(obj, id_bytes, 1, &len);
00887 }
00888 bytes = rb_str_new(0, n);
00889 ptr = RSTRING_PTR(bytes);
00890 for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) {
00891 r = genrand_int32(&rnd->mt);
00892 i = SIZEOF_INT32;
00893 do {
00894 *ptr++ = (char)r;
00895 r >>= CHAR_BIT;
00896 } while (--i);
00897 }
00898 if (n > 0) {
00899 r = genrand_int32(&rnd->mt);
00900 do {
00901 *ptr++ = (char)r;
00902 r >>= CHAR_BIT;
00903 } while (--n);
00904 }
00905 return bytes;
00906 }
00907
00908 static VALUE
00909 range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
00910 {
00911 VALUE end, r;
00912
00913 if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse;
00914 if (endp) *endp = end;
00915 if (!rb_respond_to(end, id_minus)) return Qfalse;
00916 r = rb_funcall2(end, id_minus, 1, begp);
00917 if (NIL_P(r)) return Qfalse;
00918 return r;
00919 }
00920
00921 static VALUE
00922 rand_int(struct MT *mt, VALUE vmax, int restrictive)
00923 {
00924
00925 long max;
00926 unsigned long r;
00927
00928 if (FIXNUM_P(vmax)) {
00929 max = FIX2LONG(vmax);
00930 if (!max) return Qnil;
00931 if (max < 0) {
00932 if (restrictive) return Qnil;
00933 max = -max;
00934 }
00935 r = limited_rand(mt, (unsigned long)max - 1);
00936 return ULONG2NUM(r);
00937 }
00938 else {
00939 VALUE ret;
00940 if (rb_bigzero_p(vmax)) return Qnil;
00941 if (!RBIGNUM_SIGN(vmax)) {
00942 if (restrictive) return Qnil;
00943 vmax = rb_big_uminus(vmax);
00944 }
00945 vmax = rb_big_minus(vmax, INT2FIX(1));
00946 if (FIXNUM_P(vmax)) {
00947 max = FIX2LONG(vmax);
00948 if (max == -1) return Qnil;
00949 r = limited_rand(mt, max);
00950 return LONG2NUM(r);
00951 }
00952 ret = limited_big_rand(mt, vmax);
00953 RB_GC_GUARD(vmax);
00954 return ret;
00955 }
00956 }
00957
00958 static inline double
00959 float_value(VALUE v)
00960 {
00961 double x = RFLOAT_VALUE(v);
00962 if (isinf(x) || isnan(x)) {
00963 VALUE error = INT2FIX(EDOM);
00964 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
00965 }
00966 return x;
00967 }
00968
00969 static inline VALUE
00970 rand_range(struct MT* mt, VALUE range)
00971 {
00972 VALUE beg = Qundef, end = Qundef, vmax, v;
00973 int excl = 0;
00974
00975 if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse)
00976 return Qfalse;
00977 if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
00978 long max;
00979 vmax = v;
00980 v = Qnil;
00981 if (FIXNUM_P(vmax)) {
00982 fixnum:
00983 if ((max = FIX2LONG(vmax) - excl) >= 0) {
00984 unsigned long r = limited_rand(mt, (unsigned long)max);
00985 v = ULONG2NUM(r);
00986 }
00987 }
00988 else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
00989 vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
00990 if (FIXNUM_P(vmax)) {
00991 excl = 0;
00992 goto fixnum;
00993 }
00994 v = limited_big_rand(mt, vmax);
00995 }
00996 }
00997 else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
00998 int scale = 1;
00999 double max = RFLOAT_VALUE(v), mid = 0.5, r;
01000 if (isinf(max)) {
01001 double min = float_value(rb_to_float(beg)) / 2.0;
01002 max = float_value(rb_to_float(end)) / 2.0;
01003 scale = 2;
01004 mid = max + min;
01005 max -= min;
01006 }
01007 else {
01008 float_value(v);
01009 }
01010 v = Qnil;
01011 if (max > 0.0) {
01012 if (excl) {
01013 r = genrand_real(mt);
01014 }
01015 else {
01016 r = genrand_real2(mt);
01017 }
01018 if (scale > 1) {
01019 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
01020 }
01021 v = rb_float_new(r * max);
01022 }
01023 else if (max == 0.0 && !excl) {
01024 v = rb_float_new(0.0);
01025 }
01026 }
01027
01028 if (FIXNUM_P(beg) && FIXNUM_P(v)) {
01029 long x = FIX2LONG(beg) + FIX2LONG(v);
01030 return LONG2NUM(x);
01031 }
01032 switch (TYPE(v)) {
01033 case T_NIL:
01034 break;
01035 case T_BIGNUM:
01036 return rb_big_plus(v, beg);
01037 case T_FLOAT: {
01038 VALUE f = rb_check_to_float(beg);
01039 if (!NIL_P(f)) {
01040 return DBL2NUM(RFLOAT_VALUE(v) + RFLOAT_VALUE(f));
01041 }
01042 }
01043 default:
01044 return rb_funcall2(beg, id_plus, 1, &v);
01045 }
01046
01047 return v;
01048 }
01049
01050 static VALUE rand_random(int argc, VALUE *argv, rb_random_t *rnd);
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 static VALUE
01082 random_rand(int argc, VALUE *argv, VALUE obj)
01083 {
01084 return rand_random(argc, argv, get_rnd(obj));
01085 }
01086
01087 static VALUE
01088 rand_random(int argc, VALUE *argv, rb_random_t *rnd)
01089 {
01090 VALUE vmax, v;
01091
01092 if (argc == 0) {
01093 return rb_float_new(genrand_real(&rnd->mt));
01094 }
01095 else {
01096 rb_check_arity(argc, 0, 1);
01097 }
01098 vmax = argv[0];
01099 if (NIL_P(vmax)) {
01100 v = Qnil;
01101 }
01102 else if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
01103 v = rand_int(&rnd->mt, v, 1);
01104 }
01105 else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
01106 double max = float_value(v);
01107 if (max > 0.0)
01108 v = rb_float_new(max * genrand_real(&rnd->mt));
01109 else
01110 v = Qnil;
01111 }
01112 else if ((v = rand_range(&rnd->mt, vmax)) != Qfalse) {
01113
01114 }
01115 else {
01116 v = Qnil;
01117 (void)NUM2LONG(vmax);
01118 }
01119 if (NIL_P(v)) {
01120 VALUE mesg = rb_str_new_cstr("invalid argument - ");
01121 rb_str_append(mesg, rb_obj_as_string(argv[0]));
01122 rb_exc_raise(rb_exc_new3(rb_eArgError, mesg));
01123 }
01124
01125 return v;
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152 static VALUE
01153 random_equal(VALUE self, VALUE other)
01154 {
01155 rb_random_t *r1, *r2;
01156 if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse;
01157 r1 = get_rnd(self);
01158 r2 = get_rnd(other);
01159 if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse;
01160 if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse;
01161 if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse;
01162 if (r1->mt.left != r2->mt.left) return Qfalse;
01163 return Qtrue;
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197 static VALUE
01198 rb_f_rand(int argc, VALUE *argv, VALUE obj)
01199 {
01200 VALUE v, vmax, r;
01201 struct MT *mt = default_mt();
01202
01203 if (argc == 0) goto zero_arg;
01204 rb_scan_args(argc, argv, "01", &vmax);
01205 if (NIL_P(vmax)) goto zero_arg;
01206 if ((v = rand_range(mt, vmax)) != Qfalse) {
01207 return v;
01208 }
01209 vmax = rb_to_int(vmax);
01210 if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
01211 zero_arg:
01212 return DBL2NUM(genrand_real(mt));
01213 }
01214 return r;
01215 }
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 static VALUE
01226 random_s_rand(int argc, VALUE *argv, VALUE obj)
01227 {
01228 return rand_random(argc, argv, rand_start(&default_rand));
01229 }
01230
01231 #define SIP_HASH_STREAMING 0
01232 #define sip_hash24 ruby_sip_hash24
01233 #if !defined _WIN32 && !defined BYTE_ORDER
01234 # ifdef WORDS_BIGENDIAN
01235 # define BYTE_ORDER BIG_ENDIAN
01236 # else
01237 # define BYTE_ORDER LITTLE_ENDIAN
01238 # endif
01239 # ifndef LITTLE_ENDIAN
01240 # define LITTLE_ENDIAN 1234
01241 # endif
01242 # ifndef BIG_ENDIAN
01243 # define BIG_ENDIAN 4321
01244 # endif
01245 #endif
01246 #include "siphash.c"
01247
01248 static st_index_t hashseed;
01249 static union {
01250 uint8_t key[16];
01251 uint32_t u32[(16 * sizeof(uint8_t) - 1) / sizeof(uint32_t)];
01252 } sipseed;
01253
01254 static VALUE
01255 init_randomseed(struct MT *mt, uint32_t initial[DEFAULT_SEED_CNT])
01256 {
01257 VALUE seed;
01258 fill_random_seed(initial);
01259 init_by_array(mt, initial, DEFAULT_SEED_CNT);
01260 seed = make_seed_value(initial);
01261 memset(initial, 0, DEFAULT_SEED_LEN);
01262 return seed;
01263 }
01264
01265 void
01266 Init_RandomSeed(void)
01267 {
01268 rb_random_t *r = &default_rand;
01269 uint32_t initial[DEFAULT_SEED_CNT];
01270 struct MT *mt = &r->mt;
01271 VALUE seed = init_randomseed(mt, initial);
01272 int i;
01273
01274 hashseed = genrand_int32(mt);
01275 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8
01276 hashseed <<= 32;
01277 hashseed |= genrand_int32(mt);
01278 #endif
01279 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
01280 hashseed <<= 32;
01281 hashseed |= genrand_int32(mt);
01282 #endif
01283 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8
01284 hashseed <<= 32;
01285 hashseed |= genrand_int32(mt);
01286 #endif
01287
01288 for (i = 0; i < numberof(sipseed.u32); ++i)
01289 sipseed.u32[i] = genrand_int32(mt);
01290
01291 rb_global_variable(&r->seed);
01292 r->seed = seed;
01293 }
01294
01295 st_index_t
01296 rb_hash_start(st_index_t h)
01297 {
01298 return st_hash_start(hashseed + h);
01299 }
01300
01301 st_index_t
01302 rb_memhash(const void *ptr, long len)
01303 {
01304 sip_uint64_t h = sip_hash24(sipseed.key, ptr, len);
01305 #ifdef HAVE_UINT64_T
01306 return (st_index_t)h;
01307 #else
01308 return (st_index_t)(h.u32[0] ^ h.u32[1]);
01309 #endif
01310 }
01311
01312 static void
01313 Init_RandomSeed2(void)
01314 {
01315 VALUE seed = default_rand.seed;
01316
01317 if (RB_TYPE_P(seed, T_BIGNUM)) {
01318 rb_obj_reveal(seed, rb_cBignum);
01319 }
01320 }
01321
01322 void
01323 rb_reset_random_seed(void)
01324 {
01325 rb_random_t *r = &default_rand;
01326 uninit_genrand(&r->mt);
01327 r->seed = INT2FIX(0);
01328 }
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354 void
01355 Init_Random(void)
01356 {
01357 Init_RandomSeed2();
01358 rb_define_global_function("srand", rb_f_srand, -1);
01359 rb_define_global_function("rand", rb_f_rand, -1);
01360
01361 rb_cRandom = rb_define_class("Random", rb_cObject);
01362 rb_define_alloc_func(rb_cRandom, random_alloc);
01363 rb_define_method(rb_cRandom, "initialize", random_init, -1);
01364 rb_define_method(rb_cRandom, "rand", random_rand, -1);
01365 rb_define_method(rb_cRandom, "bytes", random_bytes, 1);
01366 rb_define_method(rb_cRandom, "seed", random_get_seed, 0);
01367 rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1);
01368 rb_define_private_method(rb_cRandom, "marshal_dump", random_dump, 0);
01369 rb_define_private_method(rb_cRandom, "marshal_load", random_load, 1);
01370 rb_define_private_method(rb_cRandom, "state", random_state, 0);
01371 rb_define_private_method(rb_cRandom, "left", random_left, 0);
01372 rb_define_method(rb_cRandom, "==", random_equal, 1);
01373
01374 {
01375 VALUE rand_default = TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand);
01376 rb_gc_register_mark_object(rand_default);
01377
01378 rb_define_const(rb_cRandom, "DEFAULT", rand_default);
01379 }
01380
01381 rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1);
01382 rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1);
01383 rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0);
01384 rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0);
01385 rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0);
01386
01387 id_rand = rb_intern("rand");
01388 id_bytes = rb_intern("bytes");
01389 }
01390