Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /********************************************************************** 00002 00003 random.c - 00004 00005 $Author: nagachika $ 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 typedef struct { 00222 VALUE seed; 00223 struct MT mt; 00224 } rb_random_t; 00225 00226 #define DEFAULT_SEED_CNT 4 00227 00228 static rb_random_t default_rand; 00229 00230 static VALUE rand_init(struct MT *mt, VALUE vseed); 00231 static VALUE random_seed(void); 00232 00233 static rb_random_t * 00234 rand_start(rb_random_t *r) 00235 { 00236 struct MT *mt = &r->mt; 00237 if (!genrand_initialized(mt)) { 00238 r->seed = rand_init(mt, random_seed()); 00239 } 00240 return r; 00241 } 00242 00243 static struct MT * 00244 default_mt(void) 00245 { 00246 return &rand_start(&default_rand)->mt; 00247 } 00248 00249 unsigned int 00250 rb_genrand_int32(void) 00251 { 00252 struct MT *mt = default_mt(); 00253 return genrand_int32(mt); 00254 } 00255 00256 double 00257 rb_genrand_real(void) 00258 { 00259 struct MT *mt = default_mt(); 00260 return genrand_real(mt); 00261 } 00262 00263 #define BDIGITS(x) (RBIGNUM_DIGITS(x)) 00264 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT) 00265 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG) 00266 #define DIGSPERINT (SIZEOF_INT/SIZEOF_BDIGITS) 00267 #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG) 00268 #define BIGDN(x) RSHIFT((x),BITSPERDIG) 00269 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1))) 00270 #define BDIGMAX ((BDIGIT)-1) 00271 00272 #define roomof(n, m) (int)(((n)+(m)-1) / (m)) 00273 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) 00274 #define SIZEOF_INT32 (31/CHAR_BIT + 1) 00275 00276 static double 00277 int_pair_to_real_inclusive(unsigned int a, unsigned int b) 00278 { 00279 VALUE x = rb_big_new(roomof(64, BITSPERDIG), 1); 00280 VALUE m = rb_big_new(roomof(53, BITSPERDIG), 1); 00281 BDIGIT *xd = BDIGITS(x); 00282 int i = 0; 00283 double r; 00284 00285 xd[i++] = (BDIGIT)b; 00286 #if BITSPERDIG < 32 00287 xd[i++] = (BDIGIT)(b >> BITSPERDIG); 00288 #endif 00289 xd[i++] = (BDIGIT)a; 00290 #if BITSPERDIG < 32 00291 xd[i++] = (BDIGIT)(a >> BITSPERDIG); 00292 #endif 00293 xd = BDIGITS(m); 00294 #if BITSPERDIG < 53 00295 MEMZERO(xd, BDIGIT, roomof(53, BITSPERDIG) - 1); 00296 #endif 00297 xd[53 / BITSPERDIG] = 1 << 53 % BITSPERDIG; 00298 xd[0] |= 1; 00299 x = rb_big_mul(x, m); 00300 if (FIXNUM_P(x)) { 00301 #if CHAR_BIT * SIZEOF_LONG > 64 00302 r = (double)(FIX2ULONG(x) >> 64); 00303 #else 00304 return 0.0; 00305 #endif 00306 } 00307 else { 00308 #if 64 % BITSPERDIG == 0 00309 long len = RBIGNUM_LEN(x); 00310 xd = BDIGITS(x); 00311 MEMMOVE(xd, xd + 64 / BITSPERDIG, BDIGIT, len - 64 / BITSPERDIG); 00312 MEMZERO(xd + len - 64 / BITSPERDIG, BDIGIT, 64 / BITSPERDIG); 00313 r = rb_big2dbl(x); 00314 #else 00315 x = rb_big_rshift(x, INT2FIX(64)); 00316 if (FIXNUM_P(x)) { 00317 r = (double)FIX2ULONG(x); 00318 } 00319 else { 00320 r = rb_big2dbl(x); 00321 } 00322 #endif 00323 } 00324 return ldexp(r, -53); 00325 } 00326 00327 VALUE rb_cRandom; 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: 00454 * Random.new(seed = Random.new_seed) -> prng 00455 * 00456 * Creates a new PRNG using +seed+ to set the initial state. If +seed+ is 00457 * omitted, the generator is initialized with Random.new_seed. 00458 * 00459 * See Random.srand for more information on the use of seed values. 00460 */ 00461 static VALUE 00462 random_init(int argc, VALUE *argv, VALUE obj) 00463 { 00464 VALUE vseed; 00465 rb_random_t *rnd = get_rnd(obj); 00466 00467 if (argc == 0) { 00468 rb_check_frozen(obj); 00469 vseed = random_seed(); 00470 } 00471 else { 00472 rb_scan_args(argc, argv, "01", &vseed); 00473 rb_check_copyable(obj, vseed); 00474 } 00475 rnd->seed = rand_init(&rnd->mt, vseed); 00476 return obj; 00477 } 00478 00479 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int)) 00480 00481 #if defined(S_ISCHR) && !defined(DOSISH) 00482 # define USE_DEV_URANDOM 1 00483 #else 00484 # define USE_DEV_URANDOM 0 00485 #endif 00486 00487 static void 00488 fill_random_seed(unsigned int seed[DEFAULT_SEED_CNT]) 00489 { 00490 static int n = 0; 00491 struct timeval tv; 00492 #if USE_DEV_URANDOM 00493 int fd; 00494 struct stat statbuf; 00495 #elif defined(_WIN32) 00496 HCRYPTPROV prov; 00497 #endif 00498 00499 memset(seed, 0, DEFAULT_SEED_LEN); 00500 00501 #if USE_DEV_URANDOM 00502 if ((fd = rb_cloexec_open("/dev/urandom", O_RDONLY 00503 #ifdef O_NONBLOCK 00504 |O_NONBLOCK 00505 #endif 00506 #ifdef O_NOCTTY 00507 |O_NOCTTY 00508 #endif 00509 , 0)) >= 0) { 00510 rb_update_max_fd(fd); 00511 if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) { 00512 if (read(fd, seed, DEFAULT_SEED_LEN) < DEFAULT_SEED_LEN) { 00513 /* abandon */; 00514 } 00515 } 00516 close(fd); 00517 } 00518 #elif defined(_WIN32) 00519 if (CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 00520 CryptGenRandom(prov, DEFAULT_SEED_LEN, (void *)seed); 00521 CryptReleaseContext(prov, 0); 00522 } 00523 #endif 00524 00525 gettimeofday(&tv, 0); 00526 seed[0] ^= tv.tv_usec; 00527 seed[1] ^= (unsigned int)tv.tv_sec; 00528 #if SIZEOF_TIME_T > SIZEOF_INT 00529 seed[0] ^= (unsigned int)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT); 00530 #endif 00531 seed[2] ^= getpid() ^ (n++ << 16); 00532 seed[3] ^= (unsigned int)(VALUE)&seed; 00533 #if SIZEOF_VOIDP > SIZEOF_INT 00534 seed[2] ^= (unsigned int)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT); 00535 #endif 00536 } 00537 00538 static VALUE 00539 make_seed_value(const void *ptr) 00540 { 00541 const long len = DEFAULT_SEED_LEN/SIZEOF_BDIGITS; 00542 BDIGIT *digits; 00543 NEWOBJ_OF(big, struct RBignum, rb_cBignum, T_BIGNUM); 00544 00545 RBIGNUM_SET_SIGN(big, 1); 00546 rb_big_resize((VALUE)big, len + 1); 00547 digits = RBIGNUM_DIGITS(big); 00548 00549 MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN); 00550 00551 /* set leading-zero-guard if need. */ 00552 digits[len] = 00553 #if SIZEOF_INT32 / SIZEOF_BDIGITS > 1 00554 digits[len-2] <= 1 && digits[len-1] == 0 00555 #else 00556 digits[len-1] <= 1 00557 #endif 00558 ? 1 : 0; 00559 00560 return rb_big_norm((VALUE)big); 00561 } 00562 00563 /* 00564 * call-seq: Random.new_seed -> integer 00565 * 00566 * Returns an arbitrary seed value. This is used by Random.new 00567 * when no seed value is specified as an argument. 00568 * 00569 * Random.new_seed #=> 115032730400174366788466674494640623225 00570 */ 00571 static VALUE 00572 random_seed(void) 00573 { 00574 unsigned int buf[DEFAULT_SEED_CNT]; 00575 fill_random_seed(buf); 00576 return make_seed_value(buf); 00577 } 00578 00579 /* 00580 * call-seq: prng.seed -> integer 00581 * 00582 * Returns the seed value used to initialize the generator. This may be used to 00583 * initialize another generator with the same state at a later time, causing it 00584 * to produce the same sequence of numbers. 00585 * 00586 * prng1 = Random.new(1234) 00587 * prng1.seed #=> 1234 00588 * prng1.rand(100) #=> 47 00589 * 00590 * prng2 = Random.new(prng1.seed) 00591 * prng2.rand(100) #=> 47 00592 */ 00593 static VALUE 00594 random_get_seed(VALUE obj) 00595 { 00596 return get_rnd(obj)->seed; 00597 } 00598 00599 /* :nodoc: */ 00600 static VALUE 00601 random_copy(VALUE obj, VALUE orig) 00602 { 00603 rb_random_t *rnd1, *rnd2; 00604 struct MT *mt; 00605 00606 if (!OBJ_INIT_COPY(obj, orig)) return obj; 00607 00608 rnd1 = get_rnd(obj); 00609 rnd2 = get_rnd(orig); 00610 mt = &rnd1->mt; 00611 00612 *rnd1 = *rnd2; 00613 mt->next = mt->state + numberof(mt->state) - mt->left + 1; 00614 return obj; 00615 } 00616 00617 static VALUE 00618 mt_state(const struct MT *mt) 00619 { 00620 VALUE bigo = rb_big_new(sizeof(mt->state) / sizeof(BDIGIT), 1); 00621 BDIGIT *d = RBIGNUM_DIGITS(bigo); 00622 int i; 00623 00624 for (i = 0; i < numberof(mt->state); ++i) { 00625 unsigned int x = mt->state[i]; 00626 #if SIZEOF_BDIGITS < SIZEOF_INT32 00627 int j; 00628 for (j = 0; j < SIZEOF_INT32 / SIZEOF_BDIGITS; ++j) { 00629 *d++ = BIGLO(x); 00630 x = BIGDN(x); 00631 } 00632 #else 00633 *d++ = (BDIGIT)x; 00634 #endif 00635 } 00636 return rb_big_norm(bigo); 00637 } 00638 00639 /* :nodoc: */ 00640 static VALUE 00641 random_state(VALUE obj) 00642 { 00643 rb_random_t *rnd = get_rnd(obj); 00644 return mt_state(&rnd->mt); 00645 } 00646 00647 /* :nodoc: */ 00648 static VALUE 00649 random_s_state(VALUE klass) 00650 { 00651 return mt_state(&default_rand.mt); 00652 } 00653 00654 /* :nodoc: */ 00655 static VALUE 00656 random_left(VALUE obj) 00657 { 00658 rb_random_t *rnd = get_rnd(obj); 00659 return INT2FIX(rnd->mt.left); 00660 } 00661 00662 /* :nodoc: */ 00663 static VALUE 00664 random_s_left(VALUE klass) 00665 { 00666 return INT2FIX(default_rand.mt.left); 00667 } 00668 00669 /* :nodoc: */ 00670 static VALUE 00671 random_dump(VALUE obj) 00672 { 00673 rb_random_t *rnd = get_rnd(obj); 00674 VALUE dump = rb_ary_new2(3); 00675 00676 rb_ary_push(dump, mt_state(&rnd->mt)); 00677 rb_ary_push(dump, INT2FIX(rnd->mt.left)); 00678 rb_ary_push(dump, rnd->seed); 00679 00680 return dump; 00681 } 00682 00683 /* :nodoc: */ 00684 static VALUE 00685 random_load(VALUE obj, VALUE dump) 00686 { 00687 rb_random_t *rnd = get_rnd(obj); 00688 struct MT *mt = &rnd->mt; 00689 VALUE state, left = INT2FIX(1), seed = INT2FIX(0); 00690 VALUE *ary; 00691 unsigned long x; 00692 00693 rb_check_copyable(obj, dump); 00694 Check_Type(dump, T_ARRAY); 00695 ary = RARRAY_PTR(dump); 00696 switch (RARRAY_LEN(dump)) { 00697 case 3: 00698 seed = ary[2]; 00699 case 2: 00700 left = ary[1]; 00701 case 1: 00702 state = ary[0]; 00703 break; 00704 default: 00705 rb_raise(rb_eArgError, "wrong dump data"); 00706 } 00707 memset(mt->state, 0, sizeof(mt->state)); 00708 if (FIXNUM_P(state)) { 00709 x = FIX2ULONG(state); 00710 mt->state[0] = (unsigned int)x; 00711 #if SIZEOF_LONG / SIZEOF_INT >= 2 00712 mt->state[1] = (unsigned int)(x >> BITSPERDIG); 00713 #endif 00714 #if SIZEOF_LONG / SIZEOF_INT >= 3 00715 mt->state[2] = (unsigned int)(x >> 2 * BITSPERDIG); 00716 #endif 00717 #if SIZEOF_LONG / SIZEOF_INT >= 4 00718 mt->state[3] = (unsigned int)(x >> 3 * BITSPERDIG); 00719 #endif 00720 } 00721 else { 00722 BDIGIT *d; 00723 long len; 00724 Check_Type(state, T_BIGNUM); 00725 len = RBIGNUM_LEN(state); 00726 if (len > roomof(sizeof(mt->state), SIZEOF_BDIGITS)) { 00727 len = roomof(sizeof(mt->state), SIZEOF_BDIGITS); 00728 } 00729 #if SIZEOF_BDIGITS < SIZEOF_INT 00730 else if (len % DIGSPERINT) { 00731 d = RBIGNUM_DIGITS(state) + len; 00732 # if DIGSPERINT == 2 00733 --len; 00734 x = *--d; 00735 # else 00736 x = 0; 00737 do { 00738 x = (x << BITSPERDIG) | *--d; 00739 } while (--len % DIGSPERINT); 00740 # endif 00741 mt->state[len / DIGSPERINT] = (unsigned int)x; 00742 } 00743 #endif 00744 if (len > 0) { 00745 d = BDIGITS(state) + len; 00746 do { 00747 --len; 00748 x = *--d; 00749 # if DIGSPERINT == 2 00750 --len; 00751 x = (x << BITSPERDIG) | *--d; 00752 # elif SIZEOF_BDIGITS < SIZEOF_INT 00753 do { 00754 x = (x << BITSPERDIG) | *--d; 00755 } while (--len % DIGSPERINT); 00756 # endif 00757 mt->state[len / DIGSPERINT] = (unsigned int)x; 00758 } while (len > 0); 00759 } 00760 } 00761 x = NUM2ULONG(left); 00762 if (x > numberof(mt->state)) { 00763 rb_raise(rb_eArgError, "wrong value"); 00764 } 00765 mt->left = (unsigned int)x; 00766 mt->next = mt->state + numberof(mt->state) - x + 1; 00767 rnd->seed = rb_to_int(seed); 00768 00769 return obj; 00770 } 00771 00772 /* 00773 * call-seq: 00774 * srand(number = Random.new_seed) -> old_seed 00775 * 00776 * Seeds the system pseudo-random number generator, Random::DEFAULT, with 00777 * +number+. The previous seed value is returned. 00778 * 00779 * If +number+ is omitted, seeds the generator using a source of entropy 00780 * provided by the operating system, if available (/dev/urandom on Unix systems 00781 * or the RSA cryptographic provider on Windows), which is then combined with 00782 * the time, the process id, and a sequence number. 00783 * 00784 * srand may be used to ensure repeatable sequences of pseudo-random numbers 00785 * between different runs of the program. By setting the seed to a known value, 00786 * programs can be made deterministic during testing. 00787 * 00788 * srand 1234 # => 268519324636777531569100071560086917274 00789 * [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319] 00790 * [ rand(10), rand(1000) ] # => [4, 664] 00791 * srand 1234 # => 1234 00792 * [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319] 00793 */ 00794 00795 static VALUE 00796 rb_f_srand(int argc, VALUE *argv, VALUE obj) 00797 { 00798 VALUE seed, old; 00799 rb_random_t *r = &default_rand; 00800 00801 rb_secure(4); 00802 if (argc == 0) { 00803 seed = random_seed(); 00804 } 00805 else { 00806 rb_scan_args(argc, argv, "01", &seed); 00807 } 00808 old = r->seed; 00809 r->seed = rand_init(&r->mt, seed); 00810 00811 return old; 00812 } 00813 00814 static unsigned long 00815 make_mask(unsigned long x) 00816 { 00817 x = x | x >> 1; 00818 x = x | x >> 2; 00819 x = x | x >> 4; 00820 x = x | x >> 8; 00821 x = x | x >> 16; 00822 #if 4 < SIZEOF_LONG 00823 x = x | x >> 32; 00824 #endif 00825 return x; 00826 } 00827 00828 static unsigned long 00829 limited_rand(struct MT *mt, unsigned long limit) 00830 { 00831 /* mt must be initialized */ 00832 int i; 00833 unsigned long val, mask; 00834 00835 if (!limit) return 0; 00836 mask = make_mask(limit); 00837 retry: 00838 val = 0; 00839 for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) { 00840 if ((mask >> (i * 32)) & 0xffffffff) { 00841 val |= (unsigned long)genrand_int32(mt) << (i * 32); 00842 val &= mask; 00843 if (limit < val) 00844 goto retry; 00845 } 00846 } 00847 return val; 00848 } 00849 00850 static VALUE 00851 limited_big_rand(struct MT *mt, struct RBignum *limit) 00852 { 00853 /* mt must be initialized */ 00854 unsigned long mask, lim, rnd; 00855 struct RBignum *val; 00856 long i, len; 00857 int boundary; 00858 00859 len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4; 00860 val = (struct RBignum *)rb_big_clone((VALUE)limit); 00861 RBIGNUM_SET_SIGN(val, 1); 00862 #if SIZEOF_BDIGITS == 2 00863 # define BIG_GET32(big,i) \ 00864 (RBIGNUM_DIGITS(big)[(i)*2] | \ 00865 ((i)*2+1 < RBIGNUM_LEN(big) ? \ 00866 (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) : \ 00867 0)) 00868 # define BIG_SET32(big,i,d) \ 00869 ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \ 00870 ((i)*2+1 < RBIGNUM_LEN(big) ? \ 00871 (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) : \ 00872 0)) 00873 #else 00874 /* SIZEOF_BDIGITS == 4 */ 00875 # define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[(i)]) 00876 # define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[(i)] = (d)) 00877 #endif 00878 retry: 00879 mask = 0; 00880 boundary = 1; 00881 for (i = len-1; 0 <= i; i--) { 00882 lim = BIG_GET32(limit, i); 00883 mask = mask ? 0xffffffff : make_mask(lim); 00884 if (mask) { 00885 rnd = genrand_int32(mt) & mask; 00886 if (boundary) { 00887 if (lim < rnd) 00888 goto retry; 00889 if (rnd < lim) 00890 boundary = 0; 00891 } 00892 } 00893 else { 00894 rnd = 0; 00895 } 00896 BIG_SET32(val, i, (BDIGIT)rnd); 00897 } 00898 return rb_big_norm((VALUE)val); 00899 } 00900 00901 /* 00902 * Returns random unsigned long value in [0, +limit+]. 00903 * 00904 * Note that +limit+ is included, and the range of the argument and the 00905 * return value depends on environments. 00906 */ 00907 unsigned long 00908 rb_genrand_ulong_limited(unsigned long limit) 00909 { 00910 return limited_rand(default_mt(), limit); 00911 } 00912 00913 unsigned int 00914 rb_random_int32(VALUE obj) 00915 { 00916 rb_random_t *rnd = try_get_rnd(obj); 00917 if (!rnd) { 00918 #if SIZEOF_LONG * CHAR_BIT > 32 00919 VALUE lim = ULONG2NUM(0x100000000UL); 00920 #elif defined HAVE_LONG_LONG 00921 VALUE lim = ULL2NUM((LONG_LONG)0xffffffff+1); 00922 #else 00923 VALUE lim = rb_big_plus(ULONG2NUM(0xffffffff), INT2FIX(1)); 00924 #endif 00925 return (unsigned int)NUM2ULONG(rb_funcall2(obj, id_rand, 1, &lim)); 00926 } 00927 return genrand_int32(&rnd->mt); 00928 } 00929 00930 double 00931 rb_random_real(VALUE obj) 00932 { 00933 rb_random_t *rnd = try_get_rnd(obj); 00934 if (!rnd) { 00935 VALUE v = rb_funcall2(obj, id_rand, 0, 0); 00936 double d = NUM2DBL(v); 00937 if (d < 0.0) { 00938 rb_raise(rb_eRangeError, "random number too small %g", d); 00939 } 00940 else if (d >= 1.0) { 00941 rb_raise(rb_eRangeError, "random number too big %g", d); 00942 } 00943 return d; 00944 } 00945 return genrand_real(&rnd->mt); 00946 } 00947 00948 static inline VALUE 00949 ulong_to_num_plus_1(unsigned long n) 00950 { 00951 #if HAVE_LONG_LONG 00952 return ULL2NUM((LONG_LONG)n+1); 00953 #else 00954 if (n >= ULONG_MAX) { 00955 return rb_big_plus(ULONG2NUM(n), INT2FIX(1)); 00956 } 00957 return ULONG2NUM(n+1); 00958 #endif 00959 } 00960 00961 unsigned long 00962 rb_random_ulong_limited(VALUE obj, unsigned long limit) 00963 { 00964 rb_random_t *rnd = try_get_rnd(obj); 00965 if (!rnd) { 00966 extern int rb_num_negative_p(VALUE); 00967 VALUE lim = ulong_to_num_plus_1(limit); 00968 VALUE v = rb_funcall2(obj, id_rand, 1, &lim); 00969 unsigned long r = NUM2ULONG(v); 00970 if (rb_num_negative_p(v)) { 00971 rb_raise(rb_eRangeError, "random number too small %ld", r); 00972 } 00973 if (r > limit) { 00974 rb_raise(rb_eRangeError, "random number too big %ld", r); 00975 } 00976 return r; 00977 } 00978 return limited_rand(&rnd->mt, limit); 00979 } 00980 00981 /* 00982 * call-seq: prng.bytes(size) -> a_string 00983 * 00984 * Returns a random binary string containing +size+ bytes. 00985 * 00986 * random_string = Random.new.bytes(10) # => "\xD7:R\xAB?\x83\xCE\xFAkO" 00987 * random_string.size # => 10 00988 */ 00989 static VALUE 00990 random_bytes(VALUE obj, VALUE len) 00991 { 00992 return rb_random_bytes(obj, NUM2LONG(rb_to_int(len))); 00993 } 00994 00995 VALUE 00996 rb_random_bytes(VALUE obj, long n) 00997 { 00998 rb_random_t *rnd = try_get_rnd(obj); 00999 VALUE bytes; 01000 char *ptr; 01001 unsigned int r, i; 01002 01003 if (!rnd) { 01004 VALUE len = LONG2NUM(n); 01005 return rb_funcall2(obj, id_bytes, 1, &len); 01006 } 01007 bytes = rb_str_new(0, n); 01008 ptr = RSTRING_PTR(bytes); 01009 for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) { 01010 r = genrand_int32(&rnd->mt); 01011 i = SIZEOF_INT32; 01012 do { 01013 *ptr++ = (char)r; 01014 r >>= CHAR_BIT; 01015 } while (--i); 01016 } 01017 if (n > 0) { 01018 r = genrand_int32(&rnd->mt); 01019 do { 01020 *ptr++ = (char)r; 01021 r >>= CHAR_BIT; 01022 } while (--n); 01023 } 01024 return bytes; 01025 } 01026 01027 static VALUE 01028 range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp) 01029 { 01030 VALUE end, r; 01031 01032 if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse; 01033 if (endp) *endp = end; 01034 if (!rb_respond_to(end, id_minus)) return Qfalse; 01035 r = rb_funcall2(end, id_minus, 1, begp); 01036 if (NIL_P(r)) return Qfalse; 01037 return r; 01038 } 01039 01040 static VALUE 01041 rand_int(struct MT *mt, VALUE vmax, int restrictive) 01042 { 01043 /* mt must be initialized */ 01044 long max; 01045 unsigned long r; 01046 01047 if (FIXNUM_P(vmax)) { 01048 max = FIX2LONG(vmax); 01049 if (!max) return Qnil; 01050 if (max < 0) { 01051 if (restrictive) return Qnil; 01052 max = -max; 01053 } 01054 r = limited_rand(mt, (unsigned long)max - 1); 01055 return ULONG2NUM(r); 01056 } 01057 else { 01058 VALUE ret; 01059 if (rb_bigzero_p(vmax)) return Qnil; 01060 if (!RBIGNUM_SIGN(vmax)) { 01061 if (restrictive) return Qnil; 01062 vmax = rb_big_clone(vmax); 01063 RBIGNUM_SET_SIGN(vmax, 1); 01064 } 01065 vmax = rb_big_minus(vmax, INT2FIX(1)); 01066 if (FIXNUM_P(vmax)) { 01067 max = FIX2LONG(vmax); 01068 if (max == -1) return Qnil; 01069 r = limited_rand(mt, max); 01070 return LONG2NUM(r); 01071 } 01072 ret = limited_big_rand(mt, RBIGNUM(vmax)); 01073 RB_GC_GUARD(vmax); 01074 return ret; 01075 } 01076 } 01077 01078 static inline double 01079 float_value(VALUE v) 01080 { 01081 double x = RFLOAT_VALUE(v); 01082 if (isinf(x) || isnan(x)) { 01083 VALUE error = INT2FIX(EDOM); 01084 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError)); 01085 } 01086 return x; 01087 } 01088 01089 static inline VALUE 01090 rand_range(struct MT* mt, VALUE range) 01091 { 01092 VALUE beg = Qundef, end = Qundef, vmax, v; 01093 int excl = 0; 01094 01095 if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse) 01096 return Qfalse; 01097 if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) { 01098 long max; 01099 vmax = v; 01100 v = Qnil; 01101 if (FIXNUM_P(vmax)) { 01102 fixnum: 01103 if ((max = FIX2LONG(vmax) - excl) >= 0) { 01104 unsigned long r = limited_rand(mt, (unsigned long)max); 01105 v = ULONG2NUM(r); 01106 } 01107 } 01108 else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) { 01109 vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax); 01110 if (FIXNUM_P(vmax)) { 01111 excl = 0; 01112 goto fixnum; 01113 } 01114 v = limited_big_rand(mt, RBIGNUM(vmax)); 01115 } 01116 } 01117 else if (v = rb_check_to_float(vmax), !NIL_P(v)) { 01118 int scale = 1; 01119 double max = RFLOAT_VALUE(v), mid = 0.5, r; 01120 if (isinf(max)) { 01121 double min = float_value(rb_to_float(beg)) / 2.0; 01122 max = float_value(rb_to_float(end)) / 2.0; 01123 scale = 2; 01124 mid = max + min; 01125 max -= min; 01126 } 01127 else { 01128 float_value(v); 01129 } 01130 v = Qnil; 01131 if (max > 0.0) { 01132 if (excl) { 01133 r = genrand_real(mt); 01134 } 01135 else { 01136 r = genrand_real2(mt); 01137 } 01138 if (scale > 1) { 01139 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid); 01140 } 01141 v = rb_float_new(r * max); 01142 } 01143 else if (max == 0.0 && !excl) { 01144 v = rb_float_new(0.0); 01145 } 01146 } 01147 01148 if (FIXNUM_P(beg) && FIXNUM_P(v)) { 01149 long x = FIX2LONG(beg) + FIX2LONG(v); 01150 return LONG2NUM(x); 01151 } 01152 switch (TYPE(v)) { 01153 case T_NIL: 01154 break; 01155 case T_BIGNUM: 01156 return rb_big_plus(v, beg); 01157 case T_FLOAT: { 01158 VALUE f = rb_check_to_float(beg); 01159 if (!NIL_P(f)) { 01160 return DBL2NUM(RFLOAT_VALUE(v) + RFLOAT_VALUE(f)); 01161 } 01162 } 01163 default: 01164 return rb_funcall2(beg, id_plus, 1, &v); 01165 } 01166 01167 return v; 01168 } 01169 01170 static VALUE rand_random(int argc, VALUE *argv, rb_random_t *rnd); 01171 01172 /* 01173 * call-seq: 01174 * prng.rand -> float 01175 * prng.rand(max) -> number 01176 * 01177 * When +max+ is an Integer, +rand+ returns a random integer greater than 01178 * or equal to zero and less than +max+. Unlike Kernel.rand, when +max+ 01179 * is a negative integer or zero, +rand+ raises an ArgumentError. 01180 * 01181 * prng = Random.new 01182 * prng.rand(100) # => 42 01183 * 01184 * When +max+ is a Float, +rand+ returns a random floating point number 01185 * between 0.0 and +max+, including 0.0 and excluding +max+. 01186 * 01187 * prng.rand(1.5) # => 1.4600282860034115 01188 * 01189 * When +max+ is a Range, +rand+ returns a random number where 01190 * range.member?(number) == true. 01191 * 01192 * prng.rand(5..9) # => one of [5, 6, 7, 8, 9] 01193 * prng.rand(5...9) # => one of [5, 6, 7, 8] 01194 * prng.rand(5.0..9.0) # => between 5.0 and 9.0, including 9.0 01195 * prng.rand(5.0...9.0) # => between 5.0 and 9.0, excluding 9.0 01196 * 01197 * Both the beginning and ending values of the range must respond to subtract 01198 * (<tt>-</tt>) and add (<tt>+</tt>)methods, or rand will raise an 01199 * ArgumentError. 01200 */ 01201 static VALUE 01202 random_rand(int argc, VALUE *argv, VALUE obj) 01203 { 01204 return rand_random(argc, argv, get_rnd(obj)); 01205 } 01206 01207 static VALUE 01208 rand_random(int argc, VALUE *argv, rb_random_t *rnd) 01209 { 01210 VALUE vmax, v; 01211 01212 if (argc == 0) { 01213 return rb_float_new(genrand_real(&rnd->mt)); 01214 } 01215 else { 01216 rb_check_arity(argc, 0, 1); 01217 } 01218 vmax = argv[0]; 01219 if (NIL_P(vmax)) { 01220 v = Qnil; 01221 } 01222 else if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) { 01223 v = rand_int(&rnd->mt, v, 1); 01224 } 01225 else if (v = rb_check_to_float(vmax), !NIL_P(v)) { 01226 double max = float_value(v); 01227 if (max > 0.0) 01228 v = rb_float_new(max * genrand_real(&rnd->mt)); 01229 else 01230 v = Qnil; 01231 } 01232 else if ((v = rand_range(&rnd->mt, vmax)) != Qfalse) { 01233 /* nothing to do */ 01234 } 01235 else { 01236 v = Qnil; 01237 (void)NUM2LONG(vmax); 01238 } 01239 if (NIL_P(v)) { 01240 VALUE mesg = rb_str_new_cstr("invalid argument - "); 01241 rb_str_append(mesg, rb_obj_as_string(argv[0])); 01242 rb_exc_raise(rb_exc_new3(rb_eArgError, mesg)); 01243 } 01244 01245 return v; 01246 } 01247 01248 /* 01249 * call-seq: 01250 * prng1 == prng2 -> true or false 01251 * 01252 * Returns true if the two generators have the same internal state, otherwise 01253 * false. Equivalent generators will return the same sequence of 01254 * pseudo-random numbers. Two generators will generally have the same state 01255 * only if they were initialized with the same seed 01256 * 01257 * Random.new == Random.new # => false 01258 * Random.new(1234) == Random.new(1234) # => true 01259 * 01260 * and have the same invocation history. 01261 * 01262 * prng1 = Random.new(1234) 01263 * prng2 = Random.new(1234) 01264 * prng1 == prng2 # => true 01265 * 01266 * prng1.rand # => 0.1915194503788923 01267 * prng1 == prng2 # => false 01268 * 01269 * prng2.rand # => 0.1915194503788923 01270 * prng1 == prng2 # => true 01271 */ 01272 static VALUE 01273 random_equal(VALUE self, VALUE other) 01274 { 01275 rb_random_t *r1, *r2; 01276 if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse; 01277 r1 = get_rnd(self); 01278 r2 = get_rnd(other); 01279 if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse; 01280 if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse; 01281 if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse; 01282 if (r1->mt.left != r2->mt.left) return Qfalse; 01283 return Qtrue; 01284 } 01285 01286 /* 01287 * call-seq: 01288 * rand(max=0) -> number 01289 * 01290 * If called without an argument, or if <tt>max.to_i.abs == 0</tt>, rand 01291 * returns a pseudo-random floating point number between 0.0 and 1.0, 01292 * including 0.0 and excluding 1.0. 01293 * 01294 * rand #=> 0.2725926052826416 01295 * 01296 * When +max.abs+ is greater than or equal to 1, +rand+ returns a pseudo-random 01297 * integer greater than or equal to 0 and less than +max.to_i.abs+. 01298 * 01299 * rand(100) #=> 12 01300 * 01301 * When +max+ is a Range, +rand+ returns a random number where 01302 * range.member?(number) == true. 01303 * 01304 * Negative or floating point values for +max+ are allowed, but may give 01305 * surprising results. 01306 * 01307 * rand(-100) # => 87 01308 * rand(-0.5) # => 0.8130921818028143 01309 * rand(1.9) # equivalent to rand(1), which is always 0 01310 * 01311 * Kernel.srand may be used to ensure that sequences of random numbers are 01312 * reproducible between different runs of a program. 01313 * 01314 * See also Random.rand. 01315 */ 01316 01317 static VALUE 01318 rb_f_rand(int argc, VALUE *argv, VALUE obj) 01319 { 01320 VALUE v, vmax, r; 01321 struct MT *mt = default_mt(); 01322 01323 if (argc == 0) goto zero_arg; 01324 rb_scan_args(argc, argv, "01", &vmax); 01325 if (NIL_P(vmax)) goto zero_arg; 01326 if ((v = rand_range(mt, vmax)) != Qfalse) { 01327 return v; 01328 } 01329 vmax = rb_to_int(vmax); 01330 if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) { 01331 zero_arg: 01332 return DBL2NUM(genrand_real(mt)); 01333 } 01334 return r; 01335 } 01336 01337 /* 01338 * call-seq: 01339 * Random.rand -> float 01340 * Random.rand(max) -> number 01341 * 01342 * Alias of Random::DEFAULT.rand. 01343 */ 01344 01345 static VALUE 01346 random_s_rand(int argc, VALUE *argv, VALUE obj) 01347 { 01348 return rand_random(argc, argv, rand_start(&default_rand)); 01349 } 01350 01351 #define SIP_HASH_STREAMING 0 01352 #define sip_hash24 ruby_sip_hash24 01353 #if !defined _WIN32 && !defined BYTE_ORDER 01354 # ifdef WORDS_BIGENDIAN 01355 # define BYTE_ORDER BIG_ENDIAN 01356 # else 01357 # define BYTE_ORDER LITTLE_ENDIAN 01358 # endif 01359 # ifndef LITTLE_ENDIAN 01360 # define LITTLE_ENDIAN 1234 01361 # endif 01362 # ifndef BIG_ENDIAN 01363 # define BIG_ENDIAN 4321 01364 # endif 01365 #endif 01366 #include "siphash.c" 01367 01368 static st_index_t hashseed; 01369 static union { 01370 uint8_t key[16]; 01371 uint32_t u32[(16 * sizeof(uint8_t) - 1) / sizeof(uint32_t)]; 01372 } sipseed; 01373 01374 static VALUE 01375 init_randomseed(struct MT *mt, unsigned int initial[DEFAULT_SEED_CNT]) 01376 { 01377 VALUE seed; 01378 fill_random_seed(initial); 01379 init_by_array(mt, initial, DEFAULT_SEED_CNT); 01380 seed = make_seed_value(initial); 01381 memset(initial, 0, DEFAULT_SEED_LEN); 01382 return seed; 01383 } 01384 01385 void 01386 Init_RandomSeed(void) 01387 { 01388 rb_random_t *r = &default_rand; 01389 unsigned int initial[DEFAULT_SEED_CNT]; 01390 struct MT *mt = &r->mt; 01391 VALUE seed = init_randomseed(mt, initial); 01392 int i; 01393 01394 hashseed = genrand_int32(mt); 01395 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8 01396 hashseed <<= 32; 01397 hashseed |= genrand_int32(mt); 01398 #endif 01399 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8 01400 hashseed <<= 32; 01401 hashseed |= genrand_int32(mt); 01402 #endif 01403 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8 01404 hashseed <<= 32; 01405 hashseed |= genrand_int32(mt); 01406 #endif 01407 01408 for (i = 0; i < numberof(sipseed.u32); ++i) 01409 sipseed.u32[i] = genrand_int32(mt); 01410 01411 rb_global_variable(&r->seed); 01412 r->seed = seed; 01413 } 01414 01415 st_index_t 01416 rb_hash_start(st_index_t h) 01417 { 01418 return st_hash_start(hashseed + h); 01419 } 01420 01421 st_index_t 01422 rb_memhash(const void *ptr, long len) 01423 { 01424 sip_uint64_t h = sip_hash24(sipseed.key, ptr, len); 01425 #ifdef HAVE_UINT64_T 01426 return (st_index_t)h; 01427 #else 01428 return (st_index_t)(h.u32[0] ^ h.u32[1]); 01429 #endif 01430 } 01431 01432 static void 01433 Init_RandomSeed2(void) 01434 { 01435 VALUE seed = default_rand.seed; 01436 01437 if (RB_TYPE_P(seed, T_BIGNUM)) { 01438 RBASIC(seed)->klass = rb_cBignum; 01439 } 01440 } 01441 01442 void 01443 rb_reset_random_seed(void) 01444 { 01445 rb_random_t *r = &default_rand; 01446 uninit_genrand(&r->mt); 01447 r->seed = INT2FIX(0); 01448 } 01449 01450 /* 01451 * Document-class: Random 01452 * 01453 * Random provides an interface to Ruby's pseudo-random number generator, or 01454 * PRNG. The PRNG produces a deterministic sequence of bits which approximate 01455 * true randomness. The sequence may be represented by integers, floats, or 01456 * binary strings. 01457 * 01458 * The generator may be initialized with either a system-generated or 01459 * user-supplied seed value by using Random.srand. 01460 * 01461 * The class method Random.rand provides the base functionality of Kernel.rand 01462 * along with better handling of floating point values. These are both 01463 * interfaces to Random::DEFAULT, the Ruby system PRNG. 01464 * 01465 * Random.new will create a new PRNG with a state independent of 01466 * Random::DEFAULT, allowing multiple generators with different seed values or 01467 * sequence positions to exist simultaneously. Random objects can be 01468 * marshaled, allowing sequences to be saved and resumed. 01469 * 01470 * PRNGs are currently implemented as a modified Mersenne Twister with a period 01471 * of 2**19937-1. 01472 */ 01473 01474 void 01475 Init_Random(void) 01476 { 01477 Init_RandomSeed2(); 01478 rb_define_global_function("srand", rb_f_srand, -1); 01479 rb_define_global_function("rand", rb_f_rand, -1); 01480 01481 rb_cRandom = rb_define_class("Random", rb_cObject); 01482 rb_define_alloc_func(rb_cRandom, random_alloc); 01483 rb_define_method(rb_cRandom, "initialize", random_init, -1); 01484 rb_define_method(rb_cRandom, "rand", random_rand, -1); 01485 rb_define_method(rb_cRandom, "bytes", random_bytes, 1); 01486 rb_define_method(rb_cRandom, "seed", random_get_seed, 0); 01487 rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1); 01488 rb_define_private_method(rb_cRandom, "marshal_dump", random_dump, 0); 01489 rb_define_private_method(rb_cRandom, "marshal_load", random_load, 1); 01490 rb_define_private_method(rb_cRandom, "state", random_state, 0); 01491 rb_define_private_method(rb_cRandom, "left", random_left, 0); 01492 rb_define_method(rb_cRandom, "==", random_equal, 1); 01493 01494 { 01495 VALUE rand_default = TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand); 01496 rb_gc_register_mark_object(rand_default); 01497 rb_define_const(rb_cRandom, "DEFAULT", rand_default); 01498 } 01499 01500 rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1); 01501 rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1); 01502 rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0); 01503 rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0); 01504 rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0); 01505 01506 id_rand = rb_intern("rand"); 01507 id_bytes = rb_intern("bytes"); 01508 } 01509