|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /********************************************************************** 00002 00003 random.c - 00004 00005 $Author: nobu $ 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 struct MT * 00233 default_mt(void) 00234 { 00235 rb_random_t *r = &default_rand; 00236 struct MT *mt = &r->mt; 00237 if (!genrand_initialized(mt)) { 00238 r->seed = rand_init(mt, random_seed()); 00239 } 00240 return mt; 00241 } 00242 00243 unsigned int 00244 rb_genrand_int32(void) 00245 { 00246 struct MT *mt = default_mt(); 00247 return genrand_int32(mt); 00248 } 00249 00250 double 00251 rb_genrand_real(void) 00252 { 00253 struct MT *mt = default_mt(); 00254 return genrand_real(mt); 00255 } 00256 00257 #define BDIGITS(x) (RBIGNUM_DIGITS(x)) 00258 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT) 00259 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG) 00260 #define DIGSPERINT (SIZEOF_INT/SIZEOF_BDIGITS) 00261 #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG) 00262 #define BIGDN(x) RSHIFT(x,BITSPERDIG) 00263 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1))) 00264 #define BDIGMAX ((BDIGIT)-1) 00265 00266 #define roomof(n, m) (int)(((n)+(m)-1) / (m)) 00267 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) 00268 #define SIZEOF_INT32 (31/CHAR_BIT + 1) 00269 00270 static double 00271 int_pair_to_real_inclusive(unsigned int a, unsigned int b) 00272 { 00273 VALUE x = rb_big_new(roomof(64, BITSPERDIG), 1); 00274 VALUE m = rb_big_new(roomof(53, BITSPERDIG), 1); 00275 BDIGIT *xd = BDIGITS(x); 00276 int i = 0; 00277 double r; 00278 00279 xd[i++] = (BDIGIT)b; 00280 #if BITSPERDIG < 32 00281 xd[i++] = (BDIGIT)(b >> BITSPERDIG); 00282 #endif 00283 xd[i++] = (BDIGIT)a; 00284 #if BITSPERDIG < 32 00285 xd[i++] = (BDIGIT)(a >> BITSPERDIG); 00286 #endif 00287 xd = BDIGITS(m); 00288 #if BITSPERDIG < 53 00289 MEMZERO(xd, BDIGIT, roomof(53, BITSPERDIG) - 1); 00290 #endif 00291 xd[53 / BITSPERDIG] = 1 << 53 % BITSPERDIG; 00292 xd[0] |= 1; 00293 x = rb_big_mul(x, m); 00294 if (FIXNUM_P(x)) { 00295 #if CHAR_BIT * SIZEOF_LONG > 64 00296 r = (double)(FIX2ULONG(x) >> 64); 00297 #else 00298 return 0.0; 00299 #endif 00300 } 00301 else { 00302 #if 64 % BITSPERDIG == 0 00303 long len = RBIGNUM_LEN(x); 00304 xd = BDIGITS(x); 00305 MEMMOVE(xd, xd + 64 / BITSPERDIG, BDIGIT, len - 64 / BITSPERDIG); 00306 MEMZERO(xd + len - 64 / BITSPERDIG, BDIGIT, 64 / BITSPERDIG); 00307 r = rb_big2dbl(x); 00308 #else 00309 x = rb_big_rshift(x, INT2FIX(64)); 00310 if (FIXNUM_P(x)) { 00311 r = (double)FIX2ULONG(x); 00312 } 00313 else { 00314 r = rb_big2dbl(x); 00315 } 00316 #endif 00317 } 00318 return ldexp(r, -53); 00319 } 00320 00321 VALUE rb_cRandom; 00322 #define id_minus '-' 00323 #define id_plus '+' 00324 00325 /* :nodoc: */ 00326 static void 00327 random_mark(void *ptr) 00328 { 00329 rb_gc_mark(((rb_random_t *)ptr)->seed); 00330 } 00331 00332 #define random_free RUBY_TYPED_DEFAULT_FREE 00333 00334 static size_t 00335 random_memsize(const void *ptr) 00336 { 00337 return ptr ? sizeof(rb_random_t) : 0; 00338 } 00339 00340 static const rb_data_type_t random_data_type = { 00341 "random", 00342 random_mark, 00343 random_free, 00344 random_memsize, 00345 }; 00346 00347 static rb_random_t * 00348 get_rnd(VALUE obj) 00349 { 00350 rb_random_t *ptr; 00351 TypedData_Get_Struct(obj, rb_random_t, &random_data_type, ptr); 00352 return ptr; 00353 } 00354 00355 /* :nodoc: */ 00356 static VALUE 00357 random_alloc(VALUE klass) 00358 { 00359 rb_random_t *rnd; 00360 VALUE obj = TypedData_Make_Struct(klass, rb_random_t, &random_data_type, rnd); 00361 rnd->seed = INT2FIX(0); 00362 return obj; 00363 } 00364 00365 static VALUE 00366 rand_init(struct MT *mt, VALUE vseed) 00367 { 00368 volatile VALUE seed; 00369 long blen = 0; 00370 long fixnum_seed; 00371 int i, j, len; 00372 unsigned int buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0; 00373 00374 seed = rb_to_int(vseed); 00375 switch (TYPE(seed)) { 00376 case T_FIXNUM: 00377 len = 1; 00378 fixnum_seed = FIX2LONG(seed); 00379 if (fixnum_seed < 0) 00380 fixnum_seed = -fixnum_seed; 00381 buf[0] = (unsigned int)(fixnum_seed & 0xffffffff); 00382 #if SIZEOF_LONG > SIZEOF_INT32 00383 if ((long)(int)fixnum_seed != fixnum_seed) { 00384 if ((buf[1] = (unsigned int)(fixnum_seed >> 32)) != 0) ++len; 00385 } 00386 #endif 00387 break; 00388 case T_BIGNUM: 00389 blen = RBIGNUM_LEN(seed); 00390 if (blen == 0) { 00391 len = 1; 00392 } 00393 else { 00394 if (blen > MT_MAX_STATE * SIZEOF_INT32 / SIZEOF_BDIGITS) 00395 blen = (len = MT_MAX_STATE) * SIZEOF_INT32 / SIZEOF_BDIGITS; 00396 len = roomof((int)blen * SIZEOF_BDIGITS, SIZEOF_INT32); 00397 } 00398 /* allocate ints for init_by_array */ 00399 if (len > numberof(buf0)) buf = ALLOC_N(unsigned int, len); 00400 memset(buf, 0, len * sizeof(*buf)); 00401 len = 0; 00402 for (i = (int)(blen-1); 0 <= i; i--) { 00403 j = i * SIZEOF_BDIGITS / SIZEOF_INT32; 00404 #if SIZEOF_BDIGITS < SIZEOF_INT32 00405 buf[j] <<= BITSPERDIG; 00406 #endif 00407 buf[j] |= RBIGNUM_DIGITS(seed)[i]; 00408 if (!len && buf[j]) len = j; 00409 } 00410 ++len; 00411 break; 00412 default: 00413 rb_raise(rb_eTypeError, "failed to convert %s into Integer", 00414 rb_obj_classname(vseed)); 00415 } 00416 if (len <= 1) { 00417 init_genrand(mt, buf[0]); 00418 } 00419 else { 00420 if (buf[len-1] == 1) /* remove leading-zero-guard */ 00421 len--; 00422 init_by_array(mt, buf, len); 00423 } 00424 if (buf != buf0) xfree(buf); 00425 return seed; 00426 } 00427 00428 /* 00429 * call-seq: Random.new([seed]) -> prng 00430 * 00431 * Creates new Mersenne Twister based pseudorandom number generator with 00432 * seed. When the argument seed is omitted, the generator is initialized 00433 * with Random.new_seed. 00434 * 00435 * The argument seed is used to ensure repeatable sequences of random numbers 00436 * between different runs of the program. 00437 * 00438 * prng = Random.new(1234) 00439 * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] 00440 * [ prng.integer(10), prng.integer(1000) ] #=> [4, 664] 00441 * prng = Random.new(1234) 00442 * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] 00443 */ 00444 static VALUE 00445 random_init(int argc, VALUE *argv, VALUE obj) 00446 { 00447 VALUE vseed; 00448 rb_random_t *rnd = get_rnd(obj); 00449 00450 if (argc == 0) { 00451 vseed = random_seed(); 00452 } 00453 else { 00454 rb_scan_args(argc, argv, "01", &vseed); 00455 } 00456 rnd->seed = rand_init(&rnd->mt, vseed); 00457 return obj; 00458 } 00459 00460 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * sizeof(int)) 00461 00462 #if defined(S_ISCHR) && !defined(DOSISH) 00463 # define USE_DEV_URANDOM 1 00464 #else 00465 # define USE_DEV_URANDOM 0 00466 #endif 00467 00468 static void 00469 fill_random_seed(unsigned int seed[DEFAULT_SEED_CNT]) 00470 { 00471 static int n = 0; 00472 struct timeval tv; 00473 #if USE_DEV_URANDOM 00474 int fd; 00475 struct stat statbuf; 00476 #elif defined(_WIN32) 00477 HCRYPTPROV prov; 00478 #endif 00479 00480 memset(seed, 0, DEFAULT_SEED_LEN); 00481 00482 #if USE_DEV_URANDOM 00483 if ((fd = open("/dev/urandom", O_RDONLY 00484 #ifdef O_NONBLOCK 00485 |O_NONBLOCK 00486 #endif 00487 #ifdef O_NOCTTY 00488 |O_NOCTTY 00489 #endif 00490 )) >= 0) { 00491 if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) { 00492 (void)read(fd, seed, DEFAULT_SEED_LEN); 00493 } 00494 close(fd); 00495 } 00496 #elif defined(_WIN32) 00497 if (CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 00498 CryptGenRandom(prov, DEFAULT_SEED_LEN, (void *)seed); 00499 CryptReleaseContext(prov, 0); 00500 } 00501 #endif 00502 00503 gettimeofday(&tv, 0); 00504 seed[0] ^= tv.tv_usec; 00505 seed[1] ^= (unsigned int)tv.tv_sec; 00506 #if SIZEOF_TIME_T > SIZEOF_INT 00507 seed[0] ^= (unsigned int)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT); 00508 #endif 00509 seed[2] ^= getpid() ^ (n++ << 16); 00510 seed[3] ^= (unsigned int)(VALUE)&seed; 00511 #if SIZEOF_VOIDP > SIZEOF_INT 00512 seed[2] ^= (unsigned int)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT); 00513 #endif 00514 } 00515 00516 static VALUE 00517 make_seed_value(const void *ptr) 00518 { 00519 const long len = DEFAULT_SEED_LEN/SIZEOF_BDIGITS; 00520 BDIGIT *digits; 00521 NEWOBJ(big, struct RBignum); 00522 OBJSETUP(big, rb_cBignum, T_BIGNUM); 00523 00524 RBIGNUM_SET_SIGN(big, 1); 00525 rb_big_resize((VALUE)big, len + 1); 00526 digits = RBIGNUM_DIGITS(big); 00527 00528 MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN); 00529 00530 /* set leading-zero-guard if need. */ 00531 digits[len] = 00532 #if SIZEOF_INT32 / SIZEOF_BDIGITS > 1 00533 digits[len-2] <= 1 && digits[len-1] == 0 00534 #else 00535 digits[len-1] <= 1 00536 #endif 00537 ? 1 : 0; 00538 00539 return rb_big_norm((VALUE)big); 00540 } 00541 00542 /* 00543 * call-seq: Random.new_seed -> integer 00544 * 00545 * Returns arbitrary value for seed. 00546 */ 00547 static VALUE 00548 random_seed(void) 00549 { 00550 unsigned int buf[DEFAULT_SEED_CNT]; 00551 fill_random_seed(buf); 00552 return make_seed_value(buf); 00553 } 00554 00555 /* 00556 * call-seq: prng.seed -> integer 00557 * 00558 * Returns the seed of the generator. 00559 */ 00560 static VALUE 00561 random_get_seed(VALUE obj) 00562 { 00563 return get_rnd(obj)->seed; 00564 } 00565 00566 /* :nodoc: */ 00567 static VALUE 00568 random_copy(VALUE obj, VALUE orig) 00569 { 00570 rb_random_t *rnd1 = get_rnd(obj); 00571 rb_random_t *rnd2 = get_rnd(orig); 00572 struct MT *mt = &rnd1->mt; 00573 00574 *rnd1 = *rnd2; 00575 mt->next = mt->state + numberof(mt->state) - mt->left + 1; 00576 return obj; 00577 } 00578 00579 static VALUE 00580 mt_state(const struct MT *mt) 00581 { 00582 VALUE bigo = rb_big_new(sizeof(mt->state) / sizeof(BDIGIT), 1); 00583 BDIGIT *d = RBIGNUM_DIGITS(bigo); 00584 int i; 00585 00586 for (i = 0; i < numberof(mt->state); ++i) { 00587 unsigned int x = mt->state[i]; 00588 #if SIZEOF_BDIGITS < SIZEOF_INT32 00589 int j; 00590 for (j = 0; j < SIZEOF_INT32 / SIZEOF_BDIGITS; ++j) { 00591 *d++ = BIGLO(x); 00592 x = BIGDN(x); 00593 } 00594 #else 00595 *d++ = (BDIGIT)x; 00596 #endif 00597 } 00598 return rb_big_norm(bigo); 00599 } 00600 00601 /* :nodoc: */ 00602 static VALUE 00603 random_state(VALUE obj) 00604 { 00605 rb_random_t *rnd = get_rnd(obj); 00606 return mt_state(&rnd->mt); 00607 } 00608 00609 /* :nodoc: */ 00610 static VALUE 00611 random_s_state(VALUE klass) 00612 { 00613 return mt_state(&default_rand.mt); 00614 } 00615 00616 /* :nodoc: */ 00617 static VALUE 00618 random_left(VALUE obj) 00619 { 00620 rb_random_t *rnd = get_rnd(obj); 00621 return INT2FIX(rnd->mt.left); 00622 } 00623 00624 /* :nodoc: */ 00625 static VALUE 00626 random_s_left(VALUE klass) 00627 { 00628 return INT2FIX(default_rand.mt.left); 00629 } 00630 00631 /* :nodoc: */ 00632 static VALUE 00633 random_dump(VALUE obj) 00634 { 00635 rb_random_t *rnd = get_rnd(obj); 00636 VALUE dump = rb_ary_new2(3); 00637 00638 rb_ary_push(dump, mt_state(&rnd->mt)); 00639 rb_ary_push(dump, INT2FIX(rnd->mt.left)); 00640 rb_ary_push(dump, rnd->seed); 00641 00642 return dump; 00643 } 00644 00645 /* :nodoc: */ 00646 static VALUE 00647 random_load(VALUE obj, VALUE dump) 00648 { 00649 rb_random_t *rnd = get_rnd(obj); 00650 struct MT *mt = &rnd->mt; 00651 VALUE state, left = INT2FIX(1), seed = INT2FIX(0); 00652 VALUE *ary; 00653 unsigned long x; 00654 00655 Check_Type(dump, T_ARRAY); 00656 ary = RARRAY_PTR(dump); 00657 switch (RARRAY_LEN(dump)) { 00658 case 3: 00659 seed = ary[2]; 00660 case 2: 00661 left = ary[1]; 00662 case 1: 00663 state = ary[0]; 00664 break; 00665 default: 00666 rb_raise(rb_eArgError, "wrong dump data"); 00667 } 00668 memset(mt->state, 0, sizeof(mt->state)); 00669 if (FIXNUM_P(state)) { 00670 x = FIX2ULONG(state); 00671 mt->state[0] = (unsigned int)x; 00672 #if SIZEOF_LONG / SIZEOF_INT >= 2 00673 mt->state[1] = (unsigned int)(x >> BITSPERDIG); 00674 #endif 00675 #if SIZEOF_LONG / SIZEOF_INT >= 3 00676 mt->state[2] = (unsigned int)(x >> 2 * BITSPERDIG); 00677 #endif 00678 #if SIZEOF_LONG / SIZEOF_INT >= 4 00679 mt->state[3] = (unsigned int)(x >> 3 * BITSPERDIG); 00680 #endif 00681 } 00682 else { 00683 BDIGIT *d; 00684 long len; 00685 Check_Type(state, T_BIGNUM); 00686 len = RBIGNUM_LEN(state); 00687 if (len > roomof(sizeof(mt->state), SIZEOF_BDIGITS)) { 00688 len = roomof(sizeof(mt->state), SIZEOF_BDIGITS); 00689 } 00690 #if SIZEOF_BDIGITS < SIZEOF_INT 00691 else if (len % DIGSPERINT) { 00692 d = RBIGNUM_DIGITS(state) + len; 00693 # if DIGSPERINT == 2 00694 --len; 00695 x = *--d; 00696 # else 00697 x = 0; 00698 do { 00699 x = (x << BITSPERDIG) | *--d; 00700 } while (--len % DIGSPERINT); 00701 # endif 00702 mt->state[len / DIGSPERINT] = (unsigned int)x; 00703 } 00704 #endif 00705 if (len > 0) { 00706 d = BDIGITS(state) + len; 00707 do { 00708 --len; 00709 x = *--d; 00710 # if DIGSPERINT == 2 00711 --len; 00712 x = (x << BITSPERDIG) | *--d; 00713 # elif SIZEOF_BDIGITS < SIZEOF_INT 00714 do { 00715 x = (x << BITSPERDIG) | *--d; 00716 } while (--len % DIGSPERINT); 00717 # endif 00718 mt->state[len / DIGSPERINT] = (unsigned int)x; 00719 } while (len > 0); 00720 } 00721 } 00722 x = NUM2ULONG(left); 00723 if (x > numberof(mt->state)) { 00724 rb_raise(rb_eArgError, "wrong value"); 00725 } 00726 mt->left = (unsigned int)x; 00727 mt->next = mt->state + numberof(mt->state) - x + 1; 00728 rnd->seed = rb_to_int(seed); 00729 00730 return obj; 00731 } 00732 00733 /* 00734 * call-seq: 00735 * srand(number=0) -> old_seed 00736 * 00737 * Seeds the pseudorandom number generator to the value of 00738 * <i>number</i>. If <i>number</i> is omitted 00739 * or zero, seeds the generator using a combination of the time, the 00740 * process id, and a sequence number. (This is also the behavior if 00741 * <code>Kernel::rand</code> is called without previously calling 00742 * <code>srand</code>, but without the sequence.) By setting the seed 00743 * to a known value, scripts can be made deterministic during testing. 00744 * The previous seed value is returned. Also see <code>Kernel::rand</code>. 00745 */ 00746 00747 static VALUE 00748 rb_f_srand(int argc, VALUE *argv, VALUE obj) 00749 { 00750 VALUE seed, old; 00751 rb_random_t *r = &default_rand; 00752 00753 rb_secure(4); 00754 if (argc == 0) { 00755 seed = random_seed(); 00756 } 00757 else { 00758 rb_scan_args(argc, argv, "01", &seed); 00759 } 00760 old = r->seed; 00761 r->seed = rand_init(&r->mt, seed); 00762 00763 return old; 00764 } 00765 00766 static unsigned long 00767 make_mask(unsigned long x) 00768 { 00769 x = x | x >> 1; 00770 x = x | x >> 2; 00771 x = x | x >> 4; 00772 x = x | x >> 8; 00773 x = x | x >> 16; 00774 #if 4 < SIZEOF_LONG 00775 x = x | x >> 32; 00776 #endif 00777 return x; 00778 } 00779 00780 static unsigned long 00781 limited_rand(struct MT *mt, unsigned long limit) 00782 { 00783 /* mt must be initialized */ 00784 int i; 00785 unsigned long val, mask; 00786 00787 if (!limit) return 0; 00788 mask = make_mask(limit); 00789 retry: 00790 val = 0; 00791 for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) { 00792 if ((mask >> (i * 32)) & 0xffffffff) { 00793 val |= (unsigned long)genrand_int32(mt) << (i * 32); 00794 val &= mask; 00795 if (limit < val) 00796 goto retry; 00797 } 00798 } 00799 return val; 00800 } 00801 00802 static VALUE 00803 limited_big_rand(struct MT *mt, struct RBignum *limit) 00804 { 00805 /* mt must be initialized */ 00806 unsigned long mask, lim, rnd; 00807 struct RBignum *val; 00808 long i, len; 00809 int boundary; 00810 00811 len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4; 00812 val = (struct RBignum *)rb_big_clone((VALUE)limit); 00813 RBIGNUM_SET_SIGN(val, 1); 00814 #if SIZEOF_BDIGITS == 2 00815 # define BIG_GET32(big,i) \ 00816 (RBIGNUM_DIGITS(big)[(i)*2] | \ 00817 ((i)*2+1 < RBIGNUM_LEN(big) ? \ 00818 (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) : \ 00819 0)) 00820 # define BIG_SET32(big,i,d) \ 00821 ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \ 00822 ((i)*2+1 < RBIGNUM_LEN(big) ? \ 00823 (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) : \ 00824 0)) 00825 #else 00826 /* SIZEOF_BDIGITS == 4 */ 00827 # define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[i]) 00828 # define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[i] = (d)) 00829 #endif 00830 retry: 00831 mask = 0; 00832 boundary = 1; 00833 for (i = len-1; 0 <= i; i--) { 00834 lim = BIG_GET32(limit, i); 00835 mask = mask ? 0xffffffff : make_mask(lim); 00836 if (mask) { 00837 rnd = genrand_int32(mt) & mask; 00838 if (boundary) { 00839 if (lim < rnd) 00840 goto retry; 00841 if (rnd < lim) 00842 boundary = 0; 00843 } 00844 } 00845 else { 00846 rnd = 0; 00847 } 00848 BIG_SET32(val, i, (BDIGIT)rnd); 00849 } 00850 return rb_big_norm((VALUE)val); 00851 } 00852 00853 unsigned long 00854 rb_rand_internal(unsigned long i) 00855 { 00856 struct MT *mt = default_mt(); 00857 return limited_rand(mt, i); 00858 } 00859 00860 unsigned int 00861 rb_random_int32(VALUE obj) 00862 { 00863 rb_random_t *rnd = get_rnd(obj); 00864 return genrand_int32(&rnd->mt); 00865 } 00866 00867 double 00868 rb_random_real(VALUE obj) 00869 { 00870 rb_random_t *rnd = get_rnd(obj); 00871 return genrand_real(&rnd->mt); 00872 } 00873 00874 /* 00875 * call-seq: prng.bytes(size) -> prng 00876 * 00877 * Returns a random binary string. The argument size specified the length of 00878 * the result string. 00879 */ 00880 static VALUE 00881 random_bytes(VALUE obj, VALUE len) 00882 { 00883 return rb_random_bytes(obj, NUM2LONG(rb_to_int(len))); 00884 } 00885 00886 VALUE 00887 rb_random_bytes(VALUE obj, long n) 00888 { 00889 rb_random_t *rnd = get_rnd(obj); 00890 VALUE bytes = rb_str_new(0, n); 00891 char *ptr = RSTRING_PTR(bytes); 00892 unsigned int r, i; 00893 00894 for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) { 00895 r = genrand_int32(&rnd->mt); 00896 i = SIZEOF_INT32; 00897 do { 00898 *ptr++ = (char)r; 00899 r >>= CHAR_BIT; 00900 } while (--i); 00901 } 00902 if (n > 0) { 00903 r = genrand_int32(&rnd->mt); 00904 do { 00905 *ptr++ = (char)r; 00906 r >>= CHAR_BIT; 00907 } while (--n); 00908 } 00909 return bytes; 00910 } 00911 00912 static VALUE 00913 range_values(VALUE vmax, VALUE *begp, int *exclp) 00914 { 00915 VALUE end, r; 00916 00917 if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse; 00918 if (!rb_respond_to(end, id_minus)) return Qfalse; 00919 r = rb_funcall2(end, id_minus, 1, begp); 00920 if (NIL_P(r)) return Qfalse; 00921 return r; 00922 } 00923 00924 static VALUE 00925 rand_int(struct MT *mt, VALUE vmax, int restrictive) 00926 { 00927 /* mt must be initialized */ 00928 long max; 00929 unsigned long r; 00930 00931 if (FIXNUM_P(vmax)) { 00932 max = FIX2LONG(vmax); 00933 if (!max) return Qnil; 00934 if (max < 0) { 00935 if (restrictive) return Qnil; 00936 max = -max; 00937 } 00938 r = limited_rand(mt, (unsigned long)max - 1); 00939 return ULONG2NUM(r); 00940 } 00941 else { 00942 VALUE ret; 00943 if (rb_bigzero_p(vmax)) return Qnil; 00944 if (!RBIGNUM_SIGN(vmax)) { 00945 if (restrictive) return Qnil; 00946 vmax = rb_big_clone(vmax); 00947 RBIGNUM_SET_SIGN(vmax, 1); 00948 } 00949 vmax = rb_big_minus(vmax, INT2FIX(1)); 00950 if (FIXNUM_P(vmax)) { 00951 max = FIX2LONG(vmax); 00952 if (max == -1) return Qnil; 00953 r = limited_rand(mt, max); 00954 return LONG2NUM(r); 00955 } 00956 ret = limited_big_rand(mt, RBIGNUM(vmax)); 00957 RB_GC_GUARD(vmax); 00958 return ret; 00959 } 00960 } 00961 00962 static inline double 00963 float_value(VALUE v) 00964 { 00965 double x = RFLOAT_VALUE(v); 00966 if (isinf(x) || isnan(x)) { 00967 VALUE error = INT2FIX(EDOM); 00968 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError)); 00969 } 00970 return x; 00971 } 00972 00973 /* 00974 * call-seq: 00975 * prng.rand -> float 00976 * prng.rand(limit) -> number 00977 * 00978 * When the argument is an +Integer+ or a +Bignum+, it returns a 00979 * random integer greater than or equal to zero and less than the 00980 * argument. Unlike Random.rand, when the argument is a negative 00981 * integer or zero, it raises an ArgumentError. 00982 * 00983 * When the argument is a +Float+, it returns a random floating point 00984 * number between 0.0 and _max_, including 0.0 and excluding _max_. 00985 * 00986 * When the argument _limit_ is a +Range+, it returns a random 00987 * number where range.member?(number) == true. 00988 * prng.rand(5..9) #=> one of [5, 6, 7, 8, 9] 00989 * prng.rand(5...9) #=> one of [5, 6, 7, 8] 00990 * prng.rand(5.0..9.0) #=> between 5.0 and 9.0, including 9.0 00991 * prng.rand(5.0...9.0) #=> between 5.0 and 9.0, excluding 9.0 00992 * 00993 * +begin+/+end+ of the range have to have subtract and add methods. 00994 * 00995 * Otherwise, it raises an ArgumentError. 00996 */ 00997 static VALUE 00998 random_rand(int argc, VALUE *argv, VALUE obj) 00999 { 01000 rb_random_t *rnd = get_rnd(obj); 01001 VALUE vmax, beg = Qundef, v; 01002 int excl = 0; 01003 01004 if (argc == 0) { 01005 return rb_float_new(genrand_real(&rnd->mt)); 01006 } 01007 else if (argc != 1) { 01008 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc); 01009 } 01010 vmax = argv[0]; 01011 if (NIL_P(vmax)) { 01012 v = Qnil; 01013 } 01014 else if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) { 01015 v = rand_int(&rnd->mt, vmax = v, 1); 01016 } 01017 else if (v = rb_check_to_float(vmax), !NIL_P(v)) { 01018 double max = float_value(v); 01019 if (max > 0.0) 01020 v = rb_float_new(max * genrand_real(&rnd->mt)); 01021 else 01022 v = Qnil; 01023 } 01024 else if ((v = range_values(vmax, &beg, &excl)) != Qfalse) { 01025 vmax = v; 01026 if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) { 01027 long max; 01028 vmax = v; 01029 v = Qnil; 01030 if (FIXNUM_P(vmax)) { 01031 fixnum: 01032 if ((max = FIX2LONG(vmax) - excl) >= 0) { 01033 unsigned long r = limited_rand(&rnd->mt, (unsigned long)max); 01034 v = ULONG2NUM(r); 01035 } 01036 } 01037 else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) { 01038 vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax); 01039 if (FIXNUM_P(vmax)) { 01040 excl = 0; 01041 goto fixnum; 01042 } 01043 v = limited_big_rand(&rnd->mt, RBIGNUM(vmax)); 01044 } 01045 } 01046 else if (v = rb_check_to_float(vmax), !NIL_P(v)) { 01047 double max = float_value(v), r; 01048 v = Qnil; 01049 if (max > 0.0) { 01050 if (excl) { 01051 r = genrand_real(&rnd->mt); 01052 } 01053 else { 01054 r = genrand_real2(&rnd->mt); 01055 } 01056 v = rb_float_new(r * max); 01057 } 01058 else if (max == 0.0 && !excl) { 01059 v = rb_float_new(0.0); 01060 } 01061 } 01062 } 01063 else { 01064 v = Qnil; 01065 NUM2LONG(vmax); 01066 } 01067 if (NIL_P(v)) { 01068 VALUE mesg = rb_str_new_cstr("invalid argument - "); 01069 rb_str_append(mesg, rb_obj_as_string(argv[0])); 01070 rb_exc_raise(rb_exc_new3(rb_eArgError, mesg)); 01071 } 01072 if (beg == Qundef) return v; 01073 if (FIXNUM_P(beg) && FIXNUM_P(v)) { 01074 long x = FIX2LONG(beg) + FIX2LONG(v); 01075 return LONG2NUM(x); 01076 } 01077 switch (TYPE(v)) { 01078 case T_BIGNUM: 01079 return rb_big_plus(v, beg); 01080 case T_FLOAT: { 01081 VALUE f = rb_check_to_float(beg); 01082 if (!NIL_P(f)) { 01083 RFLOAT_VALUE(v) += RFLOAT_VALUE(f); 01084 return v; 01085 } 01086 } 01087 default: 01088 return rb_funcall2(beg, id_plus, 1, &v); 01089 } 01090 } 01091 01092 /* 01093 * call-seq: 01094 * prng1 == prng2 -> true or false 01095 * 01096 * Returns true if the generators' states equal. 01097 */ 01098 static VALUE 01099 random_equal(VALUE self, VALUE other) 01100 { 01101 rb_random_t *r1, *r2; 01102 if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse; 01103 r1 = get_rnd(self); 01104 r2 = get_rnd(other); 01105 if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse; 01106 if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse; 01107 if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse; 01108 if (r1->mt.left != r2->mt.left) return Qfalse; 01109 return Qtrue; 01110 } 01111 01112 /* 01113 * call-seq: 01114 * rand(max=0) -> number 01115 * 01116 * Converts <i>max</i> to an integer using max1 = 01117 * max<code>.to_i.abs</code>. If _max_ is +nil+ the result is zero, returns a 01118 * pseudorandom floating point number greater than or equal to 0.0 and 01119 * less than 1.0. Otherwise, returns a pseudorandom integer greater 01120 * than or equal to zero and less than max1. <code>Kernel::srand</code> 01121 * may be used to ensure repeatable sequences of random numbers between 01122 * different runs of the program. Ruby currently uses a modified 01123 * Mersenne Twister with a period of 2**19937-1. 01124 * 01125 * srand 1234 #=> 0 01126 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] 01127 * [ rand(10), rand(1000) ] #=> [6, 817] 01128 * srand 1234 #=> 1234 01129 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] 01130 */ 01131 01132 static VALUE 01133 rb_f_rand(int argc, VALUE *argv, VALUE obj) 01134 { 01135 VALUE vmax, r; 01136 struct MT *mt = default_mt(); 01137 01138 if (argc == 0) goto zero_arg; 01139 rb_scan_args(argc, argv, "01", &vmax); 01140 if (NIL_P(vmax)) goto zero_arg; 01141 vmax = rb_to_int(vmax); 01142 if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) { 01143 zero_arg: 01144 return DBL2NUM(genrand_real(mt)); 01145 } 01146 return r; 01147 } 01148 01149 static st_index_t hashseed; 01150 01151 static VALUE 01152 init_randomseed(struct MT *mt, unsigned int initial[DEFAULT_SEED_CNT]) 01153 { 01154 VALUE seed; 01155 fill_random_seed(initial); 01156 init_by_array(mt, initial, DEFAULT_SEED_CNT); 01157 seed = make_seed_value(initial); 01158 memset(initial, 0, DEFAULT_SEED_LEN); 01159 return seed; 01160 } 01161 01162 void 01163 Init_RandomSeed(void) 01164 { 01165 rb_random_t *r = &default_rand; 01166 unsigned int initial[DEFAULT_SEED_CNT]; 01167 struct MT *mt = &r->mt; 01168 VALUE seed = init_randomseed(mt, initial); 01169 01170 hashseed = genrand_int32(mt); 01171 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8 01172 hashseed <<= 32; 01173 hashseed |= genrand_int32(mt); 01174 #endif 01175 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8 01176 hashseed <<= 32; 01177 hashseed |= genrand_int32(mt); 01178 #endif 01179 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8 01180 hashseed <<= 32; 01181 hashseed |= genrand_int32(mt); 01182 #endif 01183 01184 rb_global_variable(&r->seed); 01185 r->seed = seed; 01186 } 01187 01188 st_index_t 01189 rb_hash_start(st_index_t h) 01190 { 01191 return st_hash_start(hashseed + h); 01192 } 01193 01194 static void 01195 Init_RandomSeed2(void) 01196 { 01197 VALUE seed = default_rand.seed; 01198 01199 if (RB_TYPE_P(seed, T_BIGNUM)) { 01200 RBASIC(seed)->klass = rb_cBignum; 01201 } 01202 } 01203 01204 void 01205 rb_reset_random_seed(void) 01206 { 01207 rb_random_t *r = &default_rand; 01208 uninit_genrand(&r->mt); 01209 r->seed = INT2FIX(0); 01210 } 01211 01212 void 01213 Init_Random(void) 01214 { 01215 Init_RandomSeed2(); 01216 rb_define_global_function("srand", rb_f_srand, -1); 01217 rb_define_global_function("rand", rb_f_rand, -1); 01218 01219 rb_cRandom = rb_define_class("Random", rb_cObject); 01220 rb_define_alloc_func(rb_cRandom, random_alloc); 01221 rb_define_method(rb_cRandom, "initialize", random_init, -1); 01222 rb_define_method(rb_cRandom, "rand", random_rand, -1); 01223 rb_define_method(rb_cRandom, "bytes", random_bytes, 1); 01224 rb_define_method(rb_cRandom, "seed", random_get_seed, 0); 01225 rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1); 01226 rb_define_method(rb_cRandom, "marshal_dump", random_dump, 0); 01227 rb_define_method(rb_cRandom, "marshal_load", random_load, 1); 01228 rb_define_private_method(rb_cRandom, "state", random_state, 0); 01229 rb_define_private_method(rb_cRandom, "left", random_left, 0); 01230 rb_define_method(rb_cRandom, "==", random_equal, 1); 01231 01232 rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1); 01233 rb_define_singleton_method(rb_cRandom, "rand", rb_f_rand, -1); 01234 rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0); 01235 rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0); 01236 rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0); 01237 } 01238
1.7.3