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
18namespace 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
29static long ran_seed[STREAMS] = {DEFAULT}; /* current state of each stream */
30static int ran_stream = 0; /* stream index, 0 is the default */
31static int ran_initialized = 0; /* test for stream initialization */
32
33
34//ran_plant_seeds(x)
35void ran_plant_seeds(long x) {
36 const long Q = MODULUS / A256;
37 const long R = MODULUS % A256;
38 int j;
39 int s;
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)
55void ran_put_seed(long seed) {
56 ran_seed[ran_stream] = seed;
57}
58
59//ran_select_stream(index)
60void 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)
67void 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()
75double 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)
83 else
85 return ((double) ran_seed[ran_stream] / MODULUS);
86
87}
88
89
90// ran_uniform(a,b)
91double 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)
98long 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)
107double 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)
116double 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) */
132double 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
224double 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)
double ran_gauss(double mu, double sigma, Time::Type tossLB, Time::Type tossUB)
long ran_uniform_int(long a, long b)
Definition sp_random.cpp:98
void ran_put_seed(long seed)
Definition sp_random.cpp:55
double ran_exponential(double mu)
void ran_plant_seeds(long x)
Definition sp_random.cpp:35
void ran_select_stream(int index)
Definition sp_random.cpp:60
void ran_init(long seed)
Definition sp_random.cpp:67
double ran(void)
Definition sp_random.cpp:75
double ran_gaussian_cdf_P(double x)
double ran_uniform(double a, double b)
Definition sp_random.cpp:91
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

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen