sp_random.cpp
Go to the documentation of this file.
1 /** @file sp_random.cpp Evaluating random variables */
2 
3 /*
4  FAU Discrete Event System Simulator
5 
6  Copyright (C) 2007 Christoph Doerr
7  Exclusive copyright is granted to Thomas Moor
8 
9 */
10 
11 #include "sp_random.h"
12 
13 #include <cmath>
14 
15 
16 
17 
18 namespace faudes {
19 
20 
21 
22 #define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */
23 #define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */
24 #define CHECK 399268537 /* DON'T CHANGE THIS VALUE */
25 #define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */
26 #define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */
27 #define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */
28 
29 static long ran_seed[STREAMS] = {DEFAULT}; /* current state of each stream */
30 static int ran_stream = 0; /* stream index, 0 is the default */
31 static int ran_initialized = 0; /* test for stream initialization */
32 
33 
34 //ran_plant_seeds(x)
35 void ran_plant_seeds(long x) {
36  const long Q = MODULUS / A256;
37  const long R = MODULUS % A256;
38  int j;
39  int s;
40  ran_initialized = 1;
41  s = ran_stream; /* remember the current stream */
42  ran_select_stream(0); /* change to stream 0 */
43  ran_put_seed(x); /* set seed[0] */
44  ran_stream = s; /* reset the current stream */
45  for (j = 1; j < STREAMS; j++) {
46  x = A256 * (ran_seed[j - 1] % Q) - R * (ran_seed[j - 1] / Q);
47  if (x > 0)
48  ran_seed[j] = x;
49  else
50  ran_seed[j] = x + MODULUS;
51  }
52 }
53 
54 //ran_put_seed(x)
55 void ran_put_seed(long seed) {
56  ran_seed[ran_stream] = seed;
57 }
58 
59 //ran_select_stream(index)
60 void ran_select_stream(int index) {
61  ran_stream = ((unsigned int) index) % STREAMS;
62  if ((ran_initialized == 0) && (ran_stream != 0)) /* protect against */
63  ran_plant_seeds(DEFAULT); /* un-initialized streams */
64 }
65 
66 //ran_init(seed)
67 void ran_init(long seed){
68  if(seed==0) seed = DEFAULT;
69  ran_select_stream(0); /* select the default stream */
70  ran_put_seed(seed);
71 }
72 
73 
74 // ran()
75 double ran(void){
76  const long Q = MODULUS / MULTIPLIER;
77  const long R = MODULUS % MULTIPLIER;
78  long t;
79 
80  t = MULTIPLIER * (ran_seed[ran_stream] % Q) - R * (ran_seed[ran_stream] / Q);
81  if (t > 0)
82  ran_seed[ran_stream] = t;
83  else
85  return ((double) ran_seed[ran_stream] / MODULUS);
86 
87 }
88 
89 
90 // ran_uniform(a,b)
91 double ran_uniform(double a, double b){
92  double q = ran();
93  q=a*(1-q)+b*q;
94  return q;
95 }
96 
97 // ran_uniform(a,b)
98 long ran_uniform_int(long a, long b){
99  double q = ran();
100  long i =(long) floor(((double) a)*(1-q)+((double)b)*q);
101  if(i>=b) i=b-1;
102  if(i< a) i=a;
103  return i;
104 }
105 
106 // ran_exponential(mu)
107 double ran_exponential(double mu){
108  double q=0;
109  while(q==0){
110  q=ran();
111  }
112  return -mu*log(q);
113 }
114 
115 // ran_expontial(mu, tossLB, tossUB)
116 double ran_exponential(double mu, Time::Type tossLB, Time::Type tossUB){
117  if(tossLB==tossUB){
118  FD_DS("Ran_exponential(): empty interval");
119  return Time::UnDef();
120  }
121  else{
122  double lb= -expm1(-(static_cast<double> (tossLB))/ mu);
123  double ub= -expm1(-(static_cast<double> (tossUB))/ mu);
124  double u=ran_uniform(lb,ub);
125  double ret=(-mu*(log(1-u)));
126  //FD_DS("Ran_exponential: lb="<<lb<<" ub="<<ub<<" u="<<u<<" ret="<<ret);
127  return ret;
128  }
129 }
130 
131 /* ran_gauss(mu, sigma, tossLB, tossUB) */
132 double ran_gauss(double mu, double sigma, Time::Type tossLB, Time::Type tossUB){
133  if(tossLB==tossUB){
134  FD_DS("Ran_gauss(): empty interval");
135  return Time::UnDef();
136  }
137  else{
138  //Transform to (0,1)-Normaldistribution
139  double ztossLB=(static_cast<double>(tossLB)-mu)/sigma;
140  double ztossUB=(static_cast<double>(tossUB)-mu)/sigma;
141  //Sample Boundaries
142  double zlb=ran_gaussian_cdf_P(ztossLB);
143  double zub=ran_gaussian_cdf_P(ztossUB);
144  double u=ran_uniform(zlb,zub);
145 
146  //FD_DS("Ran_gauss(): ztossLB="<<ztossLB<<" ztossUB="<<ztossUB << " zlb="<<zlb<<" zub="<<zub<<" -> u="<<u);
147 
148  //calculate inverse CDF (algorithm based on a rational approximation algorithm by Peter J. Acklam)
149  double zret;
150  static const double a[] =
151  {
152  -3.969683028665376e+01,
153  2.209460984245205e+02,
154  -2.759285104469687e+02,
155  1.383577518672690e+02,
156  -3.066479806614716e+01,
157  2.506628277459239e+00
158  };
159 
160  static const double b[] =
161  {
162  -5.447609879822406e+01,
163  1.615858368580409e+02,
164  -1.556989798598866e+02,
165  6.680131188771972e+01,
166  -1.328068155288572e+01
167  };
168 
169  static const double c[] =
170  {
171  -7.784894002430293e-03,
172  -3.223964580411365e-01,
173  -2.400758277161838e+00,
174  -2.549732539343734e+00,
175  4.374664141464968e+00,
176  2.938163982698783e+00
177  };
178 
179  static const double d[] =
180  {
181  7.784695709041462e-03,
182  3.224671290700398e-01,
183  2.445134137142996e+00,
184  3.754408661907416e+00
185  };
186  double q,r;
187  if(u<0 || u>1) zret=0.0;
188  else if (u==0){
189  FD_DS("Ran_gauss(): u="<<u<<"ret=HUGE_VAL");
190  return -HUGE_VAL;
191  }
192  else if (u==1){
193  FD_DS("Ran_gauss(): u="<<u<<"ret=-HUGE_VAL");
194  return HUGE_VAL;
195  }
196  else if (u<0.02425){
197  // Rational approximation for lower region
198  q = sqrt(-2*log(u));
199  zret=(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
200  ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
201  }
202  else if(u>0.97575){
203  // Rational approximation for upper region
204  q = sqrt(-2*log(1-u));
205  zret= -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
206  ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
207  }
208  else{
209  // Rational approximation for central region
210  q = u - 0.5;
211  r = q*q;
212  zret=(((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q /
213  (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1);
214  }
215  //Transform to (mu,sigma)-Distribution
216  double ret=(zret*sigma)+mu; //to_do: overflow protection
217  //FD_DS("Ran_gauss(): zret="<<zret<<" ret="<<ret);
218  return ret;
219  }
220 }
221 
222 
223 //ran_gaussian_cdf_P
224 double ran_gaussian_cdf_P(double x){
225  const double PI = 3.141592654;
226  const double b1 = 0.319381530;
227  const double b2 = -0.356563782;
228  const double b3 = 1.781477937;
229  const double b4 = -1.821255978;
230  const double b5 = 1.330274429;
231  const double p = 0.2316419;
232 
233  if(x >= 0.0) {
234  double t = 1.0 / (1.0 + p*x);
235  return (1.0 - (1/sqrt(2*PI))*exp(-x*x/2.0 )*t*
236  (t*(t*(t*(t*b5 + b4) + b3) + b2) + b1));
237  }
238  else {
239  double t = 1.0 / ( 1.0 - p * x );
240  return ( (1/sqrt(2*PI))*exp(-x*x/2.0 )*t*
241  (t*(t*(t*(t*b5 + b4) + b3) + b2) + b1));
242  }
243 
244 
245 }
246 
247 
248 } // name space
static Type UnDef(void)
Undefined time value.
Int Type
Datatype for point on time axis.
double ran_gauss(double mu, double sigma, Time::Type tossLB, Time::Type tossUB)
Sample a random variable gaussian distributed on a restricted interval Distribution: f(t) = 1 / sqrt(...
Definition: sp_random.cpp:132
long ran_uniform_int(long a, long b)
Sample a discrete random variable uniformly on interval [a;b) Distribution: p(n) = 1/(b-a-1)
Definition: sp_random.cpp:98
void ran_put_seed(long seed)
Put a seed.
Definition: sp_random.cpp:55
double ran_exponential(double mu)
Sample a random variable exponentially Distribution: f(t) dt = 1/mu exp(-t/mu) dt for t>=0.
Definition: sp_random.cpp:107
void ran_plant_seeds(long x)
Use this function to set the state of all the random number generator streams by "planting" a sequenc...
Definition: sp_random.cpp:35
void ran_select_stream(int index)
Use this function to set the current random number generator stream – that stream from which the next...
Definition: sp_random.cpp:60
void ran_init(long seed)
Initialize random generator.
Definition: sp_random.cpp:67
double ran(void)
Run random generator Random Number Generator (for more details see "Random Number Generators: Good On...
Definition: sp_random.cpp:75
double ran_gaussian_cdf_P(double x)
Help function: calculate gaussian CDF using an approximation from Abromowitz and Stegun: Handbook of ...
Definition: sp_random.cpp:224
double ran_uniform(double a, double b)
Sample a random variable uniformly on interval [a;b) Distribution: f(t) dt= {1/(b-a)} dt for t,...
Definition: sp_random.cpp:91
libFAUDES resides within the namespace faudes.
static long ran_seed[STREAMS]
Definition: sp_random.cpp:29
static int ran_initialized
Definition: sp_random.cpp:31
static int ran_stream
Definition: sp_random.cpp:30
#define FD_DS(message)
Definition: sp_executor.h:34
#define DEFAULT
Definition: sp_random.cpp:27
#define STREAMS
Definition: sp_random.cpp:25
#define MODULUS
Definition: sp_random.cpp:22
#define MULTIPLIER
Definition: sp_random.cpp:23
#define A256
Definition: sp_random.cpp:26
Evaluating random variables.

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen