File indexing completed on 2026-01-01 09:59:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef ROOT_Math_GenVector_LorentzVector
0019 #define ROOT_Math_GenVector_LorentzVector 1
0020
0021 #include "Math/GenVector/PxPyPzE4D.h"
0022 #include "Math/GenVector/DisplacementVector3D.h"
0023 #include "Math/GenVector/GenVectorIO.h"
0024 #include "Math/Vector2D.h"
0025
0026 #include "TMath.h"
0027
0028 #include <cmath>
0029 #include <string>
0030
0031 namespace ROOT {
0032
0033 namespace Math {
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 template< class CoordSystem >
0061 class LorentzVector {
0062
0063 public:
0064
0065
0066
0067 typedef typename CoordSystem::Scalar Scalar;
0068 typedef CoordSystem CoordinateType;
0069
0070
0071
0072
0073 LorentzVector ( ) : fCoordinates() { }
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 LorentzVector(const Scalar & a,
0085 const Scalar & b,
0086 const Scalar & c,
0087 const Scalar & d) :
0088 fCoordinates(a , b, c, d) { }
0089
0090
0091
0092
0093
0094 template< class Coords >
0095 explicit constexpr LorentzVector(const LorentzVector<Coords> & v ) :
0096 fCoordinates( v.Coordinates() ) { }
0097
0098
0099
0100
0101
0102 template<class ForeignLorentzVector,
0103 typename = decltype(std::declval<ForeignLorentzVector>().x()
0104 + std::declval<ForeignLorentzVector>().y()
0105 + std::declval<ForeignLorentzVector>().z()
0106 + std::declval<ForeignLorentzVector>().t())>
0107 explicit constexpr LorentzVector( const ForeignLorentzVector & v) :
0108 fCoordinates(PxPyPzE4D<Scalar>( v.x(), v.y(), v.z(), v.t() ) ) { }
0109
0110 #ifdef LATER
0111
0112
0113
0114
0115
0116
0117
0118
0119 template< class LAVector >
0120 explicit constexpr LorentzVector(const LAVector & v, size_t index0 ) {
0121 fCoordinates = CoordSystem ( v[index0], v[index0+1], v[index0+2], v[index0+3] );
0122 }
0123 #endif
0124
0125
0126
0127
0128
0129
0130
0131 template< class OtherCoords >
0132 LorentzVector & operator= ( const LorentzVector<OtherCoords> & v) {
0133 fCoordinates = v.Coordinates();
0134 return *this;
0135 }
0136
0137
0138
0139
0140
0141 template<class ForeignLorentzVector,
0142 typename = decltype(std::declval<ForeignLorentzVector>().x()
0143 + std::declval<ForeignLorentzVector>().y()
0144 + std::declval<ForeignLorentzVector>().z()
0145 + std::declval<ForeignLorentzVector>().t())>
0146 LorentzVector & operator = ( const ForeignLorentzVector & v) {
0147 SetXYZT( v.x(), v.y(), v.z(), v.t() );
0148 return *this;
0149 }
0150
0151 #ifdef LATER
0152
0153
0154
0155
0156
0157
0158
0159
0160 template< class LAVector >
0161 LorentzVector & AssignFrom(const LAVector & v, size_t index0=0 ) {
0162 fCoordinates.SetCoordinates( v[index0], v[index0+1], v[index0+2], v[index0+3] );
0163 return *this;
0164 }
0165 #endif
0166
0167
0168
0169
0170
0171
0172 const CoordSystem & Coordinates() const {
0173 return fCoordinates;
0174 }
0175
0176
0177
0178
0179 LorentzVector<CoordSystem>& SetCoordinates( const Scalar src[] ) {
0180 fCoordinates.SetCoordinates(src);
0181 return *this;
0182 }
0183
0184
0185
0186
0187 LorentzVector<CoordSystem>& SetCoordinates( Scalar a, Scalar b, Scalar c, Scalar d ) {
0188 fCoordinates.SetCoordinates(a, b, c, d);
0189 return *this;
0190 }
0191
0192
0193
0194
0195 template< class IT >
0196 LorentzVector<CoordSystem>& SetCoordinates( IT begin, IT end ) {
0197 IT a = begin; IT b = ++begin; IT c = ++begin; IT d = ++begin;
0198 (void)end;
0199 assert (++begin==end);
0200 SetCoordinates (*a,*b,*c,*d);
0201 return *this;
0202 }
0203
0204
0205
0206
0207
0208 void GetCoordinates( Scalar& a, Scalar& b, Scalar& c, Scalar & d ) const
0209 { fCoordinates.GetCoordinates(a, b, c, d); }
0210
0211
0212
0213
0214 void GetCoordinates( Scalar dest[] ) const
0215 { fCoordinates.GetCoordinates(dest); }
0216
0217
0218
0219
0220 template <class IT>
0221 void GetCoordinates( IT begin, IT end ) const
0222 { IT a = begin; IT b = ++begin; IT c = ++begin; IT d = ++begin;
0223 (void)end;
0224 assert (++begin==end);
0225 GetCoordinates (*a,*b,*c,*d);
0226 }
0227
0228
0229
0230
0231 template <class IT>
0232 void GetCoordinates( IT begin ) const {
0233 Scalar a,b,c,d = 0;
0234 GetCoordinates (a,b,c,d);
0235 *begin++ = a;
0236 *begin++ = b;
0237 *begin++ = c;
0238 *begin = d;
0239 }
0240
0241
0242
0243
0244
0245
0246 LorentzVector<CoordSystem>& SetXYZT (Scalar xx, Scalar yy, Scalar zz, Scalar tt) {
0247 fCoordinates.SetPxPyPzE(xx,yy,zz,tt);
0248 return *this;
0249 }
0250 LorentzVector<CoordSystem>& SetPxPyPzE (Scalar xx, Scalar yy, Scalar zz, Scalar ee) {
0251 fCoordinates.SetPxPyPzE(xx,yy,zz,ee);
0252 return *this;
0253 }
0254
0255
0256
0257
0258
0259
0260 bool operator==(const LorentzVector & rhs) const {
0261 return fCoordinates==rhs.fCoordinates;
0262 }
0263 bool operator!= (const LorentzVector & rhs) const {
0264 return !(operator==(rhs));
0265 }
0266
0267
0268
0269
0270
0271
0272 unsigned int Dimension() const
0273 {
0274 return fDimension;
0275 };
0276
0277
0278
0279
0280
0281
0282 Scalar Px() const { return fCoordinates.Px(); }
0283 Scalar X() const { return fCoordinates.Px(); }
0284
0285
0286
0287 Scalar Py() const { return fCoordinates.Py(); }
0288 Scalar Y() const { return fCoordinates.Py(); }
0289
0290
0291
0292 Scalar Pz() const { return fCoordinates.Pz(); }
0293 Scalar Z() const { return fCoordinates.Pz(); }
0294
0295
0296
0297 Scalar E() const { return fCoordinates.E(); }
0298 Scalar T() const { return fCoordinates.E(); }
0299
0300
0301
0302
0303 Scalar M2() const { return fCoordinates.M2(); }
0304
0305
0306
0307
0308
0309 Scalar M() const { return fCoordinates.M();}
0310
0311
0312
0313 Scalar R() const { return fCoordinates.R(); }
0314 Scalar P() const { return fCoordinates.R(); }
0315
0316
0317
0318 Scalar P2() const { return P() * P(); }
0319
0320
0321
0322 Scalar Perp2( ) const { return fCoordinates.Perp2();}
0323
0324
0325
0326
0327 Scalar Pt() const { return fCoordinates.Pt(); }
0328 Scalar Rho() const { return fCoordinates.Pt(); }
0329
0330
0331
0332
0333
0334 Scalar Mt2() const { return fCoordinates.Mt2(); }
0335
0336
0337
0338
0339
0340 Scalar Mt() const { return fCoordinates.Mt(); }
0341
0342
0343
0344
0345
0346 Scalar Et2() const { return fCoordinates.Et2(); }
0347
0348
0349
0350
0351
0352 Scalar Et() const { return fCoordinates.Et(); }
0353
0354
0355
0356
0357 Scalar Phi() const { return fCoordinates.Phi();}
0358
0359
0360
0361
0362 Scalar Theta() const { return fCoordinates.Theta(); }
0363
0364
0365
0366
0367
0368 Scalar Eta() const { return fCoordinates.Eta(); }
0369
0370
0371
0372
0373
0374
0375 template <class OtherLorentzVector>
0376 Scalar DeltaR(const OtherLorentzVector &v, const bool useRapidity = false) const
0377 {
0378 const double delta = useRapidity ? Rapidity() - v.Rapidity() : Eta() - v.Eta();
0379 double dphi = Phi() - v.Phi();
0380
0381 if (dphi > TMath::Pi() || dphi <= -TMath::Pi()) {
0382 if (dphi > 0) {
0383 int n = static_cast<int>(dphi / TMath::TwoPi() + 0.5);
0384 dphi -= TMath::TwoPi() * n;
0385 } else {
0386 int n = static_cast<int>(0.5 - dphi / TMath::TwoPi());
0387 dphi += TMath::TwoPi() * n;
0388 }
0389 }
0390 return std::sqrt(delta * delta + dphi * dphi);
0391 }
0392
0393
0394
0395
0396
0397 ::ROOT::Math::DisplacementVector3D<Cartesian3D<Scalar> > Vect() const {
0398 return ::ROOT::Math::DisplacementVector3D<Cartesian3D<Scalar> >( X(), Y(), Z() );
0399 }
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 template< class OtherLorentzVector >
0413 Scalar Dot(const OtherLorentzVector & q) const {
0414 return t()*q.t() - x()*q.x() - y()*q.y() - z()*q.z();
0415 }
0416
0417
0418
0419
0420
0421
0422
0423 template< class OtherLorentzVector >
0424 inline LorentzVector & operator += ( const OtherLorentzVector & q)
0425 {
0426 SetXYZT( x() + q.x(), y() + q.y(), z() + q.z(), t() + q.t() );
0427 return *this;
0428 }
0429
0430
0431
0432
0433
0434
0435
0436 template< class OtherLorentzVector >
0437 LorentzVector & operator -= ( const OtherLorentzVector & q) {
0438 SetXYZT( x() - q.x(), y() - q.y(), z() - q.z(), t() - q.t() );
0439 return *this;
0440 }
0441
0442
0443
0444
0445
0446
0447
0448
0449 template<class OtherLorentzVector>
0450 LorentzVector operator + ( const OtherLorentzVector & v2) const
0451 {
0452 LorentzVector<CoordinateType> v3(*this);
0453 v3 += v2;
0454 return v3;
0455 }
0456
0457
0458
0459
0460
0461
0462
0463
0464 template<class OtherLorentzVector>
0465 LorentzVector operator - ( const OtherLorentzVector & v2) const {
0466 LorentzVector<CoordinateType> v3(*this);
0467 v3 -= v2;
0468 return v3;
0469 }
0470
0471
0472
0473
0474
0475
0476 LorentzVector & operator *= (Scalar a) {
0477 fCoordinates.Scale(a);
0478 return *this;
0479 }
0480
0481
0482
0483
0484 LorentzVector & operator /= (Scalar a) {
0485 fCoordinates.Scale(1/a);
0486 return *this;
0487 }
0488
0489
0490
0491
0492
0493
0494 LorentzVector operator * ( const Scalar & a) const {
0495 LorentzVector tmp(*this);
0496 tmp *= a;
0497 return tmp;
0498 }
0499
0500
0501
0502
0503
0504
0505 LorentzVector<CoordSystem> operator / ( const Scalar & a) const {
0506 LorentzVector<CoordSystem> tmp(*this);
0507 tmp /= a;
0508 return tmp;
0509 }
0510
0511
0512
0513
0514
0515 LorentzVector operator - () const {
0516
0517
0518 return operator*( Scalar(-1) );
0519 }
0520 LorentzVector operator + () const {
0521 return *this;
0522 }
0523
0524
0525
0526
0527
0528
0529 Scalar Rapidity() const {
0530
0531
0532
0533 const Scalar ee = E();
0534 const Scalar ppz = Pz();
0535 using std::log;
0536 return Scalar(0.5) * log((ee + ppz) / (ee - ppz));
0537 }
0538
0539
0540
0541
0542 Scalar ColinearRapidity() const {
0543
0544
0545 const Scalar ee = E();
0546 const Scalar pp = P();
0547 using std::log;
0548 return Scalar(0.5) * log((ee + pp) / (ee - pp));
0549 }
0550
0551
0552
0553
0554 bool isTimelike( ) const {
0555 Scalar ee = E(); Scalar pp = P(); return ee*ee > pp*pp;
0556 }
0557
0558
0559
0560
0561 bool isLightlike( Scalar tolerance
0562 = 100*std::numeric_limits<Scalar>::epsilon() ) const {
0563 Scalar ee = E(); Scalar pp = P(); Scalar delta = ee-pp;
0564 if ( ee==0 ) return pp==0;
0565 return delta*delta < tolerance * ee*ee;
0566 }
0567
0568
0569
0570
0571 bool isSpacelike( ) const {
0572 Scalar ee = E(); Scalar pp = P(); return ee*ee < pp*pp;
0573 }
0574
0575 typedef DisplacementVector3D< Cartesian3D<Scalar> > BetaVector;
0576
0577
0578
0579
0580
0581 BetaVector BoostToCM( ) const {
0582 if (E() == 0) {
0583 if (P() == 0) {
0584 return BetaVector();
0585 } else {
0586
0587
0588 return -Vect()/E();
0589 }
0590 }
0591 if (M2() <= 0) {
0592
0593
0594 }
0595 return -Vect()/E();
0596 }
0597
0598
0599
0600
0601
0602 template <class Other4Vector>
0603 BetaVector BoostToCM(const Other4Vector& v ) const {
0604 Scalar eSum = E() + v.E();
0605 DisplacementVector3D< Cartesian3D<Scalar> > vecSum = Vect() + v.Vect();
0606 if (eSum == 0) {
0607 if (vecSum.Mag2() == 0) {
0608 return BetaVector();
0609 } else {
0610
0611
0612 return BetaVector(vecSum/eSum);
0613 }
0614
0615
0616 }
0617 return BetaVector (vecSum * (-1./eSum));
0618 }
0619
0620
0621
0622
0623
0624
0625 Scalar Beta() const {
0626 if ( E() == 0 ) {
0627 if ( P2() == 0)
0628
0629 return 0;
0630 else {
0631 GenVector_Throw(
0632 "LorentzVector::Beta() - beta computed for LorentzVector with t = 0. Return an Infinite result");
0633 return 1./E();
0634 }
0635 }
0636 if ( M2() <= 0 ) {
0637 GenVector_Throw("LorentzVector::Beta() - beta computed for non-timelike LorentzVector . Result is "
0638 "physically meaningless");
0639 }
0640 return P() / E();
0641 }
0642
0643
0644
0645 Scalar Gamma() const {
0646 const Scalar v2 = P2();
0647 const Scalar t2 = E() * E();
0648 if (E() == 0) {
0649 if ( P2() == 0) {
0650 return 1;
0651 } else {
0652 GenVector_Throw(
0653 "LorentzVector::Gamma() - gamma computed for LorentzVector with t = 0. Return a zero result");
0654 }
0655 }
0656 if ( t2 < v2 ) {
0657 GenVector_Throw("LorentzVector::Gamma() - gamma computed for a spacelike LorentzVector. Imaginary result");
0658 return 0;
0659 }
0660 else if ( t2 == v2 ) {
0661 GenVector_Throw("LorentzVector::Gamma() - gamma computed for a lightlike LorentzVector. Infinite result");
0662 }
0663 using std::sqrt;
0664 return Scalar(1) / sqrt(Scalar(1) - v2 / t2);
0665 }
0666
0667
0668
0669
0670 Scalar x() const { return fCoordinates.Px(); }
0671 Scalar y() const { return fCoordinates.Py(); }
0672 Scalar z() const { return fCoordinates.Pz(); }
0673 Scalar t() const { return fCoordinates.E(); }
0674 Scalar px() const { return fCoordinates.Px(); }
0675 Scalar py() const { return fCoordinates.Py(); }
0676 Scalar pz() const { return fCoordinates.Pz(); }
0677 Scalar e() const { return fCoordinates.E(); }
0678 Scalar r() const { return fCoordinates.R(); }
0679 Scalar theta() const { return fCoordinates.Theta(); }
0680 Scalar phi() const { return fCoordinates.Phi(); }
0681 Scalar rho() const { return fCoordinates.Rho(); }
0682 Scalar eta() const { return fCoordinates.Eta(); }
0683 Scalar pt() const { return fCoordinates.Pt(); }
0684 Scalar perp2() const { return fCoordinates.Perp2(); }
0685 Scalar mag2() const { return fCoordinates.M2(); }
0686 Scalar mag() const { return fCoordinates.M(); }
0687 Scalar mt() const { return fCoordinates.Mt(); }
0688 Scalar mt2() const { return fCoordinates.Mt2(); }
0689
0690
0691
0692 Scalar energy() const { return fCoordinates.E(); }
0693 Scalar mass() const { return fCoordinates.M(); }
0694 Scalar mass2() const { return fCoordinates.M2(); }
0695
0696
0697
0698
0699
0700
0701
0702 LorentzVector<CoordSystem>& SetE ( Scalar a ) { fCoordinates.SetE (a); return *this; }
0703 LorentzVector<CoordSystem>& SetEta( Scalar a ) { fCoordinates.SetEta(a); return *this; }
0704 LorentzVector<CoordSystem>& SetM ( Scalar a ) { fCoordinates.SetM (a); return *this; }
0705 LorentzVector<CoordSystem>& SetPhi( Scalar a ) { fCoordinates.SetPhi(a); return *this; }
0706 LorentzVector<CoordSystem>& SetPt ( Scalar a ) { fCoordinates.SetPt (a); return *this; }
0707 LorentzVector<CoordSystem>& SetPx ( Scalar a ) { fCoordinates.SetPx (a); return *this; }
0708 LorentzVector<CoordSystem>& SetPy ( Scalar a ) { fCoordinates.SetPy (a); return *this; }
0709 LorentzVector<CoordSystem>& SetPz ( Scalar a ) { fCoordinates.SetPz (a); return *this; }
0710
0711 private:
0712
0713 CoordSystem fCoordinates;
0714 static constexpr unsigned int fDimension = CoordinateType::Dimension;
0715
0716 };
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728 template <class CoordSystem>
0729 inline LorentzVector<CoordSystem>
0730 operator*(const typename LorentzVector<CoordSystem>::Scalar &a, const LorentzVector<CoordSystem> &v)
0731 {
0732 LorentzVector<CoordSystem> tmp(v);
0733 tmp *= a;
0734 return tmp;
0735 }
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745 template <class CoordSystem>
0746 typename LorentzVector<CoordSystem>::Scalar
0747 Acoplanarity(LorentzVector<CoordSystem> const &pp, LorentzVector<CoordSystem> const &pm)
0748 {
0749 auto dphi = pp.Phi() - pm.Phi();
0750
0751 if (dphi > TMath::Pi() || dphi <= -TMath::Pi()) {
0752 if (dphi > 0) {
0753 int n = static_cast<int>(dphi / TMath::TwoPi() + 0.5);
0754 dphi -= TMath::TwoPi() * n;
0755 } else {
0756 int n = static_cast<int>(0.5 - dphi / TMath::TwoPi());
0757 dphi += TMath::TwoPi() * n;
0758 }
0759 }
0760 return 1 - std::abs(dphi) / TMath::Pi();
0761 }
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773 template <class CoordSystem>
0774 typename LorentzVector<CoordSystem>::Scalar
0775 AsymmetryVectorial(LorentzVector<CoordSystem> const &pp, LorentzVector<CoordSystem> const &pm)
0776 {
0777 ROOT::Math::XYVector vp(pp.Px(), pp.Py());
0778 ROOT::Math::XYVector vm(pm.Px(), pm.Py());
0779 auto denom = (vp + vm).R();
0780 if (denom == 0.)
0781 return -1;
0782 return (vp - vm).R() / denom;
0783 }
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795 template< class CoordSystem >
0796 typename LorentzVector<CoordSystem>::Scalar AsymmetryScalar(LorentzVector<CoordSystem> const &pp, LorentzVector<CoordSystem> const &pm)
0797 {
0798 auto ptp = pp.Pt();
0799 auto ptm = pm.Pt();
0800 if (ptp == 0 && ptm == 0)
0801 return 0;
0802 return std::abs(ptp - ptm) / (ptp + ptm);
0803 }
0804
0805
0806
0807 template< class char_t, class traits_t, class Coords >
0808 inline
0809 std::basic_ostream<char_t,traits_t> &
0810 operator << ( std::basic_ostream<char_t,traits_t> & os
0811 , LorentzVector<Coords> const & v
0812 )
0813 {
0814 if( !os ) return os;
0815
0816 typename Coords::Scalar a, b, c, d;
0817 v.GetCoordinates(a, b, c, d);
0818
0819 if( detail::get_manip( os, detail::bitforbit ) ) {
0820 detail::set_manip( os, detail::bitforbit, '\00' );
0821
0822 }
0823 else {
0824 os << detail::get_manip( os, detail::open ) << a
0825 << detail::get_manip( os, detail::sep ) << b
0826 << detail::get_manip( os, detail::sep ) << c
0827 << detail::get_manip( os, detail::sep ) << d
0828 << detail::get_manip( os, detail::close );
0829 }
0830
0831 return os;
0832
0833 }
0834
0835
0836 template< class char_t, class traits_t, class Coords >
0837 inline
0838 std::basic_istream<char_t,traits_t> &
0839 operator >> ( std::basic_istream<char_t,traits_t> & is
0840 , LorentzVector<Coords> & v
0841 )
0842 {
0843 if( !is ) return is;
0844
0845 typename Coords::Scalar a, b, c, d;
0846
0847 if( detail::get_manip( is, detail::bitforbit ) ) {
0848 detail::set_manip( is, detail::bitforbit, '\00' );
0849
0850 }
0851 else {
0852 detail::require_delim( is, detail::open ); is >> a;
0853 detail::require_delim( is, detail::sep ); is >> b;
0854 detail::require_delim( is, detail::sep ); is >> c;
0855 detail::require_delim( is, detail::sep ); is >> d;
0856 detail::require_delim( is, detail::close );
0857 }
0858
0859 if( is )
0860 v.SetCoordinates(a, b, c, d);
0861 return is;
0862
0863 }
0864
0865
0866 template <std::size_t I, class CoordSystem>
0867 typename CoordSystem::Scalar get(LorentzVector<CoordSystem> const& p)
0868 {
0869 static_assert(I < 4);
0870 if constexpr (I == 0) {
0871 return p.X();
0872 } else if constexpr (I == 1) {
0873 return p.Y();
0874 } else if constexpr (I == 2) {
0875 return p.Z();
0876 } else {
0877 return p.E();
0878 }
0879 }
0880
0881 }
0882
0883 }
0884
0885
0886 #include <tuple>
0887 namespace std {
0888 template <class CoordSystem>
0889 struct tuple_size<ROOT::Math::LorentzVector<CoordSystem>> : integral_constant<size_t, 4> {};
0890 template <size_t I, class CoordSystem>
0891 struct tuple_element<I, ROOT::Math::LorentzVector<CoordSystem>> {
0892 static_assert(I < 4);
0893 using type = typename CoordSystem::Scalar;
0894 };
0895 }
0896
0897 #include <sstream>
0898 namespace cling
0899 {
0900 template<typename CoordSystem>
0901 std::string printValue(const ROOT::Math::LorentzVector<CoordSystem> *v)
0902 {
0903 std::stringstream s;
0904 s << *v;
0905 return s.str();
0906 }
0907
0908 }
0909
0910 #endif
0911
0912