File indexing completed on 2025-12-15 10:28:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef ROOT_Math_GenVector_PxPyPzM4D
0019 #define ROOT_Math_GenVector_PxPyPzM4D 1
0020
0021 #include "Math/GenVector/eta.h"
0022
0023 #include "Math/GenVector/GenVector_exception.h"
0024
0025
0026 #include <cmath>
0027
0028 namespace ROOT {
0029
0030 namespace Math {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 template <class ScalarType = double>
0049 class PxPyPzM4D {
0050
0051 public :
0052
0053 typedef ScalarType Scalar;
0054 static constexpr unsigned int Dimension = 4U;
0055
0056
0057
0058
0059
0060
0061 constexpr PxPyPzM4D() noexcept = default;
0062
0063
0064
0065
0066 PxPyPzM4D(Scalar px, Scalar py, Scalar pz, Scalar m) :
0067 fX(px), fY(py), fZ(pz), fM(m) {
0068
0069 if (fM < 0) RestrictNegMass();
0070 }
0071
0072
0073
0074
0075
0076 template <class CoordSystem>
0077 explicit constexpr PxPyPzM4D(const CoordSystem & v) :
0078 fX( v.X() ), fY( v.Y() ), fZ( v.Z() ), fM( v.M() )
0079 { }
0080
0081
0082
0083
0084
0085 template <class AnyCoordSystem>
0086 PxPyPzM4D & operator = (const AnyCoordSystem & v) {
0087 fX = v.X();
0088 fY = v.Y();
0089 fZ = v.Z();
0090 fM = v.M();
0091 return *this;
0092 }
0093
0094
0095
0096
0097 void SetCoordinates( const Scalar src[] ) {
0098 fX=src[0]; fY=src[1]; fZ=src[2]; fM=src[3];
0099 if (fM < 0) RestrictNegMass();
0100 }
0101
0102
0103
0104
0105 void GetCoordinates( Scalar dest[] ) const
0106 { dest[0] = fX; dest[1] = fY; dest[2] = fZ; dest[3] = fM; }
0107
0108
0109
0110
0111 void SetCoordinates(Scalar px, Scalar py, Scalar pz, Scalar m) {
0112 fX=px; fY=py; fZ=pz; fM=m;
0113 if (fM < 0) RestrictNegMass();
0114 }
0115
0116
0117
0118
0119 void GetCoordinates(Scalar& px, Scalar& py, Scalar& pz, Scalar& m) const
0120 { px=fX; py=fY; pz=fZ; m=fM;}
0121
0122
0123
0124
0125
0126 Scalar Px() const { return fX;}
0127 Scalar Py() const { return fY;}
0128 Scalar Pz() const { return fZ;}
0129 Scalar M() const { return fM; }
0130
0131 Scalar X() const { return fX;}
0132 Scalar Y() const { return fY;}
0133 Scalar Z() const { return fZ;}
0134
0135
0136
0137
0138
0139 Scalar E() const { using std::sqrt; return sqrt(E2()); }
0140
0141 Scalar T() const { return E();}
0142
0143
0144
0145
0146 Scalar P2() const { return fX*fX + fY*fY + fZ*fZ; }
0147
0148
0149
0150
0151 Scalar P() const { using std::sqrt; return sqrt(P2()); }
0152 Scalar R() const { return P(); }
0153
0154
0155
0156
0157
0158 Scalar M2() const {
0159 return ( fM >= 0 ) ? fM*fM : -fM*fM;
0160 }
0161 Scalar Mag2() const { return M2(); }
0162
0163 Scalar Mag() const { return M(); }
0164
0165
0166
0167
0168 Scalar E2() const {
0169 Scalar e2 = P2() + M2();
0170
0171 return e2 > 0 ? e2 : 0;
0172 }
0173
0174
0175
0176
0177 Scalar Pt2() const { return fX*fX + fY*fY;}
0178 Scalar Perp2() const { return Pt2();}
0179
0180
0181
0182
0183 Scalar Pt() const { using std::sqrt; return sqrt(Perp2()); }
0184 Scalar Perp() const { return Pt();}
0185 Scalar Rho() const { return Pt();}
0186
0187
0188
0189
0190 Scalar Mt2() const { return E2() - fZ*fZ; }
0191
0192
0193
0194
0195 Scalar Mt() const {
0196 const Scalar mm = Mt2();
0197 if (mm >= 0) {
0198 using std::sqrt;
0199 return sqrt(mm);
0200 } else {
0201 GenVector_Throw("PxPyPzM4D::Mt() - Tachyonic:\n"
0202 " Pz^2 > E^2 so the transverse mass would be imaginary");
0203 using std::sqrt;
0204 return -sqrt(-mm);
0205 }
0206 }
0207
0208
0209
0210
0211 Scalar Et2() const {
0212
0213 Scalar pt2 = Pt2();
0214 return pt2 == 0 ? 0 : E2() * pt2/( pt2 + fZ*fZ );
0215 }
0216
0217
0218
0219
0220 Scalar Et() const {
0221 const Scalar etet = Et2();
0222 using std::sqrt;
0223 return sqrt(etet);
0224 }
0225
0226
0227
0228
0229 Scalar Phi() const { using std::atan2; return (fX == 0.0 && fY == 0.0) ? 0.0 : atan2(fY, fX); }
0230
0231
0232
0233
0234 Scalar Theta() const { using std::atan2; return (fX == 0.0 && fY == 0.0 && fZ == 0.0) ? 0 : atan2(Pt(), fZ); }
0235
0236
0237
0238
0239 Scalar Eta() const {
0240 return Impl::Eta_FromRhoZ ( Pt(), fZ);
0241 }
0242
0243
0244
0245
0246
0247
0248
0249 void SetPx( Scalar px) {
0250 fX = px;
0251 }
0252
0253
0254
0255 void SetPy( Scalar py) {
0256 fY = py;
0257 }
0258
0259
0260
0261 void SetPz( Scalar pz) {
0262 fZ = pz;
0263 }
0264
0265
0266
0267 void SetM( Scalar m) {
0268 fM = m;
0269 if (fM < 0) RestrictNegMass();
0270 }
0271
0272
0273
0274
0275 void SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e);
0276
0277
0278
0279
0280
0281
0282
0283
0284 void Negate( ) {
0285 fX = -fX;
0286 fY = -fY;
0287 fZ = -fZ;
0288 GenVector_Throw("PxPyPzM4D::Negate - cannot negate the energy - can negate only the spatial components");
0289 }
0290
0291
0292
0293
0294 void Scale( const Scalar & a) {
0295 fX *= a;
0296 fY *= a;
0297 fZ *= a;
0298 fM *= a;
0299 }
0300
0301
0302
0303
0304
0305 bool operator == (const PxPyPzM4D & rhs) const {
0306 return fX == rhs.fX && fY == rhs.fY && fZ == rhs.fZ && fM == rhs.fM;
0307 }
0308 bool operator != (const PxPyPzM4D & rhs) const {return !(operator==(rhs));}
0309
0310
0311
0312
0313
0314
0315 Scalar x() const { return X(); }
0316 Scalar y() const { return Y(); }
0317 Scalar z() const { return Z(); }
0318 Scalar t() const { return E(); }
0319
0320
0321
0322 #if defined(__MAKECINT__) || defined(G__DICTIONARY)
0323
0324
0325
0326 void SetPt(Scalar pt);
0327
0328 void SetEta(Scalar eta);
0329
0330 void SetPhi(Scalar phi);
0331
0332 void SetE(Scalar t);
0333
0334 #endif
0335
0336 private:
0337
0338
0339
0340 inline void RestrictNegMass() {
0341 if ( fM >=0 ) return;
0342 if ( P2() - fM*fM < 0 ) {
0343 GenVector_Throw("PxPyPzM4D::unphysical value of mass, set to closest physical value");
0344 fM = - P();
0345 }
0346 return;
0347 }
0348
0349
0350
0351
0352
0353
0354 ScalarType fX = 0;
0355 ScalarType fY = 0;
0356 ScalarType fZ = 0;
0357 ScalarType fM = 0;
0358 };
0359
0360 }
0361 }
0362
0363
0364
0365
0366 #include "Math/GenVector/PxPyPzE4D.h"
0367 #include "Math/GenVector/PtEtaPhiM4D.h"
0368
0369 namespace ROOT {
0370
0371 namespace Math {
0372
0373 template <class ScalarType>
0374 inline void PxPyPzM4D<ScalarType>::SetPxPyPzE(Scalar px, Scalar py, Scalar pz, Scalar e) {
0375 *this = PxPyPzE4D<Scalar> (px, py, pz, e);
0376 }
0377
0378
0379 #if defined(__MAKECINT__) || defined(G__DICTIONARY)
0380
0381
0382
0383
0384
0385 template <class ScalarType>
0386 inline void PxPyPzM4D<ScalarType>::SetPt(ScalarType pt) {
0387 GenVector_exception e("PxPyPzM4D::SetPt() is not supposed to be called");
0388 throw e;
0389 PtEtaPhiE4D<ScalarType> v(*this); v.SetPt(pt); *this = PxPyPzM4D<ScalarType>(v);
0390 }
0391 template <class ScalarType>
0392 inline void PxPyPzM4D<ScalarType>::SetEta(ScalarType eta) {
0393 GenVector_exception e("PxPyPzM4D::SetEta() is not supposed to be called");
0394 throw e;
0395 PtEtaPhiE4D<ScalarType> v(*this); v.SetEta(eta); *this = PxPyPzM4D<ScalarType>(v);
0396 }
0397 template <class ScalarType>
0398 inline void PxPyPzM4D<ScalarType>::SetPhi(ScalarType phi) {
0399 GenVector_exception e("PxPyPzM4D::SetPhi() is not supposed to be called");
0400 throw e;
0401 PtEtaPhiE4D<ScalarType> v(*this); v.SetPhi(phi); *this = PxPyPzM4D<ScalarType>(v);
0402 }
0403 template <class ScalarType>
0404 inline void PxPyPzM4D<ScalarType>::SetE(ScalarType energy) {
0405 GenVector_exception e("PxPyPzM4D::SetE() is not supposed to be called");
0406 throw e;
0407 PxPyPzE4D<ScalarType> v(*this); v.SetE(energy);
0408 *this = PxPyPzM4D<ScalarType>(v);
0409 }
0410
0411
0412 #endif
0413
0414 }
0415
0416 }
0417
0418
0419
0420 #endif