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