Revision 006c98b85d8b743848d4a89773728740c39a465b authored by Vassil Vassilev on 27 March 2014, 10:26:03 UTC, committed by Vassil Vassilev on 31 March 2014, 11:57:22 UTC
1 parent bdd1961
coordinates4D.cxx
// $Id $
//
// Tests that each form of 4-vector has all the properties that stem from
// owning and forwarding to a 4D coordinates instance
//
// 6/28/05 m fischler
// from contents of test_coordinates.h by L. Moneta.
//
// =================================================================
#include "Math/GenVector/DisplacementVector3D.h"
#include "Math/GenVector/PositionVector3D.h"
#include "Math/GenVector/Cartesian3D.h"
#include "Math/GenVector/Polar3D.h"
#include "Math/GenVector/CylindricalEta3D.h"
#include "Math/GenVector/etaMax.h"
#include "Math/GenVector/PxPyPzE4D.h"
#include "Math/GenVector/PxPyPzM4D.h"
#include "Math/GenVector/PtEtaPhiE4D.h"
#include "Math/GenVector/PtEtaPhiM4D.h"
#include "Math/GenVector/LorentzVector.h"
#include "Math/Vector4Dfwd.h" // for typedefs definitions
#include "CoordinateTraits.h"
#include <iostream>
#include <limits>
#include <cmath>
#include <vector>
//#define TRACE1
#define DEBUG
using namespace ROOT::Math;
template <typename T1, typename T2 >
struct Precision {
enum { result = std::numeric_limits<T1>::digits <= std::numeric_limits<T2>::digits };
};
template <typename T1, typename T2, bool>
struct LessPreciseType {
typedef T1 type;
};
template <typename T1, typename T2>
struct LessPreciseType<T1, T2, false> {
typedef T2 type;
};
template <typename Scalar1, typename Scalar2>
int
closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) {
int ret = 0;
Scalar1 eps1 = std::numeric_limits<Scalar1>::epsilon();
Scalar2 eps2 = std::numeric_limits<Scalar2>::epsilon();
typedef typename LessPreciseType<Scalar1, Scalar2,Precision<Scalar1,Scalar2>::result>::type Scalar;
Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2;
int pr = std::cout.precision(18);
Scalar ss1 (s1);
Scalar ss2 (s2);
Scalar diff = ss1 - ss2;
if (diff < 0) diff = -diff;
if (ss1 == 0 || ss2 == 0) { // TODO - the ss2==0 makes a big change??
if ( diff > ticks*epsilon ) {
ret=3;
std::cout << "\nAbsolute discrepancy in " << coord << "(): "
<< ss1 << " != " << ss2 << "\n"
<< " (Allowed discrepancy is " << ticks*epsilon
<< ")\nDifference is " << diff/epsilon << " ticks\n";
}
std::cout.precision (pr);
return ret;
}
// infinity dicrepancy musy be checked with max precision
long double sd1(ss1);
long double sd2(ss2);
if ( (sd1 + sd2 == sd1) != (sd1 + sd2 == sd2) ) {
ret=5;
std::cout << "\nInfinity discrepancy in " << coord << "(): "
<< sd1 << " != " << sd2 << "\n";
std::cout.precision (pr);
return ret;
}
Scalar denom = ss1 > 0 ? ss1 : -ss1;
if ((diff/denom > ticks*epsilon) && (diff > ticks*epsilon)) {
ret=9;
std::cout << "\nDiscrepancy in " << coord << "(): "
<< ss1 << " != " << ss2 << "\n"
<< " (Allowed discrepancy is " << ticks*epsilon*ss1
<< ")\nDifference is " << (diff/denom)/epsilon << " ticks\n";
}
std::cout.precision (pr);
return ret;
}
template <class V1, class V2>
int compare4D (const V1 & v1, const V2 & v2, double ticks) {
int ret =0;
typedef typename V1::CoordinateType CoordType1;
typedef typename V2::CoordinateType CoordType2;
ret |= closeEnough ( v1.x(), v2.x(), "x" ,ticks);
ret |= closeEnough ( v1.y(), v2.y(), "y" ,ticks);
ret |= closeEnough ( v1.z(), v2.z(), "z" ,ticks);
ret |= closeEnough ( v1.t(), v2.t(), "t" ,ticks);
ret |= closeEnough ( v1.rho(), v2.rho(), "rho" ,ticks);
ret |= closeEnough ( v1.phi(), v2.phi(), "phi" ,ticks);
ret |= closeEnough ( v1.P(), v2.P(), "p" ,ticks);
ret |= closeEnough ( v1.theta(), v2.theta(), "theta" ,ticks);
ret |= closeEnough ( v1.perp2(), v2.perp2(), "perp2" ,ticks);
ret |= closeEnough ( v1.M2(), v2.M2(), "m2" ,ticks);
ret |= closeEnough ( v1.M(), v2.M(), "m" ,ticks);
ret |= closeEnough ( v1.Mt(), v2.Mt(), "mt" ,ticks);
ret |= closeEnough ( v1.Et(), v2.Et(), "et" ,ticks);
if ( v1.rho() > 0 && v2.rho() > 0 ) { // eta can legitimately vary if rho == 0
ret |= closeEnough ( v1.eta(), v2.eta(), "eta" ,ticks);
}
if (ret != 0) {
std::cout << "Discrepancy detected (see above) is between:\n "
<< CoordinateTraits<CoordType1>::name() << " and\n "
<< CoordinateTraits<CoordType2>::name() << "\n"
<< "with v = (" << v1.x() << ", " << v1.y() << ", "
<< v1.z() << ", " << v1.t() << ")\n";
}
else {
std::cout << ".";
}
return ret;
}
template <class C>
int test4D ( const LorentzVector<C> & v, double ticks ) {
#ifdef DEBUG
std::cout <<"\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks << "\t: ";
#endif
int ret = 0;
LorentzVector< PxPyPzE4D<double> > vxyzt_d (v.x(), v.y(), v.z(), v.t());
//double m = std::sqrt ( v.t()*v.t() - v.x()*v.x() - v.y()*v.y() - v.z()*v.z());
//double r = std::sqrt (v.x()*v.x() + v.y()*v.y() + v.z()*v.z());
double rho = std::sqrt (v.x()*v.x() + v.y()*v.y());
double theta = std::atan2( rho, v.z() ); // better tahn using acos
//double theta = r>0 ? std::acos ( v.z()/r ) : 0;
double phi = rho>0 ? std::atan2 (v.y(), v.x()) : 0;
double eta;
if (rho != 0) {
eta = -std::log(std::tan(theta/2));
#ifdef TRACE1
std::cout << ":::: rho != 0\n"
<< ":::: theta = " << theta
<<"/n:::: tan(theta/2) = " << std::tan(theta/2)
<<"\n:::: eta = " << eta << "\n";
#endif
} else if (v.z() == 0) {
eta = 0;
#ifdef TRACE1
std::cout << ":::: v.z() == 0\n"
<<"\n:::: eta = " << eta << "\n";
#endif
} else if (v.z() > 0) {
eta = v.z() + etaMax<long double>();
#ifdef TRACE1
std::cout << ":::: v.z() > 0\n"
<< ":::: etaMax = " << etaMax<long double>()
<<"\n:::: eta = " << eta << "\n";
#endif
} else {
eta = v.z() - etaMax<long double>();
#ifdef TRACE1
std::cout << ":::: v.z() < 0\n"
<< ":::: etaMax = " << etaMax<long double>()
<<"\n:::: eta = " << eta << "\n";
#endif
}
LorentzVector< PtEtaPhiE4D<double> > vrep_d ( rho, eta, phi, v.t() );
ret |= compare4D( vxyzt_d, vrep_d, ticks);
LorentzVector< PtEtaPhiM4D<double> > vrepm_d ( rho, eta, phi, v.M() );
ret |= compare4D( vxyzt_d, vrepm_d, ticks);
LorentzVector< PxPyPzM4D <double> > vxyzm_d ( v.x(), v.y(), v.z(), v.M() );
ret |= compare4D( vrep_d, vxyzm_d, ticks);
LorentzVector< PxPyPzE4D<float> > vxyzt_f (v.x(), v.y(), v.z(), v.t());
ret |= compare4D( vxyzt_d, vxyzt_f, ticks);
LorentzVector< PtEtaPhiE4D<float> > vrep_f ( rho, eta, phi, v.t() );
ret |= compare4D( vxyzt_f, vrep_f, ticks);
LorentzVector< PtEtaPhiM4D<float> > vrepm_f ( rho, eta, phi, v.M() );
ret |= compare4D( vxyzt_f, vrepm_f, ticks);
LorentzVector< PxPyPzM4D<float> > vxyzm_f (v.x(), v.y(), v.z(), v.M());
ret |= compare4D( vrep_f, vxyzm_f, ticks);
if (ret == 0) std::cout << "\t OK\n";
else {
std::cout << "\t FAIL\n";
std::cerr << "\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks
<< "\t:\t FAILED\n";
}
return ret;
}
int coordinates4D (bool testAll = false) {
int ret = 0;
ret |= test4D (XYZTVector ( 0.0, 0.0, 0.0, 0.0 ) , 1 );
ret |= test4D (XYZTVector ( 1.0, 2.0, 3.0, 4.0 ) ,10 );
ret |= test4D (XYZTVector ( -1.0, -2.0, 3.0, 4.0 ) ,10 );
// test for large eta values (which was giving inf before Jun 07)
ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, 10.0, 100.0 ) ,10 );
// for z < 0 precision in eta is worse since theta is close to Pi
ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, -10.0, 100.0 ) ,1000000000 );
// test cases with zero mass
// tick should be p /sqrt(eps) ~ 4 /sqrt(eps)
ret |= test4D (PxPyPzMVector ( 1., 2., 3., 0.) , 4./std::sqrt(std::numeric_limits<double>::epsilon()) );
// this test fails in some machines (skip by default)
if (!testAll) return ret;
// take a factor 1.5 in ticks to be conservative
ret |= test4D (PxPyPzMVector ( 1., 1., 100., 0.) , 150./std::sqrt(std::numeric_limits<double>::epsilon()) );
// need a larger a factor here
ret |= test4D (PxPyPzMVector ( 1.E8, 1.E8, 1.E8, 0.) , 1.E9/std::sqrt(std::numeric_limits<double>::epsilon()) );
// if use 1 here fails
ret |= test4D (PxPyPzMVector ( 1.E-8, 1.E-8, 1.E-8, 0.) , 2.E-8/std::sqrt(std::numeric_limits<double>::epsilon()) );
return ret;
}
int main() {
int ret = coordinates4D();
if (ret) std::cerr << "test FAILED !!! " << std::endl;
else std::cout << "test OK " << std::endl;
return ret;
}
Computing file changes ...