source: Sophya/trunk/SophyaLib/BaseTools/randinterf.cc@ 4057

Last change on this file since 4057 was 4019, checked in by cmv, 14 years ago

ajout generateurs tinymt32+64, cmv 24/09/2011

File size: 38.5 KB
RevLine 
[3602]1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <math.h>
4#include <stdlib.h>
[3791]5#include <stdio.h>
[3602]6#include <sys/time.h>
7#include <time.h>
8#include <iostream>
[3838]9#include <typeinfo>
10
[3602]11#include "pexceptions.h"
12
13#include "randinterf.h"
14
15namespace SOPHYA {
16
17//-------------------------------------------------------------------------------
18// ------ Definition d'interface des classes de generateurs de nombres aleatoires
[3604]19/*!
20 \class RandomGeneratorInterface
21 \ingroup BaseTools
22 \brief Base class for random number generators
[3602]23
[3604]24 This class defines the interface for random number generator classes and
25 implements the generation of some specific distributions (Gaussian, Poisson ...)
26 through generation of random number with a flat distribution in the range [0,1[.
27
28 The sub classes inheriting from this class should implement the Next() method.
29
30 This base class manages also a global instance of a default generator.
31
32 \sa frand01 drand01 frandpm1 drandpm1
[3615]33 \sa Gaussian Poisson
[3604]34
35*/
36
37
38RandomGeneratorInterface* RandomGeneratorInterface::gl_rndgen_p = NULL;
39
40/*!
41 \brief: static method to set or change the intance of the global Random Generator object
42
43 This method should be called during initialization, before any call to global
44 functions for random number generation. The rgp object should be created using new.
45*/
46void RandomGeneratorInterface::SetGlobalRandGenP(RandomGeneratorInterface* rgp)
47{
48 if (rgp == NULL) return;
49 if (gl_rndgen_p) delete gl_rndgen_p;
50 gl_rndgen_p = rgp;
51 return;
52}
53
[3602]54RandomGeneratorInterface::RandomGeneratorInterface()
55{
[3604]56 SelectGaussianAlgo();
57 SelectPoissonAlgo();
58 SelectExponentialAlgo();
[3602]59}
60
61
62RandomGeneratorInterface::~RandomGeneratorInterface(void)
63{
64 // rien a faire
65}
66
[3615]67void RandomGeneratorInterface::ShowRandom()
68{
[3838]69 cout << " RandomGeneratorInterface::ShowRandom() typeid(this)=" << typeid(*this).name() << " @ "
70 << hex << (unsigned long)(this) << dec << endl;
71 return;
[3615]72}
[3602]73
74/////////////////////////////////////////////////////////////////////////
75/////////////////////////////////////////////////////////////////////////
76/////////////////////////////////////////////////////////////////////////
77
[3838]78/*
[3602]79r_8 RandomGeneratorInterface::Next()
80{
81 printf("RandomGeneratorInterface::Next(): undefined code !!!\n");
82 throw MathExc("RandomGeneratorInterface::Next(): undefined code !!!");
83}
[3838]84*/
[3602]85
86/////////////////////////////////////////////////////////////////////////
87/////////////////////////////////////////////////////////////////////////
88/////////////////////////////////////////////////////////////////////////
89void RandomGeneratorInterface::GenerateSeedVector(int nseed,vector<uint_2>& seed,int lp)
[4019]90// renvoie un vecteur de 3+nseed entiers 16 bits
91// [0 - 2] = codage sur 3*16 = 48 bits du nombre (melange) de microsec depuis l'origine
[3602]92// [3 -> 3+ngene-1] = entiers aleatoires (poor man generator)
93//
94// L'initialiseur est donne par un codage du nombre de millisecondes
95// ecoulees depuis le 0 heure le 1er Janvier 1970 UTC (cf gettimeofday).
96// Seuls les 48 bits de poids faible sont retenus.
97// Un melange des bits est ensuite effectue pour que les 3 nombres
98// (unsigned short) d'initialisation ne soient pas trop semblables.
99// Le nombre le plus grand que l'on peut mettre
100// dans un entier unsigned de N bits est: 2^N-1
101// 48 bits -> 2^48-1 = 281474976710655 musec = 3257.8j = 8.9y
102// -> meme initialisation tous les 8.9 ans a 1 microsec pres !
103{
104 if(lp>0) cout<<"RandomGeneratorInterface::GenerateSeedVector: nseed="<<nseed<<endl;
105
106 // ---
107 // --- les deux premiers mots remplis avec le temps
108 // ---
109 // On recupere le temps ecoule depuis l'origine code en sec+musec
110 struct timeval now;
111 gettimeofday(&now,0);
112 // Calcul du temps ecoule depuis l'origine en microsecondes
113 uint_8 tmicro70 = (uint_8)now.tv_sec*(uint_8)1000000 + (uint_8)now.tv_usec;
[4019]114 if(lp>1) cout<<".since orig: "<<now.tv_sec<<" sec + "<<now.tv_usec<<" musec = "<<tmicro70<<" musec"<<endl;
[3602]115 // Remplissage du tableau de 48 bits
116 uint_2 b[48]; uint_8 tdum = tmicro70;
117 for(int ip=0;ip<48;ip++) {b[ip] = tdum&1; tdum = (tdum>>1);}
118 if(lp>2) {
119 cout<<"..b= ";
120 for(int ip=47;ip>=0;ip--) {cout<<b[ip]; if(ip%32==0 || ip%16==0) cout<<" ";}
121 cout<<endl;
122 }
123 // Melange des bits qui varient vite (poids faible, microsec)
124 // avec ceux variant lentement (poids fort, sec)
125 for(int ip=0;ip<16;ip++) {
126 if(ip%3==1) swap(b[ip],b[32+ip]);
[4019]127 else if(ip%3==2) swap(b[ip],b[16+ip]);
[3602]128 }
129 if(lp>2) {
130 cout<<"..b= ";
131 for(int ip=47;ip>=0;ip--) {cout<<b[ip]; if(ip%32==0 || ip%16==0) cout<<" ";}
132 cout<<endl;
133 }
134 // Remplissage
135 seed.resize(0);
136 for(int i=0;i<3;i++) {
137 seed.push_back(0);
138 uint_2 w = 1;
139 for(int ip=0;ip<16;ip++) {seed[i] += w*b[i*16+ip]; w *= 2;}
140 }
[4019]141 if(lp>0) cout<<"seed_time[0-2]: "<<seed[0]<<" "<<seed[1]<<" "<<seed[2]<<endl;
142 // On recree tmicro70 avec les bits melanges
143 tmicro70 = uint_8(seed[0]) | (uint_8(seed[1])<<16) | (uint_8(seed[2])<<32);
[3602]144
145 // ---
146 // --- generation des nombres aleatoires complementaires (poor man generator)
147 // ---
148 //----------------------------------------------------------------------------//
149 // Ran088: L'Ecuyer's 1996 three-component Tausworthe generator "taus88"
150 // Returns an integer random number uniformly distributed within [0,4294967295]
151 // The period length is approximately 2^88 (which is 3*10^26).
152 // This generator is very fast and passes all standard statistical tests.
153 // Reference:
154 // (1) P. L'Ecuyer, Maximally equidistributed combined Tausworthe generators,
155 // Mathematics of Computation, 65, 203-213 (1996), see Figure 4.
156 // (2) recommended in:
157 // P. L'Ecuyer, Random number generation, chapter 4 of the
158 // Handbook on Simulation, Ed. Jerry Banks, Wiley, 1997.
159 //----------------------------------------------------------------------------//
160 if(nseed<=0) return;
161 // initialize seeds using the given seed value taking care of
162 // the requirements. The constants below are arbitrary otherwise
163 uint_4 seed0 = uint_4(tmicro70&0xFFFFFFFFULL);
[4019]164 if(lp>2) cout<<"seed0_time_init_t88: "<<seed0<<endl;
[3602]165 uint_4 state_s1, state_s2, state_s3;
166 state_s1 = 1243598713U ^ seed0; if (state_s1 < 2) state_s1 = 1243598713U;
167 state_s2 = 3093459404U ^ seed0; if (state_s2 < 8) state_s2 = 3093459404U;
168 state_s3 = 1821928721U ^ seed0; if (state_s3 < 16) state_s3 = 1821928721U;
169 int nfill = 0, ico=0;
170 while(nfill<nseed) {
171 uint_4 s1 = state_s1, s2 = state_s2, s3 = state_s3;
172 // generate a random 32 bit number
173 s1 = ((s1 & -2) << 12) ^ (((s1 << 13) ^ s1) >> 19);
174 s2 = ((s2 & -8) << 4) ^ (((s2 << 2) ^ s2) >> 25);
175 s3 = ((s3 & -16) << 17) ^ (((s3 << 3) ^ s3) >> 11);
176 state_s1 = s1; state_s2 = s2; state_s3 = s3;
177 // le nombre aleatoire sur 32 bits est: s1^s2^s3
178 if(ico<15) {ico++; continue;} // des tirages blancs
179 uint_2 s = uint_2( (s1^s2^s3)&0xFFFFU );
180 seed.push_back(s);
[4019]181 if(lp>0) cout<<"seed_t88["<<nfill+3<<"]: "<<seed[3+nfill]<<endl;
[3602]182 nfill++;
183 }
184
185}
186
[3615]187void RandomGeneratorInterface::AutoInit(int lp)
188{
189 printf("RandomGeneratorInterface::AutoInit(): undefined code !!!\n");
190 throw MathExc("RandomGeneratorInterface::AutoInit(): undefined code !!!");
191}
192
[3602]193/////////////////////////////////////////////////////////////////////////
194/////////////////////////////////////////////////////////////////////////
195/////////////////////////////////////////////////////////////////////////
196
[3604]197r_8 RandomGeneratorInterface::Gaussian()
198{
199 switch (usegaussian_) {
200 case C_Gaussian_BoxMuller :
201 return GaussianBoxMuller();
202 break;
203 case C_Gaussian_RandLibSNorm :
204 return GaussianSNorm();
205 break;
206 case C_Gaussian_PolarBoxMuller :
207 return GaussianPolarBoxMuller();
208 break;
209 case C_Gaussian_RatioUnif :
210 return GaussianRatioUnif();
211 break;
212 case C_Gaussian_LevaRatioUnif :
213 return GaussianLevaRatioUnif();
214 break;
[4018]215 case C_Gaussian_Ziggurat128 :
216 return GaussianZiggurat128();
217 break;
[3604]218 default:
219 return GaussianBoxMuller();
220 break;
221 }
222}
223
[3602]224//--- Generation de nombre aleatoires suivant une distribution gaussienne
225r_8 RandomGeneratorInterface::GaussianBoxMuller()
226{
227 r_8 A=Next();
228 while (A==0.) A=Next();
229 return sqrt(-2.*log(A))*cos(2.*M_PI*Next());
230}
231
232//-------------------------------------------
233// Adapte de ranlib float snorm()
234// http://orion.math.iastate.edu/burkardt/c_src/ranlib/ranlib.c
235/*
236**********************************************************************
237 (STANDARD-) N O R M A L DISTRIBUTION
238**********************************************************************
239
240 FOR DETAILS SEE:
241
242 AHRENS, J.H. AND DIETER, U.
243 EXTENSIONS OF FORSYTHE'S METHOD FOR RANDOM
244 SAMPLING FROM THE NORMAL DISTRIBUTION.
245 MATH. COMPUT., 27,124 (OCT. 1973), 927 - 937.
246
247 ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM 'FL'
248 (M=5) IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)
249
250 Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
251 SUNIF. The argument IR thus goes away.
252
253**********************************************************************
254 THE DEFINITIONS OF THE CONSTANTS A(K), D(K), T(K) AND
255 H(K) ARE ACCORDING TO THE ABOVEMENTIONED ARTICLE
256*/
257static double a_snorm[32] = {
258 0.0,3.917609E-2,7.841241E-2,0.11777,0.1573107,0.1970991,0.2372021,0.2776904,
259 0.3186394,0.36013,0.4022501,0.4450965,0.4887764,0.5334097,0.5791322,
260 0.626099,0.6744898,0.7245144,0.7764218,0.8305109,0.8871466,0.9467818,
261 1.00999,1.077516,1.150349,1.229859,1.318011,1.417797,1.534121,1.67594,
262 1.862732,2.153875
263};
264static double d_snorm[31] = {
265 0.0,0.0,0.0,0.0,0.0,0.2636843,0.2425085,0.2255674,0.2116342,0.1999243,
266 0.1899108,0.1812252,0.1736014,0.1668419,0.1607967,0.1553497,0.1504094,
267 0.1459026,0.14177,0.1379632,0.1344418,0.1311722,0.128126,0.1252791,
268 0.1226109,0.1201036,0.1177417,0.1155119,0.1134023,0.1114027,0.1095039
269};
270static float t_snorm[31] = {
271 7.673828E-4,2.30687E-3,3.860618E-3,5.438454E-3,7.0507E-3,8.708396E-3,
272 1.042357E-2,1.220953E-2,1.408125E-2,1.605579E-2,1.81529E-2,2.039573E-2,
273 2.281177E-2,2.543407E-2,2.830296E-2,3.146822E-2,3.499233E-2,3.895483E-2,
274 4.345878E-2,4.864035E-2,5.468334E-2,6.184222E-2,7.047983E-2,8.113195E-2,
275 9.462444E-2,0.1123001,0.136498,0.1716886,0.2276241,0.330498,0.5847031
276};
277static float h_snorm[31] = {
278 3.920617E-2,3.932705E-2,3.951E-2,3.975703E-2,4.007093E-2,4.045533E-2,
279 4.091481E-2,4.145507E-2,4.208311E-2,4.280748E-2,4.363863E-2,4.458932E-2,
280 4.567523E-2,4.691571E-2,4.833487E-2,4.996298E-2,5.183859E-2,5.401138E-2,
281 5.654656E-2,5.95313E-2,6.308489E-2,6.737503E-2,7.264544E-2,7.926471E-2,
282 8.781922E-2,9.930398E-2,0.11556,0.1404344,0.1836142,0.2790016,0.7010474
283};
284r_8 RandomGeneratorInterface::GaussianSNorm()
285{
286long i;
287double snorm,u,s,ustar,aa,w,y,tt;
288 u = Next();
289 s = 0.0;
290 if(u > 0.5) s = 1.0;
291 u += (u-s);
292 u = 32.0*u;
293 i = (long) (u);
294 if(i == 32) i = 31;
295 if(i == 0) goto S100;
296/*
297 START CENTER
298*/
299 ustar = u-(double)i;
300 aa = *(a_snorm+i-1);
301S40:
302 if(ustar <= *(t_snorm+i-1)) goto S60;
303 w = (ustar-*(t_snorm+i-1))**(h_snorm+i-1);
304S50:
305/*
306 EXIT (BOTH CASES)
307*/
308 y = aa+w;
309 snorm = y;
310 if(s == 1.0) snorm = -y;
311 return snorm;
312S60:
313/*
314 CENTER CONTINUED
315*/
316 u = Next();
317 w = u*(*(a_snorm+i)-aa);
318 tt = (0.5*w+aa)*w;
319 goto S80;
320S70:
321 tt = u;
322 ustar = Next();
323S80:
324 if(ustar > tt) goto S50;
325 u = Next();
326 if(ustar >= u) goto S70;
327 ustar = Next();
328 goto S40;
329S100:
330/*
331 START TAIL
332*/
333 i = 6;
334 aa = *(a_snorm+31);
335 goto S120;
336S110:
337 aa += *(d_snorm+i-1);
338 i += 1;
339S120:
340 u += u;
341 if(u < 1.0) goto S110;
342 u -= 1.0;
343S140:
344 w = u**(d_snorm+i-1);
345 tt = (0.5*w+aa)*w;
346 goto S160;
347S150:
348 tt = u;
349S160:
350 ustar = Next();
351 if(ustar > tt) goto S50;
352 u = Next();
353 if(ustar >= u) goto S150;
354 u = Next();
355 goto S140;
356}
357
358r_8 RandomGeneratorInterface::GaussianPolarBoxMuller()
359{
[4019]360 double x1,x2,w;
361 do {
[3602]362 x1 = 2.0 * Next() - 1.0;
363 x2 = 2.0 * Next() - 1.0;
364 w = x1 * x1 + x2 * x2;
[4019]365 } while ( w >= 1.0 || w==0. );
366 return x1 * sqrt(-2.0*log(w)/w);
[3602]367}
368
369static double s2se_RatioUnif=sqrt(2./M_E) , epm135_RatioUnif=exp(-1.35) , ep1q_RatioUnif=exp(1./4.);
370r_8 RandomGeneratorInterface::GaussianRatioUnif()
371{
[4019]372 double u,v,x;
373 while(true) {
374 do {u = Next();} while ( u == 0. );
375 v = (2.0*Next()-1.0)*s2se_RatioUnif;
376 x = v/u;
377 if(x*x <= 5.0-4.0*ep1q_RatioUnif*u) break;
378 if(x*x<4.0*epm135_RatioUnif/u+1.4)
379 if(v*v<-4.0*u*u*log(u)) break;
380 }
381 return x;
[3602]382}
383
384r_8 RandomGeneratorInterface::GaussianLevaRatioUnif()
385{
[4019]386 double u,v,x,y,q;
[3602]387 do {
388 u = 1.-Next(); // in ]0,1]
389 v = Next()-0.5; // in [-0.5, 0.5[
390 v *= 1.7156;
391 x = u - 0.449871;
392 y = ((v<0)?-v:v) + 0.386595;
393 q = x*x + y*(0.19600*y - 0.25472*x);
394 } while( q>=0.27597 && (q>0.27846 || v*v>-4.0*u*u*log(u)) );
395 return v/u;
396}
397
[4018]398//-------------------------------------------------------------------------------
399// Definition des tableaux pour tirage Gaussien methode Ziggurat N=128 bandes
400// G.Marsaglia and W.W.Tsang "The ziggurat method for generating random variables
401// D.Thomas et al. ACM Computing Surveys, Vol 39, No 4, Article 11, October 2007
402// http://en.wikipedia.org/wiki/Ziggurat_algorithm (tres bien explique)
403// Calcul des tableaux avec programme "cmvziggurat.cc"
404//-------------------------------------------------------------------------------
405const int N_ZIGGURRAT_GAUSS128 = 128;
406static const double X_ZIGGURRAT_GAUSS128[N_ZIGGURRAT_GAUSS128+1] = {
4070.0000000000000000, 0.2723208647046734, 0.3628714310284243, 0.4265479863033096, 0.4774378372537916,
4080.5206560387251481, 0.5586921783755209, 0.5929629424419807, 0.6243585973090908, 0.6534786387150446,
4090.6807479186459064, 0.7064796113136101, 0.7309119106218833, 0.7542306644345121, 0.7765839878761502,
4100.7980920606262765, 0.8188539066833194, 0.8389522142812090, 0.8584568431780525, 0.8774274290977171,
4110.8959153525662399, 0.9139652510088031, 0.9316161966013551, 0.9489026254979132, 0.9658550793881319,
4120.9825008035027615, 0.9988642334806447, 1.0149673952393006, 1.0308302360564565, 1.0464709007525812,
4131.0619059636836206, 1.0771506248819389, 1.0922188768965548, 1.1071236475235364, 1.1218769225722551,
4141.1364898520030764, 1.1509728421389769, 1.1653356361550478, 1.1795873846544616, 1.1937367078237728,
4151.2077917504067583, 1.2217602305309634, 1.2356494832544818, 1.2494664995643345, 1.2632179614460288,
4161.2769102735517004, 1.2905495919178738, 1.3041418501204223, 1.3176927832013436, 1.3312079496576772,
4171.3446927517457137, 1.3581524543224235, 1.3715922024197329, 1.3850170377251492, 1.3984319141236070,
4181.4118417124397606, 1.4252512545068619, 1.4386653166774619, 1.4520886428822168, 1.4655259573357950,
4191.4789819769830983, 1.4924614237746157, 1.5059690368565506, 1.5195095847593711, 1.5330878776675565,
4201.5467087798535037, 1.5603772223598409, 1.5740982160167500, 1.5878768648844011, 1.6017183802152775,
4211.6156280950371333, 1.6296114794646788, 1.6436741568569830, 1.6578219209482079, 1.6720607540918526,
4221.6863968467734867, 1.7008366185643014, 1.7153867407081171, 1.7300541605582440, 1.7448461281083769,
4231.7597702248942324, 1.7748343955807697, 1.7900469825946195, 1.8054167642140493, 1.8209529965910054,
4241.8366654602533845, 1.8525645117230873, 1.8686611409895424, 1.8849670357028696, 1.9014946531003181,
4251.9182573008597323, 1.9352692282919006, 1.9525457295488893, 1.9701032608497135, 1.9879595741230611,
4262.0061338699589673, 2.0246469733729340, 2.0435215366506698, 2.0627822745039639, 2.0824562379877247,
4272.1025731351849992, 2.1231657086697902, 2.1442701823562618, 2.1659267937448412, 2.1881804320720208,
4282.2110814088747279, 2.2346863955870573, 2.2590595738653296, 2.2842740596736570, 2.3104136836950024,
4292.3375752413355309, 2.3658713701139877, 2.3954342780074676, 2.4264206455302118, 2.4590181774083506,
4302.4934545220919508, 2.5300096723854670, 2.5690336259216395, 2.6109722484286135, 2.6564064112581929,
4312.7061135731187225, 2.7611693723841539, 2.8231253505459666, 2.8943440070186708, 2.9786962526450171,
4323.0832288582142140, 3.2230849845786187, 3.4426198558966523, 3.7130862467403638
433};
434static const double Y_ZIGGURRAT_GAUSS128[N_ZIGGURRAT_GAUSS128+1] = {
4351.0000000000000000, 0.9635996931557651, 0.9362826817083690, 0.9130436479920363, 0.8922816508023012,
4360.8732430489268521, 0.8555006078850629, 0.8387836053106459, 0.8229072113952607, 0.8077382946961199,
4370.7931770117838580, 0.7791460859417020, 0.7655841739092348, 0.7524415591857027, 0.7396772436833371,
4380.7272569183545049, 0.7151515074204761, 0.7033360990258165, 0.6917891434460349, 0.6804918410064135,
4390.6694276673577053, 0.6585820000586529, 0.6479418211185500, 0.6374954773431442, 0.6272324852578138,
4400.6171433708265618, 0.6072195366326042, 0.5974531509518116, 0.5878370544418199, 0.5783646811267017,
4410.5690299910747210, 0.5598274127106941, 0.5507517931210546, 0.5417983550317235, 0.5329626593899870,
4420.5242405726789923, 0.5156282382498716, 0.5071220510813041, 0.4987186354765838, 0.4904148252893212,
4430.4822076463348383, 0.4740943006982492, 0.4660721526945706, 0.4581387162728716, 0.4502916436869266,
4440.4425287152802462, 0.4348478302546615, 0.4272469983095620, 0.4197243320540379, 0.4122780401070242,
4450.4049064208114880, 0.3976078564980422, 0.3903808082413892, 0.3832238110598833, 0.3761354695144541,
4460.3691144536682749, 0.3621594953730330, 0.3552693848515469, 0.3484429675498723, 0.3416791412350135,
4470.3349768533169710, 0.3283350983761522, 0.3217529158792085, 0.3152293880681574, 0.3087636380092518,
4480.3023548277894796, 0.2960021568498557, 0.2897048604458103, 0.2834622082260124, 0.2772735029218976,
4490.2711380791410251, 0.2650553022581618, 0.2590245673987105, 0.2530452985097656, 0.2471169475146965,
4500.2412389935477511, 0.2354109422657275, 0.2296323252343025, 0.2239026993871337, 0.2182216465563704,
4510.2125887730737359, 0.2070037094418736, 0.2014661100762031, 0.1959756531181102, 0.1905320403209136,
4520.1851349970107133, 0.1797842721249620, 0.1744796383324022, 0.1692208922389246, 0.1640078546849276,
4530.1588403711409350, 0.1537183122095865, 0.1486415742436969, 0.1436100800919329, 0.1386237799858510,
4540.1336826525846476, 0.1287867061971039, 0.1239359802039817, 0.1191305467087185, 0.1143705124498882,
4550.1096560210158177, 0.1049872554103545, 0.1003644410295455, 0.0957878491225781, 0.0912578008276347,
4560.0867746718955429, 0.0823388982429574, 0.0779509825146547, 0.0736115018847548, 0.0693211173941802,
4570.0650805852136318, 0.0608907703485663, 0.0567526634815385, 0.0526674019035031, 0.0486362958602840,
4580.0446608622008724, 0.0407428680747906, 0.0368843887869688, 0.0330878861465051, 0.0293563174402538,
4590.0256932919361496, 0.0221033046161116, 0.0185921027371658, 0.0151672980106720, 0.0118394786579823,
4600.0086244844129305, 0.0055489952208165, 0.0026696290839025, 0.0000000000000000
461};
462
463
464r_8 RandomGeneratorInterface::GaussianZiggurat128()
465//--------
466// On a "N = 128" bandes horizontales numerotees [0,N-1=127]
467// Les tableaux ont une taille "N + 1 = 129"
468// On tire un numero de bande dans [0,N-1=127]
469//--------
470// Pour choisir le signe sans avoir a retirer un aleatoire,
471// on utilise un digit du premier tirage qui n'est pas utilise
472// dans le choix du numero de bande "I":
473// U = [0,1[ , Ai=[0,9] (chiffres)
474// U = A1/10 + A2/100 + A3/1000 + A4/10000 + A5/100000 + ...
475// 128*U = A1*12.8 + A2*1.28 + A3*0.128 + A4*0.0128 + A5*0.00128
476// pour Ai le plus grand possible cad 9
477// 128*U = 115.2 + 11.52 + 1.152 + 0.1152 + 0.01152
478// On voit que pour Ai = 9
479// 1 terme, A1 : I = int(128*U) = int(115.2) = 115
480// 2 termes, A1,2 : I = int(128*U) = int(115.2+11.52) = int(126.72) = 126
481// 3 termes, A1,2,3 : I = int(128*U) = int(115.2+11.52+1.152) = int(127.872) = 127
482// 4 termes, A1,2,3,4 : I = int(128*U) = int(115.2+11.52+1.152+0.1152) = int(127.9872) = 127
483// ==> le digit A4 ne sert pas dans la determination de "I"
484// On prend un digit de + pour avoir de la marge -> A5 cad le dernier digit de int(U*10^5)
485//--------
[3602]486{
[4018]487 while(1) {
488 double U;
489 // -- choix de l'intervalle et de l'abscisse "x"
490 int I = N_ZIGGURRAT_GAUSS128;
491 while(I>=N_ZIGGURRAT_GAUSS128) {
492 U = Next();
493 I = int(N_ZIGGURRAT_GAUSS128*U);
494 }
495
496 // -- choix du signe (cf blabla ci-dessus)
497 double s = ( (int(U*100000)&1) == 0 ) ? -1.: 1.;
498
499 // -- choix de l'abscisse "x" dans l'intervalle
500 double x = Next() * X_ZIGGURRAT_GAUSS128[I+1];
501
502 // -- x est dans l'interieur de la bande
503 if(x<X_ZIGGURRAT_GAUSS128[I]) return s * x;
504
505 // -- x n'est pas a l'interieur de la bande mais dans la partie a 2 possibilites
506
507 // l'intervalle est celui qui contient la queue a l'infini
508 // On s'assure que la partie "rejection sur la gaussienne" ne sera pas appelle
509 // (cad que slim=1. < X[127]) pour eviter les recursions infinies (possibles?)
510 if(I==N_ZIGGURRAT_GAUSS128-1) // cas de la bande de la queue I=127
511 return s * GaussianTail(X_ZIGGURRAT_GAUSS128[N_ZIGGURRAT_GAUSS128-1],1.);
512
513 // on tire "y" uniforme a l'interieur des ordonnees de la bande choisie
514 // et on regarde si on est en-dessous ou au-dessus de la pdf
515 double y = Y_ZIGGURRAT_GAUSS128[I+1]
516 + Next()*(Y_ZIGGURRAT_GAUSS128[I]-Y_ZIGGURRAT_GAUSS128[I+1]);
517 double pdf = exp(-0.5*x*x);
518 if(pdf>y) return s * x;
519
520 // echec, on est au-dessus de la pdf -> on re-essaye
521 }
522}
523
524r_8 RandomGeneratorInterface::GaussianTail(double s,double slim)
525{
[3602]526 /* Returns a gaussian random variable larger than a
527 * This implementation does one-sided upper-tailed deviates.
528 */
[4019]529 if(s < slim) {
530 /* For small s, use a direct rejection method. The limit s < 1
531 can be adjusted to optimise the overall efficiency */
532 double x;
533 do {x = Gaussian();} while (x < s);
534 return x;
535 } else {
536 /* Use the "supertail" deviates from the last two steps
537 * of Marsaglia's rectangle-wedge-tail method, as described
538 * in Knuth, v2, 3rd ed, pp 123-128. (See also exercise 11, p139,
539 * and the solution, p586.)
540 */
541 double u, v, x;
542 do {u = Next();
543 do {v = Next();} while (v == 0.0);
544 x = sqrt (s * s - 2 * log (v));
545 } while (x * u > s);
546 return x;
547 }
[3602]548}
549
550/////////////////////////////////////////////////////////////////////////
551/////////////////////////////////////////////////////////////////////////
552/////////////////////////////////////////////////////////////////////////
553
[3604]554uint_8 RandomGeneratorInterface::Poisson(double mu, double mumax)
555{
556 switch (usepoisson_) {
557 case C_Poisson_Simple :
558 return PoissonSimple(mu,mumax);
559 break;
560 case C_Poisson_Ahrens :
561 return PoissonAhrens(mu);
562 break;
563 default:
564 return PoissonSimple(mu,mumax);
565 break;
566 }
567}
568
569
[3602]570//--- Generation de nombre aleatoires suivant une distribution de Poisson
571uint_8 RandomGeneratorInterface::PoissonSimple(double mu,double mumax)
572{
573 double pp,ppi,x;
574
575 if((mumax>0.)&&(mu>=mumax)) {
576 pp = sqrt(mu);
577 while( (x=pp*Gaussian()) < -mu );
578 return (uint_8)(mu+x+0.5);
579 }
580 else {
581 uint_8 n;
582 ppi = pp = exp(-mu);
583 x = Next();
584 n = 0;
585 while (x > ppi) {
586 n++;
587 pp = mu*pp/(double)n;
588 ppi += pp;
589 }
590 return n;
591 }
592 return 0; // pas necessaire ?
593}
594
595
596static double a0_poiahr = -0.5;
597static double a1_poiahr = 0.3333333;
598static double a2_poiahr = -0.2500068;
599static double a3_poiahr = 0.2000118;
600static double a4_poiahr = -0.1661269;
601static double a5_poiahr = 0.1421878;
602static double a6_poiahr = -0.1384794;
603static double a7_poiahr = 0.125006;
604static double fact_poiahr[10] = {
605 1.0,1.0,2.0,6.0,24.0,120.0,720.0,5040.0,40320.0,362880.0};
606uint_8 RandomGeneratorInterface::PoissonAhrens(double mu)
607/*
608**********************************************************************
609 long ignpoi(float mu)
610 GENerate POIsson random deviate
611 Function
612 Generates a single random deviate from a Poisson
613 distribution with mean AV.
614 Arguments
615 av --> The mean of the Poisson distribution from which
616 a random deviate is to be generated.
617 genexp <-- The random deviate.
618 Method
619 Renames KPOIS from TOMS as slightly modified by BWB to use RANF
620 instead of SUNIF.
621 For details see:
622 Ahrens, J.H. and Dieter, U.
623 Computer Generation of Poisson Deviates
624 From Modified Normal Distributions.
625 ACM Trans. Math. Software, 8, 2
626 (June 1982),163-179
627**********************************************************************
628**********************************************************************
629
630
631 P O I S S O N DISTRIBUTION
632
633
634**********************************************************************
635**********************************************************************
636
637 FOR DETAILS SEE:
638
639 AHRENS, J.H. AND DIETER, U.
640 COMPUTER GENERATION OF POISSON DEVIATES
641 FROM MODIFIED NORMAL DISTRIBUTIONS.
642 ACM TRANS. MATH. SOFTWARE, 8,2 (JUNE 1982), 163 - 179.
643
644 (SLIGHTLY MODIFIED VERSION OF THE PROGRAM IN THE ABOVE ARTICLE)
645
646**********************************************************************
647 INTEGER FUNCTION IGNPOI(IR,MU)
648 INPUT: IR=CURRENT STATE OF BASIC RANDOM NUMBER GENERATOR
649 MU=MEAN MU OF THE POISSON DISTRIBUTION
650 OUTPUT: IGNPOI=SAMPLE FROM THE POISSON-(MU)-DISTRIBUTION
651 MUPREV=PREVIOUS MU, MUOLD=MU AT LAST EXECUTION OF STEP P OR B.
652 TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT
653 COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL
654 SEPARATION OF CASES A AND B
655*/
656{
[3611]657uint_8 ignpoi,j,k,kflag,l,m;
[3602]658double b1,b2,c,c0,c1,c2,c3,d,del,difmuk,e,fk,fx,fy,g,omega,p,p0,px,py,q,s,
659 t,u,v,x,xx,pp[35];
660
661 if(mu < 10.0) goto S120;
662/*
663 C A S E A. (RECALCULATION OF S,D,L IF MU HAS CHANGED)
664*/
665 s = sqrt(mu);
666 d = 6.0*mu*mu;
667/*
668 THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL
669 PROBABILITIES FK WHENEVER K >= M(MU). L=IFIX(MU-1.1484)
670 IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 .
671*/
672 l = (uint_8) (mu-1.1484);
673/*
674 STEP N. NORMAL SAMPLE - SNORM(IR) FOR STANDARD NORMAL DEVIATE
675*/
676 g = mu+s*Gaussian();
677 if(g < 0.0) goto S20;
678 ignpoi = (uint_8) (g);
679/*
680 STEP I. IMMEDIATE ACCEPTANCE IF IGNPOI IS LARGE ENOUGH
681*/
682 if(ignpoi >= l) return ignpoi;
683/*
684 STEP S. SQUEEZE ACCEPTANCE - SUNIF(IR) FOR (0,1)-SAMPLE U
685*/
686 fk = (double)ignpoi;
687 difmuk = mu-fk;
688 u = Next();
689 if(d*u >= difmuk*difmuk*difmuk) return ignpoi;
690S20:
691/*
692 STEP P. PREPARATIONS FOR STEPS Q AND H.
693 (RECALCULATIONS OF PARAMETERS IF NECESSARY)
694 .3989423=(2*PI)**(-.5) .416667E-1=1./24. .1428571=1./7.
695 THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE
696 APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK.
697 C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION.
698*/
699 omega = 0.3989423/s;
700 b1 = 4.166667E-2/mu;
701 b2 = 0.3*b1*b1;
702 c3 = 0.1428571*b1*b2;
703 c2 = b2-15.0*c3;
704 c1 = b1-6.0*b2+45.0*c3;
705 c0 = 1.0-b1+3.0*b2-15.0*c3;
706 c = 0.1069/mu;
707 if(g < 0.0) goto S50;
708/*
709 'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)
710*/
711 kflag = 0;
712 goto S70;
713S40:
714/*
715 STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)
716*/
717 if(fy-u*fy <= py*exp(px-fx)) return ignpoi;
718S50:
719/*
720 STEP E. EXPONENTIAL SAMPLE - SEXPO(IR) FOR STANDARD EXPONENTIAL
721 DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'
722 (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)
723*/
[3609]724 e = Exponential();
[3602]725 u = Next();
726 u += (u-1.0);
727 //t = 1.8+fsign(e,u);
728 t = 1.8 + (((u>0. && e<0.) || (u<0. && e>0.))?-e:e);
729 if(t <= -0.6744) goto S50;
730 ignpoi = (uint_8) (mu+s*t);
731 fk = (double)ignpoi;
732 difmuk = mu-fk;
733/*
734 'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)
735*/
736 kflag = 1;
737 goto S70;
738S60:
739/*
740 STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)
741*/
742 if(c*fabs(u) > py*exp(px+e)-fy*exp(fx+e)) goto S50;
743 return ignpoi;
744S70:
745/*
746 STEP F. 'SUBROUTINE' F. CALCULATION OF PX,PY,FX,FY.
747 CASE IGNPOI .LT. 10 USES FACTORIALS FROM TABLE FACT
748*/
749 if(ignpoi >= 10) goto S80;
750 px = -mu;
751 py = pow(mu,(double)ignpoi)/ *(fact_poiahr+ignpoi);
752 goto S110;
753S80:
754/*
755 CASE IGNPOI .GE. 10 USES POLYNOMIAL APPROXIMATION
756 A0-A7 FOR ACCURACY WHEN ADVISABLE
757 .8333333E-1=1./12. .3989423=(2*PI)**(-.5)
758*/
759 del = 8.333333E-2/fk;
760 del -= (4.8*del*del*del);
761 v = difmuk/fk;
762 if(fabs(v) <= 0.25) goto S90;
763 px = fk*log(1.0+v)-difmuk-del;
764 goto S100;
765S90:
766 px = fk*v*v*(((((((a7_poiahr*v+a6_poiahr)*v+a5_poiahr)*v+a4_poiahr)*v+a3_poiahr)*v+a2_poiahr)*v+a1_poiahr)*v+a0_poiahr)-del;
767S100:
768 py = 0.3989423/sqrt(fk);
769S110:
770 x = (0.5-difmuk)/s;
771 xx = x*x;
772 fx = -0.5*xx;
773 fy = omega*(((c3*xx+c2)*xx+c1)*xx+c0);
774 if(kflag <= 0) goto S40;
775 goto S60;
776S120:
777/*
778 C A S E B. (START NEW TABLE AND CALCULATE P0 IF NECESSARY)
779*/
780// m = max(1L,(long) (mu));
781 m = (1ULL >= (uint_8)mu) ? 1ULL: (uint_8)mu;
782
783 l = 0;
784 p = exp(-mu);
785 q = p0 = p;
786S130:
787/*
788 STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
789*/
790 u = Next();
791 ignpoi = 0;
792 if(u <= p0) return ignpoi;
793/*
794 STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE
795 PP-TABLE OF CUMULATIVE POISSON PROBABILITIES
796 (0.458=PP(9) FOR MU=10)
797*/
798 if(l == 0) goto S150;
799 j = 1;
800//if(u > 0.458) j = min(l,m);
801 if(u > 0.458) j = ((l<=m)? l: m);
802 for(k=j; k<=l; k++) {
803 if(u <= *(pp+k-1)) goto S180;
804 }
805 if(l == 35) goto S130;
806S150:
807/*
808 STEP C. CREATION OF NEW POISSON PROBABILITIES P
809 AND THEIR CUMULATIVES Q=PP(K)
810*/
811 l += 1;
812 for(k=l; k<=35; k++) {
813 p = p*mu/(double)k;
814 q += p;
815 *(pp+k-1) = q;
816 if(u <= q) goto S170;
817 }
818 l = 35;
819 goto S130;
820S170:
821 l = k;
822S180:
823 ignpoi = k;
824 return ignpoi;
825}
826
827/////////////////////////////////////////////////////////////////////////
828/////////////////////////////////////////////////////////////////////////
829/////////////////////////////////////////////////////////////////////////
830
[3604]831r_8 RandomGeneratorInterface::Exponential()
832{
833 switch (useexpo_) {
834 case C_Exponential_Simple :
835 return ExpoSimple();
836 break;
837 case C_Exponential_Ahrens :
838 return ExpoAhrens();
839 break;
840 default:
841 return ExpoSimple();
842 break;
843 }
844}
845
[3602]846r_8 RandomGeneratorInterface::ExpoSimple(void)
847{
848 return -log(1.-Next());
849}
850
851
852static double q_expo[8] = {
853 0.6931472,0.9333737,0.9888778,0.9984959,0.9998293,0.9999833,0.9999986,1.0};
854r_8 RandomGeneratorInterface::ExpoAhrens(void)
855/*
856**********************************************************************
857**********************************************************************
858 (STANDARD-) E X P O N E N T I A L DISTRIBUTION
859**********************************************************************
860**********************************************************************
861
862 FOR DETAILS SEE:
863
864 AHRENS, J.H. AND DIETER, U.
865 COMPUTER METHODS FOR SAMPLING FROM THE
866 EXPONENTIAL AND NORMAL DISTRIBUTIONS.
867 COMM. ACM, 15,10 (OCT. 1972), 873 - 882.
868
869 ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM
870 'SA' IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)
871
872 Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of
873 SUNIF. The argument IR thus goes away.
874
875**********************************************************************
876 Q(N) = SUM(ALOG(2.0)**K/K!) K=1,..,N , THE HIGHEST N
877 (HERE 8) IS DETERMINED BY Q(N)=1.0 WITHIN STANDARD PRECISION
878*/
879{
880long i;
881double sexpo,a,u,ustar,umin;
882double *q1 = q_expo;
883 a = 0.0;
884 while((u=Next())==0.);
885 goto S30;
886S20:
887 a += *q1;
888S30:
889 u += u;
890 if(u <= 1.0) goto S20;
891 u -= 1.0;
892 if(u > *q1) goto S60;
893 sexpo = a+u;
894 return sexpo;
895S60:
896 i = 1;
897 ustar = Next();
898 umin = ustar;
899S70:
900 ustar = Next();
901 if(ustar < umin) umin = ustar;
902 i += 1;
903 if(u > *(q_expo+i-1)) goto S70;
904 sexpo = a+umin**q1;
905 return sexpo;
906}
907
[3615]908/////////////////////////////////////////////////////////////////////////
909/////////////////////////////////////////////////////////////////////////
910/////////////////////////////////////////////////////////////////////////
[3602]911
[3615]912int RandomGeneratorInterface::Gaussian2DRho(double &x,double &y,double mx,double my,double sx,double sy,double ro)
913/*
914++
915| Tirage de 2 nombres aleatoires x et y distribues sur une gaussienne 2D
916| de centre (mx,my), de coefficient de correlation rho (ro) et telle que
917| les sigmas finals des variables x et y soient sx,sy (ce sont
918| les valeurs des distributions marginales des variables aleatoires x et y
919| c'est a dire les sigmas des projections x et y de l'histogramme 2D
920| de la gaussienne). Retourne 0 si ok.
921|
922| - La densite de probabilite (normalisee a 1) sur laquelle on tire est:
923| N*exp[-0.5*{[(dx/sx)^2-2*ro/(sx*sy)*dx*dy+(dy/sy)^2]/(1-ro^2)}]
924| avec dx = x-mx, dy = y-my et N = 1/[2Pi*sx*sy*sqrt(1-ro^2)]
925| - Dans ce cas la distribution marginale est (ex en X):
926| 1/(sqrt(2Pi)*sx) * exp[-0.5*{dx^2/sx^2}]
927| - La matrice des covariances C des variables x,y est:
928| | sx^2 ro*sx*sy |
929| | | et det(C) = (1-ro^2)*sx^2*sy^2
930| | ro*sx*sy sy^2 |
931| - La matrice inverse C^(-1) est:
932| | 1/sx^2 -ro/(sx*sy) |
933| | | * 1/(1-ro^2)
934| | -ro/(sx*sy) 1/sy^2 |
935|
936| - Remarque:
937| le sigma que l'on obtient quand on fait une coupe de la gaussienne 2D
938| en y=0 (ou x=0) est: SX0(y=0) = sx*sqrt(1-ro^2) different de sx
939| SY0(x=0) = sy*sqrt(1-ro^2) different de sy
940| La distribution qui correspond a des sigmas SX0,SY0
941| pour les coupes en y=0,x=0 de la gaussienne 2D serait:
942| N*exp[-0.5*{ (dx/SX0)^2-2*ro/(SX0*SY0)*dx*dy+(dy/SY0)^2 }]
943| avec N = sqrt(1-ro^2)/(2Pi*SX0*SY0) et les variances
944| des variables x,y sont toujours
945| sx=SX0/sqrt(1-ro^2), sy=SY0/sqrt(1-ro^2)
946--
947*/
948{
949double a,b,sa;
950
951if( ro <= -1. || ro >= 1. ) return 1;
952
953while( (b=Flat01()) == 0. );
954b = sqrt(-2.*log(b));
955a = 2.*M_PI * Flat01();
956sa = sin(a);
957
958x = mx + sx*b*(sqrt(1.-ro*ro)*cos(a)+ro*sa);
959y = my + sy*b*sa;
960
961return 0;
962}
963
964void RandomGeneratorInterface::Gaussian2DAng(double &x,double &y,double mx,double my,double sa,double sb,double teta)
965/*
966++
967| Tirage de 2 nombres aleatoires x et y distribues sur une gaussienne 2D
968| de centre (x=mx,y=my), de sigmas grand axe et petit axe (sa,sb)
969| et dont le grand axe fait un angle teta (radian) avec l'axe des x.
970|
971| - La densite de probabilite (normalisee a 1) sur laquelle on tire est:
972| N*exp[-0.5*{ (A/sa)**2+(C/sc)**2 }], N=1/(2Pi*sa*sc)
973| ou A et B sont les coordonnees selon le grand axe et le petit axe
974| et teta = angle(x,A), le resultat subit ensuite une rotation d'angle teta.
975| - La matrice des covariances C des variables A,B est:
976| | sa^2 0 |
977| | | et det(C) = (1-ro^2)*sa^2*sb^2
978| | 0 sb^2 |
979| - La distribution x,y resultante est:
980| N*exp[-0.5*{[(dx/sx)^2-2*ro/(sx*sy)*dx*dy+(dy/sy)^2]/(1-ro^2)}]
981| ou N est donne dans NormCo et sx,sy,ro sont calcules a partir
982| de sa,sc,teta (voir fonctions paramga ou gaparam). La matrice des
983| covariances des variables x,y est donnee dans la fonction NormCo.
984--
985*/
986{
987double c,s,X,Y;
988
989while( (s = Flat01()) == 0. );
990s = sqrt(-2.*log(s));
991c = 2.*M_PI * Flat01();
992
993X = sa*s*cos(c);
994Y = sb*s*sin(c);
995
996c = cos(teta); s = sin(teta);
997x = mx + c*X - s*Y;
998y = my + s*X + c*Y;
999}
1000
[3602]1001} /* namespace SOPHYA */
1002
1003
1004
1005/////////////////////////////////////////////////////////////////
1006/*
[3615]1007**** Remarques sur complex< r_8 > ComplexGaussian(double sig) ****
[3602]1008
1009--- variables gaussiennes x,y independantes
1010x gaussien: pdf f(x) = 1/(sqrt(2Pi) Sx) exp(-(x-Mx)^2/(2 Sx^2))
1011y gaussien: pdf f(y) = 1/(sqrt(2Pi) Sy) exp(-(y-My)^2/(2 Sy^2))
1012x,y independants --> pdf f(x,y) = f(x) f(y)
1013On a:
1014 <x> = Integrate[x*f(x)] = Mx
1015 <x^2> = Integrate[x^2*f(x)] = Mx^2 + Sx^2
1016
1017--- On cherche la pdf g(r,t) du module et de la phase
1018 x = r cos(t) , y = r sin(t)
1019 r=sqrt(x^2+y^2 , t=atan2(y,x)
1020 (r,t) --> (x,y): le Jacobien = r
1021
1022 g(r,t) = r f(x,y) = r f(x) f(y)
1023 = r/(2Pi Sx Sy) exp(-(x-Mx)^2/(2 Sx^2)) exp(-(y-My)^2/(2 Sy^2))
1024
1025- Le cas general est complique
1026 (cf D.Pelat cours DEA "bruits et signaux" section 4.5)
1027
1028- Cas ou "Mx = My = 0" et "Sx = Sy = S"
1029 c'est la pdf du module et de la phase d'un nombre complexe
1030 dont les parties reelles et imaginaires sont independantes
1031 et sont distribuees selon des gaussiennes de variance S^2
1032 g(r,t) = r/(2Pi S^2) exp(-r^2/(2 S^2))
1033 La distribution de "r" est donc:
1034 g(r) = Integrate[g(r,t),{t,0,2Pi}]
1035 = r/S^2 exp(-r^2/(2 S^2))
1036 La distribution de "t" est donc:
1037 g(t) = Integrate[g(r,t),{r,0,Infinity}]
1038 = 1 / 2Pi (distribution uniforme sur [0,2Pi[)
1039 Les variables aleatoires r,t sont independantes:
1040 g(r,t) = g(r) g(t)
1041On a:
1042 <r> = Integrate[r*g(r)] = sqrt(PI/2)*S
1043 <r^2> = Integrate[r^2*g(r)] = 2*S^2
1044 <r^3> = Integrate[r^3*g(r)] = 3*sqrt(PI/2)*S^3
1045 <r^4> = Integrate[r^4*g(r)] = 8*S^4
1046
1047- Attention:
1048La variable complexe "c = x+iy = r*exp(i*t)" ainsi definie verifie:
1049 <|c|^2> = <c c*> = <x^2+y^2> = <r^2> = 2 S^2
1050Si on veut generer une variable complexe gaussienne telle que
1051 <c c*> = s^2 alors il faut prendre S = s/sqrt(2) comme argument
1052
1053*/
Note: See TracBrowser for help on using the repository browser.