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

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

adaptation de TsFunRan a RandomGeneratorInterface , cmv 28/04/2009

File size: 6.8 KB
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <iostream>
4#include "pexceptions.h"
5#include "randr48.h"
6#include "tsfunran.h"
7
8
9////////////////////////////////////////////////////////////////////////////
10/*!
11 \class SOPHYA::TsFunRan
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*/
45TsFunRan::TsFunRan(TsFunRan::Func f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
46 : Histo(xMin,xMax,nBin), rg_(NULL), internal_rg_(false)
47{
48 if(nBin<=1)
49 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
50 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
51 rg_ = new DR48RandGen();
52 create_DF(pdf);
53}
54
55/********* Methode *********/
56/*! Creator from a ClassFunc
57See TsFunRan::TsFunRan(TsFunRan::Func...) for further comments.
58*/
59TsFunRan::TsFunRan(ClassFunc& f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
60 : Histo(xMin,xMax,nBin), rg_(NULL), internal_rg_(false)
61{
62 if(nBin<=1)
63 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
64 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
65 rg_ = new DR48RandGen();
66 create_DF(pdf);
67}
68
69/********* Methode *********/
70/*! Creator from an table.
71If pdf=true, tab is a probability density fonction (not necessary normalised).
72If pdf=false, tab is a distribution function (not necessarly normalized to 1).
73The return random values will be between 0 and nBin-1.
74See TsFunRan::TsFunRan(TsFunRan::Func...) for further comments.
75*/
76TsFunRan::TsFunRan(r_8 *tab, int_4 nBin, bool pdf)
77: Histo(-0.5,nBin-0.5,nBin), rg_(NULL), internal_rg_(false)
78{
79 if(nBin<=1)
80 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
81 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab[i];
82 rg_ = new DR48RandGen();
83 create_DF(pdf);
84}
85
86/********* Methode *********/
87/*! Creator from an table.
88If pdf=true, tab is a probability density fonction (not necessary normalised).
89If pdf=false, tab is a distribution function (not necessarly normalized to 1).
90The content of tab is identified has the content of
91an Histogram define by Histo(xMin,xMax,nBin).
92See FunRan::TsFunRan(TsFunRan::Func...) for further comments.
93*/
94TsFunRan::TsFunRan(r_8 *tab, int_4 nBin, r_8 xMin, r_8 xMax, bool pdf)
95: Histo(xMin,xMax,nBin), rg_(NULL), internal_rg_(false)
96{
97 if(nBin<=1)
98 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
99 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab[i];
100 rg_ = new DR48RandGen();
101 create_DF(pdf);
102}
103
104/********* Methode *********/
105/*! Creator from a TVector
106*/
107TsFunRan::TsFunRan(TVector<r_8>& tab, int_4 nBin, bool pdf)
108: Histo(-0.5,nBin-0.5,nBin), rg_(NULL), internal_rg_(false)
109{
110 if(nBin<=1)
111 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
112 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab(i);
113 rg_ = new DR48RandGen();
114 create_DF(pdf);
115}
116
117/********* Methode *********/
118/*! Creator from a TVector
119*/
120TsFunRan::TsFunRan(TVector<r_8>& tab, int_4 nBin, r_8 xMin, r_8 xMax, bool pdf)
121: Histo(xMin,xMax,nBin), rg_(NULL), internal_rg_(false)
122{
123 if(nBin<=1)
124 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
125 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab(i);
126 rg_ = new DR48RandGen();
127 create_DF(pdf);
128}
129
130/********* Methode *********/
131/*! Creator from an histogram
132If pdf=true, h is a probability density fonction (not necessary normalised).
133If pdf=false, h is a distribution function (not necessarly normalized to 1).
134See TsFunRan::TsFunRan(TsFunRan::Func...) for further comments.
135*/
136TsFunRan::TsFunRan(Histo &h, bool pdf)
137 : Histo(h), rg_(NULL), internal_rg_(false)
138{
139 if(mBins<=1)
140 throw RangeCheckError("TsFunRan::TsFunRan less than 2 bins requested");
141 rg_ = new DR48RandGen();
142 create_DF(pdf);
143}
144
145/********* Methode *********/
146/*! Creator by copy */
147TsFunRan::TsFunRan(const TsFunRan& fh)
148 : Histo(fh), rg_(fh.rg_), internal_rg_(false)
149{
150}
151
152/********* Methode *********/
153/*! Creator by default */
154TsFunRan::TsFunRan(void)
155 : rg_(NULL), internal_rg_(false)
156{
157}
158
159/********* Methode *********/
160TsFunRan::~TsFunRan(void)
161{
162 if(rg_!=NULL && internal_rg_) 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(RandomGeneratorInterface* rg)
183{
184 if(rg_!=NULL && internal_rg_) delete rg_;
185 rg_ = 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.