File indexing completed on 2025-01-30 09:49:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_NUMERIC_INTERVAL_INTERVAL_HPP
0011 #define BOOST_NUMERIC_INTERVAL_INTERVAL_HPP
0012
0013 #include <stdexcept>
0014 #include <string>
0015 #include <boost/numeric/interval/detail/interval_prototype.hpp>
0016
0017 namespace boost {
0018 namespace numeric {
0019
0020 namespace interval_lib {
0021
0022 class comparison_error
0023 : public std::runtime_error
0024 {
0025 public:
0026 comparison_error()
0027 : std::runtime_error("boost::interval: uncertain comparison")
0028 { }
0029 };
0030
0031 }
0032
0033
0034
0035
0036
0037 template<class T, class Policies>
0038 class interval
0039 {
0040 private:
0041 struct interval_holder;
0042 struct number_holder;
0043 public:
0044 typedef T base_type;
0045 typedef Policies traits_type;
0046
0047 T const &lower() const;
0048 T const &upper() const;
0049
0050 interval();
0051 interval(T const &v);
0052 template<class T1> interval(T1 const &v);
0053 interval(T const &l, T const &u);
0054 template<class T1, class T2> interval(T1 const &l, T2 const &u);
0055 interval(interval<T, Policies> const &r);
0056 template<class Policies1> interval(interval<T, Policies1> const &r);
0057 template<class T1, class Policies1> interval(interval<T1, Policies1> const &r);
0058
0059 interval &operator=(T const &v);
0060 template<class T1> interval &operator=(T1 const &v);
0061 interval &operator=(interval<T, Policies> const &r);
0062 template<class Policies1> interval &operator=(interval<T, Policies1> const &r);
0063 template<class T1, class Policies1> interval &operator=(interval<T1, Policies1> const &r);
0064
0065 void assign(const T& l, const T& u);
0066
0067 static interval empty();
0068 static interval whole();
0069 static interval hull(const T& x, const T& y);
0070
0071 interval& operator+= (const T& r);
0072 interval& operator+= (const interval& r);
0073 interval& operator-= (const T& r);
0074 interval& operator-= (const interval& r);
0075 interval& operator*= (const T& r);
0076 interval& operator*= (const interval& r);
0077 interval& operator/= (const T& r);
0078 interval& operator/= (const interval& r);
0079
0080 bool operator< (const interval_holder& r) const;
0081 bool operator> (const interval_holder& r) const;
0082 bool operator<= (const interval_holder& r) const;
0083 bool operator>= (const interval_holder& r) const;
0084 bool operator== (const interval_holder& r) const;
0085 bool operator!= (const interval_holder& r) const;
0086
0087 bool operator< (const number_holder& r) const;
0088 bool operator> (const number_holder& r) const;
0089 bool operator<= (const number_holder& r) const;
0090 bool operator>= (const number_holder& r) const;
0091 bool operator== (const number_holder& r) const;
0092 bool operator!= (const number_holder& r) const;
0093
0094
0095
0096 interval(const T& l, const T& u, bool): low(l), up(u) {}
0097 void set_empty();
0098 void set_whole();
0099 void set(const T& l, const T& u);
0100
0101 private:
0102 struct interval_holder {
0103 template<class Policies2>
0104 interval_holder(const interval<T, Policies2>& r)
0105 : low(r.lower()), up(r.upper())
0106 {
0107 typedef typename Policies2::checking checking2;
0108 if (checking2::is_empty(low, up))
0109 throw interval_lib::comparison_error();
0110 }
0111
0112 const T& low;
0113 const T& up;
0114 };
0115
0116 struct number_holder {
0117 number_holder(const T& r) : val(r)
0118 {
0119 typedef typename Policies::checking checking;
0120 if (checking::is_nan(r))
0121 throw interval_lib::comparison_error();
0122 }
0123
0124 const T& val;
0125 };
0126
0127 typedef typename Policies::checking checking;
0128 typedef typename Policies::rounding rounding;
0129
0130 T low;
0131 T up;
0132 };
0133
0134 template<class T, class Policies> inline
0135 interval<T, Policies>::interval():
0136 low(static_cast<T>(0)), up(static_cast<T>(0))
0137 {}
0138
0139 template<class T, class Policies> inline
0140 interval<T, Policies>::interval(T const &v): low(v), up(v)
0141 {
0142 if (checking::is_nan(v)) set_empty();
0143 }
0144
0145 template<class T, class Policies> template<class T1> inline
0146 interval<T, Policies>::interval(T1 const &v)
0147 {
0148 if (checking::is_nan(v)) set_empty();
0149 else {
0150 rounding rnd;
0151 low = rnd.conv_down(v);
0152 up = rnd.conv_up (v);
0153 }
0154 }
0155
0156 template<class T, class Policies> template<class T1, class T2> inline
0157 interval<T, Policies>::interval(T1 const &l, T2 const &u)
0158 {
0159 if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u)) set_empty();
0160 else {
0161 rounding rnd;
0162 low = rnd.conv_down(l);
0163 up = rnd.conv_up (u);
0164 }
0165 }
0166
0167 template<class T, class Policies> inline
0168 interval<T, Policies>::interval(T const &l, T const &u): low(l), up(u)
0169 {
0170 if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u))
0171 set_empty();
0172 }
0173
0174
0175 template<class T, class Policies> inline
0176 interval<T, Policies>::interval(interval<T, Policies> const &r): low(r.lower()), up(r.upper())
0177 {}
0178
0179 template<class T, class Policies> template<class Policies1> inline
0180 interval<T, Policies>::interval(interval<T, Policies1> const &r): low(r.lower()), up(r.upper())
0181 {
0182 typedef typename Policies1::checking checking1;
0183 if (checking1::is_empty(r.lower(), r.upper())) set_empty();
0184 }
0185
0186 template<class T, class Policies> template<class T1, class Policies1> inline
0187 interval<T, Policies>::interval(interval<T1, Policies1> const &r)
0188 {
0189 typedef typename Policies1::checking checking1;
0190 if (checking1::is_empty(r.lower(), r.upper())) set_empty();
0191 else {
0192 rounding rnd;
0193 low = rnd.conv_down(r.lower());
0194 up = rnd.conv_up (r.upper());
0195 }
0196 }
0197
0198 template<class T, class Policies> inline
0199 interval<T, Policies> &interval<T, Policies>::operator=(T const &v)
0200 {
0201 if (checking::is_nan(v)) set_empty();
0202 else low = up = v;
0203 return *this;
0204 }
0205
0206 template<class T, class Policies> template<class T1> inline
0207 interval<T, Policies> &interval<T, Policies>::operator=(T1 const &v)
0208 {
0209 if (checking::is_nan(v)) set_empty();
0210 else {
0211 rounding rnd;
0212 low = rnd.conv_down(v);
0213 up = rnd.conv_up (v);
0214 }
0215 return *this;
0216 }
0217
0218 template<class T, class Policies> inline
0219 interval<T, Policies> &interval<T, Policies>::operator=(interval<T, Policies> const &r)
0220 {
0221 low = r.lower();
0222 up = r.upper();
0223 return *this;
0224 }
0225
0226 template<class T, class Policies> template<class Policies1> inline
0227 interval<T, Policies> &interval<T, Policies>::operator=(interval<T, Policies1> const &r)
0228 {
0229 typedef typename Policies1::checking checking1;
0230 if (checking1::is_empty(r.lower(), r.upper())) set_empty();
0231 else {
0232 low = r.lower();
0233 up = r.upper();
0234 }
0235 return *this;
0236 }
0237
0238 template<class T, class Policies> template<class T1, class Policies1> inline
0239 interval<T, Policies> &interval<T, Policies>::operator=(interval<T1, Policies1> const &r)
0240 {
0241 typedef typename Policies1::checking checking1;
0242 if (checking1::is_empty(r.lower(), r.upper())) set_empty();
0243 else {
0244 rounding rnd;
0245 low = rnd.conv_down(r.lower());
0246 up = rnd.conv_up (r.upper());
0247 }
0248 return *this;
0249 }
0250
0251 template<class T, class Policies> inline
0252 void interval<T, Policies>::assign(const T& l, const T& u)
0253 {
0254 if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u))
0255 set_empty();
0256 else set(l, u);
0257 }
0258
0259 template<class T, class Policies> inline
0260 void interval<T, Policies>::set(const T& l, const T& u)
0261 {
0262 low = l;
0263 up = u;
0264 }
0265
0266 template<class T, class Policies> inline
0267 void interval<T, Policies>::set_empty()
0268 {
0269 low = checking::empty_lower();
0270 up = checking::empty_upper();
0271 }
0272
0273 template<class T, class Policies> inline
0274 void interval<T, Policies>::set_whole()
0275 {
0276 low = checking::neg_inf();
0277 up = checking::pos_inf();
0278 }
0279
0280 template<class T, class Policies> inline
0281 interval<T, Policies> interval<T, Policies>::hull(const T& x, const T& y)
0282 {
0283 bool bad_x = checking::is_nan(x);
0284 bool bad_y = checking::is_nan(y);
0285 if (bad_x)
0286 if (bad_y) return interval::empty();
0287 else return interval(y, y, true);
0288 else
0289 if (bad_y) return interval(x, x, true);
0290 if (x <= y) return interval(x, y, true);
0291 else return interval(y, x, true);
0292 }
0293
0294 template<class T, class Policies> inline
0295 interval<T, Policies> interval<T, Policies>::empty()
0296 {
0297 return interval<T, Policies>(checking::empty_lower(),
0298 checking::empty_upper(), true);
0299 }
0300
0301 template<class T, class Policies> inline
0302 interval<T, Policies> interval<T, Policies>::whole()
0303 {
0304 return interval<T, Policies>(checking::neg_inf(), checking::pos_inf(), true);
0305 }
0306
0307 template<class T, class Policies> inline
0308 const T& interval<T, Policies>::lower() const
0309 {
0310 return low;
0311 }
0312
0313 template<class T, class Policies> inline
0314 const T& interval<T, Policies>::upper() const
0315 {
0316 return up;
0317 }
0318
0319
0320
0321
0322
0323 template<class T, class Policies> inline
0324 bool interval<T, Policies>::operator< (const interval_holder& r) const
0325 {
0326 if (!checking::is_empty(low, up)) {
0327 if (up < r.low) return true;
0328 else if (low >= r.up) return false;
0329 }
0330 throw interval_lib::comparison_error();
0331 }
0332
0333 template<class T, class Policies> inline
0334 bool interval<T, Policies>::operator> (const interval_holder& r) const
0335 {
0336 if (!checking::is_empty(low, up)) {
0337 if (low > r.up) return true;
0338 else if (up <= r.low) return false;
0339 }
0340 throw interval_lib::comparison_error();
0341 }
0342
0343 template<class T, class Policies> inline
0344 bool interval<T, Policies>::operator<= (const interval_holder& r) const
0345 {
0346 if (!checking::is_empty(low, up)) {
0347 if (up <= r.low) return true;
0348 else if (low > r.up) return false;
0349 }
0350 throw interval_lib::comparison_error();
0351 }
0352
0353 template<class T, class Policies> inline
0354 bool interval<T, Policies>::operator>= (const interval_holder& r) const
0355 {
0356 if (!checking::is_empty(low, up)) {
0357 if (low >= r.up) return true;
0358 else if (up < r.low) return false;
0359 }
0360 throw interval_lib::comparison_error();
0361 }
0362
0363 template<class T, class Policies> inline
0364 bool interval<T, Policies>::operator== (const interval_holder& r) const
0365 {
0366 if (!checking::is_empty(low, up)) {
0367 if (up == r.low && low == r.up) return true;
0368 else if (up < r.low || low > r.up) return false;
0369 }
0370 throw interval_lib::comparison_error();
0371 }
0372
0373 template<class T, class Policies> inline
0374 bool interval<T, Policies>::operator!= (const interval_holder& r) const
0375 {
0376 if (!checking::is_empty(low, up)) {
0377 if (up < r.low || low > r.up) return true;
0378 else if (up == r.low && low == r.up) return false;
0379 }
0380 throw interval_lib::comparison_error();
0381 }
0382
0383
0384
0385
0386
0387 template<class T, class Policies> inline
0388 bool interval<T, Policies>::operator< (const number_holder& r) const
0389 {
0390 if (!checking::is_empty(low, up)) {
0391 if (up < r.val) return true;
0392 else if (low >= r.val) return false;
0393 }
0394 throw interval_lib::comparison_error();
0395 }
0396
0397 template<class T, class Policies> inline
0398 bool interval<T, Policies>::operator> (const number_holder& r) const
0399 {
0400 if (!checking::is_empty(low, up)) {
0401 if (low > r.val) return true;
0402 else if (up <= r.val) return false;
0403 }
0404 throw interval_lib::comparison_error();
0405 }
0406
0407 template<class T, class Policies> inline
0408 bool interval<T, Policies>::operator<= (const number_holder& r) const
0409 {
0410 if (!checking::is_empty(low, up)) {
0411 if (up <= r.val) return true;
0412 else if (low > r.val) return false;
0413 }
0414 throw interval_lib::comparison_error();
0415 }
0416
0417 template<class T, class Policies> inline
0418 bool interval<T, Policies>::operator>= (const number_holder& r) const
0419 {
0420 if (!checking::is_empty(low, up)) {
0421 if (low >= r.val) return true;
0422 else if (up < r.val) return false;
0423 }
0424 throw interval_lib::comparison_error();
0425 }
0426
0427 template<class T, class Policies> inline
0428 bool interval<T, Policies>::operator== (const number_holder& r) const
0429 {
0430 if (!checking::is_empty(low, up)) {
0431 if (up == r.val && low == r.val) return true;
0432 else if (up < r.val || low > r.val) return false;
0433 }
0434 throw interval_lib::comparison_error();
0435 }
0436
0437 template<class T, class Policies> inline
0438 bool interval<T, Policies>::operator!= (const number_holder& r) const
0439 {
0440 if (!checking::is_empty(low, up)) {
0441 if (up < r.val || low > r.val) return true;
0442 else if (up == r.val && low == r.val) return false;
0443 }
0444 throw interval_lib::comparison_error();
0445 }
0446
0447 }
0448 }
0449
0450 #endif