LCOV - code coverage report
Current view: top level - PYTHIA8/pythia8210dev/src - Basics.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 641 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 73 0.0 %

          Line data    Source code
       1             : // Basics.cc is a part of the PYTHIA event generator.
       2             : // Copyright (C) 2015 Torbjorn Sjostrand.
       3             : // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
       4             : // Please respect the MCnet Guidelines, see GUIDELINES for details.
       5             : 
       6             : // Function definitions (not found in the header) for the Rndm, Vec4,
       7             : // RotBstMatrix and Hist classes, and some related global functions.
       8             : 
       9             : #include "Pythia8/Basics.h"
      10             : 
      11             : // Access time information.
      12             : #include <ctime>
      13             : 
      14             : namespace Pythia8 {
      15             : 
      16             : //==========================================================================
      17             : 
      18             : // Rndm class.
      19             : // This class handles random number generation according to the
      20             : // Marsaglia-Zaman-Tsang algorithm
      21             : 
      22             : //--------------------------------------------------------------------------
      23             : 
      24             : // Constants: could be changed here if desired, but normally should not.
      25             : // These are of technical nature, as described for each.
      26             : 
      27             : // The default seed, i.e. the Marsaglia-Zaman random number sequence.
      28             : const int Rndm::DEFAULTSEED     = 19780503;
      29             : 
      30             : //--------------------------------------------------------------------------
      31             : 
      32             : // Method to pass in pointer for external random number generation.
      33             : 
      34             : bool Rndm::rndmEnginePtr( RndmEngine* rndmEngPtrIn) {
      35             : 
      36             :   // Save pointer.
      37           0 :   if (rndmEngPtrIn == 0) return false;
      38           0 :   rndmEngPtr      = rndmEngPtrIn;
      39           0 :   useExternalRndm = true;
      40             : 
      41             :   // Done.
      42           0 :   return true;
      43             : 
      44           0 : }
      45             : 
      46             : //--------------------------------------------------------------------------
      47             : 
      48             : // Initialize, normally at construction or in first call.
      49             : 
      50             : void Rndm::init(int seedIn) {
      51             : 
      52             :   // Pick seed in convenient way. Assure it to be non-negative.
      53             :   int seed = seedIn;
      54           0 :   if (seedIn < 0) seed = DEFAULTSEED;
      55           0 :   else if (seedIn == 0) seed = int(time(0));
      56           0 :   if (seed < 0) seed = -seed;
      57             : 
      58             :   // Unpack seed.
      59           0 :   int ij = (seed/30082) % 31329;
      60           0 :   int kl = seed % 30082;
      61           0 :   int i  = (ij/177) % 177 + 2;
      62           0 :   int j  = ij % 177 + 2;
      63           0 :   int k  = (kl/169) % 178 + 1;
      64           0 :   int l  =  kl % 169;
      65             : 
      66             :   // Initialize random number array.
      67           0 :   for (int ii = 0; ii < 97; ++ii) {
      68             :     double s = 0.;
      69             :     double t = 0.5;
      70           0 :     for (int jj = 0; jj < 48; ++jj) {
      71           0 :       int m = (( (i*j)%179 )*k) % 179;
      72             :       i = j;
      73             :       j = k;
      74             :       k = m;
      75           0 :       l = (53*l+1) % 169;
      76           0 :       if ( (l*m) % 64 >= 32) s += t;
      77           0 :       t *= 0.5;
      78             :     }
      79           0 :     u[ii] = s;
      80             :   }
      81             : 
      82             :   // Initialize other variables.
      83             :   double twom24 = 1.;
      84           0 :   for (int i24 = 0; i24 < 24; ++i24) twom24 *= 0.5;
      85           0 :   c   = 362436. * twom24;
      86           0 :   cd  = 7654321. * twom24;
      87           0 :   cm  = 16777213. * twom24;
      88           0 :   i97 = 96;
      89           0 :   j97 = 32;
      90             : 
      91             :   // Finished.
      92           0 :   initRndm  = true;
      93           0 :   seedSave  = seed;
      94           0 :   sequence  = 0;
      95             : 
      96           0 : }
      97             : 
      98             : //--------------------------------------------------------------------------
      99             : 
     100             : // Generate next random number uniformly between 0 and 1.
     101             : 
     102             : double Rndm::flat() {
     103             : 
     104             :   // Use external random number generator if such has been linked.
     105           0 :   if (useExternalRndm) return rndmEngPtr->flat();
     106             : 
     107             :   // Ensure that already initialized.
     108           0 :   if (!initRndm) init(DEFAULTSEED);
     109             : 
     110             :   // Find next random number and update saved state.
     111           0 :   ++sequence;
     112             :   double uni;
     113           0 :   do {
     114           0 :     uni = u[i97] - u[j97];
     115           0 :     if (uni < 0.) uni += 1.;
     116           0 :     u[i97] = uni;
     117           0 :     if (--i97 < 0) i97 = 96;
     118           0 :     if (--j97 < 0) j97 = 96;
     119           0 :     c -= cd;
     120           0 :     if (c < 0.) c += cm;
     121           0 :     uni -= c;
     122           0 :     if(uni < 0.) uni += 1.;
     123           0 :    } while (uni <= 0. || uni >= 1.);
     124             :   return uni;
     125             : 
     126           0 : }
     127             : 
     128             : //--------------------------------------------------------------------------
     129             : 
     130             : // Pick one option among  vector of (positive) probabilities.
     131             : 
     132             : int Rndm::pick(const vector<double>& prob) {
     133             : 
     134             :   double work = 0.;
     135           0 :   for (int i = 0; i < int(prob.size()); ++i) work += prob[i];
     136           0 :   work *= flat();
     137             :   int index = -1;
     138           0 :   do work -= prob[++index];
     139           0 :   while (work > 0. && index < int(prob.size()));
     140           0 :   return index;
     141             : 
     142             : }
     143             : 
     144             : //--------------------------------------------------------------------------
     145             : 
     146             : // Save current state of the random number generator to a binary file.
     147             : 
     148             : bool Rndm::dumpState(string fileName) {
     149             : 
     150             :   // Open file as output stream.
     151           0 :   const char* fn = fileName.c_str();
     152           0 :   ofstream ofs(fn, ios::binary);
     153             : 
     154           0 :   if (!ofs.good()) {
     155           0 :     cout << " Rndm::dumpState: could not open output file" << endl;
     156           0 :     return false;
     157             :   }
     158             : 
     159             :   // Write the state of the generator on the file.
     160           0 :   ofs.write((char *) &seedSave, sizeof(int));
     161           0 :   ofs.write((char *) &sequence, sizeof(long));
     162           0 :   ofs.write((char *) &i97,      sizeof(int));
     163           0 :   ofs.write((char *) &j97,      sizeof(int));
     164           0 :   ofs.write((char *) &c,        sizeof(double));
     165           0 :   ofs.write((char *) &cd,       sizeof(double));
     166           0 :   ofs.write((char *) &cm,       sizeof(double));
     167           0 :   ofs.write((char *) &u,        sizeof(double) * 97);
     168             : 
     169             :   // Write confirmation on cout.
     170           0 :   cout << " PYTHIA Rndm::dumpState: seed = " << seedSave
     171           0 :        << ", sequence no = " << sequence << endl;
     172           0 :   return true;
     173             : 
     174           0 : }
     175             : 
     176             : //--------------------------------------------------------------------------
     177             : 
     178             : // Read in the state of the random number generator from a binary file.
     179             : 
     180             : bool Rndm::readState(string fileName) {
     181             : 
     182             :   // Open file as input stream.
     183           0 :   const char* fn = fileName.c_str();
     184           0 :   ifstream ifs(fn, ios::binary);
     185             : 
     186           0 :   if (!ifs.good()) {
     187           0 :     cout << " Rndm::readState: could not open input file" << endl;
     188           0 :     return false;
     189             :   }
     190             : 
     191             :   // Read the state of the generator from the file.
     192           0 :   ifs.read((char *) &seedSave, sizeof(int));
     193           0 :   ifs.read((char *) &sequence, sizeof(long));
     194           0 :   ifs.read((char *) &i97,      sizeof(int));
     195           0 :   ifs.read((char *) &j97,      sizeof(int));
     196           0 :   ifs.read((char *) &c,        sizeof(double));
     197           0 :   ifs.read((char *) &cd,       sizeof(double));
     198           0 :   ifs.read((char *) &cm,       sizeof(double));
     199           0 :   ifs.read((char *) &u,        sizeof(double) *97);
     200             : 
     201             :   // Write confirmation on cout.
     202           0 :   cout << " PYTHIA Rndm::readState: seed " << seedSave
     203           0 :        << ", sequence no = " << sequence << endl;
     204           0 :   return true;
     205             : 
     206           0 : }
     207             : 
     208             : //==========================================================================
     209             : 
     210             : // Vec4 class.
     211             : // This class implements four-vectors, in energy-momentum space.
     212             : // (But could also be used to hold space-time four-vectors.)
     213             : 
     214             : //--------------------------------------------------------------------------
     215             : 
     216             : // Constants: could be changed here if desired, but normally should not.
     217             : // These are of technical nature, as described for each.
     218             : 
     219             : // Small number to avoid division by zero.
     220             : const double Vec4::TINY = 1e-20;
     221             : 
     222             : //--------------------------------------------------------------------------
     223             : 
     224             : // Rotation (simple).
     225             : 
     226             : void Vec4::rot(double thetaIn, double phiIn) {
     227             : 
     228           0 :   double cthe = cos(thetaIn);
     229           0 :   double sthe = sin(thetaIn);
     230           0 :   double cphi = cos(phiIn);
     231           0 :   double sphi = sin(phiIn);
     232           0 :   double tmpx =  cthe * cphi * xx -    sphi * yy + sthe * cphi * zz;
     233           0 :   double tmpy =  cthe * sphi * xx +    cphi * yy + sthe * sphi * zz;
     234           0 :   double tmpz = -sthe *        xx +                cthe *        zz;
     235           0 :   xx          = tmpx;
     236           0 :   yy          = tmpy;
     237           0 :   zz          = tmpz;
     238             : 
     239           0 : }
     240             : 
     241             : //--------------------------------------------------------------------------
     242             : 
     243             : // Azimuthal rotation phi around an arbitrary axis (nz, ny, nz).
     244             : 
     245             : void Vec4::rotaxis(double phiIn, double nx, double ny, double nz) {
     246             : 
     247           0 :   double norm = 1./sqrt(nx*nx + ny*ny + nz*nz);
     248           0 :   nx         *= norm;
     249           0 :   ny         *= norm;
     250           0 :   nz         *= norm;
     251           0 :   double cphi = cos(phiIn);
     252           0 :   double sphi = sin(phiIn);
     253           0 :   double comb = (nx * xx + ny * yy + nz * zz) * (1. - cphi);
     254           0 :   double tmpx = cphi * xx + comb * nx + sphi * (ny * zz - nz * yy);
     255           0 :   double tmpy = cphi * yy + comb * ny + sphi * (nz * xx - nx * zz);
     256           0 :   double tmpz = cphi * zz + comb * nz + sphi * (nx * yy - ny * xx);
     257           0 :   xx          = tmpx;
     258           0 :   yy          = tmpy;
     259           0 :   zz          = tmpz;
     260             : 
     261           0 : }
     262             : 
     263             : //--------------------------------------------------------------------------
     264             : 
     265             : // Azimuthal rotation phi around an arbitrary (3-vector component of) axis.
     266             : 
     267             : void Vec4::rotaxis(double phiIn, const Vec4& n) {
     268             : 
     269           0 :   double nx   = n.xx;
     270           0 :   double ny   = n.yy;
     271           0 :   double nz   = n.zz;
     272           0 :   double norm = 1./sqrt(nx*nx + ny*ny + nz*nz);
     273           0 :   nx         *= norm;
     274           0 :   ny          *=norm;
     275           0 :   nz          *=norm;
     276           0 :   double cphi = cos(phiIn);
     277           0 :   double sphi = sin(phiIn);
     278           0 :   double comb = (nx * xx + ny * yy + nz * zz) * (1. - cphi);
     279           0 :   double tmpx = cphi * xx + comb * nx + sphi * (ny * zz - nz * yy);
     280           0 :   double tmpy = cphi * yy + comb * ny + sphi * (nz * xx - nx * zz);
     281           0 :   double tmpz = cphi * zz + comb * nz + sphi * (nx * yy - ny * xx);
     282           0 :   xx          = tmpx;
     283           0 :   yy          = tmpy;
     284           0 :   zz          = tmpz;
     285             : 
     286           0 : }
     287             : 
     288             : //--------------------------------------------------------------------------
     289             : 
     290             : // Boost (simple).
     291             : 
     292             : void Vec4::bst(double betaX, double betaY, double betaZ) {
     293             : 
     294           0 :   double beta2 = betaX*betaX + betaY*betaY + betaZ*betaZ;
     295           0 :   double gamma = 1. / sqrt(1. - beta2);
     296           0 :   double prod1 = betaX * xx + betaY * yy + betaZ * zz;
     297           0 :   double prod2 = gamma * (gamma * prod1 / (1. + gamma) + tt);
     298           0 :   xx += prod2 * betaX;
     299           0 :   yy += prod2 * betaY;
     300           0 :   zz += prod2 * betaZ;
     301           0 :   tt = gamma * (tt + prod1);
     302             : 
     303           0 : }
     304             : 
     305             : //--------------------------------------------------------------------------
     306             : 
     307             : // Boost (simple, given gamma).
     308             : 
     309             : void Vec4::bst(double betaX, double betaY, double betaZ, double gamma) {
     310             : 
     311           0 :   double prod1 = betaX * xx + betaY * yy + betaZ * zz;
     312           0 :   double prod2 = gamma * (gamma * prod1 / (1. + gamma) + tt);
     313           0 :   xx += prod2 * betaX;
     314           0 :   yy += prod2 * betaY;
     315           0 :   zz += prod2 * betaZ;
     316           0 :   tt = gamma * (tt + prod1);
     317             : 
     318           0 : }
     319             : 
     320             : //--------------------------------------------------------------------------
     321             : 
     322             : // Boost given by a Vec4 p.
     323             : 
     324             : void Vec4::bst(const Vec4& pIn) {
     325             : 
     326           0 :   double betaX = pIn.xx / pIn.tt;
     327           0 :   double betaY = pIn.yy / pIn.tt;
     328           0 :   double betaZ = pIn.zz / pIn.tt;
     329           0 :   double beta2 = betaX*betaX + betaY*betaY + betaZ*betaZ;
     330           0 :   double gamma = 1. / sqrt(1. - beta2);
     331           0 :   double prod1 = betaX * xx + betaY * yy + betaZ * zz;
     332           0 :   double prod2 = gamma * (gamma * prod1 / (1. + gamma) + tt);
     333           0 :   xx          += prod2 * betaX;
     334           0 :   yy          += prod2 * betaY;
     335           0 :   zz          += prod2 * betaZ;
     336           0 :   tt           = gamma * (tt + prod1);
     337             : 
     338           0 : }
     339             : 
     340             : //--------------------------------------------------------------------------
     341             : 
     342             : // Boost given by a Vec4 p and double m.
     343             : 
     344             : void Vec4::bst(const Vec4& pIn, double mIn) {
     345             : 
     346           0 :   double betaX = pIn.xx / pIn.tt;
     347           0 :   double betaY = pIn.yy / pIn.tt;
     348           0 :   double betaZ = pIn.zz / pIn.tt;
     349           0 :   double gamma = pIn.tt / mIn;
     350           0 :   double prod1 = betaX * xx + betaY * yy + betaZ * zz;
     351           0 :   double prod2 = gamma * (gamma * prod1 / (1. + gamma) + tt);
     352           0 :   xx          += prod2 * betaX;
     353           0 :   yy          += prod2 * betaY;
     354           0 :   zz          += prod2 * betaZ;
     355           0 :   tt           = gamma * (tt + prod1);
     356             : 
     357           0 : }
     358             : 
     359             : //--------------------------------------------------------------------------
     360             : 
     361             : // Boost given by a Vec4 p; boost in opposite direction.
     362             : 
     363             : void Vec4::bstback(const Vec4& pIn) {
     364             : 
     365           0 :   double betaX = -pIn.xx / pIn.tt;
     366           0 :   double betaY = -pIn.yy / pIn.tt;
     367           0 :   double betaZ = -pIn.zz / pIn.tt;
     368           0 :   double beta2 = betaX*betaX + betaY*betaY + betaZ*betaZ;
     369           0 :   if(beta2 >= 1.) beta2 = 0.9999;
     370           0 :   double gamma = 1. / sqrt(1. - beta2);
     371           0 :   double prod1 = betaX * xx + betaY * yy + betaZ * zz;
     372           0 :   double prod2 = gamma * (gamma * prod1 / (1. + gamma) + tt);
     373           0 :   xx          += prod2 * betaX;
     374           0 :   yy          += prod2 * betaY;
     375           0 :   zz          += prod2 * betaZ;
     376           0 :   tt           = gamma * (tt + prod1);
     377             : 
     378           0 : }
     379             : 
     380             : //--------------------------------------------------------------------------
     381             : 
     382             : // Boost given by a Vec4 p and double m; boost in opposite direction.
     383             : 
     384             : void Vec4::bstback(const Vec4& pIn, double mIn) {
     385             : 
     386           0 :   double betaX = -pIn.xx / pIn.tt;
     387           0 :   double betaY = -pIn.yy / pIn.tt;
     388           0 :   double betaZ = -pIn.zz / pIn.tt;
     389           0 :   double gamma = pIn.tt / mIn;
     390           0 :   double prod1 = betaX * xx + betaY * yy + betaZ * zz;
     391           0 :   double prod2 = gamma * (gamma * prod1 / (1. + gamma) + tt);
     392           0 :   xx          += prod2 * betaX;
     393           0 :   yy          += prod2 * betaY;
     394           0 :   zz          += prod2 * betaZ;
     395           0 :   tt           = gamma * (tt + prod1);
     396             : 
     397           0 : }
     398             : 
     399             : //--------------------------------------------------------------------------
     400             : 
     401             : // Arbitrary combination of rotations and boosts defined by 4 * 4 matrix.
     402             : 
     403             : void Vec4::rotbst(const RotBstMatrix& M) {
     404             : 
     405           0 :   double x = xx; double y = yy; double z = zz; double t = tt;
     406           0 :   tt = M.M[0][0] * t + M.M[0][1] * x + M.M[0][2] * y +  M.M[0][3] * z;
     407           0 :   xx = M.M[1][0] * t + M.M[1][1] * x + M.M[1][2] * y +  M.M[1][3] * z;
     408           0 :   yy = M.M[2][0] * t + M.M[2][1] * x + M.M[2][2] * y +  M.M[2][3] * z;
     409           0 :   zz = M.M[3][0] * t + M.M[3][1] * x + M.M[3][2] * y +  M.M[3][3] * z;
     410             : 
     411           0 : }
     412             : 
     413             : //--------------------------------------------------------------------------
     414             : 
     415             : // The invariant mass of two four-vectors.
     416             : 
     417             : double m(const Vec4& v1, const Vec4& v2) {
     418           0 :   double m2 = pow2(v1.tt + v2.tt) - pow2(v1.xx + v2.xx)
     419           0 :      - pow2(v1.yy + v2.yy) - pow2(v1.zz + v2.zz);
     420           0 :   return (m2 > 0.) ? sqrt(m2) : 0.;
     421             : }
     422             : 
     423             : //--------------------------------------------------------------------------
     424             : 
     425             : // The squared invariant mass of two four-vectors.
     426             : 
     427             : double m2(const Vec4& v1, const Vec4& v2) {
     428           0 :   double m2 = pow2(v1.tt + v2.tt) - pow2(v1.xx + v2.xx)
     429           0 :      - pow2(v1.yy + v2.yy) - pow2(v1.zz + v2.zz);
     430           0 :   return m2;
     431             : }
     432             : 
     433             : //--------------------------------------------------------------------------
     434             : 
     435             : // The scalar product of two three-vectors.
     436             : 
     437             : double dot3(const Vec4& v1, const Vec4& v2) {
     438           0 :   return v1.xx*v2.xx + v1.yy*v2.yy + v1.zz*v2.zz;
     439             : }
     440             : 
     441             : //--------------------------------------------------------------------------
     442             : 
     443             : // The cross product of two three-vectors.
     444             : 
     445             : Vec4 cross3(const Vec4& v1, const Vec4& v2) {
     446           0 :   Vec4 v;
     447           0 :   v.xx = v1.yy * v2.zz - v1.zz * v2.yy;
     448           0 :   v.yy = v1.zz * v2.xx - v1.xx * v2.zz;
     449           0 :   v.zz = v1.xx * v2.yy - v1.yy * v2.xx; return v;
     450             : }
     451             : 
     452             : //--------------------------------------------------------------------------
     453             : 
     454             : // Opening angle between two three-vectors.
     455             : 
     456             : double theta(const Vec4& v1, const Vec4& v2) {
     457           0 :   double cthe = (v1.xx * v2.xx + v1.yy * v2.yy + v1.zz * v2.zz)
     458           0 :     / sqrt( (v1.xx*v1.xx + v1.yy*v1.yy + v1.zz*v1.zz)
     459           0 :     * (v2.xx*v2.xx + v2.yy*v2.yy + v2.zz*v2.zz) );
     460           0 :   cthe = max(-1., min(1., cthe));
     461           0 :   return acos(cthe);
     462           0 : }
     463             : 
     464             : //--------------------------------------------------------------------------
     465             : 
     466             : // Cosine of the opening angle between two three-vectors.
     467             : 
     468             : double costheta(const Vec4& v1, const Vec4& v2) {
     469           0 :   double cthe = 0;
     470           0 :   if( (v1.xx*v1.xx + v1.yy*v1.yy + v1.zz*v1.zz) > 1e-06 &&  (v2.xx*v2.xx + v2.yy*v2.yy + v2.zz*v2.zz) > 1e-06) {
     471           0 :     cthe = (v1.xx * v2.xx + v1.yy * v2.yy + v1.zz * v2.zz)
     472           0 :     / sqrt( (v1.xx*v1.xx + v1.yy*v1.yy + v1.zz*v1.zz)
     473           0 :     * (v2.xx*v2.xx + v2.yy*v2.yy + v2.zz*v2.zz) );
     474           0 :     cthe = max(-1., min(1., cthe));}
     475           0 :   return cthe;
     476           0 : }
     477             : 
     478             : //--------------------------------------------------------------------------
     479             : 
     480             : // Azimuthal angle between two three-vectors.
     481             : 
     482             : double phi(const Vec4& v1, const Vec4& v2) {
     483           0 :   double cphi = (v1.xx * v2.xx + v1.yy * v2.yy) / sqrt( max( Vec4::TINY,
     484           0 :     (v1.xx*v1.xx + v1.yy*v1.yy) * (v2.xx*v2.xx + v2.yy*v2.yy) ));
     485           0 :   cphi = max(-1., min(1., cphi));
     486           0 :   return acos(cphi);
     487           0 : }
     488             : 
     489             : //--------------------------------------------------------------------------
     490             : 
     491             : // Cosine of the azimuthal angle between two three-vectors.
     492             : 
     493             : double cosphi(const Vec4& v1, const Vec4& v2) {
     494           0 :   double cphi = (v1.xx * v2.xx + v1.yy * v2.yy) / sqrt( max( Vec4::TINY,
     495           0 :     (v1.xx*v1.xx + v1.yy*v1.yy) * (v2.xx*v2.xx + v2.yy*v2.yy) ));
     496           0 :   cphi = max(-1., min(1., cphi));
     497           0 :   return cphi;
     498           0 : }
     499             : 
     500             : //--------------------------------------------------------------------------
     501             : 
     502             : // Azimuthal angle between two three-vectors around a third.
     503             : 
     504             : double phi(const Vec4& v1, const Vec4& v2, const Vec4& n) {
     505           0 :   double nx = n.xx; double ny = n.yy; double nz = n.zz;
     506           0 :   double norm = 1. / sqrt(nx*nx + ny*ny + nz*nz);
     507           0 :   nx *= norm; ny *=norm; nz *=norm;
     508           0 :   double v1s = v1.xx * v1.xx + v1.yy * v1.yy + v1.zz * v1.zz;
     509           0 :   double v2s = v2.xx * v2.xx + v2.yy * v2.yy + v2.zz * v2.zz;
     510           0 :   double v1v2 = v1.xx * v2.xx + v1.yy * v2.yy + v1.zz * v2.zz;
     511           0 :   double v1n = v1.xx * nx + v1.yy * ny + v1.zz * nz;
     512           0 :   double v2n = v2.xx * nx + v2.yy * ny + v2.zz * nz;
     513           0 :   double cphi = (v1v2 - v1n * v2n) / sqrt( max( Vec4::TINY,
     514           0 :     (v1s - v1n*v1n) * (v2s - v2n*v2n) ));
     515           0 :   cphi = max(-1., min(1., cphi));
     516           0 :   return acos(cphi);
     517           0 : }
     518             : 
     519             : //--------------------------------------------------------------------------
     520             : 
     521             : // Cosine of the azimuthal angle between two three-vectors around a third.
     522             : 
     523             : double cosphi(const Vec4& v1, const Vec4& v2, const Vec4& n) {
     524           0 :   double nx = n.xx; double ny = n.yy; double nz = n.zz;
     525           0 :   double norm = 1. / sqrt(nx*nx + ny*ny + nz*nz);
     526           0 :   nx *= norm; ny *=norm; nz *=norm;
     527           0 :   double v1s = v1.xx * v1.xx + v1.yy * v1.yy + v1.zz * v1.zz;
     528           0 :   double v2s = v2.xx * v2.xx + v2.yy * v2.yy + v2.zz * v2.zz;
     529           0 :   double v1v2 = v1.xx * v2.xx + v1.yy * v2.yy + v1.zz * v2.zz;
     530           0 :   double v1n = v1.xx * nx + v1.yy * ny + v1.zz * nz;
     531           0 :   double v2n = v2.xx * nx + v2.yy * ny + v2.zz * nz;
     532           0 :   double cphi = (v1v2 - v1n * v2n) / sqrt( max( Vec4::TINY,
     533           0 :     (v1s - v1n*v1n) * (v2s - v2n*v2n) ));
     534           0 :   cphi = max(-1., min(1., cphi));
     535           0 :   return cphi;
     536           0 : }
     537             : 
     538             : //--------------------------------------------------------------------------
     539             : 
     540             : // Distance in cylindrical (y, phi) coordinates.
     541             : 
     542             : double RRapPhi(const Vec4& v1, const Vec4& v2) {
     543           0 :   double dRap = abs(v1.rap() - v2.rap());
     544           0 :   double dPhi = abs(v1.phi() - v2.phi());
     545           0 :   if (dPhi > M_PI) dPhi = 2. * M_PI - dPhi;
     546           0 :   return sqrt(dRap*dRap + dPhi*dPhi);
     547             : }
     548             : 
     549             : //--------------------------------------------------------------------------
     550             : 
     551             : // Distance in cylindrical (eta, phi) coordinates.
     552             : 
     553             : double REtaPhi(const Vec4& v1, const Vec4& v2) {
     554           0 :   double dEta = abs(v1.eta() - v2.eta());
     555           0 :   double dPhi = abs(v1.phi() - v2.phi());
     556           0 :   if (dPhi > M_PI) dPhi = 2. * M_PI - dPhi;
     557           0 :   return sqrt(dEta*dEta + dPhi*dPhi);
     558             : }
     559             : 
     560             : //--------------------------------------------------------------------------
     561             : 
     562             : // Print a four-vector: also operator overloading with friend.
     563             : 
     564             : ostream& operator<<(ostream& os, const Vec4& v) {
     565           0 :   os << fixed << setprecision(3) << " " << setw(9) << v.xx << " "
     566           0 :      << setw(9) << v.yy << " " << setw(9) << v.zz << " " << setw(9)
     567           0 :      << v.tt << " (" << setw(9) << v.mCalc() << ")\n";
     568           0 :   return os;
     569             : }
     570             : 
     571             : //==========================================================================
     572             : 
     573             : // RotBstMatrix class.
     574             : // This class implements 4 * 4 matrices that encode an arbitrary combination
     575             : // of rotations and boosts, that can be applied to Vec4 four-vectors.
     576             : 
     577             : //--------------------------------------------------------------------------
     578             : 
     579             : // Constants: could be changed here if desired, but normally should not.
     580             : // These are of technical nature, as described for each.
     581             : 
     582             : // Small number to avoid division by zero.
     583             : const double RotBstMatrix::TINY = 1e-20;
     584             : 
     585             : //--------------------------------------------------------------------------
     586             : 
     587             : // Rotate by polar angle theta and azimuthal angle phi.
     588             : 
     589             : void RotBstMatrix::rot(double theta, double phi) {
     590             : 
     591             :   // Set up rotation matrix.
     592           0 :   double cthe = cos(theta);
     593           0 :   double sthe = sin(theta);
     594           0 :   double cphi = cos(phi);
     595           0 :   double sphi = sin(phi);
     596           0 :   double Mrot[4][4] = {
     597           0 :     {1.,           0.,         0.,          0.},
     598           0 :     {0.,  cthe * cphi,     - sphi, sthe * cphi},
     599           0 :     {0.,  cthe * sphi,       cphi, sthe * sphi},
     600           0 :     {0., -sthe,                0., cthe       } };
     601             : 
     602             :   // Rotate current matrix accordingly.
     603           0 :   double Mtmp[4][4];
     604           0 :   for (int i = 0; i < 4; ++i)
     605           0 :   for (int j = 0; j < 4; ++j)
     606           0 :     Mtmp[i][j] = M[i][j];
     607           0 :   for (int i = 0; i < 4; ++i)
     608           0 :   for (int j = 0; j < 4; ++j)
     609           0 :     M[i][j] = Mrot[i][0] * Mtmp[0][j] + Mrot[i][1] * Mtmp[1][j]
     610           0 :             + Mrot[i][2] * Mtmp[2][j] + Mrot[i][3] * Mtmp[3][j];
     611             : 
     612           0 : }
     613             : 
     614             : //--------------------------------------------------------------------------
     615             : 
     616             : // Rotate so that vector originally along z axis becomes parallel with p.
     617             : 
     618             : void RotBstMatrix::rot(const Vec4& p) {
     619             : 
     620           0 :   double theta = p.theta();
     621           0 :   double phi = p.phi();
     622           0 :   rot(0., -phi);
     623           0 :   rot(theta, phi);
     624             : 
     625           0 : }
     626             : 
     627             : //--------------------------------------------------------------------------
     628             : 
     629             : // Boost with velocity vector (betaX, betaY, betaZ).
     630             : 
     631             : void RotBstMatrix::bst(double betaX, double betaY, double betaZ) {
     632             : 
     633             :   // Set up boost matrix.
     634           0 :   double gm = 1. / sqrt( max( TINY, 1. - betaX*betaX - betaY*betaY
     635           0 :     - betaZ*betaZ ) );
     636           0 :   double gf = gm*gm / (1. + gm);
     637           0 :   double Mbst[4][4] = {
     638           0 :     { gm,           gm*betaX,           gm*betaY,          gm*betaZ },
     639           0 :     { gm*betaX, 1. + gf*betaX*betaX, gf*betaX*betaY, gf*betaX*betaZ },
     640           0 :     { gm*betaY, gf*betaY*betaX, 1. + gf*betaY*betaY, gf*betaY*betaZ },
     641           0 :     { gm*betaZ, gf*betaZ*betaX, gf*betaZ*betaY, 1. + gf*betaZ*betaZ } };
     642             : 
     643             :   // Boost current matrix correspondingly.
     644           0 :   double Mtmp[4][4];
     645           0 :   for (int i = 0; i < 4; ++i)
     646           0 :   for (int j = 0; j < 4; ++j)
     647           0 :     Mtmp[i][j] = M[i][j];
     648           0 :   for (int i = 0; i < 4; ++i)
     649           0 :   for (int j = 0; j < 4; ++j)
     650           0 :     M[i][j] = Mbst[i][0] * Mtmp[0][j] + Mbst[i][1] * Mtmp[1][j]
     651           0 :             + Mbst[i][2] * Mtmp[2][j] + Mbst[i][3] * Mtmp[3][j];
     652             : 
     653           0 : }
     654             : 
     655             : //--------------------------------------------------------------------------
     656             : 
     657             : // Boost so that vector originally at rest obtains same velocity as p.
     658             : 
     659             : void RotBstMatrix::bst(const Vec4& p) {
     660           0 :   double betaX = p.px() / p.e();
     661           0 :   double betaY = p.py() / p.e();
     662           0 :   double betaZ = p.pz() / p.e();
     663           0 :   bst(betaX, betaY, betaZ);
     664           0 : }
     665             : 
     666             : //--------------------------------------------------------------------------
     667             : 
     668             : // Boost so vector originally with same velocity as p is brought to rest.
     669             : 
     670             : void RotBstMatrix::bstback(const Vec4& p) {
     671           0 :   double betaX = -p.px() / p.e();
     672           0 :   double betaY = -p.py() / p.e();
     673           0 :   double betaZ = -p.pz() / p.e();
     674           0 :   bst(betaX, betaY, betaZ);
     675           0 : }
     676             : 
     677             : //--------------------------------------------------------------------------
     678             : 
     679             : // Boost that transforms p1 to p2, where p1^2 = p2^2 is assumed.
     680             : 
     681             : void RotBstMatrix::bst(const Vec4& p1, const Vec4& p2) {
     682           0 :   double eSum = p1.e() + p2.e();
     683           0 :   double betaX = (p2.px() - p1.px()) / eSum;
     684           0 :   double betaY = (p2.py() - p1.py()) / eSum;
     685           0 :   double betaZ = (p2.pz() - p1.pz()) / eSum;
     686           0 :   double fac = 2. / (1. + betaX*betaX + betaY*betaY + betaZ*betaZ);
     687           0 :   betaX *= fac; betaY *= fac; betaZ *= fac;
     688           0 :   bst(betaX, betaY, betaZ);
     689           0 : }
     690             : 
     691             : //--------------------------------------------------------------------------
     692             : 
     693             : // Boost and rotation that transforms from p1 and p2
     694             : // to their rest frame with p1 along +z axis.
     695             : 
     696             : void RotBstMatrix::toCMframe(const Vec4& p1, const Vec4& p2) {
     697           0 :   Vec4 pSum = p1 + p2;
     698           0 :   Vec4 dir  = p1;
     699           0 :   dir.bstback(pSum);
     700           0 :   double theta = dir.theta();
     701           0 :   double phi   = dir.phi();
     702           0 :   bstback(pSum);
     703           0 :   rot(0., -phi);
     704           0 :   rot(-theta, phi);
     705           0 : }
     706             : 
     707             : //--------------------------------------------------------------------------
     708             : 
     709             : // Rotation and boost that transforms from rest frame of p1 and p2
     710             : // with p1 along +z axis to actual frame of p1 and p2. (Inverse of above.)
     711             : 
     712             : void RotBstMatrix::fromCMframe(const Vec4& p1, const Vec4& p2) {
     713           0 :   Vec4 pSum = p1 + p2;
     714           0 :   Vec4 dir  = p1;
     715           0 :   dir.bstback(pSum);
     716           0 :   double theta = dir.theta();
     717           0 :   double phi   = dir.phi();
     718           0 :   rot(0., -phi);
     719           0 :   rot(theta, phi);
     720           0 :   bst(pSum);
     721           0 : }
     722             : 
     723             : //--------------------------------------------------------------------------
     724             : 
     725             : // Combine existing rotation/boost matrix with another one.
     726             : 
     727             : void RotBstMatrix::rotbst(const RotBstMatrix& Mrb) {
     728           0 :   double Mtmp[4][4];
     729           0 :   for (int i = 0; i < 4; ++i)
     730           0 :   for (int j = 0; j < 4; ++j)
     731           0 :     Mtmp[i][j] = M[i][j];
     732           0 :   for (int i = 0; i < 4; ++i)
     733           0 :   for (int j = 0; j < 4; ++j)
     734           0 :     M[i][j] = Mrb.M[i][0] * Mtmp[0][j] + Mrb.M[i][1] * Mtmp[1][j]
     735           0 :             + Mrb.M[i][2] * Mtmp[2][j] + Mrb.M[i][3] * Mtmp[3][j];
     736           0 : }
     737             : 
     738             : //--------------------------------------------------------------------------
     739             : 
     740             : // Invert the rotation and boost.
     741             : 
     742             : void RotBstMatrix::invert() {
     743           0 :   double Mtmp[4][4];
     744           0 :   for (int i = 0; i < 4; ++i)
     745           0 :   for (int j = 0; j < 4; ++j)
     746           0 :     Mtmp[i][j] = M[i][j];
     747           0 :   for (int i = 0; i < 4; ++i)
     748           0 :   for (int j = 0; j < 4; ++j)
     749           0 :     M[i][j] = ( (i == 0 && j > 0) || (i > 0 && j == 0) )
     750           0 :       ? - Mtmp[j][i] : Mtmp[j][i];
     751           0 : }
     752             : 
     753             : //--------------------------------------------------------------------------
     754             : 
     755             : // Reset to diagonal matrix.
     756             : 
     757             : void RotBstMatrix::reset() {
     758           0 :   for (int i = 0; i < 4; ++i)
     759           0 :   for (int j = 0; j < 4; ++j)
     760           0 :     M[i][j] = (i==j) ? 1. : 0.;
     761           0 : }
     762             : 
     763             : //--------------------------------------------------------------------------
     764             : 
     765             : // Crude estimate deviation from unit matrix.
     766             : 
     767             : double RotBstMatrix::deviation() const {
     768             :   double devSum = 0.;
     769           0 :   for (int i = 0; i < 4; ++i)
     770           0 :   for (int j = 0; j < 4; ++j)
     771           0 :     devSum += (i==j) ? abs(M[i][j] - 1.) : abs(M[i][j]);
     772           0 :   return devSum;
     773             : }
     774             : 
     775             : //--------------------------------------------------------------------------
     776             : 
     777             : // Print a rotation and boost matrix: operator overloading with friend.
     778             : 
     779             : ostream& operator<<(ostream& os, const RotBstMatrix& M) {
     780           0 :   os << fixed << setprecision(5) << "    Rotation/boost matrix: \n";
     781           0 :   for (int i = 0; i <4; ++i)
     782           0 :     os << setw(10) << M.M[i][0] << setw(10) << M.M[i][1]
     783           0 :        << setw(10) << M.M[i][2] << setw(10) << M.M[i][3] << "\n";
     784           0 :   return os;
     785             : }
     786             : 
     787             : //==========================================================================
     788             : 
     789             : // Hist class.
     790             : // This class handles a single histogram at a time
     791             : // (or a vector of histograms).
     792             : 
     793             : //--------------------------------------------------------------------------
     794             : 
     795             : // Constants: could be changed here if desired, but normally should not.
     796             : // These are of technical nature, as described for each.
     797             : 
     798             : // Maximum number of bins in a histogram.
     799             : const int    Hist::NBINMAX   = 1000;
     800             : 
     801             : // Maximum number of columns that can be printed for a histogram.
     802             : const int    Hist::NCOLMAX   = 100;
     803             : 
     804             : // Maximum number of lines a histogram can use at output.
     805             : const int    Hist::NLINES    = 30;
     806             : 
     807             : // Tolerance in deviation of xMin and xMax between two histograms.
     808             : const double Hist::TOLERANCE = 0.001;
     809             : 
     810             : // Small and large numbers to avoid division by zero and overflow.
     811             : const double Hist::TINY      = 1e-20;
     812             : const double Hist::LARGE     = 1e20;
     813             : 
     814             : // When minbin/maxbin < SMALLFRAC the y scale goes down to zero.
     815             : const double Hist::SMALLFRAC = 0.1;
     816             : 
     817             : // Constants for printout: fixed steps on y scale; filling characters.
     818             : const double DYAC[] = {0.04, 0.05, 0.06, 0.08, 0.10,
     819             :   0.12, 0.15, 0.20, 0.25, 0.30};
     820             : const char NUMBER[] = {'0', '1', '2', '3', '4', '5',
     821             :   '6', '7', '8', '9', 'X' };
     822             : 
     823             : //--------------------------------------------------------------------------
     824             : 
     825             : // Book a histogram.
     826             : 
     827             : void Hist::book(string titleIn, int nBinIn, double xMinIn,
     828             :   double xMaxIn) {
     829             : 
     830           0 :   title = titleIn;
     831           0 :   nBin  = nBinIn;
     832           0 :   if (nBinIn < 1) nBin = 1;
     833           0 :   if (nBinIn > NBINMAX) nBin = NBINMAX;
     834           0 :   xMin  = xMinIn;
     835           0 :   xMax  = xMaxIn;
     836           0 :   dx    = (xMax - xMin)/nBin;
     837           0 :   res.resize(nBin);
     838           0 :   null();
     839             : 
     840           0 : }
     841             : 
     842             : //--------------------------------------------------------------------------
     843             : 
     844             : // Reset bin contents.
     845             : 
     846             : void Hist::null() {
     847             : 
     848           0 :   nFill  = 0;
     849           0 :   under  = 0.;
     850           0 :   inside = 0.;
     851           0 :   over   = 0.;
     852           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] = 0.;
     853             : 
     854           0 : }
     855             : 
     856             : //--------------------------------------------------------------------------
     857             : 
     858             : // Fill bin with weight.
     859             : 
     860             : void Hist::fill(double x, double w) {
     861             : 
     862           0 :   ++nFill;
     863           0 :   int iBin = int(floor((x - xMin)/dx));
     864           0 :   if (iBin < 0)          under += w;
     865           0 :   else if (iBin >= nBin) over  += w;
     866           0 :   else                 {inside += w; res[iBin] += w; }
     867             : 
     868           0 : }
     869             : 
     870             : //--------------------------------------------------------------------------
     871             : 
     872             : // Print a histogram: also operator overloading with friend.
     873             : 
     874             : ostream& operator<<(ostream& os, const Hist& h) {
     875             : 
     876             :   // Do not print empty histograms.
     877           0 :   if (h.nFill <= 0) return os;
     878             : 
     879             :   // Write time and title.
     880           0 :   time_t t = time(0);
     881           0 :   char date[18];
     882           0 :   strftime(date,18,"%Y-%m-%d %H:%M",localtime(&t));
     883           0 :   os << "\n\n  " << date << "       " << h.title << "\n\n";
     884             : 
     885             :   // Group bins, where required, to make printout have fewer columns.
     886             :   // Avoid overflow.
     887           0 :   int nGroup = 1 + (h.nBin - 1) / Hist::NCOLMAX;
     888           0 :   int nCol   = 1 + (h.nBin - 1) / nGroup;
     889           0 :   vector<double> resCol(nCol);
     890           0 :   for (int iCol = 0; iCol < nCol; ++iCol) {
     891           0 :     resCol[iCol] = 0.;
     892           0 :     for (int ix = nGroup * iCol; ix < min( h.nBin, nGroup * (iCol + 1)); ++ix)
     893           0 :       resCol[iCol] += h.res[ix];
     894           0 :     resCol[iCol] = max( -Hist::LARGE, min( Hist::LARGE, resCol[iCol] ) );
     895             :   }
     896             : 
     897             :   // Find minimum and maximum bin content.
     898           0 :   double yMin = resCol[0];
     899           0 :   double yMax = resCol[0];
     900           0 :   for (int iCol = 1; iCol < nCol; ++iCol) {
     901           0 :     if (resCol[iCol] < yMin) yMin = resCol[iCol];
     902           0 :     if (resCol[iCol] > yMax) yMax = resCol[iCol];
     903             :   }
     904             : 
     905             :   // Determine scale and step size for y axis.
     906           0 :   if (yMax - yMin > Hist::NLINES * DYAC[0] * 1e-9) {
     907           0 :     if (yMin > 0. && yMin < Hist::SMALLFRAC * yMax) yMin = 0.;
     908           0 :     if (yMax < 0. && yMax > Hist::SMALLFRAC * yMin) yMax = 0.;
     909           0 :     int iPowY = int(floor( log10(yMax - yMin) ));
     910           0 :     if (yMax - yMin < Hist::NLINES * DYAC[0] * pow(10.,iPowY))
     911           0 :       iPowY = iPowY - 1;
     912           0 :     if (yMax - yMin > Hist::NLINES * DYAC[9] * pow(10.,iPowY))
     913           0 :       iPowY = iPowY + 1;
     914           0 :     double nLinePow = Hist::NLINES * pow(10.,iPowY);
     915             :     double delY = DYAC[0];
     916           0 :     for (int idel = 0; idel < 9; ++idel)
     917           0 :       if (yMax - yMin >= nLinePow * DYAC[idel]) delY = DYAC[idel+1];
     918           0 :     double dy = delY * pow(10.,iPowY);
     919             : 
     920             :     // Convert bin contents to integer form; fractional fill in top row.
     921           0 :     vector<int> row(nCol);
     922           0 :     vector<int> frac(nCol);
     923           0 :     for (int iCol = 0; iCol < nCol ; ++iCol) {
     924           0 :       double cta = abs(resCol[iCol]) / dy;
     925           0 :       row[iCol] = int(cta + 0.95);
     926           0 :       if(resCol[iCol] < 0.) row[iCol] = - row[iCol];
     927           0 :       frac[iCol] = int(10. * (cta + 1.05 - floor(cta + 0.95)));
     928             :     }
     929           0 :     int rowMin = int(abs(yMin)/dy + 0.95);
     930           0 :     if ( yMin < 0) rowMin = - rowMin;
     931           0 :     int rowMax = int(abs(yMax)/dy + 0.95);
     932           0 :     if ( yMax < 0) rowMax = - rowMax;
     933             : 
     934             :     // Print histogram row by row.
     935           0 :     os << fixed << setprecision(2);
     936           0 :     for (int iRow = rowMax; iRow >= rowMin; iRow--) if (iRow != 0) {
     937           0 :       os << "  " << setw(10) << iRow*delY << "*10^"
     938           0 :          << setw(2) << iPowY << "  ";
     939           0 :       for (int iCol = 0; iCol < nCol ; ++iCol) {
     940           0 :         if (iRow == row[iCol])                  os << NUMBER[frac[iCol]];
     941           0 :         else if (iRow * (row[iCol] - iRow) > 0) os << NUMBER[10];
     942           0 :         else                                    os << " ";
     943           0 :       } os << "\n";
     944           0 :     } os << "\n";
     945             : 
     946             :     // Print sign and value of bin contents
     947           0 :     double maxim = log10(max(yMax, -yMin));
     948           0 :     int iPowBin = int(floor(maxim + 0.0001));
     949           0 :     os << "          Contents  ";
     950           0 :     for (int iCol = 0; iCol < nCol ; ++iCol) {
     951           0 :       if (resCol[iCol] < - pow(10., iPowBin - 4)) os << "-";
     952           0 :       else os << " ";
     953           0 :       row[iCol] = int(abs(resCol[iCol]) * pow(10., 3 - iPowBin) + 0.5);
     954           0 :     } os << "\n";
     955           0 :     for (int iRow = 3; iRow >= 0; iRow--) {
     956           0 :       os << "            *10^" << setw(2) << iPowBin + iRow - 3 << "  ";
     957           0 :       int mask = int( pow(10., iRow) + 0.5);
     958           0 :       for (int iCol = 0; iCol < nCol ; ++iCol) {
     959           0 :         os << NUMBER[(row[iCol] / mask) % 10];
     960           0 :       } os << "\n";
     961           0 :     } os << "\n";
     962             : 
     963             :     // Print sign and value of lower bin edge.
     964           0 :     maxim = log10( max( -h.xMin, h.xMax - h.dx));
     965           0 :     int iPowExp = int(floor(maxim + 0.0001));
     966           0 :     os << "          Low edge  ";
     967           0 :     for (int iCol = 0; iCol < nCol ; ++iCol) {
     968           0 :       if (h.xMin + iCol * nGroup * h.dx < - pow(10., iPowExp - 3)) os << "-";
     969           0 :       else os << " ";
     970           0 :       row[iCol] = int(abs(h.xMin + iCol * nGroup * h.dx)
     971           0 :         * pow(10., 2 - iPowExp) + 0.5);
     972           0 :     } os << "\n";
     973           0 :     for (int iRow = 2; iRow >= 0; iRow--) {
     974           0 :       os << "            *10^" << setw(2) << iPowExp + iRow - 2 << "  ";
     975           0 :       int mask = int( pow(10., iRow) + 0.5);
     976           0 :       for (int iCol = 0; iCol < nCol ; ++iCol)
     977           0 :         os << NUMBER[(row[iCol] / mask) % 10];
     978           0 :       os << "\n";
     979           0 :     } os << "\n";
     980             : 
     981             :   // Print explanation if histogram cannot be shown.
     982           0 :   } else os << "     Histogram not shown since lowest value" << scientific
     983           0 :        << setprecision(4) << setw(12) << yMin << " and highest value"
     984           0 :        << setw(12) << yMax << " are too close \n \n";
     985             : 
     986             :   // Calculate and print statistics.
     987           0 :   double cSum   = 0.;
     988             :   double cxSum  = 0.;
     989             :   double cxxSum = 0.;
     990           0 :   for (int ix = 0; ix < h.nBin ; ++ix) {
     991           0 :     double cta = abs(h.res[ix]);
     992           0 :     double x = h.xMin + (ix + 0.5) * h.dx;
     993           0 :     cSum   = cSum   + cta;
     994           0 :     cxSum  = cxSum  + cta * x;
     995           0 :     cxxSum = cxxSum + cta * x * x;
     996             :   }
     997           0 :   double xmean = cxSum / max(cSum, Hist::TINY);
     998           0 :   double rms = sqrtpos( cxxSum / max(cSum, Hist::TINY) - xmean*xmean );
     999           0 :   os << scientific << setprecision(4)
    1000           0 :      << "   Entries  =" << setw(12) << h.nFill
    1001           0 :      << "    Mean =" << setw(12) << xmean
    1002           0 :      << "    Underflow =" << setw(12) << h.under
    1003           0 :      << "    Low edge  =" << setw(12) << h.xMin << "\n"
    1004           0 :      << "   All chan =" << setw(12) << h.inside
    1005           0 :      << "    Rms  =" << setw(12) << rms
    1006           0 :      << "    Overflow  =" << setw(12) << h.over
    1007           0 :      << "    High edge =" << setw(12) << h.xMax << endl;
    1008             :   return os;
    1009           0 : }
    1010             : 
    1011             : //--------------------------------------------------------------------------
    1012             : 
    1013             : // Print histogram contents as a table (e.g. for Gnuplot).
    1014             : 
    1015             : void Hist::table(ostream& os, bool printOverUnder, bool xMidBin) const {
    1016             : 
    1017             :   // Print histogram vector bin by bin, with mean x as first column.
    1018           0 :   os << scientific << setprecision(4);
    1019           0 :   double xBeg = (xMidBin) ? xMin + 0.5 * dx : xMin;
    1020           0 :   if (printOverUnder)
    1021           0 :     os << setw(12) << xBeg - dx << setw(12) << under << "\n";
    1022           0 :   for (int ix = 0; ix < nBin; ++ix)
    1023           0 :     os << setw(12) << xBeg + ix * dx << setw(12) << res[ix] << "\n";
    1024           0 :   if (printOverUnder)
    1025           0 :     os << setw(12) << xBeg + nBin * dx << setw(12) << over << "\n";
    1026             : 
    1027           0 : }
    1028             : 
    1029             : //--------------------------------------------------------------------------
    1030             : 
    1031             : // Print a table out of two histograms with same x axis  (e.g. for Gnuplot).
    1032             : 
    1033             : void table(const Hist& h1, const Hist& h2, ostream& os, bool printOverUnder,
    1034             :   bool xMidBin) {
    1035             : 
    1036             :   // Require histogram x axes to agree.
    1037           0 :   if (h1.nBin != h2.nBin || abs(h1.xMin - h2.xMin) > Hist::TOLERANCE * h1.dx
    1038           0 :     || abs(h1.xMax - h2.xMax) > Hist::TOLERANCE * h1.dx) return;
    1039             : 
    1040             :   // Print histogram vectors bin by bin, with mean x as first column.
    1041           0 :   os << scientific << setprecision(4);
    1042           0 :   double xBeg = (xMidBin) ? h1.xMin + 0.5 * h1.dx : h1.xMin;
    1043           0 :   if (printOverUnder)
    1044           0 :     os << setw(12) << xBeg - h1.dx << setw(12) << h1.under
    1045           0 :        << setw(12) << h2.under << "\n";
    1046           0 :   for (int ix = 0; ix < h1.nBin; ++ix)
    1047           0 :     os << setw(12) << xBeg + ix * h1.dx << setw(12) << h1.res[ix]
    1048           0 :        << setw(12) << h2.res[ix] << "\n";
    1049           0 :   if (printOverUnder)
    1050           0 :     os << setw(12) << xBeg + h1.nBin * h1.dx << setw(12) << h1.over
    1051           0 :        << setw(12) << h2.over << "\n";
    1052             : 
    1053           0 : }
    1054             : 
    1055             : void table(const Hist& h1, const Hist& h2, string fileName,
    1056             :   bool printOverUnder, bool xMidBin) {
    1057             : 
    1058           0 :   ofstream streamName(fileName.c_str());
    1059           0 :   table( h1, h2, streamName, printOverUnder, xMidBin);
    1060             : 
    1061           0 : }
    1062             : 
    1063             : //--------------------------------------------------------------------------
    1064             : 
    1065             : // Get content of specific bin.
    1066             : // Special values are bin 0 for underflow and bin nBin+1 for overflow.
    1067             : // All other bins outside proper histogram range return 0.
    1068             : 
    1069             : double Hist::getBinContent(int iBin) const {
    1070             : 
    1071           0 :   if (iBin > 0 && iBin <= nBin) return res[iBin - 1];
    1072           0 :   else if (iBin == 0)           return under;
    1073           0 :   else if (iBin == nBin + 1)    return over;
    1074           0 :   else                          return 0.;
    1075             : 
    1076           0 : }
    1077             : 
    1078             : //--------------------------------------------------------------------------
    1079             : 
    1080             : // Check whether another histogram has same size and limits.
    1081             : 
    1082             : bool Hist::sameSize(const Hist& h) const {
    1083             : 
    1084           0 :   if (nBin == h.nBin && abs(xMin - h.xMin) < TOLERANCE * dx &&
    1085           0 :     abs(xMax - h.xMax) < TOLERANCE * dx) return true;
    1086           0 :   else return false;
    1087             : 
    1088           0 : }
    1089             : 
    1090             : //--------------------------------------------------------------------------
    1091             : 
    1092             : // Take 10-logarithm or natural logarithm of contents bin by bin.
    1093             : 
    1094             : void Hist::takeLog(bool tenLog) {
    1095             : 
    1096             :   // Find smallest positive bin content, and put min a bit below.
    1097           0 :   double yMin = Hist::LARGE;
    1098           0 :   for (int ix = 0; ix < nBin; ++ix)
    1099           0 :     if (res[ix] > Hist::TINY && res[ix] < yMin ) yMin = res[ix];
    1100           0 :   yMin *= 0.8;
    1101             : 
    1102             :   // Take 10-logarithm bin by bin, but ensure positivity.
    1103           0 :   if (tenLog) {
    1104           0 :     for (int ix = 0; ix < nBin; ++ix)
    1105           0 :       res[ix] = log10( max( yMin, res[ix]) );
    1106           0 :     under  =  log10( max( yMin, under) );
    1107           0 :     inside =  log10( max( yMin, inside) );
    1108           0 :     over   =  log10( max( yMin, over) );
    1109             : 
    1110             :   // Take natural logarithm bin by bin, but ensure positivity.
    1111           0 :   } else {
    1112           0 :     for (int ix = 0; ix < nBin; ++ix)
    1113           0 :       res[ix] = log( max( yMin, res[ix]) );
    1114           0 :     under  =  log( max( yMin, under) );
    1115           0 :     inside =  log( max( yMin, inside) );
    1116           0 :     over   =  log( max( yMin, over) );
    1117             :   }
    1118             : 
    1119           0 : }
    1120             : 
    1121             : //--------------------------------------------------------------------------
    1122             : 
    1123             : // Take square root of contents bin by bin; set 0 for negative content.
    1124             : 
    1125             : void Hist::takeSqrt() {
    1126             : 
    1127           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] = sqrtpos(res[ix]);
    1128           0 :   under  = sqrtpos(under);
    1129           0 :   inside = sqrtpos(inside);
    1130           0 :   over   = sqrtpos(over);
    1131             : 
    1132           0 : }
    1133             : 
    1134             : //--------------------------------------------------------------------------
    1135             : 
    1136             : // Add histogram to existing one.
    1137             : 
    1138             : Hist& Hist::operator+=(const Hist& h) {
    1139           0 :   if (!sameSize(h)) return *this;
    1140           0 :   nFill  += h.nFill;
    1141           0 :   under  += h.under;
    1142           0 :   inside += h.inside;
    1143           0 :   over += h.over;
    1144           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] += h.res[ix];
    1145           0 :   return *this;
    1146           0 : }
    1147             : 
    1148             : //--------------------------------------------------------------------------
    1149             : 
    1150             : // Subtract histogram from existing one.
    1151             : 
    1152             : Hist& Hist::operator-=(const Hist& h) {
    1153           0 :   if (!sameSize(h)) return *this;
    1154           0 :   nFill  += h.nFill;
    1155           0 :   under  -= h.under;
    1156           0 :   inside -= h.inside;
    1157           0 :   over -= h.over;
    1158           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] -= h.res[ix];
    1159           0 :   return *this;
    1160           0 : }
    1161             : 
    1162             : //--------------------------------------------------------------------------
    1163             : 
    1164             : // Multiply existing histogram by another one.
    1165             : 
    1166             : Hist& Hist::operator*=(const Hist& h) {
    1167           0 :   if (!sameSize(h)) return *this;
    1168           0 :   nFill   += h.nFill;
    1169           0 :   under  *= h.under;
    1170           0 :   inside *= h.inside;
    1171           0 :   over *= h.over;
    1172           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] *= h.res[ix];
    1173           0 :   return *this;
    1174           0 : }
    1175             : 
    1176             : //--------------------------------------------------------------------------
    1177             : 
    1178             : // Divide existing histogram by another one.
    1179             : 
    1180             : Hist& Hist::operator/=(const Hist& h) {
    1181           0 :   if (!sameSize(h)) return *this;
    1182           0 :   nFill += h.nFill;
    1183           0 :   under  = (abs(h.under) < Hist::TINY) ? 0. : under/h.under;
    1184           0 :   inside = (abs(h.inside) < Hist::TINY) ? 0. : inside/h.inside;
    1185           0 :   over  = (abs(h.over) < Hist::TINY) ? 0. : over/h.over;
    1186           0 :   for (int ix = 0; ix < nBin; ++ix)
    1187           0 :     res[ix] = (abs(h.res[ix]) < Hist::TINY) ? 0. : res[ix]/h.res[ix];
    1188           0 :   return *this;
    1189           0 : }
    1190             : 
    1191             : //--------------------------------------------------------------------------
    1192             : 
    1193             : // Add constant offset to histogram.
    1194             : 
    1195             : Hist& Hist::operator+=(double f) {
    1196           0 :   under  += f;
    1197           0 :   inside += nBin * f;
    1198           0 :   over   += f;
    1199           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] += f;
    1200           0 :   return *this;
    1201             : }
    1202             : 
    1203             : //--------------------------------------------------------------------------
    1204             : 
    1205             : // Subtract constant offset from histogram.
    1206             : 
    1207             : Hist& Hist::operator-=(double f) {
    1208           0 :   under  -= f;
    1209           0 :   inside -= nBin * f;
    1210           0 :   over   -= f;
    1211           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] -= f;
    1212           0 :   return *this;
    1213             : }
    1214             : 
    1215             : //--------------------------------------------------------------------------
    1216             : 
    1217             : // Multiply histogram by constant.
    1218             : 
    1219             : Hist& Hist::operator*=(double f) {
    1220           0 :   under  *= f;
    1221           0 :   inside *= f;
    1222           0 :   over   *= f;
    1223           0 :   for (int ix = 0; ix < nBin; ++ix) res[ix] *= f;
    1224           0 :   return *this;
    1225             : }
    1226             : 
    1227             : //--------------------------------------------------------------------------
    1228             : 
    1229             : // Divide histogram by constant.
    1230             : 
    1231             : Hist& Hist::operator/=(double f) {
    1232           0 :   if (abs(f) > Hist::TINY) {
    1233           0 :     under  /= f;
    1234           0 :     inside /= f;
    1235           0 :     over   /= f;
    1236           0 :     for (int ix = 0; ix < nBin; ++ix) res[ix] /= f;
    1237             :   // Set empty contents when division by zero.
    1238           0 :   } else {
    1239           0 :     under  = 0.;
    1240           0 :     inside = 0.;
    1241           0 :     over   = 0.;
    1242           0 :     for (int ix = 0; ix < nBin; ++ix) res[ix] = 0.;
    1243             :   }
    1244           0 :   return *this;
    1245             : }
    1246             : 
    1247             : //--------------------------------------------------------------------------
    1248             : 
    1249             : // Implementation of operator overloading with friends.
    1250             : 
    1251             : Hist operator+(double f, const Hist& h1) {
    1252           0 :   Hist h = h1; return h += f;}
    1253             : 
    1254             : Hist operator+(const Hist& h1, double f) {
    1255           0 :   Hist h = h1; return h += f;}
    1256             : 
    1257             : Hist operator+(const Hist& h1, const Hist& h2) {
    1258           0 :   Hist h = h1; return h += h2;}
    1259             : 
    1260             : Hist operator-(double f, const Hist& h1) {
    1261           0 :   Hist h   = h1;
    1262           0 :   h.under  = f - h1.under;
    1263           0 :   h.inside = h1.nBin * f - h1.inside;
    1264           0 :   h.over   = f - h1.over;
    1265           0 :   for (int ix = 0; ix < h1.nBin; ++ix) h.res[ix] = f - h1.res[ix];
    1266           0 :   return h;}
    1267             : 
    1268             : Hist operator-(const Hist& h1, double f) {
    1269           0 :   Hist h = h1; return h -= f;}
    1270             : 
    1271             : Hist operator-(const Hist& h1, const Hist& h2) {
    1272           0 :   Hist h = h1; return h -= h2;}
    1273             : 
    1274             : Hist operator*(double f, const Hist& h1) {
    1275           0 :   Hist h = h1; return h *= f;}
    1276             : 
    1277             : Hist operator*(const Hist& h1, double f) {
    1278           0 :   Hist h = h1; return h *= f;}
    1279             : 
    1280             : Hist operator*(const Hist& h1, const Hist& h2) {
    1281           0 :   Hist h = h1; return h *= h2;}
    1282             : 
    1283             : Hist operator/(double f, const Hist& h1) {
    1284           0 :   Hist h = h1;
    1285           0 :   h.under  = (abs(h1.under)  < Hist::TINY) ? 0. :  f/h1.under;
    1286           0 :   h.inside = (abs(h1.inside) < Hist::TINY) ? 0. :  f/h1.inside;
    1287           0 :   h.over   = (abs(h1.over)   < Hist::TINY) ? 0. :  f/h1.over;
    1288           0 :   for (int ix = 0; ix < h1.nBin; ++ix)
    1289           0 :     h.res[ix] = (abs(h1.res[ix]) < Hist::TINY) ? 0. : f/h1.res[ix];
    1290             :   return h;
    1291           0 : }
    1292             : 
    1293             : Hist operator/(const Hist& h1, double f) {
    1294           0 :   Hist h = h1; return h /= f;}
    1295             : 
    1296             : Hist operator/(const Hist& h1, const Hist& h2) {
    1297           0 :   Hist h = h1; return h /= h2;}
    1298             : 
    1299             : //==========================================================================
    1300             : 
    1301             : } // end namespace Pythia8

Generated by: LCOV version 1.11