// $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 #include #include #include //#define TRACE1 #define DEBUG using namespace ROOT::Math; template struct Precision { enum { result = std::numeric_limits::digits <= std::numeric_limits::digits }; }; template struct LessPreciseType { typedef T1 type; }; template struct LessPreciseType { typedef T2 type; }; template int closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) { int ret = 0; Scalar1 eps1 = std::numeric_limits::epsilon(); Scalar2 eps2 = std::numeric_limits::epsilon(); typedef typename LessPreciseType::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 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::name() << " and\n " << CoordinateTraits::name() << "\n" << "with v = (" << v1.x() << ", " << v1.y() << ", " << v1.z() << ", " << v1.t() << ")\n"; } else { std::cout << "."; } return ret; } template int test4D ( const LorentzVector & v, double ticks ) { #ifdef DEBUG std::cout <<"\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks << "\t: "; #endif int ret = 0; LorentzVector< PxPyPzE4D > 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(); #ifdef TRACE1 std::cout << ":::: v.z() > 0\n" << ":::: etaMax = " << etaMax() <<"\n:::: eta = " << eta << "\n"; #endif } else { eta = v.z() - etaMax(); #ifdef TRACE1 std::cout << ":::: v.z() < 0\n" << ":::: etaMax = " << etaMax() <<"\n:::: eta = " << eta << "\n"; #endif } LorentzVector< PtEtaPhiE4D > vrep_d ( rho, eta, phi, v.t() ); ret |= compare4D( vxyzt_d, vrep_d, ticks); LorentzVector< PtEtaPhiM4D > vrepm_d ( rho, eta, phi, v.M() ); ret |= compare4D( vxyzt_d, vrep_d, ticks); LorentzVector< PxPyPzM4D > vxyzm_d ( v.x(), v.y(), v.z(), v.M() ); ret |= compare4D( vrep_d, vxyzm_d, ticks); LorentzVector< PxPyPzE4D > vxyzt_f (v.x(), v.y(), v.z(), v.t()); ret |= compare4D( vxyzt_d, vxyzt_f, ticks); LorentzVector< PtEtaPhiE4D > vrep_f ( rho, eta, phi, v.t() ); ret |= compare4D( vxyzt_f, vrep_f, ticks); LorentzVector< PtEtaPhiM4D > vrepm_f ( rho, eta, phi, v.M() ); ret |= compare4D( vxyzt_f, vrepm_f, ticks); LorentzVector< PxPyPzM4D > 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::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::epsilon()) ); // need a larger a factor here ret |= test4D (PxPyPzMVector ( 1.E8, 1.E8, 1.E8, 0.) , 1.E9/std::sqrt(std::numeric_limits::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::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; }