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