#ifndef ROOT_Math_GenVector_LorentzVector
#define ROOT_Math_GenVector_LorentzVector 1
#ifndef ROOT_Math_GenVector_PxPyPzE4D
#include "Math/GenVector/PxPyPzE4D.h"
#endif
#ifndef ROOT_Math_GenVector_DisplacementVector3D
#include "Math/GenVector/DisplacementVector3D.h"
#endif
#ifndef ROOT_Math_GenVector_GenVectorIO
#include "Math/GenVector/GenVectorIO.h"
#endif
namespace ROOT {
namespace Math {
template< class CoordSystem >
class LorentzVector {
public:
typedef typename CoordSystem::Scalar Scalar;
typedef CoordSystem CoordinateType;
LorentzVector ( ) : fCoordinates() { }
LorentzVector(const Scalar & a,
const Scalar & b,
const Scalar & c,
const Scalar & d) :
fCoordinates(a , b, c, d) { }
template< class Coords >
explicit LorentzVector(const LorentzVector<Coords> & v ) :
fCoordinates( v.Coordinates() ) { }
template<class ForeignLorentzVector>
explicit LorentzVector( const ForeignLorentzVector & v) :
fCoordinates(PxPyPzE4D<Scalar>( v.x(), v.y(), v.z(), v.t() ) ) { }
#ifdef LATER
template< class LAVector >
explicit LorentzVector(const LAVector & v, size_t index0 ) {
fCoordinates = CoordSystem ( v[index0], v[index0+1], v[index0+2], v[index0+3] );
}
#endif
template< class OtherCoords >
LorentzVector & operator= ( const LorentzVector<OtherCoords> & v) {
fCoordinates = v.Coordinates();
return *this;
}
template<class ForeignLorentzVector>
LorentzVector & operator = ( const ForeignLorentzVector & v) {
SetXYZT( v.x(), v.y(), v.z(), v.t() );
return *this;
}
#ifdef LATER
template< class LAVector >
LorentzVector & AssignFrom(const LAVector & v, size_t index0=0 ) {
fCoordinates.SetCoordinates( v[index0], v[index0+1], v[index0+2], v[index0+3] );
return *this;
}
#endif
const CoordSystem & Coordinates() const {
return fCoordinates;
}
void GetCoordinates( Scalar& a, Scalar& b, Scalar& c, Scalar & d ) const
{ fCoordinates.GetCoordinates(a, b, c, d); }
void GetCoordinates( Scalar dest[] ) const
{ fCoordinates.GetCoordinates(dest); }
template <class IT>
#ifndef NDEBUG
void GetCoordinates( IT begin, IT end ) const
#else
void GetCoordinates( IT begin, IT ) const
#endif
{ IT a = begin; IT b = ++begin; IT c = ++begin; IT d = ++begin;
assert (++begin==end);
GetCoordinates (*a,*b,*c,*d);
}
template <class IT>
void GetCoordinates( IT begin ) const {
Scalar a,b,c,d = 0;
GetCoordinates (a,b,c,d);
*begin++ = a;
*begin++ = b;
*begin++ = c;
*begin = d;
}
LorentzVector<CoordSystem>& SetCoordinates( const Scalar src[] ) {
fCoordinates.SetCoordinates(src);
return *this;
}
LorentzVector<CoordSystem>& SetCoordinates( Scalar a, Scalar b, Scalar c, Scalar d ) {
fCoordinates.SetCoordinates(a, b, c, d);
return *this;
}
#ifdef NDEBUG
template< class IT >
LorentzVector<CoordSystem>& SetCoordinates( IT begin, IT ) {
IT a = begin; IT b = ++begin; IT c = ++begin; IT d = ++begin;
assert (++begin==end);
SetCoordinates (*a,*b,*c,*d);
return *this;
}
#else
template< class IT >
LorentzVector<CoordSystem>& SetCoordinates( IT begin, IT end ) {
IT a = begin; IT b = ++begin; IT c = ++begin; IT d = ++begin;
assert (++begin==end);
SetCoordinates (*a,*b,*c,*d);
return *this;
}
#endif
LorentzVector<CoordSystem>& SetXYZT (Scalar xx, Scalar yy, Scalar zz, Scalar tt) {
fCoordinates.SetPxPyPzE(xx,yy,zz,tt);
return *this;
}
LorentzVector<CoordSystem>& SetPxPyPzE (Scalar xx, Scalar yy, Scalar zz, Scalar ee) {
fCoordinates.SetPxPyPzE(xx,yy,zz,ee);
return *this;
}
bool operator==(const LorentzVector & rhs) const {
return fCoordinates==rhs.fCoordinates;
}
bool operator!= (const LorentzVector & rhs) const {
return !(operator==(rhs));
}
Scalar Px() const { return fCoordinates.Px(); }
Scalar X() const { return fCoordinates.Px(); }
Scalar Py() const { return fCoordinates.Py(); }
Scalar Y() const { return fCoordinates.Py(); }
Scalar Pz() const { return fCoordinates.Pz(); }
Scalar Z() const { return fCoordinates.Pz(); }
Scalar E() const { return fCoordinates.E(); }
Scalar T() const { return fCoordinates.E(); }
Scalar M2() const { return fCoordinates.M2(); }
Scalar M() const { return fCoordinates.M();}
Scalar R() const { return fCoordinates.R(); }
Scalar P() const { return fCoordinates.R(); }
Scalar P2() const { return P() * P(); }
Scalar Perp2( ) const { return fCoordinates.Perp2();}
Scalar Pt() const { return fCoordinates.Pt(); }
Scalar Rho() const { return fCoordinates.Pt(); }
Scalar Mt2() const { return fCoordinates.Mt2(); }
Scalar Mt() const { return fCoordinates.Mt(); }
Scalar Et2() const { return fCoordinates.Et2(); }
Scalar Et() const { return fCoordinates.Et(); }
Scalar Phi() const { return fCoordinates.Phi();}
Scalar Theta() const { return fCoordinates.Theta(); }
Scalar Eta() const { return fCoordinates.Eta(); }
::ROOT::Math::DisplacementVector3D<Cartesian3D<Scalar> > Vect() const {
return ::ROOT::Math::DisplacementVector3D<Cartesian3D<Scalar> >( X(), Y(), Z() );
}
template< class OtherLorentzVector >
Scalar Dot(const OtherLorentzVector & q) const {
return t()*q.t() - x()*q.x() - y()*q.y() - z()*q.z();
}
template< class OtherLorentzVector >
inline LorentzVector & operator += ( const OtherLorentzVector & q)
{
SetXYZT( x() + q.x(), y() + q.y(), z() + q.z(), t() + q.t() );
return *this;
}
template< class OtherLorentzVector >
LorentzVector & operator -= ( const OtherLorentzVector & q) {
SetXYZT( x() - q.x(), y() - q.y(), z() - q.z(), t() - q.t() );
return *this;
}
template<class OtherLorentzVector>
LorentzVector operator + ( const OtherLorentzVector & v2) const
{
LorentzVector<CoordinateType> v3(*this);
v3 += v2;
return v3;
}
template<class OtherLorentzVector>
LorentzVector operator - ( const OtherLorentzVector & v2) const {
LorentzVector<CoordinateType> v3(*this);
v3 -= v2;
return v3;
}
LorentzVector & operator *= (Scalar a) {
fCoordinates.Scale(a);
return *this;
}
LorentzVector & operator /= (Scalar a) {
fCoordinates.Scale(1/a);
return *this;
}
LorentzVector operator * ( const Scalar & a) const {
LorentzVector tmp(*this);
tmp *= a;
return tmp;
}
LorentzVector<CoordSystem> operator / ( const Scalar & a) const {
LorentzVector<CoordSystem> tmp(*this);
tmp /= a;
return tmp;
}
LorentzVector operator - () const {
return operator*( Scalar(-1) );
}
LorentzVector operator + () const {
return *this;
}
Scalar Rapidity() const {
Scalar ee = E();
Scalar ppz = Pz();
return .5f* std::log( (ee+ppz)/(ee-ppz) );
}
Scalar ColinearRapidity() const {
Scalar ee = E();
Scalar pp = P();
return .5f* std::log( (ee+pp)/(ee-pp) );
}
bool isTimelike( ) const {
Scalar ee = E(); Scalar pp = P(); return ee*ee > pp*pp;
}
bool isLightlike( Scalar tolerance
= 100*std::numeric_limits<Scalar>::epsilon() ) const {
Scalar ee = E(); Scalar pp = P(); Scalar delta = ee-pp;
if ( ee==0 ) return pp==0;
return delta*delta < tolerance * ee*ee;
}
bool isSpacelike( ) const {
Scalar ee = E(); Scalar pp = P(); return ee*ee < pp*pp;
}
typedef DisplacementVector3D< Cartesian3D<Scalar> > BetaVector;
BetaVector BoostToCM( ) const {
if (E() == 0) {
if (P() == 0) {
return BetaVector();
} else {
return -Vect()/E();
}
}
if (M2() <= 0) {
}
return -Vect()/E();
}
template <class Other4Vector>
BetaVector BoostToCM(const Other4Vector& v ) const {
Scalar eSum = E() + v.E();
DisplacementVector3D< Cartesian3D<Scalar> > vecSum = Vect() + v.Vect();
if (eSum == 0) {
if (vecSum.Mag2() == 0) {
return BetaVector();
} else {
return BetaVector(vecSum/eSum);
}
}
return BetaVector (vecSum * (-1./eSum));
}
Scalar Beta() const {
if ( E() == 0 ) {
if ( P2() == 0)
return 0;
else {
GenVector::Throw ("LorentzVector::Beta() - beta computed for LorentzVector with t = 0. Return an Infinite result");
return 1./E();
}
}
if ( M2() <= 0 ) {
GenVector::Throw ("LorentzVector::Beta() - beta computed for non-timelike LorentzVector . Result is physically meaningless" );
}
return P() / E();
}
Scalar Gamma() const {
Scalar v2 = P2();
Scalar t2 = E()*E();
if (E() == 0) {
if ( P2() == 0) {
return 1;
} else {
GenVector::Throw ("LorentzVector::Gamma() - gamma computed for LorentzVector with t = 0. Return a zero result");
}
}
if ( t2 < v2 ) {
GenVector::Throw ("LorentzVector::Gamma() - gamma computed for a spacelike LorentzVector. Imaginary result");
return 0;
}
else if ( t2 == v2 ) {
GenVector::Throw ("LorentzVector::Gamma() - gamma computed for a lightlike LorentzVector. Infinite result");
}
return 1./std::sqrt(1. - v2/t2 );
}
Scalar x() const { return fCoordinates.Px(); }
Scalar y() const { return fCoordinates.Py(); }
Scalar z() const { return fCoordinates.Pz(); }
Scalar t() const { return fCoordinates.E(); }
Scalar px() const { return fCoordinates.Px(); }
Scalar py() const { return fCoordinates.Py(); }
Scalar pz() const { return fCoordinates.Pz(); }
Scalar e() const { return fCoordinates.E(); }
Scalar r() const { return fCoordinates.R(); }
Scalar theta() const { return fCoordinates.Theta(); }
Scalar phi() const { return fCoordinates.Phi(); }
Scalar rho() const { return fCoordinates.Rho(); }
Scalar eta() const { return fCoordinates.Eta(); }
Scalar pt() const { return fCoordinates.Pt(); }
Scalar perp2() const { return fCoordinates.Perp2(); }
Scalar mag2() const { return fCoordinates.M2(); }
Scalar mag() const { return fCoordinates.M(); }
Scalar mt() const { return fCoordinates.Mt(); }
Scalar mt2() const { return fCoordinates.Mt2(); }
Scalar energy() const { return fCoordinates.E(); }
Scalar mass() const { return fCoordinates.M(); }
Scalar mass2() const { return fCoordinates.M2(); }
LorentzVector<CoordSystem>& SetE ( Scalar a ) { fCoordinates.SetE (a); return *this; }
LorentzVector<CoordSystem>& SetEta( Scalar a ) { fCoordinates.SetEta(a); return *this; }
LorentzVector<CoordSystem>& SetM ( Scalar a ) { fCoordinates.SetM (a); return *this; }
LorentzVector<CoordSystem>& SetPhi( Scalar a ) { fCoordinates.SetPhi(a); return *this; }
LorentzVector<CoordSystem>& SetPt ( Scalar a ) { fCoordinates.SetPt (a); return *this; }
LorentzVector<CoordSystem>& SetPx ( Scalar a ) { fCoordinates.SetPx (a); return *this; }
LorentzVector<CoordSystem>& SetPy ( Scalar a ) { fCoordinates.SetPy (a); return *this; }
LorentzVector<CoordSystem>& SetPz ( Scalar a ) { fCoordinates.SetPz (a); return *this; }
private:
CoordSystem fCoordinates;
};
template< class CoordSystem >
inline LorentzVector<CoordSystem> operator *
( const typename LorentzVector<CoordSystem>::Scalar & a,
const LorentzVector<CoordSystem>& v) {
LorentzVector<CoordSystem> tmp(v);
tmp *= a;
return tmp;
}
template< class char_t, class traits_t, class Coords >
inline
std::basic_ostream<char_t,traits_t> &
operator << ( std::basic_ostream<char_t,traits_t> & os
, LorentzVector<Coords> const & v
)
{
if( !os ) return os;
typename Coords::Scalar a, b, c, d;
v.GetCoordinates(a, b, c, d);
if( detail::get_manip( os, detail::bitforbit ) ) {
detail::set_manip( os, detail::bitforbit, '\00' );
}
else {
os << detail::get_manip( os, detail::open ) << a
<< detail::get_manip( os, detail::sep ) << b
<< detail::get_manip( os, detail::sep ) << c
<< detail::get_manip( os, detail::sep ) << d
<< detail::get_manip( os, detail::close );
}
return os;
}
template< class char_t, class traits_t, class Coords >
inline
std::basic_istream<char_t,traits_t> &
operator >> ( std::basic_istream<char_t,traits_t> & is
, LorentzVector<Coords> & v
)
{
if( !is ) return is;
typename Coords::Scalar a, b, c, d;
if( detail::get_manip( is, detail::bitforbit ) ) {
detail::set_manip( is, detail::bitforbit, '\00' );
}
else {
detail::require_delim( is, detail::open ); is >> a;
detail::require_delim( is, detail::sep ); is >> b;
detail::require_delim( is, detail::sep ); is >> c;
detail::require_delim( is, detail::sep ); is >> d;
detail::require_delim( is, detail::close );
}
if( is )
v.SetCoordinates(a, b, c, d);
return is;
}
}
}
#endif