Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:06:47

0001 #ifndef RIVET_MATH_VECTOR3
0002 #define RIVET_MATH_VECTOR3
0003 
0004 #include "Rivet/Tools/TypeTraits.hh"
0005 #include "Rivet/Math/MathConstants.hh"
0006 #include "Rivet/Math/MathUtils.hh"
0007 #include "Rivet/Math/VectorN.hh"
0008 
0009 namespace Rivet {
0010 
0011 
0012   class Vector3;
0013   typedef Vector3 ThreeVector;
0014   typedef Vector3 V3;
0015   Vector3 multiply(const double, const Vector3&);
0016   Vector3 multiply(const Vector3&, const double);
0017   Vector3 add(const Vector3&, const Vector3&);
0018   Vector3 operator*(const double, const Vector3&);
0019   Vector3 operator*(const Vector3&, const double);
0020   Vector3 operator/(const Vector3&, const double);
0021   Vector3 operator+(const Vector3&, const Vector3&);
0022   Vector3 operator-(const Vector3&, const Vector3&);
0023 
0024   class ThreeMomentum;
0025   typedef ThreeMomentum P3;
0026   ThreeMomentum multiply(const double, const ThreeMomentum&);
0027   ThreeMomentum multiply(const ThreeMomentum&, const double);
0028   ThreeMomentum add(const ThreeMomentum&, const ThreeMomentum&);
0029   ThreeMomentum operator*(const double, const ThreeMomentum&);
0030   ThreeMomentum operator*(const ThreeMomentum&, const double);
0031   ThreeMomentum operator/(const ThreeMomentum&, const double);
0032   ThreeMomentum operator+(const ThreeMomentum&, const ThreeMomentum&);
0033   ThreeMomentum operator-(const ThreeMomentum&, const ThreeMomentum&);
0034 
0035   class Matrix3;
0036 
0037 
0038 
0039   /// @brief Three-dimensional specialisation of Vector.
0040   class Vector3 : public Vector<3> {
0041 
0042     friend class Matrix3;
0043     friend Vector3 multiply(const double, const Vector3&);
0044     friend Vector3 multiply(const Vector3&, const double);
0045     friend Vector3 add(const Vector3&, const Vector3&);
0046     friend Vector3 subtract(const Vector3&, const Vector3&);
0047 
0048   public:
0049     Vector3() : Vector<3>() { }
0050 
0051     template<typename V3TYPE>
0052     Vector3(const V3TYPE& other) {
0053       this->setX(other.x());
0054       this->setY(other.y());
0055       this->setZ(other.z());
0056     }
0057 
0058     Vector3(const Vector<3>& other) {
0059       this->setX(other.get(0));
0060       this->setY(other.get(1));
0061       this->setZ(other.get(2));
0062     }
0063 
0064     Vector3(double x, double y, double z) {
0065       this->setX(x);
0066       this->setY(y);
0067       this->setZ(z);
0068     }
0069 
0070     ~Vector3() { }
0071 
0072 
0073   public:
0074 
0075     static Vector3 mkX() { return Vector3(1,0,0); }
0076     static Vector3 mkY() { return Vector3(0,1,0); }
0077     static Vector3 mkZ() { return Vector3(0,0,1); }
0078 
0079 
0080   public:
0081 
0082     double x() const { return get(0); }
0083     double x2() const { return sqr(x()); }
0084     Vector3& setX(double x) { set(0, x); return *this; }
0085 
0086     double y() const { return get(1); }
0087     double y2() const { return sqr(y()); }
0088     Vector3& setY(double y) { set(1, y); return *this; }
0089 
0090     double z() const { return get(2); }
0091     double z2() const { return sqr(z()); }
0092     Vector3& setZ(double z) { set(2, z); return *this; }
0093 
0094 
0095     /// Dot-product with another vector
0096     double dot(const Vector3& v) const {
0097       return _vec.dot(v._vec);
0098     }
0099 
0100     /// Cross-product with another vector
0101     Vector3 cross(const Vector3& v) const {
0102       Vector3 result;
0103       result._vec = _vec.cross(v._vec);
0104       return result;
0105     }
0106 
0107     /// Angle in radians to another vector
0108     double angle(const Vector3& v) const {
0109       const double localDotOther = unit().dot(v.unit());
0110       if (localDotOther > 1.0) return 0.0;
0111       if (localDotOther < -1.0) return M_PI;
0112       return acos(localDotOther);
0113     }
0114 
0115 
0116     /// Unit-normalized version of this vector.
0117     Vector3 unitVec() const {
0118       double md = mod();
0119       if ( md <= 0.0 ) return Vector3();
0120       else return *this * 1.0/md;
0121     }
0122 
0123     /// Synonym for unitVec
0124     Vector3 unit() const {
0125       return unitVec();
0126     }
0127 
0128 
0129     /// Polar projection of this vector into the x-y plane
0130     Vector3 polarVec() const {
0131       Vector3 rtn = *this;
0132       rtn.setZ(0.);
0133       return rtn;
0134     }
0135     /// Synonym for polarVec
0136     Vector3 perpVec() const {
0137       return polarVec();
0138     }
0139     /// Synonym for polarVec
0140     Vector3 rhoVec() const {
0141       return polarVec();
0142     }
0143 
0144     /// Square of the polar radius (
0145     double polarRadius2() const {
0146       return x()*x() + y()*y();
0147     }
0148     /// Synonym for polarRadius2
0149     double perp2() const {
0150       return polarRadius2();
0151     }
0152     /// Synonym for polarRadius2
0153     double rho2() const {
0154       return polarRadius2();
0155     }
0156 
0157     /// Polar radius
0158     double polarRadius() const {
0159       return sqrt(polarRadius2());
0160     }
0161     /// Synonym for polarRadius
0162     double perp() const {
0163       return polarRadius();
0164     }
0165     /// Synonym for polarRadius
0166     double rho() const {
0167       return polarRadius();
0168     }
0169 
0170     /// @brief Angle subtended by the vector's projection in x-y and the x-axis.
0171     ///
0172     /// @note Returns zero in the case of a vector with null x and y components.
0173     /// @todo Would it be better to return NaN in the null-perp case? Or throw?!
0174     double azimuthalAngle(const PhiMapping mapping = ZERO_2PI) const {
0175       // If this has a null perp-vector, return zero rather than let atan2 set an error state
0176       // This isn't necessary if the implementation supports IEEE floating-point arithmetic (IEC 60559)... are we sure?
0177       if (x() == 0 && y() == 0) return 0.0; //< Or return nan / throw an exception?
0178       // Calculate the arctan and return in the requested range
0179       const double value = atan2( y(), x() );
0180       return mapAngle(value, mapping);
0181     }
0182     /// Synonym for azimuthalAngle.
0183     double phi(const PhiMapping mapping = ZERO_2PI) const {
0184       return azimuthalAngle(mapping);
0185     }
0186 
0187     /// Tangent of the polar angle
0188     double tanTheta() const {
0189       return polarRadius()/z();
0190     }
0191 
0192     /// Angle subtended by the vector and the z-axis.
0193     double polarAngle() const {
0194       // Get number beween [0,PI]
0195       const double polarangle = atan2(polarRadius(), z());
0196       return mapAngle0ToPi(polarangle);
0197     }
0198 
0199     /// Synonym for polarAngle
0200     double theta() const {
0201       return polarAngle();
0202     }
0203 
0204     /// @brief Purely geometric approximation to rapidity
0205     ///
0206     /// eta = -ln[ tan(theta/2) ]
0207     ///
0208     /// Also invariant under z-boosts, equal to y for massless particles.
0209     ///
0210     /// Implemented using the tan half-angle formula
0211     /// tan(theta/2) = sin(theta) / [1 + cos(theta)] = pT / (p + pz)
0212     double pseudorapidity() const {
0213       if (mod() == 0.0) return 0.0; ///< @todo Add [[ unlikely ]] with C++20
0214       if (mod() == fabs(z()) ) return std::copysign(INF, z()); ///< @todo Add [[ unlikely ]] with C++20
0215       const double eta = std::log((mod() + fabs(z())) / perp());
0216       return std::copysign(eta, z());
0217     }
0218 
0219     /// Synonym for pseudorapidity
0220     double eta() const {
0221       return pseudorapidity();
0222     }
0223 
0224     /// Convenience shortcut for fabs(eta())
0225     double abseta() const {
0226       return fabs(eta());
0227     }
0228 
0229 
0230   public:
0231 
0232     /// In-place scalar multiplication operator
0233     Vector3& operator *= (const double a) {
0234       _vec = multiply(a, *this)._vec;
0235       return *this;
0236     }
0237 
0238     /// In-place scalar division operator
0239     Vector3& operator /= (const double a) {
0240       _vec = multiply(1.0/a, *this)._vec;
0241       return *this;
0242     }
0243 
0244     /// In-place addition operator
0245     Vector3& operator += (const Vector3& v) {
0246       _vec = add(*this, v)._vec;
0247       return *this;
0248     }
0249 
0250     /// In-place subtraction operator
0251     Vector3& operator -= (const Vector3& v) {
0252       _vec = subtract(*this, v)._vec;
0253       return *this;
0254     }
0255 
0256     /// In-place negation operator
0257     Vector3 operator - () const {
0258       Vector3 rtn;
0259       rtn._vec = -_vec;
0260       return rtn;
0261     }
0262 
0263   };
0264 
0265 
0266 
0267   /// Unbound dot-product function
0268   inline double dot(const Vector3& a, const Vector3& b) {
0269     return a.dot(b);
0270   }
0271 
0272   /// Unbound cross-product function
0273   inline Vector3 cross(const Vector3& a, const Vector3& b) {
0274     return a.cross(b);
0275   }
0276 
0277   /// Unbound scalar-product function
0278   inline Vector3 multiply(const double a, const Vector3& v) {
0279     Vector3 result;
0280     result._vec = a * v._vec;
0281     return result;
0282   }
0283 
0284   /// Unbound scalar-product function
0285   inline Vector3 multiply(const Vector3& v, const double a) {
0286     return multiply(a, v);
0287   }
0288 
0289   /// Unbound scalar multiplication operator
0290   inline Vector3 operator * (const double a, const Vector3& v) {
0291     return multiply(a, v);
0292   }
0293 
0294   /// Unbound scalar multiplication operator
0295   inline Vector3 operator * (const Vector3& v, const double a) {
0296     return multiply(a, v);
0297   }
0298 
0299   /// Unbound scalar division operator
0300   inline Vector3 operator / (const Vector3& v, const double a) {
0301     return multiply(1.0/a, v);
0302   }
0303 
0304   /// Unbound vector addition function
0305   inline Vector3 add(const Vector3& a, const Vector3& b) {
0306     Vector3 result;
0307     result._vec = a._vec + b._vec;
0308     return result;
0309   }
0310 
0311   /// Unbound vector subtraction function
0312   inline Vector3 subtract(const Vector3& a, const Vector3& b) {
0313     Vector3 result;
0314     result._vec = a._vec - b._vec;
0315     return result;
0316   }
0317 
0318   /// Unbound vector addition operator
0319   inline Vector3 operator + (const Vector3& a, const Vector3& b) {
0320     return add(a, b);
0321   }
0322 
0323   /// Unbound vector subtraction operator
0324   inline Vector3 operator - (const Vector3& a, const Vector3& b) {
0325     return subtract(a, b);
0326   }
0327 
0328   // More physicsy coordinates etc.
0329 
0330   /// Angle (in radians) between two 3-vectors.
0331   inline double angle(const Vector3& a, const Vector3& b) {
0332     return a.angle(b);
0333   }
0334 
0335 
0336   /////////////////////////////////////////////////////
0337 
0338 
0339   /// Specialized version of the ThreeVector with momentum functionality.
0340   class ThreeMomentum : public ThreeVector {
0341   public:
0342     ThreeMomentum() { }
0343 
0344     template<typename V3TYPE, typename std::enable_if<HasXYZ<V3TYPE>::value, int>::type DUMMY=0>
0345     ThreeMomentum(const V3TYPE& other) {
0346       this->setPx(other.x());
0347       this->setPy(other.y());
0348       this->setPz(other.z());
0349     }
0350 
0351     ThreeMomentum(const Vector<3>& other)
0352       : ThreeVector(other) { }
0353 
0354     ThreeMomentum(const double px, const double py, const double pz) {
0355       this->setPx(px);
0356       this->setPy(py);
0357       this->setPz(pz);
0358     }
0359 
0360     ~ThreeMomentum() {}
0361 
0362   public:
0363 
0364 
0365     /// @name Coordinate setters
0366     /// @{
0367 
0368     /// Set x-component of momentum \f$ p_x \f$.
0369     ThreeMomentum& setPx(double px) {
0370       setX(px);
0371       return *this;
0372     }
0373 
0374     /// Set y-component of momentum \f$ p_y \f$.
0375     ThreeMomentum& setPy(double py) {
0376       setY(py);
0377       return *this;
0378     }
0379 
0380     /// Set z-component of momentum \f$ p_z \f$.
0381     ThreeMomentum& setPz(double pz) {
0382       setZ(pz);
0383       return *this;
0384     }
0385 
0386     /// @}
0387 
0388 
0389     /// @name Accessors
0390     /// @{
0391 
0392     /// Get x-component of momentum \f$ p_x \f$.
0393     double px() const { return x(); }
0394     /// Get x-squared \f$ p_x^2 \f$.
0395     double px2() const { return x2(); }
0396 
0397     /// Get y-component of momentum \f$ p_y \f$.
0398     double py() const { return y(); }
0399     /// Get y-squared \f$ p_y^2 \f$.
0400     double py2() const { return y2(); }
0401 
0402     /// Get z-component of momentum \f$ p_z \f$.
0403     double pz() const { return z(); }
0404     /// Get z-squared \f$ p_z^2 \f$.
0405     double pz2() const { return z2(); }
0406 
0407 
0408     /// Get the modulus of the 3-momentum
0409     double p() const { return mod(); }
0410     /// Get the modulus-squared of the 3-momentum
0411     double p2() const { return mod2(); }
0412 
0413 
0414     /// Calculate the transverse momentum vector \f$ \vec{p}_T \f$.
0415     ThreeMomentum pTvec() const {
0416       return polarVec();
0417     }
0418     /// Synonym for pTvec
0419     ThreeMomentum ptvec() const {
0420       return pTvec();
0421     }
0422 
0423     /// Calculate the squared transverse momentum \f$ p_T^2 \f$.
0424     double pT2() const {
0425       return polarRadius2();
0426     }
0427     /// Calculate the squared transverse momentum \f$ p_T^2 \f$.
0428     double pt2() const {
0429       return polarRadius2();
0430     }
0431 
0432     /// Calculate the transverse momentum \f$ p_T \f$.
0433     double pT() const {
0434       return sqrt(pT2());
0435     }
0436     /// Calculate the transverse momentum \f$ p_T \f$.
0437     double pt() const {
0438       return sqrt(pT2());
0439     }
0440 
0441     /// @}
0442 
0443 
0444     ////////////////////////////////////////
0445 
0446 
0447     /// @name Arithmetic operators (needed again for covariant returns)
0448     /// @{
0449 
0450     /// Multiply by a scalar
0451     ThreeMomentum& operator *= (double a) {
0452       _vec = multiply(a, *this)._vec;
0453       return *this;
0454     }
0455 
0456     /// Divide by a scalar
0457     ThreeMomentum& operator /= (double a) {
0458       _vec = multiply(1.0/a, *this)._vec;
0459       return *this;
0460     }
0461 
0462     /// Add two 3-momenta
0463     ThreeMomentum& operator += (const ThreeMomentum& v) {
0464       _vec = add(*this, v)._vec;
0465       return *this;
0466     }
0467 
0468     /// Subtract two 3-momenta
0469     ThreeMomentum& operator -= (const ThreeMomentum& v) {
0470       _vec = add(*this, -v)._vec;
0471       return *this;
0472     }
0473 
0474     /// Multiply all components by -1.
0475     ThreeMomentum operator - () const {
0476       ThreeMomentum result;
0477       result._vec = -_vec;
0478       return result;
0479     }
0480 
0481     // /// Multiply space (i.e. all!) components by -1.
0482     // ThreeMomentum reverse() const {
0483     //   return -*this;
0484     // }
0485 
0486     /// @}
0487 
0488   };
0489 
0490 
0491   inline ThreeMomentum multiply(const double a, const ThreeMomentum& v) {
0492     ThreeMomentum result;
0493     result._vec = a * v._vec;
0494     return result;
0495   }
0496 
0497   inline ThreeMomentum multiply(const ThreeMomentum& v, const double a) {
0498     return multiply(a, v);
0499   }
0500 
0501   inline ThreeMomentum operator*(const double a, const ThreeMomentum& v) {
0502     return multiply(a, v);
0503   }
0504 
0505   inline ThreeMomentum operator*(const ThreeMomentum& v, const double a) {
0506     return multiply(a, v);
0507   }
0508 
0509   inline ThreeMomentum operator/(const ThreeMomentum& v, const double a) {
0510     return multiply(1.0/a, v);
0511   }
0512 
0513   inline ThreeMomentum add(const ThreeMomentum& a, const ThreeMomentum& b) {
0514     ThreeMomentum result;
0515     result._vec = a._vec + b._vec;
0516     return result;
0517   }
0518 
0519   inline ThreeMomentum operator+(const ThreeMomentum& a, const ThreeMomentum& b) {
0520     return add(a, b);
0521   }
0522 
0523   inline ThreeMomentum operator-(const ThreeMomentum& a, const ThreeMomentum& b) {
0524     return add(a, -b);
0525   }
0526 
0527 
0528   /// @todo Mixed-arg operators: better via SFINAE??
0529   /// @note Why *does* this actually cause compiler trouble, given (V3, V3) is a correct sig-match for (V3,P3) and (P3, P3) is not?
0530   inline Vector3 operator+(const ThreeMomentum& a, const Vector3& b) {
0531     return add(static_cast<const Vector3&>(a), b);
0532   }
0533   inline Vector3 operator+(const Vector3& a, const ThreeMomentum& b) {
0534     return add(a, static_cast<const Vector3&>(b));
0535   }
0536 
0537   inline Vector3 operator-(const ThreeMomentum& a, const Vector3& b) {
0538     return add(static_cast<const Vector3&>(a), -b);
0539   }
0540   inline Vector3 operator-(const Vector3& a, const ThreeMomentum& b) {
0541     return add(a, -static_cast<const Vector3&>(b));
0542   }
0543 
0544 
0545 
0546   /////////////////////////////////////////////////////
0547 
0548 
0549   /// @defgroup momutils_vec3_deta \f$ |\Delta eta| \f$ calculations from 3-vectors
0550   /// @{
0551 
0552   /// Calculate the difference in pseudorapidity between two spatial vectors.
0553   inline double deltaEta(const Vector3& a, const Vector3& b, bool sign=false) {
0554     return deltaEta(a.pseudorapidity(), b.pseudorapidity(), sign);
0555   }
0556 
0557   /// Calculate the difference in pseudorapidity between two spatial vectors.
0558   inline double deltaEta(const Vector3& v, double eta2, bool sign=false) {
0559     return deltaEta(v.pseudorapidity(), eta2, sign);
0560   }
0561 
0562   /// Calculate the difference in pseudorapidity between two spatial vectors.
0563   inline double deltaEta(double eta1, const Vector3& v, bool sign=false) {
0564     return deltaEta(eta1, v.pseudorapidity(), sign);
0565   }
0566 
0567   /// @}
0568 
0569 
0570   /// @defgroup momutils_vec3_dphi \f$ \Delta phi \f$ calculations from 3-vectors
0571   /// @{
0572 
0573   /// Calculate the difference in azimuthal angle between two spatial vectors.
0574   inline double deltaPhi(const Vector3& a, const Vector3& b, bool sign=false) {
0575     return deltaPhi(a.azimuthalAngle(), b.azimuthalAngle(), sign);
0576   }
0577 
0578   /// Calculate the difference in azimuthal angle between two spatial vectors.
0579   inline double deltaPhi(const Vector3& v, double phi2, bool sign=false) {
0580     return deltaPhi(v.azimuthalAngle(), phi2, sign);
0581   }
0582 
0583   /// Calculate the difference in azimuthal angle between two spatial vectors.
0584   inline double deltaPhi(double phi1, const Vector3& v, bool sign=false) {
0585     return deltaPhi(phi1, v.azimuthalAngle(), sign);
0586   }
0587 
0588   /// @}
0589 
0590 
0591   /// @defgroup momutils_vec3_dr \f$ \Delta R \f$ calculations from 3-vectors
0592   /// @{
0593 
0594   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
0595   inline double deltaR2(const Vector3& a, const Vector3& b) {
0596     return deltaR2(a.pseudorapidity(), a.azimuthalAngle(),
0597                    b.pseudorapidity(), b.azimuthalAngle());
0598   }
0599 
0600   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
0601   inline double deltaR(const Vector3& a, const Vector3& b) {
0602     return sqrt(deltaR2(a,b));
0603   }
0604 
0605   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
0606   inline double deltaR2(const Vector3& v, double eta2, double phi2) {
0607     return deltaR2(v.pseudorapidity(), v.azimuthalAngle(), eta2, phi2);
0608   }
0609 
0610   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
0611   inline double deltaR(const Vector3& v, double eta2, double phi2) {
0612     return sqrt(deltaR2(v, eta2, phi2));
0613   }
0614 
0615   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
0616   inline double deltaR2(double eta1, double phi1, const Vector3& v) {
0617     return deltaR2(eta1, phi1, v.pseudorapidity(), v.azimuthalAngle());
0618   }
0619 
0620   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two spatial vectors.
0621   inline double deltaR(double eta1, double phi1, const Vector3& v) {
0622     return sqrt(deltaR2(eta1, phi1, v));
0623   }
0624 
0625   /// @}
0626 
0627 
0628   /// @defgroup momutils_vec3_mt MT calculation
0629   /// @{
0630 
0631   /// Calculate transverse mass of a visible and an invisible 3-vector
0632   ///
0633   /// @note Note assumption of zero-mass particles
0634   inline double mT(const Vector3& vis, const Vector3& invis) {
0635     // return sqrt(2*vis.perp()*invis.perp() * (1 - cos(deltaPhi(vis, invis))) );
0636     return mT(vis.perp(), invis.perp(), deltaPhi(vis, invis));
0637   }
0638 
0639   /// Calculate transverse momentum of pair of 3-vectors
0640   inline double pT(const Vector3& a, const Vector3& b) {
0641     return (a+b).perp();
0642   }
0643 
0644   /// @}
0645 
0646 
0647 }
0648 
0649 #endif