Use seed to store random number context.

This commit is contained in:
steve 2003-05-14 04:18:16 +00:00
parent 2356741169
commit 889b9bfe07
3 changed files with 71 additions and 19 deletions

View File

@ -11,7 +11,7 @@
* Change the function prototypes to use ANSI/ISO C syntax.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: mt19937int.c,v 1.3 2002/08/12 01:35:04 steve Exp $"
#ident "$Id: mt19937int.c,v 1.4 2003/05/14 04:18:16 steve Exp $"
#endif
/* A C-program for MT19937: Integer version (1998/4/6) */
@ -48,6 +48,7 @@
/* ACM Transactions on Modeling and Computer Simulation, */
/* Vol. 8, No. 1, January 1998, pp 3--30. */
#include "sys_priv.h"
/* Period parameters */
#define N 624
@ -64,13 +65,13 @@
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)
static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializing the array with a NONZERO seed */
void
sgenrand(unsigned long seed)
sgenrand(struct context_s *context, unsigned long seed)
{
unsigned long *mt = context->mt;
int mti;
/* setting initial seeds to mt[N] using */
/* the generator Line 25 of Table 1 in */
/* [KNUTH 1981, The Art of Computer Programming */
@ -78,20 +79,25 @@ sgenrand(unsigned long seed)
mt[0]= seed & 0xffffffff;
for (mti=1; mti<N; mti++)
mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
context->mti = mti;
}
unsigned long
genrand()
genrand(struct context_s *context)
{
unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
unsigned long *mt = context->mt;
int mti = context->mti;
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if sgenrand() has not been called, */
sgenrand(4357); /* a default initial seed is used */
sgenrand(context, 4357); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
@ -113,11 +119,16 @@ genrand()
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
y ^= TEMPERING_SHIFT_L(y);
context->mti = mti;
return y;
}
/*
* $Log: mt19937int.c,v $
* Revision 1.4 2003/05/14 04:18:16 steve
* Use seed to store random number context.
*
* Revision 1.3 2002/08/12 01:35:04 steve
* conditional ident string using autoconfig.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_priv.h,v 1.1 2002/08/15 02:12:20 steve Exp $"
#ident "$Id: sys_priv.h,v 1.2 2003/05/14 04:18:16 steve Exp $"
#endif
/*
@ -28,8 +28,22 @@
*/
extern int sys_vcd_dumpvars_compiletf(char*name);
/*
* Context structure for PRNG in mt19937int.c
*/
struct context_s {
int mti; /* the array for the state vector */
unsigned long mt[1023]; /* mti==N+1 means mt[N] is not init */
};
extern void sgenrand(struct context_s *context, unsigned long seed);
extern unsigned long genrand(struct context_s *context);
/*
* $Log: sys_priv.h,v $
* Revision 1.2 2003/05/14 04:18:16 steve
* Use seed to store random number context.
*
* Revision 1.1 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -17,10 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_random.c,v 1.5 2002/08/12 01:35:05 steve Exp $"
#ident "$Id: sys_random.c,v 1.6 2003/05/14 04:18:16 steve Exp $"
#endif
# include "config.h"
# include "sys_priv.h"
# include <vpi_user.h>
# include <assert.h>
@ -28,10 +29,6 @@
# include <math.h>
# include <limits.h>
extern void sgenrand(unsigned long seed);
extern unsigned long genrand(void);
static long rtl_dist_uniform(long*seed, long start, long end)
{
if (start >= end)
@ -104,12 +101,20 @@ static int sys_dist_uniform_sizetf(char*x)
* Implement the $random system function using the ``Mersenne
* Twister'' random number generator MT19937.
*/
/* make sure this matches N+1 in mti19937int.c */
#define NP1 624+1
static struct context_s global_context = { .mti = NP1 };
static int sys_random_calltf(char*name)
{
s_vpi_value val;
vpiHandle call_handle;
vpiHandle argv;
vpiHandle seed = 0;
int pseed;
struct context_s *context;
call_handle = vpi_handle(vpiSysTfCall, 0);
assert(call_handle);
@ -123,21 +128,40 @@ static int sys_random_calltf(char*name)
val.format = vpiIntVal;
vpi_get_value(seed, &val);
sgenrand(val.value.integer);
pseed = val.value.integer;
/* Since there is a seed use the current
context or create a new one */
context = (struct context_s *)vpi_get_userdata(call_handle);
if (!context) {
context = (struct context_s *)calloc(1, sizeof(*context));
context->mti = NP1;
assert(context);
/* squrrel away context */
vpi_put_userdata(call_handle, (void *)context);
}
/* If the argument is not the Icarus cookie, then
reseed context */
if (pseed != 0x1ca1ca1c)
sgenrand(context, pseed);
} else {
/* use global context */
context = &global_context;
}
val.format = vpiIntVal;
val.value.integer = genrand();
val.value.integer = genrand(context);
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
#if 0
/* mark seed with cookie */
if (seed) {
val.format = vpiIntVal;
val.value.integer = i_seed;
val.value.integer = 0x1ca1ca1c;
vpi_put_value(seed, &val, 0, vpiNoDelay);
}
#endif
return 0;
}
@ -170,6 +194,9 @@ void sys_random_register()
/*
* $Log: sys_random.c,v $
* Revision 1.6 2003/05/14 04:18:16 steve
* Use seed to store random number context.
*
* Revision 1.5 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*