3 ClassImp(AliRandom) // Class implementation to enable ROOT I/O
7 // Creation of an AliRandom object and default initialisation
9 // A seed is used to create the initial u[97] table.
10 // This seed is converted into four startup parameters i j k and l
11 // (see member function "unpack").
13 // Suggested test values : i=12 j=34 k=56 l=78 (see article)
14 // which corresponds to : seed = 53310452
16 Int_t seed=53310452; // Default seed
17 Start(seed,0,0); // Start the sequence for this seed from scratch
19 ///////////////////////////////////////////////////////////////////////////
20 AliRandom::AliRandom(Int_t seed)
22 // Creation of an AliRandom object and user defined initialisation
24 Start(seed,0,0); // Start the sequence for this seed from scratch
26 ///////////////////////////////////////////////////////////////////////////
27 AliRandom::AliRandom(Int_t seed,Int_t cnt1,Int_t cnt2)
29 // Creation of an AliRandom object and user defined initialisation
31 // seed is the seed to create the initial u[97] table.
32 // The range of the seed is : 0 <= seed <= 921350143
34 // cnt1 and cnt2 are the parameters for the counting system
35 // to enable a start of the sequence at a certain point.
36 // The current values of seed, cnt1 and cnt2 can be obtained
37 // via the member functions "GetSeed", "GetCnt1" and "GetCnt2" resp.
38 // To start from scratch one should select : cnt1=0 and cnt2=0
40 Start(seed,cnt1,cnt2); // Start the sequence from a user defined point
42 ///////////////////////////////////////////////////////////////////////////
43 AliRandom::~AliRandom()
45 // Destructor to delete memory allocated for the area function arrays
46 if (fXa) delete [] fXa;
48 if (fYa) delete [] fYa;
50 if (fIbins) delete [] fIbins;
53 ///////////////////////////////////////////////////////////////////////////
54 void AliRandom::Start(Int_t seed,Int_t cnt1,Int_t cnt2)
56 // Start a certain sequence from scratch or from a user defined point
58 // The algorithm to start from scratch is based on the routine RSTART
59 // as described in the report by G.Marsaglia and A.Zaman
60 // (FSU-SCRI-87-50 Florida State University 1987).
62 // seed is the seed to create the initial u[97] table.
63 // This seed is converted into four startup parameters i j k and l
64 // (see the member function "unpack").
66 // The range of the seed is : 0 <= seed <= 921350143
68 // Suggested test values : i=12 j=34 k=56 l=78 (see article)
69 // which corresponds to : seed = 53310452
71 // cnt1 and cnt2 are the parameters for the counting system
72 // to enable a start of the sequence at a certain point.
73 // The current values of seed, cnt1 and cnt2 can be obtained
74 // via the member functions "GetSeed", "GetCnt1" and "GetCnt2" resp.
75 // To start from scratch one should select : cnt1=0 and cnt2=0
77 // Reset the area function
83 // Clipping parameter to prevent overflow of the counting system
86 // Set the lags for the Fibonacci sequence of the first part
87 // The sequence is set to F(97,33,*) (see article)
91 // Unpack the seed value and determine i, j, k and l
100 // Fill the starting table for the first part of the combination
103 for (Int_t ii=0; ii<97; ii++)
108 for (Int_t jj=1; jj<=24; jj++)
110 m=(((i*j)%179)*k)%179;
115 if ((l*m)%64 >= 32) s+=t;
121 // Initialise the second part of the combination
122 fC=362436./16777216.;
123 fCd=7654321./16777216.;
124 fCm=16777213./16777216.;
126 // Generate random numbers upto the user selected starting point
127 // on basis of the counting system
128 if (cnt1 > 0) Uniform(cnt1);
131 for (Int_t n=1; n<=cnt2; n++)
137 ///////////////////////////////////////////////////////////////////////////
138 void AliRandom::Unpack(Int_t seed,Int_t& i,Int_t& j,Int_t& k,Int_t& l)
140 // Unpack the seed into the four startup parameters i,j,k and l
142 // The range of the seed is : 0 <= seed <= 921350143
144 // From the article :
145 // The i,j and k values may be chosen in the interval : 1 <= n <= 178
146 // The l value may be in the interval : 0 <= l <= 168
148 // Taking into account the period of the 3-lagged Fibonacci sequence
149 // The following "bad" combinations have to be ruled out :
161 // To rule these "bad" combinations out all together, we choose
162 // the following allowed ranges :
163 // The i,j and k values may be chosen in the interval : 2 <= n <= 177
164 // The l value may be in the interval : 0 <= l <= 168
166 // and use the formula :
167 // seed = (i-2)*176*176*169 + (j-2)*176*169 + (k-2)*169 + l
169 if ((seed >= 0) && (seed <= 921350143)) // Check seed value
172 Int_t imin2=idum/(176*176*169);
173 idum=idum%(176*176*169);
174 Int_t jmin2=idum/(176*169);
176 Int_t kmin2=idum/169;
185 cout << " *AliRandom::unpack()* Unallowed seed value encountered."
186 << " seed = " << seed << endl;
187 cout << " Seed will be set to default value." << endl;
189 seed=53310452; // Default seed
190 Start(seed,0,0); // Start the sequence for this seed from scratch
193 ///////////////////////////////////////////////////////////////////////////
194 Int_t AliRandom::GetSeed()
196 // Provide the current seed value
199 ///////////////////////////////////////////////////////////////////////////
200 Int_t AliRandom::GetCnt1()
202 // Provide the current value of the counter cnt1
205 ///////////////////////////////////////////////////////////////////////////
206 Int_t AliRandom::GetCnt2()
208 // Provide the current value of the counter cnt2
211 ///////////////////////////////////////////////////////////////////////////
212 void AliRandom::Info()
214 // Print the current seed, cnt1 and cnt2 values
215 cout << " *Random* seed = " << fSeed
216 << " cnt1 = " << fCnt1 << " cnt2 = " << fCnt2 << endl;
218 ///////////////////////////////////////////////////////////////////////////
219 Float_t AliRandom::Uniform()
221 // Generate uniform random numbers in the interval <0,1>
223 // The algorithm is based on lagged Fibonacci sequences (first part)
224 // combined with a congruential method (second part)
225 // as described in the report by G.Marsaglia and A.Zaman
226 // (FSU-SCRI-87-50 Florida State University 1987).
229 // 1) Period = 2**144
230 // 2) Same sequence of 24-bit real numbers on all common machines
232 // First part of the combination : F(97,33,*) (see article for explanation)
233 Float_t unirnu=fU[fI-1]-fU[fJ-1];
234 if (unirnu < 0) unirnu+=1.;
241 // Second part of the combination (see article for explanation)
243 if (fC < 0.) fC+=fCm;
245 if (unirnu < 0.) unirnu+=1.;
247 // Update the counting system to enable sequence continuation
248 // at an arbitrary starting position.
249 // Two counters have been introduced to avoid overflow
250 // fCnt1 : Counter which goes up to fClip
251 // and is reset when fClip is reached
252 // fCnt2 : Counts the number of times fClip has been reached
260 if (unirnu <= 0.) unirnu=Uniform(); // Exclude 0. from the range
264 ///////////////////////////////////////////////////////////////////////////
265 Float_t AliRandom::Uniform(Float_t a,Float_t b)
267 // Generate uniform random numbers in the interval <a,b>
271 Float_t rndm=Uniform();
272 rndm=rmin+fabs(rndm*(a-b));
276 ///////////////////////////////////////////////////////////////////////////
277 void AliRandom::Uniform(Float_t* vec,Int_t n,Float_t a,Float_t b)
279 // Generate a vector of uniform random numbers in the interval <a,b>
280 // This saves lots of (member)function calls in case many random
281 // numbers are needed at once.
283 // n = The number of random numbers to be generated
285 // The algorithm is based on lagged Fibonacci sequences (first part)
286 // combined with a congruential method (second part)
287 // as described in the report by G.Marsaglia and A.Zaman
288 // (FSU-SCRI-87-50 Florida State University 1987).
291 // 1) Period = 2**144
292 // 2) Same sequence of 24-bit real numbers on all common machines
294 // Determine the minimum of a and b
298 // First generate random numbers within <0,1>
299 if (n > 0) // Check n value
301 for (Int_t jvec=0; jvec<n; jvec++)
303 // First part of the combination : F(97,33,*)
304 Float_t unirnu=fU[fI-1]-fU[fJ-1];
305 if (unirnu < 0) unirnu+=1.;
312 // Second part of the combination
314 if (fC < 0.) fC+=fCm;
316 if (unirnu < 0.) unirnu+=1.;
318 // Update the counting system to enable sequence continuation
319 // at an arbitrary starting position.
320 // Two counters have been introduced to avoid overflow
321 // fCnt1 : Counter which goes up to fClip
322 // and is reset when fClip is reached
323 // fCnt2 : Counts the number of times fClip has been reached
331 if (unirnu <= 0.) unirnu=Uniform(); // Exclude 0. from the range
333 // Fill the vector within the selected range
334 vec[jvec]=rmin+fabs(unirnu*(a-b));
339 cout << " *AliRandom::Uniform* Invalid value n = " << n << endl;
342 ///////////////////////////////////////////////////////////////////////////
343 void AliRandom::Uniform(Float_t* vec,Int_t n)
345 // Generate a vector of uniform random numbers in the interval <0,1>
346 // This saves lots of (member)function calls in case many random
347 // numbers are needed at once.
349 // n = The number of random numbers to be generated
351 Uniform(vec,n,0.,1.);
353 ///////////////////////////////////////////////////////////////////////////
354 void AliRandom::Uniform(Int_t n)
356 // Generate n uniform random numbers in in one go.
357 // This saves lots of (member)function calls in case one needs to skip
358 // to a certain point in a sequence.
360 // n = The number of random numbers to be generated
362 // Note : No check is made here to exclude 0 from the range.
363 // It's only the number of generated randoms that counts
365 // The algorithm is based on lagged Fibonacci sequences (first part)
366 // combined with a congruential method (second part)
367 // as described in the report by G.Marsaglia and A.Zaman
368 // (FSU-SCRI-87-50 Florida State University 1987).
371 // 1) Period = 2**144
372 // 2) Same sequence of 24-bit real numbers on all common machines
374 if (n > 0) // Check n value
376 for (Int_t jvec=0; jvec<n; jvec++)
378 // First part of the combination : F(97,33,*)
379 Float_t unirnu=fU[fI-1]-fU[fJ-1];
380 if (unirnu < 0) unirnu+=1.;
387 // Second part of the combination
389 if (fC < 0.) fC+=fCm;
391 if (unirnu < 0.) unirnu+=1.;
393 // Update the counting system to enable sequence continuation
394 // at an arbitrary starting position.
395 // Two counters have been introduced to avoid overflow
396 // fCnt1 : Counter which goes up to fClip
397 // and is reset when fClip is reached
398 // fCnt2 : Counts the number of times fClip has been reached
409 cout << " *AliRandom::Uniform* Invalid value n = " << n << endl;
412 ///////////////////////////////////////////////////////////////////////////
413 Float_t AliRandom::Gauss(Float_t mean,Float_t sigma)
415 // Generate gaussian distributed random numbers with certain mean and sigma
418 // P(x) = The gaussian distribution function
419 // --> ln(P) provides an expression for (x-xmean)**2 from which
420 // the following expression for x can be obtained
422 // x = xmean +/- sigma * sqrt(-2*ln(q))
424 // in which q is an expression in terms of pi, sigma and p and lies within
425 // the interval <0,1>.
427 // The gaussian distributed x values are obtained as follows :
429 // 1) Two uniform random numbers q1 and q2 in <0,1> are generated.
430 // 2) q1 is in fact a uniform generated value for P which is substituted
431 // directly in the formula above.
432 // 3) The value of q2 determines whether we use the + or - sign.
434 // Generate the two uniform random numbers q1 and q2 in <0,1>
439 // Use q1 and q2 to get the gaussian distributed random number
440 Float_t pi=acos(-1.);
441 Float_t unirng=mean+cos(2.*pi*q2)*sigma*sqrt(-2.*log(q1));
445 ///////////////////////////////////////////////////////////////////////////
446 Float_t AliRandom::Gauss()
448 // Generate gaussian distributed random numbers with mean=0 and sigma=1
452 ///////////////////////////////////////////////////////////////////////////
453 void AliRandom::Gauss(Float_t* vec,Int_t n,Float_t mean,Float_t sigma)
455 // Generate a vector of gaussian random numbers with certain mean and sigma
456 // This saves lots of (member)function calls in case many random
457 // numbers are needed at once.
459 // n = The number of random numbers to be generated
461 if (n > 0) // Check n value
463 // The vector to hold the q1 and q2 values.
464 // Two subsequent q[] values are used for q1 and q2
465 // in order to obtain identical random numbers in the vector
466 // as when generating n single ones.
468 Float_t* q=new Float_t[m];
471 // Fill the vector with gaussian random numbers
472 Float_t pi=acos(-1.);
474 for (Int_t jvec=0; jvec<n; jvec++)
476 q1=q[jvec*2]; // use two subsequent q[] values
478 vec[jvec]=mean+cos(2.*pi*q2)*sigma*sqrt(-2.*log(q1));
484 cout << " *AliRandom::Gauss* Invalid value n = " << n << endl;
487 ///////////////////////////////////////////////////////////////////////////
488 void AliRandom::Gauss(Float_t* vec,Int_t n)
490 // Generate a vector of gaussian random numbers with mean=0 and sigma=1
491 // This saves lots of (member)function calls in case many random
492 // numbers are needed at once.
494 // n = The number of random numbers to be generated
498 ///////////////////////////////////////////////////////////////////////////
499 Float_t AliRandom::Poisson(Float_t mean)
501 // Generate Poisson distributed random numbers with certain mean
505 // P(n) = exp(-mean)*mean**n/n! is the Poisson distribution function
507 // with : n = 0,1,2,3,... and mean > 0
509 // To generate the distribution, the "sum trick" is used as mentioned
510 // in "Formulae and Methods in Experimental data Evaluation Vol. 1"
512 Float_t unirnp=0.; // Initialise the random number value
514 if (mean <= 0.) // Check the mean value
516 cout << " *AliRandom::Poisson* Invalid value mean = " << mean
517 << " Should be positive." << endl;
521 if (mean > 80.) // Use gaussian dist. for high mean values to save time
523 Float_t grndm=Gauss();
524 Float_t rpois=mean+grndm*sqrt(mean);
525 Int_t npois=int(rpois);
526 if ((rpois-float(npois)) > 0.5) npois++;
529 else // Construct a Poisson random number from a uniform one
532 Float_t expxm=exp(-mean);
534 while (poitst > expxm)
536 Float_t rndm=Uniform();
541 } // end of check for using Gauss method
542 } // end of mean validity checkn
545 ///////////////////////////////////////////////////////////////////////////
546 void AliRandom::Poisson(Float_t* vec,Int_t n,Float_t mean)
548 // Generate a vector of Poisson dist. random numbers with certain mean
549 // This saves lots of (member)function calls in case many random
550 // numbers are needed at once.
552 // n = The number of random numbers to be generated
556 // P(n) = exp(-mean)*mean**n/n! is the Poisson distribution function
558 // with : n = 0,1,2,3,... and mean > 0
560 // To generate the distribution, the "sum trick" is used as mentioned
561 // in "Formulae and Methods in Experimental data Evaluation Vol. 1"
563 if (n <= 0) // Check n value
565 cout << " *AliRandom::Poisson* Invalid value n = " << n << endl;
569 if (mean <= 0.) // Check the mean value
571 cout << " *AliRandom::Poisson* Invalid value mean = " << mean
572 << " Should be positive." << endl;
576 if (mean > 80.) // Use gaussian dist. for high mean values to save time
578 Float_t* grndm=new Float_t[n];
582 for (Int_t jvec=0; jvec<n; jvec++)
584 rpois=mean+grndm[jvec]*sqrt(mean);
586 if ((rpois-float(npois)) > 0.5) npois++;
587 vec[jvec]=float(npois);
591 else // Construct Poisson random numbers from a uniform ones
593 Float_t expxm=exp(-mean);
596 for (Int_t jvec=0; jvec<n; jvec++)
600 while (poitst > expxm)
602 Float_t rndm=Uniform();
606 vec[jvec]=float(npois);
608 } // end of check for using Gauss method
609 } // end of mean validity check
610 } // end of n validity check
612 ///////////////////////////////////////////////////////////////////////////
613 void AliRandom::SetUser(Float_t a,Float_t b,Int_t n,Float_t (*f)(Float_t))
615 // Determine the area under f(x) as a function of x
616 // This is called the "area function" and serves as a basis to
617 // provide random numbers in [a,b] according to the user defined
618 // distribution f(x).
619 // The area function is normalised such that the most extreme
622 fNa=n+1; // The number of bins for the area function
623 fXa=new Float_t[fNa]; // The binned x values of the area function
624 fYa=new Float_t[fNa]; // The corresponding summed f(x) values
625 fIbins=new Int_t[fNa]; // The bin numbers of the random x candidates
629 Float_t step=fabs(a-b)/float(n);
633 for (Int_t i=0; i<fNa; i++) // Fill bins of the area function
635 x=xmin+float(i)*step;
638 if (i > 0) fYa[i]+=fYa[i-1];
639 if (fabs(fYa[i]) > extreme) extreme=fabs(fYa[i]);
641 fYamin=fYa[0]/extreme;
642 fYamax=fYa[0]/extreme;
643 for (Int_t j=0; j<fNa; j++) // Normalise the area function
645 fYa[j]=fYa[j]/extreme;
646 if (fYa[j] < fYamin) fYamin=fYa[j];
647 if (fYa[j] > fYamax) fYamax=fYa[j];
650 ///////////////////////////////////////////////////////////////////////////
651 void AliRandom::SetUser(Float_t* x,Float_t* y,Int_t n)
653 // Determine the area under y[i] as a function of x[i]
654 // This is called the "area function" and serves as a basis to
655 // provide random numbers in x according to the user provided
656 // distribution (x[i],y[i]).
657 // The area function is normalised such that the most extreme
660 fNa=n; // The number of bins for the area function
661 fXa=new Float_t[fNa]; // The binned x values of the area function
662 fYa=new Float_t[fNa]; // The corresponding summed y values
663 fIbins=new Int_t[fNa]; // The bin numbers of the random x candidates
665 // Order input data with increasing x
668 for (Int_t i=1; i<fNa; i++) // Loop over x[]
670 for (Int_t j=0; j<i; j++) // Loop over xa[]
674 for (Int_t k=i; k>=j; k--) // Create empty position
679 fXa[j]=x[i]; // Put x[] value in empty position
680 fYa[j]=y[i]; // Put y[] value in empty position
681 break; // Go for next x[] value
683 if (j == i-1) // This x[] value is the largest so far
685 fXa[i]=x[i]; // Put x[] value at the end of x[]
686 fYa[i]=y[i]; // Put y[] value at the end of y[]
688 } // End loop over fXa[]
689 } // End loop over x[]
692 for (Int_t l=0; l<fNa; l++) // Fill area function
694 if (l > 0) fYa[l]+=fYa[l-1];
695 if (fabs(fYa[l]) > extreme) extreme=fabs(fYa[l]);
697 fYamin=fYa[0]/extreme;
698 fYamax=fYa[0]/extreme;
699 for (Int_t m=0; m<fNa; m++) // Normalise the area function
701 fYa[m]=fYa[m]/extreme;
702 if (fYa[m] < fYamin) fYamin=fYa[m];
703 if (fYa[m] > fYamax) fYamax=fYa[m];
706 ///////////////////////////////////////////////////////////////////////////
707 Float_t AliRandom::User()
709 // Provide a random number according to the user defined distribution
713 // Select by a uniform random number a certain area fraction (from fYa[])
714 // of the area function.
715 // The required random number is given by the corresponding x value (fXa[])
716 // of the area function.
717 // In case of more than one x value candidate, select randomly one of them.
721 Float_t ra=Uniform(fYamin,fYamax); // Random value of the area function
722 Float_t dmin=100.*fabs(fYamax-fYamin); // Init. the min. distance encountered
725 for (Int_t i=0; i<fNa; i++) // Search for fYa[] value(s) closest to ra
727 dist=fabs(ra-fYa[i]);
728 if (dist <= dmin) // fYa[i] within smallest distance --> extra candidate
731 if (dist < dmin) ncand=1; // Smallest distance so far --> THE candidate
737 Int_t jbin=0; // The bin number to hold the required x value
738 if (ncand == 1) jbin=fIbins[0];
740 if (ncand > 1) // Multiple x value candidates --> pick one randomly
742 Float_t cand=Uniform(1.,float(ncand));
743 Int_t jcand=int(cand);
744 if ((cand-float(jcand)) > 0.5) jcand++;
745 jbin=fIbins[jcand-1];
748 if (jbin > 0) // Pick randomly a value in this x-bin
750 Float_t xlow=fXa[jbin-1];
751 if (jbin > 1) xlow=fXa[jbin-2];
752 Float_t xup=fXa[jbin-1];
753 if (jbin < fNa-1) xup=fXa[jbin];
754 unirnf=Uniform(xlow,xup);
757 if (ncand == 0) cout << " *AliRandom::User* No candidate found." << endl;
761 ///////////////////////////////////////////////////////////////////////////
762 void AliRandom::User(Float_t* vec,Int_t n)
764 // Generate a vector of random numbers according to a user defined dist.
765 // This saves lots of (member)function calls in case many random
766 // numbers are needed at once.
768 // n = The number of random numbers to be generated
772 // Select by a uniform random number a certain area fraction (from fYa[])
773 // of the area function.
774 // The required random number is given by the corresponding x value (fXa[])
775 // of the area function.
776 // In case of more than one x value candidate, select randomly one of them.
778 Float_t unirnf,ra,dmin,dist;
780 for (Int_t jvec=0; jvec<n; jvec++)
783 ra=Uniform(fYamin,fYamax); // Random value of the area function
784 dmin=100.*fabs(fYamax-fYamin); // Init. the min. distance encountered
786 for (Int_t i=0; i<fNa; i++) // Search for fYa[] value(s) closest to ra
788 dist=fabs(ra-fYa[i]);
789 if (dist <= dmin) // fYa[i] within smallest distance --> extra candidate
792 if (dist < dmin) ncand=1; // Smallest distance so far --> THE candidate
798 jbin=0; // The bin number to hold the required x value
799 if (ncand == 1) jbin=fIbins[0];
801 if (ncand > 1) // Multiple x value candidates --> pick one randomly
803 Float_t cand=Uniform(1.,float(ncand));
804 Int_t jcand=int(cand);
805 if ((cand-float(jcand)) > 0.5) jcand++;
806 jbin=fIbins[jcand-1];
809 if (jbin > 0) // Pick randomly a value in this x-bin
811 Float_t xlow=fXa[jbin-1];
812 if (jbin > 1) xlow=fXa[jbin-2];
813 Float_t xup=fXa[jbin-1];
814 if (jbin < fNa-1) xup=fXa[jbin];
815 unirnf=Uniform(xlow,xup);
818 if (ncand == 0) cout << " *AliRandom::User* No candidate found." << endl;
824 ///////////////////////////////////////////////////////////////////////////