Ruby  1.9.3p448(2013-06-27revision41675)
random.c
Go to the documentation of this file.
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