Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members | Related Pages

RandomFuns.C

Go to the documentation of this file.
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 // Large primes taken from http://primes.utm.edu/lists/small/millions/primes1.zip:
00056 // List of 1st million primes
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 //   long long i = 3498493*seed()+7369133*index; 
00087 //   i ^= 123456789LL;
00088 //   i = std::abs(i);
00089 //   i = iterate (i);
00090 //   i = ((i & 65535)<<16) | ((i >> 16) & 65535);
00091 //   i = iterate (i);
00092 //   i = ((i & 65535)<<16) | ((i >> 16) & 65535);
00093 //   i = iterate (i);
00094 //   i = iterate (i);
00095 //   return toDouble (i);
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); // underflow bin
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; // make underflow bin as wide as first bin
00226   edges[nbins] = 2*edges[nbins-1]-edges[nbins-2];        // make overflow bin as wide as last bin
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); // underflow bin
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   // Round edges
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 }

Generated on Thu Oct 26 12:52:58 2006 for SFH by doxygen 1.3.2