Ruby 1.9.3p327(2012-11-10revision37606)
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 
00077 #ifdef _WIN32
00078 # if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0400
00079 #  undef _WIN32_WINNT
00080 #  define _WIN32_WINNT 0x400
00081 #  undef __WINCRYPT_H__
00082 # endif
00083 #include <wincrypt.h>
00084 #endif
00085 
00086 typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1];
00087 
00088 /* Period parameters */
00089 #define N 624
00090 #define M 397
00091 #define MATRIX_A 0x9908b0dfU    /* constant vector a */
00092 #define UMASK 0x80000000U       /* most significant w-r bits */
00093 #define LMASK 0x7fffffffU       /* least significant r bits */
00094 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
00095 #define TWIST(u,v) ((MIXBITS((u),(v)) >> 1) ^ ((v)&1U ? MATRIX_A : 0U))
00096 
00097 enum {MT_MAX_STATE = N};
00098 
00099 struct MT {
00100     /* assume int is enough to store 32bits */
00101     unsigned int state[N]; /* the array for the state vector  */
00102     unsigned int *next;
00103     int left;
00104 };
00105 
00106 #define genrand_initialized(mt) ((mt)->next != 0)
00107 #define uninit_genrand(mt) ((mt)->next = 0)
00108 
00109 /* initializes state[N] with a seed */
00110 static void
00111 init_genrand(struct MT *mt, unsigned int s)
00112 {
00113     int j;
00114     mt->state[0] = s & 0xffffffffU;
00115     for (j=1; j<N; j++) {
00116         mt->state[j] = (1812433253U * (mt->state[j-1] ^ (mt->state[j-1] >> 30)) + j);
00117         /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
00118         /* In the previous versions, MSBs of the seed affect   */
00119         /* only MSBs of the array state[].                     */
00120         /* 2002/01/09 modified by Makoto Matsumoto             */
00121         mt->state[j] &= 0xffffffff;  /* for >32 bit machines */
00122     }
00123     mt->left = 1;
00124     mt->next = mt->state + N;
00125 }
00126 
00127 /* initialize by an array with array-length */
00128 /* init_key is the array for initializing keys */
00129 /* key_length is its length */
00130 /* slight change for C++, 2004/2/26 */
00131 static void
00132 init_by_array(struct MT *mt, unsigned int init_key[], int key_length)
00133 {
00134     int i, j, k;
00135     init_genrand(mt, 19650218U);
00136     i=1; j=0;
00137     k = (N>key_length ? N : key_length);
00138     for (; k; k--) {
00139         mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1664525U))
00140           + init_key[j] + j; /* non linear */
00141         mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
00142         i++; j++;
00143         if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
00144         if (j>=key_length) j=0;
00145     }
00146     for (k=N-1; k; k--) {
00147         mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1566083941U))
00148           - i; /* non linear */
00149         mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
00150         i++;
00151         if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
00152     }
00153 
00154     mt->state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
00155 }
00156 
00157 static void
00158 next_state(struct MT *mt)
00159 {
00160     unsigned int *p = mt->state;
00161     int j;
00162 
00163     mt->left = N;
00164     mt->next = mt->state;
00165 
00166     for (j=N-M+1; --j; p++)
00167         *p = p[M] ^ TWIST(p[0], p[1]);
00168 
00169     for (j=M; --j; p++)
00170         *p = p[M-N] ^ TWIST(p[0], p[1]);
00171 
00172     *p = p[M-N] ^ TWIST(p[0], mt->state[0]);
00173 }
00174 
00175 /* generates a random number on [0,0xffffffff]-interval */
00176 static unsigned int
00177 genrand_int32(struct MT *mt)
00178 {
00179     /* mt must be initialized */
00180     unsigned int y;
00181 
00182     if (--mt->left <= 0) next_state(mt);
00183     y = *mt->next++;
00184 
00185     /* Tempering */
00186     y ^= (y >> 11);
00187     y ^= (y << 7) & 0x9d2c5680;
00188     y ^= (y << 15) & 0xefc60000;
00189     y ^= (y >> 18);
00190 
00191     return y;
00192 }
00193 
00194 /* generates a random number on [0,1) with 53-bit resolution*/
00195 static double
00196 genrand_real(struct MT *mt)
00197 {
00198     /* mt must be initialized */
00199     unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
00200     return(a*67108864.0+b)*(1.0/9007199254740992.0);
00201 }
00202 
00203 /* generates a random number on [0,1] with 53-bit resolution*/
00204 static double int_pair_to_real_inclusive(unsigned int a, unsigned int b);
00205 static double
00206 genrand_real2(struct MT *mt)
00207 {
00208     /* mt must be initialized */
00209     unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
00210     return int_pair_to_real_inclusive(a, b);
00211 }
00212 
00213 /* These real versions are due to Isaku Wada, 2002/01/09 added */
00214 
00215 #undef N
00216 #undef M
00217 
00218 /* These real versions are due to Isaku Wada, 2002/01/09 added */
00219 
00220 typedef struct {
00221     VALUE seed;
00222     struct MT mt;
00223 } rb_random_t;
00224 
00225 #define DEFAULT_SEED_CNT 4
00226 
00227 static rb_random_t default_rand;
00228 
00229 static VALUE rand_init(struct MT *mt, VALUE vseed);
00230 static VALUE random_seed(void);
00231 
00232 static rb_random_t *
00233 rand_start(rb_random_t *r)
00234 {
00235     struct MT *mt = &r->mt;
00236     if (!genrand_initialized(mt)) {
00237         r->seed = rand_init(mt, random_seed());
00238     }
00239     return r;
00240 }
00241 
00242 static struct MT *
00243 default_mt(void)
00244 {
00245     return &rand_start(&default_rand)->mt;
00246 }
00247 
00248 unsigned int
00249 rb_genrand_int32(void)
00250 {
00251     struct MT *mt = default_mt();
00252     return genrand_int32(mt);
00253 }
00254 
00255 double
00256 rb_genrand_real(void)
00257 {
00258     struct MT *mt = default_mt();
00259     return genrand_real(mt);
00260 }
00261 
00262 #define BDIGITS(x) (RBIGNUM_DIGITS(x))
00263 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
00264 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
00265 #define DIGSPERINT (SIZEOF_INT/SIZEOF_BDIGITS)
00266 #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
00267 #define BIGDN(x) RSHIFT((x),BITSPERDIG)
00268 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
00269 #define BDIGMAX ((BDIGIT)-1)
00270 
00271 #define roomof(n, m) (int)(((n)+(m)-1) / (m))
00272 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00273 #define SIZEOF_INT32 (31/CHAR_BIT + 1)
00274 
00275 static double
00276 int_pair_to_real_inclusive(unsigned int a, unsigned int b)
00277 {
00278     VALUE x = rb_big_new(roomof(64, BITSPERDIG), 1);
00279     VALUE m = rb_big_new(roomof(53, BITSPERDIG), 1);
00280     BDIGIT *xd = BDIGITS(x);
00281     int i = 0;
00282     double r;
00283 
00284     xd[i++] = (BDIGIT)b;
00285 #if BITSPERDIG < 32
00286     xd[i++] = (BDIGIT)(b >> BITSPERDIG);
00287 #endif
00288     xd[i++] = (BDIGIT)a;
00289 #if BITSPERDIG < 32
00290     xd[i++] = (BDIGIT)(a >> BITSPERDIG);
00291 #endif
00292     xd = BDIGITS(m);
00293 #if BITSPERDIG < 53
00294     MEMZERO(xd, BDIGIT, roomof(53, BITSPERDIG) - 1);
00295 #endif
00296     xd[53 / BITSPERDIG] = 1 << 53 % BITSPERDIG;
00297     xd[0] |= 1;
00298     x = rb_big_mul(x, m);
00299     if (FIXNUM_P(x)) {
00300 #if CHAR_BIT * SIZEOF_LONG > 64
00301         r = (double)(FIX2ULONG(x) >> 64);
00302 #else
00303         return 0.0;
00304 #endif
00305     }
00306     else {
00307 #if 64 % BITSPERDIG == 0
00308         long len = RBIGNUM_LEN(x);
00309         xd = BDIGITS(x);
00310         MEMMOVE(xd, xd + 64 / BITSPERDIG, BDIGIT, len - 64 / BITSPERDIG);
00311         MEMZERO(xd + len - 64 / BITSPERDIG, BDIGIT, 64 / BITSPERDIG);
00312         r = rb_big2dbl(x);
00313 #else
00314         x = rb_big_rshift(x, INT2FIX(64));
00315         if (FIXNUM_P(x)) {
00316             r = (double)FIX2ULONG(x);
00317         }
00318         else {
00319             r = rb_big2dbl(x);
00320         }
00321 #endif
00322     }
00323     return ldexp(r, -53);
00324 }
00325 
00326 VALUE rb_cRandom;
00327 static VALUE rb_Random_DEFAULT;
00328 #define id_minus '-'
00329 #define id_plus  '+'
00330 static ID id_rand, id_bytes;
00331 
00332 /* :nodoc: */
00333 static void
00334 random_mark(void *ptr)
00335 {
00336     rb_gc_mark(((rb_random_t *)ptr)->seed);
00337 }
00338 
00339 static void
00340 random_free(void *ptr)
00341 {
00342     if (ptr != &default_rand)
00343         xfree(ptr);
00344 }
00345 
00346 static size_t
00347 random_memsize(const void *ptr)
00348 {
00349     return ptr ? sizeof(rb_random_t) : 0;
00350 }
00351 
00352 static const rb_data_type_t random_data_type = {
00353     "random",
00354     {
00355         random_mark,
00356         random_free,
00357         random_memsize,
00358     },
00359 };
00360 
00361 static rb_random_t *
00362 get_rnd(VALUE obj)
00363 {
00364     rb_random_t *ptr;
00365     TypedData_Get_Struct(obj, rb_random_t, &random_data_type, ptr);
00366     return ptr;
00367 }
00368 
00369 static rb_random_t *
00370 try_get_rnd(VALUE obj)
00371 {
00372     if (obj == rb_cRandom) {
00373         return rand_start(&default_rand);
00374     }
00375     if (!rb_typeddata_is_kind_of(obj, &random_data_type)) return NULL;
00376     return DATA_PTR(obj);
00377 }
00378 
00379 /* :nodoc: */
00380 static VALUE
00381 random_alloc(VALUE klass)
00382 {
00383     rb_random_t *rnd;
00384     VALUE obj = TypedData_Make_Struct(klass, rb_random_t, &random_data_type, rnd);
00385     rnd->seed = INT2FIX(0);
00386     return obj;
00387 }
00388 
00389 static VALUE
00390 rand_init(struct MT *mt, VALUE vseed)
00391 {
00392     volatile VALUE seed;
00393     long blen = 0;
00394     long fixnum_seed;
00395     int i, j, len;
00396     unsigned int buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0;
00397 
00398     seed = rb_to_int(vseed);
00399     switch (TYPE(seed)) {
00400       case T_FIXNUM:
00401         len = 1;
00402         fixnum_seed = FIX2LONG(seed);
00403         if (fixnum_seed < 0)
00404             fixnum_seed = -fixnum_seed;
00405         buf[0] = (unsigned int)(fixnum_seed & 0xffffffff);
00406 #if SIZEOF_LONG > SIZEOF_INT32
00407         if ((long)(int32_t)fixnum_seed != fixnum_seed) {
00408             if ((buf[1] = (unsigned int)(fixnum_seed >> 32)) != 0) ++len;
00409         }
00410 #endif
00411         break;
00412       case T_BIGNUM:
00413         blen = RBIGNUM_LEN(seed);
00414         if (blen == 0) {
00415             len = 1;
00416         }
00417         else {
00418             if (blen > MT_MAX_STATE * SIZEOF_INT32 / SIZEOF_BDIGITS)
00419                 blen = MT_MAX_STATE * SIZEOF_INT32 / SIZEOF_BDIGITS;
00420             len = roomof((int)blen * SIZEOF_BDIGITS, SIZEOF_INT32);
00421         }
00422         /* allocate ints for init_by_array */
00423         if (len > numberof(buf0)) buf = ALLOC_N(unsigned int, len);
00424         memset(buf, 0, len * sizeof(*buf));
00425         len = 0;
00426         for (i = (int)(blen-1); 0 <= i; i--) {
00427             j = i * SIZEOF_BDIGITS / SIZEOF_INT32;
00428 #if SIZEOF_BDIGITS < SIZEOF_INT32
00429             buf[j] <<= BITSPERDIG;
00430 #endif
00431             buf[j] |= RBIGNUM_DIGITS(seed)[i];
00432             if (!len && buf[j]) len = j;
00433         }
00434         ++len;
00435         break;
00436       default:
00437         rb_raise(rb_eTypeError, "failed to convert %s into Integer",
00438                  rb_obj_classname(vseed));
00439     }
00440     if (len <= 1) {
00441         init_genrand(mt, buf[0]);
00442     }
00443     else {
00444         if (buf[len-1] == 1) /* remove leading-zero-guard */
00445             len--;
00446         init_by_array(mt, buf, len);
00447     }
00448     if (buf != buf0) xfree(buf);
00449     return seed;
00450 }
00451 
00452 /*
00453  * call-seq: Random.new([seed]) -> prng
00454  *
00455  * Creates new Mersenne Twister based pseudorandom number generator with
00456  * seed.  When the argument seed is omitted, the generator is initialized
00457  * with Random.new_seed.
00458  *
00459  * The argument seed is used to ensure repeatable sequences of random numbers
00460  * between different runs of the program.
00461  *
00462  *     prng = Random.new(1234)
00463  *     [ prng.rand, prng.rand ]   #=> [0.191519450378892, 0.622108771039832]
00464  *     [ prng.integer(10), prng.integer(1000) ]  #=> [4, 664]
00465  *     prng = Random.new(1234)
00466  *     [ prng.rand, prng.rand ]   #=> [0.191519450378892, 0.622108771039832]
00467  */
00468 static VALUE
00469 random_init(int argc, VALUE *argv, VALUE obj)
00470 {
00471     VALUE vseed;
00472     rb_random_t *rnd = get_rnd(obj);
00473 
00474     if (argc == 0) {
00475         vseed = random_seed();
00476     }
00477     else {
00478         rb_scan_args(argc, argv, "01", &vseed);
00479     }
00480     rnd->seed = rand_init(&rnd->mt, vseed);
00481     return obj;
00482 }
00483 
00484 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int))
00485 
00486 #if defined(S_ISCHR) && !defined(DOSISH)
00487 # define USE_DEV_URANDOM 1
00488 #else
00489 # define USE_DEV_URANDOM 0
00490 #endif
00491 
00492 static void
00493 fill_random_seed(unsigned int seed[DEFAULT_SEED_CNT])
00494 {
00495     static int n = 0;
00496     struct timeval tv;
00497 #if USE_DEV_URANDOM
00498     int fd;
00499     struct stat statbuf;
00500 #elif defined(_WIN32)
00501     HCRYPTPROV prov;
00502 #endif
00503 
00504     memset(seed, 0, DEFAULT_SEED_LEN);
00505 
00506 #if USE_DEV_URANDOM
00507     if ((fd = open("/dev/urandom", O_RDONLY
00508 #ifdef O_NONBLOCK
00509             |O_NONBLOCK
00510 #endif
00511 #ifdef O_NOCTTY
00512             |O_NOCTTY
00513 #endif
00514             )) >= 0) {
00515         rb_update_max_fd(fd);
00516         if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
00517             if (read(fd, seed, DEFAULT_SEED_LEN) < DEFAULT_SEED_LEN) {
00518                 /* abandon */;
00519             }
00520         }
00521         close(fd);
00522     }
00523 #elif defined(_WIN32)
00524     if (CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
00525         CryptGenRandom(prov, DEFAULT_SEED_LEN, (void *)seed);
00526         CryptReleaseContext(prov, 0);
00527     }
00528 #endif
00529 
00530     gettimeofday(&tv, 0);
00531     seed[0] ^= tv.tv_usec;
00532     seed[1] ^= (unsigned int)tv.tv_sec;
00533 #if SIZEOF_TIME_T > SIZEOF_INT
00534     seed[0] ^= (unsigned int)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT);
00535 #endif
00536     seed[2] ^= getpid() ^ (n++ << 16);
00537     seed[3] ^= (unsigned int)(VALUE)&seed;
00538 #if SIZEOF_VOIDP > SIZEOF_INT
00539     seed[2] ^= (unsigned int)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT);
00540 #endif
00541 }
00542 
00543 static VALUE
00544 make_seed_value(const void *ptr)
00545 {
00546     const long len = DEFAULT_SEED_LEN/SIZEOF_BDIGITS;
00547     BDIGIT *digits;
00548     NEWOBJ(big, struct RBignum);
00549     OBJSETUP(big, rb_cBignum, T_BIGNUM);
00550 
00551     RBIGNUM_SET_SIGN(big, 1);
00552     rb_big_resize((VALUE)big, len + 1);
00553     digits = RBIGNUM_DIGITS(big);
00554 
00555     MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN);
00556 
00557     /* set leading-zero-guard if need. */
00558     digits[len] =
00559 #if SIZEOF_INT32 / SIZEOF_BDIGITS > 1
00560         digits[len-2] <= 1 && digits[len-1] == 0
00561 #else
00562         digits[len-1] <= 1
00563 #endif
00564         ? 1 : 0;
00565 
00566     return rb_big_norm((VALUE)big);
00567 }
00568 
00569 /*
00570  * call-seq: Random.new_seed -> integer
00571  *
00572  * Returns arbitrary value for seed.
00573  */
00574 static VALUE
00575 random_seed(void)
00576 {
00577     unsigned int buf[DEFAULT_SEED_CNT];
00578     fill_random_seed(buf);
00579     return make_seed_value(buf);
00580 }
00581 
00582 /*
00583  * call-seq: prng.seed -> integer
00584  *
00585  * Returns the seed of the generator.
00586  */
00587 static VALUE
00588 random_get_seed(VALUE obj)
00589 {
00590     return get_rnd(obj)->seed;
00591 }
00592 
00593 /* :nodoc: */
00594 static VALUE
00595 random_copy(VALUE obj, VALUE orig)
00596 {
00597     rb_random_t *rnd1 = get_rnd(obj);
00598     rb_random_t *rnd2 = get_rnd(orig);
00599     struct MT *mt = &rnd1->mt;
00600 
00601     *rnd1 = *rnd2;
00602     mt->next = mt->state + numberof(mt->state) - mt->left + 1;
00603     return obj;
00604 }
00605 
00606 static VALUE
00607 mt_state(const struct MT *mt)
00608 {
00609     VALUE bigo = rb_big_new(sizeof(mt->state) / sizeof(BDIGIT), 1);
00610     BDIGIT *d = RBIGNUM_DIGITS(bigo);
00611     int i;
00612 
00613     for (i = 0; i < numberof(mt->state); ++i) {
00614         unsigned int x = mt->state[i];
00615 #if SIZEOF_BDIGITS < SIZEOF_INT32
00616         int j;
00617         for (j = 0; j < SIZEOF_INT32 / SIZEOF_BDIGITS; ++j) {
00618             *d++ = BIGLO(x);
00619             x = BIGDN(x);
00620         }
00621 #else
00622         *d++ = (BDIGIT)x;
00623 #endif
00624     }
00625     return rb_big_norm(bigo);
00626 }
00627 
00628 /* :nodoc: */
00629 static VALUE
00630 random_state(VALUE obj)
00631 {
00632     rb_random_t *rnd = get_rnd(obj);
00633     return mt_state(&rnd->mt);
00634 }
00635 
00636 /* :nodoc: */
00637 static VALUE
00638 random_s_state(VALUE klass)
00639 {
00640     return mt_state(&default_rand.mt);
00641 }
00642 
00643 /* :nodoc: */
00644 static VALUE
00645 random_left(VALUE obj)
00646 {
00647     rb_random_t *rnd = get_rnd(obj);
00648     return INT2FIX(rnd->mt.left);
00649 }
00650 
00651 /* :nodoc: */
00652 static VALUE
00653 random_s_left(VALUE klass)
00654 {
00655     return INT2FIX(default_rand.mt.left);
00656 }
00657 
00658 /* :nodoc: */
00659 static VALUE
00660 random_dump(VALUE obj)
00661 {
00662     rb_random_t *rnd = get_rnd(obj);
00663     VALUE dump = rb_ary_new2(3);
00664 
00665     rb_ary_push(dump, mt_state(&rnd->mt));
00666     rb_ary_push(dump, INT2FIX(rnd->mt.left));
00667     rb_ary_push(dump, rnd->seed);
00668 
00669     return dump;
00670 }
00671 
00672 /* :nodoc: */
00673 static VALUE
00674 random_load(VALUE obj, VALUE dump)
00675 {
00676     rb_random_t *rnd = get_rnd(obj);
00677     struct MT *mt = &rnd->mt;
00678     VALUE state, left = INT2FIX(1), seed = INT2FIX(0);
00679     VALUE *ary;
00680     unsigned long x;
00681 
00682     Check_Type(dump, T_ARRAY);
00683     ary = RARRAY_PTR(dump);
00684     switch (RARRAY_LEN(dump)) {
00685       case 3:
00686         seed = ary[2];
00687       case 2:
00688         left = ary[1];
00689       case 1:
00690         state = ary[0];
00691         break;
00692       default:
00693         rb_raise(rb_eArgError, "wrong dump data");
00694     }
00695     memset(mt->state, 0, sizeof(mt->state));
00696     if (FIXNUM_P(state)) {
00697         x = FIX2ULONG(state);
00698         mt->state[0] = (unsigned int)x;
00699 #if SIZEOF_LONG / SIZEOF_INT >= 2
00700         mt->state[1] = (unsigned int)(x >> BITSPERDIG);
00701 #endif
00702 #if SIZEOF_LONG / SIZEOF_INT >= 3
00703         mt->state[2] = (unsigned int)(x >> 2 * BITSPERDIG);
00704 #endif
00705 #if SIZEOF_LONG / SIZEOF_INT >= 4
00706         mt->state[3] = (unsigned int)(x >> 3 * BITSPERDIG);
00707 #endif
00708     }
00709     else {
00710         BDIGIT *d;
00711         long len;
00712         Check_Type(state, T_BIGNUM);
00713         len = RBIGNUM_LEN(state);
00714         if (len > roomof(sizeof(mt->state), SIZEOF_BDIGITS)) {
00715             len = roomof(sizeof(mt->state), SIZEOF_BDIGITS);
00716         }
00717 #if SIZEOF_BDIGITS < SIZEOF_INT
00718         else if (len % DIGSPERINT) {
00719             d = RBIGNUM_DIGITS(state) + len;
00720 # if DIGSPERINT == 2
00721             --len;
00722             x = *--d;
00723 # else
00724             x = 0;
00725             do {
00726                 x = (x << BITSPERDIG) | *--d;
00727             } while (--len % DIGSPERINT);
00728 # endif
00729             mt->state[len / DIGSPERINT] = (unsigned int)x;
00730         }
00731 #endif
00732         if (len > 0) {
00733             d = BDIGITS(state) + len;
00734             do {
00735                 --len;
00736                 x = *--d;
00737 # if DIGSPERINT == 2
00738                 --len;
00739                 x = (x << BITSPERDIG) | *--d;
00740 # elif SIZEOF_BDIGITS < SIZEOF_INT
00741                 do {
00742                     x = (x << BITSPERDIG) | *--d;
00743                 } while (--len % DIGSPERINT);
00744 # endif
00745                 mt->state[len / DIGSPERINT] = (unsigned int)x;
00746             } while (len > 0);
00747         }
00748     }
00749     x = NUM2ULONG(left);
00750     if (x > numberof(mt->state)) {
00751         rb_raise(rb_eArgError, "wrong value");
00752     }
00753     mt->left = (unsigned int)x;
00754     mt->next = mt->state + numberof(mt->state) - x + 1;
00755     rnd->seed = rb_to_int(seed);
00756 
00757     return obj;
00758 }
00759 
00760 /*
00761  *  call-seq:
00762  *     srand(number=0)    -> old_seed
00763  *
00764  *  Seeds the pseudorandom number generator to the value of
00765  *  <i>number</i>. If <i>number</i> is omitted,
00766  *  seeds the generator using a combination of the time, the
00767  *  process id, and a sequence number. (This is also the behavior if
00768  *  <code>Kernel::rand</code> is called without previously calling
00769  *  <code>srand</code>, but without the sequence.) By setting the seed
00770  *  to a known value, scripts can be made deterministic during testing.
00771  *  The previous seed value is returned. Also see <code>Kernel::rand</code>.
00772  */
00773 
00774 static VALUE
00775 rb_f_srand(int argc, VALUE *argv, VALUE obj)
00776 {
00777     VALUE seed, old;
00778     rb_random_t *r = &default_rand;
00779 
00780     rb_secure(4);
00781     if (argc == 0) {
00782         seed = random_seed();
00783     }
00784     else {
00785         rb_scan_args(argc, argv, "01", &seed);
00786     }
00787     old = r->seed;
00788     r->seed = rand_init(&r->mt, seed);
00789 
00790     return old;
00791 }
00792 
00793 static unsigned long
00794 make_mask(unsigned long x)
00795 {
00796     x = x | x >> 1;
00797     x = x | x >> 2;
00798     x = x | x >> 4;
00799     x = x | x >> 8;
00800     x = x | x >> 16;
00801 #if 4 < SIZEOF_LONG
00802     x = x | x >> 32;
00803 #endif
00804     return x;
00805 }
00806 
00807 static unsigned long
00808 limited_rand(struct MT *mt, unsigned long limit)
00809 {
00810     /* mt must be initialized */
00811     int i;
00812     unsigned long val, mask;
00813 
00814     if (!limit) return 0;
00815     mask = make_mask(limit);
00816   retry:
00817     val = 0;
00818     for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) {
00819         if ((mask >> (i * 32)) & 0xffffffff) {
00820             val |= (unsigned long)genrand_int32(mt) << (i * 32);
00821             val &= mask;
00822             if (limit < val)
00823                 goto retry;
00824         }
00825     }
00826     return val;
00827 }
00828 
00829 static VALUE
00830 limited_big_rand(struct MT *mt, struct RBignum *limit)
00831 {
00832     /* mt must be initialized */
00833     unsigned long mask, lim, rnd;
00834     struct RBignum *val;
00835     long i, len;
00836     int boundary;
00837 
00838     len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4;
00839     val = (struct RBignum *)rb_big_clone((VALUE)limit);
00840     RBIGNUM_SET_SIGN(val, 1);
00841 #if SIZEOF_BDIGITS == 2
00842 # define BIG_GET32(big,i) \
00843     (RBIGNUM_DIGITS(big)[(i)*2] | \
00844      ((i)*2+1 < RBIGNUM_LEN(big) ? \
00845       (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) : \
00846       0))
00847 # define BIG_SET32(big,i,d) \
00848     ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \
00849      ((i)*2+1 < RBIGNUM_LEN(big) ? \
00850       (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) : \
00851       0))
00852 #else
00853     /* SIZEOF_BDIGITS == 4 */
00854 # define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[(i)])
00855 # define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[(i)] = (d))
00856 #endif
00857   retry:
00858     mask = 0;
00859     boundary = 1;
00860     for (i = len-1; 0 <= i; i--) {
00861         lim = BIG_GET32(limit, i);
00862         mask = mask ? 0xffffffff : make_mask(lim);
00863         if (mask) {
00864             rnd = genrand_int32(mt) & mask;
00865             if (boundary) {
00866                 if (lim < rnd)
00867                     goto retry;
00868                 if (rnd < lim)
00869                     boundary = 0;
00870             }
00871         }
00872         else {
00873             rnd = 0;
00874         }
00875         BIG_SET32(val, i, (BDIGIT)rnd);
00876     }
00877     return rb_big_norm((VALUE)val);
00878 }
00879 
00880 /*
00881  * Returns random unsigned long value in [0, _limit_].
00882  *
00883  * Note that _limit_ is included, and the range of the argument and the
00884  * return value depends on environments.
00885  */
00886 unsigned long
00887 rb_genrand_ulong_limited(unsigned long limit)
00888 {
00889     return limited_rand(default_mt(), limit);
00890 }
00891 
00892 unsigned int
00893 rb_random_int32(VALUE obj)
00894 {
00895     rb_random_t *rnd = try_get_rnd(obj);
00896     if (!rnd) {
00897 #if SIZEOF_LONG * CHAR_BIT > 32
00898         VALUE lim = ULONG2NUM(0x100000000);
00899 #elif defined HAVE_LONG_LONG
00900         VALUE lim = ULL2NUM((LONG_LONG)0xffffffff+1);
00901 #else
00902         VALUE lim = rb_big_plus(ULONG2NUM(0xffffffff), INT2FIX(1));
00903 #endif
00904         return (unsigned int)NUM2ULONG(rb_funcall2(obj, id_rand, 1, &lim));
00905     }
00906     return genrand_int32(&rnd->mt);
00907 }
00908 
00909 double
00910 rb_random_real(VALUE obj)
00911 {
00912     rb_random_t *rnd = try_get_rnd(obj);
00913     if (!rnd) {
00914         VALUE v = rb_funcall2(obj, id_rand, 0, 0);
00915         double d = NUM2DBL(v);
00916         if (d < 0.0 || d >= 1.0) {
00917             rb_raise(rb_eRangeError, "random number too big %g", d);
00918         }
00919         return d;
00920     }
00921     return genrand_real(&rnd->mt);
00922 }
00923 
00924 /*
00925  * call-seq: prng.bytes(size) -> a_string
00926  *
00927  * Returns a random binary string.  The argument size specified the length of
00928  * the result string.
00929  */
00930 static VALUE
00931 random_bytes(VALUE obj, VALUE len)
00932 {
00933     return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
00934 }
00935 
00936 VALUE
00937 rb_random_bytes(VALUE obj, long n)
00938 {
00939     rb_random_t *rnd = try_get_rnd(obj);
00940     VALUE bytes;
00941     char *ptr;
00942     unsigned int r, i;
00943 
00944     if (!rnd) {
00945         VALUE len = LONG2NUM(n);
00946         return rb_funcall2(obj, id_bytes, 1, &len);
00947     }
00948     bytes = rb_str_new(0, n);
00949     ptr = RSTRING_PTR(bytes);
00950     for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) {
00951         r = genrand_int32(&rnd->mt);
00952         i = SIZEOF_INT32;
00953         do {
00954             *ptr++ = (char)r;
00955             r >>= CHAR_BIT;
00956         } while (--i);
00957     }
00958     if (n > 0) {
00959         r = genrand_int32(&rnd->mt);
00960         do {
00961             *ptr++ = (char)r;
00962             r >>= CHAR_BIT;
00963         } while (--n);
00964     }
00965     return bytes;
00966 }
00967 
00968 static VALUE
00969 range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
00970 {
00971     VALUE end, r;
00972 
00973     if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse;
00974     if (endp) *endp = end;
00975     if (!rb_respond_to(end, id_minus)) return Qfalse;
00976     r = rb_funcall2(end, id_minus, 1, begp);
00977     if (NIL_P(r)) return Qfalse;
00978     return r;
00979 }
00980 
00981 static VALUE
00982 rand_int(struct MT *mt, VALUE vmax, int restrictive)
00983 {
00984     /* mt must be initialized */
00985     long max;
00986     unsigned long r;
00987 
00988     if (FIXNUM_P(vmax)) {
00989         max = FIX2LONG(vmax);
00990         if (!max) return Qnil;
00991         if (max < 0) {
00992             if (restrictive) return Qnil;
00993             max = -max;
00994         }
00995         r = limited_rand(mt, (unsigned long)max - 1);
00996         return ULONG2NUM(r);
00997     }
00998     else {
00999         VALUE ret;
01000         if (rb_bigzero_p(vmax)) return Qnil;
01001         if (!RBIGNUM_SIGN(vmax)) {
01002             if (restrictive) return Qnil;
01003             vmax = rb_big_clone(vmax);
01004             RBIGNUM_SET_SIGN(vmax, 1);
01005         }
01006         vmax = rb_big_minus(vmax, INT2FIX(1));
01007         if (FIXNUM_P(vmax)) {
01008             max = FIX2LONG(vmax);
01009             if (max == -1) return Qnil;
01010             r = limited_rand(mt, max);
01011             return LONG2NUM(r);
01012         }
01013         ret = limited_big_rand(mt, RBIGNUM(vmax));
01014         RB_GC_GUARD(vmax);
01015         return ret;
01016     }
01017 }
01018 
01019 static inline double
01020 float_value(VALUE v)
01021 {
01022     double x = RFLOAT_VALUE(v);
01023     if (isinf(x) || isnan(x)) {
01024         VALUE error = INT2FIX(EDOM);
01025         rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
01026     }
01027     return x;
01028 }
01029 
01030 static inline VALUE
01031 rand_range(struct MT* mt, VALUE range)
01032 {
01033     VALUE beg = Qundef, end = Qundef, vmax, v;
01034     int excl = 0;
01035 
01036     if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse)
01037         return Qfalse;
01038     if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
01039         long max;
01040         vmax = v;
01041         v = Qnil;
01042         if (FIXNUM_P(vmax)) {
01043           fixnum:
01044             if ((max = FIX2LONG(vmax) - excl) >= 0) {
01045                 unsigned long r = limited_rand(mt, (unsigned long)max);
01046                 v = ULONG2NUM(r);
01047             }
01048         }
01049         else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
01050             vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
01051             if (FIXNUM_P(vmax)) {
01052                 excl = 0;
01053                 goto fixnum;
01054             }
01055             v = limited_big_rand(mt, RBIGNUM(vmax));
01056         }
01057     }
01058     else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
01059         int scale = 1;
01060         double max = RFLOAT_VALUE(v), mid = 0.5, r;
01061         if (isinf(max)) {
01062             double min = float_value(rb_to_float(beg)) / 2.0;
01063             max = float_value(rb_to_float(end)) / 2.0;
01064             scale = 2;
01065             mid = max + min;
01066             max -= min;
01067         }
01068         else {
01069             float_value(v);
01070         }
01071         v = Qnil;
01072         if (max > 0.0) {
01073             if (excl) {
01074                 r = genrand_real(mt);
01075             }
01076             else {
01077                 r = genrand_real2(mt);
01078             }
01079             if (scale > 1) {
01080                 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
01081             }
01082             v = rb_float_new(r * max);
01083         }
01084         else if (max == 0.0 && !excl) {
01085             v = rb_float_new(0.0);
01086         }
01087     }
01088 
01089     if (FIXNUM_P(beg) && FIXNUM_P(v)) {
01090         long x = FIX2LONG(beg) + FIX2LONG(v);
01091         return LONG2NUM(x);
01092     }
01093     switch (TYPE(v)) {
01094       case T_NIL:
01095         break;
01096       case T_BIGNUM:
01097         return rb_big_plus(v, beg);
01098       case T_FLOAT: {
01099         VALUE f = rb_check_to_float(beg);
01100         if (!NIL_P(f)) {
01101             RFLOAT_VALUE(v) += RFLOAT_VALUE(f);
01102             return v;
01103         }
01104       }
01105       default:
01106         return rb_funcall2(beg, id_plus, 1, &v);
01107     }
01108 
01109     return v;
01110 }
01111 
01112 /*
01113  * call-seq:
01114  *     prng.rand -> float
01115  *     prng.rand(limit) -> number
01116  *
01117  * When the argument is an +Integer+ or a +Bignum+, it returns a
01118  * random integer greater than or equal to zero and less than the
01119  * argument.  Unlike Random.rand, when the argument is a negative
01120  * integer or zero, it raises an ArgumentError.
01121  *
01122  * When the argument is a +Float+, it returns a random floating point
01123  * number between 0.0 and _max_, including 0.0 and excluding _max_.
01124  *
01125  * When the argument _limit_ is a +Range+, it returns a random
01126  * number where range.member?(number) == true.
01127  *     prng.rand(5..9)  #=> one of [5, 6, 7, 8, 9]
01128  *     prng.rand(5...9) #=> one of [5, 6, 7, 8]
01129  *     prng.rand(5.0..9.0) #=> between 5.0 and 9.0, including 9.0
01130  *     prng.rand(5.0...9.0) #=> between 5.0 and 9.0, excluding 9.0
01131  *
01132  * +begin+/+end+ of the range have to have subtract and add methods.
01133  *
01134  * Otherwise, it raises an ArgumentError.
01135  */
01136 static VALUE
01137 random_rand(int argc, VALUE *argv, VALUE obj)
01138 {
01139     rb_random_t *rnd = get_rnd(obj);
01140     VALUE vmax, v;
01141 
01142     if (argc == 0) {
01143         return rb_float_new(genrand_real(&rnd->mt));
01144     }
01145     else if (argc != 1) {
01146         rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
01147     }
01148     vmax = argv[0];
01149     if (NIL_P(vmax)) {
01150         v = Qnil;
01151     }
01152     else if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
01153         v = rand_int(&rnd->mt, v, 1);
01154     }
01155     else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
01156         double max = float_value(v);
01157         if (max > 0.0)
01158             v = rb_float_new(max * genrand_real(&rnd->mt));
01159         else
01160             v = Qnil;
01161     }
01162     else if ((v = rand_range(&rnd->mt, vmax)) != Qfalse) {
01163         /* nothing to do */
01164     }
01165     else {
01166         v = Qnil;
01167         (void)NUM2LONG(vmax);
01168     }
01169     if (NIL_P(v)) {
01170         VALUE mesg = rb_str_new_cstr("invalid argument - ");
01171         rb_str_append(mesg, rb_obj_as_string(argv[0]));
01172         rb_exc_raise(rb_exc_new3(rb_eArgError, mesg));
01173     }
01174 
01175     return v;
01176 }
01177 
01178 /*
01179  * call-seq:
01180  *     prng1 == prng2 -> true or false
01181  *
01182  * Returns true if the generators' states equal.
01183  */
01184 static VALUE
01185 random_equal(VALUE self, VALUE other)
01186 {
01187     rb_random_t *r1, *r2;
01188     if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse;
01189     r1 = get_rnd(self);
01190     r2 = get_rnd(other);
01191     if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse;
01192     if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse;
01193     if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse;
01194     if (r1->mt.left != r2->mt.left) return Qfalse;
01195     return Qtrue;
01196 }
01197 
01198 /*
01199  *  call-seq:
01200  *     rand(max=0)    -> number
01201  *
01202  *
01203  *  If <i>max</i> is +Range+, returns a pseudorandom number where
01204  *  range.member(number) == true.
01205  *
01206  *  Or else converts _max_ to an integer using max1 =
01207  *  max<code>.to_i.abs</code>.
01208  *
01209  *  Then if _max_ is +nil+ the result is zero, returns a pseudorandom floating
01210  *  point number greater than or equal to 0.0 and less than 1.0.
01211  *
01212  *  Otherwise, returns a pseudorandom integer greater than or equal to zero and
01213  *  less than max1.
01214  *
01215  *  <code>Kernel::srand</code> may be used to ensure repeatable sequences of
01216  *  random numbers between different runs of the program. Ruby currently uses
01217  *  a modified Mersenne Twister with a period of 2**19937-1.
01218  *
01219  *     srand 1234                 #=> 0
01220  *     [ rand,  rand ]            #=> [0.191519450163469, 0.49766366626136]
01221  *     [ rand(10), rand(1000) ]   #=> [6, 817]
01222  *     srand 1234                 #=> 1234
01223  *     [ rand,  rand ]            #=> [0.191519450163469, 0.49766366626136]
01224  */
01225 
01226 static VALUE
01227 rb_f_rand(int argc, VALUE *argv, VALUE obj)
01228 {
01229     VALUE v, vmax, r;
01230     struct MT *mt = default_mt();
01231 
01232     if (argc == 0) goto zero_arg;
01233     rb_scan_args(argc, argv, "01", &vmax);
01234     if (NIL_P(vmax)) goto zero_arg;
01235     if ((v = rand_range(mt, vmax)) != Qfalse) {
01236         return v;
01237     }
01238     vmax = rb_to_int(vmax);
01239     if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
01240       zero_arg:
01241         return DBL2NUM(genrand_real(mt));
01242     }
01243     return r;
01244 }
01245 
01246 /*
01247  *  call-seq:
01248  *     Random.rand -> float
01249  *     Random.rand(limit) -> number
01250  *
01251  *     Alias of _Random::DEFAULT.rand_.
01252  *
01253  */
01254 
01255 static VALUE
01256 random_s_rand(int argc, VALUE *argv, VALUE obj)
01257 {
01258     rand_start(&default_rand);
01259     return random_rand(argc, argv, rb_Random_DEFAULT);
01260 }
01261 
01262 #define SIP_HASH_STREAMING 0
01263 #define sip_hash24 ruby_sip_hash24
01264 #include "siphash.c"
01265 
01266 static st_index_t hashseed;
01267 static union {
01268     uint8_t key[16];
01269     uint32_t u32[(16 * sizeof(uint8_t) - 1) / sizeof(uint32_t)];
01270 } sipseed;
01271 
01272 static VALUE
01273 init_randomseed(struct MT *mt, unsigned int initial[DEFAULT_SEED_CNT])
01274 {
01275     VALUE seed;
01276     fill_random_seed(initial);
01277     init_by_array(mt, initial, DEFAULT_SEED_CNT);
01278     seed = make_seed_value(initial);
01279     memset(initial, 0, DEFAULT_SEED_LEN);
01280     return seed;
01281 }
01282 
01283 void
01284 Init_RandomSeed(void)
01285 {
01286     rb_random_t *r = &default_rand;
01287     unsigned int initial[DEFAULT_SEED_CNT];
01288     struct MT *mt = &r->mt;
01289     VALUE seed = init_randomseed(mt, initial);
01290     int i;
01291 
01292     hashseed = genrand_int32(mt);
01293 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8
01294     hashseed <<= 32;
01295     hashseed |= genrand_int32(mt);
01296 #endif
01297 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
01298     hashseed <<= 32;
01299     hashseed |= genrand_int32(mt);
01300 #endif
01301 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8
01302     hashseed <<= 32;
01303     hashseed |= genrand_int32(mt);
01304 #endif
01305 
01306     for (i = 0; i < numberof(sipseed.u32); ++i)
01307         sipseed.u32[i] = genrand_int32(mt);
01308 
01309     rb_global_variable(&r->seed);
01310     r->seed = seed;
01311 }
01312 
01313 st_index_t
01314 rb_hash_start(st_index_t h)
01315 {
01316     return st_hash_start(hashseed + h);
01317 }
01318 
01319 st_index_t
01320 rb_memhash(const void *ptr, long len)
01321 {
01322     sip_uint64_t h = sip_hash24(sipseed.key, ptr, len);
01323 #ifdef HAVE_UINT64_T
01324     return (st_index_t)h;
01325 #else
01326     return (st_index_t)(h.u32[0] ^ h.u32[1]);
01327 #endif
01328 }
01329 
01330 static void
01331 Init_RandomSeed2(void)
01332 {
01333     VALUE seed = default_rand.seed;
01334 
01335     if (RB_TYPE_P(seed, T_BIGNUM)) {
01336         RBASIC(seed)->klass = rb_cBignum;
01337     }
01338 }
01339 
01340 void
01341 rb_reset_random_seed(void)
01342 {
01343     rb_random_t *r = &default_rand;
01344     uninit_genrand(&r->mt);
01345     r->seed = INT2FIX(0);
01346 }
01347 
01348 void
01349 Init_Random(void)
01350 {
01351     Init_RandomSeed2();
01352     rb_define_global_function("srand", rb_f_srand, -1);
01353     rb_define_global_function("rand", rb_f_rand, -1);
01354 
01355     rb_cRandom = rb_define_class("Random", rb_cObject);
01356     rb_define_alloc_func(rb_cRandom, random_alloc);
01357     rb_define_method(rb_cRandom, "initialize", random_init, -1);
01358     rb_define_method(rb_cRandom, "rand", random_rand, -1);
01359     rb_define_method(rb_cRandom, "bytes", random_bytes, 1);
01360     rb_define_method(rb_cRandom, "seed", random_get_seed, 0);
01361     rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1);
01362     rb_define_method(rb_cRandom, "marshal_dump", random_dump, 0);
01363     rb_define_method(rb_cRandom, "marshal_load", random_load, 1);
01364     rb_define_private_method(rb_cRandom, "state", random_state, 0);
01365     rb_define_private_method(rb_cRandom, "left", random_left, 0);
01366     rb_define_method(rb_cRandom, "==", random_equal, 1);
01367 
01368     rb_Random_DEFAULT = TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand);
01369     rb_global_variable(&rb_Random_DEFAULT);
01370     rb_define_const(rb_cRandom, "DEFAULT", rb_Random_DEFAULT);
01371 
01372     rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1);
01373     rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1);
01374     rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0);
01375     rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0);
01376     rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0);
01377 
01378     id_rand = rb_intern("rand");
01379     id_bytes = rb_intern("bytes");
01380 }
01381