00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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
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
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
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
00272
00273
00274
00275
00276
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;
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
00311
00312
00313
00314
00315
00316
00317
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 }
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
00421
00422
00423
00424
00425
00426 #endif