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

Last change on this file since 3098 was 3097, checked in by cmv, 19 years ago

precisions sur ComplexGaussRan cmv 16/10/2006

File size: 6.8 KB
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include "pexceptions.h"
4#include "perandom.h"
5#include "pemath.h"
6#include <iostream>
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/*! Createur. f is a probability density function (PDF).
19 Le tirage aleatoire est fait sur un histogramme
20 Histo(xMin,xMax,nBin) (voir convention dans Histo).
21 Chaque bin de l'histogramme contient la valeur de la PDF
22 au centre du bin.
23 Les valeurs retournees sont les valeurs du centre des bins.
24 Si binw est la largeur du bin, les valeurs retournees
25 vont de xmin+binw/2 a xmax-binw/2.
26*/
27FunRan::FunRan(FunRan::Func f, r_8 xMin, r_8 xMax, int_4 nBin)
28: Histo(xMin,xMax,nBin)
29{
30 if(nBin<0)
31 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
32
33 // On cree la fonction de distribution a partir de la PDF
34 (*this)(0) = f(BinCenter(0));
35 for(int_4 i=1;i<nBin;i++) (*this)(i) = (*this)(i-1) + f(BinCenter(i));
36
37 if((*this)(nBin-1)<=0.)
38 throw RangeCheckError("FunRan::FunRan not a distribution function last bin is <=0");
39
40 for(int_4 i=0;i<nBin;i++) (*this)(i) /= (*this)(nBin-1);
41}
42
43/********* Methode *********/
44/*! Createur. tab is a probability density function.
45The return random values will be between 0 and nBin-1.
46See FunRan::FunRan(FunRan::Func...) for further comments.
47*/
48FunRan::FunRan(r_8 *tab, int_4 nBin)
49: Histo(-0.5,nBin-0.5,nBin)
50{
51 if(nBin<=0)
52 throw RangeCheckError("FunRan::FunRan no bin in Histo");
53
54 (*this)(0) = tab[0];
55 for(int_4 i=1;i<nBin;i++) (*this)(i) = (*this)(i-1) + tab[i];
56
57 if((*this)(nBin-1)<=0.)
58 throw RangeCheckError("FunRan::FunRan not a distribution function last bin is <=0");
59
60 for(int_4 i=0;i<nBin;i++) (*this)(i) /= (*this)(nBin-1);
61}
62
63/********* Methode *********/
64/*! Createur. tab is a probability density function
65The content of tab is identified has the content of
66an Histogram define by Histo(xMin,xMax,nBin).
67See FunRan::FunRan(FunRan::Func...) for further comments.
68*/
69FunRan::FunRan(r_8 *tab, int_4 nBin, r_8 xMin, r_8 xMax)
70: Histo(xMin,xMax,nBin)
71{
72 if(nBin<=0)
73 throw RangeCheckError("FunRan::FunRan no bin in Histo");
74
75 (*this)(0) = tab[0];
76 for(int_4 i=1;i<nBin;i++) (*this)(i) = (*this)(i-1) + tab[i];
77
78 if((*this)(nBin-1)<=0.)
79 throw RangeCheckError("FunRan::FunRan not a distribution function last bin is <=0");
80
81 for(int_4 i=0;i<nBin;i++) (*this)(i) /= (*this)(nBin-1);
82}
83
84/********* Methode *********/
85/*! Createur.
86If pdf=true, h is a probability density fonction.
87If pdf=false, h is a distribution function (not necessarly normalized to 1).
88See FunRan::FunRan(FunRan::Func...) for further comments.
89*/
90FunRan::FunRan(Histo &h, bool pdf)
91: Histo(h)
92{
93 if(mBins<=0)
94 throw RangeCheckError("FunRan::FunRan(Histo) no bin in Histo");
95
96 // On cree l'histo integre
97 if(pdf)
98 for(int_4 i=1;i<mBins;i++) (*this)(i) += (*this)(i-1);
99
100 if((*this)(mBins-1)<=0.)
101 throw RangeCheckError("FunRan::FunRan(Histo) not a distribution function last bin is <=0");
102
103 for(int_4 i=0;i<mBins;i++) (*this)(i) /= (*this)(mBins-1);
104}
105
106/********* Methode *********/
107/*! Tirage avec retour du numero de bin entre 0 et mBins-1.
108It returns the first bin whose content is greater or equal
109to the random uniform number (in [0,1])
110*/
111int_4 FunRan::BinRandom()
112{
113 // recherche du premier bin plus grand ou egal a z
114 r_8 z=drand01();
115 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) return i;
116 return mBins-1;
117}
118
119/********* Methode *********/
120/*! Tirage avec retour abscisse du bin non interpole. */
121r_8 FunRan::Random()
122{
123 r_8 z=drand01();
124 int ibin = mBins-1;
125 for(int_4 i=0;i<mBins;i++)
126 if(z<(*this)(i)) {ibin=i; break;}
127
128 return BinCenter(ibin);
129}
130
131
132
133////////////////////////////////////////////////////////////////////////////
134/*!
135 \class SOPHYA::FunRan2D
136 \ingroup NTools
137 Classe for generating random variables from 2D function
138*/
139
140/********* Methode *********/
141/*! Creator for random from a table */
142FunRan2D::FunRan2D(r_8 *tab, int_4 nBinX, int_4 nBinY)
143{
144 // Tirage en X, somme sur les Y.
145 r_8* tabX = new r_8[nBinX];
146 for (int_4 i=0; i<nBinX; i++) {
147 tabX[i] = 0;
148 for (int_4 j=0; j<nBinY; j++) {
149 tabX[i] += tab[i*nBinY +j];
150 }
151 }
152 ranX = new FunRan(tabX, nBinX);
153 delete[] tabX;
154
155 ranY = new FunRan* [nBinX];
156
157 for (int_4 k=0; k<nBinX; k++)
158 ranY[k] = new FunRan(tab + nBinY*k, nBinY);
159
160 nx = nBinX;
161}
162
163/********* Methode *********/
164/*! Creator for random from a table */
165FunRan2D::FunRan2D(r_8 **tab, int_4 nBinX, int_4 nBinY)
166{
167 // Tirage en X, somme sur les Y.
168 r_8* tabX = new r_8[nBinX];
169 for (int_4 i=0; i<nBinX; i++) {
170 tabX[i] = 0;
171 for (int_4 j=0; j<nBinY; j++) {
172 tabX[i] += tab[i][j];
173 }
174 }
175 ranX = new FunRan(tabX, nBinX);
176
177 ranY = new FunRan* [nBinX];
178
179 for (int_4 k=0; k<nBinX; k++)
180 if (tabX[k] != 0)
181 ranY[k] = new FunRan(tab[k], nBinY);
182 else ranY[k] = NULL;
183
184 delete[] tabX;
185 nx = nBinX;
186}
187
188/********* Methode *********/
189/*! Destructor */
190FunRan2D::~FunRan2D()
191{
192 for (int_4 i=nx-1; i>=0; i--)
193 delete ranY[i];
194
195 delete[] ranY;
196
197 delete ranX;
198}
199
200/********* Methode *********/
201/*! Tirage avec retour du numeros de bin. */
202void FunRan2D::BinRandom(int_4& x, int_4& y)
203{
204 x = ranX->BinRandom();
205 y = ranY[x]->BinRandom();
206}
207
208/********* Methode *********/
209/*! Tirage avec retour abscisse et ordonnee du bin interpole. */
210void FunRan2D::Random(r_8& x, r_8& y)
211{
212 x = ranX->Random();
213 int_4 i = int_4(ceil(x));
214 y = ranY[i]->Random();
215}
216
217
218
219/////////////////////////////////////////////////////////////////
220/*
221--- Remarque sur complex< r_8 > ComplexGaussRan(double sig)
222x = r cos(t) tire gaussien: pdf f(x) = 1/(sqrt(2Pi) Sx) exp(-(x-Mx)^2/(2 Sx^2))
223y = r sin(t) tire gaussien: pdf f(y) = 1/(sqrt(2Pi) Sy) exp(-(y-My)^2/(2 Sy^2))
224x,y independants --> pdf f(x,y) = f(x) f(y)
225- On cherche la pdf g(r,t) du module et de la phase
226 (r=sqrt(x^2+y^2,t=atan2(y,x)) --> (x,y): le Jacobien = r
227 g(r,t) = r f(x,y) = r f(x) f(y)
228 = r/(2Pi Sx Sy) exp(-(x-Mx)^2/(2 Sx^2)) exp(-(y-My)^2/(2 Sy^2))
229- Le cas general est complique
230 (cf D.Pelat cours DEA "bruits et signaux" section 4.5)
231- Cas ou "Mx = My = 0" et "Sx = Sy = S"
232 g(r,t) = r/(2Pi S^2) exp(-r^2/(2 S^2))
233 La distribution de "r" est donc:
234 g(r) = Integrate[g(r,t),{t,0,2Pi}]
235 = r/S^2 exp(-r^2/(2 S^2))
236 La distribution de "t" est donc:
237 g(t) = Integrate[g(r,t),{r,0,Infinity}]
238 = 1 / 2Pi (distribution uniforme sur [0,2Pi[)
239 Les variables aleatoires r,t sont independantes:
240 g(r,t) = g(r) g(t)
241- Attention:
242La variable complexe "c=x+iy" ainsi definie verifie:
243 <|c|^2> = <c c*> = <x^2+y^2> = <r^2> = 2 sig^2
244Si on veut generer une variable complexe gaussienne telle que
245 <c c*> = s^2 alors il faut sig = s/sqrt(2) comme argument
246*/
Note: See TracBrowser for help on using the repository browser.