coordinates4D.cxx

Go to the documentation of this file.
00001 // $Id $
00002 // 
00003 // Tests that each form of 4-vector has all the properties that stem from
00004 // owning and forwarding to a 4D coordinates instance 
00005 //
00006 // 6/28/05 m fischler   
00007 //         from contents of test_coordinates.h by L. Moneta.
00008 //
00009 // =================================================================
00010 
00011 
00012 #include "Math/GenVector/DisplacementVector3D.h"
00013 #include "Math/GenVector/PositionVector3D.h"
00014 #include "Math/GenVector/Cartesian3D.h"
00015 #include "Math/GenVector/Polar3D.h"
00016 #include "Math/GenVector/CylindricalEta3D.h"
00017 #include "Math/GenVector/etaMax.h"
00018 
00019 #include "Math/GenVector/PxPyPzE4D.h"
00020 #include "Math/GenVector/PxPyPzM4D.h"
00021 #include "Math/GenVector/PtEtaPhiE4D.h"
00022 #include "Math/GenVector/PtEtaPhiM4D.h"
00023 #include "Math/GenVector/LorentzVector.h"
00024 
00025 #include "Math/Vector4Dfwd.h"  // for typedefs definitions
00026 
00027 #include "CoordinateTraits.h"
00028 
00029 #include <iostream>
00030 #include <limits>
00031 #include <cmath>
00032 #include <vector>
00033 
00034 //#define TRACE1
00035 #define DEBUG
00036 
00037 using namespace ROOT::Math;
00038 
00039 
00040 
00041 template <typename T1, typename T2 > 
00042 struct Precision { 
00043   enum { result = std::numeric_limits<T1>::digits <= std::numeric_limits<T2>::digits   }; 
00044 }; 
00045 
00046 template <typename T1, typename T2, bool>
00047 struct LessPreciseType {
00048   typedef T1 type;
00049 };
00050 template <typename T1, typename T2>
00051 struct LessPreciseType<T1, T2, false> {
00052   typedef T2 type;
00053 };
00054 
00055 
00056 template <typename Scalar1, typename Scalar2> 
00057 int
00058 closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) {
00059   int ret = 0;
00060   Scalar1 eps1 = std::numeric_limits<Scalar1>::epsilon();
00061   Scalar2 eps2 = std::numeric_limits<Scalar2>::epsilon();
00062   typedef typename LessPreciseType<Scalar1, Scalar2,Precision<Scalar1,Scalar2>::result>::type Scalar;
00063   Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2;
00064   int pr = std::cout.precision(18);
00065   Scalar ss1 (s1);
00066   Scalar ss2 (s2);
00067   Scalar diff = ss1 - ss2;
00068   if (diff < 0) diff = -diff;
00069   if (ss1 == 0 || ss2 == 0) { // TODO - the ss2==0 makes a big change??
00070     if ( diff > ticks*epsilon ) {
00071       ret=3;
00072       std::cout << "\nAbsolute discrepancy in " << coord << "(): "
00073                 << ss1 << " != " << ss2 << "\n"
00074                 << "   (Allowed discrepancy is " << ticks*epsilon 
00075                 << ")\nDifference is " << diff/epsilon << " ticks\n";
00076     }
00077     std::cout.precision (pr);
00078     return ret;
00079   }
00080   // infinity dicrepancy musy be checked with max precision
00081   long double sd1(ss1); 
00082   long double sd2(ss2); 
00083   if ( (sd1 + sd2 == sd1) != (sd1 + sd2 == sd2) ) {
00084     ret=5;
00085     std::cout << "\nInfinity discrepancy in " << coord << "(): "
00086               << sd1 << " != " << sd2 << "\n";
00087     std::cout.precision (pr);
00088     return ret;
00089   }
00090   Scalar denom = ss1 > 0 ? ss1 : -ss1;
00091   if ((diff/denom > ticks*epsilon) && (diff > ticks*epsilon)) {
00092     ret=9;
00093     std::cout << "\nDiscrepancy in " << coord << "(): "
00094               << ss1 << " != " << ss2 << "\n"
00095               << "   (Allowed discrepancy is " << ticks*epsilon*ss1 
00096               << ")\nDifference is " << (diff/denom)/epsilon << " ticks\n";
00097   }
00098   std::cout.precision (pr);
00099   return ret;
00100 }
00101 
00102 
00103 template <class V1, class V2>
00104 int compare4D (const V1 & v1, const V2 & v2, double ticks) {
00105   int ret =0;  
00106   typedef typename V1::CoordinateType CoordType1;
00107   typedef typename V2::CoordinateType CoordType2;
00108   
00109   ret |= closeEnough ( v1.x(),     v2.x(),     "x"     ,ticks); 
00110   ret |= closeEnough ( v1.y(),     v2.y(),     "y"     ,ticks); 
00111   ret |= closeEnough ( v1.z(),     v2.z(),     "z"     ,ticks); 
00112   ret |= closeEnough ( v1.t(),     v2.t(),     "t"     ,ticks); 
00113   ret |= closeEnough ( v1.rho(),   v2.rho(),   "rho"   ,ticks); 
00114   ret |= closeEnough ( v1.phi(),   v2.phi(),   "phi"   ,ticks); 
00115   ret |= closeEnough ( v1.P(),     v2.P(),     "p"     ,ticks); 
00116   ret |= closeEnough ( v1.theta(), v2.theta(), "theta" ,ticks); 
00117   ret |= closeEnough ( v1.perp2(), v2.perp2(), "perp2" ,ticks); 
00118   ret |= closeEnough ( v1.M2(),    v2.M2(),    "m2"    ,ticks); 
00119   ret |= closeEnough ( v1.M(),     v2.M(),     "m"     ,ticks); 
00120   ret |= closeEnough ( v1.Mt(),    v2.Mt(),    "mt"     ,ticks); 
00121   ret |= closeEnough ( v1.Et(),    v2.Et(),    "et"     ,ticks); 
00122   if ( v1.rho() > 0 && v2.rho() > 0 ) { // eta can legitimately vary if rho == 0
00123     ret |= closeEnough ( v1.eta(), v2.eta(),   "eta"   ,ticks); 
00124   }
00125   
00126   if (ret != 0) {
00127     std::cout << "Discrepancy detected (see above) is between:\n  "
00128               << CoordinateTraits<CoordType1>::name() << " and\n  "
00129               << CoordinateTraits<CoordType2>::name() << "\n"
00130               << "with v = (" << v1.x() << ", " << v1.y() << ", " 
00131               << v1.z() << ", " << v1.t() << ")\n";
00132   }
00133   else { 
00134     std::cout << ".";
00135   }
00136 
00137   return ret;
00138 }
00139 
00140 
00141 
00142 
00143 template <class C>
00144 int test4D ( const LorentzVector<C> & v, double ticks ) {
00145 
00146 #ifdef DEBUG
00147    std::cout <<"\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks << "\t: ";
00148 #endif
00149 
00150   int ret = 0;
00151   LorentzVector< PxPyPzE4D<double> > vxyzt_d (v.x(), v.y(), v.z(), v.t());
00152 
00153   //double m = std::sqrt ( v.t()*v.t() - v.x()*v.x() - v.y()*v.y() - v.z()*v.z());
00154   //double r = std::sqrt (v.x()*v.x() + v.y()*v.y() + v.z()*v.z());
00155   double rho = std::sqrt (v.x()*v.x() + v.y()*v.y());
00156   double theta = std::atan2( rho, v.z() );  // better tahn using acos
00157   //double theta = r>0 ? std::acos ( v.z()/r ) : 0;
00158   double phi = rho>0 ? std::atan2 (v.y(), v.x()) : 0;
00159     
00160   double eta;
00161   if (rho != 0) {
00162     eta = -std::log(std::tan(theta/2)); 
00163         #ifdef TRACE1
00164         std::cout <<  ":::: rho != 0\n" 
00165                   <<  ":::: theta = " <<  theta 
00166                   <<"/n:::: tan(theta/2) = " << std::tan(theta/2)
00167                   <<"\n:::: eta = " << eta << "\n";
00168         #endif
00169   } else if (v.z() == 0) {
00170     eta = 0;
00171         #ifdef TRACE1
00172         std::cout <<  ":::: v.z() == 0\n" 
00173                   <<"\n:::: eta = " << eta << "\n";
00174         #endif
00175   } else if (v.z() > 0) {
00176     eta = v.z() + etaMax<long double>();
00177         #ifdef TRACE1
00178         std::cout <<  ":::: v.z() > 0\n" 
00179                   <<  ":::: etaMax =  " << etaMax<long double>() 
00180                   <<"\n:::: eta = " << eta << "\n";
00181         #endif
00182   } else {
00183     eta = v.z() - etaMax<long double>();
00184         #ifdef TRACE1
00185         std::cout <<  ":::: v.z() < 0\n" 
00186                   <<  ":::: etaMax =  " << etaMax<long double>() 
00187                   <<"\n:::: eta = " << eta << "\n";
00188         #endif
00189   }
00190 
00191 
00192   LorentzVector< PtEtaPhiE4D<double> > vrep_d ( rho, eta, phi, v.t() );
00193   ret |= compare4D( vxyzt_d, vrep_d, ticks);
00194 
00195   LorentzVector< PtEtaPhiM4D<double> > vrepm_d ( rho, eta, phi, v.M() );
00196   ret |= compare4D( vxyzt_d, vrep_d, ticks);
00197 
00198   LorentzVector< PxPyPzM4D  <double> > vxyzm_d ( v.x(), v.y(), v.z(), v.M() );
00199   ret |= compare4D( vrep_d, vxyzm_d, ticks);
00200   
00201   LorentzVector< PxPyPzE4D<float> >      vxyzt_f (v.x(), v.y(), v.z(), v.t());
00202   ret |= compare4D( vxyzt_d, vxyzt_f, ticks);
00203 
00204   LorentzVector< PtEtaPhiE4D<float> > vrep_f ( rho, eta, phi, v.t() );
00205   ret |= compare4D( vxyzt_f, vrep_f, ticks);
00206 
00207   LorentzVector< PtEtaPhiM4D<float> > vrepm_f ( rho, eta, phi, v.M() );
00208   ret |= compare4D( vxyzt_f, vrepm_f, ticks);
00209 
00210   LorentzVector< PxPyPzM4D<float> >      vxyzm_f (v.x(), v.y(), v.z(), v.M());
00211   ret |= compare4D( vrep_f, vxyzm_f, ticks);
00212 
00213   if (ret == 0) std::cout << "\t OK\n";
00214   else { 
00215      std::cout << "\t FAIL\n";
00216      std::cerr << "\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks 
00217                << "\t:\t FAILED\n";
00218   }
00219   return ret; 
00220 }
00221 
00222 
00223 int coordinates4D (bool testAll = false) {
00224   int ret = 0;
00225 
00226   ret |= test4D (XYZTVector ( 0.0, 0.0, 0.0, 0.0 )     , 1 );
00227   ret |= test4D (XYZTVector ( 1.0, 2.0, 3.0, 4.0 )     ,10 );
00228   ret |= test4D (XYZTVector ( -1.0, -2.0, 3.0, 4.0 )   ,10 );
00229   // test for large eta values (which was giving inf before  Jun 07)
00230   ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, 10.0, 100.0 )   ,10 );
00231   // for z < 0 precision in eta is worse since theta is close to Pi 
00232   ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, -10.0, 100.0 )   ,1000000000 );
00233 
00234   // test cases with zero mass
00235 
00236   // tick should be p /sqrt(eps) ~ 4 /sqrt(eps)
00237   ret |= test4D (PxPyPzMVector ( 1., 2., 3., 0.)  ,  4./std::sqrt(std::numeric_limits<double>::epsilon()) );
00238 
00239   // this test fails in some machines (skip by default) 
00240   if (!testAll) return ret;  
00241 
00242   // take a factor 1.5 in ticks to be conservative
00243   ret |= test4D (PxPyPzMVector ( 1., 1., 100., 0.)  ,  150./std::sqrt(std::numeric_limits<double>::epsilon()) );
00244   // need a larger  a factor here
00245   ret |= test4D (PxPyPzMVector ( 1.E8, 1.E8, 1.E8, 0.)  ,  1.E9/std::sqrt(std::numeric_limits<double>::epsilon()) );
00246   // if use 1 here fails
00247   ret |= test4D (PxPyPzMVector ( 1.E-8, 1.E-8, 1.E-8, 0.)  ,  2.E-8/std::sqrt(std::numeric_limits<double>::epsilon()) );
00248 
00249   return ret;
00250 }
00251 
00252 int main() { 
00253    int ret = coordinates4D();
00254    if (ret)  std::cerr << "test FAILED !!! " << std::endl; 
00255    else   std::cout << "test OK " << std::endl;
00256    return ret;
00257 }

Generated on Tue Jul 5 14:33:09 2011 for ROOT_528-00b_version by  doxygen 1.5.1