00001
00028 #include "jbltools/sfh/RandomFuns.h"
00029 #include "jbltools/sfh/IntFun.h"
00030 #include "jbltools/sfh/FloatFun.h"
00031
00032 #include "TH1.h"
00033
00034 #include <cmath>
00035 #include <cassert>
00036
00037
00038 static const char *ident="@(#)$Id: RandomFuns.C,v 1.5 2005/11/29 20:03:31 blist Exp $";
00039
00040 RandomFun::RandomFun (const IntFun& seed_, int index_, const char *name_ )
00041 : FloatFun (name_ ? name_ : str("Random(")+(seed_.getName() ? seed_.getName() : "?") + ", ",
00042 str(index_)+")"),
00043 seed(seed_),
00044 index(index_),
00045 cleanup (false)
00046 {}
00047
00048 RandomFun::RandomFun (const IntFun& seed_, int index_, const std::string &name_)
00049 : FloatFun (name_),
00050 seed(seed_),
00051 index(index_),
00052 cleanup (false)
00053 {}
00054
00055
00056
00057
00058 RandomFun::RandomFun (const IntFun& seed1_, const IntFun& seed2_, int index_, const char *name_ )
00059 : FloatFun (name_ ? name_ : str("Random(")+(seed1_.getName() ? seed1_.getName() : "?") + ", " +
00060 (seed2_.getName() ? seed2_.getName() : "?") + ", ",str(index_)+")"),
00061 seed(1327*seed1_+1997*seed2_),
00062 index(index_),
00063 cleanup (true)
00064 {}
00065
00066 RandomFun::RandomFun (const IntFun& seed1_, const IntFun& seed2_, int index_, const std::string &name_)
00067 : FloatFun (name_),
00068 seed(1327*seed1_+1997*seed2_),
00069 index(index_),
00070 cleanup (true)
00071 {}
00072
00073 const long long RandomFun::a = 16807LL;
00074 const long long RandomFun::c = 0LL;
00075 const long long RandomFun::m = 2147483647LL;
00076
00077 Float_FF RandomFun::operator() () const {
00078 long long i = 3498493*seed();
00079 i ^= 123456789LL;
00080 i = std::abs(i);
00081 i = iterate (i);
00082 i = ((i & 65535)<<16) | ((i >> 16) & 65535);
00083 i = iterate (i);
00084 for (int j = 0; j < 3*index; j++) i = iterate (i);
00085 return toDouble (i);
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 }
00097
00098 RandomFun::~RandomFun() {
00099 if (cleanup) const_cast<IntFun&>(seed).destroy();
00100 }
00101
00102 const FillIterator *RandomFun::getIterator() const {
00103 return seed.getIterator();
00104 }
00105
00106 GaussRandomFun::GaussRandomFun (const FloatFun& rnd_, double mean_, double sigma_, const char *name_ )
00107 : FloatFun (name_ ?
00108 str(name_) :
00109 str("GaussRandom(")+(rnd_.getName() ? rnd_.getName() : "?") + ", " + str(mean_) + ", " + str(sigma_)+")"),
00110 rnd(rnd_),
00111 mean(mean_),
00112 sigma (sigma_)
00113 {}
00114
00115 GaussRandomFun::GaussRandomFun (const FloatFun& rnd_, double mean_, double sigma_, const std::string &name_)
00116 : FloatFun (name_),
00117 rnd(rnd_),
00118 mean(mean_),
00119 sigma (sigma_)
00120 {}
00121
00122 const FillIterator *GaussRandomFun::getIterator() const {
00123 return rnd.getIterator();
00124 }
00125
00126
00127 Float_FF GaussRandomFun::operator() () const {
00128 double x1 = rnd();
00129 double x2 = RandomFun::generateNext(x1);
00130 double sq = sqrt(-2*log(x2));
00131 return sigma*sin(2*3.141592653589793238*x1)*sq + mean;
00132 }
00133
00134
00135 Poisson1Fun::Poisson1Fun (const FloatFun& rnd_, double mean_, const char *name_)
00136 : IntFun (name_ ? name_ : str("Poisson(")+rnd_.getName()+")"),
00137 rnd(rnd_),
00138 mean (mean_)
00139 {}
00140
00141 int Poisson1Fun::operator() () const {
00142 double r = rnd();
00143 double e = exp (-mean);
00144 double x = 0;
00145 double s = exp (-mean);
00146 for (int result = 0; result < 126; s *= mean/(++result)) {
00147 x += s;
00148 if (r < x) return result;
00149 }
00150 return 126;
00151 }
00152
00153 const FillIterator *Poisson1Fun::getIterator() const {
00154 return rnd.getIterator();
00155 }
00156
00157 Poisson2Fun::Poisson2Fun (const FloatFun& rnd_, double mean_, const char *name_)
00158 : IntFun (name_ ? name_ : str("Poisson(")+rnd_.getName()+")"),
00159 gaussrnd(*new GaussRandomFun (rnd_, mean_, std::sqrt(std::abs(mean_))))
00160 {}
00161
00162 Poisson2Fun::Poisson2Fun (const FloatFun& rnd_, double mean_, const std::string& name_)
00163 : IntFun (name_),
00164 gaussrnd(*new GaussRandomFun (rnd_, mean_, std::sqrt(std::abs(mean_))))
00165 {}
00166
00167 int Poisson2Fun::operator() () const {
00168 double g = gaussrnd();
00169 return (g < 0) ? 0 : (int)(g+0.5);
00170 }
00171
00172 const FillIterator *Poisson2Fun::getIterator() const {
00173 return gaussrnd.getIterator();
00174 }
00175
00176 Poisson2Fun::~Poisson2Fun() {
00177 gaussrnd.destroy();
00178 }
00179
00180 HistoRandomFun::HistoRandomFun (const FloatFun& rnd_, const TH1& histo, const char *name_ )
00181 : FloatFun (name_ ? str(name_) : str("HistoRandomFun(") + rnd_.getName() + ")"),
00182 rnd (rnd_),
00183 nbins (0),
00184 edges (0),
00185 values (0)
00186 {
00187 init (histo);
00188 }
00189 HistoRandomFun::HistoRandomFun (const FloatFun& rnd_, const TH1& histo, const std::string& name_ )
00190 : FloatFun (name_),
00191 rnd (rnd_),
00192 nbins (0),
00193 edges (0),
00194 values (0)
00195 {
00196 init (histo);
00197 }
00198
00199 Float_FF HistoRandomFun::operator() () const {
00200 if (nbins <= 0) return 0;
00201 assert (edges);
00202 assert (values);
00203 double x1 = rnd();
00204 double x2 = RandomFun::generateNext(x1);
00205 int ibin = 0;
00206 for (ibin=0; (ibin < nbins-1) && values[ibin] <= x1; ibin++);
00207 assert (ibin >=0);
00208 assert (ibin < nbins);
00209 return edges[ibin] + x2*(edges[ibin+1]-edges[ibin]);
00210 }
00211
00212 const FillIterator *HistoRandomFun::getIterator() const {
00213 return rnd.getIterator();
00214 }
00215
00216 void HistoRandomFun::init (const TH1& histo) {
00217 nbins = histo.GetNbinsX()+2;
00218 edges = new double[nbins+1];
00219 values = new double[nbins];
00220 values[0] = histo.GetBinContent(0);
00221 for (int ibin = 1; ibin < nbins; ibin++) {
00222 edges[ibin] = histo.GetBinLowEdge(ibin);
00223 values[ibin] = values[ibin-1] + histo.GetBinContent(ibin);
00224 }
00225 edges[0] = nbins>2 ? 2*edges[1]-edges[2] : edges[1]-1;
00226 edges[nbins] = 2*edges[nbins-1]-edges[nbins-2];
00227 double f = values[nbins-1] ? 1./values[nbins-1] : 1;
00228 for (int ibin = 0; ibin < nbins; ibin++) values[ibin] *= f;
00229 }
00230
00231 HistoRandomFun::~HistoRandomFun() {
00232 delete[] edges;
00233 delete[] values;
00234 }
00235
00236
00237 HistoRandomIntFun::HistoRandomIntFun (const FloatFun& rnd_, const TH1& histo, const char *name_ )
00238 : IntFun (name_ ? str(name_) : str("HistoRandomIntFun(") + rnd_.getName() + ")"),
00239 rnd (rnd_),
00240 nbins (0),
00241 edges (0),
00242 values (0)
00243 {
00244 init (histo);
00245 }
00246 HistoRandomIntFun::HistoRandomIntFun (const FloatFun& rnd_, const TH1& histo, const std::string& name_ )
00247 : IntFun (name_),
00248 rnd (rnd_),
00249 nbins (0),
00250 edges (0),
00251 values (0)
00252 {
00253 init (histo);
00254 }
00255
00256 int HistoRandomIntFun::operator() () const {
00257 if (nbins <= 0) return 0;
00258 assert (edges);
00259 assert (values);
00260 double x1 = rnd();
00261 double x2 = RandomFun::generateNext(x1);
00262 int ibin = 0;
00263 for (ibin=0; (ibin < nbins+1) && values[ibin] <= x1; ibin++);
00264 assert (ibin >=0);
00265 assert (ibin < nbins);
00266 return (int)(std::floor(edges[ibin] + x2*(edges[ibin+1]-edges[ibin]) + 0.5));
00267 }
00268
00269 const FillIterator *HistoRandomIntFun::getIterator() const {
00270 return rnd.getIterator();
00271 }
00272
00273 void HistoRandomIntFun::init (const TH1& histo) {
00274 nbins = histo.GetNbinsX()+2;
00275 edges = new double[nbins+1];
00276 values = new double[nbins];
00277 values[0] = histo.GetBinContent(0);
00278 for (int ibin = 1; ibin < nbins; ibin++) {
00279 edges[ibin] = histo.GetBinLowEdge(ibin);
00280 values[ibin] = values[ibin-1] + histo.GetBinContent(ibin);
00281 }
00282 edges[0] = nbins>2 ? 2*edges[1]-edges[2] : edges[1]-1;
00283 edges[nbins] = 2*edges[nbins-1]-edges[nbins-2];
00284 double f = values[nbins-1] ? 1./values[nbins-1] : 1;
00285 for (int ibin = 0; ibin < nbins; ibin++) values[ibin] *= f;
00286
00287 for (int ibin = 0; ibin <= nbins; ibin++) {
00288 if (edges[ibin] == std::floor(edges[ibin])) {
00289 edges[ibin] = edges[ibin]-0.5;
00290 }
00291 else {
00292 edges[ibin] = std::floor(edges[ibin]) + 0.5;
00293 }
00294 }
00295 }
00296
00297 HistoRandomIntFun::~HistoRandomIntFun() {
00298 delete[] edges;
00299 delete[] values;
00300 }
00301
00302 FloatFun& gauss (const FloatFunPoR& rnd, double mean, double sigma) {
00303 if (!rnd.pff) return *new ConstFun(0);
00304 return *new GaussRandomFun (*(rnd.pff), mean, sigma);
00305 }
00306
00307
00308 IntFun& poisson (const FloatFunPoR& rnd,
00309 double mean
00310 ) {
00311 if (!rnd.pff) return *new ConstIntFun(0);
00312 return (mean < 81) ?
00313 static_cast<IntFun&>(*new Poisson1Fun (*(rnd.pff), mean)) :
00314 static_cast<IntFun&>(*new Poisson2Fun (*(rnd.pff), mean));
00315 }