Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-13 09:05:14

0001 // Basics.h is a part of the PYTHIA event generator.
0002 // Copyright (C) 2025 Torbjorn Sjostrand.
0003 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
0004 // Please respect the MCnet Guidelines, see GUIDELINES for details.
0005 
0006 // Header file for basic, often-used helper classes.
0007 // RndmEngine: base class for external random number generators.
0008 // Rndm: random number generator.
0009 // Vec4: simple four-vectors.
0010 // RotBstMatrix: matrices encoding rotations and boosts of Vec4 objects.
0011 // Hist: simple one-dimensional histograms.
0012 
0013 #ifndef Pythia8_Basics_H
0014 #define Pythia8_Basics_H
0015 
0016 #include "Pythia8/PythiaStdlib.h"
0017 #include "Pythia8/SharedPointers.h"
0018 
0019 namespace Pythia8 {
0020 
0021 //==========================================================================
0022 
0023 // Forward reference to RotBstMatrix class; needed in Vec4 class.
0024 class RotBstMatrix;
0025 
0026 //--------------------------------------------------------------------------
0027 
0028 // Vec4 class.
0029 // This class implements four-vectors, in energy-momentum space.
0030 // (But can equally well be used to hold space-time four-vectors.)
0031 
0032 class Vec4 {
0033 
0034 public:
0035 
0036   // Constructors.
0037   Vec4(double xIn = 0., double yIn = 0., double zIn = 0., double tIn = 0.)
0038     : xx(xIn), yy(yIn), zz(zIn), tt(tIn) { }
0039   Vec4(const Vec4& v) : xx(v.xx), yy(v.yy), zz(v.zz), tt(v.tt) { }
0040   Vec4& operator=(const Vec4& v) { if (this != &v) { xx = v.xx; yy = v.yy;
0041     zz = v.zz; tt = v.tt; } return *this; }
0042   Vec4& operator=(double value) { xx = value; yy = value; zz = value;
0043     tt = value; return *this; }
0044 
0045   // Member functions for input.
0046   void reset() {xx = 0.; yy = 0.; zz = 0.; tt = 0.;}
0047   void p(double xIn, double yIn, double zIn, double tIn)
0048     {xx = xIn; yy = yIn; zz = zIn; tt = tIn;}
0049   void p(Vec4 pIn) {xx = pIn.xx; yy = pIn.yy; zz = pIn.zz; tt = pIn.tt;}
0050   void px(double xIn) {xx = xIn;}
0051   void py(double yIn) {yy = yIn;}
0052   void pz(double zIn) {zz = zIn;}
0053   void e(double tIn) {tt = tIn;}
0054 
0055   // Member functions for output.
0056   double px() const {return xx;}
0057   double py() const {return yy;}
0058   double pz() const {return zz;}
0059   double e() const {return tt;}
0060   double& operator[](int i) {
0061     switch(i) {
0062       case 1: return xx;
0063       case 2: return yy;
0064       case 3: return zz;
0065       default: return tt;
0066     }
0067   }
0068   double mCalc() const {double temp = tt*tt - xx*xx - yy*yy - zz*zz;
0069     return (temp >= 0.) ? sqrt(temp) : -sqrt(-temp);}
0070   double m2Calc() const {return tt*tt - xx*xx - yy*yy - zz*zz;}
0071   double pT() const {return sqrt(xx*xx + yy*yy);}
0072   double pT2() const {return xx*xx + yy*yy;}
0073   double pAbs() const {return sqrt(xx*xx + yy*yy + zz*zz);}
0074   double pAbs2() const {return xx*xx + yy*yy + zz*zz;}
0075   double eT() const {double temp = xx*xx + yy*yy;
0076     return tt * sqrt( temp / (temp + zz*zz) );}
0077   double eT2() const {double temp = xx*xx + yy*yy;
0078     return tt*tt * temp / (temp + zz*zz);}
0079   double theta() const {return atan2(sqrt(xx*xx + yy*yy), zz);}
0080   double phi() const {return atan2(yy,xx);}
0081   double thetaXZ() const {return atan2(xx,zz);}
0082   double pPos() const {return tt + zz;}
0083   double pNeg() const {return tt - zz;}
0084   double rap() const {
0085     double txyz = (tt > 0.) ? tt : sqrt(xx*xx + yy*yy + zz*zz);
0086     if (zz >= txyz) return 20.;
0087     if (zz <= -txyz) return -20.;
0088     return 0.5 * log( (txyz + zz) / (txyz - zz) );}
0089   double eta() const {double xyz = sqrt(xx*xx + yy*yy + zz*zz);
0090     if (zz >= xyz) return 20.;
0091     if (zz <= -xyz) return -20.;
0092     return 0.5 * log( (xyz + zz) / (xyz - zz) );}
0093 
0094   // Member functions that perform operations.
0095   void rescale3(double fac) {xx *= fac; yy *= fac; zz *= fac;}
0096   void rescale4(double fac) {xx *= fac; yy *= fac; zz *= fac; tt *= fac;}
0097   void flip3() {xx = -xx; yy = -yy; zz = -zz;}
0098   void flip4() {xx = -xx; yy = -yy; zz = -zz; tt = -tt;}
0099   void rot(double thetaIn, double phiIn);
0100   void rotaxis(double phiIn, double nx, double ny, double nz);
0101   void rotaxis(double phiIn, const Vec4& n);
0102   void bst(double betaX, double betaY, double betaZ);
0103   void bst(double betaX, double betaY, double betaZ, double gamma);
0104   void bst(const Vec4& pIn);
0105   void bst(const Vec4& pIn, double mIn);
0106   void bstback(const Vec4& pIn);
0107   void bstback(const Vec4& pIn, double mIn);
0108   void rotbst(const RotBstMatrix& M);
0109   double eInFrame(const Vec4& pIn) const;
0110 
0111   // Operator overloading with member functions
0112   inline Vec4 operator-() const {Vec4 tmp; tmp.xx = -xx; tmp.yy = -yy;
0113     tmp.zz = -zz; tmp.tt = -tt; return tmp;}
0114   inline Vec4& operator+=(const Vec4& v) {xx += v.xx; yy += v.yy; zz += v.zz;
0115     tt += v.tt; return *this;}
0116   inline Vec4& operator-=(const Vec4& v) {xx -= v.xx; yy -= v.yy; zz -= v.zz;
0117     tt -= v.tt; return *this;}
0118   inline Vec4& operator*=(double f) {xx *= f; yy *= f; zz *= f;
0119     tt *= f; return *this;}
0120   inline Vec4& operator/=(double f) {xx /= f; yy /= f; zz /= f;
0121     tt /= f; return *this;}
0122   inline Vec4 operator+(const Vec4& v) const {
0123     Vec4 tmp = *this; return tmp += v;}
0124   inline Vec4 operator-(const Vec4& v) const {
0125     Vec4 tmp = *this; return tmp -= v;}
0126   inline Vec4 operator*(double f) const {
0127     Vec4 tmp = *this; return tmp *= f;}
0128   inline Vec4 operator/(double f) const {
0129     Vec4 tmp = *this; return tmp /= f;}
0130   inline double operator*(const Vec4& v) const {
0131     return tt*v.tt - xx*v.xx - yy*v.yy - zz*v.zz;}
0132 
0133   // Operator overloading with friends.
0134   friend Vec4 operator*(double f, const Vec4& v1);
0135 
0136   // Print a four-vector.
0137   friend ostream& operator<<(ostream&, const Vec4& v) ;
0138 
0139   // Check if NaN, INF, or finite.
0140   friend inline bool isnan(const Vec4 &v) {
0141     return isnan(v.tt) || isnan(v.xx) || isnan(v.yy) || isnan(v.zz);}
0142   friend inline bool isinf(const Vec4 &v) {
0143     return isinf(v.tt) || isinf(v.xx) || isinf(v.yy) || isinf(v.zz);}
0144   friend inline bool isfinite(const Vec4 &v) {
0145     return isfinite(v.tt) && isfinite(v.xx) && isfinite(v.yy)
0146       && isfinite(v.zz);}
0147 
0148   // Invariant mass and its square.
0149   friend double m(const Vec4& v1);
0150   friend double m(const Vec4& v1, const Vec4& v2);
0151   friend double m2(const Vec4& v1);
0152   friend double m2(const Vec4& v1, const Vec4& v2);
0153   friend double m2(const Vec4& v1, const Vec4& v2, const Vec4& v3);
0154   friend double m2(const Vec4& v1, const Vec4& v2, const Vec4& v3,
0155                    const Vec4& v4);
0156 
0157   // Scalar and cross product of 3-vector parts.
0158   friend double dot3(const Vec4& v1, const Vec4& v2);
0159   friend Vec4 cross3(const Vec4& v1, const Vec4& v2);
0160 
0161   // Cross-product of three 4-vectors ( p_i = epsilon_{iabc} p_a p_b p_c).
0162   friend Vec4 cross4(const Vec4& a, const Vec4& b, const Vec4& c);
0163 
0164   // theta is the opening angle (on the unit sphere) between v1 and v2.
0165   friend double theta(const Vec4& v1, const Vec4& v2);
0166   friend double costheta(const Vec4& v1, const Vec4& v2);
0167   friend double sintheta(const Vec4& v1, const Vec4& v2);
0168 
0169   // phi is azimuthal angle between v1 and v2 around z axis.
0170   friend double phi(const Vec4& v1, const Vec4& v2);
0171   friend double cosphi(const Vec4& v1, const Vec4& v2);
0172 
0173   // phi is azimuthal angle between v1 and v2 around n axis.
0174   friend double phi(const Vec4& v1, const Vec4& v2, const Vec4& n);
0175   friend double cosphi(const Vec4& v1, const Vec4& v2, const Vec4& n);
0176 
0177   // R is distance in cylindrical (y/eta, phi) coordinates.
0178   friend double RRapPhi(const Vec4& v1, const Vec4& v2);
0179   friend double REtaPhi(const Vec4& v1, const Vec4& v2);
0180 
0181   // Shift four-momenta within pair from old to new masses.
0182   friend bool pShift( Vec4& p1Move, Vec4& p2Move, double m1New, double m2New);
0183 
0184   // Create two vectors that are perpendicular to both input vectors.
0185   friend pair<Vec4,Vec4> getTwoPerpendicular(const Vec4& v1, const Vec4& v2);
0186 
0187 private:
0188 
0189   // Constants: could only be changed in the code itself.
0190   static const double TINY;
0191 
0192   // The four-vector data members.
0193   double xx, yy, zz, tt;
0194 
0195 };
0196 
0197 //--------------------------------------------------------------------------
0198 
0199 // Namespace function declarations; friends of Vec4 class.
0200 
0201 // Implementation of operator overloading with friends.
0202 inline Vec4 operator*(double f, const Vec4& v1)
0203   {Vec4 v = v1; return v *= f;}
0204 
0205 // Invariant mass and its square.
0206 double m(const Vec4& v1);
0207 double m(const Vec4& v1, const Vec4& v2);
0208 double m2(const Vec4& v1);
0209 double m2(const Vec4& v1, const Vec4& v2);
0210 double m2(const Vec4& v1, const Vec4& v2, const Vec4& v3);
0211 double m2(const Vec4& v1, const Vec4& v2, const Vec4& v3,
0212           const Vec4& v4);
0213 
0214 // Scalar and cross product of 3-vector parts.
0215 double dot3(const Vec4& v1, const Vec4& v2);
0216 Vec4 cross3(const Vec4& v1, const Vec4& v2);
0217 
0218 // Cross-product of three 4-vectors ( p_i = epsilon_{iabc} p_a p_b p_c).
0219 Vec4 cross4(const Vec4& a, const Vec4& b, const Vec4& c);
0220 
0221 // theta is polar angle between v1 and v2.
0222 double theta(const Vec4& v1, const Vec4& v2);
0223 double costheta(const Vec4& v1, const Vec4& v2);
0224 double sintheta(const Vec4& v1, const Vec4& v2);
0225 double costheta(double e1, double e2, double m1, double m2, double s12);
0226 
0227 // phi is azimuthal angle between v1 and v2 around z axis.
0228 double phi(const Vec4& v1, const Vec4& v2);
0229 double cosphi(const Vec4& v1, const Vec4& v2);
0230 
0231 // phi is azimuthal angle between v1 and v2 around n axis.
0232 double phi(const Vec4& v1, const Vec4& v2, const Vec4& n);
0233 double cosphi(const Vec4& v1, const Vec4& v2, const Vec4& n);
0234 
0235 // R is distance in cylindrical (y/eta, phi) coordinates.
0236 double RRapPhi(const Vec4& v1, const Vec4& v2);
0237 double REtaPhi(const Vec4& v1, const Vec4& v2);
0238 
0239 // Print a four-vector.
0240 ostream& operator<<(ostream&, const Vec4& v) ;
0241 
0242 // Shift four-momenta within pair from old to new masses.
0243 bool pShift( Vec4& p1Move, Vec4& p2Move, double m1New, double m2New);
0244 
0245 // Create two vectors that are perpendicular to both input vectors.
0246 pair<Vec4,Vec4> getTwoPerpendicular(const Vec4& v1, const Vec4& v2);
0247 
0248 //==========================================================================
0249 
0250 // RotBstMatrix class.
0251 // This class implements 4 * 4 matrices that encode an arbitrary combination
0252 // of rotations and boosts, that can be applied to Vec4 four-vectors.
0253 
0254 class RotBstMatrix {
0255 
0256 public:
0257 
0258   // Constructors.
0259   RotBstMatrix() : M() {for (int i = 0; i < 4; ++i) {
0260     for (int j = 0; j < 4; ++j) { M[i][j] = (i==j) ? 1. : 0.; } } }
0261   RotBstMatrix(const RotBstMatrix& Min) : M() {
0262     for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) {
0263     M[i][j] = Min.M[i][j]; } } }
0264   RotBstMatrix& operator=(const RotBstMatrix& Min) {if (this != &Min) {
0265     for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) {
0266     M[i][j] = Min.M[i][j]; } } } return *this; }
0267 
0268   // Member functions.
0269   void rot(double = 0., double = 0.);
0270   void rot(const Vec4& p);
0271   void bst(double = 0., double = 0., double = 0., double = 0.);
0272   void bst(const Vec4&);
0273   void bstback(const Vec4&);
0274   void bst(const Vec4&, const Vec4&);
0275   void toCMframe(const Vec4&, const Vec4&);
0276   void fromCMframe(const Vec4&, const Vec4&, bool flip = false);
0277   void toSameVframe(const Vec4&, const Vec4&);
0278   void fromSameVframe(const Vec4&, const Vec4&);
0279   void rotbst(const RotBstMatrix&);
0280   void invert();
0281   RotBstMatrix inverse() const { RotBstMatrix tmp = *this;
0282     tmp.invert(); return tmp; }
0283   void reset();
0284 
0285   // Return value of matrix element.
0286   double value(int i, int j) { return M[i][j];}
0287 
0288   // Crude estimate deviation from unit matrix.
0289   double deviation() const;
0290 
0291   // Print a transformation matrix.
0292   friend ostream& operator<<(ostream&, const RotBstMatrix&) ;
0293 
0294   // Private members to be accessible from Vec4.
0295   friend class Vec4;
0296 
0297   // Multiplication.
0298   Vec4 operator*(Vec4 p) const { p.rotbst(*this); return p; }
0299   RotBstMatrix operator*(RotBstMatrix R) const { R.rotbst(*this); return R; }
0300 
0301 private:
0302 
0303   // Constants: could only be changed in the code itself.
0304   static const double TINY;
0305 
0306   // The rotation-and-boost matrix data members.
0307   double M[4][4];
0308 
0309 };
0310 
0311 //--------------------------------------------------------------------------
0312 
0313 // Namespace function declaration; friend of RotBstMatrix class.
0314 
0315 // Print a transformation matrix.
0316 ostream& operator<<(ostream&, const RotBstMatrix&) ;
0317 
0318 // Get a RotBstMatrix to rest frame of p.
0319 inline RotBstMatrix toCMframe(const Vec4& p) {
0320   RotBstMatrix tmp; tmp.bstback(p); return tmp; }
0321 
0322 // Get a RotBstMatrix from rest frame of p.
0323 inline RotBstMatrix fromCMframe(const Vec4& p) {
0324   RotBstMatrix tmp; tmp.bst(p); return tmp; }
0325 
0326 // Get a RotBstMatrix to rest frame of p1 and p2, where p1 is along
0327 // the z-axis.
0328 inline RotBstMatrix toCMframe(const Vec4& p1, const Vec4& p2) {
0329   RotBstMatrix tmp; tmp.toCMframe(p1, p2); return tmp; }
0330 
0331 // Get a RotBstMatrix from rest frame of p1 and p2, where p1 is
0332 // assumed by default to be along the z-axis. The flip option
0333 // handles the case when p1 is along the negative z-axis.
0334 inline RotBstMatrix fromCMframe(const Vec4& p1, const Vec4& p2,
0335   bool flip = false) {
0336   RotBstMatrix tmp; tmp.fromCMframe(p1, p2, flip); return tmp; }
0337 
0338 // Get a RotBstMatrix to rest frame of ptot where pz is along the
0339 // z-axis and pxz is in the xz-plane with positive x.
0340 inline RotBstMatrix toCMframe(const Vec4& ptot, const Vec4& pz,
0341   const Vec4 & pxz) { RotBstMatrix tmp = toCMframe(ptot);
0342   Vec4 pzp = tmp*pz; tmp.rot(0.0, -pzp.phi()); tmp.rot(-pzp.theta());
0343   tmp.rot(0.0, -(tmp*pxz).phi()); return tmp; }
0344 
0345 // Get a RotBstMatrix from rest frame of ptot where pz is along the
0346 // z-axis and pxz is in the xz-plane with positive x.
0347 inline RotBstMatrix fromCMframe(const Vec4& ptot, const Vec4& pz,
0348   const Vec4 & pxz) { return toCMframe(ptot, pz, pxz).inverse(); }
0349 
0350 //==========================================================================
0351 
0352 // RndmEngine is the base class for external random number generators.
0353 // There is only one pure virtual method, that should do the generation.
0354 
0355 class RndmEngine {
0356 
0357 public:
0358 
0359   // Destructor.
0360   virtual ~RndmEngine() {}
0361 
0362   // A virtual method, wherein the derived class method
0363   // generates a random number uniformly distributed between 0 and 1.
0364   virtual double flat() {return 1;}
0365 
0366 };
0367 
0368 //==========================================================================
0369 
0370 // RndmState class.
0371 // This class describes the configuration of a Rndm object.
0372 
0373 struct RndmState {
0374   int    i97{}, j97{}, seed{0};
0375   long   sequence{0};
0376   double u[97]{}, c{}, cd{}, cm{};
0377 
0378   // Test whether two random states would generate the same random sequence.
0379   bool operator==(const RndmState& other) const;
0380 };
0381 
0382 //==========================================================================
0383 
0384 // Rndm class.
0385 // This class handles random number generation according to the
0386 // Marsaglia-Zaman-Tsang algorithm.
0387 
0388 class Rndm {
0389 
0390 public:
0391 
0392   // Constructors.
0393   Rndm() : initRndm(false), stateSave(), useExternalRndm(false) { }
0394   Rndm(int seedIn) : initRndm(false), stateSave(), useExternalRndm(false) {
0395     init(seedIn);}
0396 
0397   // Possibility to pass in pointer for external random number generation.
0398   bool rndmEnginePtr( RndmEnginePtr rndmEngPtrIn);
0399 
0400   // Initialize, normally at construction or in first call.
0401   void init(int seedIn = 0) ;
0402 
0403   // Generate next random number uniformly between 0 and 1.
0404   double flat() ;
0405 
0406   // Generate random numbers according to exp(-x).
0407   double exp() ;
0408 
0409   // Generate random numbers according to x * exp(-x).
0410   double xexp() { return -log(flat() * flat()) ;}
0411 
0412   // Generate random numbers according to exp(-x^2/2).
0413   double gauss() {return sqrt(-2. * log(flat())) * cos(M_PI * flat());}
0414 
0415   // Generate two random numbers according to exp(-x^2/2-y^2/2).
0416   pair<double, double> gauss2() {double r = sqrt(-2. * log(flat()));
0417     double phi = 2. * M_PI * flat();
0418     return { r * sin(phi), r * cos(phi) };}
0419 
0420   // Generate a random number according to a Gamma-distribution.
0421   double gamma(double k0, double r0);
0422 
0423   // Generate two random vectors according to the phase space distribution
0424   pair<Vec4, Vec4> phaseSpace2(double eCM, double m1, double m2);
0425 
0426   // Pick one option among  vector of (positive) probabilities.
0427   int pick(const vector<double>& prob) ;
0428 
0429   // Randomly shuffle a vector, standard Fisher-Yates algorithm.
0430   template<typename T> void shuffle(vector<T>& vec);
0431 
0432   // Peek at the next random number in sequence without updating
0433   // the generator state.
0434   double peekFlat() {if (useExternalRndm) return -1;
0435     RndmState oldState = stateSave;
0436     double f = this->flat();
0437     stateSave = oldState;
0438     return f;
0439   }
0440 
0441   // Save or read current state to or from a binary file.
0442   bool dumpState(string fileName);
0443   bool readState(string fileName);
0444 
0445   // Get or set the state of the random number generator.
0446   RndmState getState() const {return stateSave;}
0447   void setState(const RndmState& state) {stateSave = state;}
0448 
0449   // The default seed, i.e. the Marsaglia-Zaman random number sequence.
0450   static constexpr int DEFAULTSEED = 19780503;
0451 
0452 #ifdef RNGDEBUG
0453   // Random number methods used for debugging only.
0454   double flatDebug(string loc, string file, int line);
0455   double xexpDebug(string loc, string file, int line);
0456   double gaussDebug(string loc, string file, int line);
0457   pair<double, double> gauss2Debug(string loc, string file, int line);
0458   double gammaDebug(string loc, string file, int line, double k0, double r0);
0459   pair<Vec4, Vec4> phaseSpace2Debug(string loc, string file, int line,
0460     double eCM, double m1, double m2);
0461 
0462   // Static members for debugging to print call file location or filter.
0463   static bool debugNow, debugLocation, debugIndex;
0464   static int debugPrecision, debugCall;
0465   static set<string> debugStarts, debugEnds, debugContains, debugMatches;
0466 #endif
0467 
0468 private:
0469 
0470   // State of the random number generator.
0471   bool      initRndm;
0472   RndmState stateSave;
0473 
0474   // Pointer for external random number generation.
0475   bool   useExternalRndm;
0476   RndmEnginePtr rndmEngPtr{};
0477 
0478 };
0479 
0480 //==========================================================================
0481 
0482 // Hist class.
0483 // This class handles a single histogram at a time.
0484 
0485 class Hist {
0486 
0487 public:
0488 
0489   // Constructors, including copy constructors.
0490   Hist() : titleSave(""), nBin(), nFill(), nNonFinite(), xMin(),
0491     xMax(), linX(), doStats(), dx(), under(), inside(), over(), sumxNw()
0492     { }
0493   Hist(string titleIn, int nBinIn = 100, double xMinIn = 0.,
0494     double xMaxIn = 1., bool logXIn = false, bool doStatsIn = false) :
0495     nBin(), nFill(), nNonFinite(), xMin(), xMax(), linX(), doStats(), dx(),
0496       under(), inside(), over(), sumxNw()
0497   { book(titleIn, nBinIn, xMinIn, xMaxIn, logXIn, doStatsIn); }
0498   Hist(const Hist& h)
0499     : titleSave(h.titleSave), nBin(h.nBin), nFill(h.nFill),
0500       nNonFinite(h.nNonFinite), xMin(h.xMin), xMax(h.xMax), linX(h.linX),
0501       doStats(h.doStats), dx(h.dx), under(h.under), inside(h.inside),
0502       over(h.over), res(h.res), res2(h.res2), sumxNw() {
0503     for (int i = 0; i < nMoments; ++i) sumxNw[i] = h.sumxNw[i];
0504   }
0505   Hist(string titleIn, const Hist& h)
0506     : titleSave(titleIn), nBin(h.nBin), nFill(h.nFill),
0507       nNonFinite(h.nNonFinite), xMin(h.xMin), xMax(h.xMax), linX(h.linX),
0508       doStats(h.doStats), dx(h.dx), under(h.under), inside(h.inside),
0509       over(h.over), res(h.res), res2(h.res2), sumxNw() {
0510     for (int i = 0; i < nMoments; ++i) sumxNw[i] = h.sumxNw[i];
0511   }
0512   Hist& operator=(const Hist& h) { if(this != &h) {
0513     nBin = h.nBin; nFill = h.nFill; nNonFinite = h.nNonFinite; xMin = h.xMin;
0514     xMax = h.xMax; linX = h.linX; doStats = h.doStats; dx = h.dx;
0515     under = h.under; inside = h.inside; over = h.over;
0516     for (int i = 0; i < nMoments; ++i) sumxNw[i] = h.sumxNw[i];
0517     res = h.res; res2 = h.res2; } return *this; }
0518 
0519   // Create a histogram that is the plot of the given function.
0520   static Hist plotFunc(function<double(double)> f, string titleIn,
0521     int nBinIn, double xMinIn, double xMaxIn, bool logXIn = false);
0522 
0523   // Book a histogram.
0524   void book(string titleIn = "  ", int nBinIn = 100, double xMinIn = 0.,
0525     double xMaxIn = 1., bool logXIn = false, bool doStatsIn = false) ;
0526 
0527   // Set title of a histogram.
0528   void title(string titleIn = "  ") {titleSave = titleIn; }
0529 
0530   // Reset bin contents.
0531   void null() ;
0532 
0533   // Fill bin with weight.
0534   void fill(double x, double w = 1.) ;
0535 
0536   // Print a histogram with overloaded << operator.
0537   friend ostream& operator<<(ostream& os, const Hist& h) ;
0538 
0539   // Print histogram contents as a table (e.g. for Gnuplot, Rivet or Pyplot),
0540   // optionally with statistical errors.
0541   void table(ostream& os = cout, bool printOverUnder = false,
0542     bool xMidBin = true, bool printError = false) const ;
0543   void table(string fileName, bool printOverUnder = false,
0544     bool xMidBin = true, bool printError = false) const {
0545     ofstream streamName(fileName.c_str());
0546     table(streamName, printOverUnder, xMidBin, printError);}
0547   void rivetTable(ostream& os = cout, bool printError = true) const ;
0548   void rivetTable(string fileName, bool printError = true) const {
0549     ofstream streamName(fileName.c_str()); rivetTable(streamName, printError);}
0550   void pyplotTable(ostream& os = cout, bool isHist = true,
0551     bool printError = false) const ;
0552   void pyplotTable(string fileName, bool isHist = true,
0553     bool printError = false) const {ofstream streamName(fileName.c_str());
0554     pyplotTable(streamName, isHist, printError);}
0555 
0556   // Fill contents of a two-column (x,y) table, e.g. written by table() above.
0557   void fillTable(istream& is = cin);
0558   void fillTable(string fileName) { ifstream streamName(fileName.c_str());
0559     fillTable(streamName);}
0560 
0561   // Print a table out of two histograms with same x axis (no errors printed).
0562   friend void table(const Hist& h1, const Hist& h2, ostream& os,
0563     bool printOverUnder, bool xMidBin) ;
0564   friend void table(const Hist& h1, const Hist& h2, string fileName,
0565     bool printOverUnder, bool xMidBin) ;
0566 
0567   // Return title and size of histogram. Also if logarithmic x scale.
0568   string getTitle() const {return titleSave;}
0569   int    getBinNumber() const {return nBin;}
0570   int    getNonFinite() const {return nNonFinite;}
0571   bool   getLinX() const {return linX;}
0572 
0573   // Return min and max in x and y directions.
0574   double getXMin() const {return xMin;}
0575   double getXMax() const {return xMax;}
0576   double getYMin() const { if (nBin == 0) return 0.;
0577     double yMin = res[0];
0578     for (int ix = 1; ix < nBin; ++ix)
0579       if (res[ix] < yMin ) yMin = res[ix];
0580     return yMin;}
0581   double getYMax() const { if (nBin == 0) return 0.;
0582     double yMax = res[0];
0583     for (int ix = 1; ix < nBin; ++ix)
0584       if (res[ix] > yMax ) yMax = res[ix];
0585     return yMax;}
0586   double getYAbsMin() const { double yAbsMin = 1e20; double yAbs;
0587     for (int ix = 0; ix < nBin; ++ix) { yAbs = abs(res[ix]);
0588       if (yAbs > 1e-20 && yAbs < yAbsMin) yAbsMin = yAbs; }
0589     return yAbsMin;}
0590 
0591   // Return <X> and error on <X>, unbinned from saved weight sums (default)
0592   // or directly from the histogram bins (unbinned = false). In the latter
0593   // case, the error estimate includes the difference between the binned and
0594   // unbinned value summed in quadrature with the statistical error, as a
0595   // measure of bin granularity error.
0596   double getXMean(bool unbinned=true) const;
0597   double getXMeanErr(bool unbinned=true) const;
0598 
0599   // Return Median in X and its statistical error, ignoring underflow and
0600   // overflow (default) or including them (includeOverUnder = true). By
0601   // default, error includes granularity estimate obtained by comparing binned
0602   // vs unbinned mean value, but this can be switched off (unbinned = false).
0603   double getXMedian(bool includeOverUnder=false) const;
0604   double getXMedianErr(bool unbinned=true) const;
0605 
0606   // Return average <Y> value.
0607   double getYMean() const { return inside / nFill; }
0608 
0609   // Return RMS and equivalent n'th roots of n'th moments about the mean,
0610   // and their error estimates. Up to n = 6, both unbinned and binned moments
0611   // can be calculated. For n >= 7, and for all error estimates, only
0612   // binned values are available. Note that (unlike ROOT), the error estimates
0613   // do not assume normal distributions.
0614   // RMN(2) = RMS is the standard root-mean-square deviation from the mean.
0615   // RMN(3) is the cube root of the mean-cube deviation,
0616   //         cbrt(<(x - <x>)^3>). It is sensitive to single-sided tails,
0617   //         as are characteristic of many particle-physics distributions.
0618   // RMN(4) adds sensitivity to double-sided long tails (eg BW vs
0619   //         Gaussian), and further sensitivity to long single-sided ones.
0620   // Etc.
0621   double getXRMN(int n=2, bool unbinned=true) const;
0622   double getXRMS(bool unbinned=true) const {return getXRMN(2, unbinned);}
0623 
0624   double getXRMNErr(int n=2, bool unbinned=true) const;
0625   double getXRMSErr(bool unbinned=true) const {
0626     return getXRMNErr(2, unbinned);}
0627 
0628   // Return content of specific bin: 0 gives underflow and nBin+1 overflow.
0629   double getBinContent(int iBin) const;
0630 
0631   // Return the lower edge of the bin.
0632   double getBinEdge(int iBin) const;
0633 
0634   // Return the width of the bin.
0635   double getBinWidth(int iBin=1) const;
0636 
0637   // Return bin contents.
0638   vector<double> getBinContents() const;
0639 
0640   // Return bin edges.
0641   vector<double> getBinEdges() const;
0642 
0643   // Return number of entries.
0644   int getEntries(bool alsoNonFinite = true) const {
0645     return alsoNonFinite ? nNonFinite + nFill : nFill; }
0646 
0647   // Return sum of weights.
0648   double getWeightSum(bool alsoOverUnder = true) const {
0649     return alsoOverUnder ? inside + over + under : inside; }
0650 
0651   // Return effective entries (for weighted histograms = number
0652   // of equivalent unweighted events for same statistical power).
0653   double getNEffective() const {
0654     double sumw2 = 0.;
0655     for (int ix = 0; ix < nBin; ++ix) sumw2 += res2[ix];
0656     if (sumw2 <= Hist::TINY) return 0.;
0657     else return pow2(sumxNw[0]) / sumw2;
0658   }
0659 
0660   // Check whether another histogram has same size and limits.
0661   bool sameSize(const Hist& h) const ;
0662 
0663   // Take an arbitrary function of bin contents.
0664   void takeFunc(function<double(double)> func);
0665 
0666   // Take logarithm (base 10 or e) of bin contents.
0667   void takeLog(bool tenLog = true);
0668 
0669   // Take square root of bin contents.
0670   void takeSqrt();
0671 
0672   // Normalize sum of bin contents to value, with or without overflow bins.
0673   void normalize(double f = 1, bool overflow = true) ;
0674 
0675   // Normalize sum of bin areas to value, with or without overflow bins.
0676   void normalizeIntegral(double f = 1, bool overflow = true);
0677 
0678   // Scale each bin content by 1 / (wtSum * bin width).
0679   void normalizeSpectrum(double wtSum);
0680 
0681   // Operator overloading with member functions
0682   Hist& operator+=(const Hist& h) ;
0683   Hist& operator-=(const Hist& h) ;
0684   Hist& operator*=(const Hist& h) ;
0685   Hist& operator/=(const Hist& h) ;
0686   Hist& operator+=(double f) ;
0687   Hist& operator-=(double f) ;
0688   Hist& operator*=(double f) ;
0689   Hist& operator/=(double f) ;
0690   Hist operator+(double f) const;
0691   Hist operator+(const Hist& h2) const;
0692   Hist operator-(double f) const;
0693   Hist operator-(const Hist& h2) const;
0694   Hist operator*(double f) const;
0695   Hist operator*(const Hist& h2) const;
0696   Hist operator/(double f) const;
0697   Hist operator/(const Hist& h2) const;
0698 
0699   // Operator overloading with friends
0700   friend Hist operator+(double f, const Hist& h1);
0701   friend Hist operator-(double f, const Hist& h1);
0702   friend Hist operator*(double f, const Hist& h1);
0703   friend Hist operator/(double f, const Hist& h1);
0704 
0705 private:
0706 
0707   // Constants: could only be changed in the code itself.
0708   static const int    NBINMAX, NCOLMAX, NLINES;
0709   static const double TOLERANCE, TINY, LARGE, SMALLFRAC, DYAC[];
0710   static const char   NUMBER[];
0711 
0712   // Properties and contents of a histogram.
0713   string titleSave;
0714   int    nBin, nFill, nNonFinite;
0715   double xMin, xMax;
0716   bool   linX, doStats;
0717   double dx, under, inside, over;
0718   vector<double> res, res2;
0719 
0720   // Sum x^N w, for different powers N, for calculation of unbinned moments.
0721   static constexpr int nMoments = 7;
0722   double sumxNw[nMoments];
0723 
0724 };
0725 
0726 //--------------------------------------------------------------------------
0727 
0728 // Namespace function declarations; friends of Hist class.
0729 
0730 // Print a histogram with overloaded << operator.
0731 ostream& operator<<(ostream& os, const Hist& h) ;
0732 
0733 // Print a table out of two histograms with same x axis.
0734 void table(const Hist& h1, const Hist& h2, ostream& os = cout,
0735   bool printOverUnder = false, bool xMidBin = true) ;
0736 void table(const Hist& h1, const Hist& h2, string fileName,
0737   bool printOverUnder = false, bool xMidBin = true) ;
0738 
0739 // Operator overloading with friends
0740 Hist operator+(double f, const Hist& h1);
0741 Hist operator-(double f, const Hist& h1);
0742 Hist operator*(double f, const Hist& h1);
0743 Hist operator/(double f, const Hist& h1);
0744 
0745 //==========================================================================
0746 
0747 // HistPlot class.
0748 // Writes a Python program that can generate PDF plots from Hist histograms.
0749 
0750 class HistPlot {
0751 
0752 public:
0753 
0754   // Constructor requires name of Python program (and adds .py).
0755   HistPlot(string pythonName, bool useLegacyIn = false)
0756     : nFrame(), nTable(), useLegacy(useLegacyIn) {
0757     toPython.open( (pythonName + ".py").c_str() );
0758     toPython << "from matplotlib import pyplot as plt" << endl
0759              << "from matplotlib.backends.backend_pdf import PdfPages" << endl;
0760     nPDF = 0; }
0761 
0762   // Destructor should do final close.
0763   ~HistPlot() { toPython << "pp.close()" << endl; }
0764 
0765   // New plot frame, with title, x and y labels, x and y sizes.
0766   void frame( string frameIn, string titleIn = "", string xLabIn = "",
0767     string yLabIn = "", double xSizeIn = 8., double ySizeIn = 6.) {
0768     framePrevious = frameName; frameName = frameIn; title = titleIn;
0769     xLabel = xLabIn; yLabel = yLabIn; xSize = xSizeIn; ySize = ySizeIn;
0770     histos.clear(); styles.clear(); legends.clear(); files.clear();
0771     fileStyles.clear(); fileLegends.clear(); filexyerr.clear();}
0772 
0773   // Add a histogram to the current plot, with optional style and legend.
0774   void add( const Hist& histIn, string styleIn = "h",
0775     string legendIn = "void") {
0776     if (histIn.getBinNumber() == 0) {
0777       cout << " Error: histogram is not booked" << endl;
0778       return;
0779     }
0780     histos.push_back(histIn);
0781     styles.push_back(styleIn); legends.push_back(legendIn); }
0782 
0783   // Add a file of (x, y) values not from a histogram, e.g. data points.
0784   void addFile( string fileIn, string styleIn = "o",
0785     string legendIn = "void", string xyerrIn="") { files.push_back(fileIn);
0786     fileStyles.push_back(styleIn); fileLegends.push_back(legendIn);
0787     filexyerr.push_back(xyerrIn);}
0788 
0789   // Plot a frame given the information from the new and add calls.
0790   void plot( bool logY = false, bool logX = false, bool userBorders = false);
0791   void plot( double xMinUserIn, double xMaxUserIn,  double yMinUserIn,
0792      double yMaxUserIn, bool logY = false, bool logX = false) {
0793      xMinUser = xMinUserIn; xMaxUser = xMaxUserIn; yMinUser = yMinUserIn;
0794      yMaxUser = yMaxUserIn; plot( logY, logX, true);}
0795 
0796   //  Omnibus single call when only one histogram in the frame.
0797   void plotFrame( string frameIn, const Hist& histIn, string titleIn = "",
0798     string xLabIn = "", string yLabIn = "", string styleIn = "h",
0799     string legendIn = "void",  bool logY = false) {
0800     frame( frameIn, titleIn, xLabIn, yLabIn);
0801     add( histIn, styleIn, legendIn); plot( logY); }
0802 
0803 private:
0804 
0805   // Initialization code.
0806   void init( string pythonName);
0807 
0808   // Stored quantities.
0809   ofstream toPython;
0810   int      nPDF, nFrame, nTable;
0811   double   xSize, ySize, xMinUser, xMaxUser, yMinUser, yMaxUser;
0812   string   frameName, framePrevious, title, xLabel, yLabel, fileName, tmpFig;
0813   vector<Hist> histos;
0814   vector<string> styles, legends, files, fileStyles, fileLegends, filexyerr;
0815 
0816   // If true, use old linthreshy matplotlib parameter (removed in 3.5.0)
0817   bool useLegacy;
0818 
0819 };
0820 
0821 //==========================================================================
0822 
0823 // Methods used for debugging random number sequences.
0824 
0825 #ifdef RNGDEBUG
0826 #define flat() flatDebug(__METHOD_NAME__, __FILE__, __LINE__)
0827 #define xexp() xexpDebug(__METHOD_NAME__, __FILE__, __LINE__)
0828 #define gauss() gaussDebug(__METHOD_NAME__, __FILE__, __LINE__)
0829 #define gamma(...) gammaDebug(__METHOD_NAME__, __FILE__, __LINE__, __VA_ARGS__)
0830 #define phaseSpace2(...) phaseSpace2Debug(__METHOD_NAME__, __FILE__, __LINE__,\
0831     __VA_ARGS__)
0832 #endif
0833 
0834 //==========================================================================
0835 
0836 // Randomly shuffle a vector, standard Fisher-Yates algorithm.
0837 // This must be defined after possible RNG debugging.
0838 
0839 template<typename T> void Rndm::shuffle(vector<T>& vec) {
0840   for (int i = vec.size() - 1; i > 0; --i)
0841     swap(vec[i], vec[floor(flat() * (i + 1))]);
0842 }
0843 
0844 //==========================================================================
0845 
0846 } // end namespace Pythia8
0847 
0848 #endif // Pythia8_Basics_H