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