diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-07-26 06:12:39 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-07-26 06:12:39 +0000 |
commit | 7194b66fb24db63dc2a23d3141ce25ad85d89777 (patch) | |
tree | 6e4a442522711c87eb3fc61bf81efc90af356394 /random.c | |
parent | 1d132e648dff057f0a5b42ddbc3704e7816213fc (diff) | |
download | ruby-7194b66fb24db63dc2a23d3141ce25ad85d89777.tar.gz |
* random.c: replace with Mersenne Twister RNG.
* eval.c (jump_tag_but_local_jump): preserve retval in
LocalJumpError exceptions.
* parse.y (command): no more check for "super outside of method".
* eval.c (rb_mod_define_method): should set last_class and
last_func in the block->frame.
* eval.c (error_handle): should handle TAG_THROW as well.
* parse.y (yylex): new decimal notation '0d4567'.
* parse.y (yylex): new octal notation '0o777'.
* parse.y (string_content): every string_content node should
return string only. use NODE_EVSTR to coercing.
* eval.c (rb_eval): NODE_EVSTR support.
* re.c (rb_reg_quote): avoid unnecessary string allocation.
* string.c (get_pat): quote metachracters before compiling a
string into a regex.
* string.c (rb_str_split_m): special treatment of strings of size
1, but AWK emulation. now uses get_pat().
* string.c (rb_str_match_m): quote metacharacters.
* string.c (rb_str_match2): ditto.
* ext/socket/socket.c (sock_addrinfo): make all 3 versions of
getaddrinfo happy. [ruby-core:00184]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'random.c')
-rw-r--r-- | random.c | 235 |
1 files changed, 155 insertions, 80 deletions
@@ -10,6 +10,131 @@ **********************************************************************/ +/* +This is based on trimmed version of MT19937. To get the original version, +contact <http://www.math.keio.ac.jp/~matumoto/emt.html>. + +The original copyright notice follows. + + A C-program for MT19937, with initialization improved 2002/2/10. + Coded by Takuji Nishimura and Makoto Matsumoto. + This is a faster version by taking Shawn Cokus's optimization, + Matthe Bellew's simplification, Isaku Wada's real version. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.keio.ac.jp/matumoto/emt.html + email: matumoto@math.keio.ac.jp +*/ + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0dfUL /* constant vector a */ +#define UMASK 0x80000000UL /* most significant w-r bits */ +#define LMASK 0x7fffffffUL /* least significant r bits */ +#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) +#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) + +static unsigned long state[N]; /* the array for the state vector */ +static int left = 1; +static int initf = 0; +static unsigned long *next; + +/* initializes state[N] with a seed */ +static void +init_genrand(s) + unsigned long s; +{ + int j; + state[0]= s & 0xffffffffUL; + for (j=1; j<N; j++) { + state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array state[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + state[j] &= 0xffffffffUL; /* for >32 bit machines */ + } + left = 1; initf = 1; +} + +static void +next_state() +{ + unsigned long *p=state; + int j; + + /* if init_genrand() has not been called, */ + /* a default initial seed is used */ + if (initf==0) init_genrand(5489UL); + + left = N; + next = state; + + for (j=N-M+1; --j; p++) + *p = p[M] ^ TWIST(p[0], p[1]); + + for (j=M; --j; p++) + *p = p[M-N] ^ TWIST(p[0], p[1]); + + *p = p[M-N] ^ TWIST(p[0], state[0]); +} + +/* generates a random number on [0,1)-real-interval */ +static double +genrand_real() +{ + unsigned long y; + + if (--left == 0) next_state(); + y = *next++; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return (double)y * (1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* These real versions are due to Isaku Wada, 2002/01/09 added */ + #include "ruby.h" #ifdef HAVE_UNISTD_H @@ -27,84 +152,33 @@ struct timeval { #endif #endif /* NT */ -#ifdef HAVE_STDLIB_H -# include <stdlib.h> -#endif - -/* - * Prefer to use drand48, otherwise use random, or rand as a last resort. - */ -#ifdef HAVE_DRAND48 - -#ifndef HAVE_DRAND48_DECL -double drand48 _((void)); -void srand48 _((long)); -#endif - -#define SRANDOM(s) srand48((long)(s)) -#define RANDOM_NUMBER drand48() - -#else /* not HAVE_DRAND48 */ - -/* - * The largest number returned by the random number generator is - * RANDOM_MAX. If we're using `rand' it's RAND_MAX, but if we're - * using `random' it's 2^31-1. - */ -#ifndef RANDOM_MAX -# ifndef HAVE_RANDOM -# define RANDOM_MAX RAND_MAX -# else -# define RANDOM_MAX 2147483647.0 -# endif -#endif - -#ifdef HAVE_RANDOM - -#define RANDOM random -#define SRANDOM srandom - -#else /* HAVE_RANDOM */ - -#define RANDOM rand -#define SRANDOM srand - -#endif /* HAVE_RANDOM */ - -/* 0 <= RANDOM_NUMBER < 1 */ -#define RANDOM_NUMBER (((double)RANDOM())/((double)RANDOM_MAX+1)) - -#endif /* not HAVE_DRAND48 */ - static int first = 1; -#ifdef HAVE_INITSTATE -static char state[256]; -#endif static int rand_init(seed) - long seed; + unsigned long seed; { - int old; - static unsigned int saved_seed; + static unsigned long saved_seed; + unsigned long old; -#ifdef HAVE_INITSTATE - if (first == 1) { - initstate(1, state, sizeof state); - } - else { - setstate(state); - } -#endif first = 0; - - SRANDOM(seed); + init_genrand(seed); old = saved_seed; saved_seed = seed; return old; } +static unsigned long +random_seed() +{ + static int n = 0; + struct timeval tv; + + gettimeofday(&tv, 0); + return tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++; +} + static VALUE rb_f_srand(argc, argv, obj) int argc; @@ -112,18 +186,14 @@ rb_f_srand(argc, argv, obj) VALUE obj; { VALUE sd; - unsigned int seed, old; + unsigned long seed, old; rb_secure(4); if (rb_scan_args(argc, argv, "01", &sd) == 0) { - static int n = 0; - struct timeval tv; - - gettimeofday(&tv, 0); - seed = tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++; + seed = random_seed(); } else { - seed = NUM2UINT(sd); + seed = NUM2ULONG(sd); } old = rand_init(seed); @@ -141,10 +211,7 @@ rb_f_rand(argc, argv, obj) rb_scan_args(argc, argv, "01", &vmax); if (first) { - struct timeval tv; - - gettimeofday(&tv, 0); - rand_init(tv.tv_sec ^ tv.tv_usec ^ getpid()); + rand_init(random_seed()); } switch (TYPE(vmax)) { case T_FLOAT: @@ -155,7 +222,15 @@ rb_f_rand(argc, argv, obj) vmax = rb_dbl2big(RFLOAT(vmax)->value); /* fall through */ case T_BIGNUM: - return rb_big_rand(vmax, RANDOM_NUMBER); + { + long len = RBIGNUM(vmax)->len; + double *buf = ALLOCA_N(double, len); + + while (len--) { + buf[len] = genrand_real(); + } + return rb_big_rand(vmax, buf); + } case T_NIL: max = 0; break; @@ -165,11 +240,11 @@ rb_f_rand(argc, argv, obj) } if (max == 0) { - return rb_float_new(RANDOM_NUMBER); + return rb_float_new(genrand_real()); } - val = max*RANDOM_NUMBER; + if (max < 0) max = -max; + val = max*genrand_real(); - if (val < 0) val = -val; return LONG2NUM(val); } |