Skip to content

Commit

Permalink
integrate Mersenne Twister based random number generator from 1.9 ups…
Browse files Browse the repository at this point in the history
…tream

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@3519 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
lrz committed Feb 13, 2010
1 parent a6878c4 commit 6581400
Show file tree
Hide file tree
Showing 9 changed files with 1,040 additions and 189 deletions.
12 changes: 12 additions & 0 deletions bignum.c
Expand Up @@ -52,6 +52,12 @@ bigzero_p(VALUE x)
return 1;
}

int
rb_bigzero_p(VALUE x)
{
return BIGZEROP(x);
}

int
rb_cmpint(VALUE val, VALUE a, VALUE b)
{
Expand Down Expand Up @@ -696,6 +702,12 @@ rb_bignum_new_retained(const char *str)
return v;
}

VALUE
rb_big_new(long len, int sign)
{
return bignew(len, sign != 0);
}

const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";

static VALUE bigsqr(VALUE x);
Expand Down
6 changes: 5 additions & 1 deletion include/ruby/intern.h
Expand Up @@ -95,6 +95,8 @@ VALUE rb_cstr2inum(const char*, int);
VALUE rb_str2inum(VALUE, int);
VALUE rb_big2str(VALUE, int);
VALUE rb_big2str0(VALUE, int, int);
VALUE rb_big_new(long len, int sign);
int rb_bigzero_p(VALUE x);
SIGNED_VALUE rb_big2long(VALUE);
#define rb_big2int(x) rb_big2long(x)
VALUE rb_big2ulong(VALUE);
Expand Down Expand Up @@ -453,6 +455,7 @@ VALUE rb_String(VALUE);
VALUE rb_Array(VALUE);
double rb_cstr_to_dbl(const char*, int);
double rb_str_to_dbl(VALUE, int);
VALUE rb_check_to_float(VALUE val);
/* parse.y */
RUBY_EXTERN int ruby_sourceline;
RUBY_EXTERN char *ruby_sourcefile;
Expand Down Expand Up @@ -497,8 +500,9 @@ VALUE rb_detach_process(rb_pid_t pid);
void rb_range_extract(VALUE range, VALUE *begp, VALUE *endp, bool *exclude);
VALUE rb_range_new(VALUE, VALUE, int);
VALUE rb_range_beg_len(VALUE, long*, long*, long, int);
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp);
/* random.c */
unsigned long rb_genrand_int32(void);
unsigned int rb_genrand_int32(void);
double rb_genrand_real(void);
/* re.c */
#define rb_memcmp memcmp
Expand Down
2 changes: 2 additions & 0 deletions include/ruby/ruby.h
Expand Up @@ -580,6 +580,7 @@ __rb_float_value(VALUE v)
}
#define RFLOAT_VALUE(v) (__rb_float_value((VALUE)v))
#define DOUBLE2NUM(dbl) rb_float_new(dbl)
#define DBL2NUM DOUBLE2NUM

#if WITH_OBJC
struct RFixnum {
Expand Down Expand Up @@ -1130,6 +1131,7 @@ RUBY_EXTERN VALUE rb_cUnboundMethod;
RUBY_EXTERN VALUE rb_cISeq;
RUBY_EXTERN VALUE rb_cVM;
RUBY_EXTERN VALUE rb_cEnv;
RUBY_EXTERN VALUE rb_cRandom;

#if WITH_OBJC
RUBY_EXTERN VALUE rb_cCFString;
Expand Down
178 changes: 178 additions & 0 deletions mt.c
@@ -0,0 +1,178 @@
/*
* This is based on trimmed version of MT19937. To get the original version,
* contact <http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/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(mt, seed)
* or init_by_array(mt, 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
*/

#include <limits.h>
typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1];

/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfU /* constant vector a */
#define UMASK 0x80000000U /* most significant w-r bits */
#define LMASK 0x7fffffffU /* least significant r bits */
#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1U ? MATRIX_A : 0U))

enum {MT_MAX_STATE = N};

struct MT {
/* assume int is enough to store 32bits */
unsigned int state[N]; /* the array for the state vector */
unsigned int *next;
int left;
};

#define genrand_initialized(mt) ((mt)->next != 0)
#define uninit_genrand(mt) ((mt)->next = 0)

/* initializes state[N] with a seed */
static void
init_genrand(struct MT *mt, unsigned int s)
{
int j;
mt->state[0] = s & 0xffffffffU;
for (j=1; j<N; j++) {
mt->state[j] = (1812433253U * (mt->state[j-1] ^ (mt->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 */
mt->state[j] &= 0xffffffff; /* for >32 bit machines */
}
mt->left = 1;
mt->next = mt->state + N;
}

/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
static void
init_by_array(struct MT *mt, unsigned int init_key[], int key_length)
{
int i, j, k;
init_genrand(mt, 19650218U);
i=1; j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1664525U))
+ init_key[j] + j; /* non linear */
mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
i++; j++;
if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1566083941U))
- i; /* non linear */
mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
i++;
if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
}

mt->state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
}

static void
next_state(struct MT *mt)
{
unsigned int *p = mt->state;
int j;

/* if init_genrand() has not been called, */
/* a default initial seed is used */
if (!genrand_initialized(mt)) init_genrand(mt, 5489U);

mt->left = N;
mt->next = mt->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], mt->state[0]);
}

/* generates a random number on [0,0xffffffff]-interval */
static unsigned int
genrand_int32(struct MT *mt)
{
unsigned int y;

if (--mt->left <= 0) next_state(mt);
y = *mt->next++;

/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680;
y ^= (y << 15) & 0xefc60000;
y ^= (y >> 18);

return y;
}

/* generates a random number on [0,1) with 53-bit resolution*/
static double
genrand_real(struct MT *mt)
{
unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}

/* generates a random number on [0,1] with 53-bit resolution*/
// TODO
#define genrand_real2 genrand_real

/* These real versions are due to Isaku Wada, 2002/01/09 added */

#undef N
#undef M
12 changes: 12 additions & 0 deletions object.c
Expand Up @@ -2778,6 +2778,18 @@ rb_f_float(VALUE obj, SEL sel, VALUE arg)
return rb_Float(arg);
}

VALUE
rb_check_to_float(VALUE val)
{
if (TYPE(val) == T_FLOAT) {
return val;
}
if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
return Qnil;
}
return rb_check_convert_type(val, T_FLOAT, "Float", "to_f");
}

double
rb_num2dbl(VALUE val)
{
Expand Down

0 comments on commit 6581400

Please sign in to comment.