random.c

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

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7