From 7ca61b3c9884aa5232f75b0c5ece36afe35f5fa3 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 1 Jul 2018 16:26:53 +0200 Subject: [PATCH] New command 'setseed' with function com_sseed to set the random number generator --- src/frontend/commands.c | 9 +++++ src/include/ngspice/randnumb.h | 5 +++ src/main.c | 6 ++-- src/maths/misc/randnumb.c | 66 ++++++++++++++++++++++++++++++++++ src/sharedspice.c | 14 +++----- 5 files changed, 88 insertions(+), 12 deletions(-) diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 40736f329..69f539193 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -83,6 +83,7 @@ #include "resource.h" #include "diff.h" #include "com_strcmp.h" +#include "ngspice/randnumb.h" #include "arg.h" @@ -193,6 +194,10 @@ struct comm spcp_coms[] = { { 040000, 0, 0, 0 }, E_DEFHMASK, 0, 1, NULL, "[vecname] : Change default scale of current working plot." } , + { "setseed", com_sseed, FALSE, FALSE, + { 04, 0, 0, 0 }, E_DEFHMASK, 0, 1, + NULL, + "[seed value] : Reset the random number generator with new seed value." } , { "transpose", com_transpose, FALSE, FALSE, { 040000, 040000, 040000, 040000 }, E_DEFHMASK, 1, LOTS, NULL, @@ -666,6 +671,10 @@ struct comm nutcp_coms[] = { { 040000, 0, 0, 0 }, E_DEFHMASK, 0, 1, NULL, "[vecname] : Change default scale of current working plot." } , + { "setseed", com_sseed, FALSE, FALSE, + { 04, 0, 0, 0 }, E_DEFHMASK, 0, 1, + NULL, + "[seed value] : Reset the random number generator with new seed value." } , { "transpose", com_transpose, FALSE, FALSE, { 040000, 040000, 040000, 040000 }, E_DEFHMASK, 1, LOTS, NULL, diff --git a/src/include/ngspice/randnumb.h b/src/include/ngspice/randnumb.h index d5c53c5e0..881175fcf 100644 --- a/src/include/ngspice/randnumb.h +++ b/src/include/ngspice/randnumb.h @@ -1,12 +1,17 @@ #ifndef ngspice_RANDNUMB_H #define ngspice_RANDNUMB_H +#include "ngspice/wordlist.h" +extern void com_sseed(wordlist *wl); +extern void setseedinfo(void); + /* initialize random number generators */ extern void initw(void); extern void checkseed(void); /* seed random or set by 'set rndseed=value'*/ extern double drand(void); extern double gauss0(void); +extern double gauss1(void); extern int poisson(double); extern double exprand(double); diff --git a/src/main.c b/src/main.c index daf41e0e5..55e1c931b 100644 --- a/src/main.c +++ b/src/main.c @@ -864,8 +864,10 @@ main(int argc, char **argv) cp_program = ft_sim->simulator; - srand((unsigned int) getpid()); - TausSeed(); + /* initialze random number generator with seed = 1 */ + int ii = 1; + cp_vset("rndseed", CP_NUM, &ii); + com_sseed(NULL); /* --- Process command line options --- */ for (;;) { diff --git a/src/maths/misc/randnumb.c b/src/maths/misc/randnumb.c index 6e8861289..b033b92d2 100644 --- a/src/maths/misc/randnumb.c +++ b/src/maths/misc/randnumb.c @@ -65,6 +65,7 @@ double CombLCGTaus(void); float CombLCGTaus2(void); void rgauss(double* py1, double* py2); +static bool seedinfo = FALSE; /* Check if a seed has been set by the command 'set rndseed=value' @@ -213,6 +214,23 @@ double gauss0(void) } } + +/*** gauss *** +to be reproducible, we just use one value per pass */ +double gauss1(void) +{ + double fac, r, v1, v2; + do { + v1 = 2.0 * CombLCGTaus() - 1.0; + v2 = 2.0 * CombLCGTaus() - 1.0; + r = v1 * v1 + v2 * v2; + } while (r >= 1.0); + /* printf("v1 %f, v2 %f\n", v1, v2); */ + fac = sqrt(-2.0 * log(r) / r); + return v2 * fac; +} + + /* Polar form of the Box-Muller generator for Gaussian distributed random variates. Generator will be fed with two uniformly distributed random variates. @@ -264,3 +282,51 @@ double exprand(double mean) expval = -log(CombLCGTaus()) * mean; return expval; } + + + +/* seed random number generators immediately +* command "setseed" +* take value of variable rndseed as seed +* command "setseed " +* seed with number +*/ +void +com_sseed(wordlist *wl) +{ + int newseed; + + if (wl == NULL) { + if (!cp_getvar("rndseed", CP_NUM, &newseed)) { + newseed = getpid(); + cp_vset("rndseed", CP_NUM, &newseed); + } + srand((unsigned int)newseed); + TausSeed(); + } + else if ((sscanf(wl->wl_word, " %d ", &newseed) != 1) || + (newseed <= 0) || (newseed > INT_MAX)) + { + fprintf(cp_err, + "\nWarning: Cannot use %s as seed!\n" + " Command 'setseed %s' ignored.\n\n", + wl->wl_word, wl->wl_word); + return; + } + else { + srand((unsigned int)newseed); + TausSeed(); + cp_vset("rndseed", CP_NUM, &newseed); + } + + if (seedinfo) + printf("\nSeed value for random number generator is set to %d\n", newseed); +} + + +void +setseedinfo(void) +{ + seedinfo = TRUE; +} + diff --git a/src/sharedspice.c b/src/sharedspice.c index f58bc1f00..7fb851757 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -648,8 +648,10 @@ ngSpice_Init(SendChar* printfcn, SendStat* statusfcn, ControlledExit* ngspiceexi /* program name*/ cp_program = ft_sim->simulator; - srand((unsigned int) getpid()); - TausSeed(); + /* initialze random number generator with seed = 1 */ + int ii = 1; + cp_vset("rndseed", CP_NUM, &ii); + com_sseed(NULL); /* set a boolean variable to be used in .control sections */ bool sm = TRUE; @@ -741,15 +743,7 @@ bot: fprintf (cp_out, "SoS %f, seed value: %ld\n", renormalize(), rseed); } #elif defined (WaGauss) - { - unsigned int rseed = 66; - if (!cp_getvar("rndseed", CP_NUM, &rseed, 0)) { - time_t acttime = time(NULL); - rseed = (unsigned int) acttime; - } - srand(rseed); initw(); - } #endif // com_version(NULL);