From 889b9bfe074434aaa39fa7e340dcc99c6cfb78d3 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 14 May 2003 04:18:16 +0000 Subject: [PATCH] Use seed to store random number context. --- vpi/mt19937int.c | 25 +++++++++++++++++------- vpi/sys_priv.h | 16 +++++++++++++++- vpi/sys_random.c | 49 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/vpi/mt19937int.c b/vpi/mt19937int.c index 2b2d1f8aa..7757c6727 100644 --- a/vpi/mt19937int.c +++ b/vpi/mt19937int.c @@ -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; mtimti = 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;kkmti = 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. * diff --git a/vpi/sys_priv.h b/vpi/sys_priv.h index 7940968d6..ad3980755 100644 --- a/vpi/sys_priv.h +++ b/vpi/sys_priv.h @@ -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. * diff --git a/vpi/sys_random.c b/vpi/sys_random.c index 83e60b493..54acf89ee 100644 --- a/vpi/sys_random.c +++ b/vpi/sys_random.c @@ -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 # include @@ -28,10 +29,6 @@ # include # include -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. *