Rivet  1.8.0
Cmp.hh
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 
00026   template <typename T>
00027   class Cmp {
00028   public:
00029 
00031 
00032 
00034     Cmp(const T& t1, const T& t2)
00035       : _value(UNDEFINED), _objects(&t1, &t2) { }
00036 
00038     template <typename U>
00039     Cmp(const Cmp<U>& x)
00040       : _value(x), _objects(0, 0) { }
00041 
00043     ~Cmp() { };
00044 
00046     template <typename U>
00047     const Cmp<T>& operator=(const Cmp<U>& x) {
00048       _value = x;
00049       return *this;
00050     }
00051 
00053 
00054   public:
00055 
00057     operator CmpState() const {
00058       _compare();
00059       return _value;
00060     }
00061 
00063     operator int() const {
00064       _compare();
00065       return _value;
00066     }
00067 
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 
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 
00089     mutable CmpState _value;
00090 
00092     pair<const T*, const T*> _objects;
00093 
00094   };
00095 
00096 
00111   template <>
00112   class Cmp<Projection> {
00113   public:
00114 
00116 
00117 
00118     Cmp(const Projection& p1, const Projection& p2)
00119       : _value(UNDEFINED), _objects(&p1, &p2)
00120     { }
00121 
00123     template <typename U>
00124     Cmp(const Cmp<U>& x)
00125       : _value(x), _objects(0, 0)
00126     { }
00127 
00129     ~Cmp() { };
00130 
00132     template <typename U>
00133     const Cmp<Projection>& operator=(const Cmp<U>& x) {
00134       _value = x;
00135       return *this;
00136     }
00138 
00139   public:
00140 
00142     operator CmpState() const {
00143       _compare();
00144       return _value;
00145     }
00146 
00147 
00149     operator int() const {
00150       _compare();
00151       return _value;
00152     }
00153 
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 
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 
00183     mutable CmpState _value;
00184 
00186     pair<const Projection*, const Projection*> _objects;
00187 
00188   };
00189 
00190 
00191 
00192 
00206   template <>
00207   class Cmp<double> {
00208   public:
00209 
00211 
00212 
00213     Cmp(const double p1, const double p2)
00214       : _value(UNDEFINED), _numA(p1), _numB(p2)
00215     { }
00216 
00218     template <typename U>
00219     Cmp(const Cmp<U>& x)
00220       : _value(x), _numA(0.0), _numB(0.0)
00221     { }
00222 
00224     ~Cmp() { }
00225 
00227     template <typename U>
00228     const Cmp<double>& operator=(const Cmp<U>& x) {
00229       _value = x;
00230       return *this;
00231     }
00233 
00234   public:
00235 
00237     operator CmpState() const {
00238       _compare();
00239       return _value;
00240     }
00241 
00243     operator int() const {
00244       _compare();
00245       return _value;
00246     }
00247 
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 
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 
00270     mutable CmpState _value;
00271 
00273     double _numA, _numB;
00274 
00275   };
00276 
00277 
00278 
00280 
00281 
00282 
00284   template <typename T>
00285   inline Cmp<T> cmp(const T& t1, const T& t2) {
00286     return Cmp<T>(t1, t2);
00287   }
00288 
00289 
00291   typedef Cmp<Projection> PCmp;
00292 
00293 
00295   inline Cmp<Projection> pcmp(const Projection& p1, const Projection& p2) {
00296     return Cmp<Projection>(p1, p2);
00297   }
00298 
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 
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 
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 
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