coordinates3D.cxx

Go to the documentation of this file.
00001 // $Id $
00002 //
00003 // Tests that each form of vector has all the properties that stem from
00004 // owning and forwarding to a coordinates instance, and that they give proper
00005 // results.
00006 //
00007 // 3D vectors have:
00008 //
00009 // accessors x(), y(), z(), r(), theta(), phi(), rho(), eta()
00010 //
00011 // =================================================================
00012 
00013 #include "Math/GenVector/DisplacementVector3D.h"
00014 #include "Math/GenVector/PositionVector3D.h"
00015 #include "Math/GenVector/Cartesian3D.h"
00016 #include "Math/GenVector/Polar3D.h"
00017 #include "Math/GenVector/CylindricalEta3D.h"
00018 #include "Math/GenVector/Cylindrical3D.h"
00019 #include "Math/GenVector/etaMax.h"
00020 
00021 #include "Math/Vector3Dfwd.h"
00022 
00023 #include "CoordinateTraits.h"
00024 
00025 #include <iostream>
00026 #include <limits>
00027 #include <cmath>
00028 #include <vector>
00029 
00030 //#define TRACE1
00031 #define DEBUG
00032 
00033 using namespace ROOT::Math;
00034 
00035 
00036 
00037 
00038 template <typename T1, typename T2 > 
00039 struct Precision { 
00040   enum { result = std::numeric_limits<T1>::digits <= std::numeric_limits<T2>::digits   }; 
00041 }; 
00042 
00043 template <typename T1, typename T2, bool>
00044 struct LessPreciseType {
00045   typedef T1 type;
00046 };
00047 template <typename T1, typename T2>
00048 struct LessPreciseType<T1, T2, false> {
00049   typedef T2 type;
00050 };
00051 
00052 
00053 template <typename Scalar1, typename Scalar2>
00054 int
00055 closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) {
00056   int ret = 0;
00057   int pr = std::cout.precision(18);
00058   Scalar1 eps1 = std::numeric_limits<Scalar1>::epsilon();
00059   Scalar2 eps2 = std::numeric_limits<Scalar2>::epsilon();
00060   typedef typename LessPreciseType<Scalar1, Scalar2,Precision<Scalar1,Scalar2>::result>::type Scalar;
00061   Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2;
00062   Scalar ss1 (s1);
00063   Scalar ss2 (s2);
00064   Scalar diff = ss1 - ss2;
00065   if (diff < 0) diff = -diff;
00066   if (ss1 == 0 || ss2 == 0) { // TODO - the ss2==0 makes a big change??
00067     if ( diff > ticks*epsilon ) {
00068       ret=3;
00069       std::cout << "\nAbsolute discrepancy in " << coord << "(): "
00070                 << ss1 << " != " << ss2 << "\n"
00071                 << "   (Allowed discrepancy is " << ticks*epsilon
00072                 << ")\nDifference is " << diff/epsilon << " ticks\n";
00073     }
00074     std::cout.precision (pr);
00075     return ret;
00076   }
00077   // infinity dicrepancy musy be checked with max precision
00078   long double sd1(ss1); 
00079   long double sd2(ss2); 
00080   if ( (sd1 + sd2 == sd1) != (sd1 + sd2 == sd2) ) {
00081     ret=5;
00082     std::cout << "\nInfinity discrepancy in " << coord << "(): "
00083               << sd1 << " != " << sd2 << "\n";
00084     std::cout.precision (pr);
00085     return ret;
00086   }
00087   Scalar denom = ss1 > 0 ? ss1 : -ss1;
00088   if ((diff/denom > ticks*epsilon) && (diff > ticks*epsilon)) {
00089     ret=9;
00090     std::cout << "\nDiscrepancy in " << coord << "(): "
00091               << ss1 << " != " << ss2 << "\n"
00092               << "   (Allowed discrepancy is " << ticks*epsilon*ss1
00093               << ")\nDifference is " << (diff/denom)/epsilon << " ticks\n";
00094    }
00095   std::cout.precision (pr);
00096   return ret;
00097 }
00098 
00099 template <class V1, class V2>
00100 int compare3D (const V1 & v1, const V2 & v2, double ticks) {
00101   int ret =0;
00102   typedef typename V1::CoordinateType CoordType1;
00103   typedef typename V2::CoordinateType CoordType2;
00104   ret |= closeEnough ( v1.x(),     v2.x(),     "x"     ,ticks);
00105   ret |= closeEnough ( v1.y(),     v2.y(),     "y"     ,ticks);
00106   ret |= closeEnough ( v1.z(),     v2.z(),     "z"     ,ticks);
00107   ret |= closeEnough ( v1.rho(),   v2.rho(),   "rho"   ,ticks);
00108   // case in phi that difference is close to 2pi
00109   typedef typename  V2::Scalar Scalar; 
00110   Scalar phi2 = v2.phi();
00111   if (std::abs(v1.phi()- phi2 ) > ROOT::Math::Pi() ) { 
00112      if (phi2<0) 
00113         phi2 += 2.*ROOT::Math::Pi();
00114      else 
00115         phi2 -= 2*ROOT::Math::Pi();
00116   }
00117   ret |= closeEnough ( v1.phi(),   phi2,   "phi"   ,ticks);
00118   ret |= closeEnough ( v1.r(),     v2.r(),     "r"     ,ticks);
00119   ret |= closeEnough ( v1.theta(), v2.theta(), "theta" ,ticks);
00120   ret |= closeEnough ( v1.mag2(),  v2.mag2(),  "mag2"  ,ticks);
00121   ret |= closeEnough ( v1.perp2(), v2.perp2(), "perp2" ,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 << "\nDiscrepancy detected (see above) is between:\n  "
00128               << CoordinateTraits<CoordType1>::name() << " and\n  "
00129               << CoordinateTraits<CoordType2>::name() << "\n"
00130               << "with v = (" << v1.x() << ", " << v1.y() << ", " << v1.z()
00131               << ")\n\n\n";
00132   }
00133   else { 
00134 #ifdef DEBUG
00135     std::cout << ".";
00136 #endif
00137   }
00138 
00139 
00140   return ret;
00141 }
00142 
00143 template <class C>
00144 int test3D ( const DisplacementVector3D<C> & v, double ticks ) {
00145 
00146 #ifdef DEBUG
00147   std::cout <<"\n>>>>> Testing 3D from " << v << " ticks = " << ticks << std::endl;
00148 #endif
00149 
00150   int ret = 0;
00151   DisplacementVector3D< Cartesian3D<double> > vxyz_d (v.x(), v.y(), v.z());
00152 
00153   double r = std::sqrt (v.x()*v.x() + v.y()*v.y() + v.z()*v.z());
00154   double rho = std::sqrt (v.x()*v.x() + v.y()*v.y());
00155   double z   = v.z();
00156 //   double theta = r>0 ? std::acos ( z/r ) : 0;
00157 //   if (std::abs( std::abs(z) - r) < 10*r* std::numeric_limits<double>::epsilon() ) 
00158    double  theta = std::atan2( rho, z );  // better when theta is small or close to pi
00159   
00160   double phi = rho>0 ? std::atan2 (v.y(), v.x()) : 0;
00161   DisplacementVector3D< Polar3D<double> > vrtp_d ( r, theta, phi );
00162 
00163   double eta;
00164   if (rho != 0) {
00165     eta = -std::log(std::tan(theta/2));
00166         #ifdef TRACE1
00167         std::cout <<  ":::: rho != 0\n"
00168                   <<  ":::: theta = << " << theta
00169                   <<"/n:::: tan(theta/2) = " << std::tan(theta/2)
00170                   <<"\n:::: eta = " << eta << "\n";
00171         #endif
00172   } else if (v.z() == 0) {
00173     eta = 0;
00174         #ifdef TRACE1
00175         std::cout <<  ":::: v.z() == 0\n"
00176                   <<"\n:::: eta = " << eta << "\n";
00177         #endif
00178   } else if (v.z() > 0) {
00179     eta = v.z() + etaMax<long double>();
00180         #ifdef TRACE1
00181         std::cout <<  ":::: v.z() > 0\n"
00182                   <<  ":::: etaMax =  " << etaMax<long double>()
00183                   <<"\n:::: eta = " << eta << "\n";
00184         #endif
00185   } else {
00186     eta = v.z() - etaMax<long double>();
00187         #ifdef TRACE1
00188         std::cout <<  ":::: v.z() < 0\n"
00189                   <<  ":::: etaMax =  " << etaMax<long double>()
00190                   <<"\n:::: eta = " << eta << "\n";
00191         #endif
00192   }
00193 
00194 #ifdef DEBUG
00195   std::cout << "           Testing DisplacementVector3D :  ";
00196 #endif
00197 
00198   DisplacementVector3D< CylindricalEta3D<double> > vrep_d ( rho, eta, phi );
00199 
00200   ret |= compare3D( vxyz_d, vrtp_d, ticks);
00201   ret |= compare3D( vrtp_d, vxyz_d, ticks);
00202   ret |= compare3D( vxyz_d, vrep_d, ticks);
00203   ret |= compare3D( vrtp_d, vrep_d, ticks);
00204 
00205   DisplacementVector3D< Cylindrical3D<double> >   vrzp_d ( rho, z, phi );
00206 
00207   ret |= compare3D( vxyz_d, vrzp_d, ticks);
00208   ret |= compare3D( vrtp_d, vrzp_d, ticks);
00209   ret |= compare3D( vrep_d, vrzp_d, ticks);
00210 
00211   DisplacementVector3D< Cartesian3D<float> >      vxyz_f (v.x(), v.y(), v.z());
00212   DisplacementVector3D< Polar3D<float> >          vrtp_f ( r, theta, phi );
00213   DisplacementVector3D< CylindricalEta3D<float> > vrep_f ( rho, eta, phi );
00214 
00215   ret |= compare3D( vxyz_d, vxyz_f, ticks);
00216   ret |= compare3D( vxyz_d, vrep_f, ticks);
00217   ret |= compare3D( vrtp_d, vrep_f, ticks);
00218 
00219   ret |= compare3D( vxyz_f, vxyz_f, ticks);
00220   ret |= compare3D( vxyz_f, vrep_f, ticks);
00221   ret |= compare3D( vrtp_f, vrep_f, ticks);
00222 
00223 #ifdef DEBUG
00224   if (ret == 0) std::cout << "\t OK\n";
00225   else { 
00226      std::cout << "\t FAIL\n";
00227      std::cerr << "\n>>>>> Testing DisplacementVector3D from " << v << " ticks = " << ticks 
00228                << "\t:\t FAILED\n";
00229   }
00230   std::cout << "           Testing PositionVector3D     :   ";
00231 #endif
00232 
00233 
00234   PositionVector3D< Cartesian3D     <double> > pxyz_d; pxyz_d = vxyz_d;
00235   PositionVector3D< Polar3D         <double> > prtp_d; prtp_d = vrtp_d;
00236   PositionVector3D< CylindricalEta3D<double> > prep_d; prep_d = vrep_d;
00237   PositionVector3D< Cylindrical3D   <double> > przp_d; przp_d = vrzp_d;
00238 
00239   ret |= compare3D( pxyz_d, prtp_d, ticks);
00240   ret |= compare3D( vxyz_d, prep_d, ticks);
00241   ret |= compare3D( vrtp_d, prep_d, ticks);
00242   ret |= compare3D( vxyz_d, przp_d, ticks);
00243 
00244   PositionVector3D< Cartesian3D<float> >      pxyz_f (v.x(), v.y(), v.z());
00245   PositionVector3D< Polar3D<float> >          prtp_f ( r, theta, phi );
00246   PositionVector3D< CylindricalEta3D<float> > prep_f ( rho, eta, phi );
00247 
00248   ret |= compare3D( vxyz_d, pxyz_f, ticks);
00249   ret |= compare3D( vxyz_d, prep_f, ticks);
00250   ret |= compare3D( vrtp_d, prep_f, ticks);
00251 
00252   ret |= compare3D( vxyz_f, pxyz_f, ticks);
00253   ret |= compare3D( vxyz_f, prep_f, ticks);
00254   ret |= compare3D( vrtp_f, prep_f, ticks);
00255 
00256 #ifdef DEBUG
00257   if (ret == 0) std::cout << "\t\t OK\n";
00258   else { 
00259      std::cout << "\t FAIL\n";
00260      std::cerr << "\n>>>>> Testing PositionVector3D from     " << v << " ticks = " << ticks 
00261                << "\t:\t FAILED\n";
00262   }
00263 #endif
00264   return ret;
00265 }
00266 
00267 
00268 
00269 int coordinates3D () {
00270   int ret = 0;
00271 
00272   ret |= test3D (XYZVector ( 0.0, 0.0, 0.0 )     ,2 );
00273   ret |= test3D (XYZVector ( 1.0, 2.0, 3.0 )     ,6 );
00274   ret |= test3D (XYZVector ( -1.0, 2.0, 3.0 )    ,6 );
00275   ret |= test3D (XYZVector ( 1.0, -2.0, 3.0 )    ,6 );
00276   ret |= test3D (XYZVector ( 1.0, 2.0, -3.0 )    ,6 );
00277   ret |= test3D (XYZVector ( -1.0, -2.0, 3.0 )   ,6 );
00278   ret |= test3D (XYZVector ( -1.0, 2.0, -3.0 )   ,6 );
00279   ret |= test3D (XYZVector ( 1.0, -2.0, -3.0 )   ,6 );
00280   ret |= test3D (XYZVector ( -1.0, -2.0, -3.0 )  ,6 );
00281   ret |= test3D (XYZVector ( 8.0, 0.0, 0.0 )     ,6 );
00282   ret |= test3D (XYZVector ( -8.0, 0.0, 0.0 )    ,12 );
00283   ret |= test3D (XYZVector ( 0.0, 9.0, 0.0 )     ,6 );
00284   ret |= test3D (XYZVector ( 0.0, -9.0, 0.0 )    ,6 );
00285 // rho == 0 tests the beyon-eta-max cases of cylindricalEta
00286   ret |= test3D (XYZVector ( 0.0, 0.0, 7.0 )     ,8 );
00287   ret |= test3D (XYZVector ( 0.0, 0.0, -7.0 )    ,8 );
00288 // Larger ratios among coordinates presents a precision challenge
00289   ret |= test3D (XYZVector ( 16.0, 0.02, .01 )   ,10 );
00290   ret |= test3D (XYZVector ( -16.0, 0.02, .01 )  ,10 );
00291   ret |= test3D (XYZVector ( -.01, 16.0, .01 )   ,2000 ); 
00292   ret |= test3D (XYZVector ( -.01, -16.0, .01 )  ,2000 ); 
00293   ret |= test3D (XYZVector ( 1.0, 2.0, 30.0 )    ,10 );  
00294         // NOTE -- these larger erros are likely the results of treating
00295         //         the vector in a ctor or assignment as foreign... 
00296         // NO -- I'm fouling up the value of x() !!!!!
00297 // As we push to higher z with zero rho, some accuracy loss is expected
00298   ret |= test3D (XYZVector ( 0.0, 0.0, 15.0 )    ,30 );
00299   ret |= test3D (XYZVector ( 0.0, 0.0, -15.0 )   ,30 );
00300   ret |= test3D (XYZVector ( 0.0, 0.0, 35.0 )    ,30 );
00301   ret |= test3D (XYZVector ( 0.0, 0.0, -35.0 )   ,30 );
00302 // When z is big compared to rho, it is very hard to get precision in polar/eta:
00303   ret |= test3D (XYZVector ( 0.01, 0.02, 16.0 )  ,10 );
00304   ret |= test3D (XYZVector ( 0.01, 0.02, -16.0 ) ,40000 );
00305 // test case when eta is large 
00306   ret |= test3D (XYZVector ( 1.E-8, 1.E-8, 10.0 )  , 20 );
00307 // when z is neg error is larger in eta when calculated from polar 
00308 // since we have a larger error in theta which is closer to pi 
00309   ret |= test3D (XYZVector ( 1.E-8, 1.E-8, -10.0 ) ,2.E9 );   
00310 
00311   // small value of z
00312   ret |= test3D (XYZVector ( 10., 10., 1.E-8 ) ,1.0E6 );   
00313   ret |= test3D (XYZVector ( 10., 10., -1.E-8 ) ,1.0E6 );   
00314 
00315 
00316   return ret;
00317 }
00318 
00319 int main() { 
00320    int ret = coordinates3D();
00321    if (ret)  std::cerr << "test FAILED !!! " << std::endl; 
00322    else   std::cout << "test OK " << std::endl;
00323    return ret;
00324 }

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