Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /********************************************************************** 00002 00003 random.c - 00004 00005 $Author: usa $ 00006 created at: Fri Dec 24 16:39:21 JST 1993 00007 00008 Copyright (C) 1993-2007 Yukihiro Matsumoto 00009 00010 **********************************************************************/ 00011 00012 /* 00013 This is based on trimmed version of MT19937. To get the original version, 00014 contact <http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html>. 00015 00016 The original copyright notice follows. 00017 00018 A C-program for MT19937, with initialization improved 2002/2/10. 00019 Coded by Takuji Nishimura and Makoto Matsumoto. 00020 This is a faster version by taking Shawn Cokus's optimization, 00021 Matthe Bellew's simplification, Isaku Wada's real version. 00022 00023 Before using, initialize the state by using init_genrand(mt, seed) 00024 or init_by_array(mt, init_key, key_length). 00025 00026 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 00027 All rights reserved. 00028 00029 Redistribution and use in source and binary forms, with or without 00030 modification, are permitted provided that the following conditions 00031 are met: 00032 00033 1. Redistributions of source code must retain the above copyright 00034 notice, this list of conditions and the following disclaimer. 00035 00036 2. Redistributions in binary form must reproduce the above copyright 00037 notice, this list of conditions and the following disclaimer in the 00038 documentation and/or other materials provided with the distribution. 00039 00040 3. The names of its contributors may not be used to endorse or promote 00041 products derived from this software without specific prior written 00042 permission. 00043 00044 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00045 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00046 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00047 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00048 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00049 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00050 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00051 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00052 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00053 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00054 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00055 00056 00057 Any feedback is very welcome. 00058 http://www.math.keio.ac.jp/matumoto/emt.html 00059 email: matumoto@math.keio.ac.jp 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 /* Period parameters */ 00089 #define N 624 00090 #define M 397 00091 #define MATRIX_A 0x9908b0dfU /* constant vector a */ 00092 #define UMASK 0x80000000U /* most significant w-r bits */ 00093 #define LMASK 0x7fffffffU /* least significant r bits */ 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 /* assume int is enough to store 32bits */ 00101 unsigned int state[N]; /* the array for the state vector */ 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 /* initializes state[N] with a seed */ 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 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 00118 /* In the previous versions, MSBs of the seed affect */ 00119 /* only MSBs of the array state[]. */ 00120 /* 2002/01/09 modified by Makoto Matsumoto */ 00121 mt->state[j] &= 0xffffffff; /* for >32 bit machines */ 00122 } 00123 mt->left = 1; 00124 mt->next = mt->state + N; 00125 } 00126 00127 /* initialize by an array with array-length */ 00128 /* init_key is the array for initializing keys */ 00129 /* key_length is its length */ 00130 /* slight change for C++, 2004/2/26 */ 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; /* non linear */ 00141 mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ 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; /* non linear */ 00149 mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ 00150 i++; 00151 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; } 00152 } 00153 00154 mt->state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ 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 /* generates a random number on [0,0xffffffff]-interval */ 00176 static unsigned int 00177 genrand_int32(struct MT *mt) 00178 { 00179 /* mt must be initialized */ 00180 unsigned int y; 00181 00182 if (--mt->left <= 0) next_state(mt); 00183 y = *mt->next++; 00184 00185 /* Tempering */ 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 /* generates a random number on [0,1) with 53-bit resolution*/ 00195 static double 00196 genrand_real(struct MT *mt) 00197 { 00198 /* mt must be initialized */ 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 /* generates a random number on [0,1] with 53-bit resolution*/ 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 /* mt must be initialized */ 00209 unsigned int a = genrand_int32(mt), b = genrand_int32(mt); 00210 return int_pair_to_real_inclusive(a, b); 00211 } 00212 00213 /* These real versions are due to Isaku Wada, 2002/01/09 added */ 00214 00215 #undef N 00216 #undef M 00217 00218 /* These real versions are due to Isaku Wada, 2002/01/09 added */ 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 /* :nodoc: */ 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 /* :nodoc: */ 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 /* allocate ints for init_by_array */ 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) /* remove leading-zero-guard */ 00445 len--; 00446 init_by_array(mt, buf, len); 00447 } 00448 if (buf != buf0) xfree(buf); 00449 return seed; 00450 } 00451 00452 /* 00453 * call-seq: Random.new([seed]) -> prng 00454 * 00455 * Creates new Mersenne Twister based pseudorandom number generator with 00456 * seed. When the argument seed is omitted, the generator is initialized 00457 * with Random.new_seed. 00458 * 00459 * The argument seed is used to ensure repeatable sequences of random numbers 00460 * between different runs of the program. 00461 * 00462 * prng = Random.new(1234) 00463 * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] 00464 * [ prng.integer(10), prng.integer(1000) ] #=> [4, 664] 00465 * prng = Random.new(1234) 00466 * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] 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 /* abandon */; 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 /* set leading-zero-guard if need. */ 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 * call-seq: Random.new_seed -> integer 00571 * 00572 * Returns arbitrary value for seed. 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 * call-seq: prng.seed -> integer 00584 * 00585 * Returns the seed of the generator. 00586 */ 00587 static VALUE 00588 random_get_seed(VALUE obj) 00589 { 00590 return get_rnd(obj)->seed; 00591 } 00592 00593 /* :nodoc: */ 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 /* :nodoc: */ 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 /* :nodoc: */ 00637 static VALUE 00638 random_s_state(VALUE klass) 00639 { 00640 return mt_state(&default_rand.mt); 00641 } 00642 00643 /* :nodoc: */ 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 /* :nodoc: */ 00652 static VALUE 00653 random_s_left(VALUE klass) 00654 { 00655 return INT2FIX(default_rand.mt.left); 00656 } 00657 00658 /* :nodoc: */ 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 /* :nodoc: */ 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 * call-seq: 00762 * srand(number=0) -> old_seed 00763 * 00764 * Seeds the pseudorandom number generator to the value of 00765 * <i>number</i>. If <i>number</i> is omitted, 00766 * seeds the generator using a combination of the time, the 00767 * process id, and a sequence number. (This is also the behavior if 00768 * <code>Kernel::rand</code> is called without previously calling 00769 * <code>srand</code>, but without the sequence.) By setting the seed 00770 * to a known value, scripts can be made deterministic during testing. 00771 * The previous seed value is returned. Also see <code>Kernel::rand</code>. 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 /* mt must be initialized */ 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 /* mt must be initialized */ 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 /* SIZEOF_BDIGITS == 4 */ 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 * Returns random unsigned long value in [0, _limit_]. 00882 * 00883 * Note that _limit_ is included, and the range of the argument and the 00884 * return value depends on environments. 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 * call-seq: prng.bytes(size) -> a_string 00926 * 00927 * Returns a random binary string. The argument size specified the length of 00928 * the result string. 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 /* mt must be initialized */ 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 * call-seq: 01114 * prng.rand -> float 01115 * prng.rand(limit) -> number 01116 * 01117 * When the argument is an +Integer+ or a +Bignum+, it returns a 01118 * random integer greater than or equal to zero and less than the 01119 * argument. Unlike Random.rand, when the argument is a negative 01120 * integer or zero, it raises an ArgumentError. 01121 * 01122 * When the argument is a +Float+, it returns a random floating point 01123 * number between 0.0 and _max_, including 0.0 and excluding _max_. 01124 * 01125 * When the argument _limit_ is a +Range+, it returns a random 01126 * number where range.member?(number) == true. 01127 * prng.rand(5..9) #=> one of [5, 6, 7, 8, 9] 01128 * prng.rand(5...9) #=> one of [5, 6, 7, 8] 01129 * prng.rand(5.0..9.0) #=> between 5.0 and 9.0, including 9.0 01130 * prng.rand(5.0...9.0) #=> between 5.0 and 9.0, excluding 9.0 01131 * 01132 * +begin+/+end+ of the range have to have subtract and add methods. 01133 * 01134 * Otherwise, it raises an ArgumentError. 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 /* nothing to do */ 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 * call-seq: 01180 * prng1 == prng2 -> true or false 01181 * 01182 * Returns true if the generators' states equal. 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 * call-seq: 01200 * rand(max=0) -> number 01201 * 01202 * 01203 * If <i>max</i> is +Range+, returns a pseudorandom number where 01204 * range.member(number) == true. 01205 * 01206 * Or else converts _max_ to an integer using max1 = 01207 * max<code>.to_i.abs</code>. 01208 * 01209 * Then if _max_ is +nil+ the result is zero, returns a pseudorandom floating 01210 * point number greater than or equal to 0.0 and less than 1.0. 01211 * 01212 * Otherwise, returns a pseudorandom integer greater than or equal to zero and 01213 * less than max1. 01214 * 01215 * <code>Kernel::srand</code> may be used to ensure repeatable sequences of 01216 * random numbers between different runs of the program. Ruby currently uses 01217 * a modified Mersenne Twister with a period of 2**19937-1. 01218 * 01219 * srand 1234 #=> 0 01220 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] 01221 * [ rand(10), rand(1000) ] #=> [6, 817] 01222 * srand 1234 #=> 1234 01223 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] 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 * call-seq: 01248 * Random.rand -> float 01249 * Random.rand(limit) -> number 01250 * 01251 * Alias of _Random::DEFAULT.rand_. 01252 * 01253 */ 01254 01255 static VALUE 01256 random_s_rand(int argc, VALUE *argv, VALUE obj) 01257 { 01258 rand_start(&default_rand); 01259 return random_rand(argc, argv, rb_Random_DEFAULT); 01260 } 01261 01262 #define SIP_HASH_STREAMING 0 01263 #define sip_hash24 ruby_sip_hash24 01264 #include "siphash.c" 01265 01266 static st_index_t hashseed; 01267 static union { 01268 uint8_t key[16]; 01269 uint32_t u32[(16 * sizeof(uint8_t) - 1) / sizeof(uint32_t)]; 01270 } sipseed; 01271 01272 static VALUE 01273 init_randomseed(struct MT *mt, unsigned int initial[DEFAULT_SEED_CNT]) 01274 { 01275 VALUE seed; 01276 fill_random_seed(initial); 01277 init_by_array(mt, initial, DEFAULT_SEED_CNT); 01278 seed = make_seed_value(initial); 01279 memset(initial, 0, DEFAULT_SEED_LEN); 01280 return seed; 01281 } 01282 01283 void 01284 Init_RandomSeed(void) 01285 { 01286 rb_random_t *r = &default_rand; 01287 unsigned int initial[DEFAULT_SEED_CNT]; 01288 struct MT *mt = &r->mt; 01289 VALUE seed = init_randomseed(mt, initial); 01290 int i; 01291 01292 hashseed = genrand_int32(mt); 01293 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8 01294 hashseed <<= 32; 01295 hashseed |= genrand_int32(mt); 01296 #endif 01297 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8 01298 hashseed <<= 32; 01299 hashseed |= genrand_int32(mt); 01300 #endif 01301 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8 01302 hashseed <<= 32; 01303 hashseed |= genrand_int32(mt); 01304 #endif 01305 01306 for (i = 0; i < numberof(sipseed.u32); ++i) 01307 sipseed.u32[i] = genrand_int32(mt); 01308 01309 rb_global_variable(&r->seed); 01310 r->seed = seed; 01311 } 01312 01313 st_index_t 01314 rb_hash_start(st_index_t h) 01315 { 01316 return st_hash_start(hashseed + h); 01317 } 01318 01319 st_index_t 01320 rb_memhash(const void *ptr, long len) 01321 { 01322 sip_uint64_t h = sip_hash24(sipseed.key, ptr, len); 01323 #ifdef HAVE_UINT64_T 01324 return (st_index_t)h; 01325 #else 01326 return (st_index_t)(h.u32[0] ^ h.u32[1]); 01327 #endif 01328 } 01329 01330 static void 01331 Init_RandomSeed2(void) 01332 { 01333 VALUE seed = default_rand.seed; 01334 01335 if (RB_TYPE_P(seed, T_BIGNUM)) { 01336 RBASIC(seed)->klass = rb_cBignum; 01337 } 01338 } 01339 01340 void 01341 rb_reset_random_seed(void) 01342 { 01343 rb_random_t *r = &default_rand; 01344 uninit_genrand(&r->mt); 01345 r->seed = INT2FIX(0); 01346 } 01347 01348 void 01349 Init_Random(void) 01350 { 01351 Init_RandomSeed2(); 01352 rb_define_global_function("srand", rb_f_srand, -1); 01353 rb_define_global_function("rand", rb_f_rand, -1); 01354 01355 rb_cRandom = rb_define_class("Random", rb_cObject); 01356 rb_define_alloc_func(rb_cRandom, random_alloc); 01357 rb_define_method(rb_cRandom, "initialize", random_init, -1); 01358 rb_define_method(rb_cRandom, "rand", random_rand, -1); 01359 rb_define_method(rb_cRandom, "bytes", random_bytes, 1); 01360 rb_define_method(rb_cRandom, "seed", random_get_seed, 0); 01361 rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1); 01362 rb_define_method(rb_cRandom, "marshal_dump", random_dump, 0); 01363 rb_define_method(rb_cRandom, "marshal_load", random_load, 1); 01364 rb_define_private_method(rb_cRandom, "state", random_state, 0); 01365 rb_define_private_method(rb_cRandom, "left", random_left, 0); 01366 rb_define_method(rb_cRandom, "==", random_equal, 1); 01367 01368 rb_Random_DEFAULT = TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand); 01369 rb_global_variable(&rb_Random_DEFAULT); 01370 rb_define_const(rb_cRandom, "DEFAULT", rb_Random_DEFAULT); 01371 01372 rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1); 01373 rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1); 01374 rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0); 01375 rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0); 01376 rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0); 01377 01378 id_rand = rb_intern("rand"); 01379 id_bytes = rb_intern("bytes"); 01380 } 01381