|
Ruby
1.9.3p448(2013-06-27revision41675)
|
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 #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 /* Period parameters */ 00092 #define N 624 00093 #define M 397 00094 #define MATRIX_A 0x9908b0dfU /* constant vector a */ 00095 #define UMASK 0x80000000U /* most significant w-r bits */ 00096 #define LMASK 0x7fffffffU /* least significant r bits */ 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 /* assume int is enough to store 32bits */ 00104 unsigned int state[N]; /* the array for the state vector */ 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 /* initializes state[N] with a seed */ 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 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 00121 /* In the previous versions, MSBs of the seed affect */ 00122 /* only MSBs of the array state[]. */ 00123 /* 2002/01/09 modified by Makoto Matsumoto */ 00124 mt->state[j] &= 0xffffffff; /* for >32 bit machines */ 00125 } 00126 mt->left = 1; 00127 mt->next = mt->state + N; 00128 } 00129 00130 /* initialize by an array with array-length */ 00131 /* init_key is the array for initializing keys */ 00132 /* key_length is its length */ 00133 /* slight change for C++, 2004/2/26 */ 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; /* non linear */ 00144 mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ 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; /* non linear */ 00152 mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ 00153 i++; 00154 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; } 00155 } 00156 00157 mt->state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ 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 /* generates a random number on [0,0xffffffff]-interval */ 00179 static unsigned int 00180 genrand_int32(struct MT *mt) 00181 { 00182 /* mt must be initialized */ 00183 unsigned int y; 00184 00185 if (--mt->left <= 0) next_state(mt); 00186 y = *mt->next++; 00187 00188 /* Tempering */ 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 /* generates a random number on [0,1) with 53-bit resolution*/ 00198 static double 00199 genrand_real(struct MT *mt) 00200 { 00201 /* mt must be initialized */ 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 /* generates a random number on [0,1] with 53-bit resolution*/ 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 /* mt must be initialized */ 00212 unsigned int a = genrand_int32(mt), b = genrand_int32(mt); 00213 return int_pair_to_real_inclusive(a, b); 00214 } 00215 00216 /* These real versions are due to Isaku Wada, 2002/01/09 added */ 00217 00218 #undef N 00219 #undef M 00220 00221 /* These real versions are due to Isaku Wada, 2002/01/09 added */ 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 /* :nodoc: */ 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 /* :nodoc: */ 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 /* allocate ints for init_by_array */ 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) /* remove leading-zero-guard */ 00448 len--; 00449 init_by_array(mt, buf, len); 00450 } 00451 if (buf != buf0) xfree(buf); 00452 return seed; 00453 } 00454 00455 /* 00456 * call-seq: Random.new([seed]) -> prng 00457 * 00458 * Creates new Mersenne Twister based pseudorandom number generator with 00459 * seed. When the argument seed is omitted, the generator is initialized 00460 * with Random.new_seed. 00461 * 00462 * The argument seed is used to ensure repeatable sequences of random numbers 00463 * between different runs of the program. 00464 * 00465 * prng = Random.new(1234) 00466 * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] 00467 * [ prng.integer(10), prng.integer(1000) ] #=> [4, 664] 00468 * prng = Random.new(1234) 00469 * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] 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 /* abandon */; 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 /* set leading-zero-guard if need. */ 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 * call-seq: Random.new_seed -> integer 00574 * 00575 * Returns arbitrary value for seed. 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 * call-seq: prng.seed -> integer 00587 * 00588 * Returns the seed of the generator. 00589 */ 00590 static VALUE 00591 random_get_seed(VALUE obj) 00592 { 00593 return get_rnd(obj)->seed; 00594 } 00595 00596 /* :nodoc: */ 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 /* :nodoc: */ 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 /* :nodoc: */ 00640 static VALUE 00641 random_s_state(VALUE klass) 00642 { 00643 return mt_state(&default_rand.mt); 00644 } 00645 00646 /* :nodoc: */ 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 /* :nodoc: */ 00655 static VALUE 00656 random_s_left(VALUE klass) 00657 { 00658 return INT2FIX(default_rand.mt.left); 00659 } 00660 00661 /* :nodoc: */ 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 /* :nodoc: */ 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 * call-seq: 00765 * srand(number=0) -> old_seed 00766 * 00767 * Seeds the pseudorandom number generator to the value of 00768 * <i>number</i>. If <i>number</i> is omitted, 00769 * seeds the generator using a combination of the time, the 00770 * process id, and a sequence number. (This is also the behavior if 00771 * <code>Kernel::rand</code> is called without previously calling 00772 * <code>srand</code>, but without the sequence.) By setting the seed 00773 * to a known value, scripts can be made deterministic during testing. 00774 * The previous seed value is returned. Also see <code>Kernel::rand</code>. 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 /* mt must be initialized */ 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 /* mt must be initialized */ 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 /* SIZEOF_BDIGITS == 4 */ 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 * Returns random unsigned long value in [0, _limit_]. 00885 * 00886 * Note that _limit_ is included, and the range of the argument and the 00887 * return value depends on environments. 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 * call-seq: prng.bytes(size) -> a_string 00929 * 00930 * Returns a random binary string. The argument size specified the length of 00931 * the result string. 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 /* mt must be initialized */ 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 * call-seq: 01117 * prng.rand -> float 01118 * prng.rand(limit) -> number 01119 * 01120 * When the argument is an +Integer+ or a +Bignum+, it returns a 01121 * random integer greater than or equal to zero and less than the 01122 * argument. Unlike Random.rand, when the argument is a negative 01123 * integer or zero, it raises an ArgumentError. 01124 * 01125 * When the argument is a +Float+, it returns a random floating point 01126 * number between 0.0 and _max_, including 0.0 and excluding _max_. 01127 * 01128 * When the argument _limit_ is a +Range+, it returns a random 01129 * number where range.member?(number) == true. 01130 * prng.rand(5..9) #=> one of [5, 6, 7, 8, 9] 01131 * prng.rand(5...9) #=> one of [5, 6, 7, 8] 01132 * prng.rand(5.0..9.0) #=> between 5.0 and 9.0, including 9.0 01133 * prng.rand(5.0...9.0) #=> between 5.0 and 9.0, excluding 9.0 01134 * 01135 * +begin+/+end+ of the range have to have subtract and add methods. 01136 * 01137 * Otherwise, it raises an ArgumentError. 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 /* nothing to do */ 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 * call-seq: 01183 * prng1 == prng2 -> true or false 01184 * 01185 * Returns true if the generators' states equal. 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 * call-seq: 01203 * rand(max=0) -> number 01204 * 01205 * 01206 * If <i>max</i> is +Range+, returns a pseudorandom number where 01207 * range.member(number) == true. 01208 * 01209 * Or else converts _max_ to an integer using max1 = 01210 * max<code>.to_i.abs</code>. 01211 * 01212 * Then if _max_ is +nil+ the result is zero, returns a pseudorandom floating 01213 * point number greater than or equal to 0.0 and less than 1.0. 01214 * 01215 * Otherwise, returns a pseudorandom integer greater than or equal to zero and 01216 * less than max1. 01217 * 01218 * <code>Kernel::srand</code> may be used to ensure repeatable sequences of 01219 * random numbers between different runs of the program. Ruby currently uses 01220 * a modified Mersenne Twister with a period of 2**19937-1. 01221 * 01222 * srand 1234 #=> 0 01223 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] 01224 * [ rand(10), rand(1000) ] #=> [6, 817] 01225 * srand 1234 #=> 1234 01226 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] 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 * call-seq: 01251 * Random.rand -> float 01252 * Random.rand(limit) -> number 01253 * 01254 * Alias of _Random::DEFAULT.rand_. 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
1.7.6.1