| 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 | */ | 
|---|
| 45 | FunRan::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 | 
|---|
| 56 | See FunRan::FunRan(FunRan::Func...) for further comments. | 
|---|
| 57 | */ | 
|---|
| 58 | FunRan::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. | 
|---|
| 69 | If pdf=true, tab is a probability density fonction (not necessary normalised). | 
|---|
| 70 | If pdf=false, tab is a distribution function (not necessarly normalized to 1). | 
|---|
| 71 | The return random values will be between 0 and nBin-1. | 
|---|
| 72 | See FunRan::FunRan(FunRan::Func...) for further comments. | 
|---|
| 73 | */ | 
|---|
| 74 | FunRan::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. | 
|---|
| 85 | If pdf=true, tab is a probability density fonction (not necessary normalised). | 
|---|
| 86 | If pdf=false, tab is a distribution function (not necessarly normalized to 1). | 
|---|
| 87 | The content of tab is identified has the content of | 
|---|
| 88 | an Histogram define by Histo(xMin,xMax,nBin). | 
|---|
| 89 | See FunRan::FunRan(FunRan::Func...) for further comments. | 
|---|
| 90 | */ | 
|---|
| 91 | FunRan::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 | */ | 
|---|
| 103 | FunRan::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 | */ | 
|---|
| 115 | FunRan::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 | 
|---|
| 126 | If pdf=true, h is a probability density fonction (not necessary normalised). | 
|---|
| 127 | If pdf=false, h is a distribution function (not necessarly normalized to 1). | 
|---|
| 128 | See FunRan::FunRan(FunRan::Func...) for further comments. | 
|---|
| 129 | */ | 
|---|
| 130 | FunRan::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 */ | 
|---|
| 140 | FunRan::FunRan(const FunRan& fh) | 
|---|
| 141 | : Histo(fh) | 
|---|
| 142 | { | 
|---|
| 143 | } | 
|---|
| 144 |  | 
|---|
| 145 | /********* Methode *********/ | 
|---|
| 146 | /*! Creator by default */ | 
|---|
| 147 | FunRan::FunRan(void) | 
|---|
| 148 | { | 
|---|
| 149 | } | 
|---|
| 150 |  | 
|---|
| 151 | /********* Methode *********/ | 
|---|
| 152 | void 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. | 
|---|
| 169 | It returns the first bin whose content is greater or equal | 
|---|
| 170 | to the random uniform number (in [0,1[) | 
|---|
| 171 | */ | 
|---|
| 172 | int_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. */ | 
|---|
| 182 | r_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. */ | 
|---|
| 192 | r_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 */ | 
|---|
| 217 | FunRan2D::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 */ | 
|---|
| 240 | FunRan2D::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 */ | 
|---|
| 265 | FunRan2D::~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. */ | 
|---|
| 277 | void 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. */ | 
|---|
| 285 | void 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 |  | 
|---|