CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/FastSimulation/Utilities/src/BaseNumericalRandomGenerator.cc

Go to the documentation of this file.
00001 #include "FastSimulation/Utilities/interface/BaseNumericalRandomGenerator.h"
00002 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00003 
00004 #include <cmath>
00005 // #include <iostream>
00006 
00007 BaseNumericalRandomGenerator::BaseNumericalRandomGenerator(
00008                               const RandomEngine* engine,
00009                               double xmin, double xmax, int n, int iter ) :
00010   random(engine),
00011   xmin(xmin), xmax(xmax), n(n), iter(iter) 
00012 {
00013   f.resize(n);
00014   sampling.resize(n);
00015 }
00016 
00017 void
00018 BaseNumericalRandomGenerator::initialize() {
00019   
00020   m = n-1;
00021   rmin = 0.;
00022   deltar = (double)m-rmin;
00023 
00024   std::vector<double> a,y,z,xnew;
00025   a.resize(n);
00026   y.resize(n);
00027   z.resize(n);
00028   xnew.resize(n);
00029 
00030   double sig1 = 0.;
00031 
00032   // Initialize sampling
00033   double du = (xmax-xmin)/(float)m;
00034   sampling[0] = xmin;
00035   for (int i=1; i<n; ++i) 
00036     sampling[i] = sampling[i-1] + du;
00037 
00038   // Starting point for iterations
00039   for (int it=0; it<iter; ++it) { 
00040     
00041     // Calculate function values
00042     for (int i=0; i<n; ++i )
00043       f[i] = function(sampling[i]);
00044 
00045     // Calculate bin areas
00046     for (int i=0; i<m; ++i )
00047       a[i] = (sampling[i+1]-sampling[i]) * (f[i+1]+f[i]) / 2.;
00048 
00049     // Calculate cumulative spectrum Y values
00050     y[0]=0.;
00051     for (int i=1; i<n; ++i )
00052       y[i] = y[i-1] + a[i-1];
00053 
00054     // Put equidistant points on y scale
00055     double dz = y[n-1]/(float)m;
00056     z[0]=0;
00057     for (int i=1; i<n; ++i ) 
00058       z[i] = z[i-1] + dz; 
00059 
00060     // Determine spacinf of Z points in between Y points
00061     // From this, determine new X values and finally replace old values
00062     xnew[0] = sampling[0];
00063     xnew[n-1] = sampling[n-1];
00064     int k=0; 
00065     for ( int i=1; i<m; ++i ) { 
00066       while ( y[k+1] < z[i] ) ++k;
00067       double r = (z[i]-y[k]) / (y[k+1]-y[k]);
00068       xnew[i] = sampling[k] + (sampling[k+1]-sampling[k])*r;
00069     }
00070 
00071     for ( int i=0; i<n; ++i )
00072       sampling[i] = xnew[i];
00073 
00074     sig1 = sig1 + y[m];
00075     // std::cout << "BaseNumericalRandomGenerator::Iteration # " << it+1 
00076     // << " Integral = " << sig1/(float)(it+1) 
00077     // << std::endl;
00078 
00079   }
00080 
00081 }
00082 
00083 double 
00084 BaseNumericalRandomGenerator::generate() const {
00085 
00086   double r=rmin+deltar*random->flatShoot();
00087   int i=(int)r;
00088   double s=r-(double)i;
00089   //  cout << " i,r,s = " << i << " " << r << " " << s << endl;
00090   return sampling[i]+s*(sampling[i+1]-sampling[i]);
00091 
00092 }
00093 
00094 double 
00095 BaseNumericalRandomGenerator::generateExp() const {
00096 
00097   double r=rmin+deltar*random->flatShoot();
00098   int i=(int)r;
00099   //  double s=r-(double)i;
00100   //  cout << " i,r,s = " << i << " " << r << " " << s << endl;
00101   double b = -std::log(f[i+1]/f[i]) / (sampling[i+1]-sampling[i]);
00102   double a = f[i] * std::exp(b*sampling[i]);
00103 
00104   double umin = -a/b*std::exp(-b*sampling[i]);
00105   double umax = -a/b*std::exp(-b*sampling[i+1]);
00106   double u= (umax-umin) * random->flatShoot() + umin;
00107 
00108   return -std::log(-b/a*u) / b;
00109 
00110 }
00111 
00112 double 
00113 BaseNumericalRandomGenerator::generateLin() const {
00114 
00115   double r=rmin+deltar*random->flatShoot();
00116   int i=(int)r;
00117   //  double s=r-(double)i;
00118   //  cout << " i,r,s = " << i << " " << r << " " << s << endl;
00119   double a = (f[i+1]-f[i]) / (sampling[i+1]-sampling[i]);
00120   double b = f[i] - a*sampling[i];
00121 
00122   double umin = a*sampling[i]*sampling[i]/2. + b*sampling[i];
00123   double umax = a*sampling[i+1]*sampling[i+1]/2. + b*sampling[i+1];
00124   double u= (umax-umin) * random->flatShoot() + umin;
00125 
00126   return (-b+std::sqrt(b*b+2.*a*u))/a;
00127 
00128 }
00129 
00130 
00131 bool BaseNumericalRandomGenerator::setSubInterval(double x1,double x2){
00132   if(x1<xmin||x2>xmax) return false;
00133   if(x1>x2)
00134     {
00135       double tmp=x1;
00136       x1=x2;
00137       x2=tmp;
00138     }
00139   
00140   unsigned ibin=1;
00141   for(;ibin<(unsigned)n&&x1>sampling[ibin];++ibin);
00142   unsigned ibin1=ibin;
00143   for(;ibin<(unsigned)n&&x2>sampling[ibin];++ibin);
00144   unsigned ibin2=ibin;
00145 
00146   //  cout << sampling[ibin1-1] << " " << x1 << " " << sampling[ibin1] << endl;
00147   // cout << sampling[ibin2-1] << " " << x2 << " " << sampling[ibin2] << endl;
00148 
00149   rmin = ibin1+(x1-sampling[ibin1])/(sampling[ibin1]-sampling[ibin1-1]);
00150   deltar= ibin2+(x2-sampling[ibin2])/(sampling[ibin2]-sampling[ibin2-1]) - rmin;
00151   //  cout << rmin << " " << deltar << endl;
00152   return true;
00153 }