Use seed to store random number context.
This commit is contained in:
parent
2356741169
commit
889b9bfe07
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue