new fcn sgauss(), new rnd-no generator
This commit is contained in:
parent
cc27e3f53f
commit
ba539d9ef1
|
|
@ -1,3 +1,8 @@
|
|||
2010-08-29 Holger Vogt
|
||||
* fteext.h, main.c, randnumb.c, parse.c, cmath2.c, cmath2.h:
|
||||
new function sgauss(), new random number generator with very
|
||||
high run length
|
||||
|
||||
2010-08-19 Holger Vogt
|
||||
* xpressn.c: bug no. 3047884 fixed
|
||||
inp.c: prevent crash if .param is last line in input deck
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ struct func ft_funcs[] = {
|
|||
{ "atan", cx_atan } ,
|
||||
{ "norm", cx_norm } ,
|
||||
{ "rnd", cx_rnd } ,
|
||||
{ "sgauss", cx_sgauss } ,
|
||||
{ "pos", cx_pos } ,
|
||||
{ "mean", cx_mean } ,
|
||||
{ "avg", cx_avg } , /* A.Roldan 03/06/05 incremental average new function */
|
||||
|
|
|
|||
|
|
@ -788,6 +788,7 @@ main(int argc, char **argv)
|
|||
cp_program = ft_sim->simulator;
|
||||
|
||||
srandom(getpid());
|
||||
TausSeed();
|
||||
|
||||
/* --- Process command line options --- */
|
||||
while (1) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ extern void srandom (unsigned int seed);
|
|||
#endif
|
||||
|
||||
extern void checkseed(void); /* seed random or set by 'set rndseed=value'*/
|
||||
extern double gauss(void); /* from randnumb.c */
|
||||
|
||||
static double *
|
||||
d_tan(double *dd, int length)
|
||||
|
|
@ -244,6 +245,38 @@ cx_rnd(void *data, short int type, int length, int *newlength, short int *newtyp
|
|||
}
|
||||
}
|
||||
|
||||
void *
|
||||
cx_sgauss(void *data, short int type, int length, int *newlength, short int *newtype)
|
||||
{
|
||||
*newlength = length;
|
||||
checkseed();
|
||||
if (type == VF_COMPLEX) {
|
||||
complex *c;
|
||||
complex *cc = (complex *) data;
|
||||
int i;
|
||||
|
||||
c = alloc_c(length);
|
||||
*newtype = VF_COMPLEX;
|
||||
for (i = 0; i < length; i++) {
|
||||
realpart(&c[i]) = gauss();
|
||||
imagpart(&c[i]) = gauss();
|
||||
}
|
||||
return ((void *) c);
|
||||
} else {
|
||||
double *d;
|
||||
double *dd = (double *) data;
|
||||
int i;
|
||||
|
||||
d = alloc_d(length);
|
||||
*newtype = VF_REAL;
|
||||
for (i = 0; i < length; i++) {
|
||||
d[i] = gauss();
|
||||
}
|
||||
return ((void *) d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Compute the avg of a vector.
|
||||
Created by A.M.Roldan 2005-05-21 */
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ void * cx_atan(void *data, short int type, int length, int *newlength, short int
|
|||
void * cx_norm(void *data, short int type, int length, int *newlength, short int *newtype);
|
||||
void * cx_uminus(void *data, short int type, int length, int *newlength, short int *newtype);
|
||||
void * cx_rnd(void *data, short int type, int length, int *newlength, short int *newtype);
|
||||
void * cx_sgauss(void *data, short int type, int length, int *newlength, short int *newtype);
|
||||
void * cx_mean(void *data, short int type, int length, int *newlength, short int *newtype);
|
||||
void * cx_length(void *data, short int type, int length, int *newlength, short int *newtype);
|
||||
void * cx_vector(void *data, short int type, int length, int *newlength, short int *newtype);
|
||||
|
|
|
|||
|
|
@ -6,9 +6,64 @@ Copyright 2008 Holger Vogt
|
|||
A fixed seed value may be set by 'set rndseed=value'.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
CombLCGTaus()
|
||||
Combined Tausworthe & LCG random number generator
|
||||
Algorithm has been suggested in:
|
||||
GPUGems 3, Addison Wesley, 2008, Chapter 37.
|
||||
It combines a three component Tausworthe generator taus88
|
||||
(see P. L'Ecuyer: "Maximally equidistributed combined Tausworthe
|
||||
generators", Mathematics of Computation, 1996,
|
||||
www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps)
|
||||
and a quick linear congruent generator (LCG), decribed in:
|
||||
Press: "Numerical recipes in C", Cambridge, 1992, p. 284.
|
||||
Generator has passed the bbattery_SmallCrush(gen) test of the
|
||||
TestU01 library from Pierre L’Ecuyer and Richard Simard,
|
||||
http://www.iro.umontreal.ca/~simardr/testu01/tu01.html
|
||||
*/
|
||||
|
||||
|
||||
/* TausSeed creates three start values for Tausworthe state variables.
|
||||
Uses rand() from <stdlib.h>, therefore values depend on the value of
|
||||
seed in srand(seed). A constant seed will result in a reproducible
|
||||
series of random variates.
|
||||
|
||||
Calling sequence:
|
||||
srand(seed);
|
||||
TausSeed();
|
||||
// generate random variates randvar uniformly distributed in
|
||||
// [0.0 .. 1.0[ by calls to CombLCGTaus().
|
||||
double randvar = CombLCGTaus(void);
|
||||
*/
|
||||
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cpdefs.h"
|
||||
#include "ftedefs.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/timeb.h>
|
||||
#include <stdarg.h> // var. argumente
|
||||
|
||||
/* Tausworthe state variables for double variates*/
|
||||
static unsigned CombState1 = 129, CombState2 = 130, CombState3 = 131;
|
||||
static unsigned CombState4; /* LCG state variable */
|
||||
|
||||
/* Tausworthe state variables for double variates*/
|
||||
static unsigned CombState5 = 133, CombState6 = 135, CombState7 = 137;
|
||||
static unsigned CombState8; /* LCG state variable */
|
||||
|
||||
unsigned TauS(unsigned *state, int C1, int C2, int C3, unsigned m);
|
||||
unsigned LGCS(unsigned *state, unsigned A1, unsigned A2);
|
||||
void TausSeed(void);
|
||||
|
||||
|
||||
|
||||
/* MINGW: random, srandom in libiberty.a, but not in libiberty.h */
|
||||
|
|
@ -35,6 +90,7 @@ void checkseed(void)
|
|||
if (cp_getvar("rndseed", CP_NUM, &newseed)) {
|
||||
if ((newseed > 0) && (oldseed != newseed)) {
|
||||
srandom(newseed);
|
||||
TausSeed();
|
||||
oldseed = newseed;
|
||||
printf("Seed value for random number generator is set to %d\n", newseed);
|
||||
}
|
||||
|
|
@ -51,6 +107,100 @@ double drand(void)
|
|||
}
|
||||
|
||||
|
||||
|
||||
void TausSeed(void)
|
||||
{
|
||||
CombState1 = CombState2 = CombState3 = 0;
|
||||
/* The Tausworthe initial states should be greater than 128 */
|
||||
while (CombState1 < 129)
|
||||
CombState1 = rand();
|
||||
while (CombState2 < 129)
|
||||
CombState2 = rand();
|
||||
while (CombState3 < 129)
|
||||
CombState3 = rand();
|
||||
while (CombState4 < 129)
|
||||
CombState4 = rand();
|
||||
#ifdef HVDEBUG
|
||||
printf("\nTausworthe Double generator init states: %d, %d, %d, %d\n",
|
||||
CombState1, CombState2, CombState3, CombState4);
|
||||
#endif
|
||||
CombState5 = CombState6 = CombState7 = 0;
|
||||
/* The Tausworthe initial states should be greater than 128 */
|
||||
while (CombState5 < 129)
|
||||
CombState5 = rand();
|
||||
while (CombState6 < 129)
|
||||
CombState6 = rand();
|
||||
while (CombState7 < 129)
|
||||
CombState7 = rand();
|
||||
while (CombState8 < 129)
|
||||
CombState8 = rand();
|
||||
#ifdef HVDEBUG
|
||||
printf("Tausworthe Integer generator init states: %d, %d, %d, %d\n",
|
||||
CombState5, CombState6, CombState7, CombState8);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned TauS(unsigned *state, int C1, int C2, int C3, unsigned m)
|
||||
{
|
||||
unsigned b = (((*state << C1) ^ *state) >> C2);
|
||||
return *state = (((*state & m) << C3) ^ b);
|
||||
}
|
||||
|
||||
unsigned LGCS(unsigned *state, unsigned A1, unsigned A2)
|
||||
{
|
||||
return *state = (A1 * *state + A2);
|
||||
}
|
||||
|
||||
|
||||
double CombLCGTaus()
|
||||
{
|
||||
return 2.3283064365387e-10 * (
|
||||
TauS(&CombState1, 13, 19, 12, 4294967294UL) ^
|
||||
TauS(&CombState2, 2, 25, 4, 4294967288UL) ^
|
||||
TauS(&CombState3, 3, 11, 17, 4294967280UL) ^
|
||||
LGCS(&CombState4, 1664525, 1013904223UL)
|
||||
);
|
||||
}
|
||||
|
||||
unsigned int CombLCGTausInt()
|
||||
{
|
||||
return (
|
||||
TauS(&CombState5, 13, 19, 12, 4294967294UL) ^
|
||||
TauS(&CombState6, 2, 25, 4, 4294967288UL) ^
|
||||
TauS(&CombState7, 3, 11, 17, 4294967280UL) ^
|
||||
LGCS(&CombState8, 1664525, 1013904223UL)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
float CombLCGTaus2()
|
||||
{
|
||||
unsigned long b;
|
||||
b = (((CombState1 << 13) ^ CombState1) >> 19);
|
||||
CombState1 = (((CombState1 & 4294967294UL) << 12) ^ b);
|
||||
b = (((CombState2 << 2) ^ CombState2) >> 25);
|
||||
CombState2 = (((CombState2 & 4294967288UL) << 4) ^ b);
|
||||
b = (((CombState3 << 3) ^ CombState3) >> 11);
|
||||
CombState3 = (((CombState3 & 4294967280UL) << 17) ^ b);
|
||||
CombState4 = (1664525 * CombState4 + 1013904223UL);
|
||||
return ((CombState1 ^ CombState2 ^ CombState3 ^ CombState4) * 2.3283064365387e-10f);
|
||||
}
|
||||
|
||||
|
||||
unsigned int CombLCGTausInt2()
|
||||
{
|
||||
unsigned long b;
|
||||
b = (((CombState5 << 13) ^ CombState5) >> 19);
|
||||
CombState5 = (((CombState5 & 4294967294UL) << 12) ^ b);
|
||||
b = (((CombState6 << 2) ^ CombState6) >> 25);
|
||||
CombState6 = (((CombState6 & 4294967288UL) << 4) ^ b);
|
||||
b = (((CombState7 << 3) ^ CombState7) >> 11);
|
||||
CombState7 = (((CombState7 & 4294967280UL) << 17) ^ b);
|
||||
CombState8 = (1664525 * CombState8 + 1013904223UL);
|
||||
return (CombState5 ^ CombState6 ^ CombState7 ^ CombState8);
|
||||
}
|
||||
|
||||
|
||||
/*** gauss ***/
|
||||
|
||||
double gauss(void)
|
||||
|
|
@ -60,7 +210,9 @@ double gauss(void)
|
|||
double fac,r,v1,v2;
|
||||
if (gliset) {
|
||||
do {
|
||||
v1 = drand(); v2 = drand();
|
||||
// v1 = drand(); v2 = drand();
|
||||
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); */
|
||||
|
|
@ -73,6 +225,3 @@ double gauss(void)
|
|||
return glgset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue