os/ossrv/ossrv_pub/boost_apis/boost/numeric/interval/interval.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* Boost interval/interval.hpp header file
     2  *
     3  * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
     4  *
     5  * Distributed under the Boost Software License, Version 1.0.
     6  * (See accompanying file LICENSE_1_0.txt or
     7  * copy at http://www.boost.org/LICENSE_1_0.txt)
     8  */
     9 
    10 #ifndef BOOST_NUMERIC_INTERVAL_INTERVAL_HPP
    11 #define BOOST_NUMERIC_INTERVAL_INTERVAL_HPP
    12 
    13 #include <stdexcept>
    14 #include <string>
    15 #include <boost/numeric/interval/detail/interval_prototype.hpp>
    16 
    17 namespace boost {
    18 namespace numeric {
    19 
    20 namespace interval_lib {
    21     
    22 class comparison_error
    23   : public std::runtime_error 
    24 {
    25 public:
    26   comparison_error()
    27     : std::runtime_error("boost::interval: uncertain comparison")
    28   { }
    29 };
    30 
    31 } // namespace interval_lib
    32 
    33 /*
    34  * interval class
    35  */
    36 
    37 template<class T, class Policies>
    38 class interval
    39 {
    40 private:
    41   struct interval_holder;
    42   struct number_holder;
    43 public:
    44   typedef T base_type;
    45   typedef Policies traits_type;
    46 
    47   T const &lower() const;
    48   T const &upper() const;
    49 
    50   interval();
    51   interval(T const &v);
    52   template<class T1> interval(T1 const &v);
    53   interval(T const &l, T const &u);
    54   template<class T1, class T2> interval(T1 const &l, T2 const &u);
    55   interval(interval<T, Policies> const &r);
    56   template<class Policies1> interval(interval<T, Policies1> const &r);
    57   template<class T1, class Policies1> interval(interval<T1, Policies1> const &r);
    58 
    59   interval &operator=(T const &v);
    60   template<class T1> interval &operator=(T1 const &v);
    61   interval &operator=(interval<T, Policies> const &r);
    62   template<class Policies1> interval &operator=(interval<T, Policies1> const &r);
    63   template<class T1, class Policies1> interval &operator=(interval<T1, Policies1> const &r);
    64  
    65   void assign(const T& l, const T& u);
    66 
    67   static interval empty();
    68   static interval whole();
    69   static interval hull(const T& x, const T& y);
    70 
    71   interval& operator+= (const T& r);
    72   interval& operator+= (const interval& r);
    73   interval& operator-= (const T& r);
    74   interval& operator-= (const interval& r);
    75   interval& operator*= (const T& r);
    76   interval& operator*= (const interval& r);
    77   interval& operator/= (const T& r);
    78   interval& operator/= (const interval& r);
    79 
    80   bool operator< (const interval_holder& r) const;
    81   bool operator> (const interval_holder& r) const;
    82   bool operator<= (const interval_holder& r) const;
    83   bool operator>= (const interval_holder& r) const;
    84   bool operator== (const interval_holder& r) const;
    85   bool operator!= (const interval_holder& r) const;
    86 
    87   bool operator< (const number_holder& r) const;
    88   bool operator> (const number_holder& r) const;
    89   bool operator<= (const number_holder& r) const;
    90   bool operator>= (const number_holder& r) const;
    91   bool operator== (const number_holder& r) const;
    92   bool operator!= (const number_holder& r) const;
    93 
    94   // the following is for internal use only, it is not a published interface
    95   // nevertheless, it's public because friends don't always work correctly.
    96   interval(const T& l, const T& u, bool): low(l), up(u) {}
    97   void set_empty();
    98   void set_whole();
    99   void set(const T& l, const T& u);
   100 
   101 private:
   102   struct interval_holder {
   103     template<class Policies2>
   104     interval_holder(const interval<T, Policies2>& r)
   105       : low(r.lower()), up(r.upper())
   106     {
   107       typedef typename Policies2::checking checking2;
   108       if (checking2::is_empty(low, up))
   109         throw interval_lib::comparison_error();
   110     }
   111 
   112     const T& low;
   113     const T& up;
   114   };
   115 
   116   struct number_holder {
   117     number_holder(const T& r) : val(r)
   118     {
   119       typedef typename Policies::checking checking;
   120       if (checking::is_nan(r))
   121         throw interval_lib::comparison_error();
   122     }
   123     
   124     const T& val;
   125   };
   126 
   127   typedef typename Policies::checking checking;
   128   typedef typename Policies::rounding rounding;
   129 
   130   T low;
   131   T up;
   132 };
   133 
   134 template<class T, class Policies> inline
   135 interval<T, Policies>::interval():
   136   low(static_cast<T>(0)), up(static_cast<T>(0))
   137 {}
   138 
   139 template<class T, class Policies> inline
   140 interval<T, Policies>::interval(T const &v): low(v), up(v)
   141 {
   142   if (checking::is_nan(v)) set_empty();
   143 }
   144 
   145 template<class T, class Policies> template<class T1> inline
   146 interval<T, Policies>::interval(T1 const &v)
   147 {
   148   if (checking::is_nan(v)) set_empty();
   149   else {
   150     rounding rnd;
   151     low = rnd.conv_down(v);
   152     up  = rnd.conv_up  (v);
   153   }
   154 }
   155 
   156 template<class T, class Policies> template<class T1, class T2> inline
   157 interval<T, Policies>::interval(T1 const &l, T2 const &u)
   158 {
   159   if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u)) set_empty();
   160   else {
   161     rounding rnd;
   162     low = rnd.conv_down(l);
   163     up  = rnd.conv_up  (u);
   164   }
   165 }
   166 
   167 template<class T, class Policies> inline
   168 interval<T, Policies>::interval(T const &l, T const &u): low(l), up(u)
   169 {
   170   if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u))
   171     set_empty();
   172 }
   173 
   174 
   175 template<class T, class Policies> inline
   176 interval<T, Policies>::interval(interval<T, Policies> const &r): low(r.lower()), up(r.upper())
   177 {}
   178 
   179 template<class T, class Policies> template<class Policies1> inline
   180 interval<T, Policies>::interval(interval<T, Policies1> const &r): low(r.lower()), up(r.upper())
   181 {
   182   typedef typename Policies1::checking checking1;
   183   if (checking1::is_empty(r.lower(), r.upper())) set_empty();
   184 }
   185 
   186 template<class T, class Policies> template<class T1, class Policies1> inline
   187 interval<T, Policies>::interval(interval<T1, Policies1> const &r)
   188 {
   189   typedef typename Policies1::checking checking1;
   190   if (checking1::is_empty(r.lower(), r.upper())) set_empty();
   191   else {
   192     rounding rnd;
   193     low = rnd.conv_down(r.lower());
   194     up  = rnd.conv_up  (r.upper());
   195   }
   196 }
   197 
   198 template<class T, class Policies> inline
   199 interval<T, Policies> &interval<T, Policies>::operator=(T const &v)
   200 {
   201   if (checking::is_nan(v)) set_empty();
   202   else low = up = v;
   203   return *this;
   204 }
   205 
   206 template<class T, class Policies> template<class T1> inline
   207 interval<T, Policies> &interval<T, Policies>::operator=(T1 const &v)
   208 {
   209   if (checking::is_nan(v)) set_empty();
   210   else {
   211     rounding rnd;
   212     low = rnd.conv_down(v);
   213     up  = rnd.conv_up  (v);
   214   }
   215   return *this;
   216 }
   217 
   218 template<class T, class Policies> inline
   219 interval<T, Policies> &interval<T, Policies>::operator=(interval<T, Policies> const &r)
   220 {
   221   low = r.lower();
   222   up  = r.upper();
   223   return *this;
   224 }
   225 
   226 template<class T, class Policies> template<class Policies1> inline
   227 interval<T, Policies> &interval<T, Policies>::operator=(interval<T, Policies1> const &r)
   228 {
   229   typedef typename Policies1::checking checking1;
   230   if (checking1::is_empty(r.lower(), r.upper())) set_empty();
   231   else {
   232     low = r.lower();
   233     up  = r.upper();
   234   }
   235   return *this;
   236 }
   237 
   238 template<class T, class Policies> template<class T1, class Policies1> inline
   239 interval<T, Policies> &interval<T, Policies>::operator=(interval<T1, Policies1> const &r)
   240 {
   241   typedef typename Policies1::checking checking1;
   242   if (checking1::is_empty(r.lower(), r.upper())) set_empty();
   243   else {
   244     rounding rnd;
   245     low = rnd.conv_down(r.lower());
   246     up  = rnd.conv_up  (r.upper());
   247   }
   248   return *this;
   249 }
   250 
   251 template<class T, class Policies> inline
   252 void interval<T, Policies>::assign(const T& l, const T& u)
   253 {
   254   if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u))
   255     set_empty();
   256   else set(l, u);
   257 }
   258 
   259 template<class T, class Policies> inline
   260 void interval<T, Policies>::set(const T& l, const T& u)
   261 {
   262   low = l;
   263   up  = u;
   264 }
   265 
   266 template<class T, class Policies> inline
   267 void interval<T, Policies>::set_empty()
   268 {
   269   low = checking::empty_lower();
   270   up  = checking::empty_upper();
   271 }
   272 
   273 template<class T, class Policies> inline
   274 void interval<T, Policies>::set_whole()
   275 {
   276   low = checking::neg_inf();
   277   up  = checking::pos_inf();
   278 }
   279 
   280 template<class T, class Policies> inline
   281 interval<T, Policies> interval<T, Policies>::hull(const T& x, const T& y)
   282 {
   283   bool bad_x = checking::is_nan(x);
   284   bool bad_y = checking::is_nan(y);
   285   if (bad_x)
   286     if (bad_y) return interval::empty();
   287     else       return interval(y, y, true);
   288   else
   289     if (bad_y) return interval(x, x, true);
   290   if (x <= y) return interval(x, y, true);
   291   else        return interval(y, x, true);
   292 }
   293 
   294 template<class T, class Policies> inline
   295 interval<T, Policies> interval<T, Policies>::empty()
   296 {
   297   return interval<T, Policies>(checking::empty_lower(),
   298                                checking::empty_upper(), true);
   299 }
   300 
   301 template<class T, class Policies> inline
   302 interval<T, Policies> interval<T, Policies>::whole()
   303 {
   304   return interval<T, Policies>(checking::neg_inf(), checking::pos_inf(), true);
   305 }
   306 
   307 template<class T, class Policies> inline
   308 const T& interval<T, Policies>::lower() const
   309 {
   310   return low;
   311 }
   312 
   313 template<class T, class Policies> inline
   314 const T& interval<T, Policies>::upper() const
   315 {
   316   return up;
   317 }
   318 
   319 /*
   320  * interval/interval comparisons
   321  */
   322 
   323 template<class T, class Policies> inline
   324 bool interval<T, Policies>::operator< (const interval_holder& r) const
   325 {
   326   if (!checking::is_empty(low, up)) {
   327     if (up < r.low) return true;
   328     else if (low >= r.up) return false;
   329   }
   330   throw interval_lib::comparison_error();
   331 }
   332 
   333 template<class T, class Policies> inline
   334 bool interval<T, Policies>::operator> (const interval_holder& r) const
   335 {
   336   if (!checking::is_empty(low, up)) {
   337     if (low > r.up) return true;
   338     else if (up <= r.low) return false;
   339   }
   340   throw interval_lib::comparison_error();
   341 }
   342 
   343 template<class T, class Policies> inline
   344 bool interval<T, Policies>::operator<= (const interval_holder& r) const
   345 {
   346   if (!checking::is_empty(low, up)) {
   347     if (up <= r.low) return true;
   348     else if (low > r.up) return false;
   349   }
   350   throw interval_lib::comparison_error();
   351 }
   352 
   353 template<class T, class Policies> inline
   354 bool interval<T, Policies>::operator>= (const interval_holder& r) const
   355 {
   356   if (!checking::is_empty(low, up)) {
   357     if (low >= r.up) return true;
   358     else if (up < r.low) return false;
   359   }
   360   throw interval_lib::comparison_error();
   361 }
   362 
   363 template<class T, class Policies> inline
   364 bool interval<T, Policies>::operator== (const interval_holder& r) const
   365 {
   366   if (!checking::is_empty(low, up)) {
   367     if (up == r.low && low == r.up) return true;
   368     else if (up < r.low || low > r.up) return false;
   369   }
   370   throw interval_lib::comparison_error();
   371 }
   372 
   373 template<class T, class Policies> inline
   374 bool interval<T, Policies>::operator!= (const interval_holder& r) const
   375 {
   376   if (!checking::is_empty(low, up)) {
   377     if (up < r.low || low > r.up) return true;
   378     else if (up == r.low && low == r.up) return false;
   379   }
   380   throw interval_lib::comparison_error();
   381 }
   382 
   383 /*
   384  * interval/number comparisons
   385  */
   386 
   387 template<class T, class Policies> inline
   388 bool interval<T, Policies>::operator< (const number_holder& r) const
   389 {
   390   if (!checking::is_empty(low, up)) {
   391     if (up < r.val) return true;
   392     else if (low >= r.val) return false;
   393   }
   394   throw interval_lib::comparison_error();
   395 }
   396 
   397 template<class T, class Policies> inline
   398 bool interval<T, Policies>::operator> (const number_holder& r) const
   399 {
   400   if (!checking::is_empty(low, up)) {
   401     if (low > r.val) return true;
   402     else if (up <= r.val) return false;
   403   }
   404   throw interval_lib::comparison_error();
   405 }
   406 
   407 template<class T, class Policies> inline
   408 bool interval<T, Policies>::operator<= (const number_holder& r) const
   409 {
   410   if (!checking::is_empty(low, up)) {
   411     if (up <= r.val) return true;
   412     else if (low > r.val) return false;
   413   }
   414   throw interval_lib::comparison_error();
   415 }
   416 
   417 template<class T, class Policies> inline
   418 bool interval<T, Policies>::operator>= (const number_holder& r) const
   419 {
   420   if (!checking::is_empty(low, up)) {
   421     if (low >= r.val) return true;
   422     else if (up < r.val) return false;
   423   }
   424   throw interval_lib::comparison_error();
   425 }
   426 
   427 template<class T, class Policies> inline
   428 bool interval<T, Policies>::operator== (const number_holder& r) const
   429 {
   430   if (!checking::is_empty(low, up)) {
   431     if (up == r.val && low == r.val) return true;
   432     else if (up < r.val || low > r.val) return false;
   433   }
   434   throw interval_lib::comparison_error();
   435 }
   436 
   437 template<class T, class Policies> inline
   438 bool interval<T, Policies>::operator!= (const number_holder& r) const
   439 {
   440   if (!checking::is_empty(low, up)) {
   441     if (up < r.val || low > r.val) return true;
   442     else if (up == r.val && low == r.val) return false;
   443   }
   444   throw interval_lib::comparison_error();
   445 }
   446 
   447 } // namespace numeric
   448 } // namespace boost
   449 
   450 #endif // BOOST_NUMERIC_INTERVAL_INTERVAL_HPP