Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:18

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