interval.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     interval.hpp -- Approches to represent intervals.
00004 
00005     This file is a part of the Arageli library.
00006 
00007     Copyright (C) Nikolai Yu. Zolotykh, 1999--2006
00008     Copyright (C) Sergey S. Lyalin, 2006
00009     University of Nizhni Novgorod, Russia, 2005--2006
00010 
00011 *****************************************************************************/
00012 
00024 #ifndef _ARAGELI_interval_hpp_
00025 #define _ARAGELI_interval_hpp_
00026 
00027 #include "config.hpp"
00028 
00029 #include <iostream>
00030 #include <sstream>
00031 #include <utility>
00032 
00033 #include "frwrddecl.hpp"
00034 #include "function_traits.hpp"
00035 #include "factory.hpp"
00036 #include "cmp.hpp"
00037 //#include "vector.hpp"
00038 
00039 #include "std_import.hpp"
00040 
00041 
00042 namespace Arageli
00043 {
00044 
00046 enum interval_kind
00047 {
00048     interval_empty = 0, 
00049     interval_point = 1, 
00050     interval_length = 2 
00051 };
00052 
00054 
00057 template <typename T> class interval
00058 {
00059     std::pair<T, T> lims;
00060 
00061     template <typename T1>
00062     friend class interval;
00063 
00064 public:
00065     
00067     typedef T value_type;
00068 
00070     typedef typename binary_function_traits<function_tag::minus, T, T>::result_type difference_type;
00071     
00073     interval () : lims(null<T>(), null<T>()) {}
00074 
00076     template <typename T1>
00077     interval (const T1& x) : lims(x, x) {}
00078 
00080     template <typename T1, typename T2>
00081     interval (const T1& first_a, const T2& second_a)
00082     : lims(first_a, second_a) {}
00083 
00085     template <typename T1>
00086     interval (const interval<T1>& x)
00087     : lims(x.lims.first, x.lims.second) {}
00088 
00090 
00092     interval (const char* s)
00093     {
00094         std::istringstream buf(s);
00095         buf >> *this;
00096     }
00097 
00098     template <typename T1>
00099     interval& operator= (const T1& x)
00100     {
00101         lims.first = x;
00102         lims.second = x;
00103         return *this;
00104     }
00105 
00106     template <typename T1>
00107     interval& operator= (const interval<T1>& x)
00108     {
00109         lims.first = x.lims.first;
00110         lims.second = x.lims.second;
00111         return *this;
00112     }
00113 
00114     interval& operator= (const char* s)
00115     {
00116         std::istringstream buf(s);
00117         buf >> *this;
00118         return *this;
00119     }
00120 
00121     const T& first () const { return lims.first; }
00122     const T& left () const { return lims.first; }
00123     const T& second () const { return lims.second; }
00124     const T& right () const { return lims.second; }
00125 
00126     T& first () { return lims.first; }
00127     T& left () { return lims.first; }
00128     T& second () { return lims.second; }
00129     T& right () { return lims.second; }
00130     
00132     bool is_point () const { return lims.first == lims.second; }
00133 
00135     bool is_empty () const { return lims.first > lims.second; }
00136 
00138     bool is_negligible () const { return lims.first >= lims.second; }
00139 
00140     interval_kind kind () const
00141     { return interval_kind(cmp(lims.second, lims.first) + 1); }
00142     
00144     typename binary_function_traits<function_tag::minus, T, T>::result_type
00145     length () const { return lims.second - lims.first; }
00146 
00148     void turn () { swap(lims.first, lims.second); }
00149 
00150     template <typename T1>
00151     bool on_limits (const T1& x) const
00152     { return lims.first == x || lims.second == x; }
00153 
00155     template <typename T1>
00156     bool inside (const T1& x) const
00157     { return lims.first < x && x < lims.second; }
00158 
00160     template <typename T1>
00161     bool outside (const T1& x) const
00162     { return x < lims.first || lims.second < x; }
00163 
00164     template <typename T1>
00165     interval& operator+= (const interval<T1>& x)
00166     { return *this = *this + x; }
00167 
00168     template <typename T1>
00169     interval& operator-= (const interval<T1>& x)
00170     { return *this = *this - x; }
00171 
00172     template <typename T1>
00173     interval& operator*= (const interval<T1>& x)
00174     { return *this = *this * x; }
00175 
00176     template <typename T1>
00177     interval& operator/= (const interval<T1>& x)
00178     { return *this = *this / x; }
00179 
00180     interval& operator++ () { return *this += interval(unit<T>()); }
00181     interval& operator-- () { return *this -= interval(unit<T>()); }
00182 
00183     interval operator++ (int) { interval t = *this; operator++(); return t; }
00184     interval operator-- (int) { interval t = *this; operator--(); return t; }
00185 
00186     const interval& operator+ () const { return *this; }
00187     interval operator- () const { return interval(null<T>()) - *this; }
00188 
00189 };
00190 
00191 
00192 template <typename T>
00193 interval<T> operator+ (const interval<T>& a, const interval<T>& b)
00194 {
00195     // WARNING! There is simpler way for reals.
00196     
00197     T   p1 = a.first() + b.first(),
00198         p2 = a.first() + b.second(),
00199         p3 = a.second() + b.first(),
00200         p4 = a.second() + b.second();
00201     
00202     return interval<T>
00203     (
00204         std::min(std::min(p1, p2), std::min(p3, p4)),
00205         std::max(std::max(p1, p2), std::max(p3, p4))
00206     );
00207 }
00208 
00209 template <typename T>
00210 interval<T> operator- (const interval<T>& a, const interval<T>& b)
00211 {
00212     // WARNING! There is simpler way for reals.
00213     
00214     T   p1 = a.first() - b.first(),
00215         p2 = a.first() - b.second(),
00216         p3 = a.second() - b.first(),
00217         p4 = a.second() - b.second();
00218     
00219     return interval<T>
00220     (
00221         std::min(std::min(p1, p2), std::min(p3, p4)),
00222         std::max(std::max(p1, p2), std::max(p3, p4))
00223     );
00224 }
00225 
00226 template <typename T>
00227 interval<T> operator* (const interval<T>& a, const interval<T>& b)
00228 {
00229     // WARNING! There is simpler way for reals.
00230     
00231     T   p1 = a.first() * b.first(),
00232         p2 = a.first() * b.second(),
00233         p3 = a.second() * b.first(),
00234         p4 = a.second() * b.second();
00235     
00236     return interval<T>
00237     (
00238         std::min(std::min(p1, p2), std::min(p3, p4)),
00239         std::max(std::max(p1, p2), std::max(p3, p4))
00240     );
00241 }
00242 
00243 template <typename T>
00244 interval<T> operator/ (const interval<T>& a, const interval<T>& b)
00245 {
00246     // WARNING! There is simpler way for reals.
00247     ARAGELI_ASSERT_0(sign(b.first())*sign(b.second()) > 0);
00248     
00249     T   p1 = a.first() / b.first(),
00250         p2 = a.first() / b.second(),
00251         p3 = a.second() / b.first(),
00252         p4 = a.second() / b.second();
00253     
00254     return interval<T>
00255     (
00256         std::min(std::min(p1, p2), std::min(p3, p4)),
00257         std::max(std::max(p1, p2), std::max(p3, p4))
00258     );
00259 }
00260 
00261 
00262 template <typename T1, typename T2>
00263 inline bool are_overlap_intervals_oooo (const T1& a, const T2& b)
00264 {
00265     if(a.is_negligible() || b.is_negligible())return false;
00266     return
00267         (a.first() < b.first()) ? (b.first < a.second) : (a.first < b.second);
00268 }
00269 
00270 
00271 //template <typename T1, typename T2>
00272 //inline bool is_overlap_interval_cooo (const T1& a, const T2& b)
00273 //{
00274 //  if(a.is_negligible() || b.is_negligible())return false;
00275 //  return
00276 //      (a.first() < b.first()) ? (b.first < a.second) : (a.first < b.second);
00277 //}
00278 //
00279 
00280 template <typename Seg1, typename Seg2>
00281 inline bool is_overlap_segs (const Seg1& a, const Seg2& b)
00282 {
00283     return (a.first() <= b.first()) ? (b.first() <= a.second()) : (a.first() <= b.second());
00284 }
00285 
00286 
00287 template <typename Out, typename T>
00288 Out& operator<< (Out& out, const interval<T>& x)
00289 {
00290     out << "(" << x.first() << ", " << x.second() << ")";
00291     return out;
00292 }
00293 
00294 template <typename In, typename T>
00295 In& operator>> (In& in, interval<T>& x)
00296 {
00297     vector<T, false> buf;   // WARNING! TEMPORARY!
00298     in >> buf;
00299     if(!in && !in.eof() || buf.size() != 2)
00300         in.clear(std::ios::badbit);
00301     else
00302     {
00303         x.first() = buf[0];
00304         x.second() = buf[1];
00305     }
00306 
00307     return in;
00308 }
00309 
00310 //template <typename T1, typename T2, typename Outiter>
00311 //void generate_range_helper (interval<T1>& t1, const interval<T2>& t2, Outiter outiter)
00312 //{ ARAGELI_ASSERT_ALWAYS(!"generate_range_helper is not implemented for interval"); }
00313 //
00314 //
00315 //template <typename T1, typename T2, typename T3, typename Outiter>
00316 //void generate_range_helper (interval<T1>& t1, const interval<T2>& t2, const interval<T3>& t3, Outiter outiter)
00317 //{ ARAGELI_ASSERT_ALWAYS(!"generate_range_helper is not implemented for interval"); }
00318 
00319 
00321 template <typename T1, typename T2>
00322 bool are_comparable_oooo (const interval<T1>& a, const interval<T2>& b)
00323 { return !are_overlap_intervals_oooo(a, b); }
00324 
00325 
00327 
00328 template <typename T1, typename T2>
00329 int cmp (const interval<T1>& a, const interval<T2>& b)
00330 {
00331     if(a.is_empty())
00332         if(b.is_empty())return 0;
00333         else return -1;
00334     else if(b.is_empty())return +1;
00335 
00336     ARAGELI_ASSERT_1(!a.is_empty() && !b.is_empty());
00337 
00338     if(a.left() < b.left())return -1;
00339     else if(a.left() > b.left())return +1;
00340     else if(a.right() < b.right())return -1;
00341     else if(a.right() > b.right())return +1;
00342     else return 0;
00343 }
00344 
00345 
00346 template <typename T1, typename T2>
00347 bool operator< (const interval<T1>& a, const interval<T2>& b)
00348 {
00349     if(a.is_empty() || b.is_empty())return true;
00350     return a.right() < b.left();
00351 }
00352 
00353 
00354 template <typename T1, typename T2>
00355 bool operator> (const interval<T1>& a, const interval<T2>& b)
00356 {
00357     if(a.is_empty() || b.is_empty())return true;
00358     return b.right() < a.left();
00359 }
00360 
00361 
00362 template <typename T1, typename T2>
00363 bool operator<= (const interval<T1>& a, const interval<T2>& b)
00364 {
00365     if(a.is_empty() || b.is_empty())return true;
00366     return a.right() <= b.left();
00367 }
00368 
00369 
00370 template <typename T1, typename T2>
00371 bool operator>= (const interval<T1>& a, const interval<T2>& b)
00372 {
00373     if(a.is_empty() || b.is_empty())return true;
00374     return b.right() <= a.left();
00375 }
00376 
00377 
00378 template <typename T1, typename T2>
00379 bool operator== (const interval<T1>& a, const interval<T2>& b)
00380 {
00381     if(a.is_empty() && b.is_empty())return true;
00382     return a.left() == b.left() && a.right() == b.right();
00383 }
00384 
00385 
00386 template <typename T1, typename T2>
00387 inline bool operator!= (const interval<T1>& a, const interval<T2>& b)
00388 { return !(a == b); }
00389 
00390 
00391 template <typename T>
00392 interval<T> abs (const interval<T>& x)
00393 {
00394     if(x.is_empty())return x;
00395 
00396     if(!x.outside(null<T>()))
00397         return interval<T>(null<T>(), std::max(abs(x.left()), abs(x.right())));
00398     else
00399     {
00400         T absleft = abs(x.left()), absright = abs(x.right());
00401         return interval<T>(std::min(absleft, absright), std::max(absleft, absright));
00402     }
00403 }
00404 
00405 
00406 
00407 
00408 } // namesapce Arageli
00409 
00410 namespace std
00411 {
00412 
00413 template <typename T>
00414 inline Arageli::interval<T> abs (const Arageli::interval<T>& x)
00415 { return Arageli::abs(x); }
00416 
00417 }
00418 
00419 
00420 //#ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00421 //  #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_INTERVAL
00422 //  #include "interval.cpp"
00423 //  #undef  ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_INTERVAL
00424 //#endif
00425 
00426 #endif

Generated on Thu Aug 31 17:38:07 2006 for Arageli by  doxygen 1.4.7