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   class FourVector : public Vector<4> {
00021     friend FourVector multiply(const double a, const FourVector& v);
00022     friend FourVector multiply(const FourVector& v, const double a);
00023     friend FourVector add(const FourVector& a, const FourVector& b);
00024     friend FourVector transform(const LorentzTransform& lt, const FourVector& v4);
00025 
00026   public:
00027 
00028     FourVector() : Vector<4>() { }
00029 
00030     template<typename V4>
00031     FourVector(const V4& other) {
00032       this->setT(other.t());
00033       this->setX(other.x());
00034       this->setY(other.y());
00035       this->setZ(other.z());
00036     }
00037 
00038     FourVector(const Vector<4>& other)
00039     : Vector<4>(other) { }
00040 
00041     FourVector(const double t, const double x, const double y, const double z) {
00042       this->setT(t);
00043       this->setX(x);
00044       this->setY(y);
00045       this->setZ(z);
00046     }
00047 
00048     virtual ~FourVector() { }
00049 
00050   public:
00051 
00052     double t() const { return get(0); }
00053     double x() const { return get(1); }
00054     double y() const { return get(2); }
00055     double z() const { return get(3); }
00056     FourVector& setT(const double t) { set(0, t); return *this; }
00057     FourVector& setX(const double x) { set(1, x); return *this; }
00058     FourVector& setY(const double y) { set(2, y); return *this; }
00059     FourVector& setZ(const double z) { set(3, z); return *this; }
00060 
00061     double invariant() const {
00062       // Done this way for numerical precision
00063       return (t() + z())*(t() - z()) - x()*x() - y()*y();
00064     }
00065 
00066     /// Angle between this vector and another
00067     double angle(const FourVector& v) const {
00068       return vector3().angle( v.vector3() );
00069     }
00070 
00071     /// Angle between this vector and another (3-vector)
00072     double angle(const Vector3& v3) const {
00073       return vector3().angle(v3);
00074     }
00075 
00076     /// @brief Square of the projection of the 3-vector on to the \f$ x-y \f$ plane
00077     /// This is a more efficient function than @c polarRadius, as it avoids the square root.
00078     /// Use it if you only need the squared value, or e.g. an ordering by magnitude.
00079     double polarRadius2() const {
00080       return vector3().polarRadius2();
00081     }
00082 
00083     /// Synonym for polarRadius2
00084     double perp2() const {
00085       return vector3().perp2();
00086     }
00087 
00088     /// Synonym for polarRadius2
00089     double rho2() const {
00090       return vector3().rho2();
00091     }
00092 
00093     /// Projection of 3-vector on to the \f$ x-y \f$ plane
00094     double polarRadius() const {
00095       return vector3().polarRadius();
00096     }
00097 
00098     /// Synonym for polarRadius
00099     double perp() const {
00100       return vector3().perp();
00101     }
00102 
00103     /// Synonym for polarRadius
00104     double rho() const {
00105       return vector3().rho();
00106     }
00107 
00108     /// Angle subtended by the 3-vector's projection in x-y and the x-axis.
00109     double azimuthalAngle(const PhiMapping mapping=ZERO_2PI) const {
00110       return vector3().azimuthalAngle(mapping);
00111     }
00112 
00113     /// Synonym for azimuthalAngle.
00114     double phi(const PhiMapping mapping=ZERO_2PI) const {
00115       return vector3().phi(mapping);
00116     }
00117 
00118     /// Angle subtended by the 3-vector and the z-axis.
00119     double polarAngle() const {
00120       return vector3().polarAngle();
00121     }
00122 
00123     /// Synonym for polarAngle.
00124     double theta() const {
00125       return vector3().theta();
00126     }
00127 
00128     /// Pseudorapidity (defined purely by the 3-vector components)
00129     double pseudorapidity() const {
00130       return vector3().pseudorapidity();
00131     }
00132 
00133     /// Synonym for pseudorapidity.
00134     double eta() const {
00135       return vector3().eta();
00136     }
00137 
00138     /// Get the \f$ |\eta| \f$ directly.
00139     double abspseudorapidity() const { return fabs(eta()); }
00140 
00141     /// Get the \f$ |\eta| \f$ directly (alias).
00142     double abseta() const { return fabs(eta()); }
00143 
00144     /// Get the spatial part of the 4-vector as a 3-vector.
00145     Vector3 vector3() const {
00146       return Vector3(get(1), get(2), get(3));
00147     }
00148 
00149 
00150   public:
00151 
00152     /// Contract two 4-vectors, with metric signature (+ - - -).
00153     double contract(const FourVector& v) const {
00154       const double result = t()*v.t() - x()*v.x() - y()*v.y() - z()*v.z();
00155       return result;
00156     }
00157 
00158     /// Contract two 4-vectors, with metric signature (+ - - -).
00159     double dot(const FourVector& v) const {
00160       return contract(v);
00161     }
00162 
00163     /// Contract two 4-vectors, with metric signature (+ - - -).
00164     double operator*(const FourVector& v) const {
00165       return contract(v);
00166     }
00167 
00168     /// Multiply by a scalar.
00169     FourVector& operator*=(double a) {
00170       _vec = multiply(a, *this)._vec;
00171       return *this;
00172     }
00173 
00174     /// Divide by a scalar.
00175     FourVector& operator/=(double a) {
00176       _vec = multiply(1.0/a, *this)._vec;
00177       return *this;
00178     }
00179 
00180     /// Add to this 4-vector.
00181     FourVector& operator+=(const FourVector& v) {
00182       _vec = add(*this, v)._vec;
00183       return *this;
00184     }
00185 
00186     /// Subtract from this 4-vector. NB time as well as space components are subtracted.
00187     FourVector& operator-=(const FourVector& v) {
00188       _vec = add(*this, -v)._vec;
00189       return *this;
00190     }
00191 
00192     /// Multiply all components (space and time) by -1.
00193     FourVector operator-() const {
00194       FourVector result;
00195       result._vec = -_vec;
00196       return result;
00197     }
00198 
00199   };
00200 
00201 
00202   /// Contract two 4-vectors, with metric signature (+ - - -).
00203   inline double contract(const FourVector& a, const FourVector& b) {
00204     return a.contract(b);
00205   }
00206 
00207   /// Contract two 4-vectors, with metric signature (+ - - -).
00208   inline double dot(const FourVector& a, const FourVector& b) {
00209     return contract(a, b);
00210   }
00211 
00212   inline FourVector multiply(const double a, const FourVector& v) {
00213     FourVector result;
00214     result._vec = a * v._vec;
00215     return result;
00216   }
00217 
00218   inline FourVector multiply(const FourVector& v, const double a) {
00219     return multiply(a, v);
00220   }
00221 
00222   inline FourVector operator*(const double a, const FourVector& v) {
00223     return multiply(a, v);
00224   }
00225 
00226   inline FourVector operator*(const FourVector& v, const double a) {
00227     return multiply(a, v);
00228   }
00229 
00230   inline FourVector operator/(const FourVector& v, const double a) {
00231     return multiply(1.0/a, v);
00232   }
00233 
00234   inline FourVector add(const FourVector& a, const FourVector& b) {
00235     FourVector result;
00236     result._vec = a._vec + b._vec;
00237     return result;
00238   }
00239 
00240   inline FourVector operator+(const FourVector& a, const FourVector& b) {
00241     return add(a, b);
00242   }
00243 
00244   inline FourVector operator-(const FourVector& a, const FourVector& b) {
00245     return add(a, -b);
00246   }
00247 
00248   /// Calculate the Lorentz self-invariant of a 4-vector.
00249   /// \f$ v_\mu v^\mu = g_{\mu\nu} x^\mu x^\nu \f$.
00250   inline double invariant(const FourVector& lv) {
00251     return lv.invariant();
00252   }
00253 
00254   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00255   inline double angle(const FourVector& a, const FourVector& b) {
00256     return a.angle(b);
00257   }
00258 
00259   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00260   inline double angle(const Vector3& a, const FourVector& b) {
00261     return angle( a, b.vector3() );
00262   }
00263 
00264   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00265   inline double angle(const FourVector& a, const Vector3& b) {
00266     return a.angle(b);
00267   }
00268 
00269 
00270   ////////////////////////////////////////////////
00271 
00272 
00273   /// Specialized version of the FourVector with momentum/energy functionality.
00274   class FourMomentum : public FourVector {
00275     friend FourMomentum multiply(const double a, const FourMomentum& v);
00276     friend FourMomentum multiply(const FourMomentum& v, const double a);
00277     friend FourMomentum add(const FourMomentum& a, const FourMomentum& b);
00278     friend FourMomentum transform(const LorentzTransform& lt, const FourMomentum& v4);
00279 
00280   public:
00281     FourMomentum() { }
00282 
00283     template<typename V4>
00284     FourMomentum(const V4& other) {
00285       this->setE(other.t());
00286       this->setPx(other.x());
00287       this->setPy(other.y());
00288       this->setPz(other.z());
00289     }
00290 
00291     FourMomentum(const Vector<4>& other)
00292       : FourVector(other) { }
00293 
00294     FourMomentum(const double E, const double px, const double py, const double pz) {
00295       this->setE(E);
00296       this->setPx(px);
00297       this->setPy(py);
00298       this->setPz(pz);
00299     }
00300 
00301     ~FourMomentum() {}
00302 
00303   public:
00304     /// Get energy \f$ E \f$ (time component of momentum).
00305     double E() const { return t(); }
00306 
00307     /// Get 3-momentum part, \f$ p \f$.
00308     Vector3 p3() const { return vector3(); }
00309     /// Get 3-momentum part, \f$ p \f$ (alias).
00310     // Vector3 p() const { return vector3(); }
00311 
00312     /// Get x-component of momentum \f$ p_x \f$.
00313     double px() const { return x(); }
00314 
00315     /// Get y-component of momentum \f$ p_y \f$.
00316     double py() const { return y(); }
00317 
00318     /// Get z-component of momentum \f$ p_z \f$.
00319     double pz() const { return z(); }
00320 
00321     /// Set energy \f$ E \f$ (time component of momentum).
00322     FourMomentum& setE(double E)   { setT(E); return *this; }
00323 
00324     /// Set x-component of momentum \f$ p_x \f$.
00325     FourMomentum& setPx(double px) { setX(px); return *this; }
00326 
00327     /// Set y-component of momentum \f$ p_y \f$.
00328     FourMomentum& setPy(double py) { setY(py); return *this; }
00329 
00330     /// Set z-component of momentum \f$ p_z \f$.
00331     FourMomentum& setPz(double pz) { setZ(pz); return *this; }
00332 
00333     /// @brief Get the mass \f$ m = \sqrt{E^2 - p^2} \f$ (the Lorentz self-invariant).
00334     ///
00335     /// For spacelike momenta, the mass will be -sqrt(|mass2|).
00336     double mass() const {
00337       // assert(Rivet::isZero(mass2()) || mass2() > 0);
00338       // if (Rivet::isZero(mass2())) {
00339       //   return 0.0;
00340       // } else {
00341       //   return sqrt(mass2());
00342       // }
00343       return sign(mass2()) * sqrt(fabs(mass2()));
00344     }
00345 
00346     /// Get the squared mass \f$ m^2 = E^2 - p^2 \f$ (the Lorentz self-invariant).
00347     double mass2() const {
00348       return invariant();
00349     }
00350 
00351     /// Calculate the rapidity.
00352     double rapidity() const {
00353       return 0.5 * std::log( (E() + pz()) / (E() - pz()) );
00354     }
00355 
00356     /// Alias for rapidity.
00357     double rap() const {
00358       return rapidity();
00359     }
00360 
00361     /// Absolute rapidity.
00362     double absrapidity() const {
00363       return fabs(rapidity());
00364     }
00365 
00366     /// Absolute rapidity.
00367     double absrap() const {
00368       return fabs(rap());
00369     }
00370 
00371     /// Calculate the squared transverse momentum \f$ p_T^2 \f$.
00372     double pT2() const {
00373       return vector3().polarRadius2();
00374     }
00375 
00376     /// Calculate the squared transverse momentum \f$ p_T^2 \f$.
00377     double pt2() const {
00378       return vector3().polarRadius2();
00379     }
00380 
00381     /// Calculate the transverse momentum \f$ p_T \f$.
00382     double pT() const {
00383       return sqrt(pT2());
00384     }
00385 
00386     /// Calculate the transverse momentum \f$ p_T \f$.
00387     double pt() const {
00388       return sqrt(pT2());
00389     }
00390 
00391     /// Calculate the transverse energy \f$ E_T^2 = E^2 \sin^2{\theta} \f$.
00392     double Et2() const {
00393       return Et() * Et();
00394     }
00395 
00396     /// Calculate the transverse energy \f$ E_T = E \sin{\theta} \f$.
00397     double Et() const {
00398       return E() * sin(polarAngle());
00399     }
00400 
00401     /// Calculate the boost vector (in units of \f$ \beta \f$).
00402     Vector3 boostVector() const {
00403       // const Vector3 p3 = vector3();
00404       // const double m2 = mass2();
00405       // if (Rivet::isZero(m2)) return p3.unit();
00406       // else {
00407       //   // Could also do this via beta = tanh(rapidity), but that's
00408       //   // probably more messy from a numerical hygiene point of view.
00409       //   const double p2 = p3.mod2();
00410       //   const double beta = sqrt( p2 / (m2 + p2) );
00411       //   return beta * p3.unit();
00412       // }
00413       /// @todo Be careful about c=1 convention...
00414       return Vector3(px()/E(), py()/E(), pz()/E());
00415     }
00416 
00417     /// Struct for sorting by increasing energy
00418     struct byEAscending {
00419       bool operator()(const FourMomentum& left, const FourMomentum& right) const{
00420         double pt2left = left.E();
00421         double pt2right = right.E();
00422         return pt2left < pt2right;
00423       }
00424 
00425       bool operator()(const FourMomentum* left, const FourMomentum* right) const{
00426         return (*this)(left, right);
00427       }
00428     };
00429 
00430     /// Struct for sorting by decreasing energy
00431     struct byEDescending {
00432       bool operator()(const FourMomentum& left, const FourMomentum& right) const{
00433         return byEAscending()(right, left);
00434       }
00435 
00436       bool operator()(const FourMomentum* left, const FourVector* right) const{
00437         return (*this)(left, right);
00438       }
00439     };
00440 
00441 
00442     /// Multiply by a scalar
00443     FourMomentum& operator*=(double a) {
00444       _vec = multiply(a, *this)._vec;
00445       return *this;
00446     }
00447 
00448     /// Divide by a scalar
00449     FourMomentum& operator/=(double a) {
00450       _vec = multiply(1.0/a, *this)._vec;
00451       return *this;
00452     }
00453 
00454     /// Add to this 4-vector. NB time as well as space components are added.
00455     FourMomentum& operator+=(const FourMomentum& v) {
00456       _vec = add(*this, v)._vec;
00457       return *this;
00458     }
00459 
00460     /// Subtract from this 4-vector. NB time as well as space components are subtracted.
00461     FourMomentum& operator-=(const FourMomentum& v) {
00462       _vec = add(*this, -v)._vec;
00463       return *this;
00464     }
00465 
00466     /// Multiply all components (time and space) by -1.
00467     FourMomentum operator-() const {
00468       FourMomentum result;
00469       result._vec = -_vec;
00470       return result;
00471     }
00472 
00473 
00474   };
00475 
00476 
00477   inline FourMomentum multiply(const double a, const FourMomentum& v) {
00478     FourMomentum result;
00479     result._vec = a * v._vec;
00480     return result;
00481   }
00482 
00483   inline FourMomentum multiply(const FourMomentum& v, const double a) {
00484     return multiply(a, v);
00485   }
00486 
00487   inline FourMomentum operator*(const double a, const FourMomentum& v) {
00488     return multiply(a, v);
00489   }
00490 
00491   inline FourMomentum operator*(const FourMomentum& v, const double a) {
00492     return multiply(a, v);
00493   }
00494 
00495   inline FourMomentum operator/(const FourMomentum& v, const double a) {
00496     return multiply(1.0/a, v);
00497   }
00498 
00499   inline FourMomentum add(const FourMomentum& a, const FourMomentum& b) {
00500     FourMomentum result;
00501     result._vec = a._vec + b._vec;
00502     return result;
00503   }
00504 
00505   inline FourMomentum operator+(const FourMomentum& a, const FourMomentum& b) {
00506     return add(a, b);
00507   }
00508 
00509   inline FourMomentum operator-(const FourMomentum& a, const FourMomentum& b) {
00510     return add(a, -b);
00511   }
00512 
00513 
00514   //////////////////////////////////////////////////////
00515 
00516 
00517   /// @name \f$ \Delta R \f$ calculations from 4-vectors
00518   //@{
00519 
00520   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00521   /// There is a scheme ambiguity for momentum-type four vectors as to whether
00522   /// the pseudorapidity (a purely geometric concept) or the rapidity (a
00523   /// relativistic energy-momentum quantity) is to be used: this can be chosen
00524   /// via the optional scheme parameter. Use of this scheme option is
00525   /// discouraged in this case since @c RAPIDITY is only a valid option for
00526   /// vectors whose type is really the FourMomentum derived class.
00527   inline double deltaR(const FourVector& a, const FourVector& b,
00528                        RapScheme scheme = PSEUDORAPIDITY) {
00529     switch (scheme) {
00530     case PSEUDORAPIDITY :
00531       return deltaR(a.vector3(), b.vector3());
00532     case RAPIDITY:
00533       {
00534         const FourMomentum* ma = dynamic_cast<const FourMomentum*>(&a);
00535         const FourMomentum* mb = dynamic_cast<const FourMomentum*>(&b);
00536         if (!ma || !mb) {
00537           string err = "deltaR with scheme RAPIDITY can only be called with FourMomentum objects, not FourVectors";
00538           throw std::runtime_error(err);
00539         }
00540         return deltaR(*ma, *mb, scheme);
00541       }
00542     default:
00543       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00544     }
00545   }
00546 
00547 
00548   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00549   /// There is a scheme ambiguity for momentum-type four vectors
00550   /// as to whether the pseudorapidity (a purely geometric concept) or the
00551   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00552   /// be chosen via the optional scheme parameter.
00553   inline double deltaR(const FourVector& v,
00554                        double eta2, double phi2,
00555                        RapScheme scheme = PSEUDORAPIDITY) {
00556     switch (scheme) {
00557     case PSEUDORAPIDITY :
00558       return deltaR(v.vector3(), eta2, phi2);
00559     case RAPIDITY:
00560       {
00561         const FourMomentum* mv = dynamic_cast<const FourMomentum*>(&v);
00562         if (!mv) {
00563           string err = "deltaR with scheme RAPIDITY can only be called with FourMomentum objects, not FourVectors";
00564           throw std::runtime_error(err);
00565         }
00566         return deltaR(*mv, eta2, phi2, scheme);
00567       }
00568     default:
00569       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00570     }
00571   }
00572 
00573 
00574   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00575   /// There is a scheme ambiguity for momentum-type four vectors
00576   /// as to whether the pseudorapidity (a purely geometric concept) or the
00577   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00578   /// be chosen via the optional scheme parameter.
00579   inline double deltaR(double eta1, double phi1,
00580                        const FourVector& v,
00581                        RapScheme scheme = PSEUDORAPIDITY) {
00582     switch (scheme) {
00583     case PSEUDORAPIDITY :
00584       return deltaR(eta1, phi1, v.vector3());
00585     case RAPIDITY:
00586       {
00587         const FourMomentum* mv = dynamic_cast<const FourMomentum*>(&v);
00588         if (!mv) {
00589           string err = "deltaR with scheme RAPIDITY can only be called with FourMomentum objects, not FourVectors";
00590           throw std::runtime_error(err);
00591         }
00592         return deltaR(eta1, phi1, *mv, scheme);
00593       }
00594     default:
00595       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00596     }
00597   }
00598 
00599 
00600   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00601   /// There is a scheme ambiguity for momentum-type four vectors
00602   /// as to whether the pseudorapidity (a purely geometric concept) or the
00603   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00604   /// be chosen via the optional scheme parameter.
00605   inline double deltaR(const FourMomentum& a, const FourMomentum& b,
00606                        RapScheme scheme = PSEUDORAPIDITY) {
00607     switch (scheme) {
00608     case PSEUDORAPIDITY:
00609       return deltaR(a.vector3(), b.vector3());
00610     case RAPIDITY:
00611       return deltaR(a.rapidity(), a.azimuthalAngle(), b.rapidity(), b.azimuthalAngle());
00612     default:
00613       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00614     }
00615   }
00616 
00617   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00618   /// There is a scheme ambiguity for momentum-type four vectors
00619   /// as to whether the pseudorapidity (a purely geometric concept) or the
00620   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00621   /// be chosen via the optional scheme parameter.
00622   inline double deltaR(const FourMomentum& v,
00623                        double eta2, double phi2,
00624                        RapScheme scheme = PSEUDORAPIDITY) {
00625     switch (scheme) {
00626     case PSEUDORAPIDITY:
00627       return deltaR(v.vector3(), eta2, phi2);
00628     case RAPIDITY:
00629       return deltaR(v.rapidity(), v.azimuthalAngle(), eta2, phi2);
00630     default:
00631       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00632     }
00633   }
00634 
00635 
00636   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00637   /// There is a scheme ambiguity for momentum-type four vectors
00638   /// as to whether the pseudorapidity (a purely geometric concept) or the
00639   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00640   /// be chosen via the optional scheme parameter.
00641   inline double deltaR(double eta1, double phi1,
00642                        const FourMomentum& v,
00643                        RapScheme scheme = PSEUDORAPIDITY) {
00644     switch (scheme) {
00645     case PSEUDORAPIDITY:
00646       return deltaR(eta1, phi1, v.vector3());
00647     case RAPIDITY:
00648       return deltaR(eta1, phi1, v.rapidity(), v.azimuthalAngle());
00649     default:
00650       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00651     }
00652   }
00653 
00654   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00655   /// There is a scheme ambiguity for momentum-type four vectors
00656   /// as to whether the pseudorapidity (a purely geometric concept) or the
00657   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00658   /// be chosen via the optional scheme parameter.
00659   inline double deltaR(const FourMomentum& a, const FourVector& b,
00660                        RapScheme scheme = PSEUDORAPIDITY) {
00661     switch (scheme) {
00662     case PSEUDORAPIDITY:
00663       return deltaR(a.vector3(), b.vector3());
00664     case RAPIDITY:
00665       return deltaR(a.rapidity(), a.azimuthalAngle(), FourMomentum(b).rapidity(), b.azimuthalAngle());
00666     default:
00667       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00668     }
00669   }
00670 
00671   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two four-vectors.
00672   /// There is a scheme ambiguity for momentum-type four vectors
00673   /// as to whether the pseudorapidity (a purely geometric concept) or the
00674   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00675   /// be chosen via the optional scheme parameter.
00676   inline double deltaR(const FourVector& a, const FourMomentum& b,
00677                        RapScheme scheme = PSEUDORAPIDITY) {
00678     return deltaR(b, a, scheme);
00679   }
00680 
00681   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
00682   /// three-vector and a four-vector.
00683   inline double deltaR(const FourMomentum& a, const Vector3& b) {
00684     return deltaR(a.vector3(), b);
00685   }
00686 
00687   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
00688   /// three-vector and a four-vector.
00689   inline double deltaR(const Vector3& a, const FourMomentum& b) {
00690     return deltaR(a, b.vector3());
00691   }
00692 
00693   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
00694   /// three-vector and a four-vector.
00695   inline double deltaR(const FourVector& a, const Vector3& b) {
00696     return deltaR(a.vector3(), b);
00697   }
00698 
00699   /// @brief Calculate the 2D rapidity-azimuthal ("eta-phi") distance between a
00700   /// three-vector and a four-vector.
00701   inline double deltaR(const Vector3& a, const FourVector& b) {
00702     return deltaR(a, b.vector3());
00703   }
00704 
00705   //@}
00706 
00707 
00708   //////////////////////////////////////////////////////
00709 
00710 
00711   /// @name \f$ \Delta phi \f$ calculations from 4-vectors
00712   //@{
00713 
00714   /// Calculate the difference in azimuthal angle between two vectors.
00715   inline double deltaPhi(const FourMomentum& a, const FourMomentum& b) {
00716     return deltaPhi(a.vector3(), b.vector3());
00717   }
00718 
00719   /// Calculate the difference in azimuthal angle between two vectors.
00720   inline double deltaPhi(const FourMomentum& v, double phi2) {
00721     return deltaPhi(v.vector3(), phi2);
00722   }
00723 
00724   /// Calculate the difference in azimuthal angle between two vectors.
00725   inline double deltaPhi(double phi1, const FourMomentum& v) {
00726     return deltaPhi(phi1, v.vector3());
00727   }
00728 
00729   /// Calculate the difference in azimuthal angle between two vectors.
00730   inline double deltaPhi(const FourVector& a, const FourVector& b) {
00731     return deltaPhi(a.vector3(), b.vector3());
00732   }
00733 
00734   /// Calculate the difference in azimuthal angle between two vectors.
00735   inline double deltaPhi(const FourVector& v, double phi2) {
00736     return deltaPhi(v.vector3(), phi2);
00737   }
00738 
00739   /// Calculate the difference in azimuthal angle between two vectors.
00740   inline double deltaPhi(double phi1, const FourVector& v) {
00741     return deltaPhi(phi1, v.vector3());
00742   }
00743 
00744   /// Calculate the difference in azimuthal angle between two vectors.
00745   inline double deltaPhi(const FourVector& a, const FourMomentum& b) {
00746     return deltaPhi(a.vector3(), b.vector3());
00747   }
00748 
00749   /// Calculate the difference in azimuthal angle between two vectors.
00750   inline double deltaPhi(const FourMomentum& a, const FourVector& b) {
00751     return deltaPhi(a.vector3(), b.vector3());
00752   }
00753 
00754   /// Calculate the difference in azimuthal angle between two vectors.
00755   inline double deltaPhi(const FourVector& a, const Vector3& b) {
00756     return deltaPhi(a.vector3(), b);
00757   }
00758 
00759   /// Calculate the difference in azimuthal angle between two vectors.
00760   inline double deltaPhi(const Vector3& a, const FourVector& b) {
00761     return deltaPhi(a, b.vector3());
00762   }
00763 
00764   /// Calculate the difference in azimuthal angle between two vectors.
00765   inline double deltaPhi(const FourMomentum& a, const Vector3& b) {
00766     return deltaPhi(a.vector3(), b);
00767   }
00768 
00769   /// Calculate the difference in azimuthal angle between two vectors.
00770   inline double deltaPhi(const Vector3& a, const FourMomentum& b) {
00771     return deltaPhi(a, b.vector3());
00772   }
00773 
00774   //@}
00775 
00776 
00777   //////////////////////////////////////////////////////
00778 
00779 
00780   /// @name \f$ |\Delta eta| \f$ calculations from 4-vectors
00781   //@{
00782 
00783   /// Calculate the difference in pseudorapidity between two vectors.
00784   inline double deltaEta(const FourMomentum& a, const FourMomentum& b) {
00785     return deltaEta(a.vector3(), b.vector3());
00786   }
00787 
00788   /// Calculate the difference in pseudorapidity between two vectors.
00789   inline double deltaEta(const FourMomentum& v, double eta2) {
00790     return deltaEta(v.vector3(), eta2);
00791   }
00792 
00793   /// Calculate the difference in pseudorapidity between two vectors.
00794   inline double deltaEta(double eta1, const FourMomentum& v) {
00795     return deltaEta(eta1, v.vector3());
00796   }
00797 
00798   /// Calculate the difference in pseudorapidity between two vectors.
00799   inline double deltaEta(const FourVector& a, const FourVector& b) {
00800     return deltaEta(a.vector3(), b.vector3());
00801   }
00802 
00803   /// Calculate the difference in pseudorapidity between two vectors.
00804   inline double deltaEta(const FourVector& v, double eta2) {
00805     return deltaEta(v.vector3(), eta2);
00806   }
00807 
00808   /// Calculate the difference in pseudorapidity between two vectors.
00809   inline double deltaEta(double eta1, const FourVector& v) {
00810     return deltaEta(eta1, v.vector3());
00811   }
00812 
00813   /// Calculate the difference in pseudorapidity between two vectors.
00814   inline double deltaEta(const FourVector& a, const FourMomentum& b) {
00815     return deltaEta(a.vector3(), b.vector3());
00816   }
00817 
00818   /// Calculate the difference in pseudorapidity between two vectors.
00819   inline double deltaEta(const FourMomentum& a, const FourVector& b) {
00820     return deltaEta(a.vector3(), b.vector3());
00821   }
00822 
00823   /// Calculate the difference in pseudorapidity between two vectors.
00824   inline double deltaEta(const FourVector& a, const Vector3& b) {
00825     return deltaEta(a.vector3(), b);
00826   }
00827 
00828   /// Calculate the difference in pseudorapidity between two vectors.
00829   inline double deltaEta(const Vector3& a, const FourVector& b) {
00830     return deltaEta(a, b.vector3());
00831   }
00832 
00833   /// Calculate the difference in pseudorapidity between two vectors.
00834   inline double deltaEta(const FourMomentum& a, const Vector3& b) {
00835     return deltaEta(a.vector3(), b);
00836   }
00837 
00838   /// Calculate the difference in pseudorapidity between two vectors.
00839   inline double deltaEta(const Vector3& a, const FourMomentum& b) {
00840     return deltaEta(a, b.vector3());
00841   }
00842 
00843   //@}
00844 
00845 
00846   /// @name \f$ |\Delta y| \f$ calculations from 4-momentum vectors
00847   //@{
00848 
00849   /// Calculate the difference in rapidity between two 4-momentum vectors.
00850   inline double deltaRap(const FourMomentum& a, const FourMomentum& b) {
00851     return deltaRap(a.rapidity(), b.rapidity());
00852   }
00853 
00854   /// Calculate the difference in rapidity between two 4-momentum vectors.
00855   inline double deltaRap(const FourMomentum& v, double y2) {
00856     return deltaRap(v.rapidity(), y2);
00857   }
00858 
00859   /// Calculate the difference in rapidity between two 4-momentum vectors.
00860   inline double deltaRap(double y1, const FourMomentum& v) {
00861     return deltaRap(y1, v.rapidity());
00862   }
00863 
00864   //@}
00865 
00866 
00867   //////////////////////////////////////////////////////
00868 
00869 
00870   /// @name 4-vector comparison functions (for sorting)
00871   //@{
00872 
00873   /// Comparison to give a sorting by decreasing pT
00874   inline bool cmpMomByPt(const FourMomentum& a, const FourMomentum& b) {
00875     return a.pt() > b.pt();
00876   }
00877   /// Comparison to give a sorting by increasing pT
00878   inline bool cmpMomByAscPt(const FourMomentum& a, const FourMomentum& b) {
00879     return a.pt() < b.pt();
00880   }
00881 
00882   /// Comparison to give a sorting by decreasing 3-momentum magnitude |p|
00883   inline bool cmpMomByP(const FourMomentum& a, const FourMomentum& b) {
00884     return a.vector3().mod() > b.vector3().mod();
00885   }
00886   /// Comparison to give a sorting by increasing 3-momentum magnitude |p|
00887   inline bool cmpMomByAscP(const FourMomentum& a, const FourMomentum& b) {
00888     return a.vector3().mod() < b.vector3().mod();
00889   }
00890 
00891   /// Comparison to give a sorting by decreasing transverse energy
00892   inline bool cmpMomByEt(const FourMomentum& a, const FourMomentum& b) {
00893     return a.Et() > b.Et();
00894   }
00895   /// Comparison to give a sorting by increasing transverse energy
00896   inline bool cmpMomByAscEt(const FourMomentum& a, const FourMomentum& b) {
00897     return a.Et() < b.Et();
00898   }
00899 
00900   /// Comparison to give a sorting by decreasing energy
00901   inline bool cmpMomByE(const FourMomentum& a, const FourMomentum& b) {
00902     return a.E() > b.E();
00903   }
00904   /// Comparison to give a sorting by increasing energy
00905   inline bool cmpMomByAscE(const FourMomentum& a, const FourMomentum& b) {
00906     return a.E() < b.E();
00907   }
00908 
00909   /// Comparison to give a sorting by increasing eta (pseudorapidity)
00910   inline bool cmpMomByEta(const FourMomentum& a, const FourMomentum& b) {
00911     return a.eta() < b.eta();
00912   }
00913   /// Comparison to give a sorting by increasing eta (pseudorapidity)
00914   /// @deprecated Use cmpMomByEta
00915   inline bool cmpMomByAscPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
00916     return cmpMomByEta(a,b);
00917   }
00918 
00919   /// Comparison to give a sorting by decreasing eta (pseudorapidity)
00920   inline bool cmpMomByDescEta(const FourMomentum& a, const FourMomentum& b) {
00921     return a.pseudorapidity() > b.pseudorapidity();
00922   }
00923   /// Comparison to give a sorting by decreasing eta (pseudorapidity)
00924   /// @deprecated Use cmpMomByDescEta
00925   inline bool cmpMomByDescPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
00926     return cmpMomByDescEta(a,b);
00927   }
00928 
00929   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
00930   inline bool cmpMomByAbsEta(const FourMomentum& a, const FourMomentum& b) {
00931     return fabs(a.eta()) < fabs(b.eta());
00932   }
00933   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
00934   /// @deprecated Use cmpMomByAbsEta
00935   inline bool cmpMomByAscAbsPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
00936     return cmpMomByAbsEta(a,b);
00937   }
00938 
00939   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
00940   inline bool cmpMomByDescAbsEta(const FourMomentum& a, const FourMomentum& b) {
00941     return fabs(a.eta()) > fabs(b.eta());
00942   }
00943   /// Comparison to give a sorting by increasing absolute eta (pseudorapidity)
00944   /// @deprecated Use cmpMomByDescAbsEta
00945   inline bool cmpMomByDescAbsPseudorapidity(const FourMomentum& a, const FourMomentum& b) {
00946     return cmpMomByDescAbsEta(a,b);
00947   }
00948 
00949   /// Comparison to give a sorting by increasing rapidity
00950   inline bool cmpMomByRap(const FourMomentum& a, const FourMomentum& b) {
00951     return a.rapidity() < b.rapidity();
00952   }
00953   /// Comparison to give a sorting by increasing rapidity
00954   /// @deprecated Use cmpMomByRap
00955   inline bool cmpMomByAscRapidity(const FourMomentum& a, const FourMomentum& b) {
00956     return cmpMomByRap(a,b);
00957   }
00958 
00959   /// Comparison to give a sorting by decreasing rapidity
00960   inline bool cmpMomByDescRap(const FourMomentum& a, const FourMomentum& b) {
00961     return a.rapidity() > b.rapidity();
00962   }
00963   /// Comparison to give a sorting by decreasing rapidity
00964   /// @deprecated Use cmpMomByDescRap
00965   inline bool cmpMomByDescRapidity(const FourMomentum& a, const FourMomentum& b) {
00966     return cmpMomByDescRap(a,b);
00967   }
00968 
00969   /// Comparison to give a sorting by increasing absolute rapidity
00970   inline bool cmpMomByAbsRap(const FourMomentum& a, const FourMomentum& b) {
00971     return fabs(a.rapidity()) < fabs(b.rapidity());
00972   }
00973   /// Comparison to give a sorting by increasing absolute rapidity
00974   /// @deprecated Use cmpMomByAbsRap
00975   inline bool cmpMomByAscAbsRapidity(const FourMomentum& a, const FourMomentum& b) {
00976     return cmpMomByAbsRap(a,b);
00977   }
00978 
00979   /// Comparison to give a sorting by decreasing absolute rapidity
00980   inline bool cmpMomByDescAbsRap(const FourMomentum& a, const FourMomentum& b) {
00981     return fabs(a.rapidity()) > fabs(b.rapidity());
00982   }
00983   /// Comparison to give a sorting by decreasing absolute rapidity
00984   /// @deprecated Use cmpMomByDescAbsRap
00985   inline bool cmpMomByDescAbsRapidity(const FourMomentum& a, const FourMomentum& b) {
00986     return cmpMomByDescAbsRap(a,b);
00987   }
00988 
00989   /// @todo Add sorting by phi [0..2PI]
00990 
00991 
00992   /// Sort a container of momenta by cmp and return by reference for non-const inputs
00993   template<typename MOMS, typename CMP>
00994   inline MOMS& sortBy(MOMS& pbs, const CMP& cmp) {
00995     std::sort(pbs.begin(), pbs.end(), cmp);
00996     return pbs;
00997   }
00998   /// Sort a container of momenta by cmp and return by value for const inputs
00999   template<typename MOMS, typename CMP>
01000   inline MOMS sortBy(const MOMS& pbs, const CMP& cmp) {
01001     MOMS rtn = pbs;
01002     std::sort(rtn.begin(), rtn.end(), cmp);
01003     return rtn;
01004   }
01005 
01006   /// Sort a container of momenta by pT (decreasing) and return by reference for non-const inputs
01007   template<typename MOMS>
01008   inline MOMS& sortByPt(MOMS& pbs) {
01009     return sortBy(pbs, cmpMomByPt);
01010   }
01011   /// Sort a container of momenta by pT (decreasing) and return by value for const inputs
01012   template<typename MOMS>
01013   inline MOMS sortByPt(const MOMS& pbs) {
01014     return sortBy(pbs, cmpMomByPt);
01015   }
01016 
01017   /// Sort a container of momenta by E (decreasing) and return by reference for non-const inputs
01018   template<typename MOMS>
01019   inline MOMS& sortByE(MOMS& pbs) {
01020     return sortBy(pbs, cmpMomByE);
01021   }
01022   /// Sort a container of momenta by E (decreasing) and return by value for const inputs
01023   template<typename MOMS>
01024   inline MOMS sortByE(const MOMS& pbs) {
01025     return sortBy(pbs, cmpMomByE);
01026   }
01027 
01028   /// Sort a container of momenta by Et (decreasing) and return by reference for non-const inputs
01029   template<typename MOMS>
01030   inline MOMS& sortByEt(MOMS& pbs) {
01031     return sortBy(pbs, cmpMomByEt);
01032   }
01033   /// Sort a container of momenta by Et (decreasing) and return by value for const inputs
01034   template<typename MOMS>
01035   inline MOMS sortByEt(const MOMS& pbs) {
01036     return sortBy(pbs, cmpMomByEt);
01037   }
01038 
01039   //@}
01040 
01041 
01042   //////////////////////////////////////////////////////
01043 
01044 
01045   /// @name 4-vector string representations
01046   //@{
01047 
01048   /// Render a 4-vector as a string.
01049   inline std::string toString(const FourVector& lv) {
01050     ostringstream out;
01051     out << "("  << (fabs(lv.t()) < 1E-30 ? 0.0 : lv.t())
01052         << "; " << (fabs(lv.x()) < 1E-30 ? 0.0 : lv.x())
01053         << ", " << (fabs(lv.y()) < 1E-30 ? 0.0 : lv.y())
01054         << ", " << (fabs(lv.z()) < 1E-30 ? 0.0 : lv.z())
01055         << ")";
01056     return out.str();
01057   }
01058 
01059   /// Write a 4-vector to an ostream.
01060   inline std::ostream& operator<<(std::ostream& out, const FourVector& lv) {
01061     out << toString(lv);
01062     return out;
01063   }
01064 
01065   //@}
01066 
01067 
01068 }
01069 
01070 #endif