source: Sophya/trunk/SophyaLib/NTools/perandom.cc@ 4033

Last change on this file since 4033 was 3615, checked in by cmv, 16 years ago

Modifs relatives a l'introduction de RandomGeneratorInterface + delete de srandgen.c, cmv 01/05/2009

File size: 7.8 KB
RevLine 
[2615]1#include "sopnamsp.h"
[244]2#include "machdefs.h"
[3615]3#include <iostream>
[244]4#include "pexceptions.h"
[3615]5#include "srandgen.h"
[220]6#include "perandom.h"
7
[3075]8
[220]9////////////////////////////////////////////////////////////////////////////
[3075]10/*!
11 \class SOPHYA::FunRan
12 \ingroup NTools
13 Classe for generating random variables from 1D function
14*/
[220]15
[3075]16
17/********* Methode *********/
[3109]18/*! Creator from a function.
19\verbatim
20 - if pdf==true: f est une densite de probabilite (PDF)
21 non necessairement normalisee
22 if pdf==false: f est une fonction de distribution (DF).
23 non necessairement normalisee
24 - Le tirage aleatoire est fait sur un histogramme
25 Histo(xMin,xMax,nBin) (voir convention dans Histo).
26 - Chaque bin de l'histogramme contient la valeur de la PDF
27 (ou de la DF) au centre du bin: h(i)=f(BinCenter(i))
28 - Les valeurs retournees sont les valeurs du centre des bins
29 pour le tirage non interpole et toutes les valeurs
30 entre [xmin,xmax] pour le tirage interpole
31 - La pdf doit etre interpretee comme etant nulle
32 pour des x<=xmin et x>=xmax
33 - Dans le bin "i" entre [x1,x2[ et de centre x0, h(i)=pdf(x0).
34 Pour le tirage interpole, la DF est approximee par un segment
35 et pdf(x0) est l'exces de proba entre x1 et x2:
36 bin 0 entre [xmin,BinHighEdge(0)[ :
37 la pdf va de 0 a pdf(BinCenter(0))
38 bin 1 entre [BinLowEdge(1),BinHighEdge(1)[:
39 la pdf va de pdf(BinCenter(0)) a pdf(BinCenter(1))
40 ...
41 bin n-1 entre [BinLowEdge(n-1),xmax[:
42 la pdf va de pdf(BinCenter(n-2)) a pdf(BinCenter(n-1))
43\endverbatim
[3075]44*/
[3109]45FunRan::FunRan(FunRan::Func f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
46 : Histo(xMin,xMax,nBin)
[220]47{
[3109]48 if(nBin<=1)
[2840]49 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
[3109]50 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
51 create_DF(pdf);
52}
[2840]53
[3109]54/********* Methode *********/
55/*! Creator from a ClassFunc
56See FunRan::FunRan(FunRan::Func...) for further comments.
57*/
58FunRan::FunRan(ClassFunc& f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
59 : Histo(xMin,xMax,nBin)
60{
61 if(nBin<=1)
62 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
63 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
64 create_DF(pdf);
[220]65}
66
[3075]67/********* Methode *********/
[3109]68/*! Creator from an table.
69If pdf=true, tab is a probability density fonction (not necessary normalised).
70If pdf=false, tab is a distribution function (not necessarly normalized to 1).
[3075]71The return random values will be between 0 and nBin-1.
72See FunRan::FunRan(FunRan::Func...) for further comments.
73*/
[3109]74FunRan::FunRan(r_8 *tab, int_4 nBin, bool pdf)
[2840]75: Histo(-0.5,nBin-0.5,nBin)
[220]76{
[3109]77 if(nBin<=1)
78 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
79 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab[i];
80 create_DF(pdf);
[220]81}
82
[3075]83/********* Methode *********/
[3109]84/*! Creator from an table.
85If pdf=true, tab is a probability density fonction (not necessary normalised).
86If pdf=false, tab is a distribution function (not necessarly normalized to 1).
[3075]87The content of tab is identified has the content of
88an Histogram define by Histo(xMin,xMax,nBin).
89See FunRan::FunRan(FunRan::Func...) for further comments.
90*/
[3109]91FunRan::FunRan(r_8 *tab, int_4 nBin, r_8 xMin, r_8 xMax, bool pdf)
[2840]92: Histo(xMin,xMax,nBin)
[220]93{
[3109]94 if(nBin<=1)
95 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
96 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab[i];
97 create_DF(pdf);
[220]98}
99
[3075]100/********* Methode *********/
[3608]101/*! Creator from a TVector
102*/
103FunRan::FunRan(TVector<r_8>& tab, bool pdf)
104: Histo(-0.5,tab.Size()-0.5,tab.Size())
105{
106 if(tab.Size()<=1)
107 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
108 for(int_4 i=0;i<tab.Size();i++) (*this)(i) = tab(i);
109 create_DF(pdf);
110}
111
112/********* Methode *********/
113/*! Creator from a TVector
114*/
115FunRan::FunRan(TVector<r_8>& tab, r_8 xMin, r_8 xMax, bool pdf)
116: Histo(xMin,xMax,tab.Size())
117{
118 if(tab.Size()<=1)
119 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
120 for(int_4 i=0;i<tab.Size();i++) (*this)(i) = tab(i);
121 create_DF(pdf);
122}
123
124/********* Methode *********/
[3109]125/*! Creator from an histogram
126If pdf=true, h is a probability density fonction (not necessary normalised).
[3075]127If pdf=false, h is a distribution function (not necessarly normalized to 1).
128See FunRan::FunRan(FunRan::Func...) for further comments.
129*/
[2840]130FunRan::FunRan(Histo &h, bool pdf)
[3109]131 : Histo(h)
[2838]132{
[3109]133 if(mBins<=1)
134 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
135 create_DF(pdf);
136}
[2840]137
[3109]138/********* Methode *********/
[3321]139/*! Creator by copy */
140FunRan::FunRan(const FunRan& fh)
141 : Histo(fh)
142{
143}
144
145/********* Methode *********/
146/*! Creator by default */
147FunRan::FunRan(void)
148{
149}
150
151/********* Methode *********/
[3109]152void FunRan::create_DF(bool pdf)
153// Creation (si necessaire) et normalisation de la DF
154{
155 // On fabrique la FD si necessaire
156 if(pdf)
157 for(int_4 i=1;i<mBins;i++) (*this)(i) += (*this)(i-1);
[2840]158
[3109]159 // On normalise la FD
[3195]160 if((*this)(mBins-1)<=0.) {
161 cout<<"FunRan::FunRan(Histo) not a distribution function last bin is <=0"<<endl;
162 throw RangeCheckError("FunRan::FunRan(Histo) not a distribution function last bin is <=0");
163 }
[2840]164 for(int_4 i=0;i<mBins;i++) (*this)(i) /= (*this)(mBins-1);
[2838]165}
166
[3075]167/********* Methode *********/
168/*! Tirage avec retour du numero de bin entre 0 et mBins-1.
169It returns the first bin whose content is greater or equal
[3109]170to the random uniform number (in [0,1[)
[3075]171*/
[1092]172int_4 FunRan::BinRandom()
[220]173{
[2840]174 // recherche du premier bin plus grand ou egal a z
175 r_8 z=drand01();
176 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) return i;
177 return mBins-1;
[220]178}
179
[3075]180/********* Methode *********/
181/*! Tirage avec retour abscisse du bin non interpole. */
[1092]182r_8 FunRan::Random()
[220]183{
[2840]184 r_8 z=drand01();
185 int ibin = mBins-1;
[3109]186 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) {ibin=i; break;}
[2840]187 return BinCenter(ibin);
[220]188}
189
[3109]190/********* Methode *********/
191/*! Tirage avec retour abscisse du bin interpole. */
192r_8 FunRan::RandomInterp(void)
193{
194 r_8 z=drand01();
195 int ibin = mBins-1;
196 r_8 z1=0., z2;
197 for(int_4 i=0;i<mBins;i++) {
198 z2 = (*this)(i);
199 if(z<z2) {ibin=i; break;}
200 z1 = z2;
201 }
[220]202
[3109]203 // l'algorithme garanti que "z2-z1 != 0" et "z1<z2"
204 return BinLowEdge(ibin) + (z-z1)/(z2-z1)*binWidth;
205
206}
207
[220]208////////////////////////////////////////////////////////////////////////////
[3075]209/*!
210 \class SOPHYA::FunRan2D
211 \ingroup NTools
212 Classe for generating random variables from 2D function
213*/
[220]214
[3075]215/********* Methode *********/
216/*! Creator for random from a table */
[1092]217FunRan2D::FunRan2D(r_8 *tab, int_4 nBinX, int_4 nBinY)
[220]218{
219 // Tirage en X, somme sur les Y.
[1092]220 r_8* tabX = new r_8[nBinX];
221 for (int_4 i=0; i<nBinX; i++) {
[220]222 tabX[i] = 0;
[1092]223 for (int_4 j=0; j<nBinY; j++) {
[220]224 tabX[i] += tab[i*nBinY +j];
225 }
226 }
227 ranX = new FunRan(tabX, nBinX);
228 delete[] tabX;
229
[2870]230 ranY = new FunRan* [nBinX];
[220]231
[1092]232 for (int_4 k=0; k<nBinX; k++)
[220]233 ranY[k] = new FunRan(tab + nBinY*k, nBinY);
234
235 nx = nBinX;
236}
237
[3075]238/********* Methode *********/
239/*! Creator for random from a table */
[1092]240FunRan2D::FunRan2D(r_8 **tab, int_4 nBinX, int_4 nBinY)
[220]241{
242 // Tirage en X, somme sur les Y.
[1092]243 r_8* tabX = new r_8[nBinX];
244 for (int_4 i=0; i<nBinX; i++) {
[220]245 tabX[i] = 0;
[1092]246 for (int_4 j=0; j<nBinY; j++) {
[220]247 tabX[i] += tab[i][j];
248 }
249 }
250 ranX = new FunRan(tabX, nBinX);
251
[2870]252 ranY = new FunRan* [nBinX];
[220]253
[1092]254 for (int_4 k=0; k<nBinX; k++)
[220]255 if (tabX[k] != 0)
256 ranY[k] = new FunRan(tab[k], nBinY);
257 else ranY[k] = NULL;
258
259 delete[] tabX;
260 nx = nBinX;
261}
262
[3075]263/********* Methode *********/
264/*! Destructor */
[220]265FunRan2D::~FunRan2D()
266{
[1092]267 for (int_4 i=nx-1; i>=0; i--)
[220]268 delete ranY[i];
269
270 delete[] ranY;
271
272 delete ranX;
273}
274
[3075]275/********* Methode *********/
276/*! Tirage avec retour du numeros de bin. */
[1092]277void FunRan2D::BinRandom(int_4& x, int_4& y)
[220]278{
279 x = ranX->BinRandom();
280 y = ranY[x]->BinRandom();
281}
282
[3075]283/********* Methode *********/
284/*! Tirage avec retour abscisse et ordonnee du bin interpole. */
[1092]285void FunRan2D::Random(r_8& x, r_8& y)
[220]286{
287 x = ranX->Random();
[1092]288 int_4 i = int_4(ceil(x));
[220]289 y = ranY[i]->Random();
290}
[3075]291
Note: See TracBrowser for help on using the repository browser.