rivet is hosted by Hepforge, IPPP Durham
Vector4.hh
Go to the documentation of this file.
00001 #ifndef RIVET_MATH_VECTOR4
00002 #define RIVET_MATH_VECTOR4
00003 
00004 #include "Rivet/Math/MathHeader.hh"
00005 #include "Rivet/Math/MathUtils.hh"
00006 #include "Rivet/Math/VectorN.hh"
00007 #include "Rivet/Math/Vector3.hh"
00008 
00009 namespace Rivet {
00010 
00011 
00012   class FourVector;
00013   class FourMomentum;
00014   class LorentzTransform;
00015   typedef FourVector Vector4;
00016   FourVector transform(const LorentzTransform& lt, const FourVector& v4);
00017 
00018 
00019   /// @brief Specialisation of VectorN to a general (non-momentum) Lorentz 4-vector.
00020   ///
00021   /// @todo Add composite set/mk methods from different coord systems
00022   class FourVector : public Vector<4> {
00023     friend FourVector multiply(const double a, const FourVector& v);
00024     friend FourVector multiply(const FourVector& v, const double a);
00025     friend FourVector add(const FourVector& a, const FourVector& b);
00026     friend FourVector transform(const LorentzTransform& lt, const FourVector& v4);
00027 
00028   public:
00029 
00030     FourVector() : Vector<4>() { }
00031 
00032     template<typename V4>
00033     FourVector(const V4& other) {
00034       this->setT(other.t());
00035       this->setX(other.x());
00036       this->setY(other.y());
00037       this->setZ(other.z());
00038     }
00039 
00040     FourVector(const Vector<4>& other)
00041       : Vector<4>(other) { }
00042 
00043     FourVector(const double t, const double x, const double y, const double z) {
00044       this->setT(t);
00045       this->setX(x);
00046       this->setY(y);
00047       this->setZ(z);
00048     }
00049 
00050     virtual ~FourVector() { }
00051 
00052   public:
00053 
00054     double t() const { return get(0); }
00055     double t2() const { return sqr(t()); }
00056     FourVector& setT(const double t) { set(0, t); return *this; }
00057 
00058     double x() const { return get(1); }
00059     double x2() const { return sqr(x()); }
00060     FourVector& setX(const double x) { set(1, x); return *this; }
00061 
00062     double y() const { return get(2); }
00063     double y2() const { return sqr(y()); }
00064     FourVector& setY(const double y) { set(2, y); return *this; }
00065 
00066     double z() const { return get(3); }
00067     double z2() const { return sqr(z()); }
00068     FourVector& setZ(const double z) { set(3, z); return *this; }
00069 
00070     double invariant() const {
00071       // Done this way for numerical precision
00072       return (t() + z())*(t() - z()) - x()*x() - y()*y();
00073     }
00074 
00075     bool isNull() const {
00076       return Rivet::isZero(invariant());
00077     }
00078 
00079     /// Angle between this vector and another
00080     double angle(const FourVector& v) const {
00081       return vector3().angle( v.vector3() );
00082     }
00083     /// Angle between this vector and another (3-vector)
00084     double angle(const Vector3& v3) const {
00085       return vector3().angle(v3);
00086     }
00087 
00088     /// @brief Square of the projection of the 3-vector on to the \f$ x-y \f$ plane
00089     /// This is a more efficient function than @c polarRadius, as it avoids the square root.
00090     /// Use it if you only need the squared value, or e.g. an ordering by magnitude.
00091     double polarRadius2() const {
00092       return vector3().polarRadius2();
00093     }
00094     /// Synonym for polarRadius2
00095     double perp2() const {
00096       return vector3().perp2();
00097     }
00098     /// Synonym for polarRadius2
00099     double rho2() const {
00100       return vector3().rho2();
00101     }
00102 
00103     /// Projection of 3-vector on to the \f$ x-y \f$ plane
00104     double polarRadius() const {
00105       return vector3().polarRadius();
00106     }
00107     /// Synonym for polarRadius
00108     double perp() const {
00109       return vector3().perp();
00110     }
00111     /// Synonym for polarRadius
00112     double rho() const {
00113       return vector3().rho();
00114     }
00115 
00116     /// Angle subtended by the 3-vector's projection in x-y and the x-axis.
00117     double azimuthalAngle(const PhiMapping mapping=ZERO_2PI) const {
00118       return vector3().azimuthalAngle(mapping);
00119     }
00120     /// Synonym for azimuthalAngle.
00121     double phi(const PhiMapping mapping=ZERO_2PI) const {
00122       return vector3().phi(mapping);
00123     }
00124 
00125     /// Angle subtended by the 3-vector and the z-axis.
00126     double polarAngle() const {
00127       return vector3().polarAngle();
00128     }
00129     /// Synonym for polarAngle.
00130     double theta() const {
00131       return vector3().theta();
00132     }
00133 
00134     /// Pseudorapidity (defined purely by the 3-vector components)
00135     double pseudorapidity() const {
00136       return vector3().pseudorapidity();
00137     }
00138     /// Synonym for pseudorapidity.
00139     double eta() const {
00140       return vector3().eta();
00141     }
00142 
00143     /// Get the \f$ |\eta| \f$ directly.
00144     double abspseudorapidity() const { return fabs(eta()); }
00145     /// Get the \f$ |\eta| \f$ directly (alias).
00146     double abseta() const { return fabs(eta()); }
00147 
00148     /// Get the spatial part of the 4-vector as a 3-vector.
00149     Vector3 vector3() const {
00150       return Vector3(get(1), get(2), get(3));
00151     }
00152 
00153 
00154   public:
00155 
00156     /// Contract two 4-vectors, with metric signature (+ - - -).
00157     double contract(const FourVector& v) const {
00158       const double result = t()*v.t() - x()*v.x() - y()*v.y() - z()*v.z();
00159       return result;
00160     }
00161 
00162     /// Contract two 4-vectors, with metric signature (+ - - -).
00163     double dot(const FourVector& v) const {
00164       return contract(v);
00165     }
00166 
00167     /// Contract two 4-vectors, with metric signature (+ - - -).
00168     double operator*(const FourVector& v) const {
00169       return contract(v);
00170     }
00171 
00172     /// Multiply by a scalar.
00173     FourVector& operator*=(double a) {
00174       _vec = multiply(a, *this)._vec;
00175       return *this;
00176     }
00177 
00178     /// Divide by a scalar.
00179     FourVector& operator/=(double a) {
00180       _vec = multiply(1.0/a, *this)._vec;
00181       return *this;
00182     }
00183 
00184     /// Add to this 4-vector.
00185     FourVector& operator+=(const FourVector& v) {
00186       _vec = add(*this, v)._vec;
00187       return *this;
00188     }
00189 
00190     /// Subtract from this 4-vector. NB time as well as space components are subtracted.
00191     FourVector& operator-=(const FourVector& v) {
00192       _vec = add(*this, -v)._vec;
00193       return *this;
00194     }
00195 
00196     /// Multiply all components (space and time) by -1.
00197     FourVector operator-() const {
00198       FourVector result;
00199       result._vec = -_vec;
00200       return result;
00201     }
00202 
00203     /// Multiply space components only by -1.
00204     FourVector reverse() const {
00205       FourVector result = -*this;
00206       result.setT(-result.t());
00207       return result;
00208     }
00209 
00210   };
00211 
00212 
00213   /// Contract two 4-vectors, with metric signature (+ - - -).
00214   inline double contract(const FourVector& a, const FourVector& b) {
00215     return a.contract(b);
00216   }
00217 
00218   /// Contract two 4-vectors, with metric signature (+ - - -).
00219   inline double dot(const FourVector& a, const FourVector& b) {
00220     return contract(a, b);
00221   }
00222 
00223   inline FourVector multiply(const double a, const FourVector& v) {
00224     FourVector result;
00225     result._vec = a * v._vec;
00226     return result;
00227   }
00228 
00229   inline FourVector multiply(const FourVector& v, const double a) {
00230     return multiply(a, v);
00231   }
00232 
00233   inline FourVector operator*(const double a, const FourVector& v) {
00234     return multiply(a, v);
00235   }
00236 
00237   inline FourVector operator*(const FourVector& v, const double a) {
00238     return multiply(a, v);
00239   }
00240 
00241   inline FourVector operator/(const FourVector& v, const double a) {
00242     return multiply(1.0/a, v);
00243   }
00244 
00245   inline FourVector add(const FourVector& a, const FourVector& b) {
00246     FourVector result;
00247     result._vec = a._vec + b._vec;
00248     return result;
00249   }
00250 
00251   inline FourVector operator+(const FourVector& a, const FourVector& b) {
00252     return add(a, b);
00253   }
00254 
00255   inline FourVector operator-(const FourVector& a, const FourVector& b) {
00256     return add(a, -b);
00257   }
00258 
00259   /// Calculate the Lorentz self-invariant of a 4-vector.
00260   /// \f$ v_\mu v^\mu = g_{\mu\nu} x^\mu x^\nu \f$.
00261   inline double invariant(const FourVector& lv) {
00262     return lv.invariant();
00263   }
00264 
00265   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00266   inline double angle(const FourVector& a, const FourVector& b) {
00267     return a.angle(b);
00268   }
00269 
00270   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00271   inline double angle(const Vector3& a, const FourVector& b) {
00272     return angle( a, b.vector3() );
00273   }
00274 
00275   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00276   inline double angle(const FourVector& a, const Vector3& b) {
00277     return a.angle(b);
00278   }
00279 
00280 
00281   ////////////////////////////////////////////////
00282 
00283 
00284   /// Specialized version of the FourVector with momentum/energy functionality.
00285   class FourMomentum : public FourVector {
00286     friend FourMomentum multiply(const double a, const FourMomentum& v);
00287     friend FourMomentum multiply(const FourMomentum& v, const double a);
00288     friend FourMomentum add(const FourMomentum& a, const FourMomentum& b);
00289     friend FourMomentum transform(const LorentzTransform& lt, const FourMomentum& v4);
00290 
00291   public:
00292     FourMomentum() { }
00293 
00294     template<typename V4>
00295     FourMomentum(const V4& other) {
00296       this->setE(other.t());
00297       this->setPx(other.x());
00298       this->setPy(other.y());
00299       this->setPz(other.z());
00300     }
00301 
00302     FourMomentum(const Vector<4>& other)
00303       : FourVector(other) { }
00304 
00305     FourMomentum(const double E, const double px, const double py, const double pz) {
00306       this->setE(E);
00307       this->setPx(px);
00308       this->setPy(py);
00309       this->setPz(pz);
00310     }
00311 
00312     ~FourMomentum() {}
00313 
00314   public:
00315 
00316 
00317     /// @name Coordinate setters
00318     //@{
00319 
00320     /// Set energy \f$ E \f$ (time component of momentum).
00321     FourMomentum& setE(double E) {
00322       setT(E);
00323       return *this;
00324     }
00325 
00326     /// Set x-component of momentum \f$ p_x \f$.
00327     FourMomentum& setPx(double px) {
00328       setX(px);
00329       return *this;
00330     }
00331 
00332     /// Set y-component of momentum \f$ p_y \f$.
00333     FourMomentum& setPy(double py) {
00334       setY(py);
00335       return *this;
00336     }
00337 
00338     /// Set z-component of momentum \f$ p_z \f$.
00339     FourMomentum& setPz(double pz) {
00340       setZ(pz);
00341       return *this;
00342     }
00343 
00344 
00345     /// Set the p coordinates and energy simultaneously
00346     FourMomentum& setPE(double px, double py, double pz, double E) {
00347       if (E < 0)
00348         throw std::invalid_argument("Negative energy given as argument: " + to_str(E));
00349       setPx(px); setPy(py); setPz(pz); setE(E);
00350       return *this;
00351     }
00352     /// Alias for setPE
00353     FourMomentum& setXYZE(double px, double py, double pz, double E) {
00354       return setPE(px, py, pz, E);
00355     }
00356     // /// Near-alias with switched arg order
00357     // FourMomentum& setEP(double E, double px, double py, double pz) {
00358     //   return setPE(px, py, pz, E);
00359     // }
00360     // /// Alias for setEP
00361     // FourMomentum& setEXYZ(double E, double px, double py, double pz) {
00362     //   return setEP(E, px, py, pz);
00363     // }
00364 
00365 
00366     /// Set the p coordinates and mass simultaneously
00367     FourMomentum& setPM(double px, double py, double pz, double mass) {
00368       if (mass < 0)
00369         throw std::invalid_argument("Negative mass given as argument: " + to_str(mass));
00370       const double E = sqrt( sqr(mass) + sqr(px) + sqr(py) + sqr(pz) );
00371       // setPx(px); setPy(py); setPz(pz); setE(E);
00372       return setPE(px, py, pz, E);
00373     }
00374     /// Alias for setPM
00375     FourMomentum& setXYZM(double px, double py, double pz, double mass) {
00376       return setPM(px, py, pz, mass);
00377     }
00378 
00379 
00380     /// Set the vector state from (eta,phi,energy) coordinates and the mass
00381     ///
00382     /// eta = -ln(tan(theta/2))
00383     /// -> theta = 2 atan(exp(-eta))
00384     FourMomentum& setEtaPhiME(double eta, double phi, double mass, double E) {
00385       if (mass < 0)
00386         throw std::invalid_argument("Negative mass given as argument");
00387       if (E < 0)
00388         throw std::invalid_argument("Negative energy given as argument");
00389       const double theta = 2 * atan(exp(-eta));
00390       if (theta < 0 || theta > M_PI)
00391         throw std::domain_error("Polar angle outside 0..pi in calculation");
00392       setThetaPhiME(theta, phi, mass, E);
00393       return *this;
00394     }
00395 
00396     /// Set the vector state from (eta,phi,pT) coordinates and the mass
00397     ///
00398     /// eta = -ln(tan(theta/2))
00399     /// -> theta = 2 atan(exp(-eta))
00400     FourMomentum& setEtaPhiMPt(double eta, double phi, double mass, double pt) {
00401       if (mass < 0)
00402         throw std::invalid_argument("Negative mass given as argument");
00403       if (pt < 0)
00404         throw std::invalid_argument("Negative transverse momentum given as argument");
00405       const double theta = 2 * atan(exp(-eta));
00406       if (theta < 0 || theta > M_PI)
00407         throw std::domain_error("Polar angle outside 0..pi in calculation");
00408       const double p = pt / sin(theta);
00409       const double E = sqrt( sqr(p) + sqr(mass) );
00410       setThetaPhiME(theta, phi, mass, E);
00411       return *this;
00412     }
00413 
00414     /// Set the vector state from (y,phi,energy) coordinates and the mass
00415     ///
00416     /// y = 0.5 * ln((E+pz)/(E-pz))
00417     /// -> (E^2 - pz^2) exp(2y) = (E+pz)^2
00418     ///  & (E^2 - pz^2) exp(-2y) = (E-pz)^2
00419     /// -> E = sqrt(pt^2 + m^2) cosh(y)
00420     /// -> pz = sqrt(pt^2 + m^2) sinh(y)
00421     /// -> sqrt(pt^2 + m^2) = E / cosh(y)
00422     FourMomentum& setRapPhiME(double y, double phi, double mass, double E) {
00423       if (mass < 0)
00424         throw std::invalid_argument("Negative mass given as argument");
00425       if (E < 0)
00426         throw std::invalid_argument("Negative energy given as argument");
00427       const double sqrt_pt2_m2 = E / cosh(y);
00428       const double pt = sqrt( sqr(sqrt_pt2_m2) - sqr(mass) );
00429       if (pt < 0)
00430         throw std::domain_error("Negative transverse momentum in calculation");
00431       const double pz = sqrt_pt2_m2 * sinh(y);
00432       const double px = pt * cos(phi);
00433       const double py = pt * sin(phi);
00434       setPE(px, py, pz, E);
00435       return *this;
00436     }
00437 
00438     /// Set the vector state from (y,phi,pT) coordinates and the mass
00439     ///
00440     /// y = 0.5 * ln((E+pz)/(E-pz))
00441     /// -> E = sqrt(pt^2 + m^2) cosh(y)  [see above]
00442     FourMomentum& setRapPhiMPt(double y, double phi, double mass, double pt) {
00443       if (mass < 0)
00444         throw std::invalid_argument("Negative mass given as argument");
00445       if (pt < 0)
00446         throw std::invalid_argument("Negative transverse mass given as argument");
00447       const double E = sqrt( sqr(pt) + sqr(mass) ) * cosh(y);
00448       if (E < 0)
00449         throw std::domain_error("Negative energy in calculation");
00450       setRapPhiME(y, phi, mass, E);
00451       return *this;
00452     }
00453 
00454     /// Set the vector state from (theta,phi,energy) coordinates and the mass
00455     ///
00456     /// p = sqrt(E^2 - mass^2)
00457     /// pz = p cos(theta)
00458     /// pt = p sin(theta)
00459     FourMomentum& setThetaPhiME(double theta, double phi, double mass, double E) {
00460       if (theta < 0 || theta > M_PI)
00461         throw std::invalid_argument("Polar angle outside 0..pi given as argument");
00462       if (mass < 0)
00463         throw std::invalid_argument("Negative mass given as argument");
00464       if (E < 0)
00465         throw std::invalid_argument("Negative energy given as argument");
00466       const double p = sqrt( sqr(E) - sqr(mass) );
00467       const double pz = p * cos(theta);
00468       const double pt = p * sin(theta);
00469       if (pt < 0)
00470         throw std::invalid_argument("Negative transverse momentum in calculation");
00471       const double px = pt * cos(phi);
00472       const double py = pt * sin(phi);
00473       setPE(px, py, pz, E);
00474       return *this;
00475     }
00476 
00477     /// Set the vector state from (theta,phi,pT) coordinates and the mass
00478     ///
00479     /// p = pt / sin(theta)
00480     /// pz = p cos(theta)
00481     /// E = sqrt(p^2 + mass^2)
00482     FourMomentum& setThetaPhiMPt(double theta, double phi, double mass, double pt) {
00483       if (theta < 0 || theta > M_PI)
00484         throw std::invalid_argument("Polar angle outside 0..pi given as argument");
00485       if (mass < 0)
00486         throw std::invalid_argument("Negative mass given as argument");
00487       if (pt < 0)
00488         throw std::invalid_argument("Negative transverse momentum given as argument");
00489       const double p = pt / sin(theta);
00490       const double px = pt * cos(phi);
00491       const double py = pt * sin(phi);
00492       const double pz = p * cos(theta);
00493       const double E = sqrt( sqr(p) + sqr(mass) );
00494       setPE(px, py, pz, E);
00495       return *this;
00496     }
00497 
00498     /// Set the vector state from (pT,phi,energy) coordinates and the mass
00499     ///
00500     /// pz = sqrt(E^2 - mass^2 - pt^2)
00501     FourMomentum& setPtPhiME(double pt, double phi, double mass, double E) {
00502       if (pt < 0)
00503         throw std::invalid_argument("Negative transverse momentum given as argument");
00504       if (mass < 0)
00505         throw std::invalid_argument("Negative mass given as argument");
00506       if (E < 0)
00507         throw std::invalid_argument("Negative energy given as argument");
00508       const double px = pt * cos(phi);
00509       const double py = pt * sin(phi);
00510       const double pz = sqrt(sqr(E) - sqr(mass) - sqr(pt));
00511       setPE(px, py, pz, E);
00512       return *this;
00513     }
00514 
00515     //@}
00516 
00517 
00518     /// @name Accessors
00519     //@{
00520 
00521     /// Get energy \f$ E \f$ (time component of momentum).
00522     double E() const { return t(); }
00523     /// Get energy-squared \f$ E^2 \f$.
00524     double E2() const { return t2(); }
00525 
00526     /// Get x-component of momentum \f$ p_x \f$.
00527     double px() const { return x(); }
00528     /// Get x-squared \f$ p_x^2 \f$.
00529     double px2() const { return x2(); }
00530 
00531     /// Get y-component of momentum \f$ p_y \f$.
00532     double py() const { return y(); }
00533     /// Get y-squared \f$ p_y^2 \f$.
00534     double py2() const { return y2(); }
00535 
00536     /// Get z-component of momentum \f$ p_z \f$.
00537     double pz() const { return z(); }
00538     /// Get z-squared \f$ p_z^2 \f$.
00539     double pz2() const { return z2(); }
00540 
00541 
00542     /// @brief Get the mass \f$ m = \sqrt{E^2 - p^2} \f$ (the Lorentz self-invariant).
00543     ///
00544     /// For spacelike momenta, the mass will be -sqrt(|mass2|).
00545     double mass() const {
00546       // assert(Rivet::isZero(mass2()) || mass2() > 0);
00547       // if (Rivet::isZero(mass2())) {
00548       //   return 0.0;
00549       // } else {
00550       //   return sqrt(mass2());
00551       // }
00552       return sign(mass2()) * sqrt(fabs(mass2()));
00553     }
00554 
00555     /// Get the squared mass \f$ m^2 = E^2 - p^2 \f$ (the Lorentz self-invariant).
00556     double mass2() const {
00557       return invariant();
00558     }
00559 
00560 
00561     /// Get 3-momentum part, \f$ p \f$.
00562     Vector3 p3() const { return vector3(); }
00563 
00564     /// Get the modulus of the 3-momentum
00565     double p() const {
00566       return p3().mod();
00567     }
00568 
00569     /// Get the modulus-squared of the 3-momentum
00570     double p2() const {
00571       return p3().mod2();
00572     }
00573 
00574 
00575     /// Calculate the rapidity.
00576     double rapidity() const {
00577       return 0.5 * std::log( (E() + pz()) / (E() - pz()) );
00578     }
00579     /// Alias for rapidity.
00580     double rap() const {
00581       return rapidity();
00582     }
00583 
00584     /// Absolute rapidity.
00585     double absrapidity() const {
00586       return fabs(rapidity());
00587     }
00588     /// Absolute rapidity.
00589     double absrap() const {
00590       return fabs(rap());
00591     }
00592 
00593     /// Calculate the squared transverse momentum \f$ p_T^2 \f$.
00594     double pT2() const {
00595       return vector3().polarRadius2();
00596     }
00597     /// Calculate the squared transverse momentum \f$ p_T^2 \f$.
00598     double pt2() const {
00599       return vector3().polarRadius2();
00600     }
00601 
00602     /// Calculate the transverse momentum \f$ p_T \f$.
00603     double pT() const {
00604       return sqrt(pT2());
00605     }
00606     /// Calculate the transverse momentum \f$ p_T \f$.
00607     double pt() const {
00608       return sqrt(pT2());
00609     }
00610 
00611     /// Calculate the transverse energy \f$ E_T^2 = E^2 \sin^2{\theta} \f$.
00612     double Et2() const {
00613       return Et() * Et();
00614     }
00615     /// Calculate the transverse energy \f$ E_T = E \sin{\theta} \f$.
00616     double Et() const {
00617       return E() * sin(polarAngle());
00618     }
00619 
00620     //@}
00621 
00622 
00623     /// @name Lorentz boost factors and vectors
00624     //@{
00625 
00626     /// Calculate the boost factor \f$ \gamma \f$.
00627     /// @note \f$ \gamma = E/mc^2 \f$ so we rely on the c=1 convention
00628     double gamma() const {
00629       return sqrt(E2()/mass2());
00630     }
00631 
00632     /// Calculate the boost vector \f$ \vec{\gamma} \f$.
00633     /// @note \f$ \gamma = E/mc^2 \f$ so we rely on the c=1 convention
00634     Vector3 gammaVec() const {
00635       return gamma() * p3().unit();
00636     }
00637 
00638     /// Calculate the boost factor \f$ \beta \f$.
00639     /// @note \f$ \beta = pc/E \f$ so we rely on the c=1 convention
00640     double beta() const {
00641       return p()/E();
00642     }
00643 
00644     /// Calculate the boost vector \f$ \vec{\beta} \f$.
00645     /// @note \f$ \beta = pc/E \f$ so we rely on the c=1 convention
00646     Vector3 betaVec() const {
00647       // return Vector3(px()/E(), py()/E(), pz()/E());
00648       return p3()/E();
00649     }
00650 
00651     /// @brief Deprecated alias for betaVec
00652     /// @deprecated This will be removed; use betaVec() instead
00653     Vector3 boostVector() const { return betaVec(); }
00654 
00655     //@}
00656 
00657 
00658     ////////////////////////////////////////
00659 
00660 
00661     /// @name Sorting helpers
00662     //@{
00663 
00664     /// Struct for sorting by increasing energy
00665     struct byEAscending {
00666       bool operator()(const FourMomentum& left, const FourMomentum& right) const{
00667         const double pt2left = left.E();
00668         const double pt2right = right.E();
00669         return pt2left < pt2right;
00670       }
00671 
00672       bool operator()(const FourMomentum* left, const FourMomentum* right) const{
00673         return (*this)(*left, *right);
00674       }
00675     };
00676 
00677 
00678     /// Struct for sorting by decreasing energy
00679     struct byEDescending {
00680       bool operator()(const FourMomentum& left, const FourMomentum& right) const{
00681         return byEAscending()(right, left);
00682       }
00683 
00684       bool operator()(const FourMomentum* left, const FourVector* right) const{
00685         return (*this)(*left, *right);
00686       }
00687     };
00688 
00689     //@}
00690 
00691 
00692     ////////////////////////////////////////
00693 
00694 
00695     /// @name Arithmetic operators
00696     //@{
00697 
00698     /// Multiply by a scalar
00699     FourMomentum& operator*=(double a) {
00700       _vec = multiply(a, *this)._vec;
00701       return *this;
00702     }
00703 
00704     /// Divide by a scalar
00705     FourMomentum& operator/=(double a) {
00706       _vec = multiply(1.0/a, *this)._vec;
00707       return *this;
00708     }
00709 
00710     /// Add to this 4-vector. NB time as well as space components are added.
00711     FourMomentum& operator+=(const FourMomentum& v) {
00712       _vec = add(*this, v)._vec;
00713       return *this;
00714     }
00715 
00716     /// Subtract from this 4-vector. NB time as well as space components are subtracted.
00717     FourMomentum& operator-=(const FourMomentum& v) {
00718       _vec = add(*this, -v)._vec;
00719       return *this;
00720     }
00721 
00722     /// Multiply all components (time and space) by -1.
00723     FourMomentum operator-() const {
00724       FourMomentum result;
00725       result._vec = -_vec;
00726       return result;
00727     }
00728 
00729     /// Multiply space components only by -1.
00730     FourMomentum reverse() const {
00731       FourMomentum result = -*this;
00732       result.setE(-result.E());
00733       return result;
00734     }
00735 
00736     //@}
00737 
00738 
00739     ////////////////////////////////////////
00740 
00741 
00742     /// @name Factory functions
00743     //@{
00744 
00745     /// Make a vector from (px,py,pz,E) coordinates
00746     static FourMomentum mkXYZE(double px, double py, double pz, double E) {
00747       return FourMomentum().setPE(px, py, pz, E);
00748     }
00749 
00750     /// Make a vector from (px,py,pz) coordinates and the mass
00751     static FourMomentum mkXYZM(double px, double py, double pz, double mass) {
00752       return FourMomentum().setPM(px, py, pz, mass);
00753     }
00754 
00755     /// Make a vector from (eta,phi,energy) coordinates and the mass
00756     static FourMomentum mkEtaPhiME(double eta, double phi, double mass, double E) {
00757       return FourMomentum().setEtaPhiME(eta, phi, mass, E);
00758     }
00759 
00760     /// Make a vector from (eta,phi,pT) coordinates and the mass
00761     static FourMomentum mkEtaPhiMPt(double eta, double phi, double mass, double pt) {
00762       return FourMomentum().setEtaPhiMPt(eta, phi, mass, pt);
00763     }
00764 
00765     /// Make a vector from (y,phi,energy) coordinates and the mass
00766     static FourMomentum mkRapPhiME(double y, double phi, double mass, double E) {
00767       return FourMomentum().setRapPhiME(y, phi, mass, E);
00768     }
00769 
00770     /// Make a vector from (y,phi,pT) coordinates and the mass
00771     static FourMomentum mkRapPhiMPt(double y, double phi, double mass, double pt) {
00772       return FourMomentum().setRapPhiMPt(y, phi, mass, pt);
00773     }
00774 
00775     /// Make a vector from (theta,phi,energy) coordinates and the mass
00776     static FourMomentum mkThetaPhiME(double theta, double phi, double mass, double E) {
00777       return FourMomentum().setThetaPhiME(theta, phi, mass, E);
00778     }
00779 
00780     /// Make a vector from (theta,phi,pT) coordinates and the mass
00781     static FourMomentum mkThetaPhiMPt(double theta, double phi, double mass, double pt) {
00782       return FourMomentum().setThetaPhiMPt(theta, phi, mass, pt);
00783     }
00784 
00785     /// Make a vector from (pT,phi,energy) coordinates and the mass
00786     static FourMomentum mkPtPhiME(double pt, double phi, double mass, double E) {
00787       return FourMomentum().setPtPhiME(pt, phi, mass, E);
00788     }
00789 
00790     //@}
00791 
00792 
00793   };
00794 
00795 
00796 
00797   inline FourMomentum multiply(const double a, const FourMomentum& v) {
00798     FourMomentum result;
00799     result._vec = a * v._vec;
00800     return result;
00801   }
00802 
00803   inline FourMomentum multiply(const FourMomentum& v, const double a) {
00804     return multiply(a, v);
00805   }
00806 
00807   inline FourMomentum operator*(const double a, const FourMomentum& v) {
00808     return multiply(a, v);
00809   }
00810 
00811   inline FourMomentum operator*(const FourMomentum& v, const double a) {
00812     return multiply(a, v);
00813   }
00814 
00815   inline FourMomentum operator/(const FourMomentum& v, const double a) {
00816     return multiply(1.0/a, v);
00817   }
00818 
00819   inline FourMomentum add(const FourMomentum& a, const FourMomentum& b) {
00820     FourMomentum result;
00821     result._vec = a._vec + b._vec;
00822     return result;
00823   }
00824 
00825   inline FourMomentum operator+(const FourMomentum& a, const FourMomentum& b) {
00826     return add(a, b);
00827   }
00828 
00829   inline FourMomentum operator-(const FourMomentum& a, const FourMomentum& b) {
00830     return add(a, -b);
00831   }
00832 
00833 
00834   //////////////////////////////////////////////////////
00835 
00836 
00837   /// @name \f$ \Delta R \f$ calculations from 4-vectors
00838   //@{
00839 
00840   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00841   /// There is a scheme ambiguity for momentum-type four vectors as to whether
00842   /// the pseudorapidity (a purely geometric concept) or the rapidity (a
00843   /// relativistic energy-momentum quantity) is to be used: this can be chosen
00844   /// via the optional scheme parameter. Use of this scheme option is
00845   /// discouraged in this case since @c RAPIDITY is only a valid option for
00846   /// vectors whose type is really the FourMomentum derived class.
00847   inline double deltaR(const FourVector& a, const FourVector& b,
00848                        RapScheme scheme = PSEUDORAPIDITY) {
00849     switch (scheme) {
00850     case PSEUDORAPIDITY :
00851       return deltaR(a.vector3(), b.vector3());
00852     case RAPIDITY:
00853       {
00854         const FourMomentum* ma = dynamic_cast<const FourMomentum*>(&a);
00855         const FourMomentum* mb = dynamic_cast<const FourMomentum*>(&b);
00856         if (!ma || !mb) {
00857           string err = "deltaR with scheme RAPIDITY can only be called with FourMomentum objects, not FourVectors";
00858           throw std::runtime_error(err);
00859         }
00860         return deltaR(*ma, *mb, scheme);
00861       }
00862     default:
00863       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00864     }
00865   }
00866 
00867 
00868   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00869   /// There is a scheme ambiguity for momentum-type four vectors
00870   /// as to whether the pseudorapidity (a purely geometric concept) or the
00871   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00872   /// be chosen via the optional scheme parameter.
00873   inline double deltaR(const FourVector& v,
00874                        double eta2, double phi2,
00875                        RapScheme scheme = PSEUDORAPIDITY) {
00876     switch (scheme) {
00877     case PSEUDORAPIDITY :
00878       return deltaR(v.vector3(), eta2, phi2);
00879     case RAPIDITY:
00880       {
00881         const FourMomentum* mv = dynamic_cast<const FourMomentum*>(&v);
00882         if (!mv) {
00883           string err = "deltaR with scheme RAPIDITY can only be called with FourMomentum objects, not FourVectors";
00884           throw std::runtime_error(err);
00885         }
00886         return deltaR(*mv, eta2, phi2, scheme);
00887       }
00888     default:
00889       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00890     }
00891   }
00892 
00893 
00894   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00895   /// There is a scheme ambiguity for momentum-type four vectors
00896   /// as to whether the pseudorapidity (a purely geometric concept) or the
00897   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00898   /// be chosen via the optional scheme parameter.
00899   inline double deltaR(double eta1, double phi1,
00900                        const FourVector& v,
00901                        RapScheme scheme = PSEUDORAPIDITY) {
00902     switch (scheme) {
00903     case PSEUDORAPIDITY :
00904       return deltaR(eta1, phi1, v.vector3());
00905     case RAPIDITY:
00906       {
00907         const FourMomentum* mv = dynamic_cast<const FourMomentum*>(&v);
00908         if (!mv) {
00909           string err = "deltaR with scheme RAPIDITY can only be called with FourMomentum objects, not FourVectors";
00910           throw std::runtime_error(err);
00911         }
00912         return deltaR(eta1, phi1, *mv, scheme);
00913       }
00914     default:
00915       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00916     }
00917   }
00918 
00919 
00920   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00921   /// There is a scheme ambiguity for momentum-type four vectors
00922   /// as to whether the pseudorapidity (a purely geometric concept) or the
00923   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00924   /// be chosen via the optional scheme parameter.
00925   inline double deltaR(const FourMomentum& a, const FourMomentum& b,
00926                        RapScheme scheme = PSEUDORAPIDITY) {
00927     switch (scheme) {
00928     case PSEUDORAPIDITY:
00929       return deltaR(a.vector3(), b.vector3());
00930     case RAPIDITY:
00931       return deltaR(a.rapidity(), a.azimuthalAngle(), b.rapidity(), b.azimuthalAngle());
00932     default:
00933       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00934     }
00935   }
00936 
00937   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00938   /// There is a scheme ambiguity for momentum-type four vectors
00939   /// as to whether the pseudorapidity (a purely geometric concept) or the
00940   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00941   /// be chosen via the optional scheme parameter.
00942   inline double deltaR(const FourMomentum& v,
00943                        double eta2, double phi2,
00944                        RapScheme scheme = PSEUDORAPIDITY) {
00945     switch (scheme) {
00946     case PSEUDORAPIDITY:
00947       return deltaR(v.vector3(), eta2, phi2);
00948     case RAPIDITY:
00949       return deltaR(v.rapidity(), v.azimuthalAngle(), eta2, phi2);
00950     default:
00951       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00952     }
00953   }
00954 
00955 
00956   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00957   /// There is a scheme ambiguity for momentum-type four vectors
00958   /// as to whether the pseudorapidity (a purely geometric concept) or the
00959   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00960   /// be chosen via the optional scheme parameter.
00961   inline double deltaR(double eta1, double phi1,
00962                        const FourMomentum& v,
00963                        RapScheme scheme = PSEUDORAPIDITY) {
00964     switch (scheme) {
00965     case PSEUDORAPIDITY:
00966       return deltaR(eta1, phi1, v.vector3());
00967     case RAPIDITY:
00968       return deltaR(eta1, phi1, v.rapidity(), v.azimuthalAngle());
00969     default:
00970       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00971     }
00972   }
00973 
00974   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00975   /// There is a scheme ambiguity for momentum-type four vectors
00976   /// as to whether the pseudorapidity (a purely geometric concept) or the
00977   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00978   /// be chosen via the optional scheme parameter.
00979   inline double deltaR(const FourMomentum& a, const FourVector& b,
00980                        RapScheme scheme = PSEUDORAPIDITY) {
00981     switch (scheme) {
00982     case PSEUDORAPIDITY:
00983       return deltaR(a.vector3(), b.vector3());
00984     case RAPIDITY:
00985       return deltaR(a.rapidity(), a.azimuthalAngle(), FourMomentum(b).rapidity(), b.azimuthalAngle());
00986     default:
00987       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00988     }
00989   }
00990 
00991   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00992   /// There is a scheme ambiguity for momentum-type four vectors
00993   /// as to whether the pseudorapidity (a purely geometric concept) or the
00994   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00995   /// be chosen via the optional scheme parameter.
00996   inline double deltaR(const FourVector& a, const FourMomentum& b,
00997                        RapScheme scheme = PSEUDORAPIDITY) {
00998     return deltaR(b, a, scheme);
00999   }
01000 
01001   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
01002   /// three-vector and a four-vector.
01003   inline double deltaR(const FourMomentum& a, const Vector3& b) {
01004     return deltaR(a.vector3(), b);
01005   }
01006 
01007   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
01008   /// three-vector and a four-vector.
01009   inline double deltaR(const Vector3& a, const FourMomentum& b) {
01010     return deltaR(a, b.vector3());
01011   }
01012 
01013   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
01014   /// three-vector and a four-vector.
01015   inline double deltaR(const FourVector& a, const Vector3& b) {
01016     return deltaR(a.vector3(), b);
01017   }
01018 
01019   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
01020   /// three-vector and a four-vector.
01021   inline double deltaR(const Vector3& a, const FourVector& b) {
01022     return deltaR(a, b.vector3());
01023   }
01024 
01025   //@}
01026 
01027 
01028   //////////////////////////////////////////////////////
01029 
01030 
01031   /// @name \f$ \Delta phi \f$ calculations from 4-vectors
01032   //@{
01033 
01034   /// Calculate the difference in azimuthal angle between two vectors.
01035   inline double deltaPhi(const FourMomentum& a, const FourMomentum& b) {
01036     return deltaPhi(a.vector3(), b.vector3());
01037   }
01038 
01039   /// Calculate the difference in azimuthal angle between two vectors.
01040   inline double deltaPhi(const FourMomentum& v, double phi2) {
01041     return deltaPhi(v.vector3(), phi2);
01042   }
01043 
01044   /// Calculate the difference in azimuthal angle between two vectors.
01045   inline double deltaPhi(double phi1, const FourMomentum& v) {
01046     return deltaPhi(phi1, v.vector3());
01047   }
01048 
01049   /// Calculate the difference in azimuthal angle between two vectors.
01050   inline double deltaPhi(const FourVector& a, const FourVector& b) {
01051     return deltaPhi(a.vector3(), b.vector3());
01052   }
01053 
01054   /// Calculate the difference in azimuthal angle between two vectors.
01055   inline double deltaPhi(const FourVector& v, double phi2) {
01056     return deltaPhi(v.vector3(), phi2);
01057   }
01058 
01059   /// Calculate the difference in azimuthal angle between two vectors.
01060   inline double deltaPhi(double phi1, const FourVector& v) {
01061     return deltaPhi(phi1, v.vector3());
01062   }
01063 
01064   /// Calculate the difference in azimuthal angle between two vectors.
01065   inline double deltaPhi(const FourVector& a, const FourMomentum& b) {
01066     return deltaPhi(a.vector3(), b.vector3());
01067   }
01068 
01069   /// Calculate the difference in azimuthal angle between two vectors.
01070   inline double deltaPhi(const FourMomentum& a, const FourVector& b) {
01071     return deltaPhi(a.vector3(), b.vector3());
01072   }
01073 
01074   /// Calculate the difference in azimuthal angle between two vectors.
01075   inline double deltaPhi(const FourVector& a, const Vector3& b) {
01076     return deltaPhi(a.vector3(), b);
01077   }
01078 
01079   /// Calculate the difference in azimuthal angle between two vectors.
01080   inline double deltaPhi(const Vector3& a, const FourVector& b) {
01081     return deltaPhi(a, b.vector3());
01082   }
01083 
01084   /// Calculate the difference in azimuthal angle between two vectors.
01085   inline double deltaPhi(const FourMomentum& a, const Vector3& b) {
01086     return deltaPhi(a.vector3(), b);
01087   }
01088 
01089   /// Calculate the difference in azimuthal angle between two vectors.
01090   inline double deltaPhi(const Vector3& a, const FourMomentum& b) {
01091     return deltaPhi(a, b.vector3());
01092   }
01093 
01094   //@}
01095 
01096 
01097   //////////////////////////////////////////////////////
01098 
01099 
01100   /// @name \f$ |\Delta eta| \f$ calculations from 4-vectors
01101   //@{
01102 
01103   /// Calculate the difference in pseudorapidity between two vectors.
01104   inline double deltaEta(const FourMomentum& a, const FourMomentum& b) {
01105     return deltaEta(a.vector3(), b.vector3());
01106   }
01107 
01108   /// Calculate the difference in pseudorapidity between two vectors.
01109   inline double deltaEta(const FourMomentum& v, double eta2) {
01110     return deltaEta(v.vector3(), eta2);
01111   }
01112 
01113   /// Calculate the difference in pseudorapidity between two vectors.
01114   inline double deltaEta(double eta1, const FourMomentum& v) {
01115     return deltaEta(eta1, v.vector3());
01116   }
01117 
01118   /// Calculate the difference in pseudorapidity between two vectors.
01119   inline double deltaEta(const FourVector& a, const FourVector& b) {
01120     return deltaEta(a.vector3(), b.vector3());
01121   }
01122 
01123   /// Calculate the difference in pseudorapidity between two vectors.
01124   inline double deltaEta(const FourVector& v, double eta2) {
01125     return deltaEta(v.vector3(), eta2);
01126   }
01127 
01128   /// Calculate the difference in pseudorapidity between two vectors.
01129   inline double deltaEta(double eta1, const FourVector& v) {
01130     return deltaEta(eta1, v.vector3());
01131   }
01132 
01133   /// Calculate the difference in pseudorapidity between two vectors.
01134   inline double deltaEta(const FourVector& a, const FourMomentum& b) {
01135     return deltaEta(a.vector3(), b.vector3());
01136   }
01137 
01138   /// Calculate the difference in pseudorapidity between two vectors.
01139   inline double deltaEta(const FourMomentum& a, const FourVector& b) {
01140     return deltaEta(a.vector3(), b.vector3());
01141   }
01142 
01143   /// Calculate the difference in pseudorapidity between two vectors.
01144   inline double deltaEta(const FourVector& a, const Vector3& b) {
01145     return deltaEta(a.vector3(), b);
01146   }
01147 
01148   /// Calculate the difference in pseudorapidity between two vectors.
01149   inline double deltaEta(const Vector3& a, const FourVector& b) {
01150     return deltaEta(a, b.vector3());
01151   }
01152 
01153   /// Calculate the difference in pseudorapidity between two vectors.
01154   inline double deltaEta(const FourMomentum& a, const Vector3& b) {
01155     return deltaEta(a.vector3(), b);
01156   }
01157 
01158   /// Calculate the difference in pseudorapidity between two vectors.
01159   inline double deltaEta(const Vector3& a, const FourMomentum& b) {
01160     return deltaEta(a, b.vector3());
01161   }
01162 
01163   //@}
01164 
01165 
01166   /// @name \f$ |\Delta y| \f$ calculations from 4-momentum vectors
01167   //@{
01168 
01169   /// Calculate the difference in rapidity between two 4-momentum vectors.
01170   inline double deltaRap(const FourMomentum& a, const FourMomentum& b) {
01171     return deltaRap(a.rapidity(), b.rapidity());
01172   }
01173 
01174   /// Calculate the difference in rapidity between two 4-momentum vectors.
01175   inline double deltaRap(const FourMomentum& v, double y2) {
01176     return deltaRap(v.rapidity(), y2);
01177   }
01178 
01179   /// Calculate the difference in rapidity between two 4-momentum vectors.
01180   inline double deltaRap(double y1, const FourMomentum& v) {
01181     return deltaRap(y1, v.rapidity());
01182   }
01183 
01184   //@}
01185 
01186 
01187   //////////////////////////////////////////////////////
01188 
01189 
01190   /// @name 4-vector comparison functions (for sorting)
01191   //@{
01192 
01193   /// Comparison to give a sorting by decreasing pT
01194   inline bool cmpMomByPt(const FourMomentum& a, const FourMomentum& b) {
01195     return a.pt() > b.pt();
01196   }
01197   /// Comparison to give a sorting by increasing pT
01198   inline bool cmpMomByAscPt(const FourMomentum& a, const FourMomentum& b) {
01199     return a.pt() < b.pt();
01200   }
01201 
01202   /// Comparison to give a sorting by decreasing 3-momentum magnitude |p|
01203   inline bool cmpMomByP(const FourMomentum& a, const FourMomentum& b) {
01204     return a.vector3().mod() > b.vector3().mod();
01205   }
01206   /// Comparison to give a sorting by increasing 3-momentum magnitude |p|
01207   inline bool cmpMomByAscP(const FourMomentum& a, const FourMomentum& b) {
01208     return a.vector3().mod() < b.vector3().mod();
01209   }
01210 
01211   /// Comparison to give a sorting by decreasing transverse energy
01212   inline bool cmpMomByEt(const FourMomentum& a, const FourMomentum& b) {
01213     return a.Et() > b.Et();
01214   }
01215   /// Comparison to give a sorting by increasing transverse energy
01216   inline bool cmpMomByAscEt(const FourMomentum& a, const FourMomentum& b) {
01217     return a.Et() < b.Et();
01218   }
01219 
01220   /// Comparison to give a sorting by decreasing energy
01221   inline bool cmpMomByE(const FourMomentum& a, const FourMomentum& b) {
01222     return a.E() > b.E();
01223   }
01224   /// Comparison to give a sorting by increasing energy
01225   inline bool cmpMomByAscE(const FourMomentum& a, const FourMomentum& b) {
01226     return a.E() < b.E();
01227   }
01228 
01229   /// Comparison to give a sorting by decreasing mass
01230   inline bool cmpMomByMass(const FourMomentum& a, const FourMomentum& b) {
01231     return a.mass() > b.mass();
01232   }
01233   /// Comparison to give a sorting by increasing mass
01234   inline bool cmpMomByAscMass(const FourMomentum& a, const FourMomentum& b) {
01235     return a.mass() < b.mass();
01236   }
01237 
01238   /// Comparison to give a sorting by increasing eta (pseudorapidity)
01239   inline bool cmpMomByEta(const FourMomentum& a, const FourMomentum& b) {
01240     return a.eta() < b.eta();
01241   }
01242   /// Comparison to give a sorting by increasing eta (pseudorapidity)
01243   /// @deprecated Use cmpMomByEta
01244   DEPRECATED("Use cmpMomByEta")
01245   inline bool cmpMomByAscPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
01246     return cmpMomByEta(a,b);
01247   }
01248 
01249   /// Comparison to give a sorting by decreasing eta (pseudorapidity)
01250   inline bool cmpMomByDescEta(const FourMomentum& a, const FourMomentum& b) {
01251     return a.pseudorapidity() > b.pseudorapidity();
01252   }
01253   /// Comparison to give a sorting by decreasing eta (pseudorapidity)
01254   /// @deprecated Use cmpMomByDescEta
01255   DEPRECATED("Use cmpMomByDescEta")
01256   inline bool cmpMomByDescPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
01257     return cmpMomByDescEta(a,b);
01258   }
01259 
01260   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
01261   inline bool cmpMomByAbsEta(const FourMomentum& a, const FourMomentum& b) {
01262     return fabs(a.eta()) < fabs(b.eta());
01263   }
01264   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
01265   /// @deprecated Use cmpMomByAbsEta
01266   DEPRECATED("Use cmpMomByAbsEta")
01267   inline bool cmpMomByAscAbsPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
01268     return cmpMomByAbsEta(a,b);
01269   }
01270 
01271   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
01272   inline bool cmpMomByDescAbsEta(const FourMomentum& a, const FourMomentum& b) {
01273     return fabs(a.eta()) > fabs(b.eta());
01274   }
01275   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
01276   /// @deprecated Use cmpMomByDescAbsEta
01277   DEPRECATED("Use cmpMomByDescAbsEta")
01278   inline bool cmpMomByDescAbsPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
01279     return cmpMomByDescAbsEta(a,b);
01280   }
01281 
01282   /// Comparison to give a sorting by increasing rapidity
01283   inline bool cmpMomByRap(const FourMomentum& a, const FourMomentum& b) {
01284     return a.rapidity() < b.rapidity();
01285   }
01286   /// Comparison to give a sorting by increasing rapidity
01287   /// @deprecated Use cmpMomByRap
01288   DEPRECATED("Use cmpMomByRap")
01289   inline bool cmpMomByAscRapidity(const FourMomentum& a, const FourMomentum& b) {
01290     return cmpMomByRap(a,b);
01291   }
01292 
01293   /// Comparison to give a sorting by decreasing rapidity
01294   inline bool cmpMomByDescRap(const FourMomentum& a, const FourMomentum& b) {
01295     return a.rapidity() > b.rapidity();
01296   }
01297   /// Comparison to give a sorting by decreasing rapidity
01298   /// @deprecated Use cmpMomByDescRap
01299   DEPRECATED("Use cmpMomByDescRap")
01300   inline bool cmpMomByDescRapidity(const FourMomentum& a, const FourMomentum& b) {
01301     return cmpMomByDescRap(a,b);
01302   }
01303 
01304   /// Comparison to give a sorting by increasing absolute rapidity
01305   inline bool cmpMomByAbsRap(const FourMomentum& a, const FourMomentum& b) {
01306     return fabs(a.rapidity()) < fabs(b.rapidity());
01307   }
01308   /// Comparison to give a sorting by increasing absolute rapidity
01309   /// @deprecated Use cmpMomByAbsRap
01310   DEPRECATED("Use cmpMomByAbsRap")
01311   inline bool cmpMomByAscAbsRapidity(const FourMomentum& a, const FourMomentum& b) {
01312     return cmpMomByAbsRap(a,b);
01313   }
01314 
01315   /// Comparison to give a sorting by decreasing absolute rapidity
01316   inline bool cmpMomByDescAbsRap(const FourMomentum& a, const FourMomentum& b) {
01317     return fabs(a.rapidity()) > fabs(b.rapidity());
01318   }
01319   /// Comparison to give a sorting by decreasing absolute rapidity
01320   /// @deprecated Use cmpMomByDescAbsRap
01321   DEPRECATED("Use cmpMomByDescAbsRap")
01322   inline bool cmpMomByDescAbsRapidity(const FourMomentum& a, const FourMomentum& b) {
01323     return cmpMomByDescAbsRap(a,b);
01324   }
01325 
01326   /// @todo Add sorting by phi [0..2PI]
01327 
01328 
01329   /// Sort a container of momenta by cmp and return by reference for non-const inputs
01330   template<typename MOMS, typename CMP>
01331   inline MOMS& sortBy(MOMS& pbs, const CMP& cmp) {
01332     std::sort(pbs.begin(), pbs.end(), cmp);
01333     return pbs;
01334   }
01335   /// Sort a container of momenta by cmp and return by value for const inputs
01336   template<typename MOMS, typename CMP>
01337   inline MOMS sortBy(const MOMS& pbs, const CMP& cmp) {
01338     MOMS rtn = pbs;
01339     std::sort(rtn.begin(), rtn.end(), cmp);
01340     return rtn;
01341   }
01342 
01343   /// Sort a container of momenta by pT (decreasing) and return by reference for non-const inputs
01344   template<typename MOMS>
01345   inline MOMS& sortByPt(MOMS& pbs) {
01346     return sortBy(pbs, cmpMomByPt);
01347   }
01348   /// Sort a container of momenta by pT (decreasing) and return by value for const inputs
01349   template<typename MOMS>
01350   inline MOMS sortByPt(const MOMS& pbs) {
01351     return sortBy(pbs, cmpMomByPt);
01352   }
01353 
01354   /// Sort a container of momenta by E (decreasing) and return by reference for non-const inputs
01355   template<typename MOMS>
01356   inline MOMS& sortByE(MOMS& pbs) {
01357     return sortBy(pbs, cmpMomByE);
01358   }
01359   /// Sort a container of momenta by E (decreasing) and return by value for const inputs
01360   template<typename MOMS>
01361   inline MOMS sortByE(const MOMS& pbs) {
01362     return sortBy(pbs, cmpMomByE);
01363   }
01364 
01365   /// Sort a container of momenta by Et (decreasing) and return by reference for non-const inputs
01366   template<typename MOMS>
01367   inline MOMS& sortByEt(MOMS& pbs) {
01368     return sortBy(pbs, cmpMomByEt);
01369   }
01370   /// Sort a container of momenta by Et (decreasing) and return by value for const inputs
01371   template<typename MOMS>
01372   inline MOMS sortByEt(const MOMS& pbs) {
01373     return sortBy(pbs, cmpMomByEt);
01374   }
01375 
01376   //@}
01377 
01378 
01379   //////////////////////////////////////////////////////
01380 
01381 
01382   /// @name 4-vector string representations
01383   //@{
01384 
01385   /// Render a 4-vector as a string.
01386   inline std::string toString(const FourVector& lv) {
01387     ostringstream out;
01388     out << "("  << (fabs(lv.t()) < 1E-30 ? 0.0 : lv.t())
01389         << "; " << (fabs(lv.x()) < 1E-30 ? 0.0 : lv.x())
01390         << ", " << (fabs(lv.y()) < 1E-30 ? 0.0 : lv.y())
01391         << ", " << (fabs(lv.z()) < 1E-30 ? 0.0 : lv.z())
01392         << ")";
01393     return out.str();
01394   }
01395 
01396   /// Write a 4-vector to an ostream.
01397   inline std::ostream& operator<<(std::ostream& out, const FourVector& lv) {
01398     out << toString(lv);
01399     return out;
01400   }
01401 
01402   //@}
01403 
01404 
01405   /// @name Typedefs of vector types to short names
01406   /// @todo Switch canonical and alias names
01407   //@{
01408   //typedef FourVector V4; //< generic
01409   typedef FourVector X4; //< spatial
01410   typedef FourMomentum P4; //< momentum
01411   //@}
01412 
01413 
01414 }
01415 
01416 #endif