Cmp.hh

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef RIVET_Cmp_HH
00003 #define RIVET_Cmp_HH
00004 
00005 #include "Rivet/Rivet.hh"
00006 #include "Rivet/Projection.hh"
00007 #include "Cmp.fhh"
00008 #include <typeinfo>
00009 
00010 
00011 namespace Rivet {
00012 
00013 
00014   /// Cmp is a helper class to be used when checking the ordering of two
00015   /// objects. When implicitly converted to an integer the value will be
00016   /// negative if the two objects used in the constructor are ordered and
00017   /// positive if they are not. Zero will be returned if they are equal.
00018   ///
00019   /// The main usage of the Cmp class is if several variables should be
00020   /// checked for ordering in which case several Cmp objects can be
00021   /// combined as follows: <code>cmp(a1, a2) || cmp(b1, b2) || cmp(c1,
00022   /// c2)</code> where cmp is a global function for easy creation of Cmp
00023   /// objects.
00024   template <typename T>
00025   class Cmp {
00026   public:
00027  
00028     /// @name Standard constructors etc.
00029     //@{
00030     /// The default constructor.
00031     Cmp(const T& t1, const T& t2)
00032       : _value(UNDEFINED), _objects(&t1, &t2) { }
00033  
00034     /// The copy constructor.
00035     template <typename U>
00036     Cmp(const Cmp<U>& x)
00037       : _value(x), _objects(0, 0) { }
00038  
00039     /// The destructor is not virtual since this is not intended to be a base class.
00040     ~Cmp() { };
00041  
00042     /// The assignment operator.
00043     template <typename U>
00044     const Cmp<T>& operator=(const Cmp<U>& x) {
00045       _value = x;
00046       return *this;
00047     }
00048     //@}
00049  
00050   public:
00051  
00052     /// Automatically convert to an enum.
00053     operator CmpState() const {
00054       _compare();
00055       return _value;
00056     }
00057 
00058     /// Automatically convert to an integer.
00059     operator int() const {
00060       _compare();
00061       return _value;
00062     }
00063  
00064     /// If this state is equivalent, set this state to the state of \a c.
00065     template <typename U>
00066     const Cmp<T>& operator||(const Cmp<U>& c) const {
00067       _compare();
00068       if (_value == EQUIVALENT) _value = c;
00069       return *this;
00070     }
00071  
00072   private:
00073  
00074     /// Perform the actual comparison if necessary.
00075     void _compare() const {
00076       if (_value == UNDEFINED) {
00077         less<T> l;
00078         if ( l(*_objects.first, *_objects.second) ) _value = ORDERED;
00079         else if ( l(*_objects.second, *_objects.first) ) _value = UNORDERED;
00080         else _value = EQUIVALENT;
00081       }
00082     }
00083  
00084     /// The state of this object.
00085     mutable CmpState _value;
00086  
00087     /// The objects to be compared.
00088     pair<const T*, const T*> _objects;
00089  
00090   };
00091 
00092 
00093 
00094   /// Specialization of the Cmp helper class to be used when checking the
00095   /// ordering of two Projection objects. When implicitly converted to an
00096   /// integer the value will be negative if the two objects used in the
00097   /// constructor are ordered and positive if they are not. Zero will be
00098   /// returned if they are equal. This specialization uses directly the
00099   /// virtual compare() function in the Projection class.
00100   ///
00101   /// The main usage of the Cmp class is if several variables should be
00102   /// checked for ordering in which case several Cmp objects can be
00103   /// combined as follows: <code>cmp(a1, a2) || cmp(b1, b2) || cmp(c1,
00104   /// c2)</code> where cmp is a global function for easy creation of Cmp
00105   /// objects.
00106   template <>
00107   class Cmp<Projection> {
00108   public:
00109  
00110     /// @name Standard constructors and destructors.
00111     //@{
00112     /// The default constructor.
00113     Cmp(const Projection& p1, const Projection& p2)
00114       : _value(UNDEFINED), _objects(&p1, &p2)
00115     { }
00116  
00117     /// The copy constructor.
00118     template <typename U>
00119     Cmp(const Cmp<U>& x)
00120       : _value(x), _objects(0, 0)
00121     { }
00122  
00123     /// The destructor is not virtual since this is not intended to be a base class.
00124     ~Cmp() { };
00125  
00126     /// The assignment operator.
00127     template <typename U>
00128     const Cmp<Projection>& operator=(const Cmp<U>& x) {
00129       _value = x;
00130       return *this;
00131     }
00132     //@}
00133  
00134   public:
00135  
00136     /// Automatically convert to an enum.
00137     operator CmpState() const {
00138       _compare();
00139       return _value;
00140     }
00141 
00142 
00143     /// Automatically convert to an integer.
00144     operator int() const {
00145       _compare();
00146       return _value;
00147     }
00148  
00149     /// If this state is equivalent, set this state to the state of \a c.
00150     template <typename U>
00151     const Cmp<Projection>& operator||(const Cmp<U>& c) const {
00152       _compare();
00153       if (_value == EQUIVALENT) _value = c;
00154       return *this;
00155     }
00156  
00157   private:
00158  
00159     /// Perform the actual comparison if necessary.
00160     void _compare() const {
00161       if (_value == UNDEFINED) {
00162         const std::type_info& id1 = typeid(*_objects.first);
00163         const std::type_info& id2 = typeid(*_objects.second);
00164         if (id1.before(id2)) _value = ORDERED;
00165         else if (id2.before(id1)) _value = UNORDERED;
00166         else {
00167           int c = _objects.first->compare(*_objects.second);
00168           if (c < 0) _value = ORDERED;
00169           else if (c > 0) _value = UNORDERED;
00170           else _value = EQUIVALENT;
00171         }
00172       }
00173     }
00174  
00175   private:
00176  
00177     /// The state of this object.
00178     mutable CmpState _value;
00179  
00180     /// The objects to be compared.
00181     pair<const Projection*, const Projection*> _objects;
00182  
00183   };
00184 
00185 
00186 
00187 
00188   /// Specialization of the Cmp helper class to be used when checking the
00189   /// ordering of two floating point numbers. When implicitly converted to an
00190   /// integer the value will be negative if the two objects used in the
00191   /// constructor are ordered and positive if they are not. Zero will be
00192   /// returned if they are equal. This specialization uses the Rivet
00193   /// fuzzyEquals function to indicate equivalence protected from numerical
00194   /// precision effects.
00195   ///
00196   /// The main usage of the Cmp class is if several variables should be
00197   /// checked for ordering in which case several Cmp objects can be
00198   /// combined as follows: <code>cmp(a1, a2) || cmp(b1, b2) || cmp(c1,
00199   /// c2)</code> where cmp is a global function for easy creation of Cmp
00200   /// objects.
00201   template <>
00202   class Cmp<double> {
00203   public:
00204  
00205     /// @name Standard constructors and destructors.
00206     //@{
00207     /// The default constructor.
00208     Cmp(const double p1, const double p2)
00209       : _value(UNDEFINED), _numA(p1), _numB(p2)
00210     { }
00211  
00212     /// The copy constructor.
00213     template <typename U>
00214     Cmp(const Cmp<U>& x)
00215       : _value(x), _numA(0.0), _numB(0.0)
00216     { }
00217  
00218     /// The destructor is not virtual since this is not intended to be a base class.
00219     ~Cmp() { }
00220  
00221     /// The assignment operator.
00222     template <typename U>
00223     const Cmp<double>& operator=(const Cmp<U>& x) {
00224       _value = x;
00225       return *this;
00226     }
00227     //@}
00228  
00229   public:
00230  
00231     /// Automatically convert to an enum.
00232     operator CmpState() const {
00233       _compare();
00234       return _value;
00235     }
00236 
00237     /// Automatically convert to an integer.
00238     operator int() const {
00239       _compare();
00240       return _value;
00241     }
00242  
00243     /// If this state is equivalent, set this state to the state of \a c.
00244     template <typename U>
00245     const Cmp<double>& operator||(const Cmp<U>& c) const {
00246       _compare();
00247       if (_value == EQUIVALENT) _value = c;
00248       return *this;
00249     }
00250  
00251   private:
00252  
00253     /// Perform the actual comparison if necessary.
00254     void _compare() const {
00255       if (_value == UNDEFINED) {
00256         if (fuzzyEquals(_numA,_numB)) _value = EQUIVALENT;
00257         else if (_numA < _numB) _value = ORDERED;
00258         else _value = UNORDERED;
00259       }
00260     }
00261  
00262   private:
00263  
00264     /// The state of this object.
00265     mutable CmpState _value;
00266  
00267     /// The objects to be compared.
00268     double _numA, _numB;
00269  
00270   };
00271 
00272 
00273 
00274   ///////////////////////////////////////////////////////////////////
00275 
00276 
00277 
00278   /// Global helper function for easy creation of Cmp objects.
00279   template <typename T>
00280   inline Cmp<T> cmp(const T& t1, const T& t2) {
00281     return Cmp<T>(t1, t2);
00282   }
00283 
00284 
00285   /// Typedef for Cmp<Projection>
00286   typedef Cmp<Projection> PCmp;
00287 
00288   /// Global helper function for easy creation of Cmp<Projection> objects.
00289   inline Cmp<Projection> pcmp(const Projection& p1, const Projection& p2) {
00290     return Cmp<Projection>(p1, p2);
00291   }
00292 
00293   /// Global helper function for easy creation of Cmp<Projection> objects from
00294   /// two parent projections and their common name for the projection to be compared.
00295   inline Cmp<Projection> pcmp(const Projection& parent1, const Projection& parent2, const string& pname) {
00296     return Cmp<Projection>(parent1.getProjection(pname), parent2.getProjection(pname));
00297   }
00298 
00299   /// Global helper function for easy creation of Cmp<Projection> objects from
00300   /// two parent projections and their common name for the projection to be compared.
00301   /// This version takes one parent as a pointer.
00302   inline Cmp<Projection> pcmp(const Projection* parent1, const Projection& parent2, const string& pname) {
00303     assert(parent1);
00304     return Cmp<Projection>(parent1->getProjection(pname), parent2.getProjection(pname));
00305   }
00306 
00307   /// Global helper function for easy creation of Cmp<Projection> objects from
00308   /// two parent projections and their common name for the projection to be compared.
00309   /// This version takes one parent as a pointer.
00310   inline Cmp<Projection> pcmp(const Projection& parent1, const Projection* parent2, const string& pname) {
00311     assert(parent2);
00312     return Cmp<Projection>(parent1.getProjection(pname), parent2->getProjection(pname));
00313   }
00314 
00315   /// Global helper function for easy creation of Cmp<Projection> objects from
00316   /// two parent projections and their common name for the projection to be compared.
00317   inline Cmp<Projection> pcmp(const Projection* parent1, const Projection* parent2, const string& pname) {
00318     assert(parent1);
00319     assert(parent2);
00320     return Cmp<Projection>(parent1->getProjection(pname), parent2->getProjection(pname));
00321   }
00322 
00323 
00324 }
00325 
00326 
00327 #endif