sp_random.cppGo to the documentation of this file.00001 /** @file sp_random.cpp Evaluating random variables */ 00002 00003 /* 00004 FAU Discrete Event System Simulator 00005 00006 Copyright (C) 2007 Christoph Doerr 00007 Exclusive copyright is granted to Thomas Moor 00008 */ 00009 00010 #include "sp_random.h" 00011 00012 #include <cmath> 00013 00014 00015 00016 00017 namespace faudes { 00018 00019 00020 00021 #define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */ 00022 #define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */ 00023 #define CHECK 399268537 /* DON'T CHANGE THIS VALUE */ 00024 #define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */ 00025 #define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */ 00026 #define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */ 00027 00028 static long ran_seed[STREAMS] = {DEFAULT}; /* current state of each stream */ 00029 static int ran_stream = 0; /* stream index, 0 is the default */ 00030 static int ran_initialized = 0; /* test for stream initialization */ 00031 00032 00033 //ran_plant_seeds(x) 00034 void ran_plant_seeds(long x) 00035 { 00036 const long Q = MODULUS / A256; 00037 //calculate inverse CDF (algorithm based on a rational approximation algorithm by Peter J. Acklam) 00038 const long R = MODULUS % A256; 00039 int j; 00040 int s; 00041 00042 ran_initialized = 1; 00043 s = ran_stream; /* remember the current stream */ 00044 ran_select_stream(0); /* change to stream 0 */ 00045 ran_put_seed(x); /* set seed[0] */ 00046 ran_stream = s; /* reset the current stream */ 00047 for (j = 1; j < STREAMS; j++) { 00048 x = A256 * (ran_seed[j - 1] % Q) - R * (ran_seed[j - 1] / Q); 00049 if (x > 0) 00050 ran_seed[j] = x; 00051 else 00052 ran_seed[j] = x + MODULUS; 00053 } 00054 } 00055 00056 //ran_put_seed(x) 00057 void ran_put_seed(long seed) 00058 { 00059 ran_seed[ran_stream] = seed; 00060 } 00061 00062 //ran_select_stream(index) 00063 void ran_select_stream(int index) 00064 { 00065 ran_stream = ((unsigned int) index) % STREAMS; 00066 if ((ran_initialized == 0) && (ran_stream != 0)) /* protect against */ 00067 ran_plant_seeds(DEFAULT); /* un-initialized streams */ 00068 } 00069 00070 //an_init(seed) 00071 void ran_init(long seed){ 00072 ran_select_stream(0); /* select the default stream */ 00073 ran_put_seed(seed); 00074 } 00075 00076 00077 // ran() 00078 double ran(void){ 00079 const long Q = MODULUS / MULTIPLIER; 00080 const long R = MODULUS % MULTIPLIER; 00081 long t; 00082 00083 t = MULTIPLIER * (ran_seed[ran_stream] % Q) - R * (ran_seed[ran_stream] / Q); 00084 if (t > 0) 00085 ran_seed[ran_stream] = t; 00086 else 00087 ran_seed[ran_stream] = t + MODULUS; 00088 return ((double) ran_seed[ran_stream] / MODULUS); 00089 00090 } 00091 00092 00093 // ran_uniform(a,b) 00094 double ran_uniform(double a, double b){ 00095 double q = ran(); 00096 q=a*(1-q)+b*q; 00097 return q; 00098 } 00099 00100 // ran_uniform(a,b) 00101 long ran_uniform_int(long a, long b){ 00102 double q = ran(); 00103 long i =(long) floor(((double) a)*(1-q)+((double)b)*q); 00104 if(i>=b) i=b-1; 00105 if(i< a) i=a; 00106 return i; 00107 } 00108 00109 // ran_exponential(mu) 00110 double ran_exponential(double mu){ 00111 double q=0; 00112 while(q==0){ 00113 q=ran(); 00114 } 00115 return -mu*log(q); 00116 } 00117 00118 // ran_expontial(mu, tossLB, tossUB) 00119 double ran_exponential(double mu, tpTime::Type tossLB, tpTime::Type tossUB){ 00120 if(tossLB==tossUB){ 00121 FD_DS("Ran_exponential(): empty interval"); 00122 return tpTime::UnDef; 00123 } 00124 else{ 00125 double lb= -expm1(-(static_cast<double> (tossLB))/ mu); 00126 double ub= -expm1(-(static_cast<double> (tossUB))/ mu); 00127 double u=ran_uniform(lb,ub); 00128 double ret=(-mu*(log(1-u))); 00129 //FD_DS("Ran_exponential: lb="<<lb<<" ub="<<ub<<" u="<<u<<" ret="<<ret); 00130 return ret; 00131 } 00132 } 00133 00134 /* ran_gauss(mu, sigma, tossLB, tossUB) */ 00135 double ran_gauss(double mu, double sigma, tpTime::Type tossLB, tpTime::Type tossUB){ 00136 if(tossLB==tossUB){ 00137 FD_DS("Ran_gauss(): empty interval"); 00138 return tpTime::UnDef; 00139 } 00140 else{ 00141 //Transform to (0,1)-Normaldistribution 00142 double ztossLB=(static_cast<double>(tossLB)-mu)/sigma; 00143 double ztossUB=(static_cast<double>(tossUB)-mu)/sigma; 00144 //Sample Boundaries 00145 double zlb=ran_gaussian_cdf_P(ztossLB); 00146 double zub=ran_gaussian_cdf_P(ztossUB); 00147 double u=ran_uniform(zlb,zub); 00148 00149 //FD_DS("Ran_gauss(): ztossLB="<<ztossLB<<" ztossUB="<<ztossUB << " zlb="<<zlb<<" zub="<<zub<<" -> u="<<u); 00150 00151 //calculate inverse CDF (algorithm based on a rational approximation algorithm by Peter J. Acklam) 00152 double zret; 00153 static const double a[] = 00154 { 00155 -3.969683028665376e+01, 00156 2.209460984245205e+02, 00157 -2.759285104469687e+02, 00158 1.383577518672690e+02, 00159 -3.066479806614716e+01, 00160 2.506628277459239e+00 00161 }; 00162 00163 static const double b[] = 00164 { 00165 -5.447609879822406e+01, 00166 1.615858368580409e+02, 00167 -1.556989798598866e+02, 00168 6.680131188771972e+01, 00169 -1.328068155288572e+01 00170 }; 00171 00172 static const double c[] = 00173 { 00174 -7.784894002430293e-03, 00175 -3.223964580411365e-01, 00176 -2.400758277161838e+00, 00177 -2.549732539343734e+00, 00178 4.374664141464968e+00, 00179 2.938163982698783e+00 00180 }; 00181 00182 static const double d[] = 00183 { 00184 7.784695709041462e-03, 00185 3.224671290700398e-01, 00186 2.445134137142996e+00, 00187 3.754408661907416e+00 00188 }; 00189 double q,r; 00190 if(u<0 || u>1) zret=0.0; 00191 else if (u==0){ 00192 FD_DS("Ran_gauss(): u="<<u<<"ret=HUGE_VAL"); 00193 return -HUGE_VAL; 00194 } 00195 else if (u==1){ 00196 FD_DS("Ran_gauss(): u="<<u<<"ret=-HUGE_VAL"); 00197 return HUGE_VAL; 00198 } 00199 else if (u<0.02425){ 00200 // Rational approximation for lower region 00201 q = sqrt(-2*log(u)); 00202 zret=(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / 00203 ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1); 00204 } 00205 else if(u>0.97575){ 00206 // Rational approximation for upper region 00207 q = sqrt(-2*log(1-u)); 00208 zret= -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / 00209 ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1); 00210 } 00211 else{ 00212 // Rational approximation for central region 00213 q = u - 0.5; 00214 r = q*q; 00215 zret=(((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q / 00216 (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1); 00217 } 00218 //Transform to (mu,sigma)-Distribution 00219 double ret=(zret*sigma)+mu; //to_do: overflow protection 00220 //FD_DS("Ran_gauss(): zret="<<zret<<" ret="<<ret); 00221 return ret; 00222 } 00223 } 00224 00225 00226 //ran_gaussian_cdf_P 00227 double ran_gaussian_cdf_P(double x){ 00228 const double PI = 3.141592654; 00229 const double b1 = 0.319381530; 00230 const double b2 = -0.356563782; 00231 const double b3 = 1.781477937; 00232 const double b4 = -1.821255978; 00233 const double b5 = 1.330274429; 00234 const double p = 0.2316419; 00235 00236 if(x >= 0.0) { 00237 double t = 1.0 / (1.0 + p*x); 00238 return (1.0 - (1/sqrt(2*PI))*exp(-x*x/2.0 )*t* 00239 (t*(t*(t*(t*b5 + b4) + b3) + b2) + b1)); 00240 } 00241 else { 00242 double t = 1.0 / ( 1.0 - p * x ); 00243 return ( (1/sqrt(2*PI))*exp(-x*x/2.0 )*t* 00244 (t*(t*(t*(t*b5 + b4) + b3) + b2) + b1)); 00245 } 00246 00247 00248 } 00249 00250 00251 } // name space libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |