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

Last change on this file since 4075 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
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <iostream>
4#include "pexceptions.h"
5#include "srandgen.h"
6#include "perandom.h"
7
8
9////////////////////////////////////////////////////////////////////////////
10/*!
11 \class SOPHYA::FunRan
12 \ingroup NTools
13 Classe for generating random variables from 1D function
14*/
15
16
17/********* Methode *********/
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
44*/
45FunRan::FunRan(FunRan::Func f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
46 : Histo(xMin,xMax,nBin)
47{
48 if(nBin<=1)
49 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
50 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
51 create_DF(pdf);
52}
53
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);
65}
66
67/********* Methode *********/
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).
71The return random values will be between 0 and nBin-1.
72See FunRan::FunRan(FunRan::Func...) for further comments.
73*/
74FunRan::FunRan(r_8 *tab, int_4 nBin, bool pdf)
75: Histo(-0.5,nBin-0.5,nBin)
76{
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);
81}
82
83/********* Methode *********/
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).
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*/
91FunRan::FunRan(r_8 *tab, int_4 nBin, r_8 xMin, r_8 xMax, bool pdf)
92: Histo(xMin,xMax,nBin)
93{
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);
98}
99
100/********* Methode *********/
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 *********/
125/*! Creator from an histogram
126If pdf=true, h is a probability density fonction (not necessary normalised).
127If pdf=false, h is a distribution function (not necessarly normalized to 1).
128See FunRan::FunRan(FunRan::Func...) for further comments.
129*/
130FunRan::FunRan(Histo &h, bool pdf)
131 : Histo(h)
132{
133 if(mBins<=1)
134 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
135 create_DF(pdf);
136}
137
138/********* Methode *********/
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 *********/
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);
158
159 // On normalise la FD
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 }
164 for(int_4 i=0;i<mBins;i++) (*this)(i) /= (*this)(mBins-1);
165}
166
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
170to the random uniform number (in [0,1[)
171*/
172int_4 FunRan::BinRandom()
173{
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;
178}
179
180/********* Methode *********/
181/*! Tirage avec retour abscisse du bin non interpole. */
182r_8 FunRan::Random()
183{
184 r_8 z=drand01();
185 int ibin = mBins-1;
186 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) {ibin=i; break;}
187 return BinCenter(ibin);
188}
189
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 }
202
203 // l'algorithme garanti que "z2-z1 != 0" et "z1<z2"
204 return BinLowEdge(ibin) + (z-z1)/(z2-z1)*binWidth;
205
206}
207
208////////////////////////////////////////////////////////////////////////////
209/*!
210 \class SOPHYA::FunRan2D
211 \ingroup NTools
212 Classe for generating random variables from 2D function
213*/
214
215/********* Methode *********/
216/*! Creator for random from a table */
217FunRan2D::FunRan2D(r_8 *tab, int_4 nBinX, int_4 nBinY)
218{
219 // Tirage en X, somme sur les Y.
220 r_8* tabX = new r_8[nBinX];
221 for (int_4 i=0; i<nBinX; i++) {
222 tabX[i] = 0;
223 for (int_4 j=0; j<nBinY; j++) {
224 tabX[i] += tab[i*nBinY +j];
225 }
226 }
227 ranX = new FunRan(tabX, nBinX);
228 delete[] tabX;
229
230 ranY = new FunRan* [nBinX];
231
232 for (int_4 k=0; k<nBinX; k++)
233 ranY[k] = new FunRan(tab + nBinY*k, nBinY);
234
235 nx = nBinX;
236}
237
238/********* Methode *********/
239/*! Creator for random from a table */
240FunRan2D::FunRan2D(r_8 **tab, int_4 nBinX, int_4 nBinY)
241{
242 // Tirage en X, somme sur les Y.
243 r_8* tabX = new r_8[nBinX];
244 for (int_4 i=0; i<nBinX; i++) {
245 tabX[i] = 0;
246 for (int_4 j=0; j<nBinY; j++) {
247 tabX[i] += tab[i][j];
248 }
249 }
250 ranX = new FunRan(tabX, nBinX);
251
252 ranY = new FunRan* [nBinX];
253
254 for (int_4 k=0; k<nBinX; k++)
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
263/********* Methode *********/
264/*! Destructor */
265FunRan2D::~FunRan2D()
266{
267 for (int_4 i=nx-1; i>=0; i--)
268 delete ranY[i];
269
270 delete[] ranY;
271
272 delete ranX;
273}
274
275/********* Methode *********/
276/*! Tirage avec retour du numeros de bin. */
277void FunRan2D::BinRandom(int_4& x, int_4& y)
278{
279 x = ranX->BinRandom();
280 y = ranY[x]->BinRandom();
281}
282
283/********* Methode *********/
284/*! Tirage avec retour abscisse et ordonnee du bin interpole. */
285void FunRan2D::Random(r_8& x, r_8& y)
286{
287 x = ranX->Random();
288 int_4 i = int_4(ceil(x));
289 y = ranY[i]->Random();
290}
291
Note: See TracBrowser for help on using the repository browser.