Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-06 08:48:40

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 w and weight uncertainty sig.
0534   // (Default sig < 0 => use sig = w, for pure stat counting.)
0535   void fill(double x, double w = 1., double sig = -1.) ;
0536 
0537   // Print a histogram with overloaded << operator.
0538   friend ostream& operator<<(ostream& os, const Hist& h) ;
0539 
0540   // Print histogram contents as a table (e.g. for Gnuplot, Rivet or Pyplot),
0541   // optionally with statistical errors.
0542   void table(ostream& os = cout, bool printOverUnder = false,
0543     bool xMidBin = true, bool printError = false) const ;
0544   void table(string fileName, bool printOverUnder = false,
0545     bool xMidBin = true, bool printError = false) const {
0546     ofstream fileStream(fileName.c_str());
0547     table(fileStream, printOverUnder, xMidBin, printError);}
0548   void yodaTable(ostream& os = cout, string path = "hist",
0549     double scaledBy = 1.0, vector<int> maskedBins = {}) const;
0550   void yodaTable(string fileName, string path, double scaledBy = 1.0,
0551     vector<int> maskedBins = {}) const {
0552     ofstream fileStream(fileName.c_str());
0553     yodaTable(fileStream, path, scaledBy, maskedBins);}
0554   void rivetTable(ostream& os = cout, bool printError = true) const;
0555   void rivetTable(string fileName, bool printError = true) const {
0556     ofstream fileStream(fileName.c_str());
0557     rivetTable(fileStream, printError);}
0558   void pyplotTable(ostream& os = cout, bool isHist = true,
0559     bool printError = false) const;
0560   void pyplotTable(string fileName, bool isHist = true,
0561     bool printError = false) const {
0562     ofstream fileStream(fileName.c_str());
0563     pyplotTable(fileStream, isHist, printError);}
0564 
0565   // Fill contents of a two-column (x,y) table, e.g. written by table() above.
0566   void fillTable(istream& is = cin);
0567   void fillTable(string fileName) { ifstream streamName(fileName.c_str());
0568     fillTable(streamName);}
0569 
0570   // Print a table out of two histograms with same x axis (no errors printed).
0571   friend void table(const Hist& h1, const Hist& h2, ostream& os,
0572     bool printOverUnder, bool xMidBin) ;
0573   friend void table(const Hist& h1, const Hist& h2, string fileName,
0574     bool printOverUnder, bool xMidBin) ;
0575 
0576   // Return title and size of histogram. Also if logarithmic x scale.
0577   string getTitle() const {return titleSave;}
0578   int    getBinNumber() const {return nBin;}
0579   int    getNonFinite() const {return nNonFinite;}
0580   bool   getLinX() const {return linX;}
0581 
0582   // Return min and max in x and y directions.
0583   double getXMin() const {return xMin;}
0584   double getXMax() const {return xMax;}
0585   double getYMin() const { if (nBin == 0) return 0.;
0586     double yMin = res[0];
0587     for (int ix = 1; ix < nBin; ++ix)
0588       if (res[ix] < yMin ) yMin = res[ix];
0589     return yMin;}
0590   double getYMax() const { if (nBin == 0) return 0.;
0591     double yMax = res[0];
0592     for (int ix = 1; ix < nBin; ++ix)
0593       if (res[ix] > yMax ) yMax = res[ix];
0594     return yMax;}
0595   double getYAbsMin() const { double yAbsMin = 1e20; double yAbs;
0596     for (int ix = 0; ix < nBin; ++ix) { yAbs = abs(res[ix]);
0597       if (yAbs > 1e-20 && yAbs < yAbsMin) yAbsMin = yAbs; }
0598     return yAbsMin;}
0599 
0600   // Return <X> and error on <X>, unbinned from saved weight sums (default)
0601   // or directly from the histogram bins (unbinned = false). In the latter
0602   // case, the error estimate includes the difference between the binned and
0603   // unbinned value summed in quadrature with the statistical error, as a
0604   // measure of bin granularity error.
0605   double getXMean(bool unbinned=true) const;
0606   double getXMeanErr(bool unbinned=true) const;
0607 
0608   // Return Median in X and its statistical error, ignoring underflow and
0609   // overflow (default) or including them (includeOverUnder = true). By
0610   // default, error includes granularity estimate obtained by comparing binned
0611   // vs unbinned mean value, but this can be switched off (unbinned = false).
0612   double getXPercentile(double n, bool includeOverUnder = false) const;
0613   double getXMedian(bool includeOverUnder=false) const {
0614     return getXPercentile(50.0, includeOverUnder);}
0615   double getXMedianErr(bool unbinned=true) const;
0616 
0617   // Return average <Y> value.
0618   double getYMean() const { return inside / nFill; }
0619 
0620   // Return RMS and equivalent n'th roots of n'th moments about the mean,
0621   // and their error estimates. Up to n = 6, both unbinned and binned moments
0622   // can be calculated. For n >= 7, and for all error estimates, only
0623   // binned values are available. Note that (unlike ROOT), the error estimates
0624   // do not assume normal distributions.
0625   // RMN(2) = RMS is the standard root-mean-square deviation from the mean.
0626   // RMN(3) is the cube root of the mean-cube deviation,
0627   //         cbrt(<(x - <x>)^3>). It is sensitive to single-sided tails,
0628   //         as are characteristic of many particle-physics distributions.
0629   // RMN(4) adds sensitivity to double-sided long tails (eg BW vs
0630   //         Gaussian), and further sensitivity to long single-sided ones.
0631   // Etc.
0632   double getXRMN(int n=2, bool unbinned=true) const;
0633   double getXRMS(bool unbinned=true) const {return getXRMN(2, unbinned);}
0634 
0635   double getXRMNErr(int n=2, bool unbinned=true) const;
0636   double getXRMSErr(bool unbinned=true) const {
0637     return getXRMNErr(2, unbinned);}
0638 
0639   // Return content of specific bin: 0 gives underflow and nBin+1 overflow.
0640   double getBinContent(int iBin) const;
0641 
0642   // Return the statistical uncertainty of the bin.
0643   double getBinError(int iBin) const;
0644 
0645   // Return the squared statistical uncertainty of the bin.
0646   double getBinError2(int iBin) const;
0647 
0648   // Return the lower edge of the bin.
0649   double getBinEdge(int iBin) const;
0650 
0651   // Return the width of the bin.
0652   double getBinWidth(int iBin=1) const;
0653 
0654   // Return the center of the bin.
0655   double getBinCenter(int iBin) const;
0656 
0657   // Return the contents for all bins.
0658   vector<double> getBinContents() const;
0659 
0660   // Return the statitistical uncertainty for all bins.
0661   vector<double> getBinErrors() const;
0662 
0663   // Return the squared statitistical uncertainty for all bins.
0664   vector<double> getBinError2s() const;
0665 
0666   // Return the lower edges for all bins.
0667   vector<double> getBinEdges() const;
0668 
0669   // Return the widths for all bins.
0670   vector<double> getBinWidths() const;
0671 
0672   // Return the center for all bins.
0673   vector<double> getBinCenters() const;
0674 
0675   // Return total number of entries.
0676   int getEntries(bool alsoNonFinite = true) const {
0677     return alsoNonFinite ? nNonFinite + nFill : nFill; }
0678 
0679   // Return total sum of weights.
0680   double getWeightSum(bool alsoOverUnder = true) const {
0681     return alsoOverUnder ? inside + over + under : inside; }
0682 
0683   // Return total effective entries (for weighted histograms = number
0684   // of equivalent unweighted events for same statistical power).
0685   double getNEffective() const {
0686     double sumw2 = 0.;
0687     for (int ix = 0; ix < nBin; ++ix) sumw2 += res2[ix];
0688     if (sumw2 <= Hist::TINY) return 0.;
0689     else return pow2(sumxNw[0]) / sumw2;
0690   }
0691 
0692   // Check whether another histogram has same size and limits.
0693   bool sameSize(const Hist& h) const ;
0694 
0695   // Take an arbitrary function of bin contents.
0696   void takeFunc(function<double(double)> func);
0697 
0698   // Take logarithm (base 10 or e) of bin contents.
0699   void takeLog(bool tenLog = true);
0700 
0701   // Take square root of bin contents.
0702   void takeSqrt();
0703 
0704   // Normalize sum of bin contents to value, with or without overflow bins.
0705   void normalize(double f = 1, bool overflow = true) ;
0706 
0707   // Normalize sum of bin areas to value, with or without overflow bins.
0708   void normalizeIntegral(double f = 1, bool overflow = true);
0709 
0710   // Scale each bin content by 1 / (wtSum * bin width).
0711   void normalizeSpectrum(double wtSum);
0712 
0713   // Operator overloading with member functions
0714   Hist& operator+=(const Hist& h) ;
0715   Hist& operator-=(const Hist& h) ;
0716   Hist& operator*=(const Hist& h) ;
0717   Hist& operator/=(const Hist& h) ;
0718   Hist& operator+=(double f) ;
0719   Hist& operator-=(double f) ;
0720   Hist& operator*=(double f) ;
0721   Hist& operator/=(double f) ;
0722   Hist operator+(double f) const;
0723   Hist operator+(const Hist& h2) const;
0724   Hist operator-(double f) const;
0725   Hist operator-(const Hist& h2) const;
0726   Hist operator*(double f) const;
0727   Hist operator*(const Hist& h2) const;
0728   Hist operator/(double f) const;
0729   Hist operator/(const Hist& h2) const;
0730 
0731   // Operator overloading with friends
0732   friend Hist operator+(double f, const Hist& h1);
0733   friend Hist operator-(double f, const Hist& h1);
0734   friend Hist operator*(double f, const Hist& h1);
0735   friend Hist operator/(double f, const Hist& h1);
0736 
0737 private:
0738 
0739   // Constants: could only be changed in the code itself.
0740   static const int    NBINMAX, NCOLMAX, NLINES;
0741   static const double TOLERANCE, TINY, LARGE, SMALLFRAC, DYAC[];
0742   static const char   NUMBER[];
0743 
0744   // Properties and contents of a histogram.
0745   string titleSave;
0746   int    nBin, nFill, nNonFinite;
0747   double xMin, xMax;
0748   bool   linX, doStats;
0749   double dx, under, inside, over;
0750   vector<double> res, res2;
0751 
0752   // Sum x^N w, for different powers N, for calculation of unbinned moments.
0753   static constexpr int nMoments = 7;
0754   double sumxNw[nMoments];
0755 
0756 };
0757 
0758 //--------------------------------------------------------------------------
0759 
0760 // Namespace function declarations; friends of Hist class.
0761 
0762 // Print a histogram with overloaded << operator.
0763 ostream& operator<<(ostream& os, const Hist& h) ;
0764 
0765 // Print a table out of two histograms with same x axis.
0766 void table(const Hist& h1, const Hist& h2, ostream& os = cout,
0767   bool printOverUnder = false, bool xMidBin = true) ;
0768 void table(const Hist& h1, const Hist& h2, string fileName,
0769   bool printOverUnder = false, bool xMidBin = true) ;
0770 
0771 // Operator overloading with friends
0772 Hist operator+(double f, const Hist& h1);
0773 Hist operator-(double f, const Hist& h1);
0774 Hist operator*(double f, const Hist& h1);
0775 Hist operator/(double f, const Hist& h1);
0776 
0777 //==========================================================================
0778 
0779 // HistPlot class.
0780 // Writes a Python program that can generate PDF plots from Hist histograms.
0781 
0782 class HistPlot {
0783 
0784 public:
0785 
0786   // Constructor requires name of Python program (and adds .py).
0787   HistPlot(string pythonName, bool useLegacyIn = false)
0788     : nFrame(), nTable(), useLegacy(useLegacyIn) {
0789     toPython.open((pythonName + ".py").c_str());
0790     toPython << "from matplotlib import pyplot as plt" << endl
0791              << "from matplotlib.backends.backend_pdf import PdfPages" << endl;
0792     nPDF = 0; }
0793 
0794   // Destructor should do final close.
0795   ~HistPlot() { toPython << "pp.close()" << endl; }
0796 
0797   // New plot frame, with title, x and y labels, x and y sizes.
0798   void frame( string frameIn, string titleIn = "", string xLabIn = "",
0799     string yLabIn = "", double xSizeIn = 8., double ySizeIn = 6.) {
0800     framePrevious = frameName; frameName = frameIn; title = titleIn;
0801     xLabel = xLabIn; yLabel = yLabIn; xSize = xSizeIn; ySize = ySizeIn;
0802     histos.clear(); styles.clear(); legends.clear(); files.clear();
0803     fileStyles.clear(); fileLegends.clear(); filexyerr.clear();}
0804 
0805   // Add a histogram to the current plot, with optional style and legend.
0806   void add( const Hist& histIn, string styleIn = "h",
0807     string legendIn = "void") {
0808     if (histIn.getBinNumber() == 0) {
0809       cout << " Error: histogram is not booked" << endl;
0810       return;
0811     }
0812     histos.push_back(histIn);
0813     styles.push_back(styleIn); legends.push_back(legendIn); }
0814 
0815   // Add a file of (x, y) values not from a histogram, e.g. data points.
0816   void addFile( string fileIn, string styleIn = "o",
0817     string legendIn = "void", string xyerrIn="") { files.push_back(fileIn);
0818     fileStyles.push_back(styleIn); fileLegends.push_back(legendIn);
0819     filexyerr.push_back(xyerrIn);}
0820 
0821   // Plot a frame given the information from the new and add calls.
0822   void plot( bool logY = false, bool logX = false, bool userBorders = false);
0823   void plot( double xMinUserIn, double xMaxUserIn,  double yMinUserIn,
0824      double yMaxUserIn, bool logY = false, bool logX = false) {
0825      xMinUser = xMinUserIn; xMaxUser = xMaxUserIn; yMinUser = yMinUserIn;
0826      yMaxUser = yMaxUserIn; plot( logY, logX, true);}
0827 
0828   //  Omnibus single call when only one histogram in the frame.
0829   void plotFrame( string frameIn, const Hist& histIn, string titleIn = "",
0830     string xLabIn = "", string yLabIn = "", string styleIn = "h",
0831     string legendIn = "void",  bool logY = false) {
0832     frame( frameIn, titleIn, xLabIn, yLabIn);
0833     add( histIn, styleIn, legendIn); plot( logY); }
0834 
0835 private:
0836 
0837   // Initialization code.
0838   void init( string pythonName);
0839 
0840   // Stored quantities.
0841   ofstream toPython;
0842   int      nPDF, nFrame, nTable;
0843   double   xSize, ySize, xMinUser, xMaxUser, yMinUser, yMaxUser;
0844   string   frameName, framePrevious, title, xLabel, yLabel, fileName, tmpFig;
0845   vector<Hist> histos;
0846   vector<string> styles, legends, files, fileStyles, fileLegends, filexyerr;
0847 
0848   // If true, use old linthreshy matplotlib parameter (removed in 3.5.0)
0849   bool useLegacy;
0850 
0851 };
0852 
0853 //==========================================================================
0854 
0855 // Methods used for debugging random number sequences.
0856 
0857 #ifdef RNGDEBUG
0858 #define flat() flatDebug(__METHOD_NAME__, __FILE__, __LINE__)
0859 #define xexp() xexpDebug(__METHOD_NAME__, __FILE__, __LINE__)
0860 #define gauss() gaussDebug(__METHOD_NAME__, __FILE__, __LINE__)
0861 #define gamma(...) gammaDebug(__METHOD_NAME__, __FILE__, __LINE__, __VA_ARGS__)
0862 #define phaseSpace2(...) phaseSpace2Debug(__METHOD_NAME__, __FILE__, __LINE__,\
0863     __VA_ARGS__)
0864 #endif
0865 
0866 //==========================================================================
0867 
0868 // Randomly shuffle a vector, standard Fisher-Yates algorithm.
0869 // This must be defined after possible RNG debugging.
0870 
0871 template<typename T> void Rndm::shuffle(vector<T>& vec) {
0872   for (int i = vec.size() - 1; i > 0; --i)
0873     swap(vec[i], vec[floor(flat() * (i + 1))]);
0874 }
0875 
0876 //==========================================================================
0877 
0878 } // end namespace Pythia8
0879 
0880 #endif // Pythia8_Basics_H