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
00077 #ifdef _WIN32
00078 # if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0400
00079 # undef _WIN32_WINNT
00080 # define _WIN32_WINNT 0x400
00081 # undef __WINCRYPT_H__
00082 # endif
00083 #include <wincrypt.h>
00084 #endif
00085
00086 typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1];
00087
00088
00089 #define N 624
00090 #define M 397
00091 #define MATRIX_A 0x9908b0dfU
00092 #define UMASK 0x80000000U
00093 #define LMASK 0x7fffffffU
00094 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
00095 #define TWIST(u,v) ((MIXBITS((u),(v)) >> 1) ^ ((v)&1U ? MATRIX_A : 0U))
00096
00097 enum {MT_MAX_STATE = N};
00098
00099 struct MT {
00100
00101 unsigned int state[N];
00102 unsigned int *next;
00103 int left;
00104 };
00105
00106 #define genrand_initialized(mt) ((mt)->next != 0)
00107 #define uninit_genrand(mt) ((mt)->next = 0)
00108
00109
00110 static void
00111 init_genrand(struct MT *mt, unsigned int s)
00112 {
00113 int j;
00114 mt->state[0] = s & 0xffffffffU;
00115 for (j=1; j<N; j++) {
00116 mt->state[j] = (1812433253U * (mt->state[j-1] ^ (mt->state[j-1] >> 30)) + j);
00117
00118
00119
00120
00121 mt->state[j] &= 0xffffffff;
00122 }
00123 mt->left = 1;
00124 mt->next = mt->state + N;
00125 }
00126
00127
00128
00129
00130
00131 static void
00132 init_by_array(struct MT *mt, unsigned int init_key[], int key_length)
00133 {
00134 int i, j, k;
00135 init_genrand(mt, 19650218U);
00136 i=1; j=0;
00137 k = (N>key_length ? N : key_length);
00138 for (; k; k--) {
00139 mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1664525U))
00140 + init_key[j] + j;
00141 mt->state[i] &= 0xffffffffU;
00142 i++; j++;
00143 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
00144 if (j>=key_length) j=0;
00145 }
00146 for (k=N-1; k; k--) {
00147 mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1566083941U))
00148 - i;
00149 mt->state[i] &= 0xffffffffU;
00150 i++;
00151 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
00152 }
00153
00154 mt->state[0] = 0x80000000U;
00155 }
00156
00157 static void
00158 next_state(struct MT *mt)
00159 {
00160 unsigned int *p = mt->state;
00161 int j;
00162
00163 mt->left = N;
00164 mt->next = mt->state;
00165
00166 for (j=N-M+1; --j; p++)
00167 *p = p[M] ^ TWIST(p[0], p[1]);
00168
00169 for (j=M; --j; p++)
00170 *p = p[M-N] ^ TWIST(p[0], p[1]);
00171
00172 *p = p[M-N] ^ TWIST(p[0], mt->state[0]);
00173 }
00174
00175
00176 static unsigned int
00177 genrand_int32(struct MT *mt)
00178 {
00179
00180 unsigned int y;
00181
00182 if (--mt->left <= 0) next_state(mt);
00183 y = *mt->next++;
00184
00185
00186 y ^= (y >> 11);
00187 y ^= (y << 7) & 0x9d2c5680;
00188 y ^= (y << 15) & 0xefc60000;
00189 y ^= (y >> 18);
00190
00191 return y;
00192 }
00193
00194
00195 static double
00196 genrand_real(struct MT *mt)
00197 {
00198
00199 unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
00200 return(a*67108864.0+b)*(1.0/9007199254740992.0);
00201 }
00202
00203
00204 static double int_pair_to_real_inclusive(unsigned int a, unsigned int b);
00205 static double
00206 genrand_real2(struct MT *mt)
00207 {
00208
00209 unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
00210 return int_pair_to_real_inclusive(a, b);
00211 }
00212
00213
00214
00215 #undef N
00216 #undef M
00217
00218
00219
00220 typedef struct {
00221 VALUE seed;
00222 struct MT mt;
00223 } rb_random_t;
00224
00225 #define DEFAULT_SEED_CNT 4
00226
00227 static rb_random_t default_rand;
00228
00229 static VALUE rand_init(struct MT *mt, VALUE vseed);
00230 static VALUE random_seed(void);
00231
00232 static rb_random_t *
00233 rand_start(rb_random_t *r)
00234 {
00235 struct MT *mt = &r->mt;
00236 if (!genrand_initialized(mt)) {
00237 r->seed = rand_init(mt, random_seed());
00238 }
00239 return r;
00240 }
00241
00242 static struct MT *
00243 default_mt(void)
00244 {
00245 return &rand_start(&default_rand)->mt;
00246 }
00247
00248 unsigned int
00249 rb_genrand_int32(void)
00250 {
00251 struct MT *mt = default_mt();
00252 return genrand_int32(mt);
00253 }
00254
00255 double
00256 rb_genrand_real(void)
00257 {
00258 struct MT *mt = default_mt();
00259 return genrand_real(mt);
00260 }
00261
00262 #define BDIGITS(x) (RBIGNUM_DIGITS(x))
00263 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
00264 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
00265 #define DIGSPERINT (SIZEOF_INT/SIZEOF_BDIGITS)
00266 #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
00267 #define BIGDN(x) RSHIFT((x),BITSPERDIG)
00268 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
00269 #define BDIGMAX ((BDIGIT)-1)
00270
00271 #define roomof(n, m) (int)(((n)+(m)-1) / (m))
00272 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00273 #define SIZEOF_INT32 (31/CHAR_BIT + 1)
00274
00275 static double
00276 int_pair_to_real_inclusive(unsigned int a, unsigned int b)
00277 {
00278 VALUE x = rb_big_new(roomof(64, BITSPERDIG), 1);
00279 VALUE m = rb_big_new(roomof(53, BITSPERDIG), 1);
00280 BDIGIT *xd = BDIGITS(x);
00281 int i = 0;
00282 double r;
00283
00284 xd[i++] = (BDIGIT)b;
00285 #if BITSPERDIG < 32
00286 xd[i++] = (BDIGIT)(b >> BITSPERDIG);
00287 #endif
00288 xd[i++] = (BDIGIT)a;
00289 #if BITSPERDIG < 32
00290 xd[i++] = (BDIGIT)(a >> BITSPERDIG);
00291 #endif
00292 xd = BDIGITS(m);
00293 #if BITSPERDIG < 53
00294 MEMZERO(xd, BDIGIT, roomof(53, BITSPERDIG) - 1);
00295 #endif
00296 xd[53 / BITSPERDIG] = 1 << 53 % BITSPERDIG;
00297 xd[0] |= 1;
00298 x = rb_big_mul(x, m);
00299 if (FIXNUM_P(x)) {
00300 #if CHAR_BIT * SIZEOF_LONG > 64
00301 r = (double)(FIX2ULONG(x) >> 64);
00302 #else
00303 return 0.0;
00304 #endif
00305 }
00306 else {
00307 #if 64 % BITSPERDIG == 0
00308 long len = RBIGNUM_LEN(x);
00309 xd = BDIGITS(x);
00310 MEMMOVE(xd, xd + 64 / BITSPERDIG, BDIGIT, len - 64 / BITSPERDIG);
00311 MEMZERO(xd + len - 64 / BITSPERDIG, BDIGIT, 64 / BITSPERDIG);
00312 r = rb_big2dbl(x);
00313 #else
00314 x = rb_big_rshift(x, INT2FIX(64));
00315 if (FIXNUM_P(x)) {
00316 r = (double)FIX2ULONG(x);
00317 }
00318 else {
00319 r = rb_big2dbl(x);
00320 }
00321 #endif
00322 }
00323 return ldexp(r, -53);
00324 }
00325
00326 VALUE rb_cRandom;
00327 static VALUE rb_Random_DEFAULT;
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
00462
00463
00464
00465
00466
00467
00468 static VALUE
00469 random_init(int argc, VALUE *argv, VALUE obj)
00470 {
00471 VALUE vseed;
00472 rb_random_t *rnd = get_rnd(obj);
00473
00474 if (argc == 0) {
00475 vseed = random_seed();
00476 }
00477 else {
00478 rb_scan_args(argc, argv, "01", &vseed);
00479 }
00480 rnd->seed = rand_init(&rnd->mt, vseed);
00481 return obj;
00482 }
00483
00484 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int))
00485
00486 #if defined(S_ISCHR) && !defined(DOSISH)
00487 # define USE_DEV_URANDOM 1
00488 #else
00489 # define USE_DEV_URANDOM 0
00490 #endif
00491
00492 static void
00493 fill_random_seed(unsigned int seed[DEFAULT_SEED_CNT])
00494 {
00495 static int n = 0;
00496 struct timeval tv;
00497 #if USE_DEV_URANDOM
00498 int fd;
00499 struct stat statbuf;
00500 #elif defined(_WIN32)
00501 HCRYPTPROV prov;
00502 #endif
00503
00504 memset(seed, 0, DEFAULT_SEED_LEN);
00505
00506 #if USE_DEV_URANDOM
00507 if ((fd = open("/dev/urandom", O_RDONLY
00508 #ifdef O_NONBLOCK
00509 |O_NONBLOCK
00510 #endif
00511 #ifdef O_NOCTTY
00512 |O_NOCTTY
00513 #endif
00514 )) >= 0) {
00515 rb_update_max_fd(fd);
00516 if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
00517 if (read(fd, seed, DEFAULT_SEED_LEN) < DEFAULT_SEED_LEN) {
00518 ;
00519 }
00520 }
00521 close(fd);
00522 }
00523 #elif defined(_WIN32)
00524 if (CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
00525 CryptGenRandom(prov, DEFAULT_SEED_LEN, (void *)seed);
00526 CryptReleaseContext(prov, 0);
00527 }
00528 #endif
00529
00530 gettimeofday(&tv, 0);
00531 seed[0] ^= tv.tv_usec;
00532 seed[1] ^= (unsigned int)tv.tv_sec;
00533 #if SIZEOF_TIME_T > SIZEOF_INT
00534 seed[0] ^= (unsigned int)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT);
00535 #endif
00536 seed[2] ^= getpid() ^ (n++ << 16);
00537 seed[3] ^= (unsigned int)(VALUE)&seed;
00538 #if SIZEOF_VOIDP > SIZEOF_INT
00539 seed[2] ^= (unsigned int)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT);
00540 #endif
00541 }
00542
00543 static VALUE
00544 make_seed_value(const void *ptr)
00545 {
00546 const long len = DEFAULT_SEED_LEN/SIZEOF_BDIGITS;
00547 BDIGIT *digits;
00548 NEWOBJ(big, struct RBignum);
00549 OBJSETUP(big, rb_cBignum, T_BIGNUM);
00550
00551 RBIGNUM_SET_SIGN(big, 1);
00552 rb_big_resize((VALUE)big, len + 1);
00553 digits = RBIGNUM_DIGITS(big);
00554
00555 MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN);
00556
00557
00558 digits[len] =
00559 #if SIZEOF_INT32 / SIZEOF_BDIGITS > 1
00560 digits[len-2] <= 1 && digits[len-1] == 0
00561 #else
00562 digits[len-1] <= 1
00563 #endif
00564 ? 1 : 0;
00565
00566 return rb_big_norm((VALUE)big);
00567 }
00568
00569
00570
00571
00572
00573
00574 static VALUE
00575 random_seed(void)
00576 {
00577 unsigned int buf[DEFAULT_SEED_CNT];
00578 fill_random_seed(buf);
00579 return make_seed_value(buf);
00580 }
00581
00582
00583
00584
00585
00586
00587 static VALUE
00588 random_get_seed(VALUE obj)
00589 {
00590 return get_rnd(obj)->seed;
00591 }
00592
00593
00594 static VALUE
00595 random_copy(VALUE obj, VALUE orig)
00596 {
00597 rb_random_t *rnd1 = get_rnd(obj);
00598 rb_random_t *rnd2 = get_rnd(orig);
00599 struct MT *mt = &rnd1->mt;
00600
00601 *rnd1 = *rnd2;
00602 mt->next = mt->state + numberof(mt->state) - mt->left + 1;
00603 return obj;
00604 }
00605
00606 static VALUE
00607 mt_state(const struct MT *mt)
00608 {
00609 VALUE bigo = rb_big_new(sizeof(mt->state) / sizeof(BDIGIT), 1);
00610 BDIGIT *d = RBIGNUM_DIGITS(bigo);
00611 int i;
00612
00613 for (i = 0; i < numberof(mt->state); ++i) {
00614 unsigned int x = mt->state[i];
00615 #if SIZEOF_BDIGITS < SIZEOF_INT32
00616 int j;
00617 for (j = 0; j < SIZEOF_INT32 / SIZEOF_BDIGITS; ++j) {
00618 *d++ = BIGLO(x);
00619 x = BIGDN(x);
00620 }
00621 #else
00622 *d++ = (BDIGIT)x;
00623 #endif
00624 }
00625 return rb_big_norm(bigo);
00626 }
00627
00628
00629 static VALUE
00630 random_state(VALUE obj)
00631 {
00632 rb_random_t *rnd = get_rnd(obj);
00633 return mt_state(&rnd->mt);
00634 }
00635
00636
00637 static VALUE
00638 random_s_state(VALUE klass)
00639 {
00640 return mt_state(&default_rand.mt);
00641 }
00642
00643
00644 static VALUE
00645 random_left(VALUE obj)
00646 {
00647 rb_random_t *rnd = get_rnd(obj);
00648 return INT2FIX(rnd->mt.left);
00649 }
00650
00651
00652 static VALUE
00653 random_s_left(VALUE klass)
00654 {
00655 return INT2FIX(default_rand.mt.left);
00656 }
00657
00658
00659 static VALUE
00660 random_dump(VALUE obj)
00661 {
00662 rb_random_t *rnd = get_rnd(obj);
00663 VALUE dump = rb_ary_new2(3);
00664
00665 rb_ary_push(dump, mt_state(&rnd->mt));
00666 rb_ary_push(dump, INT2FIX(rnd->mt.left));
00667 rb_ary_push(dump, rnd->seed);
00668
00669 return dump;
00670 }
00671
00672
00673 static VALUE
00674 random_load(VALUE obj, VALUE dump)
00675 {
00676 rb_random_t *rnd = get_rnd(obj);
00677 struct MT *mt = &rnd->mt;
00678 VALUE state, left = INT2FIX(1), seed = INT2FIX(0);
00679 VALUE *ary;
00680 unsigned long x;
00681
00682 Check_Type(dump, T_ARRAY);
00683 ary = RARRAY_PTR(dump);
00684 switch (RARRAY_LEN(dump)) {
00685 case 3:
00686 seed = ary[2];
00687 case 2:
00688 left = ary[1];
00689 case 1:
00690 state = ary[0];
00691 break;
00692 default:
00693 rb_raise(rb_eArgError, "wrong dump data");
00694 }
00695 memset(mt->state, 0, sizeof(mt->state));
00696 if (FIXNUM_P(state)) {
00697 x = FIX2ULONG(state);
00698 mt->state[0] = (unsigned int)x;
00699 #if SIZEOF_LONG / SIZEOF_INT >= 2
00700 mt->state[1] = (unsigned int)(x >> BITSPERDIG);
00701 #endif
00702 #if SIZEOF_LONG / SIZEOF_INT >= 3
00703 mt->state[2] = (unsigned int)(x >> 2 * BITSPERDIG);
00704 #endif
00705 #if SIZEOF_LONG / SIZEOF_INT >= 4
00706 mt->state[3] = (unsigned int)(x >> 3 * BITSPERDIG);
00707 #endif
00708 }
00709 else {
00710 BDIGIT *d;
00711 long len;
00712 Check_Type(state, T_BIGNUM);
00713 len = RBIGNUM_LEN(state);
00714 if (len > roomof(sizeof(mt->state), SIZEOF_BDIGITS)) {
00715 len = roomof(sizeof(mt->state), SIZEOF_BDIGITS);
00716 }
00717 #if SIZEOF_BDIGITS < SIZEOF_INT
00718 else if (len % DIGSPERINT) {
00719 d = RBIGNUM_DIGITS(state) + len;
00720 # if DIGSPERINT == 2
00721 --len;
00722 x = *--d;
00723 # else
00724 x = 0;
00725 do {
00726 x = (x << BITSPERDIG) | *--d;
00727 } while (--len % DIGSPERINT);
00728 # endif
00729 mt->state[len / DIGSPERINT] = (unsigned int)x;
00730 }
00731 #endif
00732 if (len > 0) {
00733 d = BDIGITS(state) + len;
00734 do {
00735 --len;
00736 x = *--d;
00737 # if DIGSPERINT == 2
00738 --len;
00739 x = (x << BITSPERDIG) | *--d;
00740 # elif SIZEOF_BDIGITS < SIZEOF_INT
00741 do {
00742 x = (x << BITSPERDIG) | *--d;
00743 } while (--len % DIGSPERINT);
00744 # endif
00745 mt->state[len / DIGSPERINT] = (unsigned int)x;
00746 } while (len > 0);
00747 }
00748 }
00749 x = NUM2ULONG(left);
00750 if (x > numberof(mt->state)) {
00751 rb_raise(rb_eArgError, "wrong value");
00752 }
00753 mt->left = (unsigned int)x;
00754 mt->next = mt->state + numberof(mt->state) - x + 1;
00755 rnd->seed = rb_to_int(seed);
00756
00757 return obj;
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 static VALUE
00775 rb_f_srand(int argc, VALUE *argv, VALUE obj)
00776 {
00777 VALUE seed, old;
00778 rb_random_t *r = &default_rand;
00779
00780 rb_secure(4);
00781 if (argc == 0) {
00782 seed = random_seed();
00783 }
00784 else {
00785 rb_scan_args(argc, argv, "01", &seed);
00786 }
00787 old = r->seed;
00788 r->seed = rand_init(&r->mt, seed);
00789
00790 return old;
00791 }
00792
00793 static unsigned long
00794 make_mask(unsigned long x)
00795 {
00796 x = x | x >> 1;
00797 x = x | x >> 2;
00798 x = x | x >> 4;
00799 x = x | x >> 8;
00800 x = x | x >> 16;
00801 #if 4 < SIZEOF_LONG
00802 x = x | x >> 32;
00803 #endif
00804 return x;
00805 }
00806
00807 static unsigned long
00808 limited_rand(struct MT *mt, unsigned long limit)
00809 {
00810
00811 int i;
00812 unsigned long val, mask;
00813
00814 if (!limit) return 0;
00815 mask = make_mask(limit);
00816 retry:
00817 val = 0;
00818 for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) {
00819 if ((mask >> (i * 32)) & 0xffffffff) {
00820 val |= (unsigned long)genrand_int32(mt) << (i * 32);
00821 val &= mask;
00822 if (limit < val)
00823 goto retry;
00824 }
00825 }
00826 return val;
00827 }
00828
00829 static VALUE
00830 limited_big_rand(struct MT *mt, struct RBignum *limit)
00831 {
00832
00833 unsigned long mask, lim, rnd;
00834 struct RBignum *val;
00835 long i, len;
00836 int boundary;
00837
00838 len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4;
00839 val = (struct RBignum *)rb_big_clone((VALUE)limit);
00840 RBIGNUM_SET_SIGN(val, 1);
00841 #if SIZEOF_BDIGITS == 2
00842 # define BIG_GET32(big,i) \
00843 (RBIGNUM_DIGITS(big)[(i)*2] | \
00844 ((i)*2+1 < RBIGNUM_LEN(big) ? \
00845 (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) : \
00846 0))
00847 # define BIG_SET32(big,i,d) \
00848 ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \
00849 ((i)*2+1 < RBIGNUM_LEN(big) ? \
00850 (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) : \
00851 0))
00852 #else
00853
00854 # define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[(i)])
00855 # define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[(i)] = (d))
00856 #endif
00857 retry:
00858 mask = 0;
00859 boundary = 1;
00860 for (i = len-1; 0 <= i; i--) {
00861 lim = BIG_GET32(limit, i);
00862 mask = mask ? 0xffffffff : make_mask(lim);
00863 if (mask) {
00864 rnd = genrand_int32(mt) & mask;
00865 if (boundary) {
00866 if (lim < rnd)
00867 goto retry;
00868 if (rnd < lim)
00869 boundary = 0;
00870 }
00871 }
00872 else {
00873 rnd = 0;
00874 }
00875 BIG_SET32(val, i, (BDIGIT)rnd);
00876 }
00877 return rb_big_norm((VALUE)val);
00878 }
00879
00880
00881
00882
00883
00884
00885
00886 unsigned long
00887 rb_genrand_ulong_limited(unsigned long limit)
00888 {
00889 return limited_rand(default_mt(), limit);
00890 }
00891
00892 unsigned int
00893 rb_random_int32(VALUE obj)
00894 {
00895 rb_random_t *rnd = try_get_rnd(obj);
00896 if (!rnd) {
00897 #if SIZEOF_LONG * CHAR_BIT > 32
00898 VALUE lim = ULONG2NUM(0x100000000);
00899 #elif defined HAVE_LONG_LONG
00900 VALUE lim = ULL2NUM((LONG_LONG)0xffffffff+1);
00901 #else
00902 VALUE lim = rb_big_plus(ULONG2NUM(0xffffffff), INT2FIX(1));
00903 #endif
00904 return (unsigned int)NUM2ULONG(rb_funcall2(obj, id_rand, 1, &lim));
00905 }
00906 return genrand_int32(&rnd->mt);
00907 }
00908
00909 double
00910 rb_random_real(VALUE obj)
00911 {
00912 rb_random_t *rnd = try_get_rnd(obj);
00913 if (!rnd) {
00914 VALUE v = rb_funcall2(obj, id_rand, 0, 0);
00915 double d = NUM2DBL(v);
00916 if (d < 0.0 || d >= 1.0) {
00917 rb_raise(rb_eRangeError, "random number too big %g", d);
00918 }
00919 return d;
00920 }
00921 return genrand_real(&rnd->mt);
00922 }
00923
00924
00925
00926
00927
00928
00929
00930 static VALUE
00931 random_bytes(VALUE obj, VALUE len)
00932 {
00933 return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
00934 }
00935
00936 VALUE
00937 rb_random_bytes(VALUE obj, long n)
00938 {
00939 rb_random_t *rnd = try_get_rnd(obj);
00940 VALUE bytes;
00941 char *ptr;
00942 unsigned int r, i;
00943
00944 if (!rnd) {
00945 VALUE len = LONG2NUM(n);
00946 return rb_funcall2(obj, id_bytes, 1, &len);
00947 }
00948 bytes = rb_str_new(0, n);
00949 ptr = RSTRING_PTR(bytes);
00950 for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) {
00951 r = genrand_int32(&rnd->mt);
00952 i = SIZEOF_INT32;
00953 do {
00954 *ptr++ = (char)r;
00955 r >>= CHAR_BIT;
00956 } while (--i);
00957 }
00958 if (n > 0) {
00959 r = genrand_int32(&rnd->mt);
00960 do {
00961 *ptr++ = (char)r;
00962 r >>= CHAR_BIT;
00963 } while (--n);
00964 }
00965 return bytes;
00966 }
00967
00968 static VALUE
00969 range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
00970 {
00971 VALUE end, r;
00972
00973 if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse;
00974 if (endp) *endp = end;
00975 if (!rb_respond_to(end, id_minus)) return Qfalse;
00976 r = rb_funcall2(end, id_minus, 1, begp);
00977 if (NIL_P(r)) return Qfalse;
00978 return r;
00979 }
00980
00981 static VALUE
00982 rand_int(struct MT *mt, VALUE vmax, int restrictive)
00983 {
00984
00985 long max;
00986 unsigned long r;
00987
00988 if (FIXNUM_P(vmax)) {
00989 max = FIX2LONG(vmax);
00990 if (!max) return Qnil;
00991 if (max < 0) {
00992 if (restrictive) return Qnil;
00993 max = -max;
00994 }
00995 r = limited_rand(mt, (unsigned long)max - 1);
00996 return ULONG2NUM(r);
00997 }
00998 else {
00999 VALUE ret;
01000 if (rb_bigzero_p(vmax)) return Qnil;
01001 if (!RBIGNUM_SIGN(vmax)) {
01002 if (restrictive) return Qnil;
01003 vmax = rb_big_clone(vmax);
01004 RBIGNUM_SET_SIGN(vmax, 1);
01005 }
01006 vmax = rb_big_minus(vmax, INT2FIX(1));
01007 if (FIXNUM_P(vmax)) {
01008 max = FIX2LONG(vmax);
01009 if (max == -1) return Qnil;
01010 r = limited_rand(mt, max);
01011 return LONG2NUM(r);
01012 }
01013 ret = limited_big_rand(mt, RBIGNUM(vmax));
01014 RB_GC_GUARD(vmax);
01015 return ret;
01016 }
01017 }
01018
01019 static inline double
01020 float_value(VALUE v)
01021 {
01022 double x = RFLOAT_VALUE(v);
01023 if (isinf(x) || isnan(x)) {
01024 VALUE error = INT2FIX(EDOM);
01025 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
01026 }
01027 return x;
01028 }
01029
01030 static inline VALUE
01031 rand_range(struct MT* mt, VALUE range)
01032 {
01033 VALUE beg = Qundef, end = Qundef, vmax, v;
01034 int excl = 0;
01035
01036 if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse)
01037 return Qfalse;
01038 if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
01039 long max;
01040 vmax = v;
01041 v = Qnil;
01042 if (FIXNUM_P(vmax)) {
01043 fixnum:
01044 if ((max = FIX2LONG(vmax) - excl) >= 0) {
01045 unsigned long r = limited_rand(mt, (unsigned long)max);
01046 v = ULONG2NUM(r);
01047 }
01048 }
01049 else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
01050 vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
01051 if (FIXNUM_P(vmax)) {
01052 excl = 0;
01053 goto fixnum;
01054 }
01055 v = limited_big_rand(mt, RBIGNUM(vmax));
01056 }
01057 }
01058 else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
01059 int scale = 1;
01060 double max = RFLOAT_VALUE(v), mid = 0.5, r;
01061 if (isinf(max)) {
01062 double min = float_value(rb_to_float(beg)) / 2.0;
01063 max = float_value(rb_to_float(end)) / 2.0;
01064 scale = 2;
01065 mid = max + min;
01066 max -= min;
01067 }
01068 else {
01069 float_value(v);
01070 }
01071 v = Qnil;
01072 if (max > 0.0) {
01073 if (excl) {
01074 r = genrand_real(mt);
01075 }
01076 else {
01077 r = genrand_real2(mt);
01078 }
01079 if (scale > 1) {
01080 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
01081 }
01082 v = rb_float_new(r * max);
01083 }
01084 else if (max == 0.0 && !excl) {
01085 v = rb_float_new(0.0);
01086 }
01087 }
01088
01089 if (FIXNUM_P(beg) && FIXNUM_P(v)) {
01090 long x = FIX2LONG(beg) + FIX2LONG(v);
01091 return LONG2NUM(x);
01092 }
01093 switch (TYPE(v)) {
01094 case T_NIL:
01095 break;
01096 case T_BIGNUM:
01097 return rb_big_plus(v, beg);
01098 case T_FLOAT: {
01099 VALUE f = rb_check_to_float(beg);
01100 if (!NIL_P(f)) {
01101 RFLOAT_VALUE(v) += RFLOAT_VALUE(f);
01102 return v;
01103 }
01104 }
01105 default:
01106 return rb_funcall2(beg, id_plus, 1, &v);
01107 }
01108
01109 return v;
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 static VALUE
01137 random_rand(int argc, VALUE *argv, VALUE obj)
01138 {
01139 rb_random_t *rnd = get_rnd(obj);
01140 VALUE vmax, v;
01141
01142 if (argc == 0) {
01143 return rb_float_new(genrand_real(&rnd->mt));
01144 }
01145 else if (argc != 1) {
01146 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
01147 }
01148 vmax = argv[0];
01149 if (NIL_P(vmax)) {
01150 v = Qnil;
01151 }
01152 else if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
01153 v = rand_int(&rnd->mt, v, 1);
01154 }
01155 else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
01156 double max = float_value(v);
01157 if (max > 0.0)
01158 v = rb_float_new(max * genrand_real(&rnd->mt));
01159 else
01160 v = Qnil;
01161 }
01162 else if ((v = rand_range(&rnd->mt, vmax)) != Qfalse) {
01163
01164 }
01165 else {
01166 v = Qnil;
01167 (void)NUM2LONG(vmax);
01168 }
01169 if (NIL_P(v)) {
01170 VALUE mesg = rb_str_new_cstr("invalid argument - ");
01171 rb_str_append(mesg, rb_obj_as_string(argv[0]));
01172 rb_exc_raise(rb_exc_new3(rb_eArgError, mesg));
01173 }
01174
01175 return v;
01176 }
01177
01178
01179
01180
01181
01182
01183
01184 static VALUE
01185 random_equal(VALUE self, VALUE other)
01186 {
01187 rb_random_t *r1, *r2;
01188 if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse;
01189 r1 = get_rnd(self);
01190 r2 = get_rnd(other);
01191 if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse;
01192 if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse;
01193 if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse;
01194 if (r1->mt.left != r2->mt.left) return Qfalse;
01195 return Qtrue;
01196 }
01197
01198
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 static VALUE
01227 rb_f_rand(int argc, VALUE *argv, VALUE obj)
01228 {
01229 VALUE v, vmax, r;
01230 struct MT *mt = default_mt();
01231
01232 if (argc == 0) goto zero_arg;
01233 rb_scan_args(argc, argv, "01", &vmax);
01234 if (NIL_P(vmax)) goto zero_arg;
01235 if ((v = rand_range(mt, vmax)) != Qfalse) {
01236 return v;
01237 }
01238 vmax = rb_to_int(vmax);
01239 if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
01240 zero_arg:
01241 return DBL2NUM(genrand_real(mt));
01242 }
01243 return r;
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 static VALUE
01256 random_s_rand(int argc, VALUE *argv, VALUE obj)
01257 {
01258 return random_rand(argc, argv, rb_Random_DEFAULT);
01259 }
01260
01261 static st_index_t hashseed;
01262
01263 static VALUE
01264 init_randomseed(struct MT *mt, unsigned int initial[DEFAULT_SEED_CNT])
01265 {
01266 VALUE seed;
01267 fill_random_seed(initial);
01268 init_by_array(mt, initial, DEFAULT_SEED_CNT);
01269 seed = make_seed_value(initial);
01270 memset(initial, 0, DEFAULT_SEED_LEN);
01271 return seed;
01272 }
01273
01274 void
01275 Init_RandomSeed(void)
01276 {
01277 rb_random_t *r = &default_rand;
01278 unsigned int initial[DEFAULT_SEED_CNT];
01279 struct MT *mt = &r->mt;
01280 VALUE seed = init_randomseed(mt, initial);
01281
01282 hashseed = genrand_int32(mt);
01283 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8
01284 hashseed <<= 32;
01285 hashseed |= genrand_int32(mt);
01286 #endif
01287 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
01288 hashseed <<= 32;
01289 hashseed |= genrand_int32(mt);
01290 #endif
01291 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8
01292 hashseed <<= 32;
01293 hashseed |= genrand_int32(mt);
01294 #endif
01295
01296 rb_global_variable(&r->seed);
01297 r->seed = seed;
01298 }
01299
01300 st_index_t
01301 rb_hash_start(st_index_t h)
01302 {
01303 return st_hash_start(hashseed + h);
01304 }
01305
01306 static void
01307 Init_RandomSeed2(void)
01308 {
01309 VALUE seed = default_rand.seed;
01310
01311 if (RB_TYPE_P(seed, T_BIGNUM)) {
01312 RBASIC(seed)->klass = rb_cBignum;
01313 }
01314 }
01315
01316 void
01317 rb_reset_random_seed(void)
01318 {
01319 rb_random_t *r = &default_rand;
01320 uninit_genrand(&r->mt);
01321 r->seed = INT2FIX(0);
01322 }
01323
01324 void
01325 Init_Random(void)
01326 {
01327 Init_RandomSeed2();
01328 rb_define_global_function("srand", rb_f_srand, -1);
01329 rb_define_global_function("rand", rb_f_rand, -1);
01330
01331 rb_cRandom = rb_define_class("Random", rb_cObject);
01332 rb_define_alloc_func(rb_cRandom, random_alloc);
01333 rb_define_method(rb_cRandom, "initialize", random_init, -1);
01334 rb_define_method(rb_cRandom, "rand", random_rand, -1);
01335 rb_define_method(rb_cRandom, "bytes", random_bytes, 1);
01336 rb_define_method(rb_cRandom, "seed", random_get_seed, 0);
01337 rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1);
01338 rb_define_method(rb_cRandom, "marshal_dump", random_dump, 0);
01339 rb_define_method(rb_cRandom, "marshal_load", random_load, 1);
01340 rb_define_private_method(rb_cRandom, "state", random_state, 0);
01341 rb_define_private_method(rb_cRandom, "left", random_left, 0);
01342 rb_define_method(rb_cRandom, "==", random_equal, 1);
01343
01344 rb_Random_DEFAULT = TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand);
01345 rb_global_variable(&rb_Random_DEFAULT);
01346 rb_define_const(rb_cRandom, "DEFAULT", rb_Random_DEFAULT);
01347
01348 rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1);
01349 rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1);
01350 rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0);
01351 rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0);
01352 rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0);
01353
01354 id_rand = rb_intern("rand");
01355 id_bytes = rb_intern("bytes");
01356 }
01357