source: Sophya/trunk/SophyaLib/NTools/tsfunran.cc@ 3600

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

thread safe (Ts)FunRan, cmv 22/04/2009

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