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